[gcjx] Patch: FYI: fix 'this', contains_p

Tom Tromey tromey@redhat.com
Tue Nov 8 00:01:00 GMT 2005


I'm checking this in on the gcjx branch.

This does 2 things:

* fixes outer 'this' handling to account for raw types
* changes contains_p to handle nested contains, eg now this can
  be compiled:

    class iter1a<T> { }
    class iter1b<T> { }

    public class iter<S> {
      iter1a<iter1b<? extends S>> field;
      public void m(iter1a<iter1b<? extends S>> f) {
        field = f;
      }
    }

Tom

Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>
	* conversions.cc (widen_instantiation): Directly use contains_p
	on class instance.
	* model/classinst.cc (contains_p): New method.
	* access.cc (accessible_p): Allow wildcards and type variables.
	* model/classinst.hh (model_class_instance::contains_p): Declare.
	* model/this.hh (model_this::check_match): Take erasures.
	* model/this.cc (check_outer): Take erasures.
	(check_match): Likewise.

Index: conversions.cc
===================================================================
--- conversions.cc	(revision 106616)
+++ conversions.cc	(working copy)
@@ -198,29 +198,13 @@
       return true;
     }
 
-  // Now we check 'contains' of each type argument.
-  model_class_instance *from_i = assert_cast<model_class_instance *> (from);
-  // The spec says to do capture conversion on 'from_i' here, but then
-  // it does not define the 'contains' operation on type variables.
-  // This causes us to reject valid assignments.  Instead we just keep
-  // the un-captured parameterization, which does the right thing.
-  model_class_instance *to_i = assert_cast<model_class_instance *> (to);
-  std::list<model_class *> from_args, to_args;
-  from_i->get_type_map (from_args);
-  to_i->get_type_map (to_args);
-
-  std::list<model_class *>::const_iterator from_it = from_args.begin ();
-  std::list<model_class *>::const_iterator to_it = to_args.begin ();
-  while (from_it != from_args.end ())
-    {
-      if (! (*to_it)->contains_p (*from_it))
-	return false;
-
-      ++from_it;
-      ++to_it;
-    }
-  assert (to_it == to_args.end ());
-  return true;
+  // Now we check 'contains' of each type argument.  We can easily do
+  // this by delegating to the class itself.  Note that the spec says
+  // to do capture conversion on 'from' here, but then it does not
+  // define the 'contains' operation on type variables.  This causes
+  // us to reject valid assignments.  Instead we just keep the
+  // un-captured parameterization, which does the right thing.
+  return to->contains_p (from);
 }
 
 bool
Index: model/classinst.cc
===================================================================
--- model/classinst.cc	(revision 106607)
+++ model/classinst.cc	(working copy)
@@ -168,6 +168,29 @@
   return result;
 }
 
+bool
+model_class_instance::contains_p (model_class *oc)
+{
+  model_class_instance *other = dynamic_cast<model_class_instance *> (oc);
+  if (! other || parent != other->get_parent ())
+    return false;
+
+  std::list<ref_type_variable>::const_iterator self_it
+    = type_parameters.begin ();
+
+  while (self_it != type_parameters.end ())
+    {
+      model_class *self_class = type_map.find ((*self_it).get ());
+      // Note that both classes will have the same type variables.
+      model_class *other_class = other->type_map.find ((*self_it).get ());
+      if (! self_class->contains_p (other_class))
+	return false;
+
+      ++self_it;
+    }
+  return true;
+}
+
 void
 model_class_instance::visit (visitor *v)
 {
Index: model/this.cc
===================================================================
--- model/this.cc	(revision 105944)
+++ model/this.cc	(working copy)
@@ -24,8 +24,8 @@
 void
 model_this::check_outer (model_class *current)
 {
-  model_type *self = outer->type ();
-  while (current && current != self)
+  model_type *self = outer->type ()->erasure ();
+  while (current && current->erasure () != self)
     current = current->get_lexically_enclosing_class ();
   if (current == NULL)
     throw error ("%<this%> does not refer to any enclosing class");
@@ -116,7 +116,9 @@
 bool
 model_synthetic_this::check_match (model_class *self, model_class *target)
 {
-  return self->assignable_from_p (target);
+  model_class *sc = assert_cast<model_class *> (self->erasure ());
+  model_class *tc = assert_cast<model_class *> (target->erasure ());
+  return sc->assignable_from_p (tc);
 }
 
 
Index: model/classinst.hh
===================================================================
--- model/classinst.hh	(revision 106607)
+++ model/classinst.hh	(working copy)
@@ -75,6 +75,8 @@
     return parent->erasure ();
   }
 
+  bool contains_p (model_class *);
+
   std::string get_pretty_name () const;
 
   void visit (visitor *);
Index: model/this.hh
===================================================================
--- model/this.hh	(revision 105944)
+++ model/this.hh	(working copy)
@@ -61,7 +61,7 @@
   /// "this" access we allow a subclass as well.
   virtual bool check_match (model_class *one, model_class *two)
   {
-    return one == two;
+    return one->erasure () == two->erasure ();
   }
 
   /// This will create a new model_this object given a referring class
Index: access.cc
===================================================================
--- access.cc	(revision 106616)
+++ access.cc	(working copy)
@@ -46,6 +46,9 @@
   if (t->primitive_p ())
     return true;
   model_class *klass = unwrap_raw_class (assert_cast<model_class *> (t));
+  // FIXME: is this right?
+  if (klass->type_variable_p () || klass->wildcard_p ())
+    return true;
 
   if (! klass->member_p ())
     {



More information about the Java-patches mailing list