From 4413bc0cf8b98702e8dd9e88ab5c0e19903e58e7 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 30 Mar 2022 18:13:48 +0100 Subject: Fix bad inherent overlap error When we examine HIR::ImplBlock's we determine if an impl might overlap another impl based on the Self type. So for example you might have a generic structure Foo(T), and an associated impl block for Foo, but then go on to define an associated impl of Foo the generic one will overlap any associated impl hiding the generic implementation. In this case we have two generic impl blocks *const [T] *const T This means the *const T might overlap with the slice one since it is generic. As bjorn3 pointed out in #1075, the correct implementation is to observe that [T] is constrained by size but untill we have the auto trait of Sized we must example the two generic impls and just determine that they are not-equal so for now this is the best implementation we can do. Fixes #1075 --- .../typecheck/rust-hir-inherent-impl-overlap.h | 25 +++++++++++-- gcc/rust/typecheck/rust-hir-path-probe.h | 5 ++- gcc/rust/typecheck/rust-tyty-bounds.cc | 5 ++- gcc/rust/typecheck/rust-tyty-cmp.h | 26 -------------- gcc/testsuite/rust/compile/generics7.rs | 2 +- gcc/testsuite/rust/compile/generics8.rs | 2 +- gcc/testsuite/rust/compile/torture/issue-1075.rs | 42 ++++++++++++++++++++++ 7 files changed, 74 insertions(+), 33 deletions(-) create mode 100644 gcc/testsuite/rust/compile/torture/issue-1075.rs (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h index 2908a4b..9abf872 100644 --- a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h +++ b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h @@ -123,7 +123,26 @@ public: continue; if (query->can_eq (candidate, false)) - possible_collision (it->second, iy->second); + { + // we might be in the case that we have: + // + // *const T vs *const [T] + // + // so lets use an equality check when the + // candidates are both generic to be sure we dont emit a false + // positive + + bool a = query->is_concrete (); + bool b = candidate->is_concrete (); + bool both_generic = !a && !b; + if (both_generic) + { + if (!query->is_equal (*candidate)) + continue; + } + + possible_collision (it->second, iy->second); + } } } } @@ -152,8 +171,8 @@ public: void collision_detected (HIR::ImplItem *query, HIR::ImplItem *dup, const std::string &name) { - RichLocation r (query->get_locus ()); - r.add_range (dup->get_locus ()); + RichLocation r (dup->get_locus ()); + r.add_range (query->get_locus ()); rust_error_at (r, "duplicate definitions with name %s", name.c_str ()); } diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h index 3c1858c..fda505a 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.h +++ b/gcc/rust/typecheck/rust-hir-path-probe.h @@ -284,7 +284,10 @@ protected: return; if (!receiver->can_eq (impl_block_ty, false)) - return; + { + if (!impl_block_ty->can_eq (receiver, false)) + return; + } // lets visit the impl_item item->accept_vis (*this); diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc index a7ec42c..b34db3b 100644 --- a/gcc/rust/typecheck/rust-tyty-bounds.cc +++ b/gcc/rust/typecheck/rust-tyty-bounds.cc @@ -41,7 +41,10 @@ TypeBoundsProbe::scan () return true; if (!receiver->can_eq (impl_type, false)) - return true; + { + if (!impl_type->can_eq (receiver, false)) + return true; + } possible_trait_paths.push_back ({impl->get_trait_ref ().get (), impl}); return true; diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h index afc928da..34c8963 100644 --- a/gcc/rust/typecheck/rust-tyty-cmp.h +++ b/gcc/rust/typecheck/rust-tyty-cmp.h @@ -886,8 +886,6 @@ public: ok = true; } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const ArrayType *base; @@ -916,8 +914,6 @@ public: ok = true; } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const SliceType *base; @@ -939,8 +935,6 @@ public: ok = type.get_infer_kind () == InferType::InferTypeKind::GENERAL; } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const BoolType *base; @@ -965,8 +959,6 @@ public: ok = type.get_int_kind () == base->get_int_kind (); } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const IntType *base; @@ -991,8 +983,6 @@ public: ok = type.get_uint_kind () == base->get_uint_kind (); } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const UintType *base; @@ -1017,8 +1007,6 @@ public: ok = type.get_float_kind () == base->get_float_kind (); } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const FloatType *base; @@ -1120,8 +1108,6 @@ public: ok = true; } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const TupleType *base; @@ -1143,8 +1129,6 @@ public: void visit (const USizeType &type) override { ok = true; } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const USizeType *base; @@ -1166,8 +1150,6 @@ public: void visit (const ISizeType &type) override { ok = true; } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const ISizeType *base; @@ -1189,8 +1171,6 @@ public: void visit (const CharType &type) override { ok = true; } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const CharType *base; @@ -1365,8 +1345,6 @@ public: void visit (const StrType &type) override { ok = true; } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const StrType *base; @@ -1383,8 +1361,6 @@ public: void visit (const NeverType &type) override { ok = true; } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } const NeverType *base; @@ -1478,8 +1454,6 @@ public: ok = base->bounds_compatible (type, ref_locus, false); } - void visit (const ParamType &type) override { ok = true; } - private: const BaseType *get_base () const override { return base; } diff --git a/gcc/testsuite/rust/compile/generics7.rs b/gcc/testsuite/rust/compile/generics7.rs index 78b6149..2a41632 100644 --- a/gcc/testsuite/rust/compile/generics7.rs +++ b/gcc/testsuite/rust/compile/generics7.rs @@ -15,7 +15,7 @@ impl Foo { } impl Foo { - fn bar(self) -> T { // { dg-error "duplicate definitions with name bar" } + fn bar(self) -> T { self.a } } diff --git a/gcc/testsuite/rust/compile/generics8.rs b/gcc/testsuite/rust/compile/generics8.rs index 70bad1a..ceefc5d 100644 --- a/gcc/testsuite/rust/compile/generics8.rs +++ b/gcc/testsuite/rust/compile/generics8.rs @@ -1,7 +1,7 @@ struct Foo(A, B); impl Foo { - fn test(a: T) -> T { // { dg-error "duplicate definitions with name test" } + fn test(a: T) -> T { a } } diff --git a/gcc/testsuite/rust/compile/torture/issue-1075.rs b/gcc/testsuite/rust/compile/torture/issue-1075.rs new file mode 100644 index 0000000..3bd6321 --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/issue-1075.rs @@ -0,0 +1,42 @@ +// { dg-additional-options "-w" } +extern "rust-intrinsic" { + pub fn offset(dst: *const T, offset: isize) -> *const T; +} + +struct FatPtr { + data: *const T, + len: usize, +} + +union Repr { + rust: *const [T], + rust_mut: *mut [T], + raw: FatPtr, +} + +impl *const [T] { + pub const fn len(self) -> usize { + // SAFETY: this is safe because `*const [T]` and `FatPtr` have the same layout. + // Only `std` can make this guarantee. + let a = unsafe { Repr { rust: self }.raw }; + a.len + } + + pub const fn as_ptr(self) -> *const T { + self as *const T + } +} + +impl *const T { + pub const unsafe fn offset(self, count: isize) -> *const T { + unsafe { offset(self, count) } + } + + pub const unsafe fn add(self, count: usize) -> Self { + unsafe { self.offset(count as isize) } + } + + pub const fn as_ptr(self) -> *const T { + self as *const T + } +} -- cgit v1.1