Skip to content

Commit

Permalink
Fixes #2500
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
zhanghe9702 committed Jan 28, 2025
1 parent 98d89d5 commit c8b9399
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 0 deletions.
81 changes: 81 additions & 0 deletions gcc/rust/typecheck/rust-hir-inherent-impl-check.h
Original file line number Diff line number Diff line change
@@ -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
// <http://www.gnu.org/licenses/>.
#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 <vector>

namespace Rust {
namespace Resolver {

class PrimitiveImplCheck : public TypeCheckBase
{
public:
static void go ()
{
PrimitiveImplCheck pass;

pass.scan ();
}

private:
void scan ()

{
std::vector<HIR::ImplBlock *> 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
6 changes: 6 additions & 0 deletions gcc/rust/typecheck/rust-hir-type-check.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions gcc/rust/typecheck/rust-tyty.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
25 changes: 25 additions & 0 deletions gcc/testsuite/rust/compile/issue-2500-rustc.rs
Original file line number Diff line number Diff line change
@@ -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() {}
9 changes: 9 additions & 0 deletions gcc/testsuite/rust/compile/issue-2500.rs
Original file line number Diff line number Diff line change
@@ -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 }
}

0 comments on commit c8b9399

Please sign in to comment.