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-compile-base.h"
20 : #include "rust-abi.h"
21 : #include "rust-compile-stmt.h"
22 : #include "rust-compile-expr.h"
23 : #include "rust-compile-drop.h"
24 : #include "rust-compile-fnparam.h"
25 : #include "rust-compile-var-decl.h"
26 : #include "rust-compile-type.h"
27 : #include "rust-constexpr.h"
28 : #include "rust-diagnostics.h"
29 : #include "rust-expr.h" // for AST::AttrInputLiteral
30 : #include "rust-hir-map.h"
31 : #include "rust-macro.h" // for AST::MetaNameValueStr
32 : #include "rust-hir-path-probe.h"
33 : #include "rust-type-util.h"
34 : #include "rust-compile-implitem.h"
35 : #include "rust-attribute-values.h"
36 : #include "rust-attributes.h"
37 : #include "rust-finalized-name-resolution-context.h"
38 :
39 : #include "fold-const.h"
40 : #include "stringpool.h"
41 : #include "attribs.h"
42 : #include "tree.h"
43 : #include "print-tree.h"
44 :
45 : // rust-name-resolution-2.0
46 : #include "options.h"
47 :
48 : namespace Rust {
49 : namespace Compile {
50 :
51 13050 : bool inline should_mangle_item (const tree fndecl)
52 : {
53 13050 : return lookup_attribute (Values::Attributes::NO_MANGLE,
54 13050 : DECL_ATTRIBUTES (fndecl))
55 : == NULL_TREE
56 26099 : && lookup_attribute (Values::Attributes::RUSTC_STD_INTERNAL_SYMBOL,
57 13049 : DECL_ATTRIBUTES (fndecl))
58 13050 : == NULL_TREE;
59 : }
60 :
61 : void
62 13050 : HIRCompileBase::setup_fndecl (tree fndecl, bool is_main_entry_point,
63 : bool is_generic_fn, HIR::Visibility &visibility,
64 : const HIR::FunctionQualifiers &qualifiers,
65 : const AST::AttrVec &attrs)
66 : {
67 : // if its the main fn or pub visibility mark its as DECL_PUBLIC
68 : // please see https://github.com/Rust-GCC/gccrs/pull/137
69 13050 : bool is_pub = visibility.get_vis_type () == HIR::Visibility::VisType::Public;
70 13050 : if (is_main_entry_point || (is_pub && !is_generic_fn))
71 : {
72 5888 : TREE_PUBLIC (fndecl) = 1;
73 : }
74 :
75 : // is it a const fn
76 13050 : DECL_DECLARED_CONSTEXPR_P (fndecl) = qualifiers.is_const ();
77 13050 : if (qualifiers.is_const ())
78 : {
79 695 : TREE_READONLY (fndecl) = 1;
80 : }
81 :
82 : // is it inline?
83 28666 : for (const auto &attr : attrs)
84 : {
85 15616 : std::string attr_str = attr.get_path ().as_string ();
86 :
87 15616 : bool is_inline = attr_str == Values::Attributes::INLINE;
88 15616 : bool is_must_use = attr_str == Values::Attributes::MUST_USE;
89 15616 : bool is_cold = attr_str == Values::Attributes::COLD;
90 15616 : bool is_link_section = attr_str == Values::Attributes::LINK_SECTION;
91 15616 : bool no_mangle = attr_str == Values::Attributes::NO_MANGLE;
92 15616 : bool is_std_internal
93 15616 : = attr_str == Values::Attributes::RUSTC_STD_INTERNAL_SYMBOL;
94 15616 : bool is_deprecated = attr_str == Values::Attributes::DEPRECATED;
95 15616 : bool is_proc_macro = attr_str == Values::Attributes::PROC_MACRO;
96 15616 : bool is_proc_macro_attribute
97 15616 : = attr_str == Values::Attributes::PROC_MACRO_ATTRIBUTE;
98 15616 : bool is_proc_macro_derive
99 15616 : = attr_str == Values::Attributes::PROC_MACRO_DERIVE;
100 15616 : bool is_allocator = attr_str == Values::Attributes::RUSTC_ALLOCATOR;
101 15616 : bool is_allocator_nounwind
102 15616 : = attr_str == Values::Attributes::RUSTC_ALLOCATOR_NOUNWIND;
103 :
104 15616 : if (is_inline)
105 : {
106 943 : handle_inline_attribute_on_fndecl (fndecl, attr);
107 : }
108 14673 : else if (is_must_use)
109 : {
110 1089 : handle_must_use_attribute_on_fndecl (fndecl, attr);
111 : }
112 13584 : else if (is_cold)
113 : {
114 1 : handle_cold_attribute_on_fndecl (fndecl, attr);
115 : }
116 13583 : else if (is_link_section)
117 : {
118 1 : handle_link_section_attribute_on_fndecl (fndecl, attr);
119 : }
120 13582 : else if (is_deprecated)
121 : {
122 5 : handle_deprecated_attribute_on_fndecl (fndecl, attr);
123 : }
124 13577 : else if (no_mangle)
125 : {
126 1 : handle_no_mangle_attribute_on_fndecl (fndecl, attr);
127 : }
128 13576 : else if (is_std_internal)
129 : {
130 1 : handle_rustc_std_internal_symbol_attribute_on_fndecl (fndecl, attr);
131 : }
132 13575 : else if (is_proc_macro)
133 : {
134 0 : handle_bang_proc_macro_attribute_on_fndecl (fndecl, attr);
135 : }
136 13575 : else if (is_proc_macro_attribute)
137 : {
138 0 : handle_attribute_proc_macro_attribute_on_fndecl (fndecl, attr);
139 : }
140 13575 : else if (is_proc_macro_derive)
141 : {
142 0 : handle_derive_proc_macro_attribute_on_fndecl (fndecl, attr);
143 : }
144 13575 : else if (is_allocator)
145 : {
146 2 : handle_rustc_allocator_on_fndecl (fndecl, attr);
147 : }
148 13573 : else if (is_allocator_nounwind)
149 : {
150 1 : handle_rustc_allocator_nounwind_on_fndecl (fndecl, attr);
151 : }
152 15616 : }
153 13050 : }
154 :
155 : static void
156 0 : handle_proc_macro_common (tree fndecl, const AST::Attribute &attr)
157 : {
158 0 : DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("gccrs_proc_macro"),
159 0 : NULL, DECL_ATTRIBUTES (fndecl));
160 0 : }
161 :
162 : void
163 0 : HIRCompileBase::handle_bang_proc_macro_attribute_on_fndecl (
164 : tree fndecl, const AST::Attribute &attr)
165 : {
166 0 : handle_proc_macro_common (fndecl, attr);
167 0 : ctx->collect_bang_proc_macro (fndecl);
168 0 : }
169 :
170 : void
171 0 : HIRCompileBase::handle_attribute_proc_macro_attribute_on_fndecl (
172 : tree fndecl, const AST::Attribute &attr)
173 : {
174 0 : handle_proc_macro_common (fndecl, attr);
175 0 : ctx->collect_attribute_proc_macro (fndecl);
176 0 : }
177 :
178 : static std::vector<std::string>
179 0 : get_attributes (const AST::Attribute &attr)
180 : {
181 0 : std::vector<std::string> result;
182 :
183 0 : rust_assert (attr.get_attr_input ().get_attr_input_type ()
184 : == Rust::AST::AttrInput::TOKEN_TREE);
185 0 : const auto &tt
186 0 : = static_cast<const AST::DelimTokenTree &> (attr.get_attr_input ());
187 :
188 : // TODO: Should we rely on fixed index ? Should we search for the
189 : // attribute tokentree instead ?
190 :
191 : // Derive proc macros have the following format:
192 : // #[proc_macro_derive(TraitName, attributes(attr1, attr2, attr3))]
193 : // -~~~~~~~~ - ~~~~~~~~~~---------------------
194 : // ^0 ^1 ^2 ^3 ^4
195 : // - "attributes" is stored at position 3 in the token tree
196 : // - attribute are stored in the delimited token tree in position 4
197 0 : constexpr size_t attr_kw_pos = 3;
198 0 : constexpr size_t attribute_list_pos = 4;
199 :
200 0 : if (tt.get_token_trees ().size () > attr_kw_pos)
201 : {
202 0 : rust_assert (tt.get_token_trees ()[attr_kw_pos]->as_string ()
203 : == "attributes");
204 :
205 0 : auto attributes = static_cast<const AST::DelimTokenTree *> (
206 0 : tt.get_token_trees ()[attribute_list_pos].get ());
207 :
208 0 : auto &token_trees = attributes->get_token_trees ();
209 :
210 0 : for (auto i = token_trees.cbegin () + 1; // Skip opening parenthesis
211 0 : i < token_trees.cend ();
212 0 : i += 2) // Skip comma and closing parenthesis
213 : {
214 0 : result.push_back ((*i)->as_string ());
215 : }
216 : }
217 0 : return result;
218 : }
219 :
220 : static std::string
221 0 : get_trait_name (const AST::Attribute &attr)
222 : {
223 : // Derive proc macros have the following format:
224 : // #[proc_macro_derive(TraitName, attributes(attr1, attr2, attr3))]
225 : // -~~~~~~~~ - ~~~~~~~~~~---------------------
226 : // ^0 ^1 ^2 ^3 ^4
227 : // - The trait name is stored at position 1
228 0 : constexpr size_t trait_name_pos = 1;
229 :
230 0 : rust_assert (attr.get_attr_input ().get_attr_input_type ()
231 : == Rust::AST::AttrInput::TOKEN_TREE);
232 0 : const auto &tt
233 0 : = static_cast<const AST::DelimTokenTree &> (attr.get_attr_input ());
234 0 : return tt.get_token_trees ()[trait_name_pos]->as_string ();
235 : }
236 :
237 : void
238 0 : HIRCompileBase::handle_derive_proc_macro_attribute_on_fndecl (
239 : tree fndecl, const AST::Attribute &attr)
240 : {
241 0 : handle_proc_macro_common (fndecl, attr);
242 :
243 0 : attr.get_attr_input ().parse_to_meta_item ();
244 0 : CustomDeriveInfo macro
245 0 : = {fndecl, get_trait_name (attr), get_attributes (attr)};
246 0 : ctx->collect_derive_proc_macro (macro);
247 0 : }
248 :
249 : void
250 1 : HIRCompileBase::handle_cold_attribute_on_fndecl (tree fndecl,
251 : const AST::Attribute &attr)
252 : {
253 : // simple #[cold]
254 1 : if (!attr.has_attr_input ())
255 : {
256 1 : tree cold = get_identifier (Values::Attributes::COLD);
257 : // this will get handled by the GCC backend later
258 1 : DECL_ATTRIBUTES (fndecl)
259 1 : = tree_cons (cold, NULL_TREE, DECL_ATTRIBUTES (fndecl));
260 1 : return;
261 : }
262 :
263 0 : rust_error_at (attr.get_locus (),
264 : "attribute %<cold%> does not accept any arguments");
265 : }
266 :
267 : void
268 1 : HIRCompileBase::handle_link_section_attribute_on_fndecl (
269 : tree fndecl, const AST::Attribute &attr)
270 : {
271 1 : auto msg_str = Analysis::Attributes::extract_string_literal (attr);
272 :
273 1 : if (!msg_str.has_value ())
274 : {
275 0 : rust_error_at (attr.get_locus (),
276 : "malformed %<link_section%> attribute input");
277 0 : return;
278 : }
279 :
280 1 : if (decl_section_name (fndecl))
281 : {
282 0 : rust_warning_at (attr.get_locus (), 0, "section name redefined");
283 : }
284 :
285 1 : set_decl_section_name (fndecl, msg_str->c_str ());
286 1 : }
287 :
288 : void
289 1 : HIRCompileBase::handle_no_mangle_attribute_on_fndecl (
290 : tree fndecl, const AST::Attribute &attr)
291 : {
292 1 : if (attr.has_attr_input ())
293 : {
294 0 : rust_error_at (attr.get_locus (),
295 : "attribute %<no_mangle%> does not accept any arguments");
296 0 : return;
297 : }
298 :
299 1 : DECL_ATTRIBUTES (fndecl)
300 2 : = tree_cons (get_identifier (Values::Attributes::NO_MANGLE), NULL_TREE,
301 1 : DECL_ATTRIBUTES (fndecl));
302 : }
303 :
304 : void
305 1 : HIRCompileBase::handle_rustc_std_internal_symbol_attribute_on_fndecl (
306 : tree fndecl, const AST::Attribute &attr)
307 : {
308 1 : DECL_ATTRIBUTES (fndecl)
309 1 : = tree_cons (get_identifier (Values::Attributes::RUSTC_STD_INTERNAL_SYMBOL),
310 1 : NULL_TREE, DECL_ATTRIBUTES (fndecl));
311 1 : }
312 :
313 : void
314 2 : HIRCompileBase::handle_rustc_allocator_on_fndecl (tree fndecl,
315 : const AST::Attribute &attr)
316 : {
317 2 : tree return_type = TREE_TYPE (TREE_TYPE (fndecl));
318 2 : if (!POINTER_TYPE_P (return_type))
319 : {
320 1 : rust_error_at (attr.get_locus (),
321 : "%<rustc_allocator%> attribute must be applied to a "
322 : "function returning a pointer");
323 1 : return;
324 : }
325 :
326 : // https://github.com/rust-lang/rust/blob/e1884a8e3c3e813aada8254edfa120e85bf5ffca/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs#L49
327 : // `#[rustc_allocator]`: a hint to LLVM that the pointer returned from this
328 : // function is never null.
329 : //
330 : // https://github.com/rust-lang/rust/blob/e1884a8e3c3e813aada8254edfa120e85bf5ffca/compiler/rustc_typeck/src/collect.rs#L2482
331 : // This attribute sets CodegenFnAttrFlags::ALLOCATOR.
332 : //
333 : // https://github.com/rust-lang/rust/blob/e1884a8e3c3e813aada8254edfa120e85bf5ffca/compiler/rustc_codegen_llvm/src/attributes.rs#L302
334 : // This flag activates LLVM::NoAlias attribute.
335 : //
336 : // In GCC, setting DECL_IS_MALLOC on a FUNCTION_DECL means this function
337 : // should be treated as if it were a malloc, meaning it returns a pointer that
338 : // is not an alias.
339 1 : DECL_IS_MALLOC (fndecl) = 1;
340 1 : DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("malloc"), NULL_TREE,
341 1 : DECL_ATTRIBUTES (fndecl));
342 : }
343 :
344 : void
345 1 : HIRCompileBase::handle_rustc_allocator_nounwind_on_fndecl (
346 : tree fndecl, const AST::Attribute &attr)
347 : {
348 : // https://github.com/rust-lang/rust/blob/e1884a8e3c3e813aada8254edfa120e85bf5ffca/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs#L55
349 : // `#[rustc_allocator_nounwind]`: an indicator that an imported FFI
350 : // function will never unwind.
351 : //
352 : // https://github.com/rust-lang/rust/blob/e1884a8e3c3e813aada8254edfa120e85bf5ffca/compiler/rustc_typeck/src/collect.rs#L2484
353 : // This attribute sets CodegenFnAttrFlags::NOUNWIND.
354 : //
355 : // In GCC, setting TREE_NOTHROW on a FUNCTION_DECL means a call to the
356 : // function cannot throw an exception, which exactly matches this behavior.
357 1 : TREE_NOTHROW (fndecl) = 1;
358 1 : DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("nothrow"), NULL_TREE,
359 1 : DECL_ATTRIBUTES (fndecl));
360 1 : }
361 :
362 : void
363 5 : HIRCompileBase::handle_deprecated_attribute_on_fndecl (
364 : tree fndecl, const AST::Attribute &attr)
365 : {
366 5 : tree value = NULL_TREE;
367 5 : TREE_DEPRECATED (fndecl) = 1;
368 :
369 : // simple #[deprecated]
370 5 : if (!attr.has_attr_input ())
371 : return;
372 :
373 4 : const AST::AttrInput &input = attr.get_attr_input ();
374 4 : auto input_type = input.get_attr_input_type ();
375 :
376 4 : if (input_type == AST::AttrInput::AttrInputType::LITERAL)
377 : {
378 : // handle #[deprecated = "message"]
379 1 : auto &literal
380 1 : = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ());
381 1 : const auto &msg_str = literal.get_literal ().as_string ();
382 1 : value = build_string (msg_str.size (), msg_str.c_str ());
383 1 : }
384 3 : else if (input_type == AST::AttrInput::AttrInputType::TOKEN_TREE)
385 : {
386 : // handle #[deprecated(since = "...", note = "...")]
387 3 : const auto &option = static_cast<const AST::DelimTokenTree &> (input);
388 3 : AST::AttrInputMetaItemContainer *meta_item = option.parse_to_meta_item ();
389 7 : for (const auto &item : meta_item->get_items ())
390 : {
391 4 : auto converted_item = item->to_meta_name_value_str ();
392 4 : if (!converted_item)
393 0 : continue;
394 4 : auto key_value = converted_item->get_name_value_pair ();
395 4 : if (key_value.first.as_string ().compare ("since") == 0)
396 : {
397 : // valid, but this is handled by Cargo and some third-party
398 : // audit tools
399 2 : continue;
400 : }
401 2 : else if (key_value.first.as_string ().compare ("note") == 0)
402 : {
403 1 : const auto &msg_str = key_value.second;
404 1 : if (value)
405 0 : rust_error_at (attr.get_locus (), "multiple %<note%> items");
406 1 : value = build_string (msg_str.size (), msg_str.c_str ());
407 : }
408 : else
409 : {
410 1 : rust_error_at (attr.get_locus (), ErrorCode::E0541,
411 : "unknown meta item %qs",
412 1 : key_value.first.as_string ().c_str ());
413 : }
414 4 : }
415 : }
416 :
417 4 : if (value)
418 : {
419 2 : tree attr_list = build_tree_list (NULL_TREE, value);
420 2 : DECL_ATTRIBUTES (fndecl)
421 4 : = tree_cons (get_identifier (Values::Attributes::DEPRECATED), attr_list,
422 2 : DECL_ATTRIBUTES (fndecl));
423 : }
424 : }
425 :
426 : void
427 943 : HIRCompileBase::handle_inline_attribute_on_fndecl (tree fndecl,
428 : const AST::Attribute &attr)
429 : {
430 : // simple #[inline]
431 943 : if (!attr.has_attr_input ())
432 : {
433 938 : DECL_DECLARED_INLINE_P (fndecl) = 1;
434 940 : return;
435 : }
436 :
437 5 : const AST::AttrInput &input = attr.get_attr_input ();
438 5 : bool is_token_tree
439 5 : = input.get_attr_input_type () == AST::AttrInput::AttrInputType::TOKEN_TREE;
440 5 : rust_assert (is_token_tree);
441 5 : const auto &option = static_cast<const AST::DelimTokenTree &> (input);
442 5 : AST::AttrInputMetaItemContainer *meta_item = option.parse_to_meta_item ();
443 5 : if (meta_item->get_items ().size () != 1)
444 : {
445 2 : rich_location rich_locus (line_table, attr.get_locus ());
446 2 : rich_locus.add_fixit_replace ("expected one argument");
447 2 : rust_error_at (rich_locus, ErrorCode::E0534,
448 : "invalid number of arguments");
449 2 : return;
450 2 : }
451 :
452 3 : const std::string inline_option
453 3 : = meta_item->get_items ().at (0)->as_string ();
454 :
455 : // we only care about NEVER and ALWAYS else its an error
456 3 : bool is_always = inline_option.compare ("always") == 0;
457 3 : bool is_never = inline_option.compare ("never") == 0;
458 :
459 : // #[inline(never)]
460 3 : if (is_never)
461 : {
462 1 : DECL_UNINLINABLE (fndecl) = 1;
463 : }
464 : // #[inline(always)]
465 2 : else if (is_always)
466 : {
467 1 : DECL_DECLARED_INLINE_P (fndecl) = 1;
468 1 : DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("always_inline"),
469 1 : NULL, DECL_ATTRIBUTES (fndecl));
470 : }
471 : else
472 : {
473 1 : rich_location rich_locus (line_table, attr.get_locus ());
474 1 : rich_locus.add_fixit_replace ("unknown inline option");
475 1 : rust_error_at (rich_locus, ErrorCode::E0535,
476 : "invalid argument, %<inline%> attribute only accepts "
477 : "%<always%> or %<never%>");
478 1 : }
479 3 : }
480 :
481 : void
482 1089 : HIRCompileBase::handle_must_use_attribute_on_fndecl (tree fndecl,
483 : const AST::Attribute &attr)
484 : {
485 1089 : tree nodiscard = get_identifier ("nodiscard");
486 1089 : tree value = NULL_TREE;
487 :
488 1089 : if (attr.has_attr_input ())
489 : {
490 15 : auto msg_str = Analysis::Attributes::extract_string_literal (attr);
491 15 : rust_assert (msg_str.has_value ());
492 :
493 15 : tree message = build_string (msg_str->size (), msg_str->c_str ());
494 :
495 15 : value = tree_cons (nodiscard, message, NULL_TREE);
496 15 : }
497 :
498 1089 : DECL_ATTRIBUTES (fndecl)
499 1089 : = tree_cons (nodiscard, value, DECL_ATTRIBUTES (fndecl));
500 1089 : }
501 :
502 : void
503 14142 : HIRCompileBase::setup_abi_options (tree fndecl, ABI abi)
504 : {
505 14142 : tree abi_tree = NULL_TREE;
506 :
507 14142 : switch (abi)
508 : {
509 14141 : case Rust::ABI::RUST:
510 14141 : case Rust::ABI::INTRINSIC:
511 14141 : case Rust::ABI::C:
512 14141 : case Rust::ABI::CDECL:
513 : // `decl_attributes` function (not the macro) has the side-effect of
514 : // actually switching the codegen backend to use the ABI we annotated.
515 : // However, since `cdecl` is the default ABI GCC will be using,
516 : // explicitly specifying that ABI will cause GCC to emit a warning
517 : // saying the attribute is useless (which is confusing to the user as
518 : // the attribute is added by us).
519 14141 : DECL_ATTRIBUTES (fndecl)
520 14141 : = tree_cons (get_identifier ("cdecl"), NULL, DECL_ATTRIBUTES (fndecl));
521 :
522 14141 : return;
523 :
524 0 : case Rust::ABI::STDCALL:
525 0 : abi_tree = get_identifier ("stdcall");
526 :
527 0 : break;
528 :
529 0 : case Rust::ABI::FASTCALL:
530 0 : abi_tree = get_identifier ("fastcall");
531 :
532 0 : break;
533 :
534 0 : case Rust::ABI::SYSV64:
535 0 : abi_tree = get_identifier ("sysv_abi");
536 :
537 0 : break;
538 :
539 1 : case Rust::ABI::WIN_64:
540 1 : abi_tree = get_identifier ("ms_abi");
541 :
542 1 : break;
543 :
544 : default:
545 : break;
546 : }
547 :
548 1 : decl_attributes (&fndecl, build_tree_list (abi_tree, NULL_TREE), 0);
549 : }
550 :
551 : // ported from gcc/c/c-typecheck.c
552 : //
553 : // Mark EXP saying that we need to be able to take the
554 : // address of it; it should not be allocated in a register.
555 : // Returns true if successful. ARRAY_REF_P is true if this
556 : // is for ARRAY_REF construction - in that case we don't want
557 : // to look through VIEW_CONVERT_EXPR from VECTOR_TYPE to ARRAY_TYPE,
558 : // it is fine to use ARRAY_REFs for vector subscripts on vector
559 : // register variables.
560 : bool
561 39501 : HIRCompileBase::mark_addressable (tree exp, location_t locus)
562 : {
563 39501 : tree x = exp;
564 :
565 41450 : while (1)
566 41450 : switch (TREE_CODE (x))
567 : {
568 0 : case VIEW_CONVERT_EXPR:
569 0 : if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
570 0 : && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (x, 0))))
571 : return true;
572 0 : x = TREE_OPERAND (x, 0);
573 0 : break;
574 :
575 1949 : case COMPONENT_REF:
576 : // TODO
577 : // if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
578 : // {
579 : // error ("cannot take address of bit-field %qD", TREE_OPERAND (x,
580 : // 1)); return false;
581 : // }
582 :
583 : /* FALLTHRU */
584 1949 : case ADDR_EXPR:
585 1949 : case ARRAY_REF:
586 1949 : case REALPART_EXPR:
587 1949 : case IMAGPART_EXPR:
588 1949 : x = TREE_OPERAND (x, 0);
589 1949 : break;
590 :
591 0 : case COMPOUND_LITERAL_EXPR:
592 0 : TREE_ADDRESSABLE (x) = 1;
593 0 : TREE_ADDRESSABLE (COMPOUND_LITERAL_EXPR_DECL (x)) = 1;
594 0 : return true;
595 :
596 254 : case CONSTRUCTOR:
597 254 : TREE_ADDRESSABLE (x) = 1;
598 254 : return true;
599 :
600 29112 : case VAR_DECL:
601 29112 : case CONST_DECL:
602 29112 : case PARM_DECL:
603 29112 : case RESULT_DECL:
604 : // (we don't have a concept of a "register" declaration)
605 : // fallthrough */
606 :
607 : /* FALLTHRU */
608 29112 : case FUNCTION_DECL:
609 29112 : TREE_ADDRESSABLE (x) = 1;
610 :
611 : /* FALLTHRU */
612 : default:
613 : return true;
614 : }
615 :
616 : return false;
617 : }
618 :
619 : tree
620 39521 : HIRCompileBase::address_expression (tree expr, location_t location, tree ptrty)
621 : {
622 39521 : if (expr == error_mark_node)
623 : return error_mark_node;
624 :
625 39501 : if (!mark_addressable (expr, location))
626 0 : return error_mark_node;
627 :
628 39501 : if (ptrty == NULL || ptrty == error_mark_node)
629 37700 : ptrty = build_pointer_type (TREE_TYPE (expr));
630 :
631 39501 : return build_fold_addr_expr_with_type_loc (location, expr, ptrty);
632 : }
633 :
634 : tree
635 1205 : HIRCompileBase::compile_constant_expr (
636 : Context *ctx, HirId coercion_id, TyTy::BaseType *resolved_type,
637 : TyTy::BaseType *expected_type, const Resolver::CanonicalPath &canonical_path,
638 : HIR::Expr &const_value_expr, location_t locus, location_t expr_locus)
639 : {
640 1205 : HIRCompileBase c (ctx);
641 1205 : return c.compile_constant_item (coercion_id, resolved_type, expected_type,
642 : canonical_path, const_value_expr, locus,
643 1205 : expr_locus);
644 1205 : }
645 :
646 : tree
647 1205 : HIRCompileBase::query_compile_const_expr (Context *ctx, TyTy::BaseType *expr_ty,
648 : HIR::Expr &const_value_expr)
649 : {
650 1205 : HIRCompileBase c (ctx);
651 :
652 1205 : ctx->push_const_context ();
653 :
654 1205 : HirId expr_id = const_value_expr.get_mappings ().get_hirid ();
655 1205 : location_t locus = const_value_expr.get_locus ();
656 1205 : tree capacity_expr = HIRCompileBase::compile_constant_expr (
657 1205 : ctx, expr_id, expr_ty, expr_ty, Resolver::CanonicalPath::create_empty (),
658 : const_value_expr, locus, locus);
659 :
660 1205 : ctx->pop_const_context ();
661 :
662 1205 : return fold_expr (capacity_expr);
663 1205 : }
664 :
665 : tree
666 14267 : HIRCompileBase::indirect_expression (tree expr, location_t locus)
667 : {
668 14267 : if (expr == error_mark_node)
669 : return error_mark_node;
670 :
671 14267 : return build_fold_indirect_ref_loc (locus, expr);
672 : }
673 :
674 : void
675 13144 : HIRCompileBase::compile_function_body (tree fndecl,
676 : HIR::BlockExpr &function_body,
677 : TyTy::BaseType *fn_return_ty)
678 : {
679 27778 : for (auto &s : function_body.get_statements ())
680 : {
681 14634 : auto compiled_expr = CompileStmt::Compile (s.get (), ctx);
682 14634 : if (compiled_expr != nullptr)
683 : {
684 5211 : tree s = convert_to_void (compiled_expr, ICV_STATEMENT);
685 5211 : ctx->add_statement (s);
686 : }
687 : }
688 :
689 13144 : if (function_body.has_expr ())
690 : {
691 10593 : location_t locus = function_body.get_final_expr ().get_locus ();
692 10593 : tree return_value
693 10593 : = CompileExpr::Compile (function_body.get_final_expr (), ctx);
694 :
695 : // we can only return this if non unit value return type
696 10593 : if (!fn_return_ty->is_unit ())
697 : {
698 9451 : HirId id = function_body.get_mappings ().get_hirid ();
699 9451 : location_t lvalue_locus = function_body.get_locus ();
700 9451 : location_t rvalue_locus = locus;
701 :
702 9451 : TyTy::BaseType *expected = fn_return_ty;
703 9451 : TyTy::BaseType *actual = nullptr;
704 9451 : bool ok = ctx->get_tyctx ()->lookup_type (
705 9451 : function_body.expr->get_mappings ().get_hirid (), &actual);
706 9451 : rust_assert (ok);
707 :
708 9451 : return_value = coercion_site (id, return_value, actual, expected,
709 : lvalue_locus, rvalue_locus);
710 :
711 9451 : CompileDrop (ctx).emit_current_scope_drop_calls ();
712 :
713 9451 : tree return_stmt
714 9451 : = Backend::return_statement (fndecl, return_value, locus);
715 9451 : ctx->add_statement (return_stmt);
716 : }
717 : else
718 : {
719 : // just add the stmt expression
720 1142 : ctx->add_statement (return_value);
721 :
722 : // now just return unit expression
723 1142 : tree unit_expr = unit_expression (locus);
724 1142 : tree return_stmt
725 1142 : = Backend::return_statement (fndecl, unit_expr, locus);
726 1142 : ctx->add_statement (return_stmt);
727 : }
728 : }
729 2551 : else if (fn_return_ty->is_unit ())
730 : {
731 : // we can only do this if the function is of unit type otherwise other
732 : // errors should have occurred
733 2351 : location_t locus = function_body.get_locus ();
734 2351 : tree return_value = unit_expression (locus);
735 2351 : CompileDrop (ctx).emit_current_scope_drop_calls ();
736 2351 : tree return_stmt
737 2351 : = Backend::return_statement (fndecl, return_value, locus);
738 2351 : ctx->add_statement (return_stmt);
739 : }
740 13144 : }
741 :
742 : static ABI
743 13050 : get_abi (const AST::AttrVec &outer_attrs,
744 : const HIR::FunctionQualifiers &qualifiers)
745 : {
746 13050 : bool is_proc_macro = std::any_of (outer_attrs.cbegin (), outer_attrs.cend (),
747 15616 : [] (const AST::Attribute &attr) {
748 15616 : auto path = attr.get_path ().as_string ();
749 15616 : return path == "proc_macro"
750 15616 : || path == "proc_macro_derive"
751 31232 : || path == "proc_macro_attribute";
752 15616 : });
753 :
754 13050 : return is_proc_macro ? ABI::CDECL : qualifiers.get_abi ();
755 : }
756 :
757 : tree
758 13050 : HIRCompileBase::compile_function (
759 : bool is_root_item, const std::string &fn_name,
760 : tl::optional<HIR::SelfParam> &self_param,
761 : std::vector<HIR::FunctionParam> &function_params,
762 : const HIR::FunctionQualifiers &qualifiers, HIR::Visibility &visibility,
763 : AST::AttrVec &outer_attrs, location_t locus, HIR::BlockExpr *function_body,
764 : const Resolver::CanonicalPath &canonical_path, TyTy::FnType *fntype)
765 : {
766 13050 : tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype);
767 13050 : std::string ir_symbol_name
768 13050 : = canonical_path.get () + fntype->subst_as_string ();
769 :
770 13050 : rust_debug_loc (locus, "--> Compiling [%s] - %s", ir_symbol_name.c_str (),
771 13050 : fntype->get_name ().c_str ());
772 :
773 : // we don't mangle the main fn since we haven't implemented the main shim
774 3930 : bool is_main_fn = fn_name.compare ("main") == 0 && is_root_item
775 16978 : && canonical_path.size () <= 2;
776 3927 : if (is_main_fn)
777 : {
778 3927 : rust_assert (!main_identifier_node);
779 : /* So that 'MAIN_NAME_P' works. */
780 3927 : main_identifier_node = get_identifier (ir_symbol_name.c_str ());
781 : }
782 : // Local name because fn_name is not mutable.
783 13050 : std::string asm_name = fn_name;
784 :
785 : // conditionally mangle the function name
786 13050 : bool should_mangle = true;
787 :
788 28666 : auto get_export_name = [] (AST::Attribute &attr) {
789 15616 : return attr.get_path ().as_string () == Values::Attributes::EXPORT_NAME;
790 : };
791 13050 : auto export_name_attr
792 13050 : = std::find_if (outer_attrs.begin (), outer_attrs.end (), get_export_name);
793 :
794 13050 : tl::optional<std::string> backend_asm_name = tl::nullopt;
795 :
796 13050 : if (export_name_attr != outer_attrs.end ())
797 : {
798 1 : asm_name
799 1 : = Analysis::Attributes::extract_string_literal (*export_name_attr)
800 1 : .value (); // Checked within attribute checker
801 1 : backend_asm_name = asm_name;
802 1 : should_mangle = false;
803 : }
804 :
805 13050 : unsigned int flags = 0;
806 13050 : tree fndecl = Backend::function (compiled_fn_type, ir_symbol_name,
807 13050 : backend_asm_name, flags, locus);
808 :
809 13050 : setup_fndecl (fndecl, is_main_fn, fntype->has_substitutions_defined (),
810 : visibility, qualifiers, outer_attrs);
811 13050 : setup_abi_options (fndecl, get_abi (outer_attrs, qualifiers));
812 :
813 13050 : should_mangle &= should_mangle_item (fndecl);
814 13050 : if (!is_main_fn && should_mangle)
815 9120 : asm_name = ctx->mangle_item (fntype, canonical_path);
816 13050 : SET_DECL_ASSEMBLER_NAME (fndecl,
817 : get_identifier_with_length (asm_name.data (),
818 : asm_name.length ()));
819 :
820 : // insert into the context
821 13050 : ctx->insert_function_decl (fntype, fndecl);
822 :
823 : // setup the params
824 13050 : TyTy::BaseType *tyret = fntype->get_return_type ();
825 13050 : std::vector<Bvariable *> param_vars;
826 13050 : if (self_param)
827 : {
828 11002 : rust_assert (fntype->is_method ());
829 5501 : TyTy::BaseType *self_tyty_lookup = fntype->get_self_type ();
830 :
831 5501 : tree self_type = TyTyResolveCompile::compile (ctx, self_tyty_lookup);
832 5501 : Bvariable *compiled_self_param
833 5501 : = CompileSelfParam::compile (ctx, fndecl, self_param.value (),
834 5501 : self_type, self_param->get_locus ());
835 :
836 5501 : param_vars.push_back (compiled_self_param);
837 5501 : ctx->insert_var_decl (self_param->get_mappings ().get_hirid (),
838 : compiled_self_param);
839 : }
840 :
841 : // offset from + 1 for the TyTy::FnType being used when this is a method to
842 : // skip over Self on the FnType
843 13050 : bool is_method = self_param.has_value ();
844 13050 : size_t i = is_method ? 1 : 0;
845 19363 : for (auto &referenced_param : function_params)
846 : {
847 6313 : auto &tyty_param = fntype->param_at (i++);
848 6313 : auto param_tyty = tyty_param.get_type ();
849 6313 : auto compiled_param_type = TyTyResolveCompile::compile (ctx, param_tyty);
850 :
851 6313 : location_t param_locus = referenced_param.get_locus ();
852 6313 : Bvariable *compiled_param_var
853 6313 : = CompileFnParam::compile (ctx, fndecl, referenced_param,
854 6313 : compiled_param_type, param_locus);
855 :
856 6313 : param_vars.push_back (compiled_param_var);
857 :
858 6313 : const HIR::Pattern ¶m_pattern = referenced_param.get_param_name ();
859 6313 : ctx->insert_var_decl (param_pattern.get_mappings ().get_hirid (),
860 : compiled_param_var);
861 : }
862 :
863 13050 : if (!Backend::function_set_parameters (fndecl, param_vars))
864 0 : return error_mark_node;
865 :
866 13050 : tree enclosing_scope = NULL_TREE;
867 13050 : location_t start_location = function_body->get_locus ();
868 13050 : location_t end_location = function_body->get_end_locus ();
869 :
870 13050 : tree code_block = Backend::block (fndecl, enclosing_scope, {} /*locals*/,
871 : start_location, end_location);
872 13050 : ctx->push_block (code_block);
873 :
874 13050 : Bvariable *return_address = nullptr;
875 13050 : tree return_type = TyTyResolveCompile::compile (ctx, tyret);
876 :
877 13050 : bool address_is_taken = false;
878 13050 : tree ret_var_stmt = NULL_TREE;
879 13050 : return_address
880 13050 : = Backend::temporary_variable (fndecl, code_block, return_type, NULL,
881 : address_is_taken, locus, &ret_var_stmt);
882 :
883 13050 : ctx->add_statement (ret_var_stmt);
884 :
885 13050 : ctx->push_fn (fndecl, return_address, tyret);
886 13050 : compile_function_body (fndecl, *function_body, tyret);
887 13050 : tree bind_tree = ctx->pop_block ();
888 :
889 13050 : gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR);
890 13050 : DECL_SAVED_TREE (fndecl) = bind_tree;
891 :
892 13050 : ctx->pop_fn ();
893 13050 : ctx->push_function (fndecl);
894 :
895 13050 : if (DECL_DECLARED_CONSTEXPR_P (fndecl))
896 : {
897 695 : maybe_save_constexpr_fundef (fndecl);
898 : }
899 :
900 : return fndecl;
901 13051 : }
902 :
903 : tree
904 1771 : HIRCompileBase::compile_constant_item (
905 : HirId coercion_id, TyTy::BaseType *resolved_type,
906 : TyTy::BaseType *expected_type, const Resolver::CanonicalPath &canonical_path,
907 : HIR::Expr &const_value_expr, location_t locus, location_t expr_locus)
908 : {
909 1771 : const std::string &ident = canonical_path.get ();
910 :
911 1771 : tree type = TyTyResolveCompile::compile (ctx, resolved_type);
912 1771 : tree const_type = build_qualified_type (type, TYPE_QUAL_CONST);
913 :
914 1771 : tree actual_type = TyTyResolveCompile::compile (ctx, expected_type);
915 1771 : tree actual_const_type = build_qualified_type (actual_type, TYPE_QUAL_CONST);
916 :
917 1771 : bool is_block_expr
918 1771 : = const_value_expr.get_expression_type () == HIR::Expr::ExprType::Block;
919 :
920 : // in order to compile a block expr we want to reuse as much existing
921 : // machineary that we already have. This means the best approach is to
922 : // make a _fake_ function with a block so it can hold onto temps then
923 : // use our constexpr code to fold it completely or error_mark_node
924 1771 : Backend::typed_identifier receiver ("", NULL_TREE, UNKNOWN_LOCATION);
925 1771 : tree compiled_fn_type = Backend::function_type (
926 1771 : receiver, {}, {Backend::typed_identifier ("_", const_type, locus)}, NULL,
927 : locus);
928 1771 : tree fndecl
929 1771 : = Backend::function (compiled_fn_type, ident, tl::nullopt, 0, locus);
930 1771 : TREE_READONLY (fndecl) = 1;
931 :
932 1771 : tree enclosing_scope = NULL_TREE;
933 1771 : location_t start_location = const_value_expr.get_locus ();
934 1771 : location_t end_location = const_value_expr.get_locus ();
935 1771 : if (is_block_expr)
936 : {
937 42 : HIR::BlockExpr &function_body
938 : = static_cast<HIR::BlockExpr &> (const_value_expr);
939 42 : start_location = function_body.get_locus ();
940 42 : end_location = function_body.get_end_locus ();
941 : }
942 :
943 1771 : tree code_block = Backend::block (fndecl, enclosing_scope, {} /*locals*/,
944 : start_location, end_location);
945 1771 : ctx->push_block (code_block);
946 :
947 1771 : bool address_is_taken = false;
948 1771 : tree ret_var_stmt = NULL_TREE;
949 1771 : Bvariable *return_address
950 1771 : = Backend::temporary_variable (fndecl, code_block, const_type, NULL,
951 : address_is_taken, locus, &ret_var_stmt);
952 :
953 1771 : ctx->add_statement (ret_var_stmt);
954 1771 : ctx->push_fn (fndecl, return_address, resolved_type);
955 :
956 1771 : if (is_block_expr)
957 : {
958 42 : HIR::BlockExpr &function_body
959 : = static_cast<HIR::BlockExpr &> (const_value_expr);
960 42 : compile_function_body (fndecl, function_body, resolved_type);
961 : }
962 : else
963 : {
964 1729 : tree value = CompileExpr::Compile (const_value_expr, ctx);
965 :
966 1729 : tree return_expr
967 1729 : = Backend::return_statement (fndecl, value,
968 1729 : const_value_expr.get_locus ());
969 1729 : ctx->add_statement (return_expr);
970 : }
971 :
972 1771 : tree bind_tree = ctx->pop_block ();
973 :
974 1771 : gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR);
975 1771 : DECL_SAVED_TREE (fndecl) = bind_tree;
976 1771 : DECL_DECLARED_CONSTEXPR_P (fndecl) = 1;
977 1771 : maybe_save_constexpr_fundef (fndecl);
978 :
979 1771 : ctx->pop_fn ();
980 :
981 : // lets fold it into a call expr
982 1771 : tree call = build_call_array_loc (locus, const_type, fndecl, 0, NULL);
983 1771 : tree folded_expr = fold_expr (call);
984 :
985 : // coercion site
986 1771 : tree coerced = coercion_site (coercion_id, folded_expr, resolved_type,
987 : expected_type, locus, expr_locus);
988 :
989 1771 : return named_constant_expression (actual_const_type, ident, coerced, locus);
990 1771 : }
991 :
992 : tree
993 1771 : HIRCompileBase::named_constant_expression (tree type_tree,
994 : const std::string &name,
995 : tree const_val, location_t location)
996 : {
997 1771 : if (type_tree == error_mark_node || const_val == error_mark_node)
998 : return error_mark_node;
999 :
1000 1757 : tree name_tree = get_identifier_with_length (name.data (), name.length ());
1001 1757 : tree decl = build_decl (location, CONST_DECL, name_tree, type_tree);
1002 1757 : DECL_INITIAL (decl) = const_val;
1003 1757 : TREE_CONSTANT (decl) = 1;
1004 1757 : TREE_READONLY (decl) = 1;
1005 :
1006 1757 : rust_preserve_from_gc (decl);
1007 1757 : return decl;
1008 : }
1009 :
1010 : tree
1011 3957 : HIRCompileBase::resolve_method_address (TyTy::FnType *fntype,
1012 : TyTy::BaseType *receiver,
1013 : location_t expr_locus)
1014 : {
1015 3957 : rust_debug_loc (expr_locus, "resolve_method_address for %s and receiver %s",
1016 7914 : fntype->debug_str ().c_str (),
1017 3957 : receiver->debug_str ().c_str ());
1018 :
1019 3957 : DefId id = fntype->get_id ();
1020 3957 : rust_assert (id != UNKNOWN_DEFID);
1021 :
1022 : // Now we can try and resolve the address since this might be a forward
1023 : // declared function, generic function which has not be compiled yet or
1024 : // its an not yet trait bound function
1025 3957 : if (auto resolved_item = ctx->get_mappings ().lookup_defid (id))
1026 : {
1027 3030 : if (!fntype->has_substitutions_defined ())
1028 3030 : return CompileItem::compile (*resolved_item, ctx);
1029 :
1030 766 : return CompileItem::compile (*resolved_item, ctx, fntype);
1031 : }
1032 :
1033 : // it might be resolved to a trait item
1034 927 : HIR::TraitItem *trait_item
1035 927 : = ctx->get_mappings ().lookup_trait_item_defid (id).value ();
1036 927 : HIR::Trait *trait = ctx->get_mappings ().lookup_trait_item_mapping (
1037 927 : trait_item->get_mappings ().get_hirid ());
1038 :
1039 927 : Resolver::TraitReference *trait_ref
1040 927 : = &Resolver::TraitReference::error_node ();
1041 927 : bool ok = ctx->get_tyctx ()->lookup_trait_reference (
1042 927 : trait->get_mappings ().get_defid (), &trait_ref);
1043 927 : rust_assert (ok);
1044 :
1045 : // the type resolver can only resolve type bounds to their trait
1046 : // item so its up to us to figure out if this path should resolve
1047 : // to an trait-impl-block-item or if it can be defaulted to the
1048 : // trait-impl-item's definition
1049 927 : const HIR::PathIdentSegment segment (trait_item->trait_identifier ());
1050 927 : auto root = receiver->get_root ();
1051 927 : auto candidates
1052 927 : = Resolver::PathProbeImplTrait::Probe (root, segment, trait_ref);
1053 927 : if (candidates.size () == 0)
1054 : {
1055 : // this means we are defaulting back to the trait_item if
1056 : // possible
1057 131 : Resolver::TraitItemReference *trait_item_ref = nullptr;
1058 131 : bool ok = trait_ref->lookup_hir_trait_item (*trait_item, &trait_item_ref);
1059 131 : rust_assert (ok); // found
1060 131 : rust_assert (trait_item_ref->is_optional ()); // has definition
1061 :
1062 : // FIXME tl::optional means it has a definition and an associated
1063 : // block which can be a default implementation, if it does not
1064 : // contain an implementation we should actually return
1065 : // error_mark_node
1066 :
1067 131 : return CompileTraitItem::Compile (trait_item_ref->get_hir_trait_item (),
1068 : ctx, fntype, true, expr_locus);
1069 : }
1070 :
1071 796 : const Resolver::PathProbeCandidate *selectedCandidate = nullptr;
1072 796 : rust_debug_loc (expr_locus, "resolved to %lu candidates",
1073 796 : (unsigned long) candidates.size ());
1074 :
1075 : // filter for the possible case of non fn type items
1076 796 : std::set<Resolver::PathProbeCandidate> filteredFunctionCandidates;
1077 1631 : for (auto &candidate : candidates)
1078 : {
1079 835 : bool is_fntype = candidate.ty->get_kind () == TyTy::TypeKind::FNDEF;
1080 835 : if (!is_fntype)
1081 0 : continue;
1082 :
1083 835 : filteredFunctionCandidates.insert (candidate);
1084 : }
1085 :
1086 : // look for the exact fntype
1087 797 : for (auto &candidate : filteredFunctionCandidates)
1088 : {
1089 797 : if (filteredFunctionCandidates.size () == 1)
1090 : {
1091 : selectedCandidate = &candidate;
1092 : break;
1093 : }
1094 :
1095 40 : bool compatable
1096 40 : = Resolver::types_compatable (TyTy::TyWithLocation (candidate.ty),
1097 40 : TyTy::TyWithLocation (fntype), expr_locus,
1098 : false);
1099 :
1100 80 : rust_debug_loc (candidate.locus, "candidate: %s vs %s compatable=%s",
1101 80 : candidate.ty->debug_str ().c_str (),
1102 40 : fntype->debug_str ().c_str (),
1103 : compatable ? "true" : "false");
1104 :
1105 40 : if (compatable)
1106 : {
1107 : selectedCandidate = &candidate;
1108 : break;
1109 : }
1110 : }
1111 :
1112 : // FIXME eventually this should just return error mark node when we support
1113 : // going through all the passes
1114 796 : rust_assert (selectedCandidate != nullptr);
1115 :
1116 : // lets compile it
1117 796 : const Resolver::PathProbeCandidate &candidate = *selectedCandidate;
1118 796 : rust_assert (candidate.is_impl_candidate ());
1119 796 : rust_assert (candidate.ty->get_kind () == TyTy::TypeKind::FNDEF);
1120 796 : TyTy::FnType *candidate_call = static_cast<TyTy::FnType *> (candidate.ty);
1121 796 : HIR::ImplItem *impl_item = candidate.item.impl.impl_item;
1122 :
1123 796 : TyTy::BaseType *monomorphized = candidate_call;
1124 796 : if (candidate_call->needs_generic_substitutions ())
1125 : {
1126 102 : TyTy::BaseType *infer_impl_call
1127 102 : = candidate_call->infer_substitions (expr_locus);
1128 102 : monomorphized
1129 102 : = Resolver::unify_site (fntype->get_ref (),
1130 102 : TyTy::TyWithLocation (infer_impl_call),
1131 102 : TyTy::TyWithLocation (fntype), expr_locus);
1132 : }
1133 :
1134 796 : return CompileInherentImplItem::Compile (impl_item, ctx, monomorphized);
1135 1723 : }
1136 :
1137 : tree
1138 11250 : HIRCompileBase::unit_expression (location_t locus)
1139 : {
1140 11250 : tree unit_type = TyTyResolveCompile::get_unit_type (ctx);
1141 11250 : return Backend::constructor_expression (unit_type, false, {}, -1, locus);
1142 : }
1143 :
1144 : } // namespace Compile
1145 : } // namespace Rust
|