@@ -119,31 +119,54 @@ public CFValue mostSpecific(CFValue other, CFValue backup) {
119119 *
120120 */
121121 public CFValue mostSpecificFromSlot (final Slot thisSlot , final Slot otherSlot , final CFValue other , final CFValue backup ) {
122- // TODO: refactor this method
123- if (thisSlot instanceof VariableSlot && otherSlot instanceof VariableSlot ) {
124- if (thisSlot .isMergedTo (otherSlot )) {
125- return other ;
126- } else if (otherSlot .isMergedTo (thisSlot )) {
127- return this ;
128- } else if (thisSlot instanceof RefinementVariableSlot
129- && ((RefinementVariableSlot ) thisSlot ).getRefined ().equals (otherSlot )) {
130-
131- return this ;
132- } else if (otherSlot instanceof RefinementVariableSlot
133- && ((RefinementVariableSlot ) otherSlot ).getRefined ().equals (thisSlot )) {
134-
135- return other ;
136- } else {
137- // Check if one of these has refinement variables that were merged to the other.
138- for (RefinementVariableSlot slot : ((VariableSlot ) thisSlot ).getRefinedToSlots ()) {
139- if (slot .isMergedTo (otherSlot )) {
140- return other ;
141- }
122+ if (thisSlot .isMergedTo (otherSlot )) {
123+ return other ;
124+ }
125+
126+ if (otherSlot .isMergedTo (thisSlot )) {
127+ return this ;
128+ }
129+
130+ if (thisSlot instanceof RefinementVariableSlot
131+ && ((RefinementVariableSlot ) thisSlot ).getRefined ().equals (otherSlot )) {
132+ return this ;
133+ }
134+
135+ if (otherSlot instanceof RefinementVariableSlot
136+ && ((RefinementVariableSlot ) otherSlot ).getRefined ().equals (thisSlot )) {
137+ return other ;
138+ }
139+
140+ if (thisSlot instanceof RefinementVariableSlot
141+ && otherSlot instanceof RefinementVariableSlot
142+ && ((RefinementVariableSlot ) thisSlot ).getRefined ().equals (((RefinementVariableSlot ) otherSlot ).getRefined ())) {
143+ // This happens when a local variable is declared with initializer, and is reassigned afterwards. E.g.
144+ // Object obj = null;
145+ // obj = new Object();
146+ // return obj;
147+ // Suppose RefinementVar(1) is created at variable declaration, RefinementVar(2) is created at re-assignment.
148+ // Then at the return point, when getting the most specific type of obj,
149+ // "thisSlot" is RefinementVar(1), coming from "getValueFromFactory".
150+ // "otherSlot" is RefinementVar(2), coming from the store value.
151+ // The store value is more precise, so we choose "other" as the most specific type.
152+ assert thisSlot .getId () <= otherSlot .getId ();
153+ return other ;
154+ }
155+
156+ if (thisSlot instanceof VariableSlot ) {
157+ // Check if one of these has refinement variables that were merged to the other.
158+ for (RefinementVariableSlot slot : ((VariableSlot ) thisSlot ).getRefinedToSlots ()) {
159+ if (slot .isMergedTo (otherSlot )) {
160+ return other ;
142161 }
143- for (RefinementVariableSlot slot : ((VariableSlot ) otherSlot ).getRefinedToSlots ()) {
144- if (slot .isMergedTo (thisSlot )) {
145- return this ;
146- }
162+ }
163+ }
164+
165+ if (otherSlot instanceof VariableSlot ) {
166+ // Same as above
167+ for (RefinementVariableSlot slot : ((VariableSlot ) otherSlot ).getRefinedToSlots ()) {
168+ if (slot .isMergedTo (thisSlot )) {
169+ return this ;
147170 }
148171 }
149172 }
0 commit comments