public inbox for gcc-rust@gcc.gnu.org
 help / color / mirror / Atom feed
* Rust frontend patches v2
@ 2022-08-24 11:59 herron.philip
  2022-08-24 11:59 ` [PATCH Rust front-end v2 01/37] Use DW_ATE_UTF for the Rust 'char' type herron.philip
                   ` (37 more replies)
  0 siblings, 38 replies; 57+ messages in thread
From: herron.philip @ 2022-08-24 11:59 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust

This is the 2nd patch set for gccrs, since v1 we have dropped the changes
for target hooks which are not nessecary for us right now. This now
focuses directly on the front-end the only patch that affects GCC now is a
tweak to debug info. Note we are close to merging our port of the C++
constexpr code into our front-end but this patch set does not include this
yet.

Thanks to Open Source Security, inc and Embecosm for sponsoring this work.
Special thanks to all of those who have contributed thus far.

See our branch over on https://gcc.gnu.org/git/?p=gcc.git;a=shortlog;h=refs/heads/devel/rust/master

We are currently testing on every commit the following systems:

- Debian i386 - all tests passing
- Debian testing-x86_64 - all tests passing
- Fedora arm64 - all tests passing
- Fedora X86_64 - all tests passing
- OpenSUSE Leap X86_64 - all tests passing
- OpenSUSE tw X86_64 - all tests passing
- Rawhide X86_64 - all tests passing
- macos x86_64 - all tests passing
- Debian ppc64 - some tests failing
- Fedora ppc64le - some tests failing
- Fedora s390x - some tests failing

The patch set is as follows:

[PATCH Rust front-end v2 01/37] Use DW_ATE_UTF for the Rust 'char'
[PATCH Rust front-end v2 02/37] gccrs: Add nessecary hooks for a Rust
[PATCH Rust front-end v2 03/37] gccrs: Add Debug info testsuite
[PATCH Rust front-end v2 04/37] gccrs: Add link cases testsuite
[PATCH Rust front-end v2 05/37] gccrs: Add general compilation test
[PATCH Rust front-end v2 06/37] gccrs: Add execution test cases
[PATCH Rust front-end v2 07/37] gccrs: Add gcc-check-target
[PATCH Rust front-end v2 08/37] gccrs: Add the Rust front-end AST
[PATCH Rust front-end v2 09/37] gccrs: Add Lexer for Rust front-end
[PATCH Rust front-end v2 10/37] gccrs: Add Parser for Rust front-end
[PATCH Rust front-end v2 11/37] gccrs: Add expansion pass for the
[PATCH Rust front-end v2 12/37] gccrs: Add name resolution pass to
[PATCH Rust front-end v2 13/37] gccrs: Add second intermedite
[PATCH Rust front-end v2 14/37] gccrs: Add AST to HIR lowering pass
[PATCH Rust front-end v2 15/37] gccrs: Add wrapper for make_unique
[PATCH Rust front-end v2 16/37] gccrs: Add port of FNV hash used
[PATCH Rust front-end v2 17/37] gccrs: Add Rust ABI enum helpers
[PATCH Rust front-end v2 18/37] gccrs: Add Base62 implementation
[PATCH Rust front-end v2 19/37] gccrs: Add implementation of Optional
[PATCH Rust front-end v2 20/37] gccrs: Add attributes checker
[PATCH Rust front-end v2 21/37] gccrs: Add helpers mappings canonical
[PATCH Rust front-end v2 22/37] gccrs: Add type resolution and trait
[PATCH Rust front-end v2 23/37] gccrs: Add unsafe checks for Rust
[PATCH Rust front-end v2 24/37] gccrs: Add const checker
[PATCH Rust front-end v2 25/37] gccrs: Add privacy checks
[PATCH Rust front-end v2 26/37] gccrs: Add dead code scan on HIR
[PATCH Rust front-end v2 27/37] gccrs: Add unused variable scan
[PATCH Rust front-end v2 28/37] gccrs: Add metadata ouptput pass
[PATCH Rust front-end v2 29/37] gccrs: HIR to GCC GENERIC lowering
[PATCH Rust front-end v2 30/37] gccrs: These are wrappers ported from
[PATCH Rust front-end v2 31/37] gccrs: Add GCC Rust front-end
[PATCH Rust front-end v2 32/37] gccrs: Add config-lang.in
[PATCH Rust front-end v2 33/37] gccrs: add lang-spec.h
[PATCH Rust front-end v2 34/37] gccrs: add lang.opt
[PATCH Rust front-end v2 35/37] gccrs: add compiler driver
[PATCH Rust front-end v2 36/37] gccrs: compiler proper interface
[PATCH Rust front-end v2 37/37] gccrs: Add README, CONTRIBUTING and


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

* [PATCH Rust front-end v2 01/37] Use DW_ATE_UTF for the Rust 'char' type
  2022-08-24 11:59 Rust frontend patches v2 herron.philip
@ 2022-08-24 11:59 ` herron.philip
  2022-08-24 14:28   ` Jason Merrill
  2022-08-24 11:59 ` [PATCH Rust front-end v2 02/37] gccrs: Add nessecary hooks for a Rust front-end testsuite herron.philip
                   ` (36 subsequent siblings)
  37 siblings, 1 reply; 57+ messages in thread
From: herron.philip @ 2022-08-24 11:59 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Tom Tromey

From: Tom Tromey <tom@tromey.com>

The Rust 'char' type should use the DWARF DW_ATE_UTF encoding.
---
 gcc/dwarf2out.cc | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
index e3920c898f5..a8bccbabca4 100644
--- a/gcc/dwarf2out.cc
+++ b/gcc/dwarf2out.cc
@@ -5600,6 +5600,16 @@ is_fortran (const_tree decl)
   return is_fortran ();
 }
 
+/* Return TRUE if the language is Rust.  */
+
+static inline bool
+is_rust ()
+{
+  unsigned int lang = get_AT_unsigned (comp_unit_die (), DW_AT_language);
+
+  return lang == DW_LANG_Rust || lang == DW_LANG_Rust_old;
+}
+
 /* Return TRUE if the language is Ada.  */
 
 static inline bool
@@ -13231,7 +13241,11 @@ base_type_die (tree type, bool reverse)
 	}
       if (TYPE_STRING_FLAG (type))
 	{
-	  if (TYPE_UNSIGNED (type))
+	  if ((dwarf_version >= 4 || !dwarf_strict)
+	      && is_rust ()
+	      && int_size_in_bytes (type) == 4)
+	    encoding = DW_ATE_UTF;
+	  else if (TYPE_UNSIGNED (type))
 	    encoding = DW_ATE_unsigned_char;
 	  else
 	    encoding = DW_ATE_signed_char;
@@ -25201,6 +25215,13 @@ gen_compile_unit_die (const char *filename)
     }
   else if (strcmp (language_string, "GNU F77") == 0)
     language = DW_LANG_Fortran77;
+  else if (strcmp (language_string, "GNU Rust") == 0)
+    {
+      if (dwarf_version >= 5 || !dwarf_strict)
+	language = DW_LANG_Rust;
+      else
+	language = DW_LANG_Rust_old;
+    }
   else if (dwarf_version >= 3 || !dwarf_strict)
     {
       if (strcmp (language_string, "GNU Ada") == 0)
-- 
2.25.1


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

* [PATCH Rust front-end v2 02/37] gccrs: Add nessecary hooks for a Rust front-end testsuite
  2022-08-24 11:59 Rust frontend patches v2 herron.philip
  2022-08-24 11:59 ` [PATCH Rust front-end v2 01/37] Use DW_ATE_UTF for the Rust 'char' type herron.philip
@ 2022-08-24 11:59 ` herron.philip
  2022-09-10  4:05   ` Mike Stump
  2022-08-24 11:59 ` [PATCH Rust front-end v2 03/37] gccrs: Add Debug info testsuite herron.philip
                   ` (35 subsequent siblings)
  37 siblings, 1 reply; 57+ messages in thread
From: herron.philip @ 2022-08-24 11:59 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron, Marc Poulhiès, Thomas Schwinge

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

This copy's over code from other front-end testsuites to enable testing
for the rust front-end specifically.

Co-authored-by: Marc Poulhiès <dkm@kataplop.net>
Co-authored-by: Thomas Schwinge <thomas@codesourcery.com>
---
 gcc/testsuite/lib/rust-dg.exp |  49 +++++++++
 gcc/testsuite/lib/rust.exp    | 186 ++++++++++++++++++++++++++++++++++
 2 files changed, 235 insertions(+)
 create mode 100644 gcc/testsuite/lib/rust-dg.exp
 create mode 100644 gcc/testsuite/lib/rust.exp

diff --git a/gcc/testsuite/lib/rust-dg.exp b/gcc/testsuite/lib/rust-dg.exp
new file mode 100644
index 00000000000..a8a2ac0c8eb
--- /dev/null
+++ b/gcc/testsuite/lib/rust-dg.exp
@@ -0,0 +1,49 @@
+# Copyright (C) 1997-2022 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+#
+# This program 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/>.
+
+load_lib gcc-dg.exp
+
+# Define rust callbacks for dg.exp.
+
+proc rust-dg-test { prog do_what extra_tool_flags } {
+    return [gcc-dg-test-1 rust_target_compile $prog $do_what $extra_tool_flags]
+}
+
+proc rust-dg-prune { system text } {
+    return [gcc-dg-prune $system $text]
+}
+
+# Utility routines.
+
+#
+# rust_load -- wrapper around default rust_load to handle tests that
+# require program arguments passed to them.
+#
+
+if { [info procs rust_load] != [list] \
+      && [info procs prev_rust_load] == [list] } {
+    rename rust_load prev_rust_load
+
+    proc rust_load { program args } {
+	global RUST_EXECUTE_ARGS
+	if [info exists RUST_EXECUTE_ARGS] then {
+	    set args [concat "{$RUST_EXECUTE_ARGS}"]
+	}
+	set result [eval [list prev_rust_load $program] $args ]
+	return $result
+    }
+}
+
diff --git a/gcc/testsuite/lib/rust.exp b/gcc/testsuite/lib/rust.exp
new file mode 100644
index 00000000000..6993c976304
--- /dev/null
+++ b/gcc/testsuite/lib/rust.exp
@@ -0,0 +1,186 @@
+# Copyright (C) 2012-2022 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+#
+# This program 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/>.
+
+#
+# rust support library routines
+#
+
+load_lib prune.exp
+load_lib gcc-defs.exp
+load_lib timeout.exp
+load_lib target-libpath.exp
+
+#
+# RUST_UNDER_TEST is the compiler under test.
+#
+
+set rust_compile_options ""
+
+
+#
+# rust_include_flags -- include flags for the gcc tree structure
+#
+
+proc rust_include_flags { paths } {
+    global srcdir
+    global TESTING_IN_BUILD_TREE
+
+    set flags ""
+
+    if { [is_remote host] || ![info exists TESTING_IN_BUILD_TREE] } {
+	return "${flags}"
+    }
+
+    set gccpath ${paths}
+
+    return "$flags"
+}
+
+#
+# rust_link_flags -- linker flags for the gcc tree structure
+#
+
+proc rust_link_flags { paths } {
+    global srcdir
+    global ld_library_path
+    global RUST_UNDER_TEST
+    global shlib_ext
+    global SHARED_OPTION
+
+    set gccpath ${paths}
+    set libio_dir ""
+    set flags ""
+    set ld_library_path "."
+    set shlib_ext [get_shlib_extension]
+    set SHARED_OPTION ""
+    verbose "shared lib extension: $shlib_ext"
+
+    set_ld_library_path_env_vars
+
+    return "$flags"
+}
+
+#
+# rust_init -- called at the start of each subdir of tests
+#
+
+proc rust_init { args } {
+    global subdir
+    global rust_initialized
+    global base_dir
+    global tmpdir
+    global libdir
+    global gluefile wrap_flags
+    global objdir srcdir
+    global ALWAYS_RUSTFLAGS
+    global TOOL_EXECUTABLE TOOL_OPTIONS
+    global RUST_UNDER_TEST
+    global TESTING_IN_BUILD_TREE
+    global TEST_ALWAYS_FLAGS
+    global gcc_warning_prefix
+    global gcc_error_prefix
+
+    # We set LC_ALL and LANG to C so that we get the same error messages as expected.
+    setenv LC_ALL C
+    setenv LANG C
+
+    if ![info exists RUST_UNDER_TEST] then {
+	if [info exists TOOL_EXECUTABLE] {
+	    set RUST_UNDER_TEST $TOOL_EXECUTABLE
+	} else {
+	    if { [is_remote host] || ! [info exists TESTING_IN_BUILD_TREE] } {
+		set RUST_UNDER_TEST [transform gccrs]
+	    } else {
+		set RUST_UNDER_TEST [findfile $base_dir/../../gccrs "$base_dir/../../gccrs -B$base_dir/../../" [findfile $base_dir/gccrs "$base_dir/gccrs -B$base_dir/" [transform gccrs]]]
+	    }
+	}
+    }
+
+    if ![is_remote host] {
+	if { [which $RUST_UNDER_TEST] == 0 } then {
+	    perror "RUST_UNDER_TEST ($RUST_UNDER_TEST) does not exist"
+	    exit 1
+	}
+    }
+
+    if ![info exists tmpdir] {
+	set tmpdir "/tmp"
+    }
+
+    if [info exists gluefile] {
+	unset gluefile
+    }
+
+    rust_maybe_build_wrapper "${tmpdir}/rust-testglue.o"
+
+    set ALWAYS_RUSTFLAGS ""
+
+    # TEST_ALWAYS_FLAGS are flags that should be passed to every
+    # compilation.  They are passed first to allow individual
+    # tests to override them.
+    if [info exists TEST_ALWAYS_FLAGS] {
+	lappend ALWAYS_RUSTFLAGS "additional_flags=$TEST_ALWAYS_FLAGS"
+    }
+
+    if ![is_remote host] {
+	if [info exists TOOL_OPTIONS] {
+	    lappend ALWAYS_RUSTFLAGS "additional_flags=[rust_include_flags [get_multilibs ${TOOL_OPTIONS}] ]"
+	    lappend ALWAYS_RUSTFLAGS "ldflags=[rust_link_flags [get_multilibs ${TOOL_OPTIONS}] ]"
+	} else {
+	    lappend ALWAYS_RUSTFLAGS "additional_flags=[rust_include_flags [get_multilibs] ]"
+	    lappend ALWAYS_RUSTFLAGS "ldflags=[rust_link_flags [get_multilibs] ]"
+	}
+    }
+
+    if [info exists TOOL_OPTIONS] {
+	lappend ALWAYS_RUSTFLAGS "additional_flags=$TOOL_OPTIONS"
+    }
+
+    verbose -log "ALWAYS_RUSTFLAGS set to $ALWAYS_RUSTFLAGS"
+
+    set gcc_warning_prefix "warning:"
+    set gcc_error_prefix "(fatal )?error:"
+
+    verbose "rust is initialized" 3
+}
+
+#
+# rust_target_compile -- compile a source file
+#
+
+proc rust_target_compile { source dest type options } {
+    global tmpdir
+    global gluefile wrap_flags
+    global ALWAYS_RUSTFLAGS
+    global RUST_UNDER_TEST
+    global individual_timeout
+
+    # HACK: guard against infinite loops in the compiler
+    set individual_timeout 10
+
+    if { [target_info needs_status_wrapper] != "" && [info exists gluefile] } {
+	lappend options "libs=${gluefile}"
+	lappend options "ldflags=${wrap_flags}"
+    }
+
+    lappend options "timeout=[timeout_value]"
+    lappend options "compiler=$RUST_UNDER_TEST"
+
+    set options [concat "$ALWAYS_RUSTFLAGS" $options]
+    set options [dg-additional-files-options $options $source]
+
+    return [target_compile $source $dest $type $options]
+}
-- 
2.25.1


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

* [PATCH Rust front-end v2 03/37] gccrs: Add Debug info testsuite
  2022-08-24 11:59 Rust frontend patches v2 herron.philip
  2022-08-24 11:59 ` [PATCH Rust front-end v2 01/37] Use DW_ATE_UTF for the Rust 'char' type herron.philip
  2022-08-24 11:59 ` [PATCH Rust front-end v2 02/37] gccrs: Add nessecary hooks for a Rust front-end testsuite herron.philip
@ 2022-08-24 11:59 ` herron.philip
  2022-08-24 11:59 ` [PATCH Rust front-end v2 04/37] gccrs: Add link cases testsuite herron.philip
                   ` (34 subsequent siblings)
  37 siblings, 0 replies; 57+ messages in thread
From: herron.philip @ 2022-08-24 11:59 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron, Tom Tromey

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

This testsuite is specifically about testcases which scan the asm debug
info for results.

Co-authored-by: Tom Tromey <tom@tromey.com>
---
 gcc/testsuite/rust/debug/chartype.rs          | 10 ++++++
 .../rust/debug/custom_link_section.rs         | 13 ++++++++
 gcc/testsuite/rust/debug/debug.exp            | 33 +++++++++++++++++++
 gcc/testsuite/rust/debug/i8u8.rs              | 12 +++++++
 gcc/testsuite/rust/debug/lang.rs              |  6 ++++
 gcc/testsuite/rust/debug/no_mangle.rs         | 17 ++++++++++
 gcc/testsuite/rust/debug/oldlang.rs           |  6 ++++
 gcc/testsuite/rust/debug/tuple.rs             |  8 +++++
 gcc/testsuite/rust/debug/win64-abi.rs         | 11 +++++++
 9 files changed, 116 insertions(+)
 create mode 100644 gcc/testsuite/rust/debug/chartype.rs
 create mode 100644 gcc/testsuite/rust/debug/custom_link_section.rs
 create mode 100644 gcc/testsuite/rust/debug/debug.exp
 create mode 100644 gcc/testsuite/rust/debug/i8u8.rs
 create mode 100644 gcc/testsuite/rust/debug/lang.rs
 create mode 100644 gcc/testsuite/rust/debug/no_mangle.rs
 create mode 100644 gcc/testsuite/rust/debug/oldlang.rs
 create mode 100644 gcc/testsuite/rust/debug/tuple.rs
 create mode 100644 gcc/testsuite/rust/debug/win64-abi.rs

diff --git a/gcc/testsuite/rust/debug/chartype.rs b/gcc/testsuite/rust/debug/chartype.rs
new file mode 100644
index 00000000000..69e7ab0b17f
--- /dev/null
+++ b/gcc/testsuite/rust/debug/chartype.rs
@@ -0,0 +1,10 @@
+// 'char' should use DW_ATE_UTF
+fn main () {
+    let c = 'x';
+// { dg-do compile }
+// Use -w to avoid warnings about the unused variables
+// DW_ATE_UTF entered in DWARF 4.
+// { dg-options "-w -gdwarf-4 -dA" }
+// DW_ATE_UTF = 0x10
+// { dg-final { scan-assembler "0x10\[ \t]\[^\n\r]* DW_AT_encoding" } } */
+}
diff --git a/gcc/testsuite/rust/debug/custom_link_section.rs b/gcc/testsuite/rust/debug/custom_link_section.rs
new file mode 100644
index 00000000000..142f3513136
--- /dev/null
+++ b/gcc/testsuite/rust/debug/custom_link_section.rs
@@ -0,0 +1,13 @@
+#[link_section = ".universe"]
+fn not_in_text() -> i32 {
+    42
+}
+
+fn main() -> i32 {
+// { dg-do compile }
+// { dg-options "-gdwarf-5 -dA -w" }
+    not_in_text();
+// { dg-final { scan-assembler ".universe" } } */
+
+    0
+}
diff --git a/gcc/testsuite/rust/debug/debug.exp b/gcc/testsuite/rust/debug/debug.exp
new file mode 100644
index 00000000000..c71b5930d90
--- /dev/null
+++ b/gcc/testsuite/rust/debug/debug.exp
@@ -0,0 +1,33 @@
+# Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+# 
+# This program 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/>.
+
+# Debugging tests.
+
+# Load support procs.
+load_lib rust-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+set saved-dg-do-what-default ${dg-do-what-default}
+
+set dg-do-what-default "compile"
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.rs]] "" ""
+set dg-do-what-default ${saved-dg-do-what-default}
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/rust/debug/i8u8.rs b/gcc/testsuite/rust/debug/i8u8.rs
new file mode 100644
index 00000000000..1cd21a4a8ff
--- /dev/null
+++ b/gcc/testsuite/rust/debug/i8u8.rs
@@ -0,0 +1,12 @@
+// i8 and u8 types should not have the DWARF 'char' encoding.
+fn main () {
+    let x : i8 = 5;
+    let y : u8 = 7;
+// { dg-do compile }
+// Use -w to avoid warnings about the unused variables
+// { dg-options "-w -g -dA" }
+// DW_ATE_signed_char = 6
+// { dg-final { scan-assembler-not "0x6\[ \t]\[^\n\r]* DW_AT_encoding" } } */
+// DW_ATE_unsigned_char = 8
+// { dg-final { scan-assembler-not "0x8\[ \t]\[^\n\r]* DW_AT_encoding" } } */
+}
diff --git a/gcc/testsuite/rust/debug/lang.rs b/gcc/testsuite/rust/debug/lang.rs
new file mode 100644
index 00000000000..12e0b587a02
--- /dev/null
+++ b/gcc/testsuite/rust/debug/lang.rs
@@ -0,0 +1,6 @@
+fn main () {
+// { dg-do compile }
+// { dg-options "-gdwarf-5 -dA" }
+// DW_LANG_Rust is 0x1c
+// { dg-final { scan-assembler "0x1c\[ \t]\[^\n\r]* DW_AT_language" } } */
+}
diff --git a/gcc/testsuite/rust/debug/no_mangle.rs b/gcc/testsuite/rust/debug/no_mangle.rs
new file mode 100644
index 00000000000..0cef40482f4
--- /dev/null
+++ b/gcc/testsuite/rust/debug/no_mangle.rs
@@ -0,0 +1,17 @@
+#[no_mangle]
+fn do_not_mangle() -> i32 {
+    0 
+}
+
+fn please_mangle() {}
+
+fn main() {
+// { dg-do compile }
+// { dg-options "-gdwarf-5 -dA" }
+    let _ = do_not_mangle();
+    please_mangle();
+// look for unmangled function name:
+// { dg-final { scan-assembler "do_not_mangle:" } } */
+// look for legacy mangled function name:
+// { dg-final { scan-assembler "13please_mangle" } } */
+}
diff --git a/gcc/testsuite/rust/debug/oldlang.rs b/gcc/testsuite/rust/debug/oldlang.rs
new file mode 100644
index 00000000000..ddacf0e4392
--- /dev/null
+++ b/gcc/testsuite/rust/debug/oldlang.rs
@@ -0,0 +1,6 @@
+fn main () {
+// { dg-do compile }
+// { dg-options "-gstrict-dwarf -gdwarf-3 -dA" }
+// DW_LANG_Rust_old is 0x9000
+// { dg-final { scan-assembler "0x9000\[ \t]\[^\n\r]* DW_AT_language" } } */
+}
diff --git a/gcc/testsuite/rust/debug/tuple.rs b/gcc/testsuite/rust/debug/tuple.rs
new file mode 100644
index 00000000000..e51a5ffdbb6
--- /dev/null
+++ b/gcc/testsuite/rust/debug/tuple.rs
@@ -0,0 +1,8 @@
+fn main () {
+// { dg-do compile }
+// { dg-options "-gdwarf-5 -dA -w" }
+    let x = (32, 32);
+// Look for field __0 and __1
+// { dg-final { scan-assembler "__0" } } */
+// { dg-final { scan-assembler "__1" } } */
+}
diff --git a/gcc/testsuite/rust/debug/win64-abi.rs b/gcc/testsuite/rust/debug/win64-abi.rs
new file mode 100644
index 00000000000..b2b08cd5114
--- /dev/null
+++ b/gcc/testsuite/rust/debug/win64-abi.rs
@@ -0,0 +1,11 @@
+// { dg-do compile { target { x86_64-*-* } } }
+// { dg-options "-gdwarf-5 -dA -w -O1 -m64" }
+pub extern "win64" fn square(num: i32) -> i32 {
+    num * num
+}
+
+fn main() {
+    // MS ABI dictates that the first argument is ecx instead of edi from the sysv world
+    // { dg-final { scan-assembler "%ecx, %ecx" } }
+    square(1);
+}
-- 
2.25.1


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

* [PATCH Rust front-end v2 04/37] gccrs: Add link cases testsuite
  2022-08-24 11:59 Rust frontend patches v2 herron.philip
                   ` (2 preceding siblings ...)
  2022-08-24 11:59 ` [PATCH Rust front-end v2 03/37] gccrs: Add Debug info testsuite herron.philip
@ 2022-08-24 11:59 ` herron.philip
  2022-08-24 11:59 ` [PATCH Rust front-end v2 05/37] gccrs: Add general compilation test cases herron.philip
                   ` (33 subsequent siblings)
  37 siblings, 0 replies; 57+ messages in thread
From: herron.philip @ 2022-08-24 11:59 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

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

This testsuite is heavily inspired from the lto testsuite which uses a
pattern that each file is compiled to an object file and finally linked
together. Since rust does not have headers/prototypes we rely on the
ordering here so that all files numbered greater than zero get compiled to
object files first leaving the _0 file free to test the 'extern crate' and
use keywords to force testing of the compiler to read metadata from the
other 'crates'.
---
 gcc/testsuite/rust/link/generic_function_0.rs |   7 +
 gcc/testsuite/rust/link/generic_function_1.rs |   3 +
 gcc/testsuite/rust/link/link.exp              | 172 ++++++++++++++++++
 gcc/testsuite/rust/link/simple_function_0.rs  |   8 +
 gcc/testsuite/rust/link/simple_function_1.rs  |   3 +
 gcc/testsuite/rust/link/trait_import_0.rs     |  19 ++
 gcc/testsuite/rust/link/trait_import_1.rs     |   6 +
 7 files changed, 218 insertions(+)
 create mode 100644 gcc/testsuite/rust/link/generic_function_0.rs
 create mode 100644 gcc/testsuite/rust/link/generic_function_1.rs
 create mode 100644 gcc/testsuite/rust/link/link.exp
 create mode 100644 gcc/testsuite/rust/link/simple_function_0.rs
 create mode 100644 gcc/testsuite/rust/link/simple_function_1.rs
 create mode 100644 gcc/testsuite/rust/link/trait_import_0.rs
 create mode 100644 gcc/testsuite/rust/link/trait_import_1.rs

diff --git a/gcc/testsuite/rust/link/generic_function_0.rs b/gcc/testsuite/rust/link/generic_function_0.rs
new file mode 100644
index 00000000000..58b8eb13db6
--- /dev/null
+++ b/gcc/testsuite/rust/link/generic_function_0.rs
@@ -0,0 +1,7 @@
+extern crate generic_function_1;
+use generic_function_1::generic_function;
+
+fn main() -> i32 {
+    let a = generic_function(123);
+    a - 123
+}
diff --git a/gcc/testsuite/rust/link/generic_function_1.rs b/gcc/testsuite/rust/link/generic_function_1.rs
new file mode 100644
index 00000000000..8fb0788e388
--- /dev/null
+++ b/gcc/testsuite/rust/link/generic_function_1.rs
@@ -0,0 +1,3 @@
+pub fn generic_function<X>(a: X) -> X {
+    a
+}
diff --git a/gcc/testsuite/rust/link/link.exp b/gcc/testsuite/rust/link/link.exp
new file mode 100644
index 00000000000..8b2e93ceab6
--- /dev/null
+++ b/gcc/testsuite/rust/link/link.exp
@@ -0,0 +1,172 @@
+# Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+# 
+# This program 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/>.
+
+# Execute tests, torture testing.
+
+# Load support procs.
+load_lib rust-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+set saved-dg-do-what-default ${dg-do-what-default}
+
+set dg-do-what-default "assemble"
+
+# rs-obj -- compile to an object file
+#
+# SOURCE is the source file
+# DEST is the object file
+# OPTALL is the list of compiler options to use with all tests
+# OPTFILE is the list of compiler options to use with this file
+# OPTSTR is the options to print with test messages
+# XFAILDATA is the xfail data to be passed to the compiler
+proc rs-obj { source dest optall optfile optstr xfaildata } {
+    global tool
+    global compiler_conditional_xfail_data
+
+    # Set up the options for compiling this file.
+    set options ""
+    lappend options "additional_flags=$optall $optfile"
+
+    set compiler_conditional_xfail_data $xfaildata
+    set comp_output [${tool}_target_compile "$source" "$dest" object $options]
+}
+
+# rs-execute -- compile multi-file tests
+#
+# SRC1 is the full pathname of the main file of the testcase.
+# SID identifies a test suite in the names of temporary files.
+proc rs-execute-1 { src1 } {
+    global srcdir tmpdir
+    
+    # Get extra flags for this test from the primary source file, and
+    # process other dg-* options that this suite supports.  Warn about
+    # unsupported flags.
+    verbose "rs-execute: $src1" 1
+    set compile_type "run"
+    set compile_xfail(0) "" 
+
+    # Set up the names of the other source files.
+    set dir [file dirname $src1]
+    set base [file rootname $src1]
+    set base [string range $base [string length $dir] end]
+    regsub "_0" $base "" base
+    regsub "/" $base "" base
+    set src_list $src1
+    set i 1
+    set done 0
+    while { !$done } {
+	set names [glob -nocomplain -types f -- "${dir}/${base}_${i}.*"]
+	if { [llength ${names}] > 1 } {
+	    warning "rs-link-execute: more than one file matched ${dir}/${base}_${i}.*"
+	}
+	if { [llength ${names}] == 1 } {
+	    lappend src_list [lindex ${names} 0]
+	    incr i
+	} else {
+	    set num_srcs ${i}
+	    set done 1
+	}
+    }
+
+
+    # Define the names of the object files.
+    set obj_list ""
+    for {set i 0} {$i < $num_srcs} {incr i} {
+	lappend obj_list "${base}_${i}.o"
+    }
+
+    # Get the base name of this test, for use in messages.
+    set testcase [lindex ${src_list} 0]
+
+    # Remove the $srcdir and $tmpdir prefixes from $src1.  (It would
+    # be possible to use "regsub" here, if we were careful to escape
+    # all regular expression characters in $srcdir and $tmpdir, but
+    # that would be more complicated that this approach.) 
+    if {[string first "$srcdir/" "${testcase}"] == 0} {
+	set testcase [string range "${testcase}" [string length "$srcdir/"] end]
+    }
+    if {[string first "$tmpdir/" "$testcase"] == 0} {
+	set testcase [string range "$testcase" [string length "$tmpdir/"] end]
+	set testcase "tmpdir-$testcase"
+    }
+    # If we couldn't rip $srcdir out of `src1' then just do the best we can.
+    # The point is to reduce the unnecessary noise in the logs.  Don't strip
+    # out too much because different testcases with the same name can confuse
+    # `test-tool'.
+    if [string match "/*" $testcase] then {
+        set testcase "[file tail [file dirname $src1]]/[file tail $src1]"
+    }
+
+    # Set up the base name of executable files so they'll be unique.
+    regsub -all "\[./\]" $testcase "-" execbase
+
+    verbose "Testing $testcase - $obj_list - $src_list"
+    
+    # There's a unique name for each executable we generate.
+    set execname "${execbase}-1.exe"
+
+    # The LTO tests don't use dg-test, so testname_with_flags and
+    # output_file need to be defined explicitly for each file.  scan-symbol
+    # directives rely on both of these to be defined to find the symbol to
+    # scan and for the text to print in the PASS/FAIL since they can also
+    # be called from dg-test.  testname_with_flags is also used via
+    # testname-for-summary when calling into generic function below to
+    # clean temporary files.
+    set output_file $execname
+    set testname_with_flags $execname
+
+    file_on_host delete $execname
+    
+    rs-obj [lindex ${src_list} 1] [lindex ${obj_list} 1] "" "" "" ""
+    rs-obj [lindex ${src_list} 0] [lindex ${obj_list} 0] "" "" "" ""
+
+    gcc-dg-runtest [lindex ${src_list} 0] "" ""
+
+    # FIXME it would be ideal if we could link then execute these tests.
+    # I was not able to figure out how to specify gc-dg-runtest to link
+    # against the first object.
+}
+
+proc rs-link-execute { src1 } {
+    rs-execute-1 $src1
+}
+
+# Main loop.
+foreach src [lsort [find $srcdir/$subdir *_0.rs]] {
+    # If we're only testing specific files and this isn't one of them, skip it.
+    if ![runtest_file_p $runtests $src] then {
+	continue
+    }
+
+    # To prevent 'runtest_file_p' being tested again (for example, via
+    # 'gcc-dg-runtest'), with undesirable consequences due to its side effects,
+    # interpose a dummy:
+    rename runtest_file_p saved_runtest_file_p
+    proc runtest_file_p { runtests testcase } {
+	return 1
+    }
+    rs-link-execute $src
+    rename runtest_file_p {}
+    rename saved_runtest_file_p runtest_file_p
+}
+
+set dg-do-what-default ${saved-dg-do-what-default}
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/rust/link/simple_function_0.rs b/gcc/testsuite/rust/link/simple_function_0.rs
new file mode 100644
index 00000000000..5bd4926def8
--- /dev/null
+++ b/gcc/testsuite/rust/link/simple_function_0.rs
@@ -0,0 +1,8 @@
+extern crate simple_function_1;
+use simple_function_1::test_func;
+
+fn main() -> i32 {
+    let a = test_func(123);
+    // { dg-bogus "call to extern function" "" { xfail *-*-* } .-1 }
+    a - 124
+}
diff --git a/gcc/testsuite/rust/link/simple_function_1.rs b/gcc/testsuite/rust/link/simple_function_1.rs
new file mode 100644
index 00000000000..aaa1fc39367
--- /dev/null
+++ b/gcc/testsuite/rust/link/simple_function_1.rs
@@ -0,0 +1,3 @@
+pub fn test_func(a: i32) -> i32 {
+    a + 1
+}
diff --git a/gcc/testsuite/rust/link/trait_import_0.rs b/gcc/testsuite/rust/link/trait_import_0.rs
new file mode 100644
index 00000000000..ac8c5811d22
--- /dev/null
+++ b/gcc/testsuite/rust/link/trait_import_0.rs
@@ -0,0 +1,19 @@
+extern crate trait_import_1;
+use trait_import_1::Add;
+
+struct Foo(i32);
+
+impl Add for Foo {
+    type Output = Foo;
+
+    fn add(self, other: Foo) -> Foo {
+        Foo(self.0 + other.0)
+    }
+}
+
+fn main() -> i32 {
+    let a;
+    a = Foo(1) + Foo(2);
+
+    0
+}
diff --git a/gcc/testsuite/rust/link/trait_import_1.rs b/gcc/testsuite/rust/link/trait_import_1.rs
new file mode 100644
index 00000000000..fc7f5168ede
--- /dev/null
+++ b/gcc/testsuite/rust/link/trait_import_1.rs
@@ -0,0 +1,6 @@
+#[lang = "add"]
+pub trait Add<Rhs = Self> {
+    type Output;
+
+    fn add(self, rhs: Rhs) -> Self::Output;
+}
-- 
2.25.1


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

* [PATCH Rust front-end v2 05/37] gccrs: Add general compilation test cases
  2022-08-24 11:59 Rust frontend patches v2 herron.philip
                   ` (3 preceding siblings ...)
  2022-08-24 11:59 ` [PATCH Rust front-end v2 04/37] gccrs: Add link cases testsuite herron.philip
@ 2022-08-24 11:59 ` herron.philip
  2022-08-24 11:59 ` [PATCH Rust front-end v2 06/37] gccrs: Add execution " herron.philip
                   ` (32 subsequent siblings)
  37 siblings, 0 replies; 57+ messages in thread
From: herron.philip @ 2022-08-24 11:59 UTC (permalink / raw)
  To: gcc-patches
  Cc: gcc-rust, Philip Herron, Arthur Cohen, Thomas Schwinge,
	Mark Wielaard, Marc Poulhiès

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

This suite of tests has two sections compile/*.rs and compile/torture/*.rs.
The first section are all dg-compile tests which contain dg-warning or
dg-error annotations and some with no annotations to ensure they do create
a resulting asm output. The second section is the same but have tests which
are ran with the full torture options, as during development the test case
may have had an issue with a specific optimization level.

Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
Co-authored-by: Thomas Schwinge <thomas@codesourcery.com>
Co-authored-by: Mark Wielaard <mark@klomp.org>
Co-authored-by: Marc Poulhiès <dkm@kataplop.net>
---
 gcc/testsuite/rust/compile/abi-options1.rs    |   7 ++
 gcc/testsuite/rust/compile/array3.rs          |   4 +
 .../rust/compile/array_empty_list.rs          |   4 +
 gcc/testsuite/rust/compile/arrays1.rs         |   4 +
 gcc/testsuite/rust/compile/arrays2.rs         |   5 +
 .../rust/compile/attr-mismatch-crate-name.rs  |   4 +
 gcc/testsuite/rust/compile/attr_cold.rs       |  12 +++
 gcc/testsuite/rust/compile/attr_deprecated.rs |  14 +++
 .../rust/compile/attr_deprecated_2.rs         |  11 +++
 gcc/testsuite/rust/compile/bad-crate-name.rs  |   4 +
 gcc/testsuite/rust/compile/bad=file-name.rs   |   7 ++
 .../rust/compile/bad_as_bool_char.rs          |  18 ++++
 .../rust/compile/bad_file_name.txt.rs         |   3 +
 gcc/testsuite/rust/compile/bad_inner_doc.rs   |  15 +++
 .../rust/compile/bad_pub_enumitems.rs         |  47 +++++++++
 gcc/testsuite/rust/compile/bad_stmt_enums.rs  |  22 +++++
 .../rust/compile/bad_toplevel_enums.rs        |  19 ++++
 gcc/testsuite/rust/compile/bad_tuple_index.rs |  66 +++++++++++++
 gcc/testsuite/rust/compile/bad_type1.rs       |   3 +
 gcc/testsuite/rust/compile/bad_type2.rs       |  14 +++
 gcc/testsuite/rust/compile/break1.rs          |   6 ++
 gcc/testsuite/rust/compile/break2.rs          |  15 +++
 .../compile/builtin_macro_compile_error.rs    |  13 +++
 .../rust/compile/builtin_macro_concat.rs      |  17 ++++
 .../rust/compile/builtin_macro_env.rs         |  20 ++++
 .../compile/builtin_macro_include_bytes.rs    |  13 +++
 .../rust/compile/builtin_macro_include_str.rs |  13 +++
 .../rust/compile/builtin_macro_not_found.rs   |   4 +
 gcc/testsuite/rust/compile/bytecharstring.rs  |   8 ++
 .../rust/compile/canonical_paths1.rs          |  25 +++++
 gcc/testsuite/rust/compile/cast1.rs           |   5 +
 gcc/testsuite/rust/compile/cfg1.rs            |  31 ++++++
 gcc/testsuite/rust/compile/cfg2.rs            |  13 +++
 gcc/testsuite/rust/compile/cfg3.rs            |  11 +++
 gcc/testsuite/rust/compile/cfg4.rs            |  11 +++
 gcc/testsuite/rust/compile/cfg5.rs            |  11 +++
 gcc/testsuite/rust/compile/compile.exp        |  35 +++++++
 gcc/testsuite/rust/compile/complex-path1.rs   |  18 ++++
 gcc/testsuite/rust/compile/const-issue1440.rs |  76 +++++++++++++++
 gcc/testsuite/rust/compile/const1.rs          |   6 ++
 gcc/testsuite/rust/compile/const2.rs          |   7 ++
 gcc/testsuite/rust/compile/const3.rs          |   7 ++
 .../rust/compile/const_generics_1.rs          |  19 ++++
 .../rust/compile/const_generics_2.rs          |   4 +
 .../rust/compile/const_generics_3.rs          |  26 +++++
 .../rust/compile/const_generics_4.rs          |   7 ++
 .../rust/compile/const_generics_5.rs          |  12 +++
 .../rust/compile/const_generics_6.rs          |   2 +
 gcc/testsuite/rust/compile/continue1.rs       |  10 ++
 gcc/testsuite/rust/compile/deadcode_err1.rs   |  11 +++
 gcc/testsuite/rust/compile/deadcode_err2.rs   |  16 +++
 .../rust/compile/debug-diagnostics-default.rs |   5 +
 .../rust/compile/debug-diagnostics-off.rs     |   7 ++
 .../rust/compile/debug-diagnostics-on.rs      |   7 ++
 .../compile/doc_isolated_cr_block_comment.rs  |   3 +
 .../doc_isolated_cr_inner_block_comment.rs    |   5 +
 .../doc_isolated_cr_inner_line_comment.rs     |   5 +
 .../compile/doc_isolated_cr_line_comment.rs   |   3 +
 gcc/testsuite/rust/compile/dup_fields.rs      |  23 +++++
 .../compile/empty_comment_before_match.rs     |   7 ++
 .../rust/compile/expected_type_args2.rs       |   6 ++
 .../rust/compile/expected_type_args3.rs       |   8 ++
 gcc/testsuite/rust/compile/func1.rs           |   9 ++
 gcc/testsuite/rust/compile/func2.rs           |   7 ++
 gcc/testsuite/rust/compile/func3.rs           |   9 ++
 gcc/testsuite/rust/compile/func4.rs           |   6 ++
 gcc/testsuite/rust/compile/func5.rs           |   7 ++
 .../rust/compile/generic-default1.rs          |   7 ++
 gcc/testsuite/rust/compile/generics1.rs       |  11 +++
 gcc/testsuite/rust/compile/generics10.rs      |  12 +++
 gcc/testsuite/rust/compile/generics11.rs      |  12 +++
 gcc/testsuite/rust/compile/generics12.rs      |   6 ++
 gcc/testsuite/rust/compile/generics13.rs      |   1 +
 gcc/testsuite/rust/compile/generics2.rs       |  11 +++
 gcc/testsuite/rust/compile/generics3.rs       |  10 ++
 gcc/testsuite/rust/compile/generics4.rs       |  16 +++
 gcc/testsuite/rust/compile/generics5.rs       |  10 ++
 gcc/testsuite/rust/compile/generics6.rs       |  31 ++++++
 gcc/testsuite/rust/compile/generics7.rs       |  26 +++++
 gcc/testsuite/rust/compile/generics8.rs       |  15 +++
 gcc/testsuite/rust/compile/generics9.rs       |  10 ++
 .../rust/compile/implicit_returns_err1.rs     |  12 +++
 .../rust/compile/implicit_returns_err2.rs     |  10 ++
 .../rust/compile/implicit_returns_err3.rs     |   9 ++
 .../rust/compile/implicit_returns_err4.rs     |  10 ++
 .../rust/compile/infer-crate-name.rs          |   7 ++
 gcc/testsuite/rust/compile/inline_1.rs        |  16 +++
 gcc/testsuite/rust/compile/inline_2.rs        |   6 ++
 gcc/testsuite/rust/compile/issue-1005.rs      |   4 +
 gcc/testsuite/rust/compile/issue-1019.rs      |  19 ++++
 gcc/testsuite/rust/compile/issue-1023.rs      |   4 +
 gcc/testsuite/rust/compile/issue-1031.rs      |  17 ++++
 gcc/testsuite/rust/compile/issue-1034.rs      |  16 +++
 gcc/testsuite/rust/compile/issue-1089.rs      |   6 ++
 gcc/testsuite/rust/compile/issue-1128.rs      |   6 ++
 gcc/testsuite/rust/compile/issue-1129-1.rs    |   4 +
 gcc/testsuite/rust/compile/issue-1129-2.rs    |  22 +++++
 gcc/testsuite/rust/compile/issue-1130.rs      |  47 +++++++++
 gcc/testsuite/rust/compile/issue-1131.rs      |   4 +
 gcc/testsuite/rust/compile/issue-1152.rs      |   8 ++
 gcc/testsuite/rust/compile/issue-1165.rs      |   5 +
 gcc/testsuite/rust/compile/issue-1173.rs      |  23 +++++
 gcc/testsuite/rust/compile/issue-1226.rs      |   6 ++
 gcc/testsuite/rust/compile/issue-1234.rs      |   4 +
 gcc/testsuite/rust/compile/issue-1235.rs      |  21 ++++
 gcc/testsuite/rust/compile/issue-1237.rs      |  23 +++++
 gcc/testsuite/rust/compile/issue-1251.rs      |  14 +++
 gcc/testsuite/rust/compile/issue-1271.rs      |   5 +
 gcc/testsuite/rust/compile/issue-1289.rs      |  43 +++++++++
 gcc/testsuite/rust/compile/issue-1323-1.rs    |  18 ++++
 gcc/testsuite/rust/compile/issue-1323-2.rs    |  16 +++
 gcc/testsuite/rust/compile/issue-1383.rs      |   8 ++
 gcc/testsuite/rust/compile/issue-1393.rs      |  13 +++
 gcc/testsuite/rust/compile/issue-1447.rs      |  28 ++++++
 gcc/testsuite/rust/compile/issue-407-2.rs     |  21 ++++
 gcc/testsuite/rust/compile/issue-407.rs       |   9 ++
 gcc/testsuite/rust/compile/issue-557.rs       |   4 +
 gcc/testsuite/rust/compile/issue-635-1.rs     |   5 +
 gcc/testsuite/rust/compile/issue-635-2.rs     |   5 +
 gcc/testsuite/rust/compile/lookup_err1.rs     |   7 ++
 .../rust/compile/macro-issue1053-2.rs         |   5 +
 gcc/testsuite/rust/compile/macro-issue1053.rs |   3 +
 gcc/testsuite/rust/compile/macro-issue1224.rs |   9 ++
 gcc/testsuite/rust/compile/macro-issue1233.rs |  22 +++++
 .../rust/compile/macro-issue1395-2.rs         |   7 ++
 gcc/testsuite/rust/compile/macro-issue1395.rs |   5 +
 .../rust/compile/macro-issue1400-2.rs         |  32 ++++++
 gcc/testsuite/rust/compile/macro-issue1400.rs |  33 +++++++
 gcc/testsuite/rust/compile/macro1.rs          |   3 +
 gcc/testsuite/rust/compile/macro10.rs         |  11 +++
 gcc/testsuite/rust/compile/macro11.rs         |  11 +++
 gcc/testsuite/rust/compile/macro12.rs         |   8 ++
 gcc/testsuite/rust/compile/macro13.rs         |  12 +++
 gcc/testsuite/rust/compile/macro14.rs         |  10 ++
 gcc/testsuite/rust/compile/macro15.rs         |  12 +++
 gcc/testsuite/rust/compile/macro16.rs         |  11 +++
 gcc/testsuite/rust/compile/macro17.rs         |  10 ++
 gcc/testsuite/rust/compile/macro18.rs         |  14 +++
 gcc/testsuite/rust/compile/macro19.rs         |  19 ++++
 gcc/testsuite/rust/compile/macro2.rs          |   3 +
 gcc/testsuite/rust/compile/macro20.rs         |  16 +++
 gcc/testsuite/rust/compile/macro21.rs         |   9 ++
 gcc/testsuite/rust/compile/macro22.rs         |  10 ++
 gcc/testsuite/rust/compile/macro23.rs         |  25 +++++
 gcc/testsuite/rust/compile/macro25.rs         |   9 ++
 gcc/testsuite/rust/compile/macro26.rs         |  10 ++
 gcc/testsuite/rust/compile/macro27.rs         |   8 ++
 gcc/testsuite/rust/compile/macro28.rs         |   8 ++
 gcc/testsuite/rust/compile/macro29.rs         |   8 ++
 gcc/testsuite/rust/compile/macro3.rs          |   3 +
 gcc/testsuite/rust/compile/macro30.rs         |   8 ++
 gcc/testsuite/rust/compile/macro31.rs         |   8 ++
 gcc/testsuite/rust/compile/macro32.rs         |  19 ++++
 gcc/testsuite/rust/compile/macro33.rs         |   5 +
 gcc/testsuite/rust/compile/macro34.rs         |   3 +
 gcc/testsuite/rust/compile/macro35.rs         |   7 ++
 gcc/testsuite/rust/compile/macro36.rs         |   3 +
 gcc/testsuite/rust/compile/macro37.rs         |   5 +
 gcc/testsuite/rust/compile/macro38.rs         |   5 +
 gcc/testsuite/rust/compile/macro39.rs         |   5 +
 gcc/testsuite/rust/compile/macro4.rs          |   3 +
 gcc/testsuite/rust/compile/macro40.rs         |  48 +++++++++
 gcc/testsuite/rust/compile/macro41.rs         |  13 +++
 gcc/testsuite/rust/compile/macro42.rs         |  32 ++++++
 gcc/testsuite/rust/compile/macro5.rs          |   3 +
 gcc/testsuite/rust/compile/macro6.rs          |  11 +++
 gcc/testsuite/rust/compile/macro7.rs          |  13 +++
 gcc/testsuite/rust/compile/macro8.rs          |  12 +++
 gcc/testsuite/rust/compile/macro9.rs          |  17 ++++
 gcc/testsuite/rust/compile/macro_return.rs    |  10 ++
 gcc/testsuite/rust/compile/match1.rs          |  16 +++
 gcc/testsuite/rust/compile/match2.rs          |  15 +++
 gcc/testsuite/rust/compile/match3.rs          |  16 +++
 gcc/testsuite/rust/compile/match4.rs          |  16 +++
 gcc/testsuite/rust/compile/match5.rs          |  15 +++
 gcc/testsuite/rust/compile/match6.rs          |  18 ++++
 gcc/testsuite/rust/compile/match7.rs          |  12 +++
 gcc/testsuite/rust/compile/method1.rs         |  13 +++
 gcc/testsuite/rust/compile/method2.rs         |  16 +++
 .../rust/compile/mismatch-crate-name.rs       |   4 +
 .../rust/compile/missing_middle/both_path.rs  |   3 +
 .../compile/missing_middle/explicit.not.rs    |   1 +
 .../rust/compile/missing_middle/inner_path.rs |   3 +
 .../rust/compile/missing_middle/other.rs      |   3 +
 .../rust/compile/missing_middle/outer_path.rs |   3 +
 .../rust/compile/missing_middle/sub/mod.rs    |   3 +
 gcc/testsuite/rust/compile/missing_return1.rs |   6 ++
 .../rust/compile/mod_missing_middle.rs        |  29 ++++++
 gcc/testsuite/rust/compile/never_type_err1.rs |  14 +++
 gcc/testsuite/rust/compile/privacy1.rs        |  11 +++
 gcc/testsuite/rust/compile/privacy2.rs        |  13 +++
 gcc/testsuite/rust/compile/privacy3.rs        |  28 ++++++
 gcc/testsuite/rust/compile/privacy4.rs        |  19 ++++
 gcc/testsuite/rust/compile/privacy5.rs        |  17 ++++
 gcc/testsuite/rust/compile/privacy6.rs        |  39 ++++++++
 .../rust/compile/pub_restricted_1.rs          |  13 +++
 .../rust/compile/pub_restricted_2.rs          |  18 ++++
 .../rust/compile/pub_restricted_3.rs          |  11 +++
 .../compile/raw_identifiers_bad_keywords.rs   |   3 +
 .../compile/raw_identifiers_underscore.rs     |   3 +
 gcc/testsuite/rust/compile/rawbytestring.rs   | Bin 0 -> 3234 bytes
 gcc/testsuite/rust/compile/redef_error1.rs    |   8 ++
 gcc/testsuite/rust/compile/redef_error2.rs    |   4 +
 gcc/testsuite/rust/compile/redef_error3.rs    |   9 ++
 gcc/testsuite/rust/compile/redef_error4.rs    |  27 ++++++
 gcc/testsuite/rust/compile/redef_error5.rs    |   8 ++
 gcc/testsuite/rust/compile/redef_error6.rs    |  13 +++
 gcc/testsuite/rust/compile/reference1.rs      |   6 ++
 gcc/testsuite/rust/compile/self-path1.rs      |  12 +++
 gcc/testsuite/rust/compile/self-path2.rs      |  21 ++++
 gcc/testsuite/rust/compile/shadow1.rs         |   7 ++
 .../rust/compile/specify-crate-name.rs        |   7 ++
 gcc/testsuite/rust/compile/static_var1.rs     |   5 +
 .../rust/compile/stmt_with_block_err1.rs      |  17 ++++
 gcc/testsuite/rust/compile/struct_align1.rs   |  19 ++++
 gcc/testsuite/rust/compile/struct_align2.rs   |  18 ++++
 gcc/testsuite/rust/compile/struct_init1.rs    |  10 ++
 gcc/testsuite/rust/compile/struct_pack1.rs    |  19 ++++
 gcc/testsuite/rust/compile/struct_pack2.rs    |  18 ++++
 gcc/testsuite/rust/compile/syntax-only.rs     |   6 ++
 gcc/testsuite/rust/compile/test_mod.rs        |   6 ++
 .../torture/all_doc_comment_line_blocks.rs    |  45 +++++++++
 .../all_doc_comment_line_blocks_crlf.rs       |  48 +++++++++
 .../torture/arithmetic_expressions1.rs        |  30 ++++++
 .../compile/torture/array_const_fold_1.rs     |   2 +
 .../compile/torture/array_const_fold_2.rs     |   3 +
 .../rust/compile/torture/array_function.rs    |   8 ++
 .../rust/compile/torture/array_type_infer.rs  |   4 +
 .../rust/compile/torture/array_zero_length.rs |   4 +
 gcc/testsuite/rust/compile/torture/arrays1.rs |   9 ++
 gcc/testsuite/rust/compile/torture/arrays2.rs |   8 ++
 gcc/testsuite/rust/compile/torture/arrays3.rs |   6 ++
 gcc/testsuite/rust/compile/torture/arrays4.rs |   6 ++
 gcc/testsuite/rust/compile/torture/arrays5.rs |   6 ++
 gcc/testsuite/rust/compile/torture/arrays6.rs |  10 ++
 .../rust/compile/torture/arrays_index1.rs     |   9 ++
 .../rust/compile/torture/arrays_index2.rs     |   4 +
 .../rust/compile/torture/arrays_index3.rs     |  15 +++
 .../rust/compile/torture/as_bool_char.rs      |  36 +++++++
 .../rust/compile/torture/associated_types1.rs |  12 +++
 .../rust/compile/torture/autoderef1.rs        |  15 +++
 .../rust/compile/torture/block_expr1.rs       |  29 ++++++
 .../rust/compile/torture/block_expr2.rs       |  15 +++
 .../rust/compile/torture/block_expr3.rs       |  14 +++
 .../rust/compile/torture/block_expr4.rs       |   8 ++
 .../rust/compile/torture/block_expr5.rs       |  40 ++++++++
 .../compile/torture/block_expr_parser_bug.rs  |   5 +
 gcc/testsuite/rust/compile/torture/bom.rs     |   1 +
 .../rust/compile/torture/bom_comment.rs       |   2 +
 .../rust/compile/torture/bom_shebang.rs       |   2 +
 .../rust/compile/torture/bom_whitespace.rs    |   2 +
 .../rust/compile/torture/bools_eq.rs          |  18 ++++
 gcc/testsuite/rust/compile/torture/borrow1.rs |  17 ++++
 .../rust/compile/torture/borrow_function.rs   |   5 +
 .../rust/compile/torture/break_function.rs    |  10 ++
 .../rust/compile/torture/byte_char_str.rs     |   8 ++
 .../rust/compile/torture/byte_str.rs          |   4 +
 gcc/testsuite/rust/compile/torture/cast1.rs   |   5 +
 gcc/testsuite/rust/compile/torture/cast2.rs   |   5 +
 gcc/testsuite/rust/compile/torture/cast3.rs   |   6 ++
 .../rust/compile/torture/cfg_attr.rs          |   7 ++
 gcc/testsuite/rust/compile/torture/char1.rs   |   4 +
 .../compile/torture/check-doc-attr-string.rs  |  18 ++++
 .../rust/compile/torture/coercion1.rs         |  11 +++
 .../rust/compile/torture/coercion2.rs         |  20 ++++
 .../rust/compile/torture/comparison_expr1.rs  |  38 ++++++++
 .../rust/compile/torture/compile.exp          |  33 +++++++
 .../torture/compound_assignment_expr1.rs      |  23 +++++
 .../rust/compile/torture/conditional.rs       |  11 +++
 .../rust/compile/torture/constant1.rs         |   9 ++
 .../rust/compile/torture/constant2.rs         |   6 ++
 .../rust/compile/torture/constant3.rs         |  10 ++
 .../rust/compile/torture/deadcode1.rs         |  22 +++++
 .../rust/compile/torture/deadcode2.rs         |  10 ++
 gcc/testsuite/rust/compile/torture/deref1.rs  |   6 ++
 .../rust/compile/torture/deref_function.rs    |  10 ++
 .../rust/compile/torture/doc_comment.rs       |  16 +++
 gcc/testsuite/rust/compile/torture/enum1.rs   |  13 +++
 .../rust/compile/torture/extern_mod1.rs       |   6 ++
 .../rust/compile/torture/extern_mod2.rs       |  23 +++++
 gcc/testsuite/rust/compile/torture/float1.rs  |   9 ++
 .../rust/compile/torture/float_types.rs       |  13 +++
 .../rust/compile/torture/forward_decl_1.rs    |  11 +++
 .../rust/compile/torture/forward_decl_2.rs    |   6 ++
 .../compile/torture/forward_decl_3-unsafe.rs  |  13 +++
 .../rust/compile/torture/forward_decl_3.rs    |  11 +++
 .../rust/compile/torture/forward_decl_4.rs    |   9 ++
 .../rust/compile/torture/forward_decl_5.rs    |  19 ++++
 gcc/testsuite/rust/compile/torture/func1.rs   |   7 ++
 gcc/testsuite/rust/compile/torture/func2.rs   |  20 ++++
 .../compile/torture/function_reference1.rs    |   9 ++
 .../compile/torture/function_reference2.rs    |   9 ++
 .../compile/torture/function_reference3.rs    |  20 ++++
 .../compile/torture/function_reference4.rs    |   9 ++
 .../rust/compile/torture/generics1.rs         |  51 ++++++++++
 .../rust/compile/torture/generics10.rs        |  20 ++++
 .../rust/compile/torture/generics11.rs        |   8 ++
 .../rust/compile/torture/generics12.rs        |  17 ++++
 .../rust/compile/torture/generics13.rs        |  41 ++++++++
 .../rust/compile/torture/generics14.rs        |  20 ++++
 .../rust/compile/torture/generics15.rs        |  23 +++++
 .../rust/compile/torture/generics16.rs        |  31 ++++++
 .../rust/compile/torture/generics17.rs        |  19 ++++
 .../rust/compile/torture/generics18.rs        |  20 ++++
 .../rust/compile/torture/generics19.rs        |  12 +++
 .../rust/compile/torture/generics2.rs         |  45 +++++++++
 .../rust/compile/torture/generics20.rs        |  12 +++
 .../rust/compile/torture/generics21.rs        |  13 +++
 .../rust/compile/torture/generics22.rs        |  13 +++
 .../rust/compile/torture/generics23.rs        |   6 ++
 .../rust/compile/torture/generics24.rs        |  34 +++++++
 .../rust/compile/torture/generics25.rs        |   9 ++
 .../rust/compile/torture/generics26.rs        |  21 ++++
 .../rust/compile/torture/generics27.rs        |  16 +++
 .../rust/compile/torture/generics28.rs        |  18 ++++
 .../rust/compile/torture/generics29.rs        |  16 +++
 .../rust/compile/torture/generics3.rs         |  15 +++
 .../rust/compile/torture/generics30.rs        |  16 +++
 .../rust/compile/torture/generics31.rs        |  15 +++
 .../rust/compile/torture/generics32.rs        |  15 +++
 .../rust/compile/torture/generics4.rs         |  17 ++++
 .../rust/compile/torture/generics5.rs         |  10 ++
 .../rust/compile/torture/generics6.rs         |  16 +++
 .../rust/compile/torture/generics7.rs         |  14 +++
 .../rust/compile/torture/generics8.rs         |  18 ++++
 .../rust/compile/torture/generics9.rs         |  25 +++++
 .../compile/torture/grouped_expr_function.rs  |   6 ++
 .../torture/identifier-missing-impl-1.rs      |  19 ++++
 gcc/testsuite/rust/compile/torture/if.rs      |  19 ++++
 gcc/testsuite/rust/compile/torture/if_elif.rs |  20 ++++
 .../compile/torture/if_elif_else_expr1.rs     |  14 +++
 gcc/testsuite/rust/compile/torture/if_else.rs |  19 ++++
 .../rust/compile/torture/ifunaryexpr.rs       |  22 +++++
 .../rust/compile/torture/impl_block1.rs       |  23 +++++
 .../rust/compile/torture/impl_block2.rs       |  28 ++++++
 .../rust/compile/torture/impl_block3.rs       |  36 +++++++
 .../rust/compile/torture/impl_block_unused.rs |  17 ++++
 .../rust/compile/torture/implicit_returns1.rs |  73 ++++++++++++++
 .../rust/compile/torture/infer_type1.rs       |   4 +
 .../rust/compile/torture/inner_attributes.rs  |   3 +
 .../compile/torture/integer_inference_var1.rs |   6 ++
 .../compile/torture/integer_inference_var2.rs |   6 ++
 .../compile/torture/integer_inference_var3.rs |  11 +++
 .../compile/torture/integer_inference_var4.rs |   4 +
 .../compile/torture/integer_inference_var5.rs |  25 +++++
 .../rust/compile/torture/integer_types.rs     |  27 ++++++
 .../rust/compile/torture/intrinsics-1.rs      |  22 +++++
 .../rust/compile/torture/intrinsics-2.rs      |  22 +++++
 .../torture/isolated_cr_block_comment.rs      |   2 +
 .../torture/isolated_cr_line_comment.rs       |   2 +
 .../rust/compile/torture/issue-1024.rs        |  11 +++
 .../rust/compile/torture/issue-1075.rs        |  42 ++++++++
 .../rust/compile/torture/issue-1432.rs        |  77 +++++++++++++++
 .../rust/compile/torture/issue-1434.rs        |  53 ++++++++++
 .../rust/compile/torture/issue-368.rs         |   9 ++
 .../rust/compile/torture/issue-808.rs         |  20 ++++
 .../rust/compile/torture/issue-862.rs         |  74 ++++++++++++++
 .../rust/compile/torture/issue-893-2.rs       |  35 +++++++
 .../rust/compile/torture/issue-893.rs         |  11 +++
 .../torture/lazybooleanexpr_function.rs       |  14 +++
 .../rust/compile/torture/lifetime1.rs         |   7 ++
 .../rust/compile/torture/literals1.rs         |  11 +++
 gcc/testsuite/rust/compile/torture/loop1.rs   |  10 ++
 gcc/testsuite/rust/compile/torture/loop2.rs   |  14 +++
 gcc/testsuite/rust/compile/torture/loop3.rs   |  14 +++
 gcc/testsuite/rust/compile/torture/loop4.rs   |   7 ++
 gcc/testsuite/rust/compile/torture/loop5.rs   |  14 +++
 gcc/testsuite/rust/compile/torture/loop6.rs   |  11 +++
 gcc/testsuite/rust/compile/torture/loop7.rs   |  13 +++
 .../rust/compile/torture/macro-issue1403.rs   |  23 +++++
 .../rust/compile/torture/macro-issue1426.rs   |  32 ++++++
 .../rust/compile/torture/macro_as_expr.rs     |  14 +++
 gcc/testsuite/rust/compile/torture/match1.rs  |  16 +++
 .../rust/compile/torture/methods1.rs          |  41 ++++++++
 .../rust/compile/torture/methods2.rs          |  43 +++++++++
 .../rust/compile/torture/methods3.rs          |  44 +++++++++
 .../rust/compile/torture/mod-nameresolve.rs   |   5 +
 gcc/testsuite/rust/compile/torture/mod1.rs    |  11 +++
 gcc/testsuite/rust/compile/torture/mod2.rs    |  13 +++
 gcc/testsuite/rust/compile/torture/mod3.rs    |  22 +++++
 .../rust/compile/torture/modules/mod.rs       |   3 +
 .../compile/torture/modules/valid_path.rs     |   1 +
 .../rust/compile/torture/must_use1.rs         |  16 +++
 .../rust/compile/torture/must_use2.rs         |  16 +++
 .../rust/compile/torture/name_resolve1.rs     |  23 +++++
 .../rust/compile/torture/negation_function.rs |   7 ++
 .../rust/compile/torture/nested_fn1.rs        |  10 ++
 .../rust/compile/torture/nested_fn2.rs        |  11 +++
 .../rust/compile/torture/nested_struct1.rs    |  20 ++++
 .../rust/compile/torture/never_type1.rs       |  22 +++++
 .../rust/compile/torture/not_shebang.rs       |   3 +
 .../torture/not_shebang_block_comment.rs      |   1 +
 .../compile/torture/not_shebang_comment.rs    |   3 +
 .../torture/not_shebang_multiline_comment.rs  |   7 ++
 .../compile/torture/not_shebang_spaces.rs     |   6 ++
 .../rust/compile/torture/parameter_usage1.rs  |   8 ++
 gcc/testsuite/rust/compile/torture/parens1.rs |   5 +
 .../rust/compile/torture/pointer1.rs          |   9 ++
 .../rust/compile/torture/primconsts.rs        |  72 ++++++++++++++
 .../rust/compile/torture/prims_struct_eq.rs   |  91 ++++++++++++++++++
 .../rust/compile/torture/range-lang-item1.rs  |  32 ++++++
 .../rust/compile/torture/raw_identifiers.rs   |   3 +
 .../torture/raw_identifiers_keywords.rs       |   3 +
 .../rust/compile/torture/recursive_fn1.rs     |  12 +++
 .../rust/compile/torture/return_function.rs   |   5 +
 .../rust/compile/torture/scoping1.rs          |  11 +++
 .../rust/compile/torture/self_type1.rs        |  12 +++
 gcc/testsuite/rust/compile/torture/shadow1.rs |   6 ++
 gcc/testsuite/rust/compile/torture/shadow2.rs |   5 +
 gcc/testsuite/rust/compile/torture/shebang.rs |   3 +
 .../rust/compile/torture/shebang_plus_attr.rs |   3 +
 .../compile/torture/shebang_plus_attr2.rs     |   3 +
 .../rust/compile/torture/static_function.rs   |   8 ++
 .../rust/compile/torture/static_var1.rs       |   6 ++
 .../rust/compile/torture/stmt_with_block1.rs  |  13 +++
 gcc/testsuite/rust/compile/torture/str1.rs    |   7 ++
 .../rust/compile/torture/struct_access1.rs    |  12 +++
 .../compile/torture/struct_base_init_1.rs     |  13 +++
 .../rust/compile/torture/struct_decl.rs       |  14 +++
 .../rust/compile/torture/struct_init.rs       |  11 +++
 .../rust/compile/torture/struct_init_10.rs    |   9 ++
 .../rust/compile/torture/struct_init_11.rs    |  34 +++++++
 .../rust/compile/torture/struct_init_2.rs     |   6 ++
 .../rust/compile/torture/struct_init_3.rs     |  13 +++
 .../rust/compile/torture/struct_init_4.rs     |  13 +++
 .../rust/compile/torture/struct_init_5.rs     |  10 ++
 .../rust/compile/torture/struct_init_6.rs     |  11 +++
 .../rust/compile/torture/struct_init_7.rs     |  11 +++
 .../rust/compile/torture/struct_init_8.rs     |   7 ++
 .../rust/compile/torture/struct_init_9.rs     |   6 ++
 .../rust/compile/torture/top_attr.rs          |   5 +
 gcc/testsuite/rust/compile/torture/traits1.rs |  16 +++
 .../rust/compile/torture/traits10.rs          |  30 ++++++
 .../rust/compile/torture/traits11.rs          |  31 ++++++
 .../rust/compile/torture/traits12.rs          |  29 ++++++
 .../rust/compile/torture/traits13.rs          |  17 ++++
 .../rust/compile/torture/traits14.rs          |  23 +++++
 .../rust/compile/torture/traits15.rs          |  23 +++++
 .../rust/compile/torture/traits16.rs          |  20 ++++
 .../rust/compile/torture/traits17.rs          |  23 +++++
 .../rust/compile/torture/traits18.rs          |   5 +
 .../rust/compile/torture/traits19.rs          |  33 +++++++
 gcc/testsuite/rust/compile/torture/traits2.rs |  16 +++
 gcc/testsuite/rust/compile/torture/traits3.rs |  15 +++
 gcc/testsuite/rust/compile/torture/traits4.rs |  21 ++++
 gcc/testsuite/rust/compile/torture/traits5.rs |  21 ++++
 gcc/testsuite/rust/compile/torture/traits6.rs |  20 ++++
 gcc/testsuite/rust/compile/torture/traits7.rs |  19 ++++
 gcc/testsuite/rust/compile/torture/traits8.rs |  21 ++++
 gcc/testsuite/rust/compile/torture/traits9.rs |  27 ++++++
 .../compile/torture/transmute-size-check-1.rs |  11 +++
 .../rust/compile/torture/transmute1.rs        |  11 +++
 gcc/testsuite/rust/compile/torture/tuple1.rs  |   6 ++
 gcc/testsuite/rust/compile/torture/tuple2.rs  |   5 +
 gcc/testsuite/rust/compile/torture/tuple3.rs  |   9 ++
 .../compile/torture/tuple_enum_variants.rs    |  23 +++++
 .../compile/torture/tuple_field_access.rs     |   6 ++
 .../rust/compile/torture/tuple_function.rs    |   6 ++
 .../rust/compile/torture/tuple_index.rs       |  32 ++++++
 .../rust/compile/torture/tuple_struct1.rs     |   6 ++
 .../rust/compile/torture/tuple_struct2.rs     |  11 +++
 .../rust/compile/torture/tuple_struct_unit.rs |  11 +++
 .../compile/torture/tuple_struct_unused.rs    |   4 +
 .../rust/compile/torture/type-alias1.rs       |   6 ++
 .../rust/compile/torture/type-alias2.rs       |   8 ++
 .../rust/compile/torture/type_infer1.rs       |  24 +++++
 .../rust/compile/torture/type_infer2.rs       |   9 ++
 .../rust/compile/torture/type_infer3.rs       |  14 +++
 .../rust/compile/torture/type_infer4.rs       |  11 +++
 .../rust/compile/torture/type_infer5.rs       |  13 +++
 .../rust/compile/torture/type_infer6.rs       |  14 +++
 .../rust/compile/torture/unary_operators.rs   |   8 ++
 .../rust/compile/torture/undended-string-1.rs |   5 +
 .../rust/compile/torture/undended-string-2.rs |   5 +
 .../rust/compile/torture/underscore_id.rs     |   4 +
 gcc/testsuite/rust/compile/torture/union.rs   |  32 ++++++
 .../rust/compile/torture/union_union.rs       |  27 ++++++
 .../rust/compile/torture/unit_type1.rs        |   7 ++
 .../rust/compile/torture/unit_type2.rs        |   8 ++
 .../rust/compile/torture/unit_type3.rs        |   6 ++
 .../rust/compile/torture/unit_type4.rs        |   5 +
 .../rust/compile/torture/unit_type5.rs        |   8 ++
 gcc/testsuite/rust/compile/torture/unsafe1.rs |  12 +++
 gcc/testsuite/rust/compile/torture/unsafe2.rs |   4 +
 gcc/testsuite/rust/compile/torture/unsafe3.rs |   9 ++
 gcc/testsuite/rust/compile/torture/unsafe4.rs |  12 +++
 gcc/testsuite/rust/compile/torture/unused.rs  |  17 ++++
 gcc/testsuite/rust/compile/torture/unused1.rs |  15 +++
 .../rust/compile/torture/unused_struct.rs     |   7 ++
 .../compile/torture/unused_struct_field.rs    |   9 ++
 gcc/testsuite/rust/compile/torture/usize1.rs  |   6 ++
 .../torture/very-broken-attr-string.rs        |   3 +
 .../rust/compile/torture/while_function.rs    |  10 ++
 gcc/testsuite/rust/compile/traits1.rs         |  13 +++
 gcc/testsuite/rust/compile/traits10.rs        |  15 +++
 gcc/testsuite/rust/compile/traits11.rs        |  19 ++++
 gcc/testsuite/rust/compile/traits12.rs        |  20 ++++
 gcc/testsuite/rust/compile/traits2.rs         |  14 +++
 gcc/testsuite/rust/compile/traits3.rs         |  22 +++++
 gcc/testsuite/rust/compile/traits4.rs         |  16 +++
 gcc/testsuite/rust/compile/traits5.rs         |   9 ++
 gcc/testsuite/rust/compile/traits6.rs         |  15 +++
 gcc/testsuite/rust/compile/traits7.rs         |  24 +++++
 gcc/testsuite/rust/compile/traits8.rs         |  35 +++++++
 gcc/testsuite/rust/compile/traits9.rs         |  13 +++
 gcc/testsuite/rust/compile/tuple1.rs          |   5 +
 gcc/testsuite/rust/compile/tuple_struct1.rs   |   8 ++
 gcc/testsuite/rust/compile/tuple_struct2.rs   |   5 +
 gcc/testsuite/rust/compile/tuple_struct3.rs   |   6 ++
 gcc/testsuite/rust/compile/type-alias1.rs     |   6 ++
 gcc/testsuite/rust/compile/type-bindings1.rs  |  10 ++
 gcc/testsuite/rust/compile/unary_negation.rs  |   9 ++
 gcc/testsuite/rust/compile/unary_not.rs       |   9 ++
 .../rust/compile/unconstrained_type_param.rs  |  12 +++
 gcc/testsuite/rust/compile/unicode_escape.rs  |  60 ++++++++++++
 gcc/testsuite/rust/compile/unsafe1.rs         |  14 +++
 gcc/testsuite/rust/compile/unsafe10.rs        |  12 +++
 gcc/testsuite/rust/compile/unsafe2.rs         |  16 +++
 gcc/testsuite/rust/compile/unsafe3.rs         |  10 ++
 gcc/testsuite/rust/compile/unsafe4.rs         |  29 ++++++
 gcc/testsuite/rust/compile/unsafe5.rs         |   4 +
 gcc/testsuite/rust/compile/unsafe6.rs         |  14 +++
 gcc/testsuite/rust/compile/unsafe7.rs         |   9 ++
 gcc/testsuite/rust/compile/unsafe8.rs         |  14 +++
 gcc/testsuite/rust/compile/unsafe9.rs         |  10 ++
 .../rust/compile/unterminated_c_comment.rs    |   2 +
 gcc/testsuite/rust/compile/use_1.rs           |  16 +++
 gcc/testsuite/rust/compile/usize1.rs          |   6 ++
 .../rust/compile/xfail/lifetime_param.rs      |  11 +++
 .../rust/compile/xfail/struct_field_vis.rs    |  15 +++
 gcc/testsuite/rust/compile/xfail/xfail.exp    |  63 ++++++++++++
 531 files changed, 7556 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/abi-options1.rs
 create mode 100644 gcc/testsuite/rust/compile/array3.rs
 create mode 100644 gcc/testsuite/rust/compile/array_empty_list.rs
 create mode 100644 gcc/testsuite/rust/compile/arrays1.rs
 create mode 100644 gcc/testsuite/rust/compile/arrays2.rs
 create mode 100644 gcc/testsuite/rust/compile/attr-mismatch-crate-name.rs
 create mode 100644 gcc/testsuite/rust/compile/attr_cold.rs
 create mode 100644 gcc/testsuite/rust/compile/attr_deprecated.rs
 create mode 100644 gcc/testsuite/rust/compile/attr_deprecated_2.rs
 create mode 100644 gcc/testsuite/rust/compile/bad-crate-name.rs
 create mode 100644 gcc/testsuite/rust/compile/bad=file-name.rs
 create mode 100644 gcc/testsuite/rust/compile/bad_as_bool_char.rs
 create mode 100644 gcc/testsuite/rust/compile/bad_file_name.txt.rs
 create mode 100644 gcc/testsuite/rust/compile/bad_inner_doc.rs
 create mode 100644 gcc/testsuite/rust/compile/bad_pub_enumitems.rs
 create mode 100644 gcc/testsuite/rust/compile/bad_stmt_enums.rs
 create mode 100644 gcc/testsuite/rust/compile/bad_toplevel_enums.rs
 create mode 100644 gcc/testsuite/rust/compile/bad_tuple_index.rs
 create mode 100644 gcc/testsuite/rust/compile/bad_type1.rs
 create mode 100644 gcc/testsuite/rust/compile/bad_type2.rs
 create mode 100644 gcc/testsuite/rust/compile/break1.rs
 create mode 100644 gcc/testsuite/rust/compile/break2.rs
 create mode 100644 gcc/testsuite/rust/compile/builtin_macro_compile_error.rs
 create mode 100644 gcc/testsuite/rust/compile/builtin_macro_concat.rs
 create mode 100644 gcc/testsuite/rust/compile/builtin_macro_env.rs
 create mode 100644 gcc/testsuite/rust/compile/builtin_macro_include_bytes.rs
 create mode 100644 gcc/testsuite/rust/compile/builtin_macro_include_str.rs
 create mode 100644 gcc/testsuite/rust/compile/builtin_macro_not_found.rs
 create mode 100644 gcc/testsuite/rust/compile/bytecharstring.rs
 create mode 100644 gcc/testsuite/rust/compile/canonical_paths1.rs
 create mode 100644 gcc/testsuite/rust/compile/cast1.rs
 create mode 100644 gcc/testsuite/rust/compile/cfg1.rs
 create mode 100644 gcc/testsuite/rust/compile/cfg2.rs
 create mode 100644 gcc/testsuite/rust/compile/cfg3.rs
 create mode 100644 gcc/testsuite/rust/compile/cfg4.rs
 create mode 100644 gcc/testsuite/rust/compile/cfg5.rs
 create mode 100644 gcc/testsuite/rust/compile/compile.exp
 create mode 100644 gcc/testsuite/rust/compile/complex-path1.rs
 create mode 100644 gcc/testsuite/rust/compile/const-issue1440.rs
 create mode 100644 gcc/testsuite/rust/compile/const1.rs
 create mode 100644 gcc/testsuite/rust/compile/const2.rs
 create mode 100644 gcc/testsuite/rust/compile/const3.rs
 create mode 100644 gcc/testsuite/rust/compile/const_generics_1.rs
 create mode 100644 gcc/testsuite/rust/compile/const_generics_2.rs
 create mode 100644 gcc/testsuite/rust/compile/const_generics_3.rs
 create mode 100644 gcc/testsuite/rust/compile/const_generics_4.rs
 create mode 100644 gcc/testsuite/rust/compile/const_generics_5.rs
 create mode 100644 gcc/testsuite/rust/compile/const_generics_6.rs
 create mode 100644 gcc/testsuite/rust/compile/continue1.rs
 create mode 100644 gcc/testsuite/rust/compile/deadcode_err1.rs
 create mode 100644 gcc/testsuite/rust/compile/deadcode_err2.rs
 create mode 100644 gcc/testsuite/rust/compile/debug-diagnostics-default.rs
 create mode 100644 gcc/testsuite/rust/compile/debug-diagnostics-off.rs
 create mode 100644 gcc/testsuite/rust/compile/debug-diagnostics-on.rs
 create mode 100644 gcc/testsuite/rust/compile/doc_isolated_cr_block_comment.rs
 create mode 100644 gcc/testsuite/rust/compile/doc_isolated_cr_inner_block_comment.rs
 create mode 100644 gcc/testsuite/rust/compile/doc_isolated_cr_inner_line_comment.rs
 create mode 100644 gcc/testsuite/rust/compile/doc_isolated_cr_line_comment.rs
 create mode 100644 gcc/testsuite/rust/compile/dup_fields.rs
 create mode 100644 gcc/testsuite/rust/compile/empty_comment_before_match.rs
 create mode 100644 gcc/testsuite/rust/compile/expected_type_args2.rs
 create mode 100644 gcc/testsuite/rust/compile/expected_type_args3.rs
 create mode 100644 gcc/testsuite/rust/compile/func1.rs
 create mode 100644 gcc/testsuite/rust/compile/func2.rs
 create mode 100644 gcc/testsuite/rust/compile/func3.rs
 create mode 100644 gcc/testsuite/rust/compile/func4.rs
 create mode 100644 gcc/testsuite/rust/compile/func5.rs
 create mode 100644 gcc/testsuite/rust/compile/generic-default1.rs
 create mode 100644 gcc/testsuite/rust/compile/generics1.rs
 create mode 100644 gcc/testsuite/rust/compile/generics10.rs
 create mode 100644 gcc/testsuite/rust/compile/generics11.rs
 create mode 100644 gcc/testsuite/rust/compile/generics12.rs
 create mode 100644 gcc/testsuite/rust/compile/generics13.rs
 create mode 100644 gcc/testsuite/rust/compile/generics2.rs
 create mode 100644 gcc/testsuite/rust/compile/generics3.rs
 create mode 100644 gcc/testsuite/rust/compile/generics4.rs
 create mode 100644 gcc/testsuite/rust/compile/generics5.rs
 create mode 100644 gcc/testsuite/rust/compile/generics6.rs
 create mode 100644 gcc/testsuite/rust/compile/generics7.rs
 create mode 100644 gcc/testsuite/rust/compile/generics8.rs
 create mode 100644 gcc/testsuite/rust/compile/generics9.rs
 create mode 100644 gcc/testsuite/rust/compile/implicit_returns_err1.rs
 create mode 100644 gcc/testsuite/rust/compile/implicit_returns_err2.rs
 create mode 100644 gcc/testsuite/rust/compile/implicit_returns_err3.rs
 create mode 100644 gcc/testsuite/rust/compile/implicit_returns_err4.rs
 create mode 100644 gcc/testsuite/rust/compile/infer-crate-name.rs
 create mode 100644 gcc/testsuite/rust/compile/inline_1.rs
 create mode 100644 gcc/testsuite/rust/compile/inline_2.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1005.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1019.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1023.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1031.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1034.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1089.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1128.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1129-1.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1129-2.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1130.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1131.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1152.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1165.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1173.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1226.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1234.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1235.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1237.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1251.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1271.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1289.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1323-1.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1323-2.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1383.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1393.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1447.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-407-2.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-407.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-557.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-635-1.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-635-2.rs
 create mode 100644 gcc/testsuite/rust/compile/lookup_err1.rs
 create mode 100644 gcc/testsuite/rust/compile/macro-issue1053-2.rs
 create mode 100644 gcc/testsuite/rust/compile/macro-issue1053.rs
 create mode 100644 gcc/testsuite/rust/compile/macro-issue1224.rs
 create mode 100644 gcc/testsuite/rust/compile/macro-issue1233.rs
 create mode 100644 gcc/testsuite/rust/compile/macro-issue1395-2.rs
 create mode 100644 gcc/testsuite/rust/compile/macro-issue1395.rs
 create mode 100644 gcc/testsuite/rust/compile/macro-issue1400-2.rs
 create mode 100644 gcc/testsuite/rust/compile/macro-issue1400.rs
 create mode 100644 gcc/testsuite/rust/compile/macro1.rs
 create mode 100644 gcc/testsuite/rust/compile/macro10.rs
 create mode 100644 gcc/testsuite/rust/compile/macro11.rs
 create mode 100644 gcc/testsuite/rust/compile/macro12.rs
 create mode 100644 gcc/testsuite/rust/compile/macro13.rs
 create mode 100644 gcc/testsuite/rust/compile/macro14.rs
 create mode 100644 gcc/testsuite/rust/compile/macro15.rs
 create mode 100644 gcc/testsuite/rust/compile/macro16.rs
 create mode 100644 gcc/testsuite/rust/compile/macro17.rs
 create mode 100644 gcc/testsuite/rust/compile/macro18.rs
 create mode 100644 gcc/testsuite/rust/compile/macro19.rs
 create mode 100644 gcc/testsuite/rust/compile/macro2.rs
 create mode 100644 gcc/testsuite/rust/compile/macro20.rs
 create mode 100644 gcc/testsuite/rust/compile/macro21.rs
 create mode 100644 gcc/testsuite/rust/compile/macro22.rs
 create mode 100644 gcc/testsuite/rust/compile/macro23.rs
 create mode 100644 gcc/testsuite/rust/compile/macro25.rs
 create mode 100644 gcc/testsuite/rust/compile/macro26.rs
 create mode 100644 gcc/testsuite/rust/compile/macro27.rs
 create mode 100644 gcc/testsuite/rust/compile/macro28.rs
 create mode 100644 gcc/testsuite/rust/compile/macro29.rs
 create mode 100644 gcc/testsuite/rust/compile/macro3.rs
 create mode 100644 gcc/testsuite/rust/compile/macro30.rs
 create mode 100644 gcc/testsuite/rust/compile/macro31.rs
 create mode 100644 gcc/testsuite/rust/compile/macro32.rs
 create mode 100644 gcc/testsuite/rust/compile/macro33.rs
 create mode 100644 gcc/testsuite/rust/compile/macro34.rs
 create mode 100644 gcc/testsuite/rust/compile/macro35.rs
 create mode 100644 gcc/testsuite/rust/compile/macro36.rs
 create mode 100644 gcc/testsuite/rust/compile/macro37.rs
 create mode 100644 gcc/testsuite/rust/compile/macro38.rs
 create mode 100644 gcc/testsuite/rust/compile/macro39.rs
 create mode 100644 gcc/testsuite/rust/compile/macro4.rs
 create mode 100644 gcc/testsuite/rust/compile/macro40.rs
 create mode 100644 gcc/testsuite/rust/compile/macro41.rs
 create mode 100644 gcc/testsuite/rust/compile/macro42.rs
 create mode 100644 gcc/testsuite/rust/compile/macro5.rs
 create mode 100644 gcc/testsuite/rust/compile/macro6.rs
 create mode 100644 gcc/testsuite/rust/compile/macro7.rs
 create mode 100644 gcc/testsuite/rust/compile/macro8.rs
 create mode 100644 gcc/testsuite/rust/compile/macro9.rs
 create mode 100644 gcc/testsuite/rust/compile/macro_return.rs
 create mode 100644 gcc/testsuite/rust/compile/match1.rs
 create mode 100644 gcc/testsuite/rust/compile/match2.rs
 create mode 100644 gcc/testsuite/rust/compile/match3.rs
 create mode 100644 gcc/testsuite/rust/compile/match4.rs
 create mode 100644 gcc/testsuite/rust/compile/match5.rs
 create mode 100644 gcc/testsuite/rust/compile/match6.rs
 create mode 100644 gcc/testsuite/rust/compile/match7.rs
 create mode 100644 gcc/testsuite/rust/compile/method1.rs
 create mode 100644 gcc/testsuite/rust/compile/method2.rs
 create mode 100644 gcc/testsuite/rust/compile/mismatch-crate-name.rs
 create mode 100644 gcc/testsuite/rust/compile/missing_middle/both_path.rs
 create mode 100644 gcc/testsuite/rust/compile/missing_middle/explicit.not.rs
 create mode 100644 gcc/testsuite/rust/compile/missing_middle/inner_path.rs
 create mode 100644 gcc/testsuite/rust/compile/missing_middle/other.rs
 create mode 100644 gcc/testsuite/rust/compile/missing_middle/outer_path.rs
 create mode 100644 gcc/testsuite/rust/compile/missing_middle/sub/mod.rs
 create mode 100644 gcc/testsuite/rust/compile/missing_return1.rs
 create mode 100644 gcc/testsuite/rust/compile/mod_missing_middle.rs
 create mode 100644 gcc/testsuite/rust/compile/never_type_err1.rs
 create mode 100644 gcc/testsuite/rust/compile/privacy1.rs
 create mode 100644 gcc/testsuite/rust/compile/privacy2.rs
 create mode 100644 gcc/testsuite/rust/compile/privacy3.rs
 create mode 100644 gcc/testsuite/rust/compile/privacy4.rs
 create mode 100644 gcc/testsuite/rust/compile/privacy5.rs
 create mode 100644 gcc/testsuite/rust/compile/privacy6.rs
 create mode 100644 gcc/testsuite/rust/compile/pub_restricted_1.rs
 create mode 100644 gcc/testsuite/rust/compile/pub_restricted_2.rs
 create mode 100644 gcc/testsuite/rust/compile/pub_restricted_3.rs
 create mode 100644 gcc/testsuite/rust/compile/raw_identifiers_bad_keywords.rs
 create mode 100644 gcc/testsuite/rust/compile/raw_identifiers_underscore.rs
 create mode 100644 gcc/testsuite/rust/compile/rawbytestring.rs
 create mode 100644 gcc/testsuite/rust/compile/redef_error1.rs
 create mode 100644 gcc/testsuite/rust/compile/redef_error2.rs
 create mode 100644 gcc/testsuite/rust/compile/redef_error3.rs
 create mode 100644 gcc/testsuite/rust/compile/redef_error4.rs
 create mode 100644 gcc/testsuite/rust/compile/redef_error5.rs
 create mode 100644 gcc/testsuite/rust/compile/redef_error6.rs
 create mode 100644 gcc/testsuite/rust/compile/reference1.rs
 create mode 100644 gcc/testsuite/rust/compile/self-path1.rs
 create mode 100644 gcc/testsuite/rust/compile/self-path2.rs
 create mode 100644 gcc/testsuite/rust/compile/shadow1.rs
 create mode 100644 gcc/testsuite/rust/compile/specify-crate-name.rs
 create mode 100644 gcc/testsuite/rust/compile/static_var1.rs
 create mode 100644 gcc/testsuite/rust/compile/stmt_with_block_err1.rs
 create mode 100644 gcc/testsuite/rust/compile/struct_align1.rs
 create mode 100644 gcc/testsuite/rust/compile/struct_align2.rs
 create mode 100644 gcc/testsuite/rust/compile/struct_init1.rs
 create mode 100644 gcc/testsuite/rust/compile/struct_pack1.rs
 create mode 100644 gcc/testsuite/rust/compile/struct_pack2.rs
 create mode 100644 gcc/testsuite/rust/compile/syntax-only.rs
 create mode 100644 gcc/testsuite/rust/compile/test_mod.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/all_doc_comment_line_blocks.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/all_doc_comment_line_blocks_crlf.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/arithmetic_expressions1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/array_const_fold_1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/array_const_fold_2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/array_function.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/array_type_infer.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/array_zero_length.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/arrays1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/arrays2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/arrays3.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/arrays4.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/arrays5.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/arrays6.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/arrays_index1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/arrays_index2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/arrays_index3.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/as_bool_char.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/associated_types1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/autoderef1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/block_expr1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/block_expr2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/block_expr3.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/block_expr4.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/block_expr5.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/block_expr_parser_bug.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/bom.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/bom_comment.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/bom_shebang.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/bom_whitespace.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/bools_eq.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/borrow1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/borrow_function.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/break_function.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/byte_char_str.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/byte_str.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/cast1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/cast2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/cast3.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/cfg_attr.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/char1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/check-doc-attr-string.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/coercion1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/coercion2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/comparison_expr1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/compile.exp
 create mode 100644 gcc/testsuite/rust/compile/torture/compound_assignment_expr1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/conditional.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/constant1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/constant2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/constant3.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/deadcode1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/deadcode2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/deref1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/deref_function.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/doc_comment.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/enum1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/extern_mod1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/extern_mod2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/float1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/float_types.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/forward_decl_1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/forward_decl_2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/forward_decl_3-unsafe.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/forward_decl_3.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/forward_decl_4.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/forward_decl_5.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/func1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/func2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/function_reference1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/function_reference2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/function_reference3.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/function_reference4.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics10.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics11.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics12.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics13.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics14.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics15.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics16.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics17.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics18.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics19.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics20.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics21.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics22.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics23.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics24.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics25.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics26.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics27.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics28.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics29.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics3.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics30.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics31.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics32.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics4.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics5.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics6.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics7.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics8.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/generics9.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/grouped_expr_function.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/identifier-missing-impl-1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/if.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/if_elif.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/if_elif_else_expr1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/if_else.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/ifunaryexpr.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/impl_block1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/impl_block2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/impl_block3.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/impl_block_unused.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/implicit_returns1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/infer_type1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/inner_attributes.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/integer_inference_var1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/integer_inference_var2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/integer_inference_var3.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/integer_inference_var4.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/integer_inference_var5.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/integer_types.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/intrinsics-1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/intrinsics-2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/isolated_cr_block_comment.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/isolated_cr_line_comment.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/issue-1024.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/issue-1075.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/issue-1432.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/issue-1434.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/issue-368.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/issue-808.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/issue-862.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/issue-893-2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/issue-893.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/lazybooleanexpr_function.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/lifetime1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/literals1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/loop1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/loop2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/loop3.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/loop4.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/loop5.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/loop6.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/loop7.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/macro-issue1403.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/macro-issue1426.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/macro_as_expr.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/match1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/methods1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/methods2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/methods3.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/mod-nameresolve.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/mod1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/mod2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/mod3.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/modules/mod.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/modules/valid_path.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/must_use1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/must_use2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/name_resolve1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/negation_function.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/nested_fn1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/nested_fn2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/nested_struct1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/never_type1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/not_shebang.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/not_shebang_block_comment.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/not_shebang_comment.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/not_shebang_multiline_comment.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/not_shebang_spaces.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/parameter_usage1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/parens1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/pointer1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/primconsts.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/prims_struct_eq.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/range-lang-item1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/raw_identifiers.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/raw_identifiers_keywords.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/recursive_fn1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/return_function.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/scoping1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/self_type1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/shadow1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/shadow2.rs
 create mode 100755 gcc/testsuite/rust/compile/torture/shebang.rs
 create mode 100755 gcc/testsuite/rust/compile/torture/shebang_plus_attr.rs
 create mode 100755 gcc/testsuite/rust/compile/torture/shebang_plus_attr2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/static_function.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/static_var1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/stmt_with_block1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/str1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/struct_access1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/struct_base_init_1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/struct_decl.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/struct_init.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/struct_init_10.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/struct_init_11.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/struct_init_2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/struct_init_3.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/struct_init_4.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/struct_init_5.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/struct_init_6.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/struct_init_7.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/struct_init_8.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/struct_init_9.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/top_attr.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/traits1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/traits10.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/traits11.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/traits12.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/traits13.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/traits14.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/traits15.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/traits16.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/traits17.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/traits18.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/traits19.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/traits2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/traits3.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/traits4.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/traits5.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/traits6.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/traits7.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/traits8.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/traits9.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/transmute-size-check-1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/transmute1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/tuple1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/tuple2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/tuple3.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/tuple_enum_variants.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/tuple_field_access.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/tuple_function.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/tuple_index.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/tuple_struct1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/tuple_struct2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/tuple_struct_unit.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/tuple_struct_unused.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/type-alias1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/type-alias2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/type_infer1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/type_infer2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/type_infer3.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/type_infer4.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/type_infer5.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/type_infer6.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/unary_operators.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/undended-string-1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/undended-string-2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/underscore_id.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/union.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/union_union.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/unit_type1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/unit_type2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/unit_type3.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/unit_type4.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/unit_type5.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/unsafe1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/unsafe2.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/unsafe3.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/unsafe4.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/unused.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/unused1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/unused_struct.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/unused_struct_field.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/usize1.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/very-broken-attr-string.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/while_function.rs
 create mode 100644 gcc/testsuite/rust/compile/traits1.rs
 create mode 100644 gcc/testsuite/rust/compile/traits10.rs
 create mode 100644 gcc/testsuite/rust/compile/traits11.rs
 create mode 100644 gcc/testsuite/rust/compile/traits12.rs
 create mode 100644 gcc/testsuite/rust/compile/traits2.rs
 create mode 100644 gcc/testsuite/rust/compile/traits3.rs
 create mode 100644 gcc/testsuite/rust/compile/traits4.rs
 create mode 100644 gcc/testsuite/rust/compile/traits5.rs
 create mode 100644 gcc/testsuite/rust/compile/traits6.rs
 create mode 100644 gcc/testsuite/rust/compile/traits7.rs
 create mode 100644 gcc/testsuite/rust/compile/traits8.rs
 create mode 100644 gcc/testsuite/rust/compile/traits9.rs
 create mode 100644 gcc/testsuite/rust/compile/tuple1.rs
 create mode 100644 gcc/testsuite/rust/compile/tuple_struct1.rs
 create mode 100644 gcc/testsuite/rust/compile/tuple_struct2.rs
 create mode 100644 gcc/testsuite/rust/compile/tuple_struct3.rs
 create mode 100644 gcc/testsuite/rust/compile/type-alias1.rs
 create mode 100644 gcc/testsuite/rust/compile/type-bindings1.rs
 create mode 100644 gcc/testsuite/rust/compile/unary_negation.rs
 create mode 100644 gcc/testsuite/rust/compile/unary_not.rs
 create mode 100644 gcc/testsuite/rust/compile/unconstrained_type_param.rs
 create mode 100644 gcc/testsuite/rust/compile/unicode_escape.rs
 create mode 100644 gcc/testsuite/rust/compile/unsafe1.rs
 create mode 100644 gcc/testsuite/rust/compile/unsafe10.rs
 create mode 100644 gcc/testsuite/rust/compile/unsafe2.rs
 create mode 100644 gcc/testsuite/rust/compile/unsafe3.rs
 create mode 100644 gcc/testsuite/rust/compile/unsafe4.rs
 create mode 100644 gcc/testsuite/rust/compile/unsafe5.rs
 create mode 100644 gcc/testsuite/rust/compile/unsafe6.rs
 create mode 100644 gcc/testsuite/rust/compile/unsafe7.rs
 create mode 100644 gcc/testsuite/rust/compile/unsafe8.rs
 create mode 100644 gcc/testsuite/rust/compile/unsafe9.rs
 create mode 100644 gcc/testsuite/rust/compile/unterminated_c_comment.rs
 create mode 100644 gcc/testsuite/rust/compile/use_1.rs
 create mode 100644 gcc/testsuite/rust/compile/usize1.rs
 create mode 100644 gcc/testsuite/rust/compile/xfail/lifetime_param.rs
 create mode 100644 gcc/testsuite/rust/compile/xfail/struct_field_vis.rs
 create mode 100644 gcc/testsuite/rust/compile/xfail/xfail.exp

diff --git a/gcc/testsuite/rust/compile/abi-options1.rs b/gcc/testsuite/rust/compile/abi-options1.rs
new file mode 100644
index 00000000000..a4b6241dc15
--- /dev/null
+++ b/gcc/testsuite/rust/compile/abi-options1.rs
@@ -0,0 +1,7 @@
+extern "foobar" {
+    // { dg-error "unknown ABI option" "" { target *-*-* } .-1 }
+    fn printf(s: *const i8, ...);
+}
+
+pub extern "baz" fn test() {}
+// { dg-error "unknown ABI option" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/rust/compile/array3.rs b/gcc/testsuite/rust/compile/array3.rs
new file mode 100644
index 00000000000..a56be9a0e8b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/array3.rs
@@ -0,0 +1,4 @@
+fn foo(state: &mut [u32; 16], a: usize) {
+    // { dg-warning "function is never used: .foo." "" { target *-*-* } .-1 }
+    state[a] = 1;
+}
diff --git a/gcc/testsuite/rust/compile/array_empty_list.rs b/gcc/testsuite/rust/compile/array_empty_list.rs
new file mode 100644
index 00000000000..76e082a6d57
--- /dev/null
+++ b/gcc/testsuite/rust/compile/array_empty_list.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let arr = [];
+    // { dg-error "type annotations needed" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/arrays1.rs b/gcc/testsuite/rust/compile/arrays1.rs
new file mode 100644
index 00000000000..714a6be7afb
--- /dev/null
+++ b/gcc/testsuite/rust/compile/arrays1.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let xs: [i32; 5] = [1, 2, 3, 4, 5];
+    let a: bool = xs[0]; // { dg-error "expected .bool. got .i32." }
+}
diff --git a/gcc/testsuite/rust/compile/arrays2.rs b/gcc/testsuite/rust/compile/arrays2.rs
new file mode 100644
index 00000000000..c96f4f7d820
--- /dev/null
+++ b/gcc/testsuite/rust/compile/arrays2.rs
@@ -0,0 +1,5 @@
+// { dg-additional-options "-w" }
+fn main() {
+    let array: [i32; 5] = [1, 2, 3];
+    // { dg-error "expected an array with a fixed size of 5 elements, found one with 3 elements" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/attr-mismatch-crate-name.rs b/gcc/testsuite/rust/compile/attr-mismatch-crate-name.rs
new file mode 100644
index 00000000000..1d406031fee
--- /dev/null
+++ b/gcc/testsuite/rust/compile/attr-mismatch-crate-name.rs
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fdump-tree-gimple" }
+#![crate_name = "specified_name"]
+// { dg-final { scan-tree-dump-times {specified_name::main} 1 gimple } }
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/attr_cold.rs b/gcc/testsuite/rust/compile/attr_cold.rs
new file mode 100644
index 00000000000..f705ea9b2ff
--- /dev/null
+++ b/gcc/testsuite/rust/compile/attr_cold.rs
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fdump-tree-gimple" }
+#[cold]
+fn cold_function() -> i32 {
+    42
+}
+
+fn main() -> i32 {
+    // { dg-final { scan-tree-dump-times {__attribute__\(\(cdecl, cold\)\)} 1 gimple } }
+    cold_function();
+
+    0
+}
diff --git a/gcc/testsuite/rust/compile/attr_deprecated.rs b/gcc/testsuite/rust/compile/attr_deprecated.rs
new file mode 100644
index 00000000000..01bc9c41502
--- /dev/null
+++ b/gcc/testsuite/rust/compile/attr_deprecated.rs
@@ -0,0 +1,14 @@
+#[deprecated(since="1.0", note="do not use this function")]
+fn test1() {}
+
+#[deprecated]
+fn test() {}
+
+#[deprecated = "a different message"]
+fn test2() {}
+
+fn main() {
+    test(); // { dg-warning ".attr_deprecated::test. is deprecated" }
+    test1(); // { dg-warning ".attr_deprecated::test1. is deprecated: do not use this function" }
+    test2(); // { dg-warning ".attr_deprecated::test2. is deprecated: a different message" }
+}
diff --git a/gcc/testsuite/rust/compile/attr_deprecated_2.rs b/gcc/testsuite/rust/compile/attr_deprecated_2.rs
new file mode 100644
index 00000000000..66f4ce3b076
--- /dev/null
+++ b/gcc/testsuite/rust/compile/attr_deprecated_2.rs
@@ -0,0 +1,11 @@
+#[deprecated(since="1.0")]
+fn test1() {}
+
+// { dg-excess-errors "unknown meta item ...." }
+#[deprecated(invalid="invalid")]
+fn test2() {}
+
+fn main() {
+    test1(); // { dg-warning ".attr_deprecated_2::test1. is deprecated" }
+    test2();
+}
diff --git a/gcc/testsuite/rust/compile/bad-crate-name.rs b/gcc/testsuite/rust/compile/bad-crate-name.rs
new file mode 100644
index 00000000000..6c59c255cc2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad-crate-name.rs
@@ -0,0 +1,4 @@
+// { dg-additional-options "-frust-crate=bad+name" }
+// { dg-excess-errors "invalid crate name: ...." }
+// { dg-excess-errors "unrecognized command-line option ...." }
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/bad=file-name.rs b/gcc/testsuite/rust/compile/bad=file-name.rs
new file mode 100644
index 00000000000..cfbebb0698d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad=file-name.rs
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fdump-tree-gimple -frust-crate=good_name" }
+pub fn does_nothing() {}
+fn main() {
+    does_nothing()
+}
+// { dg-final { scan-tree-dump-times {good_name::does_nothing} 2 gimple } }
+// { dg-final { scan-tree-dump-times {good_name::main} 1 gimple } }
diff --git a/gcc/testsuite/rust/compile/bad_as_bool_char.rs b/gcc/testsuite/rust/compile/bad_as_bool_char.rs
new file mode 100644
index 00000000000..91a28eebe00
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad_as_bool_char.rs
@@ -0,0 +1,18 @@
+pub fn main ()
+{
+  let t = true;
+  let f = false;
+  let fone = t as f32;   // { dg-error "invalid cast" }
+  let fzero = f as f64;  // { dg-error "invalid cast" }
+
+  let nb = 0u8 as bool;  // { dg-error "invalid cast" }
+  let nc = true as char; // { dg-error "invalid cast" }
+
+  let a = 'a';
+  let b = 'b';
+  let fa = a as f32;     // { dg-error "invalid cast" }
+  let bb = b as bool;    // { dg-error "invalid cast" }
+
+  let t32: u32 = 33;
+  let ab = t32 as char;  // { dg-error "invalid cast" }
+}
diff --git a/gcc/testsuite/rust/compile/bad_file_name.txt.rs b/gcc/testsuite/rust/compile/bad_file_name.txt.rs
new file mode 100644
index 00000000000..56e2093b27c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad_file_name.txt.rs
@@ -0,0 +1,3 @@
+// { dg-excess-errors "invalid crate name: ...." }
+// { dg-bogus "unrecognized command-line option ...." }
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/bad_inner_doc.rs b/gcc/testsuite/rust/compile/bad_inner_doc.rs
new file mode 100644
index 00000000000..cfd166ce3ec
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad_inner_doc.rs
@@ -0,0 +1,15 @@
+pub fn main ()
+{
+  //! inner doc allowed
+  let _x = 42;
+  // { dg-error "inner doc" "" { target *-*-* } .+1 }
+  //! inner doc disallowed
+  mod module
+  {
+    /*! inner doc allowed */
+    /// outer doc allowed
+    // { dg-error "inner doc" "" { target *-*-* } .+1 }
+    /*! but inner doc not here */
+    mod x { }
+  }
+}
diff --git a/gcc/testsuite/rust/compile/bad_pub_enumitems.rs b/gcc/testsuite/rust/compile/bad_pub_enumitems.rs
new file mode 100644
index 00000000000..e7fd5edb981
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad_pub_enumitems.rs
@@ -0,0 +1,47 @@
+pub enum E
+{
+  pub A { a: i32 }, // { dg-error "visibility qualifier" }
+  B (u8),
+  pub C, // { dg-error "visibility qualifier" }
+  D
+}
+
+enum E1
+{
+  A,
+  pub B = 42, // { dg-error "visibility qualifier" }
+  C = 3,
+  D,
+  pub E // { dg-error "visibility qualifier" }
+}
+
+enum E2
+{
+  pub A (u8, i32, u64), // { dg-error "visibility qualifier" }
+  B { a: u8, a: u8 }  // { dg-error "duplicate field" }}
+}
+
+fn main ()
+{
+  enum EE
+    {
+      Alpha { alpha: i32 },
+      pub Beta (u8), // { dg-error "visibility qualifier" }
+      pub Gamma, // { dg-error "visibility qualifier" }
+      Delta { delta: u32 }
+    }
+
+  enum EE1
+    {
+      pub Alpha, // { dg-error "visibility qualifier" }
+      Beta = 41,
+      pub Gamma = 3, // { dg-error "visibility qualifier" }
+      Delta,
+    }
+
+  enum E2
+    {
+      Alpha { a: u8, a: u8 },  // { dg-error "duplicate field" }}
+      pub Beta (u8, i32, u64) // { dg-error "visibility qualifier" }
+    }
+}
diff --git a/gcc/testsuite/rust/compile/bad_stmt_enums.rs b/gcc/testsuite/rust/compile/bad_stmt_enums.rs
new file mode 100644
index 00000000000..7b09a94fd27
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad_stmt_enums.rs
@@ -0,0 +1,22 @@
+fn main ()
+{
+  enum EE
+    {
+      Alpha { alpha: i32 },
+      pub Beta (u8),
+      pub Gamma,
+      Gamma { gamma: u32 } // { dg-error "redefined" }
+    }
+
+  struct EE2 { }
+  enum EE2 { } // { dg-error "redefined" }
+
+  enum EE1
+    {
+      pub Alpha,
+      Beta = 41,
+      Beta = 42, // { dg-error "redefined" }
+      pub Gamma = 3,
+      D,
+    }
+}
diff --git a/gcc/testsuite/rust/compile/bad_toplevel_enums.rs b/gcc/testsuite/rust/compile/bad_toplevel_enums.rs
new file mode 100644
index 00000000000..b655e30a93d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad_toplevel_enums.rs
@@ -0,0 +1,19 @@
+pub enum E
+{
+  pub A { a: i32 },
+  B (u8),
+  pub C,
+  B // { dg-error "redefined" }
+}
+
+enum E2 { }
+struct E2 { } // { dg-error "redefined" }
+
+enum E1
+{
+  A,
+  pub B = 42,
+  C = 3,
+  A { a: u8 }, // { dg-error "redefined" }
+  pub D
+}
diff --git a/gcc/testsuite/rust/compile/bad_tuple_index.rs b/gcc/testsuite/rust/compile/bad_tuple_index.rs
new file mode 100644
index 00000000000..c3bd1e91d10
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad_tuple_index.rs
@@ -0,0 +1,66 @@
+fn main()
+{
+  // tuples
+  let z = ();
+
+  let o = (0,);
+  /* Binary, Octal and Hex literals are invalid.  */
+  let _fb = o.0b0; // { dg-error "tuple index should be a pure decimal literal" }
+  let _fo = o.0o0; // { dg-error "tuple index should be a pure decimal literal" }
+  let _fh = o.0x0; // { dg-error "tuple index should be a pure decimal literal" }
+
+  /* No underscores.  */
+  let _fua = o.0_; // { dg-error "tuple index should be a pure decimal literal" }
+
+  /* Suffix is not allowed.  */
+  let _fu8 = o.0u8; // { dg-error "tuple index should be a pure decimal literal" }
+  let _fi8 = o.0i8; // { dg-error "tuple index should be a pure decimal literal" }
+  let _fu16 = o.0u16; // { dg-error "tuple index should be a pure decimal literal" }
+  let _fi16 = o.0i16; // { dg-error "tuple index should be a pure decimal literal" }
+  let _fu32 = o.0u32; // { dg-error "tuple index should be a pure decimal literal" }
+  let _fi32 = o.0i32; // { dg-error "tuple index should be a pure decimal literal" }
+  let _fu64 = o.0u64; // { dg-error "tuple index should be a pure decimal literal" }
+  let _fi64 = o.0i64; // { dg-error "tuple index should be a pure decimal literal" }
+  let _fu128 = o.0u128; // { dg-error "tuple index should be a pure decimal literal" }
+  let _fi128 = o.0i128; // { dg-error "tuple index should be a pure decimal literal" }
+  let _fusize = o.0usize; // { dg-error "tuple index should be a pure decimal literal" }
+  let _fisize = o.0isize; // { dg-error "tuple index should be a pure decimal literal" }
+
+  let t = (0,1);
+  /* No extra zero prefix.  */
+  let _s = t.01; // { dg-error "tuple index should be a pure decimal literal" }
+
+  let m = (0,1,2,3,4,5,6,7,8,9,10);
+  /* No extra zero prefix.  */
+  let _l = m.010; // { dg-error "tuple index should be a pure decimal literal" }
+
+  /* No underscores.  */
+  let _lu = m.1_0; // { dg-error "tuple index should be a pure decimal literal" }
+
+  // tuple structs
+  struct E();
+  let _e = E();
+
+  struct O(i32);
+  let so = O(0);
+  /* No leading zeros, no underscores.  */
+  let _sf = so.0_0; // { dg-error "tuple index should be a pure decimal literal" }
+  /* Binary, Octal and Hex literals are invalid.  */
+  let _sb = so.0b0; // { dg-error "tuple index should be a pure decimal literal" }
+  let _so = so.0o0; // { dg-error "tuple index should be a pure decimal literal" }
+  let _sh = so.0x0; // { dg-error "tuple index should be a pure decimal literal" }
+
+  struct T(i32,i32);
+  let st = T(0,1);
+  /* Suffix is not allowed.  */
+  let _stfu32 = st.1u32; // { dg-error "tuple index should be a pure decimal literal" }
+  let _stfi32 = st.1i32; // { dg-error "tuple index should be a pure decimal literal" }
+
+  struct M(i32,i32,i32,i32,i32,i32,i32,i32,i32,i32,i32);
+  let sm = M(0,1,2,3,4,5,6,7,8,9,10);
+  /* No underscores. */
+  let _sl2 = sm.1_0; // { dg-error "tuple index should be a pure decimal literal" }
+  let _sl3 = sm.10_; // { dg-error "tuple index should be a pure decimal literal" }
+
+  z
+}
diff --git a/gcc/testsuite/rust/compile/bad_type1.rs b/gcc/testsuite/rust/compile/bad_type1.rs
new file mode 100644
index 00000000000..93de439704f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad_type1.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let logical: bool = 123; // { dg-error "expected .bool. got .<integer>." }
+}
diff --git a/gcc/testsuite/rust/compile/bad_type2.rs b/gcc/testsuite/rust/compile/bad_type2.rs
new file mode 100644
index 00000000000..e47b8aac0e7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad_type2.rs
@@ -0,0 +1,14 @@
+fn test(x: i32) -> i32 {
+    return x + 1;
+}
+
+fn main() {
+    let mut an_integer = 5;
+    an_integer = test(1) + 3;
+
+    let mut x;
+    x = 1;
+    x = true; // { dg-error "expected .<integer>. got .bool." }
+
+    let call_test = test(1);
+}
diff --git a/gcc/testsuite/rust/compile/break1.rs b/gcc/testsuite/rust/compile/break1.rs
new file mode 100644
index 00000000000..91cabffa894
--- /dev/null
+++ b/gcc/testsuite/rust/compile/break1.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let a;
+    a = 1;
+    break a; // { dg-error "cannot 'break' outside of a loop" }
+    // { dg-error "failed to type resolve expression" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/break2.rs b/gcc/testsuite/rust/compile/break2.rs
new file mode 100644
index 00000000000..5ac806aeb9e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/break2.rs
@@ -0,0 +1,15 @@
+fn main() {
+    let mut a = 1;
+    let mut b = 1;
+
+    let mut c;
+    while b > 10 {
+        if (b == 2) {
+            break b;  // { dg-error "can only break with a value inside 'loop'" }
+            // { dg-error "failed to type resolve expression" "" { target *-*-* } .-1 }
+        }
+        c = a + b;
+        a = b;
+        b = c;
+    }
+}
diff --git a/gcc/testsuite/rust/compile/builtin_macro_compile_error.rs b/gcc/testsuite/rust/compile/builtin_macro_compile_error.rs
new file mode 100644
index 00000000000..9d224406a3e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/builtin_macro_compile_error.rs
@@ -0,0 +1,13 @@
+#[rustc_builtin_macro]
+macro_rules! compile_error {
+  () => {{}};
+}
+
+fn main () {
+  let message = "error message";
+  compile_error! (message); // { dg-error "argument must be a string literal" "" }
+  compile_error! (); // { dg-error "macro takes 1 argument" "" }
+  compile_error! ("a", "b"); // { dg-error "macro takes 1 argument" "" }
+  compile_error! ("expected error message"); // { dg-error "expected error message" }
+  compile_error! ("expected error message",); // { dg-error "expected error message" }
+}
diff --git a/gcc/testsuite/rust/compile/builtin_macro_concat.rs b/gcc/testsuite/rust/compile/builtin_macro_concat.rs
new file mode 100644
index 00000000000..9b878af764d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/builtin_macro_concat.rs
@@ -0,0 +1,17 @@
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {{}};
+}
+
+fn main() {
+    let not_literal = "identifier";
+    concat!();
+    concat! (,); // { dg-error "argument must be a constant literal" }
+    concat!(not_literal); // { dg-error "argument must be a constant literal" }
+    concat!("message");
+    concat!("message",);
+    concat!("message", 1, true, false, 1.0, 10usize, 2000u64);
+    concat!("message", 1, true, false, 1.0, 10usize, 2000u64,);
+    concat! ("m", not_literal); // { dg-error "argument must be a constant literal" }
+    concat!(not_literal invalid 'm' !!,); // { dg-error "argument must be a constant literal" }
+}
diff --git a/gcc/testsuite/rust/compile/builtin_macro_env.rs b/gcc/testsuite/rust/compile/builtin_macro_env.rs
new file mode 100644
index 00000000000..289e6db2cf1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/builtin_macro_env.rs
@@ -0,0 +1,20 @@
+#[rustc_builtin_macro]
+macro_rules! env {
+  () => {{}};
+}
+
+fn main () {
+  let message = "error message";
+  env! (message); // { dg-error "argument must be a string literal" "" }
+  env! (); // { dg-error "env! takes 1 or 2 arguments" "" }
+  env! (,); // { dg-error "argument must be a string literal" "" }
+  env! (1); // { dg-error "argument must be a string literal" "" }
+  env! ("NOT_DEFINED"); // { dg-error "environment variable 'NOT_DEFINED' not defined" "" }
+  env! ("NOT_DEFINED",); // { dg-error "environment variable 'NOT_DEFINED' not defined" "" }
+  env! ("NOT_DEFINED", 1); // { dg-error "argument must be a string literal" "" }
+  env! ("NOT_DEFINED", "two", "three"); // { dg-error "env! takes 1 or 2 arguments" "" }
+  env! ("NOT_DEFINED" "expected error message"); // { dg-error "expected token: ','" "" }
+  env! ("NOT_DEFINED", "expected error message"); // { dg-error "expected error message" "" }
+  env! ("NOT_DEFINED", "expected error message",); // { dg-error "expected error message" "" }
+  env! (1, "two"); // { dg-error "argument must be a string literal" "" }
+}
diff --git a/gcc/testsuite/rust/compile/builtin_macro_include_bytes.rs b/gcc/testsuite/rust/compile/builtin_macro_include_bytes.rs
new file mode 100644
index 00000000000..38716d33bcd
--- /dev/null
+++ b/gcc/testsuite/rust/compile/builtin_macro_include_bytes.rs
@@ -0,0 +1,13 @@
+#[rustc_builtin_macro]
+macro_rules! include_bytes {
+  () => {{}};
+}
+
+fn main () {
+  let file = "include.txt";
+  include_bytes! (file); // { dg-error "argument must be a string literal" "" }
+  include_bytes! (); // { dg-error "macro takes 1 argument" "" }
+  include_bytes! ("foo.txt", "bar.txt"); // { dg-error "macro takes 1 argument" "" }
+  include_bytes! ("builtin_macro_include_bytes.rs"); // ok
+  include_bytes! ("builtin_macro_include_bytes.rs",); // trailing comma ok
+}
diff --git a/gcc/testsuite/rust/compile/builtin_macro_include_str.rs b/gcc/testsuite/rust/compile/builtin_macro_include_str.rs
new file mode 100644
index 00000000000..38f5e3b7334
--- /dev/null
+++ b/gcc/testsuite/rust/compile/builtin_macro_include_str.rs
@@ -0,0 +1,13 @@
+#[rustc_builtin_macro]
+macro_rules! include_str {
+  () => {{}};
+}
+
+fn main () {
+  let file = "include.txt";
+  include_str! (file); // { dg-error "argument must be a string literal" "" }
+  include_str! (); // { dg-error "macro takes 1 argument" "" }
+  include_str! ("foo.txt", "bar.txt"); // { dg-error "macro takes 1 argument" "" }
+  include_str! ("builtin_macro_include_str.rs"); // ok
+  include_str! ("builtin_macro_include_str.rs",); // trailing comma ok
+}
diff --git a/gcc/testsuite/rust/compile/builtin_macro_not_found.rs b/gcc/testsuite/rust/compile/builtin_macro_not_found.rs
new file mode 100644
index 00000000000..1a3228b9284
--- /dev/null
+++ b/gcc/testsuite/rust/compile/builtin_macro_not_found.rs
@@ -0,0 +1,4 @@
+#[rustc_builtin_macro]
+macro_rules! crabby_crab_carb { // { dg-error "cannot find a built-in macro with name .crabby_crab_carb." }
+    () => {{}};
+}
diff --git a/gcc/testsuite/rust/compile/bytecharstring.rs b/gcc/testsuite/rust/compile/bytecharstring.rs
new file mode 100644
index 00000000000..9242e2c5a0b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bytecharstring.rs
@@ -0,0 +1,8 @@
+fn main ()
+{
+  let _bc = b'\x80';
+  let _bs = b"foo\x80bar";
+
+  let _c = '\xef';        // { dg-error "out of range" }
+  let _s = "Foo\xEFBar";  // { dg-error "out of range" }
+}
diff --git a/gcc/testsuite/rust/compile/canonical_paths1.rs b/gcc/testsuite/rust/compile/canonical_paths1.rs
new file mode 100644
index 00000000000..193e7b5b698
--- /dev/null
+++ b/gcc/testsuite/rust/compile/canonical_paths1.rs
@@ -0,0 +1,25 @@
+// { dg-additional-options "-w -fdump-tree-gimple -frust-crate=example" }
+struct Foo(i32);
+
+trait TR {
+    fn test(&self) -> i32;
+}
+
+mod A {
+    impl ::Foo {
+        pub fn test(self) {}
+        // { dg-final { scan-tree-dump-times {example::A::<impl example::Foo>::test} 2 gimple } }
+    }
+
+    impl ::TR for ::Foo {
+        fn test(&self) -> i32 {
+            // { dg-final { scan-tree-dump-times {example::A::<impl example::Foo as example::TR>::test} 1 gimple } }
+            self.0
+        }
+    }
+}
+
+pub fn test() {
+    let a = Foo(123);
+    a.test();
+}
diff --git a/gcc/testsuite/rust/compile/cast1.rs b/gcc/testsuite/rust/compile/cast1.rs
new file mode 100644
index 00000000000..74c4b1eaac4
--- /dev/null
+++ b/gcc/testsuite/rust/compile/cast1.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let a: i32 = 123;
+    let b = a as char;
+    // { dg-error "invalid cast .i32. to .char." "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/cfg1.rs b/gcc/testsuite/rust/compile/cfg1.rs
new file mode 100644
index 00000000000..6984f04d1b9
--- /dev/null
+++ b/gcc/testsuite/rust/compile/cfg1.rs
@@ -0,0 +1,31 @@
+// { dg-additional-options "-w" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[cfg(A)]
+fn test() {
+    unsafe {
+        let a = "test1\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c);
+    }
+}
+
+#[cfg(B)]
+fn test() {
+    unsafe {
+        let a = "test2\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c);
+    }
+}
+
+fn main() {
+    test();
+    // { dg-error "Cannot find path .test. in this scope" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/cfg2.rs b/gcc/testsuite/rust/compile/cfg2.rs
new file mode 100644
index 00000000000..939384c5b7d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/cfg2.rs
@@ -0,0 +1,13 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+struct Foo;
+impl Foo {
+    #[cfg(not(A))]
+    fn test(&self) {}
+}
+
+fn main() {
+    let a = Foo;
+    a.test();
+    // { dg-error "failed to resolve method for .test." "" { target *-*-* } .-1 }
+    // { dg-error "failed to type resolve expression" "" { target *-*-* } .-2 }
+}
diff --git a/gcc/testsuite/rust/compile/cfg3.rs b/gcc/testsuite/rust/compile/cfg3.rs
new file mode 100644
index 00000000000..d6ffab6bfc6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/cfg3.rs
@@ -0,0 +1,11 @@
+// { dg-additional-options "-w -frust-cfg=A -frust-cfg=B" }
+struct Foo;
+impl Foo {
+    #[cfg(all(A, B))]
+    fn test(&self) {}
+}
+
+fn main() {
+    let a = Foo;
+    a.test();
+}
diff --git a/gcc/testsuite/rust/compile/cfg4.rs b/gcc/testsuite/rust/compile/cfg4.rs
new file mode 100644
index 00000000000..2834c277ddf
--- /dev/null
+++ b/gcc/testsuite/rust/compile/cfg4.rs
@@ -0,0 +1,11 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+struct Foo;
+impl Foo {
+    #[cfg(any(A, B))]
+    fn test(&self) {}
+}
+
+fn main() {
+    let a = Foo;
+    a.test();
+}
diff --git a/gcc/testsuite/rust/compile/cfg5.rs b/gcc/testsuite/rust/compile/cfg5.rs
new file mode 100644
index 00000000000..1852efaf8df
--- /dev/null
+++ b/gcc/testsuite/rust/compile/cfg5.rs
@@ -0,0 +1,11 @@
+// { dg-additional-options "-w -frust-cfg=A=\"B\"" }
+struct Foo;
+impl Foo {
+    #[cfg(A = "B")]
+    fn test(&self) {}
+}
+
+fn main() {
+    let a = Foo;
+    a.test();
+}
diff --git a/gcc/testsuite/rust/compile/compile.exp b/gcc/testsuite/rust/compile/compile.exp
new file mode 100644
index 00000000000..13423d76c92
--- /dev/null
+++ b/gcc/testsuite/rust/compile/compile.exp
@@ -0,0 +1,35 @@
+# Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+# 
+# This program 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/>.
+
+# Compile tests, no torture testing.
+#
+# These tests raise errors in the front end; torture testing doesn't apply.
+
+# Load support procs.
+load_lib rust-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+set saved-dg-do-what-default ${dg-do-what-default}
+
+set dg-do-what-default "compile"
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.rs]] "" ""
+set dg-do-what-default ${saved-dg-do-what-default}
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/rust/compile/complex-path1.rs b/gcc/testsuite/rust/compile/complex-path1.rs
new file mode 100644
index 00000000000..54011bd6976
--- /dev/null
+++ b/gcc/testsuite/rust/compile/complex-path1.rs
@@ -0,0 +1,18 @@
+// { dg-additional-options "-w" }
+mod a {
+    pub fn foo() {}
+}
+
+mod b {
+    pub fn foo() {
+        super::a::foo();
+    }
+}
+
+mod foo {
+    pub struct bar(pub i32);
+}
+
+fn test() -> crate::foo::bar {
+    foo::bar(123)
+}
diff --git a/gcc/testsuite/rust/compile/const-issue1440.rs b/gcc/testsuite/rust/compile/const-issue1440.rs
new file mode 100644
index 00000000000..9b974b96bbb
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const-issue1440.rs
@@ -0,0 +1,76 @@
+// { dg-additional-options "-w" }
+
+mod intrinsics {
+    extern "rust-intrinsic" {
+        pub fn wrapping_add<T>(a: T, b: T) -> T;
+        pub fn rotate_left<T>(a: T, b: T) -> T;
+        pub fn rotate_right<T>(a: T, b: T) -> T;
+        pub fn offset<T>(ptr: *const T, count: isize) -> *const T;
+    }
+}
+
+mod mem {
+    extern "rust-intrinsic" {
+        #[rustc_const_stable(feature = "const_transmute", since = "1.46.0")]
+        pub fn transmute<T, U>(_: T) -> U;
+        pub fn size_of<T>() -> usize;
+    }
+}
+
+macro_rules! impl_uint {
+    ($($ty:ident = $lang:literal),*) => {
+        $(
+            impl $ty {
+                pub fn wrapping_add(self, rhs: Self) -> Self {
+                    // intrinsics::wrapping_add(self, rhs)
+                    self + rhs
+                }
+
+                pub fn rotate_left(self, n: u32) -> Self {
+                    unsafe {
+                        intrinsics::rotate_left(self, n as Self)
+                    }
+                }
+
+                pub fn rotate_right(self, n: u32) -> Self {
+                    unsafe {
+                        intrinsics::rotate_right(self, n as Self)
+                    }
+                }
+
+                pub fn to_le(self) -> Self {
+                    #[cfg(target_endian = "little")]
+                    {
+                        self
+                    }
+                }
+
+                pub const fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+                    // { dg-error "only functions marked as .const. are allowed to be called from constant contexts" "" { target *-*-* } .-1 }
+                    Self::from_le(Self::from_ne_bytes(bytes))
+                }
+
+                pub const fn from_le(x: Self) -> Self {
+                    #[cfg(target_endian = "little")]
+                    {
+                        x
+                    }
+                }
+
+                pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+                    // { dg-error "only functions marked as .const. are allowed to be called from constant contexts" "" { target *-*-* } .-1 }
+                    unsafe { mem::transmute(bytes) }
+                }
+            }
+        )*
+    }
+}
+
+impl_uint!(
+    u8 = "u8",
+    u16 = "u16",
+    u32 = "u32",
+    u64 = "u64",
+    u128 = "u128",
+    usize = "usize"
+);
diff --git a/gcc/testsuite/rust/compile/const1.rs b/gcc/testsuite/rust/compile/const1.rs
new file mode 100644
index 00000000000..5f19c674c94
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const1.rs
@@ -0,0 +1,6 @@
+fn bar() {}
+
+const fn foo() {
+    bar(); // { dg-error "only functions marked as .const. are allowed to be called from constant contexts" }
+}
+
diff --git a/gcc/testsuite/rust/compile/const2.rs b/gcc/testsuite/rust/compile/const2.rs
new file mode 100644
index 00000000000..17b6de573dd
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const2.rs
@@ -0,0 +1,7 @@
+// { dg-additional-options "-w" }
+
+const fn foo() {
+    const fn bar() {}
+
+    bar();
+}
diff --git a/gcc/testsuite/rust/compile/const3.rs b/gcc/testsuite/rust/compile/const3.rs
new file mode 100644
index 00000000000..22dc3d356ca
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const3.rs
@@ -0,0 +1,7 @@
+fn size() -> usize {
+    15
+}
+
+fn main() {
+    let a = [15; size()]; // { dg-error "only functions marked as .const. are allowed to be called from constant contexts" }
+}
diff --git a/gcc/testsuite/rust/compile/const_generics_1.rs b/gcc/testsuite/rust/compile/const_generics_1.rs
new file mode 100644
index 00000000000..bcad8ee6a19
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_generics_1.rs
@@ -0,0 +1,19 @@
+// { dg-additional-options "-w" }
+
+// There are errors about unused generic parameters, but we can't handle that yet.
+// Still, this code is invalid Rust.
+
+mod sain {
+    struct Foo<const N: usize>;
+    struct Bar<T, const N: usize>;
+    struct Baz<'l, T, const N: usize>;
+}
+
+mod doux {
+    struct Foo<const N: usize = 15>;
+    struct Bar<T, const N: usize = { 14 * 2 }>;
+
+    const N_DEFAULT: usize = 3;
+
+    struct Baz<'l, T, const N: usize = N_DEFAULT>;
+}
diff --git a/gcc/testsuite/rust/compile/const_generics_2.rs b/gcc/testsuite/rust/compile/const_generics_2.rs
new file mode 100644
index 00000000000..98495cf404d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_generics_2.rs
@@ -0,0 +1,4 @@
+struct Foo<const N>; // { dg-error "expecting .:. but .>. found" }
+struct Bar<const N: >; // { dg-error "unrecognised token .>. in type" }
+struct Baz<const N: usize = >; // { dg-error "invalid token for start of default value for const generic parameter" }
+// { dg-error "unrecognised token .>. in type" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/rust/compile/const_generics_3.rs b/gcc/testsuite/rust/compile/const_generics_3.rs
new file mode 100644
index 00000000000..6a3a0fe27bf
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_generics_3.rs
@@ -0,0 +1,26 @@
+// { dg-additional-options "-w" }
+
+const M: usize = 4;
+
+struct Foo<T, const N: usize = 1> {
+    // FIXME: This error is bogus. But having it means parsing is valid!
+    value: [i32; N], // { dg-error "failed to find name: N" }
+}
+
+fn main() {
+    let foo = Foo::<i32> { value: [15] };
+    let foo = Foo::<i32, 2> { value: [15, 13] };
+    let foo: Foo<i32, 2> = Foo { value: [15, 13] };
+    let foo: Foo<i32, 2> = Foo::<i32, 2> { value: [15, 13] };
+    let foo: Foo<i32, { 1 + 1 }> = Foo { value: [15, 13] };
+    let foo = Foo::<i32, { 1 + 1 }> { value: [15, 13] };
+    let foo: Foo<i32, { 1 + 1 }> = Foo::<i32, { 1 + 1 }> { value: [15, 13] };
+    let foo: Foo<i32, M> = Foo::<i32, 4> {
+        value: [15, 13, 11, 9],
+    };
+
+    // FIXME: Add proper const typecheck errors here
+    let invalid_foo: Foo<i32, { 1 + 1 }> = Foo::<i32, 3> { value: [15, 13] };
+    let invalid_foo: Foo<i32, { 1 + 1 }> = Foo::<i32, M> { value: [15, 13] };
+    let invalid_foo: Foo<i32> = Foo::<i32, 2> { value: [15, 13] };
+}
diff --git a/gcc/testsuite/rust/compile/const_generics_4.rs b/gcc/testsuite/rust/compile/const_generics_4.rs
new file mode 100644
index 00000000000..8a3754da433
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_generics_4.rs
@@ -0,0 +1,7 @@
+// { dg-additional-options "-w" }
+
+const P: usize = 14;
+
+struct Foo<const N: usize = { M }>; // { dg-error "failed to find name: M" }
+struct Bar<const N: usize = { P }>;
+struct Baz<const N: NotAType = { P }>; // { dg-error "failed to resolve TypePath: NotAType in this scope" }
diff --git a/gcc/testsuite/rust/compile/const_generics_5.rs b/gcc/testsuite/rust/compile/const_generics_5.rs
new file mode 100644
index 00000000000..5344e31a140
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_generics_5.rs
@@ -0,0 +1,12 @@
+struct Foo<const N: usize = { 14 }>;
+
+const M: usize = 15;
+type N = Foo<3>;
+
+fn main() {
+    let _: Foo<15> = Foo;
+    let _: Foo<{ M }> = Foo;
+    let _: Foo<M> = Foo;
+    // bogus error, but it means the above const generic gets disambiguated properly
+    let _: Foo<N> = Foo; // { dg-error "TypePath Foo<N> declares generic arguments but the type Foo{Foo {}} does not have any" }
+}
diff --git a/gcc/testsuite/rust/compile/const_generics_6.rs b/gcc/testsuite/rust/compile/const_generics_6.rs
new file mode 100644
index 00000000000..de261236d93
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_generics_6.rs
@@ -0,0 +1,2 @@
+struct Foo<const N: usize>;
+struct Bar<const N: usize = { 15i32 }>; // { dg-error "expected .usize. got .i32." }
diff --git a/gcc/testsuite/rust/compile/continue1.rs b/gcc/testsuite/rust/compile/continue1.rs
new file mode 100644
index 00000000000..994312b52cc
--- /dev/null
+++ b/gcc/testsuite/rust/compile/continue1.rs
@@ -0,0 +1,10 @@
+fn main() {
+    let mut a = 1;
+    let mut b = 1;
+
+    let _fib = {
+        continue; // { dg-error "cannot 'continue' outside of a loop" }
+        // { dg-error "failed to type resolve expression" "" { target *-*-* } .-1 }
+        123
+    };
+}
diff --git a/gcc/testsuite/rust/compile/deadcode_err1.rs b/gcc/testsuite/rust/compile/deadcode_err1.rs
new file mode 100644
index 00000000000..1dbe95731e1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/deadcode_err1.rs
@@ -0,0 +1,11 @@
+fn foo() -> i32 {
+    return 1;
+
+    let mut a = 1; // { dg-warning "unreachable statement" }
+    a = 1.1; // { dg-warning "unreachable statement" }
+    // { dg-error "expected .<integer>. got .<float>." "" { target *-*-* } .-1 }
+}
+
+fn main() {
+    foo();
+}
diff --git a/gcc/testsuite/rust/compile/deadcode_err2.rs b/gcc/testsuite/rust/compile/deadcode_err2.rs
new file mode 100644
index 00000000000..8c0eb4617a7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/deadcode_err2.rs
@@ -0,0 +1,16 @@
+fn foo() -> i32 {
+    return 1;
+    return 1.5; // { dg-error "expected .i32. got .<float>." }
+    // { dg-warning "unreachable statement" "" { target *-*-* } .-1 } 
+}
+
+fn bar() -> i32 {
+    return 1.5; // { dg-error "expected .i32. got .<float>." }
+    return 1;
+    // { dg-warning "unreachable statement" "" { target *-*-* } .-1 } 
+}
+
+fn main() {
+    foo();
+    bar();
+}
diff --git a/gcc/testsuite/rust/compile/debug-diagnostics-default.rs b/gcc/testsuite/rust/compile/debug-diagnostics-default.rs
new file mode 100644
index 00000000000..90b0e575b45
--- /dev/null
+++ b/gcc/testsuite/rust/compile/debug-diagnostics-default.rs
@@ -0,0 +1,5 @@
+// Make sure we don't see any 'note's:
+// { dg-bogus {note: } "" { target *-*-* } 0 }
+
+fn main() {
+}
diff --git a/gcc/testsuite/rust/compile/debug-diagnostics-off.rs b/gcc/testsuite/rust/compile/debug-diagnostics-off.rs
new file mode 100644
index 00000000000..77b82b35e62
--- /dev/null
+++ b/gcc/testsuite/rust/compile/debug-diagnostics-off.rs
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fno-rust-debug" }
+
+// Make sure we don't see any 'note's:
+// { dg-bogus {note: } "" { target *-*-* } 0 }
+
+fn main() {
+}
diff --git a/gcc/testsuite/rust/compile/debug-diagnostics-on.rs b/gcc/testsuite/rust/compile/debug-diagnostics-on.rs
new file mode 100644
index 00000000000..847fd24d7bd
--- /dev/null
+++ b/gcc/testsuite/rust/compile/debug-diagnostics-on.rs
@@ -0,0 +1,7 @@
+// { dg-additional-options "-frust-debug" }
+
+// Just scan for one of the Rust front end debug diagnostics:
+// { dg-message {note: Attempting to parse file: .+/gcc/testsuite/rust/compile/debug-diagnostics-on\.rs} "" { target *-*-* } 0 }
+
+fn main() {
+}
diff --git a/gcc/testsuite/rust/compile/doc_isolated_cr_block_comment.rs b/gcc/testsuite/rust/compile/doc_isolated_cr_block_comment.rs
new file mode 100644
index 00000000000..0ada77f69cf
--- /dev/null
+++ b/gcc/testsuite/rust/compile/doc_isolated_cr_block_comment.rs
@@ -0,0 +1,3 @@
+// { dg-error "Isolated CR" "" { target *-*-* } .+1 }
+/** doc cr\r comment */
+pub fn main () { }
diff --git a/gcc/testsuite/rust/compile/doc_isolated_cr_inner_block_comment.rs b/gcc/testsuite/rust/compile/doc_isolated_cr_inner_block_comment.rs
new file mode 100644
index 00000000000..7db35341bee
--- /dev/null
+++ b/gcc/testsuite/rust/compile/doc_isolated_cr_inner_block_comment.rs
@@ -0,0 +1,5 @@
+pub fn main ()
+{
+// { dg-error "Isolated CR" "" { target *-*-* } .+1 }
+  /*! doc cr\r comment */
+}
diff --git a/gcc/testsuite/rust/compile/doc_isolated_cr_inner_line_comment.rs b/gcc/testsuite/rust/compile/doc_isolated_cr_inner_line_comment.rs
new file mode 100644
index 00000000000..d75da75e218
--- /dev/null
+++ b/gcc/testsuite/rust/compile/doc_isolated_cr_inner_line_comment.rs
@@ -0,0 +1,5 @@
+pub fn main ()
+{
+// { dg-error "Isolated CR" "" { target *-*-* } .+1 }
+  //! doc cr\r comment
+}
diff --git a/gcc/testsuite/rust/compile/doc_isolated_cr_line_comment.rs b/gcc/testsuite/rust/compile/doc_isolated_cr_line_comment.rs
new file mode 100644
index 00000000000..7b6ef989c30
--- /dev/null
+++ b/gcc/testsuite/rust/compile/doc_isolated_cr_line_comment.rs
@@ -0,0 +1,3 @@
+// { dg-error "Isolated CR" "" { target *-*-* } .+1 }
+/// doc cr\r comment
+pub fn main () { }
diff --git a/gcc/testsuite/rust/compile/dup_fields.rs b/gcc/testsuite/rust/compile/dup_fields.rs
new file mode 100644
index 00000000000..ab39955eca0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/dup_fields.rs
@@ -0,0 +1,23 @@
+struct S { a: i32, b: i32, c: u8, a: i128 }
+// { dg-error "duplicate field" "" { target *-*-* } .-1 }
+
+union U
+  {
+    a: i32,
+    b: i32,
+    c: u8,
+    b: char // { dg-error "duplicate field" "" { target *-*-* } }
+  }
+
+fn main ()
+{
+  struct SS { alpha: i32, beta: i32, gamma: u8, gamma: i128 }
+  // { dg-error "duplicate field" "" { target *-*-* } .-1 }
+
+  union UU
+    {
+      alpha: i32, beta: i32,
+      gamma: u8, beta: char
+      // { dg-error "duplicate field" "" { target *-*-* } .-1 }
+    }
+}
diff --git a/gcc/testsuite/rust/compile/empty_comment_before_match.rs b/gcc/testsuite/rust/compile/empty_comment_before_match.rs
new file mode 100644
index 00000000000..3d344d3e758
--- /dev/null
+++ b/gcc/testsuite/rust/compile/empty_comment_before_match.rs
@@ -0,0 +1,7 @@
+fn foo (x: i8) -> i32 { // { dg-warning "function is never used" }
+    //
+    match x {
+        1 => { return 1; }
+        _ => { return 0; }
+    }
+}
diff --git a/gcc/testsuite/rust/compile/expected_type_args2.rs b/gcc/testsuite/rust/compile/expected_type_args2.rs
new file mode 100644
index 00000000000..79454202aad
--- /dev/null
+++ b/gcc/testsuite/rust/compile/expected_type_args2.rs
@@ -0,0 +1,6 @@
+struct Foo<A>(A);
+
+fn main() {
+    let a: Foo = Foo::<i32>(123);
+    // { dg-error "generic item takes at least 1 type arguments but 0 were supplied" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/expected_type_args3.rs b/gcc/testsuite/rust/compile/expected_type_args3.rs
new file mode 100644
index 00000000000..ba07239207a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/expected_type_args3.rs
@@ -0,0 +1,8 @@
+struct Foo<A>(A);
+
+impl Foo {
+    // { dg-error "generic item takes at least 1 type arguments but 0 were supplied" "" { target *-*-* } .-1 }
+    fn test() -> i32 {
+        123
+    }
+}
diff --git a/gcc/testsuite/rust/compile/func1.rs b/gcc/testsuite/rust/compile/func1.rs
new file mode 100644
index 00000000000..6758a3898e3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/func1.rs
@@ -0,0 +1,9 @@
+fn test(x: i32) -> bool {
+    return x + 1; // { dg-error "expected .bool. got .i32." }
+}
+
+fn main() {
+    let an_integer = 5;
+
+    let call_test = test(1);
+}
diff --git a/gcc/testsuite/rust/compile/func2.rs b/gcc/testsuite/rust/compile/func2.rs
new file mode 100644
index 00000000000..0b8d999fec1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/func2.rs
@@ -0,0 +1,7 @@
+fn test(a: i32, b: i32) -> i32 {
+    a + b
+}
+
+fn main() {
+    let a = test(1); // { dg-error "unexpected number of arguments 1 expected 2" }
+}
diff --git a/gcc/testsuite/rust/compile/func3.rs b/gcc/testsuite/rust/compile/func3.rs
new file mode 100644
index 00000000000..2a329476118
--- /dev/null
+++ b/gcc/testsuite/rust/compile/func3.rs
@@ -0,0 +1,9 @@
+fn test(a: i32, b: i32) -> i32 {
+    a + b
+}
+
+fn main() {
+    let a = test(1, true);
+    // { dg-error "expected .i32. got .bool." "" { target *-*-* } .-1 }
+    // { dg-error "Type Resolution failure on parameter" "" { target *-*-* } .-2 }
+}
diff --git a/gcc/testsuite/rust/compile/func4.rs b/gcc/testsuite/rust/compile/func4.rs
new file mode 100644
index 00000000000..3b2d2b0d773
--- /dev/null
+++ b/gcc/testsuite/rust/compile/func4.rs
@@ -0,0 +1,6 @@
+fn func() -> i32 { // { dg-error "expected .i32. got ...." }
+}
+
+fn main() {
+    func();
+}
diff --git a/gcc/testsuite/rust/compile/func5.rs b/gcc/testsuite/rust/compile/func5.rs
new file mode 100644
index 00000000000..05624f524e9
--- /dev/null
+++ b/gcc/testsuite/rust/compile/func5.rs
@@ -0,0 +1,7 @@
+fn func() -> i32 {
+    return; // { dg-error "expected .i32. got ...." }
+}
+
+fn main() {
+    func();
+}
diff --git a/gcc/testsuite/rust/compile/generic-default1.rs b/gcc/testsuite/rust/compile/generic-default1.rs
new file mode 100644
index 00000000000..0a132bf5d6b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/generic-default1.rs
@@ -0,0 +1,7 @@
+struct Foo<A = i321>(A);
+// { dg-error "failed to resolve TypePath: i321" "" { target *-*-* } .-1 }
+
+fn main() {
+    let a;
+    a = Foo(123);
+}
diff --git a/gcc/testsuite/rust/compile/generics1.rs b/gcc/testsuite/rust/compile/generics1.rs
new file mode 100644
index 00000000000..de1bbf5dafb
--- /dev/null
+++ b/gcc/testsuite/rust/compile/generics1.rs
@@ -0,0 +1,11 @@
+// { dg-error "expected .i32. got .i8." "" { target *-*-* } 0 }
+
+struct GenericStruct<T>(T, usize);
+
+fn main() {
+    let a2: GenericStruct<i8>;
+    a2 = GenericStruct::<_>(1, 456);
+
+    let b2: i32 = a2.0;
+    let c2: usize = a2.1;
+}
diff --git a/gcc/testsuite/rust/compile/generics10.rs b/gcc/testsuite/rust/compile/generics10.rs
new file mode 100644
index 00000000000..a734fa8a197
--- /dev/null
+++ b/gcc/testsuite/rust/compile/generics10.rs
@@ -0,0 +1,12 @@
+struct Foo<A, B>(A, B);
+
+impl<X = i32> Foo<X, f32> { // { dg-error "defaults for type parameters are not allowed here" }
+    fn new(a: X, b: f32) -> Self {
+        Self(a, b)
+    }
+}
+
+fn main() {
+    let a;
+    a = Foo::new(123, 456f32);
+}
diff --git a/gcc/testsuite/rust/compile/generics11.rs b/gcc/testsuite/rust/compile/generics11.rs
new file mode 100644
index 00000000000..4d3b9e1777c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/generics11.rs
@@ -0,0 +1,12 @@
+struct Foo<T>(T, bool);
+
+impl<T> Foo<T> {
+    fn test() -> i32 {
+        123
+    }
+}
+
+fn main() {
+    let a = Foo::test();
+    // { dg-error "type annotations needed" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/generics12.rs b/gcc/testsuite/rust/compile/generics12.rs
new file mode 100644
index 00000000000..f1ac8b0314b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/generics12.rs
@@ -0,0 +1,6 @@
+fn main() {
+    bar();
+    // { dg-error "type annotations needed" "" { target *-*-* } .-1 }
+}
+
+fn bar<T>() {}
diff --git a/gcc/testsuite/rust/compile/generics13.rs b/gcc/testsuite/rust/compile/generics13.rs
new file mode 100644
index 00000000000..05c75c5f63d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/generics13.rs
@@ -0,0 +1 @@
+struct Foo<A, 'a>; // { dg-error "invalid order for generic parameters: lifetimes should always come before types" }
diff --git a/gcc/testsuite/rust/compile/generics2.rs b/gcc/testsuite/rust/compile/generics2.rs
new file mode 100644
index 00000000000..5812b133038
--- /dev/null
+++ b/gcc/testsuite/rust/compile/generics2.rs
@@ -0,0 +1,11 @@
+// { dg-error "expected .i32. got .i8." "" { target *-*-* } 0 }
+
+struct GenericStruct<T>(T, usize);
+
+fn main() {
+    let a2: GenericStruct<i8>;
+    a2 = GenericStruct(1, 456);
+
+    let b2: i32 = a2.0;
+    let c2: usize = a2.1;
+}
diff --git a/gcc/testsuite/rust/compile/generics3.rs b/gcc/testsuite/rust/compile/generics3.rs
new file mode 100644
index 00000000000..2d4210588fb
--- /dev/null
+++ b/gcc/testsuite/rust/compile/generics3.rs
@@ -0,0 +1,10 @@
+// { dg-error "expected .i32. got .i8." "" { target *-*-* } 0 }
+struct GenericStruct<T>(T, usize);
+
+fn main() {
+    let a2;
+    a2 = GenericStruct::<i8>(1, 456);
+
+    let b2: i32 = a2.0;
+    let c2: usize = a2.1;
+}
diff --git a/gcc/testsuite/rust/compile/generics4.rs b/gcc/testsuite/rust/compile/generics4.rs
new file mode 100644
index 00000000000..8af13586a37
--- /dev/null
+++ b/gcc/testsuite/rust/compile/generics4.rs
@@ -0,0 +1,16 @@
+struct GenericStruct<T>(T, usize);
+
+fn main() {
+    let a2;
+    a2 = GenericStruct::<i8, i32>(1, 456); // { dg-error "generic item takes at most 1 type arguments but 2 were supplied" }
+                                           // { dg-error {failed to type resolve expression} "" { target *-*-* } .-1 }
+                                           // { dg-error {Failed to resolve expression of function call} "" { target *-*-* } .-2 }
+                                           // { duplicate _dg-error {failed to type resolve expression} "" { target *-*-* } .-3 }
+
+    let b2: i32 = a2.0;
+    // { dg-error {Expected Tuple or ADT got: T\?} "" { target *-*-* } .-1 }
+    // { dg-error {failed to type resolve expression} "" { target *-*-* } .-2 }
+    let c2: usize = a2.1;
+    // { dg-error {Expected Tuple or ADT got: T\?} "" { target *-*-* } .-1 }
+    // { dg-error {failed to type resolve expression} "" { target *-*-* } .-2 }
+}
diff --git a/gcc/testsuite/rust/compile/generics5.rs b/gcc/testsuite/rust/compile/generics5.rs
new file mode 100644
index 00000000000..6c847b5a29b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/generics5.rs
@@ -0,0 +1,10 @@
+struct GenericStruct<T>(T, usize);
+
+fn main() {
+    let a2;
+    a2 = GenericStruct::<i8, T>(1, 456);
+    // { dg-error "failed to resolve TypePath: T" "" { target *-*-* } .-1 }
+
+    let b2: i32 = a2.0;
+    let c2: usize = a2.1;
+}
diff --git a/gcc/testsuite/rust/compile/generics6.rs b/gcc/testsuite/rust/compile/generics6.rs
new file mode 100644
index 00000000000..3b81e1bbee1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/generics6.rs
@@ -0,0 +1,31 @@
+struct Foo<A> {
+    a: A,
+}
+
+impl Foo<isize> {
+    fn test() -> i32 { // { dg-error "possible candidate" "TODO" { xfail *-*-* } }
+        123
+    }
+
+    fn bar(self) -> isize {
+        self.a
+    }
+}
+
+impl Foo<f32> {
+    fn test() -> i32 { // { dg-error "possible candidate" "TODO" { xfail *-*-* } }
+        123
+    }
+
+    fn bar(self) -> f32 {
+        self.a
+    }
+}
+
+fn main() {
+    let a: i32 = Foo::test(); // { dg-error "multiple applicable items in scope for: test" }
+    // { dg-error {failed to type resolve expression} "" { target *-*-* } .-1 }
+    // { dg-error {Failed to resolve expression of function call} "" { target *-*-* } .-2 }
+    // { duplicate _dg-error {failed to type resolve expression} "" { target *-*-* } .-3 }
+}
+
diff --git a/gcc/testsuite/rust/compile/generics7.rs b/gcc/testsuite/rust/compile/generics7.rs
new file mode 100644
index 00000000000..2a41632e693
--- /dev/null
+++ b/gcc/testsuite/rust/compile/generics7.rs
@@ -0,0 +1,26 @@
+struct Foo<A> {
+    a: A,
+}
+
+impl Foo<isize> {
+    fn bar(self) -> isize { // { dg-error "duplicate definitions with name bar" }
+        self.a
+    }
+}
+
+impl Foo<char> {
+    fn bar(self) -> char { // { dg-error "duplicate definitions with name bar" }
+        self.a
+    }
+}
+
+impl<T> Foo<T> {
+    fn bar(self) -> T {
+        self.a
+    }
+}
+
+fn main() {
+    let a = Foo { a: 123 };
+    a.bar();
+}
diff --git a/gcc/testsuite/rust/compile/generics8.rs b/gcc/testsuite/rust/compile/generics8.rs
new file mode 100644
index 00000000000..ceefc5d2c6a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/generics8.rs
@@ -0,0 +1,15 @@
+struct Foo<A, B>(A, B);
+
+impl<T> Foo<i32, T> {
+    fn test(a: T) -> T {
+        a
+    }
+}
+
+impl Foo<i32, f32> {
+    fn test() -> f32 { // { dg-error "duplicate definitions with name test" }
+        123f32
+    }
+}
+
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/generics9.rs b/gcc/testsuite/rust/compile/generics9.rs
new file mode 100644
index 00000000000..3766703431e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/generics9.rs
@@ -0,0 +1,10 @@
+struct Foo<A, B = (A, B)>(A, B);
+// { dg-error "failed to resolve TypePath: B" "" { target *-*-* } .-1 }
+
+fn main() {
+    let a: Foo<bool>;
+    a = Foo::<bool>(true, (false, true));
+
+    let b: (bool, bool);
+    b = a.1;
+}
diff --git a/gcc/testsuite/rust/compile/implicit_returns_err1.rs b/gcc/testsuite/rust/compile/implicit_returns_err1.rs
new file mode 100644
index 00000000000..973ba80fb86
--- /dev/null
+++ b/gcc/testsuite/rust/compile/implicit_returns_err1.rs
@@ -0,0 +1,12 @@
+fn test(x: i32) -> i32 {
+    if x > 1 { // { dg-error "expected .... got .<integer>." }
+        1
+    } else {
+        2
+    }
+    3
+}
+
+fn main() {
+    let a = test(1);
+}
diff --git a/gcc/testsuite/rust/compile/implicit_returns_err2.rs b/gcc/testsuite/rust/compile/implicit_returns_err2.rs
new file mode 100644
index 00000000000..fb90748871f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/implicit_returns_err2.rs
@@ -0,0 +1,10 @@
+fn test(x: i32) -> i32 {
+    // { dg-error "expected .i32. got .bool." "" { target *-*-* } .-1 }
+    return 1;
+    // { dg-warning "unreachable expression" "" { target *-*-* } .+1 }
+    true
+}
+
+fn main() {
+    let a = test(1);
+}
diff --git a/gcc/testsuite/rust/compile/implicit_returns_err3.rs b/gcc/testsuite/rust/compile/implicit_returns_err3.rs
new file mode 100644
index 00000000000..37b1c62414c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/implicit_returns_err3.rs
@@ -0,0 +1,9 @@
+fn test(x: i32) -> i32 { // { dg-error "expected .i32. got ...." }
+    if x > 1 {
+        1
+    }
+}
+
+fn main() {
+    let a = test(9);
+}
diff --git a/gcc/testsuite/rust/compile/implicit_returns_err4.rs b/gcc/testsuite/rust/compile/implicit_returns_err4.rs
new file mode 100644
index 00000000000..59c6a020d4c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/implicit_returns_err4.rs
@@ -0,0 +1,10 @@
+fn test(x: bool) -> bool {
+    // { dg-error "expected .bool. got ...." "" { target *-*-*} .-1 }
+    return x;
+    // { dg-warning "unreachable expression" "" { target *-*-* } .+1 }
+    ()
+}
+
+fn main() {
+    let a = test(true);
+}
diff --git a/gcc/testsuite/rust/compile/infer-crate-name.rs b/gcc/testsuite/rust/compile/infer-crate-name.rs
new file mode 100644
index 00000000000..b0c0086c04c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/infer-crate-name.rs
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fdump-tree-gimple" }
+pub fn does_nothing() {}
+fn main() {
+    does_nothing()
+}
+// { dg-final { scan-tree-dump-times {infer_crate_name::does_nothing} 2 gimple } }
+// { dg-final { scan-tree-dump-times {infer_crate_name::main} 1 gimple } }
diff --git a/gcc/testsuite/rust/compile/inline_1.rs b/gcc/testsuite/rust/compile/inline_1.rs
new file mode 100644
index 00000000000..4b0f991765a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/inline_1.rs
@@ -0,0 +1,16 @@
+// { dg-additional-options "-fdump-tree-gimple" }
+#[inline]
+fn test_a() {}
+
+// { dg-final { scan-tree-dump-times {always_inline} 1 gimple } }
+#[inline(always)]
+fn test_b() {}
+
+#[inline(never)]
+fn test_c() {}
+
+fn main() {
+    test_a();
+    test_b();
+    test_c();
+}
diff --git a/gcc/testsuite/rust/compile/inline_2.rs b/gcc/testsuite/rust/compile/inline_2.rs
new file mode 100644
index 00000000000..3665fdac804
--- /dev/null
+++ b/gcc/testsuite/rust/compile/inline_2.rs
@@ -0,0 +1,6 @@
+// { dg-additional-options "-w" }
+#[inline(A)] // { dg-error "unknown inline option" }
+fn test_a() {}
+
+#[inline(A, B)] // { dg-error "invalid number of arguments" }
+fn test_b() {}
diff --git a/gcc/testsuite/rust/compile/issue-1005.rs b/gcc/testsuite/rust/compile/issue-1005.rs
new file mode 100644
index 00000000000..46c85eea91e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1005.rs
@@ -0,0 +1,4 @@
+// { dg-additional-options "-w" }
+impl<T> *const T {
+    fn test(self) {}
+}
diff --git a/gcc/testsuite/rust/compile/issue-1019.rs b/gcc/testsuite/rust/compile/issue-1019.rs
new file mode 100644
index 00000000000..aea86a821c7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1019.rs
@@ -0,0 +1,19 @@
+trait A<T> {
+    type Output;
+
+    fn test(self, a: &T) -> &Self::Output;
+}
+
+struct Foo<T> {
+    // { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+    start: T,
+    end: T,
+}
+
+impl<X> A<X> for Foo<usize> {
+    type Output = X;
+
+    fn test(self, a: &X) -> &Self::Output {
+        a
+    }
+}
diff --git a/gcc/testsuite/rust/compile/issue-1023.rs b/gcc/testsuite/rust/compile/issue-1023.rs
new file mode 100644
index 00000000000..5a0fe6cf530
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1023.rs
@@ -0,0 +1,4 @@
+// { dg-additional-options "-w" }
+fn foo(e: &str) -> &str {
+    &""
+}
diff --git a/gcc/testsuite/rust/compile/issue-1031.rs b/gcc/testsuite/rust/compile/issue-1031.rs
new file mode 100644
index 00000000000..939f0f981e0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1031.rs
@@ -0,0 +1,17 @@
+extern "rust-intrinsic" {
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+    pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+    pub const unsafe fn offset(self, count: isize) -> *const T {
+        // { dg-warning "associated function is never used" "" { target *-*-* } .-1 }
+        unsafe { offset(self, count) }
+    }
+
+    pub const unsafe fn add(self, count: usize) -> Self {
+        // { dg-warning "associated function is never used" "" { target *-*-* } .-1 }
+        unsafe { self.offset(count as isize) }
+    }
+}
diff --git a/gcc/testsuite/rust/compile/issue-1034.rs b/gcc/testsuite/rust/compile/issue-1034.rs
new file mode 100644
index 00000000000..23d77005452
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1034.rs
@@ -0,0 +1,16 @@
+trait Foo<T> {
+    type Output;
+
+    fn test(self, slice: &T) -> &Self::Output;
+}
+
+struct Bar<T>(T);
+// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+
+impl<T> Foo<[T]> for Bar<usize> {
+    type Output = [T];
+
+    fn test(self, slice: &[T]) -> &[T] {
+        slice
+    }
+}
diff --git a/gcc/testsuite/rust/compile/issue-1089.rs b/gcc/testsuite/rust/compile/issue-1089.rs
new file mode 100644
index 00000000000..635af293dbb
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1089.rs
@@ -0,0 +1,6 @@
+// { dg-additional-options "-w" }
+pub mod test_mod;
+
+fn main() {
+    let a = test_mod::Test(123);
+}
diff --git a/gcc/testsuite/rust/compile/issue-1128.rs b/gcc/testsuite/rust/compile/issue-1128.rs
new file mode 100644
index 00000000000..462426b679d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1128.rs
@@ -0,0 +1,6 @@
+pub trait Hasher {
+    fn write(&mut self, bytes: &[u8]);
+    fn write_u8(&mut self, i: u8) {
+        self.write(&[i])
+    }
+}
diff --git a/gcc/testsuite/rust/compile/issue-1129-1.rs b/gcc/testsuite/rust/compile/issue-1129-1.rs
new file mode 100644
index 00000000000..a15903983f0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1129-1.rs
@@ -0,0 +1,4 @@
+// { dg-additional-options "-w" }
+fn write_u8(i: u8) {
+    let x: &[u8] = &[i];
+}
diff --git a/gcc/testsuite/rust/compile/issue-1129-2.rs b/gcc/testsuite/rust/compile/issue-1129-2.rs
new file mode 100644
index 00000000000..25d30faf4aa
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1129-2.rs
@@ -0,0 +1,22 @@
+// { dg-additional-options "-w" }
+pub trait Hasher {
+    fn finish(&self) -> u64;
+    fn write(&mut self, bytes: &[u8]);
+    fn write_u8(&mut self, i: u8) {
+        self.write(&[i])
+    }
+}
+
+struct SipHasher;
+
+impl Hasher for SipHasher {
+    #[inline]
+    fn write(&mut self, msg: &[u8]) {
+        loop {}
+    }
+
+    #[inline]
+    fn finish(&self) -> u64 {
+        0
+    }
+}
diff --git a/gcc/testsuite/rust/compile/issue-1130.rs b/gcc/testsuite/rust/compile/issue-1130.rs
new file mode 100644
index 00000000000..92200c7cd5f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1130.rs
@@ -0,0 +1,47 @@
+// { dg-additional-options "-w" }
+mod mem {
+    extern "rust-intrinsic" {
+        fn size_of<T>() -> usize;
+        fn transmute<U, V>(_: U) -> V;
+    }
+}
+
+impl u16 {
+    fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
+        unsafe { mem::transmute(self) }
+    }
+}
+
+pub trait Hasher {
+    fn finish(&self) -> u64;
+
+    fn write(&mut self, bytes: &[u8]);
+
+    fn write_u8(&mut self, i: u8) {
+        self.write(&[i])
+    }
+
+    fn write_i8(&mut self, i: i8) {
+        self.write_u8(i as u8)
+    }
+
+    fn write_u16(&mut self, i: u16) {
+        self.write(&i.to_ne_bytes())
+    }
+
+    fn write_i16(&mut self, i: i16) {
+        self.write_u16(i as u16)
+    }
+}
+
+pub struct SipHasher;
+
+impl Hasher for SipHasher {
+    #[inline]
+    fn write(&mut self, msg: &[u8]) {}
+
+    #[inline]
+    fn finish(&self) -> u64 {
+        0
+    }
+}
diff --git a/gcc/testsuite/rust/compile/issue-1131.rs b/gcc/testsuite/rust/compile/issue-1131.rs
new file mode 100644
index 00000000000..fd158abc700
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1131.rs
@@ -0,0 +1,4 @@
+extern "rust-intrinsic" {
+    fn size_of<T>() -> usize;
+    fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
diff --git a/gcc/testsuite/rust/compile/issue-1152.rs b/gcc/testsuite/rust/compile/issue-1152.rs
new file mode 100644
index 00000000000..18eee9e6b4a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1152.rs
@@ -0,0 +1,8 @@
+fn test() {
+    let f = [0; -4_isize];
+    // { dg-error "expected .usize. got .isize." "" { target *-*-* } .-1 }
+    // { dg-error "failed to type resolve expression" "" { target *-*-* } .-2 }
+    let f = [0_usize; -1_isize];
+    // { dg-error "expected .usize. got .isize." "" { target *-*-* } .-1 }
+    // { dg-error "failed to type resolve expression" "" { target *-*-* } .-2 }
+}
diff --git a/gcc/testsuite/rust/compile/issue-1165.rs b/gcc/testsuite/rust/compile/issue-1165.rs
new file mode 100644
index 00000000000..f5889698d70
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1165.rs
@@ -0,0 +1,5 @@
+struct Foo<T>(T);
+
+fn main() {
+    &Foo(123);
+}
diff --git a/gcc/testsuite/rust/compile/issue-1173.rs b/gcc/testsuite/rust/compile/issue-1173.rs
new file mode 100644
index 00000000000..5c2a9173241
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1173.rs
@@ -0,0 +1,23 @@
+// { dg-additional-options "-w" }
+
+#![feature(intrinsics)]
+
+mod mem {
+    extern "rust-intrinsic" {
+        pub fn transmute<U, V>(_: U) -> V;
+    }
+}
+
+pub trait Hasher {
+    fn write(&mut self, bytes: &[u8]);
+    fn write_u16(&mut self, i: u16) {
+        self.write(unsafe { &mem::transmute::<_, [u8; 2]>(i) })
+    }
+}
+
+pub struct SipHasher;
+
+impl Hasher for SipHasher {
+    #[inline]
+    fn write(&mut self, msg: &[u8]) {}
+}
diff --git a/gcc/testsuite/rust/compile/issue-1226.rs b/gcc/testsuite/rust/compile/issue-1226.rs
new file mode 100644
index 00000000000..f5f9e5ff08d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1226.rs
@@ -0,0 +1,6 @@
+// { dg-additional-options "-w" }
+const TEST: *mut u8 = 123 as *mut u8;
+
+fn test() {
+    let a = TEST;
+}
diff --git a/gcc/testsuite/rust/compile/issue-1234.rs b/gcc/testsuite/rust/compile/issue-1234.rs
new file mode 100644
index 00000000000..c6d5932c004
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1234.rs
@@ -0,0 +1,4 @@
+fn foo() -> u8 {
+    // { dg-warning "function is never used" "" { target *-*-* } .-1 }
+    1u8 << 2u32
+}
diff --git a/gcc/testsuite/rust/compile/issue-1235.rs b/gcc/testsuite/rust/compile/issue-1235.rs
new file mode 100644
index 00000000000..098b337455f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1235.rs
@@ -0,0 +1,21 @@
+// { dg-additional-options "-w" }
+struct FatPtr<T> {
+    data: *const T,
+    len: usize,
+}
+
+pub union Repr<T> {
+    rust: *const [T],
+    rust_mut: *mut [T],
+    raw: FatPtr<T>,
+}
+
+impl<T> [T] {
+    pub const fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+
+    pub const fn len(&self) -> usize {
+        unsafe { Repr { rust: self }.raw.len }
+    }
+}
diff --git a/gcc/testsuite/rust/compile/issue-1237.rs b/gcc/testsuite/rust/compile/issue-1237.rs
new file mode 100644
index 00000000000..542be897949
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1237.rs
@@ -0,0 +1,23 @@
+// { dg-additional-options "-w" }
+mod intrinsics {
+    extern "rust-intrinsic" {
+        pub fn offset<T>(ptr: *const T, count: isize) -> *const T;
+    }
+}
+
+impl<T> *const T {
+    pub unsafe fn offset(self, count: isize) -> *const T {
+        unsafe { intrinsics::offset(self, count) }
+    }
+}
+
+impl<T> [T] {
+    pub unsafe fn get_unchecked(&self, index: usize) -> &T {
+        unsafe { &*(self as *const [T] as *const T).offset(index as isize) }
+    }
+}
+
+#[inline]
+unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 {
+    (unsafe { *buf.get_unchecked(start) } as u64)
+}
diff --git a/gcc/testsuite/rust/compile/issue-1251.rs b/gcc/testsuite/rust/compile/issue-1251.rs
new file mode 100644
index 00000000000..b16e1e0b0d9
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1251.rs
@@ -0,0 +1,14 @@
+// { dg-additional-options "-w" }
+mod a {
+    pub mod b {
+        pub mod a {
+            pub fn foo() {}
+        }
+    }
+
+    pub fn bidule() {
+        crate::a::b::a::foo()
+    }
+}
+
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/issue-1271.rs b/gcc/testsuite/rust/compile/issue-1271.rs
new file mode 100644
index 00000000000..5dd6418de4c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1271.rs
@@ -0,0 +1,5 @@
+// { dg-additional-options "-w" }
+fn test() {
+    let a: &str = "TEST 1";
+    let b: &str = &"TEST 2";
+}
diff --git a/gcc/testsuite/rust/compile/issue-1289.rs b/gcc/testsuite/rust/compile/issue-1289.rs
new file mode 100644
index 00000000000..343aaab078b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1289.rs
@@ -0,0 +1,43 @@
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+mod intrinsics {
+    extern "rust-intrinsic" {
+        #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+        pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
+    }
+}
+
+#[lang = "mut_ptr"]
+impl<T> *mut T {
+    pub const unsafe fn offset(self, count: isize) -> *mut T {
+        unsafe { intrinsics::offset(self, count) as *mut T }
+    }
+
+    pub const unsafe fn add(self, count: usize) -> Self {
+        unsafe { self.offset(count as isize) }
+    }
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+    pub const unsafe fn offset(self, count: isize) -> *mut T {
+        // { dg-warning "associated function is never used" "" { target *-*-* } .-1 }
+        unsafe { intrinsics::offset(self, count) as *mut T }
+    }
+
+    pub const unsafe fn add(self, count: usize) -> Self {
+        // { dg-warning "associated function is never used" "" { target *-*-* } .-1 }
+        unsafe { self.offset(count as isize) }
+    }
+}
+
+fn main() -> i32 {
+    let a: *mut _ = &mut 123;
+    unsafe {
+        let _b = a.add(123);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/compile/issue-1323-1.rs b/gcc/testsuite/rust/compile/issue-1323-1.rs
new file mode 100644
index 00000000000..a6174253a21
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1323-1.rs
@@ -0,0 +1,18 @@
+fn main() {
+    let mut x = [1, 2, 3];
+    let y: i32 = x[0];
+    print_int(y);
+}
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn print_int(value: i32) {
+    let s = "%d\n\0";
+    let s_p = s as *const str;
+    let c_p = s_p as *const i8;
+    unsafe {
+        printf(c_p, value as isize);
+    }
+}
diff --git a/gcc/testsuite/rust/compile/issue-1323-2.rs b/gcc/testsuite/rust/compile/issue-1323-2.rs
new file mode 100644
index 00000000000..45168b22fa7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1323-2.rs
@@ -0,0 +1,16 @@
+fn print_int(value: i32) {
+    let s = "%d\n\0";
+    let s_p = s as *const str;
+    let c_p = s_p as *const i8;
+    unsafe {
+        printf(c_p, value as isize);
+    }
+}
+
+fn main() {
+    print_int(5);
+}
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
diff --git a/gcc/testsuite/rust/compile/issue-1383.rs b/gcc/testsuite/rust/compile/issue-1383.rs
new file mode 100644
index 00000000000..cca12e8fc71
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1383.rs
@@ -0,0 +1,8 @@
+pub fn generic_function<X>(a: X) -> X {
+    a
+}
+
+fn main() -> i32 {
+    let a = generic_function(123);
+    a - 123
+}
diff --git a/gcc/testsuite/rust/compile/issue-1393.rs b/gcc/testsuite/rust/compile/issue-1393.rs
new file mode 100644
index 00000000000..e09f01b62e5
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1393.rs
@@ -0,0 +1,13 @@
+fn tst() {
+    let a = 123;
+    let b = 0;
+    let _c = if b == 0 {
+        (a & 0x7fffff) << 1
+    } else {
+        (a & 0x7fffff) | 0x800000
+    };
+}
+
+fn main() {
+    tst()
+}
diff --git a/gcc/testsuite/rust/compile/issue-1447.rs b/gcc/testsuite/rust/compile/issue-1447.rs
new file mode 100644
index 00000000000..e0543e6247c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1447.rs
@@ -0,0 +1,28 @@
+// { dg-options "-w" }
+struct PhantomData<T>;
+
+struct Hasher<S> {
+    _marker: PhantomData<S>,
+}
+
+struct Sip24Rounds;
+
+struct SipHasher24 {
+    hasher: Hasher<Sip24Rounds>,
+}
+
+impl SipHasher24 {
+    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher24 {
+        SipHasher24 {
+            hasher: Hasher::new_with_keys(),
+        }
+    }
+}
+
+impl<S> Hasher<S> {
+    fn new_with_keys() -> Hasher<S> {
+        Hasher {
+            _marker: PhantomData,
+        }
+    }
+}
diff --git a/gcc/testsuite/rust/compile/issue-407-2.rs b/gcc/testsuite/rust/compile/issue-407-2.rs
new file mode 100644
index 00000000000..cb8027b9c7f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-407-2.rs
@@ -0,0 +1,21 @@
+// #407
+pub fn loopy()  {
+    let mut a = 1;
+    // { dg-error {failed to parse expr with block in parsing expr statement} "" { target *-*-* } .+2 }
+    // { dg-error {failed to parse statement or expression without block in block expression} "" { target *-*-* } .+1 }
+    loop {
+        // { dg-error {failed to parse expr with block in parsing expr statement} "" { target *-*-* } .+2 }
+        // { dg-error {failed to parse statement or expression without block in block expression} "" { target *-*-* } .+1 }
+	if a < 40 {
+	    a + = 1; // { dg-error "found unexpected token '=' in null denotation" }
+            // { dg-error {failed to parse expression for expression without block \(pratt-parsed expression is null\)} "" { target *-*-* } .-1 }
+            // { dg-error {failed to parse statement or expression without block in block expression} "" { target *-*-* } .-2 }
+            // { dg-error {failed to parse if body block expression in if expression} "" { target *-*-* } .-3 }
+            // { dg-error {could not parse loop body in \(infinite\) loop expression} "" { target *-*-* } .+1 }
+	} else {
+	    break;
+	}
+    }
+}
+// { dg-error {unrecognised token '\}' for start of item} "" { target *-*-* } .-1 }
+// { dg-error {failed to parse item in crate} "" { target *-*-* } .-2 }
diff --git a/gcc/testsuite/rust/compile/issue-407.rs b/gcc/testsuite/rust/compile/issue-407.rs
new file mode 100644
index 00000000000..530b7ddfc12
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-407.rs
@@ -0,0 +1,9 @@
+// This already worked before the #409 code changes.
+fn test()  {
+    let mut a = 1;
+    a + = 1; // { dg-error "found unexpected token '=' in null denotation" }
+    // { dg-error {failed to parse expression for expression without block \(pratt-parsed expression is null\)} "" { target *-*-* } .-1 }
+    // { dg-error {failed to parse statement or expression without block in block expression} "" { target *-*-* } .-2 }
+    // { dg-error {unrecognised token 'integer literal' for start of item} "" { target *-*-* } .-3 }
+    // { dg-error {failed to parse item in crate} "" { target *-*-* } .-4 }
+}
diff --git a/gcc/testsuite/rust/compile/issue-557.rs b/gcc/testsuite/rust/compile/issue-557.rs
new file mode 100644
index 00000000000..aeb5ba6755b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-557.rs
@@ -0,0 +1,4 @@
+// { dg-additional-options "-w" }
+fn test(a: i32, _: i32) {
+    let _ = 42 + a;
+}
diff --git a/gcc/testsuite/rust/compile/issue-635-1.rs b/gcc/testsuite/rust/compile/issue-635-1.rs
new file mode 100644
index 00000000000..dc6a4c2eece
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-635-1.rs
@@ -0,0 +1,5 @@
+// { dg-additional-options "-w" }
+fn test() -> i32 {
+    return 10000000000000000000000000000000000000000000;
+    // { dg-error "integer overflows the respective type .i32." "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/issue-635-2.rs b/gcc/testsuite/rust/compile/issue-635-2.rs
new file mode 100644
index 00000000000..335218aa52c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-635-2.rs
@@ -0,0 +1,5 @@
+// { dg-additional-options "-w" }
+fn test() -> f32 {
+    return 10000000000000000000000000000000000000000000.0f32;
+    // { dg-error "decimal overflows the respective type .f32." "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/lookup_err1.rs b/gcc/testsuite/rust/compile/lookup_err1.rs
new file mode 100644
index 00000000000..4a96f9ff140
--- /dev/null
+++ b/gcc/testsuite/rust/compile/lookup_err1.rs
@@ -0,0 +1,7 @@
+fn test() {
+    fn nested() {}
+}
+
+fn main() {
+    nested(); // { dg-error "Cannot find path .nested. in this scope" }
+}
diff --git a/gcc/testsuite/rust/compile/macro-issue1053-2.rs b/gcc/testsuite/rust/compile/macro-issue1053-2.rs
new file mode 100644
index 00000000000..31459907c08
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro-issue1053-2.rs
@@ -0,0 +1,5 @@
+macro_rules! m {
+    ($e:expr $(forbidden)*) => {{}}; // { dg-error "token .identifier. is not allowed after .expr. fragment" }
+                                     // { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-1 }
+                                     // { dg-error "failed to parse item in crate" "" { target *-*-* } .-2 }
+}
diff --git a/gcc/testsuite/rust/compile/macro-issue1053.rs b/gcc/testsuite/rust/compile/macro-issue1053.rs
new file mode 100644
index 00000000000..1e968496e0c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro-issue1053.rs
@@ -0,0 +1,3 @@
+macro_rules! m {
+    ($e:expr $(,)*) => {{}};
+}
diff --git a/gcc/testsuite/rust/compile/macro-issue1224.rs b/gcc/testsuite/rust/compile/macro-issue1224.rs
new file mode 100644
index 00000000000..003bbcd5067
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro-issue1224.rs
@@ -0,0 +1,9 @@
+macro_rules! impl_uint {
+    ($($ty:ident),*) => {
+        impl $ty {} // { dg-error "metavariable is still repeating at this depth" }
+                    // { dg-error "unrecognised token" "" { target *-*-* } .-1 } // Spurious
+                    // { dg-error "could not parse type" "" { target *-*-* } .-2 } // Spurious
+    };
+}
+
+impl_uint!(u8, u16, u32, u64, u128);
diff --git a/gcc/testsuite/rust/compile/macro-issue1233.rs b/gcc/testsuite/rust/compile/macro-issue1233.rs
new file mode 100644
index 00000000000..7fab787b9e8
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro-issue1233.rs
@@ -0,0 +1,22 @@
+// { dg-additional-options "-frust-cfg=A -w" }
+
+macro_rules! impl_uint {
+    ($($ty:ident = $lang:literal),*) => {
+        $(
+            impl $ty {
+                pub fn to_le(self) -> Self {
+                    #[cfg(not(A))]
+                    {
+                        self
+                    }
+                    #[cfg(A)]
+                    {
+                        self
+                    }
+                }
+            }
+        )*
+    }
+}
+
+impl_uint!(u8 = "u8", u16 = "u16", u32 = "u32");
diff --git a/gcc/testsuite/rust/compile/macro-issue1395-2.rs b/gcc/testsuite/rust/compile/macro-issue1395-2.rs
new file mode 100644
index 00000000000..1df6a3a0038
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro-issue1395-2.rs
@@ -0,0 +1,7 @@
+// { dg-additional-options "-frust-edition=2018" }
+
+macro_rules! try {
+    // { dg-error "expecting .identifier. but .try. found" "" { target *-*-* } .-1 }
+    // { dg-error "failed to parse item in crate" "" { target *-*-* } .-2 }
+    () => {};
+}
diff --git a/gcc/testsuite/rust/compile/macro-issue1395.rs b/gcc/testsuite/rust/compile/macro-issue1395.rs
new file mode 100644
index 00000000000..b0368c1610f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro-issue1395.rs
@@ -0,0 +1,5 @@
+// Default edition is 2015 - this is valid
+
+macro_rules! try {
+    () => {};
+}
diff --git a/gcc/testsuite/rust/compile/macro-issue1400-2.rs b/gcc/testsuite/rust/compile/macro-issue1400-2.rs
new file mode 100644
index 00000000000..ba7b61b0b16
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro-issue1400-2.rs
@@ -0,0 +1,32 @@
+macro_rules! foo {
+    ( ( $( $Trait: ident ),+ ) for $($Ty: ident)* ) => {
+        $(
+            impl $Trait for $Ty {
+    // { dg-error "different amount of matches used in merged repetitions: expected 4, got 1" "" { target *-*-* } .-1 }
+                fn bar() -> i32 {
+                    14
+                }
+            }
+        )+
+    }
+}
+
+trait Foo {
+    fn bar() -> i32;
+}
+
+trait Bar {
+    fn bar() -> i32;
+}
+
+trait Baz {
+    fn bar() -> i32;
+}
+
+trait Qux {
+    fn bar() -> i32;
+}
+
+struct S;
+
+foo! {(Foo, Bar, Baz, Qux) for S}
diff --git a/gcc/testsuite/rust/compile/macro-issue1400.rs b/gcc/testsuite/rust/compile/macro-issue1400.rs
new file mode 100644
index 00000000000..971bd778054
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro-issue1400.rs
@@ -0,0 +1,33 @@
+// { dg-additional-options "-w" }
+
+macro_rules! foo {
+    ( ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
+        $(
+            impl $Trait for $Ty {
+                fn bar() -> i32 {
+                    14
+                }
+            }
+        )+
+    }
+}
+
+trait Foo {
+    fn bar() -> i32;
+}
+
+trait Bar {
+    fn bar() -> i32;
+}
+
+trait Baz {
+    fn bar() -> i32;
+}
+
+trait Qux {
+    fn bar() -> i32;
+}
+
+struct S;
+
+foo! {(Foo, Bar, Baz, Qux) for S}
diff --git a/gcc/testsuite/rust/compile/macro1.rs b/gcc/testsuite/rust/compile/macro1.rs
new file mode 100644
index 00000000000..8cd941891d0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro1.rs
@@ -0,0 +1,3 @@
+macro_rules! empty_parens {
+    () => ();
+}
diff --git a/gcc/testsuite/rust/compile/macro10.rs b/gcc/testsuite/rust/compile/macro10.rs
new file mode 100644
index 00000000000..3f1453e2eda
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro10.rs
@@ -0,0 +1,11 @@
+// { dg-additional-options "-w" }
+macro_rules! foo {
+    {} => {
+        15
+    };
+}
+
+fn main() {
+    let a = foo!();
+    let b = foo![];
+}
diff --git a/gcc/testsuite/rust/compile/macro11.rs b/gcc/testsuite/rust/compile/macro11.rs
new file mode 100644
index 00000000000..97b89a12d84
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro11.rs
@@ -0,0 +1,11 @@
+macro_rules! call_f {
+    ($($f:ident)*) => { $($f();)* }
+}
+
+fn f() {}
+
+// This is valid and should parse items
+fn main() {
+    call_f!(f f f f);
+}
+
diff --git a/gcc/testsuite/rust/compile/macro12.rs b/gcc/testsuite/rust/compile/macro12.rs
new file mode 100644
index 00000000000..b75fbad2c2f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro12.rs
@@ -0,0 +1,8 @@
+// { dg-additional-options "-w" }
+macro_rules! define_vars {
+    ($($v:ident)*) => { $(let $v = 15;)* }
+}
+
+fn main() {
+    define_vars!(a0 b f __some_identifier);
+}
diff --git a/gcc/testsuite/rust/compile/macro13.rs b/gcc/testsuite/rust/compile/macro13.rs
new file mode 100644
index 00000000000..eb8dfbbf393
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro13.rs
@@ -0,0 +1,12 @@
+// { dg-additional-options "-w" }
+macro_rules! create_type {
+    ($s:ident) => {
+        struct $s;
+    };
+}
+
+fn main() {
+    create_type!(A);
+
+    let a = A;
+}
diff --git a/gcc/testsuite/rust/compile/macro14.rs b/gcc/testsuite/rust/compile/macro14.rs
new file mode 100644
index 00000000000..b18c56eefc8
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro14.rs
@@ -0,0 +1,10 @@
+// { dg-additional-options "-w" }
+macro_rules! define_vars {
+    ($($v:ident)*) => { $(let $v = 15;)* }
+}
+
+fn main() -> i32 {
+    define_vars!(a0 b f __some_identifier);
+
+    b
+}
diff --git a/gcc/testsuite/rust/compile/macro15.rs b/gcc/testsuite/rust/compile/macro15.rs
new file mode 100644
index 00000000000..02c739e415e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro15.rs
@@ -0,0 +1,12 @@
+// { dg-additional-options "-w" }
+macro_rules! create_type {
+    ($s:ident) => {
+        struct $s;
+    };
+}
+
+create_type!(SomeOuterType);
+
+fn main() {
+    let a = SomeOuterType;
+}
diff --git a/gcc/testsuite/rust/compile/macro16.rs b/gcc/testsuite/rust/compile/macro16.rs
new file mode 100644
index 00000000000..e5e56ed3f03
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro16.rs
@@ -0,0 +1,11 @@
+fn main() {
+    macro_rules! create_type {
+        ($s:ident) => {
+            struct $s(i32);
+        };
+    }
+
+    create_type!(Wrapper);
+
+    let _ = Wrapper(15);
+}
diff --git a/gcc/testsuite/rust/compile/macro17.rs b/gcc/testsuite/rust/compile/macro17.rs
new file mode 100644
index 00000000000..743216529b7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro17.rs
@@ -0,0 +1,10 @@
+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" }
+    }
+}
+
+fn main() -> i32 {
+    rep!(1, 2)
+}
diff --git a/gcc/testsuite/rust/compile/macro18.rs b/gcc/testsuite/rust/compile/macro18.rs
new file mode 100644
index 00000000000..5418725b619
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro18.rs
@@ -0,0 +1,14 @@
+// { dg-additional-options "-w" }
+
+macro_rules! take_stmt {
+    ($s:stmt) => {
+        $s;
+    };
+}
+
+fn main() -> i32 {
+    take_stmt!(let complete = 15;); // { dg-error "Failed to match any rule within macro" }
+    take_stmt!(let lacking = 14);
+
+    0
+}
diff --git a/gcc/testsuite/rust/compile/macro19.rs b/gcc/testsuite/rust/compile/macro19.rs
new file mode 100644
index 00000000000..1bf9a2bfa9d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro19.rs
@@ -0,0 +1,19 @@
+// { dg-additional-options "-w" }
+
+macro_rules! call_without_semi {
+    () => {
+        f()
+    };
+    (block) => {{
+        f()
+    }};
+}
+
+fn f() {}
+
+fn main() -> i32 {
+    call_without_semi!();
+    call_without_semi!(block);
+
+    0
+}
diff --git a/gcc/testsuite/rust/compile/macro2.rs b/gcc/testsuite/rust/compile/macro2.rs
new file mode 100644
index 00000000000..a437655ef70
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro2.rs
@@ -0,0 +1,3 @@
+macro_rules! empty_brackets {
+    [] => [];
+}
diff --git a/gcc/testsuite/rust/compile/macro20.rs b/gcc/testsuite/rust/compile/macro20.rs
new file mode 100644
index 00000000000..9f3cbca012c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro20.rs
@@ -0,0 +1,16 @@
+macro_rules! define_trait {
+    ($assoc:ident, $i:item) => {
+        type $assoc;
+
+        $i
+    };
+}
+
+trait DefinedThroughMacros {
+    define_trait!(
+        Inner,
+        fn takes_inner(i: Self::Inner) -> Self::Inner {
+            i
+        }
+    );
+}
diff --git a/gcc/testsuite/rust/compile/macro21.rs b/gcc/testsuite/rust/compile/macro21.rs
new file mode 100644
index 00000000000..9a1d773ec4b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro21.rs
@@ -0,0 +1,9 @@
+macro_rules! c_fn {
+    {$name:ident ($($arg_name:ident $arg_ty:ty),*) -> $ret_ty:ty} => {
+        fn $name($($arg_name: $arg_ty)*) -> $ret_ty;
+    };
+}
+
+extern "C" {
+    c_fn! {puts (s *const i8) -> i64}
+}
diff --git a/gcc/testsuite/rust/compile/macro22.rs b/gcc/testsuite/rust/compile/macro22.rs
new file mode 100644
index 00000000000..bdc4bada270
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro22.rs
@@ -0,0 +1,10 @@
+macro_rules! print {
+    () => {
+        fn puts(s: *const i8);
+        fn printf(fmt: *const i8, ...);
+    };
+}
+
+extern "C" {
+    print! {}
+}
diff --git a/gcc/testsuite/rust/compile/macro23.rs b/gcc/testsuite/rust/compile/macro23.rs
new file mode 100644
index 00000000000..afaca9bc96b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro23.rs
@@ -0,0 +1,25 @@
+macro_rules! maybe_impl {
+    ($left:ident, $right:ident, $l_fn:ident, $r_fn:ident) => {
+        fn $l_fn(value: T) -> Maybe<T> {
+            Maybe::$left(value)
+        }
+
+        fn $r_fn() -> Maybe<T> {
+            Maybe::$right
+        }
+    };
+}
+
+enum Maybe<T> {
+    Just(T),
+    Nothing,
+}
+
+impl<T> Maybe<T> {
+    maybe_impl!(Just, Nothing, just, nothing);
+}
+
+fn main() {
+    let _ = Maybe::just(14);
+    let _: Maybe<i32> = Maybe::nothing();
+}
diff --git a/gcc/testsuite/rust/compile/macro25.rs b/gcc/testsuite/rust/compile/macro25.rs
new file mode 100644
index 00000000000..d92534c0747
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro25.rs
@@ -0,0 +1,9 @@
+macro_rules! valid {
+    ($($a:literal)* $i:ident) => {{}};
+}
+
+fn main() {
+    valid!(1 one_lit);
+    valid!(identifier_only);
+    valid!(1 2 two_lits);
+}
diff --git a/gcc/testsuite/rust/compile/macro26.rs b/gcc/testsuite/rust/compile/macro26.rs
new file mode 100644
index 00000000000..f6588e75eb0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro26.rs
@@ -0,0 +1,10 @@
+macro_rules! repeat {
+    ( $( $i:literal ),* ; $( $j:literal ),* ) => (( $( ($i,$j) ),* ))
+    // { dg-error "different amount of matches used in merged repetitions" "" { target *-*-* } .-1 }
+}
+
+fn main() -> i32 {
+    let _ = repeat!(1, 2, 3; 2, 3);
+
+    0
+}
diff --git a/gcc/testsuite/rust/compile/macro27.rs b/gcc/testsuite/rust/compile/macro27.rs
new file mode 100644
index 00000000000..ee7833be0a6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro27.rs
@@ -0,0 +1,8 @@
+macro_rules! m {
+    ($a:expr tok) => {
+        // { dg-error "token .identifier. is not allowed after .expr. fragment" "" { target *-*-* } .-1 }
+        // { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-2 }
+        // { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 }
+        $a
+    };
+}
diff --git a/gcc/testsuite/rust/compile/macro28.rs b/gcc/testsuite/rust/compile/macro28.rs
new file mode 100644
index 00000000000..8002f284ecf
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro28.rs
@@ -0,0 +1,8 @@
+macro_rules! m {
+    ($a:expr $(tok $es:expr)*) => {
+        // { dg-error "token .identifier. is not allowed after .expr. fragment" "" { target *-*-* } .-1 }
+        // { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-2 }
+        // { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 }
+        $a
+    };
+}
diff --git a/gcc/testsuite/rust/compile/macro29.rs b/gcc/testsuite/rust/compile/macro29.rs
new file mode 100644
index 00000000000..39f5021b74f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro29.rs
@@ -0,0 +1,8 @@
+macro_rules! m {
+    ($($es:expr)* tok) => {
+        // { dg-error "token .identifier. is not allowed after .expr. fragment" "" { target *-*-* } .-1 }
+        // { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-2 }
+        // { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 }
+        $a
+    };
+}
diff --git a/gcc/testsuite/rust/compile/macro3.rs b/gcc/testsuite/rust/compile/macro3.rs
new file mode 100644
index 00000000000..e5d3e93e07b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro3.rs
@@ -0,0 +1,3 @@
+macro_rules! empty_curlies {
+    {} => {};
+}
diff --git a/gcc/testsuite/rust/compile/macro30.rs b/gcc/testsuite/rust/compile/macro30.rs
new file mode 100644
index 00000000000..35064bc0ee5
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro30.rs
@@ -0,0 +1,8 @@
+macro_rules! m {
+    ($e:expr $f:expr) => {
+        // { dg-error "fragment is not allowed after .expr. fragment" "" { target *-*-* } .-1 }
+        // { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-2 }
+        // { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 }
+        $e
+    };
+}
diff --git a/gcc/testsuite/rust/compile/macro31.rs b/gcc/testsuite/rust/compile/macro31.rs
new file mode 100644
index 00000000000..6674a5fe554
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro31.rs
@@ -0,0 +1,8 @@
+macro_rules! m {
+    ($($e:expr)* $($f:expr)*) => {
+        // { dg-error "fragment is not allowed after .expr. fragment" "" { target *-*-* } .-1 }
+        // { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-2 }
+        // { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 }
+        $e
+    };
+}
diff --git a/gcc/testsuite/rust/compile/macro32.rs b/gcc/testsuite/rust/compile/macro32.rs
new file mode 100644
index 00000000000..d1d6305e6bd
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro32.rs
@@ -0,0 +1,19 @@
+macro_rules! s {
+    ($s:stmt) => {{}};
+}
+
+macro_rules! multi_s {
+    ($($s:stmt)+) => {{}};
+}
+
+fn main() -> i32 {
+    s!(let a = 15);
+    s!(;); // Empty statement
+    s!(let a = 15;); // { dg-error "Failed to match any rule within macro" }
+    multi_s!(let a = 15;);
+    // ^ this actually gets parsed as two statements - one LetStmt and one
+    // empty statement. This is the same behavior as rustc, which you can
+    // see using a count!() macro
+
+    32
+}
diff --git a/gcc/testsuite/rust/compile/macro33.rs b/gcc/testsuite/rust/compile/macro33.rs
new file mode 100644
index 00000000000..2ccd33e50d3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro33.rs
@@ -0,0 +1,5 @@
+macro_rules! forbidden_frag {
+    ($t:ty $not_block:ident) => {{}}; // { dg-error "fragment specifier .ident. is not allowed after .ty. fragments" }
+                                      // { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-1 }
+                                      // { dg-error "failed to parse item in crate" "" { target *-*-* } .-2 }
+}
diff --git a/gcc/testsuite/rust/compile/macro34.rs b/gcc/testsuite/rust/compile/macro34.rs
new file mode 100644
index 00000000000..105d042fd50
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro34.rs
@@ -0,0 +1,3 @@
+macro_rules! allowed_after_expr_matcher {
+    (($t:expr) bok) => {{}}; // follow-set restrictions do not apply after a matcher, but they do apply inside the matcher
+}
diff --git a/gcc/testsuite/rust/compile/macro35.rs b/gcc/testsuite/rust/compile/macro35.rs
new file mode 100644
index 00000000000..07b157b53c2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro35.rs
@@ -0,0 +1,7 @@
+macro_rules! inside_matcher {
+    (($e:expr tok) tok) => {{}}; // { dg-error "token .identifier. is not allowed after .expr. fragment" }
+                                 // { dg-error "failed to parse macro matcher" "" { target *-*-* } .-1 }
+                                 // { dg-error "failed to parse macro match" "" { target *-*-* } .-2 }
+                                 // { dg-error "required first macro rule" "" { target *-*-* } .-3 }
+                                 // { dg-error "failed to parse item in crate" "" { target *-*-* } .-4 }
+}
diff --git a/gcc/testsuite/rust/compile/macro36.rs b/gcc/testsuite/rust/compile/macro36.rs
new file mode 100644
index 00000000000..e5d66b22b7b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro36.rs
@@ -0,0 +1,3 @@
+macro_rules! ty_allowed {
+    ($t:ty $b:block) => {{}};
+}
diff --git a/gcc/testsuite/rust/compile/macro37.rs b/gcc/testsuite/rust/compile/macro37.rs
new file mode 100644
index 00000000000..5713d90130a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro37.rs
@@ -0,0 +1,5 @@
+macro_rules! invalid_after_zeroable {
+    ($e:expr $(,)* forbidden) => {{}}; // { dg-error "token .identifier. is not allowed after .expr. fragment" }
+                                       // { dg-error "required first macro rule" "" { target *-*-* } .-1 }
+                                       // { dg-error "failed to parse item in crate" "" { target *-*-* } .-2 }
+}
diff --git a/gcc/testsuite/rust/compile/macro38.rs b/gcc/testsuite/rust/compile/macro38.rs
new file mode 100644
index 00000000000..eb294aec83b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro38.rs
@@ -0,0 +1,5 @@
+macro_rules! invalid_after_zeroable_multi {
+    ($e:expr $(,)? $(;)* $(=>)? forbidden) => {{}}; // { dg-error "token .identifier. is not allowed after .expr. fragment" }
+                                                    // { dg-error "required first macro rule" "" { target *-*-* } .-1 }
+                                                    // { dg-error "failed to parse item in crate" "" { target *-*-* } .-2 }
+}
diff --git a/gcc/testsuite/rust/compile/macro39.rs b/gcc/testsuite/rust/compile/macro39.rs
new file mode 100644
index 00000000000..f5c498cc8ef
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro39.rs
@@ -0,0 +1,5 @@
+macro_rules! m {
+    ($e:expr (, parenthesis_forbidden)) => {{}}; // { dg-error "token .\\(. at start of matcher is not allowed after .expr. fragment" }
+                                                 // { dg-error "required first macro rule" "" { target *-*-* } .-1 }
+                                                 // { dg-error "failed to parse item in crate" "" { target *-*-* } .-2 }
+}
diff --git a/gcc/testsuite/rust/compile/macro4.rs b/gcc/testsuite/rust/compile/macro4.rs
new file mode 100644
index 00000000000..47ff6c93d87
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro4.rs
@@ -0,0 +1,3 @@
+macro_rules! one_keyword {
+    (kw) => {};
+}
diff --git a/gcc/testsuite/rust/compile/macro40.rs b/gcc/testsuite/rust/compile/macro40.rs
new file mode 100644
index 00000000000..7151f3a83bc
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro40.rs
@@ -0,0 +1,48 @@
+// { dg-additional-options "-w" }
+
+macro_rules! t {
+    () => {
+        i32
+    };
+}
+
+macro_rules! s {
+    () => {
+        *const i8
+    };
+}
+
+extern "C" {
+    fn printf(s: s!(), ...);
+}
+
+fn square(arg: t!()) -> t!() {
+    let input: t!() = arg;
+
+    input * input
+}
+
+trait Trait {
+    fn f() -> t!();
+    fn g(arg: t!());
+}
+
+struct Wrapper {
+    inner: t!(),
+}
+
+impl Trait for Wrapper {
+    fn f() -> t!() {
+        1
+    }
+
+    fn g(arg: t!()) {}
+}
+
+fn id<T>(arg: T) -> T {
+    arg
+}
+
+fn main() {
+    id::<t!()>(15);
+}
diff --git a/gcc/testsuite/rust/compile/macro41.rs b/gcc/testsuite/rust/compile/macro41.rs
new file mode 100644
index 00000000000..38244222924
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro41.rs
@@ -0,0 +1,13 @@
+macro_rules! empty {
+    ($($t:tt)*) => {};
+}
+
+empty! {nothing}
+empty! {struct OuterItem;}
+empty! {}
+
+fn main() {
+    empty! {as statement};
+    empty! {any child item};
+    empty! {};
+}
diff --git a/gcc/testsuite/rust/compile/macro42.rs b/gcc/testsuite/rust/compile/macro42.rs
new file mode 100644
index 00000000000..52d150b82ba
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro42.rs
@@ -0,0 +1,32 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+#[rustc_builtin_macro]
+macro_rules! cfg {
+    () => {{}};
+}
+
+fn main() -> i32 {
+    let mut res = 0;
+    if cfg!(A) {
+        res = 1;
+    }
+
+    if cfg!(A) {
+        res = 2;
+    } else {
+        res = 3;
+    }
+
+    if cfg!(A) {
+        res = 4;
+    } else if cfg!(A) {
+        res = 5;
+    }
+
+    let res = if cfg!(A) {
+        6
+    } else {
+        7
+    };
+
+    return res;
+}
diff --git a/gcc/testsuite/rust/compile/macro5.rs b/gcc/testsuite/rust/compile/macro5.rs
new file mode 100644
index 00000000000..a5d80952e28
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro5.rs
@@ -0,0 +1,3 @@
+macro_rules! rust_keyword {
+    (fn) => {};
+}
diff --git a/gcc/testsuite/rust/compile/macro6.rs b/gcc/testsuite/rust/compile/macro6.rs
new file mode 100644
index 00000000000..0ca35ba6888
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro6.rs
@@ -0,0 +1,11 @@
+macro_rules! zero_or_one {
+    ($($a:literal)?) => { // { dg-error "invalid amount of matches for macro invocation. Expected between 0 and 1, got 2" }
+        f();
+    }
+}
+
+fn main() {
+    zero_or_one!();
+    zero_or_one!(14);
+    zero_or_one!(125 12 "gcc"); // { dg-error "Failed to match any rule within macro" }
+}
diff --git a/gcc/testsuite/rust/compile/macro7.rs b/gcc/testsuite/rust/compile/macro7.rs
new file mode 100644
index 00000000000..abc48057c54
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro7.rs
@@ -0,0 +1,13 @@
+fn f() {}
+
+macro_rules! one_or_more {
+    ($($a:literal)+) => { // { dg-error "invalid amount of matches for macro invocation" }
+        f();
+    };
+}
+
+fn main() {
+    one_or_more!(1 1 1 1 1 1 1 1 1 1 1 "rust" 'c');
+    one_or_more!(1);
+    one_or_more!(); // { dg-error "Failed to match any rule within macro" }
+}
diff --git a/gcc/testsuite/rust/compile/macro8.rs b/gcc/testsuite/rust/compile/macro8.rs
new file mode 100644
index 00000000000..d3e8af93a6e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro8.rs
@@ -0,0 +1,12 @@
+fn f() {}
+
+macro_rules! expr {
+    ($($a:expr)?) => {
+        f();
+    };
+}
+
+fn main() {
+    expr!();
+    expr!(14);
+}
diff --git a/gcc/testsuite/rust/compile/macro9.rs b/gcc/testsuite/rust/compile/macro9.rs
new file mode 100644
index 00000000000..9a59089b1e4
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro9.rs
@@ -0,0 +1,17 @@
+macro_rules! add {
+    ($e:expr, $($es:expr),*) => {
+        $e + add!($($es),*)
+    };
+    ($e:expr) => {
+        $e
+    };
+}
+
+fn main() -> i32 {
+    let a = add!(15 2 9); // { dg-error "Failed to match any rule within macro" }
+    let b = add!(15);
+    let b = add!(15 14); // { dg-error "Failed to match any rule within macro" }
+    let b = add!(15, 14,); // { dg-error "Failed to match any rule within macro" }
+
+    0
+}
diff --git a/gcc/testsuite/rust/compile/macro_return.rs b/gcc/testsuite/rust/compile/macro_return.rs
new file mode 100644
index 00000000000..8b06f875cc0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro_return.rs
@@ -0,0 +1,10 @@
+// { dg-additional-options "-w" }
+
+macro_rules! add {
+    ($a:expr) => { $a };
+    ($a:expr, $($b:expr),+) => { $a + add!($($b),*) }
+}
+
+fn main() -> i32 {
+    add!(add!(1, 2))
+}
diff --git a/gcc/testsuite/rust/compile/match1.rs b/gcc/testsuite/rust/compile/match1.rs
new file mode 100644
index 00000000000..f649f3a1931
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match1.rs
@@ -0,0 +1,16 @@
+enum Foo {
+    A,
+    B,
+    C(char),
+    D { x: i64, y: i64 },
+}
+
+fn inspect(f: Foo) {
+    match f {
+        Foo::A => {}
+        Foo::B => {}
+        Foo::C(a, b) => {}
+        // { dg-error "this pattern has 2 fields but the corresponding tuple variant has 1 field" "" { target *-*-* } .-1 }
+        Foo::D { x, y } => {}
+    }
+}
diff --git a/gcc/testsuite/rust/compile/match2.rs b/gcc/testsuite/rust/compile/match2.rs
new file mode 100644
index 00000000000..359936a187c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match2.rs
@@ -0,0 +1,15 @@
+enum Foo {
+    A,
+    B,
+    C(char),
+    D { x: i64, y: i64 },
+}
+
+fn inspect(f: Foo) {
+    match f {
+        Foo::A => {}
+        Foo::B => {}
+        Foo::C(x) => {}
+        Foo::D { y } => {} // { dg-error "pattern does not mention fields x" }
+    }
+}
diff --git a/gcc/testsuite/rust/compile/match3.rs b/gcc/testsuite/rust/compile/match3.rs
new file mode 100644
index 00000000000..98181e85197
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match3.rs
@@ -0,0 +1,16 @@
+enum Foo {
+    A,
+    B,
+    C(char),
+    D { x: i64, y: i64 },
+}
+
+fn inspect(f: Foo) {
+    match f {
+        Foo::A => {}
+        Foo::B => {}
+        Foo::C(x) => {}
+        Foo::D { z } => {} // { dg-error "variant D does not have a field named z" }
+                           // { dg-error "pattern does not mention fields x, y" "" { target *-*-* } .-1 }
+    }
+}
diff --git a/gcc/testsuite/rust/compile/match4.rs b/gcc/testsuite/rust/compile/match4.rs
new file mode 100644
index 00000000000..35b90a64fa5
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match4.rs
@@ -0,0 +1,16 @@
+enum Foo {
+    A,
+    B,
+    C(char),
+    D { x: i64, y: i64 },
+}
+
+fn inspect(f: Foo) {
+    match f {
+        Foo::A => {}
+        Foo::B => {}
+        Foo::C { a } => {}
+        // { dg-error "expected struct variant, found tuple variant C" "" { target *-*-* } .-1 }
+        Foo::D { x, y } => {}
+    }
+}
diff --git a/gcc/testsuite/rust/compile/match5.rs b/gcc/testsuite/rust/compile/match5.rs
new file mode 100644
index 00000000000..a5f934d6aeb
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match5.rs
@@ -0,0 +1,15 @@
+enum Foo {
+    A,
+    B,
+    C(char),
+    D { x: i64, y: i64 },
+}
+
+fn inspect(f: Foo) {
+    match f {
+        Foo::A => {}
+        Foo::B => {}
+        Foo::C(a) => {}
+        Foo::D(x, y) => {} // { dg-error "expected tuple struct or tuple variant, found struct variant 'Foo::D'" }
+    }
+}
diff --git a/gcc/testsuite/rust/compile/match6.rs b/gcc/testsuite/rust/compile/match6.rs
new file mode 100644
index 00000000000..8fe06f7c116
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match6.rs
@@ -0,0 +1,18 @@
+fn foo() -> bool {
+    true
+}
+
+fn int32() -> i32 {
+    1
+}
+
+fn bar() -> i32 {
+    match foo() {
+        true => int32(),
+        false => 0
+    }
+}
+
+fn main() -> () {
+    bar();
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/match7.rs b/gcc/testsuite/rust/compile/match7.rs
new file mode 100644
index 00000000000..b16a1883522
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match7.rs
@@ -0,0 +1,12 @@
+fn bar (x: u8, y: u8) -> i32 {
+    match (x, y) {
+        (1, 1) => { return 1; }
+        (1, _) => { return -1; }
+    }
+
+    return 0;
+}
+
+fn main () -> () {
+    bar (1, 2);
+}
diff --git a/gcc/testsuite/rust/compile/method1.rs b/gcc/testsuite/rust/compile/method1.rs
new file mode 100644
index 00000000000..18652406085
--- /dev/null
+++ b/gcc/testsuite/rust/compile/method1.rs
@@ -0,0 +1,13 @@
+struct Foo(i32);
+impl Foo {
+    fn test() {}
+}
+
+pub fn main() {
+    let a;
+    a = Foo(123);
+
+    a.test();
+    // { dg-error "failed to resolve method for .test." "" { target *-*-* } .-1 }
+    // { dg-error {failed to type resolve expression} "" { target *-*-* } .-2 }
+}
diff --git a/gcc/testsuite/rust/compile/method2.rs b/gcc/testsuite/rust/compile/method2.rs
new file mode 100644
index 00000000000..c8699f77c6a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/method2.rs
@@ -0,0 +1,16 @@
+struct Foo<A, B>(A, B);
+
+impl Foo<i32, f32> {
+    fn test<X>(self, a: X) -> X {
+        a
+    }
+}
+
+fn main() {
+    let a;
+    a = Foo(123, 456f32);
+
+    let b;
+    b = a.test::<asfasfr>(false);
+    // { dg-error "failed to resolve TypePath: asfasfr" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/mismatch-crate-name.rs b/gcc/testsuite/rust/compile/mismatch-crate-name.rs
new file mode 100644
index 00000000000..e259b9e46cc
--- /dev/null
+++ b/gcc/testsuite/rust/compile/mismatch-crate-name.rs
@@ -0,0 +1,4 @@
+// { dg-additional-options "-frust-crate=another_name" }
+#![crate_name = "legit_name"]
+// { dg-error ".-frust-crate-name. and .#.crate_name.. are required to match, but .another_name. does not match .legit_name." "" { target *-*-* } .-1 }
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/missing_middle/both_path.rs b/gcc/testsuite/rust/compile/missing_middle/both_path.rs
new file mode 100644
index 00000000000..5e5ad15457a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/missing_middle/both_path.rs
@@ -0,0 +1,3 @@
+pub fn f() -> u32 {
+    5
+}
diff --git a/gcc/testsuite/rust/compile/missing_middle/explicit.not.rs b/gcc/testsuite/rust/compile/missing_middle/explicit.not.rs
new file mode 100644
index 00000000000..e28288b0f99
--- /dev/null
+++ b/gcc/testsuite/rust/compile/missing_middle/explicit.not.rs
@@ -0,0 +1 @@
+mod other;
diff --git a/gcc/testsuite/rust/compile/missing_middle/inner_path.rs b/gcc/testsuite/rust/compile/missing_middle/inner_path.rs
new file mode 100644
index 00000000000..daf4e3cc25a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/missing_middle/inner_path.rs
@@ -0,0 +1,3 @@
+pub fn f() -> u32 {
+    4
+}
diff --git a/gcc/testsuite/rust/compile/missing_middle/other.rs b/gcc/testsuite/rust/compile/missing_middle/other.rs
new file mode 100644
index 00000000000..0c0884ec968
--- /dev/null
+++ b/gcc/testsuite/rust/compile/missing_middle/other.rs
@@ -0,0 +1,3 @@
+pub fn f() -> u32 {
+    2
+}
diff --git a/gcc/testsuite/rust/compile/missing_middle/outer_path.rs b/gcc/testsuite/rust/compile/missing_middle/outer_path.rs
new file mode 100644
index 00000000000..fbe5074191b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/missing_middle/outer_path.rs
@@ -0,0 +1,3 @@
+pub fn f() -> u32 {
+    3
+}
diff --git a/gcc/testsuite/rust/compile/missing_middle/sub/mod.rs b/gcc/testsuite/rust/compile/missing_middle/sub/mod.rs
new file mode 100644
index 00000000000..f099d61e04a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/missing_middle/sub/mod.rs
@@ -0,0 +1,3 @@
+pub fn f() -> u32 {
+    1
+}
diff --git a/gcc/testsuite/rust/compile/missing_return1.rs b/gcc/testsuite/rust/compile/missing_return1.rs
new file mode 100644
index 00000000000..00bf393dbb9
--- /dev/null
+++ b/gcc/testsuite/rust/compile/missing_return1.rs
@@ -0,0 +1,6 @@
+// { dg-error "expected .* got .*" "" { target *-*-* } 0 }
+fn test1() -> i32 {}
+
+fn main() {
+    let call1 = test1();
+}
diff --git a/gcc/testsuite/rust/compile/mod_missing_middle.rs b/gcc/testsuite/rust/compile/mod_missing_middle.rs
new file mode 100644
index 00000000000..79633407671
--- /dev/null
+++ b/gcc/testsuite/rust/compile/mod_missing_middle.rs
@@ -0,0 +1,29 @@
+// { dg-additional-options "-w" }
+
+mod missing_middle {
+    mod sub;
+
+    #[path = "explicit.not.rs"]
+    mod explicit;
+}
+
+#[path = "missing_middle"]
+mod with_outer_path_attr {
+    #[path = "outer_path.rs"]
+    mod inner;
+}
+
+mod with_inner_path_attr {
+    #![path = "missing_middle"]
+
+    #[path = "inner_path.rs"]
+    mod inner;
+}
+
+#[path = "missing_middle"]
+mod with_both_path_attr {
+    #![path = "this_is_ignored"]
+
+    #[path = "both_path.rs"]
+    mod inner;
+}
diff --git a/gcc/testsuite/rust/compile/never_type_err1.rs b/gcc/testsuite/rust/compile/never_type_err1.rs
new file mode 100644
index 00000000000..52b1283fadf
--- /dev/null
+++ b/gcc/testsuite/rust/compile/never_type_err1.rs
@@ -0,0 +1,14 @@
+fn test() {
+    let a;
+
+    // FIXME: Unimplemented features
+    a = if true { // { dg-error "expected .T.. got .!." }
+        return;
+    } else {
+        return;
+    };
+}
+
+fn main() {
+    test();
+}
diff --git a/gcc/testsuite/rust/compile/privacy1.rs b/gcc/testsuite/rust/compile/privacy1.rs
new file mode 100644
index 00000000000..1cc83c04abe
--- /dev/null
+++ b/gcc/testsuite/rust/compile/privacy1.rs
@@ -0,0 +1,11 @@
+mod orange {
+    mod green {
+        fn sain() {}
+        pub fn doux() {}
+    }
+
+    fn brown() {
+        green::sain(); // { dg-error "definition is private in this context" }
+        green::doux();
+    }
+}
diff --git a/gcc/testsuite/rust/compile/privacy2.rs b/gcc/testsuite/rust/compile/privacy2.rs
new file mode 100644
index 00000000000..3c0744928b1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/privacy2.rs
@@ -0,0 +1,13 @@
+// { dg-additional-options "-w" }
+
+mod orange {
+    fn tangerine() {}
+
+    mod green {
+        mod blue {
+            fn berry() {
+                tangerine();
+            }
+        }
+    }
+}
diff --git a/gcc/testsuite/rust/compile/privacy3.rs b/gcc/testsuite/rust/compile/privacy3.rs
new file mode 100644
index 00000000000..d48acea4786
--- /dev/null
+++ b/gcc/testsuite/rust/compile/privacy3.rs
@@ -0,0 +1,28 @@
+mod orange {
+    mod green {
+        fn sain_void() {}
+        fn sain() -> bool {
+            false
+        }
+        pub fn doux() {}
+    }
+
+    fn brown() {
+        if green::sain() {
+            // { dg-error "definition is private in this context" "" { target *-*-* } .-1 }
+            green::doux();
+        }
+
+        {
+            green::sain();
+            // { dg-error "definition is private in this context" "" { target *-*-* } .-1 }
+            green::sain();
+            // { dg-error "definition is private in this context" "" { target *-*-* } .-1 }
+            green::sain_void()
+            // { dg-error "definition is private in this context" "" { target *-*-* } .-1 }
+        }
+
+        let a = green::sain();
+        // { dg-error "definition is private in this context" "" { target *-*-* } .-1 }
+    }
+}
diff --git a/gcc/testsuite/rust/compile/privacy4.rs b/gcc/testsuite/rust/compile/privacy4.rs
new file mode 100644
index 00000000000..d1ce0afd654
--- /dev/null
+++ b/gcc/testsuite/rust/compile/privacy4.rs
@@ -0,0 +1,19 @@
+mod orange {
+    mod green {
+        fn bean<T>(value: T) -> T {
+            value
+        }
+    }
+
+    fn brown() {
+        green::bean::<bool>(false);
+        // { dg-error "definition is private in this context" "" { target *-*-* } .-1 }
+        let a = green::bean::<i32>(15);
+        // { dg-error "definition is private in this context" "" { target *-*-* } .-1 }
+
+        struct S;
+
+        let s = green::bean(S);
+        // { dg-error "definition is private in this context" "" { target *-*-* } .-1 }
+    }
+}
diff --git a/gcc/testsuite/rust/compile/privacy5.rs b/gcc/testsuite/rust/compile/privacy5.rs
new file mode 100644
index 00000000000..0e0e496dde2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/privacy5.rs
@@ -0,0 +1,17 @@
+mod orange {
+    mod green {
+        struct Foo;
+        pub(in orange) struct Bar;
+        pub struct Baz;
+    }
+
+    fn brown() {
+        let _ = green::Foo; // { dg-error "definition is private in this context" }
+        let _ = green::Bar;
+        let _ = green::Baz;
+
+        let _: green::Foo; // { dg-error "definition is private in this context" }
+
+        fn any(a0: green::Foo, a1: green::Bar) {} // { dg-error "20:definition is private in this context" }
+    }
+}
diff --git a/gcc/testsuite/rust/compile/privacy6.rs b/gcc/testsuite/rust/compile/privacy6.rs
new file mode 100644
index 00000000000..487ed024209
--- /dev/null
+++ b/gcc/testsuite/rust/compile/privacy6.rs
@@ -0,0 +1,39 @@
+// { dg-additional-options "-w" }
+
+struct Adt;
+enum EAdt {
+    V0,
+    V1,
+}
+struct Registers {
+    r0: i64,
+    r1: i64,
+    r2: i64,
+    r3: i64,
+}
+trait Foo {}
+
+fn foo1(value: bool) {}
+fn foo2(value: char) {}
+fn foo3(value: i32) {}
+fn foo4(value: u16) {}
+fn foo5(value: f64) {}
+fn foo6(value: usize) {}
+fn foo7(value: isize) {}
+fn foo8(value: Adt) {}
+fn foo9(value: EAdt) {}
+fn foo10(value: &str) {}
+fn foo11(value: *const i8) {}
+fn foo12<T>(value: T) {}
+fn foo13(value: [i32; 5]) {}
+fn foo14(value: [Adt]) {}
+fn foo15(value: fn(i32) -> i32) {}
+fn foo16(value: (i32, Adt)) {}
+fn foo17(value: (i32, [f64; 5])) {}
+fn foo18(value: Registers) {}
+fn foo19(value: &dyn Foo) {}
+fn foo20(value: &[Adt]) {}
+// FIXME: Uncomment once #1257 is fixed
+// fn foo21(value: fn(i32)) {}
+// fn foo22(value: fn()) {}
+fn foo23(value: fn() -> i32) {}
diff --git a/gcc/testsuite/rust/compile/pub_restricted_1.rs b/gcc/testsuite/rust/compile/pub_restricted_1.rs
new file mode 100644
index 00000000000..9bda9682403
--- /dev/null
+++ b/gcc/testsuite/rust/compile/pub_restricted_1.rs
@@ -0,0 +1,13 @@
+pub mod foo {
+    pub mod bar {
+        pub fn baz() {}
+
+        pub(in foo::bar) struct A0;
+    }
+}
+
+pub(in foo::fah::baz) struct A1; // { dg-error "cannot find simple path segment .fah." }
+pub(in fro::bulator::saindoux) struct A2; // { dg-error "cannot find simple path segment .fro." }
+pub(in foo::bar::saindoux) struct A3; // { dg-error "cannot find simple path segment .saindoux." }
+
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/pub_restricted_2.rs b/gcc/testsuite/rust/compile/pub_restricted_2.rs
new file mode 100644
index 00000000000..8588f2775ca
--- /dev/null
+++ b/gcc/testsuite/rust/compile/pub_restricted_2.rs
@@ -0,0 +1,18 @@
+// { dg-additional-options "-w" }
+
+mod foo {
+    mod bar {
+        mod baz {
+            pub(in baz) struct A0;
+            pub(in bar::baz) struct A1;
+            pub(in foo::bar::baz) struct A2;
+
+            mod sain {
+                mod doux {}
+            }
+
+            pub(in sain) struct A3; // { dg-error "restricted path is not an ancestor of the current module" }
+            pub(in sain::doux) struct A4; // { dg-error "restricted path is not an ancestor of the current module" }
+        }
+    }
+}
diff --git a/gcc/testsuite/rust/compile/pub_restricted_3.rs b/gcc/testsuite/rust/compile/pub_restricted_3.rs
new file mode 100644
index 00000000000..d477385d761
--- /dev/null
+++ b/gcc/testsuite/rust/compile/pub_restricted_3.rs
@@ -0,0 +1,11 @@
+// { dg-additional-options "-w" }
+
+mod foo {
+    mod bar {
+        pub(in foo) fn baz() {}
+    }
+
+    fn baz() {
+        bar::baz(); // no error, foo::bar::baz is public in foo
+    }
+}
diff --git a/gcc/testsuite/rust/compile/raw_identifiers_bad_keywords.rs b/gcc/testsuite/rust/compile/raw_identifiers_bad_keywords.rs
new file mode 100644
index 00000000000..854d7e6edee
--- /dev/null
+++ b/gcc/testsuite/rust/compile/raw_identifiers_bad_keywords.rs
@@ -0,0 +1,3 @@
+pub fn plus(n: i32, m: i32) -> i32 {
+    r#crate /* { dg-error "forbidden raw identifier" } */
+}
diff --git a/gcc/testsuite/rust/compile/raw_identifiers_underscore.rs b/gcc/testsuite/rust/compile/raw_identifiers_underscore.rs
new file mode 100644
index 00000000000..86e9013a50b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/raw_identifiers_underscore.rs
@@ -0,0 +1,3 @@
+pub fn s(num: i32) -> i32 {
+    r#_ * num /* { dg-error "not a valid raw identifier" } */
+}
diff --git a/gcc/testsuite/rust/compile/rawbytestring.rs b/gcc/testsuite/rust/compile/rawbytestring.rs
new file mode 100644
index 0000000000000000000000000000000000000000..9c6b762a7fd378206a3bfe21db5b708890f5466f
GIT binary patch
literal 3234
zcmbVOO>fgc5amjL#mG4T6)1rVl`5`1a^M^Zc^f;m2zI;c($Wfvf5=~A-pqd4PU65Z
z<9Tmp-n`vS-O~56Y3cQwv*$CS<&wUX59E5=v|Go4UDeZ9>ni$0wkR&M$OnWLi=tR8
zvhYe0>#n0kp8Z~u3yqU0ZIOclm4066_dMaIdKBLE<JDDhNy~HEHGO5v9U=0T+ODUv
zC8SmEy1cFEe3@FkZM6EI->90VG(Y=lGOCeT&0tuLp+z$p*Er0}$>V{I!^8|YFtTxx
z@X*l4>D0{rUt=35bE5|t9J_s{&GuboZD*<I?tAKLvSqui3i{=Bxx4RJ6csV<pY3qx
zc%EYYDlHYkjRXh2@TuH1=aM+;Gqyvv;&mx;T8-!69@lIn-t3a5*&*G8KFpvI38NDZ
zXRR0;(@$zf^Mz-&9d5I9*G<Ew+mP5OSua;jH^}=FDaIRU+8^bv*+6`M(70oU!0U_=
z&}eCgAm&LiE1Ztuo)19+f+2(Qu2!m#_4vb;|G-CZh`7Kh;Epf$lpotHpVZa9RxPJ`
z*!LJ1N@A_5D-K2!c50h=c|}nH2&&HIi=qJdndb5#r=*{jFDfG+GVizjpnnJPCErUm
z(~py#01%ck2asI=5SB3ogcab#=?eJBr4{72%hYuq1akuw_HYtNmI2frgB`4tK#Ur;
zF6x6XH@P+_Ld&Pj=Khmtif_<#%m^#v8|1@fDley8DqbpRJ8##35S;)CLQU5(s-g1&
zGH1b11D=)VWpyG#bwi0++xi+Rry%Bx8xX28AhXsD5b>@|GH+hjmxkvqUg|FRiNY&&
zP6(%e4anlh3W@7JWKOd9E)p`E*!Jfr70=|kILq??taYC%vd4tW9O052<zlNPu3_&s
zQXTCpCkvg$z92;~u`^Cz|8;Ub$4U{W)axrh#`o>FwtHy(W1l^5)-!Q6rkeY2pcOb5
zC5~Q^#`Cf!S&N9GM~?nelacMDHe;2ejYcV-D%(M~7r|5FJ&7hOIQ$Oo!_o8>9i>^x
zV>X-Uc!7Jfq5+jI?0J=nn!sj`v1wMcU}PH?O>D8bJ*^GcSU|ak{Lxs!g8aAiFN}Pz
A0RR91

literal 0
HcmV?d00001

diff --git a/gcc/testsuite/rust/compile/redef_error1.rs b/gcc/testsuite/rust/compile/redef_error1.rs
new file mode 100644
index 00000000000..ae51e36c87f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/redef_error1.rs
@@ -0,0 +1,8 @@
+struct S1 {
+    x: f64,
+    y: f64,
+}
+
+struct S1(i32, bool); // { dg-error "redefined multiple times" }
+
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/redef_error2.rs b/gcc/testsuite/rust/compile/redef_error2.rs
new file mode 100644
index 00000000000..65793bcda8a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/redef_error2.rs
@@ -0,0 +1,4 @@
+const TEST: i32 = 2;
+const TEST: f32 = 3.0; // { dg-error "redefined multiple times" }
+
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/redef_error3.rs b/gcc/testsuite/rust/compile/redef_error3.rs
new file mode 100644
index 00000000000..a4bf1ed3d8c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/redef_error3.rs
@@ -0,0 +1,9 @@
+fn test() -> bool {
+    true
+}
+
+fn test() -> i32 { // { dg-error "redefined multiple times" }
+    123
+}
+
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/redef_error4.rs b/gcc/testsuite/rust/compile/redef_error4.rs
new file mode 100644
index 00000000000..a250c0ac00e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/redef_error4.rs
@@ -0,0 +1,27 @@
+struct Foo(i32, bool);
+
+impl Foo {
+    fn new(a: i32, b: bool) -> Foo {
+        Foo(a, b)
+    }
+
+    fn test() -> i32 {
+        test()
+    }
+
+    fn test() -> bool { // { dg-error "redefined multiple times" }
+        true
+    }
+}
+
+fn test() -> i32 {
+    123
+}
+
+fn main() {
+    let a;
+    a = Foo::new(1, true);
+
+    let b;
+    b = Foo::test();
+}
diff --git a/gcc/testsuite/rust/compile/redef_error5.rs b/gcc/testsuite/rust/compile/redef_error5.rs
new file mode 100644
index 00000000000..dc6ad50e104
--- /dev/null
+++ b/gcc/testsuite/rust/compile/redef_error5.rs
@@ -0,0 +1,8 @@
+struct Foo(i32, bool);
+
+impl Foo {
+    const TEST: i32 = 123;
+    const TEST: bool = false; // { dg-error "redefined multiple times"  }
+}
+
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/redef_error6.rs b/gcc/testsuite/rust/compile/redef_error6.rs
new file mode 100644
index 00000000000..664c6ae9894
--- /dev/null
+++ b/gcc/testsuite/rust/compile/redef_error6.rs
@@ -0,0 +1,13 @@
+struct Foo<T>(T, usize);
+
+impl Foo<i32> {
+    fn test() -> i32 {
+        123
+    }
+
+    fn test(self) -> i32 { // { dg-error "redefined multiple times" }
+        self.0
+    }
+}
+
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/reference1.rs b/gcc/testsuite/rust/compile/reference1.rs
new file mode 100644
index 00000000000..ff791533754
--- /dev/null
+++ b/gcc/testsuite/rust/compile/reference1.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let a = &123;
+    let b: &mut i32 = a;
+    // { dg-error "mismatched mutability" "" { target *-*-* } .-1 }
+    // { dg-error "expected .&mut i32. got .& i32." "" { target *-*-* } .-2 }
+}
diff --git a/gcc/testsuite/rust/compile/self-path1.rs b/gcc/testsuite/rust/compile/self-path1.rs
new file mode 100644
index 00000000000..425ba848fc0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/self-path1.rs
@@ -0,0 +1,12 @@
+// { dg-additional-options "-w" }
+struct foo;
+
+fn bar() -> self::foo {
+    crate::foo
+}
+
+fn baz() {
+    let a: foo = self::bar();
+
+    crate::bar();
+}
diff --git a/gcc/testsuite/rust/compile/self-path2.rs b/gcc/testsuite/rust/compile/self-path2.rs
new file mode 100644
index 00000000000..b9b82cae5a6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/self-path2.rs
@@ -0,0 +1,21 @@
+// { dg-additional-options "-w" }
+struct foo;
+
+fn bar() -> self::foo {
+    crate::foo
+}
+
+fn baz() {
+    let a: foo = self::bar();
+
+    crate::bar();
+
+    crate::self::foo();
+    // { dg-error "failed to resolve: .self. in paths can only be used in start position" "" { target *-*-* } .-1 }
+}
+
+type a = foo;
+type b = crate::foo;
+type c = self::foo;
+type d = crate::self::foo;
+// { dg-error "failed to resolve: .self. in paths can only be used in start position" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/rust/compile/shadow1.rs b/gcc/testsuite/rust/compile/shadow1.rs
new file mode 100644
index 00000000000..77410e932da
--- /dev/null
+++ b/gcc/testsuite/rust/compile/shadow1.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let mut x = 5;
+    let mut x;
+    x = true;
+    x = x + 2; // { dg-error "cannot apply this operator to types bool and <integer>"  }
+               // { dg-error {failed to type resolve expression} "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/specify-crate-name.rs b/gcc/testsuite/rust/compile/specify-crate-name.rs
new file mode 100644
index 00000000000..a8679157024
--- /dev/null
+++ b/gcc/testsuite/rust/compile/specify-crate-name.rs
@@ -0,0 +1,7 @@
+// { dg-additional-options "-frust-crate=fancy_crate_name -fdump-tree-gimple" }
+pub fn does_nothing() {}
+fn main() {
+    does_nothing()
+}
+// { dg-final { scan-tree-dump-times {fancy_crate_name::does_nothing} 2 gimple } }
+// { dg-final { scan-tree-dump-times {fancy_crate_name::main} 1 gimple } }
diff --git a/gcc/testsuite/rust/compile/static_var1.rs b/gcc/testsuite/rust/compile/static_var1.rs
new file mode 100644
index 00000000000..b3b5751c932
--- /dev/null
+++ b/gcc/testsuite/rust/compile/static_var1.rs
@@ -0,0 +1,5 @@
+static x = 3; // { dg-error "expecting ':' but '=' found" }
+
+fn main() {// { dg-error "failed to parse item in crate" }
+    let y = x +1;
+}
diff --git a/gcc/testsuite/rust/compile/stmt_with_block_err1.rs b/gcc/testsuite/rust/compile/stmt_with_block_err1.rs
new file mode 100644
index 00000000000..8780d0feeac
--- /dev/null
+++ b/gcc/testsuite/rust/compile/stmt_with_block_err1.rs
@@ -0,0 +1,17 @@
+fn test(x: i32) -> i32 {
+    if x > 1 { // { dg-error "expected .... got .<integer>." }
+        1
+    } else {
+        2
+    }
+
+    { // { dg-error "expected .... got .<integer>." }
+        3
+    }
+
+    3
+}
+
+fn main() {
+    let a = test(0);
+}
diff --git a/gcc/testsuite/rust/compile/struct_align1.rs b/gcc/testsuite/rust/compile/struct_align1.rs
new file mode 100644
index 00000000000..22eb6bc80fb
--- /dev/null
+++ b/gcc/testsuite/rust/compile/struct_align1.rs
@@ -0,0 +1,19 @@
+#[repr(align(8))]
+struct Foo {
+    x: i16,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+    y: i8,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+    z: i32,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+#[repr(align(8))]
+struct Bar(i8, i32);
+
+fn main () {
+    let f = Foo { x: 5, y: 2, z: 13 };
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let b = Bar (7, 262);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/struct_align2.rs b/gcc/testsuite/rust/compile/struct_align2.rs
new file mode 100644
index 00000000000..ac490643a36
--- /dev/null
+++ b/gcc/testsuite/rust/compile/struct_align2.rs
@@ -0,0 +1,18 @@
+
+fn main () {
+
+    #[repr(align(8))]
+    struct Baz {
+        x: u16,
+        y: u32,
+    };
+
+    #[repr(align(4))]
+    struct Qux (u8, i16);
+
+    let b = Baz { x: 5, y: 1984 };
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let c = Qux (1, 2);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/struct_init1.rs b/gcc/testsuite/rust/compile/struct_init1.rs
new file mode 100644
index 00000000000..1875fb4f33e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/struct_init1.rs
@@ -0,0 +1,10 @@
+struct Foo {
+    a: f32,
+    b: f32,
+}
+
+fn main() {
+    let a = Foo { 0: 10.0, 1: 20.0 }; // { dg-error "failed to resolve type for field" }
+    // { dg-error "unknown field" "" { target *-*-* } .-1 }
+    // { dg-prune-output "compilation terminated" }
+}
diff --git a/gcc/testsuite/rust/compile/struct_pack1.rs b/gcc/testsuite/rust/compile/struct_pack1.rs
new file mode 100644
index 00000000000..eb9d879c1dc
--- /dev/null
+++ b/gcc/testsuite/rust/compile/struct_pack1.rs
@@ -0,0 +1,19 @@
+#[repr(packed(2))]
+struct Foo {
+    x: i16,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+    y: i8,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+    z: i32,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+#[repr(packed)]
+struct Bar(i8, i32);
+
+fn main () {
+    let f = Foo { x: 5, y: 2, z: 13 };
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let b = Bar (7, 262);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/struct_pack2.rs b/gcc/testsuite/rust/compile/struct_pack2.rs
new file mode 100644
index 00000000000..e5f74c20bb0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/struct_pack2.rs
@@ -0,0 +1,18 @@
+
+fn main () {
+
+    #[repr(packed(2))]
+    struct Baz {
+        x: u16,
+        y: u32,
+    };
+
+    #[repr(packed)]
+    struct Qux (u8, i16);
+
+    let b = Baz { x: 5, y: 1984 };
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let c = Qux (1, 2);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/syntax-only.rs b/gcc/testsuite/rust/compile/syntax-only.rs
new file mode 100644
index 00000000000..cd84907bf84
--- /dev/null
+++ b/gcc/testsuite/rust/compile/syntax-only.rs
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fsyntax-only" }
+
+fn main() {
+    let mut a = 15;
+    a = true;
+}
diff --git a/gcc/testsuite/rust/compile/test_mod.rs b/gcc/testsuite/rust/compile/test_mod.rs
new file mode 100644
index 00000000000..4b3c000236b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/test_mod.rs
@@ -0,0 +1,6 @@
+//! test_mod inner doc comment
+//!
+//! foo bar baz cake pizza carbs
+
+pub struct Test(pub i32);
+// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/rust/compile/torture/all_doc_comment_line_blocks.rs b/gcc/testsuite/rust/compile/torture/all_doc_comment_line_blocks.rs
new file mode 100644
index 00000000000..b7368ba29ee
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/all_doc_comment_line_blocks.rs
@@ -0,0 +1,45 @@
+// comment line not a doc
+/* comment block not a doc                   */
+
+//! inner line comment for most outer crate
+/*! inner block comment for most outer crate */
+
+// comment line not a doc
+/* comment block not a doc                   */
+
+/// outer doc line for module
+/** outer doc block for module               */
+pub mod module {
+    //!  inner line doc
+    //!! inner line doc!
+    /*!  inner block doc  */
+    /*!! inner block doc! */
+
+    //   line comment
+    ///  outer line doc
+    //// line comment
+
+    /*   block comment   */
+    /**  outer block doc */
+    /*** block comment   */
+
+    mod block_doc_comments {
+        /*   /* */  /** */  /*! */  */
+        /*!  /* */  /** */  /*! */  */
+        /**  /* */  /** */  /*! */  */
+        mod item {}
+    }
+
+    pub mod empty {
+        //!
+        /*!*/
+        //
+
+        ///
+        // the following warning is issued one line earlier
+        mod doc {}
+        /**/
+        /***/
+    }
+}
+pub fn main() {}
diff --git a/gcc/testsuite/rust/compile/torture/all_doc_comment_line_blocks_crlf.rs b/gcc/testsuite/rust/compile/torture/all_doc_comment_line_blocks_crlf.rs
new file mode 100644
index 00000000000..9f2f2207397
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/all_doc_comment_line_blocks_crlf.rs
@@ -0,0 +1,48 @@
+// comment line not a doc
+/* comment block not a doc                   */
+
+//! inner line comment for most outer crate
+/*! inner block comment for most outer crate */
+
+// comment line not a doc
+/* comment block not a doc                   */
+
+/// outer doc line for module
+/** outer doc block for module               */
+pub mod module
+{
+  //!  inner line doc
+  //!! inner line doc!
+  /*!  inner block doc  */
+  /*!! inner block doc! */
+
+  //   line comment
+  ///  outer line doc
+  //// line comment
+
+  /*   block comment   */
+  /**  outer block doc */
+  /*** block comment   */
+
+  mod block_doc_comments
+  {
+    /*   /* */  /** */  /*! */  */
+    /*!  /* */  /** */  /*! */  */
+    /**  /* */  /** */  /*! */  */
+    mod item { }
+  }
+
+  pub mod empty
+  {
+    //!
+    /*!*/
+    //
+
+    ///
+    mod doc { }
+
+    /**/
+    /***/
+  }
+}
+pub fn main () { }
diff --git a/gcc/testsuite/rust/compile/torture/arithmetic_expressions1.rs b/gcc/testsuite/rust/compile/torture/arithmetic_expressions1.rs
new file mode 100644
index 00000000000..4c3ee77c835
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/arithmetic_expressions1.rs
@@ -0,0 +1,30 @@
+// { dg-prune-output "warning: unused name" } as there are many of these expected.
+
+fn main() {
+    let a: i32 = 1;
+    let b: f32 = 5f32;
+    let c: bool = true;
+
+    let a1: i32 = a + 1;
+    let a2: i32 = a - 2;
+    let a3: i32 = a * 3;
+    let a4: i32 = a / 4;
+    let a5: i32 = a % 5;
+
+    let b1: f32 = b + 1f32;
+    let b2: f32 = b - 2f32;
+    let b3: f32 = b * 3f32;
+    let b4: f32 = b / 4f32;
+    // let b5: f32 = b % 5f32;
+
+    let aa1: i32 = a & 1;
+    let aa2: i32 = a | 2;
+    let aa2: i32 = a ^ 3;
+
+    let c1: bool = c & true;
+    let c2: bool = c | false;
+    let c3: bool = c ^ true;
+
+    let aaa1: i32 = a << 1;
+    let aaa2: i32 = a >> 2;
+}
diff --git a/gcc/testsuite/rust/compile/torture/array_const_fold_1.rs b/gcc/testsuite/rust/compile/torture/array_const_fold_1.rs
new file mode 100644
index 00000000000..e45c9389c93
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/array_const_fold_1.rs
@@ -0,0 +1,2 @@
+const TEST: [i32; 16] = [2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8];
+// { dg-warning "unused name" "" { target *-*-* } .-1 }
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/torture/array_const_fold_2.rs b/gcc/testsuite/rust/compile/torture/array_const_fold_2.rs
new file mode 100644
index 00000000000..b42a68e5ddb
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/array_const_fold_2.rs
@@ -0,0 +1,3 @@
+const SIZE: usize = 14 + 2;
+const TEST: [i32; SIZE] = [2; SIZE];
+// { dg-warning "unused name" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/rust/compile/torture/array_function.rs b/gcc/testsuite/rust/compile/torture/array_function.rs
new file mode 100644
index 00000000000..4e2b2e03f31
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/array_function.rs
@@ -0,0 +1,8 @@
+fn foo() -> i32 {
+    1
+}
+
+
+fn main() {
+    let _a: [i32; 1] = [foo()];
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/torture/array_type_infer.rs b/gcc/testsuite/rust/compile/torture/array_type_infer.rs
new file mode 100644
index 00000000000..6f21bf2420c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/array_type_infer.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let arr: [_; 5] = [1, 2, 3, 4, 5];
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/array_zero_length.rs b/gcc/testsuite/rust/compile/torture/array_zero_length.rs
new file mode 100644
index 00000000000..3155b1c48c0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/array_zero_length.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let arr = ["Hello"; 0];
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/arrays1.rs b/gcc/testsuite/rust/compile/torture/arrays1.rs
new file mode 100644
index 00000000000..7250e0fa2af
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/arrays1.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let xs: [i32; 5] = [1, 2, 3, 4, 5];
+    let xy = [6, 7, 8];
+
+    let a = xs[0];
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let b = xy[2];
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/arrays2.rs b/gcc/testsuite/rust/compile/torture/arrays2.rs
new file mode 100644
index 00000000000..55491f34524
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/arrays2.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let mut array: [i32; 3] = [0; 3];
+
+    let a = array[0];
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let mut c;
+    c = array[2];
+}
diff --git a/gcc/testsuite/rust/compile/torture/arrays3.rs b/gcc/testsuite/rust/compile/torture/arrays3.rs
new file mode 100644
index 00000000000..372d969aa07
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/arrays3.rs
@@ -0,0 +1,6 @@
+const TEST: usize = 6;
+
+fn main() {
+    let a: [_; 12] = [123; TEST * 2];
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/arrays4.rs b/gcc/testsuite/rust/compile/torture/arrays4.rs
new file mode 100644
index 00000000000..ac317fedf44
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/arrays4.rs
@@ -0,0 +1,6 @@
+const TEST: usize = 4;
+
+fn main() {
+    let a: [_; TEST + 1 + 2] = [123; 7];
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/arrays5.rs b/gcc/testsuite/rust/compile/torture/arrays5.rs
new file mode 100644
index 00000000000..58950a17a15
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/arrays5.rs
@@ -0,0 +1,6 @@
+
+// Checks that we don't try to allocate a 4TB array during compilation
+fn main () {
+    let x = [0; 4 * 1024 * 1024 * 1024 * 1024];
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/arrays6.rs b/gcc/testsuite/rust/compile/torture/arrays6.rs
new file mode 100644
index 00000000000..c7212d3f183
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/arrays6.rs
@@ -0,0 +1,10 @@
+
+// Checks that we don't try to allocate a 4TB array during compilation
+fn foo() -> [u8; 4 * 1024 * 1024 * 1024 * 1024] {
+    [0; 4 * 1024 * 1024 * 1024 * 1024]
+}
+
+fn main () {
+    let x = foo ();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/arrays_index1.rs b/gcc/testsuite/rust/compile/torture/arrays_index1.rs
new file mode 100644
index 00000000000..1fe5de91bcf
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/arrays_index1.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let mut array: [i32; 3] = [0; 3];
+
+    let a = array[0];
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let x = 0;
+    let mut c;
+    c = array[x+1];
+}
diff --git a/gcc/testsuite/rust/compile/torture/arrays_index2.rs b/gcc/testsuite/rust/compile/torture/arrays_index2.rs
new file mode 100644
index 00000000000..f9bee7748ee
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/arrays_index2.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let mut array: [i32; 3] = [0; 3];
+    array[0] = 1;
+}
diff --git a/gcc/testsuite/rust/compile/torture/arrays_index3.rs b/gcc/testsuite/rust/compile/torture/arrays_index3.rs
new file mode 100644
index 00000000000..8fa0a226d02
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/arrays_index3.rs
@@ -0,0 +1,15 @@
+fn foo() -> usize {
+    1
+}
+    
+fn bar() -> [i32; 1] {
+    [0]
+}
+    
+    
+        
+fn main() -> () {
+    let a = [10];
+    let _b = a[foo()];
+    let _c = bar()[foo()];
+}
diff --git a/gcc/testsuite/rust/compile/torture/as_bool_char.rs b/gcc/testsuite/rust/compile/torture/as_bool_char.rs
new file mode 100644
index 00000000000..d687499384a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/as_bool_char.rs
@@ -0,0 +1,36 @@
+extern "C" { fn abort (); }
+
+pub fn main ()
+{
+  let t = true;
+  let f = false;
+  let one = t as u8;
+  let zero = f as u8;
+
+  if one != 1 || zero != 0 { unsafe { abort (); } }
+
+  let isizeone = true as isize;
+  let usizezero = false as usize;
+
+  if isizeone != 1 || usizezero != 0 { unsafe { abort (); } }
+
+  let i32zero = f as i32;
+  let u128one = t as u128;
+
+  if u128one != 1 || i32zero != 0 { unsafe { abort (); } }
+
+  let a = 'a';
+  let b = 'b';
+  let ua = a as u8;
+  let ib = b as i32;
+
+  if (ua + 1) as i32 != ib { unsafe { abort (); } }
+
+  let tt = ua;
+  let aa = tt as char;
+
+  let ttt = tt + 1;
+  let ab = ttt as char;
+
+  if aa != 'a' || ab != 'b' { unsafe { abort (); } }
+}
diff --git a/gcc/testsuite/rust/compile/torture/associated_types1.rs b/gcc/testsuite/rust/compile/torture/associated_types1.rs
new file mode 100644
index 00000000000..bf181df7045
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/associated_types1.rs
@@ -0,0 +1,12 @@
+pub trait Foo {
+    type A;
+
+    fn boo(&self) -> <Self as Foo>::A;
+}
+
+fn foo2<I: Foo>(x: I) {
+    // { dg-warning "function is never used: .foo2." "" { target *-*-* } .-1 }
+    x.boo();
+}
+
+pub fn main() {}
diff --git a/gcc/testsuite/rust/compile/torture/autoderef1.rs b/gcc/testsuite/rust/compile/torture/autoderef1.rs
new file mode 100644
index 00000000000..0cf070f1f37
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/autoderef1.rs
@@ -0,0 +1,15 @@
+struct Foo(i32, bool);
+struct Bar {
+    a: i32,
+    b: bool,
+}
+
+fn main() {
+    let a = &Foo(123, false);
+    let _b: i32 = a.0;
+    let _c: bool = a.1;
+
+    let a = &Bar { a: 456, b: false };
+    let _b: i32 = a.a;
+    let _c: bool = a.b;
+}
diff --git a/gcc/testsuite/rust/compile/torture/block_expr1.rs b/gcc/testsuite/rust/compile/torture/block_expr1.rs
new file mode 100644
index 00000000000..011cc1fc89d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/block_expr1.rs
@@ -0,0 +1,29 @@
+fn test3(x: i32) -> i32 {
+    if x > 1 {
+        5
+    } else {
+        0
+    }
+}
+
+fn test5(x: i32) -> i32 {
+    if x > 1 {
+        if x == 5 {
+            7
+        } else {
+            9
+        }
+    } else {
+        0
+    }
+}
+
+fn main() {
+    let call3: i32 = { test3(3) + 2 };
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let call5 = {
+        // { dg-warning "unused name" "" { target *-*-* } .-1 }
+        let a = test5(5);
+        a + 1
+    };
+}
diff --git a/gcc/testsuite/rust/compile/torture/block_expr2.rs b/gcc/testsuite/rust/compile/torture/block_expr2.rs
new file mode 100644
index 00000000000..7c3ff698097
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/block_expr2.rs
@@ -0,0 +1,15 @@
+fn test() -> i32 {
+    123
+}
+
+fn main() {
+    let a = { test() };
+    let b = {
+        // { dg-warning "unused name" "" { target *-*-* } .-1 }
+        if a > 10 {
+            a - 1
+        } else {
+            a + 1
+        }
+    };
+}
diff --git a/gcc/testsuite/rust/compile/torture/block_expr3.rs b/gcc/testsuite/rust/compile/torture/block_expr3.rs
new file mode 100644
index 00000000000..6914b6379d7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/block_expr3.rs
@@ -0,0 +1,14 @@
+fn main() {
+    let x = 111;
+
+    let a = {
+        // { dg-warning "unused name" "" { target *-*-* } .-1 }
+        if x == 10 {
+            123
+        } else if x < 10 {
+            456
+        } else {
+            789
+        }
+    };
+}
diff --git a/gcc/testsuite/rust/compile/torture/block_expr4.rs b/gcc/testsuite/rust/compile/torture/block_expr4.rs
new file mode 100644
index 00000000000..da033ef9ef4
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/block_expr4.rs
@@ -0,0 +1,8 @@
+fn foo() -> isize {
+    0
+}
+
+fn main() {
+    let a = foo();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/block_expr5.rs b/gcc/testsuite/rust/compile/torture/block_expr5.rs
new file mode 100644
index 00000000000..7e164a949bb
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/block_expr5.rs
@@ -0,0 +1,40 @@
+fn foo() -> i32 {
+    0
+}
+
+fn bar() -> i32 {
+    foo();
+    foo()
+}
+
+fn baz() -> i32 {
+    {
+        bar();
+        bar();
+    }
+    {
+        bar();
+        bar()
+    };
+    {
+        bar();
+        bar()
+    }
+}
+
+fn test(ok: i32) -> i32 {
+    if ok >= 1 {
+        foo()
+    } else if ok <= -1 {
+        bar()
+    } else {
+        baz()
+    }
+}
+
+fn main() {
+    let a = foo();
+    let b = bar();
+    let c = baz();
+    test(a + b + c);
+}
diff --git a/gcc/testsuite/rust/compile/torture/block_expr_parser_bug.rs b/gcc/testsuite/rust/compile/torture/block_expr_parser_bug.rs
new file mode 100644
index 00000000000..468aace9881
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/block_expr_parser_bug.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let a = 123;
+    let b = if a > 10 { a - 1 } else { a + 1 };
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/bom.rs b/gcc/testsuite/rust/compile/torture/bom.rs
new file mode 100644
index 00000000000..5edcab227ee
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/bom.rs
@@ -0,0 +1 @@
+pub fn main () { }
diff --git a/gcc/testsuite/rust/compile/torture/bom_comment.rs b/gcc/testsuite/rust/compile/torture/bom_comment.rs
new file mode 100644
index 00000000000..020e1707b55
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/bom_comment.rs
@@ -0,0 +1,2 @@
+// UTF8 BOM
+pub fn main () { }
diff --git a/gcc/testsuite/rust/compile/torture/bom_shebang.rs b/gcc/testsuite/rust/compile/torture/bom_shebang.rs
new file mode 100644
index 00000000000..4c552e8d71d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/bom_shebang.rs
@@ -0,0 +1,2 @@
+#!/usr/bin/cat
+pub fn main () { }
diff --git a/gcc/testsuite/rust/compile/torture/bom_whitespace.rs b/gcc/testsuite/rust/compile/torture/bom_whitespace.rs
new file mode 100644
index 00000000000..b10d5654473
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/bom_whitespace.rs
@@ -0,0 +1,2 @@
+
+pub fn main () { }
diff --git a/gcc/testsuite/rust/compile/torture/bools_eq.rs b/gcc/testsuite/rust/compile/torture/bools_eq.rs
new file mode 100644
index 00000000000..965127b5d54
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/bools_eq.rs
@@ -0,0 +1,18 @@
+extern "C"
+{
+  fn abort ();
+}
+
+fn beq (a: bool, b: bool) -> bool
+{
+  let bools_eq = a == b;
+  bools_eq
+}
+
+pub fn main ()
+{
+  let a = true;
+  let b = false;
+  let r = beq (a, b);
+  if r { unsafe { abort (); } }
+}
diff --git a/gcc/testsuite/rust/compile/torture/borrow1.rs b/gcc/testsuite/rust/compile/torture/borrow1.rs
new file mode 100644
index 00000000000..8afa4746fef
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/borrow1.rs
@@ -0,0 +1,17 @@
+fn main() {
+    let a: i32;
+    a = 123;
+
+    let b: &i32;
+    b = &a;
+
+    let aa;
+    aa = 456;
+    let bb: &_;
+    bb = &a;
+
+    let aaa;
+    aaa = 123;
+    let bbb;
+    bbb = &aaa;
+}
diff --git a/gcc/testsuite/rust/compile/torture/borrow_function.rs b/gcc/testsuite/rust/compile/torture/borrow_function.rs
new file mode 100644
index 00000000000..98c6f99683e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/borrow_function.rs
@@ -0,0 +1,5 @@
+fn foo() {}
+
+fn main() {
+    let _a = &foo;
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/torture/break_function.rs b/gcc/testsuite/rust/compile/torture/break_function.rs
new file mode 100644
index 00000000000..043e91c9502
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/break_function.rs
@@ -0,0 +1,10 @@
+fn foo() -> i32 {
+    1
+}
+    
+fn main() {
+    let _a = loop {
+        break foo();
+    };
+}
+    
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/torture/byte_char_str.rs b/gcc/testsuite/rust/compile/torture/byte_char_str.rs
new file mode 100644
index 00000000000..bc3ec5014e8
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/byte_char_str.rs
@@ -0,0 +1,8 @@
+pub fn main ()
+{
+  let _c = 'x';
+  let _bc = b'x';
+
+  let _s = "abc";
+  let _bs = b"abc";
+}
diff --git a/gcc/testsuite/rust/compile/torture/byte_str.rs b/gcc/testsuite/rust/compile/torture/byte_str.rs
new file mode 100644
index 00000000000..28934d2581d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/byte_str.rs
@@ -0,0 +1,4 @@
+pub fn main() {
+    let a: &[u8; 4];
+    a = b"test";
+}
diff --git a/gcc/testsuite/rust/compile/torture/cast1.rs b/gcc/testsuite/rust/compile/torture/cast1.rs
new file mode 100644
index 00000000000..845d08cea01
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/cast1.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let a: *const i32 = &123;
+    let b: *mut i32 = (a as *mut i32);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/cast2.rs b/gcc/testsuite/rust/compile/torture/cast2.rs
new file mode 100644
index 00000000000..82925e93271
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/cast2.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let a: i32 = 123i32;
+    let b: u8 = a as u8;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/cast3.rs b/gcc/testsuite/rust/compile/torture/cast3.rs
new file mode 100644
index 00000000000..1de95687039
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/cast3.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let a = "foo\0";
+    let b = a as *const str;
+    let c = b as *const i8;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/cfg_attr.rs b/gcc/testsuite/rust/compile/torture/cfg_attr.rs
new file mode 100644
index 00000000000..d65faf2972a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/cfg_attr.rs
@@ -0,0 +1,7 @@
+mod fake {} // Add one line so gccrs doesn't believe we're parsing a shebang
+
+#[cfg_attr(feature = "somefeature", attribute = "someattr")]
+struct Feature;
+// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/torture/char1.rs b/gcc/testsuite/rust/compile/torture/char1.rs
new file mode 100644
index 00000000000..73835c218a2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/char1.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let a;
+    a = 'c';
+}
diff --git a/gcc/testsuite/rust/compile/torture/check-doc-attr-string.rs b/gcc/testsuite/rust/compile/torture/check-doc-attr-string.rs
new file mode 100644
index 00000000000..e113120bdbc
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/check-doc-attr-string.rs
@@ -0,0 +1,18 @@
+#![crate_type = "lib"]
+
+#[doc(alias = "foo")] // ok!
+#[doc(alias("bar", "baz"))] // ok!
+pub struct Bar;
+
+#[doc(alias = "
+")] // { dg-error "invalid character used" "" { target *-*-* } .-1 }
+pub struct Foo;
+
+#[doc(alias(
+    "
+"
+))] // ko but unchecked for now
+pub struct Foo2;
+
+#[doc(whatever = "buidule")] // ko as well but unchecked for now
+struct Boo;
diff --git a/gcc/testsuite/rust/compile/torture/coercion1.rs b/gcc/testsuite/rust/compile/torture/coercion1.rs
new file mode 100644
index 00000000000..3bfa938ffdc
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/coercion1.rs
@@ -0,0 +1,11 @@
+pub fn main() {
+    let a: &i32 = &123;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let b: &mut i32 = &mut 123;
+
+    let c: &i32 = &mut 123;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let d: &i32 = b;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/coercion2.rs b/gcc/testsuite/rust/compile/torture/coercion2.rs
new file mode 100644
index 00000000000..127f257f8b6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/coercion2.rs
@@ -0,0 +1,20 @@
+pub fn main() {
+    let a: *const i32 = &123;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let b: &i32 = &123;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let c: &mut i32 = &mut 123;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let d: *mut i32 = &mut 123;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let e: &i32 = &mut 123;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let f: *const i32 = &mut 123;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let g = &123;
+    let h: *const i32 = g;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/comparison_expr1.rs b/gcc/testsuite/rust/compile/torture/comparison_expr1.rs
new file mode 100644
index 00000000000..ed71ec89025
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/comparison_expr1.rs
@@ -0,0 +1,38 @@
+fn is_zero(x: i32) -> bool {
+    x == 0
+}
+
+fn is_not_zero(x: i32) -> bool {
+    x != 0
+}
+
+fn is_positive(x: i32) -> bool {
+    x > 0
+}
+
+fn is_negative(x: i32) -> bool {
+    x < 0
+}
+
+fn is_positive_or_zero(x: i32) -> bool {
+    x >= 0
+}
+
+fn is_negative_or_zero(x: i32) -> bool {
+    x <= 0
+}
+
+fn main() {
+    let a: bool = is_zero(1);
+    let b: bool = is_not_zero(2);
+    let c: bool = is_positive(3);
+    let d: bool = is_negative(4);
+    let e: bool = is_positive_or_zero(5);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let f: bool = is_negative_or_zero(6);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let g: bool = a || b;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let h: bool = c && d;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/compile.exp b/gcc/testsuite/rust/compile/torture/compile.exp
new file mode 100644
index 00000000000..48da264a47a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/compile.exp
@@ -0,0 +1,33 @@
+# Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+# 
+# This program 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/>.
+
+# Compile tests, torture testing.
+
+# Load support procs.
+load_lib rust-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+set saved-dg-do-what-default ${dg-do-what-default}
+
+set dg-do-what-default "compile"
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.rs]] "" ""
+set dg-do-what-default ${saved-dg-do-what-default}
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/rust/compile/torture/compound_assignment_expr1.rs b/gcc/testsuite/rust/compile/torture/compound_assignment_expr1.rs
new file mode 100644
index 00000000000..1ff0d24cf8e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/compound_assignment_expr1.rs
@@ -0,0 +1,23 @@
+fn main() {
+    let mut a = 1;
+    let mut b = 2;
+    let mut c = 3;
+    let mut d = 4;
+    let mut e = 5;
+    let mut f = 6;
+    let mut g = 7;
+    let mut h = 8;
+    let mut i = 9;
+    let mut j = 10;
+
+    a += 1;
+    b -= 2;
+    c *= 3;
+    d /= 4;
+    e %= 5;
+    f &= 6;
+    g |= 7;
+    h ^= 8;
+    i <<= 9;
+    j >>= 10;
+}
diff --git a/gcc/testsuite/rust/compile/torture/conditional.rs b/gcc/testsuite/rust/compile/torture/conditional.rs
new file mode 100644
index 00000000000..2bb3a95f033
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/conditional.rs
@@ -0,0 +1,11 @@
+fn main() {
+    let mut x = 5;
+
+    if x == 5 {
+        x = 1;
+    } else if x == 3 {
+        x = 2;
+    } else {
+        x = 3;
+    }
+}
diff --git a/gcc/testsuite/rust/compile/torture/constant1.rs b/gcc/testsuite/rust/compile/torture/constant1.rs
new file mode 100644
index 00000000000..57bcb0b4970
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/constant1.rs
@@ -0,0 +1,9 @@
+const TEST_CONST:i32 = 10;
+
+fn main() {
+    let mut x = TEST_CONST;
+    x = x + 1;
+
+    let mut y = x + TEST_CONST;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/constant2.rs b/gcc/testsuite/rust/compile/torture/constant2.rs
new file mode 100644
index 00000000000..d06324e8e65
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/constant2.rs
@@ -0,0 +1,6 @@
+fn main() {
+    const C: usize = 42;
+
+    let _a = C;
+    let _b: [i32; C] = [0; C];
+}
diff --git a/gcc/testsuite/rust/compile/torture/constant3.rs b/gcc/testsuite/rust/compile/torture/constant3.rs
new file mode 100644
index 00000000000..d2f1dd5b6db
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/constant3.rs
@@ -0,0 +1,10 @@
+fn main() {
+    const A: [i32; 3] = [1, 2, 3];
+    const B: i32 = A[1];
+    const C: usize = 42;
+    const D: i32 = 7;
+
+    let _a = C;
+    let _b: [i32; C] = [0; C];
+    let _c = B + D;
+}
diff --git a/gcc/testsuite/rust/compile/torture/deadcode1.rs b/gcc/testsuite/rust/compile/torture/deadcode1.rs
new file mode 100644
index 00000000000..1ba646f5c56
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/deadcode1.rs
@@ -0,0 +1,22 @@
+fn test1() -> i32 {
+    return 2;
+    // { dg-warning "unreachable expression" "" { target *-*-* } .+1 }
+    1
+}
+
+fn test2(x: i32) -> i32 {
+    if x > 1 {
+        return 5;
+    } else {
+        return 0;
+    }
+    // { dg-warning "unreachable statement" "" { target *-*-* } .+1 }
+    return 1;
+}
+
+fn main() {
+    let call1 = test1();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let call2 = test2(2);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/deadcode2.rs b/gcc/testsuite/rust/compile/torture/deadcode2.rs
new file mode 100644
index 00000000000..ba7d5f015e9
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/deadcode2.rs
@@ -0,0 +1,10 @@
+fn foo() -> i32 {
+    return 1;
+
+    let a = -1; // { dg-warning "unreachable statement" }
+    a // { dg-warning "unreachable expression" }
+}
+
+fn main() {
+    foo();
+}
diff --git a/gcc/testsuite/rust/compile/torture/deref1.rs b/gcc/testsuite/rust/compile/torture/deref1.rs
new file mode 100644
index 00000000000..d715ce96c79
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/deref1.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let a = 123;
+    let b = &a;
+    let c = *b;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/deref_function.rs b/gcc/testsuite/rust/compile/torture/deref_function.rs
new file mode 100644
index 00000000000..b1c5ff63423
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/deref_function.rs
@@ -0,0 +1,10 @@
+fn foo() {}
+
+
+fn main() {
+    let _c = *{
+	let _a = foo;
+	let b = &1;
+	b
+    };
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/torture/doc_comment.rs b/gcc/testsuite/rust/compile/torture/doc_comment.rs
new file mode 100644
index 00000000000..f99e41524ae
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/doc_comment.rs
@@ -0,0 +1,16 @@
+/// doc comment 1
+/// doc comment 2
+/// `blah blah` markdown
+pub struct TestStruct {}
+
+#[doc(hidden)]
+pub struct DocAttribute {}
+
+#[doc(a,b)]
+pub struct UnkAttribute {}
+
+fn main() {
+    let _ = TestStruct {};
+    let _ = DocAttribute {};
+    let _ = UnkAttribute {};
+}
diff --git a/gcc/testsuite/rust/compile/torture/enum1.rs b/gcc/testsuite/rust/compile/torture/enum1.rs
new file mode 100644
index 00000000000..7cea48f29e2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/enum1.rs
@@ -0,0 +1,13 @@
+enum Foo {
+    A,
+    B,
+    C(char),
+    D { x: i64, y: i64 },
+}
+
+fn main() {
+    let _a = Foo::A;
+    let _b = Foo::B;
+    let _c = Foo::C('x');
+    let _d = Foo::D { x: 20, y: 80 };
+}
diff --git a/gcc/testsuite/rust/compile/torture/extern_mod1.rs b/gcc/testsuite/rust/compile/torture/extern_mod1.rs
new file mode 100644
index 00000000000..4b576e03d80
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/extern_mod1.rs
@@ -0,0 +1,6 @@
+// { dg-additional-options "-w" }
+mod modules;
+
+fn main() {
+    let twelve = modules::return_12();
+}
diff --git a/gcc/testsuite/rust/compile/torture/extern_mod2.rs b/gcc/testsuite/rust/compile/torture/extern_mod2.rs
new file mode 100644
index 00000000000..4984d5dc2c1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/extern_mod2.rs
@@ -0,0 +1,23 @@
+// { dg-additional-options "-w" }
+
+#[path = "modules/valid_path.rs"]
+mod not_a_valid_path;
+
+#[path ="modules/valid_path.rs"]
+mod path_without_extra_equal;
+
+#[path= "modules/valid_path.rs"]
+mod no_leading_equal;
+
+#[path       =     "modules/valid_path.rs"]
+mod extra_spaces;
+
+#[path] // { dg-error "path attributes must contain a filename" }
+mod error; // { dg-error "no candidate found" }
+
+// This is "valid", and should only error out when parsing
+// the file
+#[path = "not_a_valid_file.rs"]
+mod another_error; // { dg-error "No such file or directory" }
+
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/torture/float1.rs b/gcc/testsuite/rust/compile/torture/float1.rs
new file mode 100644
index 00000000000..fbe89382267
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/float1.rs
@@ -0,0 +1,9 @@
+fn test(x: f32) -> f32 {
+    return x + 1.0;
+}
+
+fn main() {
+    let a_float = 5.123;
+    let call_test = test(a_float + 1.0);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/float_types.rs b/gcc/testsuite/rust/compile/torture/float_types.rs
new file mode 100644
index 00000000000..7d3d298a1bb
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/float_types.rs
@@ -0,0 +1,13 @@
+// { dg-prune-output "warning: unused name" } as there are many of these expected.
+
+fn main() {
+    let a1: f32 = 1.0f32;
+    let a2: f64 = 2.0f64;
+    let a3: f32 = 3f32;
+    let a4: f64 = 4f64;
+
+    let b1 = 1.0f32;
+    let b2 = 2.0f64;
+    let b3 = 3f32;
+    let b4 = 4f64;
+}
diff --git a/gcc/testsuite/rust/compile/torture/forward_decl_1.rs b/gcc/testsuite/rust/compile/torture/forward_decl_1.rs
new file mode 100644
index 00000000000..b8403f9b97f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/forward_decl_1.rs
@@ -0,0 +1,11 @@
+fn main() {
+    let mut an_integer = 5;
+    an_integer = test(1) + 3;
+
+    let call_test = test(1);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
+
+fn test(x: i32) -> i32 {
+    return x + 1;
+}
diff --git a/gcc/testsuite/rust/compile/torture/forward_decl_2.rs b/gcc/testsuite/rust/compile/torture/forward_decl_2.rs
new file mode 100644
index 00000000000..efc3b0dc565
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/forward_decl_2.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let y = x + 1;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
+
+static x: i32 = 3;
diff --git a/gcc/testsuite/rust/compile/torture/forward_decl_3-unsafe.rs b/gcc/testsuite/rust/compile/torture/forward_decl_3-unsafe.rs
new file mode 100644
index 00000000000..04935864f02
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/forward_decl_3-unsafe.rs
@@ -0,0 +1,13 @@
+fn main() {
+    unsafe {
+        let struct_test = Foo { one: 1, two: 2 };
+        // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    };
+}
+
+struct Foo {
+    one: i32,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+    two: i32,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/forward_decl_3.rs b/gcc/testsuite/rust/compile/torture/forward_decl_3.rs
new file mode 100644
index 00000000000..9256df5f728
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/forward_decl_3.rs
@@ -0,0 +1,11 @@
+fn main() {
+    let struct_test = Foo { one: 1, two: 2 };
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
+
+struct Foo {
+    one: i32,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+    two: i32,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/forward_decl_4.rs b/gcc/testsuite/rust/compile/torture/forward_decl_4.rs
new file mode 100644
index 00000000000..e1fe51f9025
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/forward_decl_4.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let mut x = TEST_CONST;
+    x = x + 1;
+
+    let mut y = x + TEST_CONST;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
+
+const TEST_CONST: i32 = 10;
diff --git a/gcc/testsuite/rust/compile/torture/forward_decl_5.rs b/gcc/testsuite/rust/compile/torture/forward_decl_5.rs
new file mode 100644
index 00000000000..73a47fe061b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/forward_decl_5.rs
@@ -0,0 +1,19 @@
+pub fn main() {
+    let a;
+    a = foo { a: 123, b: 456f32 };
+
+    let mut a = 123;
+    a = bar(a);
+
+    let mut b = 456f32;
+    b = bar(b);
+
+    fn bar<T>(x: T) -> T {
+        x
+    }
+
+    struct foo {
+        a: i32,
+        b: f32,
+    };
+}
diff --git a/gcc/testsuite/rust/compile/torture/func1.rs b/gcc/testsuite/rust/compile/torture/func1.rs
new file mode 100644
index 00000000000..df1789e7bbe
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/func1.rs
@@ -0,0 +1,7 @@
+fn not_void() -> i32 {
+    8
+}
+
+fn main() {
+    not_void();
+}
diff --git a/gcc/testsuite/rust/compile/torture/func2.rs b/gcc/testsuite/rust/compile/torture/func2.rs
new file mode 100644
index 00000000000..f7dd556d955
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/func2.rs
@@ -0,0 +1,20 @@
+fn foo() {
+    8;
+    8;
+}
+
+fn bar() -> i32 {
+    8;
+    8
+}
+
+fn baz() -> i32 {
+    8;
+    return 8;
+}
+
+fn main() {
+    let a = foo(); // { dg-warning "unused name" }
+    let b = bar(); // { dg-warning "unused name" }
+    let c = baz(); // { dg-warning "unused name" }
+}
diff --git a/gcc/testsuite/rust/compile/torture/function_reference1.rs b/gcc/testsuite/rust/compile/torture/function_reference1.rs
new file mode 100644
index 00000000000..dfbd01bdbdc
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/function_reference1.rs
@@ -0,0 +1,9 @@
+fn test(a: i32) -> i32 {
+    a + 1
+}
+
+fn main() {
+    let a = test;
+    let b = a(1);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/function_reference2.rs b/gcc/testsuite/rust/compile/torture/function_reference2.rs
new file mode 100644
index 00000000000..3c3e7c10910
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/function_reference2.rs
@@ -0,0 +1,9 @@
+fn test(a: i32) -> i32 {
+    a + 1
+}
+
+fn main() {
+    let a: fn(i32) -> i32 = test;
+    let b = a(1);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/function_reference3.rs b/gcc/testsuite/rust/compile/torture/function_reference3.rs
new file mode 100644
index 00000000000..0cb3181f4a1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/function_reference3.rs
@@ -0,0 +1,20 @@
+struct Foo {
+    a: fn(i32) -> i32,
+    b: i32,
+}
+
+fn test(a: i32) -> i32 {
+    a + 1
+}
+
+fn main() {
+    let a = test(1);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let b: fn(i32) -> i32 = test;
+    let c = b(1);
+
+    let d = Foo { a: test, b: c };
+    let e = (d.a)(d.b);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/function_reference4.rs b/gcc/testsuite/rust/compile/torture/function_reference4.rs
new file mode 100644
index 00000000000..977e4c97215
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/function_reference4.rs
@@ -0,0 +1,9 @@
+fn test(a: i32) -> i32 {
+    a + 1
+}
+
+fn main() {
+    let a: fn(_) -> _ = test;
+    let b = a(1);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics1.rs b/gcc/testsuite/rust/compile/torture/generics1.rs
new file mode 100644
index 00000000000..87bcdc8f305
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics1.rs
@@ -0,0 +1,51 @@
+struct Foo {
+    a: f32,
+    b: bool,
+}
+
+struct GenericStruct<T> {
+    a: T,
+    b: usize,
+}
+
+fn main() {
+    let a1;
+    a1 = Foo { a: 1.0, b: false };
+
+    let b1: f32 = a1.a;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let c1: bool = a1.b;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let a2: GenericStruct<i8>;
+    a2 = GenericStruct::<i8> { a: 1, b: 456 };
+
+    let b2: i8 = a2.a;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let c2: usize = a2.b;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let a3;
+    a3 = GenericStruct::<i32> { a: 123, b: 456 };
+
+    let b3: i32 = a3.a;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let c3: usize = a3.b;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let a4;
+    a4 = GenericStruct { a: 1.0, b: 456 };
+
+    let b4: f32 = a4.a;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let c4: usize = a4.b;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let a5;
+    a5 = GenericStruct::<_> { a: true, b: 456 };
+
+    let b5: bool = a5.a;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let c5: usize = a5.b;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics10.rs b/gcc/testsuite/rust/compile/torture/generics10.rs
new file mode 100644
index 00000000000..8473d49587b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics10.rs
@@ -0,0 +1,20 @@
+struct Foo<T>(T);
+
+struct Bar<T> {
+    a: Foo<T>,
+    b: bool,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+fn test<T>(a: Bar<T>) -> Foo<T> {
+    a.a
+}
+
+fn main() {
+    let a: Bar<i32> = Bar::<i32> {
+        a: Foo::<i32>(123),
+        b: true,
+    };
+    let b: Foo<i32> = test(a);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics11.rs b/gcc/testsuite/rust/compile/torture/generics11.rs
new file mode 100644
index 00000000000..3c8f5ba0058
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics11.rs
@@ -0,0 +1,8 @@
+struct Foo<T>(T, u32);
+
+type TypeAlias = Foo<i32>;
+
+fn main() {
+    let a: Foo<i32>;
+    a = TypeAlias { 0: 123, 1: 456 };
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics12.rs b/gcc/testsuite/rust/compile/torture/generics12.rs
new file mode 100644
index 00000000000..f31be584e09
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics12.rs
@@ -0,0 +1,17 @@
+struct GenericStruct<T>(T, usize);
+
+impl GenericStruct<i32> {
+    fn new(a: i32, b: usize) -> Self {
+        GenericStruct(a, b)
+    }
+
+    fn get(self) -> i32 {
+        self.0
+    }
+}
+
+fn main() {
+    let a: GenericStruct<i32> = GenericStruct::<i32>::new(123, 456);
+    let aa: i32 = a.get();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics13.rs b/gcc/testsuite/rust/compile/torture/generics13.rs
new file mode 100644
index 00000000000..9eb598f02a8
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics13.rs
@@ -0,0 +1,41 @@
+struct Foo<A> {
+    a: A,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+struct GenericStruct<T> {
+    a: T,
+    b: usize,
+}
+
+impl Foo<isize> {
+    fn test() -> i32 {
+        123
+    }
+
+    fn bar(self) -> isize {
+        // { dg-warning "associated function is never used" "" { target *-*-* } .-1 }
+        self.a
+    }
+}
+
+fn main() {
+    let a: i32 = Foo::test();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let a2: GenericStruct<i8>;
+    a2 = GenericStruct::<i8> { a: 1, b: 456 };
+
+    let b2: i8 = a2.a;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let c2: usize = a2.b;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let a4;
+    a4 = GenericStruct { a: 1.0, b: 456 };
+
+    let b4: f32 = a4.a;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let c4: usize = a4.b;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics14.rs b/gcc/testsuite/rust/compile/torture/generics14.rs
new file mode 100644
index 00000000000..e51a4079e30
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics14.rs
@@ -0,0 +1,20 @@
+struct Foo<A> {
+    a: A,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+impl Foo<isize> {
+    fn test() -> i32 {
+        123
+    }
+
+    fn bar(self) -> isize {
+        // { dg-warning "associated function is never used" "" { target *-*-* } .-1 }
+        self.a
+    }
+}
+
+fn main() {
+    let a: i32 = Foo::test();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics15.rs b/gcc/testsuite/rust/compile/torture/generics15.rs
new file mode 100644
index 00000000000..c16a67c4dd5
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics15.rs
@@ -0,0 +1,23 @@
+struct Foo<T>(T, bool);
+
+impl Foo<i32> {
+    fn bar(self) -> i32 {
+        self.0
+    }
+}
+
+impl Foo<f32> {
+    fn bar(self) -> f32 {
+        self.0
+    }
+}
+
+fn main() {
+    let a = Foo(123, true);
+    let aa = a.bar();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let b = Foo(456f32, true);
+    let bb = b.bar();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics16.rs b/gcc/testsuite/rust/compile/torture/generics16.rs
new file mode 100644
index 00000000000..15b9d7b55e7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics16.rs
@@ -0,0 +1,31 @@
+struct Foo<T>(T, bool);
+
+impl Foo<i32> {
+    fn new() -> Self {
+        Foo(123, true)
+    }
+
+    fn bar(self) -> i32 {
+        self.0
+    }
+}
+
+impl Foo<f32> {
+    fn new() -> Self {
+        Foo(123f32, true)
+    }
+
+    fn bar(self) -> f32 {
+        self.0
+    }
+}
+
+fn main() {
+    let a = Foo::<i32>::new();
+    let aa: i32 = a.bar();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let b = Foo::<f32>::new();
+    let bb: f32 = b.bar();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics17.rs b/gcc/testsuite/rust/compile/torture/generics17.rs
new file mode 100644
index 00000000000..d52314999b9
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics17.rs
@@ -0,0 +1,19 @@
+struct Foo<T>(T);
+
+impl<X> Foo<X> {
+    fn new(a: X) -> Self {
+        Self(a)
+    }
+
+    fn test(self) -> X {
+        self.0
+    }
+}
+
+fn main() {
+    let a;
+    a = Foo::new(123);
+
+    let b = a.test();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics18.rs b/gcc/testsuite/rust/compile/torture/generics18.rs
new file mode 100644
index 00000000000..4c98b86a1b9
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics18.rs
@@ -0,0 +1,20 @@
+struct Foo<T>(T);
+
+impl<X> Foo<X> {
+    fn new(a: X) -> Self {
+        // { dg-warning "associated function is never used" "" { target *-*-* } .-1 }
+        Self(a)
+    }
+
+    fn test(self) -> X {
+        self.0
+    }
+}
+
+fn main() {
+    let a;
+    a = Foo(123);
+
+    let b = a.test();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics19.rs b/gcc/testsuite/rust/compile/torture/generics19.rs
new file mode 100644
index 00000000000..9a5b4cb48dc
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics19.rs
@@ -0,0 +1,12 @@
+struct Foo<X, Y>(X, Y);
+
+impl<T> Foo<u32, T> {
+    fn new(a: T) -> Self {
+        Self(123, a)
+    }
+}
+
+fn main() {
+    let a;
+    a = Foo::new(false);
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics2.rs b/gcc/testsuite/rust/compile/torture/generics2.rs
new file mode 100644
index 00000000000..da0ab992243
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics2.rs
@@ -0,0 +1,45 @@
+struct Foo(f32, bool);
+
+struct GenericStruct<T>(T, usize);
+
+fn main() {
+    let a1;
+    a1 = Foo(1.0, false);
+
+    let b1: f32 = a1.0;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let c1: bool = a1.1;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let a2: GenericStruct<i8>;
+    a2 = GenericStruct::<i8>(1, 456);
+
+    let b2: i8 = a2.0;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let c2: usize = a2.1;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let a3;
+    a3 = GenericStruct::<i32>(123, 456);
+
+    let b3: i32 = a3.0;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let c3: usize = a3.1;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let a4;
+    a4 = GenericStruct(1.0, 456);
+
+    let b4: f32 = a4.0;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let c4: usize = a4.1;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let a5;
+    a5 = GenericStruct::<_>(true, 456);
+
+    let b5: bool = a5.0;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let c5: usize = a5.1;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics20.rs b/gcc/testsuite/rust/compile/torture/generics20.rs
new file mode 100644
index 00000000000..8fe1cffdf7d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics20.rs
@@ -0,0 +1,12 @@
+struct Foo<A, B>(A, B);
+
+impl<T> Foo<T, T> {
+    fn new(a: T, b: T) -> Self {
+        Self(a, b)
+    }
+}
+
+fn main() {
+    let a;
+    a = Foo::new(123, 456);
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics21.rs b/gcc/testsuite/rust/compile/torture/generics21.rs
new file mode 100644
index 00000000000..dc4e935cac7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics21.rs
@@ -0,0 +1,13 @@
+fn callee<T>(t: &T) -> i32 {
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    32
+}
+
+fn caller(t: i32) -> i32 {
+    callee(&t)
+}
+
+fn main() {
+    let a;
+    a = caller(123);
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics22.rs b/gcc/testsuite/rust/compile/torture/generics22.rs
new file mode 100644
index 00000000000..465ebb0f5e1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics22.rs
@@ -0,0 +1,13 @@
+fn callee<T>(t: (T, bool)) -> i32 {
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    32
+}
+
+fn caller(t: i32) -> i32 {
+    callee((t, false))
+}
+
+fn main() {
+    let a;
+    a = caller(123);
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics23.rs b/gcc/testsuite/rust/compile/torture/generics23.rs
new file mode 100644
index 00000000000..2169e3649c6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics23.rs
@@ -0,0 +1,6 @@
+struct Foo<A = f32>(A);
+
+fn main() {
+    let a: Foo;
+    a = Foo(123f32);
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics24.rs b/gcc/testsuite/rust/compile/torture/generics24.rs
new file mode 100644
index 00000000000..0de45a8c404
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics24.rs
@@ -0,0 +1,34 @@
+struct Foo<A = (isize, char)> {
+    a: A,
+}
+
+impl Foo<isize> {
+    fn bar(self) -> isize {
+        self.a
+    }
+}
+
+impl Foo<char> {
+    fn bar(self) -> char {
+        // { dg-warning "associated function is never used" "" { target *-*-* } .-1 }
+        self.a
+    }
+}
+
+impl Foo {
+    fn bar(self) {
+        let a: (isize, char) = self.a;
+        let b = a.0;
+        let c = a.1;
+        // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+        let aa: Foo<isize> = Foo { a: b };
+        let bb: isize = aa.bar();
+        // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    }
+}
+
+fn main() {
+    let a = Foo { a: (123, 'a') };
+    a.bar();
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics25.rs b/gcc/testsuite/rust/compile/torture/generics25.rs
new file mode 100644
index 00000000000..e7792e3efb3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics25.rs
@@ -0,0 +1,9 @@
+struct Foo<A, B = (A, A)>(A, B);
+
+fn main() {
+    let a: Foo<bool>;
+    a = Foo::<bool>(true, (false, true));
+
+    let b: (bool, bool);
+    b = a.1;
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics26.rs b/gcc/testsuite/rust/compile/torture/generics26.rs
new file mode 100644
index 00000000000..522e16f32f7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics26.rs
@@ -0,0 +1,21 @@
+// github issue #415
+fn test<A, B>(a: A, b: B) -> (A, B) {
+    (a, b)
+}
+
+fn main() {
+    let a = test::<i32, i32>(123, 456);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let b = test::<f32, f32>(123f32, 456f32);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let c = test::<_, _>(123, 456f32);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let d = test(true, 1234);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let e = test((123, false), 123f32);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics27.rs b/gcc/testsuite/rust/compile/torture/generics27.rs
new file mode 100644
index 00000000000..9871638dd9f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics27.rs
@@ -0,0 +1,16 @@
+// github issue #415
+fn test<A>(a: &A) -> &A {
+    a
+}
+
+fn main() {
+    let a = 123;
+    let b = &a;
+    let c = test(b);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let a = 123f32;
+    let b = &a;
+    let c = test(b);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics28.rs b/gcc/testsuite/rust/compile/torture/generics28.rs
new file mode 100644
index 00000000000..8cee8b00fb2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics28.rs
@@ -0,0 +1,18 @@
+struct Foo<A, B>(A, B);
+
+impl Foo<i32, f32> {
+    fn test<X>(a: X) -> X {
+        a
+    }
+}
+
+fn main() {
+    let a;
+    a = Foo::test::<_>(123);
+
+    let b;
+    b = Foo::test::<bool>(true);
+
+    let c;
+    c = Foo::test(456f32);
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics29.rs b/gcc/testsuite/rust/compile/torture/generics29.rs
new file mode 100644
index 00000000000..e09a1044574
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics29.rs
@@ -0,0 +1,16 @@
+struct Foo<A, B>(A, B);
+
+impl Foo<i32, f32> {
+    fn test<X>(self, a: X) -> X {
+        // { dg-warning "unused name" "" { target *-*-* } .-1 }
+        a
+    }
+}
+
+fn main() {
+    let a;
+    a = Foo(123, 456f32);
+
+    let b;
+    b = a.test::<bool>(false);
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics3.rs b/gcc/testsuite/rust/compile/torture/generics3.rs
new file mode 100644
index 00000000000..ceec8f7d9c6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics3.rs
@@ -0,0 +1,15 @@
+fn test<T>(a: T) -> T {
+    a
+}
+
+fn main() {
+    let a;
+    a = test(123);
+    let aa: i32 = a;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let b;
+    b = test::<u32>(456);
+    let bb: u32 = b;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics30.rs b/gcc/testsuite/rust/compile/torture/generics30.rs
new file mode 100644
index 00000000000..229f6d1254b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics30.rs
@@ -0,0 +1,16 @@
+struct Foo<A, B>(A, B);
+
+impl<T> Foo<T, f32> {
+    fn test<X>(self, a: X) -> X {
+        // { dg-warning "unused name" "" { target *-*-* } .-1 }
+        a
+    }
+}
+
+fn main() {
+    let a;
+    a = Foo(123, 456f32);
+
+    let b;
+    b = a.test::<bool>(false);
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics31.rs b/gcc/testsuite/rust/compile/torture/generics31.rs
new file mode 100644
index 00000000000..68ad4bf9a96
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics31.rs
@@ -0,0 +1,15 @@
+struct Foo<A, B>(A, B);
+
+impl<T> Foo<T, f32> {
+    fn test<X>(self, a: X) -> (T, X) {
+        (self.0, a)
+    }
+}
+
+fn main() {
+    let a;
+    a = Foo(123, 456f32);
+
+    let b;
+    b = a.test::<bool>(false);
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics32.rs b/gcc/testsuite/rust/compile/torture/generics32.rs
new file mode 100644
index 00000000000..21b9cae7409
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics32.rs
@@ -0,0 +1,15 @@
+struct Foo<A, B>(A, B);
+
+impl<T> Foo<T, f32> {
+    fn test<X>(self, a: X) -> (T, X) {
+        (self.0, a)
+    }
+}
+
+fn main() {
+    let a;
+    a = Foo(123, 456f32);
+
+    let b;
+    b = a.test(false);
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics4.rs b/gcc/testsuite/rust/compile/torture/generics4.rs
new file mode 100644
index 00000000000..915cc49c68b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics4.rs
@@ -0,0 +1,17 @@
+struct Foo<T> {
+    a: T,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+    b: bool,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+fn test<T>(a: T) -> Foo<T> {
+    Foo { a: a, b: true }
+}
+
+fn main() {
+    let a: Foo<i32> = test(123);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let b: Foo<u32> = test(456);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics5.rs b/gcc/testsuite/rust/compile/torture/generics5.rs
new file mode 100644
index 00000000000..b7f43028992
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics5.rs
@@ -0,0 +1,10 @@
+fn test<T>(a: T) -> T {
+    a
+}
+
+fn main() {
+    let a: i32 = test(123);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let b: i32 = test(456);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics6.rs b/gcc/testsuite/rust/compile/torture/generics6.rs
new file mode 100644
index 00000000000..5456b6dcb97
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics6.rs
@@ -0,0 +1,16 @@
+struct Foo<T>(T);
+
+struct Bar<T> {
+    a: Foo<T>,
+    b: bool,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+fn main() {
+    let a: Bar<i32> = Bar::<i32> {
+        a: Foo::<i32>(123),
+        b: true,
+    };
+    let b: i32 = a.a.0;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics7.rs b/gcc/testsuite/rust/compile/torture/generics7.rs
new file mode 100644
index 00000000000..e8e5ca69c3d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics7.rs
@@ -0,0 +1,14 @@
+struct Foo<T>(T);
+
+struct Bar {
+    a: Foo<i32>,
+    b: bool,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+fn main() {
+    let a = Foo::<i32>(123);
+    let b: Bar = Bar { a: a, b: true };
+    let c: i32 = b.a.0;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics8.rs b/gcc/testsuite/rust/compile/torture/generics8.rs
new file mode 100644
index 00000000000..036d85568f0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics8.rs
@@ -0,0 +1,18 @@
+struct GenericStruct<T>(T, usize);
+
+impl<T> GenericStruct<T> {
+    fn new(a: T, b: usize) -> Self {
+        GenericStruct(a, b)
+    }
+}
+
+fn main() {
+    let a: GenericStruct<i32> = GenericStruct::<i32>::new(123, 456);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let b: GenericStruct<u32> = GenericStruct::<_>::new(123, 456);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let c: GenericStruct<f32> = GenericStruct::new(123f32, 456);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/generics9.rs b/gcc/testsuite/rust/compile/torture/generics9.rs
new file mode 100644
index 00000000000..307c34f3e9b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/generics9.rs
@@ -0,0 +1,25 @@
+struct GenericStruct<T>(T, usize);
+
+impl<T> GenericStruct<T> {
+    fn new(a: T, b: usize) -> Self {
+        GenericStruct(a, b)
+    }
+
+    fn get(self) -> T {
+        self.0
+    }
+}
+
+fn main() {
+    let a: GenericStruct<i32> = GenericStruct::<i32>::new(123, 456);
+    let aa: i32 = a.get();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let b: GenericStruct<u32> = GenericStruct::<_>::new(123, 456);
+    let bb: u32 = b.get();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let c: GenericStruct<f32> = GenericStruct::new(123f32, 456);
+    let cc: f32 = c.get();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/grouped_expr_function.rs b/gcc/testsuite/rust/compile/torture/grouped_expr_function.rs
new file mode 100644
index 00000000000..eca7178b7f7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/grouped_expr_function.rs
@@ -0,0 +1,6 @@
+fn foo() {}
+
+
+fn main() {
+    let _a = (foo());
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/torture/identifier-missing-impl-1.rs b/gcc/testsuite/rust/compile/torture/identifier-missing-impl-1.rs
new file mode 100644
index 00000000000..2389fa52bfd
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/identifier-missing-impl-1.rs
@@ -0,0 +1,19 @@
+struct I();
+
+impl I {
+    fn () {
+        // { dg-error {expecting 'identifier' but '\(' found} "" { target *-*-* } .-1 }
+        // { dg-error {failed to parse inherent impl item in inherent impl} "" { target *-*-* } .-2 }
+        // { dg-error {failed to parse item in crate} "" { target *-*-* } .-3 }
+    }
+}
+
+impl I {
+    unsafe fn () {
+        // { dg-error {expecting 'identifier' but '\(' found} "" { xfail *-*-* } .-1 }
+    }
+}
+
+fn main() {
+    let _i = I();
+}
diff --git a/gcc/testsuite/rust/compile/torture/if.rs b/gcc/testsuite/rust/compile/torture/if.rs
new file mode 100644
index 00000000000..bcd520f66a9
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/if.rs
@@ -0,0 +1,19 @@
+fn foo() -> bool {
+    true
+}
+
+fn bar() {}
+
+struct Foo1 {
+    one: i32
+}
+
+
+fn main() {
+    if foo() {
+        bar();
+        let a = Foo1{one: 1};
+        a.one
+    }
+
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/torture/if_elif.rs b/gcc/testsuite/rust/compile/torture/if_elif.rs
new file mode 100644
index 00000000000..a89ad5eb02f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/if_elif.rs
@@ -0,0 +1,20 @@
+fn foo() -> bool {
+    true
+}
+
+fn bar() -> bool {
+    false
+}
+
+struct Foo1 {
+    one: i32
+}
+
+
+fn main() {
+    if foo() {
+    } else if bar() {
+        let a = Foo1{one: 1};
+        a.one;
+    }
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/torture/if_elif_else_expr1.rs b/gcc/testsuite/rust/compile/torture/if_elif_else_expr1.rs
new file mode 100644
index 00000000000..65ed7f7a23a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/if_elif_else_expr1.rs
@@ -0,0 +1,14 @@
+fn test(x: i32) -> i32 {
+    if x == 10 {
+        123
+    } else if x < 10 {
+        456
+    } else {
+        789
+    }
+}
+
+fn main() {
+    let a = test(1);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/if_else.rs b/gcc/testsuite/rust/compile/torture/if_else.rs
new file mode 100644
index 00000000000..09aecaed4d6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/if_else.rs
@@ -0,0 +1,19 @@
+fn foo() -> bool {
+    true
+}
+
+fn bar() {}
+
+struct Foo1 {
+    one: i32
+}
+
+
+fn main() {
+    if foo() {
+        bar();
+    } else {
+        let a = Foo1{one: 1};
+        a.one;
+    }
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/torture/ifunaryexpr.rs b/gcc/testsuite/rust/compile/torture/ifunaryexpr.rs
new file mode 100644
index 00000000000..8f0bb87f558
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/ifunaryexpr.rs
@@ -0,0 +1,22 @@
+extern "C"
+{
+  pub fn abort ();
+}
+
+struct B { b: bool }
+
+pub fn main ()
+{
+  let n = 1;
+  if 0 > -n { } else { unsafe { abort (); } }
+
+  let b = true;
+  if !b { unsafe { abort (); } }
+  if !!b { } else { unsafe { abort (); } }
+
+  let bb = B { b: false };
+
+  if !bb.b && !b { unsafe { abort (); } }
+
+  if (B { b: true }).b { } else { unsafe { abort (); } }
+}
diff --git a/gcc/testsuite/rust/compile/torture/impl_block1.rs b/gcc/testsuite/rust/compile/torture/impl_block1.rs
new file mode 100644
index 00000000000..d67afa187b1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/impl_block1.rs
@@ -0,0 +1,23 @@
+struct Foo(i32, bool);
+
+impl Foo {
+    fn new(a: i32, b: bool) -> Foo {
+        Foo(a, b)
+    }
+
+    fn test2() -> i32 {
+        test_forward_decl()
+    }
+}
+
+fn test_forward_decl() -> i32 {
+    123
+}
+
+fn main() {
+    let a;
+    a = Foo::new(1, true);
+
+    let b;
+    b = Foo::test2();
+}
diff --git a/gcc/testsuite/rust/compile/torture/impl_block2.rs b/gcc/testsuite/rust/compile/torture/impl_block2.rs
new file mode 100644
index 00000000000..0ed592d07be
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/impl_block2.rs
@@ -0,0 +1,28 @@
+struct Foo(i32, bool);
+
+impl Foo {
+    const number: i32 = 456;
+
+    fn new(a: i32, b: bool) -> Foo {
+        Foo(a, b)
+    }
+
+    fn test2() -> i32 {
+        test_forward_decl()
+    }
+}
+
+fn test_forward_decl() -> i32 {
+    123
+}
+
+fn main() {
+    let a;
+    a = Foo::new(1, true);
+
+    let b;
+    b = Foo::test2();
+
+    let c;
+    c = Foo::new(Foo::number, true);
+}
diff --git a/gcc/testsuite/rust/compile/torture/impl_block3.rs b/gcc/testsuite/rust/compile/torture/impl_block3.rs
new file mode 100644
index 00000000000..22ce19f704d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/impl_block3.rs
@@ -0,0 +1,36 @@
+struct Point {
+    x: f64,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+    y: f64,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+impl Point {
+    fn origin() -> Point {
+        Point { x: 0.0, y: 0.0 }
+    }
+
+    fn new(x: f64, y: f64) -> Point {
+        Point { x: x, y: y }
+    }
+}
+
+struct Rectangle {
+    p1: Point,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+    p2: Point,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+impl Rectangle {
+    fn from(p1: Point, p2: Point) -> Self {
+        Self { p1, p2 }
+    }
+}
+
+fn main() {
+    let p1 = Point::origin();
+    let p2 = Point::new(3.0, 4.0);
+    let rect = Rectangle::from(p1, p2);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/impl_block_unused.rs b/gcc/testsuite/rust/compile/torture/impl_block_unused.rs
new file mode 100644
index 00000000000..fea86319243
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/impl_block_unused.rs
@@ -0,0 +1,17 @@
+struct Foo(i32, bool);
+
+impl Foo {
+    fn new(a: i32, b: bool) -> Foo {
+        // { dg-warning "associated function is never used" "" { target *-*-* } .-1 }
+        Foo(a, b)
+    }
+
+    fn test2() -> i32 {
+        // { dg-warning "associated function is never used" "" { target *-*-* } .-1 }
+        1
+    }
+}
+
+fn main() {
+    let _a = Foo(1, true);
+}
diff --git a/gcc/testsuite/rust/compile/torture/implicit_returns1.rs b/gcc/testsuite/rust/compile/torture/implicit_returns1.rs
new file mode 100644
index 00000000000..54cc8b3aea8
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/implicit_returns1.rs
@@ -0,0 +1,73 @@
+fn test1() -> i32 {
+    1
+}
+
+fn test2() -> i32 {
+    return 2;
+}
+
+fn test3(x: i32) -> i32 {
+    if x > 1 {
+        5
+    } else {
+        0
+    }
+}
+
+fn test4(x: i32) -> i32 {
+    if x > 1 {
+        return 1;
+    }
+    0
+}
+
+fn test5(x: i32) -> i32 {
+    if x > 1 {
+        if x == 5 {
+            7
+        } else {
+            9
+        }
+    } else {
+        0
+    }
+}
+
+fn test6(x: i32) -> i32 {
+    if x > 1 {
+        return 5;
+    } else {
+        return 0;
+    }
+}
+
+fn test7(x: i32) -> i32 {
+    if x > 1 {
+        return 5;
+    } else {
+        return 0;
+    }
+}
+
+fn test8() -> i32 {
+    return 1;
+}
+
+fn main() {
+    let call1 = test1();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let call2 = test2();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let call3 = test3(3);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let call4 = test4(4);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let call5 = test5(5);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let call6 = test6(6);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let call7 = test7(7);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let call8 = test8();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/infer_type1.rs b/gcc/testsuite/rust/compile/torture/infer_type1.rs
new file mode 100644
index 00000000000..aabfcef895b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/infer_type1.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let array: [_; 2] = [111, 222];
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/inner_attributes.rs b/gcc/testsuite/rust/compile/torture/inner_attributes.rs
new file mode 100644
index 00000000000..3410dd6ec87
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/inner_attributes.rs
@@ -0,0 +1,3 @@
+#![allow(dead_code)]
+#![allow(unused_variables)]
+pub fn main () { }
diff --git a/gcc/testsuite/rust/compile/torture/integer_inference_var1.rs b/gcc/testsuite/rust/compile/torture/integer_inference_var1.rs
new file mode 100644
index 00000000000..ccee06aad10
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/integer_inference_var1.rs
@@ -0,0 +1,6 @@
+const TEST_CONST: i32 = 10;
+
+fn main() {
+    let a;
+    a = TEST_CONST;
+}
diff --git a/gcc/testsuite/rust/compile/torture/integer_inference_var2.rs b/gcc/testsuite/rust/compile/torture/integer_inference_var2.rs
new file mode 100644
index 00000000000..2209e937479
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/integer_inference_var2.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let a = 1u32;
+
+    let b;
+    b = a;
+}
diff --git a/gcc/testsuite/rust/compile/torture/integer_inference_var3.rs b/gcc/testsuite/rust/compile/torture/integer_inference_var3.rs
new file mode 100644
index 00000000000..582ae77caa4
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/integer_inference_var3.rs
@@ -0,0 +1,11 @@
+fn test(a: u32) -> u32 {
+    a + 1
+}
+
+fn main() {
+    let param;
+    param = 123;
+
+    let a = test(param);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/integer_inference_var4.rs b/gcc/testsuite/rust/compile/torture/integer_inference_var4.rs
new file mode 100644
index 00000000000..136d8183d08
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/integer_inference_var4.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let a;
+    a = 1;
+}
diff --git a/gcc/testsuite/rust/compile/torture/integer_inference_var5.rs b/gcc/testsuite/rust/compile/torture/integer_inference_var5.rs
new file mode 100644
index 00000000000..051de1d6520
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/integer_inference_var5.rs
@@ -0,0 +1,25 @@
+const TEST_CONST: i32 = 10;
+
+fn test(x: u32) -> u32 {
+    x + 1
+}
+
+fn main() {
+    let x = TEST_CONST;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let a = 1u32;
+    let b = a;
+
+    let c;
+    c = 1;
+
+    let d;
+    d = b;
+
+    let param;
+    param = 123;
+
+    let test_call = test(param);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/integer_types.rs b/gcc/testsuite/rust/compile/torture/integer_types.rs
new file mode 100644
index 00000000000..95a73780bb1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/integer_types.rs
@@ -0,0 +1,27 @@
+// { dg-prune-output "warning: unused name" } as there are many of these expected.
+
+fn main() {
+    let a1: i8 = 1i8;
+    let a2: i16 = 2i16;
+    let a3: i32 = 3i32;
+    let a4: i64 = 4i64;
+    let a5: i128 = 5i128;
+
+    let b1 = 1i8;
+    let b2 = 2i16;
+    let b3 = 3i32;
+    let b4 = 4i64;
+    let b5 = 5i128;
+
+    let c1: u8 = 1u8;
+    let c2: u16 = 2u16;
+    let c3: u32 = 3u32;
+    let c4: u64 = 4u64;
+    let c5: u128 = 5u128;
+
+    let d1 = 1u8;
+    let d2 = 2u16;
+    let d3 = 3u32;
+    let d4 = 4u64;
+    let d5 = 5u128;
+}
diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-1.rs b/gcc/testsuite/rust/compile/torture/intrinsics-1.rs
new file mode 100644
index 00000000000..6704c0210d1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/intrinsics-1.rs
@@ -0,0 +1,22 @@
+// { dg-additional-options -fdump-tree-original }
+
+#![feature(intrinsics)]
+
+extern "rust-intrinsic" {
+    pub fn sqrtf32(x: f32) -> f32;
+    pub fn sinf32(x: f32) -> f32;
+}
+
+fn main() {
+    unsafe fn foo() {
+        let mut f32;
+
+        f32 = sqrtf32(5f32);
+        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_sqrtf \(5\.0e\+0\);$} 1 original } }
+
+        f32 = sinf32(39f32);
+        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_sinf \(3\.9e\+1\);$} 1 original } }
+    }
+
+    unsafe { foo() };
+}
diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-2.rs b/gcc/testsuite/rust/compile/torture/intrinsics-2.rs
new file mode 100644
index 00000000000..6b2339f38f3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/intrinsics-2.rs
@@ -0,0 +1,22 @@
+// { dg-additional-options -fdump-tree-original }
+
+#![feature(intrinsics)]
+
+extern "rust-intrinsic" {
+    pub fn size_of<T>() -> usize;
+}
+
+fn main() -> i32 {
+    unsafe fn foo() -> usize {
+        let f: f32;
+
+        let s_f32 = size_of::<f32>();
+        let s_f64 = size_of::<f64>();
+        let s_f32_again = size_of::<f32>();
+
+        s_f32 + s_f64 + s_f32_again
+    }
+
+    // useless code, just used for function compilation caching
+    unsafe { foo() as i32 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/isolated_cr_block_comment.rs b/gcc/testsuite/rust/compile/torture/isolated_cr_block_comment.rs
new file mode 100644
index 00000000000..9a1e090f330
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/isolated_cr_block_comment.rs
@@ -0,0 +1,2 @@
+/* comment cr\r is allowed */
+pub fn main () { }
diff --git a/gcc/testsuite/rust/compile/torture/isolated_cr_line_comment.rs b/gcc/testsuite/rust/compile/torture/isolated_cr_line_comment.rs
new file mode 100644
index 00000000000..4e921a225c2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/isolated_cr_line_comment.rs
@@ -0,0 +1,2 @@
+// comment cr\r is allowed
+pub fn main () { }
diff --git a/gcc/testsuite/rust/compile/torture/issue-1024.rs b/gcc/testsuite/rust/compile/torture/issue-1024.rs
new file mode 100644
index 00000000000..109540934a8
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/issue-1024.rs
@@ -0,0 +1,11 @@
+extern "rust-intrinsic" {
+    pub fn size_of<T>() -> usize;
+}
+
+fn test() -> usize {
+    unsafe { size_of::<i32>() }
+}
+
+fn main() {
+    let _a = test();
+}
diff --git a/gcc/testsuite/rust/compile/torture/issue-1075.rs b/gcc/testsuite/rust/compile/torture/issue-1075.rs
new file mode 100644
index 00000000000..7c0a0434262
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/issue-1075.rs
@@ -0,0 +1,42 @@
+// { dg-additional-options "-w" }
+extern "rust-intrinsic" {
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+    pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+struct FatPtr<T> {
+    data: *const T,
+    len: usize,
+}
+
+union Repr<T> {
+    rust: *const [T],
+    rust_mut: *mut [T],
+    raw: FatPtr<T>,
+}
+
+impl<T> *const [T] {
+    pub const fn len(self) -> usize {
+        // SAFETY: this is safe because `*const [T]` and `FatPtr<T>` have the same layout.
+        // Only `std` can make this guarantee.
+        unsafe { Repr { rust: self }.raw.len }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+impl<T> *const T {
+    pub const unsafe fn offset(self, count: isize) -> *const T {
+        unsafe { offset(self, count) }
+    }
+
+    pub const unsafe fn add(self, count: usize) -> Self {
+        unsafe { self.offset(count as isize) }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
diff --git a/gcc/testsuite/rust/compile/torture/issue-1432.rs b/gcc/testsuite/rust/compile/torture/issue-1432.rs
new file mode 100644
index 00000000000..083a369d16f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/issue-1432.rs
@@ -0,0 +1,77 @@
+// { dg-additional-options "-w" }
+mod intrinsics {
+    extern "rust-intrinsic" {
+        #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
+        pub fn wrapping_add<T>(a: T, b: T) -> T;
+        #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
+        pub fn rotate_left<T>(a: T, b: T) -> T;
+        #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
+        pub fn rotate_right<T>(a: T, b: T) -> T;
+        #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+        pub fn offset<T>(ptr: *const T, count: isize) -> *const T;
+    }
+}
+
+mod mem {
+    extern "rust-intrinsic" {
+        #[rustc_const_stable(feature = "const_transmute", since = "1.46.0")]
+        fn transmute<T, U>(_: T) -> U;
+        #[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
+        fn size_of<T>() -> usize;
+    }
+}
+
+macro_rules! impl_uint {
+    ($($ty:ident = $lang:literal),*) => {
+        $(
+            impl $ty {
+                pub fn wrapping_add(self, rhs: Self) -> Self {
+                    // intrinsics::wrapping_add(self, rhs)
+                    self + rhs
+                }
+
+                pub fn rotate_left(self, n: u32) -> Self {
+                    unsafe {
+                        intrinsics::rotate_left(self, n as Self)
+                    }
+                }
+
+                pub fn rotate_right(self, n: u32) -> Self {
+                    unsafe {
+                        intrinsics::rotate_right(self, n as Self)
+                    }
+                }
+
+                pub fn to_le(self) -> Self {
+                    #[cfg(target_endian = "little")]
+                    {
+                        self
+                    }
+                }
+
+                pub const fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+                    Self::from_le(Self::from_ne_bytes(bytes))
+                }
+
+                pub const fn from_le(x: Self) -> Self {
+                    #[cfg(target_endian = "little")]
+                    {
+                        x
+                    }
+                }
+
+                pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+                    unsafe { mem::transmute(bytes) }
+                }
+            }
+        )*
+    }
+}
+
+impl_uint!(
+    u8 = "u8",
+    u16 = "u16",
+    u32 = "u32",
+    u64 = "u64",
+    usize = "usize"
+);
diff --git a/gcc/testsuite/rust/compile/torture/issue-1434.rs b/gcc/testsuite/rust/compile/torture/issue-1434.rs
new file mode 100644
index 00000000000..dc000e942e6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/issue-1434.rs
@@ -0,0 +1,53 @@
+// { dg-options "-w" }
+const BLOCK_LEN: usize = 64;
+
+const IV: [u32; 8] = [
+    0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19,
+];
+
+struct ChunkState {
+    chaining_value: [u32; 8],
+    chunk_counter: u64,
+    block: [u8; BLOCK_LEN],
+    block_len: u8,
+    blocks_compressed: u8,
+    flags: u32,
+}
+
+impl ChunkState {
+    fn new(key_words: [u32; 8], chunk_counter: u64, flags: u32) -> Self {
+        Self {
+            chaining_value: key_words,
+            chunk_counter,
+            block: [0; BLOCK_LEN],
+            block_len: 0,
+            blocks_compressed: 0,
+            flags,
+        }
+    }
+}
+
+pub struct Hasher {
+    chunk_state: ChunkState,
+    key_words: [u32; 8],
+    cv_stack: [[u32; 8]; 54], // Space for 54 subtree chaining values:
+    cv_stack_len: u8,         // 2^54 * CHUNK_LEN = 2^64
+    flags: u32,
+}
+
+impl Hasher {
+    fn new_internal(key_words: [u32; 8], flags: u32) -> Self {
+        Self {
+            chunk_state: ChunkState::new(key_words, 0, flags),
+            key_words,
+            cv_stack: [[0; 8]; 54],
+            cv_stack_len: 0,
+            flags,
+        }
+    }
+
+    /// Construct a new `Hasher` for the regular hash function.
+    pub fn new() -> Self {
+        Self::new_internal(IV, 0)
+    }
+}
diff --git a/gcc/testsuite/rust/compile/torture/issue-368.rs b/gcc/testsuite/rust/compile/torture/issue-368.rs
new file mode 100644
index 00000000000..18bc9bdc62e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/issue-368.rs
@@ -0,0 +1,9 @@
+struct S;
+
+fn foo<S>(s: S) -> S {
+    s
+}
+
+fn main() {
+    let _s: S = foo(S);
+}
diff --git a/gcc/testsuite/rust/compile/torture/issue-808.rs b/gcc/testsuite/rust/compile/torture/issue-808.rs
new file mode 100644
index 00000000000..2e5a81fe516
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/issue-808.rs
@@ -0,0 +1,20 @@
+pub trait Foo {
+    type Target;
+
+    fn bar(&self) -> &Self::Target;
+}
+
+impl<T> Foo for &T {
+    type Target = T;
+
+    fn bar(&self) -> &T {
+        *self
+    }
+}
+
+pub fn main() {
+    let a: i32 = 123;
+    let b: &i32 = &a;
+
+    b.bar();
+}
diff --git a/gcc/testsuite/rust/compile/torture/issue-862.rs b/gcc/testsuite/rust/compile/torture/issue-862.rs
new file mode 100644
index 00000000000..c1a4609ba86
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/issue-862.rs
@@ -0,0 +1,74 @@
+// { dg-additional-options "-w" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+    type Target;
+
+    fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "imm_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+impl<T> Deref for &mut T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "mut_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        unsafe {
+            let a = "foo_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        &self.0
+    }
+}
+
+struct Bar(i32);
+impl Bar {
+    fn cake(self) -> i32 {
+        self.0 + 1
+    }
+}
+
+pub fn main() {
+    let foo: Foo<Bar> = Foo(Bar(123));
+    let bar: Bar = *foo;
+
+    let cake_result: i32 = foo.cake();
+}
diff --git a/gcc/testsuite/rust/compile/torture/issue-893-2.rs b/gcc/testsuite/rust/compile/torture/issue-893-2.rs
new file mode 100644
index 00000000000..88a865d66dc
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/issue-893-2.rs
@@ -0,0 +1,35 @@
+// { dg-additional-options "-w" }
+struct Foo<T>(T);
+impl<T> Foo<T> {
+    fn new<Y>(a: T, b: Y) -> Self {
+        Self(a)
+    }
+}
+
+struct Bar<T>(T);
+impl Bar<i32> {
+    fn baz(self) {}
+
+    fn test() -> i32 {
+        123
+    }
+}
+
+struct Baz<A, B>(A, B);
+impl Baz<i32, f32> {
+    fn test<X>(a: X) -> X {
+        a
+    }
+}
+
+pub fn main() {
+    let a = Foo::<i32>::new::<f32>(123, 456f32);
+    let b = Foo::new::<f32>(123, 456f32);
+
+    let c = Bar::<i32>(123);
+    let d = Bar::baz(c);
+
+    let e = Bar::test();
+
+    let f = Baz::test::<bool>(true);
+}
diff --git a/gcc/testsuite/rust/compile/torture/issue-893.rs b/gcc/testsuite/rust/compile/torture/issue-893.rs
new file mode 100644
index 00000000000..d8245f3e0d8
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/issue-893.rs
@@ -0,0 +1,11 @@
+// { dg-additional-options "-w" }
+struct Foo<T>(T);
+impl<T> Foo<T> {
+    fn new<Y>(a: T, b: Y) -> Self {
+        Self(a)
+    }
+}
+
+pub fn test() {
+    let a = Foo::<i32>::new::<f32>(123, 456f32);
+}
diff --git a/gcc/testsuite/rust/compile/torture/lazybooleanexpr_function.rs b/gcc/testsuite/rust/compile/torture/lazybooleanexpr_function.rs
new file mode 100644
index 00000000000..1be51274d03
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/lazybooleanexpr_function.rs
@@ -0,0 +1,14 @@
+fn foo() -> bool {
+    return true;
+}
+
+fn bar() -> bool {
+    return false;
+}
+
+
+
+fn main() {
+    let _a = true && foo();
+    let _b = true || bar();
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/torture/lifetime1.rs b/gcc/testsuite/rust/compile/torture/lifetime1.rs
new file mode 100644
index 00000000000..151fd827b5e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/lifetime1.rs
@@ -0,0 +1,7 @@
+fn foo<'a>(t: &'a str) -> &'a str {
+    t
+}
+
+fn main() {
+    foo("hello world");
+}
diff --git a/gcc/testsuite/rust/compile/torture/literals1.rs b/gcc/testsuite/rust/compile/torture/literals1.rs
new file mode 100644
index 00000000000..cf021e295d2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/literals1.rs
@@ -0,0 +1,11 @@
+// { dg-prune-output "warning: unused name" } as there are many of these expected.
+
+fn main() {
+    let hex: i32 = 0xFF;
+    let binary: i32 = 0b11110000;
+    let oct: i32 = 0o70;
+
+    let hex_u8: u8 = 0xFF_u8;
+    let bin_u16: u16 = 0b1111000011110000_u16;
+    let oct: u32 = 0o70_u32;
+}
diff --git a/gcc/testsuite/rust/compile/torture/loop1.rs b/gcc/testsuite/rust/compile/torture/loop1.rs
new file mode 100644
index 00000000000..a8ee2f59bb8
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/loop1.rs
@@ -0,0 +1,10 @@
+fn main() {
+    let mut a = 1;
+    let mut b = 1;
+
+    loop {
+        let c = a + b;
+        a = b;
+        b = c;
+    }
+}
diff --git a/gcc/testsuite/rust/compile/torture/loop2.rs b/gcc/testsuite/rust/compile/torture/loop2.rs
new file mode 100644
index 00000000000..3de3ea81947
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/loop2.rs
@@ -0,0 +1,14 @@
+fn main() {
+    let mut a = 1;
+    let mut b = 1;
+
+    // first number in Fibonacci sequence over 10:
+    loop {
+        if b > 10 {
+            break;
+        }
+        let c = a + b;
+        a = b;
+        b = c;
+    }
+}
diff --git a/gcc/testsuite/rust/compile/torture/loop3.rs b/gcc/testsuite/rust/compile/torture/loop3.rs
new file mode 100644
index 00000000000..76fadfb4337
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/loop3.rs
@@ -0,0 +1,14 @@
+fn main() {
+    let mut a = 1;
+    let mut b = 1;
+
+    // first number in Fibonacci sequence over 10:
+    loop {
+        if b > 10 {
+            return;
+        }
+        let c = a + b;
+        a = b;
+        b = c;
+    }
+}
diff --git a/gcc/testsuite/rust/compile/torture/loop4.rs b/gcc/testsuite/rust/compile/torture/loop4.rs
new file mode 100644
index 00000000000..f7b59357aeb
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/loop4.rs
@@ -0,0 +1,7 @@
+fn main() {
+    'outer: loop {
+        'inner: loop {
+            break 'outer;
+        }
+    }
+}
diff --git a/gcc/testsuite/rust/compile/torture/loop5.rs b/gcc/testsuite/rust/compile/torture/loop5.rs
new file mode 100644
index 00000000000..4004cd30b7b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/loop5.rs
@@ -0,0 +1,14 @@
+fn main() {
+    let mut a = 1;
+    let mut b = 1;
+
+    // first number in Fibonacci sequence over 10:
+    let _fib = loop {
+        if b > 10 {
+            break b;
+        }
+        let c = a + b;
+        a = b;
+        b = c;
+    };
+}
diff --git a/gcc/testsuite/rust/compile/torture/loop6.rs b/gcc/testsuite/rust/compile/torture/loop6.rs
new file mode 100644
index 00000000000..ecd3ad4fd81
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/loop6.rs
@@ -0,0 +1,11 @@
+fn main() {
+    let mut a = 1;
+    let mut b = 1;
+
+    let mut c;
+    while b > 10 {
+        c = a + b;
+        a = b;
+        b = c;
+    }
+}
diff --git a/gcc/testsuite/rust/compile/torture/loop7.rs b/gcc/testsuite/rust/compile/torture/loop7.rs
new file mode 100644
index 00000000000..0cd844592b6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/loop7.rs
@@ -0,0 +1,13 @@
+fn main() {
+    let mut a = 1;
+    let mut b = 1;
+
+    let _fib = loop {
+        if (a % 2 == 0) {
+            continue;
+        }
+        let c = a + b;
+        a = b;
+        b = c;
+    };
+}
diff --git a/gcc/testsuite/rust/compile/torture/macro-issue1403.rs b/gcc/testsuite/rust/compile/torture/macro-issue1403.rs
new file mode 100644
index 00000000000..7fe6c51053c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/macro-issue1403.rs
@@ -0,0 +1,23 @@
+macro_rules! stmt {
+    ($s:stmt) => {
+        $s
+    };
+    ($s:stmt, $($ss:stmt),*) => {
+        $s;
+        stmt!($($ss),*);
+    };
+}
+
+fn main() {
+    stmt!(
+        struct S;
+    );
+    stmt!(
+        struct A;,
+        struct B;,
+        struct C;,
+        struct D;,
+        struct E;
+    );
+}
+
diff --git a/gcc/testsuite/rust/compile/torture/macro-issue1426.rs b/gcc/testsuite/rust/compile/torture/macro-issue1426.rs
new file mode 100644
index 00000000000..1b558cfa83d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/macro-issue1426.rs
@@ -0,0 +1,32 @@
+// { dg-additional-options -fdump-tree-ccp1-raw }
+
+macro_rules! stmt {
+    ($s:stmt) => {
+        $s
+    };
+    ($s:stmt, $($ss:stmt),*) => {
+        $s;
+        stmt!($($ss),*);
+    };
+}
+
+pub fn test() -> i32 {
+    stmt!(
+        let a = 1
+	// { dg-warning {unused name 'a'} {} { target *-*-* } .-1 }
+    );
+    stmt!(
+        let b = 2,
+        let c = 3,
+        let d = 4,
+        let e = 5,
+        let f = b + c + d + e
+    );
+    f
+    // { dg-final { scan-tree-dump-times {gimple_return <14>} 1 ccp1 { target __OPTIMIZE__ } } }
+}
+
+fn main() {
+    let _ = test();
+}
+
diff --git a/gcc/testsuite/rust/compile/torture/macro_as_expr.rs b/gcc/testsuite/rust/compile/torture/macro_as_expr.rs
new file mode 100644
index 00000000000..b0084e7b466
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/macro_as_expr.rs
@@ -0,0 +1,14 @@
+// { dg-additional-options "-w" }
+
+macro_rules! add {
+    ($a:expr) => { $a };
+    ($a:expr, $($b:expr),+) => { $a + add!($($b),*) }
+}
+
+fn main() -> i32 {
+    if add!(add!(1, 2)) > add!(5) {
+        add!(1, add!(2, 3), add!(4))
+    } else {
+        add!(5, add!(6, 7), add!(8), 9) + 10
+    }
+}
diff --git a/gcc/testsuite/rust/compile/torture/match1.rs b/gcc/testsuite/rust/compile/torture/match1.rs
new file mode 100644
index 00000000000..916b11a3194
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/match1.rs
@@ -0,0 +1,16 @@
+// { dg-additional-options "-w" }
+enum Foo {
+    A,
+    B,
+    C(char),
+    D { x: i64, y: i64 },
+}
+
+fn inspect(f: Foo) {
+    match f {
+        Foo::A => {}
+        Foo::B => {}
+        Foo::C(x) => {}
+        Foo::D { x, y } => {}
+    }
+}
diff --git a/gcc/testsuite/rust/compile/torture/methods1.rs b/gcc/testsuite/rust/compile/torture/methods1.rs
new file mode 100644
index 00000000000..a8e384dabea
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/methods1.rs
@@ -0,0 +1,41 @@
+struct Point {
+    x: f64,
+    y: f64,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+impl Point {
+    fn origin() -> Point {
+        Point { x: 0.0, y: 0.0 }
+    }
+
+    fn new(x: f64, y: f64) -> Point {
+        Point { x: x, y: y }
+    }
+}
+
+struct Rectangle {
+    p1: Point,
+    p2: Point,
+}
+
+impl Rectangle {
+    fn from(p1: Point, p2: Point) -> Self {
+        Self { p1, p2 }
+    }
+
+    fn sum_x(self) -> f64 {
+        let p1 = self.p1;
+        let p2 = self.p2;
+        p1.x + p2.x
+    }
+}
+
+fn main() {
+    let p1 = Point::origin();
+    let p2 = Point::new(3.0, 4.0);
+    let rect = Rectangle::from(p1, p2);
+
+    let sum = rect.sum_x();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/methods2.rs b/gcc/testsuite/rust/compile/torture/methods2.rs
new file mode 100644
index 00000000000..d63211bdf8a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/methods2.rs
@@ -0,0 +1,43 @@
+struct Point {
+    x: f64,
+    y: f64,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+impl Point {
+    fn origin() -> Point {
+        Point { x: 0.0, y: 0.0 }
+    }
+
+    fn new(x: f64, y: f64) -> Point {
+        Point { x: x, y: y }
+    }
+}
+
+struct Rectangle {
+    p1: Point,
+    p2: Point,
+}
+
+impl Rectangle {
+    fn from(p1: Point, p2: Point) -> Self {
+        Self { p1, p2 }
+    }
+}
+
+fn main() {
+    let p1 = Point::origin();
+    let p2 = Point::new(3.0, 4.0);
+    let rect = Rectangle::from(p1, p2);
+
+    let sum = rect.sum_x();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
+
+impl Rectangle {
+    fn sum_x(self) -> f64 {
+        let p1 = self.p1;
+        let p2 = self.p2;
+        p1.x + p2.x
+    }
+}
diff --git a/gcc/testsuite/rust/compile/torture/methods3.rs b/gcc/testsuite/rust/compile/torture/methods3.rs
new file mode 100644
index 00000000000..55426f4fcf7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/methods3.rs
@@ -0,0 +1,44 @@
+struct Point {
+    x: f64,
+    y: f64,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+impl Point {
+    fn origin() -> Point {
+        Point { x: 0.0, y: 0.0 }
+    }
+
+    fn new(x: f64, y: f64) -> Point {
+        Point { x: x, y: y }
+    }
+}
+
+struct Rectangle {
+    p1: Point,
+    p2: Point,
+}
+
+impl Rectangle {
+    fn from(p1: Point, p2: Point) -> Self {
+        Self { p1, p2 }
+    }
+
+    fn sum_x(self) -> f64 {
+        let p1 = self.p1;
+        let p2 = self.p2;
+        p1.x + p2.x
+    }
+}
+
+fn main() {
+    let p1 = Point::origin();
+    let p2 = Point::new(3.0, 4.0);
+    let rect = Rectangle::from(p1, p2);
+
+    let sum = rect.sum_x();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    // multiple MethodCallExpr were causing issue #310
+    let sum = rect.sum_x();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/mod-nameresolve.rs b/gcc/testsuite/rust/compile/torture/mod-nameresolve.rs
new file mode 100644
index 00000000000..09a722681b0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/mod-nameresolve.rs
@@ -0,0 +1,5 @@
+mod foo {
+    struct A; // { dg-warning "struct is never constructed" }
+}
+
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/torture/mod1.rs b/gcc/testsuite/rust/compile/torture/mod1.rs
new file mode 100644
index 00000000000..651678c6a34
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/mod1.rs
@@ -0,0 +1,11 @@
+// This is testing name resolution
+
+mod _foo {
+    struct _A;
+}
+
+mod _bar {
+    mod _barbis {
+        struct _B;
+    }
+}
diff --git a/gcc/testsuite/rust/compile/torture/mod2.rs b/gcc/testsuite/rust/compile/torture/mod2.rs
new file mode 100644
index 00000000000..04722a94bb1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/mod2.rs
@@ -0,0 +1,13 @@
+mod foomod {
+    pub struct Foo {}
+}
+
+impl foomod::Foo {
+    pub fn new() -> Self {
+        foomod::Foo {}
+    }
+}
+
+fn main() {
+    let _a = foomod::Foo::new();
+}
diff --git a/gcc/testsuite/rust/compile/torture/mod3.rs b/gcc/testsuite/rust/compile/torture/mod3.rs
new file mode 100644
index 00000000000..2ace8c064d8
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/mod3.rs
@@ -0,0 +1,22 @@
+// { dg-additional-options "-w" }
+mod A {
+    pub mod B {
+        pub mod C {
+            pub struct Foo {
+                pub f: i32,
+            }
+            impl Foo {
+                pub fn new() -> Self {
+                    Foo { f: 23i32 }
+                }
+            }
+        }
+    }
+}
+
+fn main() -> i32 {
+    let a = A::B::C::Foo::new();
+    let b = A::B::C::Foo { f: -23i32 };
+
+    a.f - b.f
+}
diff --git a/gcc/testsuite/rust/compile/torture/modules/mod.rs b/gcc/testsuite/rust/compile/torture/modules/mod.rs
new file mode 100644
index 00000000000..3d65176b6c3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/modules/mod.rs
@@ -0,0 +1,3 @@
+pub fn return_12() -> i32 {
+    12
+}
diff --git a/gcc/testsuite/rust/compile/torture/modules/valid_path.rs b/gcc/testsuite/rust/compile/torture/modules/valid_path.rs
new file mode 100644
index 00000000000..6a1519c3fc4
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/modules/valid_path.rs
@@ -0,0 +1 @@
+fn unused() {}
diff --git a/gcc/testsuite/rust/compile/torture/must_use1.rs b/gcc/testsuite/rust/compile/torture/must_use1.rs
new file mode 100644
index 00000000000..95a6657c8c1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/must_use1.rs
@@ -0,0 +1,16 @@
+#[must_use = "TEST 1"]
+fn test1() -> i32 {
+    123
+}
+
+#[must_use = "TEST 2"]
+fn test2() -> i32 {
+    456
+}
+
+fn main() {
+    let _a = test1();
+
+    test2();
+    // { dg-warning "ignoring return value of" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/must_use2.rs b/gcc/testsuite/rust/compile/torture/must_use2.rs
new file mode 100644
index 00000000000..466f7ee7a14
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/must_use2.rs
@@ -0,0 +1,16 @@
+trait A {
+    #[must_use]
+    fn test() -> i32;
+}
+
+struct S;
+impl A for S {
+    fn test() -> i32 {
+        123
+    }
+}
+
+fn main() {
+    S::test();
+    // { dg-warning "ignoring return value of" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/name_resolve1.rs b/gcc/testsuite/rust/compile/torture/name_resolve1.rs
new file mode 100644
index 00000000000..817f48b60ee
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/name_resolve1.rs
@@ -0,0 +1,23 @@
+struct Foo(i32, bool);
+
+impl Foo {
+    fn new(a: i32, b: bool) -> Foo {
+        Foo(a, b)
+    }
+
+    fn test() -> i32 {
+        test()
+    }
+}
+
+fn test() -> i32 {
+    123
+}
+
+fn main() {
+    let a;
+    a = Foo::new(1, true);
+
+    let b;
+    b = Foo::test();
+}
diff --git a/gcc/testsuite/rust/compile/torture/negation_function.rs b/gcc/testsuite/rust/compile/torture/negation_function.rs
new file mode 100644
index 00000000000..b592f9c00ef
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/negation_function.rs
@@ -0,0 +1,7 @@
+fn ret1() -> i32 {
+    return 1;
+}
+
+fn main() {
+    let _a = -ret1();
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/torture/nested_fn1.rs b/gcc/testsuite/rust/compile/torture/nested_fn1.rs
new file mode 100644
index 00000000000..075b5dba8e0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/nested_fn1.rs
@@ -0,0 +1,10 @@
+pub fn main() {
+    let a = 123;
+
+    fn test(x: i32) -> i32 {
+        x + 456
+    }
+
+    let b;
+    b = test(a);
+}
diff --git a/gcc/testsuite/rust/compile/torture/nested_fn2.rs b/gcc/testsuite/rust/compile/torture/nested_fn2.rs
new file mode 100644
index 00000000000..7040c862e75
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/nested_fn2.rs
@@ -0,0 +1,11 @@
+pub fn main() {
+    fn test<T>(x: T) -> T {
+        x
+    }
+
+    let mut a = 123;
+    a = test(a);
+
+    let mut b = 456f32;
+    b = test(b);
+}
diff --git a/gcc/testsuite/rust/compile/torture/nested_struct1.rs b/gcc/testsuite/rust/compile/torture/nested_struct1.rs
new file mode 100644
index 00000000000..2bd5eadd4c4
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/nested_struct1.rs
@@ -0,0 +1,20 @@
+struct Point {
+    x: f64,
+    y: f64,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+struct Rectangle {
+    p1: Point,
+    p2: Point,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+fn main() {
+    let p1 = Point { x: 0.0, y: 0.0 };
+    let p2 = Point { x: 2.0, y: 4.0 };
+    let rect = Rectangle { p1, p2 };
+
+    let a = rect.p1.x;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/never_type1.rs b/gcc/testsuite/rust/compile/torture/never_type1.rs
new file mode 100644
index 00000000000..0f15029097d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/never_type1.rs
@@ -0,0 +1,22 @@
+fn foo() -> i32 {
+    let c;
+    let d;
+
+    c = if false {
+        return 1;
+    } else {
+        0.0
+    };
+
+    d = if true {
+        0.0
+    } else {
+        return 1;
+    };
+
+    0
+}
+
+fn main() {
+    foo();
+}
diff --git a/gcc/testsuite/rust/compile/torture/not_shebang.rs b/gcc/testsuite/rust/compile/torture/not_shebang.rs
new file mode 100644
index 00000000000..37e01b65940
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/not_shebang.rs
@@ -0,0 +1,3 @@
+#!
+[allow(unused)]
+fn main () { }
diff --git a/gcc/testsuite/rust/compile/torture/not_shebang_block_comment.rs b/gcc/testsuite/rust/compile/torture/not_shebang_block_comment.rs
new file mode 100644
index 00000000000..662f6506749
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/not_shebang_block_comment.rs
@@ -0,0 +1 @@
+#!/*/this/is/a/comment*/[allow(unused)] fn main () { }
diff --git a/gcc/testsuite/rust/compile/torture/not_shebang_comment.rs b/gcc/testsuite/rust/compile/torture/not_shebang_comment.rs
new file mode 100644
index 00000000000..273ae4e8e2a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/not_shebang_comment.rs
@@ -0,0 +1,3 @@
+#!//this/is/a/comment
+[allow(unused)]   
+fn main () { }
diff --git a/gcc/testsuite/rust/compile/torture/not_shebang_multiline_comment.rs b/gcc/testsuite/rust/compile/torture/not_shebang_multiline_comment.rs
new file mode 100644
index 00000000000..86800b14cb3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/not_shebang_multiline_comment.rs
@@ -0,0 +1,7 @@
+#!//this/is/a/comment
+
+/* Also a /* nested */
+   multiline // comment
+   with some more whitespace after, but then finally a [, so not a real #! line.  */
+
+[allow(unused)] fn main () { }
diff --git a/gcc/testsuite/rust/compile/torture/not_shebang_spaces.rs b/gcc/testsuite/rust/compile/torture/not_shebang_spaces.rs
new file mode 100644
index 00000000000..6b94a69111a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/not_shebang_spaces.rs
@@ -0,0 +1,6 @@
+#!   
+
+    [allow(unused)]   
+
+        fn main () { }
+    
diff --git a/gcc/testsuite/rust/compile/torture/parameter_usage1.rs b/gcc/testsuite/rust/compile/torture/parameter_usage1.rs
new file mode 100644
index 00000000000..448e9603a94
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/parameter_usage1.rs
@@ -0,0 +1,8 @@
+fn test(a: i32, b: i32) -> i32 {
+    a + b
+}
+
+fn main() {
+    let a = test(1, 4);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/parens1.rs b/gcc/testsuite/rust/compile/torture/parens1.rs
new file mode 100644
index 00000000000..795eb960805
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/parens1.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let a = 123;
+    let b = a + (a * 2);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/pointer1.rs b/gcc/testsuite/rust/compile/torture/pointer1.rs
new file mode 100644
index 00000000000..f283411abe2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/pointer1.rs
@@ -0,0 +1,9 @@
+pub fn main() {
+    let mut num = 2;
+    let r1: *const i32 = &num;
+    let r2 = unsafe { *r1 } + unsafe { *r1 };
+    let r3 = num;
+    num = 4;
+    let r4 = num + unsafe { *r1 } * r3;
+    let _eightteen = r2 + r3 + r4;
+}
diff --git a/gcc/testsuite/rust/compile/torture/primconsts.rs b/gcc/testsuite/rust/compile/torture/primconsts.rs
new file mode 100644
index 00000000000..bcf9456d059
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/primconsts.rs
@@ -0,0 +1,72 @@
+const TRUE: bool = true;
+const FALSE: bool = !TRUE;
+
+const U8ZERO: u8 = 0;
+const U8ONE: u8 = U8ZERO + 1;
+const U16ZERO: u16 = 0;
+const U16ONE: u16 = U16ZERO + 1;
+const U32ZERO: u32 = 0;
+const U32ONE: u32 = U32ZERO + 1;
+const U64ZERO: u64 = 0;
+const U64ONE: u64 = U64ZERO + 1;
+const U128ZERO: u128 = 0;
+const U128ONE: u128 = U128ZERO + 1;
+
+const I8ZERO: i8 = 0;
+const I8ONE: i8 = I8ZERO + 1;
+const I16ZERO: i16 = 0;
+const I16ONE: i16 = I16ZERO + 1;
+const I32ZERO: i32 = 0;
+const I32ONE: i32 = I32ZERO + 1;
+const I64ZERO: i64 = 0;
+const I64ONE: i64 = I64ZERO + 1;
+const I128ZERO: i128 = 0;
+const I128ONE: i128 = I128ZERO + 1;
+
+const F32ZERO: f32 = 0.0;
+const F32ONE: f32 = F32ZERO + 1.0;
+const F64ZERO: f64 = 0.0;
+const F64ONE: f64 = F64ZERO + 1.0;
+
+const USIZEZERO: usize = 0;
+const USIZEONE: usize = USIZEZERO + 1;
+const ISIZEZERO: isize = 0;
+const ISIZEONE: isize = ISIZEZERO + 1;
+
+/* Not yet supported 
+const CHARPI: char = '\u{03C0}';
+const STRHELLO: &str = "Hello World!";
+*/
+
+extern "C" { fn abort (); }
+
+pub fn main ()
+{
+  if TRUE == FALSE { unsafe { abort (); } }
+  if U8ZERO > U8ONE { unsafe { abort (); } }
+  if U16ZERO > U16ONE { unsafe { abort (); } }
+  if U32ZERO > U32ONE { unsafe { abort (); } }
+  if U64ZERO > U64ONE { unsafe { abort (); } }
+  if U128ZERO > U128ONE { unsafe { abort (); } }
+
+  if I8ONE <= I8ZERO { unsafe { abort (); } }
+  if I16ONE <= I16ZERO { unsafe { abort (); } }
+  if I32ONE <= I32ZERO { unsafe { abort (); } }
+  if I64ONE <= I64ZERO { unsafe { abort (); } }
+  if I128ONE <= I128ZERO { unsafe { abort (); } }
+
+  if F32ZERO + F32ONE != F32ONE { unsafe { abort (); } }
+  if F64ZERO + F64ONE != F64ONE { unsafe { abort (); } }
+
+  if USIZEZERO + USIZEONE - USIZEONE + USIZEZERO != USIZEZERO
+    {
+      unsafe { abort (); }
+    }
+  if ISIZEZERO + ISIZEONE - ISIZEONE + ISIZEZERO != ISIZEZERO
+    {
+      unsafe { abort (); }
+    }
+
+ // if CHARPI != '\u{03c0}'  { unsafe { abort (); } }
+ // if STRHELLO != "Hello World!" { unsafe { abort (); } }
+}
diff --git a/gcc/testsuite/rust/compile/torture/prims_struct_eq.rs b/gcc/testsuite/rust/compile/torture/prims_struct_eq.rs
new file mode 100644
index 00000000000..81ab7424627
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/prims_struct_eq.rs
@@ -0,0 +1,91 @@
+extern "C"
+{
+  fn abort ();
+}
+
+struct Prims
+{
+  b1: bool,
+  b2: bool,
+  b3: bool,
+  b4: bool,
+  c1: char,
+  c2: char,
+  u81: u8,
+  u82: u8,
+  u83: u8,
+  u84: u8,
+  i81: i8,
+  i82: i8,
+  i83: i8,
+  i84: i8,
+  u161: u16,
+  u162: u16,
+  i161: i16,
+  i162: i16,
+  u321: u32,
+  u322: u32,
+  i321: i32,
+  i322: i32,
+  u641: u64,
+  i641: i64,
+  u1281: u128,
+  i1281: i128,
+  usize1: usize,
+  isize1: isize,
+}
+
+fn prims_eq (p1: Prims, p2: Prims) -> bool
+{
+  return p1.b1 == p2.b1
+         && p1.b2 == p2.b2
+         && p1.b3 == p2.b3
+         && p1.b4 == p2.b4
+         && p1.c1 == p2.c1
+         && p1.c2 == p2.c2
+         && p1.u81 == p2.u81
+         && p1.u82 == p2.u82
+         && p1.u83 == p2.u83
+         && p1.u84 == p2.u84
+         && p1.i81 == p2.i81
+         && p1.i82 == p2.i82
+         && p1.i83 == p2.i83
+         && p1.i84 == p2.i84
+         && p1.u161 == p2.u161
+         && p1.u162 == p2.u162
+         && p1.i161 == p2.i161
+         && p1.i162 == p2.i162
+         && p1.u321 == p2.u321
+         && p1.u322 == p2.u322
+         && p1.i321 == p2.i321
+         && p1.i322 == p2.i322
+         && p1.u641 == p2.u641
+         && p1.i641 == p2.i641
+         && p1.u1281 == p2.u1281
+         && p1.i1281 == p2.i1281
+         && p1.usize1 == p2.usize1
+         && p1.isize1 == p2.isize1;
+}
+
+pub fn main ()
+{
+  let p1 = Prims { b1: true, b2: false, b3: false, b4: true,
+                   c1: 'a', c2: 'b',
+                   u81: 1, u82: 2, u83: 3, u84: 4,
+                   i81: -1, i82: -2, i83: -3, i84: -4,
+                   u161: 1, u162: 2,
+                   i161: -1, i162: -2,
+                   u321: 1, u322: 2,
+                   i321: -1, i322: -2,
+                   u641: 1,
+                   i641: -1,
+                   u1281: 1,
+                   i1281: -1,
+                   usize1: 1,
+                   isize1: -1 };
+  let p2 = Prims { usize1: 1, .. p1 };
+  let p3 = Prims { u1281: 0, .. p2 };
+  let p4 = Prims { i1281: 0, .. p3 };
+  if !prims_eq (p1, p2) { unsafe { abort (); } }
+  if prims_eq (p3, p4) { unsafe { abort (); } }
+}
diff --git a/gcc/testsuite/rust/compile/torture/range-lang-item1.rs b/gcc/testsuite/rust/compile/torture/range-lang-item1.rs
new file mode 100644
index 00000000000..86946162276
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/range-lang-item1.rs
@@ -0,0 +1,32 @@
+// { dg-additional-options "-w" }
+#[lang = "RangeFull"]
+pub struct RangeFull;
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+    pub start: Idx,
+    pub end: Idx,
+}
+
+#[lang = "RangeFrom"]
+pub struct RangeFrom<Idx> {
+    pub start: Idx,
+}
+
+#[lang = "RangeTo"]
+pub struct RangeTo<Idx> {
+    pub end: Idx,
+}
+
+#[lang = "RangeInclusive"]
+pub struct RangeInclusive<Idx> {
+    pub start: Idx,
+    pub end: Idx,
+}
+
+fn test() {
+    let a = 1..2; // range
+    let b = 1..; // range from
+    let c = ..3; // range to
+    let d = 0..=2; // range inclusive
+}
diff --git a/gcc/testsuite/rust/compile/torture/raw_identifiers.rs b/gcc/testsuite/rust/compile/torture/raw_identifiers.rs
new file mode 100644
index 00000000000..8746f337048
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/raw_identifiers.rs
@@ -0,0 +1,3 @@
+pub fn square(num: i32) -> i32 { /* { dg-warning "used" } */
+    r#num * num
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/torture/raw_identifiers_keywords.rs b/gcc/testsuite/rust/compile/torture/raw_identifiers_keywords.rs
new file mode 100644
index 00000000000..c9aa3cf4938
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/raw_identifiers_keywords.rs
@@ -0,0 +1,3 @@
+pub fn plus(r#break: i32, r#unsafe: i32) -> i32 { /* { dg-warning "used" } */
+    r#break + r#unsafe
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/torture/recursive_fn1.rs b/gcc/testsuite/rust/compile/torture/recursive_fn1.rs
new file mode 100644
index 00000000000..e13b41f70bd
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/recursive_fn1.rs
@@ -0,0 +1,12 @@
+fn gcd(x: i32, y: i32) -> i32 {
+    if y == 0 {
+        x
+    } else {
+        gcd(y, x % y)
+    }
+}
+
+fn main() {
+    let a = gcd(100, 5);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/return_function.rs b/gcc/testsuite/rust/compile/torture/return_function.rs
new file mode 100644
index 00000000000..084adaf7f24
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/return_function.rs
@@ -0,0 +1,5 @@
+fn foo() {}
+
+fn main() {
+    return foo();
+}
diff --git a/gcc/testsuite/rust/compile/torture/scoping1.rs b/gcc/testsuite/rust/compile/torture/scoping1.rs
new file mode 100644
index 00000000000..8bc8ede5f7c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/scoping1.rs
@@ -0,0 +1,11 @@
+fn main() {
+    let x = 1;
+    {
+        let mut x = true;
+        {
+            x = false;
+        }
+    }
+    let x = x + 1;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/self_type1.rs b/gcc/testsuite/rust/compile/torture/self_type1.rs
new file mode 100644
index 00000000000..373d6dd5a60
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/self_type1.rs
@@ -0,0 +1,12 @@
+struct Foo(i32, bool);
+
+impl Foo {
+    fn new(a: i32, b: bool) -> Self {
+        Self(a, b)
+    }
+}
+
+fn main() {
+    let a;
+    a = Foo::new(1, true);
+}
diff --git a/gcc/testsuite/rust/compile/torture/shadow1.rs b/gcc/testsuite/rust/compile/torture/shadow1.rs
new file mode 100644
index 00000000000..b60e7936de9
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/shadow1.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let mut x = 5;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let mut x;
+    x = true;
+}
diff --git a/gcc/testsuite/rust/compile/torture/shadow2.rs b/gcc/testsuite/rust/compile/torture/shadow2.rs
new file mode 100644
index 00000000000..161dc380a07
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/shadow2.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let x = 1;
+    let x = x + 1;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/shebang.rs b/gcc/testsuite/rust/compile/torture/shebang.rs
new file mode 100755
index 00000000000..1c8b9c9a955
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/shebang.rs
@@ -0,0 +1,3 @@
+#!/usr/bin/env cat 
+
+fn main () { }
diff --git a/gcc/testsuite/rust/compile/torture/shebang_plus_attr.rs b/gcc/testsuite/rust/compile/torture/shebang_plus_attr.rs
new file mode 100755
index 00000000000..075bc6cf594
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/shebang_plus_attr.rs
@@ -0,0 +1,3 @@
+#!/usr/bin/env cat 
+#![allow(unused)]
+fn main () { }
diff --git a/gcc/testsuite/rust/compile/torture/shebang_plus_attr2.rs b/gcc/testsuite/rust/compile/torture/shebang_plus_attr2.rs
new file mode 100755
index 00000000000..ece8a52381c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/shebang_plus_attr2.rs
@@ -0,0 +1,3 @@
+#!//usr/bin/env cat 
+#![allow(unused)]
+fn main () { }
diff --git a/gcc/testsuite/rust/compile/torture/static_function.rs b/gcc/testsuite/rust/compile/torture/static_function.rs
new file mode 100644
index 00000000000..8e3a3795023
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/static_function.rs
@@ -0,0 +1,8 @@
+fn test(x: i32) -> i32 {
+    return x + 1;
+}
+
+fn main() {
+    let call_test = test(1);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/static_var1.rs b/gcc/testsuite/rust/compile/torture/static_var1.rs
new file mode 100644
index 00000000000..5be0e75ce72
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/static_var1.rs
@@ -0,0 +1,6 @@
+static x:i32 = 3;
+
+fn main() {
+    let y = x +1;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/stmt_with_block1.rs b/gcc/testsuite/rust/compile/torture/stmt_with_block1.rs
new file mode 100644
index 00000000000..b6aa56cc2e6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/stmt_with_block1.rs
@@ -0,0 +1,13 @@
+fn test(x: i32) -> i32 {
+    if x > 1 { 1 } else { 2 };
+    if x > 1 { 1; } else { 2; }
+
+    { 3; }
+    { 3 };
+
+    { 3 }
+}
+
+fn main() {
+    let a = test(0); // { dg-warning "unused name" }
+}
diff --git a/gcc/testsuite/rust/compile/torture/str1.rs b/gcc/testsuite/rust/compile/torture/str1.rs
new file mode 100644
index 00000000000..088827853d8
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/str1.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let a;
+    a = "hello world infer";
+
+    let b: &str;
+    b = "hello world specified";
+}
diff --git a/gcc/testsuite/rust/compile/torture/struct_access1.rs b/gcc/testsuite/rust/compile/torture/struct_access1.rs
new file mode 100644
index 00000000000..ec85d289fb5
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/struct_access1.rs
@@ -0,0 +1,12 @@
+struct Foo {
+    one: i32,
+    two: i32,
+}
+
+fn main() {
+    let struct_test = Foo { one: 1, two: 2 };
+    let a = struct_test.one;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let b = struct_test.two;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/struct_base_init_1.rs b/gcc/testsuite/rust/compile/torture/struct_base_init_1.rs
new file mode 100644
index 00000000000..ee00c2c468b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/struct_base_init_1.rs
@@ -0,0 +1,13 @@
+struct Foo {
+    a: i32,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+    b: i32,
+}
+
+fn foo() -> Foo {
+    Foo { a: 42, b: 32 }
+}
+
+fn main() {
+    let _f = Foo { a: 10, ..foo() };
+}
diff --git a/gcc/testsuite/rust/compile/torture/struct_decl.rs b/gcc/testsuite/rust/compile/torture/struct_decl.rs
new file mode 100644
index 00000000000..9e8ea6b100b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/struct_decl.rs
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fdump-tree-gimple -frust-crate=example" }
+
+struct Foo {
+    a: u16,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+    b: u8,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+fn main() {
+    let my_foo = Foo { a: 1, b: 2 };
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    // { dg-final { scan-tree-dump-times {(?n)const struct example::Foo my_foo;$} 1 gimple } }
+}
diff --git a/gcc/testsuite/rust/compile/torture/struct_init.rs b/gcc/testsuite/rust/compile/torture/struct_init.rs
new file mode 100644
index 00000000000..1926f73b21d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/struct_init.rs
@@ -0,0 +1,11 @@
+struct Foo {
+    one: i32,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+    two: i32,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+fn main() {
+    let struct_test = Foo { one: 1, two: 2 };
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/struct_init_10.rs b/gcc/testsuite/rust/compile/torture/struct_init_10.rs
new file mode 100644
index 00000000000..7fbceb03974
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/struct_init_10.rs
@@ -0,0 +1,9 @@
+fn main() {
+    struct foo {
+        a: i32,
+        b: f32,
+    };
+
+    let a;
+    a = foo { a: 123, b: 456f32 };
+}
diff --git a/gcc/testsuite/rust/compile/torture/struct_init_11.rs b/gcc/testsuite/rust/compile/torture/struct_init_11.rs
new file mode 100644
index 00000000000..16a2f072566
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/struct_init_11.rs
@@ -0,0 +1,34 @@
+pub fn main() {
+    struct O(i32);
+    struct T(i32, i32);
+    struct M(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32);
+
+    // tuples
+    let z = ();
+    let o = (0,);
+    let f = o.0;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let t = (0, 1);
+    let s = t.1;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let m = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+    let l = m.10;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    // tuple structs
+    let so = O(0);
+    let sf = so.0;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let st = T(0, 1);
+    let fs = st.1;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let sm = M(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+    let sl = sm.10;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    z
+}
diff --git a/gcc/testsuite/rust/compile/torture/struct_init_2.rs b/gcc/testsuite/rust/compile/torture/struct_init_2.rs
new file mode 100644
index 00000000000..d7040d3d96d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/struct_init_2.rs
@@ -0,0 +1,6 @@
+struct Foo(f32, f32);
+
+fn main() {
+    let a = Foo { 0: 10.0, 1: 20.0 };
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/struct_init_3.rs b/gcc/testsuite/rust/compile/torture/struct_init_3.rs
new file mode 100644
index 00000000000..1398f8e7b86
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/struct_init_3.rs
@@ -0,0 +1,13 @@
+struct Foo {
+    a: i32,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+    b: i32,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+fn main() {
+    let a = 1;
+    let b = 2;
+    let c = Foo { a, b };
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/struct_init_4.rs b/gcc/testsuite/rust/compile/torture/struct_init_4.rs
new file mode 100644
index 00000000000..2b2746aba7a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/struct_init_4.rs
@@ -0,0 +1,13 @@
+struct Foo {
+    a: i32,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+    b: i32,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+fn main() {
+    let a = Foo { a: 1, b: 2 };
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let b = Foo { a: 3, b: 4, ..a };
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/struct_init_5.rs b/gcc/testsuite/rust/compile/torture/struct_init_5.rs
new file mode 100644
index 00000000000..891f64540fe
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/struct_init_5.rs
@@ -0,0 +1,10 @@
+struct Foo {
+    a: i32,
+    b: i32,
+}
+
+fn main() {
+    let a = Foo { a: 1, b: 2 };
+    let b = Foo { ..a };
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/struct_init_6.rs b/gcc/testsuite/rust/compile/torture/struct_init_6.rs
new file mode 100644
index 00000000000..9fc52ed5c50
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/struct_init_6.rs
@@ -0,0 +1,11 @@
+struct Foo {
+    a: i32,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+    b: i32,
+}
+
+fn main() {
+    let a = Foo { a: 1, b: 2 };
+    let b = Foo { a: 1, ..a };
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/struct_init_7.rs b/gcc/testsuite/rust/compile/torture/struct_init_7.rs
new file mode 100644
index 00000000000..36dc00aca60
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/struct_init_7.rs
@@ -0,0 +1,11 @@
+struct Foo {
+    a: i32,
+    b: f32,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+fn main() {
+    let c = Foo { a: 1, b: 2f32 };
+    let b = Foo { b: 4f32, ..c };
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/struct_init_8.rs b/gcc/testsuite/rust/compile/torture/struct_init_8.rs
new file mode 100644
index 00000000000..411ff7d1c6f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/struct_init_8.rs
@@ -0,0 +1,7 @@
+struct Foo(f32, i32);
+
+fn main() {
+    let a = Foo { 1: 1, 0: 2f32 };
+    let b = Foo { ..a };
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/struct_init_9.rs b/gcc/testsuite/rust/compile/torture/struct_init_9.rs
new file mode 100644
index 00000000000..2daa078d5b3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/struct_init_9.rs
@@ -0,0 +1,6 @@
+fn main() {
+    struct foo(i32, f32);
+
+    let a;
+    a = foo(123, 456f32);
+}
diff --git a/gcc/testsuite/rust/compile/torture/top_attr.rs b/gcc/testsuite/rust/compile/torture/top_attr.rs
new file mode 100644
index 00000000000..0671369cb12
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/top_attr.rs
@@ -0,0 +1,5 @@
+#![crate_name = "name"]
+
+
+#[allow(dead_code)]
+fn main() {}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/torture/traits1.rs b/gcc/testsuite/rust/compile/torture/traits1.rs
new file mode 100644
index 00000000000..90357738a81
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits1.rs
@@ -0,0 +1,16 @@
+trait Foo {
+    fn bar() -> i32;
+}
+
+struct Test(i32, f32);
+
+impl Foo for Test {
+    fn bar() -> i32 {
+        123
+    }
+}
+
+fn main() {
+    let a: i32;
+    a = Test::bar();
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits10.rs b/gcc/testsuite/rust/compile/torture/traits10.rs
new file mode 100644
index 00000000000..a02927007b3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits10.rs
@@ -0,0 +1,30 @@
+trait Foo // where
+//     Self: Sized,
+{
+    fn get(self) -> i32;
+
+    fn test(self) -> i32 {
+        self.get()
+    }
+}
+
+struct Bar(i32);
+impl Foo for Bar {
+    fn get(self) -> i32 {
+        self.0
+    }
+}
+
+fn main() {
+    let a;
+    a = Bar(123);
+
+    let b;
+    b = Bar::get(a);
+
+    let a;
+    a = Bar(123);
+
+    let b;
+    b = a.test();
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits11.rs b/gcc/testsuite/rust/compile/torture/traits11.rs
new file mode 100644
index 00000000000..41c82f01b6d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits11.rs
@@ -0,0 +1,31 @@
+trait Foo {
+    type A;
+
+    fn test(a: Self::A) -> Self::A {
+        a
+    }
+}
+
+struct Bar(i32);
+impl Foo for Bar {
+    type A = i32;
+}
+
+struct Baz(f32);
+impl Foo for Baz {
+    type A = f32;
+}
+
+fn main() {
+    let a;
+    a = Bar(123);
+
+    let b;
+    b = Bar::test(a.0);
+
+    let c;
+    c = Baz(123f32);
+
+    let d;
+    d = Baz::test(c.0);
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits12.rs b/gcc/testsuite/rust/compile/torture/traits12.rs
new file mode 100644
index 00000000000..a55b965baf0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits12.rs
@@ -0,0 +1,29 @@
+trait Foo {
+    type A;
+
+    fn test(a: Self::A) -> Self::A {
+        a
+    }
+}
+
+struct Bar(i32);
+// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+
+impl Foo for Bar {
+    type A = i32;
+}
+
+struct Baz(f32);
+// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+
+impl Foo for Baz {
+    type A = f32;
+}
+
+fn main() {
+    let a: <Baz as Foo>::A;
+    a = 123f32;
+
+    let b;
+    b = <Baz as Foo>::test(a);
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits13.rs b/gcc/testsuite/rust/compile/torture/traits13.rs
new file mode 100644
index 00000000000..326f0390756
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits13.rs
@@ -0,0 +1,17 @@
+trait Trait {
+    const FOO: usize;
+    type Target;
+}
+
+struct S;
+// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+
+impl Trait for S {
+    const FOO: usize = 0;
+    type Target = usize;
+}
+
+fn main() {
+    let a: <S as Trait>::Target;
+    a = <S as Trait>::FOO;
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits14.rs b/gcc/testsuite/rust/compile/torture/traits14.rs
new file mode 100644
index 00000000000..8bca0d5c1f6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits14.rs
@@ -0,0 +1,23 @@
+trait Foo<T> {
+    type A;
+
+    fn test(a: T) -> T {
+        a
+    }
+}
+
+struct Bar<T>(T);
+impl<T> Foo<T> for Bar<T> {
+    type A = T;
+}
+
+pub fn main() {
+    let a;
+    a = Bar(123);
+
+    let b: <Bar<i32> as Foo<i32>>::A;
+    b = 456;
+
+    let c: <Bar<i32> as Foo<i32>>::A;
+    c = <Bar<i32> as Foo<i32>>::test(a.0);
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits15.rs b/gcc/testsuite/rust/compile/torture/traits15.rs
new file mode 100644
index 00000000000..c8c40b78b45
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits15.rs
@@ -0,0 +1,23 @@
+trait Foo<T> {
+    type A;
+
+    fn test(a: T, b: Self::A) -> (T, Self::A) {
+        (a, b)
+    }
+}
+
+struct Bar<T>(T);
+impl<T> Foo<T> for Bar<T> {
+    type A = T;
+}
+
+pub fn main() {
+    let a;
+    a = Bar(123);
+
+    let b: <Bar<i32> as Foo<i32>>::A;
+    b = 456;
+
+    let c;
+    c = <Bar<i32> as Foo<i32>>::test(a.0, 123);
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits16.rs b/gcc/testsuite/rust/compile/torture/traits16.rs
new file mode 100644
index 00000000000..afc4a86de6d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits16.rs
@@ -0,0 +1,20 @@
+trait A {
+    fn a() -> i32 {
+        123
+    }
+
+    fn b() -> i32 {
+        Self::a() + 456
+    }
+}
+
+struct S;
+impl A for S {}
+
+fn main() {
+    let a;
+    a = S::a();
+
+    let b;
+    b = S::b();
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits17.rs b/gcc/testsuite/rust/compile/torture/traits17.rs
new file mode 100644
index 00000000000..6da8bcb0082
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits17.rs
@@ -0,0 +1,23 @@
+trait A {
+    fn a() -> i32 {
+        123
+    }
+}
+
+trait B: A {
+    fn b() -> i32 {
+        Self::a() + 456
+    }
+}
+
+struct S;
+impl A for S {}
+impl B for S {}
+
+fn main() {
+    let a;
+    a = S::a();
+
+    let b;
+    b = S::b();
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits18.rs b/gcc/testsuite/rust/compile/torture/traits18.rs
new file mode 100644
index 00000000000..63319dd2daa
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits18.rs
@@ -0,0 +1,5 @@
+trait Foo<'a> {}
+
+trait Bar {
+    type Item: for<'a> Foo<'a>;
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits19.rs b/gcc/testsuite/rust/compile/torture/traits19.rs
new file mode 100644
index 00000000000..4412656f535
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits19.rs
@@ -0,0 +1,33 @@
+// { dg-additional-options "-w" }
+trait Get {
+    type Value;
+    fn get(&self) -> &<Self as Get>::Value;
+}
+
+struct Struct {
+    x: isize,
+}
+
+impl Get for Struct {
+    type Value = isize;
+    fn get(&self) -> &isize {
+        &self.x
+    }
+}
+
+trait Grab {
+    type U;
+    fn grab(&self) -> &<Self as Grab>::U;
+}
+
+impl<T: Get> Grab for T {
+    type U = <T as Get>::Value;
+    fn grab(&self) -> &<T as Get>::Value {
+        self.get()
+    }
+}
+
+fn main() {
+    let s = Struct { x: 100 };
+    let a = s.grab();
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits2.rs b/gcc/testsuite/rust/compile/torture/traits2.rs
new file mode 100644
index 00000000000..fc6eb6002e0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits2.rs
@@ -0,0 +1,16 @@
+trait Foo {
+    fn bar() -> i32;
+}
+
+struct Test<T>(T);
+
+impl<T> Foo for Test<T> {
+    fn bar() -> i32 {
+        123
+    }
+}
+
+fn main() {
+    let a: i32;
+    a = Test::<i32>::bar();
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits3.rs b/gcc/testsuite/rust/compile/torture/traits3.rs
new file mode 100644
index 00000000000..deeb81e0946
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits3.rs
@@ -0,0 +1,15 @@
+pub trait Foo {
+    fn Bar(self) -> i32;
+}
+
+struct Baz;
+// { dg-warning "struct is never constructed: .Baz." "" { target *-*-* } .-1 }
+
+impl Foo for Baz {
+    fn Bar(self) -> i32 {
+        // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
+        123
+    }
+}
+
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/torture/traits4.rs b/gcc/testsuite/rust/compile/torture/traits4.rs
new file mode 100644
index 00000000000..67b012c11f5
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits4.rs
@@ -0,0 +1,21 @@
+trait Foo {
+    type A;
+    type B;
+
+    fn new(a: Self::A, b: Self::B) -> Self;
+}
+
+struct Baz(i32, f32);
+
+impl Foo for Baz {
+    type A = i32;
+    type B = f32;
+
+    fn new(a: Self::A, b: Self::B) -> Self {
+        Baz(a, b)
+    }
+}
+
+fn main() {
+    Baz::new(123, 456f32);
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits5.rs b/gcc/testsuite/rust/compile/torture/traits5.rs
new file mode 100644
index 00000000000..445b0658f5c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits5.rs
@@ -0,0 +1,21 @@
+trait Foo {
+    type A;
+    type B;
+
+    fn new(a: Self::A, b: Self::B) -> Self;
+}
+
+struct Baz(i32, f32);
+
+impl Foo for Baz {
+    type A = i32;
+    type B = f32;
+
+    fn new(a: i32, b: f32) -> Self {
+        Baz(a, b)
+    }
+}
+
+fn main() {
+    Baz::new(123, 456f32);
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits6.rs b/gcc/testsuite/rust/compile/torture/traits6.rs
new file mode 100644
index 00000000000..260dde3f465
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits6.rs
@@ -0,0 +1,20 @@
+trait Foo {
+    type A;
+
+    fn baz(a: Self::A) -> Self::A;
+}
+
+struct Bar<T>(T);
+
+impl<T> Foo for Bar<T> {
+    type A = T;
+
+    fn baz(a: Self::A) -> T {
+        a
+    }
+}
+
+fn main() {
+    let a;
+    a = Bar::<i32>::baz(123);
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits7.rs b/gcc/testsuite/rust/compile/torture/traits7.rs
new file mode 100644
index 00000000000..7bc3384ab41
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits7.rs
@@ -0,0 +1,19 @@
+trait Foo {
+    const A: i32;
+
+    fn test(self);
+}
+
+struct Bar;
+impl Foo for Bar {
+    const A: i32 = 123;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    fn test(self) {}
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
+
+fn main() {
+    let a = Bar;
+    a.test();
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits8.rs b/gcc/testsuite/rust/compile/torture/traits8.rs
new file mode 100644
index 00000000000..459032fb4a2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits8.rs
@@ -0,0 +1,21 @@
+trait Foo {
+    fn default() -> i32;
+}
+
+struct Bar(i32);
+// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+
+impl Foo for Bar {
+    fn default() -> i32 {
+        123
+    }
+}
+
+fn type_bound_test<T: Foo>() -> i32 {
+    T::default()
+}
+
+fn main() {
+    let a;
+    a = type_bound_test::<Bar>();
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits9.rs b/gcc/testsuite/rust/compile/torture/traits9.rs
new file mode 100644
index 00000000000..89e4bf19b0c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits9.rs
@@ -0,0 +1,27 @@
+trait Foo {
+    fn default() -> i32;
+    fn get(self) -> i32;
+}
+
+struct Bar(i32);
+impl Foo for Bar {
+    fn default() -> i32 {
+        123
+    }
+
+    fn get(self) -> i32 {
+        self.0
+    }
+}
+
+fn type_bound_test<T: Foo>(a: T) -> i32 {
+    T::default() + a.get()
+}
+
+fn main() {
+    let a;
+    a = Bar(456);
+
+    let b;
+    b = type_bound_test(a);
+}
diff --git a/gcc/testsuite/rust/compile/torture/transmute-size-check-1.rs b/gcc/testsuite/rust/compile/torture/transmute-size-check-1.rs
new file mode 100644
index 00000000000..461a35de8ef
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/transmute-size-check-1.rs
@@ -0,0 +1,11 @@
+mod mem {
+    extern "rust-intrinsic" {
+        fn size_of<T>() -> usize;
+        fn transmute<U, V>(_: U) -> V; // { dg-error "cannot transmute between types of different sizes, or dependently-sized types" }
+    }
+}
+
+fn main() {
+    let a = 123;
+    let _b: [u32; mem::size_of::<i32>()] = unsafe { mem::transmute(a) };
+}
diff --git a/gcc/testsuite/rust/compile/torture/transmute1.rs b/gcc/testsuite/rust/compile/torture/transmute1.rs
new file mode 100644
index 00000000000..af9a55d1b97
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/transmute1.rs
@@ -0,0 +1,11 @@
+mod mem {
+    extern "rust-intrinsic" {
+        fn size_of<T>() -> usize;
+        fn transmute<U, V>(_: U) -> V;
+    }
+}
+
+fn main() {
+    let a = 123;
+    let _b: [u8; mem::size_of::<i32>()] = unsafe { mem::transmute(a) };
+}
diff --git a/gcc/testsuite/rust/compile/torture/tuple1.rs b/gcc/testsuite/rust/compile/torture/tuple1.rs
new file mode 100644
index 00000000000..9e6f613f682
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/tuple1.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let a: (i32, bool) = (123, true);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let b;
+    b = (456, 5f32);
+}
diff --git a/gcc/testsuite/rust/compile/torture/tuple2.rs b/gcc/testsuite/rust/compile/torture/tuple2.rs
new file mode 100644
index 00000000000..ab3d0b8715b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/tuple2.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let a = 123;
+    let b = (a,);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/tuple3.rs b/gcc/testsuite/rust/compile/torture/tuple3.rs
new file mode 100644
index 00000000000..d0fb6fc4429
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/tuple3.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let a = (1, true);
+
+    let b;
+    let c;
+
+    b = a.0;
+    c = a.1;
+}
diff --git a/gcc/testsuite/rust/compile/torture/tuple_enum_variants.rs b/gcc/testsuite/rust/compile/torture/tuple_enum_variants.rs
new file mode 100644
index 00000000000..d953e3d89a1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/tuple_enum_variants.rs
@@ -0,0 +1,23 @@
+enum E {
+    T0(),
+    T1(i32),
+    T2(i32, u32),
+}
+
+/* The following doesn't parse yet...
+fn f(e0: E, e1: E, e2: E) -> (E,E,E,())
+{
+  let e = e0;
+  let f = e1;
+  let g = e2;
+  (e,f,g,())
+}
+
+fn main()
+{
+  let e0 = E::T0();
+  let e1 = E::T1(0);
+  let e2 = E::T2(0,1);
+  f(e0, e1, e2).3
+}
+*/
diff --git a/gcc/testsuite/rust/compile/torture/tuple_field_access.rs b/gcc/testsuite/rust/compile/torture/tuple_field_access.rs
new file mode 100644
index 00000000000..8d1bbe9906c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/tuple_field_access.rs
@@ -0,0 +1,6 @@
+struct Foo(i32, i32);
+
+fn main() {
+    let mut a = Foo(1, 2);
+    a.0 = 22;
+}
diff --git a/gcc/testsuite/rust/compile/torture/tuple_function.rs b/gcc/testsuite/rust/compile/torture/tuple_function.rs
new file mode 100644
index 00000000000..514b586cc09
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/tuple_function.rs
@@ -0,0 +1,6 @@
+fn foo() -> i32 {
+    return 1;
+}
+fn main() {
+    let _a = (foo(), 2);
+}
diff --git a/gcc/testsuite/rust/compile/torture/tuple_index.rs b/gcc/testsuite/rust/compile/torture/tuple_index.rs
new file mode 100644
index 00000000000..f904fae9b5b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/tuple_index.rs
@@ -0,0 +1,32 @@
+fn main()
+{
+  // tuples
+  let z = ();
+
+  let o = (0,);
+  let _f = o.0;
+
+  let t = (0,1);
+  let _s = t.1;
+
+  let m = (0,1,2,3,4,5,6,7,8,9,10);
+  let _l = m.10;
+
+  // tuple structs
+  struct E();
+  let _e = E();
+
+  struct O(i32);
+  let so = O(0);
+  let _sf = so.0;
+
+  struct T(i32,i32);
+  let st = T(0,1);
+  let _fs = st.1;
+
+  struct M(i32,i32,i32,i32,i32,i32,i32,i32,i32,i32,i32);
+  let sm = M(0,1,2,3,4,5,6,7,8,9,10);
+  let _sl = sm.10;
+
+  z
+}
diff --git a/gcc/testsuite/rust/compile/torture/tuple_struct1.rs b/gcc/testsuite/rust/compile/torture/tuple_struct1.rs
new file mode 100644
index 00000000000..0ac19b179a9
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/tuple_struct1.rs
@@ -0,0 +1,6 @@
+struct Foo(i32, i32, bool);
+
+fn main() {
+    let a = Foo(1, 2, true);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/tuple_struct2.rs b/gcc/testsuite/rust/compile/torture/tuple_struct2.rs
new file mode 100644
index 00000000000..5e0a76e1de8
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/tuple_struct2.rs
@@ -0,0 +1,11 @@
+struct Foo(i32, bool);
+
+fn main() {
+    let a = Foo(1, true);
+
+    let b;
+    let c;
+
+    b = a.0;
+    c = a.1;
+}
diff --git a/gcc/testsuite/rust/compile/torture/tuple_struct_unit.rs b/gcc/testsuite/rust/compile/torture/tuple_struct_unit.rs
new file mode 100644
index 00000000000..cda19d2af0b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/tuple_struct_unit.rs
@@ -0,0 +1,11 @@
+struct E();
+struct T(E,E,());
+
+fn main()
+{
+  let z0 = E();
+  let z1 = E();
+  let t = T(z0,z1,());
+  let z = t.2;
+  z
+}
diff --git a/gcc/testsuite/rust/compile/torture/tuple_struct_unused.rs b/gcc/testsuite/rust/compile/torture/tuple_struct_unused.rs
new file mode 100644
index 00000000000..8da0a50632b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/tuple_struct_unused.rs
@@ -0,0 +1,4 @@
+struct Foo(i32, i32);
+// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/torture/type-alias1.rs b/gcc/testsuite/rust/compile/torture/type-alias1.rs
new file mode 100644
index 00000000000..78bf0461036
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/type-alias1.rs
@@ -0,0 +1,6 @@
+type TypeAlias = (i32, u32);
+
+fn main() {
+    let a: TypeAlias;
+    a = (123, 456);
+}
diff --git a/gcc/testsuite/rust/compile/torture/type-alias2.rs b/gcc/testsuite/rust/compile/torture/type-alias2.rs
new file mode 100644
index 00000000000..a3e3f4e6851
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/type-alias2.rs
@@ -0,0 +1,8 @@
+type x = u32;
+
+fn main() {
+    let x: x = 1;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let y: x = 2;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/type_infer1.rs b/gcc/testsuite/rust/compile/torture/type_infer1.rs
new file mode 100644
index 00000000000..3fee7282bde
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/type_infer1.rs
@@ -0,0 +1,24 @@
+struct Foo {
+    one: i32,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+    two: i32,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+fn test(x: i32) -> i32 {
+    return x + 1;
+}
+
+fn main() {
+    let logical: bool = true;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let an_integer = 5;
+    let mut default_integer = 7;
+
+    default_integer = 1 + an_integer;
+
+    let call_test = test(1);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let struct_test = Foo { one: 1, two: 2 };
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/type_infer2.rs b/gcc/testsuite/rust/compile/torture/type_infer2.rs
new file mode 100644
index 00000000000..dcddda42729
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/type_infer2.rs
@@ -0,0 +1,9 @@
+fn test(x: i32) -> i32 {
+    return x + 1;
+}
+
+fn main() {
+    let an_integer = 5;
+    let call_test = test(an_integer + 1);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/type_infer3.rs b/gcc/testsuite/rust/compile/torture/type_infer3.rs
new file mode 100644
index 00000000000..303dd3d1f18
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/type_infer3.rs
@@ -0,0 +1,14 @@
+fn test(x: i32) -> i32 {
+    return x + 1;
+}
+
+fn main() {
+    let mut an_integer = 5;
+    an_integer = test(1) + 3;
+
+    let mut x;
+    x = 1;
+
+    let call_test = test(1);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/type_infer4.rs b/gcc/testsuite/rust/compile/torture/type_infer4.rs
new file mode 100644
index 00000000000..77a919f262a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/type_infer4.rs
@@ -0,0 +1,11 @@
+fn main() {
+    let xs: [i32; 5] = [1, 2, 3, 4, 5];
+    let xy = [6, 7, 8];
+
+    let a = xs[0];
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let b = xy[2];
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let mut c;
+    c = xs[0];
+}
diff --git a/gcc/testsuite/rust/compile/torture/type_infer5.rs b/gcc/testsuite/rust/compile/torture/type_infer5.rs
new file mode 100644
index 00000000000..2c2602a161f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/type_infer5.rs
@@ -0,0 +1,13 @@
+struct Foo {
+    a: i32,
+    b: i32,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+fn main() {
+    let a;
+    a = Foo { a: 1, b: 2 };
+
+    let b = a.a;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/type_infer6.rs b/gcc/testsuite/rust/compile/torture/type_infer6.rs
new file mode 100644
index 00000000000..6f5863f0107
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/type_infer6.rs
@@ -0,0 +1,14 @@
+fn test(x: u32) -> u32 {
+    return x + 1;
+}
+
+fn main() {
+    let a;
+    a = 1;
+    let b = test(a);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let c = 1;
+    let d = test(c + 1);
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/unary_operators.rs b/gcc/testsuite/rust/compile/torture/unary_operators.rs
new file mode 100644
index 00000000000..9be729c04e3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/unary_operators.rs
@@ -0,0 +1,8 @@
+// { dg-prune-output "warning: unused name" } as there are many of these expected.
+
+fn main() {
+    let a: i32 = -1;
+    let b: i32 = 3 - -1;
+    let c: bool = !false;
+    let d: i32 = !3;
+}
diff --git a/gcc/testsuite/rust/compile/torture/undended-string-1.rs b/gcc/testsuite/rust/compile/torture/undended-string-1.rs
new file mode 100644
index 00000000000..66f0cd52269
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/undended-string-1.rs
@@ -0,0 +1,5 @@
+// { dg-excess-errors "...." }
+fn main() {
+    // { dg-error "unended string literal" "" { target *-*-* } .+1 }
+    let s = "123
+}
diff --git a/gcc/testsuite/rust/compile/torture/undended-string-2.rs b/gcc/testsuite/rust/compile/torture/undended-string-2.rs
new file mode 100644
index 00000000000..c0f424927c2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/undended-string-2.rs
@@ -0,0 +1,5 @@
+// { dg-excess-errors "...." }
+fn main() {
+    // { dg-error "unended byte string literal" "" { target *-*-* } .+1 }
+    let s = b"123
+}
diff --git a/gcc/testsuite/rust/compile/torture/underscore_id.rs b/gcc/testsuite/rust/compile/torture/underscore_id.rs
new file mode 100644
index 00000000000..2c106c55df9
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/underscore_id.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let _unused_but_fine = 12;
+    let unused = 12; // { dg-warning "unused name" }
+}
diff --git a/gcc/testsuite/rust/compile/torture/union.rs b/gcc/testsuite/rust/compile/torture/union.rs
new file mode 100644
index 00000000000..724168817ad
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/union.rs
@@ -0,0 +1,32 @@
+union U
+{
+  f1: u8
+}
+
+union V
+{
+  f1: u8,
+  f2: u16,
+  f3: i32,
+}
+
+struct S
+{
+  f1: U,
+  f2: V
+}
+
+fn main ()
+{
+  let u = U { f1: 16 };
+  let v = V { f2: 365 };
+  let s = S { f1: u, f2: v };
+  let _v125 = unsafe
+    { let mut uv: u64;
+      uv = s.f1.f1 as u64;
+      uv += s.f2.f1 as u64;
+      uv += s.f2.f2 as u64;
+      uv -= s.f2.f3 as u64;
+      uv
+    };
+}
diff --git a/gcc/testsuite/rust/compile/torture/union_union.rs b/gcc/testsuite/rust/compile/torture/union_union.rs
new file mode 100644
index 00000000000..9feb145a692
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/union_union.rs
@@ -0,0 +1,27 @@
+union union
+{
+  union: u32,
+  inion: i32,
+  u8ion: u8,
+  i64on: i64,
+  u64on: u64
+}
+
+pub fn main ()
+{
+  let union = union { union: 2 };
+  let inion = union { inion: -2 };
+  let mut mnion = union { inion: -16 };
+  let m1 = unsafe { mnion.union };
+  unsafe { mnion.union = union.union };
+  let m2 = unsafe { mnion.inion };
+  let u1 = unsafe { union.union };
+  let i1 = unsafe { union.inion };
+  let u2 = unsafe { inion.union };
+  let i2 = unsafe { inion.inion };
+  let _r1 = u2 - u1 - m1;
+  let _r2 = i1 + i2 + m2;
+  let _u8 = unsafe { union.u8ion };
+  let _i64 = unsafe { union.i64on };
+  let _u64 = unsafe { union.u64on };
+}
diff --git a/gcc/testsuite/rust/compile/torture/unit_type1.rs b/gcc/testsuite/rust/compile/torture/unit_type1.rs
new file mode 100644
index 00000000000..d5f73575745
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/unit_type1.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let a: () = ();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    let b;
+    b = ();
+}
diff --git a/gcc/testsuite/rust/compile/torture/unit_type2.rs b/gcc/testsuite/rust/compile/torture/unit_type2.rs
new file mode 100644
index 00000000000..b5f925907d8
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/unit_type2.rs
@@ -0,0 +1,8 @@
+fn test(a: ()) -> () {
+    a
+}
+
+fn main() {
+    let a;
+    a = test(());
+}
diff --git a/gcc/testsuite/rust/compile/torture/unit_type3.rs b/gcc/testsuite/rust/compile/torture/unit_type3.rs
new file mode 100644
index 00000000000..d48a691046b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/unit_type3.rs
@@ -0,0 +1,6 @@
+struct S;
+
+fn main() {
+    let s = S;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/unit_type4.rs b/gcc/testsuite/rust/compile/torture/unit_type4.rs
new file mode 100644
index 00000000000..ccbfa21818a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/unit_type4.rs
@@ -0,0 +1,5 @@
+struct S;
+
+fn main() {
+    let _s = S {};
+}
diff --git a/gcc/testsuite/rust/compile/torture/unit_type5.rs b/gcc/testsuite/rust/compile/torture/unit_type5.rs
new file mode 100644
index 00000000000..3c4323aa73c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/unit_type5.rs
@@ -0,0 +1,8 @@
+struct Foo;
+
+fn main() {
+    let a = Foo {};
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let b = Foo;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/unsafe1.rs b/gcc/testsuite/rust/compile/torture/unsafe1.rs
new file mode 100644
index 00000000000..f57ef52b9c0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/unsafe1.rs
@@ -0,0 +1,12 @@
+fn test() -> i32 {
+    unsafe {
+        let a;
+        a = 123;
+        a
+    }
+}
+
+fn main() {
+    let a;
+    a = test();
+}
diff --git a/gcc/testsuite/rust/compile/torture/unsafe2.rs b/gcc/testsuite/rust/compile/torture/unsafe2.rs
new file mode 100644
index 00000000000..0b3aad53a44
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/unsafe2.rs
@@ -0,0 +1,4 @@
+fn main() {
+    unsafe {}
+    ()
+}
diff --git a/gcc/testsuite/rust/compile/torture/unsafe3.rs b/gcc/testsuite/rust/compile/torture/unsafe3.rs
new file mode 100644
index 00000000000..5f427258f60
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/unsafe3.rs
@@ -0,0 +1,9 @@
+pub fn test() -> i32 {
+    let a = unsafe { 123 };
+    a
+}
+
+pub fn main() {
+    let a = test();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/unsafe4.rs b/gcc/testsuite/rust/compile/torture/unsafe4.rs
new file mode 100644
index 00000000000..6fe3101d49c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/unsafe4.rs
@@ -0,0 +1,12 @@
+struct SS {
+    one: i32,
+    two: i32,
+}
+struct TS(i32, i32);
+
+fn main() {
+    unsafe {
+        let ss = SS { one: 1, two: 2 };
+        let _ts = TS(ss.one, ss.two);
+    };
+}
diff --git a/gcc/testsuite/rust/compile/torture/unused.rs b/gcc/testsuite/rust/compile/torture/unused.rs
new file mode 100644
index 00000000000..d95e6b01c00
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/unused.rs
@@ -0,0 +1,17 @@
+// { dg-warning "function is never used: 'bar'" "" { target *-*-* } .+1 }
+fn bar() {
+    foo();
+}
+
+// { dg-warning "function is never used: 'foo'" "" { target *-*-* } .+1 }
+fn foo() {
+    bar();
+}
+
+fn f() {
+
+}
+
+fn main() {
+    f();
+}
diff --git a/gcc/testsuite/rust/compile/torture/unused1.rs b/gcc/testsuite/rust/compile/torture/unused1.rs
new file mode 100644
index 00000000000..db7eb8fc1fc
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/unused1.rs
@@ -0,0 +1,15 @@
+fn test() -> i32 {
+    1
+}
+
+fn unused() -> i32 {
+    // { dg-warning "function is never used: 'unused'" "" { target *-*-* } .-1 }
+    2
+}
+
+fn main() {
+    let a = 1;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+    let b = test();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/unused_struct.rs b/gcc/testsuite/rust/compile/torture/unused_struct.rs
new file mode 100644
index 00000000000..ba9ec3250cf
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/unused_struct.rs
@@ -0,0 +1,7 @@
+struct Foo {
+    // { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+    one: i32,
+    two: i32,
+}
+
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/torture/unused_struct_field.rs b/gcc/testsuite/rust/compile/torture/unused_struct_field.rs
new file mode 100644
index 00000000000..429b3039da4
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/unused_struct_field.rs
@@ -0,0 +1,9 @@
+struct Foo {
+    one: i32,
+// { dg-warning "field is never read" "" { target *-*-* } .-1 }
+    two: i32
+}
+fn main() {
+    let _a = Foo {one: 1, two: 2};
+    let _b = _a.two;
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/torture/usize1.rs b/gcc/testsuite/rust/compile/torture/usize1.rs
new file mode 100644
index 00000000000..ba1d5c60320
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/usize1.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let a = [1, 2, 3];
+    let b: usize = 1;
+    let c = a[b];
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/very-broken-attr-string.rs b/gcc/testsuite/rust/compile/torture/very-broken-attr-string.rs
new file mode 100644
index 00000000000..832ba7b8ec9
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/very-broken-attr-string.rs
@@ -0,0 +1,3 @@
+// { dg-excess-errors "...." }
+// { dg-error "unended string literal" "" { target *-*-* } .+1 }
+#[doc(alias = "123
diff --git a/gcc/testsuite/rust/compile/torture/while_function.rs b/gcc/testsuite/rust/compile/torture/while_function.rs
new file mode 100644
index 00000000000..014db902769
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/while_function.rs
@@ -0,0 +1,10 @@
+fn foo() {}
+fn bar() -> i32 { return 10; }
+
+fn main() {
+	let mut i = 1;
+	while i < bar() {
+		foo();
+		i += 1;
+	}
+}
diff --git a/gcc/testsuite/rust/compile/traits1.rs b/gcc/testsuite/rust/compile/traits1.rs
new file mode 100644
index 00000000000..355064eec1a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/traits1.rs
@@ -0,0 +1,13 @@
+trait Foo {
+    fn Bar() -> i32 {}
+    // { dg-error "expected .i32. got .()." "" { target *-*-* } .-1 }
+}
+
+struct Baz;
+
+impl Foo for Baz {
+    fn Barrr() {}
+    // { dg-error "method .Barrr. is not a member of trait .Foo." "" { target *-*-* } .-1 }
+}
+
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/traits10.rs b/gcc/testsuite/rust/compile/traits10.rs
new file mode 100644
index 00000000000..f8f551ba86d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/traits10.rs
@@ -0,0 +1,15 @@
+struct Foo(i32);
+
+trait Bar {
+    const A: i32 = 123;
+    fn B();
+    fn C(&self);
+}
+
+pub fn main() {
+    let a;
+    a = Foo(123);
+
+    let b: &dyn Bar = &a;
+    // { dg-error "trait bound is not object safe" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/traits11.rs b/gcc/testsuite/rust/compile/traits11.rs
new file mode 100644
index 00000000000..d06e47d7e16
--- /dev/null
+++ b/gcc/testsuite/rust/compile/traits11.rs
@@ -0,0 +1,19 @@
+struct Foo(i32);
+
+trait A {
+    const A: i32 = 123;
+    fn B();
+    fn C(&self);
+}
+
+trait B: A {
+    fn test(&self);
+}
+
+pub fn main() {
+    let a;
+    a = Foo(123);
+
+    let b: &dyn B = &a;
+    // { dg-error "trait bound is not object safe" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/traits12.rs b/gcc/testsuite/rust/compile/traits12.rs
new file mode 100644
index 00000000000..25e0eb7aaa3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/traits12.rs
@@ -0,0 +1,20 @@
+trait A<T> {
+    type Output;
+
+    fn test(self, a: &T) -> &Self::Output;
+}
+
+struct Foo<T> {
+    start: T,
+    end: T,
+}
+
+impl<T> A for Foo<usize> {
+    // { dg-error "generic item takes at least 1 type arguments but 0 were supplied" "" { target *-*-* } .-1 }
+    // { dg-error "unconstrained type parameter" "" { target *-*-* } .-2 }
+    type Output = T;
+
+    fn test(self, a: &T) -> &Self::Output {
+        a
+    }
+}
diff --git a/gcc/testsuite/rust/compile/traits2.rs b/gcc/testsuite/rust/compile/traits2.rs
new file mode 100644
index 00000000000..7357c22f7d6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/traits2.rs
@@ -0,0 +1,14 @@
+trait Foo {
+    fn Bar() -> i32 {}
+    // { dg-error "expected .i32. got .()." "" { target *-*-* } .-1 }
+}
+
+struct Baz;
+
+impl Foo for Baz {
+    fn Bar() {}
+    // { dg-error "expected .i32. got .()." "" { target *-*-* } .-1 }
+    // { dg-error "method .Bar. has an incompatible type for trait .Foo." "" { target *-*-* } .-2 }
+}
+
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/traits3.rs b/gcc/testsuite/rust/compile/traits3.rs
new file mode 100644
index 00000000000..fd3fa457cc8
--- /dev/null
+++ b/gcc/testsuite/rust/compile/traits3.rs
@@ -0,0 +1,22 @@
+trait Foo {
+    type A;
+
+    fn baz(a: Self::A) -> Self::A;
+}
+
+struct Bar<T>(T);
+
+impl<T> Foo for Bar<T> {
+    type A = i32;
+
+    fn baz(a: f32) -> f32 {
+        // { dg-error "method .baz. has an incompatible type for trait .Foo." "" { target *-*-* } .-1 }
+        a
+        // { dg-error "expected .i32. got .f32." "" { target *-*-* } .-1 }
+    }
+}
+
+fn main() {
+    let a;
+    a = Bar::<i32>::baz(123f32);
+}
diff --git a/gcc/testsuite/rust/compile/traits4.rs b/gcc/testsuite/rust/compile/traits4.rs
new file mode 100644
index 00000000000..486301d6136
--- /dev/null
+++ b/gcc/testsuite/rust/compile/traits4.rs
@@ -0,0 +1,16 @@
+trait Foo {
+    const A: i32;
+
+    fn test(self);
+}
+
+struct Bar;
+impl Foo for Bar {
+    // { dg-error "missing A in implementation of trait .Foo." "" { target *-*-* } .-1 }
+    fn test(self) {}
+}
+
+fn main() {
+    let a = Bar;
+    a.test();
+}
diff --git a/gcc/testsuite/rust/compile/traits5.rs b/gcc/testsuite/rust/compile/traits5.rs
new file mode 100644
index 00000000000..8b2fb9bc10d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/traits5.rs
@@ -0,0 +1,9 @@
+trait Foo {
+    const A: i32;
+
+    fn test(self);
+}
+
+struct Bar;
+impl Foo for Bar {}
+// { dg-error "missing A, test in implementation of trait .Foo." "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/rust/compile/traits6.rs b/gcc/testsuite/rust/compile/traits6.rs
new file mode 100644
index 00000000000..3579b5a0842
--- /dev/null
+++ b/gcc/testsuite/rust/compile/traits6.rs
@@ -0,0 +1,15 @@
+trait Foo {
+    fn default() -> i32;
+}
+
+struct Bar(i32);
+
+fn type_bound_test<T: Foo>() -> i32 {
+    T::default()
+}
+
+fn main() {
+    let a;
+    a = type_bound_test::<Bar>();
+    // { dg-error "bounds not satisfied for Bar" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/traits7.rs b/gcc/testsuite/rust/compile/traits7.rs
new file mode 100644
index 00000000000..825553ce496
--- /dev/null
+++ b/gcc/testsuite/rust/compile/traits7.rs
@@ -0,0 +1,24 @@
+trait Foo {
+    fn default() -> i32;
+}
+
+trait Bar {
+    fn not_default() -> i32;
+}
+
+struct Test(i32);
+
+impl Foo for Test {
+    fn default() -> i32 {
+        1234
+    }
+}
+
+fn type_bound_test<T: Foo + Bar>() -> i32 {
+    T::default()
+}
+
+fn main() {
+    let a = type_bound_test::<Test>();
+    // { dg-error "bounds not satisfied for Test" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/traits8.rs b/gcc/testsuite/rust/compile/traits8.rs
new file mode 100644
index 00000000000..b22590a52bb
--- /dev/null
+++ b/gcc/testsuite/rust/compile/traits8.rs
@@ -0,0 +1,35 @@
+trait A {
+    fn get(self) -> f64;
+}
+
+trait B {
+    fn get(self) -> u8;
+}
+
+struct Foo(u8, f64);
+
+impl A for Foo {
+    fn get(self) -> f64 {
+        self.1
+    }
+}
+
+impl B for Foo {
+    fn get(self) -> u8 {
+        self.0
+    }
+}
+
+fn main() {
+    let _a;
+    _a = Foo(123, 456f64);
+
+    let _b: f64;
+    _b = <Foo as A>::get(_a);
+
+    let _a;
+    _a = Foo(123, 456f64);
+
+    let _c: u8;
+    _c = <Foo as B>::get(_a)
+}
diff --git a/gcc/testsuite/rust/compile/traits9.rs b/gcc/testsuite/rust/compile/traits9.rs
new file mode 100644
index 00000000000..e1aef5397fc
--- /dev/null
+++ b/gcc/testsuite/rust/compile/traits9.rs
@@ -0,0 +1,13 @@
+struct Foo(i32);
+trait Bar {
+    fn baz(&self);
+}
+
+fn main() {
+    let a;
+    a = Foo(123);
+
+    let b: &dyn Bar = &a;
+    // { dg-error "bounds not satisfied for Foo .Bar. is not satisfied" "" { target *-*-* } .-1 }
+    // { dg-error "expected" "" { target *-*-* } .-2 }
+}
diff --git a/gcc/testsuite/rust/compile/tuple1.rs b/gcc/testsuite/rust/compile/tuple1.rs
new file mode 100644
index 00000000000..84179b13727
--- /dev/null
+++ b/gcc/testsuite/rust/compile/tuple1.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let a: (i32, bool) = (123, 123); // { dg-error "expected .bool. got .<integer>." }
+    let b;
+    b = (456, 5f32);
+}
diff --git a/gcc/testsuite/rust/compile/tuple_struct1.rs b/gcc/testsuite/rust/compile/tuple_struct1.rs
new file mode 100644
index 00000000000..2f4cb4a353b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/tuple_struct1.rs
@@ -0,0 +1,8 @@
+struct Foo {
+    one: i32,
+    two: i32,
+}
+
+fn main() {
+    let a = Foo(1, 2); // { dg-error "expected function, tuple struct or tuple variant, found struct 'Foo'" }
+}
diff --git a/gcc/testsuite/rust/compile/tuple_struct2.rs b/gcc/testsuite/rust/compile/tuple_struct2.rs
new file mode 100644
index 00000000000..1fc18968577
--- /dev/null
+++ b/gcc/testsuite/rust/compile/tuple_struct2.rs
@@ -0,0 +1,5 @@
+struct Bar(i32, i32, bool);
+
+fn main() {
+    let a = Bar(1, 2); // { dg-error "unexpected number of arguments 2 expected 3" }
+}
diff --git a/gcc/testsuite/rust/compile/tuple_struct3.rs b/gcc/testsuite/rust/compile/tuple_struct3.rs
new file mode 100644
index 00000000000..4af66b8370e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/tuple_struct3.rs
@@ -0,0 +1,6 @@
+struct Foo(i32, i32, bool);
+
+fn main() {
+    let c = Foo(1, 2f32, true);
+    // { dg-error "expected .i32. got .f32." "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/type-alias1.rs b/gcc/testsuite/rust/compile/type-alias1.rs
new file mode 100644
index 00000000000..c7d7048246a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/type-alias1.rs
@@ -0,0 +1,6 @@
+type TypeAlias = (i32, u32);
+
+fn main() {
+    let a: TypeAlias;
+    a = (123, 456f32); // { dg-error "expected .u32. got .f32." }
+}
diff --git a/gcc/testsuite/rust/compile/type-bindings1.rs b/gcc/testsuite/rust/compile/type-bindings1.rs
new file mode 100644
index 00000000000..ad85ed97ecb
--- /dev/null
+++ b/gcc/testsuite/rust/compile/type-bindings1.rs
@@ -0,0 +1,10 @@
+struct Foo<A, B>(A, B);
+
+fn main() {
+    let a;
+    a = Foo::<A = i32, B = f32>(123f32);
+    // { dg-error "associated type bindings are not allowed here" "" { target *-*-* } .-1 }
+    // { dg-error {failed to type resolve expression} "" { target *-*-* } .-2 }
+    // { dg-error {Failed to resolve expression of function call} "" { target *-*-* } .-3 }
+    // { duplicate _dg-error {failed to type resolve expression} "" { target *-*-* } .-4 }
+}
diff --git a/gcc/testsuite/rust/compile/unary_negation.rs b/gcc/testsuite/rust/compile/unary_negation.rs
new file mode 100644
index 00000000000..848643f0bd2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unary_negation.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let a: i32 = -1;
+    let b: i32 = 3 - -1;
+    let c: bool = !false;
+    let d: i32 = !3;
+
+    let e: f32 = -true; // // { dg-error "cannot apply unary - to bool" }
+    // { dg-error {failed to type resolve expression} "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/unary_not.rs b/gcc/testsuite/rust/compile/unary_not.rs
new file mode 100644
index 00000000000..b0a3dafbbd0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unary_not.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let a: i32 = -1;
+    let b: i32 = 3 - -1;
+    let c: bool = !false;
+    let d: i32 = !3;
+
+    let e: f32 = !5f32; // { dg-error "cannot apply unary '!' to f32" }
+    // { dg-error {failed to type resolve expression} "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/unconstrained_type_param.rs b/gcc/testsuite/rust/compile/unconstrained_type_param.rs
new file mode 100644
index 00000000000..c4aaa10146f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unconstrained_type_param.rs
@@ -0,0 +1,12 @@
+struct Foo<T>(T, bool);
+
+impl<X, Y> Foo<X> {
+    // { dg-error "unconstrained type parameter" "" { target *-*-* } .-1 }
+    fn test() -> Y {
+        123
+    }
+}
+
+fn main() {
+    let a = Foo::test();
+}
diff --git a/gcc/testsuite/rust/compile/unicode_escape.rs b/gcc/testsuite/rust/compile/unicode_escape.rs
new file mode 100644
index 00000000000..39b91d8a95c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unicode_escape.rs
@@ -0,0 +1,60 @@
+fn main ()
+{
+  // Braces are required
+  let _cbl = '\u013'; // { dg-error "unicode escape" }
+  let _sbl = "\u013"; //{ dg-error "unicode escape" }
+
+  // One to six hex digits
+  let _c0 = '\u{}'; // { dg-error "unicode escape" }
+  let _c1 = '\u{0}';
+  let _c2 = '\u{00}';
+  let _c3 = '\u{000}';
+  let _c4 = '\u{0000}';
+  let _c5 = '\u{00000}';
+  let _c6 = '\u{000000}';
+  let _c7 = '\u{0000000}'; // { dg-error "unicode escape" }
+
+  let _s0 = "\u{}"; // { dg-error "unicode escape" }
+  let _s1 = "\u{0}";
+  let _s2 = "\u{00}";
+  let _s3 = "\u{000}";
+  let _s4 = "\u{0000}";
+  let _s5 = "\u{00000}";
+  let _s6 = "\u{000000}";
+  let _s7 = "\u{0000000}"; // { dg-error "unicode escape" }
+
+  // Underscores OK except for start
+  let _c_ = '\u{00___01__0_1_}';
+  let _s_ = "\u{00___01__0_1_}";
+  let _c__ = '\u{_00__01__0_}'; // { dg-error "unicode escape" }
+  let _s__ = "\u{_00__01__0_}"; // { dg-error "unicode escape" }
+
+  // Must be hex chars
+  let _chex = '\u{hex}';  // { dg-error "unicode escape" }
+  let _shex = '\u{hex}';  // { dg-error "unicode escape" }
+
+  // Only valid from 0x0 to 0xD7FF and from 0xE000 to 0x10FFF
+  let _cd7ff = '\u{D7FF}';
+  let _sd7ff = "\u{D7FF}";
+  let _cd800 = '\u{D800}'; // { dg-error "unicode escape" }
+  let _sd800 = "\u{D800}"; // { dg-error "unicode escape" }
+
+  let _cdfff = '\u{DFFF}'; // { dg-error "unicode escape" }
+  let _sdfff = "\u{DFFF}"; // { dg-error "unicode escape" }
+  let _ce000 = '\u{E000}';
+  let _se000 = "\u{E000}";
+
+  let _clast = '\u{10FFFF}';
+  let _slast = "\u{10FFFF}";
+  let _clast1 = '\u{110000}'; // { dg-error "unicode escape" }
+  let _slast1 = "\u{110000}"; // { dg-error "unicode escape" }
+
+  let _cffffff = '\u{FFFFFF}'; // { dg-error "unicode escape" }
+  let _sffffff = "\u{FFFFFF}"; // { dg-error "unicode escape" }
+
+  // unicode escapes cannot be used in bytes or byte strings.
+  // Except in raw byte strings (where they aren't escapes).
+  let _bc = b'\u{000A}'; // { dg-error "unicode escape" }
+  let _bs = b"\u{000A}"; // { dg-error "unicode escape" }
+  let _rbs = br"\u{000A}";
+}
diff --git a/gcc/testsuite/rust/compile/unsafe1.rs b/gcc/testsuite/rust/compile/unsafe1.rs
new file mode 100644
index 00000000000..9cd3f6b4bf2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unsafe1.rs
@@ -0,0 +1,14 @@
+fn foo(_a: &i32) {}
+fn bar(_a: i32) {}
+
+static mut a: i32 = 15;
+
+fn main() {
+    foo(&a); // { dg-error "use of mutable static" }
+    bar(a); // { dg-error "use of mutable static" }
+
+    unsafe {
+        foo(&a);
+        bar(a);
+    }
+}
diff --git a/gcc/testsuite/rust/compile/unsafe10.rs b/gcc/testsuite/rust/compile/unsafe10.rs
new file mode 100644
index 00000000000..6b6be06b908
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unsafe10.rs
@@ -0,0 +1,12 @@
+extern "rust-intrinsic" {
+    pub fn rotate_left<T>(l: T, r: T) -> T;
+}
+
+fn main() -> i32 {
+    let a = 15;
+    let b = 15;
+
+    let _ = rotate_left(a, b);
+
+    0
+}
diff --git a/gcc/testsuite/rust/compile/unsafe2.rs b/gcc/testsuite/rust/compile/unsafe2.rs
new file mode 100644
index 00000000000..e03e4bc59f4
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unsafe2.rs
@@ -0,0 +1,16 @@
+fn foo(_a: &i32) {}
+fn bar(_a: i32) {}
+
+mod inner {
+    pub static mut a: i32 = 15;
+}
+
+fn main() {
+    foo(&inner::a); // { dg-error "use of mutable static" }
+    bar(inner::a); // { dg-error "use of mutable static" }
+
+    unsafe {
+        foo(&inner::a);
+        bar(inner::a);
+    }
+}
diff --git a/gcc/testsuite/rust/compile/unsafe3.rs b/gcc/testsuite/rust/compile/unsafe3.rs
new file mode 100644
index 00000000000..56aec76008a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unsafe3.rs
@@ -0,0 +1,10 @@
+extern "C" {
+    static VALUE: char;
+}
+
+fn main() {
+    let _ = VALUE; // { dg-error "use of extern static" }
+    unsafe {
+        let _ = VALUE;
+    }
+}
diff --git a/gcc/testsuite/rust/compile/unsafe4.rs b/gcc/testsuite/rust/compile/unsafe4.rs
new file mode 100644
index 00000000000..7d1356bc3e5
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unsafe4.rs
@@ -0,0 +1,29 @@
+fn foo() -> i32 {
+    let a = 15;
+    let p_a = &a as *const i32;
+
+    unsafe { *p_a }
+}
+
+unsafe fn bar() -> i32 {
+    let a = 15;
+    let p_a = &a as *const i32;
+
+    *p_a
+}
+
+fn baz() -> i32 {
+    let a = 15;
+    let p_a = &a as *const i32;
+
+    *p_a // { dg-error "dereference of raw pointer" }
+}
+
+unsafe fn qux() -> i32 {
+    let a = 15;
+    let p_a = &a as *const i32;
+
+    unsafe {}
+
+    *p_a
+}
diff --git a/gcc/testsuite/rust/compile/unsafe5.rs b/gcc/testsuite/rust/compile/unsafe5.rs
new file mode 100644
index 00000000000..35990f6ee9f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unsafe5.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let b = 15;
+    let c = *(&b as *const i32); // { dg-error "dereference of raw pointer" }
+}
diff --git a/gcc/testsuite/rust/compile/unsafe6.rs b/gcc/testsuite/rust/compile/unsafe6.rs
new file mode 100644
index 00000000000..cf4b75456e4
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unsafe6.rs
@@ -0,0 +1,14 @@
+unsafe fn foo() {}
+unsafe fn bar() {
+    foo();
+}
+
+fn main() {
+    foo(); // { dg-error "call to unsafe function" }
+    bar(); // { dg-error "call to unsafe function" }
+
+    unsafe {
+        foo();
+        bar();
+    }
+}
diff --git a/gcc/testsuite/rust/compile/unsafe7.rs b/gcc/testsuite/rust/compile/unsafe7.rs
new file mode 100644
index 00000000000..a6b69e1ac37
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unsafe7.rs
@@ -0,0 +1,9 @@
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn main() {
+    let s = "hey\0";
+
+    printf(s as *const str as *const i8); // { dg-error "call to extern function" }
+}
diff --git a/gcc/testsuite/rust/compile/unsafe8.rs b/gcc/testsuite/rust/compile/unsafe8.rs
new file mode 100644
index 00000000000..03fe4910c97
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unsafe8.rs
@@ -0,0 +1,14 @@
+struct S;
+
+impl S {
+    unsafe fn foo(self) {}
+}
+
+fn main() {
+    let s = S;
+    s.foo(); // { dg-error "call to unsafe method" }
+
+    unsafe {
+        s.foo();
+    }
+}
diff --git a/gcc/testsuite/rust/compile/unsafe9.rs b/gcc/testsuite/rust/compile/unsafe9.rs
new file mode 100644
index 00000000000..fb46c8ffde3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unsafe9.rs
@@ -0,0 +1,10 @@
+union U {
+    a: i32,
+    b: f32,
+    c: u8,
+}
+
+fn main() {
+    let u = U { a: 14 };
+    let _ = u.a; // { dg-error "access to union" }
+}
diff --git a/gcc/testsuite/rust/compile/unterminated_c_comment.rs b/gcc/testsuite/rust/compile/unterminated_c_comment.rs
new file mode 100644
index 00000000000..619b7b7024d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unterminated_c_comment.rs
@@ -0,0 +1,2 @@
+// { dg-error "unexpected EOF while looking for end of comment" "" { target *-*-* } .+1 }
+/* This  comment needs closure :) !
diff --git a/gcc/testsuite/rust/compile/use_1.rs b/gcc/testsuite/rust/compile/use_1.rs
new file mode 100644
index 00000000000..94b96321a63
--- /dev/null
+++ b/gcc/testsuite/rust/compile/use_1.rs
@@ -0,0 +1,16 @@
+mod frob {}
+
+use foo::bar::baz; // { dg-error "cannot find simple path segment .foo." }
+use frob::ulator; // { dg-error "cannot find simple path segment .ulator." }
+
+mod sain {
+    mod doux {}
+
+    mod dron {}
+}
+
+use not_sain::*; // { dg-error "cannot find simple path segment .not_sain." }
+
+use sain::*;
+use sain::{doux, dron};
+use sain::{doux, dron, graal}; // { dg-error "cannot find simple path segment .graal." }
diff --git a/gcc/testsuite/rust/compile/usize1.rs b/gcc/testsuite/rust/compile/usize1.rs
new file mode 100644
index 00000000000..b1c8fe86473
--- /dev/null
+++ b/gcc/testsuite/rust/compile/usize1.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let a = [1, 2, 3];
+    let b: u32 = 1;
+    let c = a[b]; // { dg-error "the type ...integer..CAPACITY.. cannot be indexed by .u32." }
+                  // { dg-error {failed to type resolve expression} "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/xfail/lifetime_param.rs b/gcc/testsuite/rust/compile/xfail/lifetime_param.rs
new file mode 100644
index 00000000000..306fca0b3c5
--- /dev/null
+++ b/gcc/testsuite/rust/compile/xfail/lifetime_param.rs
@@ -0,0 +1,11 @@
+// { dg-excess-errors "warnings" }
+
+// { dg-error "lifetime not defined" "#359" { xfail *-*-* } .+1 }
+fn lifetime_undefined(t: &'a str) -> &'a str {
+    t
+}
+
+// { dg-error "lifetime not defined" "#359" { xfail *-*-* } .+1 }
+fn lifetime_undefined_bis<'a>(t: &'a str)-> &'b str {
+    t
+}
diff --git a/gcc/testsuite/rust/compile/xfail/struct_field_vis.rs b/gcc/testsuite/rust/compile/xfail/struct_field_vis.rs
new file mode 100644
index 00000000000..a28729e6208
--- /dev/null
+++ b/gcc/testsuite/rust/compile/xfail/struct_field_vis.rs
@@ -0,0 +1,15 @@
+// { dg-xfail-if "pub visibility not supported #432"  *-*-* }
+
+mod foomod {
+    pub struct Foo {
+        pub f: i32,
+        pub g: u32,
+    }
+}
+
+fn test() -> foomod::Foo {
+    foomod::Foo{
+        f:1,
+        g:3,
+    }
+}
diff --git a/gcc/testsuite/rust/compile/xfail/xfail.exp b/gcc/testsuite/rust/compile/xfail/xfail.exp
new file mode 100644
index 00000000000..5fb6203bb31
--- /dev/null
+++ b/gcc/testsuite/rust/compile/xfail/xfail.exp
@@ -0,0 +1,63 @@
+# Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+# 
+# This program 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/>.
+
+# Compile tests, no torture testing.
+#
+# These tests are used to keep track of known limitations :
+# 1- tests that are incorrecly build instead of being rejected
+# 2- tests that are build to an incorrect result
+# 3- tests that are rejected instead of being correctly build
+#
+# Not currently supported here:
+# - tests that are exhibiting incorrect behavior at runtime
+#
+# Here's how to annotate tests for each cases:
+#
+# 1- test is successfuly build instead of being rejected
+#
+# Expected behavior: a specific error rejecting the test
+# Observed behavior: error not present
+# Use dg-error and mark the test xfail and add reference to corresponding issue.
+# { dg-error "lifetime not defined" "#359" { xfail *-*-* } }
+#
+# 2- test is successfuly build but result is incorrect
+#
+# Expected behavior: test is correctly build and has specific property
+# Observed behavior: test is correctly build but is missing the specific property
+# Depends on the property. For example, if the property can be checked in the assembly file, use dg-final + xfail.
+# { dg-final { scan-assembler "given_string_missing_in_assembly_" "#1234" { xfail *-*-* } } }
+#
+# 3- test is rejected instead of being correctly build
+#
+# Expected behavior: test is successfully build
+# Observed behavior: the test is rejected with an error
+# Use dg-bogus + xfail to match the bogus error message, or use dg-xfail-if if it's harder to match a specific error.
+
+# Load support procs.
+load_lib rust-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+set saved-dg-do-what-default ${dg-do-what-default}
+
+set dg-do-what-default "compile"
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.rs]] "" ""
+set dg-do-what-default ${saved-dg-do-what-default}
+
+# All done.
+dg-finish
-- 
2.25.1


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

* [PATCH Rust front-end v2 06/37] gccrs: Add execution test cases
  2022-08-24 11:59 Rust frontend patches v2 herron.philip
                   ` (4 preceding siblings ...)
  2022-08-24 11:59 ` [PATCH Rust front-end v2 05/37] gccrs: Add general compilation test cases herron.philip
@ 2022-08-24 11:59 ` herron.philip
  2022-08-24 11:59 ` [PATCH Rust front-end v2 07/37] gccrs: Add gcc-check-target check-rust herron.philip
                   ` (31 subsequent siblings)
  37 siblings, 0 replies; 57+ messages in thread
From: herron.philip @ 2022-08-24 11:59 UTC (permalink / raw)
  To: gcc-patches
  Cc: gcc-rust, Philip Herron, Arthur Cohen, Thomas Schwinge,
	Mark Wielaard, Marc Poulhiès

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

This is similar to the compile/torture/*.rs test cases but all of these are
dg-execute testcases so they get compiled, linked and executed by default,
all the while being compiled with the matrix of torture options.

The only caveat here is that currently gccrs does not currently support
the main shim yet so we have a C-style main function here returning zero
which is not supported in Rustc.

Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
Co-authored-by: Thomas Schwinge <thomas@codesourcery.com>
Co-authored-by: Mark Wielaard <mark@klomp.org>
Co-authored-by: Marc Poulhiès <dkm@kataplop.net>
---
 .../rust/execute/torture/block_expr1.rs       |   8 +
 .../rust/execute/torture/builtin_macro_cfg.rs |  32 ++++
 .../execute/torture/builtin_macro_concat.rs   |  29 +++
 .../rust/execute/torture/builtin_macro_env.rs |  31 ++++
 .../torture/builtin_macro_include_bytes.rs    |  46 +++++
 .../torture/builtin_macro_include_str.rs      |  27 +++
 .../execute/torture/builtin_macro_line.rs     |  25 +++
 .../rust/execute/torture/builtin_macros1.rs   |  21 +++
 .../rust/execute/torture/builtin_macros3.rs   |  28 +++
 gcc/testsuite/rust/execute/torture/cfg1.rs    |  32 ++++
 gcc/testsuite/rust/execute/torture/cfg2.rs    |  31 ++++
 gcc/testsuite/rust/execute/torture/cfg3.rs    |  37 ++++
 gcc/testsuite/rust/execute/torture/cfg4.rs    |  38 ++++
 gcc/testsuite/rust/execute/torture/cfg5.rs    |  13 ++
 .../rust/execute/torture/coercion1.rs         |  41 +++++
 .../rust/execute/torture/coercion2.rs         |  39 ++++
 .../rust/execute/torture/const_fold1.rs       |  13 ++
 .../rust/execute/torture/const_fold2.rs       |  16 ++
 .../execute/torture/copy_nonoverlapping1.rs   |  17 ++
 .../rust/execute/torture/empty_main.rs        |   3 +
 .../rust/execute/torture/execute.exp          |  33 ++++
 .../rust/execute/torture/exit_error.rs        |   5 +
 .../rust/execute/torture/extern_mod4.rs       |  19 ++
 gcc/testsuite/rust/execute/torture/func1.rs   |   5 +
 .../rust/execute/torture/helloworld1.rs       |  15 ++
 .../rust/execute/torture/helloworld2.rs       |  15 ++
 .../rust/execute/torture/include.txt          |   1 +
 gcc/testsuite/rust/execute/torture/index1.rs  |  28 +++
 .../rust/execute/torture/issue-1120.rs        | 123 +++++++++++++
 .../rust/execute/torture/issue-1133.rs        | 146 +++++++++++++++
 .../rust/execute/torture/issue-1198.rs        |  75 ++++++++
 .../rust/execute/torture/issue-1231.rs        |  36 ++++
 .../rust/execute/torture/issue-1232.rs        | 159 ++++++++++++++++
 .../rust/execute/torture/issue-1249.rs        |  39 ++++
 .../rust/execute/torture/issue-1436.rs        | 172 ++++++++++++++++++
 .../rust/execute/torture/issue-1496.rs        |  75 ++++++++
 .../rust/execute/torture/issue-647.rs         |  33 ++++
 .../rust/execute/torture/issue-845.rs         |  47 +++++
 .../rust/execute/torture/issue-851.rs         |  35 ++++
 .../rust/execute/torture/issue-858.rs         |  32 ++++
 .../rust/execute/torture/issue-976.rs         |  14 ++
 .../rust/execute/torture/issue-995.rs         |   9 +
 gcc/testsuite/rust/execute/torture/macros1.rs |  13 ++
 .../rust/execute/torture/macros10.rs          |  22 +++
 .../rust/execute/torture/macros11.rs          |  25 +++
 .../rust/execute/torture/macros12.rs          |  22 +++
 .../rust/execute/torture/macros13.rs          |  22 +++
 .../rust/execute/torture/macros14.rs          |  22 +++
 .../rust/execute/torture/macros16.rs          |  14 ++
 .../rust/execute/torture/macros17.rs          |  17 ++
 .../rust/execute/torture/macros18.rs          |  14 ++
 .../rust/execute/torture/macros19.rs          |  14 ++
 gcc/testsuite/rust/execute/torture/macros2.rs |  40 ++++
 .../rust/execute/torture/macros20.rs          |  14 ++
 .../rust/execute/torture/macros21.rs          |  15 ++
 .../rust/execute/torture/macros22.rs          |  27 +++
 .../rust/execute/torture/macros23.rs          |  19 ++
 .../rust/execute/torture/macros24.rs          |   9 +
 .../rust/execute/torture/macros25.rs          |  13 ++
 .../rust/execute/torture/macros26.rs          |  12 ++
 .../rust/execute/torture/macros27.rs          |  24 +++
 .../rust/execute/torture/macros28.rs          |  13 ++
 .../rust/execute/torture/macros29.rs          |  24 +++
 gcc/testsuite/rust/execute/torture/macros3.rs |  61 +++++++
 .../rust/execute/torture/macros30.rs          |  25 +++
 .../rust/execute/torture/macros31.rs          |  32 ++++
 gcc/testsuite/rust/execute/torture/macros4.rs |  15 ++
 gcc/testsuite/rust/execute/torture/macros5.rs |  13 ++
 gcc/testsuite/rust/execute/torture/macros6.rs |  12 ++
 gcc/testsuite/rust/execute/torture/macros7.rs |  28 +++
 gcc/testsuite/rust/execute/torture/macros8.rs |  27 +++
 gcc/testsuite/rust/execute/torture/macros9.rs |  28 +++
 gcc/testsuite/rust/execute/torture/match1.rs  |  58 ++++++
 gcc/testsuite/rust/execute/torture/match2.rs  |  41 +++++
 gcc/testsuite/rust/execute/torture/match3.rs  |  51 ++++++
 .../rust/execute/torture/match_bool1.rs       |  49 +++++
 .../rust/execute/torture/match_byte1.rs       |  56 ++++++
 .../rust/execute/torture/match_char1.rs       |  56 ++++++
 .../rust/execute/torture/match_int1.rs        | 109 +++++++++++
 .../rust/execute/torture/match_loop1.rs       |  56 ++++++
 .../rust/execute/torture/match_range1.rs      |  37 ++++
 .../rust/execute/torture/match_range2.rs      |  45 +++++
 .../rust/execute/torture/match_tuple1.rs      |  45 +++++
 gcc/testsuite/rust/execute/torture/method1.rs |  27 +++
 gcc/testsuite/rust/execute/torture/method2.rs |  76 ++++++++
 gcc/testsuite/rust/execute/torture/method3.rs |  78 ++++++++
 gcc/testsuite/rust/execute/torture/method4.rs |  78 ++++++++
 gcc/testsuite/rust/execute/torture/mod1.rs    |  21 +++
 .../rust/execute/torture/modules/mod.rs       |   3 +
 .../execute/torture/operator_overload_1.rs    |  36 ++++
 .../execute/torture/operator_overload_10.rs   |  75 ++++++++
 .../execute/torture/operator_overload_11.rs   |  37 ++++
 .../execute/torture/operator_overload_12.rs   |  31 ++++
 .../execute/torture/operator_overload_2.rs    |  38 ++++
 .../execute/torture/operator_overload_3.rs    |  55 ++++++
 .../execute/torture/operator_overload_4.rs    |  33 ++++
 .../execute/torture/operator_overload_5.rs    |  33 ++++
 .../execute/torture/operator_overload_6.rs    |  37 ++++
 .../execute/torture/operator_overload_7.rs    |  42 +++++
 .../execute/torture/operator_overload_8.rs    |  58 ++++++
 .../execute/torture/operator_overload_9.rs    |  58 ++++++
 .../rust/execute/torture/slice-magic.rs       | 106 +++++++++++
 .../rust/execute/torture/slice-magic2.rs      | 106 +++++++++++
 gcc/testsuite/rust/execute/torture/slice1.rs  |  27 +++
 .../rust/execute/torture/str-layout1.rs       |  57 ++++++
 .../rust/execute/torture/str-zero.rs          |  26 +++
 gcc/testsuite/rust/execute/torture/trait1.rs  |  52 ++++++
 gcc/testsuite/rust/execute/torture/trait10.rs |  41 +++++
 gcc/testsuite/rust/execute/torture/trait11.rs |  38 ++++
 gcc/testsuite/rust/execute/torture/trait12.rs |  38 ++++
 gcc/testsuite/rust/execute/torture/trait13.rs |  48 +++++
 gcc/testsuite/rust/execute/torture/trait2.rs  |  37 ++++
 gcc/testsuite/rust/execute/torture/trait3.rs  |  43 +++++
 gcc/testsuite/rust/execute/torture/trait4.rs  |  34 ++++
 gcc/testsuite/rust/execute/torture/trait5.rs  |  39 ++++
 gcc/testsuite/rust/execute/torture/trait6.rs  |  39 ++++
 gcc/testsuite/rust/execute/torture/trait7.rs  |  39 ++++
 gcc/testsuite/rust/execute/torture/trait8.rs  |  39 ++++
 gcc/testsuite/rust/execute/torture/trait9.rs  |  35 ++++
 .../rust/execute/torture/transmute1.rs        |  23 +++
 .../rust/execute/torture/wrapping_op1.rs      |  14 ++
 .../rust/execute/torture/wrapping_op2.rs      |  20 ++
 gcc/testsuite/rust/execute/xfail/macro1.rs    |  32 ++++
 123 files changed, 4631 insertions(+)
 create mode 100644 gcc/testsuite/rust/execute/torture/block_expr1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/builtin_macro_cfg.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/builtin_macro_concat.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/builtin_macro_env.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/builtin_macro_include_bytes.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/builtin_macro_include_str.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/builtin_macro_line.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/builtin_macros1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/builtin_macros3.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/cfg1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/cfg2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/cfg3.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/cfg4.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/cfg5.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/coercion1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/coercion2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/const_fold1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/const_fold2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/copy_nonoverlapping1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/empty_main.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/execute.exp
 create mode 100644 gcc/testsuite/rust/execute/torture/exit_error.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/extern_mod4.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/func1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/helloworld1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/helloworld2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/include.txt
 create mode 100644 gcc/testsuite/rust/execute/torture/index1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-1120.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-1133.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-1198.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-1231.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-1232.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-1249.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-1436.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-1496.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-647.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-845.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-851.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-858.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-976.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-995.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros10.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros11.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros12.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros13.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros14.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros16.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros17.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros18.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros19.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros20.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros21.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros22.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros23.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros24.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros25.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros26.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros27.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros28.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros29.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros3.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros30.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros31.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros4.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros5.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros6.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros7.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros8.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros9.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match3.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match_bool1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match_byte1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match_char1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match_int1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match_loop1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match_range1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match_range2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match_tuple1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/method1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/method2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/method3.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/method4.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/mod1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/modules/mod.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_10.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_11.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_12.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_3.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_4.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_5.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_6.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_7.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_8.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_9.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/slice-magic.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/slice-magic2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/slice1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/str-layout1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/str-zero.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait10.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait11.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait12.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait13.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait3.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait4.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait5.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait6.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait7.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait8.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait9.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/transmute1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/wrapping_op1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/wrapping_op2.rs
 create mode 100644 gcc/testsuite/rust/execute/xfail/macro1.rs

diff --git a/gcc/testsuite/rust/execute/torture/block_expr1.rs b/gcc/testsuite/rust/execute/torture/block_expr1.rs
new file mode 100644
index 00000000000..d561f8cab59
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/block_expr1.rs
@@ -0,0 +1,8 @@
+fn main() -> i32 {
+    let ret = {
+        1;
+        2;
+        0
+    };
+    ret
+}
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_cfg.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_cfg.rs
new file mode 100644
index 00000000000..fad2daef6bc
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/builtin_macro_cfg.rs
@@ -0,0 +1,32 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+// { dg-output "A\n" }
+#[rustc_builtin_macro]
+macro_rules! cfg {
+    () => {{}};
+}
+
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: &str) {
+    unsafe {
+        printf(
+            "%s\n" as *const str as *const i8,
+            s as *const str as *const i8,
+        );
+    }
+}
+
+fn main() -> i32 {
+    let cfg = cfg!(A);
+    if cfg {
+        print("A");
+    }
+    let cfg = cfg!(B);
+    if cfg {
+        print("B");
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_concat.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_concat.rs
new file mode 100644
index 00000000000..9b33924f5a1
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/builtin_macro_concat.rs
@@ -0,0 +1,29 @@
+// { dg-output "\ntest10btrue2.15\ntest10bfalse2.151\n" }
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {{}};
+}
+
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: &str) {
+    unsafe {
+        printf(
+            "%s\n" as *const str as *const i8,
+            s as *const str as *const i8,
+        );
+    }
+}
+
+fn main() -> i32 {
+    let a = concat!();
+    let b = concat!("test", 10, 'b', true, 2.15);
+    let c = concat!("test", 10, 'b', false, 2.15, 1u64);
+    print(a);
+    print(b);
+    print(c);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_env.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_env.rs
new file mode 100644
index 00000000000..a5c80b25728
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/builtin_macro_env.rs
@@ -0,0 +1,31 @@
+// { dg-output "VALUE\nVALUE\n" }
+// { dg-set-compiler-env-var ENV_MACRO_TEST "VALUE" }
+#[rustc_builtin_macro]
+macro_rules! env {
+    () => {{}};
+}
+
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: &str) {
+    unsafe {
+        printf(
+            "%s\n" as *const str as *const i8,
+            s as *const str as *const i8,
+        );
+    }
+}
+
+fn main() -> i32 {
+    let val0 = env!("ENV_MACRO_TEST");
+
+    print(val0);
+
+    let val1 = env!("ENV_MACRO_TEST",);
+
+    print(val1);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_include_bytes.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_include_bytes.rs
new file mode 100644
index 00000000000..087f0220de5
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/builtin_macro_include_bytes.rs
@@ -0,0 +1,46 @@
+// { dg-output "104\n33\n1\n" }
+#[rustc_builtin_macro]
+macro_rules! include_bytes {
+    () => {{}};
+}
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn print_int(value: i32) {
+    let s = "%d\n\0" as *const str as *const i8;
+    unsafe {
+        printf(s, value);
+    }
+}
+
+fn main() -> i32 {
+    let bytes = include_bytes!("include.txt");
+
+    print_int(bytes[0] as i32);
+    print_int(bytes[14] as i32);
+
+    let the_bytes = b"hello, include!\n";
+
+    let x = bytes[0] == the_bytes[0]
+        && bytes[1] == the_bytes[1]
+        && bytes[2] == the_bytes[2]
+        && bytes[3] == the_bytes[3]
+        && bytes[4] == the_bytes[4]
+        && bytes[5] == the_bytes[5]
+        && bytes[6] == the_bytes[6]
+        && bytes[7] == the_bytes[7]
+        && bytes[8] == the_bytes[8]
+        && bytes[9] == the_bytes[9]
+        && bytes[10] == the_bytes[10]
+        && bytes[11] == the_bytes[11]
+        && bytes[12] == the_bytes[12]
+        && bytes[13] == the_bytes[13]
+        && bytes[14] == the_bytes[14]
+        && bytes[15] == the_bytes[15];
+
+    print_int(x as i32);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_include_str.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_include_str.rs
new file mode 100644
index 00000000000..6f9871d379c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/builtin_macro_include_str.rs
@@ -0,0 +1,27 @@
+// { dg-output "hello, include!\n" }
+#[rustc_builtin_macro]
+macro_rules! include_str {
+    () => {{}};
+}
+
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: &str) {
+    unsafe {
+        printf(
+            "%s" as *const str as *const i8,
+            s as *const str as *const i8,
+        );
+    }
+}
+
+fn main() -> i32 {
+    // include_str! (and include_bytes!) allow for an optional trailing comma.
+    let my_str = include_str!("include.txt",);
+
+    print(my_str);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_line.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_line.rs
new file mode 100644
index 00000000000..02541ed52e2
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/builtin_macro_line.rs
@@ -0,0 +1,25 @@
+// { dg-output "18\n21\n" }
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: u32) {
+    unsafe {
+        printf("%u\n\0" as *const str as *const i8, s);
+    }
+}
+
+#[rustc_builtin_macro]
+macro_rules! line {
+    () => {{}};
+}
+
+fn main() -> i32 {
+    let a = line!();
+    print(a);
+
+    let b = line!();
+    print(b);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macros1.rs b/gcc/testsuite/rust/execute/torture/builtin_macros1.rs
new file mode 100644
index 00000000000..5976478e426
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/builtin_macros1.rs
@@ -0,0 +1,21 @@
+// { dg-output "rust/execute/torture/builtin_macros1.rs" }
+#[rustc_builtin_macro]
+macro_rules! file {
+    () => {{}};
+}
+
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: &str) {
+    unsafe {
+        printf("%s\n\0" as *const str as *const i8, s);
+    }
+}
+
+fn main() -> i32 {
+    print(file!());
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macros3.rs b/gcc/testsuite/rust/execute/torture/builtin_macros3.rs
new file mode 100644
index 00000000000..24555cbdb8a
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/builtin_macros3.rs
@@ -0,0 +1,28 @@
+// { dg-output "14\n42\n" }
+#[rustc_builtin_macro]
+macro_rules! column {
+    () => {{}};
+}
+
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: u32) {
+    unsafe {
+        printf("%u\n\0" as *const str as *const i8, s);
+    }
+}
+
+fn main() -> i32 {
+    let c0 = column!();
+
+    print(c0);
+
+    let c1 =                             column!();
+
+    print(c1);
+
+    0
+}
+
diff --git a/gcc/testsuite/rust/execute/torture/cfg1.rs b/gcc/testsuite/rust/execute/torture/cfg1.rs
new file mode 100644
index 00000000000..d3c56295503
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/cfg1.rs
@@ -0,0 +1,32 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+// { dg-output "test1\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[cfg(A)]
+fn test() {
+    unsafe {
+        let a = "test1\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c);
+    }
+}
+
+#[cfg(B)]
+fn test() {
+    unsafe {
+        let a = "test2\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c);
+    }
+}
+
+fn main() -> i32 {
+    test();
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/cfg2.rs b/gcc/testsuite/rust/execute/torture/cfg2.rs
new file mode 100644
index 00000000000..5048bcb2791
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/cfg2.rs
@@ -0,0 +1,31 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+// { dg-output "test1\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn test() {
+    #[cfg(A)]
+    unsafe {
+        let a = "test1\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c);
+    }
+
+    #[cfg(B)]
+    unsafe {
+        let a = "test2\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c);
+    }
+}
+
+fn main() -> i32 {
+    test();
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/cfg3.rs b/gcc/testsuite/rust/execute/torture/cfg3.rs
new file mode 100644
index 00000000000..89312344b23
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/cfg3.rs
@@ -0,0 +1,37 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+// { dg-output "test1\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+impl Foo {
+    #[cfg(A)]
+    fn test(&self) {
+        unsafe {
+            let a = "test1\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+    }
+
+    #[cfg(B)]
+    fn test(&self) {
+        unsafe {
+            let a = "test2\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo(123);
+    a.test();
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/cfg4.rs b/gcc/testsuite/rust/execute/torture/cfg4.rs
new file mode 100644
index 00000000000..d1c2a22a0ff
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/cfg4.rs
@@ -0,0 +1,38 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+// { dg-output "test1\ntest2\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+impl Foo {
+    #[cfg(A)]
+    fn test(&self) {
+        unsafe {
+            let a = "test1\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+    }
+
+    #[cfg(not(B))]
+    fn test2(&self) {
+        unsafe {
+            let a = "test2\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo(123);
+    a.test();
+    a.test2();
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/cfg5.rs b/gcc/testsuite/rust/execute/torture/cfg5.rs
new file mode 100644
index 00000000000..581a29bb89d
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/cfg5.rs
@@ -0,0 +1,13 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+
+fn main() -> i32 {
+    let mut a = 0;
+
+    #[cfg(A)]
+    a = 3;
+
+    #[cfg(B)]
+    a = 40;
+
+    a - 3
+}
diff --git a/gcc/testsuite/rust/execute/torture/coercion1.rs b/gcc/testsuite/rust/execute/torture/coercion1.rs
new file mode 100644
index 00000000000..2cdb9bbca38
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/coercion1.rs
@@ -0,0 +1,41 @@
+/* { dg-output "123\n123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+trait Bar {
+    fn baz(&self);
+}
+
+impl Bar for Foo {
+    fn baz(&self) {
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, self.0);
+        }
+    }
+}
+
+fn static_dispatch<T: Bar>(t: &T) {
+    t.baz();
+}
+
+fn dynamic_dispatch(t: &dyn Bar) {
+    t.baz();
+}
+
+fn main() -> i32 {
+    let a;
+    a = Foo(123);
+    static_dispatch(&a);
+
+    let b: &dyn Bar;
+    b = &a;
+    dynamic_dispatch(b);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/coercion2.rs b/gcc/testsuite/rust/execute/torture/coercion2.rs
new file mode 100644
index 00000000000..12dd68ff5f7
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/coercion2.rs
@@ -0,0 +1,39 @@
+/* { dg-output "123\n123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+trait Bar {
+    fn baz(&self);
+}
+
+impl Bar for Foo {
+    fn baz(&self) {
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, self.0);
+        }
+    }
+}
+
+fn static_dispatch<T: Bar>(t: &T) {
+    t.baz();
+}
+
+fn dynamic_dispatch(t: &dyn Bar) {
+    t.baz();
+}
+
+fn main() -> i32 {
+    let a;
+    a = &Foo(123);
+
+    static_dispatch(a);
+    dynamic_dispatch(a);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/const_fold1.rs b/gcc/testsuite/rust/execute/torture/const_fold1.rs
new file mode 100644
index 00000000000..3cd6c0c77b5
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/const_fold1.rs
@@ -0,0 +1,13 @@
+// { dg-additional-options "-w" }
+const fn const_fn() -> usize {
+    4
+}
+
+const FN_TEST: usize = const_fn();
+
+const TEST: usize = 2 + FN_TEST;
+
+fn main() -> i32 {
+    let a: [_; 12] = [5; TEST * 2];
+    a[6] - 5
+}
diff --git a/gcc/testsuite/rust/execute/torture/const_fold2.rs b/gcc/testsuite/rust/execute/torture/const_fold2.rs
new file mode 100644
index 00000000000..c525648fe0b
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/const_fold2.rs
@@ -0,0 +1,16 @@
+// { dg-additional-options "-w" }
+const A: i32 = 1;
+const B: i32 = { A + 2 };
+
+const fn test() -> i32 {
+    B
+}
+
+const C: i32 = {
+    const a: i32 = 4;
+    test() + a
+};
+
+fn main() -> i32 {
+    C - 7
+}
diff --git a/gcc/testsuite/rust/execute/torture/copy_nonoverlapping1.rs b/gcc/testsuite/rust/execute/torture/copy_nonoverlapping1.rs
new file mode 100644
index 00000000000..2ae7a0869e3
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/copy_nonoverlapping1.rs
@@ -0,0 +1,17 @@
+extern "rust-intrinsic" {
+    pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+}
+
+fn main() -> i32 {
+    let i = 15;
+    let mut i_copy = 16;
+
+    let i = &i as *const i32;
+    let i_copy = &mut i_copy as *mut i32;
+
+    unsafe {
+        copy_nonoverlapping(i, i_copy, 1);
+
+        *i_copy - *i
+    }
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/execute/torture/empty_main.rs b/gcc/testsuite/rust/execute/torture/empty_main.rs
new file mode 100644
index 00000000000..6442e1e4e83
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/empty_main.rs
@@ -0,0 +1,3 @@
+fn main() -> i32 {
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/execute.exp b/gcc/testsuite/rust/execute/torture/execute.exp
new file mode 100644
index 00000000000..6dfb6d2b446
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/execute.exp
@@ -0,0 +1,33 @@
+# Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+# 
+# This program 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/>.
+
+# Execute tests, torture testing.
+
+# Load support procs.
+load_lib rust-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+set saved-dg-do-what-default ${dg-do-what-default}
+
+set dg-do-what-default "run"
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.rs]] "" ""
+set dg-do-what-default ${saved-dg-do-what-default}
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/rust/execute/torture/exit_error.rs b/gcc/testsuite/rust/execute/torture/exit_error.rs
new file mode 100644
index 00000000000..c3d0d9f2480
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/exit_error.rs
@@ -0,0 +1,5 @@
+// { dg-xfail-run-if "" { *-*-* } }
+
+fn main() -> i32 {
+    1
+}
diff --git a/gcc/testsuite/rust/execute/torture/extern_mod4.rs b/gcc/testsuite/rust/execute/torture/extern_mod4.rs
new file mode 100644
index 00000000000..99b6fb5c9ba
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/extern_mod4.rs
@@ -0,0 +1,19 @@
+// { dg-additional-options "-w" }
+// { dg-output "12" }
+mod modules;
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn main() -> i32 {
+    unsafe {
+        let fmt_s = "%d\n\0";
+        let fmt_p = fmt_s as *const str;
+        let fmt_i8 = fmt_p as *const i8;
+
+        printf(fmt_i8, modules::return_12());
+    }
+
+    return 0;
+}
diff --git a/gcc/testsuite/rust/execute/torture/func1.rs b/gcc/testsuite/rust/execute/torture/func1.rs
new file mode 100644
index 00000000000..0a093d88587
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/func1.rs
@@ -0,0 +1,5 @@
+fn main() -> i32 {
+    1;
+    2;
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/helloworld1.rs b/gcc/testsuite/rust/execute/torture/helloworld1.rs
new file mode 100644
index 00000000000..d416efa33af
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/helloworld1.rs
@@ -0,0 +1,15 @@
+/* { dg-output "Hello World" }*/
+extern "C" {
+    fn puts(s: *const i8);
+}
+
+fn main() -> i32 {
+    unsafe {
+        let a = "Hello World";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        puts(c);
+    }
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/helloworld2.rs b/gcc/testsuite/rust/execute/torture/helloworld2.rs
new file mode 100644
index 00000000000..cc05f3798fa
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/helloworld2.rs
@@ -0,0 +1,15 @@
+/* { dg-output "Hello World 123\n" }*/
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn main() -> i32 {
+    unsafe {
+        let a = "Hello World %i\n";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, 123);
+    }
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/include.txt b/gcc/testsuite/rust/execute/torture/include.txt
new file mode 100644
index 00000000000..12c368778e1
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/include.txt
@@ -0,0 +1 @@
+hello, include!
diff --git a/gcc/testsuite/rust/execute/torture/index1.rs b/gcc/testsuite/rust/execute/torture/index1.rs
new file mode 100644
index 00000000000..4682978bdd0
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/index1.rs
@@ -0,0 +1,28 @@
+// { dg-additional-options "-w" }
+#[lang = "index"]
+trait Index<Idx> {
+    type Output;
+
+    fn index(&self, index: Idx) -> &Self::Output;
+}
+
+struct Foo(i32, i32);
+impl Index<isize> for Foo {
+    type Output = i32;
+
+    fn index(&self, index: isize) -> &i32 {
+        if index == 0 {
+            &self.0
+        } else {
+            &self.1
+        }
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo(1, 2);
+    let b = a[0];
+    let c = a[1];
+
+    c - b - 1
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-1120.rs b/gcc/testsuite/rust/execute/torture/issue-1120.rs
new file mode 100644
index 00000000000..242c94b5cb6
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1120.rs
@@ -0,0 +1,123 @@
+// { dg-additional-options "-w" }
+extern "rust-intrinsic" {
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+    pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+struct FatPtr<T> {
+    data: *const T,
+    len: usize,
+}
+
+pub union Repr<T> {
+    rust: *const [T],
+    rust_mut: *mut [T],
+    raw: FatPtr<T>,
+}
+
+pub enum Option<T> {
+    None,
+    Some(T),
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+    pub start: Idx,
+    pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<T> *const [T] {
+    pub const fn len(self) -> usize {
+        unsafe { Repr { rust: self }.raw.len }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+    pub const unsafe fn offset(self, count: isize) -> *const T {
+        unsafe { offset(self, count) }
+    }
+
+    pub const unsafe fn add(self, count: usize) -> Self {
+        unsafe { self.offset(count as isize) }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+    unsafe {
+        Repr {
+            raw: FatPtr { data, len },
+        }
+        .rust
+    }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+    type Output;
+
+    fn index(&self, index: Idx) -> &Self::Output;
+}
+
+pub unsafe trait SliceIndex<T> {
+    type Output;
+
+    fn get(self, slice: &T) -> Option<&Self::Output>;
+
+    unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
+
+    fn index(self, slice: &T) -> &Self::Output;
+}
+
+unsafe impl<T> SliceIndex<[T]> for Range<usize> {
+    type Output = [T];
+
+    fn get(self, slice: &[T]) -> Option<&[T]> {
+        if self.start > self.end
+        /* || self.end > slice.len() */
+        {
+            Option::None
+        } else {
+            unsafe { Option::Some(&*self.get_unchecked(slice)) }
+        }
+    }
+
+    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+        unsafe {
+            let a: *const T = slice.as_ptr();
+            let b: *const T = a.add(self.start);
+            slice_from_raw_parts(b, self.end - self.start)
+        }
+    }
+
+    fn index(self, slice: &[T]) -> &[T] {
+        unsafe { &*self.get_unchecked(slice) }
+    }
+}
+
+impl<T, I> Index<I> for [T]
+where
+    I: SliceIndex<[T]>,
+{
+    type Output = I::Output;
+
+    fn index(&self, index: I) -> &I::Output {
+        index.index(self)
+    }
+}
+
+fn main() -> i32 {
+    let a = [1, 2, 3, 4, 5];
+    let b = &a[1..3];
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-1133.rs b/gcc/testsuite/rust/execute/torture/issue-1133.rs
new file mode 100644
index 00000000000..f2080a6e072
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1133.rs
@@ -0,0 +1,146 @@
+// { dg-additional-options "-w" }
+extern "rust-intrinsic" {
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+    pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+struct FatPtr<T> {
+    data: *const T,
+    len: usize,
+}
+
+pub union Repr<T> {
+    rust: *const [T],
+    rust_mut: *mut [T],
+    raw: FatPtr<T>,
+}
+
+pub enum Option<T> {
+    None,
+    Some(T),
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+    pub start: Idx,
+    pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<T> *const [T] {
+    pub const fn len(self) -> usize {
+        unsafe { Repr { rust: self }.raw.len }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+    pub const unsafe fn offset(self, count: isize) -> *const T {
+        unsafe { offset(self, count) }
+    }
+
+    pub const unsafe fn add(self, count: usize) -> Self {
+        unsafe { self.offset(count as isize) }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+    unsafe {
+        Repr {
+            raw: FatPtr { data, len },
+        }
+        .rust
+    }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+    type Output;
+
+    fn index(&self, index: Idx) -> &Self::Output;
+}
+
+pub unsafe trait SliceIndex<T> {
+    type Output;
+
+    fn get(self, slice: &T) -> Option<&Self::Output>;
+
+    unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
+
+    fn index(self, slice: &T) -> &Self::Output;
+}
+
+unsafe impl<T> SliceIndex<[T]> for usize {
+    type Output = T;
+
+    fn get(self, slice: &[T]) -> Option<&T> {
+        unsafe { Option::Some(&*self.get_unchecked(slice)) }
+    }
+
+    unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
+        // SAFETY: the caller guarantees that `slice` is not dangling, so it
+        // cannot be longer than `isize::MAX`. They also guarantee that
+        // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
+        // so the call to `add` is safe.
+        unsafe { slice.as_ptr().add(self) }
+    }
+
+    fn index(self, slice: &[T]) -> &T {
+        // N.B., use intrinsic indexing
+        // &(*slice)[self]
+        unsafe { &*self.get_unchecked(slice) }
+    }
+}
+
+unsafe impl<T> SliceIndex<[T]> for Range<usize> {
+    type Output = [T];
+
+    fn get(self, slice: &[T]) -> Option<&[T]> {
+        if self.start > self.end
+        /* || self.end > slice.len() */
+        {
+            Option::None
+        } else {
+            unsafe { Option::Some(&*self.get_unchecked(slice)) }
+        }
+    }
+
+    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+        unsafe {
+            let a: *const T = slice.as_ptr();
+            let b: *const T = a.add(self.start);
+            slice_from_raw_parts(b, self.end - self.start)
+        }
+    }
+
+    fn index(self, slice: &[T]) -> &[T] {
+        unsafe { &*self.get_unchecked(slice) }
+    }
+}
+
+impl<T, I> Index<I> for [T]
+where
+    I: SliceIndex<[T]>,
+{
+    type Output = I::Output;
+
+    fn index(&self, index: I) -> &I::Output {
+        index.index(self)
+    }
+}
+
+fn main() -> i32 {
+    let a = [1, 2, 3, 4, 5];
+    let b = &a[1..3];
+    let c = b[1];
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-1198.rs b/gcc/testsuite/rust/execute/torture/issue-1198.rs
new file mode 100644
index 00000000000..fce44ad1994
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1198.rs
@@ -0,0 +1,75 @@
+/* { dg-output "foo_deref\nimm_deref\n123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+    type Target;
+
+    fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "imm_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+impl<T> Deref for &mut T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "mut_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        unsafe {
+            let a = "foo_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        &self.0
+    }
+}
+
+fn main() -> i32 {
+    let foo: Foo<i32> = Foo(123);
+    let bar: &i32 = &foo;
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, *bar);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-1231.rs b/gcc/testsuite/rust/execute/torture/issue-1231.rs
new file mode 100644
index 00000000000..970e86f917a
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1231.rs
@@ -0,0 +1,36 @@
+// { dg-additional-options "-w" }
+// { dg-output "outer\ninner\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn machin() {
+    unsafe {
+        let a = "outer\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, 123);
+    }
+}
+
+fn bidule() {
+    fn machin() {
+        unsafe {
+            let a = "inner\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, 123);
+        }
+    }
+
+    self::machin();
+    machin();
+}
+
+fn main() -> i32 {
+    bidule();
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-1232.rs b/gcc/testsuite/rust/execute/torture/issue-1232.rs
new file mode 100644
index 00000000000..c56d5c18695
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1232.rs
@@ -0,0 +1,159 @@
+// { dg-additional-options "-w" }
+// { dg-output "slice_access=3\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;
+}
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct FatPtr<T> {
+    data: *const T,
+    len: usize,
+}
+
+pub union Repr<T> {
+    rust: *const [T],
+    rust_mut: *mut [T],
+    raw: FatPtr<T>,
+}
+
+pub enum Option<T> {
+    None,
+    Some(T),
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+    pub start: Idx,
+    pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<T> *const [T] {
+    pub const fn len(self) -> usize {
+        unsafe { Repr { rust: self }.raw.len }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+    pub const unsafe fn offset(self, count: isize) -> *const T {
+        unsafe { offset(self, count) }
+    }
+
+    pub const unsafe fn add(self, count: usize) -> Self {
+        unsafe { self.offset(count as isize) }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+    unsafe {
+        Repr {
+            raw: FatPtr { data, len },
+        }
+        .rust
+    }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+    type Output;
+
+    fn index(&self, index: Idx) -> &Self::Output;
+}
+
+pub unsafe trait SliceIndex<T> {
+    type Output;
+
+    fn get(self, slice: &T) -> Option<&Self::Output>;
+
+    unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
+
+    fn index(self, slice: &T) -> &Self::Output;
+}
+
+unsafe impl<T> SliceIndex<[T]> for usize {
+    type Output = T;
+
+    fn get(self, slice: &[T]) -> Option<&T> {
+        unsafe { Option::Some(&*self.get_unchecked(slice)) }
+    }
+
+    unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
+        // SAFETY: the caller guarantees that `slice` is not dangling, so it
+        // cannot be longer than `isize::MAX`. They also guarantee that
+        // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
+        // so the call to `add` is safe.
+        unsafe { slice.as_ptr().add(self) }
+    }
+
+    fn index(self, slice: &[T]) -> &T {
+        // N.B., use intrinsic indexing
+        // &(*slice)[self]
+        unsafe { &*self.get_unchecked(slice) }
+    }
+}
+
+unsafe impl<T> SliceIndex<[T]> for Range<usize> {
+    type Output = [T];
+
+    fn get(self, slice: &[T]) -> Option<&[T]> {
+        if self.start > self.end
+        /* || self.end > slice.len() */
+        {
+            Option::None
+        } else {
+            unsafe { Option::Some(&*self.get_unchecked(slice)) }
+        }
+    }
+
+    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+        unsafe {
+            let a: *const T = slice.as_ptr();
+            let b: *const T = a.add(self.start);
+            slice_from_raw_parts(b, self.end - self.start)
+        }
+    }
+
+    fn index(self, slice: &[T]) -> &[T] {
+        unsafe { &*self.get_unchecked(slice) }
+    }
+}
+
+impl<T, I> Index<I> for [T]
+where
+    I: SliceIndex<[T]>,
+{
+    type Output = I::Output;
+
+    fn index(&self, index: I) -> &I::Output {
+        index.index(self)
+    }
+}
+
+fn main() -> i32 {
+    let array = [1, 2, 3, 4, 5];
+    let slice = &array[1..3];
+    let slice_access = slice[1];
+
+    unsafe {
+        let a = "slice_access=%i\n";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, slice_access);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-1249.rs b/gcc/testsuite/rust/execute/torture/issue-1249.rs
new file mode 100644
index 00000000000..072204ea877
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1249.rs
@@ -0,0 +1,39 @@
+// { dg-options "-w" }
+// { dg-output "1\n2\n" }
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+trait T {
+    fn foo(&self);
+}
+
+impl dyn T {
+    fn bar(&self) {
+        unsafe {
+            let a = "1\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            printf(c);
+        }
+        self.foo()
+    }
+}
+
+struct S;
+impl T for S {
+    fn foo(&self) {
+        unsafe {
+            let a = "2\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            printf(c);
+        }
+    }
+}
+
+pub fn main() -> i32 {
+    <dyn T>::bar(&S);
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-1436.rs b/gcc/testsuite/rust/execute/torture/issue-1436.rs
new file mode 100644
index 00000000000..5c079a61f07
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1436.rs
@@ -0,0 +1,172 @@
+// { dg-options "-w" }
+// { dg-output "" }
+mod intrinsics {
+    extern "rust-intrinsic" {
+        #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+        pub fn offset<T>(ptr: *const T, count: isize) -> *const T;
+    }
+}
+
+mod mem {
+    extern "rust-intrinsic" {
+        fn size_of<T>() -> usize;
+    }
+}
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct FatPtr<T> {
+    data: *const T,
+    len: usize,
+}
+
+pub union Repr<T> {
+    rust: *const [T],
+    rust_mut: *mut [T],
+    raw: FatPtr<T>,
+}
+
+pub enum Option<T> {
+    None,
+    Some(T),
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+    pub start: Idx,
+    pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<T> *const [T] {
+    pub const fn len(self) -> usize {
+        unsafe { Repr { rust: self }.raw.len }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+    pub const unsafe fn offset(self, count: isize) -> *const T {
+        unsafe { intrinsics::offset(self, count) }
+    }
+
+    pub const unsafe fn add(self, count: usize) -> Self {
+        unsafe { self.offset(count as isize) }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+    unsafe {
+        Repr {
+            raw: FatPtr { data, len },
+        }
+        .rust
+    }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+    type Output;
+
+    fn index(&self, index: Idx) -> &Self::Output;
+}
+
+impl<T> [T] {
+    pub const fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+
+    pub const fn len(&self) -> usize {
+        unsafe { Repr { rust: self }.raw.len }
+    }
+}
+
+pub unsafe trait SliceIndex<T> {
+    type Output;
+
+    fn get(self, slice: &T) -> Option<&Self::Output>;
+
+    unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
+
+    fn index(self, slice: &T) -> &Self::Output;
+}
+
+unsafe impl<T> SliceIndex<[T]> for usize {
+    type Output = T;
+
+    fn get(self, slice: &[T]) -> Option<&T> {
+        unsafe { Option::Some(&*self.get_unchecked(slice)) }
+    }
+
+    unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
+        // SAFETY: the caller guarantees that `slice` is not dangling, so it
+        // cannot be longer than `isize::MAX`. They also guarantee that
+        // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
+        // so the call to `add` is safe.
+        unsafe { slice.as_ptr().add(self) }
+    }
+
+    fn index(self, slice: &[T]) -> &T {
+        unsafe { &*self.get_unchecked(slice) }
+    }
+}
+
+unsafe impl<T> SliceIndex<[T]> for Range<usize> {
+    type Output = [T];
+
+    fn get(self, slice: &[T]) -> Option<&[T]> {
+        if self.start > self.end || self.end > slice.len() {
+            Option::None
+        } else {
+            unsafe { Option::Some(&*self.get_unchecked(slice)) }
+        }
+    }
+
+    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+        unsafe {
+            let a: *const T = slice.as_ptr();
+            let b: *const T = a.add(self.start);
+            slice_from_raw_parts(b, self.end - self.start)
+        }
+    }
+
+    fn index(self, slice: &[T]) -> &[T] {
+        unsafe { &*self.get_unchecked(slice) }
+    }
+}
+
+impl<T, I> Index<I> for [T]
+where
+    I: SliceIndex<[T]>,
+{
+    type Output = I::Output;
+
+    fn index(&self, index: I) -> &I::Output {
+        unsafe {
+            let a = "slice-index\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        index.index(self)
+    }
+}
+
+fn main() -> i32 {
+    let a = [1, 2, 3, 4, 5];
+    let b = a[1];
+
+    b - 2
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-1496.rs b/gcc/testsuite/rust/execute/torture/issue-1496.rs
new file mode 100644
index 00000000000..9f08b2ae98a
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1496.rs
@@ -0,0 +1,75 @@
+/* { dg-output "foo_deref\nimm_deref\n123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+    type Target;
+
+    fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "imm_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+impl<T> Deref for &mut T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "mut_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        unsafe {
+            let a = "foo_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        &self.0
+    }
+}
+
+fn main() -> i32 {
+    let foo = Foo(123);
+    let bar = &foo as &i32;
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, *bar);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-647.rs b/gcc/testsuite/rust/execute/torture/issue-647.rs
new file mode 100644
index 00000000000..3f427ccb785
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-647.rs
@@ -0,0 +1,33 @@
+/* { dg-output "Hello World 123\n" }*/
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo<T>(T);
+
+struct Bar<T> {
+    a: Foo<T>,
+    b: bool,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+fn test<T>(a: Bar<T>) -> Foo<T> {
+    a.a
+}
+
+fn main() -> i32 {
+    let a: Bar<i32> = Bar::<i32> {
+        a: Foo::<i32>(123),
+        b: true,
+    };
+    let result: Foo<i32> = test(a);
+
+    unsafe {
+        let a = "Hello World %i\n";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, result.0);
+    }
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-845.rs b/gcc/testsuite/rust/execute/torture/issue-845.rs
new file mode 100644
index 00000000000..4c689e3b6c8
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-845.rs
@@ -0,0 +1,47 @@
+// { dg-output "Foo::bar\n" }
+// { dg-additional-options "-w" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo {}
+
+trait Bar {
+    fn bar(&self) {
+        unsafe {
+            let _a = "Bar::bar\n\0";
+            let _b = _a as *const str;
+            let _c = _b as *const i8;
+            printf(_c);
+        }
+    }
+}
+
+impl Foo {
+    fn bar(&self) {
+        unsafe {
+            let _a = "Foo::bar\n\0";
+            let _b = _a as *const str;
+            let _c = _b as *const i8;
+            printf(_c);
+        }
+    }
+}
+
+impl Bar for Foo {
+    fn bar(&self) {
+        unsafe {
+            let _a = "<Bar as Foo>::bar\n\0";
+            let _b = _a as *const str;
+            let _c = _b as *const i8;
+            printf(_c);
+        }
+    }
+}
+
+pub fn main() -> i32 {
+    let mut f = Foo {};
+    f.bar();
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-851.rs b/gcc/testsuite/rust/execute/torture/issue-851.rs
new file mode 100644
index 00000000000..3881c7a2ada
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-851.rs
@@ -0,0 +1,35 @@
+/* { dg-output "Result: 123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+enum Foo<T> {
+    A,
+    B(T),
+}
+
+fn inspect(a: Foo<i32>) {
+    match a {
+        Foo::A => unsafe {
+            let a = "A\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        },
+        Foo::B(x) => unsafe {
+            let a = "Result: %i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, x);
+        },
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo::B(123);
+    inspect(a);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-858.rs b/gcc/testsuite/rust/execute/torture/issue-858.rs
new file mode 100644
index 00000000000..5a43f3e1b1a
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-858.rs
@@ -0,0 +1,32 @@
+/* { dg-output "Result: 123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+enum Foo<T> {
+    A,
+    B(T),
+}
+
+fn main() -> i32 {
+    let result = Foo::B(123);
+
+    match result {
+        Foo::A => unsafe {
+            let a = "A\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        },
+        Foo::B(x) => unsafe {
+            let a = "Result: %i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, x);
+        },
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-976.rs b/gcc/testsuite/rust/execute/torture/issue-976.rs
new file mode 100644
index 00000000000..42cf596fb7d
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-976.rs
@@ -0,0 +1,14 @@
+/* { dg-output "hi" } */
+fn main() -> i32 {
+    {
+        extern "C" {
+            fn puts(s: *const i8);
+        }
+
+        unsafe {
+            puts("hi\0" as *const str as *const i8);
+        }
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-995.rs b/gcc/testsuite/rust/execute/torture/issue-995.rs
new file mode 100644
index 00000000000..42570e33f74
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-995.rs
@@ -0,0 +1,9 @@
+struct Pattern(i32);
+
+fn pattern_as_arg(Pattern(value): Pattern) -> i32 {
+    value
+}
+
+fn main() -> i32 {
+    pattern_as_arg(Pattern(15)) - 15
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros1.rs b/gcc/testsuite/rust/execute/torture/macros1.rs
new file mode 100644
index 00000000000..652d2d8fe5b
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros1.rs
@@ -0,0 +1,13 @@
+macro_rules! add {
+    ($a:expr,$b:expr) => {
+        $a + $b
+    };
+}
+
+fn test() -> i32 {
+    add!(1 + 2, 3)
+}
+
+fn main() -> i32 {
+    test() - 6
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros10.rs b/gcc/testsuite/rust/execute/torture/macros10.rs
new file mode 100644
index 00000000000..155a440ee04
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros10.rs
@@ -0,0 +1,22 @@
+// { dg-output "18\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn print_int(value: i32) {
+    let s = "%d\n\0" as *const str as *const i8;
+    unsafe {
+        printf(s, value);
+    }
+}
+
+macro_rules! add_exprs {
+    ($($e:expr)*) => (0 $(+ $e)*)
+}
+
+fn main() -> i32 {
+    // 1 + 2 + 15 => 18
+    print_int(add_exprs!(1 2 15));
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros11.rs b/gcc/testsuite/rust/execute/torture/macros11.rs
new file mode 100644
index 00000000000..5bde97d3dd4
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros11.rs
@@ -0,0 +1,25 @@
+// { dg-output "2" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn print_int(value: i32) {
+    let s = "%d\n\0";
+    let s_p = s as *const str;
+    let c_p = s_p as *const i8;
+    unsafe {
+        printf(c_p, value);
+    }
+}
+
+macro_rules! add_exprs {
+    ($($e:expr)?) => (0 $(+ $e)?)
+}
+
+fn main() -> i32 {
+    // 2
+    let a = add_exprs!(2);
+    print_int(a);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros12.rs b/gcc/testsuite/rust/execute/torture/macros12.rs
new file mode 100644
index 00000000000..d310dff9ba8
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros12.rs
@@ -0,0 +1,22 @@
+// { dg-output "0\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn print_int(value: i32) {
+    let s = "%d\n\0" as *const str as *const i8;
+    unsafe {
+        printf(s, value);
+    }
+}
+
+macro_rules! add_exprs {
+    ($($e:expr)?) => (0 $(+ $e)?)
+}
+
+fn main() -> i32 {
+    // 0
+    print_int(add_exprs!());
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros13.rs b/gcc/testsuite/rust/execute/torture/macros13.rs
new file mode 100644
index 00000000000..afb20264625
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros13.rs
@@ -0,0 +1,22 @@
+// { dg-output "18\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn print_int(value: i32) {
+    let s = "%d\n\0" as *const str as *const i8;
+    unsafe {
+        printf(s, value);
+    }
+}
+
+macro_rules! add_exprs {
+    ($($e:expr)+) => (0 $(+ $e)+)
+}
+
+fn main() -> i32 {
+    // 1 + 2 + 15 => 18
+    print_int(add_exprs!(1 2 15));
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros14.rs b/gcc/testsuite/rust/execute/torture/macros14.rs
new file mode 100644
index 00000000000..00656546d4c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros14.rs
@@ -0,0 +1,22 @@
+// { dg-output "15\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn print_int(value: i32) {
+    let s = "%d\n\0" as *const str as *const i8;
+    unsafe {
+        printf(s, value);
+    }
+}
+
+macro_rules! add_exprs {
+    ($($e:expr)*) => (15 $(+ $e)*)
+}
+
+fn main() -> i32 {
+    // 15
+    print_int(add_exprs!());
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros16.rs b/gcc/testsuite/rust/execute/torture/macros16.rs
new file mode 100644
index 00000000000..47ab2411c0d
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros16.rs
@@ -0,0 +1,14 @@
+macro_rules! add {
+    ($e:literal) => {
+        0 + $e
+    };
+    ($e:literal $($es:literal)*) => {
+        $e + add!($($es)*)
+    };
+}
+
+fn main() -> i32 {
+    let a = add!(1 2 3 10); // 16
+
+    a - 16
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros17.rs b/gcc/testsuite/rust/execute/torture/macros17.rs
new file mode 100644
index 00000000000..390352ec47f
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros17.rs
@@ -0,0 +1,17 @@
+macro_rules! two {
+    (2) => {
+        3
+    };
+}
+
+macro_rules! one {
+    (1) => {{
+        two!(2)
+    }};
+}
+
+fn main() -> i32 {
+    let a = one!(1);
+
+    a - 3
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros18.rs b/gcc/testsuite/rust/execute/torture/macros18.rs
new file mode 100644
index 00000000000..61df17e9da5
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros18.rs
@@ -0,0 +1,14 @@
+macro_rules! add {
+    ($e:literal) => {
+        0 + $e
+    };
+    ($e:literal $($es:literal)*) => {
+        $e + add!($($es)*)
+    };
+}
+
+fn main() -> i32 {
+    let a = add!(3 4); // 7
+
+    a - 7
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros19.rs b/gcc/testsuite/rust/execute/torture/macros19.rs
new file mode 100644
index 00000000000..4732545410e
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros19.rs
@@ -0,0 +1,14 @@
+macro_rules! add {
+    ($e:expr, $($es:expr),*) => {
+        $e + add!($($es),*)
+    };
+    ($e:expr) => {
+        $e
+    };
+}
+
+fn main() -> i32 {
+    let a = add!(15, 2, 9); // 26
+
+    a - 26
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros2.rs b/gcc/testsuite/rust/execute/torture/macros2.rs
new file mode 100644
index 00000000000..ba5098710ea
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros2.rs
@@ -0,0 +1,40 @@
+// { dg-output "arg\narg\narg\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn f() {
+    unsafe {
+        let r_s = "arg\n\0";
+        let s_p = r_s as *const str;
+        let c_p = s_p as *const i8;
+
+        printf(c_p);
+    }
+}
+
+macro_rules! kw0 {
+    (keyword) => {
+        f();
+    };
+}
+
+macro_rules! kw1 {
+    (fn) => {
+        f();
+    };
+}
+
+macro_rules! kw2 {
+    (kw0 kw1 kw3) => {
+        f();
+    };
+}
+
+fn main() -> i32 {
+    kw0!(keyword);
+    kw1!(fn);
+    kw2!(kw0 kw1 kw3);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros20.rs b/gcc/testsuite/rust/execute/torture/macros20.rs
new file mode 100644
index 00000000000..97317a0879e
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros20.rs
@@ -0,0 +1,14 @@
+macro_rules! add {
+    ($e:expr , $($es:expr) , *) => {
+        $e + add!($($es) , *)
+    };
+    ($e:expr) => {
+        $e
+    };
+}
+
+fn main() -> i32 {
+    let a = add!(15, 2, 9); // 26
+
+    a - 26
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros21.rs b/gcc/testsuite/rust/execute/torture/macros21.rs
new file mode 100644
index 00000000000..2508be1a6fd
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros21.rs
@@ -0,0 +1,15 @@
+macro_rules! add_parens {
+    ($($rep:ident ( ) )*) => {
+        { 0 $(+ $rep ( ))* }
+    };
+}
+
+fn f() -> i32 {
+    1
+}
+
+fn main() -> i32 {
+    let a = add_parens!(f() f() f());
+
+    a - 3
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros22.rs b/gcc/testsuite/rust/execute/torture/macros22.rs
new file mode 100644
index 00000000000..3f291ace98e
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros22.rs
@@ -0,0 +1,27 @@
+// { dg-output "1\n2\nNaN\n3\n" }
+
+macro_rules! print_num {
+    ($l:literal) => {{
+        unsafe {
+            printf("%d\n\0" as *const str as *const i8, $l);
+        }
+    }};
+}
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+// Check to make sure that expanding macros does not break the flow of calls
+fn main() -> i32 {
+    print_num!(1);
+    print_num!(2);
+
+    unsafe {
+        printf("NaN\n\0" as *const str as *const i8);
+    }
+
+    print_num!(3);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros23.rs b/gcc/testsuite/rust/execute/torture/macros23.rs
new file mode 100644
index 00000000000..846352d0487
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros23.rs
@@ -0,0 +1,19 @@
+trait Valuable {
+    const VALUE: i32;
+}
+
+struct Something;
+
+macro_rules! implement {
+    () => {
+        const VALUE: i32 = 18;
+    };
+}
+
+impl Valuable for Something {
+    implement!();
+}
+
+fn main() -> i32 {
+    Something::VALUE - 18
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros24.rs b/gcc/testsuite/rust/execute/torture/macros24.rs
new file mode 100644
index 00000000000..f838a83af66
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros24.rs
@@ -0,0 +1,9 @@
+macro_rules! repeat {
+    ( $( $i:literal ),* ; $( $j:literal ),* ) => (( $( ($i,$j) ),* ))
+}
+
+fn main() -> i32 {
+    let t = repeat!(1, 1; 2, 2);
+
+    t.0 .0 + t.0 .1 + t.1 .0 + t.1 .1 - 6
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros25.rs b/gcc/testsuite/rust/execute/torture/macros25.rs
new file mode 100644
index 00000000000..c2658721bdf
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros25.rs
@@ -0,0 +1,13 @@
+macro_rules! t {
+    ($t:tt) => {
+        $t
+    };
+}
+
+fn frob() -> i32 {
+    t!(15) + t!((14))
+}
+
+fn main() -> i32 {
+    frob() - 29
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros26.rs b/gcc/testsuite/rust/execute/torture/macros26.rs
new file mode 100644
index 00000000000..30f0beef0d9
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros26.rs
@@ -0,0 +1,12 @@
+macro_rules! count_tt {
+    ($t:tt) => { 1 };
+    ($t:tt $($ts:tt)*) => { 1 + count_tt!($($ts)*) };
+}
+
+fn main() -> i32 {
+    let count = count_tt!(1 2 let a = 15) + count_tt!(1 2 (let a = 15));
+    //                    ^ ^ ^^^ ^ ^ ^^              ^ ^ ^^^^^^^^^^^^
+    //                    6 token-trees               3 token-trees
+
+    count - 9
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros27.rs b/gcc/testsuite/rust/execute/torture/macros27.rs
new file mode 100644
index 00000000000..d515bb278a0
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros27.rs
@@ -0,0 +1,24 @@
+// { dg-additional-options "-frust-cfg=A" }
+
+macro_rules! attr {
+    (#[$attr:meta] $s:stmt) => {
+        #[$attr]
+        $s;
+    };
+}
+
+fn main() -> i32 {
+    let mut a = 0;
+
+    attr! {
+    #[cfg(A)]
+        a = 3
+    };
+
+    attr! {
+    #[cfg(B)]
+        a = 40
+    };
+
+    a - 3
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros28.rs b/gcc/testsuite/rust/execute/torture/macros28.rs
new file mode 100644
index 00000000000..b011f924149
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros28.rs
@@ -0,0 +1,13 @@
+macro_rules! t {
+    () => {
+        i32
+    };
+}
+
+fn id<T>(arg: T) -> T {
+    arg
+}
+
+fn main() -> i32 {
+    id::<t!()>(15) - 15
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros29.rs b/gcc/testsuite/rust/execute/torture/macros29.rs
new file mode 100644
index 00000000000..306979b9b5b
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros29.rs
@@ -0,0 +1,24 @@
+// { dg-output "1\n" }
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {{}};
+}
+
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: u32) {
+    unsafe {
+        printf("%u\n\0" as *const str as *const i8, s);
+    }
+}
+
+fn main() -> i32 {
+    let res = concat!("test2") == "test3";
+    if !res {
+        print(1);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros3.rs b/gcc/testsuite/rust/execute/torture/macros3.rs
new file mode 100644
index 00000000000..00f6d253f50
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros3.rs
@@ -0,0 +1,61 @@
+// { dg-output "invok\ninvok\ninvok\ninvok\ninvok\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn f() {
+    unsafe {
+        let r_s = "invok\n\0";
+        let s_p = r_s as *const str;
+        let c_p = s_p as *const i8;
+
+        printf(c_p);
+    }
+}
+
+macro_rules! invocation0 {
+    (valid) => {
+        f();
+    };
+    () => {};
+}
+
+macro_rules! invocation1 {
+    (valid) => {};
+    () => {
+        f();
+    };
+}
+
+macro_rules! invocation2 {
+    (valid) => {
+        f();
+    };
+    (invalid) => {};
+}
+
+macro_rules! invocation3 {
+    (this is a valid invocation) => {
+        f();
+    };
+    (not this one) => {};
+}
+
+macro_rules! invocation4 {
+    (fn f() {}) => {
+        f();
+    };
+    (not a keyword) => {};
+}
+
+fn main() -> i32 {
+    invocation0!(valid);
+    invocation1!();
+    invocation2!(valid);
+    invocation3!(this is a valid invocation);
+    invocation4!(
+        fn f() {}
+    );
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros30.rs b/gcc/testsuite/rust/execute/torture/macros30.rs
new file mode 100644
index 00000000000..ab36f5e78af
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros30.rs
@@ -0,0 +1,25 @@
+// { dg-output "1\n" }
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {{}};
+}
+
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: u32) {
+    unsafe {
+        printf("%u\n\0" as *const str as *const i8, s);
+    }
+}
+
+fn main() -> i32 {
+    let mut x = concat!("x");
+    x = concat!("y");
+    if x == "y" {
+        print(1);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros31.rs b/gcc/testsuite/rust/execute/torture/macros31.rs
new file mode 100644
index 00000000000..483f897a92b
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros31.rs
@@ -0,0 +1,32 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+// { dg-output "A\nB\n" }
+#[rustc_builtin_macro]
+macro_rules! cfg {
+    () => {{}};
+}
+
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: &str) {
+    unsafe {
+        printf(
+            "%s\n" as *const str as *const i8,
+            s as *const str as *const i8,
+        );
+    }
+}
+
+fn main() -> i32 {
+    let cfg = cfg!(A) || cfg!(B);
+    if cfg {
+        print("A");
+    }
+    let cfg = cfg!(A) && cfg!(B);
+    if !cfg {
+        print("B");
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros4.rs b/gcc/testsuite/rust/execute/torture/macros4.rs
new file mode 100644
index 00000000000..3303bfa58aa
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros4.rs
@@ -0,0 +1,15 @@
+macro_rules! add {
+    ($a:expr,$b:expr) => {
+        $a + $b
+    };
+    ($a:expr) => {
+        $a
+    };
+}
+
+fn main() -> i32 {
+    let mut x = add!(1);
+    x += add!(2, 3);
+
+    x - 6
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros5.rs b/gcc/testsuite/rust/execute/torture/macros5.rs
new file mode 100644
index 00000000000..822665494a4
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros5.rs
@@ -0,0 +1,13 @@
+macro_rules! add {
+    ($a:expr,$b:expr) => {{
+        $a + $b
+    }};
+}
+
+fn test() -> i32 {
+    add!(1, 2)
+}
+
+fn main() -> i32 {
+    test() - 3
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros6.rs b/gcc/testsuite/rust/execute/torture/macros6.rs
new file mode 100644
index 00000000000..652a765d5a8
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros6.rs
@@ -0,0 +1,12 @@
+macro_rules! Test {
+    ($a:ident, $b:ty) => {
+        struct $a($b);
+    };
+}
+
+Test!(Foo, i32);
+
+fn main() -> i32 {
+    let a = Foo(123);
+    a.0 - 123
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros7.rs b/gcc/testsuite/rust/execute/torture/macros7.rs
new file mode 100644
index 00000000000..ed1f922f581
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros7.rs
@@ -0,0 +1,28 @@
+// { dg-output "any\nany\nany\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn f() {
+    let r_s = "any\n\0";
+    let s_p = r_s as *const str;
+    let c_p = s_p as *const i8;
+
+    unsafe {
+        printf(c_p);
+    }
+}
+
+macro_rules! any {
+    ($($a:expr)*) => {
+        f();
+    };
+}
+
+fn main() -> i32 {
+    any!();
+    any!(a + b);
+    any!(a + b    14 "gcc");
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros8.rs b/gcc/testsuite/rust/execute/torture/macros8.rs
new file mode 100644
index 00000000000..a12aca4910e
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros8.rs
@@ -0,0 +1,27 @@
+// { dg-output "zo1\nzo1\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn f() {
+    let r_s = "zo1\n\0";
+    let s_p = r_s as *const str;
+    let c_p = s_p as *const i8;
+
+    unsafe {
+        printf(c_p);
+    }
+}
+
+macro_rules! zero_or_one {
+    ($($a:expr)?) => {
+        f();
+    };
+}
+
+fn main() -> i32 {
+    zero_or_one!();
+    zero_or_one!(f());
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros9.rs b/gcc/testsuite/rust/execute/torture/macros9.rs
new file mode 100644
index 00000000000..0e3fd24e8a9
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros9.rs
@@ -0,0 +1,28 @@
+// { dg-output "oom\noom\noom\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn f() {
+    let r_s = "oom\n\0";
+    let s_p = r_s as *const str;
+    let c_p = s_p as *const i8;
+
+    unsafe {
+        printf(c_p);
+    }
+}
+
+macro_rules! one_or_more {
+    ($($a:expr)+) => {
+        f();
+    };
+}
+
+fn main() -> i32 {
+    one_or_more!(f());
+    one_or_more!(f() f());
+    one_or_more!(f() f() 15 + 12);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match1.rs b/gcc/testsuite/rust/execute/torture/match1.rs
new file mode 100644
index 00000000000..e5af512f15d
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match1.rs
@@ -0,0 +1,58 @@
+// { dg-output "Foo::A\nFoo::B\nFoo::C x\nFoo::D 20 80\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+enum Foo {
+    A,
+    B,
+    C(char),
+    D { x: i32, y: i32 },
+}
+
+fn inspect(f: Foo) {
+    match f {
+        Foo::A => unsafe {
+            let a = "Foo::A\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        },
+        Foo::B => unsafe {
+            let a = "Foo::B\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        },
+        Foo::C(x) => unsafe {
+            let a = "Foo::C %c\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, x);
+        },
+        Foo::D { x, y } => unsafe {
+            let a = "Foo::D %i %i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, x, y);
+        },
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo::A;
+    let b = Foo::B;
+    let c = Foo::C('x');
+    let d = Foo::D { x: 20, y: 80 };
+
+    inspect(a);
+    inspect(b);
+    inspect(c);
+    inspect(d);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match2.rs b/gcc/testsuite/rust/execute/torture/match2.rs
new file mode 100644
index 00000000000..02cedf29b3c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match2.rs
@@ -0,0 +1,41 @@
+// { dg-output "123\n80\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+enum Foo {
+    C(i32),
+    D { x: i32, y: i32 },
+}
+
+fn inspect(f: Foo) -> i32 {
+    match f {
+        Foo::C(x) => x,
+        Foo::D { x, y } => y,
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo::C(123);
+    let b = Foo::D { x: 20, y: 80 };
+
+    let result = inspect(a);
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, result);
+    }
+
+    let result = inspect(b);
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, result);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match3.rs b/gcc/testsuite/rust/execute/torture/match3.rs
new file mode 100644
index 00000000000..8cded3044df
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match3.rs
@@ -0,0 +1,51 @@
+// { dg-output "Foo::A\nwildcard\nwildcard\nFoo::D 20 80\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+enum Foo {
+    A,
+    B,
+    C(char),
+    D { x: i32, y: i32 },
+}
+
+fn inspect(f: Foo) {
+    match f {
+        Foo::A => unsafe {
+            let a = "Foo::A\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        },
+        Foo::D { x, y } => unsafe {
+            let a = "Foo::D %i %i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, x, y);
+        },
+        _ => unsafe {
+            let a = "wildcard\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        },
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo::A;
+    let b = Foo::B;
+    let c = Foo::C('x');
+    let d = Foo::D { x: 20, y: 80 };
+
+    inspect(a);
+    inspect(b);
+    inspect(c);
+    inspect(d);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match_bool1.rs b/gcc/testsuite/rust/execute/torture/match_bool1.rs
new file mode 100644
index 00000000000..101dbb58571
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match_bool1.rs
@@ -0,0 +1,49 @@
+// { dg-output "182 is more than 100\n55 is less than 100\n" }
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn foo(x: bool) -> i32 {
+    match x {
+        true => {
+            return 182;
+        }
+        false => {
+            return 55;
+        }
+    }
+}
+
+fn bar(y: i32) {
+    match y < 100 {
+        true => {
+            let a = "%i is less than 100\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            unsafe {
+                printf(c, y);
+            }
+        }
+        _ => {
+            let a = "%i is more than 100\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            unsafe {
+                printf(c, y);
+            }
+        }
+    }
+}
+
+fn main() -> i32 {
+    let a = foo(true);
+    let b = foo(false);
+
+    bar(a);
+    bar(b);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match_byte1.rs b/gcc/testsuite/rust/execute/torture/match_byte1.rs
new file mode 100644
index 00000000000..3546cfb9d8b
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match_byte1.rs
@@ -0,0 +1,56 @@
+// { dg-output "a\nseven\nquote\nelse" }
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn foo(x: u8) {
+    match x {
+        b'a' => {
+            let a = "a\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        b'\x07' => {
+            let a = "seven\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        b'\'' => {
+            let a = "quote\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        _ => {
+            let a = "else\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+    }
+}
+
+fn main() -> i32 {
+    let x: u8 = 7;
+
+    foo(b'a');
+    foo(x);
+    foo(b'\'');
+    foo(b'\\');
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match_char1.rs b/gcc/testsuite/rust/execute/torture/match_char1.rs
new file mode 100644
index 00000000000..fa65876a907
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match_char1.rs
@@ -0,0 +1,56 @@
+// { dg-output "amazing\nwildcard\ncompiler\nproductivity\n" }
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn foo(x: char) {
+    match x {
+        'a' => {
+            let a = "amazing\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        'c' => {
+            let a = "compiler\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        'p' => {
+            let a = "productivity\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        _ => {
+            let a = "wildcard\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+    }
+}
+
+fn main() -> i32 {
+    let p = 'p';
+
+    foo('a');
+    foo('b');
+    foo('c');
+    foo(p);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match_int1.rs b/gcc/testsuite/rust/execute/torture/match_int1.rs
new file mode 100644
index 00000000000..209429added
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match_int1.rs
@@ -0,0 +1,109 @@
+// { dg-output "other!\nother!\nother!\nfifteen!\nfifteen!\nother!\nother!\nfifteen!\n" }
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn foo_i32(x: i32) {
+    match x {
+        15 => {
+            let a = "fifteen!\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        _ => {
+            let a = "other!\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+    }
+}
+
+fn foo_isize(x: isize) {
+    match x {
+        15 => {
+            let a = "fifteen!\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        _ => {
+            let a = "other!\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+    }
+}
+
+fn foo_u32(x: u32) {
+    match x {
+        15 => {
+            let a = "fifteen!\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        _ => {
+            let a = "other!\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+    }
+}
+
+fn foo_usize(x: usize) {
+    match x {
+        15 => {
+            let a = "fifteen!\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        _ => {
+            let a = "other!\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+    }
+}
+
+fn main() -> i32 {
+    let x = -2;
+    foo_i32(x);
+    foo_i32(334);
+    foo_isize(-4768);
+    foo_isize(15);
+
+    let y = 127;
+    foo_u32(15);
+    foo_u32(y);
+    foo_usize(2394);
+    foo_usize(15);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match_loop1.rs b/gcc/testsuite/rust/execute/torture/match_loop1.rs
new file mode 100644
index 00000000000..bb6aee946f6
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match_loop1.rs
@@ -0,0 +1,56 @@
+// { dg-output "E::One\nE::Two\nbreak!\n" }
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+enum E {
+    One,
+    Two,
+    Other,
+}
+
+fn foo() {
+    let mut x = E::One;
+
+    loop {
+        match x {
+            E::One => {
+                let a = "E::One\n\0";
+                let b = a as *const str;
+                let c = b as *const i8;
+                unsafe {
+                    printf(c);
+                }
+
+                x = E::Two;
+            }
+            E::Two => {
+                let a = "E::Two\n\0";
+                let b = a as *const str;
+                let c = b as *const i8;
+                unsafe {
+                    printf(c);
+                }
+
+                x = E::Other;
+            }
+            _ => {
+                let a = "break!\n\0";
+                let b = a as *const str;
+                let c = b as *const i8;
+                unsafe {
+                    printf(c);
+                }
+
+                break;
+            }
+        }
+    }
+}
+
+fn main() -> i32 {
+    foo();
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match_range1.rs b/gcc/testsuite/rust/execute/torture/match_range1.rs
new file mode 100644
index 00000000000..82e9e34a989
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match_range1.rs
@@ -0,0 +1,37 @@
+// { dg-output "zero to END_RANGE\nzero to END_RANGE\nelse\n" }
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+const END_RANGE: i32 = 15;
+
+fn foo(x: i32) {
+    match x {
+        0..=END_RANGE => {
+            let a = "zero to END_RANGE\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        _ => {
+            let a = "else\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+    }
+}
+
+fn main() -> i32 {
+    foo(11);
+    foo(15);
+    foo(21);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match_range2.rs b/gcc/testsuite/rust/execute/torture/match_range2.rs
new file mode 100644
index 00000000000..8153f9e1c7e
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match_range2.rs
@@ -0,0 +1,45 @@
+// { dg-output "lowercase\nuppercase\nother\n" }
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+const BIG_A: char = 'A';
+const BIG_Z: char = 'Z';
+
+fn bar(x: char) {
+    match x {
+        'a'..='z' => {
+            let a = "lowercase\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+        BIG_A..=BIG_Z => {
+            let a = "uppercase\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+        _ => {
+            let a = "other\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+    }
+}
+
+fn main() -> i32 {
+    bar('b');
+    bar('X');
+    bar('!');
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match_tuple1.rs b/gcc/testsuite/rust/execute/torture/match_tuple1.rs
new file mode 100644
index 00000000000..cb61cc0847c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match_tuple1.rs
@@ -0,0 +1,45 @@
+// { dg-output "x:15\ny:20\n" }
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+enum Foo {
+    A,
+    B,
+}
+
+fn inspect(f: Foo, g: u8) -> i32 {
+    match (f, g) {
+        (Foo::A, 1) => {
+            return 5;
+        }
+
+        (Foo::A, 2) => {
+            return 10;
+        }
+
+        (Foo::B, 2) => {
+            return 15;
+        }
+
+        _ => {
+            return 20;
+        }
+    }
+    return 25;
+}
+
+fn main() -> i32 {
+    let x = inspect(Foo::B, 2);
+    let y = inspect(Foo::B, 1);
+
+    unsafe {
+        printf("x:%d\n" as *const str as *const i8, x);
+    }
+    unsafe {
+        printf("y:%d\n" as *const str as *const i8, y);
+    }
+
+    y - x - 5
+}
diff --git a/gcc/testsuite/rust/execute/torture/method1.rs b/gcc/testsuite/rust/execute/torture/method1.rs
new file mode 100644
index 00000000000..6af6133939b
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/method1.rs
@@ -0,0 +1,27 @@
+/* { dg-output "124\n458" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+impl Foo {
+    fn bar(&self, i: i32) {
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, self.0 + i);
+        }
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo(123);
+    a.bar(1);
+
+    let b = &Foo(456);
+    b.bar(2);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/method2.rs b/gcc/testsuite/rust/execute/torture/method2.rs
new file mode 100644
index 00000000000..f532b4488c6
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/method2.rs
@@ -0,0 +1,76 @@
+// { dg-additional-options "-w" }
+// { dg-output "foo_deref\nimm_deref\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+    type Target;
+
+    fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "imm_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+impl<T> Deref for &mut T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "mut_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+struct Bar(i32);
+impl Bar {
+    fn foobar(self) -> i32 {
+        self.0
+    }
+}
+
+struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        unsafe {
+            let a = "foo_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        &self.0
+    }
+}
+
+pub fn main() -> i32 {
+    let bar = Bar(123);
+    let foo: Foo<&Bar> = Foo(&bar);
+    let foobar: i32 = foo.foobar();
+
+    foobar - 123
+}
diff --git a/gcc/testsuite/rust/execute/torture/method3.rs b/gcc/testsuite/rust/execute/torture/method3.rs
new file mode 100644
index 00000000000..0e9e8ff42a0
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/method3.rs
@@ -0,0 +1,78 @@
+// { dg-additional-options "-w" }
+// { dg-output "mut_deref\nfoobar: 123\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+    type Target;
+
+    fn deref(&self) -> &Self::Target;
+}
+
+#[lang = "deref_mut"]
+pub trait DerefMut: Deref {
+    fn deref_mut(&mut self) -> &mut Self::Target;
+}
+
+impl<T> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        *self
+    }
+}
+
+impl<T> Deref for &mut T {
+    type Target = T;
+    fn deref(&self) -> &T {
+        *self
+    }
+}
+
+pub struct Bar(i32);
+impl Bar {
+    pub fn foobar(&mut self) -> i32 {
+        self.0
+    }
+}
+
+pub struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl<T> DerefMut for Foo<T> {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        unsafe {
+            let a = "mut_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        &mut self.0
+    }
+}
+
+pub fn main() -> i32 {
+    let bar = Bar(123);
+    let mut foo: Foo<Bar> = Foo(bar);
+    let foobar = foo.foobar();
+
+    unsafe {
+        let a = "foobar: %i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, foobar);
+    }
+
+    foobar - 123
+}
diff --git a/gcc/testsuite/rust/execute/torture/method4.rs b/gcc/testsuite/rust/execute/torture/method4.rs
new file mode 100644
index 00000000000..5c6fdfe02c3
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/method4.rs
@@ -0,0 +1,78 @@
+// { dg-additional-options "-w" }
+// { dg-output "mut_deref\nfoobar: 123\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+    type Target;
+
+    fn deref(&self) -> &Self::Target;
+}
+
+#[lang = "deref_mut"]
+pub trait DerefMut: Deref {
+    fn deref_mut(&mut self) -> &mut Self::Target;
+}
+
+impl<T> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        *self
+    }
+}
+
+impl<T> Deref for &mut T {
+    type Target = T;
+    fn deref(&self) -> &T {
+        *self
+    }
+}
+
+pub struct Bar(i32);
+impl Bar {
+    pub fn foobar(&mut self) -> i32 {
+        self.0
+    }
+}
+
+pub struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl<T> DerefMut for Foo<T> {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        unsafe {
+            let a = "mut_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        &mut self.0
+    }
+}
+
+pub fn main() -> i32 {
+    let mut bar = Bar(123);
+    let mut foo: Foo<&mut Bar> = Foo(&mut bar);
+    let foobar = foo.foobar();
+
+    unsafe {
+        let a = "foobar: %i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, foobar);
+    }
+
+    foobar - 123
+}
diff --git a/gcc/testsuite/rust/execute/torture/mod1.rs b/gcc/testsuite/rust/execute/torture/mod1.rs
new file mode 100644
index 00000000000..700393850af
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/mod1.rs
@@ -0,0 +1,21 @@
+mod A {
+    pub mod B {
+        pub mod C {
+            pub struct Foo {
+                pub f: i32,
+            }
+            impl Foo {
+                pub fn new() -> Self {
+                    Foo { f: 23i32 }
+                }
+            }
+        }
+    }
+}
+
+fn main() -> i32 {
+    let a = A::B::C::Foo::new();
+    let b = A::B::C::Foo { f: -23i32 };
+
+    a.f + b.f
+}
diff --git a/gcc/testsuite/rust/execute/torture/modules/mod.rs b/gcc/testsuite/rust/execute/torture/modules/mod.rs
new file mode 100644
index 00000000000..9020aaf4bb8
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/modules/mod.rs
@@ -0,0 +1,3 @@
+fn return_12() -> i32 {
+    12
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_1.rs b/gcc/testsuite/rust/execute/torture/operator_overload_1.rs
new file mode 100644
index 00000000000..5a28c5f4e93
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_1.rs
@@ -0,0 +1,36 @@
+/* { dg-output "3\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "add"]
+pub trait Add<Rhs = Self> {
+    type Output;
+
+    fn add(self, rhs: Rhs) -> Self::Output;
+}
+
+impl Add for i32 {
+    type Output = i32;
+
+    fn add(self, other: i32) -> i32 {
+        let res = self + other;
+
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, res);
+        }
+
+        res
+    }
+}
+
+fn main() -> i32 {
+    let a;
+    a = 1 + 2;
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_10.rs b/gcc/testsuite/rust/execute/torture/operator_overload_10.rs
new file mode 100644
index 00000000000..f5d45db5338
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_10.rs
@@ -0,0 +1,75 @@
+/* { dg-output "foo_deref\n123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+    type Target;
+
+    fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "imm_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+impl<T> Deref for &mut T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "mut_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        unsafe {
+            let a = "foo_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        &self.0
+    }
+}
+
+fn main() -> i32 {
+    let foo: Foo<i32> = Foo(123);
+    let bar: i32 = *foo;
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, bar);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_11.rs b/gcc/testsuite/rust/execute/torture/operator_overload_11.rs
new file mode 100644
index 00000000000..1919941c486
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_11.rs
@@ -0,0 +1,37 @@
+// { dg-output "1\n" }
+// { dg-additional-options "-w" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "bitand"]
+pub trait BitAnd<Rhs = Self> {
+    type Output;
+
+    fn bitand(self, rhs: Rhs) -> Self::Output;
+}
+
+impl BitAnd for i32 {
+    type Output = i32;
+
+    fn bitand(self, other: i32) -> i32 {
+        let res = self & other;
+
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, res);
+        }
+
+        res
+    }
+}
+
+fn main() -> i32 {
+    let a;
+    a = 1 & 1;
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_12.rs b/gcc/testsuite/rust/execute/torture/operator_overload_12.rs
new file mode 100644
index 00000000000..7433330fa31
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_12.rs
@@ -0,0 +1,31 @@
+// { dg-output "1\n" }
+// { dg-additional-options "-w" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "bitand_assign"]
+pub trait BitAndAssign<Rhs = Self> {
+    fn bitand_assign(&mut self, rhs: Rhs);
+}
+
+impl BitAndAssign for i32 {
+    fn bitand_assign(&mut self, other: i32) {
+        *self &= other;
+
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, *self);
+        }
+    }
+}
+
+fn main() -> i32 {
+    let mut a = 1;
+    a &= 1;
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_2.rs b/gcc/testsuite/rust/execute/torture/operator_overload_2.rs
new file mode 100644
index 00000000000..a577718451d
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_2.rs
@@ -0,0 +1,38 @@
+/* { dg-output "3\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "add"]
+pub trait Add<Rhs = Self> {
+    type Output;
+
+    fn add(self, rhs: Rhs) -> Self::Output;
+}
+
+struct Foo(i32);
+
+impl Add for Foo {
+    type Output = Foo;
+
+    fn add(self, other: Foo) -> Foo {
+        let res = Foo(self.0 + other.0);
+
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, res.0);
+        }
+
+        res
+    }
+}
+
+fn main() -> i32 {
+    let a;
+    a = Foo(1) + Foo(2);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_3.rs b/gcc/testsuite/rust/execute/torture/operator_overload_3.rs
new file mode 100644
index 00000000000..57f58076c3e
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_3.rs
@@ -0,0 +1,55 @@
+/* { dg-output "3\n3\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "add"]
+pub trait Add<Rhs = Self> {
+    type Output;
+
+    fn add(self, rhs: Rhs) -> Self::Output;
+}
+
+impl Add for i32 {
+    type Output = i32;
+
+    fn add(self, other: i32) -> i32 {
+        let res = self + other;
+
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, res);
+        }
+
+        res
+    }
+}
+
+struct Foo(i32);
+impl Add for Foo {
+    type Output = Foo;
+
+    fn add(self, other: Foo) -> Foo {
+        let res = Foo(self.0 + other.0);
+
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, res.0);
+        }
+
+        res
+    }
+}
+
+fn main() -> i32 {
+    let a;
+    a = Foo(1) + Foo(2);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_4.rs b/gcc/testsuite/rust/execute/torture/operator_overload_4.rs
new file mode 100644
index 00000000000..ce9887b2ead
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_4.rs
@@ -0,0 +1,33 @@
+/* { dg-output "neg\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "neg"]
+pub trait Neg {
+    type Output;
+
+    fn neg(self) -> Self::Output;
+}
+
+impl Neg for i32 {
+    type Output = i32;
+
+    fn neg(self) -> i32 {
+        unsafe {
+            let a = "neg\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+        -self
+    }
+}
+
+fn main() -> i32 {
+    let a: i32 = 1;
+    let _b = -a;
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_5.rs b/gcc/testsuite/rust/execute/torture/operator_overload_5.rs
new file mode 100644
index 00000000000..a525f743680
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_5.rs
@@ -0,0 +1,33 @@
+/* { dg-output "not\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "not"]
+pub trait Not {
+    type Output;
+
+    fn not(self) -> Self::Output;
+}
+
+impl Not for i32 {
+    type Output = i32;
+
+    fn not(self) -> i32 {
+        unsafe {
+            let a = "not\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+        !self
+    }
+}
+
+fn main() -> i32 {
+    let a: i32 = 1;
+    let _b = !a;
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_6.rs b/gcc/testsuite/rust/execute/torture/operator_overload_6.rs
new file mode 100644
index 00000000000..fbd2a8fa9d3
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_6.rs
@@ -0,0 +1,37 @@
+/* { dg-output "add_assign\n3\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "add_assign"]
+pub trait AddAssign<Rhs = Self> {
+    fn add_assign(&mut self, rhs: Rhs);
+}
+
+impl AddAssign for i32 {
+    fn add_assign(&mut self, other: i32) {
+        unsafe {
+            let a = "add_assign\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+        *self += other
+    }
+}
+
+fn main() -> i32 {
+    let mut res = 1;
+    res += 2;
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, res);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_7.rs b/gcc/testsuite/rust/execute/torture/operator_overload_7.rs
new file mode 100644
index 00000000000..886a7010efc
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_7.rs
@@ -0,0 +1,42 @@
+/* { dg-output "imm_deref\n123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+    type Target;
+
+    fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "imm_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+fn main() -> i32 {
+    let foo: &i32 = &123;
+    let res: i32 = *foo;
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, res);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_8.rs b/gcc/testsuite/rust/execute/torture/operator_overload_8.rs
new file mode 100644
index 00000000000..862e29a4bc6
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_8.rs
@@ -0,0 +1,58 @@
+/* { dg-output "imm_deref\n123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+    type Target;
+
+    fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "imm_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+impl<T> Deref for &mut T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "mut_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+fn main() -> i32 {
+    let foo: &i32 = &123;
+    let res: i32 = *foo;
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, res);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_9.rs b/gcc/testsuite/rust/execute/torture/operator_overload_9.rs
new file mode 100644
index 00000000000..fd972e28ab3
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_9.rs
@@ -0,0 +1,58 @@
+/* { dg-output "mut_deref\n123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+    type Target;
+
+    fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "imm_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+impl<T> Deref for &mut T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "mut_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+fn main() -> i32 {
+    let foo = &mut 123;
+    let res: i32 = *foo;
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, res);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/slice-magic.rs b/gcc/testsuite/rust/execute/torture/slice-magic.rs
new file mode 100644
index 00000000000..d1132989ddb
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/slice-magic.rs
@@ -0,0 +1,106 @@
+// { dg-additional-options "-w" }
+extern "rust-intrinsic" {
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+    pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+struct FatPtr<T> {
+    data: *const T,
+    len: usize,
+}
+
+union Repr<T> {
+    rust: *const [T],
+    rust_mut: *mut [T],
+    raw: FatPtr<T>,
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+    pub start: Idx,
+    pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<A> *const [A] {
+    pub const fn len(self) -> usize {
+        unsafe { Repr { rust: self }.raw.len }
+    }
+
+    pub const fn as_ptr(self) -> *const A {
+        self as *const A
+    }
+}
+
+#[lang = "const_ptr"]
+impl<B> *const B {
+    pub const unsafe fn offset(self, count: isize) -> *const B {
+        unsafe { offset(self, count) }
+    }
+
+    pub const unsafe fn add(self, count: usize) -> Self {
+        unsafe { self.offset(count as isize) }
+    }
+
+    pub const fn as_ptr(self) -> *const B {
+        self as *const B
+    }
+}
+
+const fn slice_from_raw_parts<C>(data: *const C, len: usize) -> *const [C] {
+    unsafe {
+        Repr {
+            raw: FatPtr { data, len },
+        }
+        .rust
+    }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+    type Output;
+
+    fn index(&self, index: Idx) -> &Self::Output;
+}
+
+pub unsafe trait SliceIndex<X> {
+    type Output;
+
+    unsafe fn get_unchecked(self, slice: *const X) -> *const Self::Output;
+
+    fn index(self, slice: &X) -> &Self::Output;
+}
+
+unsafe impl<Y> SliceIndex<[Y]> for Range<usize> {
+    type Output = [Y];
+
+    unsafe fn get_unchecked(self, slice: *const [Y]) -> *const [Y] {
+        unsafe {
+            let a: *const Y = slice.as_ptr();
+            let b: *const Y = a.add(self.start);
+            slice_from_raw_parts(b, self.end - self.start)
+        }
+    }
+
+    fn index(self, slice: &[Y]) -> &[Y] {
+        unsafe { &*self.get_unchecked(slice) }
+    }
+}
+
+impl<T, I> Index<I> for [T]
+where
+    I: SliceIndex<[T]>,
+{
+    type Output = I::Output;
+
+    fn index(&self, index: I) -> &I::Output {
+        index.index(self)
+    }
+}
+
+fn main() -> i32 {
+    let a = [1, 2, 3, 4, 5];
+    let b = &a[1..3];
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/slice-magic2.rs b/gcc/testsuite/rust/execute/torture/slice-magic2.rs
new file mode 100644
index 00000000000..64a566185fa
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/slice-magic2.rs
@@ -0,0 +1,106 @@
+// { dg-additional-options "-w" }
+extern "rust-intrinsic" {
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+    pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+struct FatPtr<T> {
+    data: *const T,
+    len: usize,
+}
+
+union Repr<T> {
+    rust: *const [T],
+    rust_mut: *mut [T],
+    raw: FatPtr<T>,
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+    pub start: Idx,
+    pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<T> *const [T] {
+    pub const fn len(self) -> usize {
+        unsafe { Repr { rust: self }.raw.len }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+    pub const unsafe fn offset(self, count: isize) -> *const T {
+        unsafe { offset(self, count) }
+    }
+
+    pub const unsafe fn add(self, count: usize) -> Self {
+        unsafe { self.offset(count as isize) }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+    unsafe {
+        Repr {
+            raw: FatPtr { data, len },
+        }
+        .rust
+    }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+    type Output;
+
+    fn index(&self, index: Idx) -> &Self::Output;
+}
+
+pub unsafe trait SliceIndex<T> {
+    type Output;
+
+    unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
+
+    fn index(self, slice: &T) -> &Self::Output;
+}
+
+unsafe impl<T> SliceIndex<[T]> for Range<usize> {
+    type Output = [T];
+
+    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+        unsafe {
+            let a: *const T = slice.as_ptr();
+            let b: *const T = a.add(self.start);
+            slice_from_raw_parts(b, self.end - self.start)
+        }
+    }
+
+    fn index(self, slice: &[T]) -> &[T] {
+        unsafe { &*self.get_unchecked(slice) }
+    }
+}
+
+impl<T, I> Index<I> for [T]
+where
+    I: SliceIndex<[T]>,
+{
+    type Output = I::Output;
+
+    fn index(&self, index: I) -> &I::Output {
+        index.index(self)
+    }
+}
+
+fn main() -> i32 {
+    let a = [1, 2, 3, 4, 5];
+    let b = &a[1..3];
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/slice1.rs b/gcc/testsuite/rust/execute/torture/slice1.rs
new file mode 100644
index 00000000000..a0488b3912c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/slice1.rs
@@ -0,0 +1,27 @@
+// { dg-additional-options "-w" }
+struct FatPtr<T> {
+    data: *const T,
+    len: usize,
+}
+
+union Repr<T> {
+    rust: *const [T],
+    rust_mut: *mut [T],
+    raw: FatPtr<T>,
+}
+
+const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+    unsafe {
+        let a = FatPtr { data, len };
+        let b = Repr { raw: a };
+        b.rust
+    }
+}
+
+fn main() -> i32 {
+    let a = 123;
+    let b: *const i32 = &a;
+    let c = slice_from_raw_parts(b, 1);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/str-layout1.rs b/gcc/testsuite/rust/execute/torture/str-layout1.rs
new file mode 100644
index 00000000000..80bdc2a9c9f
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/str-layout1.rs
@@ -0,0 +1,57 @@
+// { dg-additional-options "-w" }
+// { dg-output "t1sz=5 t2sz=10" }
+mod mem {
+    extern "rust-intrinsic" {
+        #[rustc_const_stable(feature = "const_transmute", since = "1.46.0")]
+        fn transmute<T, U>(_: T) -> U;
+    }
+}
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct FatPtr<T> {
+    data: *const T,
+    len: usize,
+}
+
+pub union Repr<T> {
+    rust: *const [T],
+    rust_mut: *mut [T],
+    raw: FatPtr<T>,
+}
+
+impl<T> [T] {
+    pub const fn len(&self) -> usize {
+        unsafe { Repr { rust: self }.raw.len }
+    }
+}
+
+impl str {
+    pub const fn len(&self) -> usize {
+        self.as_bytes().len()
+    }
+
+    pub const fn as_bytes(&self) -> &[u8] {
+        unsafe { mem::transmute(self) }
+    }
+}
+
+fn main() -> i32 {
+    let t1: &str = "TEST1";
+    let t2: &str = &"TEST_12345";
+
+    let t1sz = t1.len();
+    let t2sz = t2.len();
+
+    unsafe {
+        let a = "t1sz=%i t2sz=%i\n";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, t1sz as i32, t2sz as i32);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/str-zero.rs b/gcc/testsuite/rust/execute/torture/str-zero.rs
new file mode 100644
index 00000000000..e7fba0d1372
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/str-zero.rs
@@ -0,0 +1,26 @@
+/* { 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;
+}
+
+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);
+    }
+  0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait1.rs b/gcc/testsuite/rust/execute/torture/trait1.rs
new file mode 100644
index 00000000000..dc3cc471c33
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait1.rs
@@ -0,0 +1,52 @@
+/* { dg-output "S::f\nT1::f\nT2::f\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct S;
+
+impl S {
+    fn f() {
+        unsafe {
+            let a = "S::f\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+    }
+}
+
+trait T1 {
+    fn f() {
+        unsafe {
+            let a = "T1::f\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+    }
+}
+impl T1 for S {}
+
+trait T2 {
+    fn f() {
+        unsafe {
+            let a = "T2::f\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+    }
+}
+impl T2 for S {}
+
+fn main() -> i32 {
+    S::f();
+    <S as T1>::f();
+    <S as T2>::f();
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait10.rs b/gcc/testsuite/rust/execute/torture/trait10.rs
new file mode 100644
index 00000000000..e581e324bbf
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait10.rs
@@ -0,0 +1,41 @@
+/* { dg-output "123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+trait Bar {
+    fn baz(&self);
+}
+
+impl Bar for Foo {
+    fn baz(&self) {
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, self.0);
+        }
+    }
+}
+
+struct S;
+impl S {
+    fn dynamic_dispatch(self, t: &dyn Bar) {
+        // { dg-warning "unused name" "" { target *-*-* } .-1 }
+        t.baz();
+    }
+}
+
+pub fn main() -> i32 {
+    let a;
+    a = &Foo(123);
+
+    let b;
+    b = S;
+
+    b.dynamic_dispatch(a);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait11.rs b/gcc/testsuite/rust/execute/torture/trait11.rs
new file mode 100644
index 00000000000..283c9ecd0ed
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait11.rs
@@ -0,0 +1,38 @@
+/* { dg-output "3\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+trait FnLike<A, R> {
+    fn call(&self, arg: A) -> R;
+}
+
+struct S;
+impl<'a, T> FnLike<&'a T, &'a T> for S {
+    fn call(&self, arg: &'a T) -> &'a T {
+        // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
+        arg
+    }
+}
+
+fn indirect<F>(f: F)
+where
+    F: for<'a> FnLike<&'a isize, &'a isize>,
+{
+    let x = 3;
+    let y = f.call(&x);
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, *y);
+    }
+}
+
+fn main() -> i32 {
+    indirect(S);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait12.rs b/gcc/testsuite/rust/execute/torture/trait12.rs
new file mode 100644
index 00000000000..68b0a4014ad
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait12.rs
@@ -0,0 +1,38 @@
+/* { dg-output "3\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+trait FnLike<A, R> {
+    fn call(&self, arg: A) -> R;
+}
+
+type FnObject<'b> = dyn for<'a> FnLike<&'a isize, &'a isize> + 'b;
+
+struct Identity;
+
+impl<'a, T> FnLike<&'a T, &'a T> for Identity {
+    fn call(&self, arg: &'a T) -> &'a T {
+        // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
+        arg
+    }
+}
+
+fn call_repeatedly(f: &FnObject) {
+    let x = 3;
+    let y = f.call(&x);
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, *y);
+    }
+}
+
+fn main() -> i32 {
+    call_repeatedly(&Identity);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait13.rs b/gcc/testsuite/rust/execute/torture/trait13.rs
new file mode 100644
index 00000000000..3071da27a6a
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait13.rs
@@ -0,0 +1,48 @@
+/* { dg-output "123\n456\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+trait Bar {
+    fn baz(&self);
+
+    fn qux(&self) {
+        // { dg-warning "unused name" "" { target *-*-* } .-1 }
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, 456);
+        }
+    }
+}
+
+impl Bar for Foo {
+    fn baz(&self) {
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, self.0);
+        }
+    }
+}
+
+fn dynamic_dispatch(t: &dyn Bar) {
+    t.baz();
+    t.qux();
+}
+
+fn main() -> i32 {
+    let a;
+    a = Foo(123);
+
+    let b: &dyn Bar;
+    b = &a;
+    dynamic_dispatch(b);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait2.rs b/gcc/testsuite/rust/execute/torture/trait2.rs
new file mode 100644
index 00000000000..c96615fa891
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait2.rs
@@ -0,0 +1,37 @@
+/* { dg-output "Bar::A = 456\n<Foo as Bar>::A = 456\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+trait Foo {
+    const A: i32 = 123;
+}
+
+struct Bar;
+impl Foo for Bar {
+    const A: i32 = 456;
+}
+
+fn main() -> i32 {
+    let a;
+    a = Bar::A;
+
+    unsafe {
+        let _a = "Bar::A = %i\n\0";
+        let _b = _a as *const str;
+        let _c = _b as *const i8;
+        printf(_c, a);
+    }
+
+    let b;
+    b = <Bar as Foo>::A;
+
+    unsafe {
+        let _a = "<Foo as Bar>::A = %i\n\0";
+        let _b = _a as *const str;
+        let _c = _b as *const i8;
+        printf(_c, b);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait3.rs b/gcc/testsuite/rust/execute/torture/trait3.rs
new file mode 100644
index 00000000000..accfa9d0a36
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait3.rs
@@ -0,0 +1,43 @@
+/* { dg-output "123, 777" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+trait A {
+    fn a() -> i32 {
+        123
+    }
+}
+
+trait B: A {
+    fn b() -> i32 {
+        <T as A>::a() + 456
+    }
+}
+
+struct T;
+// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+
+impl A for T {
+    fn a() -> i32 {
+        321
+    }
+}
+
+struct S;
+impl A for S {}
+impl B for S {}
+
+fn main() -> i32 {
+    let aa = S::a();
+    let bb = S::b();
+
+    unsafe {
+        let a = "%i, %i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, aa, bb);
+    }
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait4.rs b/gcc/testsuite/rust/execute/torture/trait4.rs
new file mode 100644
index 00000000000..8c0d257cd7e
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait4.rs
@@ -0,0 +1,34 @@
+/* { dg-output "123\n" }*/
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+trait Bar {
+    fn baz(&self);
+}
+
+impl Bar for Foo {
+    fn baz(&self) {
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, self.0);
+        }
+    }
+}
+
+fn type_bound<T: Bar>(t: &T) {
+    t.baz();
+}
+
+fn main() -> i32 {
+    let a;
+
+    a = &Foo(123);
+    type_bound(a);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait5.rs b/gcc/testsuite/rust/execute/torture/trait5.rs
new file mode 100644
index 00000000000..49f11a6085a
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait5.rs
@@ -0,0 +1,39 @@
+/* { dg-output "123\n123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+trait Bar {
+    fn baz(&self);
+}
+
+impl Bar for Foo {
+    fn baz(&self) {
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, self.0);
+        }
+    }
+}
+
+fn static_dispatch<T: Bar>(t: &T) {
+    t.baz();
+}
+
+fn dynamic_dispatch(t: &dyn Bar) {
+    t.baz();
+}
+
+fn main() -> i32 {
+    let a = &Foo(123);
+    static_dispatch(a);
+
+    let b: &dyn Bar = a;
+    dynamic_dispatch(b);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait6.rs b/gcc/testsuite/rust/execute/torture/trait6.rs
new file mode 100644
index 00000000000..c83d6666c87
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait6.rs
@@ -0,0 +1,39 @@
+/* { dg-output "123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+pub trait Foo {
+    type A;
+
+    fn bar(self) -> Self::A;
+}
+
+struct S(i32);
+impl Foo for S {
+    type A = i32;
+
+    fn bar(self) -> Self::A {
+        self.0
+    }
+}
+
+fn test_bar<T: Foo>(x: T) -> T::A {
+    x.bar()
+}
+
+fn main() -> i32 {
+    let a;
+    a = S(123);
+
+    let bar: i32 = test_bar::<S>(a);
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, bar);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait7.rs b/gcc/testsuite/rust/execute/torture/trait7.rs
new file mode 100644
index 00000000000..064f88d5de9
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait7.rs
@@ -0,0 +1,39 @@
+/* { dg-output "123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+pub trait Foo {
+    type A;
+
+    fn bar(self) -> Self::A;
+}
+
+struct S(i32);
+impl Foo for S {
+    type A = i32;
+
+    fn bar(self) -> Self::A {
+        self.0
+    }
+}
+
+fn test_bar<T: Foo>(x: T) -> T::A {
+    x.bar()
+}
+
+fn main() -> i32 {
+    let a;
+    a = S(123);
+
+    let bar: i32 = test_bar(a);
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, bar);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait8.rs b/gcc/testsuite/rust/execute/torture/trait8.rs
new file mode 100644
index 00000000000..14392ff0cca
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait8.rs
@@ -0,0 +1,39 @@
+/* { dg-output "123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+pub trait Foo {
+    type A;
+
+    fn bar(&self) -> Self::A;
+}
+
+struct S(i32);
+impl Foo for S {
+    type A = i32;
+
+    fn bar(&self) -> Self::A {
+        self.0
+    }
+}
+
+fn test_bar<T: Foo>(x: T) -> T::A {
+    x.bar()
+}
+
+fn main() -> i32 {
+    let a;
+    a = S(123);
+
+    let bar: i32 = test_bar(a);
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, bar);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait9.rs b/gcc/testsuite/rust/execute/torture/trait9.rs
new file mode 100644
index 00000000000..c0e6d36f183
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait9.rs
@@ -0,0 +1,35 @@
+/* { dg-output "3\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+trait FnLike<A, R> {
+    fn call(&self, arg: A) -> R;
+}
+
+struct S;
+impl<T> FnLike<&T, &T> for S {
+    fn call(&self, arg: &T) -> &T {
+        // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
+        arg
+    }
+}
+
+fn indirect<F: FnLike<&isize, &isize>>(f: F) {
+    let x = 3;
+    let y = f.call(&x);
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, *y);
+    }
+}
+
+fn main() -> i32 {
+    indirect(S);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/transmute1.rs b/gcc/testsuite/rust/execute/torture/transmute1.rs
new file mode 100644
index 00000000000..b9ec38ca618
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/transmute1.rs
@@ -0,0 +1,23 @@
+// { dg-additional-options "-w" }
+
+extern "rust-intrinsic" {
+    fn transmute<T, U>(value: T) -> U;
+}
+
+struct WrapI {
+    inner: i32,
+}
+
+struct WrapF {
+    inner: f32,
+}
+
+fn main() -> i32 {
+    let f = 15.4f32;
+    let f_wrap = WrapF { inner: f };
+
+    let fst = unsafe { transmute::<f32, i32>(f) };
+    let snd = unsafe { transmute::<WrapF, WrapI>(f_wrap) };
+
+    fst - snd.inner
+}
diff --git a/gcc/testsuite/rust/execute/torture/wrapping_op1.rs b/gcc/testsuite/rust/execute/torture/wrapping_op1.rs
new file mode 100644
index 00000000000..64b37085ab7
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/wrapping_op1.rs
@@ -0,0 +1,14 @@
+extern "rust-intrinsic" {
+    pub fn wrapping_add<T>(l: T, r: T) -> T;
+}
+
+fn five() -> u8 {
+    5
+}
+
+fn main() -> u8 {
+    let l = 255;
+    let r = five();
+
+    unsafe { wrapping_add(l, r) - 4 }
+}
diff --git a/gcc/testsuite/rust/execute/torture/wrapping_op2.rs b/gcc/testsuite/rust/execute/torture/wrapping_op2.rs
new file mode 100644
index 00000000000..f9990157894
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/wrapping_op2.rs
@@ -0,0 +1,20 @@
+extern "rust-intrinsic" {
+    pub fn wrapping_add<T>(l: T, r: T) -> T;
+    pub fn wrapping_sub<T>(l: T, r: T) -> T;
+    pub fn wrapping_mul<T>(l: T, r: T) -> T;
+}
+
+fn five() -> u8 {
+    5
+}
+
+fn main() -> u8 {
+    let l = 255;
+    let r = five();
+
+    let ret0 = unsafe { wrapping_add(l, r) - 4 }; // 4
+    let ret1 = unsafe { wrapping_sub(r, l) - 6 }; // 6
+    let ret2 = unsafe { wrapping_mul(r, l) - 251 }; // 251
+
+    ret0 + ret1 + ret2
+}
diff --git a/gcc/testsuite/rust/execute/xfail/macro1.rs b/gcc/testsuite/rust/execute/xfail/macro1.rs
new file mode 100644
index 00000000000..eab5a0285cf
--- /dev/null
+++ b/gcc/testsuite/rust/execute/xfail/macro1.rs
@@ -0,0 +1,32 @@
+// { dg-output "macro\nmacro\nmacro\nmacro\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn f() {
+    let r_s = "macro\n\0";
+    let s_p = r_s as *const str;
+    let c_p = s_p as *const i8;
+
+    printf(c_p);
+}
+
+macro_rules! empty0 {
+    () => ( f() );
+}
+
+macro_rules! empty1 {
+    {} => { f() };
+}
+
+macro_rules! empty2 {
+    [] => [ f() ];
+}
+
+// using multiple parens/brackets/curlies variants allows us to make sure we
+// parse everything properly
+fn main() {
+    empty0!();
+    empty1!{};
+    empty2![];
+}
-- 
2.25.1


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

* [PATCH Rust front-end v2 07/37] gccrs: Add gcc-check-target check-rust
  2022-08-24 11:59 Rust frontend patches v2 herron.philip
                   ` (5 preceding siblings ...)
  2022-08-24 11:59 ` [PATCH Rust front-end v2 06/37] gccrs: Add execution " herron.philip
@ 2022-08-24 11:59 ` herron.philip
  2022-09-14 13:41   ` Richard Biener
  2022-08-24 11:59 ` [PATCH Rust front-end v2 08/37] gccrs: Add the Rust front-end AST data structures herron.philip
                   ` (30 subsequent siblings)
  37 siblings, 1 reply; 57+ messages in thread
From: herron.philip @ 2022-08-24 11:59 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

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

This allows us to invoke the rust testsuite.

ChangeLog:
	* Makefile.def: Add autogen target
	* Makefile.in: regenerate via autogen
---
 Makefile.def | 1 +
 Makefile.in  | 8 ++++++++
 2 files changed, 9 insertions(+)

diff --git a/Makefile.def b/Makefile.def
index 3291b126b26..821016af3a2 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -681,6 +681,7 @@ languages = { language=go;	gcc-check-target=check-go;
 languages = { language=d;	gcc-check-target=check-d;
 				lib-check-target=check-target-libphobos; };
 languages = { language=jit;	gcc-check-target=check-jit; };
+languages = { language=rust;	gcc-check-target=check-rust; };
 
 // Toplevel bootstrap
 bootstrap_stage = { id=1 ; };
diff --git a/Makefile.in b/Makefile.in
index 1919dfee829..9ed2c0dec52 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -60583,6 +60583,14 @@ check-gcc-jit:
 	(cd gcc && $(MAKE) $(GCC_FLAGS_TO_PASS) check-jit);
 check-jit: check-gcc-jit
 
+.PHONY: check-gcc-rust check-rust
+check-gcc-rust:
+	r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	$(HOST_EXPORTS) \
+	(cd gcc && $(MAKE) $(GCC_FLAGS_TO_PASS) check-rust);
+check-rust: check-gcc-rust
+
 
 # The gcc part of install-no-fixedincludes, which relies on an intimate
 # knowledge of how a number of gcc internal targets (inter)operate.  Delegate.
-- 
2.25.1


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

* [PATCH Rust front-end v2 08/37] gccrs: Add the Rust front-end AST data structures
  2022-08-24 11:59 Rust frontend patches v2 herron.philip
                   ` (6 preceding siblings ...)
  2022-08-24 11:59 ` [PATCH Rust front-end v2 07/37] gccrs: Add gcc-check-target check-rust herron.philip
@ 2022-08-24 11:59 ` herron.philip
  2022-08-24 11:59 ` [PATCH Rust front-end v2 09/37] gccrs: Add Lexer for Rust front-end herron.philip
                   ` (29 subsequent siblings)
  37 siblings, 0 replies; 57+ messages in thread
From: herron.philip @ 2022-08-24 11:59 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, The Other, Philip Herron

From: The Other <simplytheother@gmail.com>

This is a full C++11 class hierarchy representing the Rust AST. We do not
allow dynamic_cast and so the main mechanism to work with the AST is by
using the visitor interface. Slowly we are adding TREE_CODE style node
types to the AST which will allow for more ways to work with the AST but
for now this is it.

See: https://doc.rust-lang.org/reference/items.html

Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com
---
 gcc/rust/ast/rust-ast-dump.cc        | 1089 +++++
 gcc/rust/ast/rust-ast-dump.h         |  246 ++
 gcc/rust/ast/rust-ast-full-decls.h   |  273 ++
 gcc/rust/ast/rust-ast-full-test.cc   | 5814 ++++++++++++++++++++++++++
 gcc/rust/ast/rust-ast-full.h         |   31 +
 gcc/rust/ast/rust-ast-visitor.h      |  234 ++
 gcc/rust/ast/rust-ast.h              | 2007 +++++++++
 gcc/rust/ast/rust-cond-compilation.h |  249 ++
 gcc/rust/ast/rust-expr.h             | 4631 ++++++++++++++++++++
 gcc/rust/ast/rust-item.h             | 4382 +++++++++++++++++++
 gcc/rust/ast/rust-macro.h            |  958 +++++
 gcc/rust/ast/rust-path.h             | 1297 ++++++
 gcc/rust/ast/rust-pattern.h          | 1576 +++++++
 gcc/rust/ast/rust-stmt.h             |  358 ++
 gcc/rust/ast/rust-type.h             |  962 +++++
 gcc/rust/operator.h                  |   72 +
 16 files changed, 24179 insertions(+)
 create mode 100644 gcc/rust/ast/rust-ast-dump.cc
 create mode 100644 gcc/rust/ast/rust-ast-dump.h
 create mode 100644 gcc/rust/ast/rust-ast-full-decls.h
 create mode 100644 gcc/rust/ast/rust-ast-full-test.cc
 create mode 100644 gcc/rust/ast/rust-ast-full.h
 create mode 100644 gcc/rust/ast/rust-ast-visitor.h
 create mode 100644 gcc/rust/ast/rust-ast.h
 create mode 100644 gcc/rust/ast/rust-cond-compilation.h
 create mode 100644 gcc/rust/ast/rust-expr.h
 create mode 100644 gcc/rust/ast/rust-item.h
 create mode 100644 gcc/rust/ast/rust-macro.h
 create mode 100644 gcc/rust/ast/rust-path.h
 create mode 100644 gcc/rust/ast/rust-pattern.h
 create mode 100644 gcc/rust/ast/rust-stmt.h
 create mode 100644 gcc/rust/ast/rust-type.h
 create mode 100644 gcc/rust/operator.h

diff --git a/gcc/rust/ast/rust-ast-dump.cc b/gcc/rust/ast/rust-ast-dump.cc
new file mode 100644
index 00000000000..ad9ad0b7de7
--- /dev/null
+++ b/gcc/rust/ast/rust-ast-dump.cc
@@ -0,0 +1,1089 @@
+// 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-ast-dump.h"
+
+namespace Rust {
+namespace AST {
+
+Indent::Indent () : tabs (0) {}
+
+std::ostream &
+operator<< (std::ostream &stream, const Indent &indent)
+{
+  return stream << std::string (indent.tabs, '\t');
+}
+
+void
+Indent::increment ()
+{
+  tabs++;
+}
+
+void
+Indent::decrement ()
+{
+  rust_assert (tabs != 0);
+  tabs--;
+}
+
+Dump::Dump (std::ostream &stream) : stream (stream), indentation (Indent ()) {}
+
+void
+Dump::go (AST::Crate &crate)
+{
+  for (auto &item : crate.items)
+    {
+      stream << indentation;
+      item->accept_vis (*this);
+      stream << "\n";
+    }
+}
+
+void
+Dump::go (AST::Item &item)
+{
+  item.accept_vis (*this);
+}
+
+void
+Dump::format_function_param (FunctionParam &param)
+{
+  param.get_pattern ()->accept_vis (*this);
+  stream << ": ";
+  param.get_type ()->accept_vis (*this);
+}
+
+void
+Dump::emit_attrib (const Attribute &attrib)
+{
+  stream << "#";
+  stream << "[";
+
+  for (size_t i = 0; i < attrib.get_path ().get_segments ().size (); i++)
+    {
+      const auto &seg = attrib.get_path ().get_segments ().at (i);
+      bool has_next = (i + 1) < attrib.get_path ().get_segments ().size ();
+
+      stream << seg.get_segment_name ();
+      if (has_next)
+	stream << "::";
+    }
+
+  if (attrib.has_attr_input ())
+    {
+      stream << " = ";
+
+      bool is_literal = attrib.get_attr_input ().get_attr_input_type ()
+			== AST::AttrInput::AttrInputType::LITERAL;
+      if (is_literal)
+	{
+	  auto &literal
+	    = static_cast<AST::AttrInputLiteral &> (attrib.get_attr_input ());
+	  const auto &value = literal.get_literal ().as_string ();
+
+	  stream << "\"" << value << "\"";
+	}
+      else
+	{
+	  stream << "FIXME";
+	}
+    }
+
+  stream << "]";
+}
+
+void
+Dump::visit (Token &tok)
+{}
+
+void
+Dump::visit (DelimTokenTree &delim_tok_tree)
+{}
+
+void
+Dump::visit (AttrInputMetaItemContainer &input)
+{}
+
+void
+Dump::visit (IdentifierExpr &ident_expr)
+{
+  stream << ident_expr.get_ident ();
+}
+
+void
+Dump::visit (Lifetime &lifetime)
+{}
+
+void
+Dump::visit (LifetimeParam &lifetime_param)
+{}
+
+void
+Dump::visit (ConstGenericParam &lifetime_param)
+{}
+
+// rust-path.h
+void
+Dump::visit (PathInExpression &path)
+{}
+
+void
+Dump::visit (TypePathSegment &segment)
+{}
+
+void
+Dump::visit (TypePathSegmentGeneric &segment)
+{}
+
+void
+Dump::visit (TypePathSegmentFunction &segment)
+{}
+
+void
+Dump::visit (TypePath &path)
+{
+  stream << path.as_string ();
+}
+
+void
+Dump::visit (QualifiedPathInExpression &path)
+{}
+
+void
+Dump::visit (QualifiedPathInType &path)
+{}
+
+// rust-expr.h
+void
+Dump::visit (LiteralExpr &expr)
+{
+  stream << expr.as_string ();
+}
+
+void
+Dump::visit (AttrInputLiteral &attr_input)
+{}
+
+void
+Dump::visit (MetaItemLitExpr &meta_item)
+{}
+
+void
+Dump::visit (MetaItemPathLit &meta_item)
+{}
+
+void
+Dump::visit (BorrowExpr &expr)
+{}
+
+void
+Dump::visit (DereferenceExpr &expr)
+{}
+
+void
+Dump::visit (ErrorPropagationExpr &expr)
+{}
+
+void
+Dump::visit (NegationExpr &expr)
+{}
+
+void
+Dump::visit (ArithmeticOrLogicalExpr &expr)
+{
+  expr.get_left_expr ()->accept_vis (*this);
+  stream << " ";
+
+  switch (expr.get_expr_type ())
+    {
+    case ArithmeticOrLogicalOperator::ADD:
+      stream << "+";
+      break;
+
+    case ArithmeticOrLogicalOperator::SUBTRACT:
+      stream << "-";
+      break;
+
+    case ArithmeticOrLogicalOperator::MULTIPLY:
+      stream << "*";
+      break;
+
+    case ArithmeticOrLogicalOperator::DIVIDE:
+      stream << "/";
+      break;
+
+    case ArithmeticOrLogicalOperator::MODULUS:
+      stream << "%";
+      break;
+
+    case ArithmeticOrLogicalOperator::BITWISE_AND:
+      stream << "&";
+      break;
+
+    case ArithmeticOrLogicalOperator::BITWISE_OR:
+      stream << "|";
+      break;
+
+    case ArithmeticOrLogicalOperator::BITWISE_XOR:
+      stream << "^";
+      break;
+
+    case ArithmeticOrLogicalOperator::LEFT_SHIFT:
+      stream << "<<";
+      break;
+
+    case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
+      stream << ">>";
+      break;
+    }
+
+  stream << " ";
+  expr.get_right_expr ()->accept_vis (*this);
+}
+
+void
+Dump::visit (ComparisonExpr &expr)
+{}
+
+void
+Dump::visit (LazyBooleanExpr &expr)
+{}
+
+void
+Dump::visit (TypeCastExpr &expr)
+{}
+
+void
+Dump::visit (AssignmentExpr &expr)
+{}
+
+void
+Dump::visit (CompoundAssignmentExpr &expr)
+{}
+
+void
+Dump::visit (GroupedExpr &expr)
+{}
+
+void
+Dump::visit (ArrayElemsValues &elems)
+{}
+
+void
+Dump::visit (ArrayElemsCopied &elems)
+{}
+
+void
+Dump::visit (ArrayExpr &expr)
+{}
+
+void
+Dump::visit (ArrayIndexExpr &expr)
+{}
+
+void
+Dump::visit (TupleExpr &expr)
+{}
+
+void
+Dump::visit (TupleIndexExpr &expr)
+{}
+
+void
+Dump::visit (StructExprStruct &expr)
+{}
+
+void
+Dump::visit (StructExprFieldIdentifier &field)
+{}
+
+void
+Dump::visit (StructExprFieldIdentifierValue &field)
+{}
+
+void
+Dump::visit (StructExprFieldIndexValue &field)
+{}
+
+void
+Dump::visit (StructExprStructFields &expr)
+{}
+
+void
+Dump::visit (StructExprStructBase &expr)
+{}
+
+void
+Dump::visit (CallExpr &expr)
+{}
+
+void
+Dump::visit (MethodCallExpr &expr)
+{}
+
+void
+Dump::visit (FieldAccessExpr &expr)
+{}
+
+void
+Dump::visit (ClosureExprInner &expr)
+{}
+
+void
+Dump::visit (BlockExpr &expr)
+{
+  stream << "{\n";
+  indentation.increment ();
+
+  for (auto &stmt : expr.get_statements ())
+    {
+      stream << indentation;
+      stmt->accept_vis (*this);
+      stream << ";\n";
+    }
+
+  if (expr.has_tail_expr ())
+    {
+      stream << indentation;
+      expr.get_tail_expr ()->accept_vis (*this);
+    }
+
+  indentation.decrement ();
+  stream << "\n" << indentation << "}\n";
+}
+
+void
+Dump::visit (ClosureExprInnerTyped &expr)
+{}
+
+void
+Dump::visit (ContinueExpr &expr)
+{}
+
+void
+Dump::visit (BreakExpr &expr)
+{}
+
+void
+Dump::visit (RangeFromToExpr &expr)
+{}
+
+void
+Dump::visit (RangeFromExpr &expr)
+{}
+
+void
+Dump::visit (RangeToExpr &expr)
+{}
+
+void
+Dump::visit (RangeFullExpr &expr)
+{}
+
+void
+Dump::visit (RangeFromToInclExpr &expr)
+{}
+
+void
+Dump::visit (RangeToInclExpr &expr)
+{}
+
+void
+Dump::visit (ReturnExpr &expr)
+{}
+
+void
+Dump::visit (UnsafeBlockExpr &expr)
+{}
+
+void
+Dump::visit (LoopExpr &expr)
+{}
+
+void
+Dump::visit (WhileLoopExpr &expr)
+{}
+
+void
+Dump::visit (WhileLetLoopExpr &expr)
+{}
+
+void
+Dump::visit (ForLoopExpr &expr)
+{}
+
+void
+Dump::visit (IfExpr &expr)
+{}
+
+void
+Dump::visit (IfExprConseqElse &expr)
+{}
+
+void
+Dump::visit (IfExprConseqIf &expr)
+{}
+
+void
+Dump::visit (IfExprConseqIfLet &expr)
+{}
+
+void
+Dump::visit (IfLetExpr &expr)
+{}
+
+void
+Dump::visit (IfLetExprConseqElse &expr)
+{}
+
+void
+Dump::visit (IfLetExprConseqIf &expr)
+{}
+
+void
+Dump::visit (IfLetExprConseqIfLet &expr)
+{}
+
+void
+Dump::visit (MatchExpr &expr)
+{}
+
+void
+Dump::visit (AwaitExpr &expr)
+{}
+
+void
+Dump::visit (AsyncBlockExpr &expr)
+{}
+
+// rust-item.h
+void
+Dump::visit (TypeParam &param)
+{
+  stream << param.get_type_representation ();
+  if (param.has_type ())
+    {
+      stream << " = ";
+      param.get_type ()->accept_vis (*this);
+    }
+}
+
+void
+Dump::visit (LifetimeWhereClauseItem &item)
+{}
+
+void
+Dump::visit (TypeBoundWhereClauseItem &item)
+{}
+
+void
+Dump::visit (Method &method)
+{
+  stream << indentation << "fn " << method.get_method_name () << '(';
+
+  auto &self = method.get_self_param ();
+  stream << self.as_string ();
+
+  auto &params = method.get_function_params ();
+  for (auto &param : params)
+    {
+      stream << ", ";
+      format_function_param (param);
+    }
+
+  stream << ") ";
+
+  if (method.has_return_type ())
+    {
+      stream << "-> ";
+      method.get_return_type ()->accept_vis (*this);
+      stream << " ";
+    }
+
+  auto &block = method.get_definition ();
+  if (!block)
+    stream << ';';
+  else
+    block->accept_vis (*this);
+
+  stream << '\n';
+}
+
+void
+Dump::visit (Module &module)
+{}
+
+void
+Dump::visit (ExternCrate &crate)
+{}
+
+void
+Dump::visit (UseTreeGlob &use_tree)
+{}
+
+void
+Dump::visit (UseTreeList &use_tree)
+{}
+
+void
+Dump::visit (UseTreeRebind &use_tree)
+{}
+
+void
+Dump::visit (UseDeclaration &use_decl)
+{}
+
+void
+Dump::visit (Function &function)
+{
+  stream << "fn " << function.get_function_name ();
+
+  if (function.has_generics ())
+    {
+      stream << "<";
+      for (size_t i = 0; i < function.get_generic_params ().size (); i++)
+	{
+	  auto &param = function.get_generic_params ().at (i);
+	  param->accept_vis (*this);
+
+	  bool has_next = (i + 1) < function.get_generic_params ().size ();
+	  if (has_next)
+	    stream << ", ";
+	}
+      stream << ">";
+    }
+
+  stream << '(';
+  auto &params = function.get_function_params ();
+  if (params.size () >= 1)
+    {
+      format_function_param (params[0]);
+      for (size_t i = 1; i < params.size (); i++)
+	{
+	  stream << ", ";
+	  format_function_param (params[i]);
+	}
+    }
+
+  stream << ") ";
+
+  if (function.has_return_type ())
+    {
+      stream << "-> ";
+      function.get_return_type ()->accept_vis (*this);
+      stream << " ";
+    }
+
+  auto &block = function.get_definition ();
+  if (!block)
+    stream << ';';
+  else
+    block->accept_vis (*this);
+
+  stream << '\n';
+}
+
+void
+Dump::visit (TypeAlias &type_alias)
+{}
+
+void
+Dump::visit (StructStruct &struct_item)
+{}
+
+void
+Dump::visit (TupleStruct &tuple_struct)
+{}
+
+void
+Dump::visit (EnumItem &item)
+{}
+
+void
+Dump::visit (EnumItemTuple &item)
+{}
+
+void
+Dump::visit (EnumItemStruct &item)
+{}
+
+void
+Dump::visit (EnumItemDiscriminant &item)
+{}
+
+void
+Dump::visit (Enum &enum_item)
+{}
+
+void
+Dump::visit (Union &union_item)
+{}
+
+void
+Dump::visit (ConstantItem &const_item)
+{}
+
+void
+Dump::visit (StaticItem &static_item)
+{}
+
+void
+Dump::format_function_common (std::unique_ptr<Type> &return_type,
+			      std::unique_ptr<BlockExpr> &block)
+{
+  if (return_type)
+    {
+      stream << "-> ";
+      return_type->accept_vis (*this);
+    }
+
+  if (block)
+    {
+      if (return_type)
+	stream << ' ';
+      block->accept_vis (*this);
+    }
+  else
+    stream << ";\n";
+}
+
+void
+Dump::visit (TraitItemFunc &item)
+{
+  auto func = item.get_trait_function_decl ();
+  stream << indentation << "fn " << func.get_identifier () << '(';
+
+  auto &params = func.get_function_params ();
+  for (auto &param : params)
+    {
+      stream << ", ";
+      format_function_param (param);
+    }
+
+  stream << ") ";
+
+  format_function_common (func.get_return_type (), item.get_definition ());
+}
+
+void
+Dump::visit (TraitItemMethod &item)
+{
+  auto method = item.get_trait_method_decl ();
+  stream << indentation << "fn " << method.get_identifier () << '(';
+
+  auto &self = method.get_self_param ();
+  stream << self.as_string ();
+
+  auto &params = method.get_function_params ();
+  for (auto &param : params)
+    {
+      stream << ", ";
+      format_function_param (param);
+    }
+
+  stream << ") ";
+
+  format_function_common (method.get_return_type (), item.get_definition ());
+}
+
+void
+Dump::visit (TraitItemConst &item)
+{
+  stream << indentation << "const " << item.get_identifier () << ": ";
+  item.get_type ()->accept_vis (*this);
+  stream << ";\n";
+}
+
+void
+Dump::visit (TraitItemType &item)
+{
+  stream << indentation << "type " << item.get_identifier () << ";\n";
+}
+
+void
+Dump::visit (Trait &trait)
+{
+  for (const auto &attr : trait.get_outer_attrs ())
+    {
+      emit_attrib (attr);
+      stream << "\n" << indentation;
+    }
+
+  stream << "trait " << trait.get_identifier ();
+
+  // Traits actually have an implicit Self thrown at the start so we must expect
+  // the number of generic params to be > 1
+  if (trait.get_generic_params ().size () > 1)
+    {
+      stream << "<";
+      for (size_t i = 1; i < trait.get_generic_params ().size (); i++)
+	{
+	  auto &param = trait.get_generic_params ().at (i);
+	  param->accept_vis (*this);
+
+	  bool has_next = (i + 1) < trait.get_generic_params ().size ();
+	  if (has_next)
+	    stream << ", ";
+	}
+      stream << ">";
+    }
+
+  stream << " {\n";
+
+  indentation.increment ();
+
+  for (auto &item : trait.get_trait_items ())
+    item->accept_vis (*this);
+
+  indentation.decrement ();
+  stream << "\n}\n";
+}
+
+void
+Dump::visit (InherentImpl &impl)
+{
+  stream << "impl ";
+
+  // FIXME: Handle generics
+
+  impl.get_type ()->accept_vis (*this);
+
+  // FIXME: Handle where-clause
+  // FIXME: Handle inner attributes
+
+  stream << " {\n";
+  indentation.increment ();
+
+  for (auto &item : impl.get_impl_items ())
+    item->accept_vis (*this);
+
+  indentation.decrement ();
+  stream << "\n}\n";
+}
+
+void
+Dump::visit (TraitImpl &impl)
+{
+  stream << "impl ";
+  impl.get_trait_path ().accept_vis (*this);
+  stream << " for ";
+  impl.get_type ()->accept_vis (*this);
+
+  stream << " {\n";
+  indentation.increment ();
+
+  for (auto &item : impl.get_impl_items ())
+    item->accept_vis (*this);
+
+  indentation.decrement ();
+  stream << "\n}\n";
+}
+
+void
+Dump::visit (ExternalStaticItem &item)
+{}
+
+void
+Dump::visit (ExternalFunctionItem &function)
+{
+  stream << "fn " << function.get_identifier () << '(';
+
+  for (size_t i = 0; i < function.get_function_params ().size (); i++)
+    {
+      auto &param = function.get_function_params ().at (i);
+      bool has_next = (i + 1) < function.get_function_params ().size ();
+
+      stream << param.get_name () << ": ";
+      param.get_type ()->accept_vis (*this);
+
+      if (has_next)
+	stream << ", ";
+    }
+
+  stream << ')';
+  if (function.has_return_type ())
+    {
+      stream << "-> ";
+      function.get_return_type ()->accept_vis (*this);
+    }
+}
+
+void
+Dump::visit (ExternBlock &block)
+{
+  stream << "extern ";
+
+  if (block.has_abi ())
+    {
+      stream << "\"";
+      stream << block.get_abi ();
+      stream << "\" ";
+    }
+
+  stream << "{\n";
+  indentation.increment ();
+
+  for (auto &item : block.get_extern_items ())
+    {
+      stream << indentation;
+      item->accept_vis (*this);
+      stream << ";\n";
+    }
+
+  indentation.decrement ();
+  stream << "\n" << indentation << "}\n";
+}
+
+// rust-macro.h
+void
+Dump::visit (MacroMatchFragment &match)
+{}
+
+void
+Dump::visit (MacroMatchRepetition &match)
+{}
+
+void
+Dump::visit (MacroMatcher &matcher)
+{}
+
+void
+Dump::visit (MacroRulesDefinition &rules_def)
+{}
+
+void
+Dump::visit (MacroInvocation &macro_invoc)
+{}
+
+void
+Dump::visit (MetaItemPath &meta_item)
+{}
+
+void
+Dump::visit (MetaItemSeq &meta_item)
+{}
+
+void
+Dump::visit (MetaWord &meta_item)
+{}
+
+void
+Dump::visit (MetaNameValueStr &meta_item)
+{}
+
+void
+Dump::visit (MetaListPaths &meta_item)
+{}
+
+void
+Dump::visit (MetaListNameValueStr &meta_item)
+{}
+
+// rust-pattern.h
+void
+Dump::visit (LiteralPattern &pattern)
+{}
+
+void
+Dump::visit (IdentifierPattern &pattern)
+{
+  stream << pattern.get_ident ();
+}
+
+void
+Dump::visit (WildcardPattern &pattern)
+{}
+
+// void Dump::visit(RangePatternBound& bound){}
+
+void
+Dump::visit (RangePatternBoundLiteral &bound)
+{}
+
+void
+Dump::visit (RangePatternBoundPath &bound)
+{}
+
+void
+Dump::visit (RangePatternBoundQualPath &bound)
+{}
+
+void
+Dump::visit (RangePattern &pattern)
+{}
+
+void
+Dump::visit (ReferencePattern &pattern)
+{}
+
+// void Dump::visit(StructPatternField& field){}
+
+void
+Dump::visit (StructPatternFieldTuplePat &field)
+{}
+
+void
+Dump::visit (StructPatternFieldIdentPat &field)
+{}
+
+void
+Dump::visit (StructPatternFieldIdent &field)
+{}
+
+void
+Dump::visit (StructPattern &pattern)
+{}
+
+// void Dump::visit(TupleStructItems& tuple_items){}
+
+void
+Dump::visit (TupleStructItemsNoRange &tuple_items)
+{}
+
+void
+Dump::visit (TupleStructItemsRange &tuple_items)
+{}
+
+void
+Dump::visit (TupleStructPattern &pattern)
+{}
+
+// void Dump::visit(TuplePatternItems& tuple_items){}
+
+void
+Dump::visit (TuplePatternItemsMultiple &tuple_items)
+{}
+
+void
+Dump::visit (TuplePatternItemsRanged &tuple_items)
+{}
+
+void
+Dump::visit (TuplePattern &pattern)
+{}
+
+void
+Dump::visit (GroupedPattern &pattern)
+{}
+
+void
+Dump::visit (SlicePattern &pattern)
+{}
+
+// rust-stmt.h
+void
+Dump::visit (EmptyStmt &stmt)
+{}
+
+void
+Dump::visit (LetStmt &stmt)
+{
+  stream << "let ";
+  auto &pattern = stmt.get_pattern ();
+  if (pattern)
+    pattern->accept_vis (*this);
+
+  if (stmt.has_type ())
+    {
+      stream << ": ";
+      stmt.get_type ()->accept_vis (*this);
+    }
+
+  if (stmt.has_init_expr ())
+    {
+      stream << " = ";
+      stmt.get_init_expr ()->accept_vis (*this);
+    }
+}
+
+void
+Dump::visit (ExprStmtWithoutBlock &stmt)
+{}
+
+void
+Dump::visit (ExprStmtWithBlock &stmt)
+{}
+
+// rust-type.h
+void
+Dump::visit (TraitBound &bound)
+{}
+
+void
+Dump::visit (ImplTraitType &type)
+{}
+
+void
+Dump::visit (TraitObjectType &type)
+{}
+
+void
+Dump::visit (ParenthesisedType &type)
+{}
+
+void
+Dump::visit (ImplTraitTypeOneBound &type)
+{}
+
+void
+Dump::visit (TraitObjectTypeOneBound &type)
+{}
+
+void
+Dump::visit (TupleType &type)
+{}
+
+void
+Dump::visit (NeverType &type)
+{}
+
+void
+Dump::visit (RawPointerType &type)
+{}
+
+void
+Dump::visit (ReferenceType &type)
+{
+  type.get_type_referenced ()->accept_vis (*this);
+}
+
+void
+Dump::visit (ArrayType &type)
+{
+  type.get_elem_type ()->accept_vis (*this);
+}
+
+void
+Dump::visit (SliceType &type)
+{
+  type.get_elem_type ()->accept_vis (*this);
+}
+
+void
+Dump::visit (InferredType &type)
+{
+  stream << "_";
+}
+
+void
+Dump::visit (BareFunctionType &type)
+{}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-ast-dump.h b/gcc/rust/ast/rust-ast-dump.h
new file mode 100644
index 00000000000..c3854e8287d
--- /dev/null
+++ b/gcc/rust/ast/rust-ast-dump.h
@@ -0,0 +1,246 @@
+// 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-ast-visitor.h"
+#include "rust-ast.h"
+#include "rust-ast-full.h"
+
+#ifndef RUST_AST_DUMP_H
+#define RUST_AST_DUMP_H
+
+namespace Rust {
+namespace AST {
+
+// TODO: We might want to reuse this class somewhere else
+class Indent
+{
+public:
+  Indent ();
+
+  friend std::ostream &operator<< (std::ostream &stream, const Indent &indent);
+
+  void increment ();
+  void decrement ();
+
+private:
+  size_t tabs;
+};
+
+class Dump : public ASTVisitor
+{
+public:
+  Dump (std::ostream &stream);
+
+  /**
+   * Run the visitor on an entire crate and its items
+   */
+  void go (AST::Crate &crate);
+  void go (AST::Item &item);
+
+private:
+  std::ostream &stream;
+  Indent indentation;
+
+  // Format together common items of functions: Parameters, return type, block
+  void format_function_common (std::unique_ptr<Type> &return_type,
+			       std::unique_ptr<BlockExpr> &block);
+
+  /**
+   * Format a function's definition parameter
+   */
+  void format_function_param (FunctionParam &param);
+  void emit_attrib (const Attribute &attrib);
+
+  // rust-ast.h
+  void visit (Token &tok);
+  void visit (DelimTokenTree &delim_tok_tree);
+  void visit (AttrInputMetaItemContainer &input);
+  void visit (IdentifierExpr &ident_expr);
+  void visit (Lifetime &lifetime);
+  void visit (LifetimeParam &lifetime_param);
+  void visit (ConstGenericParam &const_param);
+
+  // rust-path.h
+  void visit (PathInExpression &path);
+  void visit (TypePathSegment &segment);
+  void visit (TypePathSegmentGeneric &segment);
+  void visit (TypePathSegmentFunction &segment);
+  void visit (TypePath &path);
+  void visit (QualifiedPathInExpression &path);
+  void visit (QualifiedPathInType &path);
+
+  // rust-expr.h
+  void visit (LiteralExpr &expr);
+  void visit (AttrInputLiteral &attr_input);
+  void visit (MetaItemLitExpr &meta_item);
+  void visit (MetaItemPathLit &meta_item);
+  void visit (BorrowExpr &expr);
+  void visit (DereferenceExpr &expr);
+  void visit (ErrorPropagationExpr &expr);
+  void visit (NegationExpr &expr);
+  void visit (ArithmeticOrLogicalExpr &expr);
+  void visit (ComparisonExpr &expr);
+  void visit (LazyBooleanExpr &expr);
+  void visit (TypeCastExpr &expr);
+  void visit (AssignmentExpr &expr);
+  void visit (CompoundAssignmentExpr &expr);
+  void visit (GroupedExpr &expr);
+  void visit (ArrayElemsValues &elems);
+  void visit (ArrayElemsCopied &elems);
+  void visit (ArrayExpr &expr);
+  void visit (ArrayIndexExpr &expr);
+  void visit (TupleExpr &expr);
+  void visit (TupleIndexExpr &expr);
+  void visit (StructExprStruct &expr);
+  void visit (StructExprFieldIdentifier &field);
+  void visit (StructExprFieldIdentifierValue &field);
+  void visit (StructExprFieldIndexValue &field);
+  void visit (StructExprStructFields &expr);
+  void visit (StructExprStructBase &expr);
+  void visit (CallExpr &expr);
+  void visit (MethodCallExpr &expr);
+  void visit (FieldAccessExpr &expr);
+  void visit (ClosureExprInner &expr);
+  void visit (BlockExpr &expr);
+  void visit (ClosureExprInnerTyped &expr);
+  void visit (ContinueExpr &expr);
+  void visit (BreakExpr &expr);
+  void visit (RangeFromToExpr &expr);
+  void visit (RangeFromExpr &expr);
+  void visit (RangeToExpr &expr);
+  void visit (RangeFullExpr &expr);
+  void visit (RangeFromToInclExpr &expr);
+  void visit (RangeToInclExpr &expr);
+  void visit (ReturnExpr &expr);
+  void visit (UnsafeBlockExpr &expr);
+  void visit (LoopExpr &expr);
+  void visit (WhileLoopExpr &expr);
+  void visit (WhileLetLoopExpr &expr);
+  void visit (ForLoopExpr &expr);
+  void visit (IfExpr &expr);
+  void visit (IfExprConseqElse &expr);
+  void visit (IfExprConseqIf &expr);
+  void visit (IfExprConseqIfLet &expr);
+  void visit (IfLetExpr &expr);
+  void visit (IfLetExprConseqElse &expr);
+  void visit (IfLetExprConseqIf &expr);
+  void visit (IfLetExprConseqIfLet &expr);
+  void visit (MatchExpr &expr);
+  void visit (AwaitExpr &expr);
+  void visit (AsyncBlockExpr &expr);
+
+  // rust-item.h
+  void visit (TypeParam &param);
+  void visit (LifetimeWhereClauseItem &item);
+  void visit (TypeBoundWhereClauseItem &item);
+  void visit (Method &method);
+  void visit (Module &module);
+  void visit (ExternCrate &crate);
+  void visit (UseTreeGlob &use_tree);
+  void visit (UseTreeList &use_tree);
+  void visit (UseTreeRebind &use_tree);
+  void visit (UseDeclaration &use_decl);
+  void visit (Function &function);
+  void visit (TypeAlias &type_alias);
+  void visit (StructStruct &struct_item);
+  void visit (TupleStruct &tuple_struct);
+  void visit (EnumItem &item);
+  void visit (EnumItemTuple &item);
+  void visit (EnumItemStruct &item);
+  void visit (EnumItemDiscriminant &item);
+  void visit (Enum &enum_item);
+  void visit (Union &union_item);
+  void visit (ConstantItem &const_item);
+  void visit (StaticItem &static_item);
+  void visit (TraitItemFunc &item);
+  void visit (TraitItemMethod &item);
+  void visit (TraitItemConst &item);
+  void visit (TraitItemType &item);
+  void visit (Trait &trait);
+  void visit (InherentImpl &impl);
+  void visit (TraitImpl &impl);
+  void visit (ExternalStaticItem &item);
+  void visit (ExternalFunctionItem &item);
+  void visit (ExternBlock &block);
+
+  // rust-macro.h
+  void visit (MacroMatchFragment &match);
+  void visit (MacroMatchRepetition &match);
+  void visit (MacroMatcher &matcher);
+  void visit (MacroRulesDefinition &rules_def);
+  void visit (MacroInvocation &macro_invoc);
+  void visit (MetaItemPath &meta_item);
+  void visit (MetaItemSeq &meta_item);
+  void visit (MetaWord &meta_item);
+  void visit (MetaNameValueStr &meta_item);
+  void visit (MetaListPaths &meta_item);
+  void visit (MetaListNameValueStr &meta_item);
+
+  // rust-pattern.h
+  void visit (LiteralPattern &pattern);
+  void visit (IdentifierPattern &pattern);
+  void visit (WildcardPattern &pattern);
+  // void visit(RangePatternBound& bound);
+  void visit (RangePatternBoundLiteral &bound);
+  void visit (RangePatternBoundPath &bound);
+  void visit (RangePatternBoundQualPath &bound);
+  void visit (RangePattern &pattern);
+  void visit (ReferencePattern &pattern);
+  // void visit(StructPatternField& field);
+  void visit (StructPatternFieldTuplePat &field);
+  void visit (StructPatternFieldIdentPat &field);
+  void visit (StructPatternFieldIdent &field);
+  void visit (StructPattern &pattern);
+  // void visit(TupleStructItems& tuple_items);
+  void visit (TupleStructItemsNoRange &tuple_items);
+  void visit (TupleStructItemsRange &tuple_items);
+  void visit (TupleStructPattern &pattern);
+  // void visit(TuplePatternItems& tuple_items);
+  void visit (TuplePatternItemsMultiple &tuple_items);
+  void visit (TuplePatternItemsRanged &tuple_items);
+  void visit (TuplePattern &pattern);
+  void visit (GroupedPattern &pattern);
+  void visit (SlicePattern &pattern);
+
+  // rust-stmt.h
+  void visit (EmptyStmt &stmt);
+  void visit (LetStmt &stmt);
+  void visit (ExprStmtWithoutBlock &stmt);
+  void visit (ExprStmtWithBlock &stmt);
+
+  // rust-type.h
+  void visit (TraitBound &bound);
+  void visit (ImplTraitType &type);
+  void visit (TraitObjectType &type);
+  void visit (ParenthesisedType &type);
+  void visit (ImplTraitTypeOneBound &type);
+  void visit (TraitObjectTypeOneBound &type);
+  void visit (TupleType &type);
+  void visit (NeverType &type);
+  void visit (RawPointerType &type);
+  void visit (ReferenceType &type);
+  void visit (ArrayType &type);
+  void visit (SliceType &type);
+  void visit (InferredType &type);
+  void visit (BareFunctionType &type);
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // !RUST_AST_DUMP_H
diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h
new file mode 100644
index 00000000000..47f332193cc
--- /dev/null
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -0,0 +1,273 @@
+// 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_AST_FULL_DECLS_H
+#define RUST_AST_FULL_DECLS_H
+
+// Forward declarations for all AST classes. Useful for not having to include
+// all definitions.
+
+namespace Rust {
+namespace AST {
+// rust-ast.h
+class AttrInput;
+class TokenTree;
+class MacroMatch;
+class Token;
+struct Literal;
+class DelimTokenTree;
+class PathSegment;
+class SimplePathSegment;
+class SimplePath;
+struct Attribute;
+class MetaItemInner;
+class AttrInputMetaItemContainer;
+class MetaItem;
+class Stmt;
+class Item;
+class Expr;
+class ExprWithoutBlock;
+class IdentifierExpr;
+class Pattern;
+class Type;
+class TypeNoBounds;
+class TypeParamBound;
+class Lifetime;
+class GenericParam;
+class LifetimeParam;
+class ConstGenericParam;
+class MacroItem;
+class TraitItem;
+class InherentImplItem;
+class TraitImplItem;
+struct Crate;
+class PathExpr;
+
+// rust-path.h
+class PathIdentSegment;
+struct GenericArgsBinding;
+struct GenericArgs;
+class PathExprSegment;
+class PathPattern;
+class PathInExpression;
+class TypePathSegment;
+class TypePathSegmentGeneric;
+struct TypePathFunction;
+class TypePathSegmentFunction;
+class TypePath;
+struct QualifiedPathType;
+class QualifiedPathInExpression;
+class QualifiedPathInType;
+
+// rust-expr.h
+class ExprWithBlock;
+class LiteralExpr;
+class AttrInputLiteral;
+class MetaItemLitExpr;
+class MetaItemPathLit;
+class OperatorExpr;
+class BorrowExpr;
+class DereferenceExpr;
+class ErrorPropagationExpr;
+class NegationExpr;
+class ArithmeticOrLogicalExpr;
+class ComparisonExpr;
+class LazyBooleanExpr;
+class TypeCastExpr;
+class AssignmentExpr;
+class CompoundAssignmentExpr;
+class GroupedExpr;
+class ArrayElems;
+class ArrayElemsValues;
+class ArrayElemsCopied;
+class ArrayExpr;
+class ArrayIndexExpr;
+class TupleExpr;
+class TupleIndexExpr;
+class StructExpr;
+class StructExprStruct;
+struct StructBase;
+class StructExprField;
+class StructExprFieldIdentifier;
+class StructExprFieldWithVal;
+class StructExprFieldIdentifierValue;
+class StructExprFieldIndexValue;
+class StructExprStructFields;
+class StructExprStructBase;
+class CallExpr;
+class MethodCallExpr;
+class FieldAccessExpr;
+struct ClosureParam;
+class ClosureExpr;
+class ClosureExprInner;
+class BlockExpr;
+class ClosureExprInnerTyped;
+class ContinueExpr;
+class BreakExpr;
+class RangeExpr;
+class RangeFromToExpr;
+class RangeFromExpr;
+class RangeToExpr;
+class RangeFullExpr;
+class RangeFromToInclExpr;
+class RangeToInclExpr;
+class ReturnExpr;
+class UnsafeBlockExpr;
+class LoopLabel;
+class BaseLoopExpr;
+class LoopExpr;
+class WhileLoopExpr;
+class WhileLetLoopExpr;
+class ForLoopExpr;
+class IfExpr;
+class IfExprConseqElse;
+class IfExprConseqIf;
+class IfLetExpr;
+class IfExprConseqIfLet;
+class IfLetExprConseqElse;
+class IfLetExprConseqIf;
+class IfLetExprConseqIfLet;
+struct MatchArm;
+// class MatchCase;
+// class MatchCaseBlockExpr;
+// class MatchCaseExpr;
+struct MatchCase;
+class MatchExpr;
+class AwaitExpr;
+class AsyncBlockExpr;
+
+// rust-stmt.h
+class EmptyStmt;
+class LetStmt;
+class ExprStmt;
+class ExprStmtWithoutBlock;
+class ExprStmtWithBlock;
+
+// rust-item.h
+class TypeParam;
+class WhereClauseItem;
+class LifetimeWhereClauseItem;
+class TypeBoundWhereClauseItem;
+struct WhereClause;
+struct SelfParam;
+struct FunctionQualifiers;
+struct FunctionParam;
+struct Visibility;
+class Method;
+class VisItem;
+class Module;
+class ExternCrate;
+class UseTree;
+class UseTreeGlob;
+class UseTreeList;
+class UseTreeRebind;
+class UseDeclaration;
+class Function;
+class TypeAlias;
+class Struct;
+struct StructField;
+class StructStruct;
+struct TupleField;
+class TupleStruct;
+class EnumItem;
+class EnumItemTuple;
+class EnumItemStruct;
+class EnumItemDiscriminant;
+class Enum;
+class Union;
+class ConstantItem;
+class StaticItem;
+struct TraitFunctionDecl;
+class TraitItemFunc;
+struct TraitMethodDecl;
+class TraitItemMethod;
+class TraitItemConst;
+class TraitItemType;
+class Trait;
+class Impl;
+class InherentImpl;
+class TraitImpl;
+class ExternalItem;
+class ExternalStaticItem;
+struct NamedFunctionParam;
+class ExternalFunctionItem;
+class ExternBlock;
+
+// rust-macro.h
+class MacroMatchFragment;
+class MacroMatchRepetition;
+class MacroMatcher;
+struct MacroTranscriber;
+struct MacroRule;
+class MacroRulesDefinition;
+class MacroInvocation;
+class MetaItemPath;
+class MetaItemSeq;
+class MetaWord;
+class MetaNameValueStr;
+class MetaListPaths;
+class MetaListNameValueStr;
+
+// rust-pattern.h
+class LiteralPattern;
+class IdentifierPattern;
+class WildcardPattern;
+class RangePatternBound;
+class RangePatternBoundLiteral;
+class RangePatternBoundPath;
+class RangePatternBoundQualPath;
+class RangePattern;
+class ReferencePattern;
+struct StructPatternEtc;
+class StructPatternField;
+class StructPatternFieldTuplePat;
+class StructPatternFieldIdentPat;
+class StructPatternFieldIdent;
+struct StructPatternElements;
+class StructPattern;
+class TupleStructItems;
+class TupleStructItemsNoRange;
+class TupleStructItemsRange;
+class TupleStructPattern;
+class TuplePatternItems;
+class TuplePatternItemsMultiple;
+class TuplePatternItemsRanged;
+class TuplePattern;
+class GroupedPattern;
+class SlicePattern;
+
+// rust-type.h
+class TraitBound;
+class ImplTraitType;
+class TraitObjectType;
+class ParenthesisedType;
+class ImplTraitTypeOneBound;
+class TraitObjectTypeOneBound;
+class TupleType;
+class NeverType;
+class RawPointerType;
+class ReferenceType;
+class ArrayType;
+class SliceType;
+class InferredType;
+struct MaybeNamedParam;
+class BareFunctionType;
+} // namespace AST
+} // namespace Rust
+
+#endif
diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc
new file mode 100644
index 00000000000..cac816d2545
--- /dev/null
+++ b/gcc/rust/ast/rust-ast-full-test.cc
@@ -0,0 +1,5814 @@
+/* General AST-related method implementations for Rust frontend.
+   Copyright (C) 2009-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/>.  */
+
+// FIXME: This does not work on Windows
+#include <string>
+#include <unistd.h>
+#include <memory>
+
+#include "rust-ast-full.h"
+#include "rust-diagnostics.h"
+#include "rust-ast-visitor.h"
+#include "rust-macro.h"
+#include "rust-session-manager.h"
+#include "rust-lex.h"
+#include "rust-parse.h"
+#include "operator.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
+ * benefits from being defined inline because they are virtual. Also used
+ * for various other stuff. */
+
+namespace Rust {
+namespace AST {
+
+enum indent_mode
+{
+  enter,
+  out,
+  stay
+};
+
+std::string
+indent_spaces (enum indent_mode mode)
+{
+  static int indent = 0;
+  std::string str = "";
+  if (out == mode)
+    indent--;
+  for (int i = 0; i < indent; i++)
+    str += " ";
+  if (enter == mode)
+    indent++;
+
+  return str;
+}
+
+// Gets a string in a certain delim type.
+std::string
+get_string_in_delims (std::string str_input, DelimType delim_type)
+{
+  switch (delim_type)
+    {
+    case PARENS:
+      return "(" + str_input + ")";
+    case SQUARE:
+      return "[" + str_input + "]";
+    case CURLY:
+      return "{" + str_input + "}";
+    default:
+      return "ERROR-MARK-STRING (delims)";
+    }
+  gcc_unreachable ();
+}
+
+enum AttrMode
+{
+  OUTER,
+  INNER
+};
+
+std::string
+get_mode_dump_desc (AttrMode mode)
+{
+  switch (mode)
+    {
+    case OUTER:
+      return "outer attributes";
+    case INNER:
+      return "inner attributes";
+    default:
+      gcc_unreachable ();
+      return "";
+    }
+}
+
+// Adds lines below adding attributes
+std::string
+append_attributes (std::vector<Attribute> attrs, AttrMode mode)
+{
+  indent_spaces (enter);
+
+  std::string str
+    = "\n" + indent_spaces (stay) + get_mode_dump_desc (mode) + ": ";
+  // str += "\n" + indent_spaces (stay) + "inner attributes: ";
+  if (attrs.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      /* note that this does not print them with outer or "inner attribute"
+       * syntax - just prints the body */
+      for (const auto &attr : attrs)
+	str += "\n" + indent_spaces (stay) + attr.as_string ();
+    }
+
+  indent_spaces (out);
+
+  return str;
+}
+
+// Removes the beginning and end quotes of a quoted string.
+std::string
+unquote_string (std::string input)
+{
+  rust_assert (input.front () == '"');
+  rust_assert (input.back () == '"');
+  return input.substr (1, input.length () - 2);
+}
+
+std::string
+Crate::as_string () const
+{
+  rust_debug ("beginning crate recursive as-string");
+
+  std::string str ("Crate: ");
+
+  // inner attributes
+  str += append_attributes (inner_attrs, INNER);
+
+  // items
+  str += "\n items: ";
+  if (items.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &item : items)
+	{
+	  // DEBUG: null pointer check
+	  if (item == nullptr)
+	    {
+	      rust_debug ("something really terrible has gone wrong - "
+			  "null pointer item in crate.");
+	      return "NULL_POINTER_MARK";
+	    }
+
+	  str += "\n  " + item->as_string ();
+	}
+    }
+
+  return str + "\n";
+}
+
+std::string
+Attribute::as_string () const
+{
+  std::string path_str = path.as_string ();
+  if (attr_input == nullptr)
+    return path_str;
+  else
+    return path_str + attr_input->as_string ();
+}
+
+// Copy constructor must deep copy attr_input as unique pointer
+Attribute::Attribute (Attribute const &other)
+  : path (other.path), locus (other.locus)
+{
+  // guard to protect from null pointer dereference
+  if (other.attr_input != nullptr)
+    attr_input = other.attr_input->clone_attr_input ();
+}
+
+// overload assignment operator to use custom clone method
+Attribute &
+Attribute::operator= (Attribute const &other)
+{
+  path = other.path;
+  locus = other.locus;
+  // guard to protect from null pointer dereference
+  if (other.attr_input != nullptr)
+    attr_input = other.attr_input->clone_attr_input ();
+  else
+    attr_input = nullptr;
+
+  return *this;
+}
+
+std::string
+DelimTokenTree::as_string () const
+{
+  std::string start_delim;
+  std::string end_delim;
+  switch (delim_type)
+    {
+    case PARENS:
+      start_delim = "(";
+      end_delim = ")";
+      break;
+    case SQUARE:
+      start_delim = "[";
+      end_delim = "]";
+      break;
+    case CURLY:
+      start_delim = "{";
+      end_delim = "}";
+      break;
+    default:
+      rust_debug ("Invalid delimiter type, "
+		  "Should be PARENS, SQUARE, or CURLY.");
+      return "Invalid delimiter type";
+    }
+  std::string str = start_delim;
+  if (!token_trees.empty ())
+    {
+      for (const auto &tree : token_trees)
+	{
+	  // DEBUG: null pointer check
+	  if (tree == nullptr)
+	    {
+	      rust_debug (
+		"something really terrible has gone wrong - null pointer "
+		"token tree in delim token tree.");
+	      return "NULL_POINTER_MARK";
+	    }
+
+	  str += tree->as_string ();
+	}
+    }
+  str += end_delim;
+
+  return str;
+}
+
+std::string
+Token::as_string () const
+{
+  if (tok_ref->has_str ())
+    {
+      std::string str = tok_ref->get_str ();
+
+      std::string quote = is_string_lit () ? "\"" : "";
+      return quote + str + quote;
+    }
+  else
+    {
+      return tok_ref->get_token_description ();
+    }
+}
+
+std::string
+SimplePathSegment::as_string () const
+{
+  return segment_name;
+}
+
+std::string
+SimplePath::as_string () const
+{
+  std::string path;
+  if (has_opening_scope_resolution)
+    path = "::";
+
+  // crappy hack because doing proper for loop would be more code
+  bool first_time = true;
+  for (const auto &segment : segments)
+    {
+      if (first_time)
+	{
+	  path += segment.as_string ();
+	  first_time = false;
+	}
+      else
+	{
+	  path += "::" + segment.as_string ();
+	}
+
+      // DEBUG: remove later. Checks for path error.
+      if (segment.is_error ())
+	{
+	  rust_debug ("segment in path is error - this should've been filtered "
+		      "out. first segment "
+		      "was '%s'",
+		      segments.at (0).as_string ().c_str ());
+	}
+    }
+
+  return path;
+}
+
+std::string
+Visibility::as_string () const
+{
+  switch (vis_type)
+    {
+    case PRIV:
+      return std::string ("");
+    case PUB:
+      return std::string ("pub");
+    case PUB_CRATE:
+      return std::string ("pub(crate)");
+    case PUB_SELF:
+      return std::string ("pub(self)");
+    case PUB_SUPER:
+      return std::string ("pub(super)");
+    case PUB_IN_PATH:
+      return std::string ("pub(in ") + in_path.as_string () + std::string (")");
+    default:
+      gcc_unreachable ();
+    }
+}
+
+// Creates a string that reflects the visibility stored.
+std::string
+VisItem::as_string () const
+{
+  // FIXME: can't do formatting on string to make identation occur.
+  std::string str;
+
+  if (!outer_attrs.empty ())
+    {
+      for (const auto &attr : outer_attrs)
+	str += attr.as_string () + "\n";
+    }
+
+  if (has_visibility ())
+    str += visibility.as_string () + " ";
+
+  return str;
+}
+
+std::string
+Module::as_string () const
+{
+  std::string str = VisItem::as_string () + "mod " + module_name;
+
+  // Return early if we're dealing with an unloaded module as their body resides
+  // in a different file
+  if (kind == ModuleKind::UNLOADED)
+    return str + "\n no body (reference to external file)\n";
+
+  // inner attributes
+  str += append_attributes (inner_attrs, INNER);
+
+  // items
+  str += "\n items: ";
+
+  // This can still happen if the module is loaded but empty, i.e. `mod foo {}`
+  if (items.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &item : items)
+	{
+	  // DEBUG: null pointer check
+	  if (item == nullptr)
+	    {
+	      rust_debug ("something really terrible has gone wrong - "
+			  "null pointer item in crate.");
+	      return "NULL_POINTER_MARK";
+	    }
+
+	  str += "\n  " + item->as_string ();
+	}
+    }
+
+  return str + "\n";
+}
+
+std::string
+StaticItem::as_string () const
+{
+  std::string str = VisItem::as_string ();
+
+  str += indent_spaces (stay) + "static";
+
+  if (has_mut)
+    str += " mut";
+
+  str += " " + name;
+
+  // DEBUG: null pointer check
+  if (type == nullptr)
+    {
+      rust_debug ("something really terrible has gone wrong - null "
+		  "pointer type in static item.");
+      return "NULL_POINTER_MARK";
+    }
+  str += "\n" + indent_spaces (stay) + "Type: " + type->as_string ();
+
+  // DEBUG: null pointer check
+  if (expr == nullptr)
+    {
+      rust_debug ("something really terrible has gone wrong - null "
+		  "pointer expr in static item.");
+      return "NULL_POINTER_MARK";
+    }
+  str += "\n" + indent_spaces (stay) + "Expression: " + expr->as_string ();
+
+  return str + "\n";
+}
+
+std::string
+ExternCrate::as_string () const
+{
+  std::string str = VisItem::as_string ();
+
+  str += "extern crate " + referenced_crate;
+
+  if (has_as_clause ())
+    str += " as " + as_clause_name;
+
+  return str;
+}
+
+std::string
+TupleStruct::as_string () const
+{
+  std::string str = VisItem::as_string ();
+
+  str += "struct " + struct_name;
+
+  // generic params
+  str += "\n Generic params: ";
+  if (generic_params.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &param : generic_params)
+	{
+	  // DEBUG: null pointer check
+	  if (param == nullptr)
+	    {
+	      rust_debug (
+		"something really terrible has gone wrong - null pointer "
+		"generic param in enum.");
+	      return "NULL_POINTER_MARK";
+	    }
+
+	  str += "\n  " + param->as_string ();
+	}
+    }
+
+  // tuple fields
+  str += "\n Tuple fields: ";
+  if (fields.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &field : fields)
+	str += "\n  " + field.as_string ();
+    }
+
+  str += "\n Where clause: ";
+  if (has_where_clause ())
+    str += where_clause.as_string ();
+  else
+    str += "none";
+
+  return str;
+}
+
+std::string
+ConstantItem::as_string () const
+{
+  std::string str = VisItem::as_string ();
+
+  str += "const " + identifier;
+
+  // DEBUG: null pointer check
+  if (type == nullptr)
+    {
+      rust_debug ("something really terrible has gone wrong - null "
+		  "pointer type in const item.");
+      return "NULL_POINTER_MARK";
+    }
+  str += "\n  Type: " + type->as_string ();
+
+  // DEBUG: null pointer check
+  if (const_expr == nullptr)
+    {
+      rust_debug ("something really terrible has gone wrong - null "
+		  "pointer expr in const item.");
+      return "NULL_POINTER_MARK";
+    }
+  str += "\n  Expression: " + const_expr->as_string ();
+
+  return str + "\n";
+}
+
+std::string
+InherentImpl::as_string () const
+{
+  std::string str = VisItem::as_string ();
+
+  str += "impl ";
+
+  // generic params
+  str += "\n Generic params: ";
+  if (generic_params.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &param : generic_params)
+	{
+	  // DEBUG: null pointer check
+	  if (param == nullptr)
+	    {
+	      rust_debug (
+		"something really terrible has gone wrong - null pointer "
+		"generic param in inherent impl.");
+	      return "NULL_POINTER_MARK";
+	    }
+
+	  str += "\n  " + param->as_string ();
+	}
+    }
+
+  str += "\n Type: " + trait_type->as_string ();
+
+  str += "\n Where clause: ";
+  if (has_where_clause ())
+    str += where_clause.as_string ();
+  else
+    str += "none";
+
+  // inner attributes
+  str += append_attributes (inner_attrs, INNER);
+
+  // inherent impl items
+  str += "\n Inherent impl items: ";
+  if (!has_impl_items ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &item : impl_items)
+	str += "\n  " + item->as_string ();
+    }
+
+  return str;
+}
+
+std::string
+Method::as_string () const
+{
+  std::string str ("Method: \n ");
+
+  str += vis.as_string () + " " + qualifiers.as_string ();
+
+  str += " fn " + method_name;
+
+  // generic params
+  str += "\n Generic params: ";
+  if (generic_params.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &param : generic_params)
+	{
+	  // DEBUG: null pointer check
+	  if (param == nullptr)
+	    {
+	      rust_debug (
+		"something really terrible has gone wrong - null pointer "
+		"generic param in method.");
+	      return "NULL_POINTER_MARK";
+	    }
+
+	  str += "\n  " + param->as_string ();
+	}
+    }
+
+  str += "\n Self param: " + self_param.as_string ();
+
+  str += "\n Function params: ";
+  if (function_params.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &param : function_params)
+	str += "\n  " + param.as_string ();
+    }
+
+  str += "\n Return type: ";
+  if (has_return_type ())
+    str += return_type->as_string ();
+  else
+    str += "none (void)";
+
+  str += "\n Where clause: ";
+  if (has_where_clause ())
+    str += where_clause.as_string ();
+  else
+    str += "none";
+
+  str += "\n Block expr (body): \n  ";
+  str += function_body->as_string ();
+
+  return str;
+}
+
+std::string
+StructStruct::as_string () const
+{
+  std::string str = VisItem::as_string ();
+
+  str += "struct " + struct_name;
+
+  // generic params
+  str += "\n Generic params: ";
+  if (generic_params.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &param : generic_params)
+	{
+	  // DEBUG: null pointer check
+	  if (param == nullptr)
+	    {
+	      rust_debug (
+		"something really terrible has gone wrong - null pointer "
+		"generic param in enum.");
+	      return "NULL_POINTER_MARK";
+	    }
+
+	  str += "\n  " + param->as_string ();
+	}
+    }
+
+  str += "\n Where clause: ";
+  if (has_where_clause ())
+    str += where_clause.as_string ();
+  else
+    str += "none";
+
+  // struct fields
+  str += "\n Struct fields: ";
+  if (is_unit)
+    {
+      str += "none (unit)";
+    }
+  else if (fields.empty ())
+    {
+      str += "none (non-unit)";
+    }
+  else
+    {
+      for (const auto &field : fields)
+	str += "\n  " + field.as_string ();
+    }
+
+  return str;
+}
+
+std::string
+UseDeclaration::as_string () const
+{
+  std::string str = VisItem::as_string ();
+
+  // DEBUG: null pointer check
+  if (use_tree == nullptr)
+    {
+      rust_debug (
+	"something really terrible has gone wrong - null pointer use tree in "
+	"use declaration.");
+      return "NULL_POINTER_MARK";
+    }
+
+  str += "use " + use_tree->as_string ();
+
+  return str;
+}
+
+std::string
+UseTreeGlob::as_string () const
+{
+  switch (glob_type)
+    {
+    case NO_PATH:
+      return "*";
+    case GLOBAL:
+      return "::*";
+      case PATH_PREFIXED: {
+	std::string path_str = path.as_string ();
+	return path_str + "::*";
+      }
+    default:
+      // some kind of error
+      return "ERROR-PATH";
+    }
+  gcc_unreachable ();
+}
+
+std::string
+UseTreeList::as_string () const
+{
+  std::string path_str;
+  switch (path_type)
+    {
+    case NO_PATH:
+      path_str = "{";
+      break;
+    case GLOBAL:
+      path_str = "::{";
+      break;
+      case PATH_PREFIXED: {
+	path_str = path.as_string () + "::{";
+	break;
+      }
+    default:
+      // some kind of error
+      return "ERROR-PATH-LIST";
+    }
+
+  if (has_trees ())
+    {
+      auto i = trees.begin ();
+      auto e = trees.end ();
+
+      // DEBUG: null pointer check
+      if (*i == nullptr)
+	{
+	  rust_debug ("something really terrible has gone wrong - null pointer "
+		      "tree in use tree list.");
+	  return "NULL_POINTER_MARK";
+	}
+
+      for (; i != e; i++)
+	{
+	  path_str += (*i)->as_string ();
+	  if (e != i + 1)
+	    path_str += ", ";
+	}
+    }
+  else
+    {
+      path_str += "none";
+    }
+
+  return path_str + "}";
+}
+
+std::string
+UseTreeRebind::as_string () const
+{
+  std::string path_str = path.as_string ();
+
+  switch (bind_type)
+    {
+    case NONE:
+      // nothing to add, just path
+      break;
+    case IDENTIFIER:
+      path_str += " as " + identifier;
+      break;
+    case WILDCARD:
+      path_str += " as _";
+      break;
+    default:
+      // error
+      return "ERROR-PATH-REBIND";
+    }
+
+  return path_str;
+}
+
+std::string
+Enum::as_string () const
+{
+  std::string str = VisItem::as_string ();
+  str += enum_name;
+
+  // generic params
+  str += "\n Generic params: ";
+  if (generic_params.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &param : generic_params)
+	{
+	  // DEBUG: null pointer check
+	  if (param == nullptr)
+	    {
+	      rust_debug (
+		"something really terrible has gone wrong - null pointer "
+		"generic param in enum.");
+	      return "NULL_POINTER_MARK";
+	    }
+
+	  str += "\n  " + param->as_string ();
+	}
+    }
+
+  str += "\n Where clause: ";
+  if (has_where_clause ())
+    str += where_clause.as_string ();
+  else
+    str += "none";
+
+  // items
+  str += "\n Items: ";
+  if (items.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &item : items)
+	{
+	  // DEBUG: null pointer check
+	  if (item == nullptr)
+	    {
+	      rust_debug (
+		"something really terrible has gone wrong - null pointer "
+		"enum item in enum.");
+	      return "NULL_POINTER_MARK";
+	    }
+
+	  str += "\n  " + item->as_string ();
+	}
+    }
+
+  return str;
+}
+
+std::string
+Trait::as_string () const
+{
+  std::string str = VisItem::as_string ();
+
+  if (has_unsafe)
+    str += "unsafe ";
+
+  str += "trait " + name;
+
+  // generic params
+  str += "\n Generic params: ";
+  if (generic_params.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &param : generic_params)
+	{
+	  // DEBUG: null pointer check
+	  if (param == nullptr)
+	    {
+	      rust_debug (
+		"something really terrible has gone wrong - null pointer "
+		"generic param in trait.");
+	      return "NULL_POINTER_MARK";
+	    }
+
+	  str += "\n  " + param->as_string ();
+	}
+    }
+
+  str += "\n Type param bounds: ";
+  if (!has_type_param_bounds ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &bound : type_param_bounds)
+	{
+	  // DEBUG: null pointer check
+	  if (bound == nullptr)
+	    {
+	      rust_debug (
+		"something really terrible has gone wrong - null pointer "
+		"type param bound in trait.");
+	      return "NULL_POINTER_MARK";
+	    }
+
+	  str += "\n  " + bound->as_string ();
+	}
+    }
+
+  str += "\n Where clause: ";
+  if (!has_where_clause ())
+    str += "none";
+  else
+    str += where_clause.as_string ();
+
+  str += "\n Trait items: ";
+  if (!has_trait_items ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &item : trait_items)
+	{
+	  // DEBUG: null pointer check
+	  if (item == nullptr)
+	    {
+	      rust_debug (
+		"something really terrible has gone wrong - null pointer "
+		"trait item in trait.");
+	      return "NULL_POINTER_MARK";
+	    }
+
+	  str += "\n  " + item->as_string ();
+	}
+    }
+
+  return str;
+}
+
+std::string
+Union::as_string () const
+{
+  std::string str = VisItem::as_string ();
+
+  str += "union " + union_name;
+
+  // generic params
+  str += "\n Generic params: ";
+  if (generic_params.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &param : generic_params)
+	{
+	  // DEBUG: null pointer check
+	  if (param == nullptr)
+	    {
+	      rust_debug (
+		"something really terrible has gone wrong - null pointer "
+		"generic param in union.");
+	      return "NULL_POINTER_MARK";
+	    }
+
+	  str += "\n  " + param->as_string ();
+	}
+    }
+
+  str += "\n Where clause: ";
+  if (has_where_clause ())
+    str += where_clause.as_string ();
+  else
+    str += "none";
+
+  // struct fields
+  str += "\n Struct fields (variants): ";
+  if (variants.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &field : variants)
+	str += "\n  " + field.as_string ();
+    }
+
+  return str;
+}
+
+std::string
+Function::as_string () const
+{
+  std::string str = VisItem::as_string () + "\n";
+  std::string qstr = qualifiers.as_string ();
+  if ("" != qstr)
+    str += qstr + " ";
+
+  if (has_return_type ())
+    {
+      // DEBUG: null pointer check
+      if (return_type == nullptr)
+	{
+	  rust_debug (
+	    "something really terrible has gone wrong - null pointer return "
+	    "type in function.");
+	  return "NULL_POINTER_MARK";
+	}
+
+      str += return_type->as_string () + " ";
+    }
+  else
+    {
+      str += "void ";
+    }
+
+  str += function_name;
+
+  if (has_generics ())
+    {
+      str += "<";
+
+      auto i = generic_params.begin ();
+      auto e = generic_params.end ();
+
+      // DEBUG: null pointer check
+      if (i == e)
+	{
+	  rust_debug ("something really terrible has gone wrong - null pointer "
+		      "generic param in function item.");
+	  return "NULL_POINTER_MARK";
+	}
+
+      for (; i != e; i++)
+	{
+	  str += (*i)->as_string ();
+	  if (e != i + 1)
+	    str += ", ";
+	}
+      str += ">";
+    }
+
+  if (has_function_params ())
+    {
+      auto i = function_params.begin ();
+      auto e = function_params.end ();
+      str += "(";
+      for (; i != e; i++)
+	{
+	  str += (*i).as_string ();
+	  if (e != i + 1)
+	    str += ", ";
+	}
+      str += ")";
+    }
+  else
+    {
+      str += "()";
+    }
+
+  if (has_where_clause ())
+    str += " where " + where_clause.as_string ();
+
+  str += "\n";
+
+  // DEBUG: null pointer check
+  if (function_body == nullptr)
+    {
+      rust_debug (
+	"something really terrible has gone wrong - null pointer function "
+	"body in function.");
+      return "NULL_POINTER_MARK";
+    }
+  str += function_body->as_string () + "\n";
+
+  return str;
+}
+
+std::string
+WhereClause::as_string () const
+{
+  // just print where clause items, don't mention "where" or "where clause"
+  std::string str;
+
+  if (where_clause_items.empty ())
+    {
+      str = "none";
+    }
+  else
+    {
+      for (const auto &item : where_clause_items)
+	str += "\n  " + item->as_string ();
+    }
+
+  return str;
+}
+
+std::string
+BlockExpr::as_string () const
+{
+  std::string istr = indent_spaces (enter);
+  std::string str = istr + "BlockExpr:\n" + istr;
+
+  // get outer attributes
+  str += append_attributes (outer_attrs, OUTER);
+
+  // inner attributes
+  str += append_attributes (inner_attrs, INNER);
+
+  // statements
+  str += "\n" + indent_spaces (stay) + "statements: ";
+  if (statements.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &stmt : statements)
+	{
+	  // DEBUG: null pointer check
+	  if (stmt == nullptr)
+	    {
+	      rust_debug (
+		"something really terrible has gone wrong - null pointer "
+		"stmt in block expr.");
+	      return "NULL_POINTER_MARK";
+	    }
+
+	  str += "\n" + indent_spaces (stay) + stmt->as_string ();
+	}
+    }
+
+  // final expression
+  str += "\n" + indent_spaces (stay) + "final expression: ";
+  if (expr == nullptr)
+    str += "none";
+  else
+    str += "\n" + expr->as_string ();
+
+  str += "\n" + indent_spaces (out);
+  return str;
+}
+
+std::string
+TraitImpl::as_string () const
+{
+  std::string str = VisItem::as_string ();
+
+  if (has_unsafe)
+    str += "unsafe ";
+
+  str += "impl ";
+
+  // generic params
+  str += "\n Generic params: ";
+  if (!has_generics ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &param : generic_params)
+	str += "\n  " + param->as_string ();
+    }
+
+  str += "\n Has exclam: ";
+  if (has_exclam)
+    str += "true";
+  else
+    str += "false";
+
+  str += "\n TypePath (to trait): " + trait_path.as_string ();
+
+  str += "\n Type (struct to impl on): " + trait_type->as_string ();
+
+  str += "\n Where clause: ";
+  if (!has_where_clause ())
+    str += "none";
+  else
+    str += where_clause.as_string ();
+
+  // inner attributes
+  str += append_attributes (inner_attrs, INNER);
+
+  str += "\n trait impl items: ";
+  if (!has_impl_items ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &item : impl_items)
+	str += "\n  " + item->as_string ();
+    }
+
+  return str;
+}
+
+std::string
+TypeAlias::as_string () const
+{
+  std::string str = VisItem::as_string ();
+
+  str += " " + new_type_name;
+
+  // generic params
+  str += "\n Generic params: ";
+  if (!has_generics ())
+    {
+      str += "none";
+    }
+  else
+    {
+      auto i = generic_params.begin ();
+      auto e = generic_params.end ();
+
+      for (; i != e; i++)
+	{
+	  str += (*i)->as_string ();
+	  if (e != i + 1)
+	    str += ", ";
+	}
+    }
+
+  str += "\n Where clause: ";
+  if (!has_where_clause ())
+    str += "none";
+  else
+    str += where_clause.as_string ();
+
+  str += "\n Type: " + existing_type->as_string ();
+
+  return str;
+}
+
+std::string
+ExternBlock::as_string () const
+{
+  std::string str = VisItem::as_string ();
+
+  str += "extern ";
+  if (has_abi ())
+    str += "\"" + abi + "\" ";
+
+  str += append_attributes (inner_attrs, INNER);
+
+  str += "\n external items: ";
+  if (!has_extern_items ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &item : extern_items)
+	str += "\n  " + item->as_string ();
+    }
+
+  return str;
+}
+
+std::string
+MacroRule::as_string () const
+{
+  std::string str ("Macro rule: ");
+
+  str += "\n Matcher: \n  ";
+  str += matcher.as_string ();
+
+  str += "\n Transcriber: \n  ";
+  str += transcriber.as_string ();
+
+  return str;
+}
+
+std::string
+MacroRulesDefinition::as_string () const
+{
+  std::string str;
+
+  // get outer attrs
+  str += append_attributes (outer_attrs, OUTER);
+
+  str += "macro_rules!";
+
+  str += rule_name;
+
+  str += "\n Macro rules: ";
+  if (rules.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &rule : rules)
+	str += "\n  " + rule.as_string ();
+    }
+
+  str += "\n Delim type: ";
+  switch (delim_type)
+    {
+    case PARENS:
+      str += "parentheses";
+      break;
+    case SQUARE:
+      str += "square";
+      break;
+    case CURLY:
+      str += "curly";
+      break;
+    default:
+      return "ERROR_MARK_STRING - delim type in macro invocation";
+    }
+
+  return str;
+}
+
+std::string
+MacroInvocation::as_string () const
+{
+  std::string str = "MacroInvocation: ";
+
+  str += append_attributes (outer_attrs, OUTER);
+
+  str += "\n " + invoc_data.as_string ();
+
+  str += "\n has semicolon: ";
+  str += has_semicolon () ? "true" : "false";
+
+  return str;
+}
+
+std::string
+MacroInvocData::as_string () const
+{
+  return path.as_string () + "!" + token_tree.as_string ();
+}
+
+std::string
+PathInExpression::as_string () const
+{
+  std::string str;
+
+  if (has_opening_scope_resolution)
+    str = "::";
+
+  return str + PathPattern::as_string ();
+}
+
+std::string
+ExprStmtWithBlock::as_string () const
+{
+  std::string str = indent_spaces (enter) + "ExprStmtWithBlock: \n";
+
+  if (expr == nullptr)
+    {
+      str += "none (this should not happen and is an error)";
+    }
+  else
+    {
+      indent_spaces (enter);
+      str += expr->as_string ();
+      indent_spaces (out);
+    }
+
+  indent_spaces (out);
+  return str;
+}
+
+std::string
+ClosureParam::as_string () const
+{
+  std::string str (pattern->as_string ());
+
+  if (has_type_given ())
+    str += " : " + type->as_string ();
+
+  return str;
+}
+
+std::string
+ClosureExpr::as_string () const
+{
+  std::string str = "ClosureExpr:";
+
+  str += append_attributes (outer_attrs, OUTER);
+
+  str += "\n Has move: ";
+  if (has_move)
+    str += "true";
+  else
+    str += "false";
+
+  str += "\n Params: ";
+  if (params.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &param : params)
+	str += "\n  " + param.as_string ();
+    }
+
+  return str;
+}
+
+std::string
+ClosureExprInnerTyped::as_string () const
+{
+  std::string str = ClosureExpr::as_string ();
+
+  str += "\n Return type: " + return_type->as_string ();
+
+  str += "\n Body: " + expr->as_string ();
+
+  return str;
+}
+
+std::string
+PathPattern::as_string () const
+{
+  std::string str;
+
+  for (const auto &segment : segments)
+    str += segment.as_string () + "::";
+
+  // basically a hack - remove last two characters of string (remove final ::)
+  str.erase (str.length () - 2);
+
+  return str;
+}
+
+std::string
+QualifiedPathType::as_string () const
+{
+  std::string str ("<");
+  str += type_to_invoke_on->as_string ();
+
+  if (has_as_clause ())
+    str += " as " + trait_path.as_string ();
+
+  return str + ">";
+}
+
+std::string
+QualifiedPathInExpression::as_string () const
+{
+  return path_type.as_string () + "::" + PathPattern::as_string ();
+}
+
+std::string
+BorrowExpr::as_string () const
+{
+  /* TODO: find way to incorporate outer attrs - may have to represent in
+   * different style (i.e. something more like BorrowExpr: \n outer attrs) */
+
+  std::string str ("&");
+
+  if (double_borrow)
+    str += "&";
+
+  if (is_mut)
+    str += "mut ";
+
+  str += main_or_left_expr->as_string ();
+
+  return str;
+}
+
+std::string
+ReturnExpr::as_string () const
+{
+  /* TODO: find way to incorporate outer attrs - may have to represent in
+   * different style (i.e. something more like BorrowExpr: \n outer attrs) */
+
+  std::string str ("return ");
+
+  if (has_returned_expr ())
+    str += return_expr->as_string ();
+
+  return str;
+}
+
+std::string
+GroupedExpr::as_string () const
+{
+  std::string str ("Grouped expr:");
+
+  // outer attrs
+  str += append_attributes (outer_attrs, OUTER);
+
+  // inner attributes
+  str += append_attributes (inner_attrs, INNER);
+
+  str += "\n Expr in parens: " + expr_in_parens->as_string ();
+
+  return str;
+}
+
+std::string
+RangeToExpr::as_string () const
+{
+  return ".." + to->as_string ();
+}
+
+std::string
+ContinueExpr::as_string () const
+{
+  // TODO: rewrite format to allow outer attributes
+  std::string str ("continue ");
+
+  if (has_label ())
+    str += label.as_string ();
+
+  return str;
+}
+
+std::string
+NegationExpr::as_string () const
+{
+  // TODO: rewrite formula to allow outer attributes
+  std::string str;
+
+  switch (expr_type)
+    {
+    case NegationOperator::NEGATE:
+      str = "-";
+      break;
+    case NegationOperator::NOT:
+      str = "!";
+      break;
+    default:
+      return "ERROR_MARK_STRING - negation expr";
+    }
+
+  str += main_or_left_expr->as_string ();
+
+  return str;
+}
+
+std::string
+RangeFromExpr::as_string () const
+{
+  return from->as_string () + "..";
+}
+
+std::string
+RangeFullExpr::as_string () const
+{
+  return "..";
+}
+
+std::string
+ArrayIndexExpr::as_string () const
+{
+  // TODO: rewrite formula to allow outer attributes
+  return array_expr->as_string () + "[" + index_expr->as_string () + "]";
+}
+
+std::string
+AssignmentExpr::as_string () const
+{
+  std::string str ("AssignmentExpr: ");
+
+  if (main_or_left_expr == nullptr || right_expr == nullptr)
+    {
+      str += "error (either or both expressions are null)";
+    }
+  else
+    {
+      // left expr
+      str += "\n left: " + main_or_left_expr->as_string ();
+
+      // right expr
+      str += "\n right: " + right_expr->as_string ();
+    }
+
+  return str;
+}
+
+std::string
+AsyncBlockExpr::as_string () const
+{
+  std::string str = "AsyncBlockExpr: ";
+
+  // get outer attributes
+  // str += "\n " + Expr::as_string ();
+  str += append_attributes (outer_attrs, OUTER);
+
+  str += "\n Has move: ";
+  str += has_move ? "true" : "false";
+
+  return str + "\n" + block_expr->as_string ();
+}
+
+std::string
+ComparisonExpr::as_string () const
+{
+  // TODO: rewrite to better reflect non-literal expressions
+  std::string str (main_or_left_expr->as_string ());
+
+  switch (expr_type)
+    {
+    case ComparisonOperator::EQUAL:
+      str += " == ";
+      break;
+    case ComparisonOperator::NOT_EQUAL:
+      str += " != ";
+      break;
+    case ComparisonOperator::GREATER_THAN:
+      str += " > ";
+      break;
+    case ComparisonOperator::LESS_THAN:
+      str += " < ";
+      break;
+    case ComparisonOperator::GREATER_OR_EQUAL:
+      str += " >= ";
+      break;
+    case ComparisonOperator::LESS_OR_EQUAL:
+      str += " <= ";
+      break;
+    default:
+      return "ERROR_MARK_STRING - comparison expr";
+    }
+
+  str += right_expr->as_string ();
+
+  return str;
+}
+
+std::string
+MethodCallExpr::as_string () const
+{
+  std::string str = "MethodCallExpr: ";
+
+  str += append_attributes (outer_attrs, OUTER);
+
+  str += "\n Object (receiver) expr: \n";
+  str += receiver->as_string ();
+
+  str += "\n Method path segment: \n";
+  str += method_name.as_string ();
+
+  str += "\n Call params:";
+  if (params.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &param : params)
+	{
+	  if (param == nullptr)
+	    return "ERROR_MARK_STRING - method call expr param is null";
+
+	  str += "\n  " + param->as_string ();
+	}
+    }
+
+  return str;
+}
+
+std::string
+TupleIndexExpr::as_string () const
+{
+  // TODO: rewrite dump to better reflect non-literal exprs
+  return tuple_expr->as_string () + "." + std::to_string (tuple_index);
+}
+
+std::string
+DereferenceExpr::as_string () const
+{
+  // TODO: rewrite dump to better reflect non-literal exprs
+  return "*" + main_or_left_expr->as_string ();
+}
+
+std::string
+FieldAccessExpr::as_string () const
+{
+  // TODO: rewrite dump to better reflect non-literal exprs
+  return receiver->as_string () + "." + field;
+}
+
+std::string
+LazyBooleanExpr::as_string () const
+{
+  // TODO: rewrite dump to better reflect non-literal exprs
+  std::string str (main_or_left_expr->as_string ());
+
+  switch (expr_type)
+    {
+    case LazyBooleanOperator::LOGICAL_OR:
+      str += " || ";
+      break;
+    case LazyBooleanOperator::LOGICAL_AND:
+      str += " && ";
+      break;
+    default:
+      return "ERROR_MARK_STRING - lazy boolean expr out of bounds";
+    }
+
+  str += right_expr->as_string ();
+
+  return str;
+}
+
+std::string
+RangeFromToExpr::as_string () const
+{
+  // TODO: rewrite dump to better reflect non-literal exprs
+  return from->as_string () + ".." + to->as_string ();
+}
+
+std::string
+RangeToInclExpr::as_string () const
+{
+  // TODO: rewrite dump to better reflect non-literal exprs
+  return "..=" + to->as_string ();
+}
+
+std::string
+UnsafeBlockExpr::as_string () const
+{
+  std::string str = "UnsafeBlockExpr:" + indent_spaces (enter);
+
+  // get outer attributes
+  str += append_attributes (outer_attrs, OUTER);
+
+  str += indent_spaces (stay) + expr->as_string () + "\n" + indent_spaces (out);
+
+  return str;
+}
+
+std::string
+ClosureExprInner::as_string () const
+{
+  std::string str = ClosureExpr::as_string ();
+
+  str += "\n Expression: " + closure_inner->as_string ();
+
+  return str;
+}
+
+std::string
+IfExpr::as_string () const
+{
+  std::string str = "IfExpr: ";
+
+  str += append_attributes (outer_attrs, OUTER);
+
+  str += "\n Condition expr: " + condition->as_string ();
+
+  str += "\n If block expr: " + if_block->as_string ();
+
+  return str;
+}
+
+std::string
+IfExprConseqElse::as_string () const
+{
+  std::string str = IfExpr::as_string ();
+
+  str += "\n Else block expr: " + else_block->as_string ();
+
+  return str;
+}
+
+std::string
+IfExprConseqIf::as_string () const
+{
+  std::string str = IfExpr::as_string ();
+
+  str += "\n Else if expr: \n  " + conseq_if_expr->as_string ();
+
+  return str;
+}
+
+std::string
+IfExprConseqIfLet::as_string () const
+{
+  std::string str = IfExpr::as_string ();
+
+  str += "\n Else if let expr: \n  " + if_let_expr->as_string ();
+
+  return str;
+}
+
+std::string
+IfLetExpr::as_string () const
+{
+  std::string str = "IfLetExpr: ";
+
+  str += append_attributes (outer_attrs, OUTER);
+
+  str += "\n Condition match arm patterns: ";
+  if (match_arm_patterns.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &pattern : match_arm_patterns)
+	str += "\n  " + pattern->as_string ();
+    }
+
+  str += "\n Scrutinee expr: " + value->as_string ();
+
+  str += "\n If let block expr: " + if_block->as_string ();
+
+  return str;
+}
+
+std::string
+IfLetExprConseqElse::as_string () const
+{
+  std::string str = IfLetExpr::as_string ();
+
+  str += "\n Else block expr: " + else_block->as_string ();
+
+  return str;
+}
+
+std::string
+IfLetExprConseqIf::as_string () const
+{
+  std::string str = IfLetExpr::as_string ();
+
+  str += "\n Else if expr: \n  " + if_expr->as_string ();
+
+  return str;
+}
+
+std::string
+IfLetExprConseqIfLet::as_string () const
+{
+  std::string str = IfLetExpr::as_string ();
+
+  str += "\n Else if let expr: \n  " + if_let_expr->as_string ();
+
+  return str;
+}
+
+std::string
+RangeFromToInclExpr::as_string () const
+{
+  // TODO: rewrite to allow dumps with non-literal exprs
+  return from->as_string () + "..=" + to->as_string ();
+}
+
+std::string
+ErrorPropagationExpr::as_string () const
+{
+  // TODO: rewrite to allow dumps with non-literal exprs
+  return main_or_left_expr->as_string () + "?";
+}
+
+std::string
+CompoundAssignmentExpr::as_string () const
+{
+  std::string operator_str;
+  operator_str.reserve (1);
+
+  // get operator string
+  switch (expr_type)
+    {
+    case CompoundAssignmentOperator::ADD:
+      operator_str = "+";
+      break;
+    case CompoundAssignmentOperator::SUBTRACT:
+      operator_str = "-";
+      break;
+    case CompoundAssignmentOperator::MULTIPLY:
+      operator_str = "*";
+      break;
+    case CompoundAssignmentOperator::DIVIDE:
+      operator_str = "/";
+      break;
+    case CompoundAssignmentOperator::MODULUS:
+      operator_str = "%";
+      break;
+    case CompoundAssignmentOperator::BITWISE_AND:
+      operator_str = "&";
+      break;
+    case CompoundAssignmentOperator::BITWISE_OR:
+      operator_str = "|";
+      break;
+    case CompoundAssignmentOperator::BITWISE_XOR:
+      operator_str = "^";
+      break;
+    case CompoundAssignmentOperator::LEFT_SHIFT:
+      operator_str = "<<";
+      break;
+    case CompoundAssignmentOperator::RIGHT_SHIFT:
+      operator_str = ">>";
+      break;
+    default:
+      operator_str = "invalid operator. wtf";
+      break;
+    }
+
+  operator_str += "=";
+
+  std::string str ("CompoundAssignmentExpr: ");
+  if (main_or_left_expr == nullptr || right_expr == nullptr)
+    {
+      str += "error. this is probably a parsing failure.";
+    }
+  else
+    {
+      str += "\n left: " + main_or_left_expr->as_string ();
+      str += "\n right: " + right_expr->as_string ();
+      str += "\n operator: " + operator_str;
+    }
+
+  return str;
+}
+
+std::string
+ArithmeticOrLogicalExpr::as_string () const
+{
+  std::string operator_str;
+  operator_str.reserve (1);
+
+  // get operator string
+  switch (expr_type)
+    {
+    case ArithmeticOrLogicalOperator::ADD:
+      operator_str = "+";
+      break;
+    case ArithmeticOrLogicalOperator::SUBTRACT:
+      operator_str = "-";
+      break;
+    case ArithmeticOrLogicalOperator::MULTIPLY:
+      operator_str = "*";
+      break;
+    case ArithmeticOrLogicalOperator::DIVIDE:
+      operator_str = "/";
+      break;
+    case ArithmeticOrLogicalOperator::MODULUS:
+      operator_str = "%";
+      break;
+    case ArithmeticOrLogicalOperator::BITWISE_AND:
+      operator_str = "&";
+      break;
+    case ArithmeticOrLogicalOperator::BITWISE_OR:
+      operator_str = "|";
+      break;
+    case ArithmeticOrLogicalOperator::BITWISE_XOR:
+      operator_str = "^";
+      break;
+    case ArithmeticOrLogicalOperator::LEFT_SHIFT:
+      operator_str = "<<";
+      break;
+    case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
+      operator_str = ">>";
+      break;
+    default:
+      operator_str = "invalid operator. wtf";
+      break;
+    }
+
+  std::string str ("ArithmeticOrLogicalExpr: ");
+  if (main_or_left_expr == nullptr || right_expr == nullptr)
+    {
+      str += "error. this is probably a parsing failure.";
+    }
+  else
+    {
+      str += main_or_left_expr->as_string () + " ";
+      str += operator_str + " ";
+      str += right_expr->as_string ();
+    }
+
+  return str;
+}
+
+std::string
+CallExpr::as_string () const
+{
+  std::string str = "CallExpr: ";
+
+  str += append_attributes (outer_attrs, OUTER);
+
+  str += "\n Function expr: ";
+  str += function->as_string ();
+
+  str += "\n Call params:";
+  if (!has_params ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &param : params)
+	{
+	  if (param == nullptr)
+	    return "ERROR_MARK_STRING - call expr param is null";
+
+	  str += "\n  " + param->as_string ();
+	}
+    }
+
+  return str;
+}
+
+std::string
+WhileLoopExpr::as_string () const
+{
+  std::string str = "WhileLoopExpr: ";
+
+  str += append_attributes (outer_attrs, OUTER);
+
+  str += "\n Label: ";
+  if (!has_loop_label ())
+    str += "none";
+  else
+    str += loop_label.as_string ();
+
+  str += "\n Conditional expr: " + condition->as_string ();
+
+  str += "\n Loop block: " + loop_block->as_string ();
+
+  return str;
+}
+
+std::string
+WhileLetLoopExpr::as_string () const
+{
+  std::string str = "WhileLetLoopExpr: ";
+
+  str += append_attributes (outer_attrs, OUTER);
+
+  str += "\n Label: ";
+  if (!has_loop_label ())
+    str += "none";
+  else
+    str += loop_label.as_string ();
+
+  str += "\n Match arm patterns: ";
+  if (match_arm_patterns.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &pattern : match_arm_patterns)
+	str += "\n  " + pattern->as_string ();
+    }
+
+  str += "\n Scrutinee expr: " + scrutinee->as_string ();
+
+  str += "\n Loop block: " + loop_block->as_string ();
+
+  return str;
+}
+
+std::string
+LoopExpr::as_string () const
+{
+  std::string str = "LoopExpr: (infinite loop)";
+
+  str += append_attributes (outer_attrs, OUTER);
+
+  str += "\n Label: ";
+  if (!has_loop_label ())
+    str += "none";
+  else
+    str += loop_label.as_string ();
+
+  str += "\n Loop block: " + loop_block->as_string ();
+
+  return str;
+}
+
+std::string
+ArrayExpr::as_string () const
+{
+  std::string str = "ArrayExpr:";
+
+  str += append_attributes (outer_attrs, OUTER);
+
+  // inner attributes
+  str += append_attributes (inner_attrs, INNER);
+
+  str += "\n Array elems: ";
+  str += internal_elements->as_string ();
+
+  return str;
+}
+
+std::string
+AwaitExpr::as_string () const
+{
+  // TODO: rewrite dump to allow non-literal exprs
+  return awaited_expr->as_string () + ".await";
+}
+
+std::string
+BreakExpr::as_string () const
+{
+  // TODO: rewrite dump to allow outer attrs, non-literal exprs
+  std::string str ("break ");
+
+  if (has_label ())
+    str += label.as_string () + " ";
+
+  if (has_break_expr ())
+    str += break_expr->as_string ();
+
+  return str;
+}
+
+std::string
+LoopLabel::as_string () const
+{
+  return label.as_string () + ": (label) ";
+}
+
+std::string
+MatchArm::as_string () const
+{
+  // outer attributes
+  std::string str = append_attributes (outer_attrs, OUTER);
+
+  str += "\nPatterns: ";
+  if (match_arm_patterns.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &pattern : match_arm_patterns)
+	str += "\n " + pattern->as_string ();
+    }
+
+  str += "\nGuard expr: ";
+  if (!has_match_arm_guard ())
+    str += "none";
+  else
+    str += guard_expr->as_string ();
+
+  return str;
+}
+
+std::string
+MatchCase::as_string () const
+{
+  std::string str ("MatchCase: (match arm) ");
+
+  str += "\n Match arm matcher: \n" + arm.as_string ();
+  str += "\n Expr: " + expr->as_string ();
+
+  return str;
+}
+
+std::string
+MatchExpr::as_string () const
+{
+  std::string str ("MatchExpr:");
+
+  str += append_attributes (outer_attrs, OUTER);
+
+  str += "\n Scrutinee expr: " + branch_value->as_string ();
+
+  // inner attributes
+  str += append_attributes (inner_attrs, INNER);
+
+  // match arms
+  str += "\n Match arms: ";
+  if (match_arms.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &arm : match_arms)
+	str += "\n  " + arm.as_string ();
+    }
+
+  return str;
+}
+
+std::string
+TupleExpr::as_string () const
+{
+  std::string str ("TupleExpr:");
+
+  str += append_attributes (outer_attrs, OUTER);
+
+  // inner attributes
+  str += append_attributes (inner_attrs, INNER);
+
+  str += "\n Tuple elements: ";
+  if (tuple_elems.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &elem : tuple_elems)
+	str += "\n  " + elem->as_string ();
+    }
+
+  return str;
+}
+
+std::string
+ExprStmtWithoutBlock::as_string () const
+{
+  std::string str ("ExprStmtWithoutBlock:\n");
+  indent_spaces (enter);
+  str += indent_spaces (stay);
+
+  if (expr == nullptr)
+    str += "none (this shouldn't happen and is probably an error)";
+  else
+    str += expr->as_string ();
+  indent_spaces (out);
+
+  return str;
+}
+
+std::string
+FunctionParam::as_string () const
+{
+  // TODO: rewrite dump to allow non-literal types
+  return param_name->as_string () + " : " + type->as_string ();
+}
+
+std::string
+FunctionQualifiers::as_string () const
+{
+  std::string str;
+
+  switch (const_status)
+    {
+    case NONE:
+      // do nothing
+      break;
+    case CONST_FN:
+      str += "const ";
+      break;
+    case ASYNC_FN:
+      str += "async ";
+      break;
+    default:
+      return "ERROR_MARK_STRING: async-const status failure";
+    }
+
+  if (has_unsafe)
+    str += "unsafe ";
+
+  if (has_extern)
+    {
+      str += "extern";
+      if (extern_abi != "")
+	str += " \"" + extern_abi + "\"";
+    }
+
+  return str;
+}
+
+std::string
+TraitBound::as_string () const
+{
+  std::string str ("TraitBound:");
+
+  str += "\n Has opening question mark: ";
+  if (opening_question_mark)
+    str += "true";
+  else
+    str += "false";
+
+  str += "\n For lifetimes: ";
+  if (!has_for_lifetimes ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &lifetime : for_lifetimes)
+	str += "\n  " + lifetime.as_string ();
+    }
+
+  str += "\n Type path: " + type_path.as_string ();
+
+  return str;
+}
+
+std::string
+MacroMatcher::as_string () const
+{
+  std::string str ("Macro matcher: ");
+
+  str += "\n Delim type: ";
+
+  switch (delim_type)
+    {
+    case PARENS:
+      str += "parentheses";
+      break;
+    case SQUARE:
+      str += "square";
+      break;
+    case CURLY:
+      str += "curly";
+      break;
+    default:
+      return "ERROR_MARK_STRING - macro matcher delim";
+    }
+
+  str += "\n Matches: ";
+
+  if (matches.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &match : matches)
+	str += "\n  " + match->as_string ();
+    }
+
+  return str;
+}
+
+std::string
+LifetimeParam::as_string () const
+{
+  std::string str ("LifetimeParam: ");
+
+  str += "\n Outer attribute: ";
+  if (!has_outer_attribute ())
+    str += "none";
+  else
+    str += outer_attr.as_string ();
+
+  str += "\n Lifetime: " + lifetime.as_string ();
+
+  str += "\n Lifetime bounds: ";
+  if (!has_lifetime_bounds ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &bound : lifetime_bounds)
+	str += "\n  " + bound.as_string ();
+    }
+
+  return str;
+}
+
+std::string
+ConstGenericParam::as_string () const
+{
+  std::string str ("ConstGenericParam: ");
+  str += "const " + name + ": " + type->as_string ();
+
+  if (has_default_value ())
+    str += " = " + get_default_value ().as_string ();
+
+  return str;
+}
+
+std::string
+MacroMatchFragment::as_string () const
+{
+  return "$" + ident + ": " + frag_spec.as_string ();
+}
+
+std::string
+QualifiedPathInType::as_string () const
+{
+  /* TODO: this may need adjusting if segments (e.g. with functions) can't be
+   * literalised */
+  std::string str = path_type.as_string ();
+
+  for (const auto &segment : segments)
+    str += "::" + segment->as_string ();
+
+  return str;
+}
+
+std::string
+MacroMatchRepetition::as_string () const
+{
+  std::string str ("Macro match repetition: ");
+
+  str += "\n Matches: ";
+  if (matches.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &match : matches)
+	str += "\n  " + match->as_string ();
+    }
+
+  str += "\n Sep: ";
+  if (!has_sep ())
+    str += "none";
+  else
+    str += sep->as_string ();
+
+  str += "\n Op: ";
+  switch (op)
+    {
+    case ANY:
+      str += "*";
+      break;
+    case ONE_OR_MORE:
+      str += "+";
+      break;
+    case ZERO_OR_ONE:
+      str += "?";
+      break;
+    case NONE:
+      str += "no op? shouldn't be allowed";
+      break;
+    default:
+      return "ERROR_MARK_STRING - unknown op in macro match repetition";
+    }
+
+  return str;
+}
+
+std::string
+Lifetime::as_string () const
+{
+  if (is_error ())
+    return "error lifetime";
+
+  switch (lifetime_type)
+    {
+    case NAMED:
+      return "'" + lifetime_name;
+    case STATIC:
+      return "'static";
+    case WILDCARD:
+      return "'_";
+    default:
+      return "ERROR-MARK-STRING: lifetime type failure";
+    }
+}
+
+std::string
+TypePath::as_string () const
+{
+  /* TODO: this may need to be rewritten if a segment (e.g. function) can't be
+   * literalised */
+  std::string str;
+
+  if (has_opening_scope_resolution)
+    str = "::";
+
+  for (const auto &segment : segments)
+    str += segment->as_string () + "::";
+
+  // kinda hack - remove last 2 '::' characters
+  str.erase (str.length () - 2);
+
+  return str;
+}
+
+std::string
+TypeParam::as_string () const
+{
+  std::string str ("TypeParam: ");
+
+  str += "\n Outer attribute: ";
+  if (!has_outer_attribute ())
+    str += "none";
+  else
+    str += outer_attr.as_string ();
+
+  str += "\n Identifier: " + type_representation;
+
+  str += "\n Type param bounds: ";
+  if (!has_type_param_bounds ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &bound : type_param_bounds)
+	str += "\n  " + bound->as_string ();
+    }
+
+  str += "\n Type: ";
+  if (!has_type ())
+    str += "none";
+  else
+    str += type->as_string ();
+
+  return str;
+}
+
+SimplePath
+PathPattern::convert_to_simple_path (bool with_opening_scope_resolution) const
+{
+  if (!has_segments ())
+    return SimplePath::create_empty ();
+
+  // create vector of reserved size (to minimise reallocations)
+  std::vector<SimplePathSegment> simple_segments;
+  simple_segments.reserve (segments.size ());
+
+  for (const auto &segment : segments)
+    {
+      // return empty path if doesn't meet simple path segment requirements
+      if (segment.is_error () || segment.has_generic_args ()
+	  || segment.as_string () == "Self")
+	return SimplePath::create_empty ();
+
+      // create segment and add to vector
+      std::string segment_str = segment.as_string ();
+      simple_segments.push_back (
+	SimplePathSegment (std::move (segment_str), segment.get_locus ()));
+    }
+
+  // kind of a HACK to get locus depending on opening scope resolution
+  Location locus = Linemap::unknown_location ();
+  if (with_opening_scope_resolution)
+    locus = simple_segments[0].get_locus () - 2; // minus 2 chars for ::
+  else
+    locus = simple_segments[0].get_locus ();
+  // FIXME: this hack probably doesn't actually work
+
+  return SimplePath (std::move (simple_segments), with_opening_scope_resolution,
+		     locus);
+}
+
+SimplePath
+TypePath::as_simple_path () const
+{
+  if (segments.empty ())
+    return SimplePath::create_empty ();
+
+  // create vector of reserved size (to minimise reallocations)
+  std::vector<SimplePathSegment> simple_segments;
+  simple_segments.reserve (segments.size ());
+
+  for (const auto &segment : segments)
+    {
+      // return empty path if doesn't meet simple path segment requirements
+      if (segment == nullptr || segment->is_error ()
+	  || !segment->is_ident_only () || segment->as_string () == "Self")
+	return SimplePath::create_empty ();
+
+      // create segment and add to vector
+      std::string segment_str = segment->as_string ();
+      simple_segments.push_back (
+	SimplePathSegment (std::move (segment_str), segment->get_locus ()));
+    }
+
+  return SimplePath (std::move (simple_segments), has_opening_scope_resolution,
+		     locus);
+}
+
+std::string
+PathExprSegment::as_string () const
+{
+  // TODO: rewrite dump to work with non-literalisable types
+  std::string ident_str = segment_name.as_string ();
+  if (has_generic_args ())
+    ident_str += "::<" + generic_args.as_string () + ">";
+
+  return ident_str;
+}
+
+std::string
+GenericArgs::as_string () const
+{
+  std::string args;
+
+  // lifetime args
+  if (!lifetime_args.empty ())
+    {
+      auto i = lifetime_args.begin ();
+      auto e = lifetime_args.end ();
+
+      for (; i != e; i++)
+	{
+	  args += (*i).as_string ();
+	  if (e != i + 1)
+	    args += ", ";
+	}
+    }
+
+  // type args
+  if (!generic_args.empty ())
+    {
+      auto i = generic_args.begin ();
+      auto e = generic_args.end ();
+
+      for (; i != e; i++)
+	{
+	  args += (*i).as_string ();
+	  if (e != i + 1)
+	    args += ", ";
+	}
+    }
+
+  // binding args
+  if (!binding_args.empty ())
+    {
+      auto i = binding_args.begin ();
+      auto e = binding_args.end ();
+
+      for (; i != e; i++)
+	{
+	  args += (*i).as_string ();
+	  if (e != i + 1)
+	    args += ", ";
+	}
+    }
+
+  return args;
+}
+
+std::string
+GenericArgsBinding::as_string () const
+{
+  // TODO: rewrite to work with non-literalisable types
+  return identifier + " = " + type->as_string ();
+}
+
+std::string
+ForLoopExpr::as_string () const
+{
+  std::string str = "ForLoopExpr: ";
+
+  str += append_attributes (outer_attrs, OUTER);
+
+  str += "\n Label: ";
+  if (!has_loop_label ())
+    str += "none";
+  else
+    str += loop_label.as_string ();
+
+  str += "\n Pattern: " + pattern->as_string ();
+
+  str += "\n Iterator expr: " + iterator_expr->as_string ();
+
+  str += "\n Loop block: " + loop_block->as_string ();
+
+  return str;
+}
+
+std::string
+RangePattern::as_string () const
+{
+  // TODO: maybe rewrite to work with non-linearisable bounds
+  if (has_ellipsis_syntax)
+    return lower->as_string () + "..." + upper->as_string ();
+  else
+    return lower->as_string () + "..=" + upper->as_string ();
+}
+
+std::string
+RangePatternBoundLiteral::as_string () const
+{
+  std::string str;
+
+  if (has_minus)
+    str += "-";
+
+  str += literal.as_string ();
+
+  return str;
+}
+
+std::string
+SlicePattern::as_string () const
+{
+  std::string str ("SlicePattern: ");
+
+  for (const auto &pattern : items)
+    str += "\n " + pattern->as_string ();
+
+  return str;
+}
+
+std::string
+TuplePatternItemsMultiple::as_string () const
+{
+  std::string str;
+
+  for (const auto &pattern : patterns)
+    str += "\n " + pattern->as_string ();
+
+  return str;
+}
+
+std::string
+TuplePatternItemsRanged::as_string () const
+{
+  std::string str;
+
+  str += "\n Lower patterns: ";
+  if (lower_patterns.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &lower : lower_patterns)
+	str += "\n  " + lower->as_string ();
+    }
+
+  str += "\n Upper patterns: ";
+  if (upper_patterns.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &upper : upper_patterns)
+	str += "\n  " + upper->as_string ();
+    }
+
+  return str;
+}
+
+std::string
+TuplePattern::as_string () const
+{
+  return "TuplePattern: " + items->as_string ();
+}
+
+std::string
+StructPatternField::as_string () const
+{
+  // outer attributes
+  std::string str = append_attributes (outer_attrs, OUTER);
+
+  return str;
+}
+
+std::string
+StructPatternFieldIdent::as_string () const
+{
+  std::string str = StructPatternField::as_string ();
+
+  str += "\n";
+
+  if (has_ref)
+    str += "ref ";
+
+  if (has_mut)
+    str += "mut ";
+
+  str += ident;
+
+  return str;
+}
+
+std::string
+StructPatternFieldTuplePat::as_string () const
+{
+  // TODO: maybe rewrite to work with non-linearisable patterns
+  std::string str = StructPatternField::as_string ();
+
+  str += "\n";
+
+  str += std::to_string (index) + " : " + tuple_pattern->as_string ();
+
+  return str;
+}
+
+std::string
+StructPatternFieldIdentPat::as_string () const
+{
+  // TODO: maybe rewrite to work with non-linearisable patterns
+  std::string str = StructPatternField::as_string ();
+
+  str += "\n";
+
+  str += ident + " : " + ident_pattern->as_string ();
+
+  return str;
+}
+
+std::string
+StructPatternElements::as_string () const
+{
+  std::string str ("\n  Fields: ");
+
+  if (!has_struct_pattern_fields ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &field : fields)
+	str += "\n   " + field->as_string ();
+    }
+
+  str += "\n  Etc: ";
+  if (has_struct_pattern_etc)
+    str += "true";
+  else
+    str += "false";
+
+  return str;
+}
+
+std::string
+StructPattern::as_string () const
+{
+  std::string str ("StructPattern: \n Path: ");
+
+  str += path.as_string ();
+
+  str += "\n Struct pattern elems: ";
+  if (!has_struct_pattern_elems ())
+    str += "none";
+  else
+    str += elems.as_string ();
+
+  return str;
+}
+
+std::string
+LiteralPattern::as_string () const
+{
+  return lit.as_string ();
+}
+
+std::string
+ReferencePattern::as_string () const
+{
+  // TODO: maybe rewrite to work with non-linearisable patterns
+  std::string str ("&");
+
+  if (has_two_amps)
+    str += "&";
+
+  if (is_mut)
+    str += "mut ";
+
+  str += pattern->as_string ();
+
+  return str;
+}
+
+std::string
+IdentifierPattern::as_string () const
+{
+  // TODO: maybe rewrite to work with non-linearisable patterns
+  std::string str;
+
+  if (is_ref)
+    str += "ref ";
+
+  if (is_mut)
+    str += "mut ";
+
+  str += variable_ident;
+
+  if (has_pattern_to_bind ())
+    str += " @ " + to_bind->as_string ();
+
+  return str;
+}
+
+std::string
+TupleStructItemsNoRange::as_string () const
+{
+  std::string str;
+
+  for (const auto &pattern : patterns)
+    str += "\n  " + pattern->as_string ();
+
+  return str;
+}
+
+std::string
+TupleStructItemsRange::as_string () const
+{
+  std::string str ("\n  Lower patterns: ");
+
+  if (lower_patterns.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &lower : lower_patterns)
+	str += "\n   " + lower->as_string ();
+    }
+
+  str += "\n  Upper patterns: ";
+  if (upper_patterns.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &upper : upper_patterns)
+	str += "\n   " + upper->as_string ();
+    }
+
+  return str;
+}
+
+std::string
+TupleStructPattern::as_string () const
+{
+  std::string str ("TupleStructPattern: \n Path: ");
+
+  str += path.as_string ();
+
+  str += "\n Tuple struct items: " + items->as_string ();
+
+  return str;
+}
+
+std::string
+LetStmt::as_string () const
+{
+  // TODO: rewrite to work with non-linearisable types and exprs
+  std::string str = append_attributes (outer_attrs, OUTER);
+
+  str += "\n" + indent_spaces (stay) + "let " + variables_pattern->as_string ();
+
+  if (has_type ())
+    str += " : " + type->as_string ();
+
+  if (has_init_expr ())
+    str += " = " + init_expr->as_string ();
+
+  return str;
+}
+
+// hopefully definition here will prevent circular dependency issue
+TraitBound *
+TypePath::to_trait_bound (bool in_parens) const
+{
+  return new TraitBound (TypePath (*this), get_locus (), in_parens);
+}
+
+std::string
+InferredType::as_string () const
+{
+  return "_ (inferred)";
+}
+
+std::string
+TypeCastExpr::as_string () const
+{
+  // TODO: rewrite to work with non-linearisable exprs and types
+  return main_or_left_expr->as_string () + " as "
+	 + type_to_convert_to->as_string ();
+}
+
+std::string
+ImplTraitType::as_string () const
+{
+  std::string str ("ImplTraitType: \n TypeParamBounds: ");
+
+  if (type_param_bounds.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &bound : type_param_bounds)
+	str += "\n  " + bound->as_string ();
+    }
+
+  return str;
+}
+
+std::string
+ReferenceType::as_string () const
+{
+  // TODO: rewrite to work with non-linearisable types
+  std::string str ("&");
+
+  if (has_lifetime ())
+    str += lifetime.as_string () + " ";
+
+  if (has_mut)
+    str += "mut ";
+
+  str += type->as_string ();
+
+  return str;
+}
+
+std::string
+RawPointerType::as_string () const
+{
+  // TODO: rewrite to work with non-linearisable types
+  std::string str ("*");
+
+  switch (pointer_type)
+    {
+    case MUT:
+      str += "mut ";
+      break;
+    case CONST:
+      str += "const ";
+      break;
+    default:
+      return "ERROR_MARK_STRING - unknown pointer type in raw pointer type";
+    }
+
+  str += type->as_string ();
+
+  return str;
+}
+
+std::string
+TraitObjectType::as_string () const
+{
+  std::string str ("TraitObjectType: \n Has dyn dispatch: ");
+
+  if (has_dyn)
+    str += "true";
+  else
+    str += "false";
+
+  str += "\n TypeParamBounds: ";
+  if (type_param_bounds.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &bound : type_param_bounds)
+	str += "\n  " + bound->as_string ();
+    }
+
+  return str;
+}
+
+std::string
+BareFunctionType::as_string () const
+{
+  std::string str ("BareFunctionType: \n For lifetimes: ");
+
+  if (!has_for_lifetimes ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &for_lifetime : for_lifetimes)
+	str += "\n  " + for_lifetime.as_string ();
+    }
+
+  str += "\n Qualifiers: " + function_qualifiers.as_string ();
+
+  str += "\n Params: ";
+  if (params.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &param : params)
+	str += "\n  " + param.as_string ();
+    }
+
+  str += "\n Is variadic: ";
+  if (is_variadic)
+    str += "true";
+  else
+    str += "false";
+
+  str += "\n Return type: ";
+  if (!has_return_type ())
+    str += "none (void)";
+  else
+    str += return_type->as_string ();
+
+  return str;
+}
+
+std::string
+ImplTraitTypeOneBound::as_string () const
+{
+  std::string str ("ImplTraitTypeOneBound: \n TraitBound: ");
+
+  return str + trait_bound.as_string ();
+}
+
+std::string
+TypePathSegmentGeneric::as_string () const
+{
+  // TODO: rewrite to work with non-linearisable types
+  return TypePathSegment::as_string () + "<" + generic_args.as_string () + ">";
+}
+
+std::string
+TraitObjectTypeOneBound::as_string () const
+{
+  std::string str ("TraitObjectTypeOneBound: \n Has dyn dispatch: ");
+
+  if (has_dyn)
+    str += "true";
+  else
+    str += "false";
+
+  str += "\n TraitBound: " + trait_bound.as_string ();
+
+  return str;
+}
+
+std::string
+TypePathFunction::as_string () const
+{
+  // TODO: rewrite to work with non-linearisable types
+  std::string str ("(");
+
+  if (has_inputs ())
+    {
+      auto i = inputs.begin ();
+      auto e = inputs.end ();
+
+      for (; i != e; i++)
+	{
+	  str += (*i)->as_string ();
+	  if (e != i + 1)
+	    str += ", ";
+	}
+    }
+
+  str += ")";
+
+  if (has_return_type ())
+    str += " -> " + return_type->as_string ();
+
+  return str;
+}
+
+std::string
+TypePathSegmentFunction::as_string () const
+{
+  // TODO: rewrite to work with non-linearisable types
+  return TypePathSegment::as_string () + function_path.as_string ();
+}
+
+std::string
+ArrayType::as_string () const
+{
+  // TODO: rewrite to work with non-linearisable types and exprs
+  return "[" + elem_type->as_string () + "; " + size->as_string () + "]";
+}
+
+std::string
+SliceType::as_string () const
+{
+  // TODO: rewrite to work with non-linearisable types
+  return "[" + elem_type->as_string () + "]";
+}
+
+std::string
+TupleType::as_string () const
+{
+  // TODO: rewrite to work with non-linearisable types
+  std::string str ("(");
+
+  if (!is_unit_type ())
+    {
+      auto i = elems.begin ();
+      auto e = elems.end ();
+
+      for (; i != e; i++)
+	{
+	  str += (*i)->as_string ();
+	  if (e != i + 1)
+	    str += ", ";
+	}
+    }
+
+  str += ")";
+
+  return str;
+}
+
+std::string
+StructExpr::as_string () const
+{
+  std::string str = append_attributes (outer_attrs, OUTER);
+  indent_spaces (enter);
+  str += "\n" + indent_spaces (stay) + "StructExpr:";
+  indent_spaces (enter);
+  str += "\n" + indent_spaces (stay) + "PathInExpr:\n";
+  str += indent_spaces (stay) + struct_name.as_string ();
+  indent_spaces (out);
+  indent_spaces (out);
+  return str;
+}
+
+std::string
+StructExprStruct::as_string () const
+{
+  // TODO: doesn't this require data from StructExpr?
+  std::string str ("StructExprStruct (or subclass): ");
+
+  str += "\n Path: " + get_struct_name ().as_string ();
+
+  // inner attributes
+  str += append_attributes (inner_attrs, INNER);
+
+  return str;
+}
+
+std::string
+StructBase::as_string () const
+{
+  if (base_struct != nullptr)
+    return base_struct->as_string ();
+  else
+    return "ERROR_MARK_STRING - invalid struct base had as string applied";
+}
+
+std::string
+StructExprFieldWithVal::as_string () const
+{
+  // used to get value string
+  return value->as_string ();
+}
+
+std::string
+StructExprFieldIdentifierValue::as_string () const
+{
+  // TODO: rewrite to work with non-linearisable exprs
+  return field_name + " : " + StructExprFieldWithVal::as_string ();
+}
+
+std::string
+StructExprFieldIndexValue::as_string () const
+{
+  // TODO: rewrite to work with non-linearisable exprs
+  return std::to_string (index) + " : " + StructExprFieldWithVal::as_string ();
+}
+
+std::string
+StructExprStructFields::as_string () const
+{
+  std::string str = StructExprStruct::as_string ();
+
+  str += "\n Fields: ";
+  if (fields.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &field : fields)
+	str += "\n  " + field->as_string ();
+    }
+
+  str += "\n Struct base: ";
+  if (!has_struct_base ())
+    str += "none";
+  else
+    str += struct_base.as_string ();
+
+  return str;
+}
+
+std::string
+EnumItem::as_string () const
+{
+  std::string str = VisItem::as_string ();
+  str += variant_name;
+
+  return str;
+}
+
+std::string
+EnumItemTuple::as_string () const
+{
+  std::string str = EnumItem::as_string ();
+
+  // add tuple opening parens
+  str += "(";
+
+  // tuple fields
+  if (has_tuple_fields ())
+    {
+      auto i = tuple_fields.begin ();
+      auto e = tuple_fields.end ();
+
+      for (; i != e; i++)
+	{
+	  str += (*i).as_string ();
+	  if (e != i + 1)
+	    str += ", ";
+	}
+    }
+
+  // add tuple closing parens
+  str += ")";
+
+  return str;
+}
+
+std::string
+TupleField::as_string () const
+{
+  // TODO: rewrite to work with non-linearisable exprs
+
+  // outer attributes
+  std::string str = append_attributes (outer_attrs, OUTER);
+
+  if (has_visibility ())
+    str += "\n" + visibility.as_string ();
+
+  str += " " + field_type->as_string ();
+
+  return str;
+}
+
+std::string
+EnumItemStruct::as_string () const
+{
+  std::string str = EnumItem::as_string ();
+
+  // add struct opening parens
+  str += "{";
+
+  // tuple fields
+  if (has_struct_fields ())
+    {
+      auto i = struct_fields.begin ();
+      auto e = struct_fields.end ();
+
+      for (; i != e; i++)
+	{
+	  str += (*i).as_string ();
+	  if (e != i + 1)
+	    str += ", ";
+	}
+    }
+
+  // add struct closing parens
+  str += "}";
+
+  return str;
+}
+
+std::string
+StructField::as_string () const
+{
+  // TODO: rewrite to work with non-linearisable exprs
+  // outer attributes
+  std::string str = append_attributes (outer_attrs, OUTER);
+
+  if (has_visibility ())
+    str += "\n" + visibility.as_string ();
+
+  str += " " + field_name + " : " + field_type->as_string ();
+
+  return str;
+}
+
+std::string
+EnumItemDiscriminant::as_string () const
+{
+  // TODO: rewrite to work with non-linearisable exprs
+  std::string str = EnumItem::as_string ();
+
+  // add equal and expression
+  str += " = " + expression->as_string ();
+
+  return str;
+}
+
+std::string
+ExternalStaticItem::as_string () const
+{
+  // outer attributes
+  std::string str = append_attributes (outer_attrs, OUTER);
+
+  // start visibility on new line and with a space
+  str += "\n" + visibility.as_string () + " ";
+
+  str += "static ";
+
+  if (has_mut)
+    str += "mut ";
+
+  // add name
+  str += item_name;
+
+  // add type on new line
+  str += "\n Type: " + item_type->as_string ();
+
+  return str;
+}
+
+std::string
+ExternalFunctionItem::as_string () const
+{
+  // outer attributes
+  std::string str = append_attributes (outer_attrs, OUTER);
+
+  // start visibility on new line and with a space
+  str += "\n" + visibility.as_string () + " ";
+
+  str += "fn ";
+
+  // add name
+  str += item_name;
+
+  // generic params
+  str += "\n Generic params: ";
+  if (generic_params.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &param : generic_params)
+	{
+	  // DEBUG: null pointer check
+	  if (param == nullptr)
+	    {
+	      rust_debug (
+		"something really terrible has gone wrong - null pointer "
+		"generic param in external function item.");
+	      return "NULL_POINTER_MARK";
+	    }
+
+	  str += "\n  " + param->as_string ();
+	}
+    }
+
+  // function params
+  str += "\n Function params: ";
+  if (function_params.empty () && !has_variadics)
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &param : function_params)
+	str += "\n  " + param.as_string ();
+
+      if (has_variadics)
+	{
+	  str += "\n  variadic outer attrs: ";
+	  if (has_variadic_outer_attrs ())
+	    {
+	      for (const auto &attr : variadic_outer_attrs)
+		str += "\n   " + attr.as_string ();
+	    }
+	  else
+	    {
+	      str += "none";
+	    }
+	  str += "\n  ... (variadic)";
+	}
+    }
+
+  // add type on new line
+  str += "\n (return) Type: "
+	 + (has_return_type () ? return_type->as_string () : "()");
+
+  // where clause
+  str += "\n Where clause: ";
+  if (has_where_clause ())
+    str += where_clause.as_string ();
+  else
+    str += "none";
+
+  return str;
+}
+
+std::string
+NamedFunctionParam::as_string () const
+{
+  std::string str = append_attributes (outer_attrs, OUTER);
+
+  str += "\n" + name;
+
+  str += "\n Type: " + param_type->as_string ();
+
+  return str;
+}
+
+std::string
+TraitItemFunc::as_string () const
+{
+  std::string str = append_attributes (outer_attrs, OUTER);
+
+  str += "\n" + decl.as_string ();
+
+  str += "\n Definition (block expr): ";
+  if (has_definition ())
+    str += block_expr->as_string ();
+  else
+    str += "none";
+
+  return str;
+}
+
+std::string
+TraitFunctionDecl::as_string () const
+{
+  std::string str = qualifiers.as_string () + "fn " + function_name;
+
+  // generic params
+  str += "\n Generic params: ";
+  if (generic_params.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &param : generic_params)
+	{
+	  // DEBUG: null pointer check
+	  if (param == nullptr)
+	    {
+	      rust_debug (
+		"something really terrible has gone wrong - null pointer "
+		"generic param in trait function decl.");
+	      return "NULL_POINTER_MARK";
+	    }
+
+	  str += "\n  " + param->as_string ();
+	}
+    }
+
+  str += "\n Function params: ";
+  if (has_params ())
+    {
+      for (const auto &param : function_params)
+	str += "\n  " + param.as_string ();
+    }
+  else
+    {
+      str += "none";
+    }
+
+  str += "\n Return type: ";
+  if (has_return_type ())
+    str += return_type->as_string ();
+  else
+    str += "none (void)";
+
+  str += "\n Where clause: ";
+  if (has_where_clause ())
+    str += where_clause.as_string ();
+  else
+    str += "none";
+
+  return str;
+}
+
+std::string
+TraitItemMethod::as_string () const
+{
+  std::string str = append_attributes (outer_attrs, OUTER);
+
+  str += "\n" + decl.as_string ();
+
+  str += "\n Definition (block expr): ";
+  if (has_definition ())
+    str += block_expr->as_string ();
+  else
+    str += "none";
+
+  return str;
+}
+
+std::string
+TraitMethodDecl::as_string () const
+{
+  std::string str = qualifiers.as_string () + "fn " + function_name;
+
+  // generic params
+  str += "\n Generic params: ";
+  if (generic_params.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &param : generic_params)
+	{
+	  // DEBUG: null pointer check
+	  if (param == nullptr)
+	    {
+	      rust_debug (
+		"something really terrible has gone wrong - null pointer "
+		"generic param in trait function decl.");
+	      return "NULL_POINTER_MARK";
+	    }
+
+	  str += "\n  " + param->as_string ();
+	}
+    }
+
+  str += "\n Self param: " + self_param.as_string ();
+
+  str += "\n Function params: ";
+  if (has_params ())
+    {
+      for (const auto &param : function_params)
+	str += "\n  " + param.as_string ();
+    }
+  else
+    {
+      str += "none";
+    }
+
+  str += "\n Return type: ";
+  if (has_return_type ())
+    str += return_type->as_string ();
+  else
+    str += "none (void)";
+
+  str += "\n Where clause: ";
+  if (has_where_clause ())
+    str += where_clause.as_string ();
+  else
+    str += "none";
+
+  return str;
+}
+
+std::string
+TraitItemConst::as_string () const
+{
+  // TODO: rewrite to work with non-linearisable exprs
+  std::string str = append_attributes (outer_attrs, OUTER);
+
+  str += "\nconst " + name + " : " + type->as_string ();
+
+  if (has_expression ())
+    str += " = " + expr->as_string ();
+
+  return str;
+}
+
+std::string
+TraitItemType::as_string () const
+{
+  std::string str = append_attributes (outer_attrs, OUTER);
+
+  str += "\ntype " + name;
+
+  str += "\n Type param bounds: ";
+  if (!has_type_param_bounds ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &bound : type_param_bounds)
+	{
+	  // DEBUG: null pointer check
+	  if (bound == nullptr)
+	    {
+	      rust_debug (
+		"something really terrible has gone wrong - null pointer "
+		"type param bound in trait item type.");
+	      return "NULL_POINTER_MARK";
+	    }
+
+	  str += "\n  " + bound->as_string ();
+	}
+    }
+
+  return str;
+}
+
+std::string
+SelfParam::as_string () const
+{
+  // TODO: rewrite to allow non-linearisable types
+  if (is_error ())
+    {
+      return "error";
+    }
+  else
+    {
+      if (has_type ())
+	{
+	  // type (i.e. not ref, no lifetime)
+	  std::string str;
+
+	  if (is_mut)
+	    str += "mut ";
+
+	  str += "self : ";
+
+	  str += type->as_string ();
+
+	  return str;
+	}
+      else if (has_lifetime ())
+	{
+	  // ref and lifetime
+	  std::string str = "&" + lifetime.as_string () + " ";
+
+	  if (is_mut)
+	    str += "mut ";
+
+	  str += "self";
+
+	  return str;
+	}
+      else if (has_ref)
+	{
+	  // ref with no lifetime
+	  std::string str = "&";
+
+	  if (is_mut)
+	    str += " mut ";
+
+	  str += "self";
+
+	  return str;
+	}
+      else
+	{
+	  // no ref, no type
+	  std::string str;
+
+	  if (is_mut)
+	    str += "mut ";
+
+	  str += "self";
+
+	  return str;
+	}
+    }
+}
+
+std::string
+ArrayElemsCopied::as_string () const
+{
+  // TODO: rewrite to allow non-linearisable exprs
+  return elem_to_copy->as_string () + "; " + num_copies->as_string ();
+}
+
+std::string
+LifetimeWhereClauseItem::as_string () const
+{
+  std::string str ("Lifetime: ");
+
+  str += lifetime.as_string ();
+
+  str += "\nLifetime bounds: ";
+
+  for (const auto &bound : lifetime_bounds)
+    str += "\n " + bound.as_string ();
+
+  return str;
+}
+
+std::string
+TypeBoundWhereClauseItem::as_string () const
+{
+  std::string str ("For lifetimes: ");
+
+  if (!has_for_lifetimes ())
+    {
+      str += "none";
+    }
+  else
+    {
+      for (const auto &for_lifetime : for_lifetimes)
+	str += "\n " + for_lifetime.as_string ();
+    }
+
+  str += "\nType: " + bound_type->as_string ();
+
+  str += "\nType param bounds bounds: ";
+
+  for (const auto &bound : type_param_bounds)
+    {
+      // debug null pointer check
+      if (bound == nullptr)
+	return "NULL_POINTER_MARK - type param bounds";
+
+      str += "\n " + bound->as_string ();
+    }
+
+  return str;
+}
+
+std::string
+ArrayElemsValues::as_string () const
+{
+  std::string str;
+
+  for (const auto &expr : values)
+    {
+      // DEBUG: null pointer check
+      if (expr == nullptr)
+	{
+	  rust_debug ("something really terrible has gone wrong - null pointer "
+		      "expr in array elems values.");
+	  return "NULL_POINTER_MARK";
+	}
+
+      str += "\n  " + expr->as_string ();
+    }
+
+  return str;
+}
+
+std::string
+MaybeNamedParam::as_string () const
+{
+  // TODO: rewrite to allow using non-linearisable types in dump
+  std::string str;
+
+  switch (param_kind)
+    {
+    case UNNAMED:
+      break;
+    case IDENTIFIER:
+      str = name + " : ";
+      break;
+    case WILDCARD:
+      str = "_ : ";
+      break;
+    default:
+      return "ERROR_MARK_STRING - maybe named param unrecognised param kind";
+    }
+
+  str += param_type->as_string ();
+
+  return str;
+}
+
+MetaItemInner::~MetaItemInner () = default;
+
+std::unique_ptr<MetaNameValueStr>
+MetaItemInner::to_meta_name_value_str () const
+{
+  if (is_key_value_pair ())
+    {
+      auto converted_item = static_cast<const MetaNameValueStr *> (this);
+      return converted_item->to_meta_name_value_str ();
+    }
+  // TODO actually parse foo = bar
+  return nullptr;
+}
+
+std::string
+MetaItemSeq::as_string () const
+{
+  std::string path_str = path.as_string () + "(";
+
+  auto i = seq.begin ();
+  auto e = seq.end ();
+
+  for (; i != e; i++)
+    {
+      path_str += (*i)->as_string ();
+      if (e != i + 1)
+	path_str += ", ";
+    }
+
+  return path_str + ")";
+}
+
+std::string
+MetaListPaths::as_string () const
+{
+  std::string str = ident + "(";
+
+  auto i = paths.begin ();
+  auto e = paths.end ();
+
+  for (; i != e; i++)
+    {
+      str += (*i).as_string ();
+      if (e != i + 1)
+	str += ", ";
+    }
+
+  return str + ")";
+}
+
+std::string
+MetaListNameValueStr::as_string () const
+{
+  std::string str = ident + "(";
+
+  auto i = strs.begin ();
+  auto e = strs.end ();
+
+  for (; i != e; i++)
+    {
+      str += (*i).as_string ();
+      if (e != i + 1)
+	str += ", ";
+    }
+
+  return str + ")";
+}
+
+std::string
+AttrInputMetaItemContainer::as_string () const
+{
+  std::string str = "(";
+
+  auto i = items.begin ();
+  auto e = items.end ();
+
+  for (; i != e; i++)
+    {
+      str += (*i)->as_string ();
+      if (e != i + 1)
+	str += ", ";
+    }
+
+  return str + ")";
+}
+
+/* Override that calls the function recursively on all items contained within
+ * the module. */
+void
+Module::add_crate_name (std::vector<std::string> &names) const
+{
+  /* TODO: test whether module has been 'cfg'-ed out to determine whether to
+   * exclude it from search */
+
+  for (const auto &item : items)
+    item->add_crate_name (names);
+}
+
+static bool
+file_exists (const std::string path)
+{
+  // Simply check if the file exists
+  // FIXME: This does not work on Windows
+  return access (path.c_str (), F_OK) != -1;
+}
+
+static std::string
+filename_from_path_attribute (std::vector<Attribute> &outer_attrs)
+{
+  // An out-of-line module cannot have inner attributes. Additionally, the
+  // default name is specified as `""` so that the caller can detect the case
+  // of "no path given" and use the default path logic (`name.rs` or
+  // `name/mod.rs`).
+  return extract_module_path ({}, outer_attrs, "");
+}
+
+void
+Module::process_file_path ()
+{
+  rust_assert (kind == Module::ModuleKind::UNLOADED);
+  rust_assert (module_file.empty ());
+
+  // This corresponds to the path of the file 'including' the module. So the
+  // file that contains the 'mod <file>;' directive
+  std::string including_fname (outer_filename);
+
+  std::string expected_file_p