From: Philip Herron <herron.phi...@googlemail.com>

This completes the initial setup and boilerplate for the new type in the
typesystem. This is not functional yet but its a big patch already.

gcc/rust/ChangeLog:

        * backend/rust-compile-type.cc (TyTyResolveCompile::visit): new 
tyty::OpaqueType
        * backend/rust-compile-type.h: likewise
        * checks/errors/borrowck/rust-bir-fact-collector.h: likewise
        * checks/errors/borrowck/rust-bir-place.h: likewise
        * checks/errors/privacy/rust-privacy-reporter.cc 
(PrivacyReporter::check_base_type_privacy):
        likewise
        * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): likewise
        * typecheck/rust-hir-type-check-type.h: likewise
        * typecheck/rust-substitution-mapper.cc (SubstMapperInternal::visit): 
likewise
        * typecheck/rust-substitution-mapper.h: likewise
        * typecheck/rust-tyty-bounds.cc 
(TypeBoundsProbe::assemble_sized_builtin): likewise
        * typecheck/rust-tyty-call.h: likewise
        * typecheck/rust-tyty-cmp.h (class OpaqueCmp): likewise
        * typecheck/rust-tyty-variance-analysis-private.h: likewise
        * typecheck/rust-tyty-visitor.h: likewise
        * typecheck/rust-tyty.cc (TypeKindFormat::to_string): likewise
        (BaseType::is_unit): likewise
        (BaseType::destructure): likewise
        (BaseType::has_substitutions_defined): likewise
        (BaseType::needs_generic_substitutions): likewise
        (OpaqueType::OpaqueType): likewise
        (OpaqueType::can_resolve): likewise
        (OpaqueType::accept_vis): likewise
        (OpaqueType::as_string): likewise
        (OpaqueType::get_name): likewise
        (OpaqueType::can_eq): likewise
        (OpaqueType::clone): likewise
        (OpaqueType::resolve): likewise
        (OpaqueType::is_equal): likewise
        (OpaqueType::handle_substitions): likewise
        * typecheck/rust-tyty.h (enum TypeKind): likewise
        (class OpaqueType): likewise
        * typecheck/rust-unify.cc (UnifyRules::go): likewise
        (UnifyRules::expect_inference_variable): likewise
        (UnifyRules::expect_adt): likewise
        (UnifyRules::expect_str): likewise
        (UnifyRules::expect_reference): likewise
        (UnifyRules::expect_pointer): likewise
        (UnifyRules::expect_param): likewise
        (UnifyRules::expect_array): likewise
        (UnifyRules::expect_slice): likewise
        (UnifyRules::expect_fndef): likewise
        (UnifyRules::expect_fnptr): likewise
        (UnifyRules::expect_tuple): likewise
        (UnifyRules::expect_bool): likewise
        (UnifyRules::expect_char): likewise
        (UnifyRules::expect_int): likewise
        (UnifyRules::expect_uint): likewise
        (UnifyRules::expect_float): likewise
        (UnifyRules::expect_isize): likewise
        (UnifyRules::expect_usize): likewise
        (UnifyRules::expect_placeholder): likewise
        (UnifyRules::expect_projection): likewise
        (UnifyRules::expect_dyn): likewise
        (UnifyRules::expect_opaque): likewise
        * typecheck/rust-unify.h: likewise

Signed-off-by: Philip Herron <herron.phi...@googlemail.com>
---
 gcc/rust/backend/rust-compile-type.cc         |   6 +
 gcc/rust/backend/rust-compile-type.h          |   1 +
 .../errors/borrowck/rust-bir-fact-collector.h |   1 +
 .../checks/errors/borrowck/rust-bir-place.h   |   1 +
 .../errors/privacy/rust-privacy-reporter.cc   |   2 +
 .../typecheck/rust-hir-type-check-type.cc     |  37 ++++-
 gcc/rust/typecheck/rust-hir-type-check-type.h |  13 +-
 .../typecheck/rust-substitution-mapper.cc     |   5 +
 gcc/rust/typecheck/rust-substitution-mapper.h |   4 +
 gcc/rust/typecheck/rust-tyty-bounds.cc        |   1 +
 gcc/rust/typecheck/rust-tyty-call.h           |   1 +
 gcc/rust/typecheck/rust-tyty-cmp.h            |  33 ++++
 .../rust-tyty-variance-analysis-private.h     |   2 +
 gcc/rust/typecheck/rust-tyty-visitor.h        |   2 +
 gcc/rust/typecheck/rust-tyty.cc               | 152 +++++++++++++++++-
 gcc/rust/typecheck/rust-tyty.h                |  34 ++++
 gcc/rust/typecheck/rust-unify.cc              |  89 +++++++++-
 gcc/rust/typecheck/rust-unify.h               |   2 +
 18 files changed, 372 insertions(+), 14 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-type.cc 
