aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-07-20 13:47:56 +0100
committerPhilip Herron <philip.herron@embecosm.com>2021-07-20 18:46:04 +0100
commitaa4feb8867da90a03d1d04dcfa61a049a2779df5 (patch)
treeb108c383397dc0bf36153c6eabdebe62d42a20e6 /gcc
parent02713d245aaffd45d8daaf8c914b1dda5baa6eb4 (diff)
downloadgcc-aa4feb8867da90a03d1d04dcfa61a049a2779df5.zip
gcc-aa4feb8867da90a03d1d04dcfa61a049a2779df5.tar.gz
gcc-aa4feb8867da90a03d1d04dcfa61a049a2779df5.tar.bz2
Raw pointer support
This adds the initial support for raw pointers. Pointers rely on coercion rules to be able to coerce the raw fat pointers from a borrow expression into a normal raw pointer. Fixes #124
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/backend/rust-compile-context.h25
-rw-r--r--gcc/rust/backend/rust-compile-tyty.h2
-rw-r--r--gcc/rust/hir/rust-ast-lower-type.h21
-rw-r--r--gcc/rust/hir/tree/rust-hir-full-test.cc19
-rw-r--r--gcc/rust/hir/tree/rust-hir-type.h38
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.h5
-rw-r--r--gcc/rust/typecheck/rust-hir-const-fold.h2
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.h9
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.h8
-rw-r--r--gcc/rust/typecheck/rust-tyty-call.h2
-rw-r--r--gcc/rust/typecheck/rust-tyty-cmp.h54
-rw-r--r--gcc/rust/typecheck/rust-tyty-coercion.h92
-rw-r--r--gcc/rust/typecheck/rust-tyty-rules.h60
-rw-r--r--gcc/rust/typecheck/rust-tyty-visitor.h2
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc79
-rw-r--r--gcc/rust/typecheck/rust-tyty.h51
-rw-r--r--gcc/testsuite/rust/compile/torture/coercion2.rs20
17 files changed, 448 insertions, 41 deletions
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h
index efca267..bb4f0ab 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -536,10 +536,29 @@ public:
{
Btype *base_compiled_type
= TyTyResolveCompile::compile (ctx, type.get_base ());
- translated = ctx->get_backend ()->reference_type (base_compiled_type);
- if (!type.is_mutable ())
+ if (type.is_mutable ())
{
- translated = ctx->get_backend ()->immutable_type (translated);
+ translated = ctx->get_backend ()->reference_type (base_compiled_type);
+ }
+ else
+ {
+ auto base = ctx->get_backend ()->immutable_type (base_compiled_type);
+ translated = ctx->get_backend ()->reference_type (base);
+ }
+ }
+
+ void visit (TyTy::PointerType &type) override
+ {
+ Btype *base_compiled_type
+ = TyTyResolveCompile::compile (ctx, type.get_base ());
+ if (type.is_mutable ())
+ {
+ translated = ctx->get_backend ()->pointer_type (base_compiled_type);
+ }
+ else
+ {
+ auto base = ctx->get_backend ()->immutable_type (base_compiled_type);
+ translated = ctx->get_backend ()->pointer_type (base);
}
}
diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h
index d2890e0..2d0856d 100644
--- a/gcc/rust/backend/rust-compile-tyty.h
+++ b/gcc/rust/backend/rust-compile-tyty.h
@@ -62,6 +62,8 @@ public:
void visit (TyTy::ReferenceType &) override { gcc_unreachable (); }
+ void visit (TyTy::PointerType &) override { gcc_unreachable (); }
+
void visit (TyTy::ParamType &) override { gcc_unreachable (); }
void visit (TyTy::FnPtr &) override { gcc_unreachable (); }
diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h
index 0b534d0..efaf9db 100644
--- a/gcc/rust/hir/rust-ast-lower-type.h
+++ b/gcc/rust/hir/rust-ast-lower-type.h
@@ -229,6 +229,27 @@ public:
translated);
}
+ void visit (AST::RawPointerType &type) override
+ {
+ HIR::Type *base_type
+ = ASTLoweringType::translate (type.get_type_pointed_to ().get ());
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ mappings->get_next_localdef_id (crate_num));
+
+ translated
+ = new HIR::RawPointerType (mapping,
+ type.get_pointer_type ()
+ == AST::RawPointerType::PointerType::MUT,
+ std::unique_ptr<HIR::Type> (base_type),
+ type.get_locus ());
+
+ mappings->insert_hir_type (mapping.get_crate_num (), mapping.get_hirid (),
+ translated);
+ }
+
void visit (AST::InferredType &type) override
{
auto crate_num = mappings->get_current_crate ();
diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir-full-test.cc
index 05c75e0..86664d3 100644
--- a/gcc/rust/hir/tree/rust-hir-full-test.cc
+++ b/gcc/rust/hir/tree/rust-hir-full-test.cc
@@ -2806,23 +2806,8 @@ ReferenceType::as_string () const
std::string
RawPointerType::as_string () const
{
- std::string str ("*");
-
- switch (pointer_type)
- {
- case MUT:
- str += "mut ";
- break;
- case CONST:
- str += "const ";
- break;
- default:
- return "ERROR_MARK_STRING - unknown pointer type in raw pointer type";
- }
-
- str += type->as_string ();
-
- return str;
+ return std::string ("*") + (is_mut () ? "mut " : "const ")
+ + type->as_string ();
}
std::string
diff --git a/gcc/rust/hir/tree/rust-hir-type.h b/gcc/rust/hir/tree/rust-hir-type.h
index c4771b6..3cb4be1 100644
--- a/gcc/rust/hir/tree/rust-hir-type.h
+++ b/gcc/rust/hir/tree/rust-hir-type.h
@@ -446,41 +446,31 @@ public:
// A type consisting of a pointer without safety or liveness guarantees
class RawPointerType : public TypeNoBounds
{
-public:
- enum PointerType
- {
- MUT,
- CONST
- };
-
private:
- PointerType pointer_type;
- std::unique_ptr<TypeNoBounds> type;
+ bool is_mutable;
+ std::unique_ptr<Type> type;
Location locus;
public:
- // Returns whether the pointer is mutable or constant.
- PointerType get_pointer_type () const { return pointer_type; }
-
// Constructor requires pointer for polymorphism reasons
- RawPointerType (Analysis::NodeMapping mappings, PointerType pointer_type,
- std::unique_ptr<TypeNoBounds> type_no_bounds, Location locus)
- : TypeNoBounds (mappings), pointer_type (pointer_type),
- type (std::move (type_no_bounds)), locus (locus)
+ RawPointerType (Analysis::NodeMapping mappings, bool is_mutable,
+ std::unique_ptr<Type> type, Location locus)
+ : TypeNoBounds (mappings), is_mutable (is_mutable), type (std::move (type)),
+ locus (locus)
{}
// Copy constructor calls custom polymorphic clone function
RawPointerType (RawPointerType const &other)
- : TypeNoBounds (other.mappings), pointer_type (other.pointer_type),
- type (other.type->clone_type_no_bounds ()), locus (other.locus)
+ : TypeNoBounds (other.mappings), is_mutable (other.is_mutable),
+ type (other.type->clone_type ()), locus (other.locus)
{}
// overload assignment operator to use custom clone method
RawPointerType &operator= (RawPointerType const &other)
{
mappings = other.mappings;
- pointer_type = other.pointer_type;
- type = other.type->clone_type_no_bounds ();
+ is_mutable = other.is_mutable;
+ type = other.type->clone_type ();
locus = other.locus;
return *this;
}
@@ -495,6 +485,14 @@ public:
void accept_vis (HIRVisitor &vis) override;
+ std::unique_ptr<Type> &get_type () { return type; }
+
+ bool is_mut () const { return is_mutable; }
+
+ bool is_const () const { return !is_mutable; }
+
+ std::unique_ptr<Type> &get_base_type () { return type; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h
index 23419b0..d826d68 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.h
+++ b/gcc/rust/resolve/rust-ast-resolve-type.h
@@ -281,6 +281,11 @@ public:
void visit (AST::InferredType &type) override { ok = true; }
+ void visit (AST::RawPointerType &type) override
+ {
+ type.get_type_pointed_to ()->accept_vis (*this);
+ }
+
private:
ResolveType (NodeId parent, bool canonicalize_type_with_generics)
: ResolverBase (parent),
diff --git a/gcc/rust/typecheck/rust-hir-const-fold.h b/gcc/rust/typecheck/rust-hir-const-fold.h
index c71dd39..f6c6616 100644
--- a/gcc/rust/typecheck/rust-hir-const-fold.h
+++ b/gcc/rust/typecheck/rust-hir-const-fold.h
@@ -45,6 +45,8 @@ public:
void visit (TyTy::ReferenceType &) override { gcc_unreachable (); }
+ void visit (TyTy::PointerType &) override { gcc_unreachable (); }
+
void visit (TyTy::ParamType &) override { gcc_unreachable (); }
void visit (TyTy::FnPtr &) override { gcc_unreachable (); }
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h
index 567d482..0f75c54 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.h
@@ -194,6 +194,15 @@ public:
type.get_has_mut ());
}
+ void visit (HIR::RawPointerType &type) override
+ {
+ TyTy::BaseType *base
+ = TypeCheckType::Resolve (type.get_base_type ().get ());
+ translated
+ = new TyTy::PointerType (type.get_mappings ().get_hirid (),
+ TyTy::TyVar (base->get_ref ()), type.is_mut ());
+ }
+
void visit (HIR::InferredType &type) override
{
translated = new TyTy::InferType (type.get_mappings ().get_hirid (),
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h
index 9741dfa..3730faa 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.h
+++ b/gcc/rust/typecheck/rust-substitution-mapper.h
@@ -103,6 +103,7 @@ public:
void visit (TyTy::ErrorType &) override { gcc_unreachable (); }
void visit (TyTy::CharType &) override { gcc_unreachable (); }
void visit (TyTy::ReferenceType &) override { gcc_unreachable (); }
+ void visit (TyTy::PointerType &) override { gcc_unreachable (); }
void visit (TyTy::ParamType &) override { gcc_unreachable (); }
void visit (TyTy::StrType &) override { gcc_unreachable (); }
void visit (TyTy::NeverType &) override { gcc_unreachable (); }
@@ -165,6 +166,11 @@ public:
resolved = type.handle_substitions (mappings);
}
+ void visit (TyTy::PointerType &type) override
+ {
+ resolved = type.handle_substitions (mappings);
+ }
+
void visit (TyTy::ParamType &type) override
{
resolved = type.handle_substitions (mappings);
@@ -237,6 +243,7 @@ public:
void visit (TyTy::ErrorType &) override { gcc_unreachable (); }
void visit (TyTy::CharType &) override { gcc_unreachable (); }
void visit (TyTy::ReferenceType &) override { gcc_unreachable (); }
+ void visit (TyTy::PointerType &) override { gcc_unreachable (); }
void visit (TyTy::ParamType &) override { gcc_unreachable (); }
void visit (TyTy::StrType &) override { gcc_unreachable (); }
void visit (TyTy::NeverType &) override { gcc_unreachable (); }
@@ -286,6 +293,7 @@ public:
void visit (TyTy::ErrorType &) override { gcc_unreachable (); }
void visit (TyTy::CharType &) override { gcc_unreachable (); }
void visit (TyTy::ReferenceType &) override { gcc_unreachable (); }
+ void visit (TyTy::PointerType &) override { gcc_unreachable (); }
void visit (TyTy::ParamType &) override { gcc_unreachable (); }
void visit (TyTy::StrType &) override { gcc_unreachable (); }
void visit (TyTy::NeverType &) override { gcc_unreachable (); }
diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h
index f6121ca..636d40b 100644
--- a/gcc/rust/typecheck/rust-tyty-call.h
+++ b/gcc/rust/typecheck/rust-tyty-call.h
@@ -51,6 +51,7 @@ public:
void visit (ErrorType &type) override { gcc_unreachable (); }
void visit (CharType &type) override { gcc_unreachable (); }
void visit (ReferenceType &type) override { gcc_unreachable (); }
+ void visit (PointerType &type) override { gcc_unreachable (); }
void visit (ParamType &) override { gcc_unreachable (); }
void visit (StrType &) override { gcc_unreachable (); }
void visit (NeverType &) override { gcc_unreachable (); }
@@ -100,6 +101,7 @@ public:
void visit (ADTType &type) override { gcc_unreachable (); };
void visit (CharType &type) override { gcc_unreachable (); }
void visit (ReferenceType &type) override { gcc_unreachable (); }
+ void visit (PointerType &type) override { gcc_unreachable (); }
void visit (ParamType &) override { gcc_unreachable (); }
void visit (StrType &) override { gcc_unreachable (); }
void visit (NeverType &) override { gcc_unreachable (); }
diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h
index e856c41..049a4b7 100644
--- a/gcc/rust/typecheck/rust-tyty-cmp.h
+++ b/gcc/rust/typecheck/rust-tyty-cmp.h
@@ -289,6 +289,22 @@ public:
}
}
+ virtual void visit (const PointerType &type) override
+ {
+ ok = false;
+ if (emit_error_flag)
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus
+ = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "expected [%s] got [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+ }
+
virtual void visit (const StrType &type) override
{
ok = false;
@@ -542,7 +558,19 @@ public:
}
void visit (const ReferenceType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ ok = true;
+ return;
+ }
+
+ BaseCmp::visit (type);
+ }
+ void visit (const PointerType &type) override
{
bool is_valid
= (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
@@ -997,7 +1025,8 @@ public:
auto base_type = base->get_base ();
auto other_base_type = type.get_base ();
- ok = base_type->can_eq (other_base_type, emit_error_flag);
+ ok = base_type->can_eq (other_base_type, emit_error_flag)
+ && (base->is_mutable () == type.is_mutable ());
}
private:
@@ -1005,6 +1034,29 @@ private:
const ReferenceType *base;
};
+class PointerCmp : public BaseCmp
+{
+ using Rust::TyTy::BaseCmp::visit;
+
+public:
+ PointerCmp (const PointerType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
+ {}
+
+ void visit (const ReferenceType &type) override
+ {
+ auto base_type = base->get_base ();
+ auto other_base_type = type.get_base ();
+
+ ok = base_type->can_eq (other_base_type, emit_error_flag)
+ && (base->is_mutable () == type.is_mutable ());
+ }
+
+private:
+ const BaseType *get_base () const override { return base; }
+ const PointerType *base;
+};
+
class ParamCmp : public BaseCmp
{
using Rust::TyTy::BaseCmp::visit;
diff --git a/gcc/rust/typecheck/rust-tyty-coercion.h b/gcc/rust/typecheck/rust-tyty-coercion.h
index 5c10b04..f19871e 100644
--- a/gcc/rust/typecheck/rust-tyty-coercion.h
+++ b/gcc/rust/typecheck/rust-tyty-coercion.h
@@ -252,6 +252,17 @@ public:
type.as_string ().c_str ());
}
+ virtual void visit (PointerType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "expected [%s] got [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
virtual void visit (ParamType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
@@ -507,7 +518,19 @@ public:
}
void visit (ReferenceType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+ BaseCoercionRules::visit (type);
+ }
+
+ void visit (PointerType &type) override
{
bool is_valid
= (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
@@ -1087,6 +1110,75 @@ private:
ReferenceType *base;
};
+class PointerCoercionRules : public BaseCoercionRules
+{
+ using Rust::TyTy::BaseCoercionRules::visit;
+
+public:
+ PointerCoercionRules (PointerType *base)
+ : BaseCoercionRules (base), base (base)
+ {}
+
+ void visit (ReferenceType &type) override
+ {
+ auto base_type = base->get_base ();
+ auto other_base_type = type.get_base ();
+
+ TyTy::BaseType *base_resolved = base_type->unify (other_base_type);
+ if (base_resolved == nullptr
+ || base_resolved->get_kind () == TypeKind::ERROR)
+ {
+ BaseCoercionRules::visit (type);
+ return;
+ }
+
+ // we can allow for mutability changes here by casting down from mutability
+ // eg: mut vs const, we cant take a mutable pointer from a const
+ // eg: const vs mut we can take a const reference from a mutable one
+ if (!base->is_mutable () || (base->is_mutable () == type.is_mutable ()))
+ {
+ resolved = new PointerType (base->get_ref (), base->get_ty_ref (),
+ TyVar (base_resolved->get_ref ()),
+ base->is_mutable ());
+ return;
+ }
+
+ BaseCoercionRules::visit (type);
+ }
+
+ void visit (PointerType &type) override
+ {
+ auto base_type = base->get_base ();
+ auto other_base_type = type.get_base ();
+
+ TyTy::BaseType *base_resolved = base_type->unify (other_base_type);
+ if (base_resolved == nullptr
+ || base_resolved->get_kind () == TypeKind::ERROR)
+ {
+ BaseCoercionRules::visit (type);
+ return;
+ }
+
+ // we can allow for mutability changes here by casting down from mutability
+ // eg: mut vs const, we cant take a mutable pointer from a const one
+ // eg: const vs mut we can take a const reference from a mutable one
+ if (!base->is_mutable () || (base->is_mutable () == type.is_mutable ()))
+ {
+ resolved = new PointerType (base->get_ref (), base->get_ty_ref (),
+ TyVar (base_resolved->get_ref ()),
+ base->is_mutable ());
+ return;
+ }
+
+ BaseCoercionRules::visit (type);
+ }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ PointerType *base;
+};
+
class ParamCoercionRules : public BaseCoercionRules
{
using Rust::TyTy::BaseCoercionRules::visit;
diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h
index 31d7191..de9a5d9 100644
--- a/gcc/rust/typecheck/rust-tyty-rules.h
+++ b/gcc/rust/typecheck/rust-tyty-rules.h
@@ -274,6 +274,17 @@ public:
type.as_string ().c_str ());
}
+ virtual void visit (PointerType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "expected [%s] got [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
virtual void visit (ParamType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
@@ -528,7 +539,19 @@ public:
}
void visit (ReferenceType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+ BaseRules::visit (type);
+ }
+
+ void visit (PointerType &type) override
{
bool is_valid
= (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
@@ -1098,6 +1121,43 @@ private:
ReferenceType *base;
};
+class PointerRules : public BaseRules
+{
+ using Rust::TyTy::BaseRules::visit;
+
+public:
+ PointerRules (PointerType *base) : BaseRules (base), base (base) {}
+
+ void visit (PointerType &type) override
+ {
+ auto base_type = base->get_base ();
+ auto other_base_type = type.get_base ();
+
+ TyTy::BaseType *base_resolved = base_type->unify (other_base_type);
+ if (base_resolved == nullptr
+ || base_resolved->get_kind () == TypeKind::ERROR)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ if (base->is_mutable () != type.is_mutable ())
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ resolved = new PointerType (base->get_ref (), base->get_ty_ref (),
+ TyVar (base_resolved->get_ref ()),
+ base->is_mutable ());
+ }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ PointerType *base;
+};
+
class ParamRules : public BaseRules
{
using Rust::TyTy::BaseRules::visit;
diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h
index 2dd97b8..66b11b9 100644
--- a/gcc/rust/typecheck/rust-tyty-visitor.h
+++ b/gcc/rust/typecheck/rust-tyty-visitor.h
@@ -42,6 +42,7 @@ public:
virtual void visit (ErrorType &type) = 0;
virtual void visit (CharType &type) = 0;
virtual void visit (ReferenceType &type) = 0;
+ virtual void visit (PointerType &type) = 0;
virtual void visit (ParamType &type) = 0;
virtual void visit (StrType &type) = 0;
virtual void visit (NeverType &type) = 0;
@@ -66,6 +67,7 @@ public:
virtual void visit (const ErrorType &type) = 0;
virtual void visit (const CharType &type) = 0;
virtual void visit (const ReferenceType &type) = 0;
+ virtual void visit (const PointerType &type) = 0;
virtual void visit (const ParamType &type) = 0;
virtual void visit (const StrType &type) = 0;
virtual void visit (const NeverType &type) = 0;
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 16bb01b..f043c7e 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -1518,6 +1518,85 @@ ReferenceType::handle_substitions (SubstitutionArgumentMappings mappings)
}
void
+PointerType::accept_vis (TyVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+PointerType::accept_vis (TyConstVisitor &vis) const
+{
+ vis.visit (*this);
+}
+
+std::string
+PointerType::as_string () const
+{
+ return std::string ("* ") + (is_mutable () ? "mut" : "const") + " "
+ + get_base ()->as_string ();
+}
+
+BaseType *
+PointerType::unify (BaseType *other)
+{
+ PointerRules r (this);
+ return r.unify (other);
+}
+
+BaseType *
+PointerType::coerce (BaseType *other)
+{
+ PointerCoercionRules r (this);
+ return r.coerce (other);
+}
+
+bool
+PointerType::can_eq (const BaseType *other, bool emit_errors) const
+{
+ PointerCmp r (this, emit_errors);
+ return r.can_eq (other);
+}
+
+bool
+PointerType::is_equal (const BaseType &other) const
+{
+ if (get_kind () != other.get_kind ())
+ return false;
+
+ auto other2 = static_cast<const PointerType &> (other);
+ return get_base ()->is_equal (*other2.get_base ());
+}
+
+BaseType *
+PointerType::get_base () const
+{
+ return base.get_tyty ();
+}
+
+BaseType *
+PointerType::clone ()
+{
+ return new PointerType (get_ref (), get_ty_ref (), base, is_mutable (),
+ get_combined_refs ());
+}
+
+PointerType *
+PointerType::handle_substitions (SubstitutionArgumentMappings mappings)
+{
+ auto mappings_table = Analysis::Mappings::get ();
+
+ PointerType *ref = static_cast<PointerType *> (clone ());
+ ref->set_ty_ref (mappings_table->get_next_hir_id ());
+
+ // might be &T or &ADT so this needs to be recursive
+ auto base = ref->get_base ();
+ BaseType *concrete = Resolver::SubstMapperInternal::Resolve (base, mappings);
+ ref->base = TyVar (concrete->get_ty_ref ());
+
+ return ref;
+}
+
+void
ParamType::accept_vis (TyVisitor &vis)
{
vis.visit (*this);
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index c0af9f6..2152c1b 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -35,6 +35,7 @@ enum TypeKind
ADT,
STR,
REF,
+ POINTER,
PARAM,
ARRAY,
FNDEF,
@@ -72,6 +73,9 @@ public:
case TypeKind::REF:
return "REF";
+ case TypeKind::POINTER:
+ return "POINTER";
+
case TypeKind::PARAM:
return "PARAM";
@@ -1432,6 +1436,53 @@ private:
bool is_mut;
};
+class PointerType : public BaseType
+{
+public:
+ PointerType (HirId ref, TyVar base, bool is_mut,
+ std::set<HirId> refs = std::set<HirId> ())
+ : BaseType (ref, ref, TypeKind::POINTER, refs), base (base), is_mut (is_mut)
+ {}
+
+ PointerType (HirId ref, HirId ty_ref, TyVar base, bool is_mut,
+ std::set<HirId> refs = std::set<HirId> ())
+ : BaseType (ref, ty_ref, TypeKind::POINTER, refs), base (base),
+ is_mut (is_mut)
+ {}
+
+ BaseType *get_base () const;
+
+ void accept_vis (TyVisitor &vis) override;
+ void accept_vis (TyConstVisitor &vis) const override;
+
+ std::string as_string () const override;
+
+ std::string get_name () const override final { return as_string (); }
+
+ BaseType *unify (BaseType *other) override;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
+ BaseType *coerce (BaseType *other) override;
+
+ bool is_equal (const BaseType &other) const override;
+
+ BaseType *clone () final override;
+
+ bool contains_type_parameters () const override final
+ {
+ return get_base ()->contains_type_parameters ();
+ }
+
+ PointerType *handle_substitions (SubstitutionArgumentMappings mappings);
+
+ bool is_mutable () const { return is_mut; }
+
+ bool is_const () const { return !is_mut; }
+
+private:
+ TyVar base;
+ bool is_mut;
+};
+
class StrType : public BaseType
{
public:
diff --git a/gcc/testsuite/rust/compile/torture/coercion2.rs b/gcc/testsuite/rust/compile/torture/coercion2.rs
new file mode 100644
index 0000000..127f257
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/coercion2.rs
@@ -0,0 +1,20 @@
+pub fn main() {
+ let a: *const i32 = &123;
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+ let b: &i32 = &123;
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+ let c: &mut i32 = &mut 123;
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+ let d: *mut i32 = &mut 123;
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+ let e: &i32 = &mut 123;
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+ let f: *const i32 = &mut 123;
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+ let g = &123;
+ let h: *const i32 = g;
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}