Merge pull request #20403 from paldepind/rust/certain-struct-expr

Rust: Infer certain type information for struct expressions
This commit is contained in:
Simon Friis Vindum
2025-09-12 10:28:07 +02:00
committed by GitHub
4 changed files with 25 additions and 23 deletions

View File

@@ -372,6 +372,14 @@ module CertainTypeInference {
)
}
private Type inferCertainStructExprType(StructExpr se, TypePath path) {
result = se.getPath().(TypeMention).resolveTypeAt(path)
}
private Type inferCertainStructPatType(StructPat sp, TypePath path) {
result = sp.getPath().(TypeMention).resolveTypeAt(path)
}
predicate certainTypeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePath prefix2) {
prefix1.isEmpty() and
prefix2.isEmpty() and
@@ -440,6 +448,10 @@ module CertainTypeInference {
or
result = inferLogicalOperationType(n, path)
or
result = inferCertainStructExprType(n, path)
or
result = inferCertainStructPatType(n, path)
or
result = inferRangeExprType(n) and
path.isEmpty()
or
@@ -743,7 +755,12 @@ private module StructExprMatchingInput implements MatchingInputSig {
class AccessPosition = DeclarationPosition;
class Access extends StructExpr {
Type getTypeArgument(TypeArgumentPosition apos, TypePath path) { none() }
Type getTypeArgument(TypeArgumentPosition apos, TypePath path) {
exists(TypePath suffix |
suffix.isCons(TTypeParamTypeParameter(apos.asTypeParam()), path) and
result = CertainTypeInference::inferCertainType(this, suffix)
)
}
AstNode getNodeAt(AccessPosition apos) {
result = this.getFieldExpr(apos.asFieldPos()).getExpr()
@@ -754,11 +771,6 @@ private module StructExprMatchingInput implements MatchingInputSig {
Type getInferredType(AccessPosition apos, TypePath path) {
result = inferType(this.getNodeAt(apos), path)
or
// The struct/enum type is supplied explicitly as a type qualifier, e.g.
// `Foo<Bar>::Variant { ... }`.
apos.isStructPos() and
result = this.getPath().(TypeMention).resolveTypeAt(path)
}
Declaration getTarget() { result = resolvePath(this.getPath()) }

View File

@@ -34,7 +34,7 @@ mod field_access {
fn generic_field_access() {
// Explicit type argument
let x = GenericThing::<S> { a: S }; // $ type=x:A.S
let x = GenericThing::<S> { a: S }; // $ certainType=x:A.S
println!("{:?}", x.a); // $ fieldof=GenericThing
// Implicit type argument
@@ -2384,7 +2384,7 @@ mod loops {
let range_full = ..; // $ certainType=range_full:RangeFull
for i in &[1i64, 2i64, 3i64][range_full] {} // $ target=index MISSING: type=i:&T.i64
let range1 = // $ type=range1:Range type=range1:Idx.u16
let range1 = // $ certainType=range1:Range type=range1:Idx.u16
std::ops::Range {
start: 0u16,
end: 10u16,
@@ -2480,7 +2480,7 @@ mod explicit_type_args {
let x7 = S4(S2); // $ type=x7:T4.S2
let x8 = S4(0); // $ type=x8:T4.i32
let x9 = S4(S2::default()); // $ type=x9:T4.S2 target=default
let x10 = S5::<S2> // $ type=x10:T5.S2
let x10 = S5::<S2> // $ certainType=x10:T5.S2
{
field: Default::default(), // $ target=default
};
@@ -2594,7 +2594,7 @@ pub mod exec {
impl Connection for MySqlConnection {}
pub fn f() {
let c = MySqlConnection {}; // $ type=c:MySqlConnection
let c = MySqlConnection {}; // $ certainType=c:MySqlConnection
c.execute1(); // $ MISSING: target=execute1
MySqlConnection::execute1(&c); // $ MISSING: target=execute1

View File

@@ -360,16 +360,16 @@ pub fn record_patterns() {
// RecordPat - Record (struct) patterns
match point {
Point { x: 0, y: 0 } => {
let origin = point; // $ type=origin:Point
let origin = point; // $ certainType=origin:Point
println!("Origin point: {:?}", origin);
}
Point { x, y: 0 } => {
let x_axis_x = x; // $ type=x_axis_x:i32
let x_axis_point = point; // $ type=x_axis_point:Point
let x_axis_point = point; // $ certainType=x_axis_point:Point
println!("Point on x-axis: x={}, point={:?}", x_axis_x, x_axis_point);
}
Point { x: 10, .. } => {
let ten_x_point = point; // $ type=ten_x_point:Point
let ten_x_point = point; // $ certainType=ten_x_point:Point
println!("Point with x=10: {:?}", ten_x_point);
}
Point { x, y } => {

View File

@@ -385,8 +385,6 @@ inferType
| dereference.rs:122:23:122:29 | &... | &T | file://:0:0:0:0 | & |
| dereference.rs:122:23:122:29 | &... | &T.&T | dereference.rs:99:5:100:21 | Key |
| dereference.rs:122:24:122:29 | Key {...} | | dereference.rs:99:5:100:21 | Key |
| dereference.rs:122:24:122:29 | Key {...} | | file://:0:0:0:0 | & |
| dereference.rs:122:24:122:29 | Key {...} | &T | dereference.rs:99:5:100:21 | Key |
| dereference.rs:123:16:123:28 | Some(...) | | {EXTERNAL LOCATION} | Option |
| dereference.rs:123:16:123:28 | Some(...) | T | file://:0:0:0:0 | & |
| dereference.rs:123:16:123:28 | Some(...) | T.&T | dereference.rs:99:5:100:21 | Key |
@@ -501,10 +499,8 @@ inferType
| dyn_type.rs:61:5:61:36 | ...::new(...) | T | dyn_type.rs:33:1:36:1 | GenStruct |
| dyn_type.rs:61:5:61:36 | ...::new(...) | T.A | dyn_type.rs:60:18:60:43 | A |
| dyn_type.rs:61:5:61:36 | ...::new(...) | T.dyn(A) | dyn_type.rs:60:18:60:43 | A |
| dyn_type.rs:61:14:61:35 | GenStruct {...} | | dyn_type.rs:10:1:13:1 | dyn GenericGet |
| dyn_type.rs:61:14:61:35 | GenStruct {...} | | dyn_type.rs:33:1:36:1 | GenStruct |
| dyn_type.rs:61:14:61:35 | GenStruct {...} | A | dyn_type.rs:60:18:60:43 | A |
| dyn_type.rs:61:14:61:35 | GenStruct {...} | dyn(A) | dyn_type.rs:60:18:60:43 | A |
| dyn_type.rs:61:33:61:33 | a | | dyn_type.rs:60:18:60:43 | A |
| dyn_type.rs:64:25:64:27 | obj | | file://:0:0:0:0 | & |
| dyn_type.rs:64:25:64:27 | obj | &T | dyn_type.rs:5:1:8:1 | dyn MyTrait1 |
@@ -623,16 +619,13 @@ inferType
| 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 |
| dyn_type.rs:102:26:102:48 | &... | &T | dyn_type.rs:21:1:24:1 | MyStruct |
| dyn_type.rs:102:27:102:48 | MyStruct {...} | | dyn_type.rs:5:1:8:1 | dyn MyTrait1 |
| dyn_type.rs:102:27:102:48 | MyStruct {...} | | dyn_type.rs:21:1:24:1 | MyStruct |
| dyn_type.rs:102:45:102:46 | 42 | | {EXTERNAL LOCATION} | i32 |
| dyn_type.rs:103:28:105:5 | &... | | file://:0:0:0:0 | & |
| dyn_type.rs:103:28:105:5 | &... | &T | dyn_type.rs:10:1:13:1 | dyn GenericGet |
| dyn_type.rs:103:28:105:5 | &... | &T | dyn_type.rs:33:1:36:1 | GenStruct |
| dyn_type.rs:103:28:105:5 | &... | &T.dyn(A) | {EXTERNAL LOCATION} | String |
| dyn_type.rs:103:29:105:5 | GenStruct {...} | | dyn_type.rs:10:1:13:1 | dyn GenericGet |
| dyn_type.rs:103:29:105:5 | GenStruct {...} | | dyn_type.rs:33:1:36:1 | GenStruct |
| dyn_type.rs:103:29:105:5 | GenStruct {...} | dyn(A) | {EXTERNAL LOCATION} | String |
| dyn_type.rs:104:16:104:17 | "" | | file://:0:0:0:0 | & |
| dyn_type.rs:104:16:104:17 | "" | &T | {EXTERNAL LOCATION} | str |
| dyn_type.rs:107:21:107:45 | &... | | file://:0:0:0:0 | & |
@@ -641,11 +634,8 @@ inferType
| 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] |
| loop/main.rs:11:12:11:15 | SelfParam | | loop/main.rs:10:1:14:1 | Self [trait T2] |