b/gcc/rust/backend/rust-compile-type.cc
index 74368a29f49..d8af1d1af6b 100644
--- a/gcc/rust/backend/rust-compile-type.cc
+++ b/gcc/rust/backend/rust-compile-type.cc
@@ -731,6 +731,12 @@ TyTyResolveCompile::visit (const TyTy::DynamicObjectType 
&type)
                                    type.get_ident ().locus);
 }
 
+void
+TyTyResolveCompile::visit (const TyTy::OpaqueType &type)
+{
+  translated = error_mark_node;
+}
+
 tree
 TyTyResolveCompile::create_dyn_obj_record (const TyTy::DynamicObjectType &type)
 {
diff --git a/gcc/rust/backend/rust-compile-type.h 
b/gcc/rust/backend/rust-compile-type.h
index 398d7f8bda9..bc611cfbc73 100644
--- a/gcc/rust/backend/rust-compile-type.h
+++ b/gcc/rust/backend/rust-compile-type.h
@@ -56,6 +56,7 @@ public:
   void visit (const TyTy::ProjectionType &) override;
   void visit (const TyTy::DynamicObjectType &) override;
   void visit (const TyTy::ClosureType &) override;
+  void visit (const TyTy::OpaqueType &) override;
 
 public:
   static hashval_t type_hasher (tree type);
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h 
b/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h
index 1332ecfa111..32a4cd7b76c 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h
@@ -815,6 +815,7 @@ protected: // Subset helpers.
       case TyTy::PLACEHOLDER:
       case TyTy::INFER:
       case TyTy::PARAM:
+      case TyTy::OPAQUE:
        rust_unreachable ();
       }
     rust_unreachable ();
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-place.h 
b/gcc/rust/checks/errors/borrowck/rust-bir-place.h
index a1621b7455d..67ca90b93d0 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-place.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-place.h
@@ -485,6 +485,7 @@ private:
       case TyTy::PROJECTION: // TODO: DUNNO
       case TyTy::CLOSURE:    // TODO: DUNNO
       case TyTy::DYNAMIC:    // TODO: dunno
+      case TyTy::OPAQUE:
        return false;
       }
     rust_unreachable ();
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc 
b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
index 896c1c449ab..a537c4276a8 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
@@ -271,6 +271,8 @@ PrivacyReporter::check_base_type_privacy 
(Analysis::NodeMapping &node_mappings,
       // We shouldn't have inference types here, ever
     case TyTy::INFER:
       return;
+    case TyTy::OPAQUE:
+      return;
     case TyTy::ERROR:
       return;
     }
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc 
b/gcc/rust/typecheck/rust-hir-type-check-type.cc
index 6a09772d023..e56fa397e2a 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -674,6 +674,8 @@ TypeCheckType::visit (HIR::TraitObjectType &type)
 void
 TypeCheckType::visit (HIR::ParenthesisedType &type)
 {
+  // I think this really needs to be a tuple.. but will sort that out when we
+  // fix the parser issue
   translated = TypeCheckType::Resolve (type.get_type_in_parens ());
 }
 
@@ -724,7 +726,7 @@ TypeCheckType::visit (HIR::ReferenceType &type)
   translated = new TyTy::ReferenceType (type.get_mappings ().get_hirid (),
                                        TyTy::TyVar (base->get_ref ()),
                                        type.get_mut (), region.value ());
-} // namespace Resolver
+}
 
 void
 TypeCheckType::visit (HIR::RawPointerType &type)
@@ -754,6 +756,39 @@ TypeCheckType::visit (HIR::NeverType &type)
   translated = lookup->clone ();
 }
 
