@@ -3255,19 +3255,28 @@ private predicate inferOperationType =
32553255 ContextTyping:: CheckContextTyping< inferOperationType0 / 3 > :: check / 2 ;
32563256
32573257pragma [ nomagic]
3258- private Type getFieldExprLookupType ( FieldExpr fe , string name , boolean isDereferenced ) {
3258+ private Type getFieldExprLookupType ( FieldExpr fe , string name , DerefChain derefChain ) {
32593259 exists ( TypePath path |
32603260 result = inferType ( fe .getContainer ( ) , path ) and
32613261 name = fe .getIdentifier ( ) .getText ( ) and
3262- isComplexRootStripped ( path , result ) and
3263- if path .isEmpty ( ) then isDereferenced = false else isDereferenced = true
3262+ isComplexRootStripped ( path , result )
3263+ |
3264+ // TODO: Support full derefence chains as for method calls
3265+ path .isEmpty ( ) and
3266+ derefChain = DerefChain:: nil ( )
3267+ or
3268+ exists ( DerefImplItemNode impl , TypeParamTypeParameter tp |
3269+ tp .getTypeParam ( ) = impl .resolveSelfTy ( ) .getTypeParam ( 0 ) and
3270+ path .getHead ( ) = tp and
3271+ derefChain = DerefChain:: singleton ( impl )
3272+ )
32643273 )
32653274}
32663275
32673276pragma [ nomagic]
3268- private Type getTupleFieldExprLookupType ( FieldExpr fe , int pos , boolean isDereferenced ) {
3277+ private Type getTupleFieldExprLookupType ( FieldExpr fe , int pos , DerefChain derefChain ) {
32693278 exists ( string name |
3270- result = getFieldExprLookupType ( fe , name , isDereferenced ) and
3279+ result = getFieldExprLookupType ( fe , name , derefChain ) and
32713280 pos = name .toInt ( )
32723281 )
32733282}
@@ -3927,12 +3936,15 @@ private module Cached {
39273936 predicate implicitDeref ( AstNode n ) {
39283937 any ( MethodResolution:: MethodCall mc ) .receiverHasImplicitDeref ( n )
39293938 or
3930- n =
3931- any ( FieldExpr fe |
3932- exists ( resolveStructFieldExpr ( fe , true ) )
3933- or
3934- exists ( resolveTupleFieldExpr ( fe , true ) )
3935- ) .getContainer ( )
3939+ exists ( DerefChain derefChain |
3940+ n =
3941+ any ( FieldExpr fe |
3942+ exists ( resolveStructFieldExpr ( fe , derefChain ) )
3943+ or
3944+ exists ( resolveTupleFieldExpr ( fe , derefChain ) )
3945+ ) .getContainer ( ) and
3946+ not derefChain .isEmpty ( )
3947+ )
39363948 }
39373949
39383950 /** Holds if `n` is implicitly borrowed. */
@@ -3968,9 +3980,9 @@ private module Cached {
39683980 * Gets the struct field that the field expression `fe` resolves to, if any.
39693981 */
39703982 cached
3971- StructField resolveStructFieldExpr ( FieldExpr fe , boolean isDereferenced ) {
3983+ StructField resolveStructFieldExpr ( FieldExpr fe , DerefChain derefChain ) {
39723984 exists ( string name , Type ty |
3973- ty = getFieldExprLookupType ( fe , pragma [ only_bind_into ] ( name ) , isDereferenced )
3985+ ty = getFieldExprLookupType ( fe , pragma [ only_bind_into ] ( name ) , derefChain )
39743986 |
39753987 result = ty .( StructType ) .getStruct ( ) .getStructField ( pragma [ only_bind_into ] ( name ) ) or
39763988 result = ty .( UnionType ) .getUnion ( ) .getStructField ( pragma [ only_bind_into ] ( name ) )
@@ -3981,10 +3993,10 @@ private module Cached {
39813993 * Gets the tuple field that the field expression `fe` resolves to, if any.
39823994 */
39833995 cached
3984- TupleField resolveTupleFieldExpr ( FieldExpr fe , boolean isDereferenced ) {
3996+ TupleField resolveTupleFieldExpr ( FieldExpr fe , DerefChain derefChain ) {
39853997 exists ( int i |
39863998 result =
3987- getTupleFieldExprLookupType ( fe , pragma [ only_bind_into ] ( i ) , isDereferenced )
3999+ getTupleFieldExprLookupType ( fe , pragma [ only_bind_into ] ( i ) , derefChain )
39884000 .( StructType )
39894001 .getStruct ( )
39904002 .getTupleField ( pragma [ only_bind_into ] ( i ) )
0 commit comments