]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Fix bad handling for recursive type query
authorPhilip Herron <herron.philip@googlemail.com>
Tue, 12 Nov 2024 12:16:40 +0000 (12:16 +0000)
committerPhilip Herron <philip.herron@embecosm.com>
Tue, 12 Nov 2024 14:53:02 +0000 (14:53 +0000)
When resolving a type like this which is generic it causes the argument
substitution to go through bounds checking which is expected. But this
can call a type bounds probe which again calls a type query which will be
on the Impl Type on an impl block which can result in a recursive type
query which does eventually get caught and errors correctly. But this then
triggers some old error diagnositcs which are not valid error codes but old
error messages we used to catch simple errors very early on which do not
apply for this senario.

Fixes Rust-GCC#2905

gcc/rust/ChangeLog:

* typecheck/rust-hir-type-check-item.cc (TypeCheckItem::resolve_impl_block_substitutions):
dont check for unconstrained when the self is not resolved
* typecheck/rust-hir-type-check-type.cc (TypeCheckType::resolve_root_path):
remove bad debug error diagnostic
* typecheck/rust-tyty-subst.cc: likewise

gcc/testsuite/ChangeLog:

* rust/compile/nr2/exclude: nr2 cant handle this
* rust/compile/issue-2905-1.rs: New test.
* rust/compile/issue-2905-2.rs: New test.

Signed-off-by: Philip Herron <herron.philip@googlemail.com>
gcc/rust/typecheck/rust-hir-type-check-item.cc
gcc/rust/typecheck/rust-hir-type-check-type.cc
gcc/rust/typecheck/rust-tyty-subst.cc
gcc/testsuite/rust/compile/issue-2905-1.rs [new file with mode: 0644]
gcc/testsuite/rust/compile/issue-2905-2.rs [new file with mode: 0644]
gcc/testsuite/rust/compile/nr2/exclude

index 51ce8277b427ea895dfa909c3319bdc9cd3f330d..ce8e7595c6d7b94c4f0abd9f4616531b610bb452 100644 (file)
@@ -724,6 +724,14 @@ TypeCheckItem::resolve_impl_block_substitutions (HIR::ImplBlock &impl_block,
     }
 
   TyTy::BaseType *self = TypeCheckType::Resolve (impl_block.get_type ().get ());
+  if (self->is<TyTy::ErrorType> ())
+    {
+      // we cannot check for unconstrained type arguments when the Self type is
+      // not resolved it will just add extra errors that dont help as well as
+      // the case where this could just be a recursive type query that should
+      // fail and will work later on anyway
+      return {substitutions, region_constraints};
+    }
 
   // inherit the bounds
   if (!specified_bound.is_error ())
index f2e0405966df36d68de393209b1d472a33bdac55..f3aee8a972106f68db26c70a76c3160bd006f876 100644 (file)
@@ -426,11 +426,8 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
       if (!query_type (ref, &lookup))
        {
          if (is_root)
-           {
-             rust_error_at (seg->get_locus (),
-                            "failed to resolve root segment");
-             return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
-           }
+           return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
+
          return root_tyty;
        }
 