+void
+TypeCheckType::visit (HIR::ImplTraitType &type)
+{
+  std::vector<TyTy::TypeBoundPredicate> specified_bounds;
+  for (auto &bound : type.get_type_param_bounds ())
+    {
+      if (bound->get_bound_type ()
+         != HIR::TypeParamBound::BoundType::TRAITBOUND)
+       continue;
+
+      HIR::TypeParamBound &b = *bound.get ();
+      HIR::TraitBound &trait_bound = static_cast<HIR::TraitBound &> (b);
+
+      auto binder_pin = context->push_lifetime_binder ();
+      for (auto &lifetime_param : trait_bound.get_for_lifetimes ())
+       {
+         context->intern_and_insert_lifetime (lifetime_param.get_lifetime ());
+       }
+
+      TyTy::TypeBoundPredicate predicate = get_predicate_from_bound (
+       trait_bound.get_path (),
+       tl::nullopt /*this will setup a PLACEHOLDER for self*/);
+
+      if (!predicate.is_error ()
+         && predicate.is_object_safe (true, type.get_locus ()))
+       specified_bounds.push_back (std::move (predicate));
+    }
+
+  translated = new TyTy::OpaqueType (type.get_locus (),
+                                    type.get_mappings ().get_hirid (),
+                                    specified_bounds);
+}
+
 TyTy::ParamType *
 TypeResolveGenericParam::Resolve (HIR::GenericParam &param, bool apply_sized)
 {
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h 
b/gcc/rust/typecheck/rust-hir-type-check-type.h
index 558dc5cd0b6..fc272e639a3 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.h
@@ -60,16 +60,11 @@ public:
   void visit (HIR::NeverType &type) override;
   void visit (HIR::TraitObjectType &type) override;
   void visit (HIR::ParenthesisedType &type) override;
+  void visit (HIR::ImplTraitType &type) override;
 
-  void visit (HIR::TypePathSegmentFunction &segment) override
-  { /* TODO */
-  }
-  void visit (HIR::TraitBound &bound) override
-  { /* TODO */
-  }
-  void visit (HIR::ImplTraitType &type) override
-  { /* TODO */
-  }
+  // These dont need to be implemented as they are segments or part of types
+  void visit (HIR::TypePathSegmentFunction &segment) override {}
+  void visit (HIR::TraitBound &bound) override {}
 
 private:
   TypeCheckType (HirId id)
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.cc 
b/gcc/rust/typecheck/rust-substitution-mapper.cc
index 1e151577180..212ab3f3be5 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.cc
+++ b/gcc/rust/typecheck/rust-substitution-mapper.cc
@@ -346,6 +346,11 @@ SubstMapperInternal::visit (TyTy::DynamicObjectType &type)
 {
   resolved = type.clone ();
 }
+void
+SubstMapperInternal::visit (TyTy::OpaqueType &type)
+{
+  resolved = type.handle_substitions (mappings);
+}
 
 // SubstMapperFromExisting
 
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h 
b/gcc/rust/typecheck/rust-substitution-mapper.h
index bcd93fda4ea..bc54f5614cf 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.h
+++ b/gcc/rust/typecheck/rust-substitution-mapper.h
@@ -63,6 +63,7 @@ public:
   void visit (TyTy::NeverType &) override { rust_unreachable (); }
   void visit (TyTy::DynamicObjectType &) override { rust_unreachable (); }
   void visit (TyTy::ClosureType &) override { rust_unreachable (); }
+  void visit (TyTy::OpaqueType &) override { rust_unreachable (); }
 
 private:
   SubstMapper (HirId ref, HIR::GenericArgs *generics,
@@ -107,6 +108,7 @@ public:
   void visit (TyTy::StrType &type) override;
   void visit (TyTy::NeverType &type) override;
   void visit (TyTy::DynamicObjectType &type) override;
+  void visit (TyTy::OpaqueType &type) override;
 
 private:
   SubstMapperInternal (HirId ref, TyTy::SubstitutionArgumentMappings 
&mappings);
@@ -146,6 +148,7 @@ public:
   void visit (TyTy::PlaceholderType &) override { rust_unreachable (); }
   void visit (TyTy::ProjectionType &) override { rust_unreachable (); }
   void visit (TyTy::DynamicObjectType &) override { rust_unreachable (); }
+  void visit (TyTy::OpaqueType &type) override { rust_unreachable (); }
 
 private:
   SubstMapperFromExisting (TyTy::BaseType *concrete, TyTy::BaseType *receiver);
@@ -185,6 +188,7 @@ public:
   void visit (const TyTy::PlaceholderType &) override {}
   void visit (const TyTy::ProjectionType &) override {}
   void visit (const TyTy::DynamicObjectType &) override {}
+  void visit (const TyTy::OpaqueType &type) override {}
 
 private:
   GetUsedSubstArgs ();
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc 
b/gcc/rust/typecheck/rust-tyty-bounds.cc
index fc35abb6ec4..9187fc63141 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -136,6 +136,7 @@ TypeBoundsProbe::assemble_sized_builtin ()
     case TyTy::NEVER:
     case TyTy::PLACEHOLDER:
     case TyTy::PROJECTION:
+    case TyTy::OPAQUE:
       assemble_builtin_candidate (LangItem::Kind::SIZED);
       break;
 
diff --git a/gcc/rust/typecheck/rust-tyty-call.h 
b/gcc/rust/typecheck/rust-tyty-call.h
index 00ac655e5e4..c42fdcd08f9 100644
--- a/gcc/rust/typecheck/rust-tyty-call.h
+++ b/gcc/rust/typecheck/rust-tyty-call.h
@@ -61,6 +61,7 @@ public:
   void visit (ProjectionType &) override { rust_unreachable (); }
   void visit (DynamicObjectType &) override { rust_unreachable (); }
   void visit (ClosureType &type) override { rust_unreachable (); }
+  void visit (OpaqueType &type) override { rust_unreachable (); }
 
   // tuple-structs
   void visit (ADTType &type) override;
diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h 
b/gcc/rust/typecheck/rust-tyty-cmp.h
index 7088b585eda..c897c1321bd 100644
--- a/gcc/rust/typecheck/rust-tyty-cmp.h
+++ b/gcc/rust/typecheck/rust-tyty-cmp.h
@@ -431,6 +431,22 @@ public:
       }
   }
 
