Skip to content

Rust: Rework type inference for impl Trait in return position #19954

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Rust: Rework type inference for impl Trait in return position
  • Loading branch information
hvitved committed Jul 11, 2025
commit e4650fb296a5bd424cc665010e02668f99d41be7
66 changes: 15 additions & 51 deletions rust/ql/lib/codeql/rust/internal/Type.qll
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ newtype TType =
TTrait(Trait t) or
TArrayType() or // todo: add size?
TRefType() or // todo: add mut?
TImplTraitType(ImplTraitTypeRepr impl) or
TImplTraitArgumentType(Function function, ImplTraitTypeRepr impl) {
impl = function.getAParam().getTypeRepr()
} or
TSliceType() or
TTypeParamTypeParameter(TypeParam t) or
TAssociatedTypeTypeParameter(TypeAlias t) { any(TraitItemNode trait).getAnAssocItem() = t } or
Expand Down Expand Up @@ -196,53 +198,6 @@ class RefType extends Type, TRefType {
override Location getLocation() { result instanceof EmptyLocation }
}

/**
* An [impl Trait][1] type.
*
* Each syntactic `impl Trait` type gives rise to its own type, even if
* two `impl Trait` types have the same bounds.
*
* [1]: https://doc.rust-lang.org/reference/types/impl-trait.html
*/
class ImplTraitType extends Type, TImplTraitType {
ImplTraitTypeRepr impl;

ImplTraitType() { this = TImplTraitType(impl) }

/** Gets the underlying AST node. */
ImplTraitTypeRepr getImplTraitTypeRepr() { result = impl }

/** Gets the function that this `impl Trait` belongs to. */
abstract Function getFunction();

override StructField getStructField(string name) { none() }

override TupleField getTupleField(int i) { none() }

override TypeParameter getTypeParameter(int i) { none() }

override string toString() { result = impl.toString() }

override Location getLocation() { result = impl.getLocation() }
}

/**
* An [impl Trait in return position][1] type, for example:
*
* ```rust
* fn foo() -> impl Trait
* ```
*
* [1]: https://doc.rust-lang.org/reference/types/impl-trait.html#r-type.impl-trait.return
*/
class ImplTraitReturnType extends ImplTraitType {
private Function function;

ImplTraitReturnType() { impl = function.getRetType().getTypeRepr() }

override Function getFunction() { result = function }
}

