Skip to content

Commit c8b9399

Browse files
committed
Fixes #2500
Add a seperate typecheck pass collect impl blocks, then report errors. gcc/rust/ChangeLog: * typecheck/rust-hir-inherent-impl-check.h: new typecheck pass * typecheck/rust-hir-type-check.cc: modify the function which test primitive type * typecheck/rust-tyty.cc: the new typecheck pass entrypoint gcc/testsuite/ChangeLog: * rust/compile/issue-2500-rustc.rs: testsuite case same with rustc * rust/compile/issue-2500.rs: testsuite case Signed-off-by: Zhang He <[email protected]>
1 parent 98d89d5 commit c8b9399

File tree

5 files changed

+127
-0
lines changed

5 files changed

+127
-0
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright (C) 2020-2024 Free Software Foundation, Inc.
2+
3+
// This file is part of GCC.
4+
5+
// GCC is free software; you can redistribute it and/or modify it under
6+
// the terms of the GNU General Public License as published by the Free
7+
// Software Foundation; either version 3, or (at your option) any later
8+
// version.
9+
10+
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
// for more details.
14+
15+
// You should have received a copy of the GNU General Public License
16+
// along with GCC; see the file COPYING3. If not see
17+
// <http://www.gnu.org/licenses/>.
18+
#ifndef RUST_HIR_INHERENT_IMPL_ITEM_CHECK_H
19+
#define RUST_HIR_INHERENT_IMPL_ITEM_CHECK_H
20+
21+
#include "rust-hir-item.h"
22+
#include "rust-hir-type-check-base.h"
23+
#include "rust-type-util.h"
24+
#include <vector>
25+
26+
namespace Rust {
27+
namespace Resolver {
28+
29+
class PrimitiveImplCheck : public TypeCheckBase
30+
{
31+
public:
32+
static void go ()
33+
{
34+
PrimitiveImplCheck pass;
35+
36+
pass.scan ();
37+
}
38+
39+
private:
40+
void scan ()
41+
42+
{
43+
std::vector<HIR::ImplBlock *> possible_primitive_impl;
44+
mappings.iterate_impl_blocks ([&] (HirId id, HIR::ImplBlock *impl) -> bool {
45+
// filtering trait-impl-blocks
46+
if (impl->has_trait_ref ())
47+
return true;
48+
HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid ();
49+
TyTy::BaseType *impl_type = nullptr;
50+
if (!query_type (impl_ty_id, &impl_type))
51+
return true;
52+
if (is_primitive_type_kind (impl_type->get_kind ()))
53+
{
54+
possible_primitive_impl.push_back (impl);
55+
}
56+
return true;
57+
});
58+
59+
for (auto impl : possible_primitive_impl)
60+
{
61+
report_error (impl);
62+
}
63+
}
64+
65+
void report_error (HIR::ImplBlock *impl)
66+
67+
{
68+
rich_location r (line_table, impl->get_locus ());
69+
std::string msg = "consider using an extension trait instead";
70+
r.add_fixit_replace (impl->get_locus (), msg.c_str ());
71+
r.add_range (impl->get_locus ());
72+
std::string err = "impl";
73+
err = "cannot define inherent `" + err + "` for primitive types";
74+
rust_error_at (r, ErrorCode::E0390, "%s", err.c_str ());
75+
}
76+
};
77+
78+
} // namespace Resolver
79+
} // namespace Rust
80+
81+
#endif // RUST_HIR_INHERENT_IMPL_ITEM_CHECK_H

gcc/rust/typecheck/rust-hir-type-check.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818

1919
#include "rust-hir-type-check.h"
2020
#include "rust-hir-full.h"
21+
#include "rust-hir-inherent-impl-check.h"
2122
#include "rust-hir-inherent-impl-overlap.h"
23+
#include "rust-hir-inherent-impl-check.h"
2224
#include "rust-hir-pattern.h"
2325
#include "rust-hir-type-check-expr.h"
2426
#include "rust-hir-type-check-item.h"
@@ -77,6 +79,10 @@ TypeResolution::Resolve (HIR::Crate &crate)
7779
if (saw_errors ())
7880
return;
7981

82+
PrimitiveImplCheck::go ();
83+
if (saw_errors ())
84+
return;
85+
8086
OverlappingImplItemPass::go ();
8187
if (saw_errors ())
8288
return;

gcc/rust/typecheck/rust-tyty.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ is_primitive_type_kind (TypeKind kind)
131131
case TypeKind::FLOAT:
132132
case TypeKind::NEVER:
133133
case TypeKind::STR:
134+
case TypeKind::ARRAY:
135+
case TypeKind::SLICE:
136+
case TypeKind::POINTER:
137+
case TypeKind::REF:
138+
case TypeKind::FNPTR:
139+
case TypeKind::TUPLE:
134140
return true;
135141
default:
136142
return false;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
impl u8 {
2+
// { dg-error "cannot define inherent `impl` for primitive types" "" { target *-*-* } .-1 }
3+
pub const B: u8 = 0;
4+
}
5+
6+
impl str {
7+
// { dg-error "cannot define inherent `impl` for primitive types" "" { target *-*-* } .-1 }
8+
fn foo() {}
9+
}
10+
11+
impl char {
12+
// { dg-error "cannot define inherent `impl` for primitive types" "" { target *-*-* } .-1 }
13+
pub const B: u8 = 0;
14+
pub const C: u8 = 0;
15+
fn foo() {}
16+
fn bar(self) {}
17+
}
18+
19+
struct MyType;
20+
impl &MyType {
21+
// { dg-error "cannot define inherent `impl` for primitive types" "" { target *-*-* } .-1 }
22+
pub fn for_ref(self) {}
23+
}
24+
25+
fn main() {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#![allow(unused)]
2+
fn main() {
3+
struct Foo {
4+
x: i32
5+
}
6+
7+
impl *mut Foo {}
8+
// { dg-error "cannot define inherent `impl` for primitive types" "" { target *-*-* } .-1 }
9+
}

0 commit comments

Comments
 (0)