From 4a3a0e150d9a746b68fd9851bbc5aefb63f23621 Mon Sep 17 00:00:00 2001 From: Zhang He Date: Tue, 28 Jan 2025 14:45:47 +0800 Subject: [PATCH] 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 * util/rust-hir-map.cc: add the map lookup lang item by defid * util/rust-hir-map.h: add the map lookup lang item by defid gcc/testsuite/ChangeLog: * rust/compile/issue-2500-rustc.rs: testsuite case same with rustc * rust/compile/issue-2500.rs: testsuite case * rust/compile/const-issue1440.rs: add lang item attribute * rust/compile/issue-1005.rs: add lang item attribute * rust/compile/issue-1130.rs: add lang item attribute * rust/compile/issue-1235.rs: add lang item attribute * rust/compile/issue-1237.rs: add lang item attribute * rust/compile/issue-2190-2.rs: add lang item attribute * rust/compile/issue-2905-2.rs: add lang item attribute * rust/compile/iterators1.rs: add lang item attribute * rust/compile/macros/mbe/macro-issue1233.rs: add lang item attribute * rust/compile/macros/mbe/macro54.rs: add lang item attribute * rust/compile/torture/intrinsics-8.rs: add lang item attribute * rust/compile/torture/issue-1075.rs: add lang item attribute * rust/compile/torture/issue-1432.rs: add lang item attribute * rust/execute/torture/issue-1436.rs: add lang item attribute * rust/execute/torture/issue-2236.rs: add lang item attribute * rust/execute/torture/iter1.rs: add lang item attribute * rust/execute/torture/str-layout1.rs: add lang item attribute Signed-off-by: Zhang He --- .../typecheck/rust-hir-inherent-impl-check.h | 85 +++++++++++++++++++ gcc/rust/typecheck/rust-hir-type-check.cc | 5 ++ gcc/rust/typecheck/rust-tyty.cc | 6 ++ gcc/rust/util/rust-hir-map.cc | 14 ++- gcc/rust/util/rust-hir-map.h | 3 +- gcc/testsuite/rust/compile/const-issue1440.rs | 1 + gcc/testsuite/rust/compile/issue-1005.rs | 1 + gcc/testsuite/rust/compile/issue-1130.rs | 1 + gcc/testsuite/rust/compile/issue-1235.rs | 1 + gcc/testsuite/rust/compile/issue-1237.rs | 2 + gcc/testsuite/rust/compile/issue-2190-2.rs | 1 + .../rust/compile/issue-2500-rustc.rs | 25 ++++++ gcc/testsuite/rust/compile/issue-2500.rs | 9 ++ gcc/testsuite/rust/compile/issue-2905-2.rs | 1 + gcc/testsuite/rust/compile/iterators1.rs | 1 + .../compile/macros/mbe/macro-issue1233.rs | 1 + .../rust/compile/macros/mbe/macro54.rs | 1 + .../rust/compile/torture/intrinsics-8.rs | 1 + .../rust/compile/torture/issue-1075.rs | 2 + .../rust/compile/torture/issue-1432.rs | 1 + .../rust/execute/torture/issue-1436.rs | 1 + .../rust/execute/torture/issue-2236.rs | 1 + gcc/testsuite/rust/execute/torture/iter1.rs | 1 + .../rust/execute/torture/str-layout1.rs | 2 + 24 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 gcc/rust/typecheck/rust-hir-inherent-impl-check.h create mode 100644 gcc/testsuite/rust/compile/issue-2500-rustc.rs create mode 100644 gcc/testsuite/rust/compile/issue-2500.rs 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 000000000000..2426a911d014 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-inherent-impl-check.h @@ -0,0 +1,85 @@ +// Copyright (C) 2020-2025 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-diagnostics.h" +#include "rust-hir-item.h" +#include "rust-hir-type-check-base.h" +#include "rust-mapping-common.h" +#include "rust-type-util.h" + +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; + DefId defid = impl->get_mappings ().get_defid (); + // ignore lang item + if (mappings.lookup_lang_item (defid)) + 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 1e9f7d2f00dd..2cc2d85340fc 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -19,6 +19,7 @@ #include "rust-hir-type-check.h" #include "rust-hir-full.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 +78,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 116c1abdf8e8..2e1728b3a861 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/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index 4d2927281a21..705bcd472de4 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -1266,8 +1266,11 @@ Mappings::insert_lang_item (LangItem::Kind item_type, DefId id) { auto it = lang_item_mappings.find (item_type); rust_assert (it == lang_item_mappings.end ()); - lang_item_mappings[item_type] = id; + + auto rit = rev_lang_item_mappings.find (id); + rust_assert (rit == rev_lang_item_mappings.end ()); + rev_lang_item_mappings[id] = item_type; } tl::optional @@ -1280,6 +1283,15 @@ Mappings::lookup_lang_item (LangItem::Kind item_type) return it->second; } +tl::optional +Mappings::lookup_lang_item (DefId id) +{ + auto it = rev_lang_item_mappings.find (id); + if (it == rev_lang_item_mappings.end ()) + return tl::nullopt; + return it->second; +} + void Mappings::insert_lang_item_node (LangItem::Kind item_type, NodeId node_id) { diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index 6f21f38b4491..ff72a42b822e 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -258,7 +258,7 @@ class Mappings void insert_lang_item (LangItem::Kind item_type, DefId id); tl::optional lookup_lang_item (LangItem::Kind item_type); - + tl::optional lookup_lang_item (DefId id); void insert_lang_item_node (LangItem::Kind item_type, NodeId node_id); tl::optional lookup_lang_item_node (LangItem::Kind item_type); NodeId get_lang_item_node (LangItem::Kind item_type); @@ -391,6 +391,7 @@ class Mappings // We need to have two maps here, as lang-items need to be used for both AST // passes and HIR passes. Thus those two maps are created at different times. std::map lang_item_mappings; + std::map rev_lang_item_mappings; std::map lang_item_nodes; std::map paths; diff --git a/gcc/testsuite/rust/compile/const-issue1440.rs b/gcc/testsuite/rust/compile/const-issue1440.rs index 3a2989cc8d02..1cf87c0c6c15 100644 --- a/gcc/testsuite/rust/compile/const-issue1440.rs +++ b/gcc/testsuite/rust/compile/const-issue1440.rs @@ -24,6 +24,7 @@ mod mem { macro_rules! impl_uint { ($($ty:ident = $lang:literal),*) => { $( + #[lang = $lang] impl $ty { pub fn wrapping_add(self, rhs: Self) -> Self { // intrinsics::wrapping_add(self, rhs) diff --git a/gcc/testsuite/rust/compile/issue-1005.rs b/gcc/testsuite/rust/compile/issue-1005.rs index 15d4bef08c2a..e4bd7aa69046 100644 --- a/gcc/testsuite/rust/compile/issue-1005.rs +++ b/gcc/testsuite/rust/compile/issue-1005.rs @@ -2,6 +2,7 @@ #[lang = "sized"] pub trait Sized {} +#[lang = "const_ptr"] impl *const T { fn test(self) {} } diff --git a/gcc/testsuite/rust/compile/issue-1130.rs b/gcc/testsuite/rust/compile/issue-1130.rs index 115e6aad2f15..69db6e04072f 100644 --- a/gcc/testsuite/rust/compile/issue-1130.rs +++ b/gcc/testsuite/rust/compile/issue-1130.rs @@ -11,6 +11,7 @@ mod mem { } } +#[lang = "u16"] impl u16 { fn to_ne_bytes(self) -> [u8; mem::size_of::()] { unsafe { mem::transmute(self) } diff --git a/gcc/testsuite/rust/compile/issue-1235.rs b/gcc/testsuite/rust/compile/issue-1235.rs index 7c85ac4a6b00..9ff9ced6b63a 100644 --- a/gcc/testsuite/rust/compile/issue-1235.rs +++ b/gcc/testsuite/rust/compile/issue-1235.rs @@ -13,6 +13,7 @@ pub union Repr { raw: FatPtr, } +#[lang = "slice"] impl [T] { pub const fn is_empty(&self) -> bool { self.len() == 0 diff --git a/gcc/testsuite/rust/compile/issue-1237.rs b/gcc/testsuite/rust/compile/issue-1237.rs index 79b60b07b522..cdc715ab5197 100644 --- a/gcc/testsuite/rust/compile/issue-1237.rs +++ b/gcc/testsuite/rust/compile/issue-1237.rs @@ -10,12 +10,14 @@ mod intrinsics { } } +#[lang = "const_ptr"] impl *const T { pub unsafe fn offset(self, count: isize) -> *const T { unsafe { intrinsics::offset(self, count) } } } +#[lang = "slice"] impl [T] { pub unsafe fn get_unchecked(&self, index: usize) -> &T { unsafe { &*(self as *const [T] as *const T).offset(index as isize) } diff --git a/gcc/testsuite/rust/compile/issue-2190-2.rs b/gcc/testsuite/rust/compile/issue-2190-2.rs index 1c933386aa46..b8e0331649d9 100644 --- a/gcc/testsuite/rust/compile/issue-2190-2.rs +++ b/gcc/testsuite/rust/compile/issue-2190-2.rs @@ -12,6 +12,7 @@ fn foo>(t: &T) -> i32 { t.max(2) } +#[lang = "i32"] impl i32 { fn max(self, other: i32) -> i32 { if self > other { 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 000000000000..e9dbc5aa3546 --- /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 000000000000..eacb45a7728f --- /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 diff --git a/gcc/testsuite/rust/compile/issue-2905-2.rs b/gcc/testsuite/rust/compile/issue-2905-2.rs index 83c54ed92e5f..7a5e7420f247 100644 --- a/gcc/testsuite/rust/compile/issue-2905-2.rs +++ b/gcc/testsuite/rust/compile/issue-2905-2.rs @@ -92,6 +92,7 @@ pub mod core { pub(crate) len: usize, } + #[lang = "slice"] impl [T] { pub fn iter(&self) -> Weird { Weird::new(self) diff --git a/gcc/testsuite/rust/compile/iterators1.rs b/gcc/testsuite/rust/compile/iterators1.rs index 1141758b14a7..55d5942ef868 100644 --- a/gcc/testsuite/rust/compile/iterators1.rs +++ b/gcc/testsuite/rust/compile/iterators1.rs @@ -207,6 +207,7 @@ mod mem { macro_rules! impl_uint { ($($ty:ident = $lang:literal),*) => { $( + #[lang = $lang] impl $ty { pub fn wrapping_add(self, rhs: Self) -> Self { unsafe { diff --git a/gcc/testsuite/rust/compile/macros/mbe/macro-issue1233.rs b/gcc/testsuite/rust/compile/macros/mbe/macro-issue1233.rs index 7fab787b9e8d..4c003dcf3488 100644 --- a/gcc/testsuite/rust/compile/macros/mbe/macro-issue1233.rs +++ b/gcc/testsuite/rust/compile/macros/mbe/macro-issue1233.rs @@ -3,6 +3,7 @@ macro_rules! impl_uint { ($($ty:ident = $lang:literal),*) => { $( + #[lang = $lang] impl $ty { pub fn to_le(self) -> Self { #[cfg(not(A))] diff --git a/gcc/testsuite/rust/compile/macros/mbe/macro54.rs b/gcc/testsuite/rust/compile/macros/mbe/macro54.rs index d3b3f806a6a0..8f0fc6654d4a 100644 --- a/gcc/testsuite/rust/compile/macros/mbe/macro54.rs +++ b/gcc/testsuite/rust/compile/macros/mbe/macro54.rs @@ -18,6 +18,7 @@ impl Number for u32 { const VALUE: u32 = foo!(number); } +#[lang = "u32"] impl u32 { pub const TWELVE: u32 = foo!(number); } diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-8.rs b/gcc/testsuite/rust/compile/torture/intrinsics-8.rs index b9bd83c76240..47a9098ffa6a 100644 --- a/gcc/testsuite/rust/compile/torture/intrinsics-8.rs +++ b/gcc/testsuite/rust/compile/torture/intrinsics-8.rs @@ -16,6 +16,7 @@ pub enum Option { Some(T), } +#[lang = "i32"] impl i32 { pub fn checked_add(self, rhs: Self) -> Option { let (a, b) = self.overflowing_add(rhs); diff --git a/gcc/testsuite/rust/compile/torture/issue-1075.rs b/gcc/testsuite/rust/compile/torture/issue-1075.rs index d23774b2c0bb..ba1d424494ce 100644 --- a/gcc/testsuite/rust/compile/torture/issue-1075.rs +++ b/gcc/testsuite/rust/compile/torture/issue-1075.rs @@ -20,6 +20,7 @@ union Repr { raw: FatPtr, } +#[lang = "const_slice_ptr"] impl *const [T] { pub const fn len(self) -> usize { // SAFETY: this is safe because `*const [T]` and `FatPtr` have the same layout. @@ -32,6 +33,7 @@ impl *const [T] { } } +#[lang = "const_ptr"] impl *const T { pub const unsafe fn offset(self, count: isize) -> *const T { unsafe { offset(self, count) } diff --git a/gcc/testsuite/rust/compile/torture/issue-1432.rs b/gcc/testsuite/rust/compile/torture/issue-1432.rs index 5b526fdd52db..e66a9bd3c1ba 100644 --- a/gcc/testsuite/rust/compile/torture/issue-1432.rs +++ b/gcc/testsuite/rust/compile/torture/issue-1432.rs @@ -29,6 +29,7 @@ mod mem { macro_rules! impl_uint { ($($ty:ident = $lang:literal),*) => { $( + #[lang = $lang] impl $ty { pub fn wrapping_add(self, rhs: Self) -> Self { // intrinsics::wrapping_add(self, rhs) diff --git a/gcc/testsuite/rust/execute/torture/issue-1436.rs b/gcc/testsuite/rust/execute/torture/issue-1436.rs index 5d909078b5ec..769ef672839b 100644 --- a/gcc/testsuite/rust/execute/torture/issue-1436.rs +++ b/gcc/testsuite/rust/execute/torture/issue-1436.rs @@ -86,6 +86,7 @@ trait Index { fn index(&self, index: Idx) -> &Self::Output; } +#[lang = "slice"] impl [T] { pub const fn is_empty(&self) -> bool { self.len() == 0 diff --git a/gcc/testsuite/rust/execute/torture/issue-2236.rs b/gcc/testsuite/rust/execute/torture/issue-2236.rs index 850b99718ef6..884c46bd36bd 100644 --- a/gcc/testsuite/rust/execute/torture/issue-2236.rs +++ b/gcc/testsuite/rust/execute/torture/issue-2236.rs @@ -20,6 +20,7 @@ mod core { } } +#[lang = "i32"] impl i32 { fn max(self, other: i32) -> i32 { if self > other { diff --git a/gcc/testsuite/rust/execute/torture/iter1.rs b/gcc/testsuite/rust/execute/torture/iter1.rs index c3b6c7bc3f89..6ff9529ad42e 100644 --- a/gcc/testsuite/rust/execute/torture/iter1.rs +++ b/gcc/testsuite/rust/execute/torture/iter1.rs @@ -208,6 +208,7 @@ mod mem { macro_rules! impl_uint { ($($ty:ident = $lang:literal),*) => { $( + #[lang = $lang] impl $ty { pub fn wrapping_add(self, rhs: Self) -> Self { unsafe { diff --git a/gcc/testsuite/rust/execute/torture/str-layout1.rs b/gcc/testsuite/rust/execute/torture/str-layout1.rs index fb3b4e34a7c2..e76b43948672 100644 --- a/gcc/testsuite/rust/execute/torture/str-layout1.rs +++ b/gcc/testsuite/rust/execute/torture/str-layout1.rs @@ -27,12 +27,14 @@ pub union Repr { raw: FatPtr, } +#[lang = "slice"] impl [T] { pub const fn len(&self) -> usize { unsafe { Repr { rust: self }.raw.len } } } +#[lang = "str"] impl str { pub const fn len(&self) -> usize { self.as_bytes().len()