+  virtual void visit (const OpaqueType &type) override
+  {
+    ok = false;
+    if (emit_error_flag)
+      {
+       location_t ref_locus = mappings.lookup_location (type.get_ref ());
+       location_t base_locus
+         = mappings.lookup_location (get_base ()->get_ref ());
+       rich_location r (line_table, 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 ());
+      }
+  }
+
 protected:
   BaseCmp (const BaseType *base, bool emit_errors)
     : mappings (Analysis::Mappings::get ()),
@@ -1571,6 +1587,23 @@ private:
   const DynamicObjectType *base;
 };
 
+class OpaqueCmp : public BaseCmp
+{
+  using Rust::TyTy::BaseCmp::visit;
+
+public:
+  OpaqueCmp (const OpaqueType *base, bool emit_errors)
+    : BaseCmp (base, emit_errors), base (base)
+  {}
+
+  // TODO
+
+private:
+  const BaseType *get_base () const override { return base; }
+
+  const OpaqueType *base;
+};
+
 } // namespace TyTy
 } // namespace Rust
 
diff --git a/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h 
b/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h
index 450e53e728b..d36afc89732 100644
--- a/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h
+++ b/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h
@@ -168,6 +168,8 @@ public:
   {
     // TODO
   }
+
+  void visit (OpaqueType &type) override {}
 };
 
 /** Per crate context for generic type variance analysis. */
diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h 
b/gcc/rust/typecheck/rust-tyty-visitor.h
index 85726ff5325..4f8e785606e 100644
--- a/gcc/rust/typecheck/rust-tyty-visitor.h
+++ b/gcc/rust/typecheck/rust-tyty-visitor.h
@@ -51,6 +51,7 @@ public:
   virtual void visit (ProjectionType &type) = 0;
   virtual void visit (DynamicObjectType &type) = 0;
   virtual void visit (ClosureType &type) = 0;
+  virtual void visit (OpaqueType &type) = 0;
 };
 
 class TyConstVisitor
@@ -80,6 +81,7 @@ public:
   virtual void visit (const ProjectionType &type) = 0;
   virtual void visit (const DynamicObjectType &type) = 0;
   virtual void visit (const ClosureType &type) = 0;
+  virtual void visit (const OpaqueType &type) = 0;
 };
 
 } // namespace TyTy
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index fe4b8fca139..5d5da4d258c 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -111,6 +111,9 @@ TypeKindFormat::to_string (TypeKind kind)
     case TypeKind::CLOSURE:
       return "Closure";
 
+    case TypeKind::OPAQUE:
+      return "Opaque";
+
     case TypeKind::ERROR:
       return "ERROR";
     }
@@ -217,7 +220,7 @@ BaseType::is_unit () const
     case FLOAT:
     case USIZE:
     case ISIZE:
-
+    case OPAQUE:
     case STR:
     case DYNAMIC:
     case ERROR:
@@ -543,6 +546,17 @@ BaseType::destructure () const
        {
          x = p->get ();
        }