/**
* A slice type.
*
Expand Down Expand Up @@ -386,18 +341,27 @@ class SelfTypeParameter extends TypeParameter, TSelfTypeParameter {
*
* [1]: https://doc.rust-lang.org/reference/types/impl-trait.html#r-type.impl-trait.param
*/
class ImplTraitTypeTypeParameter extends ImplTraitType, TypeParameter {
class ImplTraitArgumentType extends TypeParameter, TImplTraitArgumentType {
private Function function;
private ImplTraitTypeRepr impl;

ImplTraitTypeTypeParameter() { impl = function.getAParam().getTypeRepr() }
ImplTraitArgumentType() { this = TImplTraitArgumentType(function, impl) }

override Function getFunction() { result = function }
/** Gets the function that this `impl Trait` belongs to. */
Function getFunction() { result = function }

/** Gets the underlying AST node. */
ImplTraitTypeRepr getImplTraitTypeRepr() { result = impl }

override StructField getStructField(string name) { none() }

override TupleField getTupleField(int i) { none() }

override TypeParameter getTypeParameter(int i) { none() }

override string toString() { result = impl.toString() }

override Location getLocation() { result = impl.getLocation() }
}

/**
Expand Down
19 changes: 8 additions & 11 deletions rust/ql/lib/codeql/rust/internal/TypeInference.qll
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ private module Input1 implements InputSig1<Location> {
node = tp0.(TypeParamTypeParameter).getTypeParam() or
node = tp0.(AssociatedTypeTypeParameter).getTypeAlias() or
node = tp0.(SelfTypeParameter).getTrait() or
node = tp0.(ImplTraitTypeTypeParameter).getImplTraitTypeRepr()
node = tp0.(ImplTraitArgumentType).getImplTraitTypeRepr()
)
|
tp0 order by kind, id
Expand Down Expand Up @@ -132,11 +132,7 @@ private module Input2 implements InputSig2 {
result = tp.(SelfTypeParameter).getTrait()
or
result =
tp.(ImplTraitTypeTypeParameter)
.getImplTraitTypeRepr()
.getTypeBoundList()
.getABound()
.getTypeRepr()
tp.(ImplTraitArgumentType).getImplTraitTypeRepr().getTypeBoundList().getABound().getTypeRepr()
}

/**
Expand Down Expand Up @@ -670,7 +666,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
)
or
ppos.isImplicit() and
this = result.(ImplTraitTypeTypeParameter).getFunction()
this = result.(ImplTraitArgumentType).getFunction()
}

override Type getParameterType(DeclarationPosition dpos, TypePath path) {
Expand Down Expand Up @@ -1476,7 +1472,7 @@ private Function getTypeParameterMethod(TypeParameter tp, string name) {
or
result = getMethodSuccessor(tp.(SelfTypeParameter).getTrait(), name)
or
result = getMethodSuccessor(tp.(ImplTraitTypeTypeParameter).getImplTraitTypeRepr(), name)
result = getMethodSuccessor(tp.(ImplTraitArgumentType).getImplTraitTypeRepr(), name)
}

pragma[nomagic]
Expand Down Expand Up @@ -1655,8 +1651,8 @@ private Function getMethodFromImpl(MethodCall mc) {

bindingset[trait, name]
pragma[inline_late]
private Function getTraitMethod(ImplTraitReturnType trait, string name) {
result = getMethodSuccessor(trait.getImplTraitTypeRepr(), name)
private Function getTraitMethod(TraitType trait, string name) {
result = getMethodSuccessor(trait.getTrait(), name)
}

pragma[nomagic]
Expand All @@ -1669,7 +1665,8 @@ private Function resolveMethodCallTarget(MethodCall mc) {
result = getTypeParameterMethod(mc.getTypeAt(TypePath::nil()), mc.getMethodName())
or
// The type of the receiver is an `impl Trait` type.
result = getTraitMethod(mc.getTypeAt(TypePath::nil()), mc.getMethodName())
result = getTraitMethod(mc.getTypeAt(TypePath::nil()), mc.getMethodName()) and
not exists(mc.getTrait())
}

pragma[nomagic]
Expand Down
8 changes: 7 additions & 1 deletion rust/ql/lib/codeql/rust/internal/TypeMention.qll
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,13 @@ class PathTypeReprMention extends TypeMention, PathTypeRepr {
class ImplTraitTypeReprMention extends TypeMention instanceof ImplTraitTypeRepr {
override Type resolveTypeAt(TypePath typePath) {
typePath.isEmpty() and
result.(ImplTraitType).getImplTraitTypeRepr() = this
result.(ImplTraitArgumentType).getImplTraitTypeRepr() = this
or
exists(Function f |
this = f.getRetType().getTypeRepr() and
result =
super.getTypeBoundList().getABound().getTypeRepr().(TypeMention).resolveTypeAt(typePath)
)
}
}

Expand Down
2 changes: 1 addition & 1 deletion rust/ql/test/library-tests/type-inference/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1921,7 +1921,7 @@ mod impl_trait {
let a = get_a_my_trait(); // $ method=get_a_my_trait
let c = uses_my_trait2(a); // $ type=c:S2 method=uses_my_trait2
let d = uses_my_trait2(S1); // $ type=d:S2 method=uses_my_trait2
let e = get_a_my_trait2(S1).get_a(); // $ method=get_a_my_trait2 method=MyTrait::get_a $ MISSING: type=e:S1
let e = get_a_my_trait2(S1).get_a(); // $ method=get_a_my_trait2 method=MyTrait::get_a $ type=e:S1
}
}

Expand Down
69 changes: 44 additions & 25 deletions rust/ql/test/library-tests/type-inference/type-inference.expected
Original file line number Diff line number Diff line change
Expand Up @@ -3128,10 +3128,8 @@ inferType
| main.rs:1821:25:1823:5 | { ... } | | main.rs:1815:5:1815:14 | S1 |
| main.rs:1822:9:1822:10 | S1 | | main.rs:1815:5:1815:14 | S1 |
| main.rs:1825:41:1827:5 | { ... } | | {EXTERNAL LOCATION} | trait Future |
| main.rs:1825:41:1827:5 | { ... } | | main.rs:1825:16:1825:39 | ImplTraitTypeRepr |
| main.rs:1825:41:1827:5 | { ... } | Output | main.rs:1815:5:1815:14 | S1 |
| main.rs:1826:9:1826:20 | { ... } | | {EXTERNAL LOCATION} | trait Future |
| main.rs:1826:9:1826:20 | { ... } | | main.rs:1825:16:1825:39 | ImplTraitTypeRepr |
| main.rs:1826:9:1826:20 | { ... } | Output | main.rs:1815:5:1815:14 | S1 |
| main.rs:1826:17:1826:18 | S1 | | main.rs:1815:5:1815:14 | S1 |
| main.rs:1835:13:1835:42 | SelfParam | | {EXTERNAL LOCATION} | Pin |
Expand All @@ -3144,16 +3142,20 @@ inferType
| main.rs:1838:13:1838:38 | ...::Ready(...) | | {EXTERNAL LOCATION} | Poll |
| main.rs:1838:13:1838:38 | ...::Ready(...) | T | main.rs:1815:5:1815:14 | S1 |
| main.rs:1838:36:1838:37 | S1 | | main.rs:1815:5:1815:14 | S1 |
| main.rs:1842:41:1844:5 | { ... } | | {EXTERNAL LOCATION} | trait Future |
| main.rs:1842:41:1844:5 | { ... } | | main.rs:1829:5:1829:14 | S2 |
| main.rs:1842:41:1844:5 | { ... } | | main.rs:1842:16:1842:39 | ImplTraitTypeRepr |
| main.rs:1842:41:1844:5 | { ... } | Output | main.rs:1815:5:1815:14 | S1 |
| main.rs:1843:9:1843:10 | S2 | | {EXTERNAL LOCATION} | trait Future |
| main.rs:1843:9:1843:10 | S2 | | main.rs:1829:5:1829:14 | S2 |
| main.rs:1843:9:1843:10 | S2 | | main.rs:1842:16:1842:39 | ImplTraitTypeRepr |
| main.rs:1843:9:1843:10 | S2 | Output | main.rs:1815:5:1815:14 | S1 |
| main.rs:1847:9:1847:12 | f1(...) | | {EXTERNAL LOCATION} | trait Future |
| main.rs:1847:9:1847:12 | f1(...) | Output | main.rs:1815:5:1815:14 | S1 |
| main.rs:1847:9:1847:18 | await ... | | main.rs:1815:5:1815:14 | S1 |
| main.rs:1848:9:1848:12 | f2(...) | | main.rs:1825:16:1825:39 | ImplTraitTypeRepr |
| main.rs:1848:9:1848:12 | f2(...) | | {EXTERNAL LOCATION} | trait Future |
| main.rs:1848:9:1848:12 | f2(...) | Output | main.rs:1815:5:1815:14 | S1 |
| main.rs:1848:9:1848:18 | await ... | | main.rs:1815:5:1815:14 | S1 |
| main.rs:1849:9:1849:12 | f3(...) | | main.rs:1842:16:1842:39 | ImplTraitTypeRepr |
| main.rs:1849:9:1849:12 | f3(...) | | {EXTERNAL LOCATION} | trait Future |
| main.rs:1849:9:1849:12 | f3(...) | Output | main.rs:1815:5:1815:14 | S1 |
| main.rs:1849:9:1849:18 | await ... | | main.rs:1815:5:1815:14 | S1 |
| main.rs:1850:9:1850:10 | S2 | | main.rs:1829:5:1829:14 | S2 |
| main.rs:1850:9:1850:16 | await S2 | | main.rs:1815:5:1815:14 | S1 |
Expand All @@ -3174,9 +3176,11 @@ inferType
| main.rs:1875:15:1875:19 | SelfParam | | file://:0:0:0:0 | & |
| main.rs:1875:15:1875:19 | SelfParam | &T | main.rs:1857:5:1858:14 | S1 |
| main.rs:1878:37:1880:5 | { ... } | | main.rs:1857:5:1858:14 | S1 |
| main.rs:1878:37:1880:5 | { ... } | | main.rs:1878:16:1878:35 | ImplTraitTypeRepr |
| main.rs:1878:37:1880:5 | { ... } | | main.rs:1862:5:1864:5 | trait Trait1 |
| main.rs:1878:37:1880:5 | { ... } | | main.rs:1866:5:1868:5 | trait Trait2 |
| main.rs:1879:9:1879:10 | S1 | | main.rs:1857:5:1858:14 | S1 |
| main.rs:1879:9:1879:10 | S1 | | main.rs:1878:16:1878:35 | ImplTraitTypeRepr |
| main.rs:1879:9:1879:10 | S1 | | main.rs:1862:5:1864:5 | trait Trait1 |
| main.rs:1879:9:1879:10 | S1 | | main.rs:1866:5:1868:5 | trait Trait2 |
| main.rs:1883:18:1883:22 | SelfParam | | file://:0:0:0:0 | & |
| main.rs:1883:18:1883:22 | SelfParam | &T | main.rs:1882:5:1884:5 | Self [trait MyTrait] |
| main.rs:1887:18:1887:22 | SelfParam | | file://:0:0:0:0 | & |
Expand All @@ -3198,15 +3202,19 @@ inferType
| main.rs:1894:25:1894:28 | self | &T.T3 | main.rs:1892:10:1892:17 | T |
| main.rs:1895:13:1895:21 | t.clone() | | main.rs:1892:10:1892:17 | T |
| main.rs:1899:45:1901:5 | { ... } | | main.rs:1857:5:1858:14 | S1 |
| main.rs:1899:45:1901:5 | { ... } | | main.rs:1899:28:1899:43 | ImplTraitTypeRepr |
| main.rs:1899:45:1901:5 | { ... } | | main.rs:1882:5:1884:5 | trait MyTrait |
| main.rs:1899:45:1901:5 | { ... } | A | main.rs:1859:5:1859:14 | S2 |
| main.rs:1900:9:1900:10 | S1 | | main.rs:1857:5:1858:14 | S1 |
| main.rs:1900:9:1900:10 | S1 | | main.rs:1899:28:1899:43 | ImplTraitTypeRepr |
| main.rs:1900:9:1900:10 | S1 | | main.rs:1882:5:1884:5 | trait MyTrait |
| main.rs:1900:9:1900:10 | S1 | A | main.rs:1859:5:1859:14 | S2 |
| main.rs:1903:34:1903:34 | x | | main.rs:1903:24:1903:31 | T |
| main.rs:1903:59:1905:5 | { ... } | | main.rs:1860:5:1860:22 | S3 |
| main.rs:1903:59:1905:5 | { ... } | | main.rs:1903:43:1903:57 | ImplTraitTypeRepr |
| main.rs:1903:59:1905:5 | { ... } | | main.rs:1882:5:1884:5 | trait MyTrait |
| main.rs:1903:59:1905:5 | { ... } | A | main.rs:1903:24:1903:31 | T |
| main.rs:1903:59:1905:5 | { ... } | T3 | main.rs:1903:24:1903:31 | T |
| main.rs:1904:9:1904:13 | S3(...) | | main.rs:1860:5:1860:22 | S3 |
| main.rs:1904:9:1904:13 | S3(...) | | main.rs:1903:43:1903:57 | ImplTraitTypeRepr |
| main.rs:1904:9:1904:13 | S3(...) | | main.rs:1882:5:1884:5 | trait MyTrait |
| main.rs:1904:9:1904:13 | S3(...) | A | main.rs:1903:24:1903:31 | T |
| main.rs:1904:9:1904:13 | S3(...) | T3 | main.rs:1903:24:1903:31 | T |
| main.rs:1904:12:1904:12 | x | | main.rs:1903:24:1903:31 | T |
| main.rs:1907:41:1907:41 | t | | main.rs:1907:26:1907:38 | B |
Expand All @@ -3217,26 +3225,37 @@ inferType
| main.rs:1911:51:1913:5 | { ... } | | main.rs:1911:23:1911:23 | A |
| main.rs:1912:9:1912:9 | t | | main.rs:1911:29:1911:43 | ImplTraitTypeRepr |
| main.rs:1912:9:1912:17 | t.get_a() | | main.rs:1911:23:1911:23 | A |
| main.rs:1916:13:1916:13 | x | | main.rs:1878:16:1878:35 | ImplTraitTypeRepr |
| main.rs:1916:17:1916:20 | f1(...) | | main.rs:1878:16:1878:35 | ImplTraitTypeRepr |
| main.rs:1917:9:1917:9 | x | | main.rs:1878:16:1878:35 | ImplTraitTypeRepr |
| main.rs:1918:9:1918:9 | x | | main.rs:1878:16:1878:35 | ImplTraitTypeRepr |
| main.rs:1919:13:1919:13 | a | | main.rs:1899:28:1899:43 | ImplTraitTypeRepr |
| main.rs:1919:17:1919:32 | get_a_my_trait(...) | | main.rs:1899:28:1899:43 | ImplTraitTypeRepr |
| main.rs:1916:13:1916:13 | x | | main.rs:1862:5:1864:5 | trait Trait1 |
| main.rs:1916:13:1916:13 | x | | main.rs:1866:5:1868:5 | trait Trait2 |
| main.rs:1916:17:1916:20 | f1(...) | | main.rs:1862:5:1864:5 | trait Trait1 |
| main.rs:1916:17:1916:20 | f1(...) | | main.rs:1866:5:1868:5 | trait Trait2 |
| main.rs:1917:9:1917:9 | x | | main.rs:1862:5:1864:5 | trait Trait1 |
| main.rs:1917:9:1917:9 | x | | main.rs:1866:5:1868:5 | trait Trait2 |
| main.rs:1918:9:1918:9 | x | | main.rs:1862:5:1864:5 | trait Trait1 |
| main.rs:1918:9:1918:9 | x | | main.rs:1866:5:1868:5 | trait Trait2 |
| main.rs:1919:13:1919:13 | a | | main.rs:1882:5:1884:5 | trait MyTrait |
| main.rs:1919:13:1919:13 | a | A | main.rs:1859:5:1859:14 | S2 |
| main.rs:1919:17:1919:32 | get_a_my_trait(...) | | main.rs:1882:5:1884:5 | trait MyTrait |
| main.rs:1919:17:1919:32 | get_a_my_trait(...) | A | main.rs:1859:5:1859:14 | S2 |
| main.rs:1920:13:1920:13 | b | | main.rs:1859:5:1859:14 | S2 |
| main.rs:1920:17:1920:33 | uses_my_trait1(...) | | main.rs:1859:5:1859:14 | S2 |
| main.rs:1920:32:1920:32 | a | | main.rs:1899:28:1899:43 | ImplTraitTypeRepr |
| main.rs:1921:13:1921:13 | a | | main.rs:1899:28:1899:43 | ImplTraitTypeRepr |
| main.rs:1921:17:1921:32 | get_a_my_trait(...) | | main.rs:1899:28:1899:43 | ImplTraitTypeRepr |
| main.rs:1920:32:1920:32 | a | | main.rs:1882:5:1884:5 | trait MyTrait |
| main.rs:1920:32:1920:32 | a | A | main.rs:1859:5:1859:14 | S2 |
| main.rs:1921:13:1921:13 | a | | main.rs:1882:5:1884:5 | trait MyTrait |
| main.rs:1921:13:1921:13 | a | A | main.rs:1859:5:1859:14 | S2 |
| main.rs:1921:17:1921:32 | get_a_my_trait(...) | | main.rs:1882:5:1884:5 | trait MyTrait |
| main.rs:1921:17:1921:32 | get_a_my_trait(...) | A | main.rs:1859:5:1859:14 | S2 |
| main.rs:1922:13:1922:13 | c | | main.rs:1859:5:1859:14 | S2 |
| main.rs:1922:17:1922:33 | uses_my_trait2(...) | | main.rs:1859:5:1859:14 | S2 |
| main.rs:1922:32:1922:32 | a | | main.rs:1899:28:1899:43 | ImplTraitTypeRepr |
| main.rs:1922:32:1922:32 | a | | main.rs:1882:5:1884:5 | trait MyTrait |
| main.rs:1922:32:1922:32 | a | A | main.rs:1859:5:1859:14 | S2 |
| main.rs:1923:13:1923:13 | d | | main.rs:1859:5:1859:14 | S2 |
| main.rs:1923:17:1923:34 | uses_my_trait2(...) | | main.rs:1859:5:1859:14 | S2 |
| main.rs:1923:32:1923:33 | S1 | | main.rs:1857:5:1858:14 | S1 |
| main.rs:1924:13:1924:13 | e | | main.rs:1903:24:1903:31 | T |
| main.rs:1924:17:1924:35 | get_a_my_trait2(...) | | main.rs:1903:43:1903:57 | ImplTraitTypeRepr |
| main.rs:1924:17:1924:43 | ... .get_a() | | main.rs:1903:24:1903:31 | T |
| main.rs:1924:13:1924:13 | e | | main.rs:1857:5:1858:14 | S1 |
| main.rs:1924:17:1924:35 | get_a_my_trait2(...) | | main.rs:1882:5:1884:5 | trait MyTrait |
| main.rs:1924:17:1924:35 | get_a_my_trait2(...) | A | main.rs:1857:5:1858:14 | S1 |
| main.rs:1924:17:1924:43 | ... .get_a() | | main.rs:1857:5:1858:14 | S1 |
| main.rs:1924:33:1924:34 | S1 | | main.rs:1857:5:1858:14 | S1 |
| main.rs:1935:16:1935:20 | SelfParam | | file://:0:0:0:0 | & |
| main.rs:1935:16:1935:20 | SelfParam | &T | main.rs:1931:5:1932:13 | S |
Expand Down
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy