[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