+      // else if (auto p = x->try_as<const OpaqueType> ())
+      //   {
+      //     auto pr = p->resolve ();
+
+      //     rust_debug ("XXXXXX")
+
+      //     if (pr == x)
+      //       return pr;
+
+      //     x = pr;
+      //   }
       else
        {
          return x;
@@ -792,6 +806,7 @@ BaseType::has_substitutions_defined () const
     case TUPLE:
     case PARAM:
     case PLACEHOLDER:
+    case OPAQUE:
       return false;
 
       case PROJECTION: {
@@ -853,6 +868,7 @@ BaseType::needs_generic_substitutions () const
     case TUPLE:
     case PARAM:
     case PLACEHOLDER:
+    case OPAQUE:
       return false;
 
       case PROJECTION: {
@@ -3415,6 +3431,140 @@ ParamType::is_implicit_self_trait () const
   return is_trait_self;
 }
 
+// OpaqueType
+
+OpaqueType::OpaqueType (location_t locus, HirId ref,
+                       std::vector<TypeBoundPredicate> specified_bounds,
+                       std::set<HirId> refs)
+  : BaseType (ref, ref, KIND,
+             {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, "impl"),
+              locus},
+             specified_bounds, refs)
+{}
+
+OpaqueType::OpaqueType (location_t locus, HirId ref, HirId ty_ref,
+                       std::vector<TypeBoundPredicate> specified_bounds,
+                       std::set<HirId> refs)
+  : BaseType (ref, ty_ref, KIND,
+             {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, "impl"),
+              locus},
+             specified_bounds, refs)
+{}
+
+bool
+OpaqueType::can_resolve () const
+{
+  return get_ref () != get_ty_ref ();
+}
+
+void
+OpaqueType::accept_vis (TyVisitor &vis)
+{
+  vis.visit (*this);
+}
+
+void
+OpaqueType::accept_vis (TyConstVisitor &vis) const
+{
+  vis.visit (*this);
+}
+
+std::string
+OpaqueType::as_string () const
+{
+  return get_name ();
+}
+
+std::string
+OpaqueType::get_name () const
+{
+  return "impl " + raw_bounds_as_name ();
+}
+
+bool
+OpaqueType::can_eq (const BaseType *other, bool emit_errors) const
+{
+  OpaqueCmp r (this, emit_errors);
+  return r.can_eq (other);
+}
+
+BaseType *
+OpaqueType::clone () const
+{
+  return new OpaqueType (ident.locus, get_ref (), get_ty_ref (),
+                        get_specified_bounds (), get_combined_refs ());
+}
+
+BaseType *
+OpaqueType::resolve () const
+{
+  TyVar var (get_ty_ref ());
+  BaseType *r = var.get_tyty ();
+
+  while (r->get_kind () == TypeKind::OPAQUE)
+    {
+      OpaqueType *rr = static_cast<OpaqueType *> (r);
+      if (!rr->can_resolve ())
+       break;
+
+      TyVar v (rr->get_ty_ref ());
+      BaseType *n = v.get_tyty ();
+
+      // fix infinite loop
+      if (r == n)
+       break;
+
+      r = n;
+    }
+
+  if (r->get_kind () == TypeKind::OPAQUE && (r->get_ref () == r->get_ty_ref 
()))
+    return TyVar (r->get_ty_ref ()).get_tyty ();
+
+  return r;
+}
+
+bool
+OpaqueType::is_equal (const BaseType &other) const
+{
+  auto other2 = static_cast<const OpaqueType &> (other);
+  if (can_resolve () != other2.can_resolve ())
+    return false;
+
+  if (can_resolve ())
+    return resolve ()->can_eq (other2.resolve (), false);
+
+  return bounds_compatible (other, UNDEF_LOCATION, false);
+}
+
+OpaqueType *
+OpaqueType::handle_substitions (SubstitutionArgumentMappings &subst_mappings)
+{
+  // SubstitutionArg arg = SubstitutionArg::error ();
+  // bool ok = subst_mappings.get_argument_for_symbol (this, &arg);
+  // if (!ok || arg.is_error ())
+  //   return this;
+
+  // OpaqueType *p = static_cast<OpaqueType *> (clone ());
+  // subst_mappings.on_param_subst (*p, arg);
+
+  // // there are two cases one where we substitute directly to a new PARAM and
+  // // otherwise
+  // if (arg.get_tyty ()->get_kind () == TyTy::TypeKind::PARAM)
+  //   {
+  //     p->set_ty_ref (arg.get_tyty ()->get_ref ());
+  //     return p;
+  //   }
+
+  // // this is the new subst that this needs to pass
+  // p->set_ref (mappings.get_next_hir_id ());
+  // p->set_ty_ref (arg.get_tyty ()->get_ref ());
+
+  // return p;
+
+  rust_unreachable ();
+  return nullptr;
+}
+
 // StrType
 
 StrType::StrType (HirId ref, std::set<HirId> refs)
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 504a14e3773..f83caec3bd0 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -73,6 +73,7 @@ enum TypeKind
   PROJECTION,
   DYNAMIC,
   CLOSURE,
