Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gccrs: Fix recursive type query on impl block types #3245

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion gcc/rust/typecheck/rust-type-util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
27 changes: 27 additions & 0 deletions gcc/testsuite/rust/compile/issue-2905-1.rs
Original file line number Diff line number Diff line change
@@ -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() {}
142 changes: 142 additions & 0 deletions gcc/testsuite/rust/compile/issue-2905-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#![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
// { 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<T> Weird<T> {
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::<T>()`?
let end = transmute::<usize, *const T>(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<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> {
// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
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() {}
2 changes: 2 additions & 0 deletions gcc/testsuite/rust/compile/nr2/exclude
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading