diff --git a/gcc/rust/typecheck/rust-hir-inherent-impl-check.h b/gcc/rust/typecheck/rust-hir-inherent-impl-check.h new file mode 100644 index 00000000000..3b8d3df8b34 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-inherent-impl-check.h @@ -0,0 +1,81 @@ +// Copyright (C) 2020-2024 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . +#ifndef RUST_HIR_INHERENT_IMPL_ITEM_CHECK_H +#define RUST_HIR_INHERENT_IMPL_ITEM_CHECK_H + +#include "rust-hir-item.h" +#include "rust-hir-type-check-base.h" +#include "rust-type-util.h" +#include + +namespace Rust { +namespace Resolver { + +class PrimitiveImplCheck : public TypeCheckBase +{ +public: + static void go () + { + PrimitiveImplCheck pass; + + pass.scan (); + } + +private: + void scan () + + { + std::vector possible_primitive_impl; + mappings.iterate_impl_blocks ([&] (HirId id, HIR::ImplBlock *impl) -> bool { + // filtering trait-impl-blocks + if (impl->has_trait_ref ()) + return true; + HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid (); + TyTy::BaseType *impl_type = nullptr; + if (!query_type (impl_ty_id, &impl_type)) + return true; + if (is_primitive_type_kind (impl_type->get_kind ())) + { + possible_primitive_impl.push_back (impl); + } + return true; + }); + + for (auto impl : possible_primitive_impl) + { + report_error (impl); + } + } + + void report_error (HIR::ImplBlock *impl) + + { + rich_location r (line_table, impl->get_locus ()); + std::string msg = "consider using an extension trait instead"; + r.add_fixit_replace (impl->get_locus (), msg.c_str ()); + r.add_range (impl->get_locus ()); + std::string err = "impl"; + err = "cannot define inherent `" + err + "` for primitive types"; + rust_error_at (r, ErrorCode::E0390, "%s", err.c_str ()); + } +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_INHERENT_IMPL_ITEM_CHECK_H diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index 1e9f7d2f00d..6f3acb0313b 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -18,7 +18,9 @@ #include "rust-hir-type-check.h" #include "rust-hir-full.h" +#include "rust-hir-inherent-impl-check.h" #include "rust-hir-inherent-impl-overlap.h" +#include "rust-hir-inherent-impl-check.h" #include "rust-hir-pattern.h" #include "rust-hir-type-check-expr.h" #include "rust-hir-type-check-item.h" @@ -77,6 +79,10 @@ TypeResolution::Resolve (HIR::Crate &crate) if (saw_errors ()) return; + PrimitiveImplCheck::go (); + if (saw_errors ()) + return; + OverlappingImplItemPass::go (); if (saw_errors ()) return; diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 116c1abdf8e..2e1728b3a86 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -131,6 +131,12 @@ is_primitive_type_kind (TypeKind kind) case TypeKind::FLOAT: case TypeKind::NEVER: case TypeKind::STR: + case TypeKind::ARRAY: + case TypeKind::SLICE: + case TypeKind::POINTER: + case TypeKind::REF: + case TypeKind::FNPTR: + case TypeKind::TUPLE: return true; default: return false; diff --git a/gcc/testsuite/rust/compile/issue-2500-rustc.rs b/gcc/testsuite/rust/compile/issue-2500-rustc.rs new file mode 100644 index 00000000000..e9dbc5aa354 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-2500-rustc.rs @@ -0,0 +1,25 @@ +impl u8 { + // { dg-error "cannot define inherent `impl` for primitive types" "" { target *-*-* } .-1 } + pub const B: u8 = 0; +} + +impl str { + // { dg-error "cannot define inherent `impl` for primitive types" "" { target *-*-* } .-1 } + fn foo() {} +} + +impl char { + // { dg-error "cannot define inherent `impl` for primitive types" "" { target *-*-* } .-1 } + pub const B: u8 = 0; + pub const C: u8 = 0; + fn foo() {} + fn bar(self) {} +} + +struct MyType; +impl &MyType { + // { dg-error "cannot define inherent `impl` for primitive types" "" { target *-*-* } .-1 } + pub fn for_ref(self) {} +} + +fn main() {} diff --git a/gcc/testsuite/rust/compile/issue-2500.rs b/gcc/testsuite/rust/compile/issue-2500.rs new file mode 100644 index 00000000000..eacb45a7728 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-2500.rs @@ -0,0 +1,9 @@ +#![allow(unused)] +fn main() { +struct Foo { + x: i32 +} + +impl *mut Foo {} +// { dg-error "cannot define inherent `impl` for primitive types" "" { target *-*-* } .-1 } +} \ No newline at end of file