+  OPAQUE,
   // there are more to add...
   ERROR
 };
@@ -408,6 +409,39 @@ private:
   HIR::GenericParam &param;
 };
 
+class OpaqueType : public BaseType
+{
+public:
+  static constexpr auto KIND = TypeKind::OPAQUE;
+
+  OpaqueType (location_t locus, HirId ref,
+             std::vector<TypeBoundPredicate> specified_bounds,
+             std::set<HirId> refs = std::set<HirId> ());
+
+  OpaqueType (location_t locus, HirId ref, HirId ty_ref,
+             std::vector<TypeBoundPredicate> specified_bounds,
+             std::set<HirId> refs = std::set<HirId> ());
+
+  void accept_vis (TyVisitor &vis) override;
+  void accept_vis (TyConstVisitor &vis) const override;
+
+  std::string as_string () const override;
+
+  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+
+  BaseType *clone () const final override;
+
+  bool can_resolve () const;
+
+  BaseType *resolve () const;
+
+  std::string get_name () const override final;
+
+  bool is_equal (const BaseType &other) const override;
+
+  OpaqueType *handle_substitions (SubstitutionArgumentMappings &mappings);
+};
+
 class StructFieldType
 {
 public:
diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc
index b779e7d4614..294b677ba41 100644
--- a/gcc/rust/typecheck/rust-unify.cc
+++ b/gcc/rust/typecheck/rust-unify.cc
@@ -189,7 +189,7 @@ UnifyRules::go ()
               == TyTy::InferType::GENERAL;
       bool expected_is_concrete
        = ltype->is_concrete () && !lhs_is_general_infer_var;
-      bool rneeds_infer = expected_is_concrete && rgot_param;
+      bool rneeds_infer = expected_is_concrete && (rgot_param);
 
       bool lgot_param = ltype->get_kind () == TyTy::TypeKind::PARAM;
       bool rhs_is_infer_var = rtype->get_kind () == TyTy::TypeKind::INFER;
@@ -199,7 +199,7 @@ UnifyRules::go ()
               == TyTy::InferType::GENERAL;
       bool receiver_is_concrete
        = rtype->is_concrete () && !rhs_is_general_infer_var;
-      bool lneeds_infer = receiver_is_concrete && lgot_param;
+      bool lneeds_infer = receiver_is_concrete && (lgot_param);
 
       if (rneeds_infer)
        {
@@ -312,6 +312,9 @@ UnifyRules::go ()
     case TyTy::CLOSURE:
       return expect_closure (static_cast<TyTy::ClosureType *> (ltype), rtype);
 
+    case TyTy::OPAQUE:
+      return expect_opaque (static_cast<TyTy::OpaqueType *> (ltype), rtype);
+
     case TyTy::ERROR:
       return new TyTy::ErrorType (0);
     }
@@ -400,7 +403,8 @@ UnifyRules::expect_inference_variable (TyTy::InferType 
*ltype,
     case TyTy::PLACEHOLDER:
     case TyTy::PROJECTION:
     case TyTy::DYNAMIC:
-      case TyTy::CLOSURE: {
+    case TyTy::CLOSURE:
+      case TyTy::OPAQUE: {
        bool is_valid = (ltype->get_infer_kind ()
                         == TyTy::InferType::InferTypeKind::GENERAL);
        if (is_valid)
@@ -528,6 +532,7 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, 
TyTy::BaseType *rtype)
     case TyTy::PROJECTION:
     case TyTy::DYNAMIC:
     case TyTy::CLOSURE:
+    case TyTy::OPAQUE:
     case TyTy::ERROR:
       return new TyTy::ErrorType (0);
     }
@@ -572,6 +577,7 @@ UnifyRules::expect_str (TyTy::StrType *ltype, 
TyTy::BaseType *rtype)
     case TyTy::PROJECTION:
     case TyTy::DYNAMIC:
     case TyTy::CLOSURE:
+    case TyTy::OPAQUE:
     case TyTy::ERROR:
       return new TyTy::ErrorType (0);
     }
@@ -642,6 +648,7 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, 
TyTy::BaseType *rtype)
     case TyTy::PROJECTION:
     case TyTy::DYNAMIC:
     case TyTy::CLOSURE:
