]> gcc.gnu.org Git - gcc.git/commitdiff
gccrs: Respect the concrete type when resolving qualifed path types
authorPhilip Herron <herron.philip@googlemail.com>
Wed, 31 May 2023 15:06:58 +0000 (16:06 +0100)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 16 Jan 2024 17:46:24 +0000 (18:46 +0100)
Concrete types can resolve to assoicated impl blocks which will allow us to
resolve the path to the projection type instead of the placeholder trait
associated type which can change. The projection will be fixed and is
safer to use.

Fixes #2165 #2166

gcc/rust/ChangeLog:

* typecheck/rust-hir-trait-resolve.cc: when the bound is concrete keep the mapping
* typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::visit): add missing call
* typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): make this the same as paths

gcc/testsuite/ChangeLog:

* rust/compile/issue-2165.rs: New test.
* rust/compile/issue-2166.rs: New test.

Signed-off-by: Philip Herron <herron.philip@googlemail.com>
gcc/rust/typecheck/rust-hir-trait-resolve.cc
gcc/rust/typecheck/rust-hir-type-check-path.cc
gcc/rust/typecheck/rust-hir-type-check-type.cc
gcc/testsuite/rust/compile/issue-2165.rs [new file with mode: 0644]
gcc/testsuite/rust/compile/issue-2166.rs [new file with mode: 0644]

index 37d4239fc0cb4722e7b7ed1163e0b9ed5db7da65..cf8c9c9780789018a1cfd774bd0d4bca65a12cfd 100644 (file)
@@ -415,7 +415,10 @@ AssociatedImplTrait::setup_associated_types (
   // we need to figure out what Y is
 
   TyTy::BaseType *associated_self = get_self ();
-  rust_assert (associated_self->can_eq (self, false));
+
+  rust_debug ("setup_associated_types for: %s->%s bound %s",
+             associated_self->debug_str ().c_str (),
+             self->debug_str ().c_str (), bound.as_string ().c_str ());
 
   // grab the parameters
   HIR::ImplBlock &impl_block = *get_impl_block ();
@@ -445,6 +448,14 @@ AssociatedImplTrait::setup_associated_types (
        }
     }
 
+  // this callback gives us the parameters that get substituted so we can
+  // compute the constrained type parameters for this impl block
+  std::map<std::string, HirId> param_mappings;
+  TyTy::ParamSubstCb param_subst_cb
+    = [&] (const TyTy::ParamType &p, const TyTy::SubstitutionArg &a) {
+       param_mappings[p.get_symbol ()] = a.get_tyty ()->get_ref ();
+      };
+
   // generate inference variables for these bound arguments so we can compute
   // their values
   Location locus;
@@ -458,19 +469,13 @@ AssociatedImplTrait::setup_associated_types (
        }
       else
        {
-         args.push_back (
-           TyTy::SubstitutionArg (&p, p.get_param_ty ()->resolve ()));
+         TyTy::ParamType *param = p.get_param_ty ();
+         TyTy::BaseType *resolved = param->destructure ();
+         args.push_back (TyTy::SubstitutionArg (&p, resolved));
+         param_mappings[param->get_symbol ()] = resolved->get_ref ();
        }
     }
 
-  // this callback gives us the parameters that get substituted so we can
-  // compute the constrained type parameters for this impl block
-  std::map<std::string, HirId> param_mappings;
-  TyTy::ParamSubstCb param_subst_cb
-    = [&] (const TyTy::ParamType &p, const TyTy::SubstitutionArg &a) {
-       param_mappings[p.get_symbol ()] = a.get_tyty ()->get_ref ();
-      };
-
   TyTy::SubstitutionArgumentMappings infer_arguments (std::move (args), {},
                                                      locus, param_subst_cb);
   TyTy::BaseType *impl_self_infer
index a52a4e4397ac02fc3a6f995e81351e81f3b6802c..6ae58cea631a50ac5b65c5338c95f49d4ba4aa6f 100644 (file)
@@ -89,6 +89,8 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr)
     = lookup_associated_impl_block (specified_bound, root);
   if (associated_impl_trait != nullptr)
     {
+      associated_impl_trait->setup_associated_types (root, specified_bound);
+
       for (auto &i :
           associated_impl_trait->get_impl_block ()->get_impl_items ())
        {
index 41c444029b6543cbbaa460918dac039bddae26b6..0675c491a9399e9308466ef7055568756c5ce8c8 100644 (file)
@@ -178,8 +178,8 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path)
     }
 
   // Resolve the trait now
-  TraitReference *trait_ref
-    = TraitResolver::Resolve (*qual_path_type.get_trait ().get ());
+  std::unique_ptr<HIR::TypePath> &trait_path_ref = qual_path_type.get_trait ();
+  TraitReference *trait_ref = TraitResolver::Resolve (*trait_path_ref.get ());
   if (trait_ref->is_error ())
     return;
 
@@ -201,36 +201,6 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path)
   // inherit the bound
   root->inherit_bounds ({specified_bound});
 
