Rust: Fix type inference for trait objects for traits with associated types

This commit is contained in:
Simon Friis Vindum
2025-07-24 15:50:08 +02:00
parent 1b2f160b55
commit 466bf85a67
5 changed files with 69 additions and 28 deletions

View File

@@ -7,6 +7,15 @@ private import codeql.rust.internal.CachedStages
private import codeql.rust.elements.internal.generated.Raw
private import codeql.rust.elements.internal.generated.Synth
/** Holds if a dyn trait type should have a type parameter associated with `n`. */
predicate dynTraitTypeParameter(Trait trait, AstNode n) {
trait = any(DynTraitTypeRepr dt).getTrait() and
(
n = trait.getGenericParamList().getATypeParam() or
n = trait.(TraitItemNode).getAnAssocItem().(TypeAlias)
)
}
cached
newtype TType =
TTuple(int arity) {
@@ -30,9 +39,7 @@ newtype TType =
TTypeParamTypeParameter(TypeParam t) or
TAssociatedTypeTypeParameter(TypeAlias t) { any(TraitItemNode trait).getAnAssocItem() = t } or
TArrayTypeParameter() or
TDynTraitTypeParameter(TypeParam tp) {
tp = any(DynTraitTypeRepr dt).getTrait().getGenericParamList().getATypeParam()
} or
TDynTraitTypeParameter(AstNode n) { dynTraitTypeParameter(_, n) } or
TRefTypeParameter() or
TSelfTypeParameter(Trait t) or
TSliceTypeParameter()
@@ -406,15 +413,35 @@ class ArrayTypeParameter extends TypeParameter, TArrayTypeParameter {
}
class DynTraitTypeParameter extends TypeParameter, TDynTraitTypeParameter {
private TypeParam typeParam;
private AstNode n;
DynTraitTypeParameter() { this = TDynTraitTypeParameter(typeParam) }
DynTraitTypeParameter() { this = TDynTraitTypeParameter(n) }
TypeParam getTypeParam() { result = typeParam }
Trait getTrait() { dynTraitTypeParameter(result, n) }
override string toString() { result = "dyn(" + typeParam.toString() + ")" }
/** Gets the dyn trait type that this type parameter belongs to. */
DynTraitType getDynTraitType() { result.getTrait() = this.getTrait() }
override Location getLocation() { result = typeParam.getLocation() }
/** Gets the `TypeParam` of this dyn trait type parameter, if any. */
TypeParam getTypeParam() { result = n }
/** Gets the `TypeAlias` of this dyn trait type parameter, if any. */
TypeAlias getTypeAlias() { result = n }
/** Gets the trait type parameter that this dyn trait type parameter corresponds to. */
TypeParameter getTraitTypeParameter() {
result.(TypeParamTypeParameter).getTypeParam() = n
or
result.(AssociatedTypeTypeParameter).getTypeAlias() = n
}
private string toStringInner() {
result = [this.getTypeParam().toString(), this.getTypeAlias().getName().toString()]
}
override string toString() { result = "dyn(" + this.toStringInner() + ")" }
override Location getLocation() { result = n.getLocation() }
}
/** An implicit reference type parameter. */
@@ -503,8 +530,7 @@ final class ImplTypeAbstraction extends TypeAbstraction, Impl {
final class DynTypeAbstraction extends TypeAbstraction, DynTraitTypeRepr {
override TypeParameter getATypeParameter() {
result.(TypeParamTypeParameter).getTypeParam() =
this.getTrait().getGenericParamList().getATypeParam()
result = any(DynTraitTypeParameter tp | tp.getTrait() = this.getTrait()).getTraitTypeParameter()
}
}

View File

@@ -97,7 +97,11 @@ private module Input1 implements InputSig1<Location> {
id = 2
or
kind = 1 and
id = idOfTypeParameterAstNode(tp0.(DynTraitTypeParameter).getTypeParam())
id =
idOfTypeParameterAstNode([
tp0.(DynTraitTypeParameter).getTypeParam().(AstNode),
tp0.(DynTraitTypeParameter).getTypeAlias()
])
or
kind = 2 and
exists(AstNode node | id = idOfTypeParameterAstNode(node) |

View File

@@ -324,10 +324,10 @@ class DynTraitTypeReprMention extends TypeMention instanceof DynTraitTypeRepr {
result = dynType
or
exists(DynTraitTypeParameter tp, TypePath path0, TypePath suffix |
tp = dynType.getTypeParameter(_) and
dynType = tp.getDynTraitType() and
path = TypePath::cons(tp, suffix) and
result = super.getTypeBoundList().getBound(0).getTypeRepr().(TypeMention).resolveTypeAt(path0) and
path0.isCons(TTypeParamTypeParameter(tp.getTypeParam()), suffix)
path0.isCons(tp.getTraitTypeParameter(), suffix)
)
}
}
@@ -363,10 +363,10 @@ class DynTypeBoundListMention extends TypeMention instanceof TypeBoundList {
path.isEmpty() and
result.(DynTraitType).getTrait() = trait
or
exists(TypeParam param |
param = trait.getGenericParamList().getATypeParam() and
path = TypePath::singleton(TDynTraitTypeParameter(param)) and
result = TTypeParamTypeParameter(param)
exists(DynTraitTypeParameter tp |
trait = tp.getTrait() and
path = TypePath::singleton(tp) and
result = tp.getTraitTypeParameter()
)
}
}

View File

@@ -86,15 +86,15 @@ fn assoc_get<A, B, T: AssocTrait<A, AP = B> + ?Sized>(a: &T) -> (A, B) {
fn test_assoc_type(obj: &dyn AssocTrait<i64, AP = bool>) {
let (
_gp, // $ type=_gp:i64
_ap, // $ MISSING: type=_ap:bool
_ap, // $ type=_ap:bool
) = (*obj).get(); // $ target=deref target=AssocTrait::get
let (
_gp, // $ type=_gp:i64
_ap, // $ MISSING: type=_ap:bool
_ap, // $ type=_ap:bool
) = assoc_dyn_get(obj); // $ target=assoc_dyn_get
let (
_gp, // $ type=_gp:i64
_ap, // $ MISSING: type=_ap:bool
_ap, // $ type=_ap:bool
) = assoc_get(obj); // $ target=assoc_get
}

View File

@@ -271,17 +271,17 @@ inferType
| dyn_type.rs:75:21:75:23 | obj | T.dyn(A) | {EXTERNAL LOCATION} | bool |
| dyn_type.rs:78:24:78:24 | a | | file://:0:0:0:0 | & |
| dyn_type.rs:78:24:78:24 | a | &T | dyn_type.rs:15:1:19:1 | dyn AssocTrait |
| dyn_type.rs:78:24:78:24 | a | &T.dyn(AP) | dyn_type.rs:78:21:78:21 | B |
| dyn_type.rs:78:24:78:24 | a | &T.dyn(GP) | dyn_type.rs:78:18:78:18 | A |
| dyn_type.rs:78:65:80:1 | { ... } | | file://:0:0:0:0 | (T_2) |
| dyn_type.rs:78:65:80:1 | { ... } | 0(2) | dyn_type.rs:78:18:78:18 | A |
| dyn_type.rs:78:65:80:1 | { ... } | 1(2) | dyn_type.rs:16:5:16:12 | AP |
| dyn_type.rs:78:65:80:1 | { ... } | 1(2) | dyn_type.rs:78:21:78:21 | B |
| dyn_type.rs:79:5:79:5 | a | | file://:0:0:0:0 | & |
| dyn_type.rs:79:5:79:5 | a | &T | dyn_type.rs:15:1:19:1 | dyn AssocTrait |
| dyn_type.rs:79:5:79:5 | a | &T.dyn(AP) | dyn_type.rs:78:21:78:21 | B |
| dyn_type.rs:79:5:79:5 | a | &T.dyn(GP) | dyn_type.rs:78:18:78:18 | A |
| dyn_type.rs:79:5:79:11 | a.get() | | file://:0:0:0:0 | (T_2) |
| dyn_type.rs:79:5:79:11 | a.get() | 0(2) | dyn_type.rs:78:18:78:18 | A |
| dyn_type.rs:79:5:79:11 | a.get() | 1(2) | dyn_type.rs:16:5:16:12 | AP |
| dyn_type.rs:79:5:79:11 | a.get() | 1(2) | dyn_type.rs:78:21:78:21 | B |
| dyn_type.rs:82:55:82:55 | a | | file://:0:0:0:0 | & |
| dyn_type.rs:82:55:82:55 | a | &T | dyn_type.rs:82:20:82:52 | T |
@@ -295,40 +295,49 @@ inferType
| dyn_type.rs:83:5:83:11 | a.get() | 1(2) | dyn_type.rs:82:17:82:17 | B |
| dyn_type.rs:86:20:86:22 | obj | | file://:0:0:0:0 | & |
| dyn_type.rs:86:20:86:22 | obj | &T | dyn_type.rs:15:1:19:1 | dyn AssocTrait |
| dyn_type.rs:86:20:86:22 | obj | &T.dyn(AP) | {EXTERNAL LOCATION} | bool |
| dyn_type.rs:86:20:86:22 | obj | &T.dyn(GP) | {EXTERNAL LOCATION} | i64 |
| dyn_type.rs:87:9:90:5 | TuplePat | | file://:0:0:0:0 | (T_2) |
| dyn_type.rs:87:9:90:5 | TuplePat | 0(2) | {EXTERNAL LOCATION} | i64 |
| dyn_type.rs:87:9:90:5 | TuplePat | 1(2) | dyn_type.rs:16:5:16:12 | AP |
| dyn_type.rs:87:9:90:5 | TuplePat | 1(2) | {EXTERNAL LOCATION} | bool |
| dyn_type.rs:88:9:88:11 | _gp | | {EXTERNAL LOCATION} | i64 |
| dyn_type.rs:89:9:89:11 | _ap | | dyn_type.rs:16:5:16:12 | AP |
| dyn_type.rs:89:9:89:11 | _ap | | {EXTERNAL LOCATION} | bool |
| dyn_type.rs:90:9:90:14 | (...) | | dyn_type.rs:15:1:19:1 | dyn AssocTrait |
| dyn_type.rs:90:9:90:14 | (...) | dyn(AP) | {EXTERNAL LOCATION} | bool |
| dyn_type.rs:90:9:90:14 | (...) | dyn(GP) | {EXTERNAL LOCATION} | i64 |
| dyn_type.rs:90:9:90:20 | ... .get() | | file://:0:0:0:0 | (T_2) |
| dyn_type.rs:90:9:90:20 | ... .get() | 0(2) | {EXTERNAL LOCATION} | i64 |
| dyn_type.rs:90:9:90:20 | ... .get() | 1(2) | dyn_type.rs:16:5:16:12 | AP |
| dyn_type.rs:90:9:90:20 | ... .get() | 1(2) | {EXTERNAL LOCATION} | bool |
| dyn_type.rs:90:10:90:13 | * ... | | dyn_type.rs:15:1:19:1 | dyn AssocTrait |
| dyn_type.rs:90:10:90:13 | * ... | dyn(AP) | {EXTERNAL LOCATION} | bool |
| dyn_type.rs:90:10:90:13 | * ... | dyn(GP) | {EXTERNAL LOCATION} | i64 |
| dyn_type.rs:90:11:90:13 | obj | | file://:0:0:0:0 | & |
| dyn_type.rs:90:11:90:13 | obj | &T | dyn_type.rs:15:1:19:1 | dyn AssocTrait |
| dyn_type.rs:90:11:90:13 | obj | &T.dyn(AP) | {EXTERNAL LOCATION} | bool |
| dyn_type.rs:90:11:90:13 | obj | &T.dyn(GP) | {EXTERNAL LOCATION} | i64 |
| dyn_type.rs:91:9:94:5 | TuplePat | | file://:0:0:0:0 | (T_2) |
| dyn_type.rs:91:9:94:5 | TuplePat | 0(2) | {EXTERNAL LOCATION} | i64 |
| dyn_type.rs:91:9:94:5 | TuplePat | 1(2) | {EXTERNAL LOCATION} | bool |
| dyn_type.rs:92:9:92:11 | _gp | | {EXTERNAL LOCATION} | i64 |
| dyn_type.rs:93:9:93:11 | _ap | | {EXTERNAL LOCATION} | bool |
| dyn_type.rs:94:9:94:26 | assoc_dyn_get(...) | | file://:0:0:0:0 | (T_2) |
| dyn_type.rs:94:9:94:26 | assoc_dyn_get(...) | 0(2) | {EXTERNAL LOCATION} | i64 |
| dyn_type.rs:94:9:94:26 | assoc_dyn_get(...) | 1(2) | {EXTERNAL LOCATION} | bool |
| dyn_type.rs:94:23:94:25 | obj | | file://:0:0:0:0 | & |
| dyn_type.rs:94:23:94:25 | obj | &T | dyn_type.rs:15:1:19:1 | dyn AssocTrait |
| dyn_type.rs:94:23:94:25 | obj | &T.dyn(AP) | {EXTERNAL LOCATION} | bool |
| dyn_type.rs:94:23:94:25 | obj | &T.dyn(GP) | {EXTERNAL LOCATION} | i64 |
| dyn_type.rs:95:9:98:5 | TuplePat | | file://:0:0:0:0 | (T_2) |
| dyn_type.rs:95:9:98:5 | TuplePat | 0(2) | {EXTERNAL LOCATION} | i64 |
| dyn_type.rs:95:9:98:5 | TuplePat | 1(2) | dyn_type.rs:16:5:16:12 | AP |
| dyn_type.rs:95:9:98:5 | TuplePat | 1(2) | {EXTERNAL LOCATION} | bool |
| dyn_type.rs:96:9:96:11 | _gp | | {EXTERNAL LOCATION} | i64 |
| dyn_type.rs:97:9:97:11 | _ap | | dyn_type.rs:16:5:16:12 | AP |
| dyn_type.rs:97:9:97:11 | _ap | | {EXTERNAL LOCATION} | bool |
| dyn_type.rs:98:9:98:22 | assoc_get(...) | | file://:0:0:0:0 | (T_2) |
| dyn_type.rs:98:9:98:22 | assoc_get(...) | 0(2) | {EXTERNAL LOCATION} | i64 |
| dyn_type.rs:98:9:98:22 | assoc_get(...) | 1(2) | dyn_type.rs:16:5:16:12 | AP |
| dyn_type.rs:98:9:98:22 | assoc_get(...) | 1(2) | {EXTERNAL LOCATION} | bool |
| dyn_type.rs:98:19:98:21 | obj | | file://:0:0:0:0 | & |
| dyn_type.rs:98:19:98:21 | obj | &T | dyn_type.rs:15:1:19:1 | dyn AssocTrait |
| dyn_type.rs:98:19:98:21 | obj | &T.dyn(AP) | {EXTERNAL LOCATION} | bool |
| dyn_type.rs:98:19:98:21 | obj | &T.dyn(GP) | {EXTERNAL LOCATION} | i64 |
| dyn_type.rs:102:26:102:48 | &... | | file://:0:0:0:0 | & |
| dyn_type.rs:102:26:102:48 | &... | &T | dyn_type.rs:5:1:8:1 | dyn MyTrait1 |
@@ -349,10 +358,12 @@ inferType
| dyn_type.rs:107:21:107:45 | &... | &T | dyn_type.rs:15:1:19:1 | dyn AssocTrait |
| dyn_type.rs:107:21:107:45 | &... | &T | dyn_type.rs:33:1:36:1 | GenStruct |
| dyn_type.rs:107:21:107:45 | &... | &T.A | {EXTERNAL LOCATION} | i32 |
| dyn_type.rs:107:21:107:45 | &... | &T.dyn(AP) | {EXTERNAL LOCATION} | bool |
| dyn_type.rs:107:21:107:45 | &... | &T.dyn(GP) | {EXTERNAL LOCATION} | i64 |
| dyn_type.rs:107:22:107:45 | GenStruct {...} | | dyn_type.rs:15:1:19:1 | dyn AssocTrait |
| dyn_type.rs:107:22:107:45 | GenStruct {...} | | dyn_type.rs:33:1:36:1 | GenStruct |
| dyn_type.rs:107:22:107:45 | GenStruct {...} | A | {EXTERNAL LOCATION} | i32 |
| dyn_type.rs:107:22:107:45 | GenStruct {...} | dyn(AP) | {EXTERNAL LOCATION} | bool |
| dyn_type.rs:107:22:107:45 | GenStruct {...} | dyn(GP) | {EXTERNAL LOCATION} | i64 |
| dyn_type.rs:107:41:107:43 | 100 | | {EXTERNAL LOCATION} | i32 |
| loop/main.rs:7:12:7:15 | SelfParam | | loop/main.rs:6:1:8:1 | Self [trait T1] |