+    case TyTy::OPAQUE:
     case TyTy::ERROR:
       return new TyTy::ErrorType (0);
     }
@@ -712,6 +719,7 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, 
TyTy::BaseType *rtype)
     case TyTy::PROJECTION:
     case TyTy::DYNAMIC:
     case TyTy::CLOSURE:
+    case TyTy::OPAQUE:
     case TyTy::ERROR:
       return new TyTy::ErrorType (0);
     }
@@ -773,6 +781,7 @@ UnifyRules::expect_param (TyTy::ParamType *ltype, 
TyTy::BaseType *rtype)
     case TyTy::PROJECTION:
     case TyTy::DYNAMIC:
     case TyTy::CLOSURE:
+    case TyTy::OPAQUE:
     case TyTy::ERROR:
       return new TyTy::ErrorType (0);
     }
@@ -832,6 +841,7 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, 
TyTy::BaseType *rtype)
     case TyTy::PROJECTION:
     case TyTy::DYNAMIC:
     case TyTy::CLOSURE:
+    case TyTy::OPAQUE:
     case TyTy::ERROR:
       return new TyTy::ErrorType (0);
     }
@@ -890,6 +900,7 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, 
TyTy::BaseType *rtype)
     case TyTy::PROJECTION:
     case TyTy::DYNAMIC:
     case TyTy::CLOSURE:
+    case TyTy::OPAQUE:
     case TyTy::ERROR:
       return new TyTy::ErrorType (0);
     }
@@ -980,6 +991,7 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, 
TyTy::BaseType *rtype)
     case TyTy::PROJECTION:
     case TyTy::DYNAMIC:
     case TyTy::CLOSURE:
+    case TyTy::OPAQUE:
     case TyTy::ERROR:
       return new TyTy::ErrorType (0);
     }
@@ -1096,6 +1108,7 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, 
TyTy::BaseType *rtype)
     case TyTy::PROJECTION:
     case TyTy::DYNAMIC:
     case TyTy::CLOSURE:
+    case TyTy::OPAQUE:
     case TyTy::ERROR:
       return new TyTy::ErrorType (0);
     }
@@ -1166,6 +1179,7 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, 
TyTy::BaseType *rtype)
     case TyTy::PROJECTION:
     case TyTy::DYNAMIC:
     case TyTy::CLOSURE:
+    case TyTy::OPAQUE:
     case TyTy::ERROR:
       return new TyTy::ErrorType (0);
     }
@@ -1213,6 +1227,7 @@ UnifyRules::expect_bool (TyTy::BoolType *ltype, 
TyTy::BaseType *rtype)
     case TyTy::PROJECTION:
     case TyTy::DYNAMIC:
     case TyTy::CLOSURE:
+    case TyTy::OPAQUE:
     case TyTy::ERROR:
       return new TyTy::ErrorType (0);
     }
@@ -1260,6 +1275,7 @@ UnifyRules::expect_char (TyTy::CharType *ltype, 
TyTy::BaseType *rtype)
     case TyTy::PROJECTION:
     case TyTy::DYNAMIC:
     case TyTy::CLOSURE:
+    case TyTy::OPAQUE:
     case TyTy::ERROR:
       return new TyTy::ErrorType (0);
     }
@@ -1314,6 +1330,7 @@ UnifyRules::expect_int (TyTy::IntType *ltype, 
TyTy::BaseType *rtype)
     case TyTy::PROJECTION:
     case TyTy::DYNAMIC:
     case TyTy::CLOSURE:
+    case TyTy::OPAQUE:
     case TyTy::ERROR:
       return new TyTy::ErrorType (0);
     }
@@ -1368,6 +1385,7 @@ UnifyRules::expect_uint (TyTy::UintType *ltype, 
TyTy::BaseType *rtype)
     case TyTy::PROJECTION:
     case TyTy::DYNAMIC:
     case TyTy::CLOSURE:
+    case TyTy::OPAQUE:
     case TyTy::ERROR:
       return new TyTy::ErrorType (0);
     }
