Skip to content

Commit 6431cff

Browse files
committed
gccrs: fnptr types can hold onto generic params so it needs to handle substs
This patch adds support to recursively walk fnptr types to do generic substitutions. Fixes #4090 gcc/rust/ChangeLog: * typecheck/rust-substitution-mapper.cc (SubstMapperInternal::visit): handle fnptr * typecheck/rust-tyty.cc (FnPtr::handle_substitions): new * typecheck/rust-tyty.h: likewise gcc/testsuite/ChangeLog: * rust/compile/issue-4090-1.rs: New test. * rust/compile/issue-4090-2.rs: New test. Signed-off-by: Philip Herron <[email protected]>
1 parent b404117 commit 6431cff

File tree

5 files changed

+180
-5
lines changed

5 files changed

+180
-5
lines changed

gcc/rust/typecheck/rust-substitution-mapper.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -310,15 +310,15 @@ SubstMapperInternal::visit (TyTy::SliceType &type)
310310
{
311311
resolved = type.handle_substitions (mappings);
312312
}
313-
314-
// nothing to do for these
315313
void
316-
SubstMapperInternal::visit (TyTy::InferType &type)
314+
SubstMapperInternal::visit (TyTy::FnPtr &type)
317315
{
318-
resolved = type.clone ();
316+
resolved = type.handle_substitions (mappings);
319317
}
318+
319+
// nothing to do for these
320320
void
321-
SubstMapperInternal::visit (TyTy::FnPtr &type)
321+
SubstMapperInternal::visit (TyTy::InferType &type)
322322
{
323323
resolved = type.clone ();
324324
}

gcc/rust/typecheck/rust-tyty.cc

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2314,6 +2314,40 @@ FnPtr::clone () const
23142314
get_unsafety (), get_combined_refs ());
23152315
}
23162316

