]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: add new method to infer impl block type
authorPhilip Herron <herron.philip@googlemail.com>
Tue, 20 Jun 2023 11:21:02 +0000 (12:21 +0100)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 16 Jan 2024 17:46:28 +0000 (18:46 +0100)
When we resolve a path segment the associated impl Self may not be a type
which 'binds' generic types. Which would be any type which does not inherit
SubstitionRef base class. There is a case where an impl block for generic
type T has bound generics on the trait bound of the trait impl block this
allows us to infer the T for this case.

Addresses #1893

gcc/rust/ChangeLog:

* typecheck/rust-hir-type-check-item.cc (TypeCheckItem::ResolveImplBlockSelfWithInference):
New helper utility to infer non concrete types and handle the case where its not a
binding generic type (which inherits SubstitutionRef)
* typecheck/rust-hir-type-check-item.h: new helper prototype
* typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::resolve_segments): use this helper

Signed-off-by: Philip Herron <herron.philip@googlemail.com>
gcc/rust/typecheck/rust-hir-type-check-item.cc
gcc/rust/typecheck/rust-hir-type-check-item.h
gcc/rust/typecheck/rust-hir-type-check-path.cc

index 6d6ab63e85f23fc7a23f8416bee8914d6435aaaf..8a06e6dbd189f2eb68cc95cba128a4a5d1a99b01 100644 (file)
@@ -73,6 +73,51 @@ TypeCheckItem::ResolveImplBlockSelf (HIR::ImplBlock &impl_block)
   return resolver.resolve_impl_block_self (impl_block);
 }
 
+TyTy::BaseType *
+TypeCheckItem::ResolveImplBlockSelfWithInference (HIR::ImplBlock &impl,
+                                                 Location locus)
+{
+  TypeCheckItem resolver;
+
+  bool failed_flag = false;
+  std::vector<TyTy::SubstitutionParamMapping> substitutions
+    = resolver.resolve_impl_block_substitutions (impl, failed_flag);
+  if (failed_flag)
+    {
+      return new TyTy::ErrorType (impl.get_mappings ().get_hirid ());
+    }
+
+  // now that we have the param mappings we need to query the self type
+  TyTy::BaseType *self = resolver.resolve_impl_block_self (impl);
+
+  // nothing to do
+  if (substitutions.empty () || self->is_concrete ())
+    return self;
+
+  // generate inference variables for the subst-param-mappings
+  std::vector<TyTy::SubstitutionArg> args;
+  for (auto &p : substitutions)
+    {
+      if (p.needs_substitution ())
+       {
+         TyTy::TyVar infer_var = TyTy::TyVar::get_implicit_infer_var (locus);
+         args.push_back (TyTy::SubstitutionArg (&p, infer_var.get_tyty ()));
+       }
+      else
+       {
+         TyTy::ParamType *param = p.get_param_ty ();
+         TyTy::BaseType *resolved = param->destructure ();
+         args.push_back (TyTy::SubstitutionArg (&p, resolved));
+       }
+    }
+
+  // create argument mappings
+  TyTy::SubstitutionArgumentMappings infer_arguments (std::move (args), {},
+                                                     locus);
+
+  return SubstMapperInternal::Resolve (self, infer_arguments);
+}
+
 void
 TypeCheckItem::visit (HIR::TypeAlias &alias)
 {
index 432b29271a5bb348f2c7398e1b26523ecad4661d..fc49dc69b05cee7e35ad82b9ee9fe044439b52ed 100644 (file)
@@ -35,6 +35,9 @@ public:
 
   static TyTy::BaseType *ResolveImplBlockSelf (HIR::ImplBlock &impl_block);
 
+  static TyTy::BaseType *
+  ResolveImplBlockSelfWithInference (HIR::ImplBlock &impl, Location locus);
+
   void visit (HIR::Module &module) override;
   void visit (HIR::Function &function) override;
   void visit (HIR::TypeAlias &alias) override;
index 4bac75a63d9755d96f550b97a7fb93bb9c982dac..7de6f6627b09ebd52d000bcbcd49ca4e7c695768 100644 (file)
@@ -415,11 +415,8 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
            = context->lookup_associated_trait_impl (impl_block_id,
                                                     &associated);
          TyTy::BaseType *impl_block_ty
-           = TypeCheckItem::ResolveImplBlockSelf (*associated_impl_block);
-
-         if (impl_block_ty->needs_generic_substitutions ())
-           impl_block_ty
-             = SubstMapper::InferSubst (impl_block_ty, seg.get_locus ());
+           = TypeCheckItem::ResolveImplBlockSelfWithInference (
+             *associated_impl_block, seg.get_locus ());
 
          prev_segment = unify_site (seg.get_mappings ().get_hirid (),
                                     TyTy::TyWithLocation (prev_segment),