@@ -1422,6 +1440,7 @@ UnifyRules::expect_float (TyTy::FloatType *ltype, 
TyTy::BaseType *rtype)
     case TyTy::PROJECTION:
     case TyTy::DYNAMIC:
     case TyTy::CLOSURE:
+    case TyTy::OPAQUE:
     case TyTy::ERROR:
       return new TyTy::ErrorType (0);
     }
@@ -1469,6 +1488,7 @@ UnifyRules::expect_isize (TyTy::ISizeType *ltype, 
TyTy::BaseType *rtype)
     case TyTy::PROJECTION:
     case TyTy::DYNAMIC:
     case TyTy::CLOSURE:
+    case TyTy::OPAQUE:
     case TyTy::ERROR:
       return new TyTy::ErrorType (0);
     }
@@ -1516,6 +1536,7 @@ UnifyRules::expect_usize (TyTy::USizeType *ltype, 
TyTy::BaseType *rtype)
     case TyTy::PROJECTION:
     case TyTy::DYNAMIC:
     case TyTy::CLOSURE:
+    case TyTy::OPAQUE:
     case TyTy::ERROR:
       return new TyTy::ErrorType (0);
     }
@@ -1581,6 +1602,7 @@ UnifyRules::expect_placeholder (TyTy::PlaceholderType 
*ltype,
     case TyTy::USIZE:
     case TyTy::ISIZE:
     case TyTy::NEVER:
+    case TyTy::OPAQUE:
       if (infer_flag)
        return rtype->clone ();
       gcc_fallthrough ();
@@ -1632,6 +1654,7 @@ UnifyRules::expect_projection (TyTy::ProjectionType 
*ltype,
     case TyTy::ISIZE:
     case TyTy::NEVER:
     case TyTy::PLACEHOLDER:
+    case TyTy::OPAQUE:
     case TyTy::ERROR:
       return new TyTy::ErrorType (0);
     }
@@ -1690,6 +1713,7 @@ UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, 
TyTy::BaseType *rtype)
     case TyTy::NEVER:
     case TyTy::PLACEHOLDER:
     case TyTy::PROJECTION:
+    case TyTy::OPAQUE:
     case TyTy::ERROR:
       return new TyTy::ErrorType (0);
     }
@@ -1739,6 +1763,65 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, 
TyTy::BaseType *rtype)
       }
       break;
 
+    case TyTy::SLICE:
+    case TyTy::PARAM:
+    case TyTy::POINTER:
+    case TyTy::STR:
+    case TyTy::ADT:
+    case TyTy::REF:
+    case TyTy::ARRAY:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::UINT:
+    case TyTy::FLOAT:
+    case TyTy::USIZE:
+    case TyTy::ISIZE:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::OPAQUE:
+    case TyTy::ERROR:
+      return new TyTy::ErrorType (0);
+    }
+  return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype)
+{
+  switch (rtype->get_kind ())
+    {
+      case TyTy::INFER: {
+       TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+       bool is_valid
+         = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+       if (is_valid)
+         return ltype->clone ();
+      }
+      break;
+
+      case TyTy::OPAQUE: {
+       auto &type = *static_cast<TyTy::OpaqueType *> (rtype);
+       if (ltype->num_specified_bounds () != type.num_specified_bounds ())
+         {
+           return new TyTy::ErrorType (0);
+         }
+
+       if (!ltype->bounds_compatible (type, locus, true))
+         {
+           return new TyTy::ErrorType (0);
+         }
+
+       return ltype->clone ();
+      }
+      break;
+
+    case TyTy::CLOSURE:
     case TyTy::SLICE:
     case TyTy::PARAM:
     case TyTy::POINTER:
diff --git a/gcc/rust/typecheck/rust-unify.h b/gcc/rust/typecheck/rust-unify.h
index 20f7b4e8a5c..5ff3b7c48db 100644
--- a/gcc/rust/typecheck/rust-unify.h
+++ b/gcc/rust/typecheck/rust-unify.h
@@ -82,6 +82,8 @@ protected:
                              TyTy::BaseType *rtype);
   TyTy::BaseType *expect_closure (TyTy::ClosureType *ltype,
                                  TyTy::BaseType *rtype);
+  TyTy::BaseType *expect_opaque (TyTy::OpaqueType *ltype,
+                                TyTy::BaseType *rtype);
 
 private:
   UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
-- 
2.45.2

Reply via email to