2317+
FnPtr *
2318+
FnPtr::handle_substitions (SubstitutionArgumentMappings &mappings)
2319+
{
2320+
auto &mappings_table = Analysis::Mappings::get ();
2321+
2322+
auto fn = clone ()->as<FnPtr> ();
2323+
fn->set_ref (mappings_table.get_next_hir_id ());
2324+
fn->set_ty_ref (mappings_table.get_next_hir_id ());
2325+
2326+
if (!fn->result_type.get_tyty ()->is_concrete ())
2327+
{
2328+
BaseType *concrete
2329+
= Resolver::SubstMapperInternal::Resolve (fn->result_type.get_tyty (),
2330+
mappings);
2331+
fn->result_type
2332+
= TyVar::subst_covariant_var (fn->result_type.get_tyty (), concrete);
2333+
}
2334+
2335+
for (size_t i = 0; i < fn->params.size (); i++)
2336+
{
2337+
TyVar &field = fn->params.at (i);
2338+
if (!field.get_tyty ()->is_concrete ())
2339+
{
2340+
BaseType *concrete
2341+
= Resolver::SubstMapperInternal::Resolve (field.get_tyty (),
2342+
mappings);
2343+
fn->params[i]
2344+
= TyVar::subst_covariant_var (field.get_tyty (), concrete);
2345+
}
2346+
}
2347+
2348+
return fn;
2349+
}
2350+
23172351
void
23182352
ClosureType::accept_vis (TyVisitor &vis)
23192353
{

gcc/rust/typecheck/rust-tyty.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,8 @@ class FnPtr : public CallableTypeInterface
11011101

11021102
Unsafety get_unsafety () const { return unsafety; }
11031103

1104+
FnPtr *handle_substitions (SubstitutionArgumentMappings &mappings);
1105+
11041106
private:
11051107
std::vector<TyVar> params;
11061108
TyVar result_type;
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
mod core {
2+
mod marker {
3+
#[lang = "sized"]
4+
pub trait Sized {}
5+
6+
#[lang = "phantom_data"]
7+
#[stable(feature = "rust1", since = "1.0.0")]
8+
pub struct PhantomData<T: ?Sized>;
9+
10+
#[unstable(feature = "structural_match", issue = "31434")]
11+
#[lang = "structural_teq"]
12+
pub trait StructuralEq {
13+
// Empty.
14+
}
15+
16+
#[unstable(feature = "structural_match", issue = "31434")]
17+
#[lang = "structural_peq"]
18+
pub trait StructuralPartialEq {
19+
// Empty.
20+
}
21+
}
22+
23+
pub mod cmp {
24+
use super::marker::Sized;
25+
26+
#[lang = "eq"]
27+
pub trait PartialEq<Rhs: ?Sized = Self> {
28+
fn eq(&self, other: &Rhs) -> bool;
29+
30+
fn ne(&self, other: &Rhs) -> bool {
31+
!self.eq(other)
32+
}
33+
}
34+
35+
pub trait Eq: PartialEq<Self> {
36+
fn assert_receiver_is_total_eq(&self) {}
37+
}
38+
}
39+
40+
pub mod ptr {
41+
42+
use super::cmp::{Eq, PartialEq};
43+
44+
macro_rules! fnptr_impls_safety_abi {
45+
($FnTy: ty, $($Arg: ident),*) => {
46+
#[stable(feature = "fnptr_impls", since = "1.4.0")]
47+
impl<Ret, $($Arg),*> PartialEq for $FnTy {
48+
#[inline]
49+
fn eq(&self, other: &Self) -> bool {
50+
*self as usize == *other as usize
51+
}
52+
}
53+
54+
#[stable(feature = "fnptr_impls", since = "1.4.0")]
55+
impl<Ret, $($Arg),*> Eq for $FnTy {}
56+
57+
}
58+
}
59+
60+
fnptr_impls_safety_abi! { extern "Rust" fn() -> Ret, }
61+
}
62+
}
63+
64+
#[derive(PartialEq, Eq)]
65+
struct AllowedBelow {
66+
// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
67+
f: fn(),
68+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
mod core {
2+
mod marker {
3+
#[lang = "sized"]
4+
pub trait Sized {}
5+
6+
#[lang = "phantom_data"]
7+
#[stable(feature = "rust1", since = "1.0.0")]
8+
pub struct PhantomData<T: ?Sized>;
9+
10+
#[unstable(feature = "structural_match", issue = "31434")]
11+
#[lang = "structural_teq"]
12+
pub trait StructuralEq {
13+
// Empty.
14+
}
15+
16+
#[unstable(feature = "structural_match", issue = "31434")]
17+
#[lang = "structural_peq"]
18+
pub trait StructuralPartialEq {
19+
// Empty.
20+
}
21+
}
22+
23+
pub mod cmp {
24+
use super::marker::Sized;
25+
26+
#[lang = "eq"]
27+
pub trait PartialEq<Rhs: ?Sized = Self> {
28+
fn eq(&self, other: &Rhs) -> bool;
29+
30+
fn ne(&self, other: &Rhs) -> bool {
31+
!self.eq(other)
32+
}
33+
}
34+
35+
pub trait Eq: PartialEq<Self> {
36+
fn assert_receiver_is_total_eq(&self) {}
37+
}
38+
}
39+
40+
pub mod ptr {
41+
42+
use super::cmp::{Eq, PartialEq};
43+
44+
macro_rules! fnptr_impls_safety_abi {
45+
($FnTy: ty, $($Arg: ident),*) => {
46+
#[stable(feature = "fnptr_impls", since = "1.4.0")]
47+
impl<Ret, $($Arg),*> PartialEq for $FnTy {
48+
#[inline]
49+
fn eq(&self, other: &Self) -> bool {
50+
*self as usize == *other as usize
51+
}
52+
}
53+
54+
#[stable(feature = "fnptr_impls", since = "1.4.0")]
55+
impl<Ret, $($Arg),*> Eq for $FnTy {}
56+
57+
}
58+
}
59+
60+
fnptr_impls_safety_abi! { extern "Rust" fn() -> Ret, }
61+
fnptr_impls_safety_abi! { extern "C" fn() -> Ret, }
62+
fnptr_impls_safety_abi! { unsafe extern "Rust" fn() -> Ret, }
63+
fnptr_impls_safety_abi! { unsafe extern "C" fn() -> Ret, }
64+
}
65+
}
66+
67+
#[derive(PartialEq, Eq)]
68+
struct AllowedBelow {
69+
// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
70+
f: fn(),
71+
}

0 commit comments

Comments
 (0)