diff --git a/gcc/rust/typecheck/rust-type-util.cc b/gcc/rust/typecheck/rust-type-util.cc index 079bd956d31..d462b08d11f 100644 --- a/gcc/rust/typecheck/rust-type-util.cc +++ b/gcc/rust/typecheck/rust-type-util.cc @@ -52,7 +52,7 @@ query_type (HirId reference, TyTy::BaseType **result) { HIR::Enum *parent = enum_candidiate.first; HIR::EnumItem *enum_item = enum_candidiate.second; - rust_debug_loc (enum_item->get_locus (), "resolved item {%u} to", + rust_debug_loc (enum_item->get_locus (), "resolved enum item {%u} to", reference); *result = TypeCheckItem::Resolve (*parent); @@ -87,6 +87,14 @@ query_type (HirId reference, TyTy::BaseType **result) // is it an impl_type? if (auto impl_block_by_type = mappings.lookup_impl_block_type (reference)) { + // check if the type is already being resolved + HirId impl_block_type_hirid = impl_block_by_type.value () + ->get_type () + ->get_mappings () + .get_hirid (); + if (context->query_in_progress (impl_block_type_hirid)) + return false; + *result = TypeCheckItem::ResolveImplBlockSelf (*impl_block_by_type.value ()); context->query_completed (reference); 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 00000000000..9b0c19da9bb --- /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); + +pub trait B { + type C; +} + +// ------ +// swap these two items + +impl B for i32 { + type C = Weird; +} + +pub struct Weird(A<(T,)>); + +// ------ + +trait Foo {} + +impl Foo for Weird {} + +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 00000000000..d99cbe5c19e --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-2905-2.rs @@ -0,0 +1,142 @@ +#![feature(intrinsics)] +#![feature(lang_items)] + +#[lang = "sized"] +trait Sized {} + +extern "rust-intrinsic" { + fn transmute(_: T) -> U; + fn offset(src: *const T, offset: isize) -> *const T; +} + +pub mod core { + pub mod marker { + #[lang = "phantom_data"] + pub struct PhantomData; + } + + pub mod slice { + use core::marker::PhantomData; + use core::option::Option; + + impl core::iter::IntoIterator for &[T] { + type Item = &T; + type IntoIter = Weird; + + fn into_iter(self) -> Weird { + self.iter() + } + } + + pub struct Weird { + ptr: *const T, // should be NonNull but here it does not matter + // { dg-warning "field is never read" "" { target *-*-* } .-1 } + end: *const T, + // { dg-warning "field is never read" "" { target *-*-* } .-1 } + _marker: PhantomData<&T>, + // { dg-warning "field is never read" "" { target *-*-* } .-1 } + } + + impl Weird { + pub(super) fn new(slice: &[T]) -> Self { + // { dg-warning "associated function is never used" "" { target *-*-* } .-1 } + 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::()`? + let end = transmute::(end); + + Self { + ptr, + end, + _marker: PhantomData, + } + } + } + + fn is_empty(&self) -> bool { + // { dg-warning "associated function is never used" "" { target *-*-* } .-1 } + self.ptr == self.end + } + + fn next_unchecked(&mut self) -> *const T { + // { dg-warning "associated function is never used" "" { target *-*-* } .-1 } + let old = self.ptr; + + self.ptr = unsafe { offset(self.ptr, 1) }; + + old + } + } + + trait Foo {} + + impl Foo for Weird {} + + // impl core::iter::Iterator for Iter { + // type Item = &T; + + // fn next(&mut self) -> Option<&T> { + // if self.is_empty() { + // Option::None + // } else { + // Option::Some(&*self.next_unchecked()) + // } + // } + // } + + union Repr { + pub(crate) rust: *const [T], + rust_mut: *mut [T], + pub(crate) raw: FatPtr, + } + + struct FatPtr { + // { dg-warning "struct is never constructed" "" { target *-*-* } .-1 } + data: *const T, + pub(crate) len: usize, + } + + impl [T] { + pub fn iter(&self) -> Weird { + 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; + + fn into_iter(self) -> Self::IntoIter; + } + + pub trait Iterator { + type Item; + + fn next(&mut self) -> Option; + } + } + + pub mod option { + pub enum Option { + Some(T), + None, + } + } +} + +fn main() {} diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index efee0fd1e2d..a73b1f027b1 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