-  // setup the associated types
-  const TraitReference *specified_bound_ref = specified_bound.get ();
-  auto candidates = TypeBoundsProbe::Probe (root);
-  AssociatedImplTrait *associated_impl_trait = nullptr;
-  for (auto &probed_bound : candidates)
-    {
-      const TraitReference *bound_trait_ref = probed_bound.first;
-      const HIR::ImplBlock *associated_impl = probed_bound.second;
-
-      HirId impl_block_id = associated_impl->get_mappings ().get_hirid ();
-      AssociatedImplTrait *associated = nullptr;
-      bool found_impl_trait
-       = context->lookup_associated_trait_impl (impl_block_id, &associated);
-      if (found_impl_trait)
-       {
-         bool found_trait = specified_bound_ref->is_equal (*bound_trait_ref);
-         bool found_self = associated->get_self ()->can_eq (root, false);
-         if (found_trait && found_self)
-           {
-             associated_impl_trait = associated;
-             break;
-           }
-       }
-    }
-
-  if (associated_impl_trait != nullptr)
-    {
-      associated_impl_trait->setup_associated_types (root, specified_bound);
-    }
-
   // lookup the associated item from the specified bound
   std::unique_ptr<HIR::TypePathSegment> &item_seg
     = path.get_associated_segment ();
@@ -243,8 +213,57 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path)
       return;
     }
 
-  // infer the root type
-  translated = item.get_tyty_for_receiver (root);
+  // we try to look for the real impl item if possible
+  HIR::ImplItem *impl_item = nullptr;
+  if (root->is_concrete ())
+    {
+      // lookup the associated impl trait for this if we can (it might be
+      // generic)
+      AssociatedImplTrait *associated_impl_trait
+       = lookup_associated_impl_block (specified_bound, root);
+      if (associated_impl_trait != nullptr)
+       {
+         associated_impl_trait->setup_associated_types (root, specified_bound);
+
+         for (auto &i :
+              associated_impl_trait->get_impl_block ()->get_impl_items ())
+           {
+             bool found = i->get_impl_item_name ().compare (
+                            item_seg_identifier.as_string ())
+                          == 0;
+             if (found)
+               {
+                 impl_item = i.get ();
+                 break;
+               }
+           }
+       }
+    }
+
+  NodeId root_resolved_node_id = UNKNOWN_NODEID;
+  if (impl_item == nullptr)
+    {
+      // this may be valid as there could be a default trait implementation here
+      // and we dont need to worry if the trait item is actually implemented or
+      // not because this will have already been validated as part of the trait
+      // impl block
+      translated = item.get_tyty_for_receiver (root);
+      root_resolved_node_id
+       = item.get_raw_item ()->get_mappings ().get_nodeid ();
+    }
+  else
+    {
+      HirId impl_item_id = impl_item->get_impl_mappings ().get_hirid ();
+      bool ok = query_type (impl_item_id, &translated);
+      if (!ok)
+       {
+         // FIXME
+         // I think query_type should error if required here anyway
+         return;
+       }
+
+      root_resolved_node_id = impl_item->get_impl_mappings ().get_nodeid ();
+    }
 
   // turbo-fish segment path::<ty>
   if (item_seg->get_type () == HIR::TypePathSegment::SegmentType::GENERIC)
@@ -270,8 +289,6 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path)
     }
 
   // continue on as a path-in-expression
-  const TraitItemReference *trait_item_ref = item.get_raw_item ();
-  NodeId root_resolved_node_id = trait_item_ref->get_mappings ().get_nodeid ();
   bool fully_resolved = path.get_segments ().empty ();
   if (fully_resolved)
     {
diff --git a/gcc/testsuite/rust/compile/issue-2165.rs b/gcc/testsuite/rust/compile/issue-2165.rs
new file mode 100644 (file)
index 0000000..199bc13
--- /dev/null
@@ -0,0 +1,9 @@
+pub trait Alpha<T = Self> {
+    type Beta;
+}
+
+impl Alpha for u32 {
+    type Beta = u32;
+}
+
+type Delta = <u32 as Alpha<u32>>::Beta;
diff --git a/gcc/testsuite/rust/compile/issue-2166.rs b/gcc/testsuite/rust/compile/issue-2166.rs
new file mode 100644 (file)
index 0000000..f333888
--- /dev/null
@@ -0,0 +1,23 @@
+trait Add {
+    type Output;
+
+    fn add(self) -> u32;
+}
+
+impl Add for u32 {
+    type Output = u32;
+
+    fn add(self) -> u32 {
+        // { dg-warning "unused name" "" { target *-*-* } .-1 }
+        0
+    }
+}
+
+impl<'a> Add for &'a u32 {
+    type Output = u32;
+
+    fn add(self) -> <u32 as Add>::Output {
+        // { dg-warning "unused name" "" { target *-*-* } .-1 }
+        0
+    }
+}
This page took 0.071347 seconds and 5 git commands to generate.