@@ -135,27 +135,33 @@ class OverridableCallable extends Callable {
135135 * - `C2.M = C2.M.getInherited(C3)`.
136136 */
137137 Callable getInherited ( SourceDeclarationType t ) {
138- exists ( Callable sourceDecl | result = getInherited1 ( t , sourceDecl ) |
138+ exists ( Callable sourceDecl | result = this . getInherited2 ( t , sourceDecl ) |
139139 hasSourceDeclarationCallable ( t , sourceDecl )
140140 )
141141 }
142142
143- private Callable getInherited0 ( SourceDeclarationType t ) {
143+ private Callable getInherited0 ( ValueOrRefType t ) {
144144 // A (transitive, reflexive) overrider
145- t = this .hasOverrider ( result ) .getASubType * ( ) .getSourceDeclaration ( )
145+ t = this .hasOverrider ( result )
146+ or
147+ // A (transitive) overrider of an interface implementation
148+ t = this .hasOverridingImplementor ( result )
149+ or
150+ exists ( ValueOrRefType mid | result = this .getInherited0 ( mid ) | t = mid .getASubType ( ) )
151+ }
152+
153+ private Callable getInherited1 ( SourceDeclarationType t ) {
154+ exists ( ValueOrRefType t0 | result = getInherited0 ( t0 ) | t = t0 .getSourceDeclaration ( ) )
146155 or
147156 // An interface implementation
148157 exists ( ValueOrRefType s |
149158 result = getAnImplementorSubType ( s ) and
150159 t = s .getSourceDeclaration ( )
151160 )
152- or
153- // A (transitive) overrider of an interface implementation
154- t = this .hasOverridingImplementor ( result ) .getASubType * ( ) .getSourceDeclaration ( )
155161 }
156162
157- private Callable getInherited1 ( SourceDeclarationType t , Callable sourceDecl ) {
158- result = this .getInherited0 ( t ) and
163+ private Callable getInherited2 ( SourceDeclarationType t , Callable sourceDecl ) {
164+ result = this .getInherited1 ( t ) and
159165 sourceDecl = result .getSourceDeclaration ( )
160166 }
161167
@@ -171,50 +177,51 @@ class OverridableCallable extends Callable {
171177 result = c .getDeclaringType ( )
172178 }
173179
174- /**
175- * Gets a callable defined in a sub type of `t` that overrides/implements
176- * this callable, if any.
177- *
178- * The type `t` may be a constructed type: For example, if `t = C<int>`,
179- * then only callables defined in sub types of `C<int>` (and e.g. not
180- * `C<string>`) are valid. In particular, if `C2<T> : C<T>` and `C2`
181- * contains a callable that overrides this callable, then only if `C2<int>`
182- * is ever constructed will the callable in `C2` be considered valid.
183- */
184- Callable getAnOverrider ( TypeWithoutTypeParameters t ) {
185- exists ( OverridableCallable oc , ValueOrRefType sub |
186- result = oc .getAnOverriderAux ( sub ) and
187- t = oc .getAnOverriderBaseType ( sub ) and
188- oc = getABoundInstance ( )
189- )
180+ private predicate isDeclaringSubType ( ValueOrRefType t ) {
181+ t = this .getDeclaringType ( )
182+ or
183+ exists ( ValueOrRefType mid | isDeclaringSubType ( mid ) | t = mid .getASubType ( ) )
190184 }
191185
192- // predicate folding to get proper join order
193- private Callable getAnOverriderAux ( ValueOrRefType t ) {
194- not declaredInTypeWithTypeParameters ( ) and
186+ pragma [ noinline ]
187+ private Callable getAnOverrider0 ( ValueOrRefType t ) {
188+ not this . declaredInTypeWithTypeParameters ( ) and
195189 (
196190 // A (transitive) overrider
197- result = getAnOverrider + ( ) and
191+ result = this . getAnOverrider + ( ) and
198192 t = result .getDeclaringType ( )
199193 or
200194 // An interface implementation
201- result = getAnImplementorSubType ( t )
195+ result = this . getAnImplementorSubType ( t )
202196 or
203197 // A (transitive) overrider of an interface implementation
204- result = getAnOverridingImplementor ( ) and
198+ result = this . getAnOverridingImplementor ( ) and
205199 t = result .getDeclaringType ( )
206200 )
207201 }
208202
209- private TypeWithoutTypeParameters getAnOverriderBaseType ( ValueOrRefType t ) {
210- exists ( getAnOverriderAux ( t ) ) and
211- exists ( Type t0 | t0 = t . getABaseType * ( ) |
212- result = t0
213- or
214- result = t0 . ( ConstructedType ) . getUnboundGeneric ( )
203+ private Callable getAnOverrider1 ( ValueOrRefType t ) {
204+ result = this . getAnOverrider0 ( t )
205+ or
206+ exists ( ValueOrRefType mid | result = this . getAnOverrider1 ( mid ) |
207+ t = mid . getABaseType ( ) and
208+ this . isDeclaringSubType ( t )
215209 )
216210 }
217211
212+ /**
213+ * Gets a callable defined in a sub type of `t` (which is itself a sub type
214+ * of this callable's declaring type) that overrides/implements this callable,
215+ * if any.
216+ *
217+ * The type `t` may be a constructed type: For example, if `t = C<int>`,
218+ * then only callables defined in sub types of `C<int>` (and e.g. not
219+ * `C<string>`) are valid. In particular, if `C2<T> : C<T>` and `C2`
220+ * contains a callable that overrides this callable, then only if `C2<int>`
221+ * is ever constructed will the callable in `C2` be considered valid.
222+ */
223+ Callable getAnOverrider ( ValueOrRefType t ) { result = this .getABoundInstance ( ) .getAnOverrider1 ( t ) }
224+
218225 /**
219226 * Gets a bound instance of this callable.
220227 *
@@ -264,7 +271,7 @@ class OverridableMethod extends Method, OverridableCallable {
264271 result = OverridableCallable .super .getInherited ( t )
265272 }
266273
267- override Method getAnOverrider ( TypeWithoutTypeParameters t ) {
274+ override Method getAnOverrider ( ValueOrRefType t ) {
268275 result = OverridableCallable .super .getAnOverrider ( t )
269276 }
270277}
@@ -311,7 +318,7 @@ class OverridableAccessor extends Accessor, OverridableCallable {
311318 result = OverridableCallable .super .getInherited ( t )
312319 }
313320
314- override Accessor getAnOverrider ( TypeWithoutTypeParameters t ) {
321+ override Accessor getAnOverrider ( ValueOrRefType t ) {
315322 result = OverridableCallable .super .getAnOverrider ( t )
316323 }
317324}
0 commit comments