index 48dcd95e181ac898278576fed13b0664e7fe0504..83d0e355f35d3c27e31c9fa3af2c1ecada1e8724 100644 (file)
@@ -634,8 +634,6 @@ SubstitutionRef::get_mappings_from_generic_args (
              if (resolved == nullptr
                  || resolved->get_kind () == TyTy::TypeKind::ERROR)
                {
-                 rust_error_at (binding.get_locus (),
-                                "failed to resolve type arguments");
                  return SubstitutionArgumentMappings::error ();
                }
 
@@ -701,7 +699,6 @@ SubstitutionRef::get_mappings_from_generic_args (
       BaseType *resolved = Resolver::TypeCheckType::Resolve (arg.get ());
       if (resolved == nullptr || resolved->get_kind () == TyTy::TypeKind::ERROR)
        {
-         rust_error_at (args.get_locus (), "failed to resolve type arguments");
          return SubstitutionArgumentMappings::error ();
        }
 
diff --git a/gcc/testsuite/rust/compile/issue-2905-1.rs b/gcc/testsuite/rust/compile/issue-2905-1.rs
new file mode 100644 (file)
index 0000000..9b0c19d
--- /dev/null
@@ -0,0 +1,27 @@
+#![feature(lang_items)]
+
+#[lang = "sized"]
+trait Sized {}
+
+pub struct A<T>(T);
+
+pub trait B {
+    type C;
+}
+
+// ------
+// swap these two items
+
+impl B for i32 {
+    type C = Weird<i32>;
+}
+
+pub struct Weird<T>(A<(T,)>);
+
+// ------
+
+trait Foo {}
+
+impl Foo for Weird<i32> {}
+
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/issue-2905-2.rs b/gcc/testsuite/rust/compile/issue-2905-2.rs
new file mode 100644 (file)
index 0000000..83c54ed
--- /dev/null
@@ -0,0 +1,136 @@
+// { dg-options "-w" }
+#![feature(intrinsics)]
+#![feature(lang_items)]
+
+#[lang = "sized"]
+trait Sized {}
+
+extern "rust-intrinsic" {
+    fn transmute<T, U>(_: T) -> U;
+    fn offset<T>(src: *const T, offset: isize) -> *const T;
+}
+
+pub mod core {
+    pub mod marker {
+        #[lang = "phantom_data"]
+        pub struct PhantomData<T>;
+    }
+
+    pub mod slice {
+        use core::marker::PhantomData;
+        use core::option::Option;
+
+        impl<T> core::iter::IntoIterator for &[T] {
+            type Item = &T;
+            type IntoIter = Weird<T>;
+
+            fn into_iter(self) -> Weird<T> {
+                self.iter()
+            }
+        }
+
+        pub struct Weird<T> {
+            ptr: *const T, // should be NonNull<T> but here it does not matter
+            end: *const T,
+            _marker: PhantomData<&T>,
+        }
+
+        impl<T> Weird<T> {
+            pub(super) fn new(slice: &[T]) -> Self {
+                let ptr = slice.as_ptr();
+                // SAFETY: Similar to `IterMut::new`.
+                unsafe {
+                    // should be: ptr.add(slice.len())
+                    let end = transmute::<*const T, usize>(ptr) + slice.len(); // TODO(Arthur): Missing `* size_of::<T>()`?
+                    let end = transmute::<usize, *const T>(end);
+
+                    Self {
+                        ptr,
+                        end,
+                        _marker: PhantomData,
+                    }
+                }
+            }
+
+            fn is_empty(&self) -> bool {
+                self.ptr == self.end
+            }
+
+            fn next_unchecked(&mut self) -> *const T {
+                let old = self.ptr;
+
+                self.ptr = unsafe { offset(self.ptr, 1) };
+
+                old
+            }
+        }
+
+        trait Foo {}
+
+        impl<T> Foo for Weird<T> {}
+
+        // impl<T> core::iter::Iterator for Iter<T> {
+        //     type Item = &T;
+
+        //     fn next(&mut self) -> Option<&T> {
+        //         if self.is_empty() {
+        //             Option::None
+        //         } else {
+        //             Option::Some(&*self.next_unchecked())
+        //         }
+        //     }
+        // }
+
+        union Repr<T> {
+            pub(crate) rust: *const [T],
+            rust_mut: *mut [T],
+            pub(crate) raw: FatPtr<T>,
+        }
+
+        struct FatPtr<T> {
+            data: *const T,
+            pub(crate) len: usize,
+        }
+
+        impl<T> [T] {
+            pub fn iter(&self) -> Weird<T> {
+                Weird::new(self)
+            }
+
+            pub fn as_ptr(&self) -> *const T {
+                self as *const [T] as *const T
+            }
+
+            pub fn len(&self) -> usize {
+                unsafe { Repr { rust: self }.raw.len }
+            }
+        }
+    }
+
+    pub mod iter {
+        use option::Option;
+
+        pub trait IntoIterator {
+            type Item;
+
+            type IntoIter: Iterator<Item = Self::Item>;
+
+            fn into_iter(self) -> Self::IntoIter;
+        }
+
+        pub trait Iterator {
+            type Item;
+
+            fn next(&mut self) -> Option<Self::Item>;
+        }
+    }
+
+    pub mod option {
+        pub enum Option<T> {
+            Some(T),
+            None,
+        }
+    }
+}
+
+fn main() {}
index efee0fd1e2dd72d7c9c42e52cbf2096284fd79c1..a73b1f027b1d2d2fb5d2bab7fce5d287a8ea7331 100644 (file)
@@ -217,4 +217,6 @@ issue-2323.rs
 issue-2953-1.rs
 issue-2953-2.rs
 issue-1773.rs
+issue-2905-1.rs
+issue-2905-2.rs
 # please don't delete the trailing newline