public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Rust front-end update 2023-04-05
@ 2023-04-05 14:02 arthur.cohen
  2023-04-05 14:02 ` [committed 01/88] gccrs: fatal_error_flag: Fix typo in error message arthur.cohen
                   ` (89 more replies)
  0 siblings, 90 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust

Hi everyone,

This patchset contains around 80 commits concerning the Rust frontend.

We have been hard at work trying to get the Rust core library to
compile, and hope to push more commits in the coming days as we try
and upstream a more recent version of gccrs. All of the team has done
a tremendous amount of work in the last few weeks, as we get closer
and closer to compiling libcore 1.49.

Our focus before GCC 13 releases is to improve the documentation of the
compiler and write more about the various flags used by the frontend,
which a user will need to understand and interact with.

The commits we will be pushing before GCC 13 releases will not contain
any "major breakthrough", as some functionality required to compile
libcore properly will still take some time to implement. Very often used
Rust macros such as `format_args` are defined within the core library,
and require a high amount of work on the compiler side.

Furthermore, integrating libcore as part of GCC will require
significant build system changes which are incompatible with the current
GCC stage. We will be making these changes as soon as possible and
integrate a version of libcore in GCC 14, as well as an implementation
of the libproc_macro crate. We will be submitting these patches and
pinging build system experts for extensive reviewing.

Thank you to everyone involved with the project, and to everyone who
has helped us.

All the best,

Arthur



^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 01/88] gccrs: fatal_error_flag: Fix typo in error message
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
@ 2023-04-05 14:02 ` arthur.cohen
  2023-04-05 14:02 ` [committed 02/88] gccrs: unsafe: check use of `target_feature` attribute arthur.cohen
                   ` (88 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* rust-session-manager.cc (Session::compile_crate): Fix typo.
---
 gcc/rust/rust-session-manager.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index 732aabe1f26..70b058ff992 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -438,7 +438,7 @@ Session::compile_crate (const char *filename)
       "manner by passing the following flag:\n\n"
       "`-frust-incomplete-and-experimental-compiler-do-not-use`\n\nor by "
       "defining the following environment variable (any value will "
-      "do)\n\nGCCRS_INCOMPLETE_AND_EXPERIMENTAL_COMPILER_DO_NOT_USE\n\nFor"
+      "do)\n\nGCCRS_INCOMPLETE_AND_EXPERIMENTAL_COMPILER_DO_NOT_USE\n\nFor "
       "cargo-gccrs, this means passing\n\n"
       "GCCRS_EXTRA_FLAGS=\"-frust-incomplete-and-experimental-compiler-do-not-"
       "use\"\n\nas an environment variable.");
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 02/88] gccrs: unsafe: check use of `target_feature` attribute
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
  2023-04-05 14:02 ` [committed 01/88] gccrs: fatal_error_flag: Fix typo in error message arthur.cohen
@ 2023-04-05 14:02 ` arthur.cohen
  2023-04-05 14:02 ` [committed 03/88] gccrs: Check for mutable references in const functions arthur.cohen
                   ` (87 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Prajwal S N

From: Prajwal S N <prajwalnadig21@gmail.com>

The `target_feature` attribute is for conditional compilation and may or
may not compile on all platforms. Using it requires an unsafe function
or block.

gcc/rust/ChangeLog:

	* checks/errors/rust-unsafe-checker.cc (check_target_attr): New function.
	(UnsafeChecker::check_function_attr): Call into `check_target_attr`.
	(UnsafeChecker::visit): Check for target_feature attributes.
	* checks/errors/rust-unsafe-checker.h: Add declarations.
	* util/rust-attributes.cc: Add attribute.

gcc/testsuite/ChangeLog:

	* rust/compile/unsafe11.rs: New test.

Signed-off-by: Prajwal S N <prajwalnadig21@gmail.com>
---
 gcc/rust/checks/errors/rust-unsafe-checker.cc | 29 ++++++++++++++++++-
 gcc/rust/checks/errors/rust-unsafe-checker.h  |  5 ++++
 gcc/rust/util/rust-attributes.cc              |  3 ++
 gcc/testsuite/rust/compile/unsafe11.rs        |  8 +++++
 4 files changed, 44 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/rust/compile/unsafe11.rs

diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc b/gcc/rust/checks/errors/rust-unsafe-checker.cc
index 94808632c04..3c369a2a81a 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.cc
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc
@@ -179,6 +179,31 @@ UnsafeChecker::check_function_call (HirId node_id, Location locus)
 		       locus);
 }
 
+static void
+check_target_attr (HIR::Function *fn, Location locus)
+{
+  if (std::any_of (fn->get_outer_attrs ().begin (),
+		   fn->get_outer_attrs ().end (),
+		   [] (const AST::Attribute &attr) {
+		     return attr.get_path ().as_string () == "target_feature";
+		   }))
+    rust_error_at (locus,
+		   "call to function with %<#[target_feature]%> requires "
+		   "unsafe function or block");
+}
+
+void
+UnsafeChecker::check_function_attr (HirId node_id, Location locus)
+{
+  if (unsafe_context.is_in_context ())
+    return;
+
+  auto maybe_fn = mappings.lookup_hir_item (node_id);
+
+  if (maybe_fn && maybe_fn->get_item_kind () == Item::ItemKind::Function)
+    check_target_attr (static_cast<Function *> (maybe_fn), locus);
+}
+
 void
 UnsafeChecker::visit (Lifetime &)
 {}
@@ -398,11 +423,13 @@ UnsafeChecker::visit (CallExpr &expr)
 
   rust_assert (mappings.lookup_node_to_hir (ref_node_id, &definition_id));
 
-  // At this point we have the function's HIR Id. There are two checks we
+  // At this point we have the function's HIR Id. There are three checks we
   // must perform:
   //     1. The function is an unsafe one
   //     2. The function is an extern one
+  //     3. The function is marked with a target_feature attribute
   check_function_call (definition_id, expr.get_locus ());
+  check_function_attr (definition_id, expr.get_locus ());
 
   if (expr.has_params ())
     for (auto &arg : expr.get_arguments ())
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.h b/gcc/rust/checks/errors/rust-unsafe-checker.h
index 9df44db06a9..2abd3a62351 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.h
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.h
@@ -46,6 +46,11 @@ private:
    */
   void check_function_call (HirId node_id, Location locus);
 
+  /**
+   * Check if any unsafe attributes are present on a function
+   */
+  void check_function_attr (HirId node_id, Location locus);
+
   StackedContexts<HirId> unsafe_context;
 
   Resolver::TypeCheckContext &context;
diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc
index 33f2c932d09..0458f6902b7 100644
--- a/gcc/rust/util/rust-attributes.cc
+++ b/gcc/rust/util/rust-attributes.cc
@@ -41,6 +41,9 @@ static const BuiltinAttrDefinition __definitions[]
      {"repr", CODE_GENERATION},
      {"path", EXPANSION},
      {"macro_use", NAME_RESOLUTION},
+     // FIXME: This is not implemented yet, see
+     // https://github.com/Rust-GCC/gccrs/issues/1475
+     {"target_feature", CODE_GENERATION},
      // From now on, these are reserved by the compiler and gated through
      // #![feature(rustc_attrs)]
      {"rustc_inherit_overflow_checks", CODE_GENERATION}};
diff --git a/gcc/testsuite/rust/compile/unsafe11.rs b/gcc/testsuite/rust/compile/unsafe11.rs
new file mode 100644
index 00000000000..c87902fcd5f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unsafe11.rs
@@ -0,0 +1,8 @@
+#[target_feature(sse)]
+fn foo() {
+    let a: usize = 0;
+}
+
+fn main() {
+    foo() // { dg-error "requires unsafe function or block" }
+}
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 03/88] gccrs: Check for mutable references in const functions
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
  2023-04-05 14:02 ` [committed 01/88] gccrs: fatal_error_flag: Fix typo in error message arthur.cohen
  2023-04-05 14:02 ` [committed 02/88] gccrs: unsafe: check use of `target_feature` attribute arthur.cohen
@ 2023-04-05 14:02 ` arthur.cohen
  2023-04-05 14:02 ` [committed 04/88] gccrs: rust: add bound parsing in parse_generic_arg arthur.cohen
                   ` (86 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Dave, Dave Evans

From: Dave <dme2223@gmail.com>

Use StackedContext instead. Fix error string

Signed-off-by: Dave Evans <dave@dmetwo.org>

(Squashed commits) Check for mutable references in const functions using StackedContext

gcc/rust/ChangeLog:

	* checks/errors/rust-const-checker.cc (ConstChecker::visit): Use StackedContext
	class.

gcc/testsuite/ChangeLog:

	* rust/compile/const10.rs: New test.

Signed-off-by: Dave Evans <dave@dmetwo.org>
---
 gcc/rust/checks/errors/rust-const-checker.cc | 8 ++++++--
 gcc/testsuite/rust/compile/const10.rs        | 3 +++
 2 files changed, 9 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/const10.rs

diff --git a/gcc/rust/checks/errors/rust-const-checker.cc b/gcc/rust/checks/errors/rust-const-checker.cc
index 576c1b170d6..7e31c9f9c28 100644
--- a/gcc/rust/checks/errors/rust-const-checker.cc
+++ b/gcc/rust/checks/errors/rust-const-checker.cc
@@ -898,8 +898,12 @@ ConstChecker::visit (RawPointerType &)
 {}
 
 void
-ConstChecker::visit (ReferenceType &)
-{}
+ConstChecker::visit (ReferenceType &type)
+{
+  if (const_context.is_in_context () && type.is_mut ())
+    rust_error_at (type.get_locus (),
+		   "mutable references are not allowed in constant functions");
+}
 
 void
 ConstChecker::visit (ArrayType &type)
diff --git a/gcc/testsuite/rust/compile/const10.rs b/gcc/testsuite/rust/compile/const10.rs
new file mode 100644
index 00000000000..9ab82744fbd
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const10.rs
@@ -0,0 +1,3 @@
+const fn foo (a: &mut i32) { // { dg-error "mutable references are not allowed in constant functions" }
+	*a = 1;
+}
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 04/88] gccrs: rust: add bound parsing in parse_generic_arg.
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (2 preceding siblings ...)
  2023-04-05 14:02 ` [committed 03/88] gccrs: Check for mutable references in const functions arthur.cohen
@ 2023-04-05 14:02 ` arthur.cohen
  2023-04-05 14:02 ` [committed 05/88] gccrs: Implement declarative macro 2.0 parser arthur.cohen
                   ` (85 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, mxlol233

From: mxlol233 <mxlol233@outlook.com>

gcc/rust/ChangeLog:

	* parse/rust-parse-impl.h (Parser::parse_generic_arg): Add proper bound parsing.

gcc/testsuite/ChangeLog:

	* rust/compile/bounds.rs: New test.

Signed-off-by: Xiao Ma <mxlol233@outlook.com>
---
 gcc/rust/parse/rust-parse-impl.h     | 17 +++++++++++++++++
 gcc/testsuite/rust/compile/bounds.rs | 10 ++++++++++
 2 files changed, 27 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/bounds.rs

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index cbd40efcc9b..959e0338a10 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -6198,6 +6198,23 @@ Parser<ManagedTokenSource>::parse_generic_arg ()
 	    else
 	      return AST::GenericArg::create_error ();
 	  }
+	else if (next_tok->get_id () == COLON)
+	  {
+	    lexer.skip_token (); // skip ident
+	    lexer.skip_token (); // skip colon
+
+	    auto tok = lexer.peek_token ();
+	    std::vector<std::unique_ptr<AST::TypeParamBound>> bounds
+	      = parse_type_param_bounds ();
+
+	    auto type = std::unique_ptr<AST::TraitObjectType> (
+	      new AST::TraitObjectType (std::move (bounds), tok->get_locus (),
+					false));
+	    if (type)
+	      return AST::GenericArg::create_type (std::move (type));
+	    else
+	      return AST::GenericArg::create_error ();
+	  }
 	lexer.skip_token ();
 	return AST::GenericArg::create_ambiguous (tok->get_str (),
 						  tok->get_locus ());
diff --git a/gcc/testsuite/rust/compile/bounds.rs b/gcc/testsuite/rust/compile/bounds.rs
new file mode 100644
index 00000000000..ecb10d81f65
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bounds.rs
@@ -0,0 +1,10 @@
+trait Foo {
+    type Bar;
+}
+
+trait Copy {}
+
+
+fn c<F: Foo<Bar: Foo>>() where F::Bar: Copy { // { dg-warning "function is never used: 'c'" }
+}
+
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 05/88] gccrs: Implement declarative macro 2.0 parser
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (3 preceding siblings ...)
  2023-04-05 14:02 ` [committed 04/88] gccrs: rust: add bound parsing in parse_generic_arg arthur.cohen
@ 2023-04-05 14:02 ` arthur.cohen
  2023-04-05 14:02 ` [committed 06/88] gccrs: Add name resolution to generic argument associated item bindings arthur.cohen
                   ` (84 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Raiki Tamura

From: Raiki Tamura <tamaron1203@gmail.com>

gcc/rust/ChangeLog:

	* ast/rust-ast-full-decls.h (class MacroItem): Remove forward declaration.
	* ast/rust-ast-full-test.cc (MacroRulesDefinition):
	Rework MacroRulesDefinition class
	* ast/rust-ast.h (class MacroItem): Remove abstract class.
	* ast/rust-item.h (class MacroItem): Remove forward declaration.
	* ast/rust-macro.h (class MacroItem): Likewise.
	(class MacroRulesDefinition): Add MacroKind enum.
	(class MacroInvocation): Fix inheritance.
	* lex/rust-token.h: Token "macro" is now used.
	* parse/rust-parse-impl.h (Parser::parse_item): Add handling for MACRO.
	(Parser::parse_vis_item): Call into parse_decl_macro_def.
	(Parser::parse_macro_item): Delete function.
	(Parser::parse_macro_rules_def): Return MBE macros only.
	(Parser::parse_decl_macro_def): New function.
	(Parser::parse_stmt): Handle MACRO token.
	(Parser::parse_stmt_or_expr_without_block): Call into parse_macro_rules_def.
	* parse/rust-parse.h: Declare new function.

gcc/testsuite/ChangeLog:

	* rust/compile/decl_macro1.rs: New test.
	* rust/compile/decl_macro2.rs: New test.
	* rust/compile/decl_macro3.rs: New test.
	* rust/compile/decl_macro4.rs: New test.
	* rust/compile/decl_macro5.rs: New test.
	* rust/compile/decl_macro6.rs: New test.
	* rust/compile/decl_macro7.rs: New test.
	* rust/execute/torture/decl_macro1.rs: New test.
	* rust/execute/torture/decl_macro2.rs: New test.
	* rust/execute/torture/decl_macro3.rs: New test.
	* rust/execute/torture/decl_macro4.rs: New test.

Signed-off-by: Raiki Tamura <tamaron1203@gmail.com>
---
 gcc/rust/ast/rust-ast-full-decls.h            |   1 -
 gcc/rust/ast/rust-ast-full-test.cc            |   1 +
 gcc/rust/ast/rust-ast.h                       |   5 -
 gcc/rust/ast/rust-item.h                      |   2 -
 gcc/rust/ast/rust-macro.h                     |  65 +++--
 gcc/rust/lex/rust-token.h                     |   2 +-
 gcc/rust/parse/rust-parse-impl.h              | 229 +++++++++++++-----
 gcc/rust/parse/rust-parse.h                   |   3 +-
 gcc/testsuite/rust/compile/decl_macro1.rs     |   2 +
 gcc/testsuite/rust/compile/decl_macro2.rs     |   2 +
 gcc/testsuite/rust/compile/decl_macro3.rs     |   4 +
 gcc/testsuite/rust/compile/decl_macro4.rs     |   5 +
 gcc/testsuite/rust/compile/decl_macro5.rs     |   5 +
 gcc/testsuite/rust/compile/decl_macro6.rs     |   5 +
 gcc/testsuite/rust/compile/decl_macro7.rs     |   4 +
 .../rust/execute/torture/decl_macro1.rs       |   8 +
 .../rust/execute/torture/decl_macro2.rs       |   8 +
 .../rust/execute/torture/decl_macro3.rs       |  15 ++
 .../rust/execute/torture/decl_macro4.rs       |  15 ++
 19 files changed, 301 insertions(+), 80 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/decl_macro1.rs
 create mode 100644 gcc/testsuite/rust/compile/decl_macro2.rs
 create mode 100644 gcc/testsuite/rust/compile/decl_macro3.rs
 create mode 100644 gcc/testsuite/rust/compile/decl_macro4.rs
 create mode 100644 gcc/testsuite/rust/compile/decl_macro5.rs
 create mode 100644 gcc/testsuite/rust/compile/decl_macro6.rs
 create mode 100644 gcc/testsuite/rust/compile/decl_macro7.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/decl_macro1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/decl_macro2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/decl_macro3.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/decl_macro4.rs

diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h
index 136a25ab9aa..58b12a1be0e 100644
--- a/gcc/rust/ast/rust-ast-full-decls.h
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -51,7 +51,6 @@ class Lifetime;
 class GenericParam;
 class LifetimeParam;
 class ConstGenericParam;
-class MacroItem;
 class TraitItem;
 class InherentImplItem;
 class TraitImplItem;
diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc
index 4f593dcbd49..280f59ffb16 100644
--- a/gcc/rust/ast/rust-ast-full-test.cc
+++ b/gcc/rust/ast/rust-ast-full-test.cc
@@ -1284,6 +1284,7 @@ MacroRulesDefinition::as_string () const
   // get outer attrs
   str += append_attributes (outer_attrs, OUTER);
 
+  // TODO: deal with macro_2_0
   str += "macro_rules!";
 
   str += rule_name;
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index aa86f2f9826..5f18233eb0f 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1350,11 +1350,6 @@ protected:
   }
 };
 
-// A macro item AST node - abstract base class
-class MacroItem : public Item
-{
-};
-
 // Item used in trait declarations - abstract base class
 class TraitItem
 {
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 7ea7b86562f..37ed2beabfc 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -4391,8 +4391,6 @@ protected:
   }
 };
 
-// Replaced with forward decls - defined in "rust-macro.h"
-class MacroItem;
 class MacroRulesDefinition;
 } // namespace AST
 } // namespace Rust
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index fc4b5b82fb5..bff8c7ac6fb 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -23,13 +23,11 @@
 #include "rust-ast.h"
 #include "rust-ast-fragment.h"
 #include "rust-location.h"
+#include "rust-item.h"
+#include "rust-make-unique.h"
 
 namespace Rust {
 namespace AST {
-
-// Decls as definitions moved to rust-ast.h
-class MacroItem;
-
 class MacroFragSpec
 {
 public:
@@ -446,8 +444,18 @@ public:
 };
 
 // A macro rules definition item AST node
-class MacroRulesDefinition : public MacroItem
+class MacroRulesDefinition : public VisItem
 {
+public:
+  enum MacroKind
+  {
+    // Macro by Example (legacy macro rules)
+    MBE,
+    // Declarative macros 2.0
+    DeclMacro,
+  };
+
+private:
   std::vector<Attribute> outer_attrs;
   Identifier rule_name;
   // MacroRulesDef rules_def;
@@ -460,6 +468,7 @@ class MacroRulesDefinition : public MacroItem
   std::function<Fragment (Location, MacroInvocData &)> associated_transcriber;
   // Since we can't compare std::functions, we need to use an extra boolean
   bool is_builtin_rule;
+  MacroKind kind;
 
   /**
    * Default function to use as an associated transcriber. This function should
@@ -479,27 +488,51 @@ class MacroRulesDefinition : public MacroItem
    * I am not aware of the implications of this decision. The rustc spec does
    * mention that using the same parser for macro definitions and invocations
    * is "extremely self-referential and non-intuitive". */
-
-public:
-  std::string as_string () const override;
-
   MacroRulesDefinition (Identifier rule_name, DelimType delim_type,
 			std::vector<MacroRule> rules,
-			std::vector<Attribute> outer_attrs, Location locus)
-    : outer_attrs (std::move (outer_attrs)), rule_name (std::move (rule_name)),
+			std::vector<Attribute> outer_attrs, Location locus,
+			MacroKind kind, Visibility vis)
+    : VisItem (std::move (vis), outer_attrs),
+      outer_attrs (std::move (outer_attrs)), rule_name (std::move (rule_name)),
       delim_type (delim_type), rules (std::move (rules)), locus (locus),
-      associated_transcriber (dummy_builtin), is_builtin_rule (false)
+      associated_transcriber (dummy_builtin), is_builtin_rule (false),
+      kind (kind)
   {}
 
   MacroRulesDefinition (
     Identifier builtin_name, DelimType delim_type,
-    std::function<Fragment (Location, MacroInvocData &)> associated_transcriber)
-    : outer_attrs (std::vector<Attribute> ()), rule_name (builtin_name),
+    std::function<Fragment (Location, MacroInvocData &)> associated_transcriber,
+    MacroKind kind, Visibility vis)
+    : VisItem (std::move (vis), std::vector<Attribute> ()),
+      outer_attrs (std::vector<Attribute> ()), rule_name (builtin_name),
       delim_type (delim_type), rules (std::vector<MacroRule> ()),
       locus (Location ()), associated_transcriber (associated_transcriber),
-      is_builtin_rule (true)
+      is_builtin_rule (true), kind (kind)
   {}
 
+public:
+  std::string as_string () const override;
+
+  static std::unique_ptr<MacroRulesDefinition>
+  mbe (Identifier rule_name, DelimType delim_type, std::vector<MacroRule> rules,
+       std::vector<Attribute> outer_attrs, Location locus)
+  {
+    return Rust::make_unique<MacroRulesDefinition> (
+      MacroRulesDefinition (rule_name, delim_type, rules, outer_attrs, locus,
+			    AST::MacroRulesDefinition::MacroKind::MBE,
+			    AST::Visibility::create_error ()));
+  }
+
+  static std::unique_ptr<MacroRulesDefinition>
+  decl_macro (Identifier rule_name, std::vector<MacroRule> rules,
+	      std::vector<Attribute> outer_attrs, Location locus,
+	      Visibility vis)
+  {
+    return Rust::make_unique<MacroRulesDefinition> (MacroRulesDefinition (
+      rule_name, AST::DelimType::CURLY, rules, outer_attrs, locus,
+      AST::MacroRulesDefinition::MacroKind::DeclMacro, vis));
+  }
+
   void accept_vis (ASTVisitor &vis) override;
 
   // Invalid if rule name is empty, so base stripping on that.
@@ -549,7 +582,7 @@ protected:
  * compile time */
 class MacroInvocation : public TypeNoBounds,
 			public Pattern,
-			public MacroItem,
+			public Item,
 			public TraitItem,
 			public TraitImplItem,
 			public InherentImplItem,
diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h
index 18f1afa664b..0fc55a20beb 100644
--- a/gcc/rust/lex/rust-token.h
+++ b/gcc/rust/lex/rust-token.h
@@ -171,7 +171,7 @@ enum PrimitiveCoreType
   RS_TOKEN_KEYWORD (IN, "in")                                                  \
   RS_TOKEN_KEYWORD (LET, "let")                                                \
   RS_TOKEN_KEYWORD (LOOP, "loop")                                              \
-  RS_TOKEN_KEYWORD (MACRO, "macro") /* unused */                               \
+  RS_TOKEN_KEYWORD (MACRO, "macro")                                            \
   RS_TOKEN_KEYWORD (MATCH_TOK, "match")                                        \
   RS_TOKEN_KEYWORD (MOD, "mod")                                                \
   RS_TOKEN_KEYWORD (MOVE, "move")                                              \
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 959e0338a10..d71bafded63 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -1032,11 +1032,6 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement)
 
   // parse outer attributes for item
   AST::AttrVec outer_attrs = parse_outer_attributes ();
-
-  // TODO: decide how to deal with VisItem vs MacroItem dichotomy
-  /* best current solution: catch all keywords that would imply a VisItem in a
-   * switch and have MacroItem as a last resort */
-
   const_TokenPtr t = lexer.peek_token ();
 
   switch (t->get_id ())
@@ -1064,6 +1059,7 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement)
     case STATIC_TOK:
     case TRAIT:
     case IMPL:
+    case MACRO:
     /* TODO: implement union keyword but not really because of
      * context-dependence crappy hack way to parse a union written below to
      * separate it from the good code. */
@@ -1078,7 +1074,7 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement)
     case CRATE:
     case DOLLAR_SIGN:
       // almost certainly macro invocation semi
-      return parse_macro_item (std::move (outer_attrs));
+      return parse_macro_invocation_semi (std::move (outer_attrs));
       break;
     // crappy hack to do union "keyword"
     case IDENTIFIER:
@@ -1092,19 +1088,18 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement)
       else if (t->get_str () == "macro_rules")
 	{
 	  // macro_rules! macro item
-	  return parse_macro_item (std::move (outer_attrs));
+	  return parse_macro_rules_def (std::move (outer_attrs));
 	}
       else if (lexer.peek_token (1)->get_id () == SCOPE_RESOLUTION
 	       || lexer.peek_token (1)->get_id () == EXCLAM)
 	{
 	  /* path (probably) or macro invocation, so probably a macro invocation
 	   * semi */
-	  return parse_macro_item (std::move (outer_attrs));
+	  return parse_macro_invocation_semi (std::move (outer_attrs));
 	}
       gcc_fallthrough ();
     default:
       // otherwise unrecognised
-      // return parse_macro_item(std::move(outer_attrs));
       add_error (Error (t->get_locus (),
 			"unrecognised token %qs for start of %s",
 			t->get_token_description (),
@@ -1335,6 +1330,8 @@ Parser<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs)
 	  lexer.skip_token (1); // TODO: is this right thing to do?
 	  return nullptr;
 	}
+    case MACRO:
+      return parse_decl_macro_def (std::move (vis), std::move (outer_attrs));
     default:
       // otherwise vis item clearly doesn't exist, which is not an error
       // has a catch-all post-switch return to allow other breaks to occur
@@ -1343,42 +1340,6 @@ Parser<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs)
   return nullptr;
 }
 
-// Parses a MacroItem (either a MacroInvocationSemi or MacroRulesDefinition).
-template <typename ManagedTokenSource>
-std::unique_ptr<AST::MacroItem>
-Parser<ManagedTokenSource>::parse_macro_item (AST::AttrVec outer_attrs)
-{
-  const_TokenPtr t = lexer.peek_token ();
-
-  /* dodgy way of detecting macro due to weird context-dependence thing.
-   * probably can be improved */
-  // TODO: ensure that string compare works properly
-  if (t->get_id () == IDENTIFIER && t->get_str () == "macro_rules")
-    {
-      return parse_macro_rules_def (std::move (outer_attrs));
-    }
-  else
-    {
-      // DEBUG: TODO: remove
-      rust_debug (
-	"DEBUG - parse_macro_item called and token is not macro_rules");
-      if (t->get_id () == IDENTIFIER)
-	{
-	  rust_debug ("just add to last error: token is not macro_rules and is "
-		      "instead '%s'",
-		      t->get_str ().c_str ());
-	}
-      else
-	{
-	  rust_debug ("just add to last error: token is not macro_rules and is "
-		      "not an identifier either - it is '%s'",
-		      t->get_token_description ());
-	}
-
-      return parse_macro_invocation_semi (std::move (outer_attrs));
-    }
-}
-
 // Parses a macro rules definition syntax extension whatever thing.
 template <typename ManagedTokenSource>
 std::unique_ptr<AST::MacroRulesDefinition>
@@ -1512,16 +1473,16 @@ Parser<ManagedTokenSource>::parse_macro_rules_def (AST::AttrVec outer_attrs)
 	    {
 	      // as this is the end, allow recovery (probably) - may change
 	      return std::unique_ptr<AST::MacroRulesDefinition> (
-		new AST::MacroRulesDefinition (
+		AST::MacroRulesDefinition::mbe (
 		  std::move (rule_name), delim_type, std::move (macro_rules),
 		  std::move (outer_attrs), macro_locus));
 	    }
 	}
 
       return std::unique_ptr<AST::MacroRulesDefinition> (
-	new AST::MacroRulesDefinition (std::move (rule_name), delim_type,
-				       std::move (macro_rules),
-				       std::move (outer_attrs), macro_locus));
+	AST::MacroRulesDefinition::mbe (std::move (rule_name), delim_type,
+					std::move (macro_rules),
+					std::move (outer_attrs), macro_locus));
     }
   else
     {
@@ -1541,6 +1502,165 @@ Parser<ManagedTokenSource>::parse_macro_rules_def (AST::AttrVec outer_attrs)
     }
 }
 
+// Parses a declarative macro 2.0 definition.
+template <typename ManagedTokenSource>
+std::unique_ptr<AST::MacroRulesDefinition>
+Parser<ManagedTokenSource>::parse_decl_macro_def (AST::Visibility vis,
+						  AST::AttrVec outer_attrs)
+{
+  // ensure that first token is identifier saying "macro"
+  const_TokenPtr t = lexer.peek_token ();
+  if (t->get_id () != MACRO)
+    {
+      Error error (
+	t->get_locus (),
+	"declarative macro definition does not start with %<macro%>");
+      add_error (std::move (error));
+
+      // skip after somewhere?
+      return nullptr;
+    }
+  lexer.skip_token ();
+  Location macro_locus = t->get_locus ();
+
+  // parse macro name
+  const_TokenPtr ident_tok = expect_token (IDENTIFIER);
+  if (ident_tok == nullptr)
+    {
+      return nullptr;
+    }
+  Identifier rule_name = ident_tok->get_str ();
+
+  t = lexer.peek_token ();
+  if (t->get_id () == LEFT_PAREN)
+    {
+      // single definiton of macro rule
+      // e.g. `macro foo($e:expr) {}`
+
+      // parse macro matcher
+      Location locus = lexer.peek_token ()->get_locus ();
+      AST::MacroMatcher matcher = parse_macro_matcher ();
+      if (matcher.is_error ())
+	return nullptr;
+
+      // check delimiter of macro matcher
+      if (matcher.get_delim_type () != AST::DelimType::PARENS)
+	{
+	  Error error (locus, "only parenthesis can be used for a macro "
+			      "matcher in declarative macro definition");
+	  add_error (std::move (error));
+	  return nullptr;
+	}
+
+      Location transcriber_loc = lexer.peek_token ()->get_locus ();
+      AST::DelimTokenTree delim_tok_tree = parse_delim_token_tree ();
+      AST::MacroTranscriber transcriber (delim_tok_tree, transcriber_loc);
+
+      if (transcriber.get_token_tree ().get_delim_type ()
+	  != AST::DelimType::CURLY)
+	{
+	  Error error (transcriber_loc,
+		       "only braces can be used for a macro transcriber "
+		       "in declarative macro definition");
+	  add_error (std::move (error));
+	  return nullptr;
+	}
+
+      AST::MacroRule macro_rule
+	= AST::MacroRule (std::move (matcher), std::move (transcriber), locus);
+      std::vector<AST::MacroRule> macro_rules;
+      macro_rules.push_back (macro_rule);
+
+      return std::unique_ptr<AST::MacroRulesDefinition> (
+	AST::MacroRulesDefinition::decl_macro (std::move (rule_name),
+					       macro_rules,
+					       std::move (outer_attrs),
+					       macro_locus, vis));
+    }
+  else if (t->get_id () == LEFT_CURLY)
+    {
+      // multiple definitions of macro rule separated by comma
+      // e.g. `macro foo { () => {}, ($e:expr) => {}, }`
+
+      // parse left curly
+      const_TokenPtr left_curly = expect_token (LEFT_CURLY);
+      if (left_curly == nullptr)
+	{
+	  return nullptr;
+	}
+
+      // parse actual macro rules
+      std::vector<AST::MacroRule> macro_rules;
+
+      // must be at least one macro rule, so parse it
+      AST::MacroRule initial_rule = parse_macro_rule ();
+      if (initial_rule.is_error ())
+	{
+	  Error error (
+	    lexer.peek_token ()->get_locus (),
+	    "required first macro rule in declarative macro definition "
+	    "could not be parsed");
+	  add_error (std::move (error));
+
+	  // skip after somewhere?
+	  return nullptr;
+	}
+      macro_rules.push_back (std::move (initial_rule));
+
+      t = lexer.peek_token ();
+      // parse macro rules
+      while (t->get_id () == COMMA)
+	{
+	  // skip comma
+	  lexer.skip_token ();
+
+	  // don't parse if end of macro rules
+	  if (token_id_matches_delims (lexer.peek_token ()->get_id (),
+				       AST::CURLY))
+	    {
+	      break;
+	    }
+
+	  // try to parse next rule
+	  AST::MacroRule rule = parse_macro_rule ();
+	  if (rule.is_error ())
+	    {
+	      Error error (
+		lexer.peek_token ()->get_locus (),
+		"failed to parse macro rule in declarative macro definition");
+	      add_error (std::move (error));
+
+	      return nullptr;
+	    }
+
+	  macro_rules.push_back (std::move (rule));
+
+	  t = lexer.peek_token ();
+	}
+
+      // parse right curly
+      const_TokenPtr right_curly = expect_token (RIGHT_CURLY);
+      if (right_curly == nullptr)
+	{
+	  return nullptr;
+	}
+
+      return std::unique_ptr<AST::MacroRulesDefinition> (
+	AST::MacroRulesDefinition::decl_macro (std::move (rule_name),
+					       std::move (macro_rules),
+					       std::move (outer_attrs),
+					       macro_locus, vis));
+    }
+  else
+    {
+      add_error (Error (t->get_locus (),
+			"unexpected token %qs - expecting delimiters "
+			"(for a declarative macro definiton)",
+			t->get_token_description ()));
+      return nullptr;
+    }
+}
+
 // Parses a semi-coloned (except for full block) macro invocation item.
 template <typename ManagedTokenSource>
 std::unique_ptr<AST::MacroInvocation>
@@ -6004,6 +6124,7 @@ Parser<ManagedTokenSource>::parse_stmt (ParseRestrictions restrictions)
     case STATIC_TOK:
     case TRAIT:
     case IMPL:
+    case MACRO:
     /* TODO: implement union keyword but not really because of
      * context-dependence crappy hack way to parse a union written below to
      * separate it from the good code. */
@@ -6019,7 +6140,7 @@ Parser<ManagedTokenSource>::parse_stmt (ParseRestrictions restrictions)
     case CRATE:
     case DOLLAR_SIGN:
       // almost certainly macro invocation semi
-      return parse_macro_item (std::move (outer_attrs));
+      return parse_macro_invocation_semi (std::move (outer_attrs));
       break;
     // crappy hack to do union "keyword"
     case IDENTIFIER:
@@ -6032,7 +6153,7 @@ Parser<ManagedTokenSource>::parse_stmt (ParseRestrictions restrictions)
       else if (t->get_str () == "macro_rules")
 	{
 	  // macro_rules! macro item
-	  return parse_macro_item (std::move (outer_attrs));
+	  return parse_macro_rules_def (std::move (outer_attrs));
 	}
       else if (lexer.peek_token (1)->get_id () == SCOPE_RESOLUTION
 	       || lexer.peek_token (1)->get_id () == EXCLAM)
@@ -6040,7 +6161,7 @@ Parser<ManagedTokenSource>::parse_stmt (ParseRestrictions restrictions)
 	  // FIXME: ensure doesn't take any expressions by mistake
 	  /* path (probably) or macro invocation, so probably a macro
 	   * invocation semi */
-	  return parse_macro_item (std::move (outer_attrs));
+	  return parse_macro_invocation_semi (std::move (outer_attrs));
 	}
       gcc_fallthrough ();
       // TODO: find out how to disable gcc "implicit fallthrough" warning
@@ -11711,8 +11832,8 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr_without_block ()
       else if (t->get_str () == "macro_rules")
 	{
 	  // macro_rules! macro item
-	  std::unique_ptr<AST::MacroItem> item (
-	    parse_macro_item (std::move (outer_attrs)));
+	  std::unique_ptr<AST::Item> item (
+	    parse_macro_rules_def (std::move (outer_attrs)));
 	  return ExprOrStmt (std::move (item));
 	}
       else if (lexer.peek_token (1)->get_id () == SCOPE_RESOLUTION
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 8449181b12f..5c0fcc3f174 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -197,6 +197,8 @@ private:
   AST::DelimTokenTree parse_delim_token_tree ();
   std::unique_ptr<AST::MacroRulesDefinition>
   parse_macro_rules_def (AST::AttrVec outer_attrs);
+  std::unique_ptr<AST::MacroRulesDefinition>
+  parse_decl_macro_def (AST::Visibility vis, AST::AttrVec outer_attrs);
   std::unique_ptr<AST::MacroInvocation>
   parse_macro_invocation_semi (AST::AttrVec outer_attrs);
   std::unique_ptr<AST::MacroInvocation>
@@ -209,7 +211,6 @@ private:
 
   // Top-level item-related
   std::unique_ptr<AST::VisItem> parse_vis_item (AST::AttrVec outer_attrs);
-  std::unique_ptr<AST::MacroItem> parse_macro_item (AST::AttrVec outer_attrs);
 
   // VisItem subclass-related
   std::unique_ptr<AST::Module> parse_module (AST::Visibility vis,
diff --git a/gcc/testsuite/rust/compile/decl_macro1.rs b/gcc/testsuite/rust/compile/decl_macro1.rs
new file mode 100644
index 00000000000..4a81a71e500
--- /dev/null
+++ b/gcc/testsuite/rust/compile/decl_macro1.rs
@@ -0,0 +1,2 @@
+#![feature(decl_macro)]
+macro m() {}
diff --git a/gcc/testsuite/rust/compile/decl_macro2.rs b/gcc/testsuite/rust/compile/decl_macro2.rs
new file mode 100644
index 00000000000..cbe19b0c14b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/decl_macro2.rs
@@ -0,0 +1,2 @@
+#![feature(decl_macro)]
+pub macro m($e: expr) { $e + $e }
diff --git a/gcc/testsuite/rust/compile/decl_macro3.rs b/gcc/testsuite/rust/compile/decl_macro3.rs
new file mode 100644
index 00000000000..d48da7835f9
--- /dev/null
+++ b/gcc/testsuite/rust/compile/decl_macro3.rs
@@ -0,0 +1,4 @@
+#![feature(decl_macro)]
+macro foo {
+    () => {}
+}
diff --git a/gcc/testsuite/rust/compile/decl_macro4.rs b/gcc/testsuite/rust/compile/decl_macro4.rs
new file mode 100644
index 00000000000..b8576cf0dd8
--- /dev/null
+++ b/gcc/testsuite/rust/compile/decl_macro4.rs
@@ -0,0 +1,5 @@
+#![feature(decl_macro)]
+macro foo {
+    () => { 0 },
+    ($n: expr) => { $n + 1 },
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/decl_macro5.rs b/gcc/testsuite/rust/compile/decl_macro5.rs
new file mode 100644
index 00000000000..b4ea20ffa74
--- /dev/null
+++ b/gcc/testsuite/rust/compile/decl_macro5.rs
@@ -0,0 +1,5 @@
+#![feature(decl_macro)]
+macro foo {
+    () => [],
+    ($h: expr, $(t: expr),*) => ($h),
+}
diff --git a/gcc/testsuite/rust/compile/decl_macro6.rs b/gcc/testsuite/rust/compile/decl_macro6.rs
new file mode 100644
index 00000000000..5c5e7002a98
--- /dev/null
+++ b/gcc/testsuite/rust/compile/decl_macro6.rs
@@ -0,0 +1,5 @@
+#![feature(decl_macro)]
+macro m {}
+// { dg-error "unexpected token .\}. - expecting delimiters .for a macro matcher." "" { target *-*-* } .-1 }
+// { dg-error "required first macro rule in declarative macro definition could not be parsed" "" { target *-*-* } .-2 }
+// { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 }
diff --git a/gcc/testsuite/rust/compile/decl_macro7.rs b/gcc/testsuite/rust/compile/decl_macro7.rs
new file mode 100644
index 00000000000..7327fb56782
--- /dev/null
+++ b/gcc/testsuite/rust/compile/decl_macro7.rs
@@ -0,0 +1,4 @@
+#![feature(decl_macro)]
+pub macro hello() [ "Hello" ]
+// { dg-error "only braces can be used for a macro transcriber in declarative macro definition" "" { target *-*-* } .-1 }
+// { dg-error "failed to parse item in crate" }
\ No newline at end of file
diff --git a/gcc/testsuite/rust/execute/torture/decl_macro1.rs b/gcc/testsuite/rust/execute/torture/decl_macro1.rs
new file mode 100644
index 00000000000..accc8b1db8e
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/decl_macro1.rs
@@ -0,0 +1,8 @@
+#![feature(decl_macro)]
+macro one() {
+    1
+}
+
+fn main() -> i32 {
+    one!() - 1
+}
diff --git a/gcc/testsuite/rust/execute/torture/decl_macro2.rs b/gcc/testsuite/rust/execute/torture/decl_macro2.rs
new file mode 100644
index 00000000000..f42b96262fe
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/decl_macro2.rs
@@ -0,0 +1,8 @@
+#![feature(decl_macro)]
+macro one {
+    () => { 1 }
+}
+
+fn main() -> i32 {
+    one!() - 1
+}
diff --git a/gcc/testsuite/rust/execute/torture/decl_macro3.rs b/gcc/testsuite/rust/execute/torture/decl_macro3.rs
new file mode 100644
index 00000000000..fa2cf793cf2
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/decl_macro3.rs
@@ -0,0 +1,15 @@
+#![feature(decl_macro)]
+macro add {
+    ($e:expr) => {
+        $e
+    },
+    ($h:expr, $($t:expr),*) => {
+        $h + add!($($t),*)
+    },
+}
+
+fn main() -> i32 {
+    let a = add!(1, 2, 3);
+
+    a - 6
+}
diff --git a/gcc/testsuite/rust/execute/torture/decl_macro4.rs b/gcc/testsuite/rust/execute/torture/decl_macro4.rs
new file mode 100644
index 00000000000..e700e63161d
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/decl_macro4.rs
@@ -0,0 +1,15 @@
+#![feature(decl_macro)]
+pub macro add {
+    ($e:expr) => {
+        $e
+    },
+    ($h:expr, $($t:expr),*) => {
+        $h + add!($($t),*)
+    },
+}
+
+fn main() -> i32 {
+    let a = add!(1, 2, 3);
+
+    a - 6
+}
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 06/88] gccrs: Add name resolution to generic argument associated item bindings
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (4 preceding siblings ...)
  2023-04-05 14:02 ` [committed 05/88] gccrs: Implement declarative macro 2.0 parser arthur.cohen
@ 2023-04-05 14:02 ` arthur.cohen
  2023-04-05 14:02 ` [committed 07/88] gccrs: Support associated type bound arguments arthur.cohen
                   ` (83 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

When specifying generic arguments to Traits we can also specify the
associated types using `<BindingName=i32>` syntax we need to add
name resolution to the type argument here and rely on the type
resolution pass to ensure the associated type exists and to setup the
associated types accordingly.

Addresses #1720

gcc/rust/ChangeLog:

	* resolve/rust-ast-resolve-type.cc (ResolveGenericArgs::go): Add name resolution to
	Trait items.

Signed-off-by: Philip Herron <herron.philip@googlemail.com>
---
 gcc/rust/resolve/rust-ast-resolve-type.cc | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc
index 16d05f3792b..28ab0697431 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-type.cc
@@ -589,6 +589,11 @@ ResolveGenericArgs::go (AST::GenericArgs &generic_args,
 
       resolver.resolve_disambiguated_generic (arg);
     }
+
+  for (auto &binding : generic_args.get_binding_args ())
+    {
+      ResolveType::go (binding.get_type ().get ());
+    }
 }
 
 } // namespace Resolver
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 07/88] gccrs: Support associated type bound arguments
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (5 preceding siblings ...)
  2023-04-05 14:02 ` [committed 06/88] gccrs: Add name resolution to generic argument associated item bindings arthur.cohen
@ 2023-04-05 14:02 ` arthur.cohen
  2023-04-05 14:02 ` [committed 08/88] gccrs: Reuse TypeCheckPattern on LetStmt's arthur.cohen
                   ` (82 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

This patch adds support for the GenercArgsBinding type, where you can
specify the associated types of a trait bound using `<Foo=i32>` style
syntax. Note that the type-resolution relys on the i32 impl for Add
as type resolution will resolve the `a+a` to the core::ops::Add method
so code generation will require this to exist.

I have ameded testsuite/rust/compile/bounds.rs as this code is wrongly
creating an HIR::GenericArgs with a trait-object type and causing issues.
the parsing is still correct but we dont have the mechanism to represent
this in AST and HIR properly. I think we will need a new HIR::GenericArgs
AssociatedTypeBindingBound or something similar. We are still lacking
bounds checking during are type coercions and unifications so running this
example using an f32 will wrongly pass type checking, this will need
addressed next.

Fixes #1720

gcc/rust/ChangeLog:

	* hir/tree/rust-hir-path.h: Add const get_identifier and get_type method.
	* typecheck/rust-hir-path-probe.h: Use new SubstitutionArgumentMappings constructor.
	* typecheck/rust-hir-trait-resolve.cc: Likewise.
	* typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise.
	* typecheck/rust-tyty-bounds.cc (TypeCheckBase::get_predicate_from_bound):
	Do not assert failure on size mismatch anymore.
	(TypeBoundPredicate::TypeBoundPredicate): Use new SubstitutionArgumentMappings constructor.
	(TypeBoundPredicate::operator=): Likewise.
	(TypeBoundPredicate::apply_generic_arguments): Likewise.
	(TypeBoundPredicateItem::get_tyty_for_receiver): Likewise.
	(TypeBoundPredicate::get_num_associated_bindings): Likewise.
	(TypeBoundPredicate::lookup_associated_type): Fix implementation for new system.
	(TypeBoundPredicate::get_associated_type_items): Likewise.
	* typecheck/rust-tyty.cc (SubstitutionRef::get_mappings_from_generic_args): Add new
	behavior.
	(SubstitutionRef::infer_substitions): Use new constructor and add comment.
	(SubstitutionRef::solve_missing_mappings_from_this): Use new constructor.
	* typecheck/rust-tyty.h: Define new constructors.

gcc/testsuite/ChangeLog:

	* rust/compile/bounds.rs: change to use -fsyntax-only
	* rust/execute/torture/issue-1720.rs: New test.

Signed-off-by: Philip Herron <herron.philip@googlemail.com>
---
 gcc/rust/hir/tree/rust-hir-path.h             |  4 +-
 gcc/rust/typecheck/rust-hir-path-probe.h      |  3 +-
 gcc/rust/typecheck/rust-hir-trait-resolve.cc  | 11 +--
 .../typecheck/rust-hir-type-check-expr.cc     | 12 ++-
 gcc/rust/typecheck/rust-tyty-bounds.cc        | 89 ++++++++++++++++---
 gcc/rust/typecheck/rust-tyty.cc               | 73 +++++++++++++--
 gcc/rust/typecheck/rust-tyty.h                | 48 ++++++++--
 gcc/testsuite/rust/compile/bounds.rs          |  8 +-
 .../rust/execute/torture/issue-1720.rs        | 26 ++++++
 9 files changed, 236 insertions(+), 38 deletions(-)
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-1720.rs

diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h
index 17eedb8d741..740de9391a0 100644
--- a/gcc/rust/hir/tree/rust-hir-path.h
+++ b/gcc/rust/hir/tree/rust-hir-path.h
@@ -105,9 +105,11 @@ public:
 
   std::string as_string () const;
 
-  Identifier get_identifier () const { return identifier; }
+  Identifier &get_identifier () { return identifier; }
+  const Identifier &get_identifier () const { return identifier; }
 
   std::unique_ptr<Type> &get_type () { return type; }
+  const std::unique_ptr<Type> &get_type () const { return type; }
 
   Location get_locus () const { return locus; }
 };
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h
index 6d6bcf8e7cd..bb8698ce0e1 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.h
+++ b/gcc/rust/typecheck/rust-hir-path-probe.h
@@ -362,7 +362,8 @@ protected:
 	mappings.push_back (TyTy::SubstitutionArg (param, receiver->clone ()));
 
 	Location locus; // FIXME
-	TyTy::SubstitutionArgumentMappings args (std::move (mappings), locus);
+	TyTy::SubstitutionArgumentMappings args (std::move (mappings), {},
+						 locus);
 	trait_item_tyty = SubstMapperInternal::Resolve (trait_item_tyty, args);
       }
 
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index 2ec9b2ef83e..85cad8e9c21 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -441,8 +441,8 @@ AssociatedImplTrait::setup_associated_types (
 	param_mappings[p.get_symbol ()] = a.get_tyty ()->get_ref ();
       };
 
-  TyTy::SubstitutionArgumentMappings infer_arguments (std::move (args), locus,
-						      param_subst_cb);
+  TyTy::SubstitutionArgumentMappings infer_arguments (std::move (args), {},
+						      locus, param_subst_cb);
   TyTy::BaseType *impl_self_infer
     = (associated_self->needs_generic_substitutions ())
 	? SubstMapperInternal::Resolve (associated_self, infer_arguments)
@@ -489,8 +489,9 @@ AssociatedImplTrait::setup_associated_types (
       hrtb_bound_arguments.push_back (r);
     }
 
-  rust_assert (impl_trait_predicate_args.size ()
-	       == hrtb_bound_arguments.size ());
+  if (impl_trait_predicate_args.size () != hrtb_bound_arguments.size ())
+    return;
+
   for (size_t i = 0; i < impl_trait_predicate_args.size (); i++)
     {
       TyTy::BaseType *a = impl_trait_predicate_args.at (i);
@@ -521,7 +522,7 @@ AssociatedImplTrait::setup_associated_types (
     }
 
   TyTy::SubstitutionArgumentMappings associated_type_args (
-    std::move (associated_arguments), locus);
+    std::move (associated_arguments), {}, locus);
 
   ImplTypeIterator iter (*impl, [&] (HIR::TypeAlias &type) {
     TraitItemReference *resolved_trait_item = nullptr;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 5c43cc8c7b4..46a14eb6e92 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -618,7 +618,8 @@ TypeCheckExpr::visit (HIR::RangeFromToExpr &expr)
   const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
   subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, unified));
 
-  TyTy::SubstitutionArgumentMappings subst (subst_mappings, expr.get_locus ());
+  TyTy::SubstitutionArgumentMappings subst (subst_mappings, {},
+					    expr.get_locus ());
   infered = SubstMapperInternal::Resolve (adt, subst);
 }
 
@@ -664,7 +665,8 @@ TypeCheckExpr::visit (HIR::RangeFromExpr &expr)
   const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
   subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, from_ty));
 
-  TyTy::SubstitutionArgumentMappings subst (subst_mappings, expr.get_locus ());
+  TyTy::SubstitutionArgumentMappings subst (subst_mappings, {},
+					    expr.get_locus ());
   infered = SubstMapperInternal::Resolve (adt, subst);
 }
 
@@ -709,7 +711,8 @@ TypeCheckExpr::visit (HIR::RangeToExpr &expr)
   const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
   subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, from_ty));
 
-  TyTy::SubstitutionArgumentMappings subst (subst_mappings, expr.get_locus ());
+  TyTy::SubstitutionArgumentMappings subst (subst_mappings, {},
+					    expr.get_locus ());
   infered = SubstMapperInternal::Resolve (adt, subst);
 }
 
@@ -792,7 +795,8 @@ TypeCheckExpr::visit (HIR::RangeFromToInclExpr &expr)
   const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
   subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, unified));
 
-  TyTy::SubstitutionArgumentMappings subst (subst_mappings, expr.get_locus ());
+  TyTy::SubstitutionArgumentMappings subst (subst_mappings, {},
+					    expr.get_locus ());
   infered = SubstMapperInternal::Resolve (adt, subst);
 }
 
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc
index 20a81ada6c4..30f7b0d02e3 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -145,11 +145,10 @@ TypeCheckBase::get_predicate_from_bound (HIR::TypePath &type_path)
       break;
     }
 
-  // FIXME
-  // I think this should really be just be if the !args.is_empty() because
-  // someone might wrongly apply generic arguments where they should not and
-  // they will be missing error diagnostics
-  if (predicate.requires_generic_args ())
+  // we try to apply generic arguments when they are non empty and or when the
+  // predicate requires them so that we get the relevant Foo expects x number
+  // arguments but got zero see test case rust/compile/traits12.rs
+  if (!args.is_empty () || predicate.requires_generic_args ())
     {
       // this is applying generic arguments to a trait reference
       predicate.apply_generic_arguments (&args);
@@ -222,7 +221,7 @@ TypeBoundPredicate::TypeBoundPredicate (const TypeBoundPredicate &other)
     }
 
   used_arguments
-    = SubstitutionArgumentMappings (copied_arg_mappings,
+    = SubstitutionArgumentMappings (copied_arg_mappings, {},
 				    other.used_arguments.get_locus ());
 }
 
@@ -258,7 +257,7 @@ TypeBoundPredicate::operator= (const TypeBoundPredicate &other)
     }
 
   used_arguments
-    = SubstitutionArgumentMappings (copied_arg_mappings,
+    = SubstitutionArgumentMappings (copied_arg_mappings, {},
 				    other.used_arguments.get_locus ());
 
   return *this;
@@ -331,6 +330,19 @@ TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args)
       if (ok && arg.get_tyty () != nullptr)
 	sub.fill_param_ty (subst_mappings, subst_mappings.get_locus ());
     }
+
+  // associated argument mappings
+  for (auto &it : subst_mappings.get_binding_args ())
+    {
+      std::string identifier = it.first;
+      TyTy::BaseType *type = it.second;
+
+      TypeBoundPredicateItem item = lookup_associated_item (identifier);
+      rust_assert (!item.is_error ());
+
+      const auto item_ref = item.get_raw_item ();
+      item_ref->associated_type_set (type);
+    }
 }
 
 bool
@@ -389,7 +401,8 @@ TypeBoundPredicateItem::get_tyty_for_receiver (const TyTy::BaseType *receiver)
       adjusted_mappings.push_back (std::move (arg));
     }
 
-  SubstitutionArgumentMappings adjusted (adjusted_mappings, gargs.get_locus (),
+  SubstitutionArgumentMappings adjusted (adjusted_mappings, {},
+					 gargs.get_locus (),
 					 gargs.get_subst_cb (),
 					 true /* trait-mode-flag */);
   return Resolver::SubstMapperInternal::Resolve (trait_item_tyty, adjusted);
@@ -421,6 +434,19 @@ TypeBoundPredicate::handle_substitions (
       p->set_ty_ref (s->get_ty_ref ());
     }
 
+  // associated argument mappings
+  for (auto &it : subst_mappings.get_binding_args ())
+    {
+      std::string identifier = it.first;
+      TyTy::BaseType *type = it.second;
+
+      TypeBoundPredicateItem item = lookup_associated_item (identifier);
+      rust_assert (!item.is_error ());
+
+      const auto item_ref = item.get_raw_item ();
+      item_ref->associated_type_set (type);
+    }
+
   // FIXME more error handling at some point
   // used_arguments = subst_mappings;
   // error_flag |= used_arguments.is_error ();
@@ -440,6 +466,13 @@ TypeBoundPredicate::requires_generic_args () const
 bool
 TypeBoundPredicate::contains_associated_types () const
 {
+  return get_num_associated_bindings () > 0;
+}
+
+size_t
+TypeBoundPredicate::get_num_associated_bindings () const
+{
+  size_t count = 0;
   auto trait_ref = get ();
   for (const auto &trait_item : trait_ref->get_trait_items ())
     {
@@ -447,9 +480,45 @@ TypeBoundPredicate::contains_associated_types () const
 	= trait_item.get_trait_item_type ()
 	  == Resolver::TraitItemReference::TraitItemType::TYPE;
       if (is_associated_type)
-	return true;
+	count++;
+    }
+  return count;
+}
+
+TypeBoundPredicateItem
+TypeBoundPredicate::lookup_associated_type (const std::string &search)
+{
+  TypeBoundPredicateItem item = lookup_associated_item (search);
+
+  // only need to check that it is infact an associated type because other wise
+  // if it was not found it will just be an error node anyway
+  if (!item.is_error ())
+    {
+      const auto raw = item.get_raw_item ();
+      if (raw->get_trait_item_type ()
+	  != Resolver::TraitItemReference::TraitItemType::TYPE)
+	return TypeBoundPredicateItem::error ();
+    }
+  return item;
+}
+
+std::vector<TypeBoundPredicateItem>
+TypeBoundPredicate::get_associated_type_items ()
+{
+  std::vector<TypeBoundPredicateItem> items;
+  auto trait_ref = get ();
+  for (const auto &trait_item : trait_ref->get_trait_items ())
+    {
+      bool is_associated_type
+	= trait_item.get_trait_item_type ()
+	  == Resolver::TraitItemReference::TraitItemType::TYPE;
+      if (is_associated_type)
+	{
+	  TypeBoundPredicateItem item (this, &trait_item);
+	  items.push_back (std::move (item));
+	}
     }
-  return false;
+  return items;
 }
 
 // trait item reference
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 71f0de1bbab..fd57a534562 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -674,14 +674,58 @@ SubstitutionParamMapping::override_context ()
 SubstitutionArgumentMappings
 SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args)
 {
+  std::map<std::string, BaseType *> binding_arguments;
   if (args.get_binding_args ().size () > 0)
     {
-      RichLocation r (args.get_locus ());
-      for (auto &binding : args.get_binding_args ())
-	r.add_range (binding.get_locus ());
+      if (supports_associated_bindings ())
+	{
+	  if (args.get_binding_args ().size () > get_num_associated_bindings ())
+	    {
+	      RichLocation r (args.get_locus ());
+
+	      rust_error_at (r,
+			     "generic item takes at most %lu type binding "
+			     "arguments but %lu were supplied",
+			     (unsigned long) get_num_associated_bindings (),
+			     (unsigned long) args.get_binding_args ().size ());
+	      return SubstitutionArgumentMappings::error ();
+	    }
 
-      rust_error_at (r, "associated type bindings are not allowed here");
-      return SubstitutionArgumentMappings::error ();
+	  for (auto &binding : args.get_binding_args ())
+	    {
+	      BaseType *resolved
+		= Resolver::TypeCheckType::Resolve (binding.get_type ().get ());
+	      if (resolved == nullptr
+		  || resolved->get_kind () == TyTy::TypeKind::ERROR)
+		{
+		  rust_error_at (binding.get_locus (),
+				 "failed to resolve type arguments");
+		  return SubstitutionArgumentMappings::error ();
+		}
+
+	      // resolve to relevant binding
+	      auto binding_item
+		= lookup_associated_type (binding.get_identifier ());
+	      if (binding_item.is_error ())
+		{
+		  rust_error_at (binding.get_locus (),
+				 "unknown associated type binding: %s",
+				 binding.get_identifier ().c_str ());
+		  return SubstitutionArgumentMappings::error ();
+		}
+
+	      binding_arguments[binding.get_identifier ()] = resolved;
+	    }
+	}
+      else
+	{
+	  RichLocation r (args.get_locus ());
+	  for (auto &binding : args.get_binding_args ())
+	    r.add_range (binding.get_locus ());
+
+	  rust_error_at (r, "associated type bindings are not allowed here");
+	  return SubstitutionArgumentMappings::error ();
+	}
     }
 
   // for inherited arguments
@@ -745,6 +789,7 @@ SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args)
 	  if (resolved->contains_type_parameters ())
 	    {
 	      SubstitutionArgumentMappings intermediate (mappings,
+							 binding_arguments,
 							 args.get_locus ());
 	      resolved = Resolver::SubstMapperInternal::Resolve (resolved,
 								 intermediate);
@@ -758,7 +803,8 @@ SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args)
 	}
     }
 
-  return SubstitutionArgumentMappings (mappings, args.get_locus ());
+  return SubstitutionArgumentMappings (mappings, binding_arguments,
+				       args.get_locus ());
 }
 
 BaseType *
@@ -791,7 +837,13 @@ SubstitutionRef::infer_substitions (Location locus)
 	}
     }
 
-  SubstitutionArgumentMappings infer_arguments (std::move (args), locus);
+  // FIXME do we need to add inference variables to all the possible bindings?
+  // it might just lead to inference variable hell not 100% sure if rustc does
+  // this i think the language might needs this to be explicitly set
+
+  SubstitutionArgumentMappings infer_arguments (std::move (args),
+						{} /* binding_arguments */,
+						locus);
   return handle_substitions (std::move (infer_arguments));
 }
 
@@ -835,7 +887,9 @@ SubstitutionRef::adjust_mappings_for_this (
   if (resolved_mappings.empty ())
     return SubstitutionArgumentMappings::error ();
 
-  return SubstitutionArgumentMappings (resolved_mappings, mappings.get_locus (),
+  return SubstitutionArgumentMappings (resolved_mappings,
+				       mappings.get_binding_args (),
+				       mappings.get_locus (),
 				       mappings.get_subst_cb (),
 				       mappings.trait_item_mode ());
 }
@@ -901,6 +955,7 @@ SubstitutionRef::solve_mappings_from_receiver_for_self (
     }
 
   return SubstitutionArgumentMappings (resolved_mappings,
+				       mappings.get_binding_args (),
 				       mappings.get_locus ());
 }
 
@@ -952,7 +1007,7 @@ SubstitutionRef::solve_missing_mappings_from_this (SubstitutionRef &ref,
       resolved_mappings.push_back (std::move (argument));
     }
 
-  return SubstitutionArgumentMappings (resolved_mappings, locus);
+  return SubstitutionArgumentMappings (resolved_mappings, {}, locus);
 }
 
 bool
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 0fd664c8d46..20a243fe980 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -675,16 +675,17 @@ class SubstitutionArgumentMappings
 {
 public:
   SubstitutionArgumentMappings (std::vector<SubstitutionArg> mappings,
+				std::map<std::string, BaseType *> binding_args,
 				Location locus,
 				ParamSubstCb param_subst_cb = nullptr,
 				bool trait_item_flag = false)
-    : mappings (mappings), locus (locus), param_subst_cb (param_subst_cb),
-      trait_item_flag (trait_item_flag)
+    : mappings (mappings), binding_args (binding_args), locus (locus),
+      param_subst_cb (param_subst_cb), trait_item_flag (trait_item_flag)
   {}
 
   SubstitutionArgumentMappings (const SubstitutionArgumentMappings &other)
-    : mappings (other.mappings), locus (other.locus),
-      param_subst_cb (other.param_subst_cb),
+    : mappings (other.mappings), binding_args (other.binding_args),
+      locus (other.locus), param_subst_cb (other.param_subst_cb),
       trait_item_flag (other.trait_item_flag)
   {}
 
@@ -692,6 +693,7 @@ public:
   operator= (const SubstitutionArgumentMappings &other)
   {
     mappings = other.mappings;
+    binding_args = other.binding_args;
     locus = other.locus;
     param_subst_cb = other.param_subst_cb;
     trait_item_flag = other.trait_item_flag;
@@ -705,7 +707,7 @@ public:
 
   static SubstitutionArgumentMappings error ()
   {
-    return SubstitutionArgumentMappings ({}, Location (), nullptr, false);
+    return SubstitutionArgumentMappings ({}, {}, Location (), nullptr, false);
   }
 
   bool is_error () const { return mappings.size () == 0; }
@@ -759,6 +761,16 @@ public:
 
   const std::vector<SubstitutionArg> &get_mappings () const { return mappings; }
 
+  std::map<std::string, BaseType *> &get_binding_args ()
+  {
+    return binding_args;
+  }
+
+  const std::map<std::string, BaseType *> &get_binding_args () const
+  {
+    return binding_args;
+  }
+
   std::string as_string () const
   {
     std::string buffer;
@@ -783,6 +795,7 @@ public:
 
 private:
   std::vector<SubstitutionArg> mappings;
+  std::map<std::string, BaseType *> binding_args;
   Location locus;
   ParamSubstCb param_subst_cb;
   bool trait_item_flag;
@@ -813,6 +826,24 @@ public:
     return buffer.empty () ? "" : "<" + buffer + ">";
   }
 
+  bool supports_associated_bindings () const
+  {
+    return get_num_associated_bindings () > 0;
+  }
+
+  // this is overridden in TypeBoundPredicate
+  // which support bindings we don't add them directly to the SubstitutionRef
+  // base class because this class represents the fn<X: Foo, Y: Bar>. The only
+  // construct which supports associated types
+  virtual size_t get_num_associated_bindings () const { return 0; }
+
+  // this is overridden in TypeBoundPredicate
+  virtual TypeBoundPredicateItem
+  lookup_associated_type (const std::string &search)
+  {
+    return TypeBoundPredicateItem::error ();
+  }
+
   size_t get_num_substitutions () const { return substitutions.size (); }
 
   std::vector<SubstitutionParamMapping> &get_substs () { return substitutions; }
@@ -1040,6 +1071,13 @@ public:
 
   DefId get_id () const { return reference; }
 
+  std::vector<TypeBoundPredicateItem> get_associated_type_items ();
+
+  size_t get_num_associated_bindings () const override final;
+
+  TypeBoundPredicateItem
+  lookup_associated_type (const std::string &search) override final;
+
 private:
   DefId reference;
   Location locus;
diff --git a/gcc/testsuite/rust/compile/bounds.rs b/gcc/testsuite/rust/compile/bounds.rs
index ecb10d81f65..57ff17ffcdc 100644
--- a/gcc/testsuite/rust/compile/bounds.rs
+++ b/gcc/testsuite/rust/compile/bounds.rs
@@ -1,10 +1,12 @@
+// { dg-options "-fsyntax-only" }
 trait Foo {
     type Bar;
 }
 
 trait Copy {}
 
-
-fn c<F: Foo<Bar: Foo>>() where F::Bar: Copy { // { dg-warning "function is never used: 'c'" }
+fn c<F: Foo<Bar: Foo>>()
+where
+    F::Bar: Copy,
+{
 }
-
diff --git a/gcc/testsuite/rust/execute/torture/issue-1720.rs b/gcc/testsuite/rust/execute/torture/issue-1720.rs
new file mode 100644
index 00000000000..771d7eec537
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1720.rs
@@ -0,0 +1,26 @@
+mod core {
+    mod ops {
+        #[lang = "add"]
+        pub trait Add<Rhs = Self> {
+            type Output;
+
+            fn add(self, rhs: Rhs) -> Self::Output;
+        }
+    }
+}
+
+impl core::ops::Add for i32 {
+    type Output = i32;
+
+    fn add(self, rhs: i32) -> Self::Output {
+        self + rhs
+    }
+}
+
+pub fn foo<T: core::ops::Add<Output = i32>>(a: T) -> i32 {
+    a + a
+}
+
+pub fn main() -> i32 {
+    foo(1) - 2
+}
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 08/88] gccrs: Reuse TypeCheckPattern on LetStmt's
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (6 preceding siblings ...)
  2023-04-05 14:02 ` [committed 07/88] gccrs: Support associated type bound arguments arthur.cohen
@ 2023-04-05 14:02 ` arthur.cohen
  2023-04-05 14:02 ` [committed 09/88] gccrs: Add get_locus function for abstract class MetaItemInner arthur.cohen
                   ` (81 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Owen Avery

From: Owen Avery <powerboat9.gamer@gmail.com>

Update Rust type-checking to reuse TypeCheckPattern on HIR::LetStmt's.
This will unify the paths and improve error handling.

gcc/rust/ChangeLog:

	* typecheck/rust-hir-type-check-stmt.cc (TypeCheckStmt::visit): Cleanup LetStmt
	type checking.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
---
 gcc/rust/typecheck/rust-hir-type-check-stmt.cc | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.cc b/gcc/rust/typecheck/rust-hir-type-check-stmt.cc
index 437782e8102..956249a7607 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-stmt.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.cc
@@ -82,7 +82,7 @@ TypeCheckStmt::visit (HIR::LetStmt &stmt)
 {
   infered = TyTy::TupleType::get_unit_type (stmt.get_mappings ().get_hirid ());
 
-  const HIR::Pattern &stmt_pattern = *stmt.get_pattern ();
+  HIR::Pattern &stmt_pattern = *stmt.get_pattern ();
   TyTy::BaseType *init_expr_ty = nullptr;
   Location init_expr_locus;
   if (stmt.has_init_expr ())
@@ -111,27 +111,25 @@ TypeCheckStmt::visit (HIR::LetStmt &stmt)
 		     TyTy::TyWithLocation (specified_ty, specified_ty_locus),
 		     TyTy::TyWithLocation (init_expr_ty, init_expr_locus),
 		     stmt.get_locus ());
-      context->insert_type (stmt_pattern.get_pattern_mappings (), specified_ty);
+      TypeCheckPattern::Resolve (&stmt_pattern, specified_ty);
     }
   else
     {
       // let x:i32;
       if (specified_ty != nullptr)
 	{
-	  context->insert_type (stmt_pattern.get_pattern_mappings (),
-				specified_ty);
+	  TypeCheckPattern::Resolve (&stmt_pattern, specified_ty);
 	}
       // let x = 123;
       else if (init_expr_ty != nullptr)
 	{
-	  context->insert_type (stmt_pattern.get_pattern_mappings (),
-				init_expr_ty);
+	  TypeCheckPattern::Resolve (&stmt_pattern, init_expr_ty);
 	}
       // let x;
       else
 	{
-	  context->insert_type (
-	    stmt_pattern.get_pattern_mappings (),
+	  TypeCheckPattern::Resolve (
+	    &stmt_pattern,
 	    new TyTy::InferType (
 	      stmt_pattern.get_pattern_mappings ().get_hirid (),
 	      TyTy::InferType::InferTypeKind::GENERAL, stmt.get_locus ()));
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 09/88] gccrs: Add get_locus function for abstract class MetaItemInner.
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (7 preceding siblings ...)
  2023-04-05 14:02 ` [committed 08/88] gccrs: Reuse TypeCheckPattern on LetStmt's arthur.cohen
@ 2023-04-05 14:02 ` arthur.cohen
  2023-04-05 14:02 ` [committed 10/88] gccrs: diagnostics: Add underline for tokens in diagnostics arthur.cohen
                   ` (80 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, mxlol233

From: mxlol233 <mxlol233@outlook.com>

This commit adds virtual function get_locus to base class MetaItemInner,
which is helpful when we need to print  diagnostics on some sub-classes of
MetaItemInner.

gcc/rust/ChangeLog:

	* ast/rust-ast.h: Add get_locus method.
	* ast/rust-expr.h: Likewise.
	* ast/rust-macro.h: Likewise.

Signed-off-by: Xiao Ma <mxlol233@outlook.com>
---
 gcc/rust/ast/rust-ast.h   |  2 ++
 gcc/rust/ast/rust-expr.h  |  8 ++++++++
 gcc/rust/ast/rust-macro.h | 12 ++++++++++++
 3 files changed, 22 insertions(+)

diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 5f18233eb0f..d30e6d494f2 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -630,6 +630,8 @@ public:
 
   virtual ~MetaItemInner ();
 
+  virtual Location get_locus () const = 0;
+
   virtual std::string as_string () const = 0;
 
   virtual void accept_vis (ASTVisitor &vis) = 0;
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index c58fae5e564..34bc6993ab6 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -150,6 +150,8 @@ public:
 
   std::string as_string () const override { return lit_expr.as_string (); }
 
+  Location get_locus () const override { return lit_expr.get_locus (); }
+
   void accept_vis (ASTVisitor &vis) override;
 
   bool check_cfg_predicate (const Session &session) const override;
@@ -178,6 +180,12 @@ public:
     return path.as_string () + " = " + lit.as_string ();
   }
 
+  // There are two Locations in MetaItemPathLit (path and lit_expr),
+  //  we have no idea use which of them, just simply return UNKNOWN_LOCATION
+  //  now.
+  // Maybe we will figure out when we really need the location in the future.
+  Location get_locus () const override { return Location (UNKNOWN_LOCATION); }
+
   void accept_vis (ASTVisitor &vis) override;
 
   bool check_cfg_predicate (const Session &session) const override;
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index bff8c7ac6fb..4226c6919ff 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -725,6 +725,8 @@ public:
     return path;
   }
 
+  Location get_locus () const override { return path.get_locus (); }
+
   bool check_cfg_predicate (const Session &session) const override;
 
   Attribute to_attribute () const override;
@@ -778,6 +780,8 @@ public:
 
   void accept_vis (ASTVisitor &vis) override;
 
+  Location get_locus () const override { return path.get_locus (); }
+
   bool check_cfg_predicate (const Session &session) const override;
 
   Attribute to_attribute () const override;
@@ -805,6 +809,8 @@ public:
 
   void accept_vis (ASTVisitor &vis) override;
 
+  Location get_locus () const override { return ident_locus; }
+
   bool check_cfg_predicate (const Session &session) const override;
 
   Attribute to_attribute () const override;
@@ -847,6 +853,8 @@ public:
     return std::unique_ptr<MetaNameValueStr> (clone_meta_item_inner_impl ());
   }
 
+  Location get_locus () const override { return ident_locus; }
+
   bool check_cfg_predicate (const Session &session) const override;
 
   Attribute to_attribute () const override;
@@ -885,6 +893,8 @@ public:
 
   void accept_vis (ASTVisitor &vis) override;
 
+  Location get_locus () const override { return ident_locus; }
+
   bool check_cfg_predicate (const Session &session) const override;
 
   Attribute to_attribute () const override;
@@ -919,6 +929,8 @@ public:
 
   void accept_vis (ASTVisitor &vis) override;
 
+  Location get_locus () const override { return ident_locus; }
+
   bool check_cfg_predicate (const Session &session) const override;
 
   Attribute to_attribute () const override;
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 10/88] gccrs: diagnostics: Add underline for tokens in diagnostics.
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (8 preceding siblings ...)
  2023-04-05 14:02 ` [committed 09/88] gccrs: Add get_locus function for abstract class MetaItemInner arthur.cohen
@ 2023-04-05 14:02 ` arthur.cohen
  2023-04-05 14:02 ` [committed 11/88] gccrs: Change how CompileVarDecl outputs Bvariable's arthur.cohen
                   ` (79 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, mxlol233

From: mxlol233 <mxlol233@outlook.com>

Currently, the diagnostics only point to the corresponding token's
start position by carets, and lack of underlines for full token.  This
commit add support for such underlines in diagnostics by encoding range
information in location_t.

gcc/rust/ChangeLog:

	* lex/rust-lex.cc (Lexer::build_token): Make location enclose entire token.
	(Lexer::parse_byte_char): Likewise.
	(Lexer::parse_byte_string): Likewise.
	(Lexer::parse_raw_byte_string): Likewise.
	(Lexer::parse_raw_identifier): Likewise.
	(Lexer::parse_string): Likewise.
	(Lexer::parse_identifier_or_keyword): Likewise.
	(Lexer::parse_raw_string): Likewise.
	(Lexer::parse_non_decimal_int_literal): Likewise.
	(Lexer::parse_decimal_int_or_float): Likewise.
	(Lexer::parse_char_or_lifetime): Likewise.

gcc/testsuite/ChangeLog:

	* rust/compile/diagnostic_underline.rs: New test.

Signed-off-by: Xiao Ma <mxlol233@outlook.com>
---
 gcc/rust/lex/rust-lex.cc                      | 57 +++++++++++++++++++
 .../rust/compile/diagnostic_underline.rs      | 15 +++++
 2 files changed, 72 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/diagnostic_underline.rs

diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index ac7ced540e6..9967cecb2e2 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -447,6 +447,7 @@ Lexer::build_token ()
 	      // match arm arrow
 	      skip_input ();
 	      current_column += 2;
+	      loc += 1;
 
 	      return Token::make (MATCH_ARROW, loc);
 	    }
@@ -455,6 +456,7 @@ Lexer::build_token ()
 	      // equality operator
 	      skip_input ();
 	      current_column += 2;
+	      loc += 1;
 
 	      return Token::make (EQUAL_EQUAL, loc);
 	    }
@@ -473,6 +475,7 @@ Lexer::build_token ()
 	      // return type specifier
 	      skip_input ();
 	      current_column += 2;
+	      loc += 1;
 
 	      return Token::make (RETURN_TYPE, loc);
 	    }
@@ -481,6 +484,7 @@ Lexer::build_token ()
 	      // minus-assign
 	      skip_input ();
 	      current_column += 2;
+	      loc += 1;
 
 	      return Token::make (MINUS_EQ, loc);
 	    }
@@ -496,6 +500,7 @@ Lexer::build_token ()
 	      // add-assign
 	      skip_input ();
 	      current_column += 2;
+	      loc += 1;
 
 	      return Token::make (PLUS_EQ, loc);
 	    }
@@ -517,6 +522,7 @@ Lexer::build_token ()
 	      // multiplication-assign
 	      skip_input ();
 	      current_column += 2;
+	      loc += 1;
 
 	      return Token::make (ASTERISK_EQ, loc);
 	    }
@@ -535,6 +541,7 @@ Lexer::build_token ()
 	      // division-assign
 	      skip_input ();
 	      current_column += 2;
+	      loc += 1;
 
 	      return Token::make (DIV_EQ, loc);
 	    }
@@ -602,6 +609,8 @@ Lexer::build_token ()
 	      start_line (current_line, max_column_hint);
 
 	      str.shrink_to_fit ();
+
+	      loc += str.size () - 1;
 	      if (is_inner)
 		return Token::make_inner_doc_comment (loc, std::move (str));
 	      else
@@ -756,6 +765,8 @@ Lexer::build_token ()
 		}
 
 	      str.shrink_to_fit ();
+
+	      loc += str.size () - 1;
 	      if (is_inner)
 		return Token::make_inner_doc_comment (loc, std::move (str));
 	      else
@@ -773,6 +784,7 @@ Lexer::build_token ()
 	      // modulo-assign
 	      skip_input ();
 	      current_column += 2;
+	      loc += 1;
 
 	      return Token::make (PERCENT_EQ, loc);
 	    }
@@ -788,6 +800,7 @@ Lexer::build_token ()
 	      // xor-assign?
 	      skip_input ();
 	      current_column += 2;
+	      loc += 1;
 
 	      return Token::make (CARET_EQ, loc);
 	    }
@@ -805,6 +818,7 @@ Lexer::build_token ()
 		  // left-shift assign
 		  skip_input (1);
 		  current_column += 3;
+		  loc += 2;
 
 		  return Token::make (LEFT_SHIFT_EQ, loc);
 		}
@@ -813,6 +827,7 @@ Lexer::build_token ()
 		  // left-shift
 		  skip_input ();
 		  current_column += 2;
+		  loc += 1;
 
 		  return Token::make (LEFT_SHIFT, loc);
 		}
@@ -822,6 +837,7 @@ Lexer::build_token ()
 	      // smaller than or equal to
 	      skip_input ();
 	      current_column += 2;
+	      loc += 1;
 
 	      return Token::make (LESS_OR_EQUAL, loc);
 	    }
@@ -840,6 +856,7 @@ Lexer::build_token ()
 		  // right-shift-assign
 		  skip_input (1);
 		  current_column += 3;
+		  loc += 2;
 
 		  return Token::make (RIGHT_SHIFT_EQ, loc);
 		}
@@ -848,6 +865,7 @@ Lexer::build_token ()
 		  // right-shift
 		  skip_input ();
 		  current_column += 2;
+		  loc += 1;
 
 		  return Token::make (RIGHT_SHIFT, loc);
 		}
@@ -857,6 +875,7 @@ Lexer::build_token ()
 	      // larger than or equal to
 	      skip_input ();
 	      current_column += 2;
+	      loc += 1;
 
 	      return Token::make (GREATER_OR_EQUAL, loc);
 	    }
@@ -872,6 +891,7 @@ Lexer::build_token ()
 	      // scope resolution ::
 	      skip_input ();
 	      current_column += 2;
+	      loc += 1;
 
 	      return Token::make (SCOPE_RESOLUTION, loc);
 	    }
@@ -888,6 +908,7 @@ Lexer::build_token ()
 	      // not equal boolean operator
 	      skip_input ();
 	      current_column += 2;
+	      loc += 1;
 
 	      return Token::make (NOT_EQUAL, loc);
 	    }
@@ -937,6 +958,7 @@ Lexer::build_token ()
 	      // bitwise or-assign?
 	      skip_input ();
 	      current_column += 2;
+	      loc += 1;
 
 	      return Token::make (PIPE_EQ, loc);
 	    }
@@ -945,6 +967,7 @@ Lexer::build_token ()
 	      // logical or
 	      skip_input ();
 	      current_column += 2;
+	      loc += 1;
 
 	      return Token::make (OR, loc);
 	    }
@@ -961,6 +984,7 @@ Lexer::build_token ()
 	      // bitwise and-assign?
 	      skip_input ();
 	      current_column += 2;
+	      loc += 1;
 
 	      return Token::make (AMP_EQ, loc);
 	    }
@@ -969,6 +993,7 @@ Lexer::build_token ()
 	      // logical and
 	      skip_input ();
 	      current_column += 2;
+	      loc += 1;
 
 	      return Token::make (LOGICAL_AND, loc);
 	    }
@@ -987,6 +1012,7 @@ Lexer::build_token ()
 		  // ellipsis
 		  skip_input (1);
 		  current_column += 3;
+		  loc += 2;
 
 		  return Token::make (ELLIPSIS, loc);
 		}
@@ -995,6 +1021,7 @@ Lexer::build_token ()
 		  // ..=
 		  skip_input (1);
 		  current_column += 3;
+		  loc += 2;
 
 		  return Token::make (DOT_DOT_EQ, loc);
 		}
@@ -1003,6 +1030,7 @@ Lexer::build_token ()
 		  // ..
 		  skip_input ();
 		  current_column += 2;
+		  loc += 1;
 
 		  return Token::make (DOT_DOT, loc);
 		}
@@ -1717,6 +1745,8 @@ Lexer::parse_byte_char (Location loc)
 
   current_column += length;
 
+  loc += length - 1;
+
   return Token::make_byte_char (loc, byte_char);
 }
 
@@ -1781,6 +1811,7 @@ Lexer::parse_byte_string (Location loc)
     }
 
   str.shrink_to_fit ();
+  loc += str.size () - 1;
 
   return Token::make_byte_string (loc, std::move (str));
 }
@@ -1861,6 +1892,8 @@ Lexer::parse_raw_byte_string (Location loc)
 
   current_column += length;
 
+  loc += length - 1;
+
   str.shrink_to_fit ();
 
   return Token::make_byte_string (loc, std::move (str));
@@ -1912,6 +1945,7 @@ Lexer::parse_raw_identifier (Location loc)
   else
     {
       str.shrink_to_fit ();
+      loc += length - 1;
 
       return Token::make_identifier (loc, std::move (str));
     }
@@ -2009,6 +2043,8 @@ Lexer::parse_string (Location loc)
     }
 
   str.shrink_to_fit ();
+  loc += length - 1;
+
   return Token::make_string (loc, std::move (str));
 }
 
@@ -2043,6 +2079,8 @@ Lexer::parse_identifier_or_keyword (Location loc)
 
   str.shrink_to_fit ();
 
+  loc += length - 1;
+
   TokenId keyword = classify_keyword (str);
   if (keyword == IDENTIFIER)
     return Token::make_identifier (loc, std::move (str));
@@ -2120,6 +2158,8 @@ Lexer::parse_raw_string (Location loc, int initial_hash_count)
 
   current_column += length;
 
+  loc += length - 1;
+
   str.shrink_to_fit ();
 
   return Token::make_string (loc, std::move (str));
@@ -2183,6 +2223,9 @@ Lexer::parse_non_decimal_int_literal (Location loc, IsDigitFunc is_digit_func,
 						 : "<insert unknown base>")));
       return nullptr;
     }
+
+  loc += length - 1;
+
   return Token::make_int (loc, std::move (existent_str), type_hint);
 }
 
@@ -2275,6 +2318,8 @@ Lexer::parse_decimal_int_or_float (Location loc)
 
       current_column += length;
 
+      loc += length - 1;
+
       str.shrink_to_fit ();
       return Token::make_float (loc, std::move (str), type_hint);
     }
@@ -2295,6 +2340,8 @@ Lexer::parse_decimal_int_or_float (Location loc)
 
       current_column += length;
 
+      loc += length - 1;
+
       str.shrink_to_fit ();
       return Token::make_float (loc, std::move (str), CORETYPE_UNKNOWN);
     }
@@ -2324,6 +2371,8 @@ Lexer::parse_decimal_int_or_float (Location loc)
 
       current_column += length;
 
+      loc += length - 1;
+
       str.shrink_to_fit ();
       return Token::make_float (loc, std::move (str), type_hint);
     }
@@ -2345,6 +2394,8 @@ Lexer::parse_decimal_int_or_float (Location loc)
 
       current_column += length;
 
+      loc += length - 1;
+
       str.shrink_to_fit ();
       return Token::make_int (loc, std::move (str), type_hint);
     }
@@ -2382,6 +2433,8 @@ Lexer::parse_char_or_lifetime (Location loc)
 
       current_column += length;
 
+      loc += length - 1;
+
       return Token::make_char (loc, current_char32);
     }
   else
@@ -2399,6 +2452,8 @@ Lexer::parse_char_or_lifetime (Location loc)
 	  // TODO fix due to different widths of utf-8 chars?
 	  current_column += 3;
 
+	  loc += 2;
+
 	  return Token::make_char (loc, current_char32);
 	}
       else if (ISDIGIT (current_char32.value) || ISALPHA (current_char32.value)
@@ -2421,6 +2476,8 @@ Lexer::parse_char_or_lifetime (Location loc)
 
 	  current_column += length;
 
+	  loc += length - 1;
+
 	  str.shrink_to_fit ();
 	  return Token::make_lifetime (loc, std::move (str));
 	}
diff --git a/gcc/testsuite/rust/compile/diagnostic_underline.rs b/gcc/testsuite/rust/compile/diagnostic_underline.rs
new file mode 100644
index 00000000000..fcbf468e1c8
--- /dev/null
+++ b/gcc/testsuite/rust/compile/diagnostic_underline.rs
@@ -0,0 +1,15 @@
+// { dg-additional-options "-quiet" }
+
+/* { dg-options "-fdiagnostics-show-caret" } */
+
+
+fn barbarbar() {}
+
+const fn foo() { 
+    barbarbar();// { dg-error "only functions marked as 'const' are allowed to be called from constant contexts" }
+/* { dg-begin-multiline-output "" }
+     barbarbar();//
+     ^~~~~~~~~
+{ dg-end-multiline-output "" } */
+}
+
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 11/88] gccrs: Change how CompileVarDecl outputs Bvariable's
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (9 preceding siblings ...)
  2023-04-05 14:02 ` [committed 10/88] gccrs: diagnostics: Add underline for tokens in diagnostics arthur.cohen
@ 2023-04-05 14:02 ` arthur.cohen
  2023-04-05 14:02 ` [committed 12/88] gccrs: testsuite: Handle Windows carriage returns properly arthur.cohen
                   ` (78 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Owen Avery

From: Owen Avery <powerboat9.gamer@gmail.com>

This allows patterns to declare multiple/no variables

gcc/rust/ChangeLog:

	* backend/rust-compile-base.cc (HIRCompileBase::compile_locals_for_block):
	Allow patterns to declare zero or multiple variables.
	* backend/rust-compile-var-decl.h: Change function declaration.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
---
 gcc/rust/backend/rust-compile-base.cc    |  4 +---
 gcc/rust/backend/rust-compile-var-decl.h | 26 ++++++++++++++----------
 2 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc
index 568abf9ca2c..c108661d983 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -457,9 +457,7 @@ HIRCompileBase::compile_locals_for_block (Context *ctx, Resolver::Rib &rib,
 
       // compile the local
       tree type = TyTyResolveCompile::compile (ctx, tyty);
-      Bvariable *compiled
-	= CompileVarDecl::compile (fndecl, type, pattern, ctx);
-      locals.push_back (compiled);
+      CompileVarDecl::compile (fndecl, type, pattern, locals, ctx);
     }
   return locals;
 }
diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h
index 00146a42e9d..791ee9c1112 100644
--- a/gcc/rust/backend/rust-compile-var-decl.h
+++ b/gcc/rust/backend/rust-compile-var-decl.h
@@ -30,12 +30,11 @@ class CompileVarDecl : public HIRCompileBase, public HIR::HIRPatternVisitor
   using HIR::HIRPatternVisitor::visit;
 
 public:
-  static ::Bvariable *compile (tree fndecl, tree translated_type,
-			       HIR::Pattern *pattern, Context *ctx)
+  static void compile (tree fndecl, tree translated_type, HIR::Pattern *pattern,
+		       std::vector<Bvariable *> &locals, Context *ctx)
   {
-    CompileVarDecl compiler (ctx, fndecl, translated_type);
+    CompileVarDecl compiler (ctx, fndecl, translated_type, locals);
     pattern->accept_vis (compiler);
-    return compiler.compiled_variable;
   }
 
   void visit (HIR::IdentifierPattern &pattern) override
@@ -43,26 +42,30 @@ public:
     if (!pattern.is_mut ())
       translated_type = ctx->get_backend ()->immutable_type (translated_type);
 
-    compiled_variable
+    Bvariable *var
       = ctx->get_backend ()->local_variable (fndecl, pattern.get_identifier (),
 					     translated_type, NULL /*decl_var*/,
 					     pattern.get_locus ());
 
     HirId stmt_id = pattern.get_pattern_mappings ().get_hirid ();
-    ctx->insert_var_decl (stmt_id, compiled_variable);
+    ctx->insert_var_decl (stmt_id, var);
+
+    locals.push_back (var);
   }
 
   void visit (HIR::WildcardPattern &pattern) override
   {
     translated_type = ctx->get_backend ()->immutable_type (translated_type);
 
-    compiled_variable
+    Bvariable *var
       = ctx->get_backend ()->local_variable (fndecl, "_", translated_type,
 					     NULL /*decl_var*/,
 					     pattern.get_locus ());
 
     HirId stmt_id = pattern.get_pattern_mappings ().get_hirid ();
-    ctx->insert_var_decl (stmt_id, compiled_variable);
+    ctx->insert_var_decl (stmt_id, var);
+
+    locals.push_back (var);
   }
 
   // Empty visit for unused Pattern HIR nodes.
@@ -78,15 +81,16 @@ public:
   void visit (HIR::TupleStructPattern &) override {}
 
 private:
-  CompileVarDecl (Context *ctx, tree fndecl, tree translated_type)
+  CompileVarDecl (Context *ctx, tree fndecl, tree translated_type,
+		  std::vector<Bvariable *> &locals)
     : HIRCompileBase (ctx), fndecl (fndecl), translated_type (translated_type),
-      compiled_variable (ctx->get_backend ()->error_variable ())
+      locals (locals)
   {}
 
   tree fndecl;
   tree translated_type;
 
-  Bvariable *compiled_variable;
+  std::vector<Bvariable *> &locals;
 };
 
 } // namespace Compile
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 12/88] gccrs: testsuite: Handle Windows carriage returns properly
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (10 preceding siblings ...)
  2023-04-05 14:02 ` [committed 11/88] gccrs: Change how CompileVarDecl outputs Bvariable's arthur.cohen
@ 2023-04-05 14:02 ` arthur.cohen
  2023-04-05 14:02 ` [committed 13/88] gccrs: Support GroupedPattern during name resolution arthur.cohen
                   ` (77 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

In dg-output, check for \r* carriage returns to make sure execution
tests pass on windows platforms

gcc/testsuite/ChangeLog:

	* rust/execute/torture/builtin_macro_cfg.rs: Handle carriage returns
		properly.
	* rust/execute/torture/builtin_macro_concat.rs: Likewise.
	* rust/execute/torture/builtin_macro_env.rs: Likewise.
	* rust/execute/torture/builtin_macro_include_bytes.rs: Likewise.
	* rust/execute/torture/builtin_macro_include_str.rs: Likewise.
	* rust/execute/torture/builtin_macro_line.rs: Likewise.
	* rust/execute/torture/builtin_macros1.rs: Likewise.
	* rust/execute/torture/builtin_macros3.rs: Likewise.
	* rust/execute/torture/cfg1.rs: Likewise.
	* rust/execute/torture/cfg2.rs: Likewise.
	* rust/execute/torture/cfg3.rs: Likewise.
	* rust/execute/torture/cfg4.rs: Likewise.
	* rust/execute/torture/coercion1.rs: Likewise.
	* rust/execute/torture/coercion2.rs: Likewise.
	* rust/execute/torture/extern_mod4.rs: Likewise.
	* rust/execute/torture/helloworld1.rs: Likewise.
	* rust/execute/torture/helloworld2.rs: Likewise.
	* rust/execute/torture/issue-1198.rs: Likewise.
	* rust/execute/torture/issue-1231.rs: Likewise.
	* rust/execute/torture/issue-1232.rs: Likewise.
	* rust/execute/torture/issue-1249.rs: Likewise.
	* rust/execute/torture/issue-1436.rs: Likewise.
	* rust/execute/torture/issue-1496.rs: Likewise.
	* rust/execute/torture/issue-647.rs: Likewise.
	* rust/execute/torture/issue-845.rs: Likewise.
	* rust/execute/torture/issue-851.rs: Likewise.
	* rust/execute/torture/issue-858.rs: Likewise.
	* rust/execute/torture/issue-976.rs: Likewise.
	* rust/execute/torture/macros10.rs: Likewise.
	* rust/execute/torture/macros11.rs: Likewise.
	* rust/execute/torture/macros12.rs: Likewise.
	* rust/execute/torture/macros13.rs: Likewise.
	* rust/execute/torture/macros14.rs: Likewise.
	* rust/execute/torture/macros2.rs: Likewise.
	* rust/execute/torture/macros22.rs: Likewise.
	* rust/execute/torture/macros29.rs: Likewise.
	* rust/execute/torture/macros3.rs: Likewise.
	* rust/execute/torture/macros30.rs: Likewise.
	* rust/execute/torture/macros31.rs: Likewise.
	* rust/execute/torture/macros7.rs: Likewise.
	* rust/execute/torture/macros8.rs: Likewise.
	* rust/execute/torture/macros9.rs: Likewise.
	* rust/execute/torture/match1.rs: Likewise.
	* rust/execute/torture/match2.rs: Likewise.
	* rust/execute/torture/match3.rs: Likewise.
	* rust/execute/torture/match_bool1.rs: Likewise.
	* rust/execute/torture/match_byte1.rs: Likewise.
	* rust/execute/torture/match_char1.rs: Likewise.
	* rust/execute/torture/match_int1.rs: Likewise.
	* rust/execute/torture/match_loop1.rs: Likewise.
	* rust/execute/torture/match_range1.rs: Likewise.
	* rust/execute/torture/match_range2.rs: Likewise.
	* rust/execute/torture/match_tuple1.rs: Likewise.
	* rust/execute/torture/method1.rs: Likewise.
	* rust/execute/torture/method2.rs: Likewise.
	* rust/execute/torture/method3.rs: Likewise.
	* rust/execute/torture/method4.rs: Likewise.
	* rust/execute/torture/operator_overload_1.rs: Likewise.
	* rust/execute/torture/operator_overload_10.rs: Likewise.
	* rust/execute/torture/operator_overload_11.rs: Likewise.
	* rust/execute/torture/operator_overload_12.rs: Likewise.
	* rust/execute/torture/operator_overload_2.rs: Likewise.
	* rust/execute/torture/operator_overload_4.rs: Likewise.
	* rust/execute/torture/operator_overload_5.rs: Likewise.
	* rust/execute/torture/operator_overload_6.rs: Likewise.
	* rust/execute/torture/operator_overload_7.rs: Likewise.
	* rust/execute/torture/operator_overload_8.rs: Likewise.
	* rust/execute/torture/operator_overload_9.rs: Likewise.
	* rust/execute/torture/str-layout1.rs: Likewise.
	* rust/execute/torture/str-zero.rs: Likewise.
	* rust/execute/torture/trait1.rs: Likewise.
	* rust/execute/torture/trait10.rs: Likewise.
	* rust/execute/torture/trait11.rs: Likewise.
	* rust/execute/torture/trait12.rs: Likewise.
	* rust/execute/torture/trait13.rs: Likewise.
	* rust/execute/torture/trait2.rs: Likewise.
	* rust/execute/torture/trait3.rs: Likewise.
	* rust/execute/torture/trait4.rs: Likewise.
	* rust/execute/torture/trait5.rs: Likewise.
	* rust/execute/torture/trait6.rs: Likewise.
	* rust/execute/torture/trait7.rs: Likewise.
	* rust/execute/torture/trait8.rs: Likewise.
	* rust/execute/torture/trait9.rs: Likewise.
	* rust/execute/torture/closure2.rs: Likewise.
	* rust/execute/torture/closure3.rs: Likewise.
	* rust/execute/torture/loop-condition-eval.rs: Likewise.
	* rust/execute/torture/operator_overload_3.rs: Likewise.
---
 .../rust/execute/torture/builtin_macro_cfg.rs |  8 ++---
 .../execute/torture/builtin_macro_concat.rs   |  2 +-
 .../rust/execute/torture/builtin_macro_env.rs |  2 +-
 .../torture/builtin_macro_include_bytes.rs    |  2 +-
 .../torture/builtin_macro_include_str.rs      |  2 +-
 .../execute/torture/builtin_macro_line.rs     |  2 +-
 .../rust/execute/torture/builtin_macros1.rs   |  2 +-
 .../rust/execute/torture/builtin_macros3.rs   |  5 ++-
 gcc/testsuite/rust/execute/torture/cfg1.rs    |  2 +-
 gcc/testsuite/rust/execute/torture/cfg2.rs    |  2 +-
 gcc/testsuite/rust/execute/torture/cfg3.rs    |  2 +-
 gcc/testsuite/rust/execute/torture/cfg4.rs    |  2 +-
 .../rust/execute/torture/closure2.rs          |  2 +-
 .../rust/execute/torture/closure3.rs          |  2 +-
 .../rust/execute/torture/coercion1.rs         |  2 +-
 .../rust/execute/torture/coercion2.rs         |  2 +-
 .../rust/execute/torture/extern_mod4.rs       |  2 +-
 .../rust/execute/torture/helloworld1.rs       |  2 +-
 .../rust/execute/torture/helloworld2.rs       |  2 +-
 .../rust/execute/torture/issue-1198.rs        |  2 +-
 .../rust/execute/torture/issue-1231.rs        |  2 +-
 .../rust/execute/torture/issue-1232.rs        |  2 +-
 .../rust/execute/torture/issue-1249.rs        |  2 +-
 .../rust/execute/torture/issue-1436.rs        |  1 -
 .../rust/execute/torture/issue-1496.rs        |  2 +-
 .../rust/execute/torture/issue-647.rs         |  2 +-
 .../rust/execute/torture/issue-845.rs         |  2 +-
 .../rust/execute/torture/issue-851.rs         |  2 +-
 .../rust/execute/torture/issue-858.rs         |  2 +-
 .../rust/execute/torture/issue-976.rs         |  2 +-
 .../execute/torture/loop-condition-eval.rs    |  2 +-
 .../rust/execute/torture/macros10.rs          |  2 +-
 .../rust/execute/torture/macros11.rs          |  2 +-
 .../rust/execute/torture/macros12.rs          |  2 +-
 .../rust/execute/torture/macros13.rs          |  2 +-
 .../rust/execute/torture/macros14.rs          |  2 +-
 gcc/testsuite/rust/execute/torture/macros2.rs |  2 +-
 .../rust/execute/torture/macros22.rs          |  2 +-
 .../rust/execute/torture/macros29.rs          |  2 +-
 gcc/testsuite/rust/execute/torture/macros3.rs |  2 +-
 .../rust/execute/torture/macros30.rs          |  2 +-
 .../rust/execute/torture/macros31.rs          |  2 +-
 gcc/testsuite/rust/execute/torture/macros7.rs |  2 +-
 gcc/testsuite/rust/execute/torture/macros8.rs |  2 +-
 gcc/testsuite/rust/execute/torture/macros9.rs |  2 +-
 gcc/testsuite/rust/execute/torture/match1.rs  |  2 +-
 gcc/testsuite/rust/execute/torture/match2.rs  |  2 +-
 gcc/testsuite/rust/execute/torture/match3.rs  |  2 +-
 .../rust/execute/torture/match_bool1.rs       |  2 +-
 .../rust/execute/torture/match_byte1.rs       |  2 +-
 .../rust/execute/torture/match_char1.rs       |  2 +-
 .../rust/execute/torture/match_int1.rs        |  2 +-
 .../rust/execute/torture/match_loop1.rs       |  2 +-
 .../rust/execute/torture/match_range1.rs      |  2 +-
 .../rust/execute/torture/match_range2.rs      |  2 +-
 .../rust/execute/torture/match_tuple1.rs      |  2 +-
 gcc/testsuite/rust/execute/torture/method1.rs |  2 +-
 gcc/testsuite/rust/execute/torture/method2.rs |  2 +-
 gcc/testsuite/rust/execute/torture/method3.rs |  2 +-
 gcc/testsuite/rust/execute/torture/method4.rs |  2 +-
 .../execute/torture/operator_overload_1.rs    |  2 +-
 .../execute/torture/operator_overload_10.rs   |  2 +-
 .../execute/torture/operator_overload_11.rs   |  2 +-
 .../execute/torture/operator_overload_12.rs   |  2 +-
 .../execute/torture/operator_overload_2.rs    |  2 +-
 .../execute/torture/operator_overload_3.rs    |  2 +-
 .../execute/torture/operator_overload_4.rs    |  2 +-
 .../execute/torture/operator_overload_5.rs    |  2 +-
 .../execute/torture/operator_overload_6.rs    |  2 +-
 .../execute/torture/operator_overload_7.rs    |  2 +-
 .../execute/torture/operator_overload_8.rs    |  2 +-
 .../execute/torture/operator_overload_9.rs    |  2 +-
 .../rust/execute/torture/str-layout1.rs       |  2 +-
 .../rust/execute/torture/str-zero.rs          | 33 +++++++++----------
 gcc/testsuite/rust/execute/torture/trait1.rs  |  2 +-
 gcc/testsuite/rust/execute/torture/trait10.rs |  2 +-
 gcc/testsuite/rust/execute/torture/trait11.rs |  2 +-
 gcc/testsuite/rust/execute/torture/trait12.rs |  2 +-
 gcc/testsuite/rust/execute/torture/trait13.rs |  2 +-
 gcc/testsuite/rust/execute/torture/trait2.rs  |  2 +-
 gcc/testsuite/rust/execute/torture/trait3.rs  |  2 +-
 gcc/testsuite/rust/execute/torture/trait4.rs  |  2 +-
 gcc/testsuite/rust/execute/torture/trait5.rs  |  2 +-
 gcc/testsuite/rust/execute/torture/trait6.rs  |  2 +-
 gcc/testsuite/rust/execute/torture/trait7.rs  |  2 +-
 gcc/testsuite/rust/execute/torture/trait8.rs  |  2 +-
 gcc/testsuite/rust/execute/torture/trait9.rs  |  2 +-
 87 files changed, 104 insertions(+), 109 deletions(-)

diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_cfg.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_cfg.rs
index fad2daef6bc..a8d6ae0f7ca 100644
--- a/gcc/testsuite/rust/execute/torture/builtin_macro_cfg.rs
+++ b/gcc/testsuite/rust/execute/torture/builtin_macro_cfg.rs
@@ -1,5 +1,5 @@
 // { dg-additional-options "-w -frust-cfg=A" }
-// { dg-output "A\n" }
+// { dg-output "A\r*\n" }
 #[rustc_builtin_macro]
 macro_rules! cfg {
     () => {{}};
@@ -12,7 +12,7 @@ extern "C" {
 fn print(s: &str) {
     unsafe {
         printf(
-            "%s\n" as *const str as *const i8,
+            "%s\n\0" as *const str as *const i8,
             s as *const str as *const i8,
         );
     }
@@ -21,11 +21,11 @@ fn print(s: &str) {
 fn main() -> i32 {
     let cfg = cfg!(A);
     if cfg {
-        print("A");
+        print("A\0");
     }
     let cfg = cfg!(B);
     if cfg {
-        print("B");
+        print("B\0");
     }
 
     0
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_concat.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_concat.rs
index 9b33924f5a1..a9d68e0cd35 100644
--- a/gcc/testsuite/rust/execute/torture/builtin_macro_concat.rs
+++ b/gcc/testsuite/rust/execute/torture/builtin_macro_concat.rs
@@ -1,4 +1,4 @@
-// { dg-output "\ntest10btrue2.15\ntest10bfalse2.151\n" }
+// { dg-output "\r*\ntest10btrue2.15\r*\ntest10bfalse2.151\r*\n" }
 #[rustc_builtin_macro]
 macro_rules! concat {
     () => {{}};
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_env.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_env.rs
index a5c80b25728..d64e2a00097 100644
--- a/gcc/testsuite/rust/execute/torture/builtin_macro_env.rs
+++ b/gcc/testsuite/rust/execute/torture/builtin_macro_env.rs
@@ -1,4 +1,4 @@
-// { dg-output "VALUE\nVALUE\n" }
+// { dg-output "VALUE\r*\nVALUE\r*\n" }
 // { dg-set-compiler-env-var ENV_MACRO_TEST "VALUE" }
 #[rustc_builtin_macro]
 macro_rules! env {
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_include_bytes.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_include_bytes.rs
index 087f0220de5..8be55773036 100644
--- a/gcc/testsuite/rust/execute/torture/builtin_macro_include_bytes.rs
+++ b/gcc/testsuite/rust/execute/torture/builtin_macro_include_bytes.rs
@@ -1,4 +1,4 @@
-// { dg-output "104\n33\n1\n" }
+// { dg-output "104\r*\n33\r*\n1\r*\n" }
 #[rustc_builtin_macro]
 macro_rules! include_bytes {
     () => {{}};
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_include_str.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_include_str.rs
index 6f9871d379c..43d40c9c0df 100644
--- a/gcc/testsuite/rust/execute/torture/builtin_macro_include_str.rs
+++ b/gcc/testsuite/rust/execute/torture/builtin_macro_include_str.rs
@@ -1,4 +1,4 @@
-// { dg-output "hello, include!\n" }
+// { dg-output "hello, include!\r*\n" }
 #[rustc_builtin_macro]
 macro_rules! include_str {
     () => {{}};
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_line.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_line.rs
index 02541ed52e2..9998de1402d 100644
--- a/gcc/testsuite/rust/execute/torture/builtin_macro_line.rs
+++ b/gcc/testsuite/rust/execute/torture/builtin_macro_line.rs
@@ -1,4 +1,4 @@
-// { dg-output "18\n21\n" }
+// { dg-output "18\r*\n21\r*\n" }
 extern "C" {
     fn printf(fmt: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macros1.rs b/gcc/testsuite/rust/execute/torture/builtin_macros1.rs
index 5976478e426..5bccb16e0f9 100644
--- a/gcc/testsuite/rust/execute/torture/builtin_macros1.rs
+++ b/gcc/testsuite/rust/execute/torture/builtin_macros1.rs
@@ -1,4 +1,4 @@
-// { dg-output "rust/execute/torture/builtin_macros1.rs" }
+// { dg-output "rust/execute/torture/builtin_macros1.rs\r*" }
 #[rustc_builtin_macro]
 macro_rules! file {
     () => {{}};
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macros3.rs b/gcc/testsuite/rust/execute/torture/builtin_macros3.rs
index 24555cbdb8a..5a024fa0e24 100644
--- a/gcc/testsuite/rust/execute/torture/builtin_macros3.rs
+++ b/gcc/testsuite/rust/execute/torture/builtin_macros3.rs
@@ -1,4 +1,4 @@
-// { dg-output "14\n42\n" }
+// { dg-output "14\r*\n42\r*\n" }
 #[rustc_builtin_macro]
 macro_rules! column {
     () => {{}};
@@ -19,10 +19,9 @@ fn main() -> i32 {
 
     print(c0);
 
-    let c1 =                             column!();
+    let c1 = /* --------------------- */ column!();
 
     print(c1);
 
     0
 }
-
diff --git a/gcc/testsuite/rust/execute/torture/cfg1.rs b/gcc/testsuite/rust/execute/torture/cfg1.rs
index d3c56295503..648d1f1ff72 100644
--- a/gcc/testsuite/rust/execute/torture/cfg1.rs
+++ b/gcc/testsuite/rust/execute/torture/cfg1.rs
@@ -1,5 +1,5 @@
 // { dg-additional-options "-w -frust-cfg=A" }
-// { dg-output "test1\n" }
+// { dg-output "test1\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/cfg2.rs b/gcc/testsuite/rust/execute/torture/cfg2.rs
index 5048bcb2791..7b75ac6962f 100644
--- a/gcc/testsuite/rust/execute/torture/cfg2.rs
+++ b/gcc/testsuite/rust/execute/torture/cfg2.rs
@@ -1,5 +1,5 @@
 // { dg-additional-options "-w -frust-cfg=A" }
-// { dg-output "test1\n" }
+// { dg-output "test1\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/cfg3.rs b/gcc/testsuite/rust/execute/torture/cfg3.rs
index 89312344b23..97a8fb8e461 100644
--- a/gcc/testsuite/rust/execute/torture/cfg3.rs
+++ b/gcc/testsuite/rust/execute/torture/cfg3.rs
@@ -1,5 +1,5 @@
 // { dg-additional-options "-w -frust-cfg=A" }
-// { dg-output "test1\n" }
+// { dg-output "test1\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/cfg4.rs b/gcc/testsuite/rust/execute/torture/cfg4.rs
index d1c2a22a0ff..97026d902d0 100644
--- a/gcc/testsuite/rust/execute/torture/cfg4.rs
+++ b/gcc/testsuite/rust/execute/torture/cfg4.rs
@@ -1,5 +1,5 @@
 // { dg-additional-options "-w -frust-cfg=A" }
-// { dg-output "test1\ntest2\n" }
+// { dg-output "test1\r*\ntest2\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/closure2.rs b/gcc/testsuite/rust/execute/torture/closure2.rs
index 45b3b5ce8b4..8e1502dfa43 100644
--- a/gcc/testsuite/rust/execute/torture/closure2.rs
+++ b/gcc/testsuite/rust/execute/torture/closure2.rs
@@ -1,4 +1,4 @@
-// { dg-output "3\n" }
+// { dg-output "3\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/closure3.rs b/gcc/testsuite/rust/execute/torture/closure3.rs
index 62cf3a082cf..8fa9445ab62 100644
--- a/gcc/testsuite/rust/execute/torture/closure3.rs
+++ b/gcc/testsuite/rust/execute/torture/closure3.rs
@@ -1,4 +1,4 @@
-// { dg-output "3\n" }
+// { dg-output "3\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/coercion1.rs b/gcc/testsuite/rust/execute/torture/coercion1.rs
index 2cdb9bbca38..6ca28233d60 100644
--- a/gcc/testsuite/rust/execute/torture/coercion1.rs
+++ b/gcc/testsuite/rust/execute/torture/coercion1.rs
@@ -1,4 +1,4 @@
-/* { dg-output "123\n123\n" } */
+/* { dg-output "123\r*\n123\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/coercion2.rs b/gcc/testsuite/rust/execute/torture/coercion2.rs
index 12dd68ff5f7..047fd536dca 100644
--- a/gcc/testsuite/rust/execute/torture/coercion2.rs
+++ b/gcc/testsuite/rust/execute/torture/coercion2.rs
@@ -1,4 +1,4 @@
-/* { dg-output "123\n123\n" } */
+/* { dg-output "123\r*\n123\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/extern_mod4.rs b/gcc/testsuite/rust/execute/torture/extern_mod4.rs
index 99b6fb5c9ba..55be2b8115f 100644
--- a/gcc/testsuite/rust/execute/torture/extern_mod4.rs
+++ b/gcc/testsuite/rust/execute/torture/extern_mod4.rs
@@ -1,5 +1,5 @@
 // { dg-additional-options "-w" }
-// { dg-output "12" }
+// { dg-output "12\r*" }
 mod modules;
 
 extern "C" {
diff --git a/gcc/testsuite/rust/execute/torture/helloworld1.rs b/gcc/testsuite/rust/execute/torture/helloworld1.rs
index d416efa33af..8803156b5fd 100644
--- a/gcc/testsuite/rust/execute/torture/helloworld1.rs
+++ b/gcc/testsuite/rust/execute/torture/helloworld1.rs
@@ -1,4 +1,4 @@
-/* { dg-output "Hello World" }*/
+/* { dg-output "Hello World\r*" }*/
 extern "C" {
     fn puts(s: *const i8);
 }
diff --git a/gcc/testsuite/rust/execute/torture/helloworld2.rs b/gcc/testsuite/rust/execute/torture/helloworld2.rs
index cc05f3798fa..912301bcb26 100644
--- a/gcc/testsuite/rust/execute/torture/helloworld2.rs
+++ b/gcc/testsuite/rust/execute/torture/helloworld2.rs
@@ -1,4 +1,4 @@
-/* { dg-output "Hello World 123\n" }*/
+/* { dg-output "Hello World 123\r*\n" }*/
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/issue-1198.rs b/gcc/testsuite/rust/execute/torture/issue-1198.rs
index fce44ad1994..bbc58f0f370 100644
--- a/gcc/testsuite/rust/execute/torture/issue-1198.rs
+++ b/gcc/testsuite/rust/execute/torture/issue-1198.rs
@@ -1,4 +1,4 @@
-/* { dg-output "foo_deref\nimm_deref\n123\n" } */
+/* { dg-output "foo_deref\r*\nimm_deref\r*\n123\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/issue-1231.rs b/gcc/testsuite/rust/execute/torture/issue-1231.rs
index 970e86f917a..321df5fec55 100644
--- a/gcc/testsuite/rust/execute/torture/issue-1231.rs
+++ b/gcc/testsuite/rust/execute/torture/issue-1231.rs
@@ -1,5 +1,5 @@
 // { dg-additional-options "-w" }
-// { dg-output "outer\ninner\n" }
+// { dg-output "outer\r*\ninner\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/issue-1232.rs b/gcc/testsuite/rust/execute/torture/issue-1232.rs
index c56d5c18695..9215efdba6c 100644
--- a/gcc/testsuite/rust/execute/torture/issue-1232.rs
+++ b/gcc/testsuite/rust/execute/torture/issue-1232.rs
@@ -1,5 +1,5 @@
 // { dg-additional-options "-w" }
-// { dg-output "slice_access=3\n" }
+// { dg-output "slice_access=3\r*\n" }
 extern "rust-intrinsic" {
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     fn offset<T>(dst: *const T, offset: isize) -> *const T;
diff --git a/gcc/testsuite/rust/execute/torture/issue-1249.rs b/gcc/testsuite/rust/execute/torture/issue-1249.rs
index 072204ea877..06911074c30 100644
--- a/gcc/testsuite/rust/execute/torture/issue-1249.rs
+++ b/gcc/testsuite/rust/execute/torture/issue-1249.rs
@@ -1,5 +1,5 @@
 // { dg-options "-w" }
-// { dg-output "1\n2\n" }
+// { dg-output "1\r*\n2\r*\n" }
 
 extern "C" {
     fn printf(s: *const i8, ...);
diff --git a/gcc/testsuite/rust/execute/torture/issue-1436.rs b/gcc/testsuite/rust/execute/torture/issue-1436.rs
index 5c079a61f07..96de5d69194 100644
--- a/gcc/testsuite/rust/execute/torture/issue-1436.rs
+++ b/gcc/testsuite/rust/execute/torture/issue-1436.rs
@@ -1,5 +1,4 @@
 // { dg-options "-w" }
-// { dg-output "" }
 mod intrinsics {
     extern "rust-intrinsic" {
         #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
diff --git a/gcc/testsuite/rust/execute/torture/issue-1496.rs b/gcc/testsuite/rust/execute/torture/issue-1496.rs
index 9f08b2ae98a..af4201b7d3e 100644
--- a/gcc/testsuite/rust/execute/torture/issue-1496.rs
+++ b/gcc/testsuite/rust/execute/torture/issue-1496.rs
@@ -1,4 +1,4 @@
-/* { dg-output "foo_deref\nimm_deref\n123\n" } */
+/* { dg-output "foo_deref\r*\nimm_deref\r*\n123\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/issue-647.rs b/gcc/testsuite/rust/execute/torture/issue-647.rs
index 3f427ccb785..d76d43b6110 100644
--- a/gcc/testsuite/rust/execute/torture/issue-647.rs
+++ b/gcc/testsuite/rust/execute/torture/issue-647.rs
@@ -1,4 +1,4 @@
-/* { dg-output "Hello World 123\n" }*/
+/* { dg-output "Hello World 123\r*\n" }*/
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/issue-845.rs b/gcc/testsuite/rust/execute/torture/issue-845.rs
index 4c689e3b6c8..f96714d4bae 100644
--- a/gcc/testsuite/rust/execute/torture/issue-845.rs
+++ b/gcc/testsuite/rust/execute/torture/issue-845.rs
@@ -1,4 +1,4 @@
-// { dg-output "Foo::bar\n" }
+// { dg-output "Foo::bar\r*\n" }
 // { dg-additional-options "-w" }
 extern "C" {
     fn printf(s: *const i8, ...);
diff --git a/gcc/testsuite/rust/execute/torture/issue-851.rs b/gcc/testsuite/rust/execute/torture/issue-851.rs
index 3881c7a2ada..b3b2b480ec2 100644
--- a/gcc/testsuite/rust/execute/torture/issue-851.rs
+++ b/gcc/testsuite/rust/execute/torture/issue-851.rs
@@ -1,4 +1,4 @@
-/* { dg-output "Result: 123\n" } */
+/* { dg-output "Result: 123\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/issue-858.rs b/gcc/testsuite/rust/execute/torture/issue-858.rs
index 5a43f3e1b1a..51a15613844 100644
--- a/gcc/testsuite/rust/execute/torture/issue-858.rs
+++ b/gcc/testsuite/rust/execute/torture/issue-858.rs
@@ -1,4 +1,4 @@
-/* { dg-output "Result: 123\n" } */
+/* { dg-output "Result: 123\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/issue-976.rs b/gcc/testsuite/rust/execute/torture/issue-976.rs
index 42cf596fb7d..cf6cfa66cd1 100644
--- a/gcc/testsuite/rust/execute/torture/issue-976.rs
+++ b/gcc/testsuite/rust/execute/torture/issue-976.rs
@@ -1,4 +1,4 @@
-/* { dg-output "hi" } */
+/* { dg-output "hi\r*" } */
 fn main() -> i32 {
     {
         extern "C" {
diff --git a/gcc/testsuite/rust/execute/torture/loop-condition-eval.rs b/gcc/testsuite/rust/execute/torture/loop-condition-eval.rs
index 008965917ab..67ac00ced59 100644
--- a/gcc/testsuite/rust/execute/torture/loop-condition-eval.rs
+++ b/gcc/testsuite/rust/execute/torture/loop-condition-eval.rs
@@ -1,4 +1,4 @@
-// { dg-output "1\n" }
+// { dg-output "1\r*\n" }
 pub fn test() -> u64 {
     let mut n = 113383; // #20 in https://oeis.org/A006884
     while n != 1 {
diff --git a/gcc/testsuite/rust/execute/torture/macros10.rs b/gcc/testsuite/rust/execute/torture/macros10.rs
index 155a440ee04..4f976f0b317 100644
--- a/gcc/testsuite/rust/execute/torture/macros10.rs
+++ b/gcc/testsuite/rust/execute/torture/macros10.rs
@@ -1,4 +1,4 @@
-// { dg-output "18\n" }
+// { dg-output "18\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/macros11.rs b/gcc/testsuite/rust/execute/torture/macros11.rs
index 5bde97d3dd4..70e5f25cf71 100644
--- a/gcc/testsuite/rust/execute/torture/macros11.rs
+++ b/gcc/testsuite/rust/execute/torture/macros11.rs
@@ -1,4 +1,4 @@
-// { dg-output "2" }
+// { dg-output "2\r*" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/macros12.rs b/gcc/testsuite/rust/execute/torture/macros12.rs
index d310dff9ba8..deb424ffdbc 100644
--- a/gcc/testsuite/rust/execute/torture/macros12.rs
+++ b/gcc/testsuite/rust/execute/torture/macros12.rs
@@ -1,4 +1,4 @@
-// { dg-output "0\n" }
+// { dg-output "0\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/macros13.rs b/gcc/testsuite/rust/execute/torture/macros13.rs
index afb20264625..ec36a21f26e 100644
--- a/gcc/testsuite/rust/execute/torture/macros13.rs
+++ b/gcc/testsuite/rust/execute/torture/macros13.rs
@@ -1,4 +1,4 @@
-// { dg-output "18\n" }
+// { dg-output "18\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/macros14.rs b/gcc/testsuite/rust/execute/torture/macros14.rs
index 00656546d4c..189fadd9861 100644
--- a/gcc/testsuite/rust/execute/torture/macros14.rs
+++ b/gcc/testsuite/rust/execute/torture/macros14.rs
@@ -1,4 +1,4 @@
-// { dg-output "15\n" }
+// { dg-output "15\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/macros2.rs b/gcc/testsuite/rust/execute/torture/macros2.rs
index ba5098710ea..aca528a08aa 100644
--- a/gcc/testsuite/rust/execute/torture/macros2.rs
+++ b/gcc/testsuite/rust/execute/torture/macros2.rs
@@ -1,4 +1,4 @@
-// { dg-output "arg\narg\narg\n" }
+// { dg-output "arg\r*\narg\r*\narg\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/macros22.rs b/gcc/testsuite/rust/execute/torture/macros22.rs
index 3f291ace98e..60ffae145ed 100644
--- a/gcc/testsuite/rust/execute/torture/macros22.rs
+++ b/gcc/testsuite/rust/execute/torture/macros22.rs
@@ -1,4 +1,4 @@
-// { dg-output "1\n2\nNaN\n3\n" }
+// { dg-output "1\r*\n2\r*\nNaN\r*\n3\r*\n" }
 
 macro_rules! print_num {
     ($l:literal) => {{
diff --git a/gcc/testsuite/rust/execute/torture/macros29.rs b/gcc/testsuite/rust/execute/torture/macros29.rs
index 306979b9b5b..9c2cc0e6a1b 100644
--- a/gcc/testsuite/rust/execute/torture/macros29.rs
+++ b/gcc/testsuite/rust/execute/torture/macros29.rs
@@ -1,4 +1,4 @@
-// { dg-output "1\n" }
+// { dg-output "1\r*\n" }
 #[rustc_builtin_macro]
 macro_rules! concat {
     () => {{}};
diff --git a/gcc/testsuite/rust/execute/torture/macros3.rs b/gcc/testsuite/rust/execute/torture/macros3.rs
index 00f6d253f50..91936c1ca83 100644
--- a/gcc/testsuite/rust/execute/torture/macros3.rs
+++ b/gcc/testsuite/rust/execute/torture/macros3.rs
@@ -1,4 +1,4 @@
-// { dg-output "invok\ninvok\ninvok\ninvok\ninvok\n" }
+// { dg-output "invok\r*\ninvok\r*\ninvok\r*\ninvok\r*\ninvok\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/macros30.rs b/gcc/testsuite/rust/execute/torture/macros30.rs
index ab36f5e78af..7ec77d06982 100644
--- a/gcc/testsuite/rust/execute/torture/macros30.rs
+++ b/gcc/testsuite/rust/execute/torture/macros30.rs
@@ -1,4 +1,4 @@
-// { dg-output "1\n" }
+// { dg-output "1\r*\n" }
 #[rustc_builtin_macro]
 macro_rules! concat {
     () => {{}};
diff --git a/gcc/testsuite/rust/execute/torture/macros31.rs b/gcc/testsuite/rust/execute/torture/macros31.rs
index 483f897a92b..4c6378a68c2 100644
--- a/gcc/testsuite/rust/execute/torture/macros31.rs
+++ b/gcc/testsuite/rust/execute/torture/macros31.rs
@@ -1,5 +1,5 @@
 // { dg-additional-options "-w -frust-cfg=A" }
-// { dg-output "A\nB\n" }
+// { dg-output "A\r*\nB\r*\n" }
 #[rustc_builtin_macro]
 macro_rules! cfg {
     () => {{}};
diff --git a/gcc/testsuite/rust/execute/torture/macros7.rs b/gcc/testsuite/rust/execute/torture/macros7.rs
index ed1f922f581..b8af009aed4 100644
--- a/gcc/testsuite/rust/execute/torture/macros7.rs
+++ b/gcc/testsuite/rust/execute/torture/macros7.rs
@@ -1,4 +1,4 @@
-// { dg-output "any\nany\nany\n" }
+// { dg-output "any\r*\nany\r*\nany\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/macros8.rs b/gcc/testsuite/rust/execute/torture/macros8.rs
index a12aca4910e..e532237ecde 100644
--- a/gcc/testsuite/rust/execute/torture/macros8.rs
+++ b/gcc/testsuite/rust/execute/torture/macros8.rs
@@ -1,4 +1,4 @@
-// { dg-output "zo1\nzo1\n" }
+// { dg-output "zo1\r*\nzo1\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/macros9.rs b/gcc/testsuite/rust/execute/torture/macros9.rs
index 0e3fd24e8a9..81aa3683bb3 100644
--- a/gcc/testsuite/rust/execute/torture/macros9.rs
+++ b/gcc/testsuite/rust/execute/torture/macros9.rs
@@ -1,4 +1,4 @@
-// { dg-output "oom\noom\noom\n" }
+// { dg-output "oom\r*\noom\r*\noom\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/match1.rs b/gcc/testsuite/rust/execute/torture/match1.rs
index e5af512f15d..66a5be3792a 100644
--- a/gcc/testsuite/rust/execute/torture/match1.rs
+++ b/gcc/testsuite/rust/execute/torture/match1.rs
@@ -1,4 +1,4 @@
-// { dg-output "Foo::A\nFoo::B\nFoo::C x\nFoo::D 20 80\n" }
+// { dg-output "Foo::A\r*\nFoo::B\r*\nFoo::C x\r*\nFoo::D 20 80\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/match2.rs b/gcc/testsuite/rust/execute/torture/match2.rs
index 02cedf29b3c..3c9fbde262a 100644
--- a/gcc/testsuite/rust/execute/torture/match2.rs
+++ b/gcc/testsuite/rust/execute/torture/match2.rs
@@ -1,4 +1,4 @@
-// { dg-output "123\n80\n" }
+// { dg-output "123\r*\n80\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/match3.rs b/gcc/testsuite/rust/execute/torture/match3.rs
index 8cded3044df..3dda9a35db3 100644
--- a/gcc/testsuite/rust/execute/torture/match3.rs
+++ b/gcc/testsuite/rust/execute/torture/match3.rs
@@ -1,4 +1,4 @@
-// { dg-output "Foo::A\nwildcard\nwildcard\nFoo::D 20 80\n" }
+// { dg-output "Foo::A\r*\nwildcard\r*\nwildcard\r*\nFoo::D 20 80\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/match_bool1.rs b/gcc/testsuite/rust/execute/torture/match_bool1.rs
index 101dbb58571..2fb5e02b273 100644
--- a/gcc/testsuite/rust/execute/torture/match_bool1.rs
+++ b/gcc/testsuite/rust/execute/torture/match_bool1.rs
@@ -1,4 +1,4 @@
-// { dg-output "182 is more than 100\n55 is less than 100\n" }
+// { dg-output "182 is more than 100\r*\n55 is less than 100\r*\n" }
 
 extern "C" {
     fn printf(s: *const i8, ...);
diff --git a/gcc/testsuite/rust/execute/torture/match_byte1.rs b/gcc/testsuite/rust/execute/torture/match_byte1.rs
index 3546cfb9d8b..4261b2b9f5e 100644
--- a/gcc/testsuite/rust/execute/torture/match_byte1.rs
+++ b/gcc/testsuite/rust/execute/torture/match_byte1.rs
@@ -1,4 +1,4 @@
-// { dg-output "a\nseven\nquote\nelse" }
+// { dg-output "a\r*\nseven\r*\nquote\r*\nelse" }
 
 extern "C" {
     fn printf(s: *const i8, ...);
diff --git a/gcc/testsuite/rust/execute/torture/match_char1.rs b/gcc/testsuite/rust/execute/torture/match_char1.rs
index fa65876a907..1584b419daa 100644
--- a/gcc/testsuite/rust/execute/torture/match_char1.rs
+++ b/gcc/testsuite/rust/execute/torture/match_char1.rs
@@ -1,4 +1,4 @@
-// { dg-output "amazing\nwildcard\ncompiler\nproductivity\n" }
+// { dg-output "amazing\r*\nwildcard\r*\ncompiler\r*\nproductivity\r*\n" }
 
 extern "C" {
     fn printf(s: *const i8, ...);
diff --git a/gcc/testsuite/rust/execute/torture/match_int1.rs b/gcc/testsuite/rust/execute/torture/match_int1.rs
index 209429added..a7deefbaa02 100644
--- a/gcc/testsuite/rust/execute/torture/match_int1.rs
+++ b/gcc/testsuite/rust/execute/torture/match_int1.rs
@@ -1,4 +1,4 @@
-// { dg-output "other!\nother!\nother!\nfifteen!\nfifteen!\nother!\nother!\nfifteen!\n" }
+// { dg-output "other!\r*\nother!\r*\nother!\r*\nfifteen!\r*\nfifteen!\r*\nother!\r*\nother!\r*\nfifteen!\r*\n" }
 
 extern "C" {
     fn printf(s: *const i8, ...);
diff --git a/gcc/testsuite/rust/execute/torture/match_loop1.rs b/gcc/testsuite/rust/execute/torture/match_loop1.rs
index bb6aee946f6..578712fa7f5 100644
--- a/gcc/testsuite/rust/execute/torture/match_loop1.rs
+++ b/gcc/testsuite/rust/execute/torture/match_loop1.rs
@@ -1,4 +1,4 @@
-// { dg-output "E::One\nE::Two\nbreak!\n" }
+// { dg-output "E::One\r*\nE::Two\r*\nbreak!\r*\n" }
 
 extern "C" {
     fn printf(s: *const i8, ...);
diff --git a/gcc/testsuite/rust/execute/torture/match_range1.rs b/gcc/testsuite/rust/execute/torture/match_range1.rs
index 82e9e34a989..3b705407fb2 100644
--- a/gcc/testsuite/rust/execute/torture/match_range1.rs
+++ b/gcc/testsuite/rust/execute/torture/match_range1.rs
@@ -1,4 +1,4 @@
-// { dg-output "zero to END_RANGE\nzero to END_RANGE\nelse\n" }
+// { dg-output "zero to END_RANGE\r*\nzero to END_RANGE\r*\nelse\r*\n" }
 
 extern "C" {
     fn printf(s: *const i8, ...);
diff --git a/gcc/testsuite/rust/execute/torture/match_range2.rs b/gcc/testsuite/rust/execute/torture/match_range2.rs
index 8153f9e1c7e..517f2bbeb84 100644
--- a/gcc/testsuite/rust/execute/torture/match_range2.rs
+++ b/gcc/testsuite/rust/execute/torture/match_range2.rs
@@ -1,4 +1,4 @@
-// { dg-output "lowercase\nuppercase\nother\n" }
+// { dg-output "lowercase\r*\nuppercase\r*\nother\r*\n" }
 
 extern "C" {
     fn printf(s: *const i8, ...);
diff --git a/gcc/testsuite/rust/execute/torture/match_tuple1.rs b/gcc/testsuite/rust/execute/torture/match_tuple1.rs
index cb61cc0847c..2ae3ca7db4e 100644
--- a/gcc/testsuite/rust/execute/torture/match_tuple1.rs
+++ b/gcc/testsuite/rust/execute/torture/match_tuple1.rs
@@ -1,4 +1,4 @@
-// { dg-output "x:15\ny:20\n" }
+// { dg-output "x:15\r*\ny:20\r*\n" }
 
 extern "C" {
     fn printf(s: *const i8, ...);
diff --git a/gcc/testsuite/rust/execute/torture/method1.rs b/gcc/testsuite/rust/execute/torture/method1.rs
index 6af6133939b..c57944b93eb 100644
--- a/gcc/testsuite/rust/execute/torture/method1.rs
+++ b/gcc/testsuite/rust/execute/torture/method1.rs
@@ -1,4 +1,4 @@
-/* { dg-output "124\n458" } */
+/* { dg-output "124\r*\n458" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/method2.rs b/gcc/testsuite/rust/execute/torture/method2.rs
index f532b4488c6..79a35eb53d8 100644
--- a/gcc/testsuite/rust/execute/torture/method2.rs
+++ b/gcc/testsuite/rust/execute/torture/method2.rs
@@ -1,5 +1,5 @@
 // { dg-additional-options "-w" }
-// { dg-output "foo_deref\nimm_deref\n" }
+// { dg-output "foo_deref\r*\nimm_deref\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/method3.rs b/gcc/testsuite/rust/execute/torture/method3.rs
index 0e9e8ff42a0..7217d35c4b3 100644
--- a/gcc/testsuite/rust/execute/torture/method3.rs
+++ b/gcc/testsuite/rust/execute/torture/method3.rs
@@ -1,5 +1,5 @@
 // { dg-additional-options "-w" }
-// { dg-output "mut_deref\nfoobar: 123\n" }
+// { dg-output "mut_deref\r*\nfoobar: 123\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/method4.rs b/gcc/testsuite/rust/execute/torture/method4.rs
index 5c6fdfe02c3..ba1ffd1da36 100644
--- a/gcc/testsuite/rust/execute/torture/method4.rs
+++ b/gcc/testsuite/rust/execute/torture/method4.rs
@@ -1,5 +1,5 @@
 // { dg-additional-options "-w" }
-// { dg-output "mut_deref\nfoobar: 123\n" }
+// { dg-output "mut_deref\r*\nfoobar: 123\r*\n" }
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_1.rs b/gcc/testsuite/rust/execute/torture/operator_overload_1.rs
index 5a28c5f4e93..064a77651ad 100644
--- a/gcc/testsuite/rust/execute/torture/operator_overload_1.rs
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_1.rs
@@ -1,4 +1,4 @@
-/* { dg-output "3\n" } */
+/* { dg-output "3\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_10.rs b/gcc/testsuite/rust/execute/torture/operator_overload_10.rs
index f5d45db5338..3fa5afd01f3 100644
--- a/gcc/testsuite/rust/execute/torture/operator_overload_10.rs
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_10.rs
@@ -1,4 +1,4 @@
-/* { dg-output "foo_deref\n123\n" } */
+/* { dg-output "foo_deref\r*\n123\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_11.rs b/gcc/testsuite/rust/execute/torture/operator_overload_11.rs
index 1919941c486..94bc1cd9d96 100644
--- a/gcc/testsuite/rust/execute/torture/operator_overload_11.rs
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_11.rs
@@ -1,4 +1,4 @@
-// { dg-output "1\n" }
+// { dg-output "1\r*\n" }
 // { dg-additional-options "-w" }
 extern "C" {
     fn printf(s: *const i8, ...);
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_12.rs b/gcc/testsuite/rust/execute/torture/operator_overload_12.rs
index 7433330fa31..d525ec44e8f 100644
--- a/gcc/testsuite/rust/execute/torture/operator_overload_12.rs
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_12.rs
@@ -1,4 +1,4 @@
-// { dg-output "1\n" }
+// { dg-output "1\r*\n" }
 // { dg-additional-options "-w" }
 extern "C" {
     fn printf(s: *const i8, ...);
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_2.rs b/gcc/testsuite/rust/execute/torture/operator_overload_2.rs
index a577718451d..fab3a83b7f5 100644
--- a/gcc/testsuite/rust/execute/torture/operator_overload_2.rs
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_2.rs
@@ -1,4 +1,4 @@
-/* { dg-output "3\n" } */
+/* { dg-output "3\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_3.rs b/gcc/testsuite/rust/execute/torture/operator_overload_3.rs
index 57f58076c3e..2bcb1c4267c 100644
--- a/gcc/testsuite/rust/execute/torture/operator_overload_3.rs
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_3.rs
@@ -1,4 +1,4 @@
-/* { dg-output "3\n3\n" } */
+/* { dg-output "3\r*\n3\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_4.rs b/gcc/testsuite/rust/execute/torture/operator_overload_4.rs
index ce9887b2ead..e1fcbac1c77 100644
--- a/gcc/testsuite/rust/execute/torture/operator_overload_4.rs
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_4.rs
@@ -1,4 +1,4 @@
-/* { dg-output "neg\n" } */
+/* { dg-output "neg\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_5.rs b/gcc/testsuite/rust/execute/torture/operator_overload_5.rs
index a525f743680..2ba87285ef1 100644
--- a/gcc/testsuite/rust/execute/torture/operator_overload_5.rs
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_5.rs
@@ -1,4 +1,4 @@
-/* { dg-output "not\n" } */
+/* { dg-output "not\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_6.rs b/gcc/testsuite/rust/execute/torture/operator_overload_6.rs
index fbd2a8fa9d3..50463e74761 100644
--- a/gcc/testsuite/rust/execute/torture/operator_overload_6.rs
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_6.rs
@@ -1,4 +1,4 @@
-/* { dg-output "add_assign\n3\n" } */
+/* { dg-output "add_assign\r*\n3\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_7.rs b/gcc/testsuite/rust/execute/torture/operator_overload_7.rs
index 886a7010efc..50107bb4324 100644
--- a/gcc/testsuite/rust/execute/torture/operator_overload_7.rs
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_7.rs
@@ -1,4 +1,4 @@
-/* { dg-output "imm_deref\n123\n" } */
+/* { dg-output "imm_deref\r*\n123\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_8.rs b/gcc/testsuite/rust/execute/torture/operator_overload_8.rs
index 862e29a4bc6..e0338b917f5 100644
--- a/gcc/testsuite/rust/execute/torture/operator_overload_8.rs
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_8.rs
@@ -1,4 +1,4 @@
-/* { dg-output "imm_deref\n123\n" } */
+/* { dg-output "imm_deref\r*\n123\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_9.rs b/gcc/testsuite/rust/execute/torture/operator_overload_9.rs
index fd972e28ab3..608ad0fe94e 100644
--- a/gcc/testsuite/rust/execute/torture/operator_overload_9.rs
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_9.rs
@@ -1,4 +1,4 @@
-/* { dg-output "mut_deref\n123\n" } */
+/* { dg-output "mut_deref\r*\n123\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/str-layout1.rs b/gcc/testsuite/rust/execute/torture/str-layout1.rs
index 80bdc2a9c9f..39c1e38d77b 100644
--- a/gcc/testsuite/rust/execute/torture/str-layout1.rs
+++ b/gcc/testsuite/rust/execute/torture/str-layout1.rs
@@ -1,5 +1,5 @@
 // { dg-additional-options "-w" }
-// { dg-output "t1sz=5 t2sz=10" }
+// { dg-output "t1sz=5 t2sz=10\r*" }
 mod mem {
     extern "rust-intrinsic" {
         #[rustc_const_stable(feature = "const_transmute", since = "1.46.0")]
diff --git a/gcc/testsuite/rust/execute/torture/str-zero.rs b/gcc/testsuite/rust/execute/torture/str-zero.rs
index e7fba0d1372..9042f54436e 100644
--- a/gcc/testsuite/rust/execute/torture/str-zero.rs
+++ b/gcc/testsuite/rust/execute/torture/str-zero.rs
@@ -1,26 +1,23 @@
-/* { dg-output "bar foo baz foobar\n" } */
-extern "C"
-{
-  fn printf(s: *const i8, ...);
-  fn memchr(s: *const i8, c: u8, n: usize) -> *const i8;
+/* { dg-output "bar foo baz foobar\r*\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+    fn memchr(s: *const i8, c: u8, n: usize) -> *const i8;
 }
 
-pub fn main () -> i32
-{
-  let f = "%s %s %s %s\n\0";
-  let s = "bar\0\
+pub fn main() -> i32 {
+    let f = "%s %s %s %s\n\0";
+    let s = "bar\0\
            foo\
            \x00\
            baz\u{0000}\
            foobar\0";
-  let cf = f as *const str as *const i8;
-  let cs = s as *const str as *const i8;
-  unsafe
-    {
-      let cs2 = memchr (cs, b'f', 5);
-      let cs3 = memchr (cs2, b'b', 5);
-      let cs4 = memchr (cs3, b'f', 5);
-      printf (cf, cs, cs2, cs3, cs4);
+    let cf = f as *const str as *const i8;
+    let cs = s as *const str as *const i8;
+    unsafe {
+        let cs2 = memchr(cs, b'f', 5);
+        let cs3 = memchr(cs2, b'b', 5);
+        let cs4 = memchr(cs3, b'f', 5);
+        printf(cf, cs, cs2, cs3, cs4);
     }
-  0
+    0
 }
diff --git a/gcc/testsuite/rust/execute/torture/trait1.rs b/gcc/testsuite/rust/execute/torture/trait1.rs
index dc3cc471c33..d4f5878ef18 100644
--- a/gcc/testsuite/rust/execute/torture/trait1.rs
+++ b/gcc/testsuite/rust/execute/torture/trait1.rs
@@ -1,4 +1,4 @@
-/* { dg-output "S::f\nT1::f\nT2::f\n" } */
+/* { dg-output "S::f\r*\nT1::f\r*\nT2::f\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/trait10.rs b/gcc/testsuite/rust/execute/torture/trait10.rs
index e581e324bbf..b0bdeab9091 100644
--- a/gcc/testsuite/rust/execute/torture/trait10.rs
+++ b/gcc/testsuite/rust/execute/torture/trait10.rs
@@ -1,4 +1,4 @@
-/* { dg-output "123\n" } */
+/* { dg-output "123\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/trait11.rs b/gcc/testsuite/rust/execute/torture/trait11.rs
index 283c9ecd0ed..ed7b7c9d6ee 100644
--- a/gcc/testsuite/rust/execute/torture/trait11.rs
+++ b/gcc/testsuite/rust/execute/torture/trait11.rs
@@ -1,4 +1,4 @@
-/* { dg-output "3\n" } */
+/* { dg-output "3\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/trait12.rs b/gcc/testsuite/rust/execute/torture/trait12.rs
index 68b0a4014ad..a4ba5be116e 100644
--- a/gcc/testsuite/rust/execute/torture/trait12.rs
+++ b/gcc/testsuite/rust/execute/torture/trait12.rs
@@ -1,4 +1,4 @@
-/* { dg-output "3\n" } */
+/* { dg-output "3\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/trait13.rs b/gcc/testsuite/rust/execute/torture/trait13.rs
index 3071da27a6a..49befb8fbb1 100644
--- a/gcc/testsuite/rust/execute/torture/trait13.rs
+++ b/gcc/testsuite/rust/execute/torture/trait13.rs
@@ -1,4 +1,4 @@
-/* { dg-output "123\n456\n" } */
+/* { dg-output "123\r*\n456\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/trait2.rs b/gcc/testsuite/rust/execute/torture/trait2.rs
index c96615fa891..9974f70da8c 100644
--- a/gcc/testsuite/rust/execute/torture/trait2.rs
+++ b/gcc/testsuite/rust/execute/torture/trait2.rs
@@ -1,4 +1,4 @@
-/* { dg-output "Bar::A = 456\n<Foo as Bar>::A = 456\n" } */
+/* { dg-output "Bar::A = 456\r*\n<Foo as Bar>::A = 456\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/trait3.rs b/gcc/testsuite/rust/execute/torture/trait3.rs
index accfa9d0a36..6fe92ef70f9 100644
--- a/gcc/testsuite/rust/execute/torture/trait3.rs
+++ b/gcc/testsuite/rust/execute/torture/trait3.rs
@@ -1,4 +1,4 @@
-/* { dg-output "123, 777" } */
+/* { dg-output "123, 777\r*" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/trait4.rs b/gcc/testsuite/rust/execute/torture/trait4.rs
index 8c0d257cd7e..3b2d000780a 100644
--- a/gcc/testsuite/rust/execute/torture/trait4.rs
+++ b/gcc/testsuite/rust/execute/torture/trait4.rs
@@ -1,4 +1,4 @@
-/* { dg-output "123\n" }*/
+/* { dg-output "123\r*\n" }*/
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/trait5.rs b/gcc/testsuite/rust/execute/torture/trait5.rs
index 49f11a6085a..f9c0dfdae74 100644
--- a/gcc/testsuite/rust/execute/torture/trait5.rs
+++ b/gcc/testsuite/rust/execute/torture/trait5.rs
@@ -1,4 +1,4 @@
-/* { dg-output "123\n123\n" } */
+/* { dg-output "123\r*\n123\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/trait6.rs b/gcc/testsuite/rust/execute/torture/trait6.rs
index c83d6666c87..74363c2ddac 100644
--- a/gcc/testsuite/rust/execute/torture/trait6.rs
+++ b/gcc/testsuite/rust/execute/torture/trait6.rs
@@ -1,4 +1,4 @@
-/* { dg-output "123\n" } */
+/* { dg-output "123\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/trait7.rs b/gcc/testsuite/rust/execute/torture/trait7.rs
index 064f88d5de9..fc1bbe87170 100644
--- a/gcc/testsuite/rust/execute/torture/trait7.rs
+++ b/gcc/testsuite/rust/execute/torture/trait7.rs
@@ -1,4 +1,4 @@
-/* { dg-output "123\n" } */
+/* { dg-output "123\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/trait8.rs b/gcc/testsuite/rust/execute/torture/trait8.rs
index 14392ff0cca..c26737f58e6 100644
--- a/gcc/testsuite/rust/execute/torture/trait8.rs
+++ b/gcc/testsuite/rust/execute/torture/trait8.rs
@@ -1,4 +1,4 @@
-/* { dg-output "123\n" } */
+/* { dg-output "123\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/trait9.rs b/gcc/testsuite/rust/execute/torture/trait9.rs
index c0e6d36f183..738d1935291 100644
--- a/gcc/testsuite/rust/execute/torture/trait9.rs
+++ b/gcc/testsuite/rust/execute/torture/trait9.rs
@@ -1,4 +1,4 @@
-/* { dg-output "3\n" } */
+/* { dg-output "3\r*\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 13/88] gccrs: Support GroupedPattern during name resolution
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (11 preceding siblings ...)
  2023-04-05 14:02 ` [committed 12/88] gccrs: testsuite: Handle Windows carriage returns properly arthur.cohen
@ 2023-04-05 14:02 ` arthur.cohen
  2023-04-05 14:02 ` [committed 14/88] gccrs: Do not crash on empty macros expand. Fixes #1712 arthur.cohen
                   ` (76 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Owen Avery

From: Owen Avery <powerboat9.gamer@gmail.com>

gcc/rust/ChangeLog:

	* resolve/rust-ast-resolve-pattern.h: Support GroupedPattern properly.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
---
 gcc/rust/resolve/rust-ast-resolve-pattern.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h
index 5f2b7293cf2..3e74f0a4cc6 100644
--- a/gcc/rust/resolve/rust-ast-resolve-pattern.h
+++ b/gcc/rust/resolve/rust-ast-resolve-pattern.h
@@ -77,6 +77,11 @@ public:
       pattern.get_node_id (), pattern.get_locus (), type);
   }
 
+  void visit (AST::GroupedPattern &pattern) override
+  {
+    pattern.get_pattern_in_parens ()->accept_vis (*this);
+  }
+
   // cases in a match expression
   void visit (AST::PathInExpression &pattern) override;
 
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 14/88] gccrs: Do not crash on empty macros expand. Fixes #1712
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (12 preceding siblings ...)
  2023-04-05 14:02 ` [committed 13/88] gccrs: Support GroupedPattern during name resolution arthur.cohen
@ 2023-04-05 14:02 ` arthur.cohen
  2023-04-05 14:02 ` [committed 15/88] gccrs: Add HIR lowering for GroupedPattern arthur.cohen
                   ` (75 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Lyra

From: Lyra <teromene@teromene.fr>

This commit fixes a compiler crash when expanding an empty macro into an existing AST.

gcc/rust/ChangeLog:

	* expand/rust-macro-expand.cc (transcribe_expression): Fix ICE when expanding
	empty macros.

gcc/testsuite/ChangeLog:

	* rust/compile/macro45.rs: New test.

Signed-off-by: Lyra Karenai <teromene@teromene.fr>
---
 gcc/rust/expand/rust-macro-expand.cc  | 2 ++
 gcc/testsuite/rust/compile/macro45.rs | 7 +++++++
 2 files changed, 9 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/macro45.rs

diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index 9c3523e0515..bf914ee19e3 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -839,6 +839,8 @@ static AST::Fragment
 transcribe_expression (Parser<MacroInvocLexer> &parser)
 {
   auto expr = parser.parse_expr ();
+  if (expr == nullptr)
+    return AST::Fragment::create_error ();
 
   return AST::Fragment::complete ({std::move (expr)});
 }
diff --git a/gcc/testsuite/rust/compile/macro45.rs b/gcc/testsuite/rust/compile/macro45.rs
new file mode 100644
index 00000000000..52dbcbb0016
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro45.rs
@@ -0,0 +1,7 @@
+macro_rules! empty {
+    () => {}; // { dg-error "found unexpected token '\}' in null denotation" }
+}
+
+fn main() {
+    let a = empty!();
+}
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 15/88] gccrs: Add HIR lowering for GroupedPattern
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (13 preceding siblings ...)
  2023-04-05 14:02 ` [committed 14/88] gccrs: Do not crash on empty macros expand. Fixes #1712 arthur.cohen
@ 2023-04-05 14:02 ` arthur.cohen
  2023-04-05 14:03 ` [committed 16/88] gccrs: Add get_item method for HIR::GroupedPattern arthur.cohen
                   ` (74 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Owen Avery

From: Owen Avery <powerboat9.gamer@gmail.com>

gcc/rust/ChangeLog:

	* hir/rust-ast-lower-pattern.cc (ASTLoweringPattern::visit): Add proper visitor.
	* hir/rust-ast-lower-pattern.h: Declare it.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
---
 gcc/rust/hir/rust-ast-lower-pattern.cc | 16 ++++++++++++++++
 gcc/rust/hir/rust-ast-lower-pattern.h  |  1 +
 2 files changed, 17 insertions(+)

diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc
index 30a188286c8..8ee3a979a33 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.cc
+++ b/gcc/rust/hir/rust-ast-lower-pattern.cc
@@ -243,5 +243,21 @@ ASTLoweringPattern::visit (AST::RangePattern &pattern)
 			     std::move (upper_bound), pattern.get_locus ());
 }
 
+void
+ASTLoweringPattern::visit (AST::GroupedPattern &pattern)
+{
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  HIR::Pattern *inner
+    = ASTLoweringPattern::translate (pattern.get_pattern_in_parens ().get ());
+
+  translated
+    = new HIR::GroupedPattern (mapping, std::unique_ptr<HIR::Pattern> (inner),
+			       pattern.get_locus ());
+}
+
 } // namespace HIR
 } // namespace Rust
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.h b/gcc/rust/hir/rust-ast-lower-pattern.h
index 8b191d56868..0075e27e9c0 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.h
+++ b/gcc/rust/hir/rust-ast-lower-pattern.h
@@ -39,6 +39,7 @@ public:
   void visit (AST::TuplePattern &pattern) override;
   void visit (AST::LiteralPattern &pattern) override;
   void visit (AST::RangePattern &pattern) override;
+  void visit (AST::GroupedPattern &pattern) override;
 
 private:
   ASTLoweringPattern ();
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 16/88] gccrs: Add get_item method for HIR::GroupedPattern
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (14 preceding siblings ...)
  2023-04-05 14:02 ` [committed 15/88] gccrs: Add HIR lowering for GroupedPattern arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 17/88] gccrs: Add type resolution for grouped patterns arthur.cohen
                   ` (73 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Owen Avery

From: Owen Avery <powerboat9.gamer@gmail.com>

gcc/rust/ChangeLog:

	* hir/tree/rust-hir-pattern.h: Add get_item method.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
---
 gcc/rust/hir/tree/rust-hir-pattern.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h
index 80fa9b791a7..b7a230c526f 100644
--- a/gcc/rust/hir/tree/rust-hir-pattern.h
+++ b/gcc/rust/hir/tree/rust-hir-pattern.h
@@ -1269,6 +1269,12 @@ public:
     return PatternType::GROUPED;
   }
 
+  std::unique_ptr<Pattern> &get_item () { return pattern_in_parens; }
+  const std::unique_ptr<Pattern> &get_item () const
+  {
+    return pattern_in_parens;
+  }
+
 protected:
   /* Use covariance to implement clone function as returning this object rather
    * than base */
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 17/88] gccrs: Add type resolution for grouped patterns
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (15 preceding siblings ...)
  2023-04-05 14:03 ` [committed 16/88] gccrs: Add get_item method for HIR::GroupedPattern arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 18/88] gccrs: Added missing GroupedPattern visitors for code generation arthur.cohen
                   ` (72 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Owen Avery

From: Owen Avery <powerboat9.gamer@gmail.com>

gcc/rust/ChangeLog:

	* typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): Add proper
	visitor.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
---
 gcc/rust/typecheck/rust-hir-type-check-pattern.cc | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
index b017a851b5d..393f4158003 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -387,10 +387,12 @@ TypeCheckPattern::visit (HIR::IdentifierPattern &)
 }
 
 void
-TypeCheckPattern::visit (HIR::GroupedPattern &)
+TypeCheckPattern::visit (HIR::GroupedPattern &pattern)
 {
-  // TODO
-  gcc_unreachable ();
+  TyTy::BaseType *inner_ty
+    = TypeCheckPattern::Resolve (pattern.get_item ().get (), parent);
+  infered = inner_ty->clone ();
+  infered->set_ref (pattern.get_pattern_mappings ().get_hirid ());
 }
 
 void
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 18/88] gccrs: Added missing GroupedPattern visitors for code generation
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (16 preceding siblings ...)
  2023-04-05 14:03 ` [committed 17/88] gccrs: Add type resolution for grouped patterns arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 19/88] gccrs: Rename file rust-ast-full-test.cc to rust-ast.cc arthur.cohen
                   ` (71 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Owen Avery

From: Owen Avery <powerboat9.gamer@gmail.com>

gcc/rust/ChangeLog:

	* backend/rust-compile-pattern.cc (CompilePatternCaseLabelExpr::visit): Add proper
	visitor.
	(CompilePatternBindings::visit): Likewise.
	* backend/rust-compile-pattern.h: Declare them.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
---
 gcc/rust/backend/rust-compile-pattern.cc | 12 ++++++++++++
 gcc/rust/backend/rust-compile-pattern.h  |  4 ++--
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc
index fc70d4ba58d..9218b815dd8 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -161,6 +161,12 @@ CompilePatternCaseLabelExpr::visit (HIR::RangePattern &pattern)
   case_label_expr = build_case_label (lower, upper, associated_case_label);
 }
 
+void
+CompilePatternCaseLabelExpr::visit (HIR::GroupedPattern &pattern)
+{
+  pattern.get_item ()->accept_vis (*this);
+}
+
 // setup the bindings
 
 void
@@ -329,5 +335,11 @@ CompilePatternBindings::visit (HIR::StructPattern &pattern)
     }
 }
 
+void
+CompilePatternBindings::visit (HIR::GroupedPattern &pattern)
+{
+  pattern.get_item ()->accept_vis (*this);
+}
+
 } // namespace Compile
 } // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-pattern.h b/gcc/rust/backend/rust-compile-pattern.h
index 22812a45405..43334affca7 100644
--- a/gcc/rust/backend/rust-compile-pattern.h
+++ b/gcc/rust/backend/rust-compile-pattern.h
@@ -38,9 +38,9 @@ public:
   void visit (HIR::TupleStructPattern &pattern) override;
   void visit (HIR::WildcardPattern &pattern) override;
   void visit (HIR::RangePattern &pattern) override;
+  void visit (HIR::GroupedPattern &pattern) override;
 
   // Empty visit for unused Pattern HIR nodes.
-  void visit (HIR::GroupedPattern &) override {}
   void visit (HIR::IdentifierPattern &) override {}
   void visit (HIR::LiteralPattern &) override;
   void visit (HIR::QualifiedPathInExpression &) override {}
@@ -70,9 +70,9 @@ public:
 
   void visit (HIR::StructPattern &pattern) override;
   void visit (HIR::TupleStructPattern &pattern) override;
+  void visit (HIR::GroupedPattern &) override;
 
   // Empty visit for unused Pattern HIR nodes.
-  void visit (HIR::GroupedPattern &) override {}
   void visit (HIR::IdentifierPattern &) override {}
   void visit (HIR::LiteralPattern &) override {}
   void visit (HIR::PathInExpression &) override {}
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 19/88] gccrs: Rename file rust-ast-full-test.cc to rust-ast.cc
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (17 preceding siblings ...)
  2023-04-05 14:03 ` [committed 18/88] gccrs: Added missing GroupedPattern visitors for code generation arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 20/88] gccrs: moved operator.h to util/rust-operators.h arthur.cohen
                   ` (70 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Parthib

From: Parthib <parthibdutta02@gmail.com>

gcc/rust/ChangeLog:

	* Make-lang.in: Rename object file.
	* ast/rust-ast-full-test.cc: Moved to...
	* ast/rust-ast.cc: ...here.
---
 gcc/rust/Make-lang.in                               | 2 +-
 gcc/rust/ast/{rust-ast-full-test.cc => rust-ast.cc} | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename gcc/rust/ast/{rust-ast-full-test.cc => rust-ast.cc} (100%)

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index dddc70a26ec..87f3ba66eba 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -73,7 +73,7 @@ GRS_OBJS = \
     rust/rust-lex.o \
     rust/rust-cfg-parser.o \
     rust/rust-parse.o \
-    rust/rust-ast-full-test.o \
+    rust/rust-ast.o \
     rust/rust-ast-fragment.o \
     rust/rust-ast-dump.o \
     rust/rust-hir-dump.o \
diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast.cc
similarity index 100%
rename from gcc/rust/ast/rust-ast-full-test.cc
rename to gcc/rust/ast/rust-ast.cc
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 20/88] gccrs: moved operator.h to util/rust-operators.h
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (18 preceding siblings ...)
  2023-04-05 14:03 ` [committed 19/88] gccrs: Rename file rust-ast-full-test.cc to rust-ast.cc arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 21/88] gccrs: fixed compiler error message on wildcard pattern within expression arthur.cohen
                   ` (69 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Abdul Rafey

From: Abdul Rafey <abdulrafeyq@gmail.com>

gcc/rust/ChangeLog:

	* ast/rust-ast.cc: Fix include list.
	* ast/rust-expr.h: Likewise.
	* hir/tree/rust-hir-expr.h: Likewise.
	* rust-backend.h: Likewise.
	* util/rust-lang-item.h: Likewise.
	* operator.h: Moved to...
	* util/rust-operators.h: ...here.

Signed-off-by: Abdul Rafey <abdulrafeyq@gmail.com>
---
 gcc/rust/ast/rust-ast.cc                       | 2 +-
 gcc/rust/ast/rust-expr.h                       | 2 +-
 gcc/rust/hir/tree/rust-hir-expr.h              | 2 +-
 gcc/rust/rust-backend.h                        | 2 +-
 gcc/rust/util/rust-lang-item.h                 | 2 +-
 gcc/rust/{operator.h => util/rust-operators.h} | 0
 6 files changed, 5 insertions(+), 5 deletions(-)
 rename gcc/rust/{operator.h => util/rust-operators.h} (100%)

diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 280f59ffb16..60a9f01e17f 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -25,7 +25,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "rust-session-manager.h"
 #include "rust-lex.h"
 #include "rust-parse.h"
-#include "operator.h"
+#include "rust-operators.h"
 
 /* Compilation unit used for various AST-related functions that would make
  * the headers too long if they were defined inline and don't receive any
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index 34bc6993ab6..3ed1885d5af 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -3,7 +3,7 @@
 
 #include "rust-ast.h"
 #include "rust-path.h"
-#include "operator.h"
+#include "rust-operators.h"
 
 namespace Rust {
 namespace AST {
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h
index cc884420bef..bf103516800 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -23,7 +23,7 @@
 #include "rust-ast-full-decls.h"
 #include "rust-hir.h"
 #include "rust-hir-path.h"
-#include "operator.h"
+#include "rust-operators.h"
 
 namespace Rust {
 namespace HIR {
diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h
index 01c5fc40e8c..076104f3a40 100644
--- a/gcc/rust/rust-backend.h
+++ b/gcc/rust/rust-backend.h
@@ -26,7 +26,7 @@
 #include "rust-location.h"
 #include "rust-linemap.h"
 #include "rust-diagnostics.h"
-#include "operator.h"
+#include "util/rust-operators.h"
 #include "tree.h"
 
 // Pointers to these types are created by the backend, passed to the
diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h
index ea0c91aa5f2..29c364bad61 100644
--- a/gcc/rust/util/rust-lang-item.h
+++ b/gcc/rust/util/rust-lang-item.h
@@ -17,7 +17,7 @@
 // <http://www.gnu.org/licenses/>.
 
 #include "rust-system.h"
-#include "operator.h"
+#include "rust-operators.h"
 
 namespace Rust {
 namespace Analysis {
diff --git a/gcc/rust/operator.h b/gcc/rust/util/rust-operators.h
similarity index 100%
rename from gcc/rust/operator.h
rename to gcc/rust/util/rust-operators.h
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 21/88] gccrs: fixed compiler error message on wildcard pattern within expression
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (19 preceding siblings ...)
  2023-04-05 14:03 ` [committed 20/88] gccrs: moved operator.h to util/rust-operators.h arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 22/88] gccrs: fixed indentations in AST pretty expanded dump of trait arthur.cohen
                   ` (68 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Abdul Rafey

From: Abdul Rafey <abdulrafeyq@gmail.com>

gcc/rust/ChangeLog:

	* parse/rust-parse-impl.h (Parser::null_denotation): Add proper error
	when seeing wildcard var on right side of assignment.

gcc/testsuite/ChangeLog:

	* rust/compile/issue-867.rs: New test.

Signed-off-by: Abdul Rafey <abdulrafeyq@gmail.com>
---
 gcc/rust/parse/rust-parse-impl.h        | 6 ++++++
 gcc/testsuite/rust/compile/issue-867.rs | 8 ++++++++
 2 files changed, 14 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/issue-867.rs

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index d71bafded63..af749ca9200 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -13021,6 +13021,12 @@ Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok,
     case UNSAFE:
       return parse_unsafe_block_expr (std::move (outer_attrs),
 				      tok->get_locus ());
+    case UNDERSCORE:
+      add_error (
+	Error (tok->get_locus (),
+	       "use of %qs is not allowed on the right-side of an assignment",
+	       tok->get_token_description ()));
+      return nullptr;
     default:
       if (!restrictions.expr_can_be_null)
 	add_error (Error (tok->get_locus (),
diff --git a/gcc/testsuite/rust/compile/issue-867.rs b/gcc/testsuite/rust/compile/issue-867.rs
new file mode 100644
index 00000000000..8e120685c1a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-867.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let _ = 42;
+    let a = _ + 123; // { dg-error "use of '_' is not allowed on the right-side of an assignment" }
+                     // { dg-error {failed to parse expression in let statement} "" { target *-*-* } .-1  }
+                     // { dg-error {failed to parse statement or expression without block in block expression} "" { target *-*-* } .-2 }
+                     // { dg-error {unrecognised token '\}' for start of item} "" { target *-*-* } .+2 }
+                     // { dg-error {failed to parse item in crate} "" { target *-*-* } .+1 }
+}
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 22/88] gccrs: fixed indentations in AST pretty expanded dump of trait
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (20 preceding siblings ...)
  2023-04-05 14:03 ` [committed 21/88] gccrs: fixed compiler error message on wildcard pattern within expression arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 23/88] gccrs: macro: Allow builtin `MacroInvocation`s within the AST arthur.cohen
                   ` (67 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Abdul Rafey

From: Abdul Rafey <abdulrafeyq@gmail.com>

gcc/rust/ChangeLog:

	* ast/rust-ast-dump.cc (Dump::visit): removed extra indentations in trait ast dump

Signed-off-by: Abdul Rafey <abdulrafeyq@gmail.com>
---
 gcc/rust/ast/rust-ast-dump.cc | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-dump.cc b/gcc/rust/ast/rust-ast-dump.cc
index 77e04b972dc..58eb35ad1db 100644
--- a/gcc/rust/ast/rust-ast-dump.cc
+++ b/gcc/rust/ast/rust-ast-dump.cc
@@ -1072,8 +1072,6 @@ Dump::visit (TypeBoundWhereClauseItem &item)
 void
 Dump::visit (Method &method)
 {
-  // FIXME: Do we really need to dump the indentation here?
-  stream << indentation;
   visit (method.get_visibility ());
   stream << "fn " << method.get_method_name () << '(';
 
@@ -1326,7 +1324,7 @@ void
 Dump::visit (TraitItemFunc &item)
 {
   auto func = item.get_trait_function_decl ();
-  stream << indentation << "fn " << func.get_identifier () << '(';
+  stream << "fn " << func.get_identifier () << '(';
 
   visit_items_joined_by_separator (func.get_function_params ());
 
@@ -1340,9 +1338,6 @@ Dump::visit (TraitItemMethod &item)
 {
   auto method = item.get_trait_method_decl ();
 
-  // FIXME: Do we really need to dump the indentation here?
-  stream << indentation;
-
   // FIXME: Can we have visibility here?
   // emit_visibility (method.get_visibility ());
   stream << "fn " << method.get_identifier () << '(';
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 23/88] gccrs: macro: Allow builtin `MacroInvocation`s within the AST
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (21 preceding siblings ...)
  2023-04-05 14:03 ` [committed 22/88] gccrs: fixed indentations in AST pretty expanded dump of trait arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 24/88] gccrs: Create and use CompilePatternLet visitor for compiling let statments arthur.cohen
                   ` (66 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* ast/rust-macro.h (enum class): Add `BuiltinMacro` enum class.
	* expand/rust-attribute-visitor.cc (AttrVisitor::visit): Mention
	switching on `macro.kind` once builtin macro invocations are properly
	handled.
	* parse/rust-parse-impl.h (Parser::parse_macro_invocation): Switch to new MacroInvocation
	API.
	(Parser::parse_type): Likewise.
	(Parser::parse_type_no_bounds): Likewise.
---
 gcc/rust/ast/rust-macro.h                 | 110 ++++++++++++++++++----
 gcc/rust/expand/rust-attribute-visitor.cc |   2 +
 gcc/rust/parse/rust-parse-impl.h          |  70 +++++++-------
 3 files changed, 126 insertions(+), 56 deletions(-)

diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index 4226c6919ff..68dd7d660d3 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -578,8 +578,30 @@ protected:
   }
 };
 
+/**
+ * All builtin macros possible
+ */
+enum class BuiltinMacro
+{
+  Assert,
+  File,
+  Line,
+  Column,
+  IncludeBytes,
+  IncludeStr,
+  CompileError,
+  Concat,
+  Env,
+  Cfg,
+  Include
+};
+
 /* AST node of a macro invocation, which is replaced by the macro result at
- * compile time */
+ * compile time. This is technically a sum-type/tagged-union, which represents
+ * both classic macro invocations and builtin macro invocations. Regular macro
+ * invocations are expanded lazily, but builtin macro invocations need to be
+ * expanded eagerly, hence the differentiation.
+ */
 class MacroInvocation : public TypeNoBounds,
 			public Pattern,
 			public Item,
@@ -589,26 +611,47 @@ class MacroInvocation : public TypeNoBounds,
 			public ExternalItem,
 			public ExprWithoutBlock
 {
-  std::vector<Attribute> outer_attrs;
-  MacroInvocData invoc_data;
-  Location locus;
-
-  // Important for when we actually expand the macro
-  bool is_semi_coloned;
-
-  NodeId node_id;
-
 public:
+  enum class InvocKind
+  {
+    Regular,
+    Builtin,
+  };
+
   std::string as_string () const override;
 
-  MacroInvocation (MacroInvocData invoc_data,
-		   std::vector<Attribute> outer_attrs, Location locus,
-		   bool is_semi_coloned = false)
-    : outer_attrs (std::move (outer_attrs)),
-      invoc_data (std::move (invoc_data)), locus (locus),
-      is_semi_coloned (is_semi_coloned),
-      node_id (Analysis::Mappings::get ()->get_next_node_id ())
-  {}
+  /**
+   * The default constructor you should use. Whenever we parse a macro call, we
+   * cannot possibly know whether or not this call refers to a builtin macro or
+   * a regular macro. With name resolution and scopes and nested macro calls,
+   * this is literally impossible. Hence, always start by creating a `Regular`
+   * MacroInvocation which will then (maybe!) become a `Builtin` macro
+   * invocation in the expander.
+   */
+  static std::unique_ptr<MacroInvocation>
+  Regular (MacroInvocData invoc_data, std::vector<Attribute> outer_attrs,
+	   Location locus, bool is_semi_coloned = false)
+  {
+    return std::unique_ptr<MacroInvocation> (
+      new MacroInvocation (InvocKind::Regular, Optional<BuiltinMacro>::none (),
+			   invoc_data, outer_attrs, locus, is_semi_coloned));
+  }
+
+  /**
+   * Create a builtin macro invocation. This can only be done after macro
+   * name-resolution and within the macro expander, so unless you're modifying
+   * these visitors, you probably do not want to use this function.
+   */
+  static std::unique_ptr<MacroInvocation>
+  Builtin (BuiltinMacro kind, MacroInvocData invoc_data,
+	   std::vector<Attribute> outer_attrs, Location locus,
+	   bool is_semi_coloned = false)
+  {
+    return std::unique_ptr<MacroInvocation> (
+      new MacroInvocation (InvocKind::Builtin,
+			   Optional<BuiltinMacro>::some (kind), invoc_data,
+			   outer_attrs, locus, is_semi_coloned));
+  }
 
   Location get_locus () const override final { return locus; }
 
@@ -642,6 +685,37 @@ public:
 
   bool has_semicolon () const { return is_semi_coloned; }
 
+  InvocKind get_kind () const { return kind; }
+  Optional<BuiltinMacro> get_builtin_kind () const { return builtin_kind; }
+
+private:
+  /* Full constructor */
+  MacroInvocation (InvocKind kind, Optional<BuiltinMacro> builtin_kind,
+		   MacroInvocData invoc_data,
+		   std::vector<Attribute> outer_attrs, Location locus,
+		   bool is_semi_coloned)
+    : outer_attrs (std::move (outer_attrs)), locus (locus),
+      node_id (Analysis::Mappings::get ()->get_next_node_id ()),
+      invoc_data (std::move (invoc_data)), is_semi_coloned (is_semi_coloned),
+      kind (kind), builtin_kind (builtin_kind)
+  {}
+
+  std::vector<Attribute> outer_attrs;
+  Location locus;
+  NodeId node_id;
+
+  /* The data given to the macro invocation */
+  MacroInvocData invoc_data;
+
+  /* Important for when we actually expand the macro */
+  bool is_semi_coloned;
+
+  /* Is this a builtin macro or a regular macro */
+  InvocKind kind;
+
+  /* If it is a builtin macro, which one */
+  Optional<BuiltinMacro> builtin_kind = Optional<BuiltinMacro>::none ();
+
 protected:
   /* Use covariance to implement clone function as returning this object rather
    * than base */
diff --git a/gcc/rust/expand/rust-attribute-visitor.cc b/gcc/rust/expand/rust-attribute-visitor.cc
index a1895749b82..6bceed62096 100644
--- a/gcc/rust/expand/rust-attribute-visitor.cc
+++ b/gcc/rust/expand/rust-attribute-visitor.cc
@@ -389,6 +389,8 @@ AttrVisitor::visit (AST::ConstGenericParam &)
 void
 AttrVisitor::visit (AST::MacroInvocation &macro_invoc)
 {
+  // FIXME: Probably need to check macro_invoc.kind
+
   // initial strip test based on outer attrs
   expander.expand_cfg_attrs (macro_invoc.get_outer_attrs ());
   if (expander.fails_cfg_with_expand (macro_invoc.get_outer_attrs ()))
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index af749ca9200..a0bc2e10d2f 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -1752,10 +1752,9 @@ Parser<ManagedTokenSource>::parse_macro_invocation_semi (
 	    {
 	      // as this is the end, allow recovery (probably) - may change
 
-	      return std::unique_ptr<AST::MacroInvocation> (
-		new AST::MacroInvocation (std::move (invoc_data),
-					  std::move (outer_attrs), macro_locus,
-					  true));
+	      return AST::MacroInvocation::Regular (std::move (invoc_data),
+						    std::move (outer_attrs),
+						    macro_locus, true);
 	    }
 	}
 
@@ -1764,9 +1763,9 @@ Parser<ManagedTokenSource>::parse_macro_invocation_semi (
 		  t->get_token_description (),
 		  lexer.peek_token ()->get_token_description ());
 
-      return std::unique_ptr<AST::MacroInvocation> (
-	new AST::MacroInvocation (std::move (invoc_data),
-				  std::move (outer_attrs), macro_locus, true));
+      return AST::MacroInvocation::Regular (std::move (invoc_data),
+					    std::move (outer_attrs),
+					    macro_locus, true);
     }
   else
     {
@@ -1814,10 +1813,9 @@ Parser<ManagedTokenSource>::parse_macro_invocation (AST::AttrVec outer_attrs)
 
   Location macro_locus = macro_path.get_locus ();
 
-  return std::unique_ptr<AST::MacroInvocation> (
-    new AST::MacroInvocation (AST::MacroInvocData (std::move (macro_path),
-						   std::move (delim_tok_tree)),
-			      std::move (outer_attrs), macro_locus));
+  return AST::MacroInvocation::Regular (
+    AST::MacroInvocData (std::move (macro_path), std::move (delim_tok_tree)),
+    std::move (outer_attrs), macro_locus);
 }
 
 // Parses a macro rule definition - does not parse semicolons.
@@ -9308,11 +9306,10 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
 
 	      AST::DelimTokenTree tok_tree = parse_delim_token_tree ();
 
-	      return std::unique_ptr<AST::MacroInvocation> (
-		new AST::MacroInvocation (
-		  AST::MacroInvocData (std::move (macro_path),
-				       std::move (tok_tree)),
-		  {}, locus));
+	      return AST::MacroInvocation::Regular (
+		AST::MacroInvocData (std::move (macro_path),
+				     std::move (tok_tree)),
+		{}, locus);
 	    }
 	    case PLUS: {
 	      // type param bounds
@@ -10146,11 +10143,10 @@ Parser<ManagedTokenSource>::parse_type_no_bounds ()
 
 	      AST::DelimTokenTree tok_tree = parse_delim_token_tree ();
 
-	      return std::unique_ptr<AST::MacroInvocation> (
-		new AST::MacroInvocation (
-		  AST::MacroInvocData (std::move (macro_path),
-				       std::move (tok_tree)),
-		  {}, locus));
+	      return AST::MacroInvocation::Regular (
+		AST::MacroInvocData (std::move (macro_path),
+				     std::move (tok_tree)),
+		{}, locus);
 	    }
 	  default:
 	    // assume that this is a type path and not an error
@@ -12010,18 +12006,17 @@ Parser<ManagedTokenSource>::parse_path_based_stmt_or_expr (
 	      {
 		lexer.skip_token ();
 
-		std::unique_ptr<AST::MacroInvocation> stmt (
-		  new AST::MacroInvocation (std::move (invoc_data),
-					    std::move (outer_attrs),
-					    stmt_or_expr_loc, true));
+		auto stmt
+		  = AST::MacroInvocation::Regular (std::move (invoc_data),
+						   std::move (outer_attrs),
+						   stmt_or_expr_loc, true);
 		return ExprOrStmt (std::move (stmt));
 	      }
 
 	    // otherwise, create macro invocation
-	    std::unique_ptr<AST::MacroInvocation> expr (
-	      new AST::MacroInvocation (std::move (invoc_data),
-					std::move (outer_attrs),
-					stmt_or_expr_loc, false));
+	    auto expr = AST::MacroInvocation::Regular (std::move (invoc_data),
+						       std::move (outer_attrs),
+						       stmt_or_expr_loc, false);
 	    return ExprOrStmt (std::move (expr));
 	  }
 	else
@@ -12330,17 +12325,16 @@ Parser<ManagedTokenSource>::parse_macro_invocation_maybe_semi (
 	{
 	  lexer.skip_token ();
 
-	  std::unique_ptr<AST::MacroInvocation> stmt (
-	    new AST::MacroInvocation (std::move (invoc_data),
-				      std::move (outer_attrs), macro_locus,
-				      true));
+	  auto stmt = AST::MacroInvocation::Regular (std::move (invoc_data),
+						     std::move (outer_attrs),
+						     macro_locus, true);
 	  return ExprOrStmt (std::move (stmt));
 	}
 
       // otherwise, create macro invocation
-      std::unique_ptr<AST::MacroInvocation> expr (
-	new AST::MacroInvocation (std::move (invoc_data),
-				  std::move (outer_attrs), macro_locus));
+      auto expr
+	= AST::MacroInvocation::Regular (std::move (invoc_data),
+					 std::move (outer_attrs), macro_locus);
       return ExprOrStmt (std::move (expr));
     }
   else
@@ -14552,9 +14546,9 @@ Parser<ManagedTokenSource>::parse_macro_invocation_partial (
 
   Location macro_locus = converted_path.get_locus ();
 
-  return std::unique_ptr<AST::MacroInvocation> (new AST::MacroInvocation (
+  return AST::MacroInvocation::Regular (
     AST::MacroInvocData (std::move (converted_path), std::move (tok_tree)),
-    std::move (outer_attrs), macro_locus, restrictions.expr_can_be_stmt));
+    std::move (outer_attrs), macro_locus, restrictions.expr_can_be_stmt);
 }
 
 /* Parses a struct expr struct with a path in expression already parsed (but
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 24/88] gccrs: Create and use CompilePatternLet visitor for compiling let statments
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (22 preceding siblings ...)
  2023-04-05 14:03 ` [committed 23/88] gccrs: macro: Allow builtin `MacroInvocation`s within the AST arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 25/88] gccrs: parser: Allow parsing multiple reference types arthur.cohen
                   ` (65 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Owen Avery

From: Owen Avery <powerboat9.gamer@gmail.com>

gcc/rust/ChangeLog:

	* backend/rust-compile-pattern.cc (CompilePatternLet::visit): New function.
	* backend/rust-compile-stmt.cc (CompileStmt::visit): Likewise.
	* backend/rust-compile-pattern.h (class CompilePatternLet): New visitor.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
---
 gcc/rust/backend/rust-compile-pattern.cc | 58 ++++++++++++++++
 gcc/rust/backend/rust-compile-pattern.h  | 87 ++++++++++++++++++++++++
 gcc/rust/backend/rust-compile-stmt.cc    | 31 +--------
 3 files changed, 148 insertions(+), 28 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc
index 9218b815dd8..e13d6caf7e6 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -341,5 +341,63 @@ CompilePatternBindings::visit (HIR::GroupedPattern &pattern)
   pattern.get_item ()->accept_vis (*this);
 }
 
+void
+CompilePatternLet::visit (HIR::IdentifierPattern &pattern)
+{
+  Bvariable *var = nullptr;
+  rust_assert (
+    ctx->lookup_var_decl (pattern.get_pattern_mappings ().get_hirid (), &var));
+
+  auto fnctx = ctx->peek_fn ();
+  if (ty->is_unit ())
+    {
+      ctx->add_statement (init_expr);
+
+      tree stmt_type = TyTyResolveCompile::compile (ctx, ty);
+
+      auto unit_type_init_expr
+	= ctx->get_backend ()->constructor_expression (stmt_type, false, {}, -1,
+						       rval_locus);
+      auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var,
+						    unit_type_init_expr);
+      ctx->add_statement (s);
+    }
+  else
+    {
+      auto s
+	= ctx->get_backend ()->init_statement (fnctx.fndecl, var, init_expr);
+      ctx->add_statement (s);
+    }
+}
+
+void
+CompilePatternLet::visit (HIR::WildcardPattern &pattern)
+{
+  Bvariable *var = nullptr;
+  rust_assert (
+    ctx->lookup_var_decl (pattern.get_pattern_mappings ().get_hirid (), &var));
+
+  auto fnctx = ctx->peek_fn ();
+  if (ty->is_unit ())
+    {
+      ctx->add_statement (init_expr);
+
+      tree stmt_type = TyTyResolveCompile::compile (ctx, ty);
+
+      auto unit_type_init_expr
+	= ctx->get_backend ()->constructor_expression (stmt_type, false, {}, -1,
+						       rval_locus);
+      auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var,
+						    unit_type_init_expr);
+      ctx->add_statement (s);
+    }
+  else
+    {
+      auto s
+	= ctx->get_backend ()->init_statement (fnctx.fndecl, var, init_expr);
+      ctx->add_statement (s);
+    }
+}
+
 } // namespace Compile
 } // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-pattern.h b/gcc/rust/backend/rust-compile-pattern.h
index 43334affca7..317a3451161 100644
--- a/gcc/rust/backend/rust-compile-pattern.h
+++ b/gcc/rust/backend/rust-compile-pattern.h
@@ -91,5 +91,92 @@ protected:
   tree match_scrutinee_expr;
 };
 
+class CompilePatternLet : public HIRCompileBase, public HIR::HIRPatternVisitor
+{
+public:
+  static void Compile (HIR::Pattern *pattern, tree init_expr,
+		       TyTy::BaseType *ty, Location rval_locus, Context *ctx)
+  {
+    CompilePatternLet compiler (ctx, init_expr, ty, rval_locus);
+    pattern->accept_vis (compiler);
+  }
+
+  void visit (HIR::IdentifierPattern &) override;
+  void visit (HIR::WildcardPattern &) override;
+
+  // check for unimplemented Pattern HIR nodes.
+  void visit (HIR::GroupedPattern &pattern) override
+  {
+    rust_sorry_at (pattern.get_locus (),
+		   "grouped pattern let statements not supported");
+  }
+
+  void visit (HIR::LiteralPattern &pattern) override
+  {
+    rust_sorry_at (pattern.get_locus (),
+		   "literal pattern let statements not supported");
+  }
+
+  void visit (HIR::PathInExpression &pattern) override
+  {
+    rust_sorry_at (pattern.get_locus (),
+		   "path-in-expression pattern let statements not supported");
+  }
+
+  void visit (HIR::QualifiedPathInExpression &pattern) override
+  {
+    rust_sorry_at (
+      pattern.get_locus (),
+      "qualified-path-in-expression pattern let statements not supported");
+  }
+
+  void visit (HIR::RangePattern &pattern) override
+  {
+    rust_sorry_at (pattern.get_locus (),
+		   "range pattern let statements not supported");
+  }
+
+  void visit (HIR::ReferencePattern &pattern) override
+  {
+    rust_sorry_at (pattern.get_locus (),
+		   "reference pattern let statements not supported");
+  }
+
+  void visit (HIR::SlicePattern &pattern) override
+  {
+    rust_sorry_at (pattern.get_locus (),
+		   "slice pattern let statements not supported");
+  }
+
+  void visit (HIR::StructPattern &pattern) override
+  {
+    rust_sorry_at (pattern.get_locus (),
+		   "struct pattern let statements not supported");
+  }
+
+  void visit (HIR::TuplePattern &pattern) override
+  {
+    rust_sorry_at (pattern.get_locus (),
+		   "tuple pattern let statements not supported");
+  }
+
+  void visit (HIR::TupleStructPattern &pattern) override
+  {
+    rust_sorry_at (pattern.get_locus (),
+		   "tuple-struct pattern let statements not supported");
+  }
+
+protected:
+  CompilePatternLet (Context *ctx, tree init_expr, TyTy::BaseType *ty,
+		     Location rval_locus)
+    : HIRCompileBase (ctx), init_expr (init_expr), ty (ty),
+      rval_locus (rval_locus)
+  {}
+
+  tree init_expr;
+  TyTy::BaseType *ty;
+  Location rval_locus;
+};
+
 } // namespace Compile
 } // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-stmt.cc b/gcc/rust/backend/rust-compile-stmt.cc
index 3fc2528ff6b..6bb4ead9451 100644
--- a/gcc/rust/backend/rust-compile-stmt.cc
+++ b/gcc/rust/backend/rust-compile-stmt.cc
@@ -16,6 +16,7 @@
 // along with GCC; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
+#include "rust-compile-pattern.h"
 #include "rust-compile-stmt.h"
 #include "rust-compile-expr.h"
 
@@ -53,7 +54,7 @@ CompileStmt::visit (HIR::LetStmt &stmt)
   if (!stmt.has_init_expr ())
     return;
 
-  const HIR::Pattern &stmt_pattern = *stmt.get_pattern ();
+  HIR::Pattern &stmt_pattern = *stmt.get_pattern ();
   HirId stmt_id = stmt_pattern.get_pattern_mappings ().get_hirid ();
 
   TyTy::BaseType *ty = nullptr;
@@ -65,15 +66,6 @@ CompileStmt::visit (HIR::LetStmt &stmt)
       return;
     }
 
-  Bvariable *var = nullptr;
-  if (!ctx->lookup_var_decl (stmt_id, &var))
-    {
-      // FIXME this should be an assertion instead and use error mark node
-      rust_fatal_error (stmt.get_locus (),
-			"failed to lookup compiled variable declaration");
-      return;
-    }
-
   tree init = CompileExpr::Compile (stmt.get_init_expr (), ctx);
   // FIXME use error_mark_node, check that CompileExpr returns error_mark_node
   // on failure and make this an assertion
@@ -84,7 +76,6 @@ CompileStmt::visit (HIR::LetStmt &stmt)
   bool ok = ctx->get_tyctx ()->lookup_type (
     stmt.get_init_expr ()->get_mappings ().get_hirid (), &actual);
   rust_assert (ok);
-  tree stmt_type = TyTyResolveCompile::compile (ctx, ty);
 
   Location lvalue_locus = stmt.get_pattern ()->get_locus ();
   Location rvalue_locus = stmt.get_init_expr ()->get_locus ();
@@ -92,23 +83,7 @@ CompileStmt::visit (HIR::LetStmt &stmt)
   init = coercion_site (stmt.get_mappings ().get_hirid (), init, actual,
 			expected, lvalue_locus, rvalue_locus);
 
-  auto fnctx = ctx->peek_fn ();
-  if (ty->is_unit ())
-    {
-      ctx->add_statement (init);
-
-      auto unit_type_init_expr
-	= ctx->get_backend ()->constructor_expression (stmt_type, false, {}, -1,
-						       rvalue_locus);
-      auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var,
-						    unit_type_init_expr);
-      ctx->add_statement (s);
-    }
-  else
-    {
-      auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var, init);
-      ctx->add_statement (s);
-    }
+  CompilePatternLet::Compile (&stmt_pattern, init, ty, rvalue_locus, ctx);
 }
 
 } // namespace Compile
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 25/88] gccrs: parser: Allow parsing multiple reference types
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (23 preceding siblings ...)
  2023-04-05 14:03 ` [committed 24/88] gccrs: Create and use CompilePatternLet visitor for compiling let statments arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 26/88] gccrs: Move rust-buffered-queue.h to util folder #1766 arthur.cohen
                   ` (64 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

The parser now recursively tries to parse a reference type after seeing
a `&` or `&&` token.

gcc/rust/ChangeLog:

	* parse/rust-parse-impl.h (Parser::parse_type): Handle double ampersan
	properly
	(Parser::parse_reference_type): Call into `parse_reference_type_inner`
	and wrap double reference types in another `AST::ReferenceType` node
	(Parser::parse_reference_type_inner): Add parsing implementation
	which does not care about the leading token (& or  &&)
	(Parser::parse_type_no_bounds): Handle double ampersand properly
	* parse/rust-parse.h: Declare `parse_reference_type_inner`

gcc/testsuite/ChangeLog:

	* rust/compile/multi_reference_type.rs: New test.
---
 gcc/rust/parse/rust-parse-impl.h              | 33 +++++++++++++++----
 gcc/rust/parse/rust-parse.h                   |  2 ++
 .../rust/compile/multi_reference_type.rs      | 12 +++++++
 3 files changed, 41 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/multi_reference_type.rs

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index a0bc2e10d2f..23b033fb26e 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -9237,6 +9237,7 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
       // raw pointer type
       return parse_raw_pointer_type ();
     case AMP: // does this also include AMP_AMP?
+    case LOGICAL_AND:
       // reference type
       return parse_reference_type ();
       case LIFETIME: {
@@ -9886,14 +9887,10 @@ Parser<ManagedTokenSource>::parse_bare_function_type (
 			       std::move (return_type), best_try_locus));
 }
 
-// Parses a reference type (mutable or immutable, with given lifetime).
 template <typename ManagedTokenSource>
 std::unique_ptr<AST::ReferenceType>
-Parser<ManagedTokenSource>::parse_reference_type ()
+Parser<ManagedTokenSource>::parse_reference_type_inner (Location locus)
 {
-  Location locus = lexer.peek_token ()->get_locus ();
-  skip_token (AMP);
-
   // parse optional lifetime
   AST::Lifetime lifetime = AST::Lifetime::error ();
   if (lexer.peek_token ()->get_id () == LIFETIME)
@@ -9932,6 +9929,29 @@ Parser<ManagedTokenSource>::parse_reference_type ()
 			    std::move (lifetime)));
 }
 
+// Parses a reference type (mutable or immutable, with given lifetime).
+template <typename ManagedTokenSource>
+std::unique_ptr<AST::ReferenceType>
+Parser<ManagedTokenSource>::parse_reference_type ()
+{
+  auto t = lexer.peek_token ();
+  auto locus = t->get_locus ();
+
+  switch (t->get_id ())
+    {
+    case AMP:
+      skip_token (AMP);
+      return parse_reference_type_inner (locus);
+    case LOGICAL_AND:
+      skip_token (LOGICAL_AND);
+      return std::unique_ptr<AST::ReferenceType> (
+	new AST::ReferenceType (false, parse_reference_type_inner (locus),
+				locus));
+    default:
+      gcc_unreachable ();
+    }
+}
+
 // Parses a raw (unsafe) pointer type.
 template <typename ManagedTokenSource>
 std::unique_ptr<AST::RawPointerType>
@@ -10079,7 +10099,8 @@ Parser<ManagedTokenSource>::parse_type_no_bounds ()
     case ASTERISK:
       // raw pointer type
       return parse_raw_pointer_type ();
-    case AMP: // does this also include AMP_AMP?
+    case AMP: // does this also include AMP_AMP? Yes! Which is... LOGICAL_AND?
+    case LOGICAL_AND:
       // reference type
       return parse_reference_type ();
     case LIFETIME:
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 5c0fcc3f174..2f767bb2a53 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -604,6 +604,8 @@ private:
   std::unique_ptr<AST::TypeNoBounds> parse_type_no_bounds ();
   std::unique_ptr<AST::TypeNoBounds> parse_slice_or_array_type ();
   std::unique_ptr<AST::RawPointerType> parse_raw_pointer_type ();
+  std::unique_ptr<AST::ReferenceType>
+  parse_reference_type_inner (Location locus);
   std::unique_ptr<AST::ReferenceType> parse_reference_type ();
   std::unique_ptr<AST::BareFunctionType>
   parse_bare_function_type (std::vector<AST::LifetimeParam> for_lifetimes);
diff --git a/gcc/testsuite/rust/compile/multi_reference_type.rs b/gcc/testsuite/rust/compile/multi_reference_type.rs
new file mode 100644
index 00000000000..5ad7d84adbc
--- /dev/null
+++ b/gcc/testsuite/rust/compile/multi_reference_type.rs
@@ -0,0 +1,12 @@
+fn main() {
+    let a = 15u8;
+    let a: &u8 = &a;
+    let a: &&u8 = &a;
+    let a: &&&u8 = &a;
+    let _: &&&&u8 = &a;
+
+    let _: &&u8;
+    let _: &mut &u8;
+    let _: &&mut u8;
+    let _: &mut &mut &u8;
+}
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 26/88] gccrs: Move rust-buffered-queue.h to util folder #1766
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (24 preceding siblings ...)
  2023-04-05 14:03 ` [committed 25/88] gccrs: parser: Allow parsing multiple reference types arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 27/88] gccrs: Improve GroupedPattern lowering arthur.cohen
                   ` (63 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, MAHAD

From: MAHAD <mahadtxt@gmail.com>

gcc/rust/ChangeLog:

	* rust-buffered-queue.h: Moved to...
	* util/rust-buffered-queue.h: ...here.

Signed-off-by: Muhammad Mahad <mahadtxt@gmail.com>
---
 gcc/rust/{ => util}/rust-buffered-queue.h | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename gcc/rust/{ => util}/rust-buffered-queue.h (100%)

diff --git a/gcc/rust/rust-buffered-queue.h b/gcc/rust/util/rust-buffered-queue.h
similarity index 100%
rename from gcc/rust/rust-buffered-queue.h
rename to gcc/rust/util/rust-buffered-queue.h
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 27/88] gccrs: Improve GroupedPattern lowering
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (25 preceding siblings ...)
  2023-04-05 14:03 ` [committed 26/88] gccrs: Move rust-buffered-queue.h to util folder #1766 arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 28/88] gccrs: Remove HIR::GroupedPattern arthur.cohen
                   ` (62 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Owen Avery

From: Owen Avery <powerboat9.gamer@gmail.com>

gcc/rust/ChangeLog:

	* hir/rust-ast-lower-pattern.cc
	(ASTLoweringPattern::visit): Lower AST::GroupedPattern to its inner pattern.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
---
 gcc/rust/hir/rust-ast-lower-pattern.cc | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc
index 8ee3a979a33..a0fd8dded38 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.cc
+++ b/gcc/rust/hir/rust-ast-lower-pattern.cc
@@ -246,17 +246,7 @@ ASTLoweringPattern::visit (AST::RangePattern &pattern)
 void
 ASTLoweringPattern::visit (AST::GroupedPattern &pattern)
 {
-  auto crate_num = mappings->get_current_crate ();
-  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
-				 mappings->get_next_hir_id (crate_num),
-				 UNKNOWN_LOCAL_DEFID);
-
-  HIR::Pattern *inner
-    = ASTLoweringPattern::translate (pattern.get_pattern_in_parens ().get ());
-
-  translated
-    = new HIR::GroupedPattern (mapping, std::unique_ptr<HIR::Pattern> (inner),
-			       pattern.get_locus ());
+  pattern.get_pattern_in_parens ()->accept_vis (*this);
 }
 
 } // namespace HIR
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 28/88] gccrs: Remove HIR::GroupedPattern
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (26 preceding siblings ...)
  2023-04-05 14:03 ` [committed 27/88] gccrs: Improve GroupedPattern lowering arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 29/88] gccrs: Optimize HIR::ReferencePattern arthur.cohen
                   ` (61 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Owen Avery

From: Owen Avery <powerboat9.gamer@gmail.com>

gcc/rust/ChangeLog:

	* backend/rust-compile-fnparam.h
	(CompileFnParam::visit): Remove HIR::GroupedPattern visitor.
	* backend/rust-compile-pattern.cc
	(CompilePatternCaseLabelExpr::visit): Remove HIR::GroupedPattern visitor.
	(CompilePatternBindings::visit): Remove HIR::GroupedPattern visitor.
	* backend/rust-compile-pattern.h
	(CompilePatternCaseLabelExpr::visit): Remove HIR::GroupedPattern visitor.
	(CompilePatternBindings::visit): Remove HIR::GroupedPattern visitor.
	(CompilePatternLet::visit): Remove HIR::GroupedPattern visitor.
	* backend/rust-compile-resolve-path.h
	(ResolvePathRef::visit): Remove HIR::GroupedPattern visitor.
	* backend/rust-compile-var-decl.h
	(CompileVarDecl::visit): Remove HIR::GroupedPattern visitor.
	* checks/errors/rust-const-checker.cc
	(ConstChecker::visit): Remove HIR::GroupedPattern visitor.
	* checks/errors/rust-const-checker.h
	(ConstChecker::visit): Remove HIR::GroupedPattern visitor.
	* checks/errors/rust-unsafe-checker.cc
	(UnsafeChecker::visit): Remove HIR::GroupedPattern visitor.
	* checks/errors/rust-unsafe-checker.h
	(UnsafeChecker::visit): Remove HIR::GroupedPattern visitor.
	* hir/rust-hir-dump.cc (Dump::visit): Remove HIR::GroupedPattern visitor.
	* hir/rust-hir-dump.h (Dump::visit): Remove HIR::GroupedPattern visitor.
	* hir/tree/rust-hir-full-decls.h (class GroupedPattern): Remove class.
	* hir/tree/rust-hir-full-test.cc (GroupedPattern::accept_vis): Remove method.
	* hir/tree/rust-hir-pattern.h (class GroupedPattern): Remove class.
	* hir/tree/rust-hir-visitor.h
	(HIRFullVisitor::visit): Remove HIR::GroupedPattern visitor.
	(HIRFullVisitorBase::visit): Remove HIR::GroupedPattern visitor.
	(HIRPatternVisitor::visit): Remove HIR::GroupedPattern visitor.
	* typecheck/rust-hir-type-check-pattern.cc
	(TypeCheckPattern::visit): Remove HIR::GroupedPattern visitor.
	* typecheck/rust-hir-type-check-pattern.h
	(TypeCheckPattern::visit): Remove HIR::GroupedPattern visitor.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
---
 gcc/rust/backend/rust-compile-fnparam.h       |  1 -
 gcc/rust/backend/rust-compile-pattern.cc      | 12 ----
 gcc/rust/backend/rust-compile-pattern.h       |  8 ---
 gcc/rust/backend/rust-compile-resolve-path.h  |  1 -
 gcc/rust/backend/rust-compile-var-decl.h      |  1 -
 gcc/rust/checks/errors/rust-const-checker.cc  |  4 --
 gcc/rust/checks/errors/rust-const-checker.h   |  1 -
 gcc/rust/checks/errors/rust-unsafe-checker.cc |  4 --
 gcc/rust/checks/errors/rust-unsafe-checker.h  |  1 -
 gcc/rust/hir/rust-hir-dump.cc                 |  3 -
 gcc/rust/hir/rust-hir-dump.h                  |  1 -
 gcc/rust/hir/tree/rust-hir-full-decls.h       |  1 -
 gcc/rust/hir/tree/rust-hir-full-test.cc       | 12 ----
 gcc/rust/hir/tree/rust-hir-pattern.h          | 69 -------------------
 gcc/rust/hir/tree/rust-hir-visitor.h          |  3 -
 .../typecheck/rust-hir-type-check-pattern.cc  |  9 ---
 .../typecheck/rust-hir-type-check-pattern.h   |  1 -
 17 files changed, 132 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-fnparam.h b/gcc/rust/backend/rust-compile-fnparam.h
index 0d99814a6b3..10e8b67c140 100644
--- a/gcc/rust/backend/rust-compile-fnparam.h
+++ b/gcc/rust/backend/rust-compile-fnparam.h
@@ -39,7 +39,6 @@ public:
   void visit (HIR::TupleStructPattern &) override;
 
   // Empty visit for unused Pattern HIR nodes.
-  void visit (HIR::GroupedPattern &) override {}
   void visit (HIR::LiteralPattern &) override {}
   void visit (HIR::PathInExpression &) override {}
   void visit (HIR::QualifiedPathInExpression &) override {}
diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc
index e13d6caf7e6..bad98be44d0 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -161,12 +161,6 @@ CompilePatternCaseLabelExpr::visit (HIR::RangePattern &pattern)
   case_label_expr = build_case_label (lower, upper, associated_case_label);
 }
 
-void
-CompilePatternCaseLabelExpr::visit (HIR::GroupedPattern &pattern)
-{
-  pattern.get_item ()->accept_vis (*this);
-}
-
 // setup the bindings
 
 void
@@ -335,12 +329,6 @@ CompilePatternBindings::visit (HIR::StructPattern &pattern)
     }
 }
 
-void
-CompilePatternBindings::visit (HIR::GroupedPattern &pattern)
-{
-  pattern.get_item ()->accept_vis (*this);
-}
-
 void
 CompilePatternLet::visit (HIR::IdentifierPattern &pattern)
 {
diff --git a/gcc/rust/backend/rust-compile-pattern.h b/gcc/rust/backend/rust-compile-pattern.h
index 317a3451161..ddf5b14265e 100644
--- a/gcc/rust/backend/rust-compile-pattern.h
+++ b/gcc/rust/backend/rust-compile-pattern.h
@@ -38,7 +38,6 @@ public:
   void visit (HIR::TupleStructPattern &pattern) override;
   void visit (HIR::WildcardPattern &pattern) override;
   void visit (HIR::RangePattern &pattern) override;
-  void visit (HIR::GroupedPattern &pattern) override;
 
   // Empty visit for unused Pattern HIR nodes.
   void visit (HIR::IdentifierPattern &) override {}
@@ -70,7 +69,6 @@ public:
 
   void visit (HIR::StructPattern &pattern) override;
   void visit (HIR::TupleStructPattern &pattern) override;
-  void visit (HIR::GroupedPattern &) override;
 
   // Empty visit for unused Pattern HIR nodes.
   void visit (HIR::IdentifierPattern &) override {}
@@ -105,12 +103,6 @@ public:
   void visit (HIR::WildcardPattern &) override;
 
   // check for unimplemented Pattern HIR nodes.
-  void visit (HIR::GroupedPattern &pattern) override
-  {
-    rust_sorry_at (pattern.get_locus (),
-		   "grouped pattern let statements not supported");
-  }
-
   void visit (HIR::LiteralPattern &pattern) override
   {
     rust_sorry_at (pattern.get_locus (),
diff --git a/gcc/rust/backend/rust-compile-resolve-path.h b/gcc/rust/backend/rust-compile-resolve-path.h
index 67ff7eed2d5..6aec7be472f 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.h
+++ b/gcc/rust/backend/rust-compile-resolve-path.h
@@ -45,7 +45,6 @@ public:
   void visit (HIR::QualifiedPathInExpression &expr) override;
 
   // Empty visit for unused Pattern HIR nodes.
-  void visit (HIR::GroupedPattern &) override {}
   void visit (HIR::IdentifierPattern &) override {}
   void visit (HIR::LiteralPattern &) override {}
   void visit (HIR::RangePattern &) override {}
diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h
index 791ee9c1112..9e07999f273 100644
--- a/gcc/rust/backend/rust-compile-var-decl.h
+++ b/gcc/rust/backend/rust-compile-var-decl.h
@@ -69,7 +69,6 @@ public:
   }
 
   // Empty visit for unused Pattern HIR nodes.
-  void visit (HIR::GroupedPattern &) override {}
   void visit (HIR::LiteralPattern &) override {}
   void visit (HIR::PathInExpression &) override {}
   void visit (HIR::QualifiedPathInExpression &) override {}
diff --git a/gcc/rust/checks/errors/rust-const-checker.cc b/gcc/rust/checks/errors/rust-const-checker.cc
index 7e31c9f9c28..3752cf36716 100644
--- a/gcc/rust/checks/errors/rust-const-checker.cc
+++ b/gcc/rust/checks/errors/rust-const-checker.cc
@@ -834,10 +834,6 @@ void
 ConstChecker::visit (TuplePattern &)
 {}
 
-void
-ConstChecker::visit (GroupedPattern &)
-{}
-
 void
 ConstChecker::visit (SlicePattern &)
 {}
diff --git a/gcc/rust/checks/errors/rust-const-checker.h b/gcc/rust/checks/errors/rust-const-checker.h
index 238173874aa..e0402361367 100644
--- a/gcc/rust/checks/errors/rust-const-checker.h
+++ b/gcc/rust/checks/errors/rust-const-checker.h
@@ -186,7 +186,6 @@ private:
   virtual void visit (TuplePatternItemsMultiple &tuple_items) override;
   virtual void visit (TuplePatternItemsRanged &tuple_items) override;
   virtual void visit (TuplePattern &pattern) override;
-  virtual void visit (GroupedPattern &pattern) override;
   virtual void visit (SlicePattern &pattern) override;
   virtual void visit (EmptyStmt &stmt) override;
   virtual void visit (LetStmt &stmt) override;
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc b/gcc/rust/checks/errors/rust-unsafe-checker.cc
index 3c369a2a81a..ff7a0b3f85a 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.cc
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc
@@ -901,10 +901,6 @@ void
 UnsafeChecker::visit (TuplePattern &)
 {}
 
-void
-UnsafeChecker::visit (GroupedPattern &)
-{}
-
 void
 UnsafeChecker::visit (SlicePattern &)
 {}
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.h b/gcc/rust/checks/errors/rust-unsafe-checker.h
index 2abd3a62351..ce270c0e7ef 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.h
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.h
@@ -168,7 +168,6 @@ private:
   virtual void visit (TuplePatternItemsMultiple &tuple_items) override;
   virtual void visit (TuplePatternItemsRanged &tuple_items) override;
   virtual void visit (TuplePattern &pattern) override;
-  virtual void visit (GroupedPattern &pattern) override;
   virtual void visit (SlicePattern &pattern) override;
   virtual void visit (EmptyStmt &stmt) override;
   virtual void visit (LetStmt &stmt) override;
diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc
index 875e1dd9374..10720c43294 100644
--- a/gcc/rust/hir/rust-hir-dump.cc
+++ b/gcc/rust/hir/rust-hir-dump.cc
@@ -457,9 +457,6 @@ void
 Dump::visit (TuplePattern &)
 {}
 void
-Dump::visit (GroupedPattern &)
-{}
-void
 Dump::visit (SlicePattern &)
 {}
 
diff --git a/gcc/rust/hir/rust-hir-dump.h b/gcc/rust/hir/rust-hir-dump.h
index 8715a95ada8..b66e6b13f7c 100644
--- a/gcc/rust/hir/rust-hir-dump.h
+++ b/gcc/rust/hir/rust-hir-dump.h
@@ -163,7 +163,6 @@ private:
   virtual void visit (TuplePatternItemsMultiple &) override;
   virtual void visit (TuplePatternItemsRanged &) override;
   virtual void visit (TuplePattern &) override;
-  virtual void visit (GroupedPattern &) override;
   virtual void visit (SlicePattern &) override;
 
   virtual void visit (EmptyStmt &) override;
diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h b/gcc/rust/hir/tree/rust-hir-full-decls.h
index 7870a5497ed..30adda6a1f3 100644
--- a/gcc/rust/hir/tree/rust-hir-full-decls.h
+++ b/gcc/rust/hir/tree/rust-hir-full-decls.h
@@ -206,7 +206,6 @@ class TuplePatternItems;
 class TuplePatternItemsMultiple;
 class TuplePatternItemsRanged;
 class TuplePattern;
-class GroupedPattern;
 class SlicePattern;
 
 // rust-type.h
diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir-full-test.cc
index 230b7f72a85..b6646d61b28 100644
--- a/gcc/rust/hir/tree/rust-hir-full-test.cc
+++ b/gcc/rust/hir/tree/rust-hir-full-test.cc
@@ -4476,12 +4476,6 @@ TuplePattern::accept_vis (HIRFullVisitor &vis)
   vis.visit (*this);
 }
 
-void
-GroupedPattern::accept_vis (HIRFullVisitor &vis)
-{
-  vis.visit (*this);
-}
-
 void
 SlicePattern::accept_vis (HIRFullVisitor &vis)
 {
@@ -4608,12 +4602,6 @@ EmptyStmt::accept_vis (HIRStmtVisitor &vis)
   vis.visit (*this);
 }
 
-void
-GroupedPattern::accept_vis (HIRPatternVisitor &vis)
-{
-  vis.visit (*this);
-}
-
 void
 WildcardPattern::accept_vis (HIRPatternVisitor &vis)
 {
diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h
index b7a230c526f..5243d7898c0 100644
--- a/gcc/rust/hir/tree/rust-hir-pattern.h
+++ b/gcc/rust/hir/tree/rust-hir-pattern.h
@@ -1215,75 +1215,6 @@ protected:
   }
 };
 
-// HIR node representing a pattern in parentheses, used to control precedence
-class GroupedPattern : public Pattern
-{
-  std::unique_ptr<Pattern> pattern_in_parens;
-  Location locus;
-  Analysis::NodeMapping mappings;
-
-public:
-  std::string as_string () const override
-  {
-    return "(" + pattern_in_parens->as_string () + ")";
-  }
-
-  GroupedPattern (Analysis::NodeMapping mappings,
-		  std::unique_ptr<Pattern> pattern_in_parens, Location locus)
-    : pattern_in_parens (std::move (pattern_in_parens)), locus (locus),
-      mappings (mappings)
-  {}
-
-  // Copy constructor uses clone
-  GroupedPattern (GroupedPattern const &other)
-    : pattern_in_parens (other.pattern_in_parens->clone_pattern ()),
-      locus (other.locus), mappings (other.mappings)
-  {}
-
-  // Overload assignment operator to clone
-  GroupedPattern &operator= (GroupedPattern const &other)
-  {
-    pattern_in_parens = other.pattern_in_parens->clone_pattern ();
-    locus = other.locus;
-    mappings = other.mappings;
-
-    return *this;
-  }
-
-  // default move semantics
-  GroupedPattern (GroupedPattern &&other) = default;
-  GroupedPattern &operator= (GroupedPattern &&other) = default;
-
-  Location get_locus () const override { return locus; }
-
-  void accept_vis (HIRFullVisitor &vis) override;
-  void accept_vis (HIRPatternVisitor &vis) override;
-
-  Analysis::NodeMapping get_pattern_mappings () const override final
-  {
-    return mappings;
-  }
-
-  PatternType get_pattern_type () const override final
-  {
-    return PatternType::GROUPED;
-  }
-
-  std::unique_ptr<Pattern> &get_item () { return pattern_in_parens; }
-  const std::unique_ptr<Pattern> &get_item () const
-  {
-    return pattern_in_parens;
-  }
-
-protected:
-  /* Use covariance to implement clone function as returning this object rather
-   * than base */
-  GroupedPattern *clone_pattern_impl () const override
-  {
-    return new GroupedPattern (*this);
-  }
-};
-
 // HIR node representing patterns that can match slices and arrays
 class SlicePattern : public Pattern
 {
diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h b/gcc/rust/hir/tree/rust-hir-visitor.h
index ba6cad7614b..a635f9079f1 100644
--- a/gcc/rust/hir/tree/rust-hir-visitor.h
+++ b/gcc/rust/hir/tree/rust-hir-visitor.h
@@ -138,7 +138,6 @@ public:
   virtual void visit (TuplePatternItemsMultiple &tuple_items) = 0;
   virtual void visit (TuplePatternItemsRanged &tuple_items) = 0;
   virtual void visit (TuplePattern &pattern) = 0;
-  virtual void visit (GroupedPattern &pattern) = 0;
   virtual void visit (SlicePattern &pattern) = 0;
   virtual void visit (EmptyStmt &stmt) = 0;
   virtual void visit (LetStmt &stmt) = 0;
@@ -290,7 +289,6 @@ public:
   virtual void visit (TuplePatternItemsMultiple &) override {}
   virtual void visit (TuplePatternItemsRanged &) override {}
   virtual void visit (TuplePattern &) override {}
-  virtual void visit (GroupedPattern &) override {}
   virtual void visit (SlicePattern &) override {}
 
   virtual void visit (EmptyStmt &) override {}
@@ -470,7 +468,6 @@ public:
 class HIRPatternVisitor
 {
 public:
-  virtual void visit (GroupedPattern &) = 0;
   virtual void visit (IdentifierPattern &) = 0;
   virtual void visit (LiteralPattern &) = 0;
   virtual void visit (PathInExpression &) = 0;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
index 393f4158003..fd4814c3604 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -386,15 +386,6 @@ TypeCheckPattern::visit (HIR::IdentifierPattern &)
   infered = parent;
 }
 
-void
-TypeCheckPattern::visit (HIR::GroupedPattern &pattern)
-{
-  TyTy::BaseType *inner_ty
-    = TypeCheckPattern::Resolve (pattern.get_item ().get (), parent);
-  infered = inner_ty->clone ();
-  infered->set_ref (pattern.get_pattern_mappings ().get_hirid ());
-}
-
 void
 TypeCheckPattern::visit (HIR::QualifiedPathInExpression &)
 {
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.h b/gcc/rust/typecheck/rust-hir-type-check-pattern.h
index bdfc90723e9..e7550071548 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.h
@@ -39,7 +39,6 @@ public:
   void visit (HIR::LiteralPattern &pattern) override;
   void visit (HIR::RangePattern &pattern) override;
   void visit (HIR::IdentifierPattern &pattern) override;
-  void visit (HIR::GroupedPattern &pattern) override;
   void visit (HIR::QualifiedPathInExpression &pattern) override;
   void visit (HIR::ReferencePattern &pattern) override;
   void visit (HIR::SlicePattern &pattern) override;
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 29/88] gccrs: Optimize HIR::ReferencePattern
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (27 preceding siblings ...)
  2023-04-05 14:03 ` [committed 28/88] gccrs: Remove HIR::GroupedPattern arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 30/88] gccrs: Implement lowering ReferencePattern from AST to HIR arthur.cohen
                   ` (60 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Owen Avery

From: Owen Avery <powerboat9.gamer@gmail.com>

gcc/rust/ChangeLog:

	* hir/tree/rust-hir-pattern.h
	(class ReferencePattern): Remove has_two_amps field.
	* hir/tree/rust-hir-full-test.cc
	(ReferencePattern::as_string): Remove usage of ReferencePattern::has_two_amps.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
---
 gcc/rust/hir/tree/rust-hir-full-test.cc |  5 -----
 gcc/rust/hir/tree/rust-hir-pattern.h    | 13 +++++--------
 2 files changed, 5 insertions(+), 13 deletions(-)

diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir-full-test.cc
index b6646d61b28..0ddb8418e95 100644
--- a/gcc/rust/hir/tree/rust-hir-full-test.cc
+++ b/gcc/rust/hir/tree/rust-hir-full-test.cc
@@ -2583,11 +2583,6 @@ ReferencePattern::as_string () const
 {
   std::string str ("&");
 
-  if (has_two_amps)
-    {
-      str += "&";
-    }
-
   if (is_mut ())
     {
       str += "mut ";
diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h
index 5243d7898c0..83b041d2770 100644
--- a/gcc/rust/hir/tree/rust-hir-pattern.h
+++ b/gcc/rust/hir/tree/rust-hir-pattern.h
@@ -424,7 +424,6 @@ protected:
 // HIR node for pattern based on dereferencing the pointers given
 class ReferencePattern : public Pattern
 {
-  bool has_two_amps;
   Mutability mut;
   std::unique_ptr<Pattern> pattern;
   Location locus;
@@ -435,16 +434,15 @@ public:
 
   ReferencePattern (Analysis::NodeMapping mappings,
 		    std::unique_ptr<Pattern> pattern, Mutability reference_mut,
-		    bool ref_has_two_amps, Location locus)
-    : has_two_amps (ref_has_two_amps), mut (reference_mut),
-      pattern (std::move (pattern)), locus (locus), mappings (mappings)
+		    Location locus)
+    : mut (reference_mut), pattern (std::move (pattern)), locus (locus),
+      mappings (mappings)
   {}
 
   // Copy constructor requires clone
   ReferencePattern (ReferencePattern const &other)
-    : has_two_amps (other.has_two_amps), mut (other.mut),
-      pattern (other.pattern->clone_pattern ()), locus (other.locus),
-      mappings (other.mappings)
+    : mut (other.mut), pattern (other.pattern->clone_pattern ()),
+      locus (other.locus), mappings (other.mappings)
   {}
 
   // Overload assignment operator to clone
@@ -452,7 +450,6 @@ public:
   {
     pattern = other.pattern->clone_pattern ();
     mut = other.mut;
-    has_two_amps = other.has_two_amps;
     locus = other.locus;
     mappings = other.mappings;
 
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 30/88] gccrs: Implement lowering ReferencePattern from AST to HIR
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (28 preceding siblings ...)
  2023-04-05 14:03 ` [committed 29/88] gccrs: Optimize HIR::ReferencePattern arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 31/88] gccrs: parser: Improve parsing of complex generic arguments arthur.cohen
                   ` (59 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Owen Avery

From: Owen Avery <powerboat9.gamer@gmail.com>

gcc/rust/ChangeLog:

	* ast/rust-pattern.h:
	(ReferencePattern::is_double_reference): Add method.
	(ReferencePattern::get_is_mut): Add method.
	* hir/rust-ast-lower-pattern.cc
	(ASTLoweringPattern::visit): Add ReferencePattern visitor.
	* hir/rust-ast-lower-pattern.h:
	(ASTLoweringPattern::visit): Add ReferencePattern visitor.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
---
 gcc/rust/ast/rust-pattern.h            |  4 ++++
 gcc/rust/hir/rust-ast-lower-pattern.cc | 29 ++++++++++++++++++++++++++
 gcc/rust/hir/rust-ast-lower-pattern.h  |  1 +
 3 files changed, 34 insertions(+)

diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h
index c86bdf6f820..cf5d2ead10d 100644
--- a/gcc/rust/ast/rust-pattern.h
+++ b/gcc/rust/ast/rust-pattern.h
@@ -469,6 +469,10 @@ public:
     return pattern;
   }
 
+  bool is_double_reference () const { return has_two_amps; }
+
+  bool get_is_mut () const { return is_mut; }
+
   NodeId get_node_id () const { return node_id; }
 
   NodeId get_pattern_node_id () const override final { return node_id; }
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc
index a0fd8dded38..1961c740624 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.cc
+++ b/gcc/rust/hir/rust-ast-lower-pattern.cc
@@ -249,5 +249,34 @@ ASTLoweringPattern::visit (AST::GroupedPattern &pattern)
   pattern.get_pattern_in_parens ()->accept_vis (*this);
 }
 
+void
+ASTLoweringPattern::visit (AST::ReferencePattern &pattern)
+{
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  HIR::Pattern *inner
+    = ASTLoweringPattern::translate (pattern.get_referenced_pattern ().get ());
+
+  translated
+    = new HIR::ReferencePattern (mapping, std::unique_ptr<HIR::Pattern> (inner),
+				 pattern.get_is_mut () ? Mutability::Mut
+						       : Mutability::Imm,
+				 pattern.get_locus ());
+
+  if (pattern.is_double_reference ())
+    {
+      Analysis::NodeMapping mapping2 (crate_num, pattern.get_node_id (),
+				      mappings->get_next_hir_id (crate_num),
+				      UNKNOWN_LOCAL_DEFID);
+      translated
+	= new HIR::ReferencePattern (mapping2,
+				     std::unique_ptr<HIR::Pattern> (translated),
+				     Mutability::Imm, pattern.get_locus ());
+    }
+}
+
 } // namespace HIR
 } // namespace Rust
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.h b/gcc/rust/hir/rust-ast-lower-pattern.h
index 0075e27e9c0..2d175a25cb4 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.h
+++ b/gcc/rust/hir/rust-ast-lower-pattern.h
@@ -40,6 +40,7 @@ public:
   void visit (AST::LiteralPattern &pattern) override;
   void visit (AST::RangePattern &pattern) override;
   void visit (AST::GroupedPattern &pattern) override;
+  void visit (AST::ReferencePattern &pattern) override;
 
 private:
   ASTLoweringPattern ();
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 31/88] gccrs: parser: Improve parsing of complex generic arguments
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (29 preceding siblings ...)
  2023-04-05 14:03 ` [committed 30/88] gccrs: Implement lowering ReferencePattern from AST to HIR arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 32/88] gccrs: parser: Fix parsing of closure param list arthur.cohen
                   ` (58 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

The parser was missing code for handling complex type arguments such
as type paths or nested generics.

gcc/rust/ChangeLog:

	* parse/rust-parse-impl.h (Parser::parse_generic_arg): Handle type
	paths and nested generics properly.

gcc/testsuite/ChangeLog:

	* rust/compile/parse_complex_generic_application.rs: New test.
	* rust/compile/parse_complex_generic_application2.rs: New test.
---
 gcc/rust/parse/rust-parse-impl.h                |  4 +++-
 .../parse_complex_generic_application.rs        | 17 +++++++++++++++++
 .../parse_complex_generic_application2.rs       | 10 ++++++++++
 3 files changed, 30 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/rust/compile/parse_complex_generic_application.rs
 create mode 100644 gcc/testsuite/rust/compile/parse_complex_generic_application2.rs

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 23b033fb26e..3610790815c 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -6309,7 +6309,9 @@ Parser<ManagedTokenSource>::parse_generic_arg ()
 	// could either have a valid type or a macro (FIXME: anything else?). So
 	// we need one bit of lookahead to differentiate if this is really
 	auto next_tok = lexer.peek_token (1);
-	if (next_tok->get_id () == EXCLAM)
+	if (next_tok->get_id () == LEFT_ANGLE
+	    || next_tok->get_id () == SCOPE_RESOLUTION
+	    || next_tok->get_id () == EXCLAM)
 	  {
 	    auto type = parse_type ();
 	    if (type)
diff --git a/gcc/testsuite/rust/compile/parse_complex_generic_application.rs b/gcc/testsuite/rust/compile/parse_complex_generic_application.rs
new file mode 100644
index 00000000000..d5c7bf488b7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/parse_complex_generic_application.rs
@@ -0,0 +1,17 @@
+pub enum Either<T, E> {
+    Left(T),
+    Right(E),
+}
+
+pub mod err {
+    pub struct Error;
+    pub struct ErrorWrap<T>(T);
+}
+
+pub fn foo_err() -> Either<(), err::Error> {
+    Either::Left(())
+}
+
+pub fn foo_err_wrap() -> Either<(), err::ErrorWrap<u8>> {
+    Either::Left(())
+}
diff --git a/gcc/testsuite/rust/compile/parse_complex_generic_application2.rs b/gcc/testsuite/rust/compile/parse_complex_generic_application2.rs
new file mode 100644
index 00000000000..0361931c50c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/parse_complex_generic_application2.rs
@@ -0,0 +1,10 @@
+pub enum Either<L, R> {
+    Left(L),
+    Right(R),
+}
+
+pub struct Wrap<T>(T);
+
+pub fn foo_wrap() -> Either<(), Wrap<u8>> {
+    Either::Left(())
+}
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 32/88] gccrs: parser: Fix parsing of closure param list
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (30 preceding siblings ...)
  2023-04-05 14:03 ` [committed 31/88] gccrs: parser: Improve parsing of complex generic arguments arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 33/88] gccrs: Add support for feature check arthur.cohen
                   ` (57 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* parse/rust-parse-impl.h (Parser::parse_closure_expr): Advance tokens
	properly when parsing closure param list.

gcc/testsuite/ChangeLog:

	* rust/compile/closure_move_expr.rs: New test.
---
 gcc/rust/parse/rust-parse-impl.h                | 2 ++
 gcc/testsuite/rust/compile/closure_move_expr.rs | 9 +++++++++
 2 files changed, 11 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/closure_move_expr.rs

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 3610790815c..4ceb978f7f4 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -7592,6 +7592,7 @@ Parser<ManagedTokenSource>::parse_closure_expr (AST::AttrVec outer_attrs)
     case PIPE:
       // actually may have parameters
       lexer.skip_token ();
+      t = lexer.peek_token ();
 
       while (t->get_id () != PIPE)
 	{
@@ -7608,6 +7609,7 @@ Parser<ManagedTokenSource>::parse_closure_expr (AST::AttrVec outer_attrs)
 
 	  if (lexer.peek_token ()->get_id () != COMMA)
 	    {
+	      lexer.skip_token ();
 	      // not an error but means param list is done
 	      break;
 	    }
diff --git a/gcc/testsuite/rust/compile/closure_move_expr.rs b/gcc/testsuite/rust/compile/closure_move_expr.rs
new file mode 100644
index 00000000000..780c316e0af
--- /dev/null
+++ b/gcc/testsuite/rust/compile/closure_move_expr.rs
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fsyntax-only" }
+
+fn foo() {
+    move |l: u32, r: u32| l + r
+}
+
+fn foo2() {
+    |l: u32, r: u32| l + r
+}
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 33/88] gccrs: Add  support for feature check.
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (31 preceding siblings ...)
  2023-04-05 14:03 ` [committed 32/88] gccrs: parser: Fix parsing of closure param list arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 34/88] gccrs: Removed comment copy-pasted from gcc/tree.def arthur.cohen
                   ` (56 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, mxlol233

From: mxlol233 <mxlol233@outlook.com>

This commit implements a very basic feature checking module.

gcc/rust/ChangeLog:

	* Make-lang.in: Add object files: `rust-feature.o` and `rust-feature-gate.o`
	* checks/errors/rust-feature-gate.cc: New file.
	* checks/errors/rust-feature-gate.h: New file.
	* checks/errors/rust-feature.cc: New file.
	* checks/errors/rust-feature.h: New file.
	* rust-session-manager.cc: Add FeatureGate check.

gcc/testsuite/ChangeLog:

	* rust/compile/feature.rs: New test.

Signed-off-by: Xiao Ma <mxlol233@outlook.com>
---
 gcc/rust/Make-lang.in                       |   2 +
 gcc/rust/checks/errors/rust-feature-gate.cc |  63 +++++++
 gcc/rust/checks/errors/rust-feature-gate.h  | 191 ++++++++++++++++++++
 gcc/rust/checks/errors/rust-feature.cc      |  66 +++++++
 gcc/rust/checks/errors/rust-feature.h       |  76 ++++++++
 gcc/rust/rust-session-manager.cc            |   4 +
 gcc/testsuite/rust/compile/feature.rs       |   4 +
 7 files changed, 406 insertions(+)
 create mode 100644 gcc/rust/checks/errors/rust-feature-gate.cc
 create mode 100644 gcc/rust/checks/errors/rust-feature-gate.h
 create mode 100644 gcc/rust/checks/errors/rust-feature.cc
 create mode 100644 gcc/rust/checks/errors/rust-feature.h
 create mode 100644 gcc/testsuite/rust/compile/feature.rs

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 87f3ba66eba..a0c5757592e 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -161,6 +161,8 @@ GRS_OBJS = \
     rust/rust-import-archive.o \
     rust/rust-extern-crate.o \
     rust/rust-builtins.o \
+    rust/rust-feature.o \
+    rust/rust-feature-gate.o \
     $(END)
 # removed object files from here
 
diff --git a/gcc/rust/checks/errors/rust-feature-gate.cc b/gcc/rust/checks/errors/rust-feature-gate.cc
new file mode 100644
index 00000000000..cd26f8a17f5
--- /dev/null
+++ b/gcc/rust/checks/errors/rust-feature-gate.cc
@@ -0,0 +1,63 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-feature-gate.h"
+#include "rust-feature.h"
+
+namespace Rust {
+
+void
+FeatureGate::check (AST::Crate &crate)
+{
+  std::vector<Feature> valid_features;
+  for (const auto &attr : crate.inner_attrs)
+    {
+      if (attr.get_path ().as_string () == "feature")
+	{
+	  const auto &attr_input = attr.get_attr_input ();
+	  auto type = attr_input.get_attr_input_type ();
+	  if (type == AST::AttrInput::AttrInputType::TOKEN_TREE)
+	    {
+	      const auto &option = static_cast<const AST::DelimTokenTree &> (
+		attr.get_attr_input ());
+	      std::unique_ptr<AST::AttrInputMetaItemContainer> meta_item (
+		option.parse_to_meta_item ());
+	      for (const auto &item : meta_item->get_items ())
+		{
+		  const auto &name = item->as_string ();
+		  auto tname = Feature::as_name (name);
+		  if (!tname.is_none ())
+		    valid_features.push_back (Feature::create (tname.get ()));
+		  else
+		    rust_error_at (item->get_locus (), "unknown feature '%s'",
+				   name.c_str ());
+		}
+	    }
+	}
+    }
+  valid_features.shrink_to_fit ();
+
+  // TODO (mxlol233): add the real feature gate stuff.
+  auto &items = crate.items;
+  for (auto it = items.begin (); it != items.end (); it++)
+    {
+      auto &item = *it;
+      item->accept_vis (*this);
+    }
+}
+} // namespace Rust
\ No newline at end of file
diff --git a/gcc/rust/checks/errors/rust-feature-gate.h b/gcc/rust/checks/errors/rust-feature-gate.h
new file mode 100644
index 00000000000..080c15ccd23
--- /dev/null
+++ b/gcc/rust/checks/errors/rust-feature-gate.h
@@ -0,0 +1,191 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_FEATURE_GATE_H
+#define RUST_FEATURE_GATE_H
+
+#include "rust-ast-visitor.h"
+#include "rust-ast-full.h"
+
+namespace Rust {
+
+struct Feature;
+
+class FeatureGate : public AST::ASTVisitor
+{
+public:
+  FeatureGate () {}
+
+  void check (AST::Crate &crate);
+
+  void visit (AST::Token &tok) override {}
+  void visit (AST::DelimTokenTree &delim_tok_tree) override {}
+  void visit (AST::AttrInputMetaItemContainer &input) override {}
+  void visit (AST::IdentifierExpr &ident_expr) override {}
+  void visit (AST::Lifetime &lifetime) override {}
+  void visit (AST::LifetimeParam &lifetime_param) override {}
+  void visit (AST::ConstGenericParam &const_param) override {}
+  void visit (AST::PathInExpression &path) override {}
+  void visit (AST::TypePathSegment &segment) override {}
+  void visit (AST::TypePathSegmentGeneric &segment) override {}
+  void visit (AST::TypePathSegmentFunction &segment) override {}
+  void visit (AST::TypePath &path) override {}
+  void visit (AST::QualifiedPathInExpression &path) override {}
+  void visit (AST::QualifiedPathInType &path) override {}
+  void visit (AST::LiteralExpr &expr) override {}
+  void visit (AST::AttrInputLiteral &attr_input) override {}
+  void visit (AST::MetaItemLitExpr &meta_item) override {}
+  void visit (AST::MetaItemPathLit &meta_item) override {}
+  void visit (AST::BorrowExpr &expr) override {}
+  void visit (AST::DereferenceExpr &expr) override {}
+  void visit (AST::ErrorPropagationExpr &expr) override {}
+  void visit (AST::NegationExpr &expr) override {}
+  void visit (AST::ArithmeticOrLogicalExpr &expr) override {}
+  void visit (AST::ComparisonExpr &expr) override {}
+  void visit (AST::LazyBooleanExpr &expr) override {}
+  void visit (AST::TypeCastExpr &expr) override {}
+  void visit (AST::AssignmentExpr &expr) override {}
+  void visit (AST::CompoundAssignmentExpr &expr) override {}
+  void visit (AST::GroupedExpr &expr) override {}
+  void visit (AST::ArrayElemsValues &elems) override {}
+  void visit (AST::ArrayElemsCopied &elems) override {}
+  void visit (AST::ArrayExpr &expr) override {}
+  void visit (AST::ArrayIndexExpr &expr) override {}
+  void visit (AST::TupleExpr &expr) override {}
+  void visit (AST::TupleIndexExpr &expr) override {}
+  void visit (AST::StructExprStruct &expr) override {}
+  void visit (AST::StructExprFieldIdentifier &field) override {}
+  void visit (AST::StructExprFieldIdentifierValue &field) override {}
+  void visit (AST::StructExprFieldIndexValue &field) override {}
+  void visit (AST::StructExprStructFields &expr) override {}
+  void visit (AST::StructExprStructBase &expr) override {}
+  void visit (AST::CallExpr &expr) override {}
+  void visit (AST::MethodCallExpr &expr) override {}
+  void visit (AST::FieldAccessExpr &expr) override {}
+  void visit (AST::ClosureExprInner &expr) override {}
+  void visit (AST::BlockExpr &expr) override {}
+  void visit (AST::ClosureExprInnerTyped &expr) override {}
+  void visit (AST::ContinueExpr &expr) override {}
+  void visit (AST::BreakExpr &expr) override {}
+  void visit (AST::RangeFromToExpr &expr) override {}
+  void visit (AST::RangeFromExpr &expr) override {}
+  void visit (AST::RangeToExpr &expr) override {}
+  void visit (AST::RangeFullExpr &expr) override {}
+  void visit (AST::RangeFromToInclExpr &expr) override {}
+  void visit (AST::RangeToInclExpr &expr) override {}
+  void visit (AST::ReturnExpr &expr) override {}
+  void visit (AST::UnsafeBlockExpr &expr) override {}
+  void visit (AST::LoopExpr &expr) override {}
+  void visit (AST::WhileLoopExpr &expr) override {}
+  void visit (AST::WhileLetLoopExpr &expr) override {}
+  void visit (AST::ForLoopExpr &expr) override {}
+  void visit (AST::IfExpr &expr) override {}
+  void visit (AST::IfExprConseqElse &expr) override {}
+  void visit (AST::IfExprConseqIf &expr) override {}
+  void visit (AST::IfExprConseqIfLet &expr) override {}
+  void visit (AST::IfLetExpr &expr) override {}
+  void visit (AST::IfLetExprConseqElse &expr) override {}
+  void visit (AST::IfLetExprConseqIf &expr) override {}
+  void visit (AST::IfLetExprConseqIfLet &expr) override {}
+  void visit (AST::MatchExpr &expr) override {}
+  void visit (AST::AwaitExpr &expr) override {}
+  void visit (AST::AsyncBlockExpr &expr) override {}
+  void visit (AST::TypeParam &param) override {}
+  void visit (AST::LifetimeWhereClauseItem &item) override {}
+  void visit (AST::TypeBoundWhereClauseItem &item) override {}
+  void visit (AST::Method &method) override {}
+  void visit (AST::Module &module) override {}
+  void visit (AST::ExternCrate &crate) override {}
+  void visit (AST::UseTreeGlob &use_tree) override {}
+  void visit (AST::UseTreeList &use_tree) override {}
+  void visit (AST::UseTreeRebind &use_tree) override {}
+  void visit (AST::UseDeclaration &use_decl) override {}
+  void visit (AST::Function &function) override {}
+  void visit (AST::TypeAlias &type_alias) override {}
+  void visit (AST::StructStruct &struct_item) override {}
+  void visit (AST::TupleStruct &tuple_struct) override {}
+  void visit (AST::EnumItem &item) override {}
+  void visit (AST::EnumItemTuple &item) override {}
+  void visit (AST::EnumItemStruct &item) override {}
+  void visit (AST::EnumItemDiscriminant &item) override {}
+  void visit (AST::Enum &enum_item) override {}
+  void visit (AST::Union &union_item) override {}
+  void visit (AST::ConstantItem &const_item) override {}
+  void visit (AST::StaticItem &static_item) override {}
+  void visit (AST::TraitItemFunc &item) override {}
+  void visit (AST::TraitItemMethod &item) override {}
+  void visit (AST::TraitItemConst &item) override {}
+  void visit (AST::TraitItemType &item) override {}
+  void visit (AST::Trait &trait) override {}
+  void visit (AST::InherentImpl &impl) override {}
+  void visit (AST::TraitImpl &impl) override {}
+  void visit (AST::ExternalStaticItem &item) override {}
+  void visit (AST::ExternalFunctionItem &item) override {}
+  void visit (AST::ExternBlock &block) override {}
+  void visit (AST::MacroMatchFragment &match) override {}
+  void visit (AST::MacroMatchRepetition &match) override {}
+  void visit (AST::MacroMatcher &matcher) override {}
+  void visit (AST::MacroRulesDefinition &rules_def) override {}
+  void visit (AST::MacroInvocation &macro_invoc) override {}
+  void visit (AST::MetaItemPath &meta_item) override {}
+  void visit (AST::MetaItemSeq &meta_item) override {}
+  void visit (AST::MetaWord &meta_item) override {}
+  void visit (AST::MetaNameValueStr &meta_item) override {}
+  void visit (AST::MetaListPaths &meta_item) override {}
+  void visit (AST::MetaListNameValueStr &meta_item) override {}
+  void visit (AST::LiteralPattern &pattern) override {}
+  void visit (AST::IdentifierPattern &pattern) override {}
+  void visit (AST::WildcardPattern &pattern) override {}
+  void visit (AST::RangePatternBoundLiteral &bound) override {}
+  void visit (AST::RangePatternBoundPath &bound) override {}
+  void visit (AST::RangePatternBoundQualPath &bound) override {}
+  void visit (AST::RangePattern &pattern) override {}
+  void visit (AST::ReferencePattern &pattern) override {}
+  void visit (AST::StructPatternFieldTuplePat &field) override {}
+  void visit (AST::StructPatternFieldIdentPat &field) override {}
+  void visit (AST::StructPatternFieldIdent &field) override {}
+  void visit (AST::StructPattern &pattern) override {}
+  void visit (AST::TupleStructItemsNoRange &tuple_items) override {}
+  void visit (AST::TupleStructItemsRange &tuple_items) override {}
+  void visit (AST::TupleStructPattern &pattern) override {}
+  void visit (AST::TuplePatternItemsMultiple &tuple_items) override {}
+  void visit (AST::TuplePatternItemsRanged &tuple_items) override {}
+  void visit (AST::TuplePattern &pattern) override {}
+  void visit (AST::GroupedPattern &pattern) override {}
+  void visit (AST::SlicePattern &pattern) override {}
+  void visit (AST::EmptyStmt &stmt) override {}
+  void visit (AST::LetStmt &stmt) override {}
+  void visit (AST::ExprStmtWithoutBlock &stmt) override {}
+  void visit (AST::ExprStmtWithBlock &stmt) override {}
+  void visit (AST::TraitBound &bound) override {}
+  void visit (AST::ImplTraitType &type) override {}
+  void visit (AST::TraitObjectType &type) override {}
+  void visit (AST::ParenthesisedType &type) override {}
+  void visit (AST::ImplTraitTypeOneBound &type) override {}
+  void visit (AST::TraitObjectTypeOneBound &type) override {}
+  void visit (AST::TupleType &type) override {}
+  void visit (AST::NeverType &type) override {}
+  void visit (AST::RawPointerType &type) override {}
+  void visit (AST::ReferenceType &type) override {}
+  void visit (AST::ArrayType &type) override {}
+  void visit (AST::SliceType &type) override {}
+  void visit (AST::InferredType &type) override {}
+  void visit (AST::BareFunctionType &type) override {}
+};
+} // namespace Rust
+#endif
\ No newline at end of file
diff --git a/gcc/rust/checks/errors/rust-feature.cc b/gcc/rust/checks/errors/rust-feature.cc
new file mode 100644
index 00000000000..b87b4ca38ef
--- /dev/null
+++ b/gcc/rust/checks/errors/rust-feature.cc
@@ -0,0 +1,66 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-feature.h"
+#include "rust-session-manager.h"
+
+namespace Rust {
+
+Feature
+Feature::create (Feature::Name name)
+{
+  switch (name)
+    {
+    case Feature::Name::ASSOCIATED_TYPE_BOUNDS:
+      return Feature (Feature::Name::ASSOCIATED_TYPE_BOUNDS,
+		      Feature::State::ACCEPTED, "associated_type_bounds",
+		      "1.34.0", 52662,
+		      Optional<CompileOptions::Edition>::none (), "");
+    case Feature::Name::INTRINSICS:
+      return Feature (Feature::Name::INTRINSICS, Feature::State::ACCEPTED,
+		      "intrinsics", "1.0.0", 0,
+		      Optional<CompileOptions::Edition>::none (), "");
+    case Feature::Name::RUSTC_ATTRS:
+      return Feature (Feature::Name::RUSTC_ATTRS, Feature::State::ACCEPTED,
+		      "rustc_attrs", "1.0.0", 0,
+		      Optional<CompileOptions::Edition>::none (), "");
+    case Feature::Name::DECL_MACRO:
+      return Feature (Feature::Name::DECL_MACRO, Feature::State::ACCEPTED,
+		      "decl_macro", "1.0.0", 0,
+		      Optional<CompileOptions::Edition>::none (), "");
+    default:
+      gcc_unreachable ();
+    }
+}
+
+const std::map<std::string, Feature::Name> Feature::name_hash_map = {
+  {"associated_type_bounds", Feature::Name::ASSOCIATED_TYPE_BOUNDS},
+  {"intrinsics", Feature::Name::INTRINSICS},
+  {"rustc_attrs", Feature::Name::RUSTC_ATTRS},
+  {"decl_macro", Feature::Name::DECL_MACRO},
+};
+
+Optional<Feature::Name>
+Feature::as_name (const std::string &name)
+{
+  if (Feature::name_hash_map.count (name))
+    return Optional<Feature::Name>::some (Feature::name_hash_map.at (name));
+  return Optional<Feature::Name>::none ();
+}
+
+} // namespace Rust
\ No newline at end of file
diff --git a/gcc/rust/checks/errors/rust-feature.h b/gcc/rust/checks/errors/rust-feature.h
new file mode 100644
index 00000000000..bf93b090af5
--- /dev/null
+++ b/gcc/rust/checks/errors/rust-feature.h
@@ -0,0 +1,76 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_FEATURE_H
+#define RUST_FEATURE_H
+
+#include "rust-session-manager.h"
+#include "rust-optional.h"
+
+namespace Rust {
+
+class Feature
+{
+public:
+  enum class State
+  {
+    ACCEPTED,
+    ACTIVE,
+    REMOVED,
+    STABILIZED,
+  };
+
+  enum class Name
+  {
+    ASSOCIATED_TYPE_BOUNDS,
+    INTRINSICS,
+    RUSTC_ATTRS,
+    DECL_MACRO,
+  };
+
+  const std::string &as_string () { return m_name_str; }
+  Name name () { return m_name; }
+  const std::string &description () { return m_description; }
+  State state () { return m_state; }
+
+  static Optional<Name> as_name (const std::string &name);
+  static Feature create (Name name);
+
+private:
+  Feature (Name name, State state, const char *name_str,
+	   const char *rustc_since, uint64_t issue_number,
+	   const Optional<CompileOptions::Edition> &edition,
+	   const char *description)
+    : m_state (state), m_name (name), m_name_str (name_str),
+      m_rustc_since (rustc_since), issue (issue_number), edition (edition),
+      m_description (description)
+  {}
+
+  State m_state;
+  Name m_name;
+  std::string m_name_str;
+  std::string m_rustc_since;
+  uint64_t issue;
+  Optional<CompileOptions::Edition> edition;
+  std::string m_description;
+
+  static const std::map<std::string, Name> name_hash_map;
+};
+
+} // namespace Rust
+#endif
\ No newline at end of file
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index 70b058ff992..28ac2ba4a53 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -27,6 +27,7 @@
 #include "rust-hir-type-check.h"
 #include "rust-privacy-check.h"
 #include "rust-const-checker.h"
+#include "rust-feature-gate.h"
 #include "rust-tycheck-dump.h"
 #include "rust-compile.h"
 #include "rust-cfg-parser.h"
@@ -558,6 +559,9 @@ Session::compile_crate (const char *filename)
       rust_debug ("END POST-EXPANSION AST DUMP");
     }
 
+  // feature gating
+  FeatureGate ().check (parsed_crate);
+
   if (last_step == CompileOptions::CompileStep::NameResolution)
     return;
 
diff --git a/gcc/testsuite/rust/compile/feature.rs b/gcc/testsuite/rust/compile/feature.rs
new file mode 100644
index 00000000000..305d112b7c4
--- /dev/null
+++ b/gcc/testsuite/rust/compile/feature.rs
@@ -0,0 +1,4 @@
+#![feature(AA)] //{ dg-error "unknown feature 'AA'" }
+                   
+
+fn main(){}
\ No newline at end of file
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 34/88] gccrs: Removed comment copy-pasted from gcc/tree.def
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (32 preceding siblings ...)
  2023-04-05 14:03 ` [committed 33/88] gccrs: Add support for feature check arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 35/88] gccrs: Add another test case for passing associated type-bounds arthur.cohen
                   ` (55 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Owen Avery

From: Owen Avery <powerboat9.gamer@gmail.com>

gcc/rust/ChangeLog:

	* backend/rust-compile-expr.cc (CompileExpr::visit): Removed copy-pasted comment.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
---
 gcc/rust/backend/rust-compile-expr.cc | 24 ------------------------
 1 file changed, 24 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 436fc924a13..c26f6f440ec 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -1341,30 +1341,6 @@ CompileExpr::visit (HIR::MatchExpr &expr)
   // SWITCH_ALL_CASES_P is true if the switch includes a default label or the
   // case label ranges cover all possible values of the condition expression
 
-  /* Switch expression.
-
-     TREE_TYPE is the original type of the condition, before any
-     language required type conversions.  It may be NULL, in which case
-     the original type and final types are assumed to be the same.
-
-     Operand 0 is the expression used to perform the branch,
-     Operand 1 is the body of the switch, which probably contains
-       CASE_LABEL_EXPRs.  It may also be NULL, in which case operand 2
-       must not be NULL.  */
-  // DEFTREECODE (SWITCH_EXPR, "switch_expr", tcc_statement, 2)
-
-  /* Used to represent a case label.
-
-     Operand 0 is CASE_LOW.  It may be NULL_TREE, in which case the label
-       is a 'default' label.
-     Operand 1 is CASE_HIGH.  If it is NULL_TREE, the label is a simple
-       (one-value) case label.  If it is non-NULL_TREE, the case is a range.
-     Operand 2 is CASE_LABEL, which has the corresponding LABEL_DECL.
-     Operand 3 is CASE_CHAIN.  This operand is only used in tree-cfg.cc to
-       speed up the lookup of case labels which use a particular edge in
-       the control flow graph.  */
-  // DEFTREECODE (CASE_LABEL_EXPR, "case_label_expr", tcc_statement, 4)
-
   TyTy::TypeKind scrutinee_kind = check_match_scrutinee (expr, ctx);
   if (scrutinee_kind == TyTy::TypeKind::ERROR)
     {
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 35/88] gccrs: Add another test case for passing associated type-bounds
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (33 preceding siblings ...)
  2023-04-05 14:03 ` [committed 34/88] gccrs: Removed comment copy-pasted from gcc/tree.def arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 36/88] gccrs: Move TypePredicateItem impl out of the header arthur.cohen
                   ` (54 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

This demonstrates that this also works for custom algebraic data types too.

gcc/testsuite/ChangeLog:

	* rust/execute/torture/issue-1720-2.rs: New test.

Signed-off-by: Philip Herron <herron.philip@googlemail.com>
---
 .../rust/execute/torture/issue-1720-2.rs      | 30 +++++++++++++++++++
 1 file changed, 30 insertions(+)
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-1720-2.rs

diff --git a/gcc/testsuite/rust/execute/torture/issue-1720-2.rs b/gcc/testsuite/rust/execute/torture/issue-1720-2.rs
new file mode 100644
index 00000000000..35833dbb813
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1720-2.rs
@@ -0,0 +1,30 @@
+mod core {
+    mod ops {
+        #[lang = "add"]
+        pub trait Add<Rhs = Self> {
+            type Output;
+
+            fn add(self, rhs: Rhs) -> Self::Output;
+        }
+    }
+}
+
+struct Foo(i32);
+
+impl core::ops::Add for Foo {
+    type Output = i32;
+
+    fn add(self, rhs: Foo) -> Self::Output {
+        self.0 + rhs.0
+    }
+}
+
+pub fn bar<T: core::ops::Add<Output = i32>>(a: T) -> i32 {
+    a + a
+}
+
+pub fn main() -> i32 {
+    let a = Foo(1);
+
+    bar(a) - 2
+}
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 36/88] gccrs: Move TypePredicateItem impl out of the header
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (34 preceding siblings ...)
  2023-04-05 14:03 ` [committed 35/88] gccrs: Add another test case for passing associated type-bounds arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 37/88] gccrs: Refactor TyVar and TypeBoundPredicates arthur.cohen
                   ` (53 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

This moves the implementation code out of the header and into its
respective cc file.

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* typecheck/rust-tyty-bounds.cc (TypeBoundPredicateItem::error): refactor
	(TypeBoundPredicateItem::is_error): likewise
	(TypeBoundPredicateItem::get_parent): likewise
	* typecheck/rust-tyty.h: Move the implementation for the above
---
 gcc/rust/typecheck/rust-tyty-bounds.cc | 24 ++++++++++++++++++++++++
 gcc/rust/typecheck/rust-tyty.h         | 16 ++++------------
 2 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc
index 30f7b0d02e3..e7eb9a760f5 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -364,6 +364,30 @@ TypeBoundPredicate::lookup_associated_item (const std::string &search) const
   return TypeBoundPredicateItem (this, trait_item_ref);
 }
 
+TypeBoundPredicateItem::TypeBoundPredicateItem (
+  const TypeBoundPredicate *parent,
+  const Resolver::TraitItemReference *trait_item_ref)
+  : parent (parent), trait_item_ref (trait_item_ref)
+{}
+
+TypeBoundPredicateItem
+TypeBoundPredicateItem::error ()
+{
+  return TypeBoundPredicateItem (nullptr, nullptr);
+}
+
+bool
+TypeBoundPredicateItem::is_error () const
+{
+  return parent == nullptr || trait_item_ref == nullptr;
+}
+
+const TypeBoundPredicate *
+TypeBoundPredicateItem::get_parent () const
+{
+  return parent;
+}
+
 TypeBoundPredicateItem
 TypeBoundPredicate::lookup_associated_item (
   const Resolver::TraitItemReference *ref) const
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 20a243fe980..7d32ed59494 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -82,19 +82,11 @@ class TypeBoundPredicateItem
 {
 public:
   TypeBoundPredicateItem (const TypeBoundPredicate *parent,
-			  const Resolver::TraitItemReference *trait_item_ref)
-    : parent (parent), trait_item_ref (trait_item_ref)
-  {}
+			  const Resolver::TraitItemReference *trait_item_ref);
 
-  static TypeBoundPredicateItem error ()
-  {
-    return TypeBoundPredicateItem (nullptr, nullptr);
-  }
+  static TypeBoundPredicateItem error ();
 
-  bool is_error () const
-  {
-    return parent == nullptr || trait_item_ref == nullptr;
-  }
+  bool is_error () const;
 
   BaseType *get_tyty_for_receiver (const TyTy::BaseType *receiver);
 
@@ -102,7 +94,7 @@ public:
 
   bool needs_implementation () const;
 
-  const TypeBoundPredicate *get_parent () const { return parent; }
+  const TypeBoundPredicate *get_parent () const;
 
   Location get_locus () const;
 
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 37/88] gccrs: Refactor TyVar and TypeBoundPredicates
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (35 preceding siblings ...)
  2023-04-05 14:03 ` [committed 36/88] gccrs: Move TypePredicateItem impl out of the header arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 38/88] gccrs: Refactor SubstitutionRef base class into its own CC file arthur.cohen
                   ` (52 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

This extract these helpers into seperate files

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* Make-lang.in: update makefile
	* typecheck/rust-tyty.cc (TyVar::TyVar): move to new file
	(TyVar::get_tyty): likewise
	(TyVar::get_implicit_infer_var): likewise
	(TyVar::subst_covariant_var): likewise
	(TyVar::clone): likewise
	(TyVar::monomorphized_clone): likewise
	(TyWithLocation::TyWithLocation): likewise
	* typecheck/rust-tyty.h (class BaseType): cleanup
	(class TypeBoundPredicate): move to its own file
	(class TypeBoundPredicateItem): likewise
	(class TypeBoundsMappings): likewise
	(class TyVar): likewise
	(class TyWithLocation): likewise
	* typecheck/rust-tyty-bounds.h: New file.
	* typecheck/rust-tyty-util.cc: New file.
	* typecheck/rust-tyty-util.h: New file.
---
 gcc/rust/Make-lang.in                 |   1 +
 gcc/rust/typecheck/rust-tyty-bounds.h |  88 +++++++++++++++++++
 gcc/rust/typecheck/rust-tyty-util.cc  | 116 ++++++++++++++++++++++++++
 gcc/rust/typecheck/rust-tyty-util.h   |  69 +++++++++++++++
 gcc/rust/typecheck/rust-tyty.cc       |  90 --------------------
 gcc/rust/typecheck/rust-tyty.h        |  90 +-------------------
 6 files changed, 276 insertions(+), 178 deletions(-)
 create mode 100644 gcc/rust/typecheck/rust-tyty-bounds.h
 create mode 100644 gcc/rust/typecheck/rust-tyty-util.cc
 create mode 100644 gcc/rust/typecheck/rust-tyty-util.h

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index a0c5757592e..2aa61bcfb19 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -115,6 +115,7 @@ GRS_OBJS = \
     rust/rust-pub-restricted-visitor.o \
     rust/rust-privacy-reporter.o \
     rust/rust-tyty.o \
+    rust/rust-tyty-util.o \
     rust/rust-tyty-call.o \
     rust/rust-tyctx.o \
     rust/rust-tyty-bounds.o \
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.h b/gcc/rust/typecheck/rust-tyty-bounds.h
new file mode 100644
index 00000000000..44839bd0b40
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-bounds.h
@@ -0,0 +1,88 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_TYTY_BOUNDS_H
+#define RUST_TYTY_BOUNDS_H
+
+#include "rust-location.h"
+
+namespace Rust {
+
+namespace Resolver {
+class TraitReference;
+class TraitItemReference;
+class AssociatedImplTrait;
+} // namespace Resolver
+
+namespace TyTy {
+
+class BaseType;
+class TypeBoundPredicate;
+class TypeBoundPredicateItem
+{
+public:
+  TypeBoundPredicateItem (const TypeBoundPredicate *parent,
+			  const Resolver::TraitItemReference *trait_item_ref);
+
+  static TypeBoundPredicateItem error ();
+
+  bool is_error () const;
+
+  BaseType *get_tyty_for_receiver (const TyTy::BaseType *receiver);
+
+  const Resolver::TraitItemReference *get_raw_item () const;
+
+  bool needs_implementation () const;
+
+  const TypeBoundPredicate *get_parent () const;
+
+  Location get_locus () const;
+
+private:
+  const TypeBoundPredicate *parent;
+  const Resolver::TraitItemReference *trait_item_ref;
+};
+
+class TypeBoundsMappings
+{
+protected:
+  TypeBoundsMappings (std::vector<TypeBoundPredicate> specified_bounds);
+
+public:
+  std::vector<TypeBoundPredicate> &get_specified_bounds ();
+
+  const std::vector<TypeBoundPredicate> &get_specified_bounds () const;
+
+  size_t num_specified_bounds () const;
+
+  std::string raw_bounds_as_string () const;
+
+  std::string bounds_as_string () const;
+
+  std::string raw_bounds_as_name () const;
+
+protected:
+  void add_bound (TypeBoundPredicate predicate);
+
+  std::vector<TypeBoundPredicate> specified_bounds;
+};
+
+} // namespace TyTy
+} // namespace Rust
+
+#endif // RUST_TYTY_BOUNDS_H
diff --git a/gcc/rust/typecheck/rust-tyty-util.cc b/gcc/rust/typecheck/rust-tyty-util.cc
new file mode 100644
index 00000000000..5037f68cb3f
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-util.cc
@@ -0,0 +1,116 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-hir-type-check.h"
+#include "rust-tyty.h"
+
+namespace Rust {
+namespace TyTy {
+
+TyVar::TyVar (HirId ref) : ref (ref)
+{
+  // ensure this reference is defined within the context
+  auto context = Resolver::TypeCheckContext::get ();
+  BaseType *lookup = nullptr;
+  bool ok = context->lookup_type (ref, &lookup);
+  rust_assert (ok);
+}
+
+BaseType *
+TyVar::get_tyty () const
+{
+  auto context = Resolver::TypeCheckContext::get ();
+  BaseType *lookup = nullptr;
+  bool ok = context->lookup_type (ref, &lookup);
+  rust_assert (ok);
+  return lookup;
+}
+
+TyVar
+TyVar::get_implicit_infer_var (Location locus)
+{
+  auto mappings = Analysis::Mappings::get ();
+  auto context = Resolver::TypeCheckContext::get ();
+
+  InferType *infer = new InferType (mappings->get_next_hir_id (),
+				    InferType::InferTypeKind::GENERAL, locus);
+  context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
+					       UNKNOWN_NODEID,
+					       infer->get_ref (),
+					       UNKNOWN_LOCAL_DEFID),
+			infer);
+  mappings->insert_location (infer->get_ref (), locus);
+
+  return TyVar (infer->get_ref ());
+}
+
+TyVar
+TyVar::subst_covariant_var (TyTy::BaseType *orig, TyTy::BaseType *subst)
+{
+  if (orig->get_kind () != TyTy::TypeKind::PARAM)
+    return TyVar (subst->get_ty_ref ());
+  else if (subst->get_kind () == TyTy::TypeKind::PARAM)
+    {
+      TyTy::ParamType *p = static_cast<TyTy::ParamType *> (subst);
+      if (p->resolve ()->get_kind () == TyTy::TypeKind::PARAM)
+	{
+	  return TyVar (subst->get_ty_ref ());
+	}
+    }
+
+  return TyVar (subst->get_ref ());
+}
+
+TyVar
+TyVar::clone () const
+{
+  TyTy::BaseType *c = get_tyty ()->clone ();
+  return TyVar (c->get_ref ());
+}
+
+TyVar
+TyVar::monomorphized_clone () const
+{
+  auto mappings = Analysis::Mappings::get ();
+  auto context = Resolver::TypeCheckContext::get ();
+
+  // this needs a new hirid
+  TyTy::BaseType *c = get_tyty ()->monomorphized_clone ();
+  c->set_ref (mappings->get_next_hir_id ());
+
+  // insert it
+  context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
+					       UNKNOWN_NODEID, c->get_ref (),
+					       UNKNOWN_LOCAL_DEFID),
+			c);
+
+  return TyVar (c->get_ref ());
+}
+
+TyWithLocation::TyWithLocation (BaseType *ty, Location locus)
+  : ty (ty), locus (locus)
+{}
+
+TyWithLocation::TyWithLocation (BaseType *ty) : ty (ty)
+{
+  auto mappings = Analysis::Mappings::get ();
+  locus = mappings->lookup_location (ty->get_ref ());
+}
+
+} // namespace TyTy
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty-util.h b/gcc/rust/typecheck/rust-tyty-util.h
new file mode 100644
index 00000000000..eccbb4423d5
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-util.h
@@ -0,0 +1,69 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_TYTY_UTIL_H
+#define RUST_TYTY_UTIL_H
+
+#include "rust-hir-map.h"
+
+namespace Rust {
+namespace TyTy {
+
+class BaseType;
+
+// this is a placeholder for types that can change like inference variables
+class TyVar
+{
+public:
+  explicit TyVar (HirId ref);
+
+  HirId get_ref () const { return ref; }
+
+  BaseType *get_tyty () const;
+
+  TyVar clone () const;
+
+  TyVar monomorphized_clone () const;
+
+  static TyVar get_implicit_infer_var (Location locus);
+
+  static TyVar subst_covariant_var (TyTy::BaseType *orig,
+				    TyTy::BaseType *subst);
+
+private:
+  HirId ref;
+};
+
+class TyWithLocation
+{
+public:
+  explicit TyWithLocation (BaseType *ty, Location locus);
+  explicit TyWithLocation (BaseType *ty);
+
+  BaseType *get_ty () const { return ty; }
+  Location get_locus () const { return locus; }
+
+private:
+  BaseType *ty;
+  Location locus;
+};
+
+} // namespace TyTy
+} // namespace Rust
+
+#endif // RUST_TYTY_UTIL_H
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index fd57a534562..55a8123ce87 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -330,96 +330,6 @@ BaseType::debug () const
 	      debug_str ().c_str ());
 }
 
-TyVar::TyVar (HirId ref) : ref (ref)
-{
-  // ensure this reference is defined within the context
-  auto context = Resolver::TypeCheckContext::get ();
-  BaseType *lookup = nullptr;
-  bool ok = context->lookup_type (ref, &lookup);
-  rust_assert (ok);
-}
-
-BaseType *
-TyVar::get_tyty () const
-{
-  auto context = Resolver::TypeCheckContext::get ();
-  BaseType *lookup = nullptr;
-  bool ok = context->lookup_type (ref, &lookup);
-  rust_assert (ok);
-  return lookup;
-}
-
-TyVar
-TyVar::get_implicit_infer_var (Location locus)
-{
-  auto mappings = Analysis::Mappings::get ();
-  auto context = Resolver::TypeCheckContext::get ();
-
-  InferType *infer = new InferType (mappings->get_next_hir_id (),
-				    InferType::InferTypeKind::GENERAL, locus);
-  context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
-					       UNKNOWN_NODEID,
-					       infer->get_ref (),
-					       UNKNOWN_LOCAL_DEFID),
-			infer);
-  mappings->insert_location (infer->get_ref (), locus);
-
-  return TyVar (infer->get_ref ());
-}
-
-TyVar
-TyVar::subst_covariant_var (TyTy::BaseType *orig, TyTy::BaseType *subst)
-{
-  if (orig->get_kind () != TyTy::TypeKind::PARAM)
-    return TyVar (subst->get_ty_ref ());
-  else if (subst->get_kind () == TyTy::TypeKind::PARAM)
-    {
-      TyTy::ParamType *p = static_cast<TyTy::ParamType *> (subst);
-      if (p->resolve ()->get_kind () == TyTy::TypeKind::PARAM)
-	{
-	  return TyVar (subst->get_ty_ref ());
-	}
-    }
-
-  return TyVar (subst->get_ref ());
-}
-
-TyVar
-TyVar::clone () const
-{
-  TyTy::BaseType *c = get_tyty ()->clone ();
-  return TyVar (c->get_ref ());
-}
-
-TyVar
-TyVar::monomorphized_clone () const
-{
-  auto mappings = Analysis::Mappings::get ();
-  auto context = Resolver::TypeCheckContext::get ();
-
-  // this needs a new hirid
-  TyTy::BaseType *c = get_tyty ()->monomorphized_clone ();
-  c->set_ref (mappings->get_next_hir_id ());
-
-  // insert it
-  context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
-					       UNKNOWN_NODEID, c->get_ref (),
-					       UNKNOWN_LOCAL_DEFID),
-			c);
-
-  return TyVar (c->get_ref ());
-}
-
-TyWithLocation::TyWithLocation (BaseType *ty, Location locus)
-  : ty (ty), locus (locus)
-{}
-
-TyWithLocation::TyWithLocation (BaseType *ty) : ty (ty)
-{
-  auto mappings = Analysis::Mappings::get ();
-  locus = mappings->lookup_location (ty->get_ref ());
-}
-
 void
 InferType::accept_vis (TyVisitor &vis)
 {
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 7d32ed59494..a8bdf6f3a15 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -25,6 +25,8 @@
 #include "rust-abi.h"
 #include "rust-common.h"
 #include "rust-identifier.h"
+#include "rust-tyty-bounds.h"
+#include "rust-tyty-util.h"
 
 namespace Rust {
 
@@ -76,57 +78,6 @@ public:
   static std::string to_string (TypeKind kind);
 };
 
-class BaseType;
-class TypeBoundPredicate;
-class TypeBoundPredicateItem
-{
-public:
-  TypeBoundPredicateItem (const TypeBoundPredicate *parent,
-			  const Resolver::TraitItemReference *trait_item_ref);
-
-  static TypeBoundPredicateItem error ();
-
-  bool is_error () const;
-
-  BaseType *get_tyty_for_receiver (const TyTy::BaseType *receiver);
-
-  const Resolver::TraitItemReference *get_raw_item () const;
-
-  bool needs_implementation () const;
-
-  const TypeBoundPredicate *get_parent () const;
-
-  Location get_locus () const;
-
-private:
-  const TypeBoundPredicate *parent;
-  const Resolver::TraitItemReference *trait_item_ref;
-};
-
-class TypeBoundsMappings
-{
-protected:
-  TypeBoundsMappings (std::vector<TypeBoundPredicate> specified_bounds);
-
-public:
-  std::vector<TypeBoundPredicate> &get_specified_bounds ();
-
-  const std::vector<TypeBoundPredicate> &get_specified_bounds () const;
-
-  size_t num_specified_bounds () const;
-
-  std::string raw_bounds_as_string () const;
-
-  std::string bounds_as_string () const;
-
-  std::string raw_bounds_as_name () const;
-
-protected:
-  void add_bound (TypeBoundPredicate predicate);
-
-  std::vector<TypeBoundPredicate> specified_bounds;
-};
-
 extern void
 set_cmp_autoderef_mode ();
 extern void
@@ -268,43 +219,6 @@ protected:
   Analysis::Mappings *mappings;
 };
 
-// this is a placeholder for types that can change like inference variables
-class TyVar
-{
-public:
-  explicit TyVar (HirId ref);
-
-  HirId get_ref () const { return ref; }
-
-  BaseType *get_tyty () const;
-
-  TyVar clone () const;
-
-  TyVar monomorphized_clone () const;
-
-  static TyVar get_implicit_infer_var (Location locus);
-
-  static TyVar subst_covariant_var (TyTy::BaseType *orig,
-				    TyTy::BaseType *subst);
-
-private:
-  HirId ref;
-};
-
-class TyWithLocation
-{
-public:
-  explicit TyWithLocation (BaseType *ty, Location locus);
-  explicit TyWithLocation (BaseType *ty);
-
-  BaseType *get_ty () const { return ty; }
-  Location get_locus () const { return locus; }
-
-private:
-  BaseType *ty;
-  Location locus;
-};
-
 class InferType : public BaseType
 {
 public:
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 38/88] gccrs: Refactor SubstitutionRef base class into its own CC file
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (36 preceding siblings ...)
  2023-04-05 14:03 ` [committed 37/88] gccrs: Refactor TyVar and TypeBoundPredicates arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 39/88] gccrs: Refactor all substitution mapper code implementation " arthur.cohen
                   ` (51 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* Make-lang.in: update the makefile
	* typecheck/rust-tyty.cc (SubstitutionParamMapping::need_substitution): likewise
	(SubstitutionParamMapping::override_context): likewise
	(SubstitutionRef::get_mappings_from_generic_args): likewise
	(SubstitutionRef::infer_substitions): likewise
	(SubstitutionRef::are_mappings_bound): likewise
	(SubstitutionRef::solve_missing_mappings_from_this): likewise
	(SubstitutionRef::monomorphize): likewise
	* typecheck/rust-tyty.h (class SubstitutionParamMapping): likewise
	(class SubstitutionArg): likewise
	(std::function<void): likewise
	(class SubstitutionArgumentMappings): likewise
	(class SubstitutionRef): likewise
	* typecheck/rust-tyty-subst.cc: New file.
	* typecheck/rust-tyty-subst.h: New file.
---
 gcc/rust/Make-lang.in                 |   1 +
 gcc/rust/typecheck/rust-tyty-subst.cc | 927 ++++++++++++++++++++++++++
 gcc/rust/typecheck/rust-tyty-subst.h  | 316 +++++++++
 gcc/rust/typecheck/rust-tyty.cc       | 466 -------------
 gcc/rust/typecheck/rust-tyty.h        | 464 +------------
 5 files changed, 1245 insertions(+), 929 deletions(-)
 create mode 100644 gcc/rust/typecheck/rust-tyty-subst.cc
 create mode 100644 gcc/rust/typecheck/rust-tyty-subst.h

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 2aa61bcfb19..5e173f1d2dc 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -117,6 +117,7 @@ GRS_OBJS = \
     rust/rust-tyty.o \
     rust/rust-tyty-util.o \
     rust/rust-tyty-call.o \
+    rust/rust-tyty-subst.o \
     rust/rust-tyctx.o \
     rust/rust-tyty-bounds.o \
     rust/rust-hir-type-check-util.o \
diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc
new file mode 100644
index 00000000000..64001459b4d
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -0,0 +1,927 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-tyty-subst.h"
+#include "rust-hir-full.h"
+#include "rust-tyty.h"
+#include "rust-hir-type-check.h"
+#include "rust-substitution-mapper.h"
+#include "rust-hir-type-check-type.h"
+
+namespace Rust {
+namespace TyTy {
+
+SubstitutionParamMapping::SubstitutionParamMapping (
+  const HIR::TypeParam &generic, ParamType *param)
+  : generic (generic), param (param)
+{}
+
+SubstitutionParamMapping::SubstitutionParamMapping (
+  const SubstitutionParamMapping &other)
+  : generic (other.generic), param (other.param)
+{}
+
+std::string
+SubstitutionParamMapping::as_string () const
+{
+  if (param == nullptr)
+    return "nullptr";
+
+  return param->get_name ();
+}
+
+SubstitutionParamMapping
+SubstitutionParamMapping::clone () const
+{
+  return SubstitutionParamMapping (generic,
+				   static_cast<ParamType *> (param->clone ()));
+}
+
+ParamType *
+SubstitutionParamMapping::get_param_ty ()
+{
+  return param;
+}
+
+const ParamType *
+SubstitutionParamMapping::get_param_ty () const
+{
+  return param;
+}
+
+const HIR::TypeParam &
+SubstitutionParamMapping::get_generic_param ()
+{
+  return generic;
+};
+
+bool
+SubstitutionParamMapping::needs_substitution () const
+{
+  return !(get_param_ty ()->is_concrete ());
+}
+
+Location
+SubstitutionParamMapping::get_param_locus () const
+{
+  return generic.get_locus ();
+}
+
+bool
+SubstitutionParamMapping::param_has_default_ty () const
+{
+  return generic.has_type ();
+}
+
+BaseType *
+SubstitutionParamMapping::get_default_ty () const
+{
+  TyVar var (generic.get_type_mappings ().get_hirid ());
+  return var.get_tyty ();
+}
+
+bool
+SubstitutionParamMapping::need_substitution () const
+{
+  if (!param->can_resolve ())
+    return true;
+
+  auto resolved = param->resolve ();
+  return !resolved->is_concrete ();
+}
+
+bool
+SubstitutionParamMapping::fill_param_ty (
+  SubstitutionArgumentMappings &subst_mappings, Location locus)
+{
+  SubstitutionArg arg = SubstitutionArg::error ();
+  bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg);
+  if (!ok)
+    return true;
+
+  TyTy::BaseType &type = *arg.get_tyty ();
+  if (type.get_kind () == TyTy::TypeKind::INFER)
+    {
+      type.inherit_bounds (*param);
+    }
+  else
+    {
+      if (!param->bounds_compatible (type, locus, true))
+	return false;
+    }
+
+  if (type.get_kind () == TypeKind::PARAM)
+    {
+      // delete param;
+      param = static_cast<ParamType *> (type.clone ());
+    }
+  else
+    {
+      // check the substitution is compatible with bounds
+      if (!param->bounds_compatible (type, locus, true))
+	return false;
+
+      // recursively pass this down to all HRTB's
+      for (auto &bound : param->get_specified_bounds ())
+	bound.handle_substitions (subst_mappings);
+
+      param->set_ty_ref (type.get_ref ());
+    }
+
+  return true;
+}
+
+void
+SubstitutionParamMapping::override_context ()
+{
+  if (!param->can_resolve ())
+    return;
+
+  auto mappings = Analysis::Mappings::get ();
+  auto context = Resolver::TypeCheckContext::get ();
+
+  context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
+					       UNKNOWN_NODEID,
+					       param->get_ref (),
+					       UNKNOWN_LOCAL_DEFID),
+			param->resolve ());
+}
+
+SubstitutionArg::SubstitutionArg (const SubstitutionParamMapping *param,
+				  BaseType *argument)
+  : param (param), argument (argument)
+{}
+
+SubstitutionArg::SubstitutionArg (const SubstitutionArg &other)
+  : param (other.param), argument (other.argument)
+{}
+
+SubstitutionArg &
+SubstitutionArg::operator= (const SubstitutionArg &other)
+{
+  param = other.param;
+  argument = other.argument;
+  return *this;
+}
+
+BaseType *
+SubstitutionArg::get_tyty ()
+{
+  return argument;
+}
+
+const BaseType *
+SubstitutionArg::get_tyty () const
+{
+  return argument;
+}
+
+const SubstitutionParamMapping *
+SubstitutionArg::get_param_mapping () const
+{
+  return param;
+}
+
+SubstitutionArg
+SubstitutionArg::error ()
+{
+  return SubstitutionArg (nullptr, nullptr);
+}
+
+bool
+SubstitutionArg::is_error () const
+{
+  return param == nullptr || argument == nullptr;
+}
+
+bool
+SubstitutionArg::is_conrete () const
+{
+  if (argument != nullptr)
+    return true;
+
+  if (argument->get_kind () == TyTy::TypeKind::PARAM)
+    return false;
+
+  return argument->is_concrete ();
+}
+
+std::string
+SubstitutionArg::as_string () const
+{
+  return param->as_string ()
+	 + (argument != nullptr ? ":" + argument->as_string () : "");
+}
+
+// SubstitutionArgumentMappings
+
+SubstitutionArgumentMappings::SubstitutionArgumentMappings (
+  std::vector<SubstitutionArg> mappings,
+  std::map<std::string, BaseType *> binding_args, Location locus,
+  ParamSubstCb param_subst_cb, bool trait_item_flag)
+  : mappings (mappings), binding_args (binding_args), locus (locus),
+    param_subst_cb (param_subst_cb), trait_item_flag (trait_item_flag)
+{}
+
+SubstitutionArgumentMappings::SubstitutionArgumentMappings (
+  const SubstitutionArgumentMappings &other)
+  : mappings (other.mappings), binding_args (other.binding_args),
+    locus (other.locus), param_subst_cb (other.param_subst_cb),
+    trait_item_flag (other.trait_item_flag)
+{}
+
+SubstitutionArgumentMappings &
+SubstitutionArgumentMappings::operator= (
+  const SubstitutionArgumentMappings &other)
+{
+  mappings = other.mappings;
+  binding_args = other.binding_args;
+  locus = other.locus;
+  param_subst_cb = other.param_subst_cb;
+  trait_item_flag = other.trait_item_flag;
+
+  return *this;
+}
+
+SubstitutionArgumentMappings
+SubstitutionArgumentMappings::error ()
+{
+  return SubstitutionArgumentMappings ({}, {}, Location (), nullptr, false);
+}
+
+bool
+SubstitutionArgumentMappings::is_error () const
+{
+  return mappings.size () == 0;
+}
+
+bool
+SubstitutionArgumentMappings::get_argument_for_symbol (
+  const ParamType *param_to_find, SubstitutionArg *argument)
+{
+  for (auto &mapping : mappings)
+    {
+      const SubstitutionParamMapping *param = mapping.get_param_mapping ();
+      const ParamType *p = param->get_param_ty ();
+
+      if (p->get_symbol ().compare (param_to_find->get_symbol ()) == 0)
+	{
+	  *argument = mapping;
+	  return true;
+	}
+    }
+  return false;
+}
+
+bool
+SubstitutionArgumentMappings::get_argument_at (size_t index,
+					       SubstitutionArg *argument)
+{
+  if (index > mappings.size ())
+    return false;
+
+  *argument = mappings.at (index);
+  return true;
+}
+
+bool
+SubstitutionArgumentMappings::is_concrete () const
+{
+  for (auto &mapping : mappings)
+    {
+      if (!mapping.is_conrete ())
+	return false;
+    }
+  return true;
+}
+
+Location
+SubstitutionArgumentMappings::get_locus () const
+{
+  return locus;
+}
+
+size_t
+SubstitutionArgumentMappings::size () const
+{
+  return mappings.size ();
+}
+
+bool
+SubstitutionArgumentMappings::is_empty () const
+{
+  return size () == 0;
+}
+
+std::vector<SubstitutionArg> &
+SubstitutionArgumentMappings::get_mappings ()
+{
+  return mappings;
+}
+
+const std::vector<SubstitutionArg> &
+SubstitutionArgumentMappings::get_mappings () const
+{
+  return mappings;
+}
+
+std::map<std::string, BaseType *> &
+SubstitutionArgumentMappings::get_binding_args ()
+{
+  return binding_args;
+}
+
+const std::map<std::string, BaseType *> &
+SubstitutionArgumentMappings::get_binding_args () const
+{
+  return binding_args;
+}
+
+std::string
+SubstitutionArgumentMappings::as_string () const
+{
+  std::string buffer;
+  for (auto &mapping : mappings)
+    {
+      buffer += mapping.as_string () + ", ";
+    }
+  return "<" + buffer + ">";
+}
+
+void
+SubstitutionArgumentMappings::on_param_subst (const ParamType &p,
+					      const SubstitutionArg &a) const
+{
+  if (param_subst_cb == nullptr)
+    return;
+
+  param_subst_cb (p, a);
+}
+
+ParamSubstCb
+SubstitutionArgumentMappings::get_subst_cb () const
+{
+  return param_subst_cb;
+}
+
+bool
+SubstitutionArgumentMappings::trait_item_mode () const
+{
+  return trait_item_flag;
+}
+
+// SubstitutionRef
+
+SubstitutionRef::SubstitutionRef (
+  std::vector<SubstitutionParamMapping> substitutions,
+  SubstitutionArgumentMappings arguments)
+  : substitutions (substitutions), used_arguments (arguments)
+{}
+
+bool
+SubstitutionRef::has_substitutions () const
+{
+  return substitutions.size () > 0;
+}
+
+std::string
+SubstitutionRef::subst_as_string () const
+{
+  std::string buffer;
+  for (size_t i = 0; i < substitutions.size (); i++)
+    {
+      const SubstitutionParamMapping &sub = substitutions.at (i);
+      buffer += sub.as_string ();
+
+      if ((i + 1) < substitutions.size ())
+	buffer += ", ";
+    }
+
+  return buffer.empty () ? "" : "<" + buffer + ">";
+}
+
+bool
+SubstitutionRef::supports_associated_bindings () const
+{
+  return get_num_associated_bindings () > 0;
+}
+
+size_t
+SubstitutionRef::get_num_associated_bindings () const
+{
+  return 0;
+}
+
+TypeBoundPredicateItem
+SubstitutionRef::lookup_associated_type (const std::string &search)
+{
+  return TypeBoundPredicateItem::error ();
+}
+
+size_t
+SubstitutionRef::get_num_substitutions () const
+{
+  return substitutions.size ();
+}
+
+std::vector<SubstitutionParamMapping> &
+SubstitutionRef::get_substs ()
+{
+  return substitutions;
+}
+
+const std::vector<SubstitutionParamMapping> &
+SubstitutionRef::get_substs () const
+{
+  return substitutions;
+}
+
+std::vector<SubstitutionParamMapping>
+SubstitutionRef::clone_substs () const
+{
+  std::vector<SubstitutionParamMapping> clone;
+
+  for (auto &sub : substitutions)
+    clone.push_back (sub.clone ());
+
+  return clone;
+}
+
+void
+SubstitutionRef::override_context ()
+{
+  for (auto &sub : substitutions)
+    {
+      sub.override_context ();
+    }
+}
+
+bool
+SubstitutionRef::needs_substitution () const
+{
+  for (auto &sub : substitutions)
+    {
+      if (sub.need_substitution ())
+	return true;
+    }
+  return false;
+}
+
+bool
+SubstitutionRef::was_substituted () const
+{
+  return !needs_substitution ();
+}
+
+SubstitutionArgumentMappings
+SubstitutionRef::get_substitution_arguments () const
+{
+  return used_arguments;
+}
+
+size_t
+SubstitutionRef::num_required_substitutions () const
+{
+  size_t n = 0;
+  for (auto &p : substitutions)
+    {
+      if (p.needs_substitution ())
+	n++;
+    }
+  return n;
+}
+
+size_t
+SubstitutionRef::min_required_substitutions () const
+{
+  size_t n = 0;
+  for (auto &p : substitutions)
+    {
+      if (p.needs_substitution () && !p.param_has_default_ty ())
+	n++;
+    }
+  return n;
+}
+
+SubstitutionArgumentMappings
+SubstitutionRef::get_used_arguments () const
+{
+  return used_arguments;
+}
+
+SubstitutionArgumentMappings
+SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args)
+{
+  std::map<std::string, BaseType *> binding_arguments;
+  if (args.get_binding_args ().size () > 0)
+    {
+      if (supports_associated_bindings ())
+	{
+	  if (args.get_binding_args ().size () > get_num_associated_bindings ())
+	    {
+	      RichLocation r (args.get_locus ());
+
+	      rust_error_at (r,
+			     "generic item takes at most %lu type binding "
+			     "arguments but %lu were supplied",
+			     (unsigned long) get_num_associated_bindings (),
+			     (unsigned long) args.get_binding_args ().size ());
+	      return SubstitutionArgumentMappings::error ();
+	    }
+
+	  for (auto &binding : args.get_binding_args ())
+	    {
+	      BaseType *resolved
+		= Resolver::TypeCheckType::Resolve (binding.get_type ().get ());
+	      if (resolved == nullptr
+		  || resolved->get_kind () == TyTy::TypeKind::ERROR)
+		{
+		  rust_error_at (binding.get_locus (),
+				 "failed to resolve type arguments");
+		  return SubstitutionArgumentMappings::error ();
+		}
+
+	      // resolve to relevant binding
+	      auto binding_item
+		= lookup_associated_type (binding.get_identifier ());
+	      if (binding_item.is_error ())
+		{
+		  rust_error_at (binding.get_locus (),
+				 "unknown associated type binding: %s",
+				 binding.get_identifier ().c_str ());
+		  return SubstitutionArgumentMappings::error ();
+		}
+
+	      binding_arguments[binding.get_identifier ()] = resolved;
+	    }
+	}
+      else
+	{
+	  RichLocation r (args.get_locus ());
+	  for (auto &binding : args.get_binding_args ())
+	    r.add_range (binding.get_locus ());
+
+	  rust_error_at (r, "associated type bindings are not allowed here");
+	  return SubstitutionArgumentMappings::error ();
+	}
+    }
+
+  // for inherited arguments
+  size_t offs = used_arguments.size ();
+  if (args.get_type_args ().size () + offs > substitutions.size ())
+    {
+      RichLocation r (args.get_locus ());
+      r.add_range (substitutions.front ().get_param_locus ());
+
+      rust_error_at (
+	r,
+	"generic item takes at most %lu type arguments but %lu were supplied",
+	(unsigned long) substitutions.size (),
+	(unsigned long) args.get_type_args ().size ());
+      return SubstitutionArgumentMappings::error ();
+    }
+
+  if (args.get_type_args ().size () + offs < min_required_substitutions ())
+    {
+      RichLocation r (args.get_locus ());
+      r.add_range (substitutions.front ().get_param_locus ());
+
+      rust_error_at (
+	r,
+	"generic item takes at least %lu type arguments but %lu were supplied",
+	(unsigned long) (min_required_substitutions () - offs),
+	(unsigned long) args.get_type_args ().size ());
+      return SubstitutionArgumentMappings::error ();
+    }
+
+  std::vector<SubstitutionArg> mappings = used_arguments.get_mappings ();
+  for (auto &arg : args.get_type_args ())
+    {
+      BaseType *resolved = Resolver::TypeCheckType::Resolve (arg.get ());
+      if (resolved == nullptr || resolved->get_kind () == TyTy::TypeKind::ERROR)
+	{
+	  rust_error_at (args.get_locus (), "failed to resolve type arguments");
+	  return SubstitutionArgumentMappings::error ();
+	}
+
+      SubstitutionArg subst_arg (&substitutions.at (offs), resolved);
+      offs++;
+      mappings.push_back (std::move (subst_arg));
+    }
+
+  // we must need to fill out defaults
+  size_t left_over
+    = num_required_substitutions () - min_required_substitutions ();
+  if (left_over > 0)
+    {
+      for (size_t offs = mappings.size (); offs < substitutions.size (); offs++)
+	{
+	  SubstitutionParamMapping &param = substitutions.at (offs);
+	  rust_assert (param.param_has_default_ty ());
+
+	  BaseType *resolved = param.get_default_ty ();
+	  if (resolved->get_kind () == TypeKind::ERROR)
+	    return SubstitutionArgumentMappings::error ();
+
+	  // this resolved default might already contain default parameters
+	  if (resolved->contains_type_parameters ())
+	    {
+	      SubstitutionArgumentMappings intermediate (mappings,
+							 binding_arguments,
+							 args.get_locus ());
+	      resolved = Resolver::SubstMapperInternal::Resolve (resolved,
+								 intermediate);
+
+	      if (resolved->get_kind () == TypeKind::ERROR)
+		return SubstitutionArgumentMappings::error ();
+	    }
+
+	  SubstitutionArg subst_arg (&param, resolved);
+	  mappings.push_back (std::move (subst_arg));
+	}
+    }
+
+  return SubstitutionArgumentMappings (mappings, binding_arguments,
+				       args.get_locus ());
+}
+
+BaseType *
+SubstitutionRef::infer_substitions (Location locus)
+{
+  std::vector<SubstitutionArg> args;
+  std::map<std::string, BaseType *> argument_mappings;
+  for (auto &p : get_substs ())
+    {
+      if (p.needs_substitution ())
+	{
+	  const std::string &symbol = p.get_param_ty ()->get_symbol ();
+	  auto it = argument_mappings.find (symbol);
+	  bool have_mapping = it != argument_mappings.end ();
+
+	  if (have_mapping)
+	    {
+	      args.push_back (SubstitutionArg (&p, it->second));
+	    }
+	  else
+	    {
+	      TyVar infer_var = TyVar::get_implicit_infer_var (locus);
+	      args.push_back (SubstitutionArg (&p, infer_var.get_tyty ()));
+	      argument_mappings[symbol] = infer_var.get_tyty ();
+	    }
+	}
+      else
+	{
+	  args.push_back (SubstitutionArg (&p, p.get_param_ty ()->resolve ()));
+	}
+    }
+
+  // FIXME do we need to add inference variables to all the possible bindings?
+  // it might just lead to inference variable hell not 100% sure if rustc does
+  // this i think the language might needs this to be explicitly set
+
+  SubstitutionArgumentMappings infer_arguments (std::move (args),
+						{} /* binding_arguments */,
+						locus);
+  return handle_substitions (std::move (infer_arguments));
+}
+
+SubstitutionArgumentMappings
+SubstitutionRef::adjust_mappings_for_this (
+  SubstitutionArgumentMappings &mappings)
+{
+  std::vector<SubstitutionArg> resolved_mappings;
+  for (size_t i = 0; i < substitutions.size (); i++)
+    {
+      auto &subst = substitutions.at (i);
+
+      SubstitutionArg arg = SubstitutionArg::error ();
+      if (mappings.size () == substitutions.size ())
+	{
+	  mappings.get_argument_at (i, &arg);
+	}
+      else
+	{
+	  if (subst.needs_substitution ())
+	    {
+	      // get from passed in mappings
+	      mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
+	    }
+	  else
+	    {
+	      // we should already have this somewhere
+	      used_arguments.get_argument_for_symbol (subst.get_param_ty (),
+						      &arg);
+	    }
+	}
+
+      bool ok = !arg.is_error ();
+      if (ok)
+	{
+	  SubstitutionArg adjusted (&subst, arg.get_tyty ());
+	  resolved_mappings.push_back (std::move (adjusted));
+	}
+    }
+
+  if (resolved_mappings.empty ())
+    return SubstitutionArgumentMappings::error ();
+
+  return SubstitutionArgumentMappings (resolved_mappings,
+				       mappings.get_binding_args (),
+				       mappings.get_locus (),
+				       mappings.get_subst_cb (),
+				       mappings.trait_item_mode ());
+}
+
+bool
+SubstitutionRef::are_mappings_bound (SubstitutionArgumentMappings &mappings)
+{
+  std::vector<SubstitutionArg> resolved_mappings;
+  for (size_t i = 0; i < substitutions.size (); i++)
+    {
+      auto &subst = substitutions.at (i);
+
+      SubstitutionArg arg = SubstitutionArg::error ();
+      if (mappings.size () == substitutions.size ())
+	{
+	  mappings.get_argument_at (i, &arg);
+	}
+      else
+	{
+	  if (subst.needs_substitution ())
+	    {
+	      // get from passed in mappings
+	      mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
+	    }
+	  else
+	    {
+	      // we should already have this somewhere
+	      used_arguments.get_argument_for_symbol (subst.get_param_ty (),
+						      &arg);
+	    }
+	}
+
+      bool ok = !arg.is_error ();
+      if (ok)
+	{
+	  SubstitutionArg adjusted (&subst, arg.get_tyty ());
+	  resolved_mappings.push_back (std::move (adjusted));
+	}
+    }
+
+  return !resolved_mappings.empty ();
+}
+
+// this function assumes that the mappings being passed are for the same type as
+// this new substitution reference so ordering matters here
+SubstitutionArgumentMappings
+SubstitutionRef::solve_mappings_from_receiver_for_self (
+  SubstitutionArgumentMappings &mappings) const
+{
+  std::vector<SubstitutionArg> resolved_mappings;
+
+  rust_assert (mappings.size () == get_num_substitutions ());
+  for (size_t i = 0; i < get_num_substitutions (); i++)
+    {
+      const SubstitutionParamMapping &param_mapping = substitutions.at (i);
+      SubstitutionArg &arg = mappings.get_mappings ().at (i);
+
+      if (param_mapping.needs_substitution ())
+	{
+	  SubstitutionArg adjusted (&param_mapping, arg.get_tyty ());
+	  resolved_mappings.push_back (std::move (adjusted));
+	}
+    }
+
+  return SubstitutionArgumentMappings (resolved_mappings,
+				       mappings.get_binding_args (),
+				       mappings.get_locus ());
+}
+
+SubstitutionArgumentMappings
+SubstitutionRef::solve_missing_mappings_from_this (SubstitutionRef &ref,
+						   SubstitutionRef &to)
+{
+  rust_assert (!ref.needs_substitution ());
+  rust_assert (needs_substitution ());
+  rust_assert (get_num_substitutions () == ref.get_num_substitutions ());
+
+  Location locus = used_arguments.get_locus ();
+  std::vector<SubstitutionArg> resolved_mappings;
+
+  std::map<HirId, std::pair<ParamType *, BaseType *>> substs;
+  for (size_t i = 0; i < get_num_substitutions (); i++)
+    {
+      SubstitutionParamMapping &a = substitutions.at (i);
+      SubstitutionParamMapping &b = ref.substitutions.at (i);
+
+      if (a.need_substitution ())
+	{
+	  const BaseType *root = a.get_param_ty ()->resolve ()->get_root ();
+	  rust_assert (root->get_kind () == TyTy::TypeKind::PARAM);
+	  const ParamType *p = static_cast<const TyTy::ParamType *> (root);
+
+	  substs[p->get_ty_ref ()] = {static_cast<ParamType *> (p->clone ()),
+				      b.get_param_ty ()->resolve ()};
+	}
+    }
+
+  for (auto it = substs.begin (); it != substs.end (); it++)
+    {
+      HirId param_id = it->first;
+      BaseType *arg = it->second.second;
+
+      const SubstitutionParamMapping *associate_param = nullptr;
+      for (SubstitutionParamMapping &p : to.substitutions)
+	{
+	  if (p.get_param_ty ()->get_ty_ref () == param_id)
+	    {
+	      associate_param = &p;
+	      break;
+	    }
+	}
+
+      rust_assert (associate_param != nullptr);
+      SubstitutionArg argument (associate_param, arg);
+      resolved_mappings.push_back (std::move (argument));
+    }
+
+  return SubstitutionArgumentMappings (resolved_mappings, {}, locus);
+}
+
+bool
+SubstitutionRef::monomorphize ()
+{
+  auto context = Resolver::TypeCheckContext::get ();
+  for (const auto &subst : get_substs ())
+    {
+      const TyTy::ParamType *pty = subst.get_param_ty ();
+
+      if (!pty->can_resolve ())
+	continue;
+
+      const TyTy::BaseType *binding = pty->resolve ();
+      if (binding->get_kind () == TyTy::TypeKind::PARAM)
+	continue;
+
+      for (const auto &bound : pty->get_specified_bounds ())
+	{
+	  const Resolver::TraitReference *specified_bound_ref = bound.get ();
+
+	  // setup any associated type mappings for the specified bonds and this
+	  // type
+	  auto candidates = Resolver::TypeBoundsProbe::Probe (binding);
+
+	  Resolver::AssociatedImplTrait *associated_impl_trait = nullptr;
+	  for (auto &probed_bound : candidates)
+	    {
+	      const Resolver::TraitReference *bound_trait_ref
+		= probed_bound.first;
+	      const HIR::ImplBlock *associated_impl = probed_bound.second;
+
+	      HirId impl_block_id
+		= associated_impl->get_mappings ().get_hirid ();
+	      Resolver::AssociatedImplTrait *associated = nullptr;
+	      bool found_impl_trait
+		= context->lookup_associated_trait_impl (impl_block_id,
+							 &associated);
+	      if (found_impl_trait)
+		{
+		  bool found_trait
+		    = specified_bound_ref->is_equal (*bound_trait_ref);
+		  bool found_self
+		    = associated->get_self ()->can_eq (binding, false);
+		  if (found_trait && found_self)
+		    {
+		      associated_impl_trait = associated;
+		      break;
+		    }
+		}
+	    }
+
+	  if (associated_impl_trait != nullptr)
+	    {
+	      associated_impl_trait->setup_associated_types (binding, bound);
+	    }
+	}
+    }
+
+  return true;
+}
+
+} // namespace TyTy
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h
new file mode 100644
index 00000000000..4d09a3013e7
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-subst.h
@@ -0,0 +1,316 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_TYTY_SUBST_H
+#define RUST_TYTY_SUBST_H
+
+#include "rust-system.h"
+#include "rust-location.h"
+#include "rust-hir-full-decls.h"
+#include "rust-tyty-bounds.h"
+
+namespace Rust {
+namespace TyTy {
+
+class BaseType;
+class ParamType;
+class SubstitutionArgumentMappings;
+class SubstitutionParamMapping
+{
+public:
+  SubstitutionParamMapping (const HIR::TypeParam &generic, ParamType *param);
+
+  SubstitutionParamMapping (const SubstitutionParamMapping &other);
+
+  std::string as_string () const;
+
+  bool fill_param_ty (SubstitutionArgumentMappings &subst_mappings,
+		      Location locus);
+
+  SubstitutionParamMapping clone () const;
+
+  ParamType *get_param_ty ();
+
+  const ParamType *get_param_ty () const;
+
+  const HIR::TypeParam &get_generic_param ();
+
+  // this is used for the backend to override the HirId ref of the param to
+  // what the concrete type is for the rest of the context
+  void override_context ();
+
+  bool needs_substitution () const;
+
+  Location get_param_locus () const;
+
+  bool param_has_default_ty () const;
+
+  BaseType *get_default_ty () const;
+
+  bool need_substitution () const;
+
+private:
+  const HIR::TypeParam &generic;
+  ParamType *param;
+};
+
+class SubstitutionArg
+{
+public:
+  SubstitutionArg (const SubstitutionParamMapping *param, BaseType *argument);
+
+  // FIXME
+  // the copy constructors need removed - they are unsafe see
+  // TypeBoundPredicate
+  SubstitutionArg (const SubstitutionArg &other);
+
+  SubstitutionArg &operator= (const SubstitutionArg &other);
+
+  BaseType *get_tyty ();
+
+  const BaseType *get_tyty () const;
+
+  const SubstitutionParamMapping *get_param_mapping () const;
+
+  static SubstitutionArg error ();
+
+  bool is_error () const;
+
+  bool is_conrete () const;
+
+  std::string as_string () const;
+
+private:
+  const SubstitutionParamMapping *param;
+  BaseType *argument;
+};
+
+typedef std::function<void (const ParamType &, const SubstitutionArg &)>
+  ParamSubstCb;
+class SubstitutionArgumentMappings
+{
+public:
+  SubstitutionArgumentMappings (std::vector<SubstitutionArg> mappings,
+				std::map<std::string, BaseType *> binding_args,
+				Location locus,
+				ParamSubstCb param_subst_cb = nullptr,
+				bool trait_item_flag = false);
+
+  SubstitutionArgumentMappings (const SubstitutionArgumentMappings &other);
+  SubstitutionArgumentMappings &
+  operator= (const SubstitutionArgumentMappings &other);
+
+  SubstitutionArgumentMappings (SubstitutionArgumentMappings &&other) = default;
+  SubstitutionArgumentMappings &operator= (SubstitutionArgumentMappings &&other)
+    = default;
+
+  static SubstitutionArgumentMappings error ();
+
+  bool is_error () const;
+
+  bool get_argument_for_symbol (const ParamType *param_to_find,
+				SubstitutionArg *argument);
+
+  bool get_argument_at (size_t index, SubstitutionArg *argument);
+
+  // is_concrete means if the used args is non error, ie: non empty this will
+  // verify if actual real types have been put in place of are they still
+  // ParamTy
+  bool is_concrete () const;
+
+  Location get_locus () const;
+
+  size_t size () const;
+
+  bool is_empty () const;
+
+  std::vector<SubstitutionArg> &get_mappings ();
+
+  const std::vector<SubstitutionArg> &get_mappings () const;
+
+  std::map<std::string, BaseType *> &get_binding_args ();
+
+  const std::map<std::string, BaseType *> &get_binding_args () const;
+
+  std::string as_string () const;
+
+  void on_param_subst (const ParamType &p, const SubstitutionArg &a) const;
+
+  ParamSubstCb get_subst_cb () const;
+
+  bool trait_item_mode () const;
+
+private:
+  std::vector<SubstitutionArg> mappings;
+  std::map<std::string, BaseType *> binding_args;
+  Location locus;
+  ParamSubstCb param_subst_cb;
+  bool trait_item_flag;
+};
+
+class SubstitutionRef
+{
+public:
+  SubstitutionRef (std::vector<SubstitutionParamMapping> substitutions,
+		   SubstitutionArgumentMappings arguments);
+
+  bool has_substitutions () const;
+
+  std::string subst_as_string () const;
+
+  bool supports_associated_bindings () const;
+
+  // this is overridden in TypeBoundPredicate
+  // which support bindings we don't add them directly to the SubstitutionRef
+  // base class because this class represents the fn<X: Foo, Y: Bar>. The only
+  // construct which supports associated types
+  virtual size_t get_num_associated_bindings () const;
+
+  // this is overridden in TypeBoundPredicate
+  virtual TypeBoundPredicateItem
+  lookup_associated_type (const std::string &search);
+
+  size_t get_num_substitutions () const;
+
+  std::vector<SubstitutionParamMapping> &get_substs ();
+
+  const std::vector<SubstitutionParamMapping> &get_substs () const;
+
+  std::vector<SubstitutionParamMapping> clone_substs () const;
+
+  void override_context ();
+
+  bool needs_substitution () const;
+
+  bool was_substituted () const;
+
+  SubstitutionArgumentMappings get_substitution_arguments () const;
+
+  // this is the count of type params that are not substituted fuly
+  size_t num_required_substitutions () const;
+
+  // this is the count of type params that need substituted taking into account
+  // possible defaults
+  size_t min_required_substitutions () const;
+
+  // We are trying to subst <i32, f32> into Struct Foo<X,Y> {}
+  // in the case of Foo<i32,f32>{...}
+  //
+  // the substitions we have here define X,Y but the arguments have no bindings
+  // so its a matter of ordering
+  SubstitutionArgumentMappings
+  get_mappings_from_generic_args (HIR::GenericArgs &args);
+
+  // Recursive substitutions
+  // Foo <A,B> { a:A, b: B}; Bar <X,Y,Z>{a:X, b: Foo<Y,Z>}
+  //
+  // we have bindings for X Y Z and need to propagate the binding Y,Z into Foo
+  // Which binds to A,B
+  SubstitutionArgumentMappings
+  adjust_mappings_for_this (SubstitutionArgumentMappings &mappings);
+
+  // Are the mappings here actually bound to this type. For example imagine the
+  // case:
+  //
+  // struct Foo<T>(T);
+  // impl<T> Foo<T> {
+  //   fn test(self) { ... }
+  // }
+  //
+  // In this case we have a generic ADT of Foo and an impl block of a generic T
+  // on Foo for the Self type. When we it comes to path resolution we can have:
+  //
+  // Foo::<i32>::test()
+  //
+  // This means the first segment of Foo::<i32> returns the ADT Foo<i32> not the
+  // Self ADT bound to the T from the impl block. This means when it comes to
+  // the next segment of test which resolves to the function we need to check
+  // wether the arguments in the struct definition of foo can be bound here
+  // before substituting the previous segments type here. This functions acts as
+  // a guard for the solve_mappings_from_receiver_for_self to handle the case
+  // where arguments are not bound. This is important for this next case:
+  //
+  // struct Baz<A, B>(A, B);
+  // impl Baz<i32, f32> {
+  //   fn test<X>(a: X) -> X {
+  //       a
+  //   }
+  // }
+  //
+  // In this case Baz has been already substituted for the impl's Self to become
+  // ADT<i32, f32> so that the function test only has 1 generic argument of X.
+  // The path for this will be:
+  //
+  // Baz::test::<_>(123)
+  //
+  // So the first segment here will be Baz<_, _> to try and infer the arguments
+  // which will be taken from the impl's Self type in this case since it is
+  // already substituted and like the previous case the check to see if we need
+  // to inherit the previous segments generic arguments takes place but the
+  // generic arguments are not bound to this type as they have already been
+  // substituted.
+  //
+  // Its important to remember from the first example the FnType actually looks
+  // like:
+  //
+  // fn <T>test(self :Foo<T>(T))
+  //
+  // As the generic parameters are "bound" to each of the items in the impl
+  // block. So this check is about wether the arguments we have here can
+  // actually be bound to this type.
+  bool are_mappings_bound (SubstitutionArgumentMappings &mappings);
+
+  // struct Foo<A, B>(A, B);
+  //
+  // impl<T> Foo<T, f32>;
+  //     -> fn test<X>(self, a: X) -> X
+  //
+  // We might invoke this via:
+  //
+  // a = Foo(123, 456f32);
+  // b = a.test::<bool>(false);
+  //
+  // we need to figure out relevant generic arguemts for self to apply to the
+  // fntype
+  SubstitutionArgumentMappings solve_mappings_from_receiver_for_self (
+    SubstitutionArgumentMappings &mappings) const;
+
+  // TODO comment
+  SubstitutionArgumentMappings
+  solve_missing_mappings_from_this (SubstitutionRef &ref, SubstitutionRef &to);
+
+  // TODO comment
+  BaseType *infer_substitions (Location locus);
+
+  // TODO comment
+  bool monomorphize ();
+
+  // TODO comment
+  virtual BaseType *handle_substitions (SubstitutionArgumentMappings mappings)
+    = 0;
+
+  SubstitutionArgumentMappings get_used_arguments () const;
+
+protected:
+  std::vector<SubstitutionParamMapping> substitutions;
+  SubstitutionArgumentMappings used_arguments;
+};
+
+} // namespace TyTy
+} // namespace Rust
+#endif // RUST_TYTY_SUBST_H
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 55a8123ce87..b45bd99b1bd 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -514,472 +514,6 @@ StructFieldType::monomorphized_clone () const
 			      get_field_type ()->monomorphized_clone (), locus);
 }
 
-bool
-SubstitutionParamMapping::need_substitution () const
-{
-  if (!param->can_resolve ())
-    return true;
-
-  auto resolved = param->resolve ();
-  return !resolved->is_concrete ();
-}
-
-bool
-SubstitutionParamMapping::fill_param_ty (
-  SubstitutionArgumentMappings &subst_mappings, Location locus)
-{
-  SubstitutionArg arg = SubstitutionArg::error ();
-  bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg);
-  if (!ok)
-    return true;
-
-  TyTy::BaseType &type = *arg.get_tyty ();
-  if (type.get_kind () == TyTy::TypeKind::INFER)
-    {
-      type.inherit_bounds (*param);
-    }
-  else
-    {
-      if (!param->bounds_compatible (type, locus, true))
-	return false;
-    }
-
-  if (type.get_kind () == TypeKind::PARAM)
-    {
-      // delete param;
-      param = static_cast<ParamType *> (type.clone ());
-    }
-  else
-    {
-      // check the substitution is compatible with bounds
-      if (!param->bounds_compatible (type, locus, true))
-	return false;
-
-      // recursively pass this down to all HRTB's
-      for (auto &bound : param->get_specified_bounds ())
-	bound.handle_substitions (subst_mappings);
-
-      param->set_ty_ref (type.get_ref ());
-    }
-
-  return true;
-}
-
-void
-SubstitutionParamMapping::override_context ()
-{
-  if (!param->can_resolve ())
-    return;
-
-  auto mappings = Analysis::Mappings::get ();
-  auto context = Resolver::TypeCheckContext::get ();
-
-  context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
-					       UNKNOWN_NODEID,
-					       param->get_ref (),
-					       UNKNOWN_LOCAL_DEFID),
-			param->resolve ());
-}
-
-SubstitutionArgumentMappings
-SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args)
-{
-  std::map<std::string, BaseType *> binding_arguments;
-  if (args.get_binding_args ().size () > 0)
-    {
-      if (supports_associated_bindings ())
-	{
-	  if (args.get_binding_args ().size () > get_num_associated_bindings ())
-	    {
-	      RichLocation r (args.get_locus ());
-
-	      rust_error_at (r,
-			     "generic item takes at most %lu type binding "
-			     "arguments but %lu were supplied",
-			     (unsigned long) get_num_associated_bindings (),
-			     (unsigned long) args.get_binding_args ().size ());
-	      return SubstitutionArgumentMappings::error ();
-	    }
-
-	  for (auto &binding : args.get_binding_args ())
-	    {
-	      BaseType *resolved
-		= Resolver::TypeCheckType::Resolve (binding.get_type ().get ());
-	      if (resolved == nullptr
-		  || resolved->get_kind () == TyTy::TypeKind::ERROR)
-		{
-		  rust_error_at (binding.get_locus (),
-				 "failed to resolve type arguments");
-		  return SubstitutionArgumentMappings::error ();
-		}
-
-	      // resolve to relevant binding
-	      auto binding_item
-		= lookup_associated_type (binding.get_identifier ());
-	      if (binding_item.is_error ())
-		{
-		  rust_error_at (binding.get_locus (),
-				 "unknown associated type binding: %s",
-				 binding.get_identifier ().c_str ());
-		  return SubstitutionArgumentMappings::error ();
-		}
-
-	      binding_arguments[binding.get_identifier ()] = resolved;
-	    }
-	}
-      else
-	{
-	  RichLocation r (args.get_locus ());
-	  for (auto &binding : args.get_binding_args ())
-	    r.add_range (binding.get_locus ());
-
-	  rust_error_at (r, "associated type bindings are not allowed here");
-	  return SubstitutionArgumentMappings::error ();
-	}
-    }
-
-  // for inherited arguments
-  size_t offs = used_arguments.size ();
-  if (args.get_type_args ().size () + offs > substitutions.size ())
-    {
-      RichLocation r (args.get_locus ());
-      r.add_range (substitutions.front ().get_param_locus ());
-
-      rust_error_at (
-	r,
-	"generic item takes at most %lu type arguments but %lu were supplied",
-	(unsigned long) substitutions.size (),
-	(unsigned long) args.get_type_args ().size ());
-      return SubstitutionArgumentMappings::error ();
-    }
-
-  if (args.get_type_args ().size () + offs < min_required_substitutions ())
-    {
-      RichLocation r (args.get_locus ());
-      r.add_range (substitutions.front ().get_param_locus ());
-
-      rust_error_at (
-	r,
-	"generic item takes at least %lu type arguments but %lu were supplied",
-	(unsigned long) (min_required_substitutions () - offs),
-	(unsigned long) args.get_type_args ().size ());
-      return SubstitutionArgumentMappings::error ();
-    }
-
-  std::vector<SubstitutionArg> mappings = used_arguments.get_mappings ();
-  for (auto &arg : args.get_type_args ())
-    {
-      BaseType *resolved = Resolver::TypeCheckType::Resolve (arg.get ());
-      if (resolved == nullptr || resolved->get_kind () == TyTy::TypeKind::ERROR)
-	{
-	  rust_error_at (args.get_locus (), "failed to resolve type arguments");
-	  return SubstitutionArgumentMappings::error ();
-	}
-
-      SubstitutionArg subst_arg (&substitutions.at (offs), resolved);
-      offs++;
-      mappings.push_back (std::move (subst_arg));
-    }
-
-  // we must need to fill out defaults
-  size_t left_over
-    = num_required_substitutions () - min_required_substitutions ();
-  if (left_over > 0)
-    {
-      for (size_t offs = mappings.size (); offs < substitutions.size (); offs++)
-	{
-	  SubstitutionParamMapping &param = substitutions.at (offs);
-	  rust_assert (param.param_has_default_ty ());
-
-	  BaseType *resolved = param.get_default_ty ();
-	  if (resolved->get_kind () == TypeKind::ERROR)
-	    return SubstitutionArgumentMappings::error ();
-
-	  // this resolved default might already contain default parameters
-	  if (resolved->contains_type_parameters ())
-	    {
-	      SubstitutionArgumentMappings intermediate (mappings,
-							 binding_arguments,
-							 args.get_locus ());
-	      resolved = Resolver::SubstMapperInternal::Resolve (resolved,
-								 intermediate);
-
-	      if (resolved->get_kind () == TypeKind::ERROR)
-		return SubstitutionArgumentMappings::error ();
-	    }
-
-	  SubstitutionArg subst_arg (&param, resolved);
-	  mappings.push_back (std::move (subst_arg));
-	}
-    }
-
-  return SubstitutionArgumentMappings (mappings, binding_arguments,
-				       args.get_locus ());
-}
-
-BaseType *
-SubstitutionRef::infer_substitions (Location locus)
-{
-  std::vector<SubstitutionArg> args;
-  std::map<std::string, BaseType *> argument_mappings;
-  for (auto &p : get_substs ())
-    {
-      if (p.needs_substitution ())
-	{
-	  const std::string &symbol = p.get_param_ty ()->get_symbol ();
-	  auto it = argument_mappings.find (symbol);
-	  bool have_mapping = it != argument_mappings.end ();
-
-	  if (have_mapping)
-	    {
-	      args.push_back (SubstitutionArg (&p, it->second));
-	    }
-	  else
-	    {
-	      TyVar infer_var = TyVar::get_implicit_infer_var (locus);
-	      args.push_back (SubstitutionArg (&p, infer_var.get_tyty ()));
-	      argument_mappings[symbol] = infer_var.get_tyty ();
-	    }
-	}
-      else
-	{
-	  args.push_back (SubstitutionArg (&p, p.get_param_ty ()->resolve ()));
-	}
-    }
-
-  // FIXME do we need to add inference variables to all the possible bindings?
-  // it might just lead to inference variable hell not 100% sure if rustc does
-  // this i think the language might needs this to be explicitly set
-
-  SubstitutionArgumentMappings infer_arguments (std::move (args),
-						{} /* binding_arguments */,
-						locus);
-  return handle_substitions (std::move (infer_arguments));
-}
-
-SubstitutionArgumentMappings
-SubstitutionRef::adjust_mappings_for_this (
-  SubstitutionArgumentMappings &mappings)
-{
-  std::vector<SubstitutionArg> resolved_mappings;
-  for (size_t i = 0; i < substitutions.size (); i++)
-    {
-      auto &subst = substitutions.at (i);
-
-      SubstitutionArg arg = SubstitutionArg::error ();
-      if (mappings.size () == substitutions.size ())
-	{
-	  mappings.get_argument_at (i, &arg);
-	}
-      else
-	{
-	  if (subst.needs_substitution ())
-	    {
-	      // get from passed in mappings
-	      mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
-	    }
-	  else
-	    {
-	      // we should already have this somewhere
-	      used_arguments.get_argument_for_symbol (subst.get_param_ty (),
-						      &arg);
-	    }
-	}
-
-      bool ok = !arg.is_error ();
-      if (ok)
-	{
-	  SubstitutionArg adjusted (&subst, arg.get_tyty ());
-	  resolved_mappings.push_back (std::move (adjusted));
-	}
-    }
-
-  if (resolved_mappings.empty ())
-    return SubstitutionArgumentMappings::error ();
-
-  return SubstitutionArgumentMappings (resolved_mappings,
-				       mappings.get_binding_args (),
-				       mappings.get_locus (),
-				       mappings.get_subst_cb (),
-				       mappings.trait_item_mode ());
-}
-
-bool
-SubstitutionRef::are_mappings_bound (SubstitutionArgumentMappings &mappings)
-{
-  std::vector<SubstitutionArg> resolved_mappings;
-  for (size_t i = 0; i < substitutions.size (); i++)
-    {
-      auto &subst = substitutions.at (i);
-
-      SubstitutionArg arg = SubstitutionArg::error ();
-      if (mappings.size () == substitutions.size ())
-	{
-	  mappings.get_argument_at (i, &arg);
-	}
-      else
-	{
-	  if (subst.needs_substitution ())
-	    {
-	      // get from passed in mappings
-	      mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
-	    }
-	  else
-	    {
-	      // we should already have this somewhere
-	      used_arguments.get_argument_for_symbol (subst.get_param_ty (),
-						      &arg);
-	    }
-	}
-
-      bool ok = !arg.is_error ();
-      if (ok)
-	{
-	  SubstitutionArg adjusted (&subst, arg.get_tyty ());
-	  resolved_mappings.push_back (std::move (adjusted));
-	}
-    }
-
-  return !resolved_mappings.empty ();
-}
-
-// this function assumes that the mappings being passed are for the same type as
-// this new substitution reference so ordering matters here
-SubstitutionArgumentMappings
-SubstitutionRef::solve_mappings_from_receiver_for_self (
-  SubstitutionArgumentMappings &mappings) const
-{
-  std::vector<SubstitutionArg> resolved_mappings;
-
-  rust_assert (mappings.size () == get_num_substitutions ());
-  for (size_t i = 0; i < get_num_substitutions (); i++)
-    {
-      const SubstitutionParamMapping &param_mapping = substitutions.at (i);
-      SubstitutionArg &arg = mappings.get_mappings ().at (i);
-
-      if (param_mapping.needs_substitution ())
-	{
-	  SubstitutionArg adjusted (&param_mapping, arg.get_tyty ());
-	  resolved_mappings.push_back (std::move (adjusted));
-	}
-    }
-
-  return SubstitutionArgumentMappings (resolved_mappings,
-				       mappings.get_binding_args (),
-				       mappings.get_locus ());
-}
-
-SubstitutionArgumentMappings
-SubstitutionRef::solve_missing_mappings_from_this (SubstitutionRef &ref,
-						   SubstitutionRef &to)
-{
-  rust_assert (!ref.needs_substitution ());
-  rust_assert (needs_substitution ());
-  rust_assert (get_num_substitutions () == ref.get_num_substitutions ());
-
-  Location locus = used_arguments.get_locus ();
-  std::vector<SubstitutionArg> resolved_mappings;
-
-  std::map<HirId, std::pair<ParamType *, BaseType *>> substs;
-  for (size_t i = 0; i < get_num_substitutions (); i++)
-    {
-      SubstitutionParamMapping &a = substitutions.at (i);
-      SubstitutionParamMapping &b = ref.substitutions.at (i);
-
-      if (a.need_substitution ())
-	{
-	  const BaseType *root = a.get_param_ty ()->resolve ()->get_root ();
-	  rust_assert (root->get_kind () == TyTy::TypeKind::PARAM);
-	  const ParamType *p = static_cast<const TyTy::ParamType *> (root);
-
-	  substs[p->get_ty_ref ()] = {static_cast<ParamType *> (p->clone ()),
-				      b.get_param_ty ()->resolve ()};
-	}
-    }
-
-  for (auto it = substs.begin (); it != substs.end (); it++)
-    {
-      HirId param_id = it->first;
-      BaseType *arg = it->second.second;
-
-      const SubstitutionParamMapping *associate_param = nullptr;
-      for (SubstitutionParamMapping &p : to.substitutions)
-	{
-	  if (p.get_param_ty ()->get_ty_ref () == param_id)
-	    {
-	      associate_param = &p;
-	      break;
-	    }
-	}
-
-      rust_assert (associate_param != nullptr);
-      SubstitutionArg argument (associate_param, arg);
-      resolved_mappings.push_back (std::move (argument));
-    }
-
-  return SubstitutionArgumentMappings (resolved_mappings, {}, locus);
-}
-
-bool
-SubstitutionRef::monomorphize ()
-{
-  auto context = Resolver::TypeCheckContext::get ();
-  for (const auto &subst : get_substs ())
-    {
-      const TyTy::ParamType *pty = subst.get_param_ty ();
-
-      if (!pty->can_resolve ())
-	continue;
-
-      const TyTy::BaseType *binding = pty->resolve ();
-      if (binding->get_kind () == TyTy::TypeKind::PARAM)
-	continue;
-
-      for (const auto &bound : pty->get_specified_bounds ())
-	{
-	  const Resolver::TraitReference *specified_bound_ref = bound.get ();
-
-	  // setup any associated type mappings for the specified bonds and this
-	  // type
-	  auto candidates = Resolver::TypeBoundsProbe::Probe (binding);
-
-	  Resolver::AssociatedImplTrait *associated_impl_trait = nullptr;
-	  for (auto &probed_bound : candidates)
-	    {
-	      const Resolver::TraitReference *bound_trait_ref
-		= probed_bound.first;
-	      const HIR::ImplBlock *associated_impl = probed_bound.second;
-
-	      HirId impl_block_id
-		= associated_impl->get_mappings ().get_hirid ();
-	      Resolver::AssociatedImplTrait *associated = nullptr;
-	      bool found_impl_trait
-		= context->lookup_associated_trait_impl (impl_block_id,
-							 &associated);
-	      if (found_impl_trait)
-		{
-		  bool found_trait
-		    = specified_bound_ref->is_equal (*bound_trait_ref);
-		  bool found_self
-		    = associated->get_self ()->can_eq (binding, false);
-		  if (found_trait && found_self)
-		    {
-		      associated_impl_trait = associated;
-		      break;
-		    }
-		}
-	    }
-
-	  if (associated_impl_trait != nullptr)
-	    {
-	      associated_impl_trait->setup_associated_types (binding, bound);
-	    }
-	}
-    }
-
-  return true;
-}
-
 void
 ADTType::accept_vis (TyVisitor &vis)
 {
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index a8bdf6f3a15..cb30a60ae96 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -27,6 +27,7 @@
 #include "rust-identifier.h"
 #include "rust-tyty-bounds.h"
 #include "rust-tyty-util.h"
+#include "rust-tyty-subst.h"
 
 namespace Rust {
 
@@ -462,469 +463,6 @@ private:
   std::vector<TyVar> fields;
 };
 
-class SubstitutionParamMapping
-{
-public:
-  SubstitutionParamMapping (const HIR::TypeParam &generic, ParamType *param)
-    : generic (generic), param (param)
-  {}
-
-  SubstitutionParamMapping (const SubstitutionParamMapping &other)
-    : generic (other.generic), param (other.param)
-  {}
-
-  std::string as_string () const
-  {
-    if (param == nullptr)
-      return "nullptr";
-
-    return param->get_name ();
-  }
-
-  bool fill_param_ty (SubstitutionArgumentMappings &subst_mappings,
-		      Location locus);
-
-  SubstitutionParamMapping clone () const
-  {
-    return SubstitutionParamMapping (generic, static_cast<ParamType *> (
-						param->clone ()));
-  }
-
-  ParamType *get_param_ty () { return param; }
-
-  const ParamType *get_param_ty () const { return param; }
-
-  const HIR::TypeParam &get_generic_param () { return generic; };
-
-  // this is used for the backend to override the HirId ref of the param to
-  // what the concrete type is for the rest of the context
-  void override_context ();
-
-  bool needs_substitution () const
-  {
-    return !(get_param_ty ()->is_concrete ());
-  }
-
-  Location get_param_locus () const { return generic.get_locus (); }
-
-  bool param_has_default_ty () const { return generic.has_type (); }
-
-  BaseType *get_default_ty () const
-  {
-    TyVar var (generic.get_type_mappings ().get_hirid ());
-    return var.get_tyty ();
-  }
-
-  bool need_substitution () const;
-
-private:
-  const HIR::TypeParam &generic;
-  ParamType *param;
-};
-
-class SubstitutionArg
-{
-public:
-  SubstitutionArg (const SubstitutionParamMapping *param, BaseType *argument)
-    : param (param), argument (argument)
-  {}
-
-  // FIXME
-  // the copy constructors need removed - they are unsafe see
-  // TypeBoundPredicate
-  SubstitutionArg (const SubstitutionArg &other)
-    : param (other.param), argument (other.argument)
-  {}
-
-  SubstitutionArg &operator= (const SubstitutionArg &other)
-  {
-    param = other.param;
-    argument = other.argument;
-    return *this;
-  }
-
-  BaseType *get_tyty () { return argument; }
-
-  const BaseType *get_tyty () const { return argument; }
-
-  const SubstitutionParamMapping *get_param_mapping () const { return param; }
-
-  static SubstitutionArg error () { return SubstitutionArg (nullptr, nullptr); }
-
-  bool is_error () const { return param == nullptr || argument == nullptr; }
-
-  bool is_conrete () const
-  {
-    if (argument != nullptr)
-      return true;
-
-    if (argument->get_kind () == TyTy::TypeKind::PARAM)
-      return false;
-
-    return argument->is_concrete ();
-  }
-
-  std::string as_string () const
-  {
-    return param->as_string ()
-	   + (argument != nullptr ? ":" + argument->as_string () : "");
-  }
-
-private:
-  const SubstitutionParamMapping *param;
-  BaseType *argument;
-};
-
-typedef std::function<void (const ParamType &, const SubstitutionArg &)>
-  ParamSubstCb;
-class SubstitutionArgumentMappings
-{
-public:
-  SubstitutionArgumentMappings (std::vector<SubstitutionArg> mappings,
-				std::map<std::string, BaseType *> binding_args,
-				Location locus,
-				ParamSubstCb param_subst_cb = nullptr,
-				bool trait_item_flag = false)
-    : mappings (mappings), binding_args (binding_args), locus (locus),
-      param_subst_cb (param_subst_cb), trait_item_flag (trait_item_flag)
-  {}
-
-  SubstitutionArgumentMappings (const SubstitutionArgumentMappings &other)
-    : mappings (other.mappings), binding_args (other.binding_args),
-      locus (other.locus), param_subst_cb (other.param_subst_cb),
-      trait_item_flag (other.trait_item_flag)
-  {}
-
-  SubstitutionArgumentMappings &
-  operator= (const SubstitutionArgumentMappings &other)
-  {
-    mappings = other.mappings;
-    binding_args = other.binding_args;
-    locus = other.locus;
-    param_subst_cb = other.param_subst_cb;
-    trait_item_flag = other.trait_item_flag;
-
-    return *this;
-  }
-
-  SubstitutionArgumentMappings (SubstitutionArgumentMappings &&other) = default;
-  SubstitutionArgumentMappings &operator= (SubstitutionArgumentMappings &&other)
-    = default;
-
-  static SubstitutionArgumentMappings error ()
-  {
-    return SubstitutionArgumentMappings ({}, {}, Location (), nullptr, false);
-  }
-
-  bool is_error () const { return mappings.size () == 0; }
-
-  bool get_argument_for_symbol (const ParamType *param_to_find,
-				SubstitutionArg *argument)
-  {
-    for (auto &mapping : mappings)
-      {
-	const SubstitutionParamMapping *param = mapping.get_param_mapping ();
-	const ParamType *p = param->get_param_ty ();
-
-	if (p->get_symbol ().compare (param_to_find->get_symbol ()) == 0)
-	  {
-	    *argument = mapping;
-	    return true;
-	  }
-      }
-    return false;
-  }
-
-  bool get_argument_at (size_t index, SubstitutionArg *argument)
-  {
-    if (index > mappings.size ())
-      return false;
-
-    *argument = mappings.at (index);
-    return true;
-  }
-
-  // is_concrete means if the used args is non error, ie: non empty this will
-  // verify if actual real types have been put in place of are they still
-  // ParamTy
-  bool is_concrete () const
-  {
-    for (auto &mapping : mappings)
-      {
-	if (!mapping.is_conrete ())
-	  return false;
-      }
-    return true;
-  }
-
-  Location get_locus () const { return locus; }
-
-  size_t size () const { return mappings.size (); }
-
-  bool is_empty () const { return size () == 0; }
-
-  std::vector<SubstitutionArg> &get_mappings () { return mappings; }
-
-  const std::vector<SubstitutionArg> &get_mappings () const { return mappings; }
-
-  std::map<std::string, BaseType *> &get_binding_args ()
-  {
-    return binding_args;
-  }
-
-  const std::map<std::string, BaseType *> &get_binding_args () const
-  {
-    return binding_args;
-  }
-
-  std::string as_string () const
-  {
-    std::string buffer;
-    for (auto &mapping : mappings)
-      {
-	buffer += mapping.as_string () + ", ";
-      }
-    return "<" + buffer + ">";
-  }
-
-  void on_param_subst (const ParamType &p, const SubstitutionArg &a) const
-  {
-    if (param_subst_cb == nullptr)
-      return;
-
-    param_subst_cb (p, a);
-  }
-
-  ParamSubstCb get_subst_cb () const { return param_subst_cb; }
-
-  bool trait_item_mode () const { return trait_item_flag; }
-
-private:
-  std::vector<SubstitutionArg> mappings;
-  std::map<std::string, BaseType *> binding_args;
-  Location locus;
-  ParamSubstCb param_subst_cb;
-  bool trait_item_flag;
-};
-
-class SubstitutionRef
-{
-public:
-  SubstitutionRef (std::vector<SubstitutionParamMapping> substitutions,
-		   SubstitutionArgumentMappings arguments)
-    : substitutions (substitutions), used_arguments (arguments)
-  {}
-
-  bool has_substitutions () const { return substitutions.size () > 0; }
-
-  std::string subst_as_string () const
-  {
-    std::string buffer;
-    for (size_t i = 0; i < substitutions.size (); i++)
-      {
-	const SubstitutionParamMapping &sub = substitutions.at (i);
-	buffer += sub.as_string ();
-
-	if ((i + 1) < substitutions.size ())
-	  buffer += ", ";
-      }
-
-    return buffer.empty () ? "" : "<" + buffer + ">";
-  }
-
-  bool supports_associated_bindings () const
-  {
-    return get_num_associated_bindings () > 0;
-  }
-
-  // this is overridden in TypeBoundPredicate
-  // which support bindings we don't add them directly to the SubstitutionRef
-  // base class because this class represents the fn<X: Foo, Y: Bar>. The only
-  // construct which supports associated types
-  virtual size_t get_num_associated_bindings () const { return 0; }
-
-  // this is overridden in TypeBoundPredicate
-  virtual TypeBoundPredicateItem
-  lookup_associated_type (const std::string &search)
-  {
-    return TypeBoundPredicateItem::error ();
-  }
-
-  size_t get_num_substitutions () const { return substitutions.size (); }
-
-  std::vector<SubstitutionParamMapping> &get_substs () { return substitutions; }
-
-  const std::vector<SubstitutionParamMapping> &get_substs () const
-  {
-    return substitutions;
-  }
-
-  std::vector<SubstitutionParamMapping> clone_substs () const
-  {
-    std::vector<SubstitutionParamMapping> clone;
-
-    for (auto &sub : substitutions)
-      clone.push_back (sub.clone ());
-
-    return clone;
-  }
-
-  void override_context ()
-  {
-    for (auto &sub : substitutions)
-      {
-	sub.override_context ();
-      }
-  }
-
-  bool needs_substitution () const
-  {
-    for (auto &sub : substitutions)
-      {
-	if (sub.need_substitution ())
-	  return true;
-      }
-    return false;
-  }
-
-  bool was_substituted () const { return !needs_substitution (); }
-
-  SubstitutionArgumentMappings get_substitution_arguments () const
-  {
-    return used_arguments;
-  }
-
-  // this is the count of type params that are not substituted fuly
-  size_t num_required_substitutions () const
-  {
-    size_t n = 0;
-    for (auto &p : substitutions)
-      {
-	if (p.needs_substitution ())
-	  n++;
-      }
-    return n;
-  }
-
-  // this is the count of type params that need substituted taking into account
-  // possible defaults
-  size_t min_required_substitutions () const
-  {
-    size_t n = 0;
-    for (auto &p : substitutions)
-      {
-	if (p.needs_substitution () && !p.param_has_default_ty ())
-	  n++;
-      }
-    return n;
-  }
-
-  // We are trying to subst <i32, f32> into Struct Foo<X,Y> {}
-  // in the case of Foo<i32,f32>{...}
-  //
-  // the substitions we have here define X,Y but the arguments have no bindings
-  // so its a matter of ordering
-  SubstitutionArgumentMappings
-  get_mappings_from_generic_args (HIR::GenericArgs &args);
-
-  // Recursive substitutions
-  // Foo <A,B> { a:A, b: B}; Bar <X,Y,Z>{a:X, b: Foo<Y,Z>}
-  //
-  // we have bindings for X Y Z and need to propagate the binding Y,Z into Foo
-  // Which binds to A,B
-  SubstitutionArgumentMappings
-  adjust_mappings_for_this (SubstitutionArgumentMappings &mappings);
-
-  // Are the mappings here actually bound to this type. For example imagine the
-  // case:
-  //
-  // struct Foo<T>(T);
-  // impl<T> Foo<T> {
-  //   fn test(self) { ... }
-  // }
-  //
-  // In this case we have a generic ADT of Foo and an impl block of a generic T
-  // on Foo for the Self type. When we it comes to path resolution we can have:
-  //
-  // Foo::<i32>::test()
-  //
-  // This means the first segment of Foo::<i32> returns the ADT Foo<i32> not the
-  // Self ADT bound to the T from the impl block. This means when it comes to
-  // the next segment of test which resolves to the function we need to check
-  // wether the arguments in the struct definition of foo can be bound here
-  // before substituting the previous segments type here. This functions acts as
-  // a guard for the solve_mappings_from_receiver_for_self to handle the case
-  // where arguments are not bound. This is important for this next case:
-  //
-  // struct Baz<A, B>(A, B);
-  // impl Baz<i32, f32> {
-  //   fn test<X>(a: X) -> X {
-  //       a
-  //   }
-  // }
-  //
-  // In this case Baz has been already substituted for the impl's Self to become
-  // ADT<i32, f32> so that the function test only has 1 generic argument of X.
-  // The path for this will be:
-  //
-  // Baz::test::<_>(123)
-  //
-  // So the first segment here will be Baz<_, _> to try and infer the arguments
-  // which will be taken from the impl's Self type in this case since it is
-  // already substituted and like the previous case the check to see if we need
-  // to inherit the previous segments generic arguments takes place but the
-  // generic arguments are not bound to this type as they have already been
-  // substituted.
-  //
-  // Its important to remember from the first example the FnType actually looks
-  // like:
-  //
-  // fn <T>test(self :Foo<T>(T))
-  //
-  // As the generic parameters are "bound" to each of the items in the impl
-  // block. So this check is about wether the arguments we have here can
-  // actually be bound to this type.
-  bool are_mappings_bound (SubstitutionArgumentMappings &mappings);
-
-  // struct Foo<A, B>(A, B);
-  //
-  // impl<T> Foo<T, f32>;
-  //     -> fn test<X>(self, a: X) -> X
-  //
-  // We might invoke this via:
-  //
-  // a = Foo(123, 456f32);
-  // b = a.test::<bool>(false);
-  //
-  // we need to figure out relevant generic arguemts for self to apply to the
-  // fntype
-  SubstitutionArgumentMappings solve_mappings_from_receiver_for_self (
-    SubstitutionArgumentMappings &mappings) const;
-
-  // TODO comment
-  SubstitutionArgumentMappings
-  solve_missing_mappings_from_this (SubstitutionRef &ref, SubstitutionRef &to);
-
-  // TODO comment
-  BaseType *infer_substitions (Location locus);
-
-  // TODO comment
-  bool monomorphize ();
-
-  // TODO comment
-  virtual BaseType *handle_substitions (SubstitutionArgumentMappings mappings)
-    = 0;
-
-  SubstitutionArgumentMappings get_used_arguments () const
-  {
-    return used_arguments;
-  }
-
-protected:
-  std::vector<SubstitutionParamMapping> substitutions;
-  SubstitutionArgumentMappings used_arguments;
-};
-
 class TypeBoundPredicate : public SubstitutionRef
 {
 public:
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 39/88] gccrs: Refactor all substitution mapper code implementation into its own CC file
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (37 preceding siblings ...)
  2023-04-05 14:03 ` [committed 38/88] gccrs: Refactor SubstitutionRef base class into its own CC file arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 40/88] gccrs: Refactor BaseType, InferType and ErrorType impl into cc file arthur.cohen
                   ` (50 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* typecheck/rust-substitution-mapper.cc (SubstMapper::SubstMapper): refactor
	(SubstMapper::Resolve): likewise
	(SubstMapper::InferSubst): likewise
	(SubstMapper::have_generic_args): likewise
	(SubstMapper::visit): likewise
	(SubstMapperInternal::visit): likewise
	(SubstMapperFromExisting::SubstMapperFromExisting): likewise
	(SubstMapperFromExisting::Resolve): likewise
	(SubstMapperFromExisting::visit): likewise
	(GetUsedSubstArgs::GetUsedSubstArgs): likewise
	(GetUsedSubstArgs::From): likewise
	(GetUsedSubstArgs::visit): likewise
	* typecheck/rust-substitution-mapper.h: refactor
	* typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::get_generic_param): likewise
---
 .../typecheck/rust-substitution-mapper.cc     | 343 ++++++++++++++++++
 gcc/rust/typecheck/rust-substitution-mapper.h | 286 +++------------
 gcc/rust/typecheck/rust-tyty-subst.cc         |   2 +-
 3 files changed, 387 insertions(+), 244 deletions(-)

diff --git a/gcc/rust/typecheck/rust-substitution-mapper.cc b/gcc/rust/typecheck/rust-substitution-mapper.cc
index e1d988818bb..dc93857e60f 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.cc
+++ b/gcc/rust/typecheck/rust-substitution-mapper.cc
@@ -22,6 +22,116 @@
 namespace Rust {
 namespace Resolver {
 
+SubstMapper::SubstMapper (HirId ref, HIR::GenericArgs *generics, Location locus)
+  : resolved (new TyTy::ErrorType (ref)), generics (generics), locus (locus)
+{}
+
+TyTy::BaseType *
+SubstMapper::Resolve (TyTy::BaseType *base, Location locus,
+		      HIR::GenericArgs *generics)
+{
+  SubstMapper mapper (base->get_ref (), generics, locus);
+  base->accept_vis (mapper);
+  rust_assert (mapper.resolved != nullptr);
+  return mapper.resolved;
+}
+
+TyTy::BaseType *
+SubstMapper::InferSubst (TyTy::BaseType *base, Location locus)
+{
+  return SubstMapper::Resolve (base, locus, nullptr);
+}
+
+bool
+SubstMapper::have_generic_args () const
+{
+  return generics != nullptr;
+}
+
+void
+SubstMapper::visit (TyTy::FnType &type)
+{
+  TyTy::FnType *concrete = nullptr;
+  if (!have_generic_args ())
+    {
+      TyTy::BaseType *substs = type.infer_substitions (locus);
+      rust_assert (substs->get_kind () == TyTy::TypeKind::FNDEF);
+      concrete = static_cast<TyTy::FnType *> (substs);
+    }
+  else
+    {
+      TyTy::SubstitutionArgumentMappings mappings
+	= type.get_mappings_from_generic_args (*generics);
+      if (mappings.is_error ())
+	return;
+
+      concrete = type.handle_substitions (mappings);
+    }
+
+  if (concrete != nullptr)
+    resolved = concrete;
+}
+
+void
+SubstMapper::visit (TyTy::ADTType &type)
+{
+  TyTy::ADTType *concrete = nullptr;
+  if (!have_generic_args ())
+    {
+      TyTy::BaseType *substs = type.infer_substitions (locus);
+      rust_assert (substs->get_kind () == TyTy::TypeKind::ADT);
+      concrete = static_cast<TyTy::ADTType *> (substs);
+    }
+  else
+    {
+      TyTy::SubstitutionArgumentMappings mappings
+	= type.get_mappings_from_generic_args (*generics);
+      if (mappings.is_error ())
+	return;
+
+      concrete = type.handle_substitions (mappings);
+    }
+
+  if (concrete != nullptr)
+    resolved = concrete;
+}
+
+void
+SubstMapper::visit (TyTy::PlaceholderType &type)
+{
+  rust_assert (type.can_resolve ());
+  resolved = SubstMapper::Resolve (type.resolve (), locus, generics);
+}
+
+void
+SubstMapper::visit (TyTy::ProjectionType &type)
+{
+  TyTy::ProjectionType *concrete = nullptr;
+  if (!have_generic_args ())
+    {
+      TyTy::BaseType *substs = type.infer_substitions (locus);
+      rust_assert (substs->get_kind () == TyTy::TypeKind::PROJECTION);
+      concrete = static_cast<TyTy::ProjectionType *> (substs);
+    }
+  else
+    {
+      TyTy::SubstitutionArgumentMappings mappings
+	= type.get_mappings_from_generic_args (*generics);
+      if (mappings.is_error ())
+	return;
+
+      concrete = type.handle_substitions (mappings);
+    }
+
+  if (concrete != nullptr)
+    resolved = concrete;
+}
+
+SubstMapperInternal::SubstMapperInternal (
+  HirId ref, TyTy::SubstitutionArgumentMappings &mappings)
+  : resolved (new TyTy::ErrorType (ref)), mappings (mappings)
+{}
+
 TyTy::BaseType *
 SubstMapperInternal::Resolve (TyTy::BaseType *base,
 			      TyTy::SubstitutionArgumentMappings &mappings)
@@ -73,5 +183,238 @@ SubstMapperInternal::mappings_are_bound (
   return false;
 }
 
+void
+SubstMapperInternal::visit (TyTy::FnType &type)
+{
+  TyTy::SubstitutionArgumentMappings adjusted
+    = type.adjust_mappings_for_this (mappings);
+  if (adjusted.is_error ())
+    return;
+
+  TyTy::BaseType *concrete = type.handle_substitions (adjusted);
+  if (concrete != nullptr)
+    resolved = concrete;
+}
+
+void
+SubstMapperInternal::visit (TyTy::ADTType &type)
+{
+  TyTy::SubstitutionArgumentMappings adjusted
+    = type.adjust_mappings_for_this (mappings);
+  if (adjusted.is_error ())
+    return;
+
+  TyTy::BaseType *concrete = type.handle_substitions (adjusted);
+  if (concrete != nullptr)
+    resolved = concrete;
+}
+
+// these don't support generic arguments but might contain a type param
+void
+SubstMapperInternal::visit (TyTy::TupleType &type)
+{
+  resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::ReferenceType &type)
+{
+  resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::PointerType &type)
+{
+  resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::ParamType &type)
+{
+  resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::PlaceholderType &type)
+{
+  rust_assert (type.can_resolve ());
+  if (mappings.trait_item_mode ())
+    {
+      resolved = type.resolve ();
+    }
+  else
+    {
+      resolved = SubstMapperInternal::Resolve (type.resolve (), mappings);
+    }
+}
+
+void
+SubstMapperInternal::visit (TyTy::ProjectionType &type)
+{
+  resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::ClosureType &type)
+{
+  resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::ArrayType &type)
+{
+  resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::SliceType &type)
+{
+  resolved = type.handle_substitions (mappings);
+}
+
+// nothing to do for these
+void
+SubstMapperInternal::visit (TyTy::InferType &type)
+{
+  resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::FnPtr &type)
+{
+  resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::BoolType &type)
+{
+  resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::IntType &type)
+{
+  resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::UintType &type)
+{
+  resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::FloatType &type)
+{
+  resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::USizeType &type)
+{
+  resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::ISizeType &type)
+{
+  resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::ErrorType &type)
+{
+  resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::CharType &type)
+{
+  resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::StrType &type)
+{
+  resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::NeverType &type)
+{
+  resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::DynamicObjectType &type)
+{
+  resolved = type.clone ();
+}
+
+// SubstMapperFromExisting
+
+SubstMapperFromExisting::SubstMapperFromExisting (TyTy::BaseType *concrete,
+						  TyTy::BaseType *receiver)
+  : concrete (concrete), receiver (receiver), resolved (nullptr)
+{}
+
+TyTy::BaseType *
+SubstMapperFromExisting::Resolve (TyTy::BaseType *concrete,
+				  TyTy::BaseType *receiver)
+{
+  rust_assert (concrete->get_kind () == receiver->get_kind ());
+
+  SubstMapperFromExisting mapper (concrete, receiver);
+  concrete->accept_vis (mapper);
+  return mapper.resolved;
+}
+
+void
+SubstMapperFromExisting::visit (TyTy::FnType &type)
+{
+  rust_assert (type.was_substituted ());
+
+  TyTy::FnType *to_sub = static_cast<TyTy::FnType *> (receiver);
+  resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
+}
+
+void
+SubstMapperFromExisting::visit (TyTy::ADTType &type)
+{
+  rust_assert (type.was_substituted ());
+
+  TyTy::ADTType *to_sub = static_cast<TyTy::ADTType *> (receiver);
+  resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
+}
+
+void
+SubstMapperFromExisting::visit (TyTy::ClosureType &type)
+{
+  rust_assert (type.was_substituted ());
+
+  TyTy::ClosureType *to_sub = static_cast<TyTy::ClosureType *> (receiver);
+  resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
+}
+
+// GetUsedSubstArgs
+
+GetUsedSubstArgs::GetUsedSubstArgs ()
+  : args (TyTy::SubstitutionArgumentMappings::error ())
+{}
+
+TyTy::SubstitutionArgumentMappings
+GetUsedSubstArgs::From (const TyTy::BaseType *from)
+{
+  GetUsedSubstArgs mapper;
+  from->accept_vis (mapper);
+  return mapper.args;
+}
+
+void
+GetUsedSubstArgs::visit (const TyTy::FnType &type)
+{
+  args = type.get_substitution_arguments ();
+}
+
+void
+GetUsedSubstArgs::visit (const TyTy::ADTType &type)
+{
+  args = type.get_substitution_arguments ();
+}
+
+void
+GetUsedSubstArgs::visit (const TyTy::ClosureType &type)
+{
+  args = type.get_substitution_arguments ();
+}
+
 } // namespace Resolver
 } // namespace Rust
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h
index 995d9c88ec4..43b80b36713 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.h
+++ b/gcc/rust/typecheck/rust-substitution-mapper.h
@@ -29,95 +29,16 @@ class SubstMapper : public TyTy::TyVisitor
 {
 public:
   static TyTy::BaseType *Resolve (TyTy::BaseType *base, Location locus,
-				  HIR::GenericArgs *generics = nullptr)
-  {
-    SubstMapper mapper (base->get_ref (), generics, locus);
-    base->accept_vis (mapper);
-    rust_assert (mapper.resolved != nullptr);
-    return mapper.resolved;
-  }
+				  HIR::GenericArgs *generics = nullptr);
 
-  static TyTy::BaseType *InferSubst (TyTy::BaseType *base, Location locus)
-  {
-    return SubstMapper::Resolve (base, locus, nullptr);
-  }
+  static TyTy::BaseType *InferSubst (TyTy::BaseType *base, Location locus);
 
-  bool have_generic_args () const { return generics != nullptr; }
+  bool have_generic_args () const;
 
-  void visit (TyTy::FnType &type) override
-  {
-    TyTy::FnType *concrete = nullptr;
-    if (!have_generic_args ())
-      {
-	TyTy::BaseType *substs = type.infer_substitions (locus);
-	rust_assert (substs->get_kind () == TyTy::TypeKind::FNDEF);
-	concrete = static_cast<TyTy::FnType *> (substs);
-      }
-    else
-      {
-	TyTy::SubstitutionArgumentMappings mappings
-	  = type.get_mappings_from_generic_args (*generics);
-	if (mappings.is_error ())
-	  return;
-
-	concrete = type.handle_substitions (mappings);
-      }
-
-    if (concrete != nullptr)
-      resolved = concrete;
-  }
-
-  void visit (TyTy::ADTType &type) override
-  {
-    TyTy::ADTType *concrete = nullptr;
-    if (!have_generic_args ())
-      {
-	TyTy::BaseType *substs = type.infer_substitions (locus);
-	rust_assert (substs->get_kind () == TyTy::TypeKind::ADT);
-	concrete = static_cast<TyTy::ADTType *> (substs);
-      }
-    else
-      {
-	TyTy::SubstitutionArgumentMappings mappings
-	  = type.get_mappings_from_generic_args (*generics);
-	if (mappings.is_error ())
-	  return;
-
-	concrete = type.handle_substitions (mappings);
-      }
-
-    if (concrete != nullptr)
-      resolved = concrete;
-  }
-
-  void visit (TyTy::PlaceholderType &type) override
-  {
-    rust_assert (type.can_resolve ());
-    resolved = SubstMapper::Resolve (type.resolve (), locus, generics);
-  }
-
-  void visit (TyTy::ProjectionType &type) override
-  {
-    TyTy::ProjectionType *concrete = nullptr;
-    if (!have_generic_args ())
-      {
-	TyTy::BaseType *substs = type.infer_substitions (locus);
-	rust_assert (substs->get_kind () == TyTy::TypeKind::PROJECTION);
-	concrete = static_cast<TyTy::ProjectionType *> (substs);
-      }
-    else
-      {
-	TyTy::SubstitutionArgumentMappings mappings
-	  = type.get_mappings_from_generic_args (*generics);
-	if (mappings.is_error ())
-	  return;
-
-	concrete = type.handle_substitions (mappings);
-      }
-
-    if (concrete != nullptr)
-      resolved = concrete;
-  }
+  void visit (TyTy::FnType &type) override;
+  void visit (TyTy::ADTType &type) override;
+  void visit (TyTy::PlaceholderType &type) override;
+  void visit (TyTy::ProjectionType &type) override;
 
   // nothing to do for these
   void visit (TyTy::InferType &) override { gcc_unreachable (); }
@@ -142,9 +63,7 @@ public:
   void visit (TyTy::ClosureType &) override { gcc_unreachable (); }
 
 private:
-  SubstMapper (HirId ref, HIR::GenericArgs *generics, Location locus)
-    : resolved (new TyTy::ErrorType (ref)), generics (generics), locus (locus)
-  {}
+  SubstMapper (HirId ref, HIR::GenericArgs *generics, Location locus);
 
   TyTy::BaseType *resolved;
   HIR::GenericArgs *generics;
@@ -160,106 +79,33 @@ public:
   static bool mappings_are_bound (TyTy::BaseType *ty,
 				  TyTy::SubstitutionArgumentMappings &mappings);
 
-  void visit (TyTy::FnType &type) override
-  {
-    TyTy::SubstitutionArgumentMappings adjusted
-      = type.adjust_mappings_for_this (mappings);
-    if (adjusted.is_error ())
-      return;
-
-    TyTy::BaseType *concrete = type.handle_substitions (adjusted);
-    if (concrete != nullptr)
-      resolved = concrete;
-  }
-
-  void visit (TyTy::ADTType &type) override
-  {
-    TyTy::SubstitutionArgumentMappings adjusted
-      = type.adjust_mappings_for_this (mappings);
-    if (adjusted.is_error ())
-      return;
-
-    TyTy::BaseType *concrete = type.handle_substitions (adjusted);
-    if (concrete != nullptr)
-      resolved = concrete;
-  }
-
-  // these don't support generic arguments but might contain a type param
-  void visit (TyTy::TupleType &type) override
-  {
-    resolved = type.handle_substitions (mappings);
-  }
-
-  void visit (TyTy::ReferenceType &type) override
-  {
-    resolved = type.handle_substitions (mappings);
-  }
-
-  void visit (TyTy::PointerType &type) override
-  {
-    resolved = type.handle_substitions (mappings);
-  }
-
-  void visit (TyTy::ParamType &type) override
-  {
-    resolved = type.handle_substitions (mappings);
-  }
-
-  void visit (TyTy::PlaceholderType &type) override
-  {
-    rust_assert (type.can_resolve ());
-    if (mappings.trait_item_mode ())
-      {
-	resolved = type.resolve ();
-      }
-    else
-      {
-	resolved = SubstMapperInternal::Resolve (type.resolve (), mappings);
-      }
-  }
-
-  void visit (TyTy::ProjectionType &type) override
-  {
-    resolved = type.handle_substitions (mappings);
-  }
-
-  void visit (TyTy::ClosureType &type) override
-  {
-    resolved = type.handle_substitions (mappings);
-  }
-
-  void visit (TyTy::ArrayType &type) override
-  {
-    resolved = type.handle_substitions (mappings);
-  }
-
-  void visit (TyTy::SliceType &type) override
-  {
-    resolved = type.handle_substitions (mappings);
-  }
-
-  // nothing to do for these
-  void visit (TyTy::InferType &type) override { resolved = type.clone (); }
-  void visit (TyTy::FnPtr &type) override { resolved = type.clone (); }
-  void visit (TyTy::BoolType &type) override { resolved = type.clone (); }
-  void visit (TyTy::IntType &type) override { resolved = type.clone (); }
-  void visit (TyTy::UintType &type) override { resolved = type.clone (); }
-  void visit (TyTy::FloatType &type) override { resolved = type.clone (); }
-  void visit (TyTy::USizeType &type) override { resolved = type.clone (); }
-  void visit (TyTy::ISizeType &type) override { resolved = type.clone (); }
-  void visit (TyTy::ErrorType &type) override { resolved = type.clone (); }
-  void visit (TyTy::CharType &type) override { resolved = type.clone (); }
-  void visit (TyTy::StrType &type) override { resolved = type.clone (); }
-  void visit (TyTy::NeverType &type) override { resolved = type.clone (); }
-  void visit (TyTy::DynamicObjectType &type) override
-  {
-    resolved = type.clone ();
-  }
+  void visit (TyTy::FnType &type) override;
+  void visit (TyTy::ADTType &type) override;
+  void visit (TyTy::TupleType &type) override;
+  void visit (TyTy::ReferenceType &type) override;
+  void visit (TyTy::PointerType &type) override;
+  void visit (TyTy::ParamType &type) override;
+  void visit (TyTy::PlaceholderType &type) override;
+  void visit (TyTy::ProjectionType &type) override;
+  void visit (TyTy::ClosureType &type) override;
+  void visit (TyTy::ArrayType &type) override;
+  void visit (TyTy::SliceType &type) override;
+  void visit (TyTy::InferType &type) override;
+  void visit (TyTy::FnPtr &type) override;
+  void visit (TyTy::BoolType &type) override;
+  void visit (TyTy::IntType &type) override;
+  void visit (TyTy::UintType &type) override;
+  void visit (TyTy::FloatType &type) override;
+  void visit (TyTy::USizeType &type) override;
+  void visit (TyTy::ISizeType &type) override;
+  void visit (TyTy::ErrorType &type) override;
+  void visit (TyTy::CharType &type) override;
+  void visit (TyTy::StrType &type) override;
+  void visit (TyTy::NeverType &type) override;
+  void visit (TyTy::DynamicObjectType &type) override;
 
 private:
-  SubstMapperInternal (HirId ref, TyTy::SubstitutionArgumentMappings &mappings)
-    : resolved (new TyTy::ErrorType (ref)), mappings (mappings)
-  {}
+  SubstMapperInternal (HirId ref, TyTy::SubstitutionArgumentMappings &mappings);
 
   TyTy::BaseType *resolved;
   TyTy::SubstitutionArgumentMappings &mappings;
@@ -269,38 +115,11 @@ class SubstMapperFromExisting : public TyTy::TyVisitor
 {
 public:
   static TyTy::BaseType *Resolve (TyTy::BaseType *concrete,
-				  TyTy::BaseType *receiver)
-  {
-    rust_assert (concrete->get_kind () == receiver->get_kind ());
-
-    SubstMapperFromExisting mapper (concrete, receiver);
-    concrete->accept_vis (mapper);
-    return mapper.resolved;
-  }
+				  TyTy::BaseType *receiver);
 
-  void visit (TyTy::FnType &type) override
-  {
-    rust_assert (type.was_substituted ());
-
-    TyTy::FnType *to_sub = static_cast<TyTy::FnType *> (receiver);
-    resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
-  }
-
-  void visit (TyTy::ADTType &type) override
-  {
-    rust_assert (type.was_substituted ());
-
-    TyTy::ADTType *to_sub = static_cast<TyTy::ADTType *> (receiver);
-    resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
-  }
-
-  void visit (TyTy::ClosureType &type) override
-  {
-    rust_assert (type.was_substituted ());
-
-    TyTy::ClosureType *to_sub = static_cast<TyTy::ClosureType *> (receiver);
-    resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
-  }
+  void visit (TyTy::FnType &type) override;
+  void visit (TyTy::ADTType &type) override;
+  void visit (TyTy::ClosureType &type) override;
 
   void visit (TyTy::InferType &) override { gcc_unreachable (); }
   void visit (TyTy::TupleType &) override { gcc_unreachable (); }
@@ -325,40 +144,21 @@ public:
   void visit (TyTy::DynamicObjectType &) override { gcc_unreachable (); }
 
 private:
-  SubstMapperFromExisting (TyTy::BaseType *concrete, TyTy::BaseType *receiver)
-    : concrete (concrete), receiver (receiver), resolved (nullptr)
-  {}
+  SubstMapperFromExisting (TyTy::BaseType *concrete, TyTy::BaseType *receiver);
 
   TyTy::BaseType *concrete;
   TyTy::BaseType *receiver;
-
   TyTy::BaseType *resolved;
 };
 
 class GetUsedSubstArgs : public TyTy::TyConstVisitor
 {
 public:
-  static TyTy::SubstitutionArgumentMappings From (const TyTy::BaseType *from)
-  {
-    GetUsedSubstArgs mapper;
-    from->accept_vis (mapper);
-    return mapper.args;
-  }
-
-  void visit (const TyTy::FnType &type) override
-  {
-    args = type.get_substitution_arguments ();
-  }
-
-  void visit (const TyTy::ADTType &type) override
-  {
-    args = type.get_substitution_arguments ();
-  }
+  static TyTy::SubstitutionArgumentMappings From (const TyTy::BaseType *from);
 
-  void visit (const TyTy::ClosureType &type) override
-  {
-    args = type.get_substitution_arguments ();
-  }
+  void visit (const TyTy::FnType &type) override;
+  void visit (const TyTy::ADTType &type) override;
+  void visit (const TyTy::ClosureType &type) override;
 
   void visit (const TyTy::InferType &) override {}
   void visit (const TyTy::TupleType &) override {}
@@ -383,7 +183,7 @@ public:
   void visit (const TyTy::DynamicObjectType &) override {}
 
 private:
-  GetUsedSubstArgs () : args (TyTy::SubstitutionArgumentMappings::error ()) {}
+  GetUsedSubstArgs ();
 
   TyTy::SubstitutionArgumentMappings args;
 };
diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc
index 64001459b4d..aceed29ff03 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -68,7 +68,7 @@ const HIR::TypeParam &
 SubstitutionParamMapping::get_generic_param ()
 {
   return generic;
-};
+}
 
 bool
 SubstitutionParamMapping::needs_substitution () const
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 40/88] gccrs: Refactor BaseType, InferType and ErrorType impl into cc file
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (38 preceding siblings ...)
  2023-04-05 14:03 ` [committed 39/88] gccrs: Refactor all substitution mapper code implementation " arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 41/88] gccrs: Refactor PathProbe " arthur.cohen
                   ` (49 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* typecheck/rust-tyty.cc (BaseType::BaseType): refactor
	(BaseType::~BaseType): likewise
	(BaseType::get_ref): likewise
	(BaseType::set_ref): likewise
	(BaseType::get_ty_ref): likewise
	(BaseType::set_ty_ref): likewise
	(BaseType::is_equal): likewise
	(BaseType::is_unit): likewise
	(BaseType::get_kind): likewise
	(BaseType::get_combined_refs): likewise
	(BaseType::append_reference): likewise
	(BaseType::supports_substitutions): likewise
	(BaseType::has_subsititions_defined): likewise
	(BaseType::can_substitute): likewise
	(BaseType::needs_generic_substitutions): likewise
	(BaseType::contains_type_parameters): likewise
	(BaseType::get_ident): likewise
	(BaseType::get_locus): likewise
	(InferType::InferType): likewise
	(InferType::get_infer_kind): likewise
	(InferType::get_name): likewise
	(InferType::is_concrete): likewise
	(ErrorType::ErrorType): likewise
	(ErrorType::is_unit): likewise
	(ErrorType::is_concrete): likewise
	(ErrorType::get_name): likewise
	(ErrorType::monomorphized_clone): likewise
	* typecheck/rust-tyty.h (class SubstitutionArgumentMappings): likewise
---
 gcc/rust/typecheck/rust-tyty.cc | 181 ++++++++++++++++++++++++++++++++
 gcc/rust/typecheck/rust-tyty.h  |  92 ++++++----------
 2 files changed, 211 insertions(+), 62 deletions(-)

diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index b45bd99b1bd..079055e870d 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -146,6 +146,122 @@ is_primitive_type_kind (TypeKind kind)
     }
 }
 
+// BASE TYPE
+
+BaseType::BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident,
+		    std::set<HirId> refs)
+  : TypeBoundsMappings ({}), kind (kind), ref (ref), ty_ref (ty_ref),
+    combined (refs), ident (ident), mappings (Analysis::Mappings::get ())
+{}
+
+BaseType::BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident,
+		    std::vector<TypeBoundPredicate> specified_bounds,
+		    std::set<HirId> refs)
+  : TypeBoundsMappings (specified_bounds), kind (kind), ref (ref),
+    ty_ref (ty_ref), combined (refs), ident (ident),
+    mappings (Analysis::Mappings::get ())
+{}
+
+BaseType::~BaseType () {}
+
+HirId
+BaseType::get_ref () const
+{
+  return ref;
+}
+
+void
+BaseType::set_ref (HirId id)
+{
+  if (id != ref)
+    append_reference (ref);
+  ref = id;
+}
+
+HirId
+BaseType::get_ty_ref () const
+{
+  return ty_ref;
+}
+
+void
+BaseType::set_ty_ref (HirId id)
+{
+  ty_ref = id;
+}
+
+bool
+BaseType::is_equal (const BaseType &other) const
+{
+  return get_kind () == other.get_kind ();
+}
+
+bool
+BaseType::is_unit () const
+{
+  return false;
+}
+
+TypeKind
+BaseType::get_kind () const
+{
+  return kind;
+}
+
+std::set<HirId>
+BaseType::get_combined_refs () const
+{
+  return combined;
+}
+
+void
+BaseType::append_reference (HirId id)
+{
+  combined.insert (id);
+}
+
+bool
+BaseType::supports_substitutions () const
+{
+  return false;
+}
+
+bool
+BaseType::has_subsititions_defined () const
+{
+  return false;
+}
+
+bool
+BaseType::can_substitute () const
+{
+  return supports_substitutions () && has_subsititions_defined ();
+}
+
+bool
+BaseType::needs_generic_substitutions () const
+{
+  return false;
+}
+
+bool
+BaseType::contains_type_parameters () const
+{
+  return !is_concrete ();
+}
+
+const RustIdent &
+BaseType::get_ident () const
+{
+  return ident;
+}
+
+Location
+BaseType::get_locus () const
+{
+  return ident.locus;
+}
+
 bool
 BaseType::satisfies_bound (const TypeBoundPredicate &predicate) const
 {
@@ -330,6 +446,40 @@ BaseType::debug () const
 	      debug_str ().c_str ());
 }
 
+// InferType
+
+InferType::InferType (HirId ref, InferTypeKind infer_kind, Location locus,
+		      std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::INFER,
+	      {Resolver::CanonicalPath::create_empty (), locus}, refs),
+    infer_kind (infer_kind)
+{}
+
+InferType::InferType (HirId ref, HirId ty_ref, InferTypeKind infer_kind,
+		      Location locus, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::INFER,
+	      {Resolver::CanonicalPath::create_empty (), locus}, refs),
+    infer_kind (infer_kind)
+{}
+
+InferType::InferTypeKind
+InferType::get_infer_kind () const
+{
+  return infer_kind;
+}
+
+std::string
+InferType::get_name () const
+{
+  return as_string ();
+}
+
+bool
+InferType::is_concrete () const
+{
+  return true;
+}
+
 void
 InferType::accept_vis (TyVisitor &vis)
 {
@@ -435,6 +585,35 @@ InferType::default_type (BaseType **type) const
   return false;
 }
 
+// ErrorType
+
+ErrorType::ErrorType (HirId ref, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::ERROR,
+	      {Resolver::CanonicalPath::create_empty (), Location ()}, refs)
+{}
+
+ErrorType::ErrorType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::ERROR,
+	      {Resolver::CanonicalPath::create_empty (), Location ()}, refs)
+{}
+
+bool
+ErrorType::is_unit () const
+{
+  return true;
+}
+bool
+ErrorType::is_concrete () const
+{
+  return false;
+}
+
+std::string
+ErrorType::get_name () const
+{
+  return as_string ();
+}
+
 void
 ErrorType::accept_vis (TyVisitor &vis)
 {
@@ -477,6 +656,8 @@ ErrorType::monomorphized_clone () const
   return clone ();
 }
 
+// Struct Field type
+
 std::string
 StructFieldType::as_string () const
 {
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index cb30a60ae96..1a6bac3f864 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -89,20 +89,15 @@ class TyConstVisitor;
 class BaseType : public TypeBoundsMappings
 {
 public:
-  virtual ~BaseType () {}
+  virtual ~BaseType ();
 
-  HirId get_ref () const { return ref; }
+  HirId get_ref () const;
 
-  void set_ref (HirId id)
-  {
-    if (id != ref)
-      append_reference (ref);
-    ref = id;
-  }
+  void set_ref (HirId id);
 
-  HirId get_ty_ref () const { return ty_ref; }
+  HirId get_ty_ref () const;
 
-  void set_ty_ref (HirId id) { ty_ref = id; }
+  void set_ty_ref (HirId id);
 
   virtual void accept_vis (TyVisitor &vis) = 0;
 
@@ -133,10 +128,7 @@ public:
   //   ty are considered equal if they're of the same kind, and
   //     1. (For ADTs, arrays, tuples, refs) have the same underlying ty
   //     2. (For functions) have the same signature
-  virtual bool is_equal (const BaseType &other) const
-  {
-    return get_kind () == other.get_kind ();
-  }
+  virtual bool is_equal (const BaseType &other) const;
 
   bool satisfies_bound (const TypeBoundPredicate &predicate) const;
 
@@ -148,11 +140,11 @@ public:
   void inherit_bounds (
     const std::vector<TyTy::TypeBoundPredicate> &specified_bounds);
 
-  virtual bool is_unit () const { return false; }
+  virtual bool is_unit () const;
 
   virtual bool is_concrete () const = 0;
 
-  TypeKind get_kind () const { return kind; }
+  TypeKind get_kind () const;
 
   /* Returns a pointer to a clone of this. The caller is responsible for
    * releasing the memory of the returned ty. */
@@ -162,22 +154,19 @@ public:
   virtual BaseType *monomorphized_clone () const = 0;
 
   // get_combined_refs returns the chain of node refs involved in unification
-  std::set<HirId> get_combined_refs () const { return combined; }
+  std::set<HirId> get_combined_refs () const;
 
-  void append_reference (HirId id) { combined.insert (id); }
+  void append_reference (HirId id);
 
-  virtual bool supports_substitutions () const { return false; }
+  virtual bool supports_substitutions () const;
 
-  virtual bool has_subsititions_defined () const { return false; }
+  virtual bool has_subsititions_defined () const;
 
-  virtual bool can_substitute () const
-  {
-    return supports_substitutions () && has_subsititions_defined ();
-  }
+  virtual bool can_substitute () const;
 
-  virtual bool needs_generic_substitutions () const { return false; }
+  virtual bool needs_generic_substitutions () const;
 
-  bool contains_type_parameters () const { return !is_concrete (); }
+  bool contains_type_parameters () const;
 
   std::string mappings_str () const;
 
@@ -192,24 +181,17 @@ public:
   // Projections if available or error
   const BaseType *destructure () const;
 
-  const RustIdent &get_ident () const { return ident; }
+  const RustIdent &get_ident () const;
 
-  Location get_locus () const { return ident.locus; }
+  Location get_locus () const;
 
 protected:
   BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident,
-	    std::set<HirId> refs = std::set<HirId> ())
-    : TypeBoundsMappings ({}), kind (kind), ref (ref), ty_ref (ty_ref),
-      combined (refs), ident (ident), mappings (Analysis::Mappings::get ())
-  {}
+	    std::set<HirId> refs = std::set<HirId> ());
 
   BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident,
 	    std::vector<TypeBoundPredicate> specified_bounds,
-	    std::set<HirId> refs = std::set<HirId> ())
-    : TypeBoundsMappings (specified_bounds), kind (kind), ref (ref),
-      ty_ref (ty_ref), combined (refs), ident (ident),
-      mappings (Analysis::Mappings::get ())
-  {}
+	    std::set<HirId> refs = std::set<HirId> ());
 
   TypeKind kind;
   HirId ref;
@@ -231,18 +213,10 @@ public:
   };
 
   InferType (HirId ref, InferTypeKind infer_kind, Location locus,
-	     std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::INFER,
-		{Resolver::CanonicalPath::create_empty (), locus}, refs),
-      infer_kind (infer_kind)
-  {}
+	     std::set<HirId> refs = std::set<HirId> ());
 
   InferType (HirId ref, HirId ty_ref, InferTypeKind infer_kind, Location locus,
-	     std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::INFER,
-		{Resolver::CanonicalPath::create_empty (), locus}, refs),
-      infer_kind (infer_kind)
-  {}
+	     std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
@@ -256,13 +230,13 @@ public:
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
 
-  InferTypeKind get_infer_kind () const { return infer_kind; }
+  InferTypeKind get_infer_kind () const;
 
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
   bool default_type (BaseType **type) const;
 
-  bool is_concrete () const final override { return true; }
+  bool is_concrete () const final override;
 
 private:
   InferTypeKind infer_kind;
@@ -271,20 +245,15 @@ private:
 class ErrorType : public BaseType
 {
 public:
-  ErrorType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::ERROR,
-		{Resolver::CanonicalPath::create_empty (), Location ()}, refs)
-  {}
+  ErrorType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
 
-  ErrorType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::ERROR,
-		{Resolver::CanonicalPath::create_empty (), Location ()}, refs)
-  {}
+  ErrorType (HirId ref, HirId ty_ref,
+	     std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
 
-  bool is_unit () const override { return true; }
+  bool is_unit () const override;
 
   std::string as_string () const override;
 
@@ -294,12 +263,11 @@ public:
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
 
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
-  bool is_concrete () const final override { return false; }
+  bool is_concrete () const final override;
 };
 
-class SubstitutionArgumentMappings;
 class ParamType : public BaseType
 {
 public:
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 41/88] gccrs: Refactor PathProbe into cc file
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (39 preceding siblings ...)
  2023-04-05 14:03 ` [committed 40/88] gccrs: Refactor BaseType, InferType and ErrorType impl into cc file arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 42/88] gccrs: Refactor PathProbeType code into CC file arthur.cohen
                   ` (48 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* typecheck/rust-hir-path-probe.cc (PathProbeType::PathProbeType): refactor
	(PathProbeType::Probe): likewise
	(PathProbeType::visit): likewise
	(PathProbeType::process_enum_item_for_candiates): likewise
	(PathProbeType::process_impl_items_for_candidates): likewise
	(PathProbeType::is_reciever_generic): likewise
	(PathProbeImplTrait::PathProbeImplTrait): likewise
	(PathProbeImplTrait::Probe): likewise
	(PathProbeImplTrait::process_trait_impl_items_for_candidates): likewise
	* typecheck/rust-hir-path-probe.h (struct PathProbeCandidate): likewise
	* typecheck/rust-hir-trait-resolve.cc
	(PathProbeImplTrait::process_trait_impl_items_for_candidates): likewise
---
 gcc/rust/typecheck/rust-hir-path-probe.cc    | 344 +++++++++++++++++++
 gcc/rust/typecheck/rust-hir-path-probe.h     | 302 +---------------
 gcc/rust/typecheck/rust-hir-trait-resolve.cc |  22 --
 3 files changed, 360 insertions(+), 308 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-path-probe.cc b/gcc/rust/typecheck/rust-hir-path-probe.cc
index cb3270d3623..06d8920d2eb 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.cc
+++ b/gcc/rust/typecheck/rust-hir-path-probe.cc
@@ -18,10 +18,168 @@
 
 #include "rust-hir-path-probe.h"
 #include "rust-hir-type-check-item.h"
+#include "rust-hir-trait-resolve.h"
 
 namespace Rust {
 namespace Resolver {
 
+// PathProbeType
+
+PathProbeType::PathProbeType (const TyTy::BaseType *receiver,
+			      const HIR::PathIdentSegment &query,
+			      DefId specific_trait_id)
+  : TypeCheckBase (), receiver (receiver), search (query),
+    current_impl (nullptr), specific_trait_id (specific_trait_id)
+{}
+
+std::set<PathProbeCandidate>
+PathProbeType::Probe (const TyTy::BaseType *receiver,
+		      const HIR::PathIdentSegment &segment_name,
+		      bool probe_impls, bool probe_bounds,
+		      bool ignore_mandatory_trait_items,
+		      DefId specific_trait_id)
+{
+  PathProbeType probe (receiver, segment_name, specific_trait_id);
+  if (probe_impls)
+    {
+      if (receiver->get_kind () == TyTy::TypeKind::ADT)
+	{
+	  const TyTy::ADTType *adt
+	    = static_cast<const TyTy::ADTType *> (receiver);
+	  if (adt->is_enum ())
+	    probe.process_enum_item_for_candiates (adt);
+	}
+
+      probe.process_impl_items_for_candidates ();
+    }
+
+  if (!probe_bounds)
+    return probe.candidates;
+
+  if (!probe.is_reciever_generic ())
+    {
+      std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> probed_bounds
+	= TypeBoundsProbe::Probe (receiver);
+      for (auto &candidate : probed_bounds)
+	{
+	  const TraitReference *trait_ref = candidate.first;
+	  if (specific_trait_id != UNKNOWN_DEFID)
+	    {
+	      if (trait_ref->get_mappings ().get_defid () != specific_trait_id)
+		continue;
+	    }
+
+	  HIR::ImplBlock *impl = candidate.second;
+	  probe.process_associated_trait_for_candidates (
+	    trait_ref, impl, ignore_mandatory_trait_items);
+	}
+    }
+
+  for (const TyTy::TypeBoundPredicate &predicate :
+       receiver->get_specified_bounds ())
+    {
+      const TraitReference *trait_ref = predicate.get ();
+      if (specific_trait_id != UNKNOWN_DEFID)
+	{
+	  if (trait_ref->get_mappings ().get_defid () != specific_trait_id)
+	    continue;
+	}
+
+      probe.process_predicate_for_candidates (predicate,
+					      ignore_mandatory_trait_items);
+    }
+
+  return probe.candidates;
+}
+
+void
+PathProbeType::visit (HIR::TypeAlias &alias)
+{
+  Identifier name = alias.get_new_type_name ();
+  if (search.as_string ().compare (name) == 0)
+    {
+      HirId tyid = alias.get_mappings ().get_hirid ();
+      TyTy::BaseType *ty = nullptr;
+      bool ok = query_type (tyid, &ty);
+      rust_assert (ok);
+
+      PathProbeCandidate::ImplItemCandidate impl_item_candidate{&alias,
+								current_impl};
+      PathProbeCandidate candidate{
+	PathProbeCandidate::CandidateType::IMPL_TYPE_ALIAS, ty,
+	alias.get_locus (), impl_item_candidate};
+      candidates.insert (std::move (candidate));
+    }
+}
+
+void
+PathProbeType::visit (HIR::ConstantItem &constant)
+{
+  Identifier name = constant.get_identifier ();
+  if (search.as_string ().compare (name) == 0)
+    {
+      HirId tyid = constant.get_mappings ().get_hirid ();
+      TyTy::BaseType *ty = nullptr;
+      bool ok = query_type (tyid, &ty);
+      rust_assert (ok);
+
+      PathProbeCandidate::ImplItemCandidate impl_item_candidate{&constant,
+								current_impl};
+      PathProbeCandidate candidate{
+	PathProbeCandidate::CandidateType::IMPL_CONST, ty,
+	constant.get_locus (), impl_item_candidate};
+      candidates.insert (std::move (candidate));
+    }
+}
+
+void
+PathProbeType::visit (HIR::Function &function)
+{
+  Identifier name = function.get_function_name ();
+  if (search.as_string ().compare (name) == 0)
+    {
+      HirId tyid = function.get_mappings ().get_hirid ();
+      TyTy::BaseType *ty = nullptr;
+      bool ok = query_type (tyid, &ty);
+      rust_assert (ok);
+
+      PathProbeCandidate::ImplItemCandidate impl_item_candidate{&function,
+								current_impl};
+      PathProbeCandidate candidate{PathProbeCandidate::CandidateType::IMPL_FUNC,
+				   ty, function.get_locus (),
+				   impl_item_candidate};
+      candidates.insert (std::move (candidate));
+    }
+}
+
+void
+PathProbeType::process_enum_item_for_candiates (const TyTy::ADTType *adt)
+{
+  if (specific_trait_id != UNKNOWN_DEFID)
+    return;
+
+  TyTy::VariantDef *v;
+  if (!adt->lookup_variant (search.as_string (), &v))
+    return;
+
+  PathProbeCandidate::EnumItemCandidate enum_item_candidate{adt, v};
+  PathProbeCandidate candidate{PathProbeCandidate::CandidateType::ENUM_VARIANT,
+			       receiver->clone (),
+			       mappings->lookup_location (adt->get_ty_ref ()),
+			       enum_item_candidate};
+  candidates.insert (std::move (candidate));
+}
+
+void
+PathProbeType::process_impl_items_for_candidates ()
+{
+  mappings->iterate_impl_items (
+    [&] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool {
+      process_impl_item_candidate (id, item, impl);
+      return true;
+    });
+}
+
 void
 PathProbeType::process_impl_item_candidate (HirId id, HIR::ImplItem *item,
 					    HIR::ImplBlock *impl)
@@ -42,5 +200,191 @@ PathProbeType::process_impl_item_candidate (HirId id, HIR::ImplItem *item,
   item->accept_vis (*this);
 }
 
+void
+PathProbeType::process_associated_trait_for_candidates (
+  const TraitReference *trait_ref, HIR::ImplBlock *impl,
+  bool ignore_mandatory_trait_items)
+{
+  const TraitItemReference *trait_item_ref = nullptr;
+  if (!trait_ref->lookup_trait_item (search.as_string (), &trait_item_ref))
+    return;
+
+  bool trait_item_needs_implementation = !trait_item_ref->is_optional ();
+  if (ignore_mandatory_trait_items && trait_item_needs_implementation)
+    return;
+
+  PathProbeCandidate::CandidateType candidate_type;
+  switch (trait_item_ref->get_trait_item_type ())
+    {
+    case TraitItemReference::TraitItemType::FN:
+      candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC;
+      break;
+    case TraitItemReference::TraitItemType::CONST:
+      candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST;
+      break;
+    case TraitItemReference::TraitItemType::TYPE:
+      candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
+      break;
+
+    case TraitItemReference::TraitItemType::ERROR:
+    default:
+      gcc_unreachable ();
+      break;
+    }
+
+  TyTy::BaseType *trait_item_tyty = trait_item_ref->get_tyty ();
+
+  // we can substitute the Self with the receiver here
+  if (trait_item_tyty->get_kind () == TyTy::TypeKind::FNDEF)
+    {
+      TyTy::FnType *fn = static_cast<TyTy::FnType *> (trait_item_tyty);
+      TyTy::SubstitutionParamMapping *param = nullptr;
+      for (auto &param_mapping : fn->get_substs ())
+	{
+	  const HIR::TypeParam &type_param = param_mapping.get_generic_param ();
+	  if (type_param.get_type_representation ().compare ("Self") == 0)
+	    {
+	      param = &param_mapping;
+	      break;
+	    }
+	}
+      rust_assert (param != nullptr);
+
+      std::vector<TyTy::SubstitutionArg> mappings;
+      mappings.push_back (TyTy::SubstitutionArg (param, receiver->clone ()));
+
+      Location locus; // FIXME
+      TyTy::SubstitutionArgumentMappings args (std::move (mappings), {}, locus);
+      trait_item_tyty = SubstMapperInternal::Resolve (trait_item_tyty, args);
+    }
+
+  PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref,
+							      trait_item_ref,
+							      impl};
+
+  PathProbeCandidate candidate{candidate_type, trait_item_tyty,
+			       trait_item_ref->get_locus (),
+			       trait_item_candidate};
+  candidates.insert (std::move (candidate));
+}
+
+void
+PathProbeType::process_predicate_for_candidates (
+  const TyTy::TypeBoundPredicate &predicate, bool ignore_mandatory_trait_items)
+{
+  const TraitReference *trait_ref = predicate.get ();
+
+  TyTy::TypeBoundPredicateItem item
+    = predicate.lookup_associated_item (search.as_string ());
+  if (item.is_error ())
+    return;
+
+  if (ignore_mandatory_trait_items && item.needs_implementation ())
+    return;
+
+  const TraitItemReference *trait_item_ref = item.get_raw_item ();
+  PathProbeCandidate::CandidateType candidate_type;
+  switch (trait_item_ref->get_trait_item_type ())
+    {
+    case TraitItemReference::TraitItemType::FN:
+      candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC;
+      break;
+    case TraitItemReference::TraitItemType::CONST:
+      candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST;
+      break;
+    case TraitItemReference::TraitItemType::TYPE:
+      candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
+      break;
+
+    case TraitItemReference::TraitItemType::ERROR:
+    default:
+      gcc_unreachable ();
+      break;
+    }
+
+  TyTy::BaseType *trait_item_tyty = item.get_tyty_for_receiver (receiver);
+  PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref,
+							      trait_item_ref,
+							      nullptr};
+  PathProbeCandidate candidate{candidate_type, trait_item_tyty,
+			       trait_item_ref->get_locus (),
+			       trait_item_candidate};
+  candidates.insert (std::move (candidate));
+}
+
+std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>>
+PathProbeType::union_bounds (
+  const std::vector<std::pair</*const*/ TraitReference *, HIR::ImplBlock *>> a,
+  const std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> b)
+  const
+{
+  std::map<DefId, std::pair<const TraitReference *, HIR::ImplBlock *>> mapper;
+  for (auto &ref : a)
+    {
+      mapper.insert ({ref.first->get_mappings ().get_defid (), ref});
+    }
+  for (auto &ref : b)
+    {
+      mapper.insert ({ref.first->get_mappings ().get_defid (), ref});
+    }
+
+  std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> union_set;
+  for (auto it = mapper.begin (); it != mapper.end (); it++)
+    {
+      union_set.push_back ({it->second.first, it->second.second});
+    }
+  return union_set;
+}
+
+bool
+PathProbeType::is_reciever_generic () const
+{
+  const TyTy::BaseType *root = receiver->get_root ();
+  bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM;
+  bool receiver_is_dyn = root->get_kind () == TyTy::TypeKind::DYNAMIC;
+  return receiver_is_type_param || receiver_is_dyn;
+}
+
+// PathProbImplTrait
+
+PathProbeImplTrait::PathProbeImplTrait (const TyTy::BaseType *receiver,
+					const HIR::PathIdentSegment &query,
+					const TraitReference *trait_reference)
+  : PathProbeType (receiver, query, UNKNOWN_DEFID),
+    trait_reference (trait_reference)
+{}
+
+std::set<PathProbeCandidate>
+PathProbeImplTrait::Probe (const TyTy::BaseType *receiver,
+			   const HIR::PathIdentSegment &segment_name,
+			   const TraitReference *trait_reference)
+{
+  PathProbeImplTrait probe (receiver, segment_name, trait_reference);
+  // iterate all impls for this trait and receiver
+  // then search for possible candidates using base class behaviours
+  probe.process_trait_impl_items_for_candidates ();
+  return probe.candidates;
+}
+
+void
+PathProbeImplTrait::process_trait_impl_items_for_candidates ()
+{
+  mappings->iterate_impl_items (
+    [&] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool {
+      // just need to check if this is an impl block for this trait the next
+      // function checks the receiver
+      if (!impl->has_trait_ref ())
+	return true;
+
+      TraitReference *resolved
+	= TraitResolver::Lookup (*(impl->get_trait_ref ().get ()));
+      if (!trait_reference->is_equal (*resolved))
+	return true;
+
+      process_impl_item_candidate (id, item, impl);
+      return true;
+    });
+}
+
 } // namespace Resolver
 } // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h
index bb8698ce0e1..783282a0dc9 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.h
+++ b/gcc/rust/typecheck/rust-hir-path-probe.h
@@ -152,7 +152,7 @@ struct PathProbeCandidate
     return UNKNOWN_DEFID;
   }
 
-  bool operator< (const PathProbeCandidate &c) const
+  bool operator<(const PathProbeCandidate &c) const
   {
     return get_defid () < c.get_defid ();
   }
@@ -165,144 +165,16 @@ public:
   Probe (const TyTy::BaseType *receiver,
 	 const HIR::PathIdentSegment &segment_name, bool probe_impls,
 	 bool probe_bounds, bool ignore_mandatory_trait_items,
-	 DefId specific_trait_id = UNKNOWN_DEFID)
-  {
-    PathProbeType probe (receiver, segment_name, specific_trait_id);
-    if (probe_impls)
-      {
-	if (receiver->get_kind () == TyTy::TypeKind::ADT)
-	  {
-	    const TyTy::ADTType *adt
-	      = static_cast<const TyTy::ADTType *> (receiver);
-	    if (adt->is_enum ())
-	      probe.process_enum_item_for_candiates (adt);
-	  }
-
-	probe.process_impl_items_for_candidates ();
-      }
+	 DefId specific_trait_id = UNKNOWN_DEFID);
 
-    if (!probe_bounds)
-      return probe.candidates;
-
-    if (!probe.is_reciever_generic ())
-      {
-	std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> probed_bounds
-	  = TypeBoundsProbe::Probe (receiver);
-	for (auto &candidate : probed_bounds)
-	  {
-	    const TraitReference *trait_ref = candidate.first;
-	    if (specific_trait_id != UNKNOWN_DEFID)
-	      {
-		if (trait_ref->get_mappings ().get_defid ()
-		    != specific_trait_id)
-		  continue;
-	      }
-
-	    HIR::ImplBlock *impl = candidate.second;
-	    probe.process_associated_trait_for_candidates (
-	      trait_ref, impl, ignore_mandatory_trait_items);
-	  }
-      }
-
-    for (const TyTy::TypeBoundPredicate &predicate :
-	 receiver->get_specified_bounds ())
-      {
-	const TraitReference *trait_ref = predicate.get ();
-	if (specific_trait_id != UNKNOWN_DEFID)
-	  {
-	    if (trait_ref->get_mappings ().get_defid () != specific_trait_id)
-	      continue;
-	  }
-
-	probe.process_predicate_for_candidates (predicate,
-						ignore_mandatory_trait_items);
-      }
-
-    return probe.candidates;
-  }
-
-  void visit (HIR::TypeAlias &alias) override
-  {
-    Identifier name = alias.get_new_type_name ();
-    if (search.as_string ().compare (name) == 0)
-      {
-	HirId tyid = alias.get_mappings ().get_hirid ();
-	TyTy::BaseType *ty = nullptr;
-	bool ok = query_type (tyid, &ty);
-	rust_assert (ok);
-
-	PathProbeCandidate::ImplItemCandidate impl_item_candidate{&alias,
-								  current_impl};
-	PathProbeCandidate candidate{
-	  PathProbeCandidate::CandidateType::IMPL_TYPE_ALIAS, ty,
-	  alias.get_locus (), impl_item_candidate};
-	candidates.insert (std::move (candidate));
-      }
-  }
-
-  void visit (HIR::ConstantItem &constant) override
-  {
-    Identifier name = constant.get_identifier ();
-    if (search.as_string ().compare (name) == 0)
-      {
-	HirId tyid = constant.get_mappings ().get_hirid ();
-	TyTy::BaseType *ty = nullptr;
-	bool ok = query_type (tyid, &ty);
-	rust_assert (ok);
-
-	PathProbeCandidate::ImplItemCandidate impl_item_candidate{&constant,
-								  current_impl};
-	PathProbeCandidate candidate{
-	  PathProbeCandidate::CandidateType::IMPL_CONST, ty,
-	  constant.get_locus (), impl_item_candidate};
-	candidates.insert (std::move (candidate));
-      }
-  }
-
-  void visit (HIR::Function &function) override
-  {
-    Identifier name = function.get_function_name ();
-    if (search.as_string ().compare (name) == 0)
-      {
-	HirId tyid = function.get_mappings ().get_hirid ();
-	TyTy::BaseType *ty = nullptr;
-	bool ok = query_type (tyid, &ty);
-	rust_assert (ok);
-
-	PathProbeCandidate::ImplItemCandidate impl_item_candidate{&function,
-								  current_impl};
-	PathProbeCandidate candidate{
-	  PathProbeCandidate::CandidateType::IMPL_FUNC, ty,
-	  function.get_locus (), impl_item_candidate};
-	candidates.insert (std::move (candidate));
-      }
-  }
+  void visit (HIR::TypeAlias &alias) override;
+  void visit (HIR::ConstantItem &constant) override;
+  void visit (HIR::Function &function) override;
 
 protected:
-  void process_enum_item_for_candiates (const TyTy::ADTType *adt)
-  {
-    if (specific_trait_id != UNKNOWN_DEFID)
-      return;
-
-    TyTy::VariantDef *v;
-    if (!adt->lookup_variant (search.as_string (), &v))
-      return;
-
-    PathProbeCandidate::EnumItemCandidate enum_item_candidate{adt, v};
-    PathProbeCandidate candidate{
-      PathProbeCandidate::CandidateType::ENUM_VARIANT, receiver->clone (),
-      mappings->lookup_location (adt->get_ty_ref ()), enum_item_candidate};
-    candidates.insert (std::move (candidate));
-  }
+  void process_enum_item_for_candiates (const TyTy::ADTType *adt);
 
-  void process_impl_items_for_candidates ()
-  {
-    mappings->iterate_impl_items ([&] (HirId id, HIR::ImplItem *item,
-				       HIR::ImplBlock *impl) mutable -> bool {
-      process_impl_item_candidate (id, item, impl);
-      return true;
-    });
-  }
+  void process_impl_items_for_candidates ();
 
   void process_impl_item_candidate (HirId id, HIR::ImplItem *item,
 				    HIR::ImplBlock *impl);
@@ -310,156 +182,24 @@ protected:
   void
   process_associated_trait_for_candidates (const TraitReference *trait_ref,
 					   HIR::ImplBlock *impl,
-					   bool ignore_mandatory_trait_items)
-  {
-    const TraitItemReference *trait_item_ref = nullptr;
-    if (!trait_ref->lookup_trait_item (search.as_string (), &trait_item_ref))
-      return;
-
-    bool trait_item_needs_implementation = !trait_item_ref->is_optional ();
-    if (ignore_mandatory_trait_items && trait_item_needs_implementation)
-      return;
-
-    PathProbeCandidate::CandidateType candidate_type;
-    switch (trait_item_ref->get_trait_item_type ())
-      {
-      case TraitItemReference::TraitItemType::FN:
-	candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC;
-	break;
-      case TraitItemReference::TraitItemType::CONST:
-	candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST;
-	break;
-      case TraitItemReference::TraitItemType::TYPE:
-	candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
-	break;
-
-      case TraitItemReference::TraitItemType::ERROR:
-      default:
-	gcc_unreachable ();
-	break;
-      }
-
-    TyTy::BaseType *trait_item_tyty = trait_item_ref->get_tyty ();
-
-    // we can substitute the Self with the receiver here
-    if (trait_item_tyty->get_kind () == TyTy::TypeKind::FNDEF)
-      {
-	TyTy::FnType *fn = static_cast<TyTy::FnType *> (trait_item_tyty);
-	TyTy::SubstitutionParamMapping *param = nullptr;
-	for (auto &param_mapping : fn->get_substs ())
-	  {
-	    const HIR::TypeParam &type_param
-	      = param_mapping.get_generic_param ();
-	    if (type_param.get_type_representation ().compare ("Self") == 0)
-	      {
-		param = &param_mapping;
-		break;
-	      }
-	  }
-	rust_assert (param != nullptr);
-
-	std::vector<TyTy::SubstitutionArg> mappings;
-	mappings.push_back (TyTy::SubstitutionArg (param, receiver->clone ()));
-
-	Location locus; // FIXME
-	TyTy::SubstitutionArgumentMappings args (std::move (mappings), {},
-						 locus);
-	trait_item_tyty = SubstMapperInternal::Resolve (trait_item_tyty, args);
-      }
-
-    PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref,
-								trait_item_ref,
-								impl};
-
-    PathProbeCandidate candidate{candidate_type, trait_item_tyty,
-				 trait_item_ref->get_locus (),
-				 trait_item_candidate};
-    candidates.insert (std::move (candidate));
-  }
+					   bool ignore_mandatory_trait_items);
 
   void
   process_predicate_for_candidates (const TyTy::TypeBoundPredicate &predicate,
-				    bool ignore_mandatory_trait_items)
-  {
-    const TraitReference *trait_ref = predicate.get ();
-
-    TyTy::TypeBoundPredicateItem item
-      = predicate.lookup_associated_item (search.as_string ());
-    if (item.is_error ())
-      return;
-
-    if (ignore_mandatory_trait_items && item.needs_implementation ())
-      return;
-
-    const TraitItemReference *trait_item_ref = item.get_raw_item ();
-    PathProbeCandidate::CandidateType candidate_type;
-    switch (trait_item_ref->get_trait_item_type ())
-      {
-      case TraitItemReference::TraitItemType::FN:
-	candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC;
-	break;
-      case TraitItemReference::TraitItemType::CONST:
-	candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST;
-	break;
-      case TraitItemReference::TraitItemType::TYPE:
-	candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
-	break;
-
-      case TraitItemReference::TraitItemType::ERROR:
-      default:
-	gcc_unreachable ();
-	break;
-      }
-
-    TyTy::BaseType *trait_item_tyty = item.get_tyty_for_receiver (receiver);
-    PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref,
-								trait_item_ref,
-								nullptr};
-    PathProbeCandidate candidate{candidate_type, trait_item_tyty,
-				 trait_item_ref->get_locus (),
-				 trait_item_candidate};
-    candidates.insert (std::move (candidate));
-  }
+				    bool ignore_mandatory_trait_items);
 
 protected:
   PathProbeType (const TyTy::BaseType *receiver,
-		 const HIR::PathIdentSegment &query, DefId specific_trait_id)
-    : TypeCheckBase (), receiver (receiver), search (query),
-      current_impl (nullptr), specific_trait_id (specific_trait_id)
-  {}
+		 const HIR::PathIdentSegment &query, DefId specific_trait_id);
 
   std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>>
   union_bounds (
     const std::vector<std::pair</*const*/ TraitReference *, HIR::ImplBlock *>>
       a,
     const std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> b)
-    const
-  {
-    std::map<DefId, std::pair<const TraitReference *, HIR::ImplBlock *>> mapper;
-    for (auto &ref : a)
-      {
-	mapper.insert ({ref.first->get_mappings ().get_defid (), ref});
-      }
-    for (auto &ref : b)
-      {
-	mapper.insert ({ref.first->get_mappings ().get_defid (), ref});
-      }
-
-    std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> union_set;
-    for (auto it = mapper.begin (); it != mapper.end (); it++)
-      {
-	union_set.push_back ({it->second.first, it->second.second});
-      }
-    return union_set;
-  }
+    const;
 
-  bool is_reciever_generic () const
-  {
-    const TyTy::BaseType *root = receiver->get_root ();
-    bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM;
-    bool receiver_is_dyn = root->get_kind () == TyTy::TypeKind::DYNAMIC;
-    return receiver_is_type_param || receiver_is_dyn;
-  }
+  bool is_reciever_generic () const;
 
   const TyTy::BaseType *receiver;
   const HIR::PathIdentSegment &search;
@@ -489,24 +229,14 @@ public:
   static std::set<PathProbeCandidate>
   Probe (const TyTy::BaseType *receiver,
 	 const HIR::PathIdentSegment &segment_name,
-	 const TraitReference *trait_reference)
-  {
-    PathProbeImplTrait probe (receiver, segment_name, trait_reference);
-    // iterate all impls for this trait and receiver
-    // then search for possible candidates using base class behaviours
-    probe.process_trait_impl_items_for_candidates ();
-    return probe.candidates;
-  }
+	 const TraitReference *trait_reference);
 
 private:
-  void process_trait_impl_items_for_candidates ();
-
   PathProbeImplTrait (const TyTy::BaseType *receiver,
 		      const HIR::PathIdentSegment &query,
-		      const TraitReference *trait_reference)
-    : PathProbeType (receiver, query, UNKNOWN_DEFID),
-      trait_reference (trait_reference)
-  {}
+		      const TraitReference *trait_reference);
+
+  void process_trait_impl_items_for_candidates ();
 
   const TraitReference *trait_reference;
 };
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index 85cad8e9c21..19f95ca4488 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -594,27 +594,5 @@ TraitItemReference::is_object_safe () const
   return false;
 }
 
-// rust-hir-path-probe.h
-
-void
-PathProbeImplTrait::process_trait_impl_items_for_candidates ()
-{
-  mappings->iterate_impl_items (
-    [&] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool {
-      // just need to check if this is an impl block for this trait the next
-      // function checks the receiver
-      if (!impl->has_trait_ref ())
-	return true;
-
-      TraitReference *resolved
-	= TraitResolver::Lookup (*(impl->get_trait_ref ().get ()));
-      if (!trait_reference->is_equal (*resolved))
-	return true;
-
-      process_impl_item_candidate (id, item, impl);
-      return true;
-    });
-}
-
 } // namespace Resolver
 } // namespace Rust
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 42/88] gccrs: Refactor PathProbeType code into CC file
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (40 preceding siblings ...)
  2023-04-05 14:03 ` [committed 41/88] gccrs: Refactor PathProbe " arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 43/88] gccrs: Refactor all code out of the rust-tyty.h header arthur.cohen
                   ` (47 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* typecheck/rust-hir-path-probe.cc (PathProbeCandidate::Candidate::Candidate): refactor
	(PathProbeCandidate::PathProbeCandidate): likewise
	(PathProbeCandidate::as_string): likewise
	(PathProbeCandidate::is_enum_candidate): likewise
	(PathProbeCandidate::is_impl_candidate): likewise
	(PathProbeCandidate::is_trait_candidate): likewise
	(PathProbeCandidate::is_full_trait_item_candidate): likewise
	(PathProbeCandidate::get_error): likewise
	(PathProbeCandidate::is_error): likewise
	(PathProbeCandidate::get_defid): likewise
	(PathProbeCandidate::operator<): likewise
	* typecheck/rust-hir-path-probe.h (struct PathProbeCandidate): likewise
---
 gcc/rust/typecheck/rust-hir-path-probe.cc | 109 ++++++++++++++++++++++
 gcc/rust/typecheck/rust-hir-path-probe.h  |  82 +++-------------
 2 files changed, 124 insertions(+), 67 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-path-probe.cc b/gcc/rust/typecheck/rust-hir-path-probe.cc
index 06d8920d2eb..be89ceb8645 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.cc
+++ b/gcc/rust/typecheck/rust-hir-path-probe.cc
@@ -23,6 +23,115 @@
 namespace Rust {
 namespace Resolver {
 
+// PathProbeCandidate
+
+PathProbeCandidate::Candidate::Candidate (EnumItemCandidate enum_field)
+  : enum_field (enum_field)
+{}
+
+PathProbeCandidate::Candidate::Candidate (ImplItemCandidate impl) : impl (impl)
+{}
+
+PathProbeCandidate::Candidate::Candidate (TraitItemCandidate trait)
+  : trait (trait)
+{}
+
+PathProbeCandidate::PathProbeCandidate (CandidateType type, TyTy::BaseType *ty,
+					Location locus,
+					EnumItemCandidate enum_field)
+  : type (type), ty (ty), locus (locus), item (enum_field)
+{}
+
+PathProbeCandidate::PathProbeCandidate (CandidateType type, TyTy::BaseType *ty,
+					Location locus, ImplItemCandidate impl)
+  : type (type), ty (ty), locus (locus), item (impl)
+{}
+
+PathProbeCandidate::PathProbeCandidate (CandidateType type, TyTy::BaseType *ty,
+					Location locus,
+					TraitItemCandidate trait)
+  : type (type), ty (ty), locus (locus), item (trait)
+{}
+
+std::string
+PathProbeCandidate::as_string () const
+{
+  return "PathProbe candidate TODO - as_string";
+}
+
+bool
+PathProbeCandidate::is_enum_candidate () const
+{
+  return type == ENUM_VARIANT;
+}
+
+bool
+PathProbeCandidate::is_impl_candidate () const
+{
+  return type == IMPL_CONST || type == IMPL_TYPE_ALIAS || type == IMPL_FUNC;
+}
+
+bool
+PathProbeCandidate::is_trait_candidate () const
+{
+  return type == TRAIT_ITEM_CONST || type == TRAIT_TYPE_ALIAS
+	 || type == TRAIT_FUNC;
+}
+
+bool
+PathProbeCandidate::is_full_trait_item_candidate () const
+{
+  return is_trait_candidate () && item.trait.impl == nullptr;
+}
+
+PathProbeCandidate
+PathProbeCandidate::get_error ()
+{
+  return PathProbeCandidate (ERROR, nullptr, Location (),
+			     ImplItemCandidate{nullptr, nullptr});
+}
+
+bool
+PathProbeCandidate::is_error () const
+{
+  return type == ERROR;
+}
+
+DefId
+PathProbeCandidate::get_defid () const
+{
+  switch (type)
+    {
+    case ENUM_VARIANT:
+      return item.enum_field.variant->get_defid ();
+      break;
+
+    case IMPL_CONST:
+    case IMPL_TYPE_ALIAS:
+    case IMPL_FUNC:
+      return item.impl.impl_item->get_impl_mappings ().get_defid ();
+      break;
+
+    case TRAIT_ITEM_CONST:
+    case TRAIT_TYPE_ALIAS:
+    case TRAIT_FUNC:
+      return item.trait.item_ref->get_mappings ().get_defid ();
+      break;
+
+    case ERROR:
+    default:
+      return UNKNOWN_DEFID;
+    }
+
+  return UNKNOWN_DEFID;
+}
+
+bool
+PathProbeCandidate::operator< (const PathProbeCandidate &c) const
+{
+  return get_defid () < c.get_defid ();
+}
+
 // PathProbeType
 
 PathProbeType::PathProbeType (const TyTy::BaseType *receiver,
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h
index 783282a0dc9..dd511ac4184 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.h
+++ b/gcc/rust/typecheck/rust-hir-path-probe.h
@@ -73,89 +73,37 @@ struct PathProbeCandidate
     ImplItemCandidate impl;
     TraitItemCandidate trait;
 
-    Candidate (EnumItemCandidate enum_field) : enum_field (enum_field) {}
-    Candidate (ImplItemCandidate impl) : impl (impl) {}
-    Candidate (TraitItemCandidate trait) : trait (trait) {}
+    Candidate (EnumItemCandidate enum_field);
+    Candidate (ImplItemCandidate impl);
+    Candidate (TraitItemCandidate trait);
   } item;
 
   PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, Location locus,
-		      EnumItemCandidate enum_field)
-    : type (type), ty (ty), locus (locus), item (enum_field)
-  {}
+		      EnumItemCandidate enum_field);
 
   PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, Location locus,
-		      ImplItemCandidate impl)
-    : type (type), ty (ty), locus (locus), item (impl)
-  {}
+		      ImplItemCandidate impl);
 
   PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, Location locus,
-		      TraitItemCandidate trait)
-    : type (type), ty (ty), locus (locus), item (trait)
-  {}
+		      TraitItemCandidate trait);
 
-  std::string as_string () const
-  {
-    return "PathProbe candidate TODO - as_string";
-  }
+  std::string as_string () const;
 
-  bool is_enum_candidate () const { return type == ENUM_VARIANT; }
+  bool is_enum_candidate () const;
 
-  bool is_impl_candidate () const
-  {
-    return type == IMPL_CONST || type == IMPL_TYPE_ALIAS || type == IMPL_FUNC;
-  }
+  bool is_impl_candidate () const;
 
-  bool is_trait_candidate () const
-  {
-    return type == TRAIT_ITEM_CONST || type == TRAIT_TYPE_ALIAS
-	   || type == TRAIT_FUNC;
-  }
+  bool is_trait_candidate () const;
 
-  bool is_full_trait_item_candidate () const
-  {
-    return is_trait_candidate () && item.trait.impl == nullptr;
-  }
+  bool is_full_trait_item_candidate () const;
 
-  static PathProbeCandidate get_error ()
-  {
-    return PathProbeCandidate (ERROR, nullptr, Location (),
-			       ImplItemCandidate{nullptr, nullptr});
-  }
+  static PathProbeCandidate get_error ();
 
-  bool is_error () const { return type == ERROR; }
+  bool is_error () const;
 
-  DefId get_defid () const
-  {
-    switch (type)
-      {
-      case ENUM_VARIANT:
-	return item.enum_field.variant->get_defid ();
-	break;
-
-      case IMPL_CONST:
-      case IMPL_TYPE_ALIAS:
-      case IMPL_FUNC:
-	return item.impl.impl_item->get_impl_mappings ().get_defid ();
-	break;
-
-      case TRAIT_ITEM_CONST:
-      case TRAIT_TYPE_ALIAS:
-      case TRAIT_FUNC:
-	return item.trait.item_ref->get_mappings ().get_defid ();
-	break;
-
-      case ERROR:
-      default:
-	return UNKNOWN_DEFID;
-      }
-
-    return UNKNOWN_DEFID;
-  }
+  DefId get_defid () const;
 
-  bool operator<(const PathProbeCandidate &c) const
-  {
-    return get_defid () < c.get_defid ();
-  }
+  bool operator< (const PathProbeCandidate &c) const;
 };
 
 class PathProbeType : public TypeCheckBase, public HIR::HIRImplVisitor
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 43/88] gccrs: Refactor all code out of the rust-tyty.h header
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (41 preceding siblings ...)
  2023-04-05 14:03 ` [committed 42/88] gccrs: Refactor PathProbeType code into CC file arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 44/88] gccrs: Rename rust-tyctx.cc to rust-typecheck-context.cc arthur.cohen
                   ` (46 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* typecheck/rust-hir-type-check.h: refactor
	* typecheck/rust-tyctx.cc (TypeCheckContext::iterate): refactor
	(TypeCheckContext::have_loop_context): likewise
	(TypeCheckContext::push_new_loop_context): likewise
	(TypeCheckContext::push_new_while_loop_context): likewise
	(TypeCheckContext::peek_loop_context): likewise
	(TypeCheckContext::pop_loop_context): likewise
	(TypeCheckContext::swap_head_loop_context): likewise
	(TypeCheckContext::insert_trait_reference): likewise
	(TypeCheckContext::lookup_trait_reference): likewise
	(TypeCheckContext::insert_receiver): likewise
	(TypeCheckContext::lookup_receiver): likewise
	(TypeCheckContext::insert_associated_type_mapping): likewise
	(TypeCheckContext::clear_associated_type_mapping): likewise
	(TypeCheckContext::lookup_associated_type_mapping): likewise
	(TypeCheckContext::insert_variant_definition): likewise
	(TypeCheckContext::lookup_variant_definition): likewise
	(TypeCheckContext::insert_operator_overload): likewise
	(TypeCheckContext::lookup_operator_overload): likewise
	(TypeCheckContext::insert_unconstrained_check_marker): likewise
	(TypeCheckContext::have_checked_for_unconstrained): likewise
	(TypeCheckContext::insert_resolved_predicate): likewise
	(TypeCheckContext::lookup_predicate): likewise
	(TypeCheckContext::insert_query): likewise
	(TypeCheckContext::query_completed): likewise
	(TypeCheckContext::query_in_progress): likewise
	(TypeCheckContext::insert_trait_query): likewise
	(TypeCheckContext::trait_query_completed): likewise
	(TypeCheckContext::trait_query_in_progress): likewise
	(TypeCheckContextItem::Item::Item): likewise
	(TypeCheckContextItem::TypeCheckContextItem): likewise
	(TypeCheckContextItem::get_item): likewise
	(TypeCheckContextItem::get_impl_item): likewise
	(TypeCheckContextItem::get_trait_item): likewise
	(TypeCheckContextItem::get_type): likewise
	* typecheck/rust-tyty.cc (StructFieldType::StructFieldType): likewise
	(StructFieldType::get_ref): likewise
	(StructFieldType::get_name): likewise
	(StructFieldType::get_field_type): likewise
	(StructFieldType::set_field_type): likewise
	(StructFieldType::is_concrete): likewise
	(StructFieldType::debug): likewise
	(StructFieldType::get_locus): likewise
	(VariantDef::variant_type_string): likewise
	(VariantDef::VariantDef): likewise
	(VariantDef::operator=): likewise
	(VariantDef::get_error_node): likewise
	(VariantDef::is_error): likewise
	(VariantDef::get_id): likewise
	(VariantDef::get_defid): likewise
	(VariantDef::get_variant_type): likewise
	(VariantDef::is_data_variant): likewise
	(VariantDef::is_dataless_variant): likewise
	(VariantDef::get_identifier): likewise
	(VariantDef::num_fields): likewise
	(VariantDef::get_field_at_index): likewise
	(VariantDef::get_fields): likewise
	(VariantDef::lookup_field): likewise
	(VariantDef::get_discriminant): likewise
	(VariantDef::as_string): likewise
	(VariantDef::is_equal): likewise
	(VariantDef::clone): likewise
	(VariantDef::monomorphized_clone): likewise
	(VariantDef::get_ident): likewise
	(TupleType::TupleType): likewise
	(TupleType::get_unit_type): likewise
	(TupleType::is_unit): likewise
	(TupleType::num_fields): likewise
	(TupleType::is_concrete): likewise
	(TupleType::get_fields): likewise
	(BoolType::BoolType): likewise
	(BoolType::get_name): likewise
	(BoolType::is_concrete): likewise
	(IntType::IntType): likewise
	(IntType::get_name): likewise
	(IntType::get_int_kind): likewise
	(IntType::is_concrete): likewise
	(UintType::UintType): likewise
	(UintType::get_name): likewise
	(UintType::get_uint_kind): likewise
	(UintType::is_concrete): likewise
	(FloatType::FloatType): likewise
	(FloatType::get_name): likewise
	(FloatType::get_float_kind): likewise
	(FloatType::is_concrete): likewise
	(USizeType::USizeType): likewise
	(USizeType::get_name): likewise
	(USizeType::is_concrete): likewise
	(ISizeType::ISizeType): likewise
	(ISizeType::get_name): likewise
	(ISizeType::is_concrete): likewise
	(CharType::CharType): likewise
	(CharType::is_concrete): likewise
	(CharType::get_name): likewise
	(ReferenceType::ReferenceType): likewise
	(ReferenceType::is_concrete): likewise
	(ReferenceType::mutability): likewise
	(ReferenceType::is_mutable): likewise
	(ReferenceType::is_dyn_object): likewise
	(ReferenceType::is_dyn_slice_type): likewise
	(ReferenceType::is_dyn_str_type): likewise
	(PointerType::PointerType): likewise
	(PointerType::is_concrete): likewise
	(PointerType::mutability): likewise
	(PointerType::is_mutable): likewise
	(PointerType::is_const): likewise
	(PointerType::is_dyn_object): likewise
	(PointerType::is_dyn_slice_type): likewise
	(PointerType::is_dyn_str_type): likewise
	(ParamType::ParamType): likewise
	(ParamType::get_generic_param): likewise
	(ParamType::can_resolve): likewise
	(ParamType::is_concrete): likewise
	(StrType::StrType): likewise
	(StrType::get_name): likewise
	(StrType::is_concrete): likewise
	(NeverType::NeverType): likewise
	(NeverType::get_name): likewise
	(NeverType::is_unit): likewise
	(NeverType::is_concrete): likewise
	(PlaceholderType::PlaceholderType): likewise
	(PlaceholderType::get_name): likewise
	(PlaceholderType::is_unit): likewise
	(PlaceholderType::get_symbol): likewise
	(PlaceholderType::is_concrete): likewise
	(ProjectionType::is_unit): likewise
	(ProjectionType::get_name): likewise
	(ProjectionType::needs_generic_substitutions): likewise
	(ProjectionType::supports_substitutions): likewise
	(ProjectionType::has_subsititions_defined): likewise
	(ProjectionType::get): likewise
	(ProjectionType::is_concrete): likewise
	(DynamicObjectType::is_concrete): likewise
	* typecheck/rust-tyty.h: likewise
---
 gcc/rust/typecheck/rust-hir-type-check.h | 332 ++------
 gcc/rust/typecheck/rust-tyctx.cc         | 379 +++++++++
 gcc/rust/typecheck/rust-tyty.cc          | 960 ++++++++++++++++++++++-
 gcc/rust/typecheck/rust-tyty.h           | 667 +++-------------
 4 files changed, 1508 insertions(+), 830 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index adec2f91961..d1eb750a621 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -38,37 +38,17 @@ public:
     TRAIT_ITEM,
   };
 
-  TypeCheckContextItem (HIR::Function *item)
-    : type (ItemType::ITEM), item (item)
-  {}
+  TypeCheckContextItem (HIR::Function *item);
+  TypeCheckContextItem (HIR::ImplBlock *impl_block, HIR::Function *item);
+  TypeCheckContextItem (HIR::TraitItemFunc *trait_item);
 
-  TypeCheckContextItem (HIR::ImplBlock *impl_block, HIR::Function *item)
-    : type (ItemType::IMPL_ITEM), item (impl_block, item)
-  {}
+  ItemType get_type () const;
 
-  TypeCheckContextItem (HIR::TraitItemFunc *trait_item)
-    : type (ItemType::TRAIT_ITEM), item (trait_item)
-  {}
+  HIR::Function *get_item ();
 
-  ItemType get_type () const { return type; }
+  std::pair<HIR::ImplBlock *, HIR::Function *> &get_impl_item ();
 
-  HIR::Function *get_item ()
-  {
-    rust_assert (get_type () == ItemType::ITEM);
-    return item.item;
-  }
-
-  std::pair<HIR::ImplBlock *, HIR::Function *> &get_impl_item ()
-  {
-    rust_assert (get_type () == ItemType::IMPL_ITEM);
-    return item.impl_item;
-  };
-
-  HIR::TraitItemFunc *get_trait_item ()
-  {
-    rust_assert (get_type () == ItemType::TRAIT_ITEM);
-    return item.trait_item;
-  }
+  HIR::TraitItemFunc *get_trait_item ();
 
   TyTy::FnType *get_context_type ();
 
@@ -79,13 +59,9 @@ private:
     std::pair<HIR::ImplBlock *, HIR::Function *> impl_item;
     HIR::TraitItemFunc *trait_item;
 
-    Item (HIR::Function *item) : item (item) {}
-
-    Item (HIR::ImplBlock *impl_block, HIR::Function *item)
-      : impl_item ({impl_block, item})
-    {}
-
-    Item (HIR::TraitItemFunc *trait_item) : trait_item (trait_item) {}
+    Item (HIR::Function *item);
+    Item (HIR::ImplBlock *impl_block, HIR::Function *item);
+    Item (HIR::TraitItemFunc *trait_item);
   };
 
   ItemType type;
@@ -118,283 +94,71 @@ public:
   void push_return_type (TypeCheckContextItem item,
 			 TyTy::BaseType *return_type);
   void pop_return_type ();
+  void iterate (std::function<bool (HirId, TyTy::BaseType *)> cb);
 
-  void iterate (std::function<bool (HirId, TyTy::BaseType *)> cb)
-  {
-    for (auto it = resolved.begin (); it != resolved.end (); it++)
-      {
-	if (!cb (it->first, it->second))
-	  return;
-      }
-  }
-
-  bool have_loop_context () const { return !loop_type_stack.empty (); }
-
-  void push_new_loop_context (HirId id, Location locus)
-  {
-    TyTy::BaseType *infer_var
-      = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL,
-			     locus);
-    loop_type_stack.push_back (infer_var);
-  }
-
-  void push_new_while_loop_context (HirId id)
-  {
-    TyTy::BaseType *infer_var = new TyTy::ErrorType (id);
-    loop_type_stack.push_back (infer_var);
-  }
-
-  TyTy::BaseType *peek_loop_context () { return loop_type_stack.back (); }
-
-  TyTy::BaseType *pop_loop_context ()
-  {
-    auto back = peek_loop_context ();
-    loop_type_stack.pop_back ();
-    return back;
-  }
-
-  void swap_head_loop_context (TyTy::BaseType *val)
-  {
-    loop_type_stack.pop_back ();
-    loop_type_stack.push_back (val);
-  }
-
-  void insert_trait_reference (DefId id, TraitReference &&ref)
-  {
-    rust_assert (trait_context.find (id) == trait_context.end ());
-    trait_context.emplace (id, std::move (ref));
-  }
-
-  bool lookup_trait_reference (DefId id, TraitReference **ref)
-  {
-    auto it = trait_context.find (id);
-    if (it == trait_context.end ())
-      return false;
+  bool have_loop_context () const;
+  void push_new_loop_context (HirId id, Location locus);
+  void push_new_while_loop_context (HirId id);
+  TyTy::BaseType *peek_loop_context ();
+  TyTy::BaseType *pop_loop_context ();
 
-    *ref = &it->second;
-    return true;
-  }
-
-  void insert_receiver (HirId id, TyTy::BaseType *t)
-  {
-    receiver_context[id] = t;
-  }
+  void swap_head_loop_context (TyTy::BaseType *val);
 
-  bool lookup_receiver (HirId id, TyTy::BaseType **ref)
-  {
-    auto it = receiver_context.find (id);
-    if (it == receiver_context.end ())
-      return false;
+  void insert_trait_reference (DefId id, TraitReference &&ref);
+  bool lookup_trait_reference (DefId id, TraitReference **ref);
 
-    *ref = it->second;
-    return true;
-  }
+  void insert_receiver (HirId id, TyTy::BaseType *t);
+  bool lookup_receiver (HirId id, TyTy::BaseType **ref);
 
-  void insert_associated_trait_impl (HirId id, AssociatedImplTrait &&associated)
-  {
-    rust_assert (associated_impl_traits.find (id)
-		 == associated_impl_traits.end ());
-    associated_impl_traits.emplace (id, std::move (associated));
-  }
+  void insert_associated_trait_impl (HirId id,
+				     AssociatedImplTrait &&associated);
+  bool lookup_associated_trait_impl (HirId id,
+				     AssociatedImplTrait **associated);
 
-  bool lookup_associated_trait_impl (HirId id, AssociatedImplTrait **associated)
-  {
-    auto it = associated_impl_traits.find (id);
-    if (it == associated_impl_traits.end ())
-      return false;
-
-    *associated = &it->second;
-    return true;
-  }
-
-  void insert_associated_type_mapping (HirId id, HirId mapping)
-  {
-    associated_type_mappings[id] = mapping;
-  }
-
-  void clear_associated_type_mapping (HirId id)
-  {
-    auto it = associated_type_mappings.find (id);
-    if (it != associated_type_mappings.end ())
-      associated_type_mappings.erase (it);
-  }
+  void insert_associated_type_mapping (HirId id, HirId mapping);
+  void clear_associated_type_mapping (HirId id);
 
   // lookup any associated type mappings, the out parameter of mapping is
   // allowed to be nullptr which allows this interface to do a simple does exist
   // check
-  bool lookup_associated_type_mapping (HirId id, HirId *mapping)
-  {
-    auto it = associated_type_mappings.find (id);
-    if (it == associated_type_mappings.end ())
-      return false;
-
-    if (mapping != nullptr)
-      *mapping = it->second;
-
-    return true;
-  }
+  bool lookup_associated_type_mapping (HirId id, HirId *mapping);
 
   void insert_associated_impl_mapping (HirId trait_id,
 				       const TyTy::BaseType *impl_type,
-				       HirId impl_id)
-  {
-    auto it = associated_traits_to_impls.find (trait_id);
-    if (it == associated_traits_to_impls.end ())
-      {
-	associated_traits_to_impls[trait_id] = {};
-      }
-
-    associated_traits_to_impls[trait_id].push_back ({impl_type, impl_id});
-  }
-
+				       HirId impl_id);
   bool lookup_associated_impl_mapping_for_self (HirId trait_id,
 						const TyTy::BaseType *self,
-						HirId *mapping)
-  {
-    auto it = associated_traits_to_impls.find (trait_id);
-    if (it == associated_traits_to_impls.end ())
-      return false;
-
-    for (auto &item : it->second)
-      {
-	if (item.first->can_eq (self, false))
-	  {
-	    *mapping = item.second;
-	    return true;
-	  }
-      }
-    return false;
-  }
+						HirId *mapping);
 
   void insert_autoderef_mappings (HirId id,
-				  std::vector<Adjustment> &&adjustments)
-  {
-    rust_assert (autoderef_mappings.find (id) == autoderef_mappings.end ());
-    autoderef_mappings.emplace (id, std::move (adjustments));
-  }
-
+				  std::vector<Adjustment> &&adjustments);
   bool lookup_autoderef_mappings (HirId id,
-				  std::vector<Adjustment> **adjustments)
-  {
-    auto it = autoderef_mappings.find (id);
-    if (it == autoderef_mappings.end ())
-      return false;
-
-    *adjustments = &it->second;
-    return true;
-  }
+				  std::vector<Adjustment> **adjustments);
 
   void insert_cast_autoderef_mappings (HirId id,
-				       std::vector<Adjustment> &&adjustments)
-  {
-    rust_assert (cast_autoderef_mappings.find (id)
-		 == cast_autoderef_mappings.end ());
-    cast_autoderef_mappings.emplace (id, std::move (adjustments));
-  }
-
+				       std::vector<Adjustment> &&adjustments);
   bool lookup_cast_autoderef_mappings (HirId id,
-				       std::vector<Adjustment> **adjustments)
-  {
-    auto it = cast_autoderef_mappings.find (id);
-    if (it == cast_autoderef_mappings.end ())
-      return false;
+				       std::vector<Adjustment> **adjustments);
 
-    *adjustments = &it->second;
-    return true;
-  }
+  void insert_variant_definition (HirId id, HirId variant);
+  bool lookup_variant_definition (HirId id, HirId *variant);
 
-  void insert_variant_definition (HirId id, HirId variant)
-  {
-    auto it = variants.find (id);
-    rust_assert (it == variants.end ());
+  void insert_operator_overload (HirId id, TyTy::FnType *call_site);
+  bool lookup_operator_overload (HirId id, TyTy::FnType **call);
 
-    variants[id] = variant;
-  }
+  void insert_unconstrained_check_marker (HirId id, bool status);
+  bool have_checked_for_unconstrained (HirId id, bool *result);
 
-  bool lookup_variant_definition (HirId id, HirId *variant)
-  {
-    auto it = variants.find (id);
-    if (it == variants.end ())
-      return false;
+  void insert_resolved_predicate (HirId id, TyTy::TypeBoundPredicate predicate);
+  bool lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result);
 
-    *variant = it->second;
-    return true;
-  }
-
-  void insert_operator_overload (HirId id, TyTy::FnType *call_site)
-  {
-    auto it = operator_overloads.find (id);
-    rust_assert (it == operator_overloads.end ());
-
-    operator_overloads[id] = call_site;
-  }
-
-  bool lookup_operator_overload (HirId id, TyTy::FnType **call)
-  {
-    auto it = operator_overloads.find (id);
-    if (it == operator_overloads.end ())
-      return false;
-
-    *call = it->second;
-    return true;
-  }
+  void insert_query (HirId id);
+  void query_completed (HirId id);
+  bool query_in_progress (HirId id) const;
 
-  void insert_unconstrained_check_marker (HirId id, bool status)
-  {
-    unconstrained[id] = status;
-  }
-
-  bool have_checked_for_unconstrained (HirId id, bool *result)
-  {
-    auto it = unconstrained.find (id);
-    bool found = it != unconstrained.end ();
-    if (!found)
-      return false;
-
-    *result = it->second;
-    return true;
-  }
-
-  void insert_resolved_predicate (HirId id, TyTy::TypeBoundPredicate predicate)
-  {
-    auto it = predicates.find (id);
-    rust_assert (it == predicates.end ());
-
-    predicates.insert ({id, predicate});
-  }
-
-  bool lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result)
-  {
-    auto it = predicates.find (id);
-    bool found = it != predicates.end ();
-    if (!found)
-      return false;
-
-    *result = it->second;
-    return true;
-  }
-
-  void insert_query (HirId id) { querys_in_progress.insert (id); }
-
-  void query_completed (HirId id) { querys_in_progress.erase (id); }
-
-  bool query_in_progress (HirId id) const
-  {
-    return querys_in_progress.find (id) != querys_in_progress.end ();
-  }
-
-  void insert_trait_query (DefId id) { trait_queries_in_progress.insert (id); }
-
-  void trait_query_completed (DefId id)
-  {
-    trait_queries_in_progress.erase (id);
-  }
-
-  bool trait_query_in_progress (DefId id) const
-  {
-    return trait_queries_in_progress.find (id)
-	   != trait_queries_in_progress.end ();
-  }
+  void insert_trait_query (DefId id);
+  void trait_query_completed (DefId id);
+  bool trait_query_in_progress (DefId id) const;
 
 private:
   TypeCheckContext ();
diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc
index 886842b0623..27ff96986dc 100644
--- a/gcc/rust/typecheck/rust-tyctx.cc
+++ b/gcc/rust/typecheck/rust-tyctx.cc
@@ -154,8 +154,387 @@ TypeCheckContext::peek_context ()
   return return_type_stack.back ().first;
 }
 
+void
+TypeCheckContext::iterate (std::function<bool (HirId, TyTy::BaseType *)> cb)
+{
+  for (auto it = resolved.begin (); it != resolved.end (); it++)
+    {
+      if (!cb (it->first, it->second))
+	return;
+    }
+}
+
+bool
+TypeCheckContext::have_loop_context () const
+{
+  return !loop_type_stack.empty ();
+}
+
+void
+TypeCheckContext::push_new_loop_context (HirId id, Location locus)
+{
+  TyTy::BaseType *infer_var
+    = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL, locus);
+  loop_type_stack.push_back (infer_var);
+}
+
+void
+TypeCheckContext::push_new_while_loop_context (HirId id)
+{
+  TyTy::BaseType *infer_var = new TyTy::ErrorType (id);
+  loop_type_stack.push_back (infer_var);
+}
+
+TyTy::BaseType *
+TypeCheckContext::peek_loop_context ()
+{
+  return loop_type_stack.back ();
+}
+
+TyTy::BaseType *
+TypeCheckContext::pop_loop_context ()
+{
+  auto back = peek_loop_context ();
+  loop_type_stack.pop_back ();
+  return back;
+}
+
+void
+TypeCheckContext::swap_head_loop_context (TyTy::BaseType *val)
+{
+  loop_type_stack.pop_back ();
+  loop_type_stack.push_back (val);
+}
+
+void
+TypeCheckContext::insert_trait_reference (DefId id, TraitReference &&ref)
+{
+  rust_assert (trait_context.find (id) == trait_context.end ());
+  trait_context.emplace (id, std::move (ref));
+}
+
+bool
+TypeCheckContext::lookup_trait_reference (DefId id, TraitReference **ref)
+{
+  auto it = trait_context.find (id);
+  if (it == trait_context.end ())
+    return false;
+
+  *ref = &it->second;
+  return true;
+}
+
+void
+TypeCheckContext::insert_receiver (HirId id, TyTy::BaseType *t)
+{
+  receiver_context[id] = t;
+}
+
+bool
+TypeCheckContext::lookup_receiver (HirId id, TyTy::BaseType **ref)
+{
+  auto it = receiver_context.find (id);
+  if (it == receiver_context.end ())
+    return false;
+
+  *ref = it->second;
+  return true;
+}
+
+void
+TypeCheckContext::insert_associated_trait_impl (
+  HirId id, AssociatedImplTrait &&associated)
+{
+  rust_assert (associated_impl_traits.find (id)
+	       == associated_impl_traits.end ());
+  associated_impl_traits.emplace (id, std::move (associated));
+}
+
+bool
+TypeCheckContext::lookup_associated_trait_impl (
+  HirId id, AssociatedImplTrait **associated)
+{
+  auto it = associated_impl_traits.find (id);
+  if (it == associated_impl_traits.end ())
+    return false;
+
+  *associated = &it->second;
+  return true;
+}
+
+void
+TypeCheckContext::insert_associated_type_mapping (HirId id, HirId mapping)
+{
+  associated_type_mappings[id] = mapping;
+}
+
+void
+TypeCheckContext::clear_associated_type_mapping (HirId id)
+{
+  auto it = associated_type_mappings.find (id);
+  if (it != associated_type_mappings.end ())
+    associated_type_mappings.erase (it);
+}
+
+// lookup any associated type mappings, the out parameter of mapping is
+// allowed to be nullptr which allows this interface to do a simple does exist
+// check
+bool
+TypeCheckContext::lookup_associated_type_mapping (HirId id, HirId *mapping)
+{
+  auto it = associated_type_mappings.find (id);
+  if (it == associated_type_mappings.end ())
+    return false;
+
+  if (mapping != nullptr)
+    *mapping = it->second;
+
+  return true;
+}
+
+void
+TypeCheckContext::insert_associated_impl_mapping (
+  HirId trait_id, const TyTy::BaseType *impl_type, HirId impl_id)
+{
+  auto it = associated_traits_to_impls.find (trait_id);
+  if (it == associated_traits_to_impls.end ())
+    {
+      associated_traits_to_impls[trait_id] = {};
+    }
+
+  associated_traits_to_impls[trait_id].push_back ({impl_type, impl_id});
+}
+
+bool
+TypeCheckContext::lookup_associated_impl_mapping_for_self (
+  HirId trait_id, const TyTy::BaseType *self, HirId *mapping)
+{
+  auto it = associated_traits_to_impls.find (trait_id);
+  if (it == associated_traits_to_impls.end ())
+    return false;
+
+  for (auto &item : it->second)
+    {
+      if (item.first->can_eq (self, false))
+	{
+	  *mapping = item.second;
+	  return true;
+	}
+    }
+  return false;
+}
+
+void
+TypeCheckContext::insert_autoderef_mappings (
+  HirId id, std::vector<Adjustment> &&adjustments)
+{
+  rust_assert (autoderef_mappings.find (id) == autoderef_mappings.end ());
+  autoderef_mappings.emplace (id, std::move (adjustments));
+}
+
+bool
+TypeCheckContext::lookup_autoderef_mappings (
+  HirId id, std::vector<Adjustment> **adjustments)
+{
+  auto it = autoderef_mappings.find (id);
+  if (it == autoderef_mappings.end ())
+    return false;
+
+  *adjustments = &it->second;
+  return true;
+}
+
+void
+TypeCheckContext::insert_cast_autoderef_mappings (
+  HirId id, std::vector<Adjustment> &&adjustments)
+{
+  rust_assert (cast_autoderef_mappings.find (id)
+	       == cast_autoderef_mappings.end ());
+  cast_autoderef_mappings.emplace (id, std::move (adjustments));
+}
+
+bool
+TypeCheckContext::lookup_cast_autoderef_mappings (
+  HirId id, std::vector<Adjustment> **adjustments)
+{
+  auto it = cast_autoderef_mappings.find (id);
+  if (it == cast_autoderef_mappings.end ())
+    return false;
+
+  *adjustments = &it->second;
+  return true;
+}
+
+void
+TypeCheckContext::insert_variant_definition (HirId id, HirId variant)
+{
+  auto it = variants.find (id);
+  rust_assert (it == variants.end ());
+
+  variants[id] = variant;
+}
+
+bool
+TypeCheckContext::lookup_variant_definition (HirId id, HirId *variant)
+{
+  auto it = variants.find (id);
+  if (it == variants.end ())
+    return false;
+
+  *variant = it->second;
+  return true;
+}
+
+void
+TypeCheckContext::insert_operator_overload (HirId id, TyTy::FnType *call_site)
+{
+  auto it = operator_overloads.find (id);
+  rust_assert (it == operator_overloads.end ());
+
+  operator_overloads[id] = call_site;
+}
+
+bool
+TypeCheckContext::lookup_operator_overload (HirId id, TyTy::FnType **call)
+{
+  auto it = operator_overloads.find (id);
+  if (it == operator_overloads.end ())
+    return false;
+
+  *call = it->second;
+  return true;
+}
+
+void
+TypeCheckContext::insert_unconstrained_check_marker (HirId id, bool status)
+{
+  unconstrained[id] = status;
+}
+
+bool
+TypeCheckContext::have_checked_for_unconstrained (HirId id, bool *result)
+{
+  auto it = unconstrained.find (id);
+  bool found = it != unconstrained.end ();
+  if (!found)
+    return false;
+
+  *result = it->second;
+  return true;
+}
+
+void
+TypeCheckContext::insert_resolved_predicate (HirId id,
+					     TyTy::TypeBoundPredicate predicate)
+{
+  auto it = predicates.find (id);
+  rust_assert (it == predicates.end ());
+
+  predicates.insert ({id, predicate});
+}
+
+bool
+TypeCheckContext::lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result)
+{
+  auto it = predicates.find (id);
+  bool found = it != predicates.end ();
+  if (!found)
+    return false;
+
+  *result = it->second;
+  return true;
+}
+
+void
+TypeCheckContext::insert_query (HirId id)
+{
+  querys_in_progress.insert (id);
+}
+
+void
+TypeCheckContext::query_completed (HirId id)
+{
+  querys_in_progress.erase (id);
+}
+
+bool
+TypeCheckContext::query_in_progress (HirId id) const
+{
+  return querys_in_progress.find (id) != querys_in_progress.end ();
+}
+
+void
+TypeCheckContext::insert_trait_query (DefId id)
+{
+  trait_queries_in_progress.insert (id);
+}
+
+void
+TypeCheckContext::trait_query_completed (DefId id)
+{
+  trait_queries_in_progress.erase (id);
+}
+
+bool
+TypeCheckContext::trait_query_in_progress (DefId id) const
+{
+  return trait_queries_in_progress.find (id)
+	 != trait_queries_in_progress.end ();
+}
+
 // TypeCheckContextItem
 
+TypeCheckContextItem::Item::Item (HIR::Function *item) : item (item) {}
+
+TypeCheckContextItem::Item::Item (HIR::ImplBlock *impl_block,
+				  HIR::Function *item)
+  : impl_item ({impl_block, item})
+{}
+
+TypeCheckContextItem::Item::Item (HIR::TraitItemFunc *trait_item)
+  : trait_item (trait_item)
+{}
+
+TypeCheckContextItem::TypeCheckContextItem (HIR::Function *item)
+  : type (ItemType::ITEM), item (item)
+{}
+
+TypeCheckContextItem::TypeCheckContextItem (HIR::ImplBlock *impl_block,
+					    HIR::Function *item)
+  : type (ItemType::IMPL_ITEM), item (impl_block, item)
+{}
+
+TypeCheckContextItem::TypeCheckContextItem (HIR::TraitItemFunc *trait_item)
+  : type (ItemType::TRAIT_ITEM), item (trait_item)
+{}
+
+HIR::Function *
+TypeCheckContextItem::get_item ()
+{
+  rust_assert (get_type () == ItemType::ITEM);
+  return item.item;
+}
+
+std::pair<HIR::ImplBlock *, HIR::Function *> &
+TypeCheckContextItem::get_impl_item ()
+{
+  rust_assert (get_type () == ItemType::IMPL_ITEM);
+  return item.impl_item;
+}
+
+HIR::TraitItemFunc *
+TypeCheckContextItem::get_trait_item ()
+{
+  rust_assert (get_type () == ItemType::TRAIT_ITEM);
+  return item.trait_item;
+}
+
+TypeCheckContextItem::ItemType
+TypeCheckContextItem::get_type () const
+{
+  return type;
+}
+
 TyTy::FnType *
 TypeCheckContextItem::get_context_type ()
 {
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 079055e870d..61c02a85c53 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -17,17 +17,22 @@
 // <http://www.gnu.org/licenses/>.
 
 #include "rust-tyty.h"
-#include "rust-tyty-visitor.h"
-#include "rust-tyty-call.h"
+
 #include "rust-hir-type-check-expr.h"
 #include "rust-hir-type-check-type.h"
-#include "rust-tyty-rules.h"
-#include "rust-tyty-cmp.h"
+#include "rust-tyty-visitor.h"
+#include "rust-tyty-call.h"
 #include "rust-hir-map.h"
+#include "rust-location.h"
+#include "rust-linemap.h"
+
 #include "rust-substitution-mapper.h"
 #include "rust-hir-trait-ref.h"
 #include "rust-hir-type-bounds.h"
 #include "rust-hir-trait-resolve.h"
+#include "rust-tyty-rules.h"
+#include "rust-tyty-cmp.h"
+
 #include "options.h"
 
 namespace Rust {
@@ -658,6 +663,53 @@ ErrorType::monomorphized_clone () const
 
 // Struct Field type
 
+StructFieldType::StructFieldType (HirId ref, std::string name, BaseType *ty,
+				  Location locus)
+  : ref (ref), name (name), ty (ty), locus (locus)
+{}
+
+HirId
+StructFieldType::get_ref () const
+{
+  return ref;
+}
+
+std::string
+StructFieldType::get_name () const
+{
+  return name;
+}
+
+BaseType *
+StructFieldType::get_field_type () const
+{
+  return ty;
+}
+
+void
+StructFieldType::set_field_type (BaseType *fty)
+{
+  ty = fty;
+}
+
+bool
+StructFieldType::is_concrete () const
+{
+  return ty->is_concrete ();
+}
+
+void
+StructFieldType::debug () const
+{
+  rust_debug ("%s", as_string ().c_str ());
+}
+
+Location
+StructFieldType::get_locus () const
+{
+  return locus;
+}
+
 std::string
 StructFieldType::as_string () const
 {
@@ -695,6 +747,241 @@ StructFieldType::monomorphized_clone () const
 			      get_field_type ()->monomorphized_clone (), locus);
 }
 
+// VariantDef
+
+std::string
+VariantDef::variant_type_string (VariantType type)
+{
+  switch (type)
+    {
+    case NUM:
+      return "enumeral";
+    case TUPLE:
+      return "tuple";
+    case STRUCT:
+      return "struct";
+    }
+  gcc_unreachable ();
+  return "";
+}
+
+VariantDef::VariantDef (HirId id, DefId defid, std::string identifier,
+			RustIdent ident, HIR::Expr *discriminant)
+  : id (id), defid (defid), identifier (identifier), ident (ident),
+    discriminant (discriminant)
+
+{
+  type = VariantType::NUM;
+  fields = {};
+}
+
+VariantDef::VariantDef (HirId id, DefId defid, std::string identifier,
+			RustIdent ident, VariantType type,
+			HIR::Expr *discriminant,
+			std::vector<StructFieldType *> fields)
+  : id (id), defid (defid), identifier (identifier), ident (ident), type (type),
+    discriminant (discriminant), fields (fields)
+{
+  rust_assert ((type == VariantType::NUM && fields.empty ())
+	       || (type == VariantType::TUPLE || type == VariantType::STRUCT));
+}
+
+VariantDef::VariantDef (const VariantDef &other)
+  : id (other.id), defid (other.defid), identifier (other.identifier),
+    ident (other.ident), type (other.type), discriminant (other.discriminant),
+    fields (other.fields)
+{}
+
+VariantDef &
+VariantDef::operator= (const VariantDef &other)
+{
+  id = other.id;
+  identifier = other.identifier;
+  type = other.type;
+  discriminant = other.discriminant;
+  fields = other.fields;
+  ident = other.ident;
+
+  return *this;
+}
+
+VariantDef &
+VariantDef::get_error_node ()
+{
+  static VariantDef node
+    = VariantDef (UNKNOWN_HIRID, UNKNOWN_DEFID, "",
+		  {Resolver::CanonicalPath::create_empty (),
+		   Linemap::unknown_location ()},
+		  nullptr);
+
+  return node;
+}
+
+bool
+VariantDef::is_error () const
+{
+  return get_id () == UNKNOWN_HIRID;
+}
+
+HirId
+VariantDef::get_id () const
+{
+  return id;
+}
+
+DefId
+VariantDef::get_defid () const
+{
+  return defid;
+}
+
+VariantDef::VariantType
+VariantDef::get_variant_type () const
+{
+  return type;
+}
+
+bool
+VariantDef::is_data_variant () const
+{
+  return type != VariantType::NUM;
+}
+
+bool
+VariantDef::is_dataless_variant () const
+{
+  return type == VariantType::NUM;
+}
+
+std::string
+VariantDef::get_identifier () const
+{
+  return identifier;
+}
+
+size_t
+VariantDef::num_fields () const
+{
+  return fields.size ();
+}
+
+StructFieldType *
+VariantDef::get_field_at_index (size_t index)
+{
+  rust_assert (index < fields.size ());
+  return fields.at (index);
+}
+
+std::vector<StructFieldType *> &
+VariantDef::get_fields ()
+{
+  rust_assert (type != NUM);
+  return fields;
+}
+
+bool
+VariantDef::lookup_field (const std::string &lookup,
+			  StructFieldType **field_lookup, size_t *index) const
+{
+  size_t i = 0;
+  for (auto &field : fields)
+    {
+      if (field->get_name ().compare (lookup) == 0)
+	{
+	  if (index != nullptr)
+	    *index = i;
+
+	  if (field_lookup != nullptr)
+	    *field_lookup = field;
+
+	  return true;
+	}
+      i++;
+    }
+  return false;
+}
+
+HIR::Expr *
+VariantDef::get_discriminant () const
+{
+  rust_assert (discriminant != nullptr);
+  return discriminant;
+}
+
+std::string
+VariantDef::as_string () const
+{
+  if (type == VariantType::NUM)
+    return identifier + " = " + discriminant->as_string ();
+
+  std::string buffer;
+  for (size_t i = 0; i < fields.size (); ++i)
+    {
+      buffer += fields.at (i)->as_string ();
+      if ((i + 1) < fields.size ())
+	buffer += ", ";
+    }
+
+  if (type == VariantType::TUPLE)
+    return identifier + " (" + buffer + ")";
+  else
+    return identifier + " {" + buffer + "}";
+}
+
+bool
+VariantDef::is_equal (const VariantDef &other) const
+{
+  if (type != other.type)
+    return false;
+
+  if (identifier.compare (other.identifier) != 0)
+    return false;
+
+  if (discriminant != other.discriminant)
+    return false;
+
+  if (fields.size () != other.fields.size ())
+    return false;
+
+  for (size_t i = 0; i < fields.size (); i++)
+    {
+      if (!fields.at (i)->is_equal (*other.fields.at (i)))
+	return false;
+    }
+
+  return true;
+}
+
+VariantDef *
+VariantDef::clone () const
+{
+  std::vector<StructFieldType *> cloned_fields;
+  for (auto &f : fields)
+    cloned_fields.push_back ((StructFieldType *) f->clone ());
+
+  return new VariantDef (id, defid, identifier, ident, type, discriminant,
+			 cloned_fields);
+}
+
+VariantDef *
+VariantDef::monomorphized_clone () const
+{
+  std::vector<StructFieldType *> cloned_fields;
+  for (auto &f : fields)
+    cloned_fields.push_back ((StructFieldType *) f->monomorphized_clone ());
+
+  return new VariantDef (id, defid, identifier, ident, type, discriminant,
+			 cloned_fields);
+}
+
+const RustIdent &
+VariantDef::get_ident () const
+{
+  return ident;
+}
+
+// ADTType
+
 void
 ADTType::accept_vis (TyVisitor &vis)
 {
@@ -892,6 +1179,57 @@ ADTType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
   return adt;
 }
 
+// TupleType
+
+TupleType::TupleType (HirId ref, Location locus, std::vector<TyVar> fields,
+		      std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::TUPLE,
+	      {Resolver::CanonicalPath::create_empty (), locus}, refs),
+    fields (fields)
+{}
+
+TupleType::TupleType (HirId ref, HirId ty_ref, Location locus,
+		      std::vector<TyVar> fields, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::TUPLE,
+	      {Resolver::CanonicalPath::create_empty (), locus}, refs),
+    fields (fields)
+{}
+
+TupleType *
+TupleType::get_unit_type (HirId ref)
+{
+  return new TupleType (ref, Linemap::predeclared_location ());
+}
+
+bool
+TupleType::is_unit () const
+{
+  return this->fields.empty ();
+}
+
+size_t
+TupleType::num_fields () const
+{
+  return fields.size ();
+}
+
+bool
+TupleType::is_concrete () const
+{
+  for (size_t i = 0; i < num_fields (); i++)
+    {
+      if (!get_field (i)->is_concrete ())
+	return false;
+    }
+  return true;
+}
+
+const std::vector<TyVar> &
+TupleType::get_fields () const
+{
+  return fields;
+}
+
 void
 TupleType::accept_vis (TyVisitor &vis)
 {
@@ -1622,6 +1960,34 @@ SliceType::handle_substitions (SubstitutionArgumentMappings mappings)
   return ref;
 }
 
+// BoolType
+
+BoolType::BoolType (HirId ref, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::BOOL,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+BoolType::BoolType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::BOOL,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+std::string
+BoolType::get_name () const
+{
+  return as_string ();
+}
+
+bool
+BoolType::is_concrete () const
+{
+  return true;
+}
+
 void
 BoolType::accept_vis (TyVisitor &vis)
 {
@@ -1666,6 +2032,36 @@ BoolType::monomorphized_clone () const
   return clone ();
 }
 
+// IntType
+
+IntType::IntType (HirId ref, IntKind kind, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::INT,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    int_kind (kind)
+{}
+
+IntType::IntType (HirId ref, HirId ty_ref, IntKind kind, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::INT,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    int_kind (kind)
+{}
+
+std::string
+IntType::get_name () const
+{
+  return as_string ();
+}
+
+IntType::IntKind
+IntType::get_int_kind () const
+{
+  return int_kind;
+}
+
 void
 IntType::accept_vis (TyVisitor &vis)
 {
@@ -1735,6 +2131,43 @@ IntType::is_equal (const BaseType &other) const
   return get_int_kind () == o.get_int_kind ();
 }
 
+bool
+IntType::is_concrete () const
+{
+  return true;
+}
+
+// UintType
+
+UintType::UintType (HirId ref, UintKind kind, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::UINT,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    uint_kind (kind)
+{}
+
+UintType::UintType (HirId ref, HirId ty_ref, UintKind kind,
+		    std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::UINT,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    uint_kind (kind)
+{}
+
+std::string
+UintType::get_name () const
+{
+  return as_string ();
+}
+
+UintType::UintKind
+UintType::get_uint_kind () const
+{
+  return uint_kind;
+}
+
 void
 UintType::accept_vis (TyVisitor &vis)
 {
@@ -1804,6 +2237,49 @@ UintType::is_equal (const BaseType &other) const
   return get_uint_kind () == o.get_uint_kind ();
 }
 
+bool
+UintType::is_concrete () const
+{
+  return true;
+}
+
+// FloatType
+
+FloatType::FloatType (HirId ref, FloatKind kind, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::FLOAT,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    float_kind (kind)
+{}
+
+FloatType::FloatType (HirId ref, HirId ty_ref, FloatKind kind,
+		      std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::FLOAT,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    float_kind (kind)
+{}
+
+std::string
+FloatType::get_name () const
+{
+  return as_string ();
+}
+
+FloatType::FloatKind
+FloatType::get_float_kind () const
+{
+  return float_kind;
+}
+
+bool
+FloatType::is_concrete () const
+{
+  return true;
+}
+
 void
 FloatType::accept_vis (TyVisitor &vis)
 {
@@ -1867,6 +2343,34 @@ FloatType::is_equal (const BaseType &other) const
   return get_float_kind () == o.get_float_kind ();
 }
 
+// UsizeType
+
+USizeType::USizeType (HirId ref, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::USIZE,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+USizeType::USizeType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::USIZE,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+std::string
+USizeType::get_name () const
+{
+  return as_string ();
+}
+
+bool
+USizeType::is_concrete () const
+{
+  return true;
+}
+
 void
 USizeType::accept_vis (TyVisitor &vis)
 {
@@ -1911,6 +2415,34 @@ USizeType::monomorphized_clone () const
   return clone ();
 }
 
+// ISizeType
+
+ISizeType::ISizeType (HirId ref, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::ISIZE,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+ISizeType::ISizeType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::ISIZE,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+std::string
+ISizeType::get_name () const
+{
+  return as_string ();
+}
+
+bool
+ISizeType::is_concrete () const
+{
+  return true;
+}
+
 void
 ISizeType::accept_vis (TyVisitor &vis)
 {
@@ -1955,6 +2487,34 @@ ISizeType::monomorphized_clone () const
   return clone ();
 }
 
+// Char Type
+
+CharType::CharType (HirId ref, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::CHAR,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+CharType::CharType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::CHAR,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+bool
+CharType::is_concrete () const
+{
+  return true;
+}
+
+std::string
+CharType::get_name () const
+{
+  return as_string ();
+}
+
 void
 CharType::accept_vis (TyVisitor &vis)
 {
@@ -1999,6 +2559,76 @@ CharType::monomorphized_clone () const
   return clone ();
 }
 
+// Reference Type
+
+ReferenceType::ReferenceType (HirId ref, TyVar base, Mutability mut,
+			      std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::REF,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    base (base), mut (mut)
+{}
+
+ReferenceType::ReferenceType (HirId ref, HirId ty_ref, TyVar base,
+			      Mutability mut, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::REF,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    base (base), mut (mut)
+{}
+
+bool
+ReferenceType::is_concrete () const
+{
+  return get_base ()->is_concrete ();
+}
+
+Mutability
+ReferenceType::mutability () const
+{
+  return mut;
+}
+
+bool
+ReferenceType::is_mutable () const
+{
+  return mut == Mutability::Mut;
+}
+
+bool
+ReferenceType::is_dyn_object () const
+{
+  return is_dyn_slice_type () || is_dyn_str_type ();
+}
+
+bool
+ReferenceType::is_dyn_slice_type (const TyTy::SliceType **slice) const
+{
+  const TyTy::BaseType *element = get_base ()->destructure ();
+  if (element->get_kind () != TyTy::TypeKind::SLICE)
+    return false;
+  if (slice == nullptr)
+    return true;
+
+  *slice = static_cast<const TyTy::SliceType *> (element);
+  return true;
+}
+
+bool
+ReferenceType::is_dyn_str_type (const TyTy::StrType **str) const
+{
+  const TyTy::BaseType *element = get_base ()->destructure ();
+  if (element->get_kind () != TyTy::TypeKind::STR)
+    return false;
+  if (str == nullptr)
+    return true;
+
+  *str = static_cast<const TyTy::StrType *> (element);
+  return true;
+}
+
 void
 ReferenceType::accept_vis (TyVisitor &vis)
 {
@@ -2089,6 +2719,82 @@ ReferenceType::handle_substitions (SubstitutionArgumentMappings mappings)
   return ref;
 }
 
+// PointerType
+
+PointerType::PointerType (HirId ref, TyVar base, Mutability mut,
+			  std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::POINTER,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    base (base), mut (mut)
+{}
+
+PointerType::PointerType (HirId ref, HirId ty_ref, TyVar base, Mutability mut,
+			  std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::POINTER,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    base (base), mut (mut)
+{}
+
+bool
+PointerType::is_concrete () const
+{
+  return get_base ()->is_concrete ();
+}
+
+Mutability
+PointerType::mutability () const
+{
+  return mut;
+}
+
+bool
+PointerType::is_mutable () const
+{
+  return mut == Mutability::Mut;
+}
+
+bool
+PointerType::is_const () const
+{
+  return mut == Mutability::Imm;
+}
+
+bool
+PointerType::is_dyn_object () const
+{
+  return is_dyn_slice_type () || is_dyn_str_type ();
+}
+
+bool
+PointerType::is_dyn_slice_type (const TyTy::SliceType **slice) const
+{
+  const TyTy::BaseType *element = get_base ()->destructure ();
+  if (element->get_kind () != TyTy::TypeKind::SLICE)
+    return false;
+  if (slice == nullptr)
+    return true;
+
+  *slice = static_cast<const TyTy::SliceType *> (element);
+  return true;
+}
+
+bool
+PointerType::is_dyn_str_type (const TyTy::StrType **str) const
+{
+  const TyTy::BaseType *element = get_base ()->destructure ();
+  if (element->get_kind () != TyTy::TypeKind::STR)
+    return false;
+  if (str == nullptr)
+    return true;
+
+  *str = static_cast<const TyTy::StrType *> (element);
+  return true;
+}
+
 void
 PointerType::accept_vis (TyVisitor &vis)
 {
@@ -2179,6 +2885,52 @@ PointerType::handle_substitions (SubstitutionArgumentMappings mappings)
   return ref;
 }
 
+// PARAM Type
+
+ParamType::ParamType (std::string symbol, Location locus, HirId ref,
+		      HIR::GenericParam &param,
+		      std::vector<TypeBoundPredicate> specified_bounds,
+		      std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::PARAM,
+	      {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
+	       locus},
+	      specified_bounds, refs),
+    symbol (symbol), param (param)
+{}
+
+ParamType::ParamType (std::string symbol, Location locus, HirId ref,
+		      HirId ty_ref, HIR::GenericParam &param,
+		      std::vector<TypeBoundPredicate> specified_bounds,
+		      std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::PARAM,
+	      {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
+	       locus},
+	      specified_bounds, refs),
+    symbol (symbol), param (param)
+{}
+
+HIR::GenericParam &
+ParamType::get_generic_param ()
+{
+  return param;
+}
+
+bool
+ParamType::can_resolve () const
+{
+  return get_ref () != get_ty_ref ();
+}
+
+bool
+ParamType::is_concrete () const
+{
+  auto r = resolve ();
+  if (r == this)
+    return false;
+
+  return r->is_concrete ();
+}
+
 void
 ParamType::accept_vis (TyVisitor &vis)
 {
@@ -2320,6 +3072,34 @@ ParamType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
   return p;
 }
 
+// StrType
+
+StrType::StrType (HirId ref, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::STR,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+StrType::StrType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::STR,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+std::string
+StrType::get_name () const
+{
+  return as_string ();
+}
+
+bool
+StrType::is_concrete () const
+{
+  return true;
+}
+
 BaseType *
 StrType::clone () const
 {
@@ -2370,6 +3150,40 @@ StrType::is_equal (const BaseType &other) const
   return get_kind () == other.get_kind ();
 }
 
+// Never Type
+
+NeverType::NeverType (HirId ref, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::NEVER,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+NeverType::NeverType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::NEVER,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+std::string
+NeverType::get_name () const
+{
+  return as_string ();
+}
+
+bool
+NeverType::is_unit () const
+{
+  return true;
+}
+
+bool
+NeverType::is_concrete () const
+{
+  return true;
+}
+
 void
 NeverType::accept_vis (TyVisitor &vis)
 {
@@ -2416,6 +3230,52 @@ NeverType::monomorphized_clone () const
 
 // placeholder type
 
+PlaceholderType::PlaceholderType (std::string symbol, HirId ref,
+				  std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::PLACEHOLDER,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    symbol (symbol)
+{}
+
+PlaceholderType::PlaceholderType (std::string symbol, HirId ref, HirId ty_ref,
+				  std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::PLACEHOLDER,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    symbol (symbol)
+{}
+
+std::string
+PlaceholderType::get_name () const
+{
+  return as_string ();
+}
+
+bool
+PlaceholderType::is_unit () const
+{
+  rust_assert (can_resolve ());
+  return resolve ()->is_unit ();
+}
+
+std::string
+PlaceholderType::get_symbol () const
+{
+  return symbol;
+}
+
+bool
+PlaceholderType::is_concrete () const
+{
+  if (!can_resolve ())
+    return true;
+
+  return resolve ()->is_concrete ();
+}
+
 void
 PlaceholderType::accept_vis (TyVisitor &vis)
 {
@@ -2515,6 +3375,78 @@ PlaceholderType::is_equal (const BaseType &other) const
 
 // Projection type
 
+ProjectionType::ProjectionType (
+  HirId ref, BaseType *base, const Resolver::TraitReference *trait, DefId item,
+  std::vector<SubstitutionParamMapping> subst_refs,
+  SubstitutionArgumentMappings generic_arguments, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::PROJECTION,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)),
+    base (base), trait (trait), item (item)
+{}
+
+ProjectionType::ProjectionType (
+  HirId ref, HirId ty_ref, BaseType *base,
+  const Resolver::TraitReference *trait, DefId item,
+  std::vector<SubstitutionParamMapping> subst_refs,
+  SubstitutionArgumentMappings generic_arguments, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::PROJECTION,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)),
+    base (base), trait (trait), item (item)
+{}
+
+bool
+ProjectionType::is_unit () const
+{
+  return false;
+}
+
+std::string
+ProjectionType::get_name () const
+{
+  return as_string ();
+}
+
+bool
+ProjectionType::needs_generic_substitutions () const
+{
+  return needs_substitution ();
+}
+
+bool
+ProjectionType::supports_substitutions () const
+{
+  return true;
+}
+
+bool
+ProjectionType::has_subsititions_defined () const
+{
+  return has_substitutions ();
+}
+
+const BaseType *
+ProjectionType::get () const
+{
+  return base;
+}
+BaseType *
+ProjectionType::get ()
+{
+  return base;
+}
+
+bool
+ProjectionType::is_concrete () const
+{
+  return base->is_concrete ();
+}
+
 void
 ProjectionType::accept_vis (TyVisitor &vis)
 {
@@ -2631,6 +3563,26 @@ ProjectionType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
   return projection;
 }
 
+// DynObjectType
+
+DynamicObjectType::DynamicObjectType (
+  HirId ref, RustIdent ident, std::vector<TypeBoundPredicate> specified_bounds,
+  std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::DYNAMIC, ident, specified_bounds, refs)
+{}
+
+DynamicObjectType::DynamicObjectType (
+  HirId ref, HirId ty_ref, RustIdent ident,
+  std::vector<TypeBoundPredicate> specified_bounds, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::DYNAMIC, ident, specified_bounds, refs)
+{}
+
+bool
+DynamicObjectType::is_concrete () const
+{
+  return true;
+}
+
 void
 DynamicObjectType::accept_vis (TyVisitor &vis)
 {
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 1a6bac3f864..85b3a3b7abc 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -20,11 +20,9 @@
 #define RUST_TYTY
 
 #include "rust-hir-map.h"
-#include "rust-hir-full.h"
-#include "rust-diagnostics.h"
-#include "rust-abi.h"
 #include "rust-common.h"
 #include "rust-identifier.h"
+#include "rust-abi.h"
 #include "rust-tyty-bounds.h"
 #include "rust-tyty-util.h"
 #include "rust-tyty-subst.h"
@@ -274,24 +272,12 @@ public:
   ParamType (std::string symbol, Location locus, HirId ref,
 	     HIR::GenericParam &param,
 	     std::vector<TypeBoundPredicate> specified_bounds,
-	     std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::PARAM,
-		{Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
-		 locus},
-		specified_bounds, refs),
-      symbol (symbol), param (param)
-  {}
+	     std::set<HirId> refs = std::set<HirId> ());
 
   ParamType (std::string symbol, Location locus, HirId ref, HirId ty_ref,
 	     HIR::GenericParam &param,
 	     std::vector<TypeBoundPredicate> specified_bounds,
-	     std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::PARAM,
-		{Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
-		 locus},
-		specified_bounds, refs),
-      symbol (symbol), param (param)
-  {}
+	     std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
@@ -306,9 +292,9 @@ public:
 
   std::string get_symbol () const;
 
-  HIR::GenericParam &get_generic_param () { return param; }
+  HIR::GenericParam &get_generic_param ();
 
-  bool can_resolve () const { return get_ref () != get_ty_ref (); }
+  bool can_resolve () const;
 
   BaseType *resolve () const;
 
@@ -316,14 +302,7 @@ public:
 
   bool is_equal (const BaseType &other) const override;
 
-  bool is_concrete () const override final
-  {
-    auto r = resolve ();
-    if (r == this)
-      return false;
-
-    return r->is_concrete ();
-  }
+  bool is_concrete () const override final;
 
   ParamType *handle_substitions (SubstitutionArgumentMappings mappings);
 
@@ -335,31 +314,25 @@ private:
 class StructFieldType
 {
 public:
-  StructFieldType (HirId ref, std::string name, BaseType *ty, Location locus)
-    : ref (ref), name (name), ty (ty), locus (locus)
-  {}
-
-  HirId get_ref () const { return ref; }
+  StructFieldType (HirId ref, std::string name, BaseType *ty, Location locus);
 
-  std::string as_string () const;
+  HirId get_ref () const;
 
   bool is_equal (const StructFieldType &other) const;
 
-  std::string get_name () const { return name; }
-
-  BaseType *get_field_type () const { return ty; }
+  std::string get_name () const;
 
-  void set_field_type (BaseType *fty) { ty = fty; }
+  BaseType *get_field_type () const;
+  void set_field_type (BaseType *fty);
 
   StructFieldType *clone () const;
-
   StructFieldType *monomorphized_clone () const;
 
-  bool is_concrete () const { return ty->is_concrete (); }
-
-  void debug () const { rust_debug ("%s", as_string ().c_str ()); }
+  bool is_concrete () const;
 
-  Location get_locus () const { return locus; }
+  void debug () const;
+  Location get_locus () const;
+  std::string as_string () const;
 
 private:
   HirId ref;
@@ -373,29 +346,18 @@ class TupleType : public BaseType
 public:
   TupleType (HirId ref, Location locus,
 	     std::vector<TyVar> fields = std::vector<TyVar> (),
-	     std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::TUPLE,
-		{Resolver::CanonicalPath::create_empty (), locus}, refs),
-      fields (fields)
-  {}
+	     std::set<HirId> refs = std::set<HirId> ());
 
   TupleType (HirId ref, HirId ty_ref, Location locus,
 	     std::vector<TyVar> fields = std::vector<TyVar> (),
-	     std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::TUPLE,
-		{Resolver::CanonicalPath::create_empty (), locus}, refs),
-      fields (fields)
-  {}
+	     std::set<HirId> refs = std::set<HirId> ());
 
-  static TupleType *get_unit_type (HirId ref)
-  {
-    return new TupleType (ref, Linemap::predeclared_location ());
-  }
+  static TupleType *get_unit_type (HirId ref);
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
 
-  bool is_unit () const override { return this->fields.empty (); }
+  bool is_unit () const override;
 
   std::string as_string () const override;
 
@@ -404,24 +366,16 @@ public:
 
   bool is_equal (const BaseType &other) const override;
 
-  size_t num_fields () const { return fields.size (); }
+  size_t num_fields () const;
 
   BaseType *get_field (size_t index) const;
 
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
 
-  bool is_concrete () const override final
-  {
-    for (size_t i = 0; i < num_fields (); i++)
-      {
-	if (!get_field (i)->is_concrete ())
-	  return false;
-      }
-    return true;
-  }
+  bool is_concrete () const override final;
 
-  const std::vector<TyVar> &get_fields () const { return fields; }
+  const std::vector<TyVar> &get_fields () const;
 
   std::string get_name () const override final;
 
@@ -507,185 +461,48 @@ public:
     STRUCT
   };
 
-  static std::string variant_type_string (VariantType type)
-  {
-    switch (type)
-      {
-      case NUM:
-	return "enumeral";
-      case TUPLE:
-	return "tuple";
-      case STRUCT:
-	return "struct";
-      }
-    gcc_unreachable ();
-    return "";
-  }
+  static std::string variant_type_string (VariantType type);
 
   VariantDef (HirId id, DefId defid, std::string identifier, RustIdent ident,
-	      HIR::Expr *discriminant)
-    : id (id), defid (defid), identifier (identifier), ident (ident),
-      discriminant (discriminant)
-
-  {
-    type = VariantType::NUM;
-    fields = {};
-  }
+	      HIR::Expr *discriminant);
 
   VariantDef (HirId id, DefId defid, std::string identifier, RustIdent ident,
 	      VariantType type, HIR::Expr *discriminant,
-	      std::vector<StructFieldType *> fields)
-    : id (id), defid (defid), identifier (identifier), ident (ident),
-      type (type), discriminant (discriminant), fields (fields)
-  {
-    rust_assert (
-      (type == VariantType::NUM && fields.empty ())
-      || (type == VariantType::TUPLE || type == VariantType::STRUCT));
-  }
+	      std::vector<StructFieldType *> fields);
 
-  VariantDef (const VariantDef &other)
-    : id (other.id), defid (other.defid), identifier (other.identifier),
-      ident (other.ident), type (other.type), discriminant (other.discriminant),
-      fields (other.fields)
-  {}
+  VariantDef (const VariantDef &other);
 
-  VariantDef &operator= (const VariantDef &other)
-  {
-    id = other.id;
-    identifier = other.identifier;
-    type = other.type;
-    discriminant = other.discriminant;
-    fields = other.fields;
-    ident = other.ident;
-
-    return *this;
-  }
+  VariantDef &operator= (const VariantDef &other);
 
-  static VariantDef &get_error_node ()
-  {
-    static VariantDef node
-      = VariantDef (UNKNOWN_HIRID, UNKNOWN_DEFID, "",
-		    {Resolver::CanonicalPath::create_empty (),
-		     Linemap::unknown_location ()},
-		    nullptr);
+  static VariantDef &get_error_node ();
+  bool is_error () const;
 
-    return node;
-  }
+  HirId get_id () const;
+  DefId get_defid () const;
 
-  bool is_error () const { return get_id () == UNKNOWN_HIRID; }
+  VariantType get_variant_type () const;
+  bool is_data_variant () const;
+  bool is_dataless_variant () const;
 
-  HirId get_id () const { return id; }
-  DefId get_defid () const { return defid; }
+  std::string get_identifier () const;
 
-  VariantType get_variant_type () const { return type; }
-  bool is_data_variant () const { return type != VariantType::NUM; }
-  bool is_dataless_variant () const { return type == VariantType::NUM; }
+  size_t num_fields () const;
+  StructFieldType *get_field_at_index (size_t index);
 
-  std::string get_identifier () const { return identifier; }
-
-  size_t num_fields () const { return fields.size (); }
-  StructFieldType *get_field_at_index (size_t index)
-  {
-    rust_assert (index < fields.size ());
-    return fields.at (index);
-  }
-
-  std::vector<StructFieldType *> &get_fields ()
-  {
-    rust_assert (type != NUM);
-    return fields;
-  }
+  std::vector<StructFieldType *> &get_fields ();
 
   bool lookup_field (const std::string &lookup, StructFieldType **field_lookup,
-		     size_t *index) const
-  {
-    size_t i = 0;
-    for (auto &field : fields)
-      {
-	if (field->get_name ().compare (lookup) == 0)
-	  {
-	    if (index != nullptr)
-	      *index = i;
-
-	    if (field_lookup != nullptr)
-	      *field_lookup = field;
-
-	    return true;
-	  }
-	i++;
-      }
-    return false;
-  }
-
-  HIR::Expr *get_discriminant () const
-  {
-    rust_assert (discriminant != nullptr);
-    return discriminant;
-  }
-
-  std::string as_string () const
-  {
-    if (type == VariantType::NUM)
-      return identifier + " = " + discriminant->as_string ();
-
-    std::string buffer;
-    for (size_t i = 0; i < fields.size (); ++i)
-      {
-	buffer += fields.at (i)->as_string ();
-	if ((i + 1) < fields.size ())
-	  buffer += ", ";
-      }
-
-    if (type == VariantType::TUPLE)
-      return identifier + " (" + buffer + ")";
-    else
-      return identifier + " {" + buffer + "}";
-  }
-
-  bool is_equal (const VariantDef &other) const
-  {
-    if (type != other.type)
-      return false;
-
-    if (identifier.compare (other.identifier) != 0)
-      return false;
+		     size_t *index) const;
 
-    if (discriminant != other.discriminant)
-      return false;
-
-    if (fields.size () != other.fields.size ())
-      return false;
-
-    for (size_t i = 0; i < fields.size (); i++)
-      {
-	if (!fields.at (i)->is_equal (*other.fields.at (i)))
-	  return false;
-      }
-
-    return true;
-  }
-
-  VariantDef *clone () const
-  {
-    std::vector<StructFieldType *> cloned_fields;
-    for (auto &f : fields)
-      cloned_fields.push_back ((StructFieldType *) f->clone ());
+  HIR::Expr *get_discriminant () const;
 
-    return new VariantDef (id, defid, identifier, ident, type, discriminant,
-			   cloned_fields);
-  }
+  std::string as_string () const;
 
-  VariantDef *monomorphized_clone () const
-  {
-    std::vector<StructFieldType *> cloned_fields;
-    for (auto &f : fields)
-      cloned_fields.push_back ((StructFieldType *) f->monomorphized_clone ());
+  bool is_equal (const VariantDef &other) const;
+  VariantDef *clone () const;
+  VariantDef *monomorphized_clone () const;
 
-    return new VariantDef (id, defid, identifier, ident, type, discriminant,
-			   cloned_fields);
-  }
-
-  const RustIdent &get_ident () const { return ident; }
+  const RustIdent &get_ident () const;
 
 private:
   HirId id;
@@ -1262,33 +1079,22 @@ private:
 class BoolType : public BaseType
 {
 public:
-  BoolType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::BOOL,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
-
-  BoolType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::BOOL,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
+  BoolType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+  BoolType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
 
   std::string as_string () const override;
 
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
   BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
-  bool is_concrete () const override final { return true; }
+  bool is_concrete () const override final;
 };
 
 class IntType : public BaseType
@@ -1303,40 +1109,27 @@ public:
     I128
   };
 
-  IntType (HirId ref, IntKind kind, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::INT,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      int_kind (kind)
-  {}
-
+  IntType (HirId ref, IntKind kind, std::set<HirId> refs = std::set<HirId> ());
   IntType (HirId ref, HirId ty_ref, IntKind kind,
-	   std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::INT,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      int_kind (kind)
-  {}
+	   std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
 
   std::string as_string () const override;
 
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
   BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
-  IntKind get_int_kind () const { return int_kind; }
+  IntKind get_int_kind () const;
 
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
 
   bool is_equal (const BaseType &other) const override;
-  bool is_concrete () const override final { return true; }
+  bool is_concrete () const override final;
 
 private:
   IntKind int_kind;
@@ -1354,40 +1147,28 @@ public:
     U128
   };
 
-  UintType (HirId ref, UintKind kind, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::UINT,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      uint_kind (kind)
-  {}
-
+  UintType (HirId ref, UintKind kind,
+	    std::set<HirId> refs = std::set<HirId> ());
   UintType (HirId ref, HirId ty_ref, UintKind kind,
-	    std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::UINT,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      uint_kind (kind)
-  {}
+	    std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
 
   std::string as_string () const override;
 
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
   BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
-  UintKind get_uint_kind () const { return uint_kind; }
+  UintKind get_uint_kind () const;
 
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
 
   bool is_equal (const BaseType &other) const override;
-  bool is_concrete () const override final { return true; }
+  bool is_concrete () const override final;
 
 private:
   UintKind uint_kind;
@@ -1403,40 +1184,26 @@ public:
   };
 
   FloatType (HirId ref, FloatKind kind,
-	     std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::FLOAT,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      float_kind (kind)
-  {}
-
+	     std::set<HirId> refs = std::set<HirId> ());
   FloatType (HirId ref, HirId ty_ref, FloatKind kind,
-	     std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::FLOAT,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      float_kind (kind)
-  {}
+	     std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
 
   std::string as_string () const override;
-
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
   BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
-  FloatKind get_float_kind () const { return float_kind; }
+  FloatKind get_float_kind () const;
 
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
 
   bool is_equal (const BaseType &other) const override;
-  bool is_concrete () const override final { return true; }
+  bool is_concrete () const override final;
 
 private:
   FloatKind float_kind;
@@ -1445,117 +1212,72 @@ private:
 class USizeType : public BaseType
 {
 public:
-  USizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::USIZE,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
-
-  USizeType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::USIZE,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
+  USizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+  USizeType (HirId ref, HirId ty_ref,
+	     std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
 
   std::string as_string () const override;
-
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
   BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
-  bool is_concrete () const override final { return true; }
+  bool is_concrete () const override final;
 };
 
 class ISizeType : public BaseType
 {
 public:
-  ISizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::ISIZE,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
-
-  ISizeType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::ISIZE,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
+  ISizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+  ISizeType (HirId ref, HirId ty_ref,
+	     std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
 
   std::string as_string () const override;
-
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
   BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
-  bool is_concrete () const override final { return true; }
+  bool is_concrete () const override final;
 };
 
 class CharType : public BaseType
 {
 public:
-  CharType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::CHAR,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
-
-  CharType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::CHAR,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
+  CharType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+  CharType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
 
   std::string as_string () const override;
-
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
   BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
-  bool is_concrete () const override final { return true; }
+  bool is_concrete () const override final;
 };
 
 class StrType : public BaseType
 {
 public:
-  StrType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::STR,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
-
-  StrType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::STR,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
+  StrType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+  StrType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ());
 
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
@@ -1569,29 +1291,16 @@ public:
 
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
-  bool is_concrete () const override final { return true; }
+  bool is_concrete () const override final;
 };
 
 class ReferenceType : public BaseType
 {
 public:
   ReferenceType (HirId ref, TyVar base, Mutability mut,
-		 std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::REF,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      base (base), mut (mut)
-  {}
-
+		 std::set<HirId> refs = std::set<HirId> ());
   ReferenceType (HirId ref, HirId ty_ref, TyVar base, Mutability mut,
-		 std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::REF,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      base (base), mut (mut)
-  {}
+		 std::set<HirId> refs = std::set<HirId> ());
 
   BaseType *get_base () const;
 
@@ -1610,45 +1319,19 @@ public:
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
 
-  bool is_concrete () const override final
-  {
-    return get_base ()->is_concrete ();
-  }
+  bool is_concrete () const override final;
 
   ReferenceType *handle_substitions (SubstitutionArgumentMappings mappings);
 
-  Mutability mutability () const { return mut; }
+  Mutability mutability () const;
 
-  bool is_mutable () const { return mut == Mutability::Mut; }
+  bool is_mutable () const;
 
-  bool is_dyn_object () const
-  {
-    return is_dyn_slice_type () || is_dyn_str_type ();
-  }
+  bool is_dyn_object () const;
 
-  bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const
-  {
-    const TyTy::BaseType *element = get_base ()->destructure ();
-    if (element->get_kind () != TyTy::TypeKind::SLICE)
-      return false;
-    if (slice == nullptr)
-      return true;
+  bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const;
 
-    *slice = static_cast<const TyTy::SliceType *> (element);
-    return true;
-  }
-
-  bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const
-  {
-    const TyTy::BaseType *element = get_base ()->destructure ();
-    if (element->get_kind () != TyTy::TypeKind::STR)
-      return false;
-    if (str == nullptr)
-      return true;
-
-    *str = static_cast<const TyTy::StrType *> (element);
-    return true;
-  }
+  bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const;
 
 private:
   TyVar base;
@@ -1659,22 +1342,9 @@ class PointerType : public BaseType
 {
 public:
   PointerType (HirId ref, TyVar base, Mutability mut,
-	       std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::POINTER,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      base (base), mut (mut)
-  {}
-
+	       std::set<HirId> refs = std::set<HirId> ());
   PointerType (HirId ref, HirId ty_ref, TyVar base, Mutability mut,
-	       std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::POINTER,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      base (base), mut (mut)
-  {}
+	       std::set<HirId> refs = std::set<HirId> ());
 
   BaseType *get_base () const;
 
@@ -1692,47 +1362,17 @@ public:
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
 
-  bool is_concrete () const override final
-  {
-    return get_base ()->is_concrete ();
-  }
+  bool is_concrete () const override final;
 
   PointerType *handle_substitions (SubstitutionArgumentMappings mappings);
 
-  Mutability mutability () const { return mut; }
-
-  bool is_mutable () const { return mut == Mutability::Mut; }
-
-  bool is_const () const { return mut == Mutability::Imm; }
-
-  bool is_dyn_object () const
-  {
-    return is_dyn_slice_type () || is_dyn_str_type ();
-  }
-
-  bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const
-  {
-    const TyTy::BaseType *element = get_base ()->destructure ();
-    if (element->get_kind () != TyTy::TypeKind::SLICE)
-      return false;
-    if (slice == nullptr)
-      return true;
+  Mutability mutability () const;
+  bool is_mutable () const;
+  bool is_const () const;
+  bool is_dyn_object () const;
 
-    *slice = static_cast<const TyTy::SliceType *> (element);
-    return true;
-  }
-
-  bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const
-  {
-    const TyTy::BaseType *element = get_base ()->destructure ();
-    if (element->get_kind () != TyTy::TypeKind::STR)
-      return false;
-    if (str == nullptr)
-      return true;
-
-    *str = static_cast<const TyTy::StrType *> (element);
-    return true;
-  }
+  bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const;
+  bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const;
 
 private:
   TyVar base;
@@ -1752,19 +1392,9 @@ private:
 class NeverType : public BaseType
 {
 public:
-  NeverType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::NEVER,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
-
-  NeverType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::NEVER,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
+  NeverType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+  NeverType (HirId ref, HirId ty_ref,
+	     std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
@@ -1777,10 +1407,10 @@ public:
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
 
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
-  bool is_unit () const override { return true; }
-  bool is_concrete () const override final { return true; }
+  bool is_unit () const override;
+  bool is_concrete () const override final;
 };
 
 // used at the type in associated types in traits
@@ -1789,22 +1419,9 @@ class PlaceholderType : public BaseType
 {
 public:
   PlaceholderType (std::string symbol, HirId ref,
-		   std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::PLACEHOLDER,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      symbol (symbol)
-  {}
-
+		   std::set<HirId> refs = std::set<HirId> ());
   PlaceholderType (std::string symbol, HirId ref, HirId ty_ref,
-		   std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::PLACEHOLDER,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      symbol (symbol)
-  {}
+		   std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
@@ -1817,15 +1434,11 @@ public:
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
 
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
-  bool is_unit () const override
-  {
-    rust_assert (can_resolve ());
-    return resolve ()->is_unit ();
-  }
+  bool is_unit () const override;
 
-  std::string get_symbol () const { return symbol; }
+  std::string get_symbol () const;
 
   void set_associated_type (HirId ref);
 
@@ -1837,13 +1450,7 @@ public:
 
   bool is_equal (const BaseType &other) const override;
 
-  bool is_concrete () const override final
-  {
-    if (!can_resolve ())
-      return true;
-
-    return resolve ()->is_concrete ();
-  }
+  bool is_concrete () const override final;
 
 private:
   std::string symbol;
@@ -1857,28 +1464,14 @@ public:
 		  std::vector<SubstitutionParamMapping> subst_refs,
 		  SubstitutionArgumentMappings generic_arguments
 		  = SubstitutionArgumentMappings::error (),
-		  std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::PROJECTION,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)),
-      base (base), trait (trait), item (item)
-  {}
+		  std::set<HirId> refs = std::set<HirId> ());
 
   ProjectionType (HirId ref, HirId ty_ref, BaseType *base,
 		  const Resolver::TraitReference *trait, DefId item,
 		  std::vector<SubstitutionParamMapping> subst_refs,
 		  SubstitutionArgumentMappings generic_arguments
 		  = SubstitutionArgumentMappings::error (),
-		  std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::PROJECTION,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)),
-      base (base), trait (trait), item (item)
-  {}
+		  std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
@@ -1891,26 +1484,20 @@ public:
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
 
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
-  bool is_unit () const override { return false; }
+  bool is_unit () const override;
 
-  bool needs_generic_substitutions () const override final
-  {
-    return needs_substitution ();
-  }
+  bool needs_generic_substitutions () const override final;
 
-  bool supports_substitutions () const override final { return true; }
+  bool supports_substitutions () const override final;
 
-  bool has_subsititions_defined () const override final
-  {
-    return has_substitutions ();
-  }
+  bool has_subsititions_defined () const override final;
 
-  const BaseType *get () const { return base; }
-  BaseType *get () { return base; }
+  const BaseType *get () const;
+  BaseType *get ();
 
-  bool is_concrete () const override final { return base->is_concrete (); }
+  bool is_concrete () const override final;
 
   ProjectionType *
   handle_substitions (SubstitutionArgumentMappings mappings) override final;
@@ -1926,15 +1513,11 @@ class DynamicObjectType : public BaseType
 public:
   DynamicObjectType (HirId ref, RustIdent ident,
 		     std::vector<TypeBoundPredicate> specified_bounds,
-		     std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::DYNAMIC, ident, specified_bounds, refs)
-  {}
+		     std::set<HirId> refs = std::set<HirId> ());
 
   DynamicObjectType (HirId ref, HirId ty_ref, RustIdent ident,
 		     std::vector<TypeBoundPredicate> specified_bounds,
-		     std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::DYNAMIC, ident, specified_bounds, refs)
-  {}
+		     std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
@@ -1951,7 +1534,7 @@ public:
 
   std::string get_name () const override final;
 
-  bool is_concrete () const override final { return true; }
+  bool is_concrete () const override final;
 
   // this returns a flat list of items including super trait bounds
   const std::vector<
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 44/88] gccrs: Rename rust-tyctx.cc to rust-typecheck-context.cc
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (42 preceding siblings ...)
  2023-04-05 14:03 ` [committed 43/88] gccrs: Refactor all code out of the rust-tyty.h header arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 45/88] gccrs: Rename header rust-hir-trait-ref.h to rust-hir-trait-reference.h arthur.cohen
                   ` (45 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* Make-lang.in: update name
	* typecheck/rust-tyctx.cc: Moved to...
	* typecheck/rust-typecheck-context.cc: ...here.
---
 gcc/rust/Make-lang.in                                           | 2 +-
 gcc/rust/typecheck/{rust-tyctx.cc => rust-typecheck-context.cc} | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename gcc/rust/typecheck/{rust-tyctx.cc => rust-typecheck-context.cc} (100%)

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 5e173f1d2dc..4752bb83562 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -118,7 +118,7 @@ GRS_OBJS = \
     rust/rust-tyty-util.o \
     rust/rust-tyty-call.o \
     rust/rust-tyty-subst.o \
-    rust/rust-tyctx.o \
+    rust/rust-typecheck-context.o \
     rust/rust-tyty-bounds.o \
     rust/rust-hir-type-check-util.o \
     rust/rust-hir-trait-resolve.o \
diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-typecheck-context.cc
similarity index 100%
rename from gcc/rust/typecheck/rust-tyctx.cc
rename to gcc/rust/typecheck/rust-typecheck-context.cc
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 45/88] gccrs: Rename header rust-hir-trait-ref.h to rust-hir-trait-reference.h
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (43 preceding siblings ...)
  2023-04-05 14:03 ` [committed 44/88] gccrs: Rename rust-tyctx.cc to rust-typecheck-context.cc arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 46/88] gccrs: Refactor handle_substitutions to take a reference arthur.cohen
                   ` (44 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* typecheck/rust-hir-trait-ref.h: Moved to...
	* typecheck/rust-hir-trait-reference.h: ...here.
	* typecheck/rust-hir-trait-resolve.cc: refactor
	* typecheck/rust-hir-trait-resolve.h (RUST_HIR_TRAIT_RESOLVE_H): likewise
	* typecheck/rust-hir-type-check.h: likewise
	* typecheck/rust-tyty.cc: likewise
---
 ...rust-hir-trait-ref.h => rust-hir-trait-reference.h} |  0
 gcc/rust/typecheck/rust-hir-trait-resolve.cc           | 10 ++++++++++
 gcc/rust/typecheck/rust-hir-trait-resolve.h            |  9 +--------
 gcc/rust/typecheck/rust-hir-type-check.h               |  2 +-
 gcc/rust/typecheck/rust-tyty.cc                        |  2 +-
 5 files changed, 13 insertions(+), 10 deletions(-)
 rename gcc/rust/typecheck/{rust-hir-trait-ref.h => rust-hir-trait-reference.h} (100%)

diff --git a/gcc/rust/typecheck/rust-hir-trait-ref.h b/gcc/rust/typecheck/rust-hir-trait-reference.h
similarity index 100%
rename from gcc/rust/typecheck/rust-hir-trait-ref.h
rename to gcc/rust/typecheck/rust-hir-trait-reference.h
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index 19f95ca4488..e2d0cf2d7a2 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -22,6 +22,16 @@
 namespace Rust {
 namespace Resolver {
 
+TraitItemReference
+ResolveTraitItemToRef::Resolve (
+  HIR::TraitItem &item, TyTy::BaseType *self,
+  std::vector<TyTy::SubstitutionParamMapping> substitutions)
+{
+  ResolveTraitItemToRef resolver (self, std::move (substitutions));
+  item.accept_vis (resolver);
+  return std::move (resolver.resolved);
+}
+
 void
 ResolveTraitItemToRef::visit (HIR::TraitItemType &type)
 {
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.h b/gcc/rust/typecheck/rust-hir-trait-resolve.h
index ca23d48c3dd..da8e2c0b838 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.h
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.h
@@ -19,9 +19,7 @@
 #ifndef RUST_HIR_TRAIT_RESOLVE_H
 #define RUST_HIR_TRAIT_RESOLVE_H
 
-#include "rust-hir-type-check-base.h"
 #include "rust-hir-type-check-type.h"
-#include "rust-hir-trait-ref.h"
 
 namespace Rust {
 namespace Resolver {
@@ -32,12 +30,7 @@ class ResolveTraitItemToRef : public TypeCheckBase,
 public:
   static TraitItemReference
   Resolve (HIR::TraitItem &item, TyTy::BaseType *self,
-	   std::vector<TyTy::SubstitutionParamMapping> substitutions)
-  {
-    ResolveTraitItemToRef resolver (self, std::move (substitutions));
-    item.accept_vis (resolver);
-    return std::move (resolver.resolved);
-  }
+	   std::vector<TyTy::SubstitutionParamMapping> substitutions);
 
   void visit (HIR::TraitItemType &type) override;
 
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index d1eb750a621..512453947a6 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -22,7 +22,7 @@
 #include "rust-hir-full-decls.h"
 #include "rust-hir-map.h"
 #include "rust-tyty.h"
-#include "rust-hir-trait-ref.h"
+#include "rust-hir-trait-reference.h"
 #include "rust-autoderef.h"
 
 namespace Rust {
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 61c02a85c53..4c324c66c16 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -27,7 +27,7 @@
 #include "rust-linemap.h"
 
 #include "rust-substitution-mapper.h"
-#include "rust-hir-trait-ref.h"
+#include "rust-hir-trait-reference.h"
 #include "rust-hir-type-bounds.h"
 #include "rust-hir-trait-resolve.h"
 #include "rust-tyty-rules.h"
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 46/88] gccrs: Refactor handle_substitutions to take a reference
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (44 preceding siblings ...)
  2023-04-05 14:03 ` [committed 45/88] gccrs: Rename header rust-hir-trait-ref.h to rust-hir-trait-reference.h arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 47/88] gccrs: Clear the substitution callbacks when copying ArgumentMappings arthur.cohen
                   ` (43 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

This patch changes the recusive substitution code to take a reference
instead of a copy. This is important as the callback field is going to be
made non-copyable in a future patch and this pipeline is for recursive
substitutions so its ok to reuse the same mappings here.

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* typecheck/rust-tyty-bounds.cc: refactor to take a reference
	* typecheck/rust-tyty-subst.cc: likewise
	(SubstitutionRef::get_substitution_arguments): likewise
	(SubstitutionRef::infer_substitions): likewise
	* typecheck/rust-tyty-subst.h: likewise
	* typecheck/rust-tyty.cc (ADTType::handle_substitions): likewise
	(TupleType::handle_substitions): likewise
	(FnType::handle_substitions): likewise
	(ClosureType::handle_substitions): likewise
	(ArrayType::handle_substitions): likewise
	(SliceType::handle_substitions): likewise
	(ReferenceType::handle_substitions): likewise
	(PointerType::handle_substitions): likewise
	(ParamType::handle_substitions): likewise
	(ProjectionType::handle_substitions): likewise
	* typecheck/rust-tyty.h: likewise
---
 gcc/rust/typecheck/rust-tyty-bounds.cc |  2 +-
 gcc/rust/typecheck/rust-tyty-subst.cc  | 10 ++++++++--
 gcc/rust/typecheck/rust-tyty-subst.h   |  5 +++--
 gcc/rust/typecheck/rust-tyty.cc        | 21 +++++++++++----------
 gcc/rust/typecheck/rust-tyty.h         | 22 +++++++++++-----------
 5 files changed, 34 insertions(+), 26 deletions(-)

diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc
index e7eb9a760f5..b14e0c68e5a 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -444,7 +444,7 @@ TypeBoundPredicate::is_error () const
 
 BaseType *
 TypeBoundPredicate::handle_substitions (
-  SubstitutionArgumentMappings subst_mappings)
+  SubstitutionArgumentMappings &subst_mappings)
 {
   for (auto &sub : get_substs ())
     {
diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc
index aceed29ff03..a5d738744fc 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -488,7 +488,13 @@ SubstitutionRef::was_substituted () const
   return !needs_substitution ();
 }
 
-SubstitutionArgumentMappings
+SubstitutionArgumentMappings &
+SubstitutionRef::get_substitution_arguments ()
+{
+  return used_arguments;
+}
+
+const SubstitutionArgumentMappings &
 SubstitutionRef::get_substitution_arguments () const
 {
   return used_arguments;
@@ -697,7 +703,7 @@ SubstitutionRef::infer_substitions (Location locus)
   SubstitutionArgumentMappings infer_arguments (std::move (args),
 						{} /* binding_arguments */,
 						locus);
-  return handle_substitions (std::move (infer_arguments));
+  return handle_substitions (infer_arguments);
 }
 
 SubstitutionArgumentMappings
diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h
index 4d09a3013e7..039eb36589e 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.h
+++ b/gcc/rust/typecheck/rust-tyty-subst.h
@@ -199,7 +199,8 @@ public:
 
   bool was_substituted () const;
 
-  SubstitutionArgumentMappings get_substitution_arguments () const;
+  SubstitutionArgumentMappings &get_substitution_arguments ();
+  const SubstitutionArgumentMappings &get_substitution_arguments () const;
 
   // this is the count of type params that are not substituted fuly
   size_t num_required_substitutions () const;
@@ -301,7 +302,7 @@ public:
   bool monomorphize ();
 
   // TODO comment
-  virtual BaseType *handle_substitions (SubstitutionArgumentMappings mappings)
+  virtual BaseType *handle_substitions (SubstitutionArgumentMappings &mappings)
     = 0;
 
   SubstitutionArgumentMappings get_used_arguments () const;
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 4c324c66c16..a3271eb0d1a 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -1148,7 +1148,7 @@ handle_substitions (SubstitutionArgumentMappings &subst_mappings,
 }
 
 ADTType *
-ADTType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
+ADTType::handle_substitions (SubstitutionArgumentMappings &subst_mappings)
 {
   ADTType *adt = static_cast<ADTType *> (clone ());
   adt->set_ty_ref (mappings->get_next_hir_id ());
@@ -1333,7 +1333,7 @@ TupleType::monomorphized_clone () const
 }
 
 TupleType *
-TupleType::handle_substitions (SubstitutionArgumentMappings mappings)
+TupleType::handle_substitions (SubstitutionArgumentMappings &mappings)
 {
   auto mappings_table = Analysis::Mappings::get ();
 
@@ -1474,7 +1474,7 @@ FnType::monomorphized_clone () const
 }
 
 FnType *
-FnType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
+FnType::handle_substitions (SubstitutionArgumentMappings &subst_mappings)
 {
   FnType *fn = static_cast<FnType *> (clone ());
   fn->set_ty_ref (mappings->get_next_hir_id ());
@@ -1742,7 +1742,7 @@ ClosureType::monomorphized_clone () const
 }
 
 ClosureType *
-ClosureType::handle_substitions (SubstitutionArgumentMappings mappings)
+ClosureType::handle_substitions (SubstitutionArgumentMappings &mappings)
 {
   gcc_unreachable ();
   return nullptr;
@@ -1862,7 +1862,7 @@ ArrayType::monomorphized_clone () const
 }
 
 ArrayType *
-ArrayType::handle_substitions (SubstitutionArgumentMappings mappings)
+ArrayType::handle_substitions (SubstitutionArgumentMappings &mappings)
 {
   auto mappings_table = Analysis::Mappings::get ();
 
@@ -1945,7 +1945,7 @@ SliceType::monomorphized_clone () const
 }
 
 SliceType *
-SliceType::handle_substitions (SubstitutionArgumentMappings mappings)
+SliceType::handle_substitions (SubstitutionArgumentMappings &mappings)
 {
   auto mappings_table = Analysis::Mappings::get ();
 
@@ -2704,7 +2704,7 @@ ReferenceType::monomorphized_clone () const
 }
 
 ReferenceType *
-ReferenceType::handle_substitions (SubstitutionArgumentMappings mappings)
+ReferenceType::handle_substitions (SubstitutionArgumentMappings &mappings)
 {
   auto mappings_table = Analysis::Mappings::get ();
 
@@ -2870,7 +2870,7 @@ PointerType::monomorphized_clone () const
 }
 
 PointerType *
-PointerType::handle_substitions (SubstitutionArgumentMappings mappings)
+PointerType::handle_substitions (SubstitutionArgumentMappings &mappings)
 {
   auto mappings_table = Analysis::Mappings::get ();
 
@@ -3047,7 +3047,7 @@ ParamType::is_equal (const BaseType &other) const
 }
 
 ParamType *
-ParamType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
+ParamType::handle_substitions (SubstitutionArgumentMappings &subst_mappings)
 {
   SubstitutionArg arg = SubstitutionArg::error ();
   bool ok = subst_mappings.get_argument_for_symbol (this, &arg);
@@ -3492,7 +3492,8 @@ ProjectionType::monomorphized_clone () const
 }
 
 ProjectionType *
-ProjectionType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
+ProjectionType::handle_substitions (
+  SubstitutionArgumentMappings &subst_mappings)
 {
   // // do we really need to substitute this?
   // if (base->needs_generic_substitutions () || base->contains_type_parameters
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 85b3a3b7abc..1cf7131c1cb 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -304,7 +304,7 @@ public:
 
   bool is_concrete () const override final;
 
-  ParamType *handle_substitions (SubstitutionArgumentMappings mappings);
+  ParamType *handle_substitions (SubstitutionArgumentMappings &mappings);
 
 private:
   std::string symbol;
@@ -379,7 +379,7 @@ public:
 
   std::string get_name () const override final;
 
-  TupleType *handle_substitions (SubstitutionArgumentMappings mappings);
+  TupleType *handle_substitions (SubstitutionArgumentMappings &mappings);
 
 private:
   std::vector<TyVar> fields;
@@ -427,7 +427,7 @@ public:
 
   // WARNING THIS WILL ALWAYS RETURN NULLPTR
   BaseType *
-  handle_substitions (SubstitutionArgumentMappings mappings) override final;
+  handle_substitions (SubstitutionArgumentMappings &mappings) override final;
 
   bool is_error () const;
 
@@ -682,7 +682,7 @@ public:
   }
 
   ADTType *
-  handle_substitions (SubstitutionArgumentMappings mappings) override final;
+  handle_substitions (SubstitutionArgumentMappings &mappings) override final;
 
 private:
   std::string identifier;
@@ -815,7 +815,7 @@ public:
   }
 
   FnType *
-  handle_substitions (SubstitutionArgumentMappings mappings) override final;
+  handle_substitions (SubstitutionArgumentMappings &mappings) override final;
 
   ABI get_abi () const { return abi; }
 
@@ -965,7 +965,7 @@ public:
   }
 
   ClosureType *
-  handle_substitions (SubstitutionArgumentMappings mappings) override final;
+  handle_substitions (SubstitutionArgumentMappings &mappings) override final;
 
   TyTy::TupleType &get_parameters () const { return *parameters; }
   TyTy::BaseType &get_result_type () const { return *result_type.get_tyty (); }
@@ -1024,7 +1024,7 @@ public:
 
   HIR::Expr &get_capacity_expr () const { return capacity_expr; }
 
-  ArrayType *handle_substitions (SubstitutionArgumentMappings mappings);
+  ArrayType *handle_substitions (SubstitutionArgumentMappings &mappings);
 
 private:
   TyVar element_type;
@@ -1070,7 +1070,7 @@ public:
     return get_element_type ()->is_concrete ();
   }
 
-  SliceType *handle_substitions (SubstitutionArgumentMappings mappings);
+  SliceType *handle_substitions (SubstitutionArgumentMappings &mappings);
 
 private:
   TyVar element_type;
@@ -1321,7 +1321,7 @@ public:
 
   bool is_concrete () const override final;
 
-  ReferenceType *handle_substitions (SubstitutionArgumentMappings mappings);
+  ReferenceType *handle_substitions (SubstitutionArgumentMappings &mappings);
 
   Mutability mutability () const;
 
@@ -1364,7 +1364,7 @@ public:
 
   bool is_concrete () const override final;
 
-  PointerType *handle_substitions (SubstitutionArgumentMappings mappings);
+  PointerType *handle_substitions (SubstitutionArgumentMappings &mappings);
 
   Mutability mutability () const;
   bool is_mutable () const;
@@ -1500,7 +1500,7 @@ public:
   bool is_concrete () const override final;
 
   ProjectionType *
-  handle_substitions (SubstitutionArgumentMappings mappings) override final;
+  handle_substitions (SubstitutionArgumentMappings &mappings) override final;
 
 private:
   BaseType *base;
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 47/88] gccrs: Clear the substitution callbacks when copying ArgumentMappings
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (45 preceding siblings ...)
  2023-04-05 14:03 ` [committed 46/88] gccrs: Refactor handle_substitutions to take a reference arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 48/88] gccrs: Add missing param subst callback arthur.cohen
                   ` (42 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

When we set the callback on substitutions this is not safe to be copied
around since we store the used argument mappings and can reuse them in
different contexts. This clears the callback on copy's to make it safer.

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* typecheck/rust-tyty-subst.cc: update copy constructors
---
 gcc/rust/typecheck/rust-tyty-subst.cc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc
index a5d738744fc..0e181efb359 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -241,7 +241,7 @@ SubstitutionArgumentMappings::SubstitutionArgumentMappings (
 SubstitutionArgumentMappings::SubstitutionArgumentMappings (
   const SubstitutionArgumentMappings &other)
   : mappings (other.mappings), binding_args (other.binding_args),
-    locus (other.locus), param_subst_cb (other.param_subst_cb),
+    locus (other.locus), param_subst_cb (nullptr),
     trait_item_flag (other.trait_item_flag)
 {}
 
@@ -252,7 +252,7 @@ SubstitutionArgumentMappings::operator= (
   mappings = other.mappings;
   binding_args = other.binding_args;
   locus = other.locus;
-  param_subst_cb = other.param_subst_cb;
+  param_subst_cb = nullptr;
   trait_item_flag = other.trait_item_flag;
 
   return *this;
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 48/88] gccrs: Add missing param subst callback
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (46 preceding siblings ...)
  2023-04-05 14:03 ` [committed 47/88] gccrs: Clear the substitution callbacks when copying ArgumentMappings arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 49/88] gccrs: Remove monomorphization hack to setup possible associated types arthur.cohen
                   ` (41 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* typecheck/rust-tyty-subst.cc: add missing callback
---
 gcc/rust/typecheck/rust-tyty-subst.cc | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc
index 0e181efb359..7f5bb22687d 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -141,6 +141,7 @@ SubstitutionParamMapping::fill_param_ty (
 	bound.handle_substitions (subst_mappings);
 
       param->set_ty_ref (type.get_ref ());
+      subst_mappings.on_param_subst (*param, arg);
     }
 
   return true;
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 49/88] gccrs: Remove monomorphization hack to setup possible associated types
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (47 preceding siblings ...)
  2023-04-05 14:03 ` [committed 48/88] gccrs: Add missing param subst callback arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 50/88] gccrs: Refactor the type unification code arthur.cohen
                   ` (40 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

During CallExpr argument type checking we may be calling a default
implementation of a trait function this will require any possible
associated types to be resolved and setup. This monomoprhization call does
this but it will premtivly do extra unification of types which will throw
off type checking later on. This fix is required for my work into type
bounds checking.

Fixes #1773

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* typecheck/rust-hir-trait-reference.h: change interface to return self
	* typecheck/rust-hir-trait-resolve.cc: likewise
	* typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::resolve_segments): likewise
	* typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit): remove monomorphization hack

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1773.rs: New test.
---
 gcc/rust/typecheck/rust-hir-trait-reference.h |  5 +--
 gcc/rust/typecheck/rust-hir-trait-resolve.cc  | 10 +++---
 .../typecheck/rust-hir-type-check-path.cc     | 36 ++++++++++++++-----
 gcc/rust/typecheck/rust-tyty-call.cc          |  1 -
 gcc/testsuite/rust/compile/issue-1773.rs      | 20 +++++++++++
 5 files changed, 56 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/issue-1773.rs

diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h b/gcc/rust/typecheck/rust-hir-trait-reference.h
index 0df35265959..9b4461b9f18 100644
--- a/gcc/rust/typecheck/rust-hir-trait-reference.h
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.h
@@ -497,8 +497,9 @@ public:
 
   TyTy::BaseType *get_self () { return self; }
 
-  void setup_associated_types (const TyTy::BaseType *self,
-			       const TyTy::TypeBoundPredicate &bound);
+  TyTy::BaseType *
+  setup_associated_types (const TyTy::BaseType *self,
+			  const TyTy::TypeBoundPredicate &bound);
 
   void reset_associated_types ();
 
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index e2d0cf2d7a2..6e23093eceb 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -377,13 +377,10 @@ TraitItemReference::associated_type_reset () const
   placeholder->clear_associated_type ();
 }
 
-void
+TyTy::BaseType *
 AssociatedImplTrait::setup_associated_types (
   const TyTy::BaseType *self, const TyTy::TypeBoundPredicate &bound)
 {
-  if (!bound.contains_associated_types ())
-    return;
-
   // compute the constrained impl block generic arguments based on self and the
   // higher ranked trait bound
   TyTy::BaseType *receiver = self->clone ();
@@ -486,6 +483,7 @@ AssociatedImplTrait::setup_associated_types (
     TyTy::TyWithLocation (receiver), TyTy::TyWithLocation (impl_self_infer),
     impl_predicate.get_locus ());
   rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
+  TyTy::BaseType *self_result = result;
 
   // unify the bounds arguments
   std::vector<TyTy::BaseType *> hrtb_bound_arguments;
@@ -500,7 +498,7 @@ AssociatedImplTrait::setup_associated_types (
     }
 
   if (impl_trait_predicate_args.size () != hrtb_bound_arguments.size ())
-    return;
+    return self_result;
 
   for (size_t i = 0; i < impl_trait_predicate_args.size (); i++)
     {
@@ -554,6 +552,8 @@ AssociatedImplTrait::setup_associated_types (
     resolved_trait_item->associated_type_set (substituted);
   });
   iter.go ();
+
+  return self_result;
 }
 
 void
diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc
index 6f1fd416c19..9d9b2949944 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-path.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -379,16 +379,36 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
 
       if (associated_impl_block != nullptr)
 	{
-	  // get the type of the parent Self
-	  HirId impl_ty_id
-	    = associated_impl_block->get_type ()->get_mappings ().get_hirid ();
+	  // associated types
+	  HirId impl_block_id
+	    = associated_impl_block->get_mappings ().get_hirid ();
+
+	  AssociatedImplTrait *associated = nullptr;
+	  bool found_impl_trait
+	    = context->lookup_associated_trait_impl (impl_block_id,
+						     &associated);
 	  TyTy::BaseType *impl_block_ty = nullptr;
-	  bool ok = query_type (impl_ty_id, &impl_block_ty);
-	  rust_assert (ok);
+	  if (found_impl_trait)
+	    {
+	      TyTy::TypeBoundPredicate predicate (*associated->get_trait (),
+						  seg.get_locus ());
+	      impl_block_ty
+		= associated->setup_associated_types (prev_segment, predicate);
+	    }
+	  else
+	    {
+	      // get the type of the parent Self
+	      HirId impl_ty_id = associated_impl_block->get_type ()
+				   ->get_mappings ()
+				   .get_hirid ();
 
-	  if (impl_block_ty->needs_generic_substitutions ())
-	    impl_block_ty
-	      = SubstMapper::InferSubst (impl_block_ty, seg.get_locus ());
+	      bool ok = query_type (impl_ty_id, &impl_block_ty);
+	      rust_assert (ok);
+
+	      if (impl_block_ty->needs_generic_substitutions ())
+		impl_block_ty
+		  = SubstMapper::InferSubst (impl_block_ty, seg.get_locus ());
+	    }
 
 	  prev_segment = unify_site (seg.get_mappings ().get_hirid (),
 				     TyTy::TyWithLocation (prev_segment),
diff --git a/gcc/rust/typecheck/rust-tyty-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc
index d520b595e43..4c6442e2d82 100644
--- a/gcc/rust/typecheck/rust-tyty-call.cc
+++ b/gcc/rust/typecheck/rust-tyty-call.cc
@@ -85,7 +85,6 @@ TypeCheckCallExpr::visit (ADTType &type)
 void
 TypeCheckCallExpr::visit (FnType &type)
 {
-  type.monomorphize ();
   if (call.num_params () != type.num_params ())
     {
       if (type.is_varadic ())
diff --git a/gcc/testsuite/rust/compile/issue-1773.rs b/gcc/testsuite/rust/compile/issue-1773.rs
new file mode 100644
index 00000000000..c627ac09cec
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1773.rs
@@ -0,0 +1,20 @@
+trait Foo<T> {
+    type A;
+
+    fn test(a: Self::A) -> Self::A {
+        a
+    }
+}
+
+struct Bar<T>(T);
+impl<T> Foo<T> for Bar<i32> {
+    type A = T;
+}
+
+fn main() {
+    let a;
+    a = Bar(123);
+
+    let b;
+    b = Bar::test(a.0);
+}
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 50/88] gccrs: Refactor the type unification code
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (48 preceding siblings ...)
  2023-04-05 14:03 ` [committed 49/88] gccrs: Remove monomorphization hack to setup possible associated types arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 51/88] gccrs: Fix nullptr dereference arthur.cohen
                   ` (39 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

This refactors the unification systems to be a consistent interface using
switch statements and simple functions instead of the old clunky visitor
system. This is more maintainable as it is harder to miss cases when we
can take advantages of switch statements.

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* Make-lang.in: update names
	* backend/rust-compile-expr.cc (CompileExpr::resolve_method_address):
	update to use new interface
	* typecheck/rust-coercion.cc (TypeCoercionRules::coerce_borrowed_pointer): likewise
	* typecheck/rust-hir-type-check-base.cc (TypeCheckBase::unify_site): likewise
	* typecheck/rust-tyty.cc (BaseType::destructure): likewise
	(InferType::unify): removed old unify interface
	(ErrorType::unify): likewise
	(ADTType::unify): likewise
	(TupleType::unify): likewise
	(FnType::unify): likewise
	(FnPtr::unify): likewise
	(ClosureType::unify): likewise
	(ArrayType::unify): likewise
	(SliceType::unify): likewise
	(BoolType::unify): likewise
	(IntType::unify): likewise
	(UintType::unify): likewise
	(FloatType::unify): likewise
	(USizeType::unify): likewise
	(ISizeType::unify): likewise
	(CharType::unify): likewise
	(ReferenceType::unify): likewise
	(PointerType::unify): likewise
	(ParamType::unify): likewise
	(StrType::unify): likewise
	(NeverType::unify): likewise
	(PlaceholderType::unify): likewise
	(ProjectionType::unify): likewise
	(DynamicObjectType::unify): likewise
	* typecheck/rust-tyty.h: update destructure interface
	* typecheck/rust-tyty-rules.h: Removed.
	* typecheck/rust-unify.cc: New file.
	* typecheck/rust-unify.h: New file.

gcc/testsuite/ChangeLog:

	* rust/compile/never_type_err1.rs: Moved to...
	* rust/compile/never_type1.rs: ...here. It now works
---
 gcc/rust/Make-lang.in                         |    1 +
 gcc/rust/backend/rust-compile-expr.cc         |    6 +-
 gcc/rust/typecheck/rust-coercion.cc           |    6 +-
 .../typecheck/rust-hir-type-check-base.cc     |   15 +-
 gcc/rust/typecheck/rust-tyty-rules.h          | 1406 --------------
 gcc/rust/typecheck/rust-tyty.cc               |  229 +--
 gcc/rust/typecheck/rust-tyty.h                |   31 +-
 gcc/rust/typecheck/rust-unify.cc              | 1640 +++++++++++++++++
 gcc/rust/typecheck/rust-unify.h               |   91 +
 .../{never_type_err1.rs => never_type1.rs}    |    3 +-
 10 files changed, 1807 insertions(+), 1621 deletions(-)
 delete mode 100644 gcc/rust/typecheck/rust-tyty-rules.h
 create mode 100644 gcc/rust/typecheck/rust-unify.cc
 create mode 100644 gcc/rust/typecheck/rust-unify.h
 rename gcc/testsuite/rust/compile/{never_type_err1.rs => never_type1.rs} (52%)

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 4752bb83562..1d2f34d7919 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -134,6 +134,7 @@ GRS_OBJS = \
     rust/rust-hir-path-probe.o \
     rust/rust-coercion.o \
     rust/rust-casts.o \
+    rust/rust-unify.o \
     rust/rust-hir-type-check-base.o \
     rust/rust-autoderef.o \
     rust/rust-substitution-mapper.o \
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index c26f6f440ec..d7945dbf26b 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -26,6 +26,7 @@
 #include "rust-compile-block.h"
 #include "rust-compile-implitem.h"
 #include "rust-constexpr.h"
+#include "rust-unify.h"
 #include "rust-gcc.h"
 
 #include "fold-const.h"
@@ -2006,7 +2007,10 @@ CompileExpr::resolve_method_address (TyTy::FnType *fntype, HirId ref,
 	{
 	  TyTy::BaseType *infer_impl_call
 	    = candidate_call->infer_substitions (expr_locus);
-	  monomorphized = infer_impl_call->unify (fntype);
+	  monomorphized = Resolver::UnifyRules::Resolve (
+	    TyTy::TyWithLocation (infer_impl_call),
+	    TyTy::TyWithLocation (fntype), expr_locus, true /* commit */,
+	    true /* emit_errors */);
 	}
 
       return CompileInherentImplItem::Compile (impl_item, ctx, monomorphized);
diff --git a/gcc/rust/typecheck/rust-coercion.cc b/gcc/rust/typecheck/rust-coercion.cc
index fdf8eb95a33..bea40840fbf 100644
--- a/gcc/rust/typecheck/rust-coercion.cc
+++ b/gcc/rust/typecheck/rust-coercion.cc
@@ -18,6 +18,7 @@
 
 #include "rust-hir-type-check-base.h"
 #include "rust-coercion.h"
+#include "rust-unify.h"
 
 namespace Rust {
 namespace Resolver {
@@ -218,7 +219,10 @@ TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType *receiver,
 	// we might be able to replace this with a can_eq because we default
 	// back to a final unity anyway
 	rust_debug ("coerce_borrowed_pointer -- unify");
-	TyTy::BaseType *result = receiver->unify (expected);
+	TyTy::BaseType *result
+	  = UnifyRules::Resolve (TyTy::TyWithLocation (receiver),
+				 TyTy::TyWithLocation (expected), locus,
+				 true /* commit */, true /* emit_errors */);
 	return CoercionResult{{}, result};
       }
     }
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc
index 85826aec8fe..6e42b7b7b23 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc
@@ -22,6 +22,7 @@
 #include "rust-hir-type-check-expr.h"
 #include "rust-hir-type-check-implitem.h"
 #include "rust-coercion.h"
+#include "rust-unify.h"
 #include "rust-casts.h"
 
 namespace Rust {
@@ -359,18 +360,8 @@ TypeCheckBase::unify_site (HirId id, TyTy::TyWithLocation lhs,
   rust_debug ("unify_site id={%u} expected={%s} expr={%s}", id,
 	      expected->debug_str ().c_str (), expr->debug_str ().c_str ());
 
-  TyTy::BaseType *unified = expected->unify (expr);
-  if (unified->get_kind () == TyTy::TypeKind::ERROR)
-    {
-      RichLocation r (unify_locus);
-      r.add_range (lhs.get_locus ());
-      r.add_range (rhs.get_locus ());
-      rust_error_at (r, "expected %<%s%> got %<%s%>",
-		     expected->get_name ().c_str (),
-		     expr->get_name ().c_str ());
-    }
-
-  return unified;
+  return UnifyRules::Resolve (lhs, rhs, unify_locus, true /*commit*/,
+			      true /*emit_error*/);
 }
 
 TyTy::BaseType *
diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h
deleted file mode 100644
index cfe269221bd..00000000000
--- a/gcc/rust/typecheck/rust-tyty-rules.h
+++ /dev/null
@@ -1,1406 +0,0 @@
-// Copyright (C) 2020-2023 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3.  If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_TYTY_RULES
-#define RUST_TYTY_RULES
-
-#include "rust-diagnostics.h"
-#include "rust-tyty.h"
-#include "rust-tyty-visitor.h"
-#include "rust-hir-map.h"
-#include "rust-hir-type-check.h"
-
-namespace Rust {
-namespace TyTy {
-
-/* Rules specify how to unify two Ty. For example, the result of unifying the
-   two tuples (u64, A) and (B, i64) would be (u64, i64).
-
-   Performing a unification requires a double dispatch. To illustrate, suppose
-   we want to unify `ty1` and `ty2`. Here's what it looks like:
-     1. The caller calls `ty1.unify(ty2)`. This is the first dispatch.
-     2. `ty1` creates a rule specific to its type(e.g. TupleRules).
-     3. The rule calls `ty2.accept_vis(rule)`. This is the second dispatch.
-     4. `ty2` calls `rule.visit(*this)`, which will method-overload to the
-	      correct implementation at compile time.
-
-   The nice thing about Rules is that they seperate unification logic from the
-   representation of Ty. To support unifying a new Ty, implement its
-   `accept_vis` and `unify` method to pass the unification request to Rules.
-   Then, create a new `XXXRules` class and implement one `visit` method for
-   every Ty it can unify with. */
-class BaseRules : public TyVisitor
-{
-public:
-  virtual ~BaseRules () {}
-
-  /* Unify two ty. Returns a pointer to the newly-created unified ty, or nullptr
-     if the two types cannot be unified. The caller is responsible for releasing
-     the memory of the returned ty.
-
-     This method is meant to be used internally by Ty. If you're trying to unify
-     two ty, you can simply call `unify` on ty themselves. */
-  virtual BaseType *unify (BaseType *other)
-  {
-    if (other->get_kind () == TypeKind::PARAM)
-      {
-	ParamType *p = static_cast<ParamType *> (other);
-	other = p->resolve ();
-      }
-    else if (other->get_kind () == TypeKind::PLACEHOLDER)
-      {
-	PlaceholderType *p = static_cast<PlaceholderType *> (other);
-	if (p->can_resolve ())
-	  {
-	    other = p->resolve ();
-	    return get_base ()->unify (other);
-	  }
-      }
-    else if (other->get_kind () == TypeKind::PROJECTION)
-      {
-	ProjectionType *p = static_cast<ProjectionType *> (other);
-	other = p->get ();
-	return get_base ()->unify (other);
-      }
-
-    other->accept_vis (*this);
-    if (resolved->get_kind () == TyTy::TypeKind::ERROR)
-      return resolved;
-
-    resolved->append_reference (get_base ()->get_ref ());
-    resolved->append_reference (other->get_ref ());
-    for (auto ref : get_base ()->get_combined_refs ())
-      resolved->append_reference (ref);
-    for (auto ref : other->get_combined_refs ())
-      resolved->append_reference (ref);
-
-    other->append_reference (resolved->get_ref ());
-    other->append_reference (get_base ()->get_ref ());
-    get_base ()->append_reference (resolved->get_ref ());
-    get_base ()->append_reference (other->get_ref ());
-
-    bool result_resolved = resolved->get_kind () != TyTy::TypeKind::INFER;
-    bool result_is_infer_var = resolved->get_kind () == TyTy::TypeKind::INFER;
-    bool results_is_non_general_infer_var
-      = (result_is_infer_var
-	 && (static_cast<InferType *> (resolved))->get_infer_kind ()
-	      != TyTy::InferType::GENERAL);
-    if (result_resolved || results_is_non_general_infer_var)
-      {
-	for (auto &ref : resolved->get_combined_refs ())
-	  {
-	    TyTy::BaseType *ref_tyty = nullptr;
-	    bool ok = context->lookup_type (ref, &ref_tyty);
-	    if (!ok)
-	      continue;
-
-	    // if any of the types are inference variables lets fix them
-	    if (ref_tyty->get_kind () == TyTy::TypeKind::INFER)
-	      {
-		context->insert_type (
-		  Analysis::NodeMapping (mappings->get_current_crate (),
-					 UNKNOWN_NODEID, ref,
-					 UNKNOWN_LOCAL_DEFID),
-		  resolved->clone ());
-	      }
-	  }
-      }
-    return resolved;
-  }
-
-  virtual void visit (TupleType &) override {}
-
-  virtual void visit (ADTType &) override {}
-
-  virtual void visit (InferType &) override {}
-
-  virtual void visit (FnType &) override {}
-
-  virtual void visit (FnPtr &) override {}
-
-  virtual void visit (ArrayType &) override {}
-
-  virtual void visit (SliceType &) override {}
-
-  virtual void visit (BoolType &) override {}
-
-  virtual void visit (IntType &) override {}
-
-  virtual void visit (UintType &) override {}
-
-  virtual void visit (USizeType &) override {}
-
-  virtual void visit (ISizeType &) override {}
-
-  virtual void visit (FloatType &) override {}
-
-  virtual void visit (ErrorType &) override {}
-
-  virtual void visit (CharType &) override {}
-
-  virtual void visit (ReferenceType &) override {}
-
-  virtual void visit (PointerType &) override {}
-
-  virtual void visit (ParamType &) override {}
-
-  virtual void visit (StrType &) override {}
-
-  virtual void visit (NeverType &) override {}
-
-  virtual void visit (PlaceholderType &) override {}
-
-  virtual void visit (ProjectionType &) override {}
-
-  virtual void visit (DynamicObjectType &) override {}
-
-  virtual void visit (ClosureType &) override {}
-
-protected:
-  BaseRules (BaseType *base)
-    : mappings (Analysis::Mappings::get ()),
-      context (Resolver::TypeCheckContext::get ()),
-      resolved (new ErrorType (base->get_ref (), base->get_ref ()))
-  {}
-
-  Analysis::Mappings *mappings;
-  Resolver::TypeCheckContext *context;
-
-  /* Temporary storage for the result of a unification.
-     We could return the result directly instead of storing it in the rule
-     object, but that involves modifying the visitor pattern to accommodate
-     the return value, which is too complex. */
-  BaseType *resolved;
-
-private:
-  /* Returns a pointer to the ty that created this rule. */
-  virtual BaseType *get_base () = 0;
-};
-
-class InferRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  InferRules (InferType *base) : BaseRules (base), base (base) {}
-
-  void visit (BoolType &type) override
-  {
-    bool is_valid
-      = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
-    if (is_valid)
-      {
-	resolved = type.clone ();
-	return;
-      }
-
-    BaseRules::visit (type);
-  }
-
-  void visit (IntType &type) override
-  {
-    bool is_valid
-      = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
-	|| (base->get_infer_kind ()
-	    == TyTy::InferType::InferTypeKind::INTEGRAL);
-    if (is_valid)
-      {
-	resolved = type.clone ();
-	return;
-      }
-
-    BaseRules::visit (type);
-  }
-
-  void visit (UintType &type) override
-  {
-    bool is_valid
-      = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
-	|| (base->get_infer_kind ()
-	    == TyTy::InferType::InferTypeKind::INTEGRAL);
-    if (is_valid)
-      {
-	resolved = type.clone ();
-	return;
-      }
-
-    BaseRules::visit (type);
-  }
-
-  void visit (USizeType &type) override
-  {
-    bool is_valid
-      = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
-	|| (base->get_infer_kind ()
-	    == TyTy::InferType::InferTypeKind::INTEGRAL);
-    if (is_valid)
-      {
-	resolved = type.clone ();
-	return;
-      }
-
-    BaseRules::visit (type);
-  }
-
-  void visit (ISizeType &type) override
-  {
-    bool is_valid
-      = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
-	|| (base->get_infer_kind ()
-	    == TyTy::InferType::InferTypeKind::INTEGRAL);
-    if (is_valid)
-      {
-	resolved = type.clone ();
-	return;
-      }
-
-    BaseRules::visit (type);
-  }
-
-  void visit (FloatType &type) override
-  {
-    bool is_valid
-      = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
-	|| (base->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT);
-    if (is_valid)
-      {
-	resolved = type.clone ();
-	return;
-      }
-
-    BaseRules::visit (type);
-  }
-
-  void visit (ArrayType &type) override
-  {
-    bool is_valid
-      = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
-    if (is_valid)
-      {
-	resolved = type.clone ();
-	return;
-      }
-
-    BaseRules::visit (type);
-  }
-
-  void visit (SliceType &type) override
-  {
-    bool is_valid
-      = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
-    if (is_valid)
-      {
-	resolved = type.clone ();
-	return;
-      }
-
-    BaseRules::visit (type);
-  }
-
-  void visit (ADTType &type) override
-  {
-    bool is_valid
-      = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
-    if (is_valid)
-      {
-	resolved = type.clone ();
-	return;
-      }
-
-    BaseRules::visit (type);
-  }
-
-  void visit (TupleType &type) override
-  {
-    bool is_valid
-      = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
-    if (is_valid)
-      {
-	resolved = type.clone ();
-	return;
-      }
-
-    BaseRules::visit (type);
-  }
-
-  void visit (InferType &type) override
-  {
-    switch (base->get_infer_kind ())
-      {
-      case InferType::InferTypeKind::GENERAL:
-	resolved = type.clone ();
-	return;
-
-	case InferType::InferTypeKind::INTEGRAL: {
-	  if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL)
-	    {
-	      resolved = type.clone ();
-	      return;
-	    }
-	  else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL)
-	    {
-	      resolved = base->clone ();
-	      return;
-	    }
-	}
-	break;
-
-	case InferType::InferTypeKind::FLOAT: {
-	  if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
-	    {
-	      resolved = type.clone ();
-	      return;
-	    }
-	  else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL)
-	    {
-	      resolved = base->clone ();
-	      return;
-	    }
-	}
-	break;
-      }
-
-    BaseRules::visit (type);
-  }
-
-  void visit (CharType &type) override
-  {
-    {
-      bool is_valid
-	= (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
-      if (is_valid)
-	{
-	  resolved = type.clone ();
-	  return;
-	}
-
-      BaseRules::visit (type);
-    }
-  }
-
-  void visit (ReferenceType &type) override
-  {
-    bool is_valid
-      = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
-    if (is_valid)
-      {
-	resolved = type.clone ();
-	return;
-      }
-
-    BaseRules::visit (type);
-  }
-
-  void visit (PointerType &type) override
-  {
-    bool is_valid
-      = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
-    if (is_valid)
-      {
-	resolved = type.clone ();
-	return;
-      }
-
-    BaseRules::visit (type);
-  }
-
-  void visit (ParamType &type) override
-  {
-    bool is_valid
-      = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
-    if (is_valid)
-      {
-	resolved = type.clone ();
-	return;
-      }
-
-    BaseRules::visit (type);
-  }
-
-  void visit (DynamicObjectType &type) override
-  {
-    bool is_valid
-      = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
-    if (is_valid)
-      {
-	resolved = type.clone ();
-	return;
-      }
-
-    BaseRules::visit (type);
-  }
-
-  void visit (ClosureType &type) override
-  {
-    bool is_valid
-      = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
-    if (is_valid)
-      {
-	resolved = type.clone ();
-	return;
-      }
-
-    BaseRules::visit (type);
-  }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  InferType *base;
-};
-
-class FnRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  FnRules (FnType *base) : BaseRules (base), base (base) {}
-
-  void visit (InferType &type) override
-  {
-    if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-    resolved->set_ref (type.get_ref ());
-  }
-
-  void visit (FnType &type) override
-  {
-    if (base->num_params () != type.num_params ())
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    for (size_t i = 0; i < base->num_params (); i++)
-      {
-	auto a = base->param_at (i).second;
-	auto b = type.param_at (i).second;
-
-	auto unified_param = a->unify (b);
-	if (unified_param == nullptr)
-	  {
-	    BaseRules::visit (type);
-	    return;
-	  }
-      }
-
-    auto unified_return
-      = base->get_return_type ()->unify (type.get_return_type ());
-    if (unified_return == nullptr)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-    resolved->set_ref (type.get_ref ());
-  }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  FnType *base;
-};
-
-class FnptrRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  FnptrRules (FnPtr *base) : BaseRules (base), base (base) {}
-
-  void visit (InferType &type) override
-  {
-    if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-    resolved->set_ref (type.get_ref ());
-  }
-
-  void visit (FnPtr &type) override
-  {
-    auto this_ret_type = base->get_return_type ();
-    auto other_ret_type = type.get_return_type ();
-    auto unified_result = this_ret_type->unify (other_ret_type);
-    if (unified_result == nullptr
-	|| unified_result->get_kind () == TypeKind::ERROR)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    if (base->num_params () != type.num_params ())
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    for (size_t i = 0; i < base->num_params (); i++)
-      {
-	auto this_param = base->param_at (i);
-	auto other_param = type.param_at (i);
-	auto unified_param = this_param->unify (other_param);
-	if (unified_param == nullptr
-	    || unified_param->get_kind () == TypeKind::ERROR)
-	  {
-	    BaseRules::visit (type);
-	    return;
-	  }
-      }
-
-    resolved = base->clone ();
-    resolved->set_ref (type.get_ref ());
-  }
-
-  void visit (FnType &type) override
-  {
-    auto this_ret_type = base->get_return_type ();
-    auto other_ret_type = type.get_return_type ();
-    auto unified_result = this_ret_type->unify (other_ret_type);
-    if (unified_result == nullptr
-	|| unified_result->get_kind () == TypeKind::ERROR)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    if (base->num_params () != type.num_params ())
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    for (size_t i = 0; i < base->num_params (); i++)
-      {
-	auto this_param = base->param_at (i);
-	auto other_param = type.param_at (i).second;
-	auto unified_param = this_param->unify (other_param);
-	if (unified_param == nullptr
-	    || unified_param->get_kind () == TypeKind::ERROR)
-	  {
-	    BaseRules::visit (type);
-	    return;
-	  }
-      }
-
-    resolved = base->clone ();
-    resolved->set_ref (type.get_ref ());
-  }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  FnPtr *base;
-};
-
-class ClosureRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  ClosureRules (ClosureType *base) : BaseRules (base), base (base) {}
-
-  void visit (InferType &type) override
-  {
-    if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-    resolved->set_ref (type.get_ref ());
-  }
-
-  void visit (ClosureType &type) override
-  {
-    if (base->get_def_id () != type.get_def_id ())
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    TyTy::BaseType *args_res
-      = base->get_parameters ().unify (&type.get_parameters ());
-    if (args_res == nullptr || args_res->get_kind () == TypeKind::ERROR)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    TyTy::BaseType *res
-      = base->get_result_type ().unify (&type.get_result_type ());
-    if (res == nullptr || res->get_kind () == TypeKind::ERROR)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-    resolved->set_ref (type.get_ref ());
-  }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  ClosureType *base;
-};
-
-class ArrayRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  ArrayRules (ArrayType *base) : BaseRules (base), base (base) {}
-
-  void visit (ArrayType &type) override
-  {
-    // check base type
-    auto base_resolved
-      = base->get_element_type ()->unify (type.get_element_type ());
-    if (base_resolved == nullptr)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved
-      = new ArrayType (type.get_ref (), type.get_ty_ref (),
-		       type.get_ident ().locus, type.get_capacity_expr (),
-		       TyVar (base_resolved->get_ref ()));
-  }
-
-  void visit (InferType &type) override
-  {
-    if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-    resolved->set_ref (type.get_ref ());
-  }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  ArrayType *base;
-};
-
-class SliceRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  SliceRules (SliceType *base) : BaseRules (base), base (base) {}
-
-  void visit (SliceType &type) override
-  {
-    // check base type
-    auto base_resolved
-      = base->get_element_type ()->unify (type.get_element_type ());
-    if (base_resolved == nullptr)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = new SliceType (type.get_ref (), type.get_ty_ref (),
-			      type.get_ident ().locus,
-			      TyVar (base_resolved->get_ref ()));
-  }
-
-  void visit (InferType &type) override
-  {
-    if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-    resolved->set_ref (type.get_ref ());
-  }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  SliceType *base;
-};
-
-class BoolRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  BoolRules (BoolType *base) : BaseRules (base), base (base) {}
-
-  void visit (BoolType &type) override
-  {
-    resolved = new BoolType (type.get_ref (), type.get_ty_ref ());
-  }
-
-  void visit (InferType &type) override
-  {
-    switch (type.get_infer_kind ())
-      {
-      case InferType::InferTypeKind::GENERAL:
-	resolved = base->clone ();
-	break;
-
-      default:
-	BaseRules::visit (type);
-	break;
-      }
-  }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  BoolType *base;
-};
-
-class IntRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  IntRules (IntType *base) : BaseRules (base), base (base) {}
-
-  void visit (InferType &type) override
-  {
-    // cant assign a float inference variable
-    if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-    resolved->set_ref (type.get_ref ());
-  }
-
-  void visit (IntType &type) override
-  {
-    if (type.get_int_kind () != base->get_int_kind ())
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved
-      = new IntType (type.get_ref (), type.get_ty_ref (), type.get_int_kind ());
-  }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  IntType *base;
-};
-
-class UintRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  UintRules (UintType *base) : BaseRules (base), base (base) {}
-
-  void visit (InferType &type) override
-  {
-    // cant assign a float inference variable
-    if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-    resolved->set_ref (type.get_ref ());
-  }
-
-  void visit (UintType &type) override
-  {
-    if (type.get_uint_kind () != base->get_uint_kind ())
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = new UintType (type.get_ref (), type.get_ty_ref (),
-			     type.get_uint_kind ());
-  }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  UintType *base;
-};
-
-class FloatRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  FloatRules (FloatType *base) : BaseRules (base), base (base) {}
-
-  void visit (InferType &type) override
-  {
-    if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-    resolved->set_ref (type.get_ref ());
-  }
-
-  void visit (FloatType &type) override
-  {
-    if (type.get_float_kind () != base->get_float_kind ())
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = new FloatType (type.get_ref (), type.get_ty_ref (),
-			      type.get_float_kind ());
-  }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  FloatType *base;
-};
-
-class ADTRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  ADTRules (ADTType *base) : BaseRules (base), base (base) {}
-
-  void visit (ADTType &type) override
-  {
-    if (base->get_adt_kind () != type.get_adt_kind ())
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    if (base->get_identifier ().compare (type.get_identifier ()) != 0)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    if (base->number_of_variants () != type.number_of_variants ())
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    for (size_t i = 0; i < type.number_of_variants (); ++i)
-      {
-	TyTy::VariantDef *a = base->get_variants ().at (i);
-	TyTy::VariantDef *b = type.get_variants ().at (i);
-
-	if (a->num_fields () != b->num_fields ())
-	  {
-	    BaseRules::visit (type);
-	    return;
-	  }
-
-	for (size_t j = 0; j < a->num_fields (); j++)
-	  {
-	    TyTy::StructFieldType *base_field = a->get_field_at_index (j);
-	    TyTy::StructFieldType *other_field = b->get_field_at_index (j);
-
-	    TyTy::BaseType *this_field_ty = base_field->get_field_type ();
-	    TyTy::BaseType *other_field_ty = other_field->get_field_type ();
-
-	    BaseType *unified_ty = this_field_ty->unify (other_field_ty);
-	    if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
-	      return;
-	  }
-      }
-
-    // generic args for the unit-struct case
-    if (type.is_unit () && base->is_unit ())
-      {
-	rust_assert (type.get_num_substitutions ()
-		     == base->get_num_substitutions ());
-
-	for (size_t i = 0; i < type.get_num_substitutions (); i++)
-	  {
-	    auto &a = base->get_substs ().at (i);
-	    auto &b = type.get_substs ().at (i);
-
-	    auto pa = a.get_param_ty ();
-	    auto pb = b.get_param_ty ();
-
-	    auto res = pa->unify (pb);
-	    if (res->get_kind () == TyTy::TypeKind::ERROR)
-	      {
-		return;
-	      }
-	  }
-      }
-
-    resolved = type.clone ();
-  }
-
-  void visit (InferType &type) override
-  {
-    if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-    resolved->set_ref (type.get_ref ());
-  }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  ADTType *base;
-};
-
-class TupleRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  TupleRules (TupleType *base) : BaseRules (base), base (base) {}
-
-  void visit (TupleType &type) override
-  {
-    if (base->num_fields () != type.num_fields ())
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    std::vector<TyVar> fields;
-    for (size_t i = 0; i < base->num_fields (); i++)
-      {
-	BaseType *bo = base->get_field (i);
-	BaseType *fo = type.get_field (i);
-
-	BaseType *unified_ty = bo->unify (fo);
-	if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
-	  return;
-
-	fields.push_back (TyVar (unified_ty->get_ref ()));
-      }
-
-    resolved = new TyTy::TupleType (type.get_ref (), type.get_ty_ref (),
-				    type.get_ident ().locus, fields);
-  }
-
-  void visit (InferType &type) override
-  {
-    if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-    resolved->set_ref (type.get_ref ());
-  }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  TupleType *base;
-};
-
-class USizeRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  USizeRules (USizeType *base) : BaseRules (base), base (base) {}
-
-  void visit (InferType &type) override
-  {
-    // cant assign a float inference variable
-    if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-    resolved->set_ref (type.get_ref ());
-  }
-
-  void visit (USizeType &type) override { resolved = type.clone (); }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  USizeType *base;
-};
-
-class ISizeRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  ISizeRules (ISizeType *base) : BaseRules (base), base (base) {}
-
-  void visit (InferType &type) override
-  {
-    // cant assign a float inference variable
-    if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-    resolved->set_ref (type.get_ref ());
-  }
-
-  void visit (ISizeType &type) override { resolved = type.clone (); }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  ISizeType *base;
-};
-
-class CharRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  CharRules (CharType *base) : BaseRules (base), base (base) {}
-
-  void visit (InferType &type) override
-  {
-    if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-    resolved->set_ref (type.get_ref ());
-  }
-
-  void visit (CharType &type) override { resolved = type.clone (); }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  CharType *base;
-};
-
-class ReferenceRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  ReferenceRules (ReferenceType *base) : BaseRules (base), base (base) {}
-
-  void visit (ReferenceType &type) override
-  {
-    auto base_type = base->get_base ();
-    auto other_base_type = type.get_base ();
-
-    TyTy::BaseType *base_resolved = base_type->unify (other_base_type);
-    if (base_resolved == nullptr
-	|| base_resolved->get_kind () == TypeKind::ERROR)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    // rust is permissive about mutablity here you can always go from mutable to
-    // immutable but not the otherway round
-    bool mutability_ok = base->is_mutable () ? type.is_mutable () : true;
-    if (!mutability_ok)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = new ReferenceType (base->get_ref (), base->get_ty_ref (),
-				  TyVar (base_resolved->get_ref ()),
-				  base->mutability ());
-  }
-
-  void visit (InferType &type) override
-  {
-    if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-    resolved->set_ref (type.get_ref ());
-  }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  ReferenceType *base;
-};
-
-class PointerRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  PointerRules (PointerType *base) : BaseRules (base), base (base) {}
-
-  void visit (PointerType &type) override
-  {
-    auto base_type = base->get_base ();
-    auto other_base_type = type.get_base ();
-
-    TyTy::BaseType *base_resolved = base_type->unify (other_base_type);
-    if (base_resolved == nullptr
-	|| base_resolved->get_kind () == TypeKind::ERROR)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    // rust is permissive about mutablity here you can always go from mutable to
-    // immutable but not the otherway round
-    bool mutability_ok = base->is_mutable () ? type.is_mutable () : true;
-    if (!mutability_ok)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = new PointerType (base->get_ref (), base->get_ty_ref (),
-				TyVar (base_resolved->get_ref ()),
-				base->mutability ());
-  }
-
-  void visit (InferType &type) override
-  {
-    if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-    resolved->set_ref (type.get_ref ());
-  }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  PointerType *base;
-};
-
-class ParamRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  ParamRules (ParamType *base) : BaseRules (base), base (base) {}
-
-  // param types are a placeholder we shouldn't have cases where we unify
-  // against it. eg: struct foo<T> { a: T }; When we invoke it we can do either:
-  //
-  // foo<i32>{ a: 123 }.
-  // Then this enforces the i32 type to be referenced on the
-  // field via an hirid.
-  //
-  // rust also allows for a = foo{a:123}; Where we can use an Inference Variable
-  // to handle the typing of the struct
-  BaseType *unify (BaseType *other) override final
-  {
-    if (!base->can_resolve ())
-      return BaseRules::unify (other);
-
-    auto lookup = base->resolve ();
-    return lookup->unify (other);
-  }
-
-  void visit (ParamType &type) override
-  {
-    if (base->get_symbol ().compare (type.get_symbol ()) != 0)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = type.clone ();
-  }
-
-  void visit (InferType &type) override
-  {
-    if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-  }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  ParamType *base;
-};
-
-class StrRules : public BaseRules
-{
-  // FIXME we will need a enum for the StrType like ByteBuf etc..
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  StrRules (StrType *base) : BaseRules (base), base (base) {}
-
-  void visit (StrType &type) override { resolved = type.clone (); }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  StrType *base;
-};
-
-class NeverRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  NeverRules (NeverType *base) : BaseRules (base), base (base) {}
-
-  void visit (NeverType &type) override { resolved = type.clone (); }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  NeverType *base;
-};
-
-class PlaceholderRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  PlaceholderRules (PlaceholderType *base) : BaseRules (base), base (base) {}
-
-  BaseType *unify (BaseType *other) override final
-  {
-    if (!base->can_resolve ())
-      return BaseRules::unify (other);
-
-    BaseType *lookup = base->resolve ();
-    return lookup->unify (other);
-  }
-
-  void visit (PlaceholderType &type) override
-  {
-    if (base->get_symbol ().compare (type.get_symbol ()) != 0)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = type.clone ();
-  }
-
-  void visit (InferType &type) override
-  {
-    if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-  }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  PlaceholderType *base;
-};
-
-class DynamicRules : public BaseRules
-{
-  using Rust::TyTy::BaseRules::visit;
-
-public:
-  DynamicRules (DynamicObjectType *base) : BaseRules (base), base (base) {}
-
-  void visit (InferType &type) override
-  {
-    if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-  }
-
-  void visit (DynamicObjectType &type) override
-  {
-    if (base->num_specified_bounds () != type.num_specified_bounds ())
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    if (!base->bounds_compatible (type, ref_locus, true))
-      {
-	BaseRules::visit (type);
-	return;
-      }
-
-    resolved = base->clone ();
-  }
-
-private:
-  BaseType *get_base () override { return base; }
-
-  DynamicObjectType *base;
-};
-
-} // namespace TyTy
-} // namespace Rust
-
-#endif // RUST_TYTY_RULES
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index a3271eb0d1a..fe5aa2b059c 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -30,7 +30,6 @@
 #include "rust-hir-trait-reference.h"
 #include "rust-hir-type-bounds.h"
 #include "rust-hir-trait-resolve.h"
-#include "rust-tyty-rules.h"
 #include "rust-tyty-cmp.h"
 
 #include "options.h"
@@ -376,6 +375,58 @@ BaseType::get_root () const
   return root;
 }
 
+BaseType *
+BaseType::destructure ()
+{
+  int recurisve_ops = 0;
+  BaseType *x = this;
+  while (true)
+    {
+      if (recurisve_ops++ >= rust_max_recursion_depth)
+	{
+	  rust_error_at (
+	    Location (),
+	    "%<recursion depth%> count exceeds limit of %i (use "
+	    "%<frust-max-recursion-depth=%> to increase the limit)",
+	    rust_max_recursion_depth);
+	  return new ErrorType (get_ref ());
+	}
+
+      switch (x->get_kind ())
+	{
+	  case TyTy::TypeKind::PARAM: {
+	    TyTy::ParamType *p = static_cast<TyTy::ParamType *> (x);
+	    TyTy::BaseType *pr = p->resolve ();
+	    if (pr == x)
+	      return pr;
+
+	    x = pr;
+	  }
+	  break;
+
+	  case TyTy::TypeKind::PLACEHOLDER: {
+	    TyTy::PlaceholderType *p = static_cast<TyTy::PlaceholderType *> (x);
+	    if (!p->can_resolve ())
+	      return p;
+
+	    x = p->resolve ();
+	  }
+	  break;
+
+	  case TyTy::TypeKind::PROJECTION: {
+	    TyTy::ProjectionType *p = static_cast<TyTy::ProjectionType *> (x);
+	    x = p->get ();
+	  }
+	  break;
+
+	default:
+	  return x;
+	}
+    }
+
+  return x;
+}
+
 const BaseType *
 BaseType::destructure () const
 {
@@ -397,14 +448,20 @@ BaseType::destructure () const
 	{
 	  case TyTy::TypeKind::PARAM: {
 	    const TyTy::ParamType *p = static_cast<const TyTy::ParamType *> (x);
-	    x = p->resolve ();
+	    const TyTy::BaseType *pr = p->resolve ();
+	    if (pr == x)
+	      return pr;
+
+	    x = pr;
 	  }
 	  break;
 
 	  case TyTy::TypeKind::PLACEHOLDER: {
 	    const TyTy::PlaceholderType *p
 	      = static_cast<const TyTy::PlaceholderType *> (x);
-	    rust_assert (p->can_resolve ());
+	    if (!p->can_resolve ())
+	      return p;
+
 	    x = p->resolve ();
 	  }
 	  break;
@@ -512,13 +569,6 @@ InferType::as_string () const
   return "<infer::error>";
 }
 
-BaseType *
-InferType::unify (BaseType *other)
-{
-  InferRules r (this);
-  return r.unify (other);
-}
-
 bool
 InferType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -637,12 +687,6 @@ ErrorType::as_string () const
   return "<tyty::error>";
 }
 
-BaseType *
-ErrorType::unify (BaseType *other)
-{
-  return this;
-}
-
 bool
 ErrorType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -1009,13 +1053,6 @@ ADTType::as_string () const
   return identifier + subst_as_string () + "{" + variants_buffer + "}";
 }
 
-BaseType *
-ADTType::unify (BaseType *other)
-{
-  ADTRules r (this);
-  return r.unify (other);
-}
-
 bool
 ADTType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -1278,13 +1315,6 @@ TupleType::get_field (size_t index) const
   return fields.at (index).get_tyty ();
 }
 
-BaseType *
-TupleType::unify (BaseType *other)
-{
-  TupleRules r (this);
-  return r.unify (other);
-}
-
 bool
 TupleType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -1385,13 +1415,6 @@ FnType::as_string () const
   return "fn" + subst_as_string () + " (" + params_str + ") -> " + ret_str;
 }
 
-BaseType *
-FnType::unify (BaseType *other)
-{
-  FnRules r (this);
-  return r.unify (other);
-}
-
 bool
 FnType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -1616,13 +1639,6 @@ FnPtr::as_string () const
   return "fnptr (" + params_str + ") -> " + get_return_type ()->as_string ();
 }
 
-BaseType *
-FnPtr::unify (BaseType *other)
-{
-  FnptrRules r (this);
-  return r.unify (other);
-}
-
 bool
 FnPtr::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -1696,13 +1712,6 @@ ClosureType::as_string () const
   return "|" + params_buf + "| {" + result_type.get_tyty ()->as_string () + "}";
 }
 
-BaseType *
-ClosureType::unify (BaseType *other)
-{
-  ClosureRules r (this);
-  return r.unify (other);
-}
-
 bool
 ClosureType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -1812,13 +1821,6 @@ ArrayType::as_string () const
   return "[" + get_element_type ()->as_string () + ":" + "CAPACITY" + "]";
 }
 
-BaseType *
-ArrayType::unify (BaseType *other)
-{
-  ArrayRules r (this);
-  return r.unify (other);
-}
-
 bool
 ArrayType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -1895,13 +1897,6 @@ SliceType::as_string () const
   return "[" + get_element_type ()->as_string () + "]";
 }
 
-BaseType *
-SliceType::unify (BaseType *other)
-{
-  SliceRules r (this);
-  return r.unify (other);
-}
-
 bool
 SliceType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -2006,13 +2001,6 @@ BoolType::as_string () const
   return "bool";
 }
 
-BaseType *
-BoolType::unify (BaseType *other)
-{
-  BoolRules r (this);
-  return r.unify (other);
-}
-
 bool
 BoolType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -2094,13 +2082,6 @@ IntType::as_string () const
   return "__unknown_int_type";
 }
 
-BaseType *
-IntType::unify (BaseType *other)
-{
-  IntRules r (this);
-  return r.unify (other);
-}
-
 bool
 IntType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -2200,13 +2181,6 @@ UintType::as_string () const
   return "__unknown_uint_type";
 }
 
-BaseType *
-UintType::unify (BaseType *other)
-{
-  UintRules r (this);
-  return r.unify (other);
-}
-
 bool
 UintType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -2306,13 +2280,6 @@ FloatType::as_string () const
   return "__unknown_float_type";
 }
 
-BaseType *
-FloatType::unify (BaseType *other)
-{
-  FloatRules r (this);
-  return r.unify (other);
-}
-
 bool
 FloatType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -2389,13 +2356,6 @@ USizeType::as_string () const
   return "usize";
 }
 
-BaseType *
-USizeType::unify (BaseType *other)
-{
-  USizeRules r (this);
-  return r.unify (other);
-}
-
 bool
 USizeType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -2461,13 +2421,6 @@ ISizeType::as_string () const
   return "isize";
 }
 
-BaseType *
-ISizeType::unify (BaseType *other)
-{
-  ISizeRules r (this);
-  return r.unify (other);
-}
-
 bool
 ISizeType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -2533,13 +2486,6 @@ CharType::as_string () const
   return "char";
 }
 
-BaseType *
-CharType::unify (BaseType *other)
-{
-  CharRules r (this);
-  return r.unify (other);
-}
-
 bool
 CharType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -2655,13 +2601,6 @@ ReferenceType::get_name () const
 	 + get_base ()->get_name ();
 }
 
-BaseType *
-ReferenceType::unify (BaseType *other)
-{
-  ReferenceRules r (this);
-  return r.unify (other);
-}
-
 bool
 ReferenceType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -2821,13 +2760,6 @@ PointerType::get_name () const
 	 + get_base ()->get_name ();
 }
 
-BaseType *
-PointerType::unify (BaseType *other)
-{
-  PointerRules r (this);
-  return r.unify (other);
-}
-
 bool
 PointerType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -2964,13 +2896,6 @@ ParamType::get_name () const
   return resolve ()->get_name ();
 }
 
-BaseType *
-ParamType::unify (BaseType *other)
-{
-  ParamRules r (this);
-  return r.unify (other);
-}
-
 bool
 ParamType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -3130,13 +3055,6 @@ StrType::as_string () const
   return "str";
 }
 
-BaseType *
-StrType::unify (BaseType *other)
-{
-  StrRules r (this);
-  return r.unify (other);
-}
-
 bool
 StrType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -3202,13 +3120,6 @@ NeverType::as_string () const
   return "!";
 }
 
-BaseType *
-NeverType::unify (BaseType *other)
-{
-  NeverRules r (this);
-  return r.unify (other);
-}
-
 bool
 NeverType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -3295,13 +3206,6 @@ PlaceholderType::as_string () const
 	 + ">";
 }
 
-BaseType *
-PlaceholderType::unify (BaseType *other)
-{
-  PlaceholderRules r (this);
-  return r.unify (other);
-}
-
 bool
 PlaceholderType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -3465,12 +3369,6 @@ ProjectionType::as_string () const
   return "<Projection=" + subst_as_string () + "::" + base->as_string () + ">";
 }
 
-BaseType *
-ProjectionType::unify (BaseType *other)
-{
-  return base->unify (other);
-}
-
 bool
 ProjectionType::can_eq (const BaseType *other, bool emit_errors) const
 {
@@ -3602,13 +3500,6 @@ DynamicObjectType::as_string () const
   return "dyn [" + raw_bounds_as_string () + "]";
 }
 
-BaseType *
-DynamicObjectType::unify (BaseType *other)
-{
-  DynamicRules r (this);
-  return r.unify (other);
-}
-
 bool
 DynamicObjectType::can_eq (const BaseType *other, bool emit_errors) const
 {
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 1cf7131c1cb..d2cf5b07fc1 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -105,11 +105,6 @@ public:
 
   virtual std::string get_name () const = 0;
 
-  // Unify two types. Returns a pointer to the newly-created unified ty, or
-  // nullptr if the two ty cannot be unified. The caller is responsible for
-  // releasing the memory of the returned ty.
-  virtual BaseType *unify (BaseType *other) = 0;
-
   // similar to unify but does not actually perform type unification but
   // determines whether they are compatible. Consider the following
   //
@@ -177,6 +172,7 @@ public:
 
   // This will get the monomorphized type from Params, Placeholders or
   // Projections if available or error
+  BaseType *destructure ();
   const BaseType *destructure () const;
 
   const RustIdent &get_ident () const;
@@ -221,8 +217,6 @@ public:
 
   std::string as_string () const override;
 
-  BaseType *unify (BaseType *other) override;
-
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   BaseType *clone () const final override;
@@ -255,7 +249,6 @@ public:
 
   std::string as_string () const override;
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   BaseType *clone () const final override;
@@ -284,7 +277,6 @@ public:
 
   std::string as_string () const override;
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   BaseType *clone () const final override;
@@ -361,7 +353,6 @@ public:
 
   std::string as_string () const override;
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   bool is_equal (const BaseType &other) const override;
@@ -598,7 +589,6 @@ public:
 
   std::string as_string () const override;
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   bool is_equal (const BaseType &other) const override;
@@ -738,7 +728,6 @@ public:
 
   std::string get_identifier () const { return identifier; }
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   bool is_equal (const BaseType &other) const override;
@@ -858,7 +847,6 @@ public:
 
   std::string as_string () const override;
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   bool is_equal (const BaseType &other) const override;
@@ -938,7 +926,6 @@ public:
   std::string as_string () const override;
   std::string get_name () const override final { return as_string (); }
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   bool is_equal (const BaseType &other) const override;
@@ -1007,7 +994,6 @@ public:
 
   std::string get_name () const override final { return as_string (); }
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   bool is_equal (const BaseType &other) const override;
@@ -1055,7 +1041,6 @@ public:
 
   std::string get_name () const override final { return as_string (); }
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   bool is_equal (const BaseType &other) const override;
@@ -1089,7 +1074,6 @@ public:
 
   std::string get_name () const override final;
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   BaseType *clone () const final override;
@@ -1120,7 +1104,6 @@ public:
 
   std::string get_name () const override final;
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   IntKind get_int_kind () const;
@@ -1159,7 +1142,6 @@ public:
 
   std::string get_name () const override final;
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   UintKind get_uint_kind () const;
@@ -1194,7 +1176,6 @@ public:
   std::string as_string () const override;
   std::string get_name () const override final;
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   FloatKind get_float_kind () const;
@@ -1222,7 +1203,6 @@ public:
   std::string as_string () const override;
   std::string get_name () const override final;
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   BaseType *clone () const final override;
@@ -1243,7 +1223,6 @@ public:
   std::string as_string () const override;
   std::string get_name () const override final;
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   BaseType *clone () const final override;
@@ -1263,7 +1242,6 @@ public:
   std::string as_string () const override;
   std::string get_name () const override final;
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   BaseType *clone () const final override;
@@ -1284,7 +1262,6 @@ public:
 
   std::string as_string () const override;
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   bool is_equal (const BaseType &other) const override;
@@ -1311,7 +1288,6 @@ public:
 
   std::string get_name () const override final;
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   bool is_equal (const BaseType &other) const override;
@@ -1354,7 +1330,6 @@ public:
   std::string as_string () const override;
   std::string get_name () const override final;
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   bool is_equal (const BaseType &other) const override;
@@ -1401,7 +1376,6 @@ public:
 
   std::string as_string () const override;
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   BaseType *clone () const final override;
@@ -1428,7 +1402,6 @@ public:
 
   std::string as_string () const override;
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   BaseType *clone () const final override;
@@ -1478,7 +1451,6 @@ public:
 
   std::string as_string () const override;
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   BaseType *clone () const final override;
@@ -1524,7 +1496,6 @@ public:
 
   std::string as_string () const override;
 
-  BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   bool is_equal (const BaseType &other) const override;
diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc
new file mode 100644
index 00000000000..072f76133bc
--- /dev/null
+++ b/gcc/rust/typecheck/rust-unify.cc
@@ -0,0 +1,1640 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-unify.h"
+
+namespace Rust {
+namespace Resolver {
+
+UnifyRules::UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
+			Location locus, bool commit_flag, bool emit_error)
+  : lhs (lhs), rhs (rhs), locus (locus), commit_flag (commit_flag),
+    emit_error (emit_error), mappings (*Analysis::Mappings::get ()),
+    context (*TypeCheckContext::get ())
+{}
+
+TyTy::BaseType *
+UnifyRules::Resolve (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
+		     Location locus, bool commit_flag, bool emit_error)
+{
+  UnifyRules r (lhs, rhs, locus, commit_flag, emit_error);
+  TyTy::BaseType *result = r.go ();
+
+  if (r.commit_flag)
+    r.commit (result);
+
+  bool failed = result->get_kind () == TyTy::TypeKind::ERROR;
+  if (failed && r.emit_error)
+    r.emit_type_mismatch ();
+
+  return result;
+}
+
+TyTy::BaseType *
+UnifyRules::get_base ()
+{
+  return lhs.get_ty ()->destructure ();
+}
+
+TyTy::BaseType *
+UnifyRules::get_other ()
+{
+  return rhs.get_ty ()->destructure ();
+}
+
+void
+UnifyRules::commit (TyTy::BaseType *resolved)
+{
+  resolved->append_reference (get_base ()->get_ref ());
+  resolved->append_reference (get_other ()->get_ref ());
+  for (auto ref : get_base ()->get_combined_refs ())
+    resolved->append_reference (ref);
+  for (auto ref : get_other ()->get_combined_refs ())
+    resolved->append_reference (ref);
+
+  get_other ()->append_reference (resolved->get_ref ());
+  get_other ()->append_reference (get_base ()->get_ref ());
+  get_base ()->append_reference (resolved->get_ref ());
+  get_base ()->append_reference (get_other ()->get_ref ());
+
+  bool result_resolved = resolved->get_kind () != TyTy::TypeKind::INFER;
+  bool result_is_infer_var = resolved->get_kind () == TyTy::TypeKind::INFER;
+  bool results_is_non_general_infer_var
+    = (result_is_infer_var
+       && (static_cast<TyTy::InferType *> (resolved))->get_infer_kind ()
+	    != TyTy::InferType::GENERAL);
+  if (result_resolved || results_is_non_general_infer_var)
+    {
+      for (auto &ref : resolved->get_combined_refs ())
+	{
+	  TyTy::BaseType *ref_tyty = nullptr;
+	  bool ok = context.lookup_type (ref, &ref_tyty);
+	  if (!ok)
+	    continue;
+
+	  // if any of the types are inference variables lets fix them
+	  if (ref_tyty->get_kind () == TyTy::TypeKind::INFER)
+	    {
+	      auto node = Analysis::NodeMapping (mappings.get_current_crate (),
+						 UNKNOWN_NODEID, ref,
+						 UNKNOWN_LOCAL_DEFID);
+	      context.insert_type (node, resolved->clone ());
+	    }
+	}
+    }
+}
+
+void
+UnifyRules::emit_type_mismatch () const
+{
+  TyTy::BaseType *expected = lhs.get_ty ();
+  TyTy::BaseType *expr = rhs.get_ty ();
+
+  RichLocation r (locus);
+  r.add_range (lhs.get_locus ());
+  r.add_range (rhs.get_locus ());
+  rust_error_at (r, "expected %<%s%> got %<%s%>",
+		 expected->get_name ().c_str (), expr->get_name ().c_str ());
+}
+
+TyTy::BaseType *
+UnifyRules::go ()
+{
+  TyTy::BaseType *ltype = lhs.get_ty ();
+  TyTy::BaseType *rtype = rhs.get_ty ();
+
+  ltype = lhs.get_ty ()->destructure ();
+  rtype = rhs.get_ty ()->destructure ();
+
+  rust_debug ("unify::go ltype={%s} rtype={%s}", ltype->debug_str ().c_str (),
+	      rtype->debug_str ().c_str ());
+
+  switch (ltype->get_kind ())
+    {
+    case TyTy::INFER:
+      return expect_inference_variable (static_cast<TyTy::InferType *> (ltype),
+					rtype);
+
+    case TyTy::ADT:
+      return expect_adt (static_cast<TyTy::ADTType *> (ltype), rtype);
+
+    case TyTy::STR:
+      return expect_str (static_cast<TyTy::StrType *> (ltype), rtype);
+
+    case TyTy::REF:
+      return expect_reference (static_cast<TyTy::ReferenceType *> (ltype),
+			       rtype);
+
+    case TyTy::POINTER:
+      return expect_pointer (static_cast<TyTy::PointerType *> (ltype), rtype);
+
+    case TyTy::PARAM:
+      return expect_param (static_cast<TyTy::ParamType *> (ltype), rtype);
+
+    case TyTy::ARRAY:
+      return expect_array (static_cast<TyTy::ArrayType *> (ltype), rtype);
+
+    case TyTy::SLICE:
+      return expect_slice (static_cast<TyTy::SliceType *> (ltype), rtype);
+
+    case TyTy::FNDEF:
+      return expect_fndef (static_cast<TyTy::FnType *> (ltype), rtype);
+
+    case TyTy::FNPTR:
+      return expect_fnptr (static_cast<TyTy::FnPtr *> (ltype), rtype);
+
+    case TyTy::TUPLE:
+      return expect_tuple (static_cast<TyTy::TupleType *> (ltype), rtype);
+
+    case TyTy::BOOL:
+      return expect_bool (static_cast<TyTy::BoolType *> (ltype), rtype);
+
+    case TyTy::CHAR:
+      return expect_char (static_cast<TyTy::CharType *> (ltype), rtype);
+
+    case TyTy::INT:
+      return expect_int (static_cast<TyTy::IntType *> (ltype), rtype);
+
+    case TyTy::UINT:
+      return expect_uint (static_cast<TyTy::UintType *> (ltype), rtype);
+
+    case TyTy::FLOAT:
+      return expect_float (static_cast<TyTy::FloatType *> (ltype), rtype);
+
+    case TyTy::USIZE:
+      return expect_usize (static_cast<TyTy::USizeType *> (ltype), rtype);
+
+    case TyTy::ISIZE:
+      return expect_isize (static_cast<TyTy::ISizeType *> (ltype), rtype);
+
+    case TyTy::NEVER:
+      return expect_never (static_cast<TyTy::NeverType *> (ltype), rtype);
+
+    case TyTy::PLACEHOLDER:
+      return expect_placeholder (static_cast<TyTy::PlaceholderType *> (ltype),
+				 rtype);
+
+    case TyTy::PROJECTION:
+      return expect_projection (static_cast<TyTy::ProjectionType *> (ltype),
+				rtype);
+
+    case TyTy::DYNAMIC:
+      return expect_dyn (static_cast<TyTy::DynamicObjectType *> (ltype), rtype);
+
+    case TyTy::CLOSURE:
+      return expect_closure (static_cast<TyTy::ClosureType *> (ltype), rtype);
+
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_inference_variable (TyTy::InferType *ltype,
+				       TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	switch (ltype->get_infer_kind ())
+	  {
+	  case TyTy::InferType::InferTypeKind::GENERAL:
+	    return rtype->clone ();
+
+	    case TyTy::InferType::InferTypeKind::INTEGRAL: {
+	      bool is_valid = r->get_infer_kind ()
+				== TyTy::InferType::InferTypeKind::INTEGRAL
+			      || r->get_infer_kind ()
+				   == TyTy::InferType::InferTypeKind::GENERAL;
+	      if (is_valid)
+		return rtype->clone ();
+	    }
+	    break;
+
+	    case TyTy::InferType::InferTypeKind::FLOAT: {
+	      bool is_valid
+		= r->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT
+		  || r->get_infer_kind ()
+		       == TyTy::InferType::InferTypeKind::GENERAL;
+	      if (is_valid)
+		return rtype->clone ();
+	    }
+	    break;
+	  }
+      }
+      break;
+
+    case TyTy::INT:
+    case TyTy::UINT:
+    case TyTy::USIZE:
+      case TyTy::ISIZE: {
+	bool is_valid = (ltype->get_infer_kind ()
+			 == TyTy::InferType::InferTypeKind::GENERAL)
+			|| (ltype->get_infer_kind ()
+			    == TyTy::InferType::InferTypeKind::INTEGRAL);
+	if (is_valid)
+	  return rtype->clone ();
+      }
+      break;
+
+      case TyTy::FLOAT: {
+	bool is_valid = (ltype->get_infer_kind ()
+			 == TyTy::InferType::InferTypeKind::GENERAL)
+			|| (ltype->get_infer_kind ()
+			    == TyTy::InferType::InferTypeKind::FLOAT);
+	if (is_valid)
+	  return rtype->clone ();
+      }
+      break;
+
+    case TyTy::ADT:
+    case TyTy::STR:
+    case TyTy::REF:
+    case TyTy::POINTER:
+    case TyTy::PARAM:
+    case TyTy::ARRAY:
+    case TyTy::SLICE:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+      case TyTy::CLOSURE: {
+	bool is_valid = (ltype->get_infer_kind ()
+			 == TyTy::InferType::InferTypeKind::GENERAL);
+	if (is_valid)
+	  return rtype->clone ();
+      }
+      break;
+
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+      case TyTy::ADT: {
+	TyTy::ADTType &type = *static_cast<TyTy::ADTType *> (rtype);
+	if (ltype->get_adt_kind () != type.get_adt_kind ())
+	  {
+	    return new TyTy::ErrorType (0);
+	  }
+
+	if (ltype->get_identifier ().compare (type.get_identifier ()) != 0)
+	  {
+	    return new TyTy::ErrorType (0);
+	  }
+
+	if (ltype->number_of_variants () != type.number_of_variants ())
+	  {
+	    return new TyTy::ErrorType (0);
+	  }
+
+	for (size_t i = 0; i < type.number_of_variants (); ++i)
+	  {
+	    TyTy::VariantDef *a = ltype->get_variants ().at (i);
+	    TyTy::VariantDef *b = type.get_variants ().at (i);
+
+	    if (a->num_fields () != b->num_fields ())
+	      {
+		return new TyTy::ErrorType (0);
+	      }
+
+	    for (size_t j = 0; j < a->num_fields (); j++)
+	      {
+		TyTy::StructFieldType *base_field = a->get_field_at_index (j);
+		TyTy::StructFieldType *other_field = b->get_field_at_index (j);
+
+		TyTy::BaseType *this_field_ty = base_field->get_field_type ();
+		TyTy::BaseType *other_field_ty = other_field->get_field_type ();
+
+		TyTy::BaseType *unified_ty
+		  = UnifyRules::Resolve (TyTy::TyWithLocation (this_field_ty),
+					 TyTy::TyWithLocation (other_field_ty),
+					 locus, commit_flag,
+					 false /* emit_error */);
+		if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
+		  {
+		    return new TyTy::ErrorType (0);
+		  }
+	      }
+	  }
+
+	// generic args for the unit-struct case
+	if (type.is_unit () && ltype->is_unit ())
+	  {
+	    rust_assert (type.get_num_substitutions ()
+			 == ltype->get_num_substitutions ());
+
+	    for (size_t i = 0; i < type.get_num_substitutions (); i++)
+	      {
+		auto &a = ltype->get_substs ().at (i);
+		auto &b = type.get_substs ().at (i);
+
+		auto pa = a.get_param_ty ();
+		auto pb = b.get_param_ty ();
+
+		auto res
+		  = UnifyRules::Resolve (TyTy::TyWithLocation (pa),
+					 TyTy::TyWithLocation (pb), locus,
+					 commit_flag, false /* emit_error */);
+		if (res->get_kind () == TyTy::TypeKind::ERROR)
+		  {
+		    return new TyTy::ErrorType (0);
+		  }
+	      }
+	  }
+
+	return type.clone ();
+      }
+      break;
+
+    case TyTy::STR:
+    case TyTy::REF:
+    case TyTy::POINTER:
+    case TyTy::PARAM:
+    case TyTy::ARRAY:
+    case TyTy::SLICE:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::UINT:
+    case TyTy::FLOAT:
+    case TyTy::USIZE:
+    case TyTy::ISIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_str (TyTy::StrType *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+    case TyTy::STR:
+      return rtype->clone ();
+
+    case TyTy::ADT:
+    case TyTy::REF:
+    case TyTy::POINTER:
+    case TyTy::PARAM:
+    case TyTy::ARRAY:
+    case TyTy::SLICE:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::UINT:
+    case TyTy::FLOAT:
+    case TyTy::USIZE:
+    case TyTy::ISIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+      case TyTy::REF: {
+	TyTy::ReferenceType &type = *static_cast<TyTy::ReferenceType *> (rtype);
+	auto base_type = ltype->get_base ();
+	auto other_base_type = type.get_base ();
+
+	TyTy::BaseType *base_resolved
+	  = UnifyRules::Resolve (TyTy::TyWithLocation (base_type),
+				 TyTy::TyWithLocation (other_base_type), locus,
+				 commit_flag, false /* emit_error */);
+	if (base_resolved->get_kind () == TyTy::TypeKind::ERROR)
+	  {
+	    return new TyTy::ErrorType (0);
+	  }
+
+	// rust is permissive about mutablity here you can always go from
+	// mutable to immutable but not the otherway round
+	bool mutability_ok = ltype->is_mutable () ? type.is_mutable () : true;
+	if (!mutability_ok)
+	  {
+	    return new TyTy::ErrorType (0);
+	  }
+
+	return new TyTy::ReferenceType (ltype->get_ref (), ltype->get_ty_ref (),
+					TyTy::TyVar (base_resolved->get_ref ()),
+					ltype->mutability ());
+      }
+      break;
+
+    case TyTy::STR:
+    case TyTy::ADT:
+    case TyTy::POINTER:
+    case TyTy::PARAM:
+    case TyTy::ARRAY:
+    case TyTy::SLICE:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::UINT:
+    case TyTy::FLOAT:
+    case TyTy::USIZE:
+    case TyTy::ISIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+      case TyTy::POINTER: {
+	TyTy::PointerType &type = *static_cast<TyTy::PointerType *> (rtype);
+	auto base_type = ltype->get_base ();
+	auto other_base_type = type.get_base ();
+
+	TyTy::BaseType *base_resolved
+	  = UnifyRules::Resolve (TyTy::TyWithLocation (base_type),
+				 TyTy::TyWithLocation (other_base_type), locus,
+				 commit_flag, false /* emit_error */);
+	if (base_resolved->get_kind () == TyTy::TypeKind::ERROR)
+	  {
+	    return new TyTy::ErrorType (0);
+	  }
+
+	// rust is permissive about mutablity here you can always go from
+	// mutable to immutable but not the otherway round
+	bool mutability_ok = ltype->is_mutable () ? type.is_mutable () : true;
+	if (!mutability_ok)
+	  {
+	    return new TyTy::ErrorType (0);
+	  }
+
+	return new TyTy::PointerType (ltype->get_ref (), ltype->get_ty_ref (),
+				      TyTy::TyVar (base_resolved->get_ref ()),
+				      ltype->mutability ());
+      }
+      break;
+
+    case TyTy::STR:
+    case TyTy::ADT:
+    case TyTy::REF:
+    case TyTy::PARAM:
+    case TyTy::ARRAY:
+    case TyTy::SLICE:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::UINT:
+    case TyTy::FLOAT:
+    case TyTy::USIZE:
+    case TyTy::ISIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+      case TyTy::PARAM: {
+	TyTy::ParamType &type = *static_cast<TyTy::ParamType *> (rtype);
+	// bool symbol_matches
+	//   = ltype->get_symbol ().compare (type.get_symbol ()) == 0;
+	// // TODO
+	// // I think rustc checks a debruinj index
+	// if (symbol_matches)
+	//   {
+	//     return type.clone ();
+	//   }
+
+	// matching symbol is not going to work when we mix symbol's and have
+	// nested generics
+
+	// bounds match? FIXME
+
+	return type.clone ();
+      }
+      break;
+
+    case TyTy::POINTER:
+    case TyTy::STR:
+    case TyTy::ADT:
+    case TyTy::REF:
+    case TyTy::ARRAY:
+    case TyTy::SLICE:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::UINT:
+    case TyTy::FLOAT:
+    case TyTy::USIZE:
+    case TyTy::ISIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+      case TyTy::ARRAY: {
+	TyTy::ArrayType &type = *static_cast<TyTy::ArrayType *> (rtype);
+	TyTy::BaseType *element_unify = UnifyRules::Resolve (
+	  TyTy::TyWithLocation (ltype->get_element_type ()),
+	  TyTy::TyWithLocation (type.get_element_type ()), locus, commit_flag,
+	  false /* emit_error*/);
+
+	if (element_unify->get_kind () != TyTy::TypeKind::ERROR)
+	  {
+	    return new TyTy::ArrayType (type.get_ref (), type.get_ty_ref (),
+					type.get_ident ().locus,
+					type.get_capacity_expr (),
+					TyTy::TyVar (
+					  element_unify->get_ref ()));
+	  }
+      }
+      break;
+
+    case TyTy::PARAM:
+    case TyTy::POINTER:
+    case TyTy::STR:
+    case TyTy::ADT:
+    case TyTy::REF:
+    case TyTy::SLICE:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::UINT:
+    case TyTy::FLOAT:
+    case TyTy::USIZE:
+    case TyTy::ISIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+      case TyTy::SLICE: {
+	TyTy::SliceType &type = *static_cast<TyTy::SliceType *> (rtype);
+	TyTy::BaseType *element_unify = UnifyRules::Resolve (
+	  TyTy::TyWithLocation (ltype->get_element_type ()),
+	  TyTy::TyWithLocation (type.get_element_type ()), locus, commit_flag,
+	  false /* emit_error*/);
+
+	if (element_unify->get_kind () != TyTy::TypeKind::ERROR)
+	  {
+	    return new TyTy::SliceType (type.get_ref (), type.get_ty_ref (),
+					type.get_ident ().locus,
+					TyTy::TyVar (
+					  element_unify->get_ref ()));
+	  }
+      }
+      break;
+
+    case TyTy::PARAM:
+    case TyTy::POINTER:
+    case TyTy::STR:
+    case TyTy::ADT:
+    case TyTy::REF:
+    case TyTy::ARRAY:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::UINT:
+    case TyTy::FLOAT:
+    case TyTy::USIZE:
+    case TyTy::ISIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+      case TyTy::FNDEF: {
+	TyTy::FnType &type = *static_cast<TyTy::FnType *> (rtype);
+	if (ltype->num_params () != type.num_params ())
+	  {
+	    return new TyTy::ErrorType (0);
+	  }
+
+	for (size_t i = 0; i < ltype->num_params (); i++)
+	  {
+	    auto a = ltype->param_at (i).second;
+	    auto b = type.param_at (i).second;
+
+	    auto unified_param
+	      = UnifyRules::Resolve (TyTy::TyWithLocation (a),
+				     TyTy::TyWithLocation (b), locus,
+				     commit_flag, false /* emit_errors */);
+	    if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
+	      {
+		return new TyTy::ErrorType (0);
+	      }
+	  }
+
+	auto unified_return
+	  = UnifyRules::Resolve (TyTy::TyWithLocation (
+				   ltype->get_return_type ()),
+				 TyTy::TyWithLocation (type.get_return_type ()),
+				 locus, commit_flag, false /* emit_errors */);
+	if (unified_return->get_kind () == TyTy::TypeKind::ERROR)
+	  {
+	    return new TyTy::ErrorType (0);
+	  }
+
+	return ltype->clone ();
+      }
+      break;
+
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::FLOAT:
+    case TyTy::ISIZE:
+    case TyTy::ADT:
+    case TyTy::STR:
+    case TyTy::REF:
+    case TyTy::POINTER:
+    case TyTy::PARAM:
+    case TyTy::ARRAY:
+    case TyTy::SLICE:
+    case TyTy::FNPTR:
+    case TyTy::UINT:
+    case TyTy::USIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+      case TyTy::FNPTR: {
+	TyTy::FnPtr &type = *static_cast<TyTy::FnPtr *> (rtype);
+	if (ltype->num_params () != type.num_params ())
+	  {
+	    return new TyTy::ErrorType (0);
+	  }
+
+	for (size_t i = 0; i < ltype->num_params (); i++)
+	  {
+	    auto a = ltype->param_at (i);
+	    auto b = type.param_at (i);
+
+	    auto unified_param
+	      = UnifyRules::Resolve (TyTy::TyWithLocation (a),
+				     TyTy::TyWithLocation (b), locus,
+				     commit_flag, false /* emit_errors */);
+	    if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
+	      {
+		return new TyTy::ErrorType (0);
+	      }
+	  }
+
+	auto unified_return
+	  = UnifyRules::Resolve (TyTy::TyWithLocation (
+				   ltype->get_return_type ()),
+				 TyTy::TyWithLocation (type.get_return_type ()),
+				 locus, commit_flag, false /* emit_errors */);
+	if (unified_return->get_kind () == TyTy::TypeKind::ERROR)
+	  {
+	    return new TyTy::ErrorType (0);
+	  }
+
+	return ltype->clone ();
+      }
+      break;
+
+      case TyTy::FNDEF: {
+	TyTy::FnType &type = *static_cast<TyTy::FnType *> (rtype);
+	auto this_ret_type = ltype->get_return_type ();
+	auto other_ret_type = type.get_return_type ();
+
+	auto unified_result
+	  = UnifyRules::Resolve (TyTy::TyWithLocation (this_ret_type),
+				 TyTy::TyWithLocation (other_ret_type), locus,
+				 commit_flag, false /*emit_errors*/);
+	if (unified_result->get_kind () == TyTy::TypeKind::ERROR)
+	  {
+	    return new TyTy::ErrorType (0);
+	  }
+
+	if (ltype->num_params () != type.num_params ())
+	  {
+	    return new TyTy::ErrorType (0);
+	  }
+
+	for (size_t i = 0; i < ltype->num_params (); i++)
+	  {
+	    auto this_param = ltype->param_at (i);
+	    auto other_param = type.param_at (i).second;
+
+	    auto unified_param
+	      = UnifyRules::Resolve (TyTy::TyWithLocation (this_param),
+				     TyTy::TyWithLocation (other_param), locus,
+				     commit_flag, false /* emit_errors */);
+	    if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
+	      {
+		return new TyTy::ErrorType (0);
+	      }
+	  }
+
+	return ltype->clone ();
+      }
+      break;
+
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::FLOAT:
+    case TyTy::ISIZE:
+    case TyTy::ADT:
+    case TyTy::STR:
+    case TyTy::REF:
+    case TyTy::POINTER:
+    case TyTy::PARAM:
+    case TyTy::ARRAY:
+    case TyTy::SLICE:
+    case TyTy::UINT:
+    case TyTy::USIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+      case TyTy::TUPLE: {
+	TyTy::TupleType &type = *static_cast<TyTy::TupleType *> (rtype);
+	if (ltype->num_fields () != type.num_fields ())
+	  {
+	    return new TyTy::ErrorType (0);
+	  }
+
+	std::vector<TyTy::TyVar> fields;
+	for (size_t i = 0; i < ltype->num_fields (); i++)
+	  {
+	    TyTy::BaseType *bo = ltype->get_field (i);
+	    TyTy::BaseType *fo = type.get_field (i);
+
+	    TyTy::BaseType *unified_ty
+	      = UnifyRules::Resolve (TyTy::TyWithLocation (bo),
+				     TyTy::TyWithLocation (fo), locus,
+				     commit_flag, false /* emit_errors */);
+	    if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
+	      return new TyTy::ErrorType (0);
+
+	    fields.push_back (TyTy::TyVar (unified_ty->get_ref ()));
+	  }
+
+	return new TyTy::TupleType (type.get_ref (), type.get_ty_ref (),
+				    type.get_ident ().locus, fields);
+      }
+      break;
+
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::FLOAT:
+    case TyTy::ISIZE:
+    case TyTy::ADT:
+    case TyTy::STR:
+    case TyTy::REF:
+    case TyTy::POINTER:
+    case TyTy::PARAM:
+    case TyTy::ARRAY:
+    case TyTy::SLICE:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::UINT:
+    case TyTy::USIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_bool (TyTy::BoolType *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+    case TyTy::BOOL:
+      return rtype->clone ();
+
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::FLOAT:
+    case TyTy::ISIZE:
+    case TyTy::ADT:
+    case TyTy::STR:
+    case TyTy::REF:
+    case TyTy::POINTER:
+    case TyTy::PARAM:
+    case TyTy::ARRAY:
+    case TyTy::SLICE:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::UINT:
+    case TyTy::USIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_char (TyTy::CharType *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+    case TyTy::CHAR:
+      return rtype->clone ();
+
+    case TyTy::INT:
+    case TyTy::FLOAT:
+    case TyTy::ISIZE:
+    case TyTy::ADT:
+    case TyTy::STR:
+    case TyTy::REF:
+    case TyTy::POINTER:
+    case TyTy::PARAM:
+    case TyTy::ARRAY:
+    case TyTy::SLICE:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::UINT:
+    case TyTy::USIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL
+	    || r->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+      case TyTy::INT: {
+	TyTy::IntType &type = *static_cast<TyTy::IntType *> (rtype);
+	bool is_valid = ltype->get_int_kind () == type.get_int_kind ();
+	if (is_valid)
+	  return new TyTy::IntType (type.get_ref (), type.get_ty_ref (),
+				    type.get_int_kind ());
+      }
+      break;
+
+    case TyTy::FLOAT:
+    case TyTy::ISIZE:
+    case TyTy::ADT:
+    case TyTy::STR:
+    case TyTy::REF:
+    case TyTy::POINTER:
+    case TyTy::PARAM:
+    case TyTy::ARRAY:
+    case TyTy::SLICE:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::UINT:
+    case TyTy::USIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL
+	    || r->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+      case TyTy::UINT: {
+	TyTy::UintType &type = *static_cast<TyTy::UintType *> (rtype);
+	bool is_valid = ltype->get_uint_kind () == type.get_uint_kind ();
+	if (is_valid)
+	  return new TyTy::UintType (type.get_ref (), type.get_ty_ref (),
+				     type.get_uint_kind ());
+      }
+      break;
+
+    case TyTy::FLOAT:
+    case TyTy::ISIZE:
+    case TyTy::ADT:
+    case TyTy::STR:
+    case TyTy::REF:
+    case TyTy::POINTER:
+    case TyTy::PARAM:
+    case TyTy::ARRAY:
+    case TyTy::SLICE:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::USIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL
+	    || r->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+      case TyTy::FLOAT: {
+	TyTy::FloatType &type = *static_cast<TyTy::FloatType *> (rtype);
+	bool is_valid = ltype->get_float_kind () == type.get_float_kind ();
+	if (is_valid)
+	  return new TyTy::FloatType (type.get_ref (), type.get_ty_ref (),
+				      type.get_float_kind ());
+      }
+      break;
+
+    case TyTy::ISIZE:
+    case TyTy::ADT:
+    case TyTy::STR:
+    case TyTy::REF:
+    case TyTy::POINTER:
+    case TyTy::PARAM:
+    case TyTy::ARRAY:
+    case TyTy::SLICE:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::UINT:
+    case TyTy::USIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_isize (TyTy::ISizeType *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () != TyTy::InferType::InferTypeKind::FLOAT;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+    case TyTy::ISIZE:
+      return rtype->clone ();
+
+    case TyTy::ADT:
+    case TyTy::STR:
+    case TyTy::REF:
+    case TyTy::POINTER:
+    case TyTy::PARAM:
+    case TyTy::ARRAY:
+    case TyTy::SLICE:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::UINT:
+    case TyTy::FLOAT:
+    case TyTy::USIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_usize (TyTy::USizeType *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () != TyTy::InferType::InferTypeKind::FLOAT;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+    case TyTy::USIZE:
+      return rtype->clone ();
+
+    case TyTy::ADT:
+    case TyTy::STR:
+    case TyTy::REF:
+    case TyTy::POINTER:
+    case TyTy::PARAM:
+    case TyTy::ARRAY:
+    case TyTy::SLICE:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::UINT:
+    case TyTy::FLOAT:
+    case TyTy::ISIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_never (TyTy::NeverType *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+    case TyTy::NEVER:
+      return rtype->clone ();
+
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::SLICE:
+    case TyTy::PARAM:
+    case TyTy::POINTER:
+    case TyTy::STR:
+    case TyTy::ADT:
+    case TyTy::REF:
+    case TyTy::ARRAY:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::UINT:
+    case TyTy::FLOAT:
+    case TyTy::USIZE:
+    case TyTy::ISIZE:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_placeholder (TyTy::PlaceholderType *ltype,
+				TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+      case TyTy::PLACEHOLDER: {
+	TyTy::PlaceholderType &type
+	  = *static_cast<TyTy::PlaceholderType *> (rtype);
+	bool symbol_match
+	  = ltype->get_symbol ().compare (type.get_symbol ()) == 0;
+	if (symbol_match)
+	  {
+	    return type.clone ();
+	  }
+      }
+      break;
+
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::SLICE:
+    case TyTy::PARAM:
+    case TyTy::POINTER:
+    case TyTy::STR:
+    case TyTy::ADT:
+    case TyTy::REF:
+    case TyTy::ARRAY:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::UINT:
+    case TyTy::FLOAT:
+    case TyTy::USIZE:
+    case TyTy::ISIZE:
+    case TyTy::NEVER:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_projection (TyTy::ProjectionType *ltype,
+			       TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+      // FIXME
+    case TyTy::PROJECTION:
+      gcc_unreachable ();
+      break;
+
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::SLICE:
+    case TyTy::PARAM:
+    case TyTy::POINTER:
+    case TyTy::STR:
+    case TyTy::ADT:
+    case TyTy::REF:
+    case TyTy::ARRAY:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::UINT:
+    case TyTy::FLOAT:
+    case TyTy::USIZE:
+    case TyTy::ISIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+      case TyTy::DYNAMIC: {
+	TyTy::DynamicObjectType &type
+	  = *static_cast<TyTy::DynamicObjectType *> (rtype);
+	if (ltype->num_specified_bounds () != type.num_specified_bounds ())
+	  {
+	    return new TyTy::ErrorType (0);
+	  }
+
+	if (!ltype->bounds_compatible (type, locus, true))
+	  {
+	    return new TyTy::ErrorType (0);
+	  }
+
+	return ltype->clone ();
+      }
+      break;
+
+    case TyTy::CLOSURE:
+    case TyTy::SLICE:
+    case TyTy::PARAM:
+    case TyTy::POINTER:
+    case TyTy::STR:
+    case TyTy::ADT:
+    case TyTy::REF:
+    case TyTy::ARRAY:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::UINT:
+    case TyTy::FLOAT:
+    case TyTy::USIZE:
+    case TyTy::ISIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+	TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+	bool is_valid
+	  = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+	if (is_valid)
+	  return ltype->clone ();
+      }
+      break;
+
+      case TyTy::CLOSURE: {
+	TyTy::ClosureType &type = *static_cast<TyTy::ClosureType *> (rtype);
+	if (ltype->get_def_id () != type.get_def_id ())
+	  {
+	    return new TyTy::ErrorType (0);
+	  }
+
+	TyTy::BaseType *args_res
+	  = UnifyRules::Resolve (TyTy::TyWithLocation (
+				   &ltype->get_parameters ()),
+				 TyTy::TyWithLocation (&type.get_parameters ()),
+				 locus, commit_flag, false /* emit_error */);
+	if (args_res->get_kind () == TyTy::TypeKind::ERROR)
+	  {
+	    return new TyTy::ErrorType (0);
+	  }
+
+	TyTy::BaseType *res = UnifyRules::Resolve (
+	  TyTy::TyWithLocation (&ltype->get_result_type ()),
+	  TyTy::TyWithLocation (&type.get_result_type ()), locus, commit_flag,
+	  false /* emit_error */);
+	if (res == nullptr || res->get_kind () == TyTy::TypeKind::ERROR)
+	  {
+	    return new TyTy::ErrorType (0);
+	  }
+
+	return ltype->clone ();
+      }
+      break;
+
+    case TyTy::SLICE:
+    case TyTy::PARAM:
+    case TyTy::POINTER:
+    case TyTy::STR:
+    case TyTy::ADT:
+    case TyTy::REF:
+    case TyTy::ARRAY:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::UINT:
+    case TyTy::FLOAT:
+    case TyTy::USIZE:
+    case TyTy::ISIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+} // namespace Resolver
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-unify.h b/gcc/rust/typecheck/rust-unify.h
new file mode 100644
index 00000000000..6e46b9642a6
--- /dev/null
+++ b/gcc/rust/typecheck/rust-unify.h
@@ -0,0 +1,91 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_UNIFY
+#define RUST_UNIFY
+
+#include "rust-tyty-util.h"
+#include "rust-hir-type-check.h"
+
+namespace Rust {
+namespace Resolver {
+
+class UnifyRules
+{
+public:
+  static TyTy::BaseType *Resolve (TyTy::TyWithLocation lhs,
+				  TyTy::TyWithLocation rhs, Location locus,
+				  bool commit_flag, bool emit_error);
+
+protected:
+  TyTy::BaseType *expect_inference_variable (TyTy::InferType *ltype,
+					     TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_str (TyTy::StrType *ltype, TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_reference (TyTy::ReferenceType *ltype,
+				    TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_pointer (TyTy::PointerType *ltype,
+				  TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_bool (TyTy::BoolType *ltype, TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_char (TyTy::CharType *ltype, TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_isize (TyTy::ISizeType *ltype, TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_usize (TyTy::USizeType *ltype, TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_never (TyTy::NeverType *ltype, TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_placeholder (TyTy::PlaceholderType *ltype,
+				      TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_projection (TyTy::ProjectionType *ltype,
+				     TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_dyn (TyTy::DynamicObjectType *ltype,
+			      TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_closure (TyTy::ClosureType *ltype,
+				  TyTy::BaseType *rtype);
+
+private:
+  UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
+	      Location locus, bool commit_flag, bool emit_error);
+
+  void emit_type_mismatch () const;
+  void commit (TyTy::BaseType *resolved);
+  TyTy::BaseType *go ();
+
+  TyTy::BaseType *get_base ();
+  TyTy::BaseType *get_other ();
+
+  TyTy::TyWithLocation lhs;
+  TyTy::TyWithLocation rhs;
+  Location locus;
+  bool commit_flag;
+  bool emit_error;
+
+  Analysis::Mappings &mappings;
+  TypeCheckContext &context;
+};
+
+} // namespace Resolver
+} // namespace Rust
+
+#endif // RUST_UNIFY
diff --git a/gcc/testsuite/rust/compile/never_type_err1.rs b/gcc/testsuite/rust/compile/never_type1.rs
similarity index 52%
rename from gcc/testsuite/rust/compile/never_type_err1.rs
rename to gcc/testsuite/rust/compile/never_type1.rs
index 52b1283fadf..8d56176fee3 100644
--- a/gcc/testsuite/rust/compile/never_type_err1.rs
+++ b/gcc/testsuite/rust/compile/never_type1.rs
@@ -1,8 +1,7 @@
 fn test() {
     let a;
 
-    // FIXME: Unimplemented features
-    a = if true { // { dg-error "expected .T.. got .!." }
+    a = if true {
         return;
     } else {
         return;
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 51/88] gccrs: Fix nullptr dereference
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (49 preceding siblings ...)
  2023-04-05 14:03 ` [committed 50/88] gccrs: Refactor the type unification code arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 52/88] gccrs: Add missing Sized, Copy and Clone lang item mappings arthur.cohen
                   ` (38 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

When we check if this is concrete the guard checks to ensure the argument
is non null but the check here is wrongly returning early when the check
is non null meaning when it is null and therefore not concrete it will
end up doing a null dereference.

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* typecheck/rust-tyty-subst.cc (SubstitutionArg::is_conrete): fix check
---
 gcc/rust/typecheck/rust-tyty-subst.cc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc
index 7f5bb22687d..996bbf2d885 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -213,8 +213,8 @@ SubstitutionArg::is_error () const
 bool
 SubstitutionArg::is_conrete () const
 {
-  if (argument != nullptr)
-    return true;
+  if (argument == nullptr)
+    return false;
 
   if (argument->get_kind () == TyTy::TypeKind::PARAM)
     return false;
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 52/88] gccrs: Add missing Sized, Copy and Clone lang item mappings
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (50 preceding siblings ...)
  2023-04-05 14:03 ` [committed 51/88] gccrs: Fix nullptr dereference arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 53/88] gccrs: Fix higher ranked trait bounds computation of self arthur.cohen
                   ` (37 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

We need these lang items to be defined and later down the line the mappings
will be used to implement proper copy and clone logic.

Fixes #1786

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* util/rust-lang-item.h:

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1786.rs: New test.
---
 gcc/rust/util/rust-lang-item.h           | 24 ++++++++++++++++++++++++
 gcc/testsuite/rust/compile/issue-1786.rs | 23 +++++++++++++++++++++++
 2 files changed, 47 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/issue-1786.rs

diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h
index 29c364bad61..c5ef6200fb4 100644
--- a/gcc/rust/util/rust-lang-item.h
+++ b/gcc/rust/util/rust-lang-item.h
@@ -80,6 +80,12 @@ public:
     FN_ONCE,
     FN_ONCE_OUTPUT,
 
+    // markers
+    COPY,
+    CLONE,
+    SIZED,
+
+    // delimiter
     UNKNOWN,
   };
 
@@ -237,6 +243,18 @@ public:
       {
 	return ItemType::FN_ONCE_OUTPUT;
       }
+    else if (item.compare ("copy") == 0)
+      {
+	return ItemType::COPY;
+      }
+    else if (item.compare ("clone") == 0)
+      {
+	return ItemType::CLONE;
+      }
+    else if (item.compare ("sized") == 0)
+      {
+	return ItemType::SIZED;
+      }
 
     return ItemType::UNKNOWN;
   }
@@ -321,6 +339,12 @@ public:
 	return "fn_once";
       case FN_ONCE_OUTPUT:
 	return "fn_once_output";
+      case COPY:
+	return "copy";
+      case CLONE:
+	return "clone";
+      case SIZED:
+	return "sized";
 
       case UNKNOWN:
 	return "<UNKNOWN>";
diff --git a/gcc/testsuite/rust/compile/issue-1786.rs b/gcc/testsuite/rust/compile/issue-1786.rs
new file mode 100644
index 00000000000..f73b63d0cb6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1786.rs
@@ -0,0 +1,23 @@
+#[lang = "clone"]
+trait Clone {
+    fn clone(&self) -> Self;
+
+    fn clone_from(&mut self, source: &Self) {
+        *self = source.clone()
+    }
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+    // Empty.
+}
+
+mod impls {
+    use super::Clone;
+
+    impl Clone for char {
+        fn clone(&self) -> Self {
+            *self
+        }
+    }
+}
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 53/88] gccrs: Fix higher ranked trait bounds computation of self
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (51 preceding siblings ...)
  2023-04-05 14:03 ` [committed 52/88] gccrs: Add missing Sized, Copy and Clone lang item mappings arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 54/88] gccrs: Remove bad error message on checking function arguments arthur.cohen
                   ` (36 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

This updates the higher ranked trait bounds computation to handle ambigious
cases. When we have a slice for example:

  let slice = &a[1..3];

This works by reusing the Index operator overload from libcore, so when the
index range of 1..3 is computed, the type system needs to compute what the
types of index are; this works by integer inference variables
Range<<integer>> that need to be unified with the impl Index for
Range<Usize> which computes the real type of usize for the index. This is
fine but what happens when we have the Copy and Clone traits bounds which
have implementations for all the primitive types i8, i16, i32, i64...
which is valid for any integer inference variable so the code prior to this
patch would have grabbed the first impl it would have found and used it
which is incorrect. When we have integer or float inference variables we
need to look for their respective defaults or emit an ambigious type bound
error.

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* typecheck/rust-hir-trait-reference.h: add const infterface
	* typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::get_generic_param): make const
	(SubstitutionRef::monomorphize): fix issue
	* typecheck/rust-tyty-subst.h: constify interface
---
 gcc/rust/typecheck/rust-hir-trait-reference.h |   1 +
 gcc/rust/typecheck/rust-tyty-subst.cc         | 107 ++++++++++++++++--
 gcc/rust/typecheck/rust-tyty-subst.h          |   2 +-
 3 files changed, 102 insertions(+), 8 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h b/gcc/rust/typecheck/rust-hir-trait-reference.h
index 9b4461b9f18..adb63b468d1 100644
--- a/gcc/rust/typecheck/rust-hir-trait-reference.h
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.h
@@ -496,6 +496,7 @@ public:
   HIR::ImplBlock *get_impl_block () { return impl; }
 
   TyTy::BaseType *get_self () { return self; }
+  const TyTy::BaseType *get_self () const { return self; }
 
   TyTy::BaseType *
   setup_associated_types (const TyTy::BaseType *self,
diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc
index 996bbf2d885..3dfe95873bc 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -65,7 +65,7 @@ SubstitutionParamMapping::get_param_ty () const
 }
 
 const HIR::TypeParam &
-SubstitutionParamMapping::get_generic_param ()
+SubstitutionParamMapping::get_generic_param () const
 {
   return generic;
 }
@@ -892,8 +892,7 @@ SubstitutionRef::monomorphize ()
 	  // setup any associated type mappings for the specified bonds and this
 	  // type
 	  auto candidates = Resolver::TypeBoundsProbe::Probe (binding);
-
-	  Resolver::AssociatedImplTrait *associated_impl_trait = nullptr;
+	  std::vector<Resolver::AssociatedImplTrait *> associated_impl_traits;
 	  for (auto &probed_bound : candidates)
 	    {
 	      const Resolver::TraitReference *bound_trait_ref
@@ -914,15 +913,109 @@ SubstitutionRef::monomorphize ()
 		    = associated->get_self ()->can_eq (binding, false);
 		  if (found_trait && found_self)
 		    {
-		      associated_impl_trait = associated;
-		      break;
+		      associated_impl_traits.push_back (associated);
 		    }
 		}
 	    }
 
-	  if (associated_impl_trait != nullptr)
+	  if (!associated_impl_traits.empty ())
 	    {
-	      associated_impl_trait->setup_associated_types (binding, bound);
+	      // This code is important when you look at slices for example when
+	      // you have a slice such as:
+	      //
+	      // let slice = &array[1..3]
+	      //
+	      // the higher ranked bounds will end up having an Index trait
+	      // implementation for Range<usize> so we need this code to resolve
+	      // that we have an integer inference variable that needs to become
+	      // a usize
+	      //
+	      // The other complicated issue is that we might have an intrinsic
+	      // which requires the :Clone or Copy bound but the libcore adds
+	      // implementations for all the integral types so when there are
+	      // multiple candidates we need to resolve to the default
+	      // implementation for that type otherwise its an error for
+	      // ambiguous type bounds
+
+	      if (associated_impl_traits.size () == 1)
+		{
+		  Resolver::AssociatedImplTrait *associate_impl_trait
+		    = associated_impl_traits.at (0);
+		  associate_impl_trait->setup_associated_types (binding, bound);
+		}
+	      else
+		{
+		  // if we have a non-general inference variable we need to be
+		  // careful about the selection here
+		  bool is_infer_var
+		    = binding->get_kind () == TyTy::TypeKind::INFER;
+		  bool is_integer_infervar
+		    = is_infer_var
+		      && static_cast<const TyTy::InferType *> (binding)
+			     ->get_infer_kind ()
+			   == TyTy::InferType::InferTypeKind::INTEGRAL;
+		  bool is_float_infervar
+		    = is_infer_var
+		      && static_cast<const TyTy::InferType *> (binding)
+			     ->get_infer_kind ()
+			   == TyTy::InferType::InferTypeKind::FLOAT;
+
+		  Resolver::AssociatedImplTrait *associate_impl_trait = nullptr;
+		  if (is_integer_infervar)
+		    {
+		      TyTy::BaseType *type = nullptr;
+		      bool ok = context->lookup_builtin ("i32", &type);
+		      rust_assert (ok);
+
+		      for (auto &impl : associated_impl_traits)
+			{
+			  bool found = impl->get_self ()->is_equal (*type);
+			  if (found)
+			    {
+			      associate_impl_trait = impl;
+			      break;
+			    }
+			}
+		    }
+		  else if (is_float_infervar)
+		    {
+		      TyTy::BaseType *type = nullptr;
+		      bool ok = context->lookup_builtin ("f64", &type);
+		      rust_assert (ok);
+
+		      for (auto &impl : associated_impl_traits)
+			{
+			  bool found = impl->get_self ()->is_equal (*type);
+			  if (found)
+			    {
+			      associate_impl_trait = impl;
+			      break;
+			    }
+			}
+		    }
+
+		  if (associate_impl_trait == nullptr)
+		    {
+		      // go for the first one? or error out?
+		      auto &mappings = *Analysis::Mappings::get ();
+		      const auto &type_param = subst.get_generic_param ();
+		      const auto *trait_ref = bound.get ();
+
+		      RichLocation r (type_param.get_locus ());
+		      r.add_range (bound.get_locus ());
+		      r.add_range (
+			mappings.lookup_location (binding->get_ref ()));
+
+		      rust_error_at (
+			r, "ambiguous type bound for trait %s and type %s",
+			trait_ref->get_name ().c_str (),
+			binding->get_name ().c_str ());
+
+		      return false;
+		    }
+
+		  associate_impl_trait->setup_associated_types (binding, bound);
+		}
 	    }
 	}
     }
diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h
index 039eb36589e..982861e9bc6 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.h
+++ b/gcc/rust/typecheck/rust-tyty-subst.h
@@ -48,7 +48,7 @@ public:
 
   const ParamType *get_param_ty () const;
 
-  const HIR::TypeParam &get_generic_param ();
+  const HIR::TypeParam &get_generic_param () const;
 
   // this is used for the backend to override the HirId ref of the param to
   // what the concrete type is for the rest of the context
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 54/88] gccrs: Remove bad error message on checking function arguments
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (52 preceding siblings ...)
  2023-04-05 14:03 ` [committed 53/88] gccrs: Fix higher ranked trait bounds computation of self arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 55/88] gccrs: Add general TypeBounds checks arthur.cohen
                   ` (35 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit): remove error message

gcc/testsuite/ChangeLog:

	* rust/compile/func3.rs: update test case
---
 gcc/rust/typecheck/rust-tyty-call.cc | 5 -----
 gcc/testsuite/rust/compile/func3.rs  | 1 -
 2 files changed, 6 deletions(-)

diff --git a/gcc/rust/typecheck/rust-tyty-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc
index 4c6442e2d82..67e2866cbce 100644
--- a/gcc/rust/typecheck/rust-tyty-call.cc
+++ b/gcc/rust/typecheck/rust-tyty-call.cc
@@ -140,8 +140,6 @@ TypeCheckCallExpr::visit (FnType &type)
 	    argument->get_locus ());
 	  if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
 	    {
-	      rust_error_at (argument->get_locus (),
-			     "Type Resolution failure on parameter");
 	      return;
 	    }
 	}
@@ -193,8 +191,6 @@ TypeCheckCallExpr::visit (FnPtr &type)
 	TyWithLocation (argument_expr_tyty, arg_locus), argument->get_locus ());
       if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
 	{
-	  rust_error_at (argument->get_locus (),
-			 "Type Resolution failure on parameter");
 	  return;
 	}
 
@@ -301,7 +297,6 @@ TypeCheckMethodCallExpr::check (FnType &type)
 	TyWithLocation (argument_expr_tyty, arg_locus), arg_locus);
       if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
 	{
-	  rust_error_at (arg_locus, "Type Resolution failure on parameter");
 	  return new ErrorType (type.get_ref ());
 	}
 
diff --git a/gcc/testsuite/rust/compile/func3.rs b/gcc/testsuite/rust/compile/func3.rs
index 2a329476118..002e5c90ab5 100644
--- a/gcc/testsuite/rust/compile/func3.rs
+++ b/gcc/testsuite/rust/compile/func3.rs
@@ -5,5 +5,4 @@ fn test(a: i32, b: i32) -> i32 {
 fn main() {
     let a = test(1, true);
     // { dg-error "expected .i32. got .bool." "" { target *-*-* } .-1 }
-    // { dg-error "Type Resolution failure on parameter" "" { target *-*-* } .-2 }
 }
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 55/88] gccrs: Add general TypeBounds checks
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (53 preceding siblings ...)
  2023-04-05 14:03 ` [committed 54/88] gccrs: Remove bad error message on checking function arguments arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 56/88] gccrs: Add support for TuplePattern in let statements arthur.cohen
                   ` (34 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

Existing tests are updated to use libcore copy and clone implementation.

Addresses #1725

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* typecheck/rust-unify.cc (UnifyRules::go): ensure the bounds are checked

gcc/testsuite/ChangeLog:

	* rust/compile/torture/intrinsics-4.rs: implement Copy trait
	* rust/compile/torture/intrinsics-5.rs: likewise
	* rust/execute/torture/atomic_load.rs: likewise
	* rust/execute/torture/atomic_store.rs: likewise
	* rust/bounds1.rs: New test.
---
 gcc/rust/typecheck/rust-unify.cc              | 11 ++++
 gcc/testsuite/rust/bounds1.rs                 | 19 ++++++
 .../rust/compile/torture/intrinsics-4.rs      | 63 +++++++++++++++++-
 .../rust/compile/torture/intrinsics-5.rs      | 66 ++++++++++++++++++-
 .../rust/execute/torture/atomic_load.rs       | 59 ++++++++++++++++-
 .../rust/execute/torture/atomic_store.rs      | 59 ++++++++++++++++-
 6 files changed, 271 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/rust/bounds1.rs

diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc
index 072f76133bc..415ffcdc6ea 100644
--- a/gcc/rust/typecheck/rust-unify.cc
+++ b/gcc/rust/typecheck/rust-unify.cc
@@ -124,6 +124,17 @@ UnifyRules::go ()
   rust_debug ("unify::go ltype={%s} rtype={%s}", ltype->debug_str ().c_str (),
 	      rtype->debug_str ().c_str ());
 
+  // check bounds
+  if (ltype->num_specified_bounds () > 0)
+    {
+      if (!ltype->bounds_compatible (*rtype, locus, true))
+	{
+	  // already emitted an error
+	  emit_error = false;
+	  return new TyTy::ErrorType (0);
+	}
+    }
+
   switch (ltype->get_kind ())
     {
     case TyTy::INFER:
diff --git a/gcc/testsuite/rust/bounds1.rs b/gcc/testsuite/rust/bounds1.rs
new file mode 100644
index 00000000000..665836088be
--- /dev/null
+++ b/gcc/testsuite/rust/bounds1.rs
@@ -0,0 +1,19 @@
+mod core {
+    mod ops {
+        #[lang = "add"]
+        pub trait Add<Rhs = Self> {
+            type Output;
+
+            fn add(self, rhs: Rhs) -> Self::Output;
+        }
+    }
+}
+
+pub fn foo<T: core::ops::Add<Output = i32>>(a: T) -> i32 {
+    // { dg-error "bounds not satisfied for f32 .Add. is not satisfied" "" { target *-*-* } .-1 }
+    a + a
+}
+
+pub fn main() {
+    foo(123f32);
+}
diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-4.rs b/gcc/testsuite/rust/compile/torture/intrinsics-4.rs
index 243d4460089..4e09f1089b0 100644
--- a/gcc/testsuite/rust/compile/torture/intrinsics-4.rs
+++ b/gcc/testsuite/rust/compile/torture/intrinsics-4.rs
@@ -1,10 +1,67 @@
-trait Copy {}
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {
+    fn clone(&self) -> Self;
+
+    fn clone_from(&mut self, source: &Self) {
+        *self = source.clone()
+    }
+}
+
+mod impls {
+    use super::Clone;
+
+    macro_rules! impl_clone {
+        ($($t:ty)*) => {
+            $(
+                impl Clone for $t {
+                    fn clone(&self) -> Self {
+                        *self
+                    }
+                }
+            )*
+        }
+    }
+
+    impl_clone! {
+        usize u8 u16 u32 u64 // u128
+        isize i8 i16 i32 i64 // i128
+        f32 f64
+        bool char
+    }
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+    // Empty.
+}
+
+mod copy_impls {
+    use super::Copy;
+
+    macro_rules! impl_copy {
+        ($($t:ty)*) => {
+            $(
+                impl Copy for $t {}
+            )*
+        }
+    }
+
+    impl_copy! {
+        usize u8 u16 u32 u64 // u128
+        isize i8 i16 i32 i64 // i128
+        f32 f64
+        bool char
+    }
+}
 
 extern "rust-intrinsic" {
     pub fn atomic_store_seqcst<T: Copy>(dst: *mut T, val: T);
     pub fn atomic_store_release<T: Copy>(dst: *mut T, val: T);
     pub fn atomic_store_relaxed<T: Copy>(dst: *mut T, val: T);
-    // pub fn atomic_store_unordered<T: Copy>(dst: *mut T, val: T);
+    pub fn atomic_store_unordered<T: Copy>(dst: *mut T, val: T);
 }
 
 fn main() {
@@ -15,6 +72,6 @@ fn main() {
         atomic_store_seqcst(&mut dst, new_value);
         atomic_store_release(&mut dst, new_value);
         atomic_store_relaxed(&mut dst, new_value);
-        // atomic_store_unordered(&mut dst, new_value);
+        atomic_store_unordered(&mut dst, new_value);
     }
 }
diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-5.rs b/gcc/testsuite/rust/compile/torture/intrinsics-5.rs
index 7fd84dcd635..ffad0bd3a85 100644
--- a/gcc/testsuite/rust/compile/torture/intrinsics-5.rs
+++ b/gcc/testsuite/rust/compile/torture/intrinsics-5.rs
@@ -1,4 +1,61 @@
-trait Copy {}
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {
+    fn clone(&self) -> Self;
+
+    fn clone_from(&mut self, source: &Self) {
+        *self = source.clone()
+    }
+}
+
+mod impls {
+    use super::Clone;
+
+    macro_rules! impl_clone {
+        ($($t:ty)*) => {
+            $(
+                impl Clone for $t {
+                    fn clone(&self) -> Self {
+                        *self
+                    }
+                }
+            )*
+        }
+    }
+
+    impl_clone! {
+        usize u8 u16 u32 u64 // u128
+        isize i8 i16 i32 i64 // i128
+        f32 f64
+        bool char
+    }
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+    // Empty.
+}
+
+mod copy_impls {
+    use super::Copy;
+
+    macro_rules! impl_copy {
+        ($($t:ty)*) => {
+            $(
+                impl Copy for $t {}
+            )*
+        }
+    }
+
+    impl_copy! {
+        usize u8 u16 u32 u64 // u128
+        isize i8 i16 i32 i64 // i128
+        f32 f64
+        bool char
+    }
+}
 
 extern "rust-intrinsic" {
     pub fn atomic_store_seqcst<T: Copy>(dst: *mut T, value: T);
@@ -24,6 +81,13 @@ impl VeryLargeType {
     }
 }
 
+impl Clone for VeryLargeType {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+impl Copy for VeryLargeType {}
+
 fn main() {
     let mut dst = VeryLargeType::new(0);
     let mut b = false;
diff --git a/gcc/testsuite/rust/execute/torture/atomic_load.rs b/gcc/testsuite/rust/execute/torture/atomic_load.rs
index 28ed8ae78f1..6e7383aa7e9 100644
--- a/gcc/testsuite/rust/execute/torture/atomic_load.rs
+++ b/gcc/testsuite/rust/execute/torture/atomic_load.rs
@@ -1,4 +1,61 @@
-trait Copy {}
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {
+    fn clone(&self) -> Self;
+
+    fn clone_from(&mut self, source: &Self) {
+        *self = source.clone()
+    }
+}
+
+mod impls {
+    use super::Clone;
+
+    macro_rules! impl_clone {
+        ($($t:ty)*) => {
+            $(
+                impl Clone for $t {
+                    fn clone(&self) -> Self {
+                        *self
+                    }
+                }
+            )*
+        }
+    }
+
+    impl_clone! {
+        usize u8 u16 u32 u64 // u128
+        isize i8 i16 i32 i64 // i128
+        f32 f64
+        bool char
+    }
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+    // Empty.
+}
+
+mod copy_impls {
+    use super::Copy;
+
+    macro_rules! impl_copy {
+        ($($t:ty)*) => {
+            $(
+                impl Copy for $t {}
+            )*
+        }
+    }
+
+    impl_copy! {
+        usize u8 u16 u32 u64 // u128
+        isize i8 i16 i32 i64 // i128
+        f32 f64
+        bool char
+    }
+}
 
 extern "rust-intrinsic" {
     pub fn atomic_load_seqcst<T: Copy>(src: *const T) -> T;
diff --git a/gcc/testsuite/rust/execute/torture/atomic_store.rs b/gcc/testsuite/rust/execute/torture/atomic_store.rs
index 9f248b4f823..46960a7a186 100644
--- a/gcc/testsuite/rust/execute/torture/atomic_store.rs
+++ b/gcc/testsuite/rust/execute/torture/atomic_store.rs
@@ -1,4 +1,61 @@
-trait Copy {}
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {
+    fn clone(&self) -> Self;
+
+    fn clone_from(&mut self, source: &Self) {
+        *self = source.clone()
+    }
+}
+
+mod impls {
+    use super::Clone;
+
+    macro_rules! impl_clone {
+        ($($t:ty)*) => {
+            $(
+                impl Clone for $t {
+                    fn clone(&self) -> Self {
+                        *self
+                    }
+                }
+            )*
+        }
+    }
+
+    impl_clone! {
+        usize u8 u16 u32 u64 // u128
+        isize i8 i16 i32 i64 // i128
+        f32 f64
+        bool char
+    }
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+    // Empty.
+}
+
+mod copy_impls {
+    use super::Copy;
+
+    macro_rules! impl_copy {
+        ($($t:ty)*) => {
+            $(
+                impl Copy for $t {}
+            )*
+        }
+    }
+
+    impl_copy! {
+        usize u8 u16 u32 u64 // u128
+        isize i8 i16 i32 i64 // i128
+        f32 f64
+        bool char
+    }
+}
 
 extern "rust-intrinsic" {
     pub fn atomic_store_seqcst<T: Copy>(dst: *mut T, val: T);
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 56/88] gccrs: Add support for TuplePattern in let statements
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (54 preceding siblings ...)
  2023-04-05 14:03 ` [committed 55/88] gccrs: Add general TypeBounds checks arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 57/88] gccrs: rust-item: include rust-expr.h arthur.cohen
                   ` (33 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Owen Avery

From: Owen Avery <powerboat9.gamer@gmail.com>

gcc/rust/ChangeLog:

	* hir/tree/rust-hir-pattern.h
	(TuplePatternItemsRanged::get_lower_patterns): Add method.
	(TuplePatternItemsRanged::get_upper_patterns): Add method.
	* backend/rust-compile-pattern.cc
	(CompilePatternLet::visit): Implement TuplePattern visitor.
	* backend/rust-compile-pattern.h
	(CompilePatternLet::visit): Move TuplePattern visitor out of header file.

gcc/testsuite/ChangeLog:

	* rust/execute/torture/let-pattern-1.rs: New test.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
---
 gcc/rust/backend/rust-compile-pattern.cc      | 87 +++++++++++++++++++
 gcc/rust/backend/rust-compile-pattern.h       |  7 +-
 gcc/rust/hir/tree/rust-hir-pattern.h          | 18 ++++
 .../rust/execute/torture/let-pattern-1.rs     |  4 +
 4 files changed, 110 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/rust/execute/torture/let-pattern-1.rs

diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc
index bad98be44d0..cb4b082f9c8 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -387,5 +387,92 @@ CompilePatternLet::visit (HIR::WildcardPattern &pattern)
     }
 }
 
+void
+CompilePatternLet::visit (HIR::TuplePattern &pattern)
+{
+  rust_assert (pattern.has_tuple_pattern_items ());
+
+  tree tuple_type = TyTyResolveCompile::compile (ctx, ty);
+  tree init_stmt;
+  Bvariable *tmp_var
+    = ctx->get_backend ()->temporary_variable (ctx->peek_fn ().fndecl,
+					       NULL_TREE, tuple_type, init_expr,
+					       false, pattern.get_locus (),
+					       &init_stmt);
+  tree access_expr
+    = ctx->get_backend ()->var_expression (tmp_var, pattern.get_locus ());
+  ctx->add_statement (init_stmt);
+
+  switch (pattern.get_items ()->get_pattern_type ())
+    {
+      case HIR::TuplePatternItems::TuplePatternItemType::RANGED: {
+	size_t tuple_idx = 0;
+	auto &items
+	  = static_cast<HIR::TuplePatternItemsRanged &> (*pattern.get_items ());
+
+	auto &items_lower = items.get_lower_patterns ();
+	auto &items_upper = items.get_upper_patterns ();
+
+	for (auto &sub : items_lower)
+	  {
+	    TyTy::BaseType *ty_sub = nullptr;
+	    HirId pattern_id = pattern.get_pattern_mappings ().get_hirid ();
+	    bool ok = ctx->get_tyctx ()->lookup_type (pattern_id, &ty_sub);
+	    rust_assert (ok);
+
+	    tree sub_init = ctx->get_backend ()->struct_field_expression (
+	      access_expr, tuple_idx, sub->get_locus ());
+	    CompilePatternLet::Compile (sub.get (), sub_init, ty_sub,
+					rval_locus, ctx);
+	    tuple_idx++;
+	  }
+
+	rust_assert (ty->get_kind () == TyTy::TypeKind::TUPLE);
+	tuple_idx = static_cast<TyTy::TupleType &> (*ty).num_fields ()
+		    - items_upper.size ();
+
+	for (auto &sub : items_upper)
+	  {
+	    TyTy::BaseType *ty_sub = nullptr;
+	    HirId pattern_id = pattern.get_pattern_mappings ().get_hirid ();
+	    bool ok = ctx->get_tyctx ()->lookup_type (pattern_id, &ty_sub);
+	    rust_assert (ok);
+
+	    tree sub_init = ctx->get_backend ()->struct_field_expression (
+	      access_expr, tuple_idx, sub->get_locus ());
+	    CompilePatternLet::Compile (sub.get (), sub_init, ty_sub,
+					rval_locus, ctx);
+	    tuple_idx++;
+	  }
+
+	return;
+      }
+      case HIR::TuplePatternItems::TuplePatternItemType::MULTIPLE: {
+	size_t tuple_idx = 0;
+	auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
+	  *pattern.get_items ());
+
+	for (auto &sub : items.get_patterns ())
+	  {
+	    TyTy::BaseType *ty_sub = nullptr;
+	    HirId pattern_id = pattern.get_pattern_mappings ().get_hirid ();
+	    bool ok = ctx->get_tyctx ()->lookup_type (pattern_id, &ty_sub);
+	    rust_assert (ok);
+
+	    tree sub_init = ctx->get_backend ()->struct_field_expression (
+	      access_expr, tuple_idx, sub->get_locus ());
+	    CompilePatternLet::Compile (sub.get (), sub_init, ty_sub,
+					rval_locus, ctx);
+	    tuple_idx++;
+	  }
+
+	return;
+      }
+      default: {
+	gcc_unreachable ();
+      }
+    }
+}
+
 } // namespace Compile
 } // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-pattern.h b/gcc/rust/backend/rust-compile-pattern.h
index ddf5b14265e..8f44b7b5dbb 100644
--- a/gcc/rust/backend/rust-compile-pattern.h
+++ b/gcc/rust/backend/rust-compile-pattern.h
@@ -101,6 +101,7 @@ public:
 
   void visit (HIR::IdentifierPattern &) override;
   void visit (HIR::WildcardPattern &) override;
+  void visit (HIR::TuplePattern &) override;
 
   // check for unimplemented Pattern HIR nodes.
   void visit (HIR::LiteralPattern &pattern) override
@@ -146,12 +147,6 @@ public:
 		   "struct pattern let statements not supported");
   }
 
-  void visit (HIR::TuplePattern &pattern) override
-  {
-    rust_sorry_at (pattern.get_locus (),
-		   "tuple pattern let statements not supported");
-  }
-
   void visit (HIR::TupleStructPattern &pattern) override
   {
     rust_sorry_at (pattern.get_locus (),
diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h
index 83b041d2770..1b08ab88a34 100644
--- a/gcc/rust/hir/tree/rust-hir-pattern.h
+++ b/gcc/rust/hir/tree/rust-hir-pattern.h
@@ -1142,6 +1142,24 @@ public:
     return TuplePatternItemType::RANGED;
   }
 
+  std::vector<std::unique_ptr<Pattern> > &get_lower_patterns ()
+  {
+    return lower_patterns;
+  }
+  const std::vector<std::unique_ptr<Pattern> > &get_lower_patterns () const
+  {
+    return lower_patterns;
+  }
+
+  std::vector<std::unique_ptr<Pattern> > &get_upper_patterns ()
+  {
+    return upper_patterns;
+  }
+  const std::vector<std::unique_ptr<Pattern> > &get_upper_patterns () const
+  {
+    return upper_patterns;
+  }
+
 protected:
   /* Use covariance to implement clone function as returning this object rather
    * than base */
diff --git a/gcc/testsuite/rust/execute/torture/let-pattern-1.rs b/gcc/testsuite/rust/execute/torture/let-pattern-1.rs
new file mode 100644
index 00000000000..107d819a69f
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/let-pattern-1.rs
@@ -0,0 +1,4 @@
+fn main() -> i32 {
+    let (x, y, z) = (2, 3, 6);
+    x * y - z
+}
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 57/88] gccrs: rust-item: include rust-expr.h
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (55 preceding siblings ...)
  2023-04-05 14:03 ` [committed 56/88] gccrs: Add support for TuplePattern in let statements arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 58/88] gccrs: parser: Expose parse_macro_invocation as public API arthur.cohen
                   ` (32 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* ast/rust-item.h (class BlockExpr): Remove forward declaration of
	class `BlockExpr`.
---
 gcc/rust/ast/rust-item.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 37ed2beabfc..51ed815c700 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -22,11 +22,11 @@
 #include "rust-ast.h"
 #include "rust-path.h"
 #include "rust-common.h"
+#include "rust-expr.h"
 
 namespace Rust {
 namespace AST {
 // forward decls
-class BlockExpr;
 class TypePath;
 
 // TODO: inline?
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 58/88] gccrs: parser: Expose parse_macro_invocation as public API
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (56 preceding siblings ...)
  2023-04-05 14:03 ` [committed 57/88] gccrs: rust-item: include rust-expr.h arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 59/88] gccrs: expansion: Add `get_token_slice` to `MacroInvocLexer` class arthur.cohen
                   ` (31 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* parse/rust-parse.h: Move `parse_macro_invocation` to public API.
---
 gcc/rust/parse/rust-parse.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 2f767bb2a53..a4b65c50221 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -150,6 +150,8 @@ public:
   std::unique_ptr<AST::TokenTree> parse_token_tree ();
   AST::Attribute parse_attribute_body ();
   AST::AttrVec parse_inner_attributes ();
+  std::unique_ptr<AST::MacroInvocation>
+  parse_macro_invocation (AST::AttrVec outer_attrs);
 
 private:
   void skip_after_semicolon ();
@@ -201,8 +203,6 @@ private:
   parse_decl_macro_def (AST::Visibility vis, AST::AttrVec outer_attrs);
   std::unique_ptr<AST::MacroInvocation>
   parse_macro_invocation_semi (AST::AttrVec outer_attrs);
-  std::unique_ptr<AST::MacroInvocation>
-  parse_macro_invocation (AST::AttrVec outer_attrs);
   AST::MacroRule parse_macro_rule ();
   AST::MacroMatcher parse_macro_matcher ();
   std::unique_ptr<AST::MacroMatch> parse_macro_match ();
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 59/88] gccrs: expansion: Add `get_token_slice` to `MacroInvocLexer` class
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (57 preceding siblings ...)
  2023-04-05 14:03 ` [committed 58/88] gccrs: parser: Expose parse_macro_invocation as public API arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 60/88] gccrs: macros: Perform macro expansion in a fixed-point fashion arthur.cohen
                   ` (30 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* expand/rust-macro-invoc-lexer.cc (MacroInvocLexer::get_token_slice):
	Add API to retrieve token slices when lexing macro expansions.
	* expand/rust-macro-invoc-lexer.h: Declare `get_token_slice`.
---
 gcc/rust/expand/rust-macro-invoc-lexer.cc | 14 ++++++++++++++
 gcc/rust/expand/rust-macro-invoc-lexer.h  |  3 +++
 2 files changed, 17 insertions(+)

diff --git a/gcc/rust/expand/rust-macro-invoc-lexer.cc b/gcc/rust/expand/rust-macro-invoc-lexer.cc
index 8a43d29e0d1..321f0f97a76 100644
--- a/gcc/rust/expand/rust-macro-invoc-lexer.cc
+++ b/gcc/rust/expand/rust-macro-invoc-lexer.cc
@@ -26,4 +26,18 @@ MacroInvocLexer::split_current_token (TokenId new_left __attribute__ ((unused)),
   // FIXME
   gcc_unreachable ();
 }
+
+std::vector<std::unique_ptr<AST::Token>>
+MacroInvocLexer::get_token_slice (size_t start_idx, size_t end_idx) const
+{
+  std::vector<std::unique_ptr<AST::Token>> slice;
+
+  rust_assert (end_idx < token_stream.size ());
+
+  for (size_t i = start_idx; i < end_idx; i++)
+    slice.emplace_back (token_stream[i]->clone_token ());
+
+  return slice;
+}
+
 } // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-invoc-lexer.h b/gcc/rust/expand/rust-macro-invoc-lexer.h
index a0d30164850..0923c18c84d 100644
--- a/gcc/rust/expand/rust-macro-invoc-lexer.h
+++ b/gcc/rust/expand/rust-macro-invoc-lexer.h
@@ -55,6 +55,9 @@ public:
 
   size_t get_offs () const { return offs; }
 
+  std::vector<std::unique_ptr<AST::Token>>
+  get_token_slice (size_t start_idx, size_t end_idx) const;
+
 private:
   size_t offs;
   std::vector<std::unique_ptr<AST::Token>> token_stream;
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 60/88] gccrs: macros: Perform macro expansion in a fixed-point fashion.
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (58 preceding siblings ...)
  2023-04-05 14:03 ` [committed 59/88] gccrs: expansion: Add `get_token_slice` to `MacroInvocLexer` class arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 61/88] gccrs: expander: Add documentation for `expand_eager_invocations` arthur.cohen
                   ` (29 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

This commit changes our macro expansion system from an eager and recursive
macro expansion to a fixed-point like system. Instead of, when seeing
a macro invocation, expanding it and all of the macros within it, we
now perform multiple passes of expansion on the entire crate.

This, however, leads to a problem. Rust macros are expanded lazily, but
Rust builtin macros should be expanded eagerly. Due to this, we must
work around the lazy expansion in builtin macros and perform eager
expansion for each pass of the fixed-point, before finally expanding
the builtin when there are no longer any inner macro invocations.

To perform proper macro scoping, the ENR now keeps track of the current
scope (`current_scope` member) and resolves macros accordingly.

This is done through the use of the `scoped` method, which creates a new
scope, runs a specified lambda and then exits the scope. This prevents
pushing/popping errors that we've seen happen already in similar
contexts.

We might think about generalizing it to other classes, providing a
`Scoped<EntryFn, ExitFn>` class or similar

gcc/rust/ChangeLog:

	* ast/rust-macro.cc: New file.
	* Make-lang.in: Add `rust-macro.o` object
	* ast/rust-ast-fragment.cc (Fragment::Fragment): Change API around
	the construction of AST fragments.
	(Fragment::operator=): Correct `Fragment::operator=` to take into
	account the fragment tokens.
	(Fragment::create_error): Use new constructor.
	(Fragment::complete): Remove in favor of new constructor.
	(Fragment::unexpanded): Remove as that Fragment type is no longer used
	or possible.
	(Fragment::get_tokens): Add helper to access a fragment's tokens.
	* ast/rust-ast-fragment.h (enum class): Remove `FragmentKind::Unused`
	* ast/rust-ast.cc (MacroInvocation::as_string): Display
	builtin macro invocations properly.
	* ast/rust-ast.h: Fix `DelimTokenTree` class copy constructors and
	handling of its token vector.
	* ast/rust-macro.h (class MacroMatcher): Format.
	(class MetaItemSeq): Likewise.
	(builtin_macro_from_string): Get a `BuiltinMacroKind` from a given
	string, i.e the name of the macro (`assert!`, `cfg!` and so on).
	* expand/rust-attribute-visitor.cc (AttrVisitor::visit): Do not expand
	macros recursively anymore.
	(AttrVisitor::maybe_expand_expr): Likewise.
	(AttrVisitor::maybe_expand_type): Likewise.
	* expand/rust-attribute-visitor.h: Likewise, and remove
	`expand_macro_fragment_recursively` function.
	* expand/rust-macro-builtins.cc (make_token): Add shorthand for
	returning `std::unique_ptr<AST::Token>`s.
	(make_macro_invocation): Add shorthand for returning fragments
	containing builtin macro invocations.
	(try_expand_macro_expression): Do not expand macros recursively.
	(try_expand_single_string_literal): Likewise.
	(try_expand_many_expr): Likewise.
	(parse_single_string_literal): Error out more appropriately.
	(MacroBuiltin::compile_error_handler): Add explanation for eager
	invocation
	(MacroBuiltin::file_handler): Return the proper tokens associated with
	macro invocation, and builtin macros in the case of necessary eager
	expansion.
	(MacroBuiltin::column_handler): Likewise.
	(MacroBuiltin::include_bytes_handler): Likewise.
	(MacroBuiltin::include_str_handler): Likewise.
	(MacroBuiltin::concat_handler): Likewise.
	(MacroBuiltin::env_handler): Likewise.
	(MacroBuiltin::cfg_handler): Likewise.
	(MacroBuiltin::include_handler): Likewise.
	(MacroBuiltin::line_handler): Likewise.
	* expand/rust-macro-expand.cc (MacroExpander::expand_eager_invocations):
	Add function to expand eager invocations *once* in the fixed point
	pipeline.
	(MacroExpander::expand_invoc): Call into `expand_eager_invocations` for
	builtin macro invocations.
	(MacroExpander::expand_crate): Use new `AttrVisitor` API.
	(parse_many): Return tokens in `AST::Fragment`.
	(transcribe_expression): Likewise.
	(transcribe_type): Likewise.
	* expand/rust-macro-expand.h (struct MacroExpander): Add `has_changed`
	flag for fixed point checking.
	* resolve/rust-early-name-resolver.cc (EarlyNameResolver::EarlyNameResolver):
	Keep track of the current macro scope.
	(EarlyNameResolver::go): Use `scoped` API.
	(EarlyNameResolver::visit): Likewise.
	* resolve/rust-early-name-resolver.h: Add `scoped` API.
	* rust-session-manager.cc (Session::expansion): Perform macro expansion
	in a fixed-point fashion.

gcc/testsuite/ChangeLog:

	* rust/compile/macro17.rs: Fix testsuite for new recursion errors.
	* rust/compile/macro44.rs: Fix invalid testcase assertions.
	* rust/compile/builtin_macro_recurse.rs: Fix invalid test.
	* rust/compile/builtin_macro_recurse2.rs: New test.
	* rust/compile/macro46.rs: New test.
---
 gcc/rust/Make-lang.in                         |   1 +
 gcc/rust/ast/rust-ast-fragment.cc             |  42 ++-
 gcc/rust/ast/rust-ast-fragment.h              |  23 +-
 gcc/rust/ast/rust-ast.cc                      |  16 ++
 gcc/rust/ast/rust-ast.h                       |   5 +
 gcc/rust/ast/rust-macro.cc                    |  64 +++++
 gcc/rust/ast/rust-macro.h                     | 101 +++++--
 gcc/rust/expand/rust-attribute-visitor.cc     |   8 +-
 gcc/rust/expand/rust-attribute-visitor.h      |  36 +--
 gcc/rust/expand/rust-macro-builtins.cc        | 256 +++++++++++++-----
 gcc/rust/expand/rust-macro-expand.cc          | 138 +++++++++-
 gcc/rust/expand/rust-macro-expand.h           |  63 ++---
 gcc/rust/resolve/rust-early-name-resolver.cc  | 127 ++++++---
 gcc/rust/resolve/rust-early-name-resolver.h   |  65 +++++
 gcc/rust/rust-session-manager.cc              |  35 ++-
 ...cro_recurse.rs => builtin_macro_eager1.rs} |   0
 .../rust/compile/builtin_macro_eager2.rs      |  16 ++
 .../rust/compile/builtin_macro_recurse2.rs    |  20 ++
 gcc/testsuite/rust/compile/macro17.rs         |   6 +-
 gcc/testsuite/rust/compile/macro44.rs         |   6 +-
 gcc/testsuite/rust/compile/macro46.rs         |  19 ++
 21 files changed, 813 insertions(+), 234 deletions(-)
 create mode 100644 gcc/rust/ast/rust-macro.cc
 rename gcc/testsuite/rust/compile/{builtin_macro_recurse.rs => builtin_macro_eager1.rs} (100%)
 create mode 100644 gcc/testsuite/rust/compile/builtin_macro_eager2.rs
 create mode 100644 gcc/testsuite/rust/compile/builtin_macro_recurse2.rs
 create mode 100644 gcc/testsuite/rust/compile/macro46.rs

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 1d2f34d7919..d9bc40945c3 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -90,6 +90,7 @@ GRS_OBJS = \
     rust/rust-hir-map.o \
     rust/rust-attributes.o \
     rust/rust-abi.o \
+	rust/rust-macro.o \
     rust/rust-ast-lower.o \
     rust/rust-ast-lower-base.o \
     rust/rust-ast-lower-pattern.o \
diff --git a/gcc/rust/ast/rust-ast-fragment.cc b/gcc/rust/ast/rust-ast-fragment.cc
index c4916093fc6..fba629c0119 100644
--- a/gcc/rust/ast/rust-ast-fragment.cc
+++ b/gcc/rust/ast/rust-ast-fragment.cc
@@ -21,8 +21,9 @@
 namespace Rust {
 namespace AST {
 
-Fragment::Fragment (FragmentKind kind, std::vector<SingleASTNode> nodes)
-  : kind (kind), nodes (std::move (nodes))
+Fragment::Fragment (FragmentKind kind, std::vector<SingleASTNode> nodes,
+		    std::vector<std::unique_ptr<AST::Token>> tokens)
+  : kind (kind), nodes (std::move (nodes)), tokens (std::move (tokens))
 {}
 
 Fragment::Fragment (Fragment const &other) : kind (other.get_kind ())
@@ -33,13 +34,17 @@ Fragment::Fragment (Fragment const &other) : kind (other.get_kind ())
 Fragment &
 Fragment::operator= (Fragment const &other)
 {
+  kind = other.get_kind ();
+
   nodes.clear ();
   nodes.reserve (other.nodes.size ());
-  kind = other.get_kind ();
   for (auto &n : other.nodes)
-    {
-      nodes.push_back (n);
-    }
+    nodes.push_back (n);
+
+  tokens.clear ();
+  tokens.reserve (other.tokens.size ());
+  for (auto &t : other.tokens)
+    tokens.emplace_back (t->clone_token ());
 
   return *this;
 }
@@ -47,19 +52,20 @@ Fragment::operator= (Fragment const &other)
 Fragment
 Fragment::create_error ()
 {
-  return Fragment (FragmentKind::Error, {});
+  return Fragment (FragmentKind::Error, {}, {});
 }
 
-Fragment
-Fragment::complete (std::vector<AST::SingleASTNode> nodes)
-{
-  return Fragment (FragmentKind::Complete, std::move (nodes));
-}
+Fragment::Fragment (std::vector<AST::SingleASTNode> nodes,
+		    std::vector<std::unique_ptr<AST::Token>> tokens)
+  : kind (FragmentKind::Complete), nodes (std::move (nodes)),
+    tokens (std::move (tokens))
+{}
 
-Fragment
-Fragment::unexpanded ()
+Fragment::Fragment (std::vector<AST::SingleASTNode> nodes,
+		    std::unique_ptr<AST::Token> token)
+  : kind (FragmentKind::Complete), nodes (std::move (nodes))
 {
-  return Fragment (FragmentKind::Unexpanded, {});
+  tokens.emplace_back (std::move (token));
 }
 
 std::vector<SingleASTNode> &
@@ -68,6 +74,12 @@ Fragment::get_nodes ()
   return nodes;
 }
 
+std::vector<std::unique_ptr<AST::Token>> &
+Fragment::get_tokens ()
+{
+  return tokens;
+}
+
 FragmentKind
 Fragment::get_kind () const
 {
diff --git a/gcc/rust/ast/rust-ast-fragment.h b/gcc/rust/ast/rust-ast-fragment.h
index 3ef4ba16dce..22e99090b25 100644
--- a/gcc/rust/ast/rust-ast-fragment.h
+++ b/gcc/rust/ast/rust-ast-fragment.h
@@ -27,11 +27,6 @@ namespace AST {
 
 enum class FragmentKind
 {
-  /**
-   * If an AST Fragment still contains unexpanded tokens - this should only be
-   * used in the case of builtin macros which need to be expanded eagerly.
-   */
-  Unexpanded,
   /**
    * A completely expanded AST Fragment. This signifies that all
    * `SingleASTNode`s in the `nodes` vector are valid.
@@ -68,15 +63,18 @@ public:
   /**
    * Create a complete AST fragment
    */
-  static Fragment complete (std::vector<AST::SingleASTNode> nodes);
+  Fragment (std::vector<AST::SingleASTNode> nodes,
+	    std::vector<std::unique_ptr<AST::Token>> tokens);
 
   /**
-   * Create a fragment which contains unexpanded nodes
+   * Create a complete AST fragment made of a single token
    */
-  static Fragment unexpanded ();
+  Fragment (std::vector<AST::SingleASTNode> nodes,
+	    std::unique_ptr<AST::Token> tok);
 
   FragmentKind get_kind () const;
   std::vector<SingleASTNode> &get_nodes ();
+  std::vector<std::unique_ptr<AST::Token>> &get_tokens ();
 
   bool is_error () const;
   bool should_expand () const;
@@ -90,7 +88,8 @@ public:
   void accept_vis (ASTVisitor &vis);
 
 private:
-  Fragment (FragmentKind kind, std::vector<SingleASTNode> nodes);
+  Fragment (FragmentKind kind, std::vector<SingleASTNode> nodes,
+	    std::vector<std::unique_ptr<AST::Token>> tokens);
 
   FragmentKind kind;
 
@@ -104,6 +103,12 @@ private:
    */
   std::vector<SingleASTNode> nodes;
 
+  /**
+   * The tokens associated with an AST fragment. This vector represents the
+   * actual tokens of the various nodes that are part of the fragment.
+   */
+  std::vector<std::unique_ptr<AST::Token>> tokens;
+
   /**
    * We need to make a special case for Expression and Type fragments as only
    * one Node will be extracted from the `nodes` vector
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 60a9f01e17f..972cba2e7bb 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -1323,6 +1323,12 @@ std::string
 MacroInvocation::as_string () const
 {
   std::string str = "MacroInvocation: ";
+  auto is_builtin = kind == InvocKind::Builtin;
+
+  if (is_builtin)
+    str += "[builtin] ";
+  else
+    str += "[regular] ";
 
   str += append_attributes (outer_attrs, OUTER);
 
@@ -1331,6 +1337,16 @@ MacroInvocation::as_string () const
   str += "\n has semicolon: ";
   str += has_semicolon () ? "true" : "false";
 
+  if (is_builtin)
+    {
+      str += "[PENDING EAGER INVOCATIONS]: ";
+      for (auto &pending : pending_eager_invocs)
+	{
+	  str += pending->as_string ();
+	  str += "\n";
+	}
+    }
+
   return str;
 }
 
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index d30e6d494f2..d986fdf9368 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -773,6 +773,7 @@ public:
   DelimTokenTree (DelimTokenTree const &other)
     : delim_type (other.delim_type), locus (other.locus)
   {
+    token_trees.clear ();
     token_trees.reserve (other.token_trees.size ());
     for (const auto &e : other.token_trees)
       token_trees.push_back (e->clone_token_tree ());
@@ -784,6 +785,7 @@ public:
     delim_type = other.delim_type;
     locus = other.locus;
 
+    token_trees.clear ();
     token_trees.reserve (other.token_trees.size ());
     for (const auto &e : other.token_trees)
       token_trees.push_back (e->clone_token_tree ());
@@ -1523,6 +1525,9 @@ public:
   DelimTokenTree &get_delim_tok_tree () { return token_tree; }
   const DelimTokenTree &get_delim_tok_tree () const { return token_tree; }
 
+  // Set the delim token tree of a macro invocation
+  void set_delim_tok_tree (DelimTokenTree tree) { token_tree = tree; }
+
   // TODO: this mutable getter seems kinda dodgy
   SimplePath &get_path () { return path; }
   const SimplePath &get_path () const { return path; }
diff --git a/gcc/rust/ast/rust-macro.cc b/gcc/rust/ast/rust-macro.cc
new file mode 100644
index 00000000000..b90cc15898e
--- /dev/null
+++ b/gcc/rust/ast/rust-macro.cc
@@ -0,0 +1,64 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-macro.h"
+
+namespace Rust {
+namespace AST {
+
+BuiltinMacro
+builtin_macro_from_string (const std::string &identifier)
+{
+  if (identifier == "assert")
+    return BuiltinMacro::Assert;
+
+  if (identifier == "file")
+    return BuiltinMacro::File;
+
+  if (identifier == "line")
+    return BuiltinMacro::Line;
+
+  if (identifier == "column")
+    return BuiltinMacro::Column;
+
+  if (identifier == "include_bytes")
+    return BuiltinMacro::IncludeBytes;
+
+  if (identifier == "include_str")
+    return BuiltinMacro::IncludeStr;
+
+  if (identifier == "compile_error")
+    return BuiltinMacro::CompileError;
+
+  if (identifier == "concat")
+    return BuiltinMacro::Concat;
+
+  if (identifier == "env")
+    return BuiltinMacro::Env;
+
+  if (identifier == "cfg")
+    return BuiltinMacro::Cfg;
+
+  if (identifier == "include")
+    return BuiltinMacro::Include;
+
+  gcc_unreachable ();
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index 68dd7d660d3..1a1a32da34c 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -222,7 +222,7 @@ public:
   };
 
 private:
-  std::vector<std::unique_ptr<MacroMatch> > matches;
+  std::vector<std::unique_ptr<MacroMatch>> matches;
   MacroRepOp op;
 
   // bool has_sep;
@@ -235,7 +235,7 @@ public:
   // Returns whether macro match repetition has separator token.
   bool has_sep () const { return sep != nullptr; }
 
-  MacroMatchRepetition (std::vector<std::unique_ptr<MacroMatch> > matches,
+  MacroMatchRepetition (std::vector<std::unique_ptr<MacroMatch>> matches,
 			MacroRepOp op, std::unique_ptr<MacroRepSep> sep,
 			Location locus)
     : matches (std::move (matches)), op (op), sep (std::move (sep)),
@@ -290,8 +290,8 @@ public:
 
   MacroRepOp get_op () const { return op; }
   const std::unique_ptr<MacroRepSep> &get_sep () const { return sep; }
-  std::vector<std::unique_ptr<MacroMatch> > &get_matches () { return matches; }
-  const std::vector<std::unique_ptr<MacroMatch> > &get_matches () const
+  std::vector<std::unique_ptr<MacroMatch>> &get_matches () { return matches; }
+  const std::vector<std::unique_ptr<MacroMatch>> &get_matches () const
   {
     return matches;
   }
@@ -309,7 +309,7 @@ protected:
 class MacroMatcher : public MacroMatch
 {
   DelimType delim_type;
-  std::vector<std::unique_ptr<MacroMatch> > matches;
+  std::vector<std::unique_ptr<MacroMatch>> matches;
   Location locus;
 
   // TODO: think of way to mark invalid that doesn't take up more space
@@ -317,7 +317,7 @@ class MacroMatcher : public MacroMatch
 
 public:
   MacroMatcher (DelimType delim_type,
-		std::vector<std::unique_ptr<MacroMatch> > matches,
+		std::vector<std::unique_ptr<MacroMatch>> matches,
 		Location locus)
     : delim_type (delim_type), matches (std::move (matches)), locus (locus),
       is_invalid (false)
@@ -369,8 +369,8 @@ public:
   }
 
   DelimType get_delim_type () const { return delim_type; }
-  std::vector<std::unique_ptr<MacroMatch> > &get_matches () { return matches; }
-  const std::vector<std::unique_ptr<MacroMatch> > &get_matches () const
+  std::vector<std::unique_ptr<MacroMatch>> &get_matches () { return matches; }
+  const std::vector<std::unique_ptr<MacroMatch>> &get_matches () const
   {
     return matches;
   }
@@ -596,6 +596,9 @@ enum class BuiltinMacro
   Include
 };
 
+BuiltinMacro
+builtin_macro_from_string (const std::string &identifier);
+
 /* AST node of a macro invocation, which is replaced by the macro result at
  * compile time. This is technically a sum-type/tagged-union, which represents
  * both classic macro invocations and builtin macro invocations. Regular macro
@@ -634,7 +637,8 @@ public:
   {
     return std::unique_ptr<MacroInvocation> (
       new MacroInvocation (InvocKind::Regular, Optional<BuiltinMacro>::none (),
-			   invoc_data, outer_attrs, locus, is_semi_coloned));
+			   invoc_data, outer_attrs, locus, is_semi_coloned,
+			   {}));
   }
 
   /**
@@ -642,15 +646,18 @@ public:
    * name-resolution and within the macro expander, so unless you're modifying
    * these visitors, you probably do not want to use this function.
    */
-  static std::unique_ptr<MacroInvocation>
-  Builtin (BuiltinMacro kind, MacroInvocData invoc_data,
-	   std::vector<Attribute> outer_attrs, Location locus,
-	   bool is_semi_coloned = false)
+  static std::unique_ptr<MacroInvocation> Builtin (
+    BuiltinMacro kind, MacroInvocData invoc_data,
+    std::vector<Attribute> outer_attrs, Location locus,
+    std::vector<std::unique_ptr<MacroInvocation>> &&pending_eager_invocations
+    = {},
+    bool is_semi_coloned = false)
   {
     return std::unique_ptr<MacroInvocation> (
       new MacroInvocation (InvocKind::Builtin,
 			   Optional<BuiltinMacro>::some (kind), invoc_data,
-			   outer_attrs, locus, is_semi_coloned));
+			   outer_attrs, locus, is_semi_coloned,
+			   std::move (pending_eager_invocations)));
   }
 
   Location get_locus () const override final { return locus; }
@@ -688,18 +695,53 @@ public:
   InvocKind get_kind () const { return kind; }
   Optional<BuiltinMacro> get_builtin_kind () const { return builtin_kind; }
 
+  /**
+   * Turn the current MacroInvocation into a builtin macro invocation
+   */
+  void map_to_builtin (BuiltinMacro macro)
+  {
+    kind = InvocKind::Builtin;
+    builtin_kind = Optional<BuiltinMacro>::some (macro);
+  }
+
+  /**
+   * Get the list of pending macro invcations within the builtin macro
+   * invocation that should get expanded eagerly.
+   */
+  std::vector<std::unique_ptr<MacroInvocation>> &
+  get_pending_eager_invocations ()
+  {
+    rust_assert (kind == InvocKind::Builtin);
+
+    return pending_eager_invocs;
+  }
+
 private:
   /* Full constructor */
-  MacroInvocation (InvocKind kind, Optional<BuiltinMacro> builtin_kind,
-		   MacroInvocData invoc_data,
-		   std::vector<Attribute> outer_attrs, Location locus,
-		   bool is_semi_coloned)
+  MacroInvocation (
+    InvocKind kind, Optional<BuiltinMacro> builtin_kind,
+    MacroInvocData invoc_data, std::vector<Attribute> outer_attrs,
+    Location locus, bool is_semi_coloned,
+    std::vector<std::unique_ptr<MacroInvocation>> &&pending_eager_invocs)
     : outer_attrs (std::move (outer_attrs)), locus (locus),
       node_id (Analysis::Mappings::get ()->get_next_node_id ()),
       invoc_data (std::move (invoc_data)), is_semi_coloned (is_semi_coloned),
-      kind (kind), builtin_kind (builtin_kind)
+      kind (kind), builtin_kind (builtin_kind),
+      pending_eager_invocs (std::move (pending_eager_invocs))
   {}
 
+  MacroInvocation (const MacroInvocation &other)
+    : outer_attrs (other.outer_attrs), locus (other.locus),
+      node_id (other.node_id), invoc_data (other.invoc_data),
+      is_semi_coloned (other.is_semi_coloned), kind (other.kind),
+      builtin_kind (other.builtin_kind)
+  {
+    if (other.kind == InvocKind::Builtin)
+      for (auto &pending : other.pending_eager_invocs)
+	pending_eager_invocs.emplace_back (
+	  pending->clone_macro_invocation_impl ());
+  }
+
   std::vector<Attribute> outer_attrs;
   Location locus;
   NodeId node_id;
@@ -716,6 +758,16 @@ private:
   /* If it is a builtin macro, which one */
   Optional<BuiltinMacro> builtin_kind = Optional<BuiltinMacro>::none ();
 
+  /**
+   * Pending invocations within a builtin macro invocation. This vector is empty
+   * and should not be accessed for a regular macro invocation. The macro
+   * invocations within should be name resolved and expanded before the builtin
+   * macro invocation get expanded again. It is then the role of the expander to
+   * insert these new tokens properly in the delimited token tree and try the
+   * builtin transcriber once again.
+   */
+  std::vector<std::unique_ptr<MacroInvocation>> pending_eager_invocs;
+
 protected:
   /* Use covariance to implement clone function as returning this object rather
    * than base */
@@ -817,11 +869,10 @@ protected:
 class MetaItemSeq : public MetaItem
 {
   SimplePath path;
-  std::vector<std::unique_ptr<MetaItemInner> > seq;
+  std::vector<std::unique_ptr<MetaItemInner>> seq;
 
 public:
-  MetaItemSeq (SimplePath path,
-	       std::vector<std::unique_ptr<MetaItemInner> > seq)
+  MetaItemSeq (SimplePath path, std::vector<std::unique_ptr<MetaItemInner>> seq)
     : path (std::move (path)), seq (std::move (seq))
   {}
 
@@ -1024,18 +1075,18 @@ struct AttributeParser
 {
 private:
   // TODO: might as well rewrite to use lexer tokens
-  std::vector<std::unique_ptr<Token> > token_stream;
+  std::vector<std::unique_ptr<Token>> token_stream;
   int stream_pos;
 
 public:
-  AttributeParser (std::vector<std::unique_ptr<Token> > token_stream,
+  AttributeParser (std::vector<std::unique_ptr<Token>> token_stream,
 		   int stream_start_pos = 0)
     : token_stream (std::move (token_stream)), stream_pos (stream_start_pos)
   {}
 
   ~AttributeParser () = default;
 
-  std::vector<std::unique_ptr<MetaItemInner> > parse_meta_item_seq ();
+  std::vector<std::unique_ptr<MetaItemInner>> parse_meta_item_seq ();
 
 private:
   // Parses a MetaItemInner.
diff --git a/gcc/rust/expand/rust-attribute-visitor.cc b/gcc/rust/expand/rust-attribute-visitor.cc
index 6bceed62096..9abec9221ab 100644
--- a/gcc/rust/expand/rust-attribute-visitor.cc
+++ b/gcc/rust/expand/rust-attribute-visitor.cc
@@ -389,8 +389,6 @@ AttrVisitor::visit (AST::ConstGenericParam &)
 void
 AttrVisitor::visit (AST::MacroInvocation &macro_invoc)
 {
-  // FIXME: Probably need to check macro_invoc.kind
-
   // initial strip test based on outer attrs
   expander.expand_cfg_attrs (macro_invoc.get_outer_attrs ());
   if (expander.fails_cfg_with_expand (macro_invoc.get_outer_attrs ()))
@@ -1124,7 +1122,7 @@ AttrVisitor::visit (AST::CallExpr &expr)
 
       stmt->accept_vis (*this);
 
-      auto final_fragment = expand_macro_fragment_recursive ();
+      auto final_fragment = expander.take_expanded_fragment ();
       if (final_fragment.should_expand ())
 	{
 	  // Remove the current expanded invocation
@@ -3423,7 +3421,7 @@ AttrVisitor::visit (AST::BareFunctionType &type)
 void
 AttrVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr)
 {
-  auto final_fragment = expand_macro_fragment_recursive ();
+  auto final_fragment = expander.take_expanded_fragment ();
   if (final_fragment.should_expand ()
       && final_fragment.is_expression_fragment ())
     expr = final_fragment.take_expression_fragment ();
@@ -3432,7 +3430,7 @@ AttrVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr)
 void
 AttrVisitor::maybe_expand_type (std::unique_ptr<AST::Type> &type)
 {
-  auto final_fragment = expand_macro_fragment_recursive ();
+  auto final_fragment = expander.take_expanded_fragment ();
   if (final_fragment.should_expand () && final_fragment.is_type_fragment ())
     type = final_fragment.take_type_fragment ();
 }
diff --git a/gcc/rust/expand/rust-attribute-visitor.h b/gcc/rust/expand/rust-attribute-visitor.h
index cbddc163da7..9b0e315fc08 100644
--- a/gcc/rust/expand/rust-attribute-visitor.h
+++ b/gcc/rust/expand/rust-attribute-visitor.h
@@ -43,39 +43,6 @@ public:
   void expand_trait_function_decl (AST::TraitFunctionDecl &decl);
   void expand_trait_method_decl (AST::TraitMethodDecl &decl);
 
-  /**
-   * Expand The current macro fragment recursively until it could not be
-   * expanded further.
-   *
-   * The return value checking works because correctly
-   * expanded fragment can never be an error (if the fragment can not be
-   * expanded, a stand-in error fragment will be returned; for fragments that
-   * could not be further expanded: the fragment prior to the expansion failure
-   * will be returned).
-   *
-   * @return Either the expanded fragment or an empty errored-out fragment
-   * indicating an expansion failure.
-   */
-  AST::Fragment expand_macro_fragment_recursive ()
-  {
-    auto fragment = expander.take_expanded_fragment (*this);
-    unsigned int original_depth = expander.expansion_depth;
-    auto final_fragment = AST::Fragment::create_error ();
-
-    while (fragment.should_expand ())
-      {
-	final_fragment = std::move (fragment);
-	expander.expansion_depth++;
-	// further expand the previously expanded macro fragment
-	auto new_fragment = expander.take_expanded_fragment (*this);
-	if (new_fragment.is_error ())
-	  break;
-	fragment = std::move (new_fragment);
-      }
-    expander.expansion_depth = original_depth;
-    return final_fragment;
-  }
-
   /**
    * Expand a set of values, erasing them if they are marked for strip, and
    * replacing them with expanded macro nodes if necessary.
@@ -101,8 +68,7 @@ public:
 	// mark for stripping if required
 	value->accept_vis (*this);
 
-	// recursively expand the children
-	auto final_fragment = expand_macro_fragment_recursive ();
+	auto final_fragment = expander.take_expanded_fragment ();
 
 	if (final_fragment.should_expand ())
 	  {
diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc
index 11334409fe3..e594a2500d0 100644
--- a/gcc/rust/expand/rust-macro-builtins.cc
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -29,6 +29,16 @@
 
 namespace Rust {
 namespace {
+
+/**
+ * Shorthand function for creating unique_ptr tokens
+ */
+static std::unique_ptr<AST::Token>
+make_token (const TokenPtr tok)
+{
+  return std::unique_ptr<AST::Token> (new AST::Token (tok));
+}
+
 std::unique_ptr<AST::Expr>
 make_string (Location locus, std::string value)
 {
@@ -37,8 +47,64 @@ make_string (Location locus, std::string value)
 			  PrimitiveCoreType::CORETYPE_STR, {}, locus));
 }
 
-/* Match the end token of a macro given the start delimiter of the macro */
+// TODO: Is this correct?
+static AST::Fragment
+make_eager_builtin_invocation (
+  AST::BuiltinMacro kind, Location locus, AST::DelimTokenTree arguments,
+  std::vector<std::unique_ptr<AST::MacroInvocation>> &&pending_invocations)
+{
+  std::string path_str;
 
+  switch (kind)
+    {
+    // TODO: Should this be a table lookup?
+    case AST::BuiltinMacro::Assert:
+      path_str = "assert";
+      break;
+    case AST::BuiltinMacro::File:
+      path_str = "file";
+      break;
+    case AST::BuiltinMacro::Line:
+      path_str = "line";
+      break;
+    case AST::BuiltinMacro::Column:
+      path_str = "column";
+      break;
+    case AST::BuiltinMacro::IncludeBytes:
+      path_str = "include_bytes";
+      break;
+    case AST::BuiltinMacro::IncludeStr:
+      path_str = "include_str";
+      break;
+    case AST::BuiltinMacro::CompileError:
+      path_str = "compile_error";
+      break;
+    case AST::BuiltinMacro::Concat:
+      path_str = "concat";
+      break;
+    case AST::BuiltinMacro::Env:
+      path_str = "env";
+      break;
+    case AST::BuiltinMacro::Cfg:
+      path_str = "cfg";
+      break;
+    case AST::BuiltinMacro::Include:
+      path_str = "include";
+      break;
+    }
+
+  std::unique_ptr<AST::Expr> node = AST::MacroInvocation::Builtin (
+    kind,
+    AST::MacroInvocData (AST::SimplePath (
+			   {AST::SimplePathSegment (path_str, locus)}),
+			 std::move (arguments)),
+    {}, locus, std::move (pending_invocations));
+
+  return AST::Fragment ({AST::SingleASTNode (std::move (node))},
+			arguments.to_token_stream ());
+}
+
+/* Match the end token of a macro given the start delimiter of the macro */
 static inline TokenId
 macro_end_token (AST::DelimTokenTree &invoc_token_tree,
 		 Parser<MacroInvocLexer> &parser)
@@ -64,22 +130,7 @@ macro_end_token (AST::DelimTokenTree &invoc_token_tree,
   return last_token_id;
 }
 
-/* Expand and extract an expression from the macro */
-
-static inline AST::Fragment
-try_expand_macro_expression (AST::Expr *expr, MacroExpander *expander)
-{
-  rust_assert (expander);
-
-  auto attr_visitor = Rust::AttrVisitor (*expander);
-  auto early_name_resolver = Resolver::EarlyNameResolver ();
-  expr->accept_vis (early_name_resolver);
-  expr->accept_vis (attr_visitor);
-  return expander->take_expanded_fragment (attr_visitor);
-}
-
 /* Expand and then extract a string literal from the macro */
-
 static std::unique_ptr<AST::LiteralExpr>
 try_extract_string_literal_from_fragment (const Location &parent_locus,
 					  std::unique_ptr<AST::Expr> &node)
@@ -97,22 +148,6 @@ try_extract_string_literal_from_fragment (const Location &parent_locus,
     static_cast<AST::LiteralExpr *> (node->clone_expr ().release ()));
 }
 
-static std::unique_ptr<AST::LiteralExpr>
-try_expand_single_string_literal (AST::Expr *input_expr,
-				  MacroExpander *expander)
-{
-  auto nodes = try_expand_macro_expression (input_expr, expander);
-  if (nodes.is_error () || nodes.is_expression_fragment ())
-    {
-      rust_error_at (input_expr->get_locus (),
-		     "argument must be a string literal");
-      return nullptr;
-    }
-  auto expr = nodes.take_expression_fragment ();
-  return try_extract_string_literal_from_fragment (input_expr->get_locus (),
-						   expr);
-}
-
 static std::vector<std::unique_ptr<AST::Expr>>
 try_expand_many_expr (Parser<MacroInvocLexer> &parser,
 		      const TokenId last_token_id, MacroExpander *expander,
@@ -140,22 +175,7 @@ try_expand_many_expr (Parser<MacroInvocLexer> &parser,
       auto expr = parser.parse_expr (AST::AttrVec (), restrictions);
       // something must be so wrong that the expression could not be parsed
       rust_assert (expr);
-      auto nodes = try_expand_macro_expression (expr.get (), expander);
-      if (nodes.is_error ())
-	{
-	  // not macro
-	  result.push_back (std::move (expr));
-	}
-      else if (!nodes.is_expression_fragment ())
-	{
-	  rust_error_at (expr->get_locus (), "expected expression");
-	  has_error = true;
-	  return empty_expr;
-	}
-      else
-	{
-	  result.push_back (nodes.take_expression_fragment ());
-	}
+      result.push_back (std::move (expr));
 
       auto next_token = parser.peek_current_token ();
       if (!parser.skip_token (COMMA) && next_token->get_id () != last_token_id)
@@ -199,12 +219,7 @@ parse_single_string_literal (AST::DelimTokenTree &invoc_token_tree,
   else if (parser.peek_current_token ()->get_id () == last_token_id)
     rust_error_at (invoc_locus, "macro takes 1 argument");
   else
-    {
-      // when the expression does not seem to be a string literal, we then try
-      // to parse/expand it as macro to see if it expands to a string literal
-      auto expr = parser.parse_expr ();
-      lit_expr = try_expand_single_string_literal (expr.get (), expander);
-    }
+    rust_error_at (invoc_locus, "argument must be a string literal");
 
   parser.skip_token (last_token_id);
 
@@ -276,8 +291,10 @@ MacroBuiltin::file_handler (Location invoc_locus, AST::MacroInvocData &)
   auto current_file
     = Session::get_instance ().linemap->location_file (invoc_locus);
   auto file_str = AST::SingleASTNode (make_string (invoc_locus, current_file));
+  auto str_token
+    = make_token (Token::make_string (invoc_locus, std::move (current_file)));
 
-  return AST::Fragment::complete ({file_str});
+  return AST::Fragment ({file_str}, std::move (str_token));
 }
 
 AST::Fragment
@@ -286,11 +303,13 @@ MacroBuiltin::column_handler (Location invoc_locus, AST::MacroInvocData &)
   auto current_column
     = Session::get_instance ().linemap->location_to_column (invoc_locus);
 
+  auto column_tok = make_token (
+    Token::make_int (invoc_locus, std::to_string (current_column)));
   auto column_no = AST::SingleASTNode (std::unique_ptr<AST::Expr> (
     new AST::LiteralExpr (std::to_string (current_column), AST::Literal::INT,
 			  PrimitiveCoreType::CORETYPE_U32, {}, invoc_locus)));
 
-  return AST::Fragment::complete ({column_no});
+  return AST::Fragment ({column_no}, std::move (column_tok));
 }
 
 /* Expand builtin macro include_bytes!("filename"), which includes the contents
@@ -316,14 +335,25 @@ MacroBuiltin::include_bytes_handler (Location invoc_locus,
 
   /* Is there a more efficient way to do this?  */
   std::vector<std::unique_ptr<AST::Expr>> elts;
+
+  // We create the tokens for a borrow expression of a byte array, so
+  // & [ <byte0>, <byte1>, ... ]
+  std::vector<std::unique_ptr<AST::Token>> toks;
+  toks.emplace_back (make_token (Token::make (AMP, invoc_locus)));
+  toks.emplace_back (make_token (Token::make (LEFT_SQUARE, invoc_locus)));
+
   for (uint8_t b : bytes)
     {
       elts.emplace_back (
 	new AST::LiteralExpr (std::string (1, (char) b), AST::Literal::BYTE,
 			      PrimitiveCoreType::CORETYPE_U8,
 			      {} /* outer_attrs */, invoc_locus));
+      toks.emplace_back (make_token (Token::make_byte_char (invoc_locus, b)));
+      toks.emplace_back (make_token (Token::make (COMMA, invoc_locus)));
     }
 
+  toks.emplace_back (make_token (Token::make (RIGHT_SQUARE, invoc_locus)));
+
   auto elems = std::unique_ptr<AST::ArrayElems> (
     new AST::ArrayElemsValues (std::move (elts), invoc_locus));
 
@@ -334,8 +364,9 @@ MacroBuiltin::include_bytes_handler (Location invoc_locus,
     new AST::BorrowExpr (std::move (array), false, false, {}, invoc_locus));
 
   auto node = AST::SingleASTNode (std::move (borrow));
-  return AST::Fragment::complete ({node});
-}
+
+  return AST::Fragment ({node}, std::move (toks));
+} // namespace Rust
 
 /* Expand builtin macro include_str!("filename"), which includes the contents
    of the given file as a string. The file must be UTF-8 encoded. Yields an
@@ -362,7 +393,10 @@ MacroBuiltin::include_str_handler (Location invoc_locus,
   std::string str ((const char *) &bytes[0], bytes.size ());
 
   auto node = AST::SingleASTNode (make_string (invoc_locus, str));
-  return AST::Fragment::complete ({node});
+  auto str_tok = make_token (Token::make_string (invoc_locus, std::move (str)));
+
+  // FIXME: Do not return an empty token vector here
+  return AST::Fragment ({node}, std::move (str_tok));
 }
 
 /* Expand builtin macro compile_error!("error"), which forces a compile error
@@ -383,9 +417,62 @@ MacroBuiltin::compile_error_handler (Location invoc_locus,
   return AST::Fragment::create_error ();
 }
 
+static std::vector<std::unique_ptr<AST::MacroInvocation>>
+check_for_eager_invocations (
+  std::vector<std::unique_ptr<AST::Expr>> &expressions)
+{
+  std::vector<std::unique_ptr<AST::MacroInvocation>> pending;
+
+  for (auto &expr : expressions)
+    if (expr->get_ast_kind () == AST::Kind::MACRO_INVOCATION)
+      pending.emplace_back (std::unique_ptr<AST::MacroInvocation> (
+	static_cast<AST::MacroInvocation *> (expr->clone_expr ().release ())));
+
+  return pending;
+}
+
 /* Expand builtin macro concat!(), which joins all the literal parameters
    into a string with no delimiter. */
 
+// This is a weird one. We want to do something where, if something cannot be
+// expanded yet (i.e. macro invocation?) we return the whole MacroInvocation
+// node again but expanded as much as possible.
+// Is that possible? How do we do that?
+//
+// Let's take a few examples:
+//
+// 1. concat!(1, 2, true);
+// 2. concat!(a!(), 2, true);
+// 3. concat!(concat!(1, false), 2, true);
+// 4. concat!(concat!(1, a!()), 2, true);
+//
+// 1. We simply want to return the new fragment: "12true"
+// 2. We want to return `concat!(a_expanded, 2, true)` as a fragment
+// 3. We want to return `concat!(1, false, 2, true)`
+// 4. We want to return `concat!(concat!(1, a_expanded), 2, true);
+//
+// How do we do that?
+//
+// For each (un)expanded fragment: we check if it is expanded fully
+//
+// 1. What is expanded fully?
+// 2. How to check?
+//
+// If it is expanded fully and not a literal, then we error out.
+// Otherwise we simply emplace it back and keep going.
+//
+// In the second case, we must mark that this concat invocation still has some
+// expansion to do: This allows us to return a `MacroInvocation { ... }` as an
+// AST fragment, instead of a completed string.
+//
+// This means that we must change all the `try_expand_many_*` APIs and so on to
+// return some sort of index or way to signify that we might want to reuse some
+// bits and pieces of the original token tree.
+//
+// Now, before that: How do we resolve the names used in a builtin macro
+// invocation?
+// Do we split the two passes of parsing the token tree and then expanding it?
+// Can we do that easily?
 AST::Fragment
 MacroBuiltin::concat_handler (Location invoc_locus, AST::MacroInvocData &invoc)
 {
@@ -398,12 +485,25 @@ MacroBuiltin::concat_handler (Location invoc_locus, AST::MacroInvocData &invoc)
 
   auto last_token_id = macro_end_token (invoc_token_tree, parser);
 
+  auto start = lex.get_offs ();
   /* NOTE: concat! could accept no argument, so we don't have any checks here */
   auto expanded_expr = try_expand_many_expr (parser, last_token_id,
 					     invoc.get_expander (), has_error);
+  auto end = lex.get_offs ();
+
+  auto tokens = lex.get_token_slice (start, end);
+
+  auto pending_invocations = check_for_eager_invocations (expanded_expr);
+  if (!pending_invocations.empty ())
+    return make_eager_builtin_invocation (AST::BuiltinMacro::Concat,
+					  invoc_locus,
+					  invoc.get_delim_tok_tree (),
+					  std::move (pending_invocations));
+
   for (auto &expr : expanded_expr)
     {
-      if (!expr->is_literal ())
+      if (!expr->is_literal ()
+	  && expr->get_ast_kind () != AST::MACRO_INVOCATION)
 	{
 	  has_error = true;
 	  rust_error_at (expr->get_locus (), "expected a literal");
@@ -431,12 +531,13 @@ MacroBuiltin::concat_handler (Location invoc_locus, AST::MacroInvocData &invoc)
     return AST::Fragment::create_error ();
 
   auto node = AST::SingleASTNode (make_string (invoc_locus, str));
-  return AST::Fragment::complete ({node});
+  auto str_tok = make_token (Token::make_string (invoc_locus, std::move (str)));
+
+  return AST::Fragment ({node}, std::move (str_tok));
 }
 
 /* Expand builtin macro env!(), which inspects an environment variable at
    compile time. */
-
 AST::Fragment
 MacroBuiltin::env_handler (Location invoc_locus, AST::MacroInvocData &invoc)
 {
@@ -449,10 +550,22 @@ MacroBuiltin::env_handler (Location invoc_locus, AST::MacroInvocData &invoc)
   std::unique_ptr<AST::LiteralExpr> lit_expr = nullptr;
   bool has_error = false;
 
+  auto start = lex.get_offs ();
   auto expanded_expr = try_expand_many_expr (parser, last_token_id,
 					     invoc.get_expander (), has_error);
+  auto end = lex.get_offs ();
+
+  auto tokens = lex.get_token_slice (start, end);
+
   if (has_error)
     return AST::Fragment::create_error ();
+
+  auto pending = check_for_eager_invocations (expanded_expr);
+  if (!pending.empty ())
+    return make_eager_builtin_invocation (AST::BuiltinMacro::Env, invoc_locus,
+					  invoc_token_tree,
+					  std::move (pending));
+
   if (expanded_expr.size () < 1 || expanded_expr.size () > 2)
     {
       rust_error_at (invoc_locus, "env! takes 1 or 2 arguments");
@@ -492,7 +605,11 @@ MacroBuiltin::env_handler (Location invoc_locus, AST::MacroInvocData &invoc)
     }
 
   auto node = AST::SingleASTNode (make_string (invoc_locus, env_value));
-  return AST::Fragment::complete ({node});
+  auto tok
+    = make_token (Token::make_string (invoc_locus, std::move (env_value)));
+
+  // FIXME: Do not return an empty token vector here
+  return AST::Fragment ({node}, std::move (tok));
 }
 
 AST::Fragment
@@ -527,8 +644,11 @@ MacroBuiltin::cfg_handler (Location invoc_locus, AST::MacroInvocData &invoc)
   auto literal_exp = AST::SingleASTNode (std::unique_ptr<AST::Expr> (
     new AST::LiteralExpr (result ? "true" : "false", AST::Literal::BOOL,
 			  PrimitiveCoreType::CORETYPE_BOOL, {}, invoc_locus)));
+  auto tok = make_token (
+    Token::make (result ? TRUE_LITERAL : FALSE_LITERAL, invoc_locus));
 
-  return AST::Fragment::complete ({literal_exp});
+  // FIXME: Do not return an empty token vector here
+  return AST::Fragment ({literal_exp}, std::move (tok));
 }
 
 /* Expand builtin macro include!(), which includes a source file at the current
@@ -585,7 +705,8 @@ MacroBuiltin::include_handler (Location invoc_locus, AST::MacroInvocData &invoc)
       nodes.push_back (node);
     }
 
-  return AST::Fragment::complete (nodes);
+  // FIXME: Do not return an empty token vector here
+  return AST::Fragment (nodes, nullptr);
 }
 
 AST::Fragment
@@ -597,8 +718,11 @@ MacroBuiltin::line_handler (Location invoc_locus, AST::MacroInvocData &)
   auto line_no = AST::SingleASTNode (std::unique_ptr<AST::Expr> (
     new AST::LiteralExpr (std::to_string (current_line), AST::Literal::INT,
 			  PrimitiveCoreType::CORETYPE_U32, {}, invoc_locus)));
+  auto tok
+    = make_token (Token::make_int (invoc_locus, std::to_string (current_line)));
 
-  return AST::Fragment::complete ({line_no});
+  // FIXME: Do not return an empty token vector here
+  return AST::Fragment ({line_no}, std::move (tok));
 }
 
 } // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index bf914ee19e3..0ff849dc85d 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -110,6 +110,114 @@ MacroExpander::expand_decl_macro (Location invoc_locus,
 			  semicolon, peek_context ());
 }
 
+void
+MacroExpander::expand_eager_invocations (AST::MacroInvocation &invoc)
+{
+  if (invoc.get_pending_eager_invocations ().empty ())
+    return;
+
+  // We have to basically create a new delimited token tree which contains the
+  // result of one step of expansion. In the case of builtin macros called with
+  // other macro invocations, such as `concat!("h", 'a', a!())`, we need to
+  // expand `a!()` before expanding the concat macro.
+  // This will, ideally, give us a new token tree containing the various
+  // existing tokens + the result of the expansion of a!().
+  // To do this, we "parse" the given token tree to find anything that "looks
+  // like a macro invocation". Then, we get the corresponding macro invocation
+  // from the `pending_eager_invocations` vector and expand it.
+  // Because the `pending_eager_invocations` vector is created in the same order
+  // that the DelimTokenTree is parsed, we know that the first macro invocation
+  // within the DelimTokenTree corresponds to the first element in
+  // `pending_eager_invocations`. The idea is thus to:
+  // 1. Find a macro invocation in the token tree, noting the index of the start
+  //    token and of the end token
+  // 2. Get its associated invocation in `pending_eager_invocations`
+  // 3. Expand that element
+  // 4. Get the token tree associated with that AST fragment
+  // 5. Replace the original tokens corresponding to the invocation with the new
+  //    tokens from the fragment
+  // pseudo-code:
+  //
+  // i = 0;
+  // for tok in dtt:
+  //   if tok is identifier && tok->next() is !:
+  //     start = index(tok);
+  //     l_delim = tok->next()->next();
+  //     tok = skip_until_r_delim();
+  //     end = index(tok);
+  //
+  //     new_tt = expand_eager_invoc(eagers[i++]);
+  //     old_tt[start..end] = new_tt;
+
+  auto dtt = invoc.get_invoc_data ().get_delim_tok_tree ();
+  auto stream = dtt.to_token_stream ();
+  std::vector<std::unique_ptr<AST::TokenTree>> new_stream;
+  size_t current_pending = 0;
+
+  // we need to create a clone of the delimited token tree as the lexer
+  // expects ownership of the tokens
+  std::vector<std::unique_ptr<Rust::AST::Token>> dtt_clone;
+  for (auto &tok : stream)
+    dtt_clone.emplace_back (tok->clone_token ());
+
+  MacroInvocLexer lex (std::move (dtt_clone));
+  Parser<MacroInvocLexer> parser (lex);
+
+  // we want to build a substitution map - basically, associating a `start` and
+  // `end` index for each of the pending macro invocations
+  std::map<std::pair<size_t, size_t>, std::unique_ptr<AST::MacroInvocation> &>
+    substitution_map;
+
+  for (size_t i = 0; i < stream.size (); i++)
+    {
+      // FIXME: Can't these offsets be figure out when we actually parse the
+      // pending_eager_invocation in the first place?
+      auto invocation = parser.parse_macro_invocation ({});
+
+      // if we've managed to parse a macro invocation, we look at the current
+      // offset and store them in the substitution map. Otherwise, we skip one
+      // token and try parsing again
+      if (invocation)
+	substitution_map.insert (
+	  {{i, parser.get_token_source ().get_offs ()},
+	   invoc.get_pending_eager_invocations ()[current_pending++]});
+      else
+	parser.skip_token (stream[i]->get_id ());
+    }
+
+  size_t current_idx = 0;
+  for (auto kv : substitution_map)
+    {
+      auto &to_expand = kv.second;
+      expand_invoc (*to_expand, false);
+
+      auto fragment = take_expanded_fragment ();
+      auto &new_tokens = fragment.get_tokens ();
+
+      auto start = kv.first.first;
+      auto end = kv.first.second;
+
+      // TODO: Add doc
+      for (size_t i = current_idx; i < start; i++)
+	new_stream.emplace_back (stream[i]->clone_token ());
+
+      // TODO: Add doc
+      for (auto &tok : new_tokens)
+	new_stream.emplace_back (tok->clone_token ());
+
+      current_idx = end;
+    }
+  // TODO: Add doc
+  for (size_t i = current_idx; i < stream.size (); i++)
+    new_stream.emplace_back (stream[i]->clone_token ());
+
+  auto new_dtt
+    = AST::DelimTokenTree (dtt.get_delim_type (), std::move (new_stream));
+
+  invoc.get_pending_eager_invocations ().clear ();
+  invoc.get_invoc_data ().set_delim_tok_tree (new_dtt);
+}
+
 void
 MacroExpander::expand_invoc (AST::MacroInvocation &invoc, bool has_semicolon)
 {
@@ -119,6 +227,9 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc, bool has_semicolon)
       return;
     }
 
+  if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin)
+    expand_eager_invocations (invoc);
+
   AST::MacroInvocData &invoc_data = invoc.get_invoc_data ();
 
   // ??
@@ -151,6 +262,11 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc, bool has_semicolon)
   if (!ok)
     return;
 
+  // We store the last expanded invocation and macro definition for error
+  // reporting in case the recursion limit is reached
+  last_invoc = &invoc;
+  last_def = rules_def;
+
   if (rules_def->is_builtin ())
     fragment
       = rules_def->get_builtin_transcriber () (invoc.get_locus (), invoc_data);
@@ -292,7 +408,7 @@ MacroExpander::expand_crate ()
       // mark for stripping if required
       item->accept_vis (attr_visitor);
 
-      auto fragment = take_expanded_fragment (attr_visitor);
+      auto fragment = take_expanded_fragment ();
       if (fragment.should_expand ())
 	{
 	  // Remove the current expanded invocation
@@ -711,6 +827,9 @@ static AST::Fragment
 parse_many (Parser<MacroInvocLexer> &parser, TokenId &delimiter,
 	    std::function<AST::SingleASTNode ()> parse_fn)
 {
+  auto &lexer = parser.get_token_source ();
+  auto start = lexer.get_offs ();
+
   std::vector<AST::SingleASTNode> nodes;
   while (true)
     {
@@ -728,8 +847,9 @@ parse_many (Parser<MacroInvocLexer> &parser, TokenId &delimiter,
 
       nodes.emplace_back (std::move (node));
     }
+  auto end = lexer.get_offs ();
 
-  return AST::Fragment::complete (std::move (nodes));
+  return AST::Fragment (std::move (nodes), lexer.get_token_slice (start, end));
 }
 
 /**
@@ -838,11 +958,16 @@ transcribe_many_stmts (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
 static AST::Fragment
 transcribe_expression (Parser<MacroInvocLexer> &parser)
 {
+  auto &lexer = parser.get_token_source ();
+  auto start = lexer.get_offs ();
+
   auto expr = parser.parse_expr ();
   if (expr == nullptr)
     return AST::Fragment::create_error ();
 
-  return AST::Fragment::complete ({std::move (expr)});
+  auto end = lexer.get_offs ();
+
+  return AST::Fragment ({std::move (expr)}, lexer.get_token_slice (start, end));
 }
 
 /**
@@ -853,11 +978,16 @@ transcribe_expression (Parser<MacroInvocLexer> &parser)
 static AST::Fragment
 transcribe_type (Parser<MacroInvocLexer> &parser)
 {
+  auto &lexer = parser.get_token_source ();
+  auto start = lexer.get_offs ();
+
   auto type = parser.parse_type (true);
   for (auto err : parser.get_errors ())
     err.emit_error ();
 
-  return AST::Fragment::complete ({std::move (type)});
+  auto end = lexer.get_offs ();
+
+  return AST::Fragment ({std::move (type)}, lexer.get_token_slice (start, end));
 }
 
 static AST::Fragment
diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h
index bf761c1b199..94714169971 100644
--- a/gcc/rust/expand/rust-macro-expand.h
+++ b/gcc/rust/expand/rust-macro-expand.h
@@ -231,7 +231,7 @@ struct MacroExpander
     : cfg (cfg), crate (crate), session (session),
       sub_stack (SubstitutionScope ()),
       expanded_fragment (AST::Fragment::create_error ()),
-      resolver (Resolver::Resolver::get ()),
+      has_changed_flag (false), resolver (Resolver::Resolver::get ()),
       mappings (Analysis::Mappings::get ())
   {}
 
@@ -240,6 +240,12 @@ struct MacroExpander
   // Expands all macros in the crate passed in.
   void expand_crate ();
 
+  /**
+   * Expand the eager invocations contained within a builtin macro invocation.
+   * Called by `expand_invoc` when expanding builtin invocations.
+   */
+  void expand_eager_invocations (AST::MacroInvocation &invoc);
+
   /* Expands a macro invocation - possibly make both
    * have similar duck-typed interface and use templates?*/
   // should this be public or private?
@@ -315,49 +321,44 @@ struct MacroExpander
 
   void set_expanded_fragment (AST::Fragment &&fragment)
   {
+    if (!fragment.is_error ())
+      has_changed_flag = true;
+
     expanded_fragment = std::move (fragment);
   }
 
-  AST::Fragment take_expanded_fragment (AST::ASTVisitor &vis)
+  AST::Fragment take_expanded_fragment ()
   {
-    AST::Fragment old_fragment = std::move (expanded_fragment);
-    auto accumulator = std::vector<AST::SingleASTNode> ();
+    auto fragment = std::move (expanded_fragment);
     expanded_fragment = AST::Fragment::create_error ();
-    auto early_name_resolver = Resolver::EarlyNameResolver ();
-
-    for (auto &node : old_fragment.get_nodes ())
-      {
-	expansion_depth++;
-
-	node.accept_vis (early_name_resolver);
-	node.accept_vis (vis);
-	// we'll decide the next move according to the outcome of the macro
-	// expansion
-	if (expanded_fragment.is_error ())
-	  accumulator.push_back (node); // if expansion fails, there might be a
-					// non-macro expression we need to keep
-	else
-	  {
-	    // if expansion succeeded, then we need to merge the fragment with
-	    // the contents in the accumulator, so that our final expansion
-	    // result will contain non-macro nodes as it should
-	    auto new_nodes = expanded_fragment.get_nodes ();
-	    std::move (new_nodes.begin (), new_nodes.end (),
-		       std::back_inserter (accumulator));
-	    expanded_fragment = AST::Fragment::complete (accumulator);
-	  }
-	expansion_depth--;
-      }
-
-    return old_fragment;
+
+    return fragment;
   }
 
+  /**
+   * Has the MacroExpander expanded a macro since its state was last reset?
+   */
+  bool has_changed () const { return has_changed_flag; }
+
+  /**
+   * Reset the expander's "changed" state. This function should be executed at
+   * each iteration in a fixed point loop
+   */
+  void reset_changed_state () { has_changed_flag = false; }
+
+  AST::MacroRulesDefinition *get_last_definition () { return last_def; }
+  AST::MacroInvocation *get_last_invocation () { return last_invoc; }
+
 private:
   AST::Crate &crate;
   Session &session;
   SubstitutionScope sub_stack;
   std::vector<ContextType> context;
   AST::Fragment expanded_fragment;
+  bool has_changed_flag;
+
+  AST::MacroRulesDefinition *last_def;
+  AST::MacroInvocation *last_invoc;
 
 public:
   Resolver::Resolver *resolver;
diff --git a/gcc/rust/resolve/rust-early-name-resolver.cc b/gcc/rust/resolve/rust-early-name-resolver.cc
index 8100564dc78..60d6c8abc4d 100644
--- a/gcc/rust/resolve/rust-early-name-resolver.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver.cc
@@ -24,20 +24,17 @@ namespace Rust {
 namespace Resolver {
 
 EarlyNameResolver::EarlyNameResolver ()
-  : resolver (*Resolver::get ()), mappings (*Analysis::Mappings::get ())
+  : current_scope (UNKNOWN_NODEID), resolver (*Resolver::get ()),
+    mappings (*Analysis::Mappings::get ())
 {}
 
 void
 EarlyNameResolver::go (AST::Crate &crate)
 {
-  // FIXME: Is that valid? Why is the regular name resolution doing
-  // mappings->get_next_node_id()?
-  resolver.get_macro_scope ().push (crate.get_node_id ());
-
-  for (auto &item : crate.items)
-    item->accept_vis (*this);
-
-  // FIXME: Should we pop the macro scope?
+  scoped (crate.get_node_id (), [&crate, this] () {
+    for (auto &item : crate.items)
+      item->accept_vis (*this);
+  });
 }
 
 void
@@ -335,11 +332,13 @@ EarlyNameResolver::visit (AST::ClosureExprInner &expr)
 void
 EarlyNameResolver::visit (AST::BlockExpr &expr)
 {
-  for (auto &stmt : expr.get_statements ())
-    stmt->accept_vis (*this);
+  scoped (expr.get_node_id (), [&expr, this] () {
+    for (auto &stmt : expr.get_statements ())
+      stmt->accept_vis (*this);
 
-  if (expr.has_tail_expr ())
-    expr.get_tail_expr ()->accept_vis (*this);
+    if (expr.has_tail_expr ())
+      expr.get_tail_expr ()->accept_vis (*this);
+  });
 }
 
 void
@@ -434,8 +433,11 @@ EarlyNameResolver::visit (AST::WhileLetLoopExpr &expr)
 void
 EarlyNameResolver::visit (AST::ForLoopExpr &expr)
 {
-  expr.get_iterator_expr ()->accept_vis (*this);
-  expr.get_loop_block ()->accept_vis (*this);
+  scoped (expr.get_node_id (), [&expr, this] () {
+    expr.get_pattern ()->accept_vis (*this);
+    expr.get_iterator_expr ()->accept_vis (*this);
+    expr.get_loop_block ()->accept_vis (*this);
+  });
 }
 
 void
@@ -473,7 +475,9 @@ void
 EarlyNameResolver::visit (AST::IfLetExpr &expr)
 {
   expr.get_value_expr ()->accept_vis (*this);
-  expr.get_if_block ()->accept_vis (*this);
+
+  scoped (expr.get_node_id (),
+	  [&expr, this] () { expr.get_if_block ()->accept_vis (*this); });
 }
 
 void
@@ -504,16 +508,21 @@ void
 EarlyNameResolver::visit (AST::MatchExpr &expr)
 {
   expr.get_scrutinee_expr ()->accept_vis (*this);
-  for (auto &match_arm : expr.get_match_cases ())
-    {
-      if (match_arm.get_arm ().has_match_arm_guard ())
-	match_arm.get_arm ().get_guard_expr ()->accept_vis (*this);
 
-      for (auto &pattern : match_arm.get_arm ().get_patterns ())
-	pattern->accept_vis (*this);
+  scoped (expr.get_node_id (), [&expr, this] () {
+    for (auto &arm : expr.get_match_cases ())
+      {
+	scoped (arm.get_node_id (), [&arm, this] () {
+	  if (arm.get_arm ().has_match_arm_guard ())
+	    arm.get_arm ().get_guard_expr ()->accept_vis (*this);
 
-      match_arm.get_expr ()->accept_vis (*this);
-    }
+	  for (auto &pattern : arm.get_arm ().get_patterns ())
+	    pattern->accept_vis (*this);
+
+	  arm.get_expr ()->accept_vis (*this);
+	});
+      }
+  });
 }
 
 void
@@ -571,8 +580,10 @@ EarlyNameResolver::visit (AST::Method &method)
 void
 EarlyNameResolver::visit (AST::Module &module)
 {
-  for (auto &item : module.get_items ())
-    item->accept_vis (*this);
+  scoped (module.get_node_id (), [&module, this] () {
+    for (auto &item : module.get_items ())
+      item->accept_vis (*this);
+  });
 }
 
 void
@@ -722,8 +733,13 @@ EarlyNameResolver::visit (AST::TraitItemType &)
 void
 EarlyNameResolver::visit (AST::Trait &trait)
 {
-  for (auto &item : trait.get_trait_items ())
-    item->accept_vis (*this);
+  for (auto &generic : trait.get_generic_params ())
+    generic->accept_vis (*this);
+
+  scoped (trait.get_node_id (), [&trait, this] () {
+    for (auto &item : trait.get_trait_items ())
+      item->accept_vis (*this);
+  });
 }
 
 void
@@ -734,8 +750,10 @@ EarlyNameResolver::visit (AST::InherentImpl &impl)
   for (auto &generic : impl.get_generic_params ())
     generic->accept_vis (*this);
 
-  for (auto &item : impl.get_impl_items ())
-    item->accept_vis (*this);
+  scoped (impl.get_node_id (), [&impl, this] () {
+    for (auto &item : impl.get_impl_items ())
+      item->accept_vis (*this);
+  });
 }
 
 void
@@ -746,8 +764,10 @@ EarlyNameResolver::visit (AST::TraitImpl &impl)
   for (auto &generic : impl.get_generic_params ())
     generic->accept_vis (*this);
 
-  for (auto &item : impl.get_impl_items ())
-    item->accept_vis (*this);
+  scoped (impl.get_node_id (), [&impl, this] () {
+    for (auto &item : impl.get_impl_items ())
+      item->accept_vis (*this);
+  });
 }
 
 void
@@ -772,8 +792,10 @@ EarlyNameResolver::visit (AST::ExternalFunctionItem &item)
 void
 EarlyNameResolver::visit (AST::ExternBlock &block)
 {
-  for (auto &item : block.get_extern_items ())
-    item->accept_vis (*this);
+  scoped (block.get_node_id (), [&block, this] () {
+    for (auto &item : block.get_extern_items ())
+      item->accept_vis (*this);
+  });
 }
 
 void
@@ -795,6 +817,15 @@ EarlyNameResolver::visit (AST::MacroRulesDefinition &rules_def)
 				      rules_def.get_rule_name ());
   resolver.get_macro_scope ().insert (path, rules_def.get_node_id (),
 				      rules_def.get_locus ());
+
+  /* Since the EarlyNameResolver runs multiple time (fixed point algorithm)
+   * we could be inserting the same macro def over and over again until we
+   * implement some optimizations */
+  // FIXME: ARTHUR: Remove that lookup and add proper optimizations instead
+  AST::MacroRulesDefinition *tmp = nullptr;
+  if (mappings.lookup_macro_def (rules_def.get_node_id (), &tmp))
+    return;
+
   mappings.insert_macro_def (&rules_def);
   rust_debug_loc (rules_def.get_locus (), "inserting macro def: [%s]",
 		  path.get ().c_str ());
@@ -806,6 +837,10 @@ EarlyNameResolver::visit (AST::MacroInvocation &invoc)
   auto &invoc_data = invoc.get_invoc_data ();
   auto has_semicolon = invoc.has_semicolon ();
 
+  if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin)
+    for (auto &pending_invoc : invoc.get_pending_eager_invocations ())
+      pending_invoc->accept_vis (*this);
+
   // ??
   // switch on type of macro:
   //  - '!' syntax macro (inner switch)
@@ -847,6 +882,30 @@ EarlyNameResolver::visit (AST::MacroInvocation &invoc)
   bool ok = mappings.lookup_macro_def (resolved_node, &rules_def);
   rust_assert (ok);
 
+  auto &outer_attrs = rules_def->get_outer_attrs ();
+  bool is_builtin
+    = std::any_of (outer_attrs.begin (), outer_attrs.end (),
+		   [] (AST::Attribute attr) {
+		     return attr.get_path () == "rustc_builtin_macro";
+		   });
+
+  if (is_builtin)
+    {
+      auto builtin_kind
+	= AST::builtin_macro_from_string (rules_def->get_rule_name ());
+      invoc.map_to_builtin (builtin_kind);
+    }
+
+  auto attributes = rules_def->get_outer_attrs ();
+
+  /* Since the EarlyNameResolver runs multiple time (fixed point algorithm)
+   * we could be inserting the same macro def over and over again until we
+   * implement some optimizations */
+  // FIXME: ARTHUR: Remove that lookup and add proper optimizations instead
+  AST::MacroRulesDefinition *tmp_def = nullptr;
+  if (mappings.lookup_macro_invocation (invoc, &tmp_def))
+    return;
+
   mappings.insert_macro_invocation (invoc, rules_def);
 }
 
diff --git a/gcc/rust/resolve/rust-early-name-resolver.h b/gcc/rust/resolve/rust-early-name-resolver.h
index c53ab9f3d6a..c74c452ecaf 100644
--- a/gcc/rust/resolve/rust-early-name-resolver.h
+++ b/gcc/rust/resolve/rust-early-name-resolver.h
@@ -35,6 +35,71 @@ public:
   void go (AST::Crate &crate);
 
 private:
+  /**
+   * Execute a lambda within a scope. This is equivalent to calling
+   * `enter_scope` before your code and `exit_scope` after. This ensures
+   * no errors can be committed
+   */
+  void scoped (NodeId scope_id, std::function<void ()> fn)
+  {
+    auto old_scope = current_scope;
+    current_scope = scope_id;
+    resolver.get_macro_scope ().push (scope_id);
+    resolver.push_new_macro_rib (resolver.get_macro_scope ().peek ());
+
+    fn ();
+
+    resolver.get_macro_scope ().pop ();
+    current_scope = old_scope;
+  }
+
+  /**
+   * The "scope" we are currently in.
+   *
+   * This involves lexical scopes:
+   *
+   * ```rust
+   * // current_scope = crate_id;
+   * macro_rules! foo { () => {} )
+   *
+   * {
+   *     // current_scope = current_block_id;
+   *     macro_rules! foo { () => { something!(); } }
+   * }
+   * // current_scope = crate_id;
+   * ```
+   *
+   * as well as any sort of scope-like structure that might impact import name
+   * resolution or macro name resolution:
+   *
+   * ```rust
+   * macro_rules! foo {
+   *     () => { fn empty() {} }
+   * }
+   *
+   *
+   * trait Foo {
+   *     fn foo() {
+   *         fn inner_foo() {
+   *             macro_rules! foo { () => {} )
+   *
+   *             foo!();
+   *         }
+   *
+   *         foo!();
+   *     }
+   *
+   *     foo!();
+   * }
+   *
+   * foo!();
+   * ```
+   */
+  NodeId current_scope;
+
+  /* The crate's scope */
+  NodeId crate_scope;
+
   Resolver &resolver;
   Analysis::Mappings &mappings;
 
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index 28ac2ba4a53..0f460e2d2f4 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -821,9 +821,6 @@ Session::injection (AST::Crate &crate)
 void
 Session::expansion (AST::Crate &crate)
 {
-  /* We need to name resolve macros and imports here */
-  Resolver::EarlyNameResolver ().go (crate);
-
   rust_debug ("started expansion");
 
   /* rustc has a modification to windows PATH temporarily here, which may end
@@ -833,11 +830,41 @@ Session::expansion (AST::Crate &crate)
   // if not, would at least have to configure recursion_limit
   ExpansionCfg cfg;
 
+  auto fixed_point_reached = false;
+  unsigned iterations = 0;
+
   // create extctxt? from parse session, cfg, and resolver?
   /* expand by calling cxtctxt object's monotonic_expander's expand_crate
    * method. */
   MacroExpander expander (crate, cfg, *this);
-  expander.expand_crate ();
+
+  while (!fixed_point_reached && iterations < cfg.recursion_limit)
+    {
+      /* We need to name resolve macros and imports here */
+      Resolver::EarlyNameResolver ().go (crate);
+
+      expander.expand_crate ();
+
+      fixed_point_reached = !expander.has_changed ();
+      expander.reset_changed_state ();
+      iterations++;
+
+      if (saw_errors ())
+	break;
+    }
+
+  if (iterations == cfg.recursion_limit)
+    {
+      auto last_invoc = expander.get_last_invocation ();
+      auto last_def = expander.get_last_definition ();
+
+      rust_assert (last_def && last_invoc);
+
+      RichLocation range (last_invoc->get_locus ());
+      range.add_range (last_def->get_locus ());
+
+      rust_error_at (range, "reached recursion limit");
+    }
 
   // error reporting - check unused macros, get missing fragment specifiers
 
diff --git a/gcc/testsuite/rust/compile/builtin_macro_recurse.rs b/gcc/testsuite/rust/compile/builtin_macro_eager1.rs
similarity index 100%
rename from gcc/testsuite/rust/compile/builtin_macro_recurse.rs
rename to gcc/testsuite/rust/compile/builtin_macro_eager1.rs
diff --git a/gcc/testsuite/rust/compile/builtin_macro_eager2.rs b/gcc/testsuite/rust/compile/builtin_macro_eager2.rs
new file mode 100644
index 00000000000..21bf95c7829
--- /dev/null
+++ b/gcc/testsuite/rust/compile/builtin_macro_eager2.rs
@@ -0,0 +1,16 @@
+#[rustc_builtin_macro]
+macro_rules! env {
+    () => {};
+}
+
+macro_rules! a {
+    () => {
+        "__undefined__"
+    };
+}
+
+fn main() {
+    let _ = env!(a!()); // { dg-error "environment variable .__undefined__. not defined" }
+    let _ = env!(a!(), "custom"); // { dg-error "custom" }
+    let _ = env!(a!(), a!()); // { dg-error "__undefined__" }
+}
diff --git a/gcc/testsuite/rust/compile/builtin_macro_recurse2.rs b/gcc/testsuite/rust/compile/builtin_macro_recurse2.rs
new file mode 100644
index 00000000000..d8599208624
--- /dev/null
+++ b/gcc/testsuite/rust/compile/builtin_macro_recurse2.rs
@@ -0,0 +1,20 @@
+// { dg-additional-options "-fdump-tree-gimple" }
+
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+
+macro_rules! a {
+    () => {
+        "hey"
+    };
+    ($($t:tt)*) => {
+        "ho"
+    };
+}
+
+fn main() {
+    // { dg-final { scan-tree-dump-times {"abheyho"} 1 gimple } }
+    let _ = concat!("a", 'b', a!(), a!(b c d e f a!()), '\0');
+}
diff --git a/gcc/testsuite/rust/compile/macro17.rs b/gcc/testsuite/rust/compile/macro17.rs
index 743216529b7..b50afbece41 100644
--- a/gcc/testsuite/rust/compile/macro17.rs
+++ b/gcc/testsuite/rust/compile/macro17.rs
@@ -1,7 +1,7 @@
 macro_rules! rep {
-    ($a:literal) => { $a }; // { dg-error "reached recursion limit" }
-    ($a:literal $(, $e:literal)*) => { // { dg-error "reached recursion limit" }
-        $a + rep!(0 $(, $e)*) // { dg-error "Failed to match" }
+    ($a:literal) => { $a };
+    ($a:literal $(, $e:literal)*) => {
+        $a + rep!(0 $(, $e)*) // { dg-error "reached recursion limit" }
     }
 }
 
diff --git a/gcc/testsuite/rust/compile/macro44.rs b/gcc/testsuite/rust/compile/macro44.rs
index 84b2cdbb506..dabac6f7844 100644
--- a/gcc/testsuite/rust/compile/macro44.rs
+++ b/gcc/testsuite/rust/compile/macro44.rs
@@ -11,12 +11,12 @@ mod foo {
         () => {{}};
     }
 
-    fn foo_f() { // { dg-warning "function is never used" }
+    fn foo_f() {
         foo!();
     }
 
-    fn bar_f() { // { dg-warning "function is never used" }
-        baz!();
+    fn bar_f() {
+        baz!(); // { dg-error "unknown macro" }
     }
 }
 
diff --git a/gcc/testsuite/rust/compile/macro46.rs b/gcc/testsuite/rust/compile/macro46.rs
new file mode 100644
index 00000000000..3ef811aeab5
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro46.rs
@@ -0,0 +1,19 @@
+fn foo() {}
+
+fn main() {
+    macro_rules! a {
+        () => {
+            foo();
+        };
+    }
+
+    {
+        macro_rules! a {
+            () => {
+                bar();
+            };
+        }
+    }
+
+    a!();
+}
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 61/88] gccrs: expander: Add documentation for `expand_eager_invocations`
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (59 preceding siblings ...)
  2023-04-05 14:03 ` [committed 60/88] gccrs: macros: Perform macro expansion in a fixed-point fashion arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 62/88] gccrs: typecheck: Refactor rust-hir-trait-reference.h arthur.cohen
                   ` (28 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* expand/rust-macro-expand.cc (MacroExpander::expand_eager_invocations):
	Add documentation explaining the algorithm.
---
 gcc/rust/expand/rust-macro-expand.cc | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index 0ff849dc85d..4b494490424 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -197,17 +197,25 @@ MacroExpander::expand_eager_invocations (AST::MacroInvocation &invoc)
       auto start = kv.first.first;
       auto end = kv.first.second;
 
-      // TODO: Add doc
+      // We're now going to re-add the tokens to the invocation's token tree.
+      // 1. Basically, what we want to do is insert all tokens up until the
+      //    beginning of the macro invocation (start).
+      // 2. Then, we'll insert all of the tokens resulting from the macro
+      //    expansion: These are in `new_tokens`.
+      // 3. Finally, we'll do that again from
+      //    the end of macro and go back to 1.
+
       for (size_t i = current_idx; i < start; i++)
 	new_stream.emplace_back (stream[i]->clone_token ());
 
-      // TODO: Add doc
       for (auto &tok : new_tokens)
 	new_stream.emplace_back (tok->clone_token ());
 
       current_idx = end;
     }
-  // TODO: Add doc
+
+  // Once all of that is done, we copy the last remaining tokens from the
+  // original stream
   for (size_t i = current_idx; i < stream.size (); i++)
     new_stream.emplace_back (stream[i]->clone_token ());
 
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 62/88] gccrs: typecheck: Refactor rust-hir-trait-reference.h
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (60 preceding siblings ...)
  2023-04-05 14:03 ` [committed 61/88] gccrs: expander: Add documentation for `expand_eager_invocations` arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 63/88] gccrs: cli: Update safety warning message arthur.cohen
                   ` (27 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Move function body to their own cc file instead of keeping them in the
header file.

gcc/rust/ChangeLog:

	* Make-lang.in: Add `rust-hir-trait-reference.o`.
	* typecheck/rust-hir-trait-reference.h: Remove multiple function body.
	* typecheck/rust-hir-trait-reference.cc: Add multiple function body.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/Make-lang.in                         |   1 +
 .../typecheck/rust-hir-trait-reference.cc     | 463 ++++++++++++++++++
 gcc/rust/typecheck/rust-hir-trait-reference.h | 343 ++-----------
 3 files changed, 510 insertions(+), 297 deletions(-)
 create mode 100644 gcc/rust/typecheck/rust-hir-trait-reference.cc

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index d9bc40945c3..09bbe450bd5 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -123,6 +123,7 @@ GRS_OBJS = \
     rust/rust-tyty-bounds.o \
     rust/rust-hir-type-check-util.o \
     rust/rust-hir-trait-resolve.o \
+    rust/rust-hir-trait-reference.o \
     rust/rust-hir-type-check-item.o \
     rust/rust-hir-type-check-type.o \
     rust/rust-hir-type-check-struct.o \
diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.cc b/gcc/rust/typecheck/rust-hir-trait-reference.cc
new file mode 100644
index 00000000000..651c55abc82
--- /dev/null
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.cc
@@ -0,0 +1,463 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-hir-trait-reference.h"
+
+namespace Rust {
+namespace Resolver {
+
+std::string
+TraitItemReference::as_string () const
+{
+  return "(" + trait_item_type_as_string (type) + " " + identifier + " " + ")";
+}
+
+bool
+TraitItemReference::is_error () const
+{
+  return type == ERROR;
+}
+
+bool
+TraitItemReference::is_optional () const
+{
+  return optional_flag;
+};
+
+std::string
+TraitItemReference::get_identifier () const
+{
+  return identifier;
+}
+
+TraitItemReference::TraitItemType
+TraitItemReference::get_trait_item_type () const
+{
+  return type;
+}
+
+HIR::TraitItem *
+TraitItemReference::get_hir_trait_item () const
+{
+  return hir_trait_item;
+}
+
+Location
+TraitItemReference::get_locus () const
+{
+  return locus;
+}
+
+const Analysis::NodeMapping
+TraitItemReference::get_mappings () const
+{
+  return hir_trait_item->get_mappings ();
+}
+
+TyTy::BaseType *
+TraitItemReference::get_tyty () const
+{
+  rust_assert (hir_trait_item != nullptr);
+
+  switch (type)
+    {
+    case CONST:
+      return get_type_from_constant (
+	static_cast</*const*/ HIR::TraitItemConst &> (*hir_trait_item));
+      break;
+
+    case TYPE:
+      return get_type_from_typealias (
+	static_cast</*const*/ HIR::TraitItemType &> (*hir_trait_item));
+
+    case FN:
+      return get_type_from_fn (
+	static_cast</*const*/ HIR::TraitItemFunc &> (*hir_trait_item));
+      break;
+
+    default:
+      return get_error ();
+    }
+
+  gcc_unreachable ();
+  return get_error ();
+}
+
+TyTy::ErrorType *
+TraitItemReference::get_error () const
+{
+  return new TyTy::ErrorType (get_mappings ().get_hirid ());
+}
+
+TraitReference::TraitReference (
+  const HIR::Trait *hir_trait_ref, std::vector<TraitItemReference> item_refs,
+  std::vector<const TraitReference *> super_traits,
+  std::vector<TyTy::SubstitutionParamMapping> substs)
+  : hir_trait_ref (hir_trait_ref), item_refs (item_refs),
+    super_traits (super_traits)
+{
+  trait_substs.clear ();
+  trait_substs.reserve (substs.size ());
+  for (const auto &p : substs)
+    trait_substs.push_back (p.clone ());
+}
+
+TraitReference::TraitReference (TraitReference const &other)
+  : hir_trait_ref (other.hir_trait_ref), item_refs (other.item_refs),
+    super_traits (other.super_traits)
+{
+  trait_substs.clear ();
+  trait_substs.reserve (other.trait_substs.size ());
+  for (const auto &p : other.trait_substs)
+    trait_substs.push_back (p.clone ());
+}
+
+TraitReference &
+TraitReference::operator= (TraitReference const &other)
+{
+  hir_trait_ref = other.hir_trait_ref;
+  item_refs = other.item_refs;
+  super_traits = other.super_traits;
+
+  trait_substs.clear ();
+  trait_substs.reserve (other.trait_substs.size ());
+  for (const auto &p : other.trait_substs)
+    trait_substs.push_back (p.clone ());
+
+  return *this;
+}
+
+bool
+TraitReference::is_error () const
+{
+  return hir_trait_ref == nullptr;
+}
+
+Location
+TraitReference::get_locus () const
+{
+  return hir_trait_ref->get_locus ();
+}
+
+std::string
+TraitReference::get_name () const
+{
+  rust_assert (!is_error ());
+  return hir_trait_ref->get_name ();
+}
+
+std::string
+TraitReference::as_string () const
+{
+  if (is_error ())
+    return "<trait-ref-error-node>";
+
+  std::string item_buf;
+  for (auto &item : item_refs)
+    {
+      item_buf += item.as_string () + ", ";
+    }
+  return "HIR Trait: " + get_name () + "->"
+	 + hir_trait_ref->get_mappings ().as_string () + " [" + item_buf + "]";
+}
+
+const HIR::Trait *
+TraitReference::get_hir_trait_ref () const
+{
+  return hir_trait_ref;
+}
+
+const Analysis::NodeMapping &
+TraitReference::get_mappings () const
+{
+  return hir_trait_ref->get_mappings ();
+}
+
+DefId
+TraitReference::get_defid () const
+{
+  return get_mappings ().get_defid ();
+}
+
+bool
+TraitReference::lookup_hir_trait_item (const HIR::TraitItem &item,
+				       TraitItemReference **ref)
+{
+  return lookup_trait_item (item.trait_identifier (), ref);
+}
+
+bool
+TraitReference::lookup_trait_item (const std::string &ident,
+				   TraitItemReference **ref)
+{
+  for (auto &item : item_refs)
+    {
+      if (ident.compare (item.get_identifier ()) == 0)
+	{
+	  *ref = &item;
+	  return true;
+	}
+    }
+  return false;
+}
+
+bool
+TraitReference::lookup_trait_item_by_type (
+  const std::string &ident, TraitItemReference::TraitItemType type,
+  TraitItemReference **ref)
+{
+  for (auto &item : item_refs)
+    {
+      if (item.get_trait_item_type () != type)
+	continue;
+
+      if (ident.compare (item.get_identifier ()) == 0)
+	{
+	  *ref = &item;
+	  return true;
+	}
+    }
+  return false;
+}
+
+bool
+TraitReference::lookup_trait_item_by_type (
+  const std::string &ident, TraitItemReference::TraitItemType type,
+  const TraitItemReference **ref) const
+{
+  for (auto &item : item_refs)
+    {
+      if (item.get_trait_item_type () != type)
+	continue;
+
+      if (ident.compare (item.get_identifier ()) == 0)
+	{
+	  *ref = &item;
+	  return true;
+	}
+    }
+  return false;
+}
+
+bool
+TraitReference::lookup_hir_trait_item (const HIR::TraitItem &item,
+				       const TraitItemReference **ref) const
+{
+  return lookup_trait_item (item.trait_identifier (), ref);
+}
+
+bool
+TraitReference::lookup_trait_item (const std::string &ident,
+				   const TraitItemReference **ref) const
+{
+  for (auto &item : item_refs)
+    {
+      if (ident.compare (item.get_identifier ()) == 0)
+	{
+	  *ref = &item;
+	  return true;
+	}
+    }
+
+  // lookup super traits
+  for (const auto &super_trait : super_traits)
+    {
+      bool found = super_trait->lookup_trait_item (ident, ref);
+      if (found)
+	return true;
+    }
+
+  return false;
+}
+
+const TraitItemReference *
+TraitReference::lookup_trait_item (const std::string &ident,
+				   TraitItemReference::TraitItemType type) const
+{
+  for (auto &item : item_refs)
+    {
+      if (item.get_trait_item_type () != type)
+	continue;
+
+      if (ident.compare (item.get_identifier ()) == 0)
+	return &item;
+    }
+
+  // lookup super traits
+  for (const auto &super_trait : super_traits)
+    {
+      const TraitItemReference *res
+	= super_trait->lookup_trait_item (ident, type);
+      if (!res->is_error ())
+	return res;
+    }
+
+  return &TraitItemReference::error_node ();
+}
+
+size_t
+TraitReference::size () const
+{
+  return item_refs.size ();
+}
+
+const std::vector<TraitItemReference> &
+TraitReference::get_trait_items () const
+{
+  return item_refs;
+}
+
+void
+TraitReference::get_trait_items_and_supers (
+  std::vector<const TraitItemReference *> &result) const
+{
+  for (const auto &item : item_refs)
+    result.push_back (&item);
+
+  for (const auto &super_trait : super_traits)
+    super_trait->get_trait_items_and_supers (result);
+}
+
+void
+TraitReference::on_resolved ()
+{
+  for (auto &item : item_refs)
+    {
+      item.on_resolved ();
+    }
+}
+
+void
+TraitReference::clear_associated_types ()
+{
+  for (auto &item : item_refs)
+    {
+      bool is_assoc_type = item.get_trait_item_type ()
+			   == TraitItemReference::TraitItemType::TYPE;
+      if (is_assoc_type)
+	item.associated_type_reset ();
+    }
+}
+
+bool
+TraitReference::is_equal (const TraitReference &other) const
+{
+  DefId this_id = get_mappings ().get_defid ();
+  DefId other_id = other.get_mappings ().get_defid ();
+  return this_id == other_id;
+}
+
+const std::vector<const TraitReference *>
+TraitReference::get_super_traits () const
+{
+  return super_traits;
+}
+
+bool
+TraitReference::is_object_safe (bool emit_error, Location locus) const
+{
+  // https: // doc.rust-lang.org/reference/items/traits.html#object-safety
+  std::vector<const TraitReference *> non_object_super_traits;
+  for (auto &item : super_traits)
+    {
+      if (!item->is_object_safe (false, Location ()))
+	non_object_super_traits.push_back (item);
+    }
+
+  std::vector<const Resolver::TraitItemReference *> non_object_safe_items;
+  for (auto &item : get_trait_items ())
+    {
+      if (!item.is_object_safe ())
+	non_object_safe_items.push_back (&item);
+    }
+
+  bool is_safe
+    = non_object_super_traits.empty () && non_object_safe_items.empty ();
+  if (emit_error && !is_safe)
+    {
+      RichLocation r (locus);
+      for (auto &item : non_object_super_traits)
+	r.add_range (item->get_locus ());
+      for (auto &item : non_object_safe_items)
+	r.add_range (item->get_locus ());
+
+      rust_error_at (r, "trait bound is not object safe");
+    }
+
+  return is_safe;
+}
+
+bool
+TraitReference::trait_has_generics () const
+{
+  return !trait_substs.empty ();
+}
+
+std::vector<TyTy::SubstitutionParamMapping>
+TraitReference::get_trait_substs () const
+{
+  return trait_substs;
+}
+
+bool
+TraitReference::satisfies_bound (const TraitReference &reference) const
+{
+  if (is_equal (reference))
+    return true;
+
+  for (const auto &super_trait : super_traits)
+    {
+      if (super_trait->satisfies_bound (reference))
+	return true;
+    }
+
+  return false;
+}
+
+AssociatedImplTrait::AssociatedImplTrait (TraitReference *trait,
+					  HIR::ImplBlock *impl,
+					  TyTy::BaseType *self,
+					  Resolver::TypeCheckContext *context)
+  : trait (trait), impl (impl), self (self), context (context)
+{}
+
+TraitReference *
+AssociatedImplTrait::get_trait ()
+{
+  return trait;
+}
+
+HIR::ImplBlock *
+AssociatedImplTrait::get_impl_block ()
+{
+  return impl;
+}
+
+TyTy::BaseType *
+AssociatedImplTrait::get_self ()
+{
+  return self;
+}
+const TyTy::BaseType *
+AssociatedImplTrait::get_self () const
+{
+  return self;
+}
+
+} // namespace Resolver
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h b/gcc/rust/typecheck/rust-hir-trait-reference.h
index adb63b468d1..f3703efcced 100644
--- a/gcc/rust/typecheck/rust-hir-trait-reference.h
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.h
@@ -20,8 +20,8 @@
 #define RUST_HIR_TRAIT_REF_H
 
 #include "rust-hir-full.h"
-#include "rust-tyty-visitor.h"
 #include "rust-hir-type-check-util.h"
+#include "rust-tyty-visitor.h"
 
 namespace Rust {
 namespace Resolver {
@@ -61,13 +61,9 @@ public:
     return error;
   }
 
-  bool is_error () const { return type == ERROR; }
+  bool is_error () const;
 
-  std::string as_string () const
-  {
-    return "(" + trait_item_type_as_string (type) + " " + identifier + " "
-	   + ")";
-  }
+  std::string as_string () const;
 
   static std::string trait_item_type_as_string (TraitItemType ty)
   {
@@ -85,53 +81,24 @@ public:
     return "ERROR";
   }
 
-  bool is_optional () const { return optional_flag; }
-
-  std::string get_identifier () const { return identifier; }
-
-  TraitItemType get_trait_item_type () const { return type; }
-
-  HIR::TraitItem *get_hir_trait_item () const { return hir_trait_item; }
+  bool is_optional () const;
 
-  Location get_locus () const { return locus; }
+  std::string get_identifier () const;
 
-  const Analysis::NodeMapping get_mappings () const
-  {
-    return hir_trait_item->get_mappings ();
-  }
+  TraitItemType get_trait_item_type () const;
 
-  TyTy::BaseType *get_tyty () const
-  {
-    rust_assert (hir_trait_item != nullptr);
+  HIR::TraitItem *get_hir_trait_item () const;
 
-    switch (type)
-      {
-      case CONST:
-	return get_type_from_constant (
-	  static_cast</*const*/ HIR::TraitItemConst &> (*hir_trait_item));
-	break;
+  Location get_locus () const;
 
-      case TYPE:
-	return get_type_from_typealias (
-	  static_cast</*const*/ HIR::TraitItemType &> (*hir_trait_item));
+  const Analysis::NodeMapping get_mappings () const;
 
-      case FN:
-	return get_type_from_fn (
-	  static_cast</*const*/ HIR::TraitItemFunc &> (*hir_trait_item));
-	break;
-
-      default:
-	return get_error ();
-      }
-
-    gcc_unreachable ();
-    return get_error ();
-  }
+  TyTy::BaseType *get_tyty () const;
 
   Analysis::NodeMapping get_parent_trait_mappings () const;
 
-  // this is called when the trait is completed resolution and gives the items a
-  // chance to run their specific type resolution passes. If we call their
+  // this is called when the trait is completed resolution and gives the items
+  // a chance to run their specific type resolution passes. If we call their
   // resolution on construction it can lead to a case where the trait being
   // resolved recursively trying to resolve the trait itself infinitely since
   // the trait will not be stored in its own map yet
@@ -144,10 +111,7 @@ public:
   bool is_object_safe () const;
 
 private:
-  TyTy::ErrorType *get_error () const
-  {
-    return new TyTy::ErrorType (get_mappings ().get_hirid ());
-  }
+  TyTy::ErrorType *get_error () const;
 
   TyTy::BaseType *get_type_from_typealias (/*const*/
 					   HIR::TraitItemType &type) const;
@@ -182,39 +146,11 @@ public:
   TraitReference (const HIR::Trait *hir_trait_ref,
 		  std::vector<TraitItemReference> item_refs,
 		  std::vector<const TraitReference *> super_traits,
-		  std::vector<TyTy::SubstitutionParamMapping> substs)
-    : hir_trait_ref (hir_trait_ref), item_refs (item_refs),
-      super_traits (super_traits)
-  {
-    trait_substs.clear ();
-    trait_substs.reserve (substs.size ());
-    for (const auto &p : substs)
-      trait_substs.push_back (p.clone ());
-  }
-
-  TraitReference (TraitReference const &other)
-    : hir_trait_ref (other.hir_trait_ref), item_refs (other.item_refs),
-      super_traits (other.super_traits)
-  {
-    trait_substs.clear ();
-    trait_substs.reserve (other.trait_substs.size ());
-    for (const auto &p : other.trait_substs)
-      trait_substs.push_back (p.clone ());
-  }
-
-  TraitReference &operator= (TraitReference const &other)
-  {
-    hir_trait_ref = other.hir_trait_ref;
-    item_refs = other.item_refs;
-    super_traits = other.super_traits;
+		  std::vector<TyTy::SubstitutionParamMapping> substs);
 
-    trait_substs.clear ();
-    trait_substs.reserve (other.trait_substs.size ());
-    for (const auto &p : other.trait_substs)
-      trait_substs.push_back (p.clone ());
+  TraitReference (TraitReference const &other);
 
-    return *this;
-  }
+  TraitReference &operator= (TraitReference const &other);
 
   TraitReference (TraitReference &&other) = default;
   TraitReference &operator= (TraitReference &&other) = default;
@@ -224,7 +160,7 @@ public:
     return TraitReference (nullptr, {}, {}, {});
   }
 
-  bool is_error () const { return hir_trait_ref == nullptr; }
+  bool is_error () const;
 
   static TraitReference &error_node ()
   {
@@ -232,248 +168,63 @@ public:
     return trait_error_node;
   }
 
-  Location get_locus () const { return hir_trait_ref->get_locus (); }
+  Location get_locus () const;
 
-  std::string get_name () const
-  {
-    rust_assert (!is_error ());
-    return hir_trait_ref->get_name ();
-  }
+  std::string get_name () const;
 
-  std::string as_string () const
-  {
-    if (is_error ())
-      return "<trait-ref-error-node>";
-
-    std::string item_buf;
-    for (auto &item : item_refs)
-      {
-	item_buf += item.as_string () + ", ";
-      }
-    return "HIR Trait: " + get_name () + "->"
-	   + hir_trait_ref->get_mappings ().as_string () + " [" + item_buf
-	   + "]";
-  }
+  std::string as_string () const;
 
-  const HIR::Trait *get_hir_trait_ref () const { return hir_trait_ref; }
+  const HIR::Trait *get_hir_trait_ref () const;
 
-  const Analysis::NodeMapping &get_mappings () const
-  {
-    return hir_trait_ref->get_mappings ();
-  }
+  const Analysis::NodeMapping &get_mappings () const;
 
-  DefId get_defid () const { return get_mappings ().get_defid (); }
+  DefId get_defid () const;
 
   bool lookup_hir_trait_item (const HIR::TraitItem &item,
-			      TraitItemReference **ref)
-  {
-    return lookup_trait_item (item.trait_identifier (), ref);
-  }
+			      TraitItemReference **ref);
 
-  bool lookup_trait_item (const std::string &ident, TraitItemReference **ref)
-  {
-    for (auto &item : item_refs)
-      {
-	if (ident.compare (item.get_identifier ()) == 0)
-	  {
-	    *ref = &item;
-	    return true;
-	  }
-      }
-    return false;
-  }
+  bool lookup_trait_item (const std::string &ident, TraitItemReference **ref);
 
   bool lookup_trait_item_by_type (const std::string &ident,
 				  TraitItemReference::TraitItemType type,
-				  TraitItemReference **ref)
-  {
-    for (auto &item : item_refs)
-      {
-	if (item.get_trait_item_type () != type)
-	  continue;
-
-	if (ident.compare (item.get_identifier ()) == 0)
-	  {
-	    *ref = &item;
-	    return true;
-	  }
-      }
-    return false;
-  }
+				  TraitItemReference **ref);
 
   bool lookup_trait_item_by_type (const std::string &ident,
 				  TraitItemReference::TraitItemType type,
-				  const TraitItemReference **ref) const
-  {
-    for (auto &item : item_refs)
-      {
-	if (item.get_trait_item_type () != type)
-	  continue;
-
-	if (ident.compare (item.get_identifier ()) == 0)
-	  {
-	    *ref = &item;
-	    return true;
-	  }
-      }
-    return false;
-  }
+				  const TraitItemReference **ref) const;
 
   bool lookup_hir_trait_item (const HIR::TraitItem &item,
-			      const TraitItemReference **ref) const
-  {
-    return lookup_trait_item (item.trait_identifier (), ref);
-  }
+			      const TraitItemReference **ref) const;
 
   bool lookup_trait_item (const std::string &ident,
-			  const TraitItemReference **ref) const
-  {
-    for (auto &item : item_refs)
-      {
-	if (ident.compare (item.get_identifier ()) == 0)
-	  {
-	    *ref = &item;
-	    return true;
-	  }
-      }
-
-    // lookup super traits
-    for (const auto &super_trait : super_traits)
-      {
-	bool found = super_trait->lookup_trait_item (ident, ref);
-	if (found)
-	  return true;
-      }
-
-    return false;
-  }
+			  const TraitItemReference **ref) const;
 
   const TraitItemReference *
   lookup_trait_item (const std::string &ident,
-		     TraitItemReference::TraitItemType type) const
-  {
-    for (auto &item : item_refs)
-      {
-	if (item.get_trait_item_type () != type)
-	  continue;
+		     TraitItemReference::TraitItemType type) const;
 
-	if (ident.compare (item.get_identifier ()) == 0)
-	  return &item;
-      }
+  size_t size () const;
 
-    // lookup super traits
-    for (const auto &super_trait : super_traits)
-      {
-	const TraitItemReference *res
-	  = super_trait->lookup_trait_item (ident, type);
-	if (!res->is_error ())
-	  return res;
-      }
-
-    return &TraitItemReference::error_node ();
-  }
-
-  size_t size () const { return item_refs.size (); }
-
-  const std::vector<TraitItemReference> &get_trait_items () const
-  {
-    return item_refs;
-  }
+  const std::vector<TraitItemReference> &get_trait_items () const;
 
   void get_trait_items_and_supers (
-    std::vector<const TraitItemReference *> &result) const
-  {
-    for (const auto &item : item_refs)
-      result.push_back (&item);
-
-    for (const auto &super_trait : super_traits)
-      super_trait->get_trait_items_and_supers (result);
-  }
-
-  void on_resolved ()
-  {
-    for (auto &item : item_refs)
-      {
-	item.on_resolved ();
-      }
-  }
-
-  void clear_associated_types ()
-  {
-    for (auto &item : item_refs)
-      {
-	bool is_assoc_type = item.get_trait_item_type ()
-			     == TraitItemReference::TraitItemType::TYPE;
-	if (is_assoc_type)
-	  item.associated_type_reset ();
-      }
-  }
-
-  bool is_equal (const TraitReference &other) const
-  {
-    DefId this_id = get_mappings ().get_defid ();
-    DefId other_id = other.get_mappings ().get_defid ();
-    return this_id == other_id;
-  }
-
-  const std::vector<const TraitReference *> get_super_traits () const
-  {
-    return super_traits;
-  }
-
-  bool is_object_safe (bool emit_error, Location locus) const
-  {
-    // https: // doc.rust-lang.org/reference/items/traits.html#object-safety
-    std::vector<const TraitReference *> non_object_super_traits;
-    for (auto &item : super_traits)
-      {
-	if (!item->is_object_safe (false, Location ()))
-	  non_object_super_traits.push_back (item);
-      }
+    std::vector<const TraitItemReference *> &result) const;
 
-    std::vector<const Resolver::TraitItemReference *> non_object_safe_items;
-    for (auto &item : get_trait_items ())
-      {
-	if (!item.is_object_safe ())
-	  non_object_safe_items.push_back (&item);
-      }
+  void on_resolved ();
 
-    bool is_safe
-      = non_object_super_traits.empty () && non_object_safe_items.empty ();
-    if (emit_error && !is_safe)
-      {
-	RichLocation r (locus);
-	for (auto &item : non_object_super_traits)
-	  r.add_range (item->get_locus ());
-	for (auto &item : non_object_safe_items)
-	  r.add_range (item->get_locus ());
+  void clear_associated_types ();
 
-	rust_error_at (r, "trait bound is not object safe");
-      }
+  bool is_equal (const TraitReference &other) const;
 
-    return is_safe;
-  }
+  const std::vector<const TraitReference *> get_super_traits () const;
 
-  bool trait_has_generics () const { return !trait_substs.empty (); }
+  bool is_object_safe (bool emit_error, Location locus) const;
 
-  std::vector<TyTy::SubstitutionParamMapping> get_trait_substs () const
-  {
-    return trait_substs;
-  }
-
-  bool satisfies_bound (const TraitReference &reference) const
-  {
-    if (is_equal (reference))
-      return true;
+  bool trait_has_generics () const;
 
-    for (const auto &super_trait : super_traits)
-      {
-	if (super_trait->satisfies_bound (reference))
-	  return true;
-      }
+  std::vector<TyTy::SubstitutionParamMapping> get_trait_substs () const;
 
-    return false;
-  }
+  bool satisfies_bound (const TraitReference &reference) const;
 
 private:
   const HIR::Trait *hir_trait_ref;
@@ -487,16 +238,14 @@ class AssociatedImplTrait
 public:
   AssociatedImplTrait (TraitReference *trait, HIR::ImplBlock *impl,
 		       TyTy::BaseType *self,
-		       Resolver::TypeCheckContext *context)
-    : trait (trait), impl (impl), self (self), context (context)
-  {}
+		       Resolver::TypeCheckContext *context);
 
-  TraitReference *get_trait () { return trait; }
+  TraitReference *get_trait ();
 
-  HIR::ImplBlock *get_impl_block () { return impl; }
+  HIR::ImplBlock *get_impl_block ();
 
-  TyTy::BaseType *get_self () { return self; }
-  const TyTy::BaseType *get_self () const { return self; }
+  TyTy::BaseType *get_self ();
+  const TyTy::BaseType *get_self () const;
 
   TyTy::BaseType *
   setup_associated_types (const TyTy::BaseType *self,
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 63/88] gccrs: cli: Update safety warning message
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (61 preceding siblings ...)
  2023-04-05 14:03 ` [committed 62/88] gccrs: typecheck: Refactor rust-hir-trait-reference.h arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 64/88] gccrs: Update copyright years arthur.cohen
                   ` (26 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

The compiler's warning message about the safety flag did not match
cargo-gccrs environment variable name anymore.

gcc/rust/ChangeLog:

	* rust-session-manager.cc (Session::compile_crate): Update the
	environment variable name.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/rust-session-manager.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index 0f460e2d2f4..a086f83a3d0 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -441,7 +441,7 @@ Session::compile_crate (const char *filename)
       "defining the following environment variable (any value will "
       "do)\n\nGCCRS_INCOMPLETE_AND_EXPERIMENTAL_COMPILER_DO_NOT_USE\n\nFor "
       "cargo-gccrs, this means passing\n\n"
-      "GCCRS_EXTRA_FLAGS=\"-frust-incomplete-and-experimental-compiler-do-not-"
+      "GCCRS_EXTRA_ARGS=\"-frust-incomplete-and-experimental-compiler-do-not-"
       "use\"\n\nas an environment variable.");
 
   RAIIFile file_wrap (filename);
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [committed 64/88] gccrs: Update copyright years.
  2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
                   ` (62 preceding siblings ...)
  2023-04-05 14:03 ` [committed 63/88] gccrs: cli: Update safety warning message arthur.cohen
@ 2023-04-05 14:03 ` arthur.cohen
  2023-04-05 14:03 ` [committed 65/88] gccrs: Add feature gate for "rust-intrinsic" arthur.cohen
                   ` (25 subsequent siblings)
  89 siblings, 0 replies; 92+ messages in thread
From: arthur.cohen @ 2023-04-05 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Thomas Schwinge

From: Thomas Schwinge <thomas@codesourcery.com>

gcc/rust/ChangeLog:

	* ast/rust-ast-fragment.cc: Update copyright years.
	* ast/rust-ast-fragment.h: Likewise.
	* ast/rust-macro.cc: Likewise.
	* checks/errors/rust-feature-gate.cc: Likewise.
	* checks/errors/rust-feature-gate.h: Likewise.
	* checks/errors/rust-feature.cc: Likewise.
	* checks/errors/rust-feature.h: Likewise.
	* hir/rust-ast-lower-expr.cc: Likewise.
	* hir/rust-ast-lower-type.cc: Likewise.
	* resolve/rust-early-name-resolver.cc: Likewise.
	* resolve/rust-early-name-resolver.h: Likewise.
	* rust-gcc.h: Likewise.
	* typecheck/rust-hir-path-probe.cc: Likewise.
	* typecheck/rust-hir-trait-reference.cc: Likewise.
	* typecheck/rust-tyty-bounds.h: Likewise.
	* typecheck/rust-tyty-subst.cc: Likewise.
	* typecheck/rust-tyty-subst.h: Likewise.
	* typecheck/rust-tyty-util.cc: Likewise.
	* typecheck/rust-tyty-util.h: Likewise.
	* typecheck/rust-unify.cc: Likewise.
	* typecheck/rust-unify.h: Likewise.
	* util/rust-inline-visitor.h: Likewise.
---
 gcc/rust/ast/rust-ast-fragment.cc              | 2 +-
 gcc/rust/ast/rust-ast-fragment.h               | 2 +-
 gcc/rust/ast/rust-macro.cc                     | 2 +-
 gcc/rust/checks/errors/rust-feature-gate.cc    | 2 +-
 gcc/rust/checks/errors/rust-feature-gate.h     | 2 +-
 gcc/rust/checks/errors/rust-feature.cc         | 2 +-
 gcc/rust/checks/errors/rust-feature.h          | 2 +-
 gcc/rust/hir/rust-ast-lower-expr.cc            | 2 +-
 gcc/rust/hir/rust-ast-lower-type.cc            | 2 +-
 gcc/rust/resolve/rust-early-name-resolver.cc   | 2 +-
 gcc/rust/resolve/rust-early-name-resolver.h    | 2 +-
 gcc/rust/rust-gcc.h                            | 2 +-
 gcc/rust/typecheck/rust-hir-path-probe.cc      | 2 +-
 gcc/rust/typecheck/rust-hir-trait-reference.cc | 2 +-
 gcc/rust/typecheck/rust-tyty-bounds.h          | 2 +-
 gcc/rust/typecheck/rust-tyty-subst.cc          | 2 +-
 gcc/rust/typecheck/rust-tyty-subst.h           | 2 +-
 gcc/rust/typecheck/rust-tyty-util.cc           | 2 +-
 gcc/rust/typecheck/rust-tyty-util.h            | 2 +-
 gcc/rust/typecheck/rust-unify.cc               | 2 +-
 gcc/rust/typecheck/rust-unify.h                | 2 +-
 gcc/rust/util/rust-inline-visitor.h            | 2 +-
 22 files changed, 22 insertions(+), 22 deletions(-)