aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <herron.philip@googlemail.com>2024-11-12 12:16:40 +0000
committerArthur Cohen <arthur.cohen@embecosm.com>2025-03-21 12:32:56 +0100
commit2992ff08f68e7b9bb36cdeb6747cdc1ee9015d54 (patch)
tree97a1c133cdcc7f0dcd1cc3fe8cab5e9f9293b7ad /gcc
parent1e12ef057250e1d3a4a53697862bc270d9cfa45c (diff)
downloadgcc-2992ff08f68e7b9bb36cdeb6747cdc1ee9015d54.zip
gcc-2992ff08f68e7b9bb36cdeb6747cdc1ee9015d54.tar.gz
gcc-2992ff08f68e7b9bb36cdeb6747cdc1ee9015d54.tar.bz2
gccrs: Fix bad handling for recursive type query
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>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.cc8
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.cc7
-rw-r--r--gcc/rust/typecheck/rust-tyty-subst.cc3
-rw-r--r--gcc/testsuite/rust/compile/issue-2905-1.rs27
-rw-r--r--gcc/testsuite/rust/compile/issue-2905-2.rs136
-rw-r--r--gcc/testsuite/rust/compile/nr2/exclude2
6 files changed, 175 insertions, 8 deletions
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc
index 28368d4..0652777 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc
@@ -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 ())
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc
index ee17e53..0ff4ac4 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -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;
}
diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc
index a3ebf0a..575f04a 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -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
index 0000000..9b0c19d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2905-1.rs
@@ -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
index 0000000..83c54ed
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2905-2.rs
@@ -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() {}
diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude
index efee0fd..a73b1f0 100644
--- a/gcc/testsuite/rust/compile/nr2/exclude
+++ b/gcc/testsuite/rust/compile/nr2/exclude
@@ -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