aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/rust
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/rust')
-rw-r--r--gcc/testsuite/rust/compile/additional-trait-bounds2.rs2
-rw-r--r--gcc/testsuite/rust/compile/auto_traits2.rs5
-rw-r--r--gcc/testsuite/rust/compile/auto_traits3.rs34
-rw-r--r--gcc/testsuite/rust/compile/auto_traits4.rs14
-rw-r--r--gcc/testsuite/rust/compile/cfg-core1.rs12
-rw-r--r--gcc/testsuite/rust/compile/cfg-core2.rs12
-rw-r--r--gcc/testsuite/rust/compile/const_generics_3.rs8
-rw-r--r--gcc/testsuite/rust/compile/const_generics_4.rs2
-rw-r--r--gcc/testsuite/rust/compile/const_generics_7.rs14
-rw-r--r--gcc/testsuite/rust/compile/crate-metavar1.rs14
-rw-r--r--gcc/testsuite/rust/compile/derive-debug1.rs41
-rw-r--r--gcc/testsuite/rust/compile/derive-default1.rs29
-rw-r--r--gcc/testsuite/rust/compile/derive-eq-invalid.rs52
-rw-r--r--gcc/testsuite/rust/compile/derive-hash1.rs91
-rw-r--r--gcc/testsuite/rust/compile/derive-partialeq1.rs62
-rw-r--r--gcc/testsuite/rust/compile/derive_macro6.rs2
-rw-r--r--gcc/testsuite/rust/compile/enum_variant_name.rs12
-rw-r--r--gcc/testsuite/rust/compile/extern_generics.rs8
-rw-r--r--gcc/testsuite/rust/compile/feature_rust_attri0.rs6
-rw-r--r--gcc/testsuite/rust/compile/for-loop1.rs543
-rw-r--r--gcc/testsuite/rust/compile/for-loop2.rs547
-rw-r--r--gcc/testsuite/rust/compile/generic-default1.rs2
-rw-r--r--gcc/testsuite/rust/compile/generics4.rs1
-rw-r--r--gcc/testsuite/rust/compile/generics5.rs2
-rw-r--r--gcc/testsuite/rust/compile/generics6.rs1
-rw-r--r--gcc/testsuite/rust/compile/generics9.rs2
-rw-r--r--gcc/testsuite/rust/compile/if-without-else.rs9
-rw-r--r--gcc/testsuite/rust/compile/implicit_returns_err3.rs2
-rw-r--r--gcc/testsuite/rust/compile/issue-1901.rs4
-rw-r--r--gcc/testsuite/rust/compile/issue-1981.rs40
-rw-r--r--gcc/testsuite/rust/compile/issue-2015.rs19
-rw-r--r--gcc/testsuite/rust/compile/issue-2035.rs10
-rw-r--r--gcc/testsuite/rust/compile/issue-2330.rs38
-rw-r--r--gcc/testsuite/rust/compile/issue-2369.rs21
-rw-r--r--gcc/testsuite/rust/compile/issue-2423.rs6
-rw-r--r--gcc/testsuite/rust/compile/issue-2905-2.rs8
-rw-r--r--gcc/testsuite/rust/compile/issue-2954.rs17
-rw-r--r--gcc/testsuite/rust/compile/issue-3022.rs18
-rw-r--r--gcc/testsuite/rust/compile/issue-3031.rs15
-rw-r--r--gcc/testsuite/rust/compile/issue-3174.rs28
-rw-r--r--gcc/testsuite/rust/compile/issue-3242.rs1
-rw-r--r--gcc/testsuite/rust/compile/issue-3315-1.rs8
-rw-r--r--gcc/testsuite/rust/compile/issue-3315-2.rs7
-rw-r--r--gcc/testsuite/rust/compile/issue-3382.rs61
-rw-r--r--gcc/testsuite/rust/compile/issue-3402-1.rs29
-rw-r--r--gcc/testsuite/rust/compile/issue-3402-2.rs18
-rw-r--r--gcc/testsuite/rust/compile/issue-3403.rs38
-rw-r--r--gcc/testsuite/rust/compile/issue-3541-1.rs5
-rw-r--r--gcc/testsuite/rust/compile/issue-3541-2.rs3
-rw-r--r--gcc/testsuite/rust/compile/issue-3549.rs3
-rw-r--r--gcc/testsuite/rust/compile/issue-3552.rs14
-rw-r--r--gcc/testsuite/rust/compile/issue-3553.rs18
-rw-r--r--gcc/testsuite/rust/compile/issue-3554-1.rs8
-rw-r--r--gcc/testsuite/rust/compile/issue-3554-2.rs18
-rw-r--r--gcc/testsuite/rust/compile/issue-3563.rs17
-rw-r--r--gcc/testsuite/rust/compile/issue-3566-1.rs8
-rw-r--r--gcc/testsuite/rust/compile/issue-3566-2.rs22
-rw-r--r--gcc/testsuite/rust/compile/issue-3567.rs4
-rw-r--r--gcc/testsuite/rust/compile/issue-3568.rs7
-rw-r--r--gcc/testsuite/rust/compile/issue-3588.rs5
-rw-r--r--gcc/testsuite/rust/compile/issue-3605.rs5
-rw-r--r--gcc/testsuite/rust/compile/issue-3606.rs6
-rw-r--r--gcc/testsuite/rust/compile/issue-3613.rs18
-rw-r--r--gcc/testsuite/rust/compile/issue-3614.rs3
-rw-r--r--gcc/testsuite/rust/compile/issue-3615.rs7
-rw-r--r--gcc/testsuite/rust/compile/iterators1.rs58
-rw-r--r--gcc/testsuite/rust/compile/macros/builtin/option_env1.rs29
-rw-r--r--gcc/testsuite/rust/compile/macros/builtin/option_env2.rs27
-rw-r--r--gcc/testsuite/rust/compile/macros/builtin/option_env3.rs28
-rw-r--r--gcc/testsuite/rust/compile/macros/mbe/macro-expand-module.rs11
-rw-r--r--gcc/testsuite/rust/compile/macros/mbe/macro43.rs17
-rw-r--r--gcc/testsuite/rust/compile/macros/mbe/macro44.rs2
-rw-r--r--gcc/testsuite/rust/compile/method2.rs2
-rw-r--r--gcc/testsuite/rust/compile/nested_macro_use2.rs2
-rw-r--r--gcc/testsuite/rust/compile/nr2/compile.exp6
-rw-r--r--gcc/testsuite/rust/compile/nr2/exclude145
-rw-r--r--gcc/testsuite/rust/compile/redef_error2.rs2
-rw-r--r--gcc/testsuite/rust/compile/redef_error5.rs2
-rw-r--r--gcc/testsuite/rust/compile/reference1.rs2
-rw-r--r--gcc/testsuite/rust/compile/self-path2.rs4
-rw-r--r--gcc/testsuite/rust/compile/self_import_namespace.rs14
-rw-r--r--gcc/testsuite/rust/compile/sizeof-stray-infer-var-bug.rs2
-rw-r--r--gcc/testsuite/rust/compile/structural-eq-peq.rs9
-rw-r--r--gcc/testsuite/rust/compile/torture/builtin_abort.rs4
-rw-r--r--gcc/testsuite/rust/compile/torture/if.rs8
-rw-r--r--gcc/testsuite/rust/compile/torture/uninit-intrinsic-1.rs4
-rw-r--r--gcc/testsuite/rust/compile/try-expr1.rs84
-rw-r--r--gcc/testsuite/rust/compile/try-trait.rs44
-rw-r--r--gcc/testsuite/rust/compile/type-bindings1.rs1
-rw-r--r--gcc/testsuite/rust/compile/unconstrained_type_param.rs1
-rw-r--r--gcc/testsuite/rust/execute/crate-metavar1.rs11
-rw-r--r--gcc/testsuite/rust/execute/torture/builtin_macro_option_env.rs65
-rw-r--r--gcc/testsuite/rust/execute/torture/derive-default1.rs26
-rw-r--r--gcc/testsuite/rust/execute/torture/derive-partialeq1.rs64
-rw-r--r--gcc/testsuite/rust/execute/torture/enum_intrinsics1.rs48
-rw-r--r--gcc/testsuite/rust/execute/torture/enum_intrinsics2.rs25
-rw-r--r--gcc/testsuite/rust/execute/torture/for-loop1.rs545
-rw-r--r--gcc/testsuite/rust/execute/torture/for-loop2.rs544
-rw-r--r--gcc/testsuite/rust/execute/torture/issue-3126.rs52
-rw-r--r--gcc/testsuite/rust/execute/torture/issue-3381.rs90
-rw-r--r--gcc/testsuite/rust/execute/torture/issue-3502.rs52
101 files changed, 3822 insertions, 294 deletions
diff --git a/gcc/testsuite/rust/compile/additional-trait-bounds2.rs b/gcc/testsuite/rust/compile/additional-trait-bounds2.rs
index 843228a..1c49b75 100644
--- a/gcc/testsuite/rust/compile/additional-trait-bounds2.rs
+++ b/gcc/testsuite/rust/compile/additional-trait-bounds2.rs
@@ -6,4 +6,4 @@ pub unsafe auto trait Sync {}
trait A {}
-impl dyn A + Send + Sync + NonExist {} // { dg-error "failed to resolve TypePath: NonExist in this scope" }
+impl dyn A + Send + Sync + NonExist {} // { dg-error "could not resolve type path .NonExist." }
diff --git a/gcc/testsuite/rust/compile/auto_traits2.rs b/gcc/testsuite/rust/compile/auto_traits2.rs
index 7d0dcc1..382d446 100644
--- a/gcc/testsuite/rust/compile/auto_traits2.rs
+++ b/gcc/testsuite/rust/compile/auto_traits2.rs
@@ -15,12 +15,11 @@ fn foo(a: &(dyn A + Send + Sync)) {
struct S;
impl A for S {
- fn a_method(&self) {}
+ fn a_method(&self) {} // { dg-warning "unused name" }
}
fn main() {
let s = S;
- foo(&s); // { dg-error "bounds not satisfied" }
- // { dg-error "mismatched type" "" { target *-*-* } .-1 }
+ foo(&s);
}
diff --git a/gcc/testsuite/rust/compile/auto_traits3.rs b/gcc/testsuite/rust/compile/auto_traits3.rs
deleted file mode 100644
index 81c39ec..0000000
--- a/gcc/testsuite/rust/compile/auto_traits3.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-#![feature(optin_builtin_traits)]
-
-pub unsafe auto trait Send {}
-#[lang = "sync"]
-pub unsafe auto trait Sync {}
-
-trait A {
- fn a_method(&self) {}
-}
-
-fn foo(a: &(dyn A + Send + Sync)) {
- a.a_method();
-}
-
-struct S;
-
-impl A for S {
- fn a_method(&self) {} // { dg-warning "unused" }
-}
-
-// These should not be necessary because they are both auto traits
-// They need to be removed once we figure out the proper implementation for each of them
-// However, it'd be silly to implement other traits in order to ensure the test is okay,
-// as these extra trait bounds are only allowed to use auto traits
-// FIXME: #3327
-// FIXME: #3326
-unsafe impl Send for S {}
-unsafe impl Sync for S {}
-
-fn main() {
- let s = S;
-
- foo(&s);
-}
diff --git a/gcc/testsuite/rust/compile/auto_traits4.rs b/gcc/testsuite/rust/compile/auto_traits4.rs
new file mode 100644
index 0000000..f1cd1e4
--- /dev/null
+++ b/gcc/testsuite/rust/compile/auto_traits4.rs
@@ -0,0 +1,14 @@
+#![feature(optin_builtin_traits)]
+
+unsafe auto trait Send {}
+unsafe auto trait Sync {}
+
+fn take_send(_: &dyn Send) {}
+fn take_sync(_: &dyn Sync) {}
+
+fn main() {
+ let a = i32;
+
+ take_send(&a);
+ take_sync(&a);
+}
diff --git a/gcc/testsuite/rust/compile/cfg-core1.rs b/gcc/testsuite/rust/compile/cfg-core1.rs
new file mode 100644
index 0000000..7780cc9
--- /dev/null
+++ b/gcc/testsuite/rust/compile/cfg-core1.rs
@@ -0,0 +1,12 @@
+// { dg-additional-options "-frust-cfg=A -frust-cfg=B" }
+
+#[cfg_attr(A, cfg(B))]
+struct Foo0;
+
+#[cfg_attr(A, cfg(C))]
+struct Bar0;
+
+fn main() {
+ let a = Foo0;
+ let a = Bar0; // { dg-error "cannot find value" }
+}
diff --git a/gcc/testsuite/rust/compile/cfg-core2.rs b/gcc/testsuite/rust/compile/cfg-core2.rs
new file mode 100644
index 0000000..e346edd
--- /dev/null
+++ b/gcc/testsuite/rust/compile/cfg-core2.rs
@@ -0,0 +1,12 @@
+// { dg-additional-options "-frust-cfg=B" }
+
+#[cfg(not(any(A, B)))]
+struct Foo0;
+
+#[cfg(not(any(A, C)))]
+struct Bar0;
+
+fn main() {
+ let a = Foo0; // { dg-error "cannot find value" }
+ let a = Bar0;
+}
diff --git a/gcc/testsuite/rust/compile/const_generics_3.rs b/gcc/testsuite/rust/compile/const_generics_3.rs
index e4e9008..524d48d 100644
--- a/gcc/testsuite/rust/compile/const_generics_3.rs
+++ b/gcc/testsuite/rust/compile/const_generics_3.rs
@@ -1,10 +1,12 @@
-// { dg-additional-options "-w" }
+// { dg-additional-options "-w -frust-name-resolution-2.0" }
+
+#[lang = "sized"]
+trait Sized {}
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 "cannot find value .N. in this scope" }
+ value: [T; N],
}
fn main() {
diff --git a/gcc/testsuite/rust/compile/const_generics_4.rs b/gcc/testsuite/rust/compile/const_generics_4.rs
index b364d3b..2766e4c 100644
--- a/gcc/testsuite/rust/compile/const_generics_4.rs
+++ b/gcc/testsuite/rust/compile/const_generics_4.rs
@@ -4,4 +4,4 @@ const P: usize = 14;
struct Foo<const N: usize = { M }>; // { dg-error "cannot find value .M. in this scope" }
struct Bar<const N: usize = { P }>;
-struct Baz<const N: NotAType = { P }>; // { dg-error "failed to resolve TypePath: NotAType in this scope" }
+struct Baz<const N: NotAType = { P }>; // { dg-error "could not resolve type path .NotAType." }
diff --git a/gcc/testsuite/rust/compile/const_generics_7.rs b/gcc/testsuite/rust/compile/const_generics_7.rs
index 2c128db..dad4c21 100644
--- a/gcc/testsuite/rust/compile/const_generics_7.rs
+++ b/gcc/testsuite/rust/compile/const_generics_7.rs
@@ -1,17 +1,17 @@
struct S<const N: usize>;
-pub fn foo<const N: FooBar>() {} // { dg-error "failed to resolve" }
-type Foo<const N: FooBar> = S<N>; // { dg-error "failed to resolve" }
-struct Foo2<const N: FooBar>; // { dg-error "failed to resolve" }
-enum Foo3<const N: FooBar> { // { dg-error "failed to resolve" }
+pub fn foo<const N: FooBar>() {} // { dg-error "could not resolve" }
+type Foo<const N: FooBar> = S<N>; // { dg-error "could not resolve" }
+struct Foo2<const N: FooBar>; // { dg-error "could not resolve" }
+enum Foo3<const N: FooBar> { // { dg-error "could not resolve" }
Foo,
Bar,
}
-union Foo4<const N: FooBar> { // { dg-error "failed to resolve" }
+union Foo4<const N: FooBar> { // { dg-error "could not resolve" }
a: usize,
b: i32,
}
-trait Fooable<const N: FooBar> {} // { dg-error "failed to resolve" }
+trait Fooable<const N: FooBar> {} // { dg-error "could not resolve" }
trait Traitable {}
-impl<const N: FooBar> Traitable for Foo2<N> {} // { dg-error "failed to resolve" }
+impl<const N: FooBar> Traitable for Foo2<N> {} // { dg-error "could not resolve" }
diff --git a/gcc/testsuite/rust/compile/crate-metavar1.rs b/gcc/testsuite/rust/compile/crate-metavar1.rs
new file mode 100644
index 0000000..45384e1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/crate-metavar1.rs
@@ -0,0 +1,14 @@
+macro_rules! foo {
+ () => {
+ $crate::inner::bar()
+ }
+}
+
+pub mod inner {
+ pub fn bar() { }
+}
+
+fn main() {
+ foo!();
+ crate::inner::bar();
+}
diff --git a/gcc/testsuite/rust/compile/derive-debug1.rs b/gcc/testsuite/rust/compile/derive-debug1.rs
new file mode 100644
index 0000000..2596a37
--- /dev/null
+++ b/gcc/testsuite/rust/compile/derive-debug1.rs
@@ -0,0 +1,41 @@
+#[lang = "sized"]
+trait Sized {}
+
+mod core {
+ pub mod result {
+ pub enum Result<T, E> {
+ #[lang = "Ok"]
+ Ok(T),
+ #[lang = "Err"]
+ Err(E),
+ }
+ }
+
+ mod fmt {
+ struct Formatter; // { dg-warning "is never constructed" }
+ struct Error; // { dg-warning "is never constructed" }
+
+ type Result = core::result::Result<(), Error>;
+
+ trait Debug {
+ fn fmt(&self, fmt: &mut Formatter) -> Result;
+ }
+ }
+}
+
+#[derive(Debug)] // { dg-warning "unused name" }
+// { dg-warning "stub implementation" "" { target *-*-* } .-1 }
+struct Foo { a: i32, b: i64 } // { dg-warning "is never constructed" }
+
+#[derive(Debug)] // { dg-warning "unused name" }
+// { dg-warning "stub implementation" "" { target *-*-* } .-1 }
+struct Bar(i32, i32); // { dg-warning "is never constructed" }
+
+#[derive(Debug)] // { dg-warning "unused name" }
+// { dg-warning "stub implementation" "" { target *-*-* } .-1 }
+enum Baz {
+ A,
+ B(i32),
+ C { a: i32 }
+}
+
diff --git a/gcc/testsuite/rust/compile/derive-default1.rs b/gcc/testsuite/rust/compile/derive-default1.rs
new file mode 100644
index 0000000..902c65e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/derive-default1.rs
@@ -0,0 +1,29 @@
+#[derive(Default)]
+struct Foo { _a: i32, _b: i64, _c: u8 }
+
+#[lang = "sized"]
+trait Sized {}
+
+mod core {
+ mod default {
+ trait Default: Sized {
+ fn default() -> Self;
+ }
+
+ impl Default for i32 {
+ fn default() -> Self { 0 }
+ }
+
+ impl Default for i64 {
+ fn default() -> Self { 27 }
+ }
+
+ impl Default for u8 {
+ fn default() -> Self { 18 }
+ }
+ }
+}
+
+fn main() {
+ let _ = Foo::default();
+}
diff --git a/gcc/testsuite/rust/compile/derive-eq-invalid.rs b/gcc/testsuite/rust/compile/derive-eq-invalid.rs
new file mode 100644
index 0000000..b0bf856
--- /dev/null
+++ b/gcc/testsuite/rust/compile/derive-eq-invalid.rs
@@ -0,0 +1,52 @@
+mod core {
+ mod cmp {
+ #[lang = "eq"]
+ pub trait PartialEq<Rhs: ?Sized = Self> {
+ fn eq(&self, other: &Rhs) -> bool;
+
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+ }
+
+ pub trait Eq: PartialEq<Self> {
+ fn assert_receiver_is_total_eq(&self) {}
+ }
+ }
+}
+
+#[lang = "phantom_data"]
+struct PhantomData<T>;
+
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "structural_peq"]
+trait StructuralPartialEq {}
+
+#[lang = "structural_teq"]
+trait StructuralEq {}
+
+#[derive(PartialEq)]
+struct NotEq;
+
+#[derive(Eq, PartialEq)] // { dg-error "bounds not satisfied for NotEq .Eq." }
+struct Container(NotEq);
+
+// #[derive(Eq)]
+// struct Foo { a: i32 }
+// #[derive(Eq)]
+// struct Bar(i32);
+
+// #[derive(Eq)]
+// enum Baz {
+// A,
+// B(i32),
+// C { a: i32 }
+// }
+
+// #[derive(Eq)]
+// union Qux {
+// a: i32,
+// b: i64,
+// }
diff --git a/gcc/testsuite/rust/compile/derive-hash1.rs b/gcc/testsuite/rust/compile/derive-hash1.rs
new file mode 100644
index 0000000..80e1e2d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/derive-hash1.rs
@@ -0,0 +1,91 @@
+#![feature(intrinsics)]
+
+#[lang = "sized"]
+trait Sized {}
+
+pub mod core {
+ pub mod intrinsics {
+ #[lang = "discriminant_kind"]
+ pub trait DiscriminantKind {
+ #[lang = "discriminant_type"]
+ type Discriminant;
+ }
+
+ extern "rust-intrinsic" {
+ pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
+ }
+ }
+
+ pub mod hash {
+ pub trait Hasher {}
+
+ pub trait Hash {
+ /// Feeds this value into the given [`Hasher`].
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::hash_map::DefaultHasher;
+ /// use std::hash::{Hash, Hasher};
+ ///
+ /// let mut hasher = DefaultHasher::new();
+ /// 7920.hash(&mut hasher);
+ /// println!("Hash is {:x}!", hasher.finish());
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn hash<H: Hasher>(&self, state: &mut H);
+
+ /// Feeds a slice of this type into the given [`Hasher`].
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::hash_map::DefaultHasher;
+ /// use std::hash::{Hash, Hasher};
+ ///
+ /// let mut hasher = DefaultHasher::new();
+ /// let numbers = [6, 28, 496, 8128];
+ /// Hash::hash_slice(&numbers, &mut hasher);
+ /// println!("Hash is {:x}!", hasher.finish());
+ /// ```
+ #[stable(feature = "hash_slice", since = "1.3.0")]
+ fn hash_slice<H: Hasher>(data: &[Self], state: &mut H)
+ where
+ Self: Sized,
+ {
+ // for piece in data {
+ // piece.hash(state);
+ // }
+ }
+ }
+ }
+}
+
+impl core::hash::Hash for i32 {
+ fn hash<H: core::hash::Hasher>(&self, state: &mut H) {}
+}
+
+impl core::hash::Hash for i64 {
+ fn hash<H: core::hash::Hasher>(&self, state: &mut H) {}
+}
+
+// for the discriminant value
+impl core::hash::Hash for isize {
+ fn hash<H: core::hash::Hasher>(&self, state: &mut H) {}
+}
+
+#[derive(Hash)]
+struct Foo { // { dg-warning "never constructed" }
+ a: i32,
+ b: i32,
+}
+
+#[derive(Hash)]
+struct Bar(i32, i64); // { dg-warning "never constructed" }
+
+#[derive(Hash)]
+enum Baz {
+ A,
+ B(i32),
+ C { a: i64 }
+}
diff --git a/gcc/testsuite/rust/compile/derive-partialeq1.rs b/gcc/testsuite/rust/compile/derive-partialeq1.rs
new file mode 100644
index 0000000..35e33fb
--- /dev/null
+++ b/gcc/testsuite/rust/compile/derive-partialeq1.rs
@@ -0,0 +1,62 @@
+#![feature(intrinsics)]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "copy"]
+trait Copy {}
+
+#[lang = "structural_peq"]
+trait StructuralPartialEq {}
+
+#[lang = "eq"]
+pub trait PartialEq<Rhs: ?Sized = Self> {
+ /// This method tests for `self` and `other` values to be equal, and is used
+ /// by `==`.
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn eq(&self, other: &Rhs) -> bool;
+
+ /// This method tests for `!=`.
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+}
+
+#[derive(PartialEq, Copy)] // { dg-warning "unused name" }
+struct Foo;
+
+#[derive(PartialEq)]
+struct Bar(Foo);
+
+#[derive(PartialEq)]
+struct Baz { _inner: Foo }
+
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn print(b: bool) {
+ if b {
+ unsafe { puts("true" as *const str as *const i8) }
+ } else {
+ unsafe { puts("false" as *const str as *const i8) }
+ }
+}
+
+fn main() -> i32 {
+ let x = Foo;
+
+ let b1 = x == Foo;
+ let b2 = Bar(x) != Bar(Foo);
+ let b3 = Baz { _inner: Foo } != Baz { _inner: x };
+
+ print(b1);
+ print(b2);
+ print(b3);
+
+ 0
+}
diff --git a/gcc/testsuite/rust/compile/derive_macro6.rs b/gcc/testsuite/rust/compile/derive_macro6.rs
index 35327c0..412144d 100644
--- a/gcc/testsuite/rust/compile/derive_macro6.rs
+++ b/gcc/testsuite/rust/compile/derive_macro6.rs
@@ -1,9 +1,9 @@
#[lang = "sized"]
pub trait Sized {}
+#[lang = "copy"]
pub trait Copy {}
-
#[lang = "clone"]
pub trait Clone {
fn clone(&self) -> Self;
diff --git a/gcc/testsuite/rust/compile/enum_variant_name.rs b/gcc/testsuite/rust/compile/enum_variant_name.rs
new file mode 100644
index 0000000..671fced
--- /dev/null
+++ b/gcc/testsuite/rust/compile/enum_variant_name.rs
@@ -0,0 +1,12 @@
+// { dg-additional-options "-w -frust-name-resolution-2.0" }
+struct E1;
+
+enum Test {
+ E1 = {
+ let x = E1;
+ {
+ let x = E1;
+ }
+ 0
+ },
+}
diff --git a/gcc/testsuite/rust/compile/extern_generics.rs b/gcc/testsuite/rust/compile/extern_generics.rs
new file mode 100644
index 0000000..26f97a6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/extern_generics.rs
@@ -0,0 +1,8 @@
+#[lang="sized"]
+trait Sized {}
+
+
+// E0044
+fn main() {
+extern "C" { fn some_func<T>(x: T); } // { dg-error "foreign items may not have type parameters .E0044." }
+} \ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/feature_rust_attri0.rs b/gcc/testsuite/rust/compile/feature_rust_attri0.rs
index 9c11f56..1937acf 100644
--- a/gcc/testsuite/rust/compile/feature_rust_attri0.rs
+++ b/gcc/testsuite/rust/compile/feature_rust_attri0.rs
@@ -1,3 +1,7 @@
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
#[rustc_builtin_macro] //{ dg-error "internal implementation detail. " "" { target *-*-* } }
macro_rules! line {
() => {{}};
@@ -5,7 +9,7 @@ macro_rules! line {
fn main() -> i32 {
let a = line!();
- print(a);
+ printf("%d\0" as *const str as *const i8, a);
0
}
diff --git a/gcc/testsuite/rust/compile/for-loop1.rs b/gcc/testsuite/rust/compile/for-loop1.rs
new file mode 100644
index 0000000..21e0399
--- /dev/null
+++ b/gcc/testsuite/rust/compile/for-loop1.rs
@@ -0,0 +1,543 @@
+// { dg-output "loop\r*\nloop\r*\n" }
+#![feature(intrinsics)]
+
+pub use option::Option::{self, None, Some};
+pub use result::Result::{self, Err, Ok};
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+ fn puts(s: *const i8);
+}
+
+mod option {
+ pub enum Option<T> {
+ #[lang = "None"]
+ None,
+ #[lang = "Some"]
+ Some(T),
+ }
+}
+
+mod result {
+ enum Result<T, E> {
+ Ok(T),
+ Err(E),
+ }
+}
+
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {
+ fn clone(&self) -> Self;
+
+ fn clone_from(&mut self, source: &Self) {
+ *self = source.clone()
+ }
+}
+
+mod impls {
+ use super::Clone;
+
+ macro_rules! impl_clone {
+ ($($t:ty)*) => {
+ $(
+ impl Clone for $t {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+ )*
+ }
+ }
+
+ impl_clone! {
+ usize u8 u16 u32 u64 // u128
+ isize i8 i16 i32 i64 // i128
+ f32 f64
+ bool char
+ }
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+ // Empty.
+}
+
+mod copy_impls {
+ use super::Copy;
+
+ macro_rules! impl_copy {
+ ($($t:ty)*) => {
+ $(
+ impl Copy for $t {}
+ )*
+ }
+ }
+
+ impl_copy! {
+ usize u8 u16 u32 u64 // u128
+ isize i8 i16 i32 i64 // i128
+ f32 f64
+ bool char
+ }
+}
+
+mod intrinsics {
+ extern "rust-intrinsic" {
+ pub fn add_with_overflow<T>(x: T, y: T) -> (T, bool);
+ pub fn wrapping_add<T>(a: T, b: T) -> T;
+ pub fn wrapping_sub<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;
+ pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+ pub fn move_val_init<T>(dst: *mut T, src: T);
+ pub fn uninit<T>() -> T;
+ }
+}
+
+mod ptr {
+ #[lang = "const_ptr"]
+ impl<T> *const T {
+ pub unsafe fn offset(self, count: isize) -> *const T {
+ crate::intrinsics::offset(self, count)
+ }
+ }
+
+ #[lang = "mut_ptr"]
+ impl<T> *mut T {
+ pub unsafe fn offset(self, count: isize) -> *mut T {
+ crate::intrinsics::offset(self, count) as *mut T
+ }
+ }
+
+ pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
+ let x = x as *mut u8;
+ let y = y as *mut u8;
+ let len = crate::mem::size_of::<T>() * count;
+ swap_nonoverlapping_bytes(x, y, len)
+ }
+
+ pub unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
+ // For types smaller than the block optimization below,
+ // just swap directly to avoid pessimizing codegen.
+ if crate::mem::size_of::<T>() < 32 {
+ let z = read(x);
+ crate::intrinsics::copy_nonoverlapping(y, x, 1);
+ write(y, z);
+ } else {
+ swap_nonoverlapping(x, y, 1);
+ }
+ }
+
+ pub unsafe fn write<T>(dst: *mut T, src: T) {
+ crate::intrinsics::move_val_init(&mut *dst, src)
+ }
+
+ pub unsafe fn read<T>(src: *const T) -> T {
+ let mut tmp: T = crate::mem::uninitialized();
+ crate::intrinsics::copy_nonoverlapping(src, &mut tmp, 1);
+ tmp
+ }
+
+ pub unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
+ struct Block(u64, u64, u64, u64);
+ struct UnalignedBlock(u64, u64, u64, u64);
+
+ let block_size = crate::mem::size_of::<Block>();
+
+ // Loop through x & y, copying them `Block` at a time
+ // The optimizer should unroll the loop fully for most types
+ // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively
+ let mut i: usize = 0;
+ while i + block_size <= len {
+ // Create some uninitialized memory as scratch space
+ // Declaring `t` here avoids aligning the stack when this loop is unused
+ let mut t: Block = crate::mem::uninitialized();
+ let t = &mut t as *mut _ as *mut u8;
+ let x = x.offset(i as isize);
+ let y = y.offset(i as isize);
+
+ // Swap a block of bytes of x & y, using t as a temporary buffer
+ // This should be optimized into efficient SIMD operations where available
+ crate::intrinsics::copy_nonoverlapping(x, t, block_size);
+ crate::intrinsics::copy_nonoverlapping(y, x, block_size);
+ crate::intrinsics::copy_nonoverlapping(t, y, block_size);
+ i += block_size;
+ }
+
+ if i < len {
+ // Swap any remaining bytes
+ let mut t: UnalignedBlock = crate::mem::uninitialized();
+ let rem = len - i;
+
+ let t = &mut t as *mut _ as *mut u8;
+ let x = x.offset(i as isize);
+ let y = y.offset(i as isize);
+
+ crate::intrinsics::copy_nonoverlapping(x, t, rem);
+ crate::intrinsics::copy_nonoverlapping(y, x, rem);
+ crate::intrinsics::copy_nonoverlapping(t, y, rem);
+ }
+ }
+}
+
+mod mem {
+ extern "rust-intrinsic" {
+ #[rustc_const_stable(feature = "const_transmute", since = "1.46.0")]
+ pub fn transmute<T, U>(_: T) -> U;
+ #[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
+ pub fn size_of<T>() -> usize;
+ }
+
+ pub fn swap<T>(x: &mut T, y: &mut T) {
+ unsafe {
+ crate::ptr::swap_nonoverlapping_one(x, y);
+ }
+ }
+
+ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
+ swap(dest, &mut src);
+ src
+ }
+
+ pub unsafe fn uninitialized<T>() -> T {
+ crate::intrinsics::uninit()
+ }
+}
+
+macro_rules! impl_uint {
+ ($($ty:ident = $lang:literal),*) => {
+ $(
+ impl $ty {
+ pub fn wrapping_add(self, rhs: Self) -> Self {
+ unsafe {
+ crate::intrinsics::wrapping_add(self, rhs)
+ }
+ }
+
+ pub fn wrapping_sub(self, rhs: Self) -> Self {
+ unsafe {
+ crate::intrinsics::wrapping_sub(self, rhs)
+ }
+ }
+
+ pub fn rotate_left(self, n: u32) -> Self {
+ unsafe {
+ crate::intrinsics::rotate_left(self, n as Self)
+ }
+ }
+
+ pub fn rotate_right(self, n: u32) -> Self {
+ unsafe {
+ crate::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; crate::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; crate::mem::size_of::<Self>()]) -> Self {
+ unsafe { crate::mem::transmute(bytes) }
+ }
+
+ pub fn checked_add(self, rhs: Self) -> Option<Self> {
+ let (a, b) = self.overflowing_add(rhs);
+ if b {
+ Option::None
+ } else {
+ Option::Some(a)
+ }
+ }
+
+ pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
+ let (a, b) = unsafe { crate::intrinsics::add_with_overflow(self as $ty, rhs as $ty) };
+ (a as Self, b)
+ }
+ }
+ )*
+ }
+}
+
+impl_uint!(
+ u8 = "u8",
+ u16 = "u16",
+ u32 = "u32",
+ u64 = "u64",
+ usize = "usize"
+);
+
+#[lang = "add"]
+pub trait Add<RHS = Self> {
+ type Output;
+
+ fn add(self, rhs: RHS) -> Self::Output;
+}
+macro_rules! add_impl {
+ ($($t:ty)*) => ($(
+ impl Add for $t {
+ type Output = $t;
+
+ fn add(self, other: $t) -> $t { self + other }
+ }
+ )*)
+}
+
+add_impl! { usize u8 u16 u32 u64 /*isize i8 i16 i32 i64*/ f32 f64 }
+
+#[lang = "sub"]
+pub trait Sub<RHS = Self> {
+ type Output;
+
+ fn sub(self, rhs: RHS) -> Self::Output;
+}
+macro_rules! sub_impl {
+ ($($t:ty)*) => ($(
+ impl Sub for $t {
+ type Output = $t;
+
+ fn sub(self, other: $t) -> $t { self - other }
+ }
+ )*)
+}
+
+sub_impl! { usize u8 u16 u32 u64 /*isize i8 i16 i32 i64*/ f32 f64 }
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+ pub start: Idx,
+ pub end: Idx,
+}
+
+pub trait TryFrom<T>: Sized {
+ /// The type returned in the event of a conversion error.
+ type Error;
+
+ /// Performs the conversion.
+ fn try_from(value: T) -> Result<Self, Self::Error>;
+}
+
+pub trait From<T>: Sized {
+ fn from(_: T) -> Self;
+}
+
+impl<T> From<T> for T {
+ fn from(t: T) -> T {
+ t
+ }
+}
+
+impl<T, U> TryFrom<U> for T
+where
+ T: From<U>,
+{
+ type Error = !;
+
+ fn try_from(value: U) -> Result<Self, Self::Error> {
+ Ok(T::from(value))
+ }
+}
+
+trait Step {
+ /// Returns the number of steps between two step objects. The count is
+ /// inclusive of `start` and exclusive of `end`.
+ ///
+ /// Returns `None` if it is not possible to calculate `steps_between`
+ /// without overflow.
+ fn steps_between(start: &Self, end: &Self) -> Option<usize>;
+
+ /// Replaces this step with `1`, returning itself
+ fn replace_one(&mut self) -> Self;
+
+ /// Replaces this step with `0`, returning itself
+ fn replace_zero(&mut self) -> Self;
+
+ /// Adds one to this step, returning the result
+ fn add_one(&self) -> Self;
+
+ /// Subtracts one to this step, returning the result
+ fn sub_one(&self) -> Self;
+
+ /// Add an usize, returning None on overflow
+ fn add_usize(&self, n: usize) -> Option<Self>;
+}
+
+// These are still macro-generated because the integer literals resolve to different types.
+macro_rules! step_identical_methods {
+ () => {
+ #[inline]
+ fn replace_one(&mut self) -> Self {
+ crate::mem::replace(self, 1)
+ }
+
+ #[inline]
+ fn replace_zero(&mut self) -> Self {
+ crate::mem::replace(self, 0)
+ }
+
+ #[inline]
+ fn add_one(&self) -> Self {
+ Add::add(*self, 1)
+ }
+
+ #[inline]
+ fn sub_one(&self) -> Self {
+ Sub::sub(*self, 1)
+ }
+ };
+}
+
+macro_rules! step_impl_unsigned {
+ ($($t:ty)*) => ($(
+ impl Step for $t {
+ fn steps_between(start: &$t, end: &$t) -> Option<usize> {
+ if *start < *end {
+ // Note: We assume $t <= usize here
+ Option::Some((*end - *start) as usize)
+ } else {
+ Option::Some(0)
+ }
+ }
+
+ fn add_usize(&self, n: usize) -> Option<Self> {
+ match <$t>::try_from(n) {
+ Result::Ok(n_as_t) => self.checked_add(n_as_t),
+ Result::Err(_) => Option::None,
+ }
+ }
+
+ step_identical_methods!();
+ }
+ )*)
+}
+macro_rules! step_impl_signed {
+ ($( [$t:ty : $unsigned:ty] )*) => ($(
+ impl Step for $t {
+ #[inline]
+ #[allow(trivial_numeric_casts)]
+ fn steps_between(start: &$t, end: &$t) -> Option<usize> {
+ if *start < *end {
+ // Note: We assume $t <= isize here
+ // Use .wrapping_sub and cast to usize to compute the
+ // difference that may not fit inside the range of isize.
+ Option::Some((*end as isize).wrapping_sub(*start as isize) as usize)
+ } else {
+ Option::Some(0)
+ }
+ }
+
+ #[inline]
+ #[allow(unreachable_patterns)]
+ fn add_usize(&self, n: usize) -> Option<Self> {
+ match <$unsigned>::try_from(n) {
+ Result::Ok(n_as_unsigned) => {
+ // Wrapping in unsigned space handles cases like
+ // `-120_i8.add_usize(200) == Option::Some(80_i8)`,
+ // even though 200_usize is out of range for i8.
+ let wrapped = (*self as $unsigned).wrapping_add(n_as_unsigned) as $t;
+ if wrapped >= *self {
+ Option::Some(wrapped)
+ } else {
+ Option::None // Addition overflowed
+ }
+ }
+ Result::Err(_) => Option::None,
+ }
+ }
+
+ step_identical_methods!();
+ }
+ )*)
+}
+
+macro_rules! step_impl_no_between {
+ ($($t:ty)*) => ($(
+ impl Step for $t {
+ #[inline]
+ fn steps_between(_start: &Self, _end: &Self) -> Option<usize> {
+ Option::None
+ }
+
+ #[inline]
+ fn add_usize(&self, n: usize) -> Option<Self> {
+ self.checked_add(n as $t)
+ }
+
+ step_identical_methods!();
+ }
+ )*)
+}
+
+step_impl_unsigned!(usize);
+
+pub trait Iterator {
+ type Item;
+
+ #[lang = "next"]
+ fn next(&mut self) -> Option<Self::Item>;
+}
+
+impl<A: Step> Iterator for Range<A> {
+ type Item = A;
+
+ fn next(&mut self) -> Option<A> {
+ if self.start < self.end {
+ // We check for overflow here, even though it can't actually
+ // happen. Adding this check does however help llvm vectorize loops
+ // for some ranges that don't get vectorized otherwise,
+ // and this won't actually result in an extra check in an optimized build.
+ match self.start.add_usize(1) {
+ Option::Some(mut n) => {
+ crate::mem::swap(&mut n, &mut self.start);
+ Option::Some(n)
+ }
+ Option::None => Option::None,
+ }
+ } else {
+ Option::None
+ }
+ }
+}
+
+pub trait IntoIterator {
+ type Item;
+
+ type IntoIter: Iterator<Item = Self::Item>;
+
+ #[lang = "into_iter"]
+ fn into_iter(self) -> Self::IntoIter;
+}
+
+impl<I: Iterator> IntoIterator for I {
+ type Item = I::Item;
+ type IntoIter = I;
+
+ fn into_iter(self) -> I {
+ self
+ }
+}
+
+pub fn main() {
+ let a = 1usize..3usize;
+
+ for i in a { // { dg-warning "unused name" }
+ unsafe { puts("loop\0" as *const str as *const i8); }
+ }
+}
diff --git a/gcc/testsuite/rust/compile/for-loop2.rs b/gcc/testsuite/rust/compile/for-loop2.rs
new file mode 100644
index 0000000..a0ad066
--- /dev/null
+++ b/gcc/testsuite/rust/compile/for-loop2.rs
@@ -0,0 +1,547 @@
+// { dg-output "1\r*\n2\r*\n" }
+#![feature(intrinsics)]
+
+pub use option::Option::{self, None, Some};
+pub use result::Result::{self, Err, Ok};
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+ fn puts(s: *const i8);
+}
+
+mod option {
+ pub enum Option<T> {
+ #[lang = "None"]
+ None,
+ #[lang = "Some"]
+ Some(T),
+ }
+}
+
+mod result {
+ enum Result<T, E> {
+ Ok(T),
+ Err(E),
+ }
+}
+
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {
+ fn clone(&self) -> Self;
+
+ fn clone_from(&mut self, source: &Self) {
+ *self = source.clone()
+ }
+}
+
+mod impls {
+ use super::Clone;
+
+ macro_rules! impl_clone {
+ ($($t:ty)*) => {
+ $(
+ impl Clone for $t {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+ )*
+ }
+ }
+
+ impl_clone! {
+ usize u8 u16 u32 u64 // u128
+ isize i8 i16 i32 i64 // i128
+ f32 f64
+ bool char
+ }
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+ // Empty.
+}
+
+mod copy_impls {
+ use super::Copy;
+
+ macro_rules! impl_copy {
+ ($($t:ty)*) => {
+ $(
+ impl Copy for $t {}
+ )*
+ }
+ }
+
+ impl_copy! {
+ usize u8 u16 u32 u64 // u128
+ isize i8 i16 i32 i64 // i128
+ f32 f64
+ bool char
+ }
+}
+
+mod intrinsics {
+ extern "rust-intrinsic" {
+ pub fn add_with_overflow<T>(x: T, y: T) -> (T, bool);
+ pub fn wrapping_add<T>(a: T, b: T) -> T;
+ pub fn wrapping_sub<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;
+ pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+ pub fn move_val_init<T>(dst: *mut T, src: T);
+ pub fn uninit<T>() -> T;
+ }
+}
+
+mod ptr {
+ #[lang = "const_ptr"]
+ impl<T> *const T {
+ pub unsafe fn offset(self, count: isize) -> *const T {
+ crate::intrinsics::offset(self, count)
+ }
+ }
+
+ #[lang = "mut_ptr"]
+ impl<T> *mut T {
+ pub unsafe fn offset(self, count: isize) -> *mut T {
+ crate::intrinsics::offset(self, count) as *mut T
+ }
+ }
+
+ pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
+ let x = x as *mut u8;
+ let y = y as *mut u8;
+ let len = crate::mem::size_of::<T>() * count;
+ swap_nonoverlapping_bytes(x, y, len)
+ }
+
+ pub unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
+ // For types smaller than the block optimization below,
+ // just swap directly to avoid pessimizing codegen.
+ if crate::mem::size_of::<T>() < 32 {
+ let z = read(x);
+ crate::intrinsics::copy_nonoverlapping(y, x, 1);
+ write(y, z);
+ } else {
+ swap_nonoverlapping(x, y, 1);
+ }
+ }
+
+ pub unsafe fn write<T>(dst: *mut T, src: T) {
+ crate::intrinsics::move_val_init(&mut *dst, src)
+ }
+
+ pub unsafe fn read<T>(src: *const T) -> T {
+ let mut tmp: T = crate::mem::uninitialized();
+ crate::intrinsics::copy_nonoverlapping(src, &mut tmp, 1);
+ tmp
+ }
+
+ pub unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
+ struct Block(u64, u64, u64, u64);
+ struct UnalignedBlock(u64, u64, u64, u64);
+
+ let block_size = crate::mem::size_of::<Block>();
+
+ // Loop through x & y, copying them `Block` at a time
+ // The optimizer should unroll the loop fully for most types
+ // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively
+ let mut i: usize = 0;
+ while i + block_size <= len {
+ // Create some uninitialized memory as scratch space
+ // Declaring `t` here avoids aligning the stack when this loop is unused
+ let mut t: Block = crate::mem::uninitialized();
+ let t = &mut t as *mut _ as *mut u8;
+ let x = x.offset(i as isize);
+ let y = y.offset(i as isize);
+
+ // Swap a block of bytes of x & y, using t as a temporary buffer
+ // This should be optimized into efficient SIMD operations where available
+ crate::intrinsics::copy_nonoverlapping(x, t, block_size);
+ crate::intrinsics::copy_nonoverlapping(y, x, block_size);
+ crate::intrinsics::copy_nonoverlapping(t, y, block_size);
+ i += block_size;
+ }
+
+ if i < len {
+ // Swap any remaining bytes
+ let mut t: UnalignedBlock = crate::mem::uninitialized();
+ let rem = len - i;
+
+ let t = &mut t as *mut _ as *mut u8;
+ let x = x.offset(i as isize);
+ let y = y.offset(i as isize);
+
+ crate::intrinsics::copy_nonoverlapping(x, t, rem);
+ crate::intrinsics::copy_nonoverlapping(y, x, rem);
+ crate::intrinsics::copy_nonoverlapping(t, y, rem);
+ }
+ }
+}
+
+mod mem {
+ extern "rust-intrinsic" {
+ #[rustc_const_stable(feature = "const_transmute", since = "1.46.0")]
+ pub fn transmute<T, U>(_: T) -> U;
+ #[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
+ pub fn size_of<T>() -> usize;
+ }
+
+ pub fn swap<T>(x: &mut T, y: &mut T) {
+ unsafe {
+ crate::ptr::swap_nonoverlapping_one(x, y);
+ }
+ }
+
+ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
+ swap(dest, &mut src);
+ src
+ }
+
+ pub unsafe fn uninitialized<T>() -> T {
+ crate::intrinsics::uninit()
+ }
+}
+
+macro_rules! impl_uint {
+ ($($ty:ident = $lang:literal),*) => {
+ $(
+ impl $ty {
+ pub fn wrapping_add(self, rhs: Self) -> Self {
+ unsafe {
+ crate::intrinsics::wrapping_add(self, rhs)
+ }
+ }
+
+ pub fn wrapping_sub(self, rhs: Self) -> Self {
+ unsafe {
+ crate::intrinsics::wrapping_sub(self, rhs)
+ }
+ }
+
+ pub fn rotate_left(self, n: u32) -> Self {
+ unsafe {
+ crate::intrinsics::rotate_left(self, n as Self)
+ }
+ }
+
+ pub fn rotate_right(self, n: u32) -> Self {
+ unsafe {
+ crate::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; crate::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; crate::mem::size_of::<Self>()]) -> Self {
+ unsafe { crate::mem::transmute(bytes) }
+ }
+
+ pub fn checked_add(self, rhs: Self) -> Option<Self> {
+ let (a, b) = self.overflowing_add(rhs);
+ if b {
+ Option::None
+ } else {
+ Option::Some(a)
+ }
+ }
+
+ pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
+ let (a, b) = unsafe { crate::intrinsics::add_with_overflow(self as $ty, rhs as $ty) };
+ (a as Self, b)
+ }
+ }
+ )*
+ }
+}
+
+impl_uint!(
+ u8 = "u8",
+ u16 = "u16",
+ u32 = "u32",
+ u64 = "u64",
+ usize = "usize"
+);
+
+#[lang = "add"]
+pub trait Add<RHS = Self> {
+ type Output;
+
+ fn add(self, rhs: RHS) -> Self::Output;
+}
+macro_rules! add_impl {
+ ($($t:ty)*) => ($(
+ impl Add for $t {
+ type Output = $t;
+
+ fn add(self, other: $t) -> $t { self + other }
+ }
+ )*)
+}
+
+add_impl! { usize u8 u16 u32 u64 /*isize i8 i16 i32 i64*/ f32 f64 }
+
+#[lang = "sub"]
+pub trait Sub<RHS = Self> {
+ type Output;
+
+ fn sub(self, rhs: RHS) -> Self::Output;
+}
+macro_rules! sub_impl {
+ ($($t:ty)*) => ($(
+ impl Sub for $t {
+ type Output = $t;
+
+ fn sub(self, other: $t) -> $t { self - other }
+ }
+ )*)
+}
+
+sub_impl! { usize u8 u16 u32 u64 /*isize i8 i16 i32 i64*/ f32 f64 }
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+ pub start: Idx,
+ pub end: Idx,
+}
+
+pub trait TryFrom<T>: Sized {
+ /// The type returned in the event of a conversion error.
+ type Error;
+
+ /// Performs the conversion.
+ fn try_from(value: T) -> Result<Self, Self::Error>;
+}
+
+pub trait From<T>: Sized {
+ fn from(_: T) -> Self;
+}
+
+impl<T> From<T> for T {
+ fn from(t: T) -> T {
+ t
+ }
+}
+
+impl<T, U> TryFrom<U> for T
+where
+ T: From<U>,
+{
+ type Error = !;
+
+ fn try_from(value: U) -> Result<Self, Self::Error> {
+ Ok(T::from(value))
+ }
+}
+
+trait Step {
+ /// Returns the number of steps between two step objects. The count is
+ /// inclusive of `start` and exclusive of `end`.
+ ///
+ /// Returns `None` if it is not possible to calculate `steps_between`
+ /// without overflow.
+ fn steps_between(start: &Self, end: &Self) -> Option<usize>;
+
+ /// Replaces this step with `1`, returning itself
+ fn replace_one(&mut self) -> Self;
+
+ /// Replaces this step with `0`, returning itself
+ fn replace_zero(&mut self) -> Self;
+
+ /// Adds one to this step, returning the result
+ fn add_one(&self) -> Self;
+
+ /// Subtracts one to this step, returning the result
+ fn sub_one(&self) -> Self;
+
+ /// Add an usize, returning None on overflow
+ fn add_usize(&self, n: usize) -> Option<Self>;
+}
+
+// These are still macro-generated because the integer literals resolve to different types.
+macro_rules! step_identical_methods {
+ () => {
+ #[inline]
+ fn replace_one(&mut self) -> Self {
+ crate::mem::replace(self, 1)
+ }
+
+ #[inline]
+ fn replace_zero(&mut self) -> Self {
+ crate::mem::replace(self, 0)
+ }
+
+ #[inline]
+ fn add_one(&self) -> Self {
+ Add::add(*self, 1)
+ }
+
+ #[inline]
+ fn sub_one(&self) -> Self {
+ Sub::sub(*self, 1)
+ }
+ };
+}
+
+macro_rules! step_impl_unsigned {
+ ($($t:ty)*) => ($(
+ impl Step for $t {
+ fn steps_between(start: &$t, end: &$t) -> Option<usize> {
+ if *start < *end {
+ // Note: We assume $t <= usize here
+ Option::Some((*end - *start) as usize)
+ } else {
+ Option::Some(0)
+ }
+ }
+
+ fn add_usize(&self, n: usize) -> Option<Self> {
+ match <$t>::try_from(n) {
+ Result::Ok(n_as_t) => self.checked_add(n_as_t),
+ Result::Err(_) => Option::None,
+ }
+ }
+
+ step_identical_methods!();
+ }
+ )*)
+}
+macro_rules! step_impl_signed {
+ ($( [$t:ty : $unsigned:ty] )*) => ($(
+ impl Step for $t {
+ #[inline]
+ #[allow(trivial_numeric_casts)]
+ fn steps_between(start: &$t, end: &$t) -> Option<usize> {
+ if *start < *end {
+ // Note: We assume $t <= isize here
+ // Use .wrapping_sub and cast to usize to compute the
+ // difference that may not fit inside the range of isize.
+ Option::Some((*end as isize).wrapping_sub(*start as isize) as usize)
+ } else {
+ Option::Some(0)
+ }
+ }
+
+ #[inline]
+ #[allow(unreachable_patterns)]
+ fn add_usize(&self, n: usize) -> Option<Self> {
+ match <$unsigned>::try_from(n) {
+ Result::Ok(n_as_unsigned) => {
+ // Wrapping in unsigned space handles cases like
+ // `-120_i8.add_usize(200) == Option::Some(80_i8)`,
+ // even though 200_usize is out of range for i8.
+ let wrapped = (*self as $unsigned).wrapping_add(n_as_unsigned) as $t;
+ if wrapped >= *self {
+ Option::Some(wrapped)
+ } else {
+ Option::None // Addition overflowed
+ }
+ }
+ Result::Err(_) => Option::None,
+ }
+ }
+
+ step_identical_methods!();
+ }
+ )*)
+}
+
+macro_rules! step_impl_no_between {
+ ($($t:ty)*) => ($(
+ impl Step for $t {
+ #[inline]
+ fn steps_between(_start: &Self, _end: &Self) -> Option<usize> {
+ Option::None
+ }
+
+ #[inline]
+ fn add_usize(&self, n: usize) -> Option<Self> {
+ self.checked_add(n as $t)
+ }
+
+ step_identical_methods!();
+ }
+ )*)
+}
+
+step_impl_unsigned!(usize);
+
+pub trait Iterator {
+ type Item;
+
+ #[lang = "next"]
+ fn next(&mut self) -> Option<Self::Item>;
+}
+
+impl<A: Step> Iterator for Range<A> {
+ type Item = A;
+
+ fn next(&mut self) -> Option<A> {
+ if self.start < self.end {
+ // We check for overflow here, even though it can't actually
+ // happen. Adding this check does however help llvm vectorize loops
+ // for some ranges that don't get vectorized otherwise,
+ // and this won't actually result in an extra check in an optimized build.
+ match self.start.add_usize(1) {
+ Option::Some(mut n) => {
+ crate::mem::swap(&mut n, &mut self.start);
+ Option::Some(n)
+ }
+ Option::None => Option::None,
+ }
+ } else {
+ Option::None
+ }
+ }
+}
+
+pub trait IntoIterator {
+ type Item;
+
+ type IntoIter: Iterator<Item = Self::Item>;
+
+ #[lang = "into_iter"]
+ fn into_iter(self) -> Self::IntoIter;
+}
+
+impl<I: Iterator> IntoIterator for I {
+ type Item = I::Item;
+ type IntoIter = I;
+
+ fn into_iter(self) -> I {
+ self
+ }
+}
+
+pub fn main() {
+ // make sure we can desugar for-loops inside other blocks
+
+ if true {
+ for _ in 20usize..40usize {
+ unsafe {
+ puts("loop\0" as *const str as *const i8);
+ }
+ }
+ }
+}
diff --git a/gcc/testsuite/rust/compile/generic-default1.rs b/gcc/testsuite/rust/compile/generic-default1.rs
index 0a132bf..4155640 100644
--- a/gcc/testsuite/rust/compile/generic-default1.rs
+++ b/gcc/testsuite/rust/compile/generic-default1.rs
@@ -1,5 +1,5 @@
struct Foo<A = i321>(A);
-// { dg-error "failed to resolve TypePath: i321" "" { target *-*-* } .-1 }
+// { dg-error "could not resolve type path .i321." "" { target *-*-* } .-1 }
fn main() {
let a;
diff --git a/gcc/testsuite/rust/compile/generics4.rs b/gcc/testsuite/rust/compile/generics4.rs
index 31b681a..c4dbc432 100644
--- a/gcc/testsuite/rust/compile/generics4.rs
+++ b/gcc/testsuite/rust/compile/generics4.rs
@@ -6,7 +6,6 @@ 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 resolve expression of function call} "" { target *-*-* } .-1 }
let b2: i32 = a2.0;
// { dg-error {Expected Tuple or ADT got: T\?} "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/rust/compile/generics5.rs b/gcc/testsuite/rust/compile/generics5.rs
index 6c847b5..f861038 100644
--- a/gcc/testsuite/rust/compile/generics5.rs
+++ b/gcc/testsuite/rust/compile/generics5.rs
@@ -3,7 +3,7 @@ struct GenericStruct<T>(T, usize);
fn main() {
let a2;
a2 = GenericStruct::<i8, T>(1, 456);
- // { dg-error "failed to resolve TypePath: T" "" { target *-*-* } .-1 }
+ // { dg-error "could not resolve type path .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
index 33093cf..d77c559 100644
--- a/gcc/testsuite/rust/compile/generics6.rs
+++ b/gcc/testsuite/rust/compile/generics6.rs
@@ -27,6 +27,5 @@ impl Foo<f32> {
fn main() {
let a: i32 = Foo::test(); // { dg-error "multiple applicable items in scope for: .test." }
- // { dg-error {Failed to resolve expression of function call} "" { target *-*-* } .-1 }
}
diff --git a/gcc/testsuite/rust/compile/generics9.rs b/gcc/testsuite/rust/compile/generics9.rs
index 3766703..3c787aa 100644
--- a/gcc/testsuite/rust/compile/generics9.rs
+++ b/gcc/testsuite/rust/compile/generics9.rs
@@ -1,5 +1,5 @@
struct Foo<A, B = (A, B)>(A, B);
-// { dg-error "failed to resolve TypePath: B" "" { target *-*-* } .-1 }
+// { dg-error "could not resolve type path .B." "" { target *-*-* } .-1 }
fn main() {
let a: Foo<bool>;
diff --git a/gcc/testsuite/rust/compile/if-without-else.rs b/gcc/testsuite/rust/compile/if-without-else.rs
new file mode 100644
index 0000000..1a0f644
--- /dev/null
+++ b/gcc/testsuite/rust/compile/if-without-else.rs
@@ -0,0 +1,9 @@
+fn foo(pred: bool) -> u8 {
+ if pred { // { dg-error "mismatched types" }
+ 1
+ }
+ 3
+}
+
+fn main(){
+}
diff --git a/gcc/testsuite/rust/compile/implicit_returns_err3.rs b/gcc/testsuite/rust/compile/implicit_returns_err3.rs
index ac98213..f0330ac 100644
--- a/gcc/testsuite/rust/compile/implicit_returns_err3.rs
+++ b/gcc/testsuite/rust/compile/implicit_returns_err3.rs
@@ -1,6 +1,6 @@
fn test(x: i32) -> i32 { // { dg-error "mismatched types, expected .i32. but got ...." }
if x > 1 {
- 1
+ return 1;
}
}
diff --git a/gcc/testsuite/rust/compile/issue-1901.rs b/gcc/testsuite/rust/compile/issue-1901.rs
index cfd8ef4..b43e34f 100644
--- a/gcc/testsuite/rust/compile/issue-1901.rs
+++ b/gcc/testsuite/rust/compile/issue-1901.rs
@@ -13,14 +13,14 @@ mod ptr {
#[lang = "const_ptr"]
impl<T> *const T {
pub unsafe fn offset(self, count: isize) -> *const T {
- intrinsics::offset(self, count)
+ crate::intrinsics::offset(self, count)
}
}
#[lang = "mut_ptr"]
impl<T> *mut T {
pub unsafe fn offset(self, count: isize) -> *mut T {
- intrinsics::offset(self, count) as *mut T
+ crate::intrinsics::offset(self, count) as *mut T
}
}
}
diff --git a/gcc/testsuite/rust/compile/issue-1981.rs b/gcc/testsuite/rust/compile/issue-1981.rs
index bfd8d2c..de9588c 100644
--- a/gcc/testsuite/rust/compile/issue-1981.rs
+++ b/gcc/testsuite/rust/compile/issue-1981.rs
@@ -16,30 +16,30 @@ mod ptr {
#[lang = "const_ptr"]
impl<T> *const T {
pub unsafe fn offset(self, count: isize) -> *const T {
- intrinsics::offset(self, count)
+ crate::intrinsics::offset(self, count)
}
}
#[lang = "mut_ptr"]
impl<T> *mut T {
pub unsafe fn offset(self, count: isize) -> *mut T {
- intrinsics::offset(self, count) as *mut T
+ crate::intrinsics::offset(self, count) as *mut T
}
}
pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
let x = x as *mut u8;
let y = y as *mut u8;
- let len = mem::size_of::<T>() * count;
+ let len = crate::mem::size_of::<T>() * count;
swap_nonoverlapping_bytes(x, y, len)
}
pub unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
// For types smaller than the block optimization below,
// just swap directly to avoid pessimizing codegen.
- if mem::size_of::<T>() < 32 {
+ if crate::mem::size_of::<T>() < 32 {
let z = read(x);
- intrinsics::copy_nonoverlapping(y, x, 1);
+ crate::intrinsics::copy_nonoverlapping(y, x, 1);
write(y, z);
} else {
swap_nonoverlapping(x, y, 1);
@@ -47,12 +47,12 @@ mod ptr {
}
pub unsafe fn write<T>(dst: *mut T, src: T) {
- intrinsics::move_val_init(&mut *dst, src)
+ crate::intrinsics::move_val_init(&mut *dst, src)
}
pub unsafe fn read<T>(src: *const T) -> T {
- let mut tmp: T = mem::uninitialized();
- intrinsics::copy_nonoverlapping(src, &mut tmp, 1);
+ let mut tmp: T = crate::mem::uninitialized();
+ crate::intrinsics::copy_nonoverlapping(src, &mut tmp, 1);
tmp
}
@@ -60,7 +60,7 @@ mod ptr {
struct Block(u64, u64, u64, u64);
struct UnalignedBlock(u64, u64, u64, u64);
- let block_size = mem::size_of::<Block>();
+ let block_size = crate::mem::size_of::<Block>();
// Loop through x & y, copying them `Block` at a time
// The optimizer should unroll the loop fully for most types
@@ -69,31 +69,31 @@ mod ptr {
while i + block_size <= len {
// Create some uninitialized memory as scratch space
// Declaring `t` here avoids aligning the stack when this loop is unused
- let mut t: Block = mem::uninitialized();
+ let mut t: Block = crate::mem::uninitialized();
let t = &mut t as *mut _ as *mut u8;
let x = x.offset(i as isize);
let y = y.offset(i as isize);
// Swap a block of bytes of x & y, using t as a temporary buffer
// This should be optimized into efficient SIMD operations where available
- intrinsics::copy_nonoverlapping(x, t, block_size);
- intrinsics::copy_nonoverlapping(y, x, block_size);
- intrinsics::copy_nonoverlapping(t, y, block_size);
+ crate::intrinsics::copy_nonoverlapping(x, t, block_size);
+ crate::intrinsics::copy_nonoverlapping(y, x, block_size);
+ crate::intrinsics::copy_nonoverlapping(t, y, block_size);
i += block_size;
}
if i < len {
// Swap any remaining bytes
- let mut t: UnalignedBlock = mem::uninitialized();
+ let mut t: UnalignedBlock = crate::mem::uninitialized();
let rem = len - i;
let t = &mut t as *mut _ as *mut u8;
let x = x.offset(i as isize);
let y = y.offset(i as isize);
- intrinsics::copy_nonoverlapping(x, t, rem);
- intrinsics::copy_nonoverlapping(y, x, rem);
- intrinsics::copy_nonoverlapping(t, y, rem);
+ crate::intrinsics::copy_nonoverlapping(x, t, rem);
+ crate::intrinsics::copy_nonoverlapping(y, x, rem);
+ crate::intrinsics::copy_nonoverlapping(t, y, rem);
}
}
}
@@ -106,7 +106,7 @@ mod mem {
pub fn swap<T>(x: &mut T, y: &mut T) {
unsafe {
- ptr::swap_nonoverlapping_one(x, y);
+ crate::ptr::swap_nonoverlapping_one(x, y);
}
}
@@ -116,7 +116,7 @@ mod mem {
}
pub unsafe fn uninitialized<T>() -> T {
- intrinsics::uninit()
+ crate::intrinsics::uninit()
}
}
@@ -126,7 +126,7 @@ trait Step {
impl Step for i32 {
fn replace_zero(&mut self) -> Self {
- mem::replace(self, 0)
+ crate::mem::replace(self, 0)
}
}
diff --git a/gcc/testsuite/rust/compile/issue-2015.rs b/gcc/testsuite/rust/compile/issue-2015.rs
new file mode 100644
index 0000000..7789ecd
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2015.rs
@@ -0,0 +1,19 @@
+// { dg-additional-options "-frust-compile-until=lowering" }
+
+macro_rules! impl_foo {
+ () => { impl Foo }
+}
+
+pub trait Foo {}
+
+pub trait Bar {
+ type Baz;
+}
+
+pub fn foo(_value: impl Bar<Baz = impl_foo!()>) -> i32 {
+ 15
+}
+
+pub fn bar(_value: impl Bar<Baz = impl Foo>) -> i32 {
+ 16
+}
diff --git a/gcc/testsuite/rust/compile/issue-2035.rs b/gcc/testsuite/rust/compile/issue-2035.rs
new file mode 100644
index 0000000..c0817d5
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2035.rs
@@ -0,0 +1,10 @@
+fn func(i: i32) {
+ i();
+ // { dg-error "expected function, found .i32. .E0618." "" { target *-*-* } .-1 }
+}
+
+fn main() {
+ let i = 0i32;
+ i();
+ // { dg-error "expected function, found .i32. .E0618." "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/issue-2330.rs b/gcc/testsuite/rust/compile/issue-2330.rs
index 97c1503..6ab46c7 100644
--- a/gcc/testsuite/rust/compile/issue-2330.rs
+++ b/gcc/testsuite/rust/compile/issue-2330.rs
@@ -95,30 +95,30 @@ mod ptr {
#[lang = "const_ptr"]
impl<T> *const T {
pub unsafe fn offset(self, count: isize) -> *const T {
- intrinsics::offset(self, count)
+ crate::intrinsics::offset(self, count)
}
}
#[lang = "mut_ptr"]
impl<T> *mut T {
pub unsafe fn offset(self, count: isize) -> *mut T {
- intrinsics::offset(self, count) as *mut T
+ crate::intrinsics::offset(self, count) as *mut T
}
}
pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
let x = x as *mut u8;
let y = y as *mut u8;
- let len = mem::size_of::<T>() * count;
+ let len = crate::mem::size_of::<T>() * count;
swap_nonoverlapping_bytes(x, y, len)
}
pub unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
// For types smaller than the block optimization below,
// just swap directly to avoid pessimizing codegen.
- if mem::size_of::<T>() < 32 {
+ if crate::mem::size_of::<T>() < 32 {
let z = read(x);
- intrinsics::copy_nonoverlapping(y, x, 1);
+ crate::intrinsics::copy_nonoverlapping(y, x, 1);
write(y, z);
} else {
swap_nonoverlapping(x, y, 1);
@@ -126,12 +126,12 @@ mod ptr {
}
pub unsafe fn write<T>(dst: *mut T, src: T) {
- intrinsics::move_val_init(&mut *dst, src)
+ crate::intrinsics::move_val_init(&mut *dst, src)
}
pub unsafe fn read<T>(src: *const T) -> T {
- let mut tmp: T = mem::uninitialized();
- intrinsics::copy_nonoverlapping(src, &mut tmp, 1);
+ let mut tmp: T = crate::mem::uninitialized();
+ crate::intrinsics::copy_nonoverlapping(src, &mut tmp, 1);
tmp
}
@@ -139,7 +139,7 @@ mod ptr {
struct Block(u64, u64, u64, u64);
struct UnalignedBlock(u64, u64, u64, u64);
- let block_size = mem::size_of::<Block>();
+ let block_size = crate::mem::size_of::<Block>();
// Loop through x & y, copying them `Block` at a time
// The optimizer should unroll the loop fully for most types
@@ -148,31 +148,31 @@ mod ptr {
while i + block_size <= len {
// Create some uninitialized memory as scratch space
// Declaring `t` here avoids aligning the stack when this loop is unused
- let mut t: Block = mem::uninitialized();
+ let mut t: Block = crate::mem::uninitialized();
let t = &mut t as *mut _ as *mut u8;
let x = x.offset(i as isize);
let y = y.offset(i as isize);
// Swap a block of bytes of x & y, using t as a temporary buffer
// This should be optimized into efficient SIMD operations where available
- intrinsics::copy_nonoverlapping(x, t, block_size);
- intrinsics::copy_nonoverlapping(y, x, block_size);
- intrinsics::copy_nonoverlapping(t, y, block_size);
+ crate::intrinsics::copy_nonoverlapping(x, t, block_size);
+ crate::intrinsics::copy_nonoverlapping(y, x, block_size);
+ crate::intrinsics::copy_nonoverlapping(t, y, block_size);
i += block_size;
}
if i < len {
// Swap any remaining bytes
- let mut t: UnalignedBlock = mem::uninitialized();
+ let mut t: UnalignedBlock = crate::mem::uninitialized();
let rem = len - i;
let t = &mut t as *mut _ as *mut u8;
let x = x.offset(i as isize);
let y = y.offset(i as isize);
- intrinsics::copy_nonoverlapping(x, t, rem);
- intrinsics::copy_nonoverlapping(y, x, rem);
- intrinsics::copy_nonoverlapping(t, y, rem);
+ crate::intrinsics::copy_nonoverlapping(x, t, rem);
+ crate::intrinsics::copy_nonoverlapping(y, x, rem);
+ crate::intrinsics::copy_nonoverlapping(t, y, rem);
}
}
}
@@ -185,7 +185,7 @@ mod mem {
pub fn swap<T>(x: &mut T, y: &mut T) {
unsafe {
- ptr::swap_nonoverlapping_one(x, y);
+ crate::ptr::swap_nonoverlapping_one(x, y);
}
}
@@ -195,6 +195,6 @@ mod mem {
}
pub unsafe fn uninitialized<T>() -> T {
- intrinsics::uninit()
+ crate::intrinsics::uninit()
}
}
diff --git a/gcc/testsuite/rust/compile/issue-2369.rs b/gcc/testsuite/rust/compile/issue-2369.rs
new file mode 100644
index 0000000..9475aef
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2369.rs
@@ -0,0 +1,21 @@
+#[lang = "sized"]
+trait Sized {}
+
+fn main() {
+ pub trait Foo {
+ type A;
+ fn boo(&self) -> <Self as Foo>::A;
+ }
+
+ struct Bar;
+
+ impl Foo for isize {
+ type A = usize;
+ fn boo(&self) -> usize {
+ 42
+ }
+ }
+
+ fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
+ // { dg-error "associated type bindings are not allowed here .E0229." "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/issue-2423.rs b/gcc/testsuite/rust/compile/issue-2423.rs
index ae7897c..6fcd32f 100644
--- a/gcc/testsuite/rust/compile/issue-2423.rs
+++ b/gcc/testsuite/rust/compile/issue-2423.rs
@@ -1,14 +1,14 @@
impl NonExistant {
- // { dg-error "failed to resolve" "" { target *-*-* } .-1 }
+ // { dg-error "could not resolve" "" { target *-*-* } .-1 }
fn test() {}
}
impl NotFound for NonExistant {
- // { dg-error "failed to resolve" "" { target *-*-* } .-1 }
+ // { dg-error "could not resolve" "" { target *-*-* } .-1 }
fn test() {}
}
trait A {}
impl A for NotFound {}
-// { dg-error "failed to resolve" "" { target *-*-* } .-1 }
+// { dg-error "could not resolve" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/rust/compile/issue-2905-2.rs b/gcc/testsuite/rust/compile/issue-2905-2.rs
index 83c54ed..1c9516d 100644
--- a/gcc/testsuite/rust/compile/issue-2905-2.rs
+++ b/gcc/testsuite/rust/compile/issue-2905-2.rs
@@ -17,10 +17,10 @@ pub mod core {
}
pub mod slice {
- use core::marker::PhantomData;
- use core::option::Option;
+ use crate::core::marker::PhantomData;
+ use crate::core::option::Option;
- impl<T> core::iter::IntoIterator for &[T] {
+ impl<T> crate::core::iter::IntoIterator for &[T] {
type Item = &T;
type IntoIter = Weird<T>;
@@ -108,7 +108,7 @@ pub mod core {
}
pub mod iter {
- use option::Option;
+ use crate::core::option::Option;
pub trait IntoIterator {
type Item;
diff --git a/gcc/testsuite/rust/compile/issue-2954.rs b/gcc/testsuite/rust/compile/issue-2954.rs
new file mode 100644
index 0000000..52f7c91
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2954.rs
@@ -0,0 +1,17 @@
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "receiver"]
+#[unstable(feature = "receiver_trait", issue = "none")]
+// #[doc(hidden)]
+pub trait Receiver {
+ // Empty.
+}
+
+#[unstable(feature = "receiver_trait", issue = "none")]
+impl<T: ?Sized> Receiver for &T {}
+
+#[unstable(feature = "receiver_trait", issue = "none")]
+impl<T: ?Sized> Receiver for &mut T {}
+
+
diff --git a/gcc/testsuite/rust/compile/issue-3022.rs b/gcc/testsuite/rust/compile/issue-3022.rs
new file mode 100644
index 0000000..b8b8e6f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3022.rs
@@ -0,0 +1,18 @@
+#[lang = "sized"]
+trait Sized {}
+
+trait Foo<T> {
+ fn foo(self) -> T;
+}
+
+struct Bar<T, U> {
+ // { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+ value: U,
+ valte: T,
+}
+
+impl<T: Foo<U>, U> Foo<U> for Bar<T, U> {
+ fn foo(self) -> U {
+ self.value
+ }
+}
diff --git a/gcc/testsuite/rust/compile/issue-3031.rs b/gcc/testsuite/rust/compile/issue-3031.rs
new file mode 100644
index 0000000..33f5bf0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3031.rs
@@ -0,0 +1,15 @@
+#![feature(no_core)]
+#![feature(lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+trait A<T: ?Sized> {}
+
+struct Cell<X> {
+ // { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+ x: X,
+}
+
+impl<T, U> A<Cell<U>> for Cell<T> where T: A<U> {}
diff --git a/gcc/testsuite/rust/compile/issue-3174.rs b/gcc/testsuite/rust/compile/issue-3174.rs
new file mode 100644
index 0000000..87588e1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3174.rs
@@ -0,0 +1,28 @@
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+enum Option {
+ Some(i32),
+ None,
+}
+
+impl Option {
+ fn add(&mut self) {
+ match *self {
+ Option::Some(ref mut a) => *a += 1,
+ Option::None => {}
+ }
+ }
+}
+
+fn main() {
+ unsafe {
+ let mut a = Option::None;
+ a.add();
+ let _s = "%d\n\0";
+ let _s = _s as *const str;
+ let s = _s as *const i8;
+ printf(s, a);
+ }
+}
diff --git a/gcc/testsuite/rust/compile/issue-3242.rs b/gcc/testsuite/rust/compile/issue-3242.rs
index 468497a..a4542aea0 100644
--- a/gcc/testsuite/rust/compile/issue-3242.rs
+++ b/gcc/testsuite/rust/compile/issue-3242.rs
@@ -1,5 +1,4 @@
#[lang = "sized"]
-// { dg-skip-if "" { *-*-* } }
pub trait Sized {}
trait Foo<T> {
diff --git a/gcc/testsuite/rust/compile/issue-3315-1.rs b/gcc/testsuite/rust/compile/issue-3315-1.rs
new file mode 100644
index 0000000..07581da
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3315-1.rs
@@ -0,0 +1,8 @@
+//You should be able to create a module of the same name as a builtin type
+
+mod i32 {
+}
+
+fn main() -> isize {
+ 0
+}
diff --git a/gcc/testsuite/rust/compile/issue-3315-2.rs b/gcc/testsuite/rust/compile/issue-3315-2.rs
new file mode 100644
index 0000000..71abd6c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3315-2.rs
@@ -0,0 +1,7 @@
+mod i32 {
+}
+
+fn main() -> isize {
+ let i:i32 = 0 as i32;
+ i as isize
+}
diff --git a/gcc/testsuite/rust/compile/issue-3382.rs b/gcc/testsuite/rust/compile/issue-3382.rs
new file mode 100644
index 0000000..6f4382f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3382.rs
@@ -0,0 +1,61 @@
+#[lang = "sized"]
+trait Sized {}
+
+enum Result<T, E> {
+ #[lang = "Ok"]
+ Ok(T),
+ #[lang = "Err"]
+ Err(E),
+}
+
+#[lang = "try"]
+pub trait Try {
+ /// The type of this value when viewed as successful.
+ // #[unstable(feature = "try_trait", issue = "42327")]
+ type Ok;
+ /// The type of this value when viewed as failed.
+ // #[unstable(feature = "try_trait", issue = "42327")]
+ type Error;
+
+ /// Applies the "?" operator. A return of `Ok(t)` means that the
+ /// execution should continue normally, and the result of `?` is the
+ /// value `t`. A return of `Err(e)` means that execution should branch
+ /// to the innermost enclosing `catch`, or return from the function.
+ ///
+ /// If an `Err(e)` result is returned, the value `e` will be "wrapped"
+ /// in the return type of the enclosing scope (which must itself implement
+ /// `Try`). Specifically, the value `X::from_error(From::from(e))`
+ /// is returned, where `X` is the return type of the enclosing function.
+ #[lang = "into_result"]
+ #[unstable(feature = "try_trait", issue = "42327")]
+ fn into_result(self) -> Result<Self::Ok, Self::Error>;
+
+ /// Wrap an error value to construct the composite result. For example,
+ /// `Result::Err(x)` and `Result::from_error(x)` are equivalent.
+ #[lang = "from_error"]
+ #[unstable(feature = "try_trait", issue = "42327")]
+ fn from_error(v: Self::Ok) -> Self;
+
+ /// Wrap an OK value to construct the composite result. For example,
+ /// `Result::Ok(x)` and `Result::from_ok(x)` are equivalent.
+ #[lang = "from_ok"]
+ #[unstable(feature = "try_trait", issue = "42327")]
+ fn from_ok(v: Self::Error) -> Self;
+}
+
+impl<T, E> Try for Result<T, E> {
+ type Ok = T;
+ type Error = E;
+
+ fn into_result(self) -> Result<T, E> {
+ self
+ }
+
+ fn from_ok(v: T) -> Self {
+ Result::Ok(v)
+ }
+
+ fn from_error(v: E) -> Self {
+ Result::Err(v)
+ }
+}
diff --git a/gcc/testsuite/rust/compile/issue-3402-1.rs b/gcc/testsuite/rust/compile/issue-3402-1.rs
new file mode 100644
index 0000000..ed603ce
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3402-1.rs
@@ -0,0 +1,29 @@
+pub struct Foo {
+ a: i32,
+ // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+pub struct Bar(i32);
+
+#[lang = "sized"]
+trait Sized {}
+
+pub mod core {
+ pub mod default {
+ pub trait Default: Sized {
+ fn default() -> Self;
+ }
+
+ impl Default for i32 {
+ fn default() -> Self {
+ 0
+ }
+ }
+ }
+}
+
+impl ::core::default::Default for Bar {
+ #[inline]
+ fn default() -> Bar {
+ Bar(core::default::Default::default())
+ }
+}
diff --git a/gcc/testsuite/rust/compile/issue-3402-2.rs b/gcc/testsuite/rust/compile/issue-3402-2.rs
new file mode 100644
index 0000000..b665af2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3402-2.rs
@@ -0,0 +1,18 @@
+pub struct Bar(i32);
+
+#[lang = "sized"]
+trait Sized {}
+
+pub trait A: Sized {
+ fn foo() -> Self;
+}
+
+impl A for i32 {
+ fn foo() -> Self {
+ 0
+ }
+}
+
+pub fn bar() {
+ let _ = Bar(A::foo());
+}
diff --git a/gcc/testsuite/rust/compile/issue-3403.rs b/gcc/testsuite/rust/compile/issue-3403.rs
new file mode 100644
index 0000000..ced6b4e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3403.rs
@@ -0,0 +1,38 @@
+pub struct Foo {
+ a: i32,
+ // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+pub struct Bar(i32);
+
+#[lang = "sized"]
+trait Sized {}
+
+pub mod core {
+ pub mod default {
+ pub trait Default: Sized {
+ fn default() -> Self;
+ }
+
+ impl Default for i32 {
+ fn default() -> Self {
+ 0
+ }
+ }
+ }
+}
+
+impl ::core::default::Default for Bar {
+ #[inline]
+ fn default() -> Bar {
+ Bar(core::default::Default::default())
+ }
+}
+
+impl ::core::default::Default for Foo {
+ #[inline]
+ fn default() -> Foo {
+ Foo {
+ a: core::default::Default::default(),
+ }
+ }
+}
diff --git a/gcc/testsuite/rust/compile/issue-3541-1.rs b/gcc/testsuite/rust/compile/issue-3541-1.rs
new file mode 100644
index 0000000..6b47b7e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3541-1.rs
@@ -0,0 +1,5 @@
+impl B for u32 {
+ const BAR: i32; // { dg-error "associated constant in .impl." }
+}
+
+trait B {}
diff --git a/gcc/testsuite/rust/compile/issue-3541-2.rs b/gcc/testsuite/rust/compile/issue-3541-2.rs
new file mode 100644
index 0000000..9f17eed
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3541-2.rs
@@ -0,0 +1,3 @@
+trait B {
+ const BAR: i32;
+}
diff --git a/gcc/testsuite/rust/compile/issue-3549.rs b/gcc/testsuite/rust/compile/issue-3549.rs
new file mode 100644
index 0000000..cedbb5a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3549.rs
@@ -0,0 +1,3 @@
+fn main() {
+ r#""#;
+}
diff --git a/gcc/testsuite/rust/compile/issue-3552.rs b/gcc/testsuite/rust/compile/issue-3552.rs
new file mode 100644
index 0000000..9a4451b14b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3552.rs
@@ -0,0 +1,14 @@
+trait Foo {
+ const BAR: u32;
+}
+
+const TRAIT_REF_BAR: u32 = <Foo>::BAR;
+// { dg-error "no default expression on trait constant" "" { target *-*-* } .-1 }
+
+struct GlobalTraitRef;
+
+impl Foo for GlobalTraitRef {
+ const BAR: u32 = TRAIT_REF_BAR;
+}
+
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/issue-3553.rs b/gcc/testsuite/rust/compile/issue-3553.rs
new file mode 100644
index 0000000..546f3c1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3553.rs
@@ -0,0 +1,18 @@
+trait Foo {
+ fn f(&self) -> isize;
+}
+
+trait Bar: Foo {
+ fn g(&self) -> isize;
+}
+
+struct A {
+ x: isize,
+}
+
+impl Bar for A {
+ // { dg-error "the trait bound .A: Foo. is not satisfied .E0277." "" { target *-*-* } .-1 }
+ fn g(&self) -> isize {
+ self.f()
+ }
+}
diff --git a/gcc/testsuite/rust/compile/issue-3554-1.rs b/gcc/testsuite/rust/compile/issue-3554-1.rs
new file mode 100644
index 0000000..a66be35
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3554-1.rs
@@ -0,0 +1,8 @@
+trait Tr {
+ fn foo();
+
+ fn bar(&self) {
+ self.foo()
+ // { dg-error "no method named .foo. found in the current scope .E0599." "" { target *-*-* } .-1 }
+ }
+}
diff --git a/gcc/testsuite/rust/compile/issue-3554-2.rs b/gcc/testsuite/rust/compile/issue-3554-2.rs
new file mode 100644
index 0000000..e455a8b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3554-2.rs
@@ -0,0 +1,18 @@
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "fn_once"]
+pub trait FnOnce<Args> {
+ #[lang = "fn_once_output"]
+ type Output;
+
+ extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
+trait Tr {
+ fn foo();
+
+ fn bar(&self) {
+ (|| self.foo())()
+ // { dg-error "no method named .foo. found in the current scope .E0599." "" { target *-*-* } .-1 }
+ }
+}
diff --git a/gcc/testsuite/rust/compile/issue-3563.rs b/gcc/testsuite/rust/compile/issue-3563.rs
new file mode 100644
index 0000000..46e7624
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3563.rs
@@ -0,0 +1,17 @@
+pub struct AA {
+ pub data: [u8; 10],
+}
+
+impl AA {
+ pub const fn new() -> Self {
+ let mut res: AA = AA { data: [0; 10] };
+ res.data[0] = 5;
+ res
+ }
+}
+
+static mut BB: AA = AA::new();
+
+fn main() {
+ let _ptr = unsafe { &mut BB };
+}
diff --git a/gcc/testsuite/rust/compile/issue-3566-1.rs b/gcc/testsuite/rust/compile/issue-3566-1.rs
new file mode 100644
index 0000000..b7e5be0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3566-1.rs
@@ -0,0 +1,8 @@
+mod a {
+ pub mod b {
+
+ pub fn f(x: [u8; { 100 }]) -> [u8; { 100 }] {
+ x
+ }
+ }
+}
diff --git a/gcc/testsuite/rust/compile/issue-3566-2.rs b/gcc/testsuite/rust/compile/issue-3566-2.rs
new file mode 100644
index 0000000..3f3ea73
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3566-2.rs
@@ -0,0 +1,22 @@
+// run-pass
+
+#![allow(H8)]
+#![allow(dead_code)]
+
+
+// pretty-expanded FIXME #23616
+
+mod a {
+ pub mod b {
+ pub type t = isize;
+
+ pub fn f(x: [u8; { let s = 17; 100 }]) -> [u8; { let z = 18; 100 }] {
+ //~^ WARN unused variable: `s`
+ //~| WARN unused variable: `z`
+ x
+}
+ }
+}
+
+pub fn main() { //~ ERROR cannot move out
+ }
diff --git a/gcc/testsuite/rust/compile/issue-3567.rs b/gcc/testsuite/rust/compile/issue-3567.rs
new file mode 100644
index 0000000..021d9c2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3567.rs
@@ -0,0 +1,4 @@
+fn main() {
+ let _: &[i8] = &[i8];
+ // { dg-error "expected value .E0423." "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/issue-3568.rs b/gcc/testsuite/rust/compile/issue-3568.rs
new file mode 100644
index 0000000..222a174
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3568.rs
@@ -0,0 +1,7 @@
+pub type T = ();
+mod foo {
+ pub use super::T;
+}
+
+pub use foo::super::foo::S as T;
+// { dg-error ".super. can only be used in start position" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/rust/compile/issue-3588.rs b/gcc/testsuite/rust/compile/issue-3588.rs
new file mode 100644
index 0000000..744d967
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3588.rs
@@ -0,0 +1,5 @@
+const FOO: i32 = if true { [1, 2, 3] } else { [2, 3, 4] }[0];
+
+pub fn test() -> i32 {
+ FOO
+}
diff --git a/gcc/testsuite/rust/compile/issue-3605.rs b/gcc/testsuite/rust/compile/issue-3605.rs
new file mode 100644
index 0000000..05e6e48
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3605.rs
@@ -0,0 +1,5 @@
+enum Foo<'a> {}
+
+enum Bar<'a> {
+ in_band_def_explicit_impl(Foo<'a>),
+}
diff --git a/gcc/testsuite/rust/compile/issue-3606.rs b/gcc/testsuite/rust/compile/issue-3606.rs
new file mode 100644
index 0000000..73b0bd6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3606.rs
@@ -0,0 +1,6 @@
+// { dg-options "-w" }
+#[repr()]
+pub struct Coord {
+ x: u32,
+ y: u32,
+}
diff --git a/gcc/testsuite/rust/compile/issue-3613.rs b/gcc/testsuite/rust/compile/issue-3613.rs
new file mode 100644
index 0000000..f2e1092
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3613.rs
@@ -0,0 +1,18 @@
+mod m1 {
+ pub enum Baz4 {
+ foo1,
+ foo2,
+ }
+}
+
+fn bar(x: m1::foo) {
+ // { dg-error "unknown reference for resolved name: .foo." "" { target *-*-* } .-1 }
+ match x {
+ m1::foo::foo1 => {}
+ // { dg-error "failed to type resolve root segment" "" { target *-*-* } .-1 }
+ m1::NodePosition::foo2 => {}
+ // { dg-error "failed to type resolve root segment" "" { target *-*-* } .-1 }
+ }
+}
+
+pub fn main() {}
diff --git a/gcc/testsuite/rust/compile/issue-3614.rs b/gcc/testsuite/rust/compile/issue-3614.rs
new file mode 100644
index 0000000..350a7e4
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3614.rs
@@ -0,0 +1,3 @@
+#[repr] // { dg-error "malformed .repr. attribute" }
+
+struct _B {}
diff --git a/gcc/testsuite/rust/compile/issue-3615.rs b/gcc/testsuite/rust/compile/issue-3615.rs
new file mode 100644
index 0000000..e5c5072
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3615.rs
@@ -0,0 +1,7 @@
+pub trait Trait {
+ pub fn nrvo(init: fn()) -> [u8; 4096] {
+ let mut buf = [0; 4096];
+
+ buf
+ }
+}
diff --git a/gcc/testsuite/rust/compile/iterators1.rs b/gcc/testsuite/rust/compile/iterators1.rs
index 1141758..2ea3d74 100644
--- a/gcc/testsuite/rust/compile/iterators1.rs
+++ b/gcc/testsuite/rust/compile/iterators1.rs
@@ -98,30 +98,30 @@ mod ptr {
#[lang = "const_ptr"]
impl<T> *const T {
pub unsafe fn offset(self, count: isize) -> *const T {
- intrinsics::offset(self, count)
+ crate::intrinsics::offset(self, count)
}
}
#[lang = "mut_ptr"]
impl<T> *mut T {
pub unsafe fn offset(self, count: isize) -> *mut T {
- intrinsics::offset(self, count) as *mut T
+ crate::intrinsics::offset(self, count) as *mut T
}
}
pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
let x = x as *mut u8;
let y = y as *mut u8;
- let len = mem::size_of::<T>() * count;
+ let len = crate::mem::size_of::<T>() * count;
swap_nonoverlapping_bytes(x, y, len)
}
pub unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
// For types smaller than the block optimization below,
// just swap directly to avoid pessimizing codegen.
- if mem::size_of::<T>() < 32 {
+ if crate::mem::size_of::<T>() < 32 {
let z = read(x);
- intrinsics::copy_nonoverlapping(y, x, 1);
+ crate::intrinsics::copy_nonoverlapping(y, x, 1);
write(y, z);
} else {
swap_nonoverlapping(x, y, 1);
@@ -129,12 +129,12 @@ mod ptr {
}
pub unsafe fn write<T>(dst: *mut T, src: T) {
- intrinsics::move_val_init(&mut *dst, src)
+ crate::intrinsics::move_val_init(&mut *dst, src)
}
pub unsafe fn read<T>(src: *const T) -> T {
- let mut tmp: T = mem::uninitialized();
- intrinsics::copy_nonoverlapping(src, &mut tmp, 1);
+ let mut tmp: T = crate::mem::uninitialized();
+ crate::intrinsics::copy_nonoverlapping(src, &mut tmp, 1);
tmp
}
@@ -142,7 +142,7 @@ mod ptr {
struct Block(u64, u64, u64, u64);
struct UnalignedBlock(u64, u64, u64, u64);
- let block_size = mem::size_of::<Block>();
+ let block_size = crate::mem::size_of::<Block>();
// Loop through x & y, copying them `Block` at a time
// The optimizer should unroll the loop fully for most types
@@ -151,31 +151,31 @@ mod ptr {
while i + block_size <= len {
// Create some uninitialized memory as scratch space
// Declaring `t` here avoids aligning the stack when this loop is unused
- let mut t: Block = mem::uninitialized();
+ let mut t: Block = crate::mem::uninitialized();
let t = &mut t as *mut _ as *mut u8;
let x = x.offset(i as isize);
let y = y.offset(i as isize);
// Swap a block of bytes of x & y, using t as a temporary buffer
// This should be optimized into efficient SIMD operations where available
- intrinsics::copy_nonoverlapping(x, t, block_size);
- intrinsics::copy_nonoverlapping(y, x, block_size);
- intrinsics::copy_nonoverlapping(t, y, block_size);
+ crate::intrinsics::copy_nonoverlapping(x, t, block_size);
+ crate::intrinsics::copy_nonoverlapping(y, x, block_size);
+ crate::intrinsics::copy_nonoverlapping(t, y, block_size);
i += block_size;
}
if i < len {
// Swap any remaining bytes
- let mut t: UnalignedBlock = mem::uninitialized();
+ let mut t: UnalignedBlock = crate::mem::uninitialized();
let rem = len - i;
let t = &mut t as *mut _ as *mut u8;
let x = x.offset(i as isize);
let y = y.offset(i as isize);
- intrinsics::copy_nonoverlapping(x, t, rem);
- intrinsics::copy_nonoverlapping(y, x, rem);
- intrinsics::copy_nonoverlapping(t, y, rem);
+ crate::intrinsics::copy_nonoverlapping(x, t, rem);
+ crate::intrinsics::copy_nonoverlapping(y, x, rem);
+ crate::intrinsics::copy_nonoverlapping(t, y, rem);
}
}
}
@@ -190,7 +190,7 @@ mod mem {
pub fn swap<T>(x: &mut T, y: &mut T) {
unsafe {
- ptr::swap_nonoverlapping_one(x, y);
+ crate::ptr::swap_nonoverlapping_one(x, y);
}
}
@@ -200,7 +200,7 @@ mod mem {
}
pub unsafe fn uninitialized<T>() -> T {
- intrinsics::uninit()
+ crate::intrinsics::uninit()
}
}
@@ -210,30 +210,30 @@ macro_rules! impl_uint {
impl $ty {
pub fn wrapping_add(self, rhs: Self) -> Self {
unsafe {
- intrinsics::wrapping_add(self, rhs)
+ crate::intrinsics::wrapping_add(self, rhs)
}
}
pub fn wrapping_sub(self, rhs: Self) -> Self {
unsafe {
- intrinsics::wrapping_sub(self, rhs)
+ crate::intrinsics::wrapping_sub(self, rhs)
}
}
pub fn rotate_left(self, n: u32) -> Self {
unsafe {
- intrinsics::rotate_left(self, n as Self)
+ crate::intrinsics::rotate_left(self, n as Self)
}
}
pub fn rotate_right(self, n: u32) -> Self {
unsafe {
- intrinsics::rotate_right(self, n as Self)
+ crate::intrinsics::rotate_right(self, n as Self)
}
}
- pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
- unsafe { mem::transmute(bytes) }
+ pub const fn from_ne_bytes(bytes: [u8; crate::mem::size_of::<Self>()]) -> Self {
+ unsafe { crate::mem::transmute(bytes) }
}
pub fn checked_add(self, rhs: Self) -> Option<Self> {
@@ -246,7 +246,7 @@ macro_rules! impl_uint {
}
pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
- let (a, b) = unsafe { intrinsics::add_with_overflow(self as $ty, rhs as $ty) };
+ let (a, b) = unsafe { crate::intrinsics::add_with_overflow(self as $ty, rhs as $ty) };
(a as Self, b)
}
}
@@ -362,12 +362,12 @@ macro_rules! step_identical_methods {
() => {
#[inline]
fn replace_one(&mut self) -> Self {
- mem::replace(self, 1)
+ crate::mem::replace(self, 1)
}
#[inline]
fn replace_zero(&mut self) -> Self {
- mem::replace(self, 0)
+ crate::mem::replace(self, 0)
}
#[inline]
@@ -482,7 +482,7 @@ impl<A: Step> Iterator for Range<A> {
// and this won't actually result in an extra check in an optimized build.
match self.start.add_usize(1) {
Option::Some(mut n) => {
- mem::swap(&mut n, &mut self.start);
+ crate::mem::swap(&mut n, &mut self.start);
Option::Some(n)
}
Option::None => Option::None,
diff --git a/gcc/testsuite/rust/compile/macros/builtin/option_env1.rs b/gcc/testsuite/rust/compile/macros/builtin/option_env1.rs
new file mode 100644
index 0000000..cf9f65b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macros/builtin/option_env1.rs
@@ -0,0 +1,29 @@
+#![feature(rustc_attrs)]
+
+#[rustc_builtin_macro]
+macro_rules! option_env {
+ () => {}
+}
+
+#[lang = "sized"]
+trait Sized {}
+
+pub mod core {
+ pub mod option {
+ pub enum Option<T> {
+ #[lang = "Some"]
+ Some(T),
+ #[lang = "None"]
+ None,
+ }
+ }
+}
+
+use core::option::Option;
+
+
+fn main() {
+ // Both a guaranteed-to-exist variable and a failed find should compile
+ let _: Option<&str> = option_env!("PWD");
+ let _: Option<&str> = option_env!("PROBABLY_DOESNT_EXIST");
+}
diff --git a/gcc/testsuite/rust/compile/macros/builtin/option_env2.rs b/gcc/testsuite/rust/compile/macros/builtin/option_env2.rs
new file mode 100644
index 0000000..63f72545
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macros/builtin/option_env2.rs
@@ -0,0 +1,27 @@
+#![feature(rustc_attrs)]
+
+#[rustc_builtin_macro]
+macro_rules! option_env {
+ () => {}
+}
+
+#[lang = "sized"]
+trait Sized {}
+
+pub mod core {
+ pub mod option {
+ pub enum Option<T> {
+ #[lang = "Some"]
+ Some(T),
+ #[lang = "None"]
+ None,
+ }
+ }
+}
+
+use core::option::Option;
+
+fn main() {
+ let _: Option<&str> = option_env!(42);
+ // { dg-error "argument must be a string literal" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/macros/builtin/option_env3.rs b/gcc/testsuite/rust/compile/macros/builtin/option_env3.rs
new file mode 100644
index 0000000..ad6dd4c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macros/builtin/option_env3.rs
@@ -0,0 +1,28 @@
+#![feature(rustc_attrs)]
+
+#[rustc_builtin_macro]
+macro_rules! option_env {
+ () => {}
+}
+
+#[lang = "sized"]
+trait Sized {}
+
+pub mod core {
+ pub mod option {
+ pub enum Option<T> {
+ #[lang = "Some"]
+ Some(T),
+ #[lang = "None"]
+ None,
+ }
+ }
+}
+
+use core::option::Option;
+
+
+fn main() {
+ let _: Option<&str> = option_env!("A","B");
+ // { dg-error "'option_env!' takes 1 argument" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/macros/mbe/macro-expand-module.rs b/gcc/testsuite/rust/compile/macros/mbe/macro-expand-module.rs
new file mode 100644
index 0000000..e3e702e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macros/mbe/macro-expand-module.rs
@@ -0,0 +1,11 @@
+mod foo {
+ macro_rules! bar {
+ () => ()
+ }
+
+ bar! ();
+
+ pub struct S;
+}
+
+pub fn buzz(_: foo::S) {}
diff --git a/gcc/testsuite/rust/compile/macros/mbe/macro43.rs b/gcc/testsuite/rust/compile/macros/mbe/macro43.rs
index 992bc77..0a7f038 100644
--- a/gcc/testsuite/rust/compile/macros/mbe/macro43.rs
+++ b/gcc/testsuite/rust/compile/macros/mbe/macro43.rs
@@ -1,3 +1,10 @@
+use Option::{None, Some};
+
+enum Option<T> {
+ None,
+ Some(T)
+}
+
macro_rules! nonzero_integers {
( $( $Ty: ident($Int: ty); )+ ) => {
$(
@@ -14,7 +21,7 @@ macro_rules! nonzero_integers {
// not all derive macros are implemented yet, and this test does not test these anyways
// #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(transparent)]
- pub struct $Ty(NonZero<$Int>);
+ pub struct $Ty($Int);
impl $Ty {
/// Create a non-zero without checking the value.
@@ -25,7 +32,7 @@ macro_rules! nonzero_integers {
#[stable(feature = "nonzero", since = "1.28.0")]
#[inline]
pub const unsafe fn new_unchecked(n: $Int) -> Self {
- $Ty(NonZero(n))
+ $Ty(n)
}
/// Create a non-zero if the given value is not zero.
@@ -33,7 +40,7 @@ macro_rules! nonzero_integers {
#[inline]
pub fn new(n: $Int) -> Option<Self> {
if n != 0 {
- Some($Ty(NonZero(n)))
+ Some($Ty(n))
} else {
None
}
@@ -43,12 +50,12 @@ macro_rules! nonzero_integers {
#[stable(feature = "nonzero", since = "1.28.0")]
#[inline]
pub fn get(self) -> $Int {
- self.0 .0
+ self.0
}
}
- impl_nonzero_fmt! { // { dg-error "unknown macro" }
+ impl_nonzero_fmt! { // { dg-error "could not resolve macro invocation" }
(Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty
}
)+
diff --git a/gcc/testsuite/rust/compile/macros/mbe/macro44.rs b/gcc/testsuite/rust/compile/macros/mbe/macro44.rs
index dabac6f..0cfd987 100644
--- a/gcc/testsuite/rust/compile/macros/mbe/macro44.rs
+++ b/gcc/testsuite/rust/compile/macros/mbe/macro44.rs
@@ -16,7 +16,7 @@ mod foo {
}
fn bar_f() {
- baz!(); // { dg-error "unknown macro" }
+ baz!(); // { dg-error "could not resolve macro invocation" }
}
}
diff --git a/gcc/testsuite/rust/compile/method2.rs b/gcc/testsuite/rust/compile/method2.rs
index c8699f7..961a039 100644
--- a/gcc/testsuite/rust/compile/method2.rs
+++ b/gcc/testsuite/rust/compile/method2.rs
@@ -12,5 +12,5 @@ fn main() {
let b;
b = a.test::<asfasfr>(false);
- // { dg-error "failed to resolve TypePath: asfasfr" "" { target *-*-* } .-1 }
+ // { dg-error "could not resolve type path .asfasfr." "" { target *-*-* } .-1 }
}
diff --git a/gcc/testsuite/rust/compile/nested_macro_use2.rs b/gcc/testsuite/rust/compile/nested_macro_use2.rs
index 4659500..7bb6154 100644
--- a/gcc/testsuite/rust/compile/nested_macro_use2.rs
+++ b/gcc/testsuite/rust/compile/nested_macro_use2.rs
@@ -8,5 +8,5 @@ mod foo {
}
fn main() {
- baz!(); // { dg-error "unknown macro: .baz." }
+ baz!(); // { dg-error "could not resolve macro invocation .baz." }
}
diff --git a/gcc/testsuite/rust/compile/nr2/compile.exp b/gcc/testsuite/rust/compile/nr2/compile.exp
index f2724f6..35637f1 100644
--- a/gcc/testsuite/rust/compile/nr2/compile.exp
+++ b/gcc/testsuite/rust/compile/nr2/compile.exp
@@ -14,9 +14,7 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# Compile tests, no torture testing, for name resolution 2.0
-#
-# These tests raise errors in the front end; torture testing doesn't apply.
+# Run compile tests with name resolution 2.0 enabled
# Load support procs.
load_lib rust-dg.exp
@@ -44,7 +42,7 @@ namespace eval rust-nr2-ns {
# Run tests in directories
# Manually specifying these, in case some other test file
# does something weird
- set test_dirs {{} {macros builtin} {macros mbe} {macros proc}}
+ set test_dirs {{} {macros builtin} {macros mbe} {macros proc} {torture}}
set tests_expect_ok ""
set tests_expect_err ""
diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude
index 60322f3..19bf6f8 100644
--- a/gcc/testsuite/rust/compile/nr2/exclude
+++ b/gcc/testsuite/rust/compile/nr2/exclude
@@ -1,154 +1,33 @@
-bounds1.rs
-break-rust2.rs
-break-rust3.rs
canonical_paths1.rs
cfg1.rs
-cfg3.rs
-cfg4.rs
-cfg5.rs
-closure_no_type_anno.rs
-complex-path1.rs
-const-issue1440.rs
-const_generics_3.rs
-const_generics_4.rs
-const_generics_5.rs
-const_generics_7.rs
-derive_empty.rs
-derive_macro1.rs
-expected_type_args2.rs
-feature_rust_attri0.rs
-format_args_basic_expansion.rs
-generic-default1.rs
-generics1.rs
-generics10.rs
-generics11.rs
-generics3.rs
-generics4.rs
-generics5.rs
-generics6.rs
generics9.rs
-if_let_expr.rs
-issue-1130.rs
-issue-1173.rs
-issue-1272.rs
-issue-1447.rs
-issue-1483.rs
-issue-1725-1.rs
-issue-1725-2.rs
-issue-1786.rs
-issue-1893.rs
-issue-1901.rs
-issue-1981.rs
-issue-2036.rs
issue-2043.rs
-issue-2136-2.rs
-issue-2142.rs
-issue-2238.rs
-issue-2330.rs
-issue-2479.rs
-issue-2723-1.rs
-issue-2723-2.rs
-issue-2772-2.rs
-issue-2775.rs
-issue-2782.rs
issue-2812.rs
-issue-850.rs
-issue-852.rs
-issue-855.rs
-iterators1.rs
+issue-3315-2.rs
lookup_err1.rs
-macros/mbe/macro13.rs
-macros/mbe/macro15.rs
-macros/mbe/macro23.rs
-macros/mbe/macro40.rs
-macros/mbe/macro43.rs
-macros/mbe/macro44.rs
-macros/mbe/macro50.rs
-macros/mbe/macro54.rs
macros/mbe/macro6.rs
-macros/mbe/macro_rules_macro_rules.rs
-macros/mbe/macro_use1.rs
-match-never-ltype.rs
-match-never-rtype.rs
-match1.rs
-match2.rs
-match3.rs
-match4.rs
-match5.rs
-match9.rs
-method2.rs
multiple_bindings1.rs
multiple_bindings2.rs
-name_resolution2.rs
-name_resolution4.rs
-nested_macro_use1.rs
-nested_macro_use2.rs
-nested_macro_use3.rs
-not_find_value_in_scope.rs
-parse_associated_type_as_generic_arg.rs
-parse_associated_type_as_generic_arg2.rs
-parse_associated_type_as_generic_arg3.rs
-parse_complex_generic_application.rs
-parse_complex_generic_application2.rs
-path_as_generic_arg.rs
-pattern-struct.rs
-privacy4.rs
privacy5.rs
privacy8.rs
-macros/proc/attribute_non_function.rs
-macros/proc/derive_non_function.rs
-macros/proc/non_function.rs
pub_restricted_1.rs
pub_restricted_2.rs
pub_restricted_3.rs
-redef_error2.rs
-redef_error4.rs
-redef_error5.rs
-self-path1.rs
-self-path2.rs
-sizeof-stray-infer-var-bug.rs
-struct-expr-parse.rs
-traits3.rs
-traits6.rs
-traits7.rs
-type-bindings1.rs
-unconstrained_type_param.rs
undeclared_label.rs
use_1.rs
-use_2.rs
-v0-mangle1.rs
-v0-mangle2.rs
while_break_expr.rs
-exhaustiveness1.rs
-exhaustiveness2.rs
-exhaustiveness3.rs
-issue-2324-1.rs
-issue-2324-2.rs
-issue-3046.rs
-issue-3139-2.rs
-issue-3032-1.rs
-issue-3032-2.rs
-# https://github.com/Rust-GCC/gccrs/issues/3189
-if_let_expr_simple.rs
-iflet.rs
-issue-3033.rs
-issue-3009.rs
-issue-2953-2.rs
-issue-1773.rs
issue-2905-2.rs
-issue-2907.rs
-issue-2423.rs
issue-266.rs
-additional-trait-bounds2.rs
-auto_traits3.rs
-issue-3140.rs
-cmp1.rs
-derive_clone_enum1.rs
-derive_clone_enum2.rs
derive_clone_enum3.rs
-derive_macro4.rs
-derive_macro6.rs
-issue-2987.rs
-issue-3139-1.rs
-issue-3139-3.rs
+derive-debug1.rs
+derive-default1.rs
+issue-3402-1.rs
+issue-3403.rs
+derive-eq-invalid.rs
+derive-hash1.rs
+torture/alt_patterns1.rs
+torture/loop4.rs
+torture/loop8.rs
+torture/name_resolve1.rs
+issue-3568.rs
# please don't delete the trailing newline
diff --git a/gcc/testsuite/rust/compile/redef_error2.rs b/gcc/testsuite/rust/compile/redef_error2.rs
index 65793bc..ed946f8 100644
--- a/gcc/testsuite/rust/compile/redef_error2.rs
+++ b/gcc/testsuite/rust/compile/redef_error2.rs
@@ -1,4 +1,4 @@
const TEST: i32 = 2;
-const TEST: f32 = 3.0; // { dg-error "redefined multiple times" }
+const TEST: f32 = 3.0; // { dg-error "defined multiple times" }
fn main() {}
diff --git a/gcc/testsuite/rust/compile/redef_error5.rs b/gcc/testsuite/rust/compile/redef_error5.rs
index dc6ad50..b3d71e1 100644
--- a/gcc/testsuite/rust/compile/redef_error5.rs
+++ b/gcc/testsuite/rust/compile/redef_error5.rs
@@ -2,7 +2,7 @@ struct Foo(i32, bool);
impl Foo {
const TEST: i32 = 123;
- const TEST: bool = false; // { dg-error "redefined multiple times" }
+ const TEST: bool = false; // { dg-error "defined multiple times" }
}
fn main() {}
diff --git a/gcc/testsuite/rust/compile/reference1.rs b/gcc/testsuite/rust/compile/reference1.rs
index 2f94754..28f7a26 100644
--- a/gcc/testsuite/rust/compile/reference1.rs
+++ b/gcc/testsuite/rust/compile/reference1.rs
@@ -2,5 +2,5 @@ fn main() {
let a = &123;
let b: &mut i32 = a;
// { dg-error "mismatched mutability" "" { target *-*-* } .-1 }
- // { dg-error "mismatched types, expected .&mut i32. but got .& i32." "" { target *-*-* } .-2 }
+ // { dg-error "mismatched types, expected .&mut i32. but got .& <integer>." "" { target *-*-* } .-2 }
}
diff --git a/gcc/testsuite/rust/compile/self-path2.rs b/gcc/testsuite/rust/compile/self-path2.rs
index b9b82ca..6441c33 100644
--- a/gcc/testsuite/rust/compile/self-path2.rs
+++ b/gcc/testsuite/rust/compile/self-path2.rs
@@ -11,11 +11,11 @@ fn baz() {
crate::bar();
crate::self::foo();
- // { dg-error "failed to resolve: .self. in paths can only be used in start position" "" { target *-*-* } .-1 }
+ // { dg-error "leading path segment .self. can only be used at the beginning of a path" "" { 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 }
+// { dg-error "leading path segment .self. can only be used at the beginning of a path" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/rust/compile/self_import_namespace.rs b/gcc/testsuite/rust/compile/self_import_namespace.rs
new file mode 100644
index 0000000..2d9b2ed
--- /dev/null
+++ b/gcc/testsuite/rust/compile/self_import_namespace.rs
@@ -0,0 +1,14 @@
+// { dg-additional-options "-frust-name-resolution-2.0" }
+
+mod bar {
+ pub mod foo {}
+ pub fn foo() {}
+}
+
+// This only imports the module `foo`. The function `foo` lives in
+// the value namespace and is not imported.
+use bar::foo::{self};
+
+fn main() {
+ foo(); // { dg-error "expected value" }
+}
diff --git a/gcc/testsuite/rust/compile/sizeof-stray-infer-var-bug.rs b/gcc/testsuite/rust/compile/sizeof-stray-infer-var-bug.rs
index 8275691..c46a97d 100644
--- a/gcc/testsuite/rust/compile/sizeof-stray-infer-var-bug.rs
+++ b/gcc/testsuite/rust/compile/sizeof-stray-infer-var-bug.rs
@@ -14,6 +14,6 @@ mod ptr {
pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
let x = x as *mut T;
let y = y as *mut T;
- let len = mem::size_of::<T>() * count;
+ let len = crate::mem::size_of::<T>() * count;
}
}
diff --git a/gcc/testsuite/rust/compile/structural-eq-peq.rs b/gcc/testsuite/rust/compile/structural-eq-peq.rs
new file mode 100644
index 0000000..d04c295
--- /dev/null
+++ b/gcc/testsuite/rust/compile/structural-eq-peq.rs
@@ -0,0 +1,9 @@
+#[lang = "structural_peq"]
+pub trait StructuralPartialEq {
+ // Empty.
+}
+
+#[lang = "structural_teq"]
+pub trait StructuralEq {
+ // Empty.
+}
diff --git a/gcc/testsuite/rust/compile/torture/builtin_abort.rs b/gcc/testsuite/rust/compile/torture/builtin_abort.rs
index 3112cdc..919caa4 100644
--- a/gcc/testsuite/rust/compile/torture/builtin_abort.rs
+++ b/gcc/testsuite/rust/compile/torture/builtin_abort.rs
@@ -12,7 +12,7 @@ mod intrinsics {
}
}
-pub fn main () -> i32 {
- abort();
+pub fn main() -> i32 {
+ crate::intrinsics::abort();
0
}
diff --git a/gcc/testsuite/rust/compile/torture/if.rs b/gcc/testsuite/rust/compile/torture/if.rs
index bcd520f..3b753a7 100644
--- a/gcc/testsuite/rust/compile/torture/if.rs
+++ b/gcc/testsuite/rust/compile/torture/if.rs
@@ -4,6 +4,10 @@ fn foo() -> bool {
fn bar() {}
+fn baz(a: i32) {
+ a;
+}
+
struct Foo1 {
one: i32
}
@@ -13,7 +17,7 @@ fn main() {
if foo() {
bar();
let a = Foo1{one: 1};
- a.one
+ baz (a.one);
}
-} \ No newline at end of file
+}
diff --git a/gcc/testsuite/rust/compile/torture/uninit-intrinsic-1.rs b/gcc/testsuite/rust/compile/torture/uninit-intrinsic-1.rs
index fa329c6..af1cb54 100644
--- a/gcc/testsuite/rust/compile/torture/uninit-intrinsic-1.rs
+++ b/gcc/testsuite/rust/compile/torture/uninit-intrinsic-1.rs
@@ -11,7 +11,7 @@ mod intrinsics {
mod mem {
pub unsafe fn uninitialized<T>() -> T {
- intrinsics::uninit()
+ crate::intrinsics::uninit()
}
}
@@ -21,6 +21,6 @@ struct Foo(i32, i32);
impl Foo {
pub fn new() -> Self {
- unsafe { mem::uninitialized::<Foo>() }
+ unsafe { crate::mem::uninitialized::<Foo>() }
}
}
diff --git a/gcc/testsuite/rust/compile/try-expr1.rs b/gcc/testsuite/rust/compile/try-expr1.rs
new file mode 100644
index 0000000..f1a7865
--- /dev/null
+++ b/gcc/testsuite/rust/compile/try-expr1.rs
@@ -0,0 +1,84 @@
+// { dg-additional-options "-frust-compile-until=typecheck" }
+
+#[lang = "sized"]
+trait Sized {}
+
+enum Result {
+ #[lang = "Ok"]
+ Ok(i32),
+ #[lang = "Err"]
+ Err(i32)
+}
+
+pub trait From<T>: Sized {
+ /// Performs the conversion.
+ #[lang = "from"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn from(_: T) -> Self;
+}
+
+impl<T> From<T> for T {
+ fn from(t: T) -> Self { t }
+}
+
+#[lang = "try"]
+pub trait Try {
+ /// The type of this value when viewed as successful.
+ // #[unstable(feature = "try_trait", issue = "42327")]
+ // type Ok;
+ /// The type of this value when viewed as failed.
+ // #[unstable(feature = "try_trait", issue = "42327")]
+ // type Error;
+
+ /// Applies the "?" operator. A return of `Ok(t)` means that the
+ /// execution should continue normally, and the result of `?` is the
+ /// value `t`. A return of `Err(e)` means that execution should branch
+ /// to the innermost enclosing `catch`, or return from the function.
+ ///
+ /// If an `Err(e)` result is returned, the value `e` will be "wrapped"
+ /// in the return type of the enclosing scope (which must itself implement
+ /// `Try`). Specifically, the value `X::from_error(From::from(e))`
+ /// is returned, where `X` is the return type of the enclosing function.
+ #[lang = "into_result"]
+ #[unstable(feature = "try_trait", issue = "42327")]
+ fn into_result(self) -> Result;
+
+ /// Wrap an error value to construct the composite result. For example,
+ /// `Result::Err(x)` and `Result::from_error(x)` are equivalent.
+ #[lang = "from_error"]
+ #[unstable(feature = "try_trait", issue = "42327")]
+ fn from_error(v: i32) -> Self;
+
+ /// Wrap an OK value to construct the composite result. For example,
+ /// `Result::Ok(x)` and `Result::from_ok(x)` are equivalent.
+ #[lang = "from_ok"]
+ #[unstable(feature = "try_trait", issue = "42327")]
+ fn from_ok(v: i32) -> Self;
+}
+
+impl Try for Result {
+ // type Ok = i32;
+ // type Error = i32;
+
+ fn into_result(self) -> Result {
+ self
+ }
+
+ fn from_ok(v: i32) -> Self {
+ Result::Ok(v)
+ }
+
+ fn from_error(v: i32) -> Self {
+ Result::Err(v)
+ }
+}
+
+fn bar() -> Result {
+ Result::Ok(15)
+}
+
+fn foo() -> Result {
+ let a = bar()?;
+
+ Result::Ok(a)
+}
diff --git a/gcc/testsuite/rust/compile/try-trait.rs b/gcc/testsuite/rust/compile/try-trait.rs
new file mode 100644
index 0000000..9ec135d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/try-trait.rs
@@ -0,0 +1,44 @@
+#[lang = "sized"]
+trait Sized {}
+
+enum Result<T, E> {
+ #[lang = "Ok"]
+ Ok(T),
+ #[lang = "Err"]
+ Err(E)
+}
+
+#[lang = "try"]
+pub trait Try {
+ /// The type of this value when viewed as successful.
+ #[unstable(feature = "try_trait", issue = "42327")]
+ type Ok;
+ /// The type of this value when viewed as failed.
+ #[unstable(feature = "try_trait", issue = "42327")]
+ type Error;
+
+ /// Applies the "?" operator. A return of `Ok(t)` means that the
+ /// execution should continue normally, and the result of `?` is the
+ /// value `t`. A return of `Err(e)` means that execution should branch
+ /// to the innermost enclosing `catch`, or return from the function.
+ ///
+ /// If an `Err(e)` result is returned, the value `e` will be "wrapped"
+ /// in the return type of the enclosing scope (which must itself implement
+ /// `Try`). Specifically, the value `X::from_error(From::from(e))`
+ /// is returned, where `X` is the return type of the enclosing function.
+ #[lang = "into_result"]
+ #[unstable(feature = "try_trait", issue = "42327")]
+ fn into_result(self) -> Result<Self::Ok, Self::Error>;
+
+ /// Wrap an error value to construct the composite result. For example,
+ /// `Result::Err(x)` and `Result::from_error(x)` are equivalent.
+ #[lang = "from_error"]
+ #[unstable(feature = "try_trait", issue = "42327")]
+ fn from_error(v: Self::Error) -> Self;
+
+ /// Wrap an OK value to construct the composite result. For example,
+ /// `Result::Ok(x)` and `Result::from_ok(x)` are equivalent.
+ #[lang = "from_ok"]
+ #[unstable(feature = "try_trait", issue = "42327")]
+ fn from_ok(v: Self::Ok) -> Self;
+}
diff --git a/gcc/testsuite/rust/compile/type-bindings1.rs b/gcc/testsuite/rust/compile/type-bindings1.rs
index 358035b..ef0b471 100644
--- a/gcc/testsuite/rust/compile/type-bindings1.rs
+++ b/gcc/testsuite/rust/compile/type-bindings1.rs
@@ -7,5 +7,4 @@ 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 resolve expression of function call} "" { target *-*-* } .-2 }
}
diff --git a/gcc/testsuite/rust/compile/unconstrained_type_param.rs b/gcc/testsuite/rust/compile/unconstrained_type_param.rs
index 1cef0b9..60554da 100644
--- a/gcc/testsuite/rust/compile/unconstrained_type_param.rs
+++ b/gcc/testsuite/rust/compile/unconstrained_type_param.rs
@@ -13,5 +13,4 @@ impl<X, Y> Foo<X> {
fn main() {
let a = Foo::test();
// { dg-error "expected" "" { target *-*-* } .-1 }
- // { dg-error "Failed to resolve expression of function call" "" { target *-*-* } .-2 }
}
diff --git a/gcc/testsuite/rust/execute/crate-metavar1.rs b/gcc/testsuite/rust/execute/crate-metavar1.rs
new file mode 100644
index 0000000..8418308
--- /dev/null
+++ b/gcc/testsuite/rust/execute/crate-metavar1.rs
@@ -0,0 +1,11 @@
+macro_rules! foo {
+ () => {
+ $crate::bar()
+ }
+}
+
+pub fn bar() -> i32 { 1 }
+
+fn main() -> i32 {
+ foo!() - crate::bar()
+}
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_option_env.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_option_env.rs
new file mode 100644
index 0000000..56fbeaa
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/builtin_macro_option_env.rs
@@ -0,0 +1,65 @@
+// { dg-output "VALUE\r*\nVALUE\r*\n" }
+// { dg-set-compiler-env-var ENV_MACRO_TEST "VALUE" }
+
+#![feature(rustc_attrs)]
+
+#[rustc_builtin_macro]
+macro_rules! option_env {
+ () => {{}};
+}
+
+#[lang = "sized"]
+trait Sized {}
+
+pub mod core {
+ pub mod option {
+ pub enum Option<T> {
+ #[lang = "Some"]
+ Some(T),
+ #[lang = "None"]
+ None,
+ }
+ }
+}
+
+use core::option::Option;
+
+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,
+ );
+ }
+}
+
+macro_rules! env_macro_test {
+ () => { "ENV_MACRO_TEST" }
+}
+
+fn main() -> i32 {
+ let val0: Option<&'static str> = option_env!("ENV_MACRO_TEST");
+
+
+ match val0 {
+ Option::None => {},
+ Option::Some(s) => {
+ print(s);
+ }
+ }
+
+ //eager expansion test
+ let val1: Option<&'static str> = option_env!(env_macro_test!(),);
+
+ match val1 {
+ Option::None => {},
+ Option::Some(s) => {
+ print(s);
+ }
+ }
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/derive-default1.rs b/gcc/testsuite/rust/execute/torture/derive-default1.rs
new file mode 100644
index 0000000..4bcafa0
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/derive-default1.rs
@@ -0,0 +1,26 @@
+#[derive(Default)]
+struct Foo { a: i32 }
+#[derive(Default)]
+struct Bar(i32);
+
+#[lang = "sized"]
+trait Sized {}
+
+mod core {
+ mod default {
+ trait Default: Sized {
+ fn default() -> Self;
+ }
+
+ impl Default for i32 {
+ fn default() -> Self { 1 }
+ }
+ }
+}
+
+fn main() -> i32 {
+ let foo = Foo::default();
+ let bar = Bar::default();
+
+ foo.a + bar.0 - 2
+}
diff --git a/gcc/testsuite/rust/execute/torture/derive-partialeq1.rs b/gcc/testsuite/rust/execute/torture/derive-partialeq1.rs
new file mode 100644
index 0000000..67b2773
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/derive-partialeq1.rs
@@ -0,0 +1,64 @@
+// { dg-output "true\r*\nfalse\r*\nfalse\r*\n" }
+
+#![feature(intrinsics)]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "copy"]
+trait Copy {}
+
+#[lang = "eq"]
+pub trait PartialEq<Rhs: ?Sized = Self> {
+ /// This method tests for `self` and `other` values to be equal, and is used
+ /// by `==`.
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn eq(&self, other: &Rhs) -> bool;
+
+ /// This method tests for `!=`.
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+}
+
+#[lang = "structural_peq"]
+trait StructuralPartialEq {}
+
+#[derive(PartialEq, Copy)] // { dg-warning "unused name" }
+struct Foo;
+
+#[derive(PartialEq)]
+struct Bar(Foo);
+
+#[derive(PartialEq)]
+struct Baz { _inner: Foo }
+
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn print(b: bool) {
+ if b {
+ unsafe { puts("true" as *const str as *const i8) }
+ } else {
+ unsafe { puts("false" as *const str as *const i8) }
+ }
+}
+
+fn main() -> i32 {
+ let x = Foo;
+
+ let b1 = x == Foo;
+ let b2 = Bar(x) != Bar(Foo);
+ let b3 = Baz { _inner: Foo } != Baz { _inner: x };
+
+ print(b1);
+ print(b2);
+ print(b3);
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/enum_intrinsics1.rs b/gcc/testsuite/rust/execute/torture/enum_intrinsics1.rs
new file mode 100644
index 0000000..c30bbd3
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/enum_intrinsics1.rs
@@ -0,0 +1,48 @@
+/* { dg-output "0\r*\n2\r*\n" } */
+#![feature(intrinsics)]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+enum BookFormat {
+ Paperback,
+ Hardback,
+ Ebook,
+}
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+mod core {
+ mod intrinsics {
+ #[lang = "discriminant_kind"]
+ pub trait DiscriminantKind {
+ #[lang = "discriminant_type"]
+ type Discriminant;
+ }
+
+ extern "rust-intrinsic" {
+ pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
+ }
+ }
+}
+
+pub fn main() -> i32 {
+ let a = BookFormat::Paperback;
+ let b = BookFormat::Ebook;
+
+ unsafe {
+ let val1: isize = core::intrinsics::discriminant_value(&a);
+ let val2 = core::intrinsics::discriminant_value(&b);
+
+ let a = "%i\n";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, val1 as i32);
+ printf(c, val2 as i32);
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/enum_intrinsics2.rs b/gcc/testsuite/rust/execute/torture/enum_intrinsics2.rs
new file mode 100644
index 0000000..c1bae35
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/enum_intrinsics2.rs
@@ -0,0 +1,25 @@
+#![feature(intrinsics)]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+enum BookFormat {
+ Paperback,
+ Hardback,
+ Ebook,
+}
+
+mod core {
+ mod intrinsics {
+ extern "rust-intrinsic" {
+ #[rustc_const_unstable(feature = "variant_count", issue = "73662")]
+ pub fn variant_count<T>() -> usize;
+ }
+ }
+}
+
+pub fn main() -> i32 {
+ let count = core::intrinsics::variant_count::<BookFormat>();
+
+ (count as i32) - 3
+}
diff --git a/gcc/testsuite/rust/execute/torture/for-loop1.rs b/gcc/testsuite/rust/execute/torture/for-loop1.rs
new file mode 100644
index 0000000..5a6a70c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/for-loop1.rs
@@ -0,0 +1,545 @@
+// { dg-output "loop\r*\nloop\r*\n" }
+#![feature(intrinsics)]
+
+pub use option::Option::{self, None, Some};
+pub use result::Result::{self, Err, Ok};
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+ fn puts(s: *const i8);
+}
+
+mod option {
+ pub enum Option<T> {
+ #[lang = "None"]
+ None,
+ #[lang = "Some"]
+ Some(T),
+ }
+}
+
+mod result {
+ enum Result<T, E> {
+ Ok(T),
+ Err(E),
+ }
+}
+
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {
+ fn clone(&self) -> Self;
+
+ fn clone_from(&mut self, source: &Self) {
+ *self = source.clone()
+ }
+}
+
+mod impls {
+ use super::Clone;
+
+ macro_rules! impl_clone {
+ ($($t:ty)*) => {
+ $(
+ impl Clone for $t {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+ )*
+ }
+ }
+
+ impl_clone! {
+ usize u8 u16 u32 u64 // u128
+ isize i8 i16 i32 i64 // i128
+ f32 f64
+ bool char
+ }
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+ // Empty.
+}
+
+mod copy_impls {
+ use super::Copy;
+
+ macro_rules! impl_copy {
+ ($($t:ty)*) => {
+ $(
+ impl Copy for $t {}
+ )*
+ }
+ }
+
+ impl_copy! {
+ usize u8 u16 u32 u64 // u128
+ isize i8 i16 i32 i64 // i128
+ f32 f64
+ bool char
+ }
+}
+
+mod intrinsics {
+ extern "rust-intrinsic" {
+ pub fn add_with_overflow<T>(x: T, y: T) -> (T, bool);
+ pub fn wrapping_add<T>(a: T, b: T) -> T;
+ pub fn wrapping_sub<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;
+ pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+ pub fn move_val_init<T>(dst: *mut T, src: T);
+ pub fn uninit<T>() -> T;
+ }
+}
+
+mod ptr {
+ #[lang = "const_ptr"]
+ impl<T> *const T {
+ pub unsafe fn offset(self, count: isize) -> *const T {
+ intrinsics::offset(self, count)
+ }
+ }
+
+ #[lang = "mut_ptr"]
+ impl<T> *mut T {
+ pub unsafe fn offset(self, count: isize) -> *mut T {
+ intrinsics::offset(self, count) as *mut T
+ }
+ }
+
+ pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
+ let x = x as *mut u8;
+ let y = y as *mut u8;
+ let len = mem::size_of::<T>() * count;
+ swap_nonoverlapping_bytes(x, y, len)
+ }
+
+ pub unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
+ // For types smaller than the block optimization below,
+ // just swap directly to avoid pessimizing codegen.
+ if mem::size_of::<T>() < 32 {
+ let z = read(x);
+ intrinsics::copy_nonoverlapping(y, x, 1);
+ write(y, z);
+ } else {
+ swap_nonoverlapping(x, y, 1);
+ }
+ }
+
+ pub unsafe fn write<T>(dst: *mut T, src: T) {
+ intrinsics::move_val_init(&mut *dst, src)
+ }
+
+ pub unsafe fn read<T>(src: *const T) -> T {
+ let mut tmp: T = mem::uninitialized();
+ intrinsics::copy_nonoverlapping(src, &mut tmp, 1);
+ tmp
+ }
+
+ pub unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
+ struct Block(u64, u64, u64, u64);
+ struct UnalignedBlock(u64, u64, u64, u64);
+
+ let block_size = mem::size_of::<Block>();
+
+ // Loop through x & y, copying them `Block` at a time
+ // The optimizer should unroll the loop fully for most types
+ // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively
+ let mut i: usize = 0;
+ while i + block_size <= len {
+ // Create some uninitialized memory as scratch space
+ // Declaring `t` here avoids aligning the stack when this loop is unused
+ let mut t: Block = mem::uninitialized();
+ let t = &mut t as *mut _ as *mut u8;
+ let x = x.offset(i as isize);
+ let y = y.offset(i as isize);
+
+ // Swap a block of bytes of x & y, using t as a temporary buffer
+ // This should be optimized into efficient SIMD operations where available
+ intrinsics::copy_nonoverlapping(x, t, block_size);
+ intrinsics::copy_nonoverlapping(y, x, block_size);
+ intrinsics::copy_nonoverlapping(t, y, block_size);
+ i += block_size;
+ }
+
+ if i < len {
+ // Swap any remaining bytes
+ let mut t: UnalignedBlock = mem::uninitialized();
+ let rem = len - i;
+
+ let t = &mut t as *mut _ as *mut u8;
+ let x = x.offset(i as isize);
+ let y = y.offset(i as isize);
+
+ intrinsics::copy_nonoverlapping(x, t, rem);
+ intrinsics::copy_nonoverlapping(y, x, rem);
+ intrinsics::copy_nonoverlapping(t, y, rem);
+ }
+ }
+}
+
+mod mem {
+ extern "rust-intrinsic" {
+ #[rustc_const_stable(feature = "const_transmute", since = "1.46.0")]
+ pub fn transmute<T, U>(_: T) -> U;
+ #[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
+ pub fn size_of<T>() -> usize;
+ }
+
+ pub fn swap<T>(x: &mut T, y: &mut T) {
+ unsafe {
+ ptr::swap_nonoverlapping_one(x, y);
+ }
+ }
+
+ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
+ swap(dest, &mut src);
+ src
+ }
+
+ pub unsafe fn uninitialized<T>() -> T {
+ intrinsics::uninit()
+ }
+}
+
+macro_rules! impl_uint {
+ ($($ty:ident = $lang:literal),*) => {
+ $(
+ impl $ty {
+ pub fn wrapping_add(self, rhs: Self) -> Self {
+ unsafe {
+ intrinsics::wrapping_add(self, rhs)
+ }
+ }
+
+ pub fn wrapping_sub(self, rhs: Self) -> Self {
+ unsafe {
+ intrinsics::wrapping_sub(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) }
+ }
+
+ pub fn checked_add(self, rhs: Self) -> Option<Self> {
+ let (a, b) = self.overflowing_add(rhs);
+ if b {
+ Option::None
+ } else {
+ Option::Some(a)
+ }
+ }
+
+ pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
+ let (a, b) = unsafe { intrinsics::add_with_overflow(self as $ty, rhs as $ty) };
+ (a as Self, b)
+ }
+ }
+ )*
+ }
+}
+
+impl_uint!(
+ u8 = "u8",
+ u16 = "u16",
+ u32 = "u32",
+ u64 = "u64",
+ usize = "usize"
+);
+
+#[lang = "add"]
+pub trait Add<RHS = Self> {
+ type Output;
+
+ fn add(self, rhs: RHS) -> Self::Output;
+}
+macro_rules! add_impl {
+ ($($t:ty)*) => ($(
+ impl Add for $t {
+ type Output = $t;
+
+ fn add(self, other: $t) -> $t { self + other }
+ }
+ )*)
+}
+
+add_impl! { usize u8 u16 u32 u64 /*isize i8 i16 i32 i64*/ f32 f64 }
+
+#[lang = "sub"]
+pub trait Sub<RHS = Self> {
+ type Output;
+
+ fn sub(self, rhs: RHS) -> Self::Output;
+}
+macro_rules! sub_impl {
+ ($($t:ty)*) => ($(
+ impl Sub for $t {
+ type Output = $t;
+
+ fn sub(self, other: $t) -> $t { self - other }
+ }
+ )*)
+}
+
+sub_impl! { usize u8 u16 u32 u64 /*isize i8 i16 i32 i64*/ f32 f64 }
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+ pub start: Idx,
+ pub end: Idx,
+}
+
+pub trait TryFrom<T>: Sized {
+ /// The type returned in the event of a conversion error.
+ type Error;
+
+ /// Performs the conversion.
+ fn try_from(value: T) -> Result<Self, Self::Error>;
+}
+
+pub trait From<T>: Sized {
+ fn from(_: T) -> Self;
+}
+
+impl<T> From<T> for T {
+ fn from(t: T) -> T {
+ t
+ }
+}
+
+impl<T, U> TryFrom<U> for T
+where
+ T: From<U>,
+{
+ type Error = !;
+
+ fn try_from(value: U) -> Result<Self, Self::Error> {
+ Ok(T::from(value))
+ }
+}
+
+trait Step {
+ /// Returns the number of steps between two step objects. The count is
+ /// inclusive of `start` and exclusive of `end`.
+ ///
+ /// Returns `None` if it is not possible to calculate `steps_between`
+ /// without overflow.
+ fn steps_between(start: &Self, end: &Self) -> Option<usize>;
+
+ /// Replaces this step with `1`, returning itself
+ fn replace_one(&mut self) -> Self;
+
+ /// Replaces this step with `0`, returning itself
+ fn replace_zero(&mut self) -> Self;
+
+ /// Adds one to this step, returning the result
+ fn add_one(&self) -> Self;
+
+ /// Subtracts one to this step, returning the result
+ fn sub_one(&self) -> Self;
+
+ /// Add an usize, returning None on overflow
+ fn add_usize(&self, n: usize) -> Option<Self>;
+}
+
+// These are still macro-generated because the integer literals resolve to different types.
+macro_rules! step_identical_methods {
+ () => {
+ #[inline]
+ fn replace_one(&mut self) -> Self {
+ mem::replace(self, 1)
+ }
+
+ #[inline]
+ fn replace_zero(&mut self) -> Self {
+ mem::replace(self, 0)
+ }
+
+ #[inline]
+ fn add_one(&self) -> Self {
+ Add::add(*self, 1)
+ }
+
+ #[inline]
+ fn sub_one(&self) -> Self {
+ Sub::sub(*self, 1)
+ }
+ };
+}
+
+macro_rules! step_impl_unsigned {
+ ($($t:ty)*) => ($(
+ impl Step for $t {
+ fn steps_between(start: &$t, end: &$t) -> Option<usize> {
+ if *start < *end {
+ // Note: We assume $t <= usize here
+ Option::Some((*end - *start) as usize)
+ } else {
+ Option::Some(0)
+ }
+ }
+
+ fn add_usize(&self, n: usize) -> Option<Self> {
+ match <$t>::try_from(n) {
+ Result::Ok(n_as_t) => self.checked_add(n_as_t),
+ Result::Err(_) => Option::None,
+ }
+ }
+
+ step_identical_methods!();
+ }
+ )*)
+}
+macro_rules! step_impl_signed {
+ ($( [$t:ty : $unsigned:ty] )*) => ($(
+ impl Step for $t {
+ #[inline]
+ #[allow(trivial_numeric_casts)]
+ fn steps_between(start: &$t, end: &$t) -> Option<usize> {
+ if *start < *end {
+ // Note: We assume $t <= isize here
+ // Use .wrapping_sub and cast to usize to compute the
+ // difference that may not fit inside the range of isize.
+ Option::Some((*end as isize).wrapping_sub(*start as isize) as usize)
+ } else {
+ Option::Some(0)
+ }
+ }
+
+ #[inline]
+ #[allow(unreachable_patterns)]
+ fn add_usize(&self, n: usize) -> Option<Self> {
+ match <$unsigned>::try_from(n) {
+ Result::Ok(n_as_unsigned) => {
+ // Wrapping in unsigned space handles cases like
+ // `-120_i8.add_usize(200) == Option::Some(80_i8)`,
+ // even though 200_usize is out of range for i8.
+ let wrapped = (*self as $unsigned).wrapping_add(n_as_unsigned) as $t;
+ if wrapped >= *self {
+ Option::Some(wrapped)
+ } else {
+ Option::None // Addition overflowed
+ }
+ }
+ Result::Err(_) => Option::None,
+ }
+ }
+
+ step_identical_methods!();
+ }
+ )*)
+}
+
+macro_rules! step_impl_no_between {
+ ($($t:ty)*) => ($(
+ impl Step for $t {
+ #[inline]
+ fn steps_between(_start: &Self, _end: &Self) -> Option<usize> {
+ Option::None
+ }
+
+ #[inline]
+ fn add_usize(&self, n: usize) -> Option<Self> {
+ self.checked_add(n as $t)
+ }
+
+ step_identical_methods!();
+ }
+ )*)
+}
+
+step_impl_unsigned!(usize);
+
+pub trait Iterator {
+ type Item;
+
+ #[lang = "next"]
+ fn next(&mut self) -> Option<Self::Item>;
+}
+
+impl<A: Step> Iterator for Range<A> {
+ type Item = A;
+
+ fn next(&mut self) -> Option<A> {
+ if self.start < self.end {
+ // We check for overflow here, even though it can't actually
+ // happen. Adding this check does however help llvm vectorize loops
+ // for some ranges that don't get vectorized otherwise,
+ // and this won't actually result in an extra check in an optimized build.
+ match self.start.add_usize(1) {
+ Option::Some(mut n) => {
+ mem::swap(&mut n, &mut self.start);
+ Option::Some(n)
+ }
+ Option::None => Option::None,
+ }
+ } else {
+ Option::None
+ }
+ }
+}
+
+pub trait IntoIterator {
+ type Item;
+
+ type IntoIter: Iterator<Item = Self::Item>;
+
+ #[lang = "into_iter"]
+ fn into_iter(self) -> Self::IntoIter;
+}
+
+impl<I: Iterator> IntoIterator for I {
+ type Item = I::Item;
+ type IntoIter = I;
+
+ fn into_iter(self) -> I {
+ self
+ }
+}
+
+pub fn main() -> i32 {
+ let a = 1usize..3usize;
+
+ for i in a { // { dg-warning "unused name" }
+ unsafe { puts("loop\0" as *const str as *const i8); }
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/for-loop2.rs b/gcc/testsuite/rust/execute/torture/for-loop2.rs
new file mode 100644
index 0000000..5ba2cd1
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/for-loop2.rs
@@ -0,0 +1,544 @@
+// { dg-output "loop1\r*\nloop2\r*\n" }
+#![feature(intrinsics)]
+
+pub use option::Option::{self, None, Some};
+pub use result::Result::{self, Err, Ok};
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+mod option {
+ pub enum Option<T> {
+ #[lang = "None"]
+ None,
+ #[lang = "Some"]
+ Some(T),
+ }
+}
+
+mod result {
+ enum Result<T, E> {
+ Ok(T),
+ Err(E),
+ }
+}
+
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {
+ fn clone(&self) -> Self;
+
+ fn clone_from(&mut self, source: &Self) {
+ *self = source.clone()
+ }
+}
+
+mod impls {
+ use super::Clone;
+
+ macro_rules! impl_clone {
+ ($($t:ty)*) => {
+ $(
+ impl Clone for $t {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+ )*
+ }
+ }
+
+ impl_clone! {
+ usize u8 u16 u32 u64 // u128
+ isize i8 i16 i32 i64 // i128
+ f32 f64
+ bool char
+ }
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+ // Empty.
+}
+
+mod copy_impls {
+ use super::Copy;
+
+ macro_rules! impl_copy {
+ ($($t:ty)*) => {
+ $(
+ impl Copy for $t {}
+ )*
+ }
+ }
+
+ impl_copy! {
+ usize u8 u16 u32 u64 // u128
+ isize i8 i16 i32 i64 // i128
+ f32 f64
+ bool char
+ }
+}
+
+mod intrinsics {
+ extern "rust-intrinsic" {
+ pub fn add_with_overflow<T>(x: T, y: T) -> (T, bool);
+ pub fn wrapping_add<T>(a: T, b: T) -> T;
+ pub fn wrapping_sub<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;
+ pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+ pub fn move_val_init<T>(dst: *mut T, src: T);
+ pub fn uninit<T>() -> T;
+ }
+}
+
+mod ptr {
+ #[lang = "const_ptr"]
+ impl<T> *const T {
+ pub unsafe fn offset(self, count: isize) -> *const T {
+ intrinsics::offset(self, count)
+ }
+ }
+
+ #[lang = "mut_ptr"]
+ impl<T> *mut T {
+ pub unsafe fn offset(self, count: isize) -> *mut T {
+ intrinsics::offset(self, count) as *mut T
+ }
+ }
+
+ pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
+ let x = x as *mut u8;
+ let y = y as *mut u8;
+ let len = mem::size_of::<T>() * count;
+ swap_nonoverlapping_bytes(x, y, len)
+ }
+
+ pub unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
+ // For types smaller than the block optimization below,
+ // just swap directly to avoid pessimizing codegen.
+ if mem::size_of::<T>() < 32 {
+ let z = read(x);
+ intrinsics::copy_nonoverlapping(y, x, 1);
+ write(y, z);
+ } else {
+ swap_nonoverlapping(x, y, 1);
+ }
+ }
+
+ pub unsafe fn write<T>(dst: *mut T, src: T) {
+ intrinsics::move_val_init(&mut *dst, src)
+ }
+
+ pub unsafe fn read<T>(src: *const T) -> T {
+ let mut tmp: T = mem::uninitialized();
+ intrinsics::copy_nonoverlapping(src, &mut tmp, 1);
+ tmp
+ }
+
+ pub unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
+ struct Block(u64, u64, u64, u64);
+ struct UnalignedBlock(u64, u64, u64, u64);
+
+ let block_size = mem::size_of::<Block>();
+
+ // Loop through x & y, copying them `Block` at a time
+ // The optimizer should unroll the loop fully for most types
+ // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively
+ let mut i: usize = 0;
+ while i + block_size <= len {
+ // Create some uninitialized memory as scratch space
+ // Declaring `t` here avoids aligning the stack when this loop is unused
+ let mut t: Block = mem::uninitialized();
+ let t = &mut t as *mut _ as *mut u8;
+ let x = x.offset(i as isize);
+ let y = y.offset(i as isize);
+
+ // Swap a block of bytes of x & y, using t as a temporary buffer
+ // This should be optimized into efficient SIMD operations where available
+ intrinsics::copy_nonoverlapping(x, t, block_size);
+ intrinsics::copy_nonoverlapping(y, x, block_size);
+ intrinsics::copy_nonoverlapping(t, y, block_size);
+ i += block_size;
+ }
+
+ if i < len {
+ // Swap any remaining bytes
+ let mut t: UnalignedBlock = mem::uninitialized();
+ let rem = len - i;
+
+ let t = &mut t as *mut _ as *mut u8;
+ let x = x.offset(i as isize);
+ let y = y.offset(i as isize);
+
+ intrinsics::copy_nonoverlapping(x, t, rem);
+ intrinsics::copy_nonoverlapping(y, x, rem);
+ intrinsics::copy_nonoverlapping(t, y, rem);
+ }
+ }
+}
+
+mod mem {
+ extern "rust-intrinsic" {
+ #[rustc_const_stable(feature = "const_transmute", since = "1.46.0")]
+ pub fn transmute<T, U>(_: T) -> U;
+ #[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
+ pub fn size_of<T>() -> usize;
+ }
+
+ pub fn swap<T>(x: &mut T, y: &mut T) {
+ unsafe {
+ ptr::swap_nonoverlapping_one(x, y);
+ }
+ }
+
+ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
+ swap(dest, &mut src);
+ src
+ }
+
+ pub unsafe fn uninitialized<T>() -> T {
+ intrinsics::uninit()
+ }
+}
+
+macro_rules! impl_uint {
+ ($($ty:ident = $lang:literal),*) => {
+ $(
+ impl $ty {
+ pub fn wrapping_add(self, rhs: Self) -> Self {
+ unsafe {
+ intrinsics::wrapping_add(self, rhs)
+ }
+ }
+
+ pub fn wrapping_sub(self, rhs: Self) -> Self {
+ unsafe {
+ intrinsics::wrapping_sub(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) }
+ }
+
+ pub fn checked_add(self, rhs: Self) -> Option<Self> {
+ let (a, b) = self.overflowing_add(rhs);
+ if b {
+ Option::None
+ } else {
+ Option::Some(a)
+ }
+ }
+
+ pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
+ let (a, b) = unsafe { intrinsics::add_with_overflow(self as $ty, rhs as $ty) };
+ (a as Self, b)
+ }
+ }
+ )*
+ }
+}
+
+impl_uint!(
+ u8 = "u8",
+ u16 = "u16",
+ u32 = "u32",
+ u64 = "u64",
+ usize = "usize"
+);
+
+#[lang = "add"]
+pub trait Add<RHS = Self> {
+ type Output;
+
+ fn add(self, rhs: RHS) -> Self::Output;
+}
+macro_rules! add_impl {
+ ($($t:ty)*) => ($(
+ impl Add for $t {
+ type Output = $t;
+
+ fn add(self, other: $t) -> $t { self + other }
+ }
+ )*)
+}
+
+add_impl! { usize u8 u16 u32 u64 /*isize i8 i16 i32 i64*/ f32 f64 }
+
+#[lang = "sub"]
+pub trait Sub<RHS = Self> {
+ type Output;
+
+ fn sub(self, rhs: RHS) -> Self::Output;
+}
+macro_rules! sub_impl {
+ ($($t:ty)*) => ($(
+ impl Sub for $t {
+ type Output = $t;
+
+ fn sub(self, other: $t) -> $t { self - other }
+ }
+ )*)
+}
+
+sub_impl! { usize u8 u16 u32 u64 /*isize i8 i16 i32 i64*/ f32 f64 }
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+ pub start: Idx,
+ pub end: Idx,
+}
+
+pub trait TryFrom<T>: Sized {
+ /// The type returned in the event of a conversion error.
+ type Error;
+
+ /// Performs the conversion.
+ fn try_from(value: T) -> Result<Self, Self::Error>;
+}
+
+pub trait From<T>: Sized {
+ fn from(_: T) -> Self;
+}
+
+impl<T> From<T> for T {
+ fn from(t: T) -> T {
+ t
+ }
+}
+
+impl<T, U> TryFrom<U> for T
+where
+ T: From<U>,
+{
+ type Error = !;
+
+ fn try_from(value: U) -> Result<Self, Self::Error> {
+ Ok(T::from(value))
+ }
+}
+
+trait Step {
+ /// Returns the number of steps between two step objects. The count is
+ /// inclusive of `start` and exclusive of `end`.
+ ///
+ /// Returns `None` if it is not possible to calculate `steps_between`
+ /// without overflow.
+ fn steps_between(start: &Self, end: &Self) -> Option<usize>;
+
+ /// Replaces this step with `1`, returning itself
+ fn replace_one(&mut self) -> Self;
+
+ /// Replaces this step with `0`, returning itself
+ fn replace_zero(&mut self) -> Self;
+
+ /// Adds one to this step, returning the result
+ fn add_one(&self) -> Self;
+
+ /// Subtracts one to this step, returning the result
+ fn sub_one(&self) -> Self;
+
+ /// Add an usize, returning None on overflow
+ fn add_usize(&self, n: usize) -> Option<Self>;
+}
+
+// These are still macro-generated because the integer literals resolve to different types.
+macro_rules! step_identical_methods {
+ () => {
+ #[inline]
+ fn replace_one(&mut self) -> Self {
+ mem::replace(self, 1)
+ }
+
+ #[inline]
+ fn replace_zero(&mut self) -> Self {
+ mem::replace(self, 0)
+ }
+
+ #[inline]
+ fn add_one(&self) -> Self {
+ Add::add(*self, 1)
+ }
+
+ #[inline]
+ fn sub_one(&self) -> Self {
+ Sub::sub(*self, 1)
+ }
+ };
+}
+
+macro_rules! step_impl_unsigned {
+ ($($t:ty)*) => ($(
+ impl Step for $t {
+ fn steps_between(start: &$t, end: &$t) -> Option<usize> {
+ if *start < *end {
+ // Note: We assume $t <= usize here
+ Option::Some((*end - *start) as usize)
+ } else {
+ Option::Some(0)
+ }
+ }
+
+ fn add_usize(&self, n: usize) -> Option<Self> {
+ match <$t>::try_from(n) {
+ Result::Ok(n_as_t) => self.checked_add(n_as_t),
+ Result::Err(_) => Option::None,
+ }
+ }
+
+ step_identical_methods!();
+ }
+ )*)
+}
+macro_rules! step_impl_signed {
+ ($( [$t:ty : $unsigned:ty] )*) => ($(
+ impl Step for $t {
+ #[inline]
+ #[allow(trivial_numeric_casts)]
+ fn steps_between(start: &$t, end: &$t) -> Option<usize> {
+ if *start < *end {
+ // Note: We assume $t <= isize here
+ // Use .wrapping_sub and cast to usize to compute the
+ // difference that may not fit inside the range of isize.
+ Option::Some((*end as isize).wrapping_sub(*start as isize) as usize)
+ } else {
+ Option::Some(0)
+ }
+ }
+
+ #[inline]
+ #[allow(unreachable_patterns)]
+ fn add_usize(&self, n: usize) -> Option<Self> {
+ match <$unsigned>::try_from(n) {
+ Result::Ok(n_as_unsigned) => {
+ // Wrapping in unsigned space handles cases like
+ // `-120_i8.add_usize(200) == Option::Some(80_i8)`,
+ // even though 200_usize is out of range for i8.
+ let wrapped = (*self as $unsigned).wrapping_add(n_as_unsigned) as $t;
+ if wrapped >= *self {
+ Option::Some(wrapped)
+ } else {
+ Option::None // Addition overflowed
+ }
+ }
+ Result::Err(_) => Option::None,
+ }
+ }
+
+ step_identical_methods!();
+ }
+ )*)
+}
+
+macro_rules! step_impl_no_between {
+ ($($t:ty)*) => ($(
+ impl Step for $t {
+ #[inline]
+ fn steps_between(_start: &Self, _end: &Self) -> Option<usize> {
+ Option::None
+ }
+
+ #[inline]
+ fn add_usize(&self, n: usize) -> Option<Self> {
+ self.checked_add(n as $t)
+ }
+
+ step_identical_methods!();
+ }
+ )*)
+}
+
+step_impl_unsigned!(usize);
+
+pub trait Iterator {
+ type Item;
+
+ #[lang = "next"]
+ fn next(&mut self) -> Option<Self::Item>;
+}
+
+impl<A: Step> Iterator for Range<A> {
+ type Item = A;
+
+ fn next(&mut self) -> Option<A> {
+ if self.start < self.end {
+ // We check for overflow here, even though it can't actually
+ // happen. Adding this check does however help llvm vectorize loops
+ // for some ranges that don't get vectorized otherwise,
+ // and this won't actually result in an extra check in an optimized build.
+ match self.start.add_usize(1) {
+ Option::Some(mut n) => {
+ mem::swap(&mut n, &mut self.start);
+ Option::Some(n)
+ }
+ Option::None => Option::None,
+ }
+ } else {
+ Option::None
+ }
+ }
+}
+
+pub trait IntoIterator {
+ type Item;
+
+ type IntoIter: Iterator<Item = Self::Item>;
+
+ #[lang = "into_iter"]
+ fn into_iter(self) -> Self::IntoIter;
+}
+
+impl<I: Iterator> IntoIterator for I {
+ type Item = I::Item;
+ type IntoIter = I;
+
+ fn into_iter(self) -> I {
+ self
+ }
+}
+
+pub fn main() -> i32 {
+ let a = 1usize..3usize;
+
+ for i in a {
+ unsafe { printf("loop%d\n\0" as *const str as *const i8, i); }
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-3126.rs b/gcc/testsuite/rust/execute/torture/issue-3126.rs
new file mode 100644
index 0000000..f505146
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-3126.rs
@@ -0,0 +1,52 @@
+/* { dg-output "child\r*\n" }*/
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "sized"]
+pub trait Sized {}
+
+struct Foo {
+ my_int: u32,
+ // { dg-warning "field is never read: .my_int." "" { target *-*-* } .-1 }
+}
+
+trait Parent<T> {
+ fn parent(&self) -> T;
+}
+
+trait Child: Parent<u32> {
+ fn child(&self);
+}
+
+impl Parent<u32> for Foo {
+ fn parent(&self) -> u32 {
+ unsafe {
+ let parent = "parent %i\n\0";
+ let msg = parent as *const str;
+ printf(msg as *const i8, self.my_int);
+ return self.my_int;
+ }
+ }
+}
+
+impl Child for Foo {
+ fn child(&self) {
+ let _ = self;
+ unsafe {
+ let child = "child\n\0";
+ let msg = child as *const str;
+ printf(msg as *const i8);
+ }
+ }
+}
+
+pub fn main() -> i32 {
+ let a = Foo { my_int: 0xf00dfeed };
+ let b: &dyn Child = &a;
+
+ // b.parent();
+ b.child();
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-3381.rs b/gcc/testsuite/rust/execute/torture/issue-3381.rs
new file mode 100644
index 0000000..62dbcd0
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-3381.rs
@@ -0,0 +1,90 @@
+/* { dg-output "Err: 15\r*\n" } */
+#[lang = "sized"]
+trait Sized {}
+
+enum Result<T, E> {
+ #[lang = "Ok"]
+ Ok(T),
+ #[lang = "Err"]
+ Err(E),
+}
+
+#[lang = "try"]
+pub trait Try {
+ type Ok;
+ type Error;
+
+ #[lang = "into_result"]
+ #[unstable(feature = "try_trait", issue = "42327")]
+ fn into_result(self) -> Result<Self::Ok, Self::Error>;
+
+ #[lang = "from_error"]
+ #[unstable(feature = "try_trait", issue = "42327")]
+ fn from_error(v: Self::Ok) -> Self;
+
+ #[lang = "from_ok"]
+ #[unstable(feature = "try_trait", issue = "42327")]
+ fn from_ok(v: Self::Error) -> Self;
+}
+
+impl<T, E> Try for Result<T, E> {
+ type Ok = T;
+ type Error = E;
+
+ fn into_result(self) -> Result<T, E> {
+ self
+ }
+
+ fn from_ok(v: T) -> Self {
+ Result::Ok(v)
+ }
+
+ fn from_error(v: E) -> Self {
+ Result::Err(v)
+ }
+}
+
+pub trait From<T>: Sized {
+ fn from(_: T) -> Self;
+}
+
+impl<T> From<T> for T {
+ fn from(t: T) -> Self {
+ t
+ }
+}
+
+fn print(s: &str, value: i32) {
+ extern "C" {
+ fn printf(s: *const i8, ...);
+ }
+
+ unsafe {
+ printf(s as *const str as *const i8, value);
+ }
+}
+
+fn baz() -> Result<i32, i32> {
+ Result::Err(15)
+}
+
+fn foo() -> Result<i32, i32> {
+ let b = match baz() {
+ Result::Ok(value) => value,
+ Result::Err(err) => {
+ return Try::from_error(From::from(err));
+ }
+ };
+
+ Result::Ok(15 + b)
+}
+
+fn main() -> i32 {
+ let a = foo();
+ match a {
+ Result::Ok(value) => print("Ok: %i\n", value),
+ Result::Err(err) => print("Err: %i\n", err),
+ };
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-3502.rs b/gcc/testsuite/rust/execute/torture/issue-3502.rs
new file mode 100644
index 0000000..f07a126
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-3502.rs
@@ -0,0 +1,52 @@
+/* { dg-output "parent 123\r*\nchild\r*\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "sized"]
+pub trait Sized {}
+
+struct Foo {
+ my_int: u32,
+ // { dg-warning "field is never read: .my_int." "" { target *-*-* } .-1 }
+}
+
+trait Parent<T> {
+ fn parent(&self) -> T;
+}
+
+trait Child: Parent<u32> {
+ fn child(&self);
+}
+
+impl Parent<u32> for Foo {
+ fn parent(&self) -> u32 {
+ unsafe {
+ let parent = "parent %u\n\0";
+ let msg = parent as *const str;
+ printf(msg as *const i8, self.my_int);
+ return self.my_int;
+ }
+ }
+}
+
+impl Child for Foo {
+ fn child(&self) {
+ let _ = self;
+ unsafe {
+ let child = "child\n\0";
+ let msg = child as *const str;
+ printf(msg as *const i8);
+ }
+ }
+}
+
+pub fn main() -> i32 {
+ let a = Foo { my_int: 123 };
+ let b: &dyn Child = &a;
+
+ b.parent();
+ b.child();
+
+ 0
+}