diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h b/gcc/rust/typecheck/rust-hir-trait-reference.h index a34463d3574..b35227dcff5 100644 --- a/gcc/rust/typecheck/rust-hir-trait-reference.h +++ b/gcc/rust/typecheck/rust-hir-trait-reference.h @@ -246,6 +246,8 @@ class AssociatedImplTrait HIR::ImplBlock *get_impl_block (); + location_t get_locus () const; + TyTy::BaseType *get_self (); const TyTy::BaseType *get_self () const; diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc index 9f07f547c9c..3e41d2f5a61 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc @@ -669,6 +669,12 @@ AssociatedImplTrait::reset_associated_types () trait->clear_associated_types (); } +location_t +AssociatedImplTrait::get_locus () const +{ + return impl->get_locus (); +} + Analysis::NodeMapping TraitItemReference::get_parent_trait_mappings () const { diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index 62bbd25d485..49f1bbb1a61 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -1822,10 +1822,20 @@ TypeCheckExpr::resolve_operator_overload (LangItem::Kind lang_item_type, HIR::ImplBlock *parent = impl_item.first; HIR::Function *fn = impl_item.second; - if (parent->has_trait_ref () - && fn->get_function_name ().as_string ().compare ( - associated_item_name) - == 0) + bool is_deref = lang_item_type == LangItem::Kind::DEREF + || lang_item_type == LangItem::Kind::DEREF_MUT; + bool is_deref_match = fn->get_function_name ().as_string ().compare ( + LangItem::ToString (LangItem::Kind::DEREF)) + == 0 + || fn->get_function_name ().as_string ().compare ( + LangItem::ToString (LangItem::Kind::DEREF_MUT)) + == 0; + + bool is_recursive_op + = fn->get_function_name ().as_string ().compare (associated_item_name) + == 0 + || (is_deref && is_deref_match); + if (parent->has_trait_ref () && is_recursive_op) { TraitReference *trait_reference = TraitResolver::Lookup (*parent->get_trait_ref ().get ()); @@ -1842,7 +1852,8 @@ TypeCheckExpr::resolve_operator_overload (LangItem::Kind lang_item_type, bool is_lang_item_impl = trait_reference->get_mappings ().get_defid () - == respective_lang_item_id; + == respective_lang_item_id + || (is_deref && is_deref_match); bool self_is_lang_item_self = fntype->get_self_type ()->is_equal (*adjusted_self); bool recursive_operator_overload diff --git a/gcc/testsuite/rust/compile/issue-3032-1.rs b/gcc/testsuite/rust/compile/issue-3032-1.rs new file mode 100644 index 00000000000..e9eb02794ce --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3032-1.rs @@ -0,0 +1,58 @@ +#![feature(negative_impls)] + +#[lang = "sized"] +trait Sized {} + +#[lang = "deref"] +pub trait Deref { + /// The resulting type after dereferencing. + #[stable(feature = "rust1", since = "1.0.0")] + // #[rustc_diagnostic_item = "deref_target"] + type Target: ?Sized; + + /// Dereferences the value. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + // #[rustc_diagnostic_item = "deref_method"] + fn deref(&self) -> &Self::Target; +} + +impl Deref for &T { + type Target = T; + + fn deref(&self) -> &T { + *self + } +} + +// this is added because of #3030 +extern "C" { + fn never() -> !; +} + +impl !DerefMut for &T { + fn deref_mut(&mut self) -> &mut T { + unsafe { never() } + } +} + +impl Deref for &mut T { + type Target = T; + + fn deref(&self) -> &T { + *self + } +} + +#[lang = "deref_mut"] +pub trait DerefMut: Deref { + /// Mutably dereferences the value. + #[stable(feature = "rust1", since = "1.0.0")] + fn deref_mut(&mut self) -> &mut Self::Target; +} + +impl DerefMut for &mut T { + fn deref_mut(&mut self) -> &mut T { + *self + } +} diff --git a/gcc/testsuite/rust/compile/issue-3032-2.rs b/gcc/testsuite/rust/compile/issue-3032-2.rs new file mode 100644 index 00000000000..9e09d419072 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3032-2.rs @@ -0,0 +1,49 @@ +#![feature(negative_impls)] + +#[lang = "sized"] +trait Sized {} + +#[lang = "deref"] +pub trait Deref { + /// The resulting type after dereferencing. + #[stable(feature = "rust1", since = "1.0.0")] + // #[rustc_diagnostic_item = "deref_target"] + type Target: ?Sized; + + /// Dereferences the value. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + // #[rustc_diagnostic_item = "deref_method"] + fn deref(&self) -> &Self::Target; +} + +impl Deref for &T { + type Target = T; + + fn deref(&self) -> &T { + *self + } +} + +impl !DerefMut for &T {} + +impl Deref for &mut T { + type Target = T; + + fn deref(&self) -> &T { + *self + } +} + +#[lang = "deref_mut"] +pub trait DerefMut: Deref { + /// Mutably dereferences the value. + #[stable(feature = "rust1", since = "1.0.0")] + fn deref_mut(&mut self) -> &mut Self::Target; +} + +impl DerefMut for &mut T { + fn deref_mut(&mut self) -> &mut T { + *self + } +} diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index ecef6d2bb25..383950ca863 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -234,4 +234,6 @@ issue-3139-3.rs issue-3036.rs issue-2951.rs issue-2203.rs -issue-2499.rs \ No newline at end of file +issue-2499.rs +issue-3032-1.rs +issue-3032-2.rs \ No newline at end of file