Rust: Handle (Enum::)Variant::<TypeArg> type mentions

This commit is contained in:
Tom Hvitved
2025-07-11 12:40:14 +02:00
parent a96d3d7be8
commit edf6c7fbd6
4 changed files with 32 additions and 25 deletions

View File

@@ -509,12 +509,7 @@ private module StructExprMatchingInput implements MatchingInputSig {
// The struct/enum type is supplied explicitly as a type qualifier, e.g.
// `Foo<Bar>::Variant { ... }`.
apos.isStructPos() and
exists(Path p, TypeMention tm |
p = this.getPath() and
if resolvePath(p) instanceof Variant then tm = p.getQualifier() else tm = p
|
result = tm.resolveTypeAt(path)
)
result = this.getPath().(TypeMention).resolveTypeAt(path)
}
Declaration getTarget() { result = resolvePath(this.getPath()) }
@@ -1242,12 +1237,7 @@ private module StructPatMatchingInput implements MatchingInputSig {
// The struct/enum type is supplied explicitly as a type qualifier, e.g.
// `let Foo<Bar>::Variant { ... } = ...`.
apos.isStructPos() and
exists(Path p, TypeMention tm |
p = this.getPath() and
if resolvePath(p) instanceof Variant then tm = p.getQualifier() else tm = p
|
result = tm.resolveTypeAt(path)
)
result = this.getPath().(TypeMention).resolveTypeAt(path)
}
Declaration getTarget() { result = resolvePath(this.getPath()) }
@@ -1297,14 +1287,9 @@ private module TupleStructPatMatchingInput implements MatchingInputSig {
result = inferType(this.getNodeAt(apos), path)
or
// The struct/enum type is supplied explicitly as a type qualifier, e.g.
// `let Option::<Foo>(x) = ...`.
// `let Option::<Foo>::Some(x) = ...`.
apos.isSelf() and
exists(Path p, TypeMention tm |
p = this.getPath() and
if resolvePath(p) instanceof Variant then tm = p.getQualifier() else tm = p
|
result = tm.resolveTypeAt(path)
)
result = this.getPath().(TypeMention).resolveTypeAt(path)
}
Declaration getTarget() { result = resolvePath(this.getPath()) }

View File

@@ -53,9 +53,13 @@ class SliceTypeReprMention extends TypeMention instanceof SliceTypeRepr {
class PathTypeMention extends TypeMention, Path {
TypeItemNode resolved;
PathTypeMention() { resolved = resolvePath(this) }
PathTypeMention() {
resolved = resolvePath(this)
or
resolved = resolvePath(this).(Variant).getEnum()
}
ItemNode getResolved() { result = resolved }
TypeItemNode getResolved() { result = resolved }
pragma[nomagic]
private TypeAlias getResolvedTraitAlias(string name) {
@@ -99,6 +103,10 @@ class PathTypeMention extends TypeMention, Path {
this = node.getASelfPath() and
result = node.(ImplItemNode).getSelfPath().getSegment().getGenericArgList().getTypeArg(i)
)
or
// `Option::<i32>::Some` is valid in addition to `Option::Some::<i32>`
resolvePath(this) instanceof Variant and
result = this.getQualifier().getSegment().getGenericArgList().getTypeArg(i)
}
private TypeMention getPositionalTypeArgument(int i) {

View File

@@ -2462,18 +2462,18 @@ pub mod pattern_matching {
_ => (),
}
let opt1 = Some(Default::default()); // $ MISSING: type=opt1:T.i32 method=default
let opt1 = Some(Default::default()); // $ type=opt1:T.i32 method=default
#[rustfmt::skip]
let _ = if let Some::<i32>(x) = opt1
{
x; // $ MISSING: type=x:i32
x; // $ type=x:i32
};
let opt2 = Some(Default::default()); // $ MISSING: type=opt2:T.i32 method=default
let opt2 = Some(Default::default()); // $ type=opt2:T.i32 method=default
#[rustfmt::skip]
let _ = if let Option::Some::<i32>(x) = opt2
{
x; // $ MISSING: type=x:i32
x; // $ type=x:i32
};
let opt3 = Some(Default::default()); // $ type=opt3:T.i32 method=default

View File

@@ -4303,13 +4303,27 @@ inferType
| main.rs:2462:13:2462:13 | _ | T1.T2.&T | {EXTERNAL LOCATION} | str |
| main.rs:2462:13:2462:13 | _ | T2 | {EXTERNAL LOCATION} | bool |
| main.rs:2465:13:2465:16 | opt1 | | {EXTERNAL LOCATION} | Option |
| main.rs:2465:13:2465:16 | opt1 | T | {EXTERNAL LOCATION} | i32 |
| main.rs:2465:20:2465:43 | Some(...) | | {EXTERNAL LOCATION} | Option |
| main.rs:2465:20:2465:43 | Some(...) | T | {EXTERNAL LOCATION} | i32 |
| main.rs:2465:25:2465:42 | ...::default(...) | | {EXTERNAL LOCATION} | i32 |
| main.rs:2467:24:2467:37 | Some::<...>(...) | | {EXTERNAL LOCATION} | Option |
| main.rs:2467:24:2467:37 | Some::<...>(...) | T | {EXTERNAL LOCATION} | i32 |
| main.rs:2467:36:2467:36 | x | | {EXTERNAL LOCATION} | i32 |
| main.rs:2467:41:2467:44 | opt1 | | {EXTERNAL LOCATION} | Option |
| main.rs:2467:41:2467:44 | opt1 | T | {EXTERNAL LOCATION} | i32 |
| main.rs:2469:13:2469:13 | x | | {EXTERNAL LOCATION} | i32 |
| main.rs:2472:13:2472:16 | opt2 | | {EXTERNAL LOCATION} | Option |
| main.rs:2472:13:2472:16 | opt2 | T | {EXTERNAL LOCATION} | i32 |
| main.rs:2472:20:2472:43 | Some(...) | | {EXTERNAL LOCATION} | Option |
| main.rs:2472:20:2472:43 | Some(...) | T | {EXTERNAL LOCATION} | i32 |
| main.rs:2472:25:2472:42 | ...::default(...) | | {EXTERNAL LOCATION} | i32 |
| main.rs:2474:24:2474:45 | ...::Some::<...>(...) | | {EXTERNAL LOCATION} | Option |
| main.rs:2474:24:2474:45 | ...::Some::<...>(...) | T | {EXTERNAL LOCATION} | i32 |
| main.rs:2474:44:2474:44 | x | | {EXTERNAL LOCATION} | i32 |
| main.rs:2474:49:2474:52 | opt2 | | {EXTERNAL LOCATION} | Option |
| main.rs:2474:49:2474:52 | opt2 | T | {EXTERNAL LOCATION} | i32 |
| main.rs:2476:13:2476:13 | x | | {EXTERNAL LOCATION} | i32 |
| main.rs:2479:13:2479:16 | opt3 | | {EXTERNAL LOCATION} | Option |
| main.rs:2479:13:2479:16 | opt3 | T | {EXTERNAL LOCATION} | i32 |
| main.rs:2479:20:2479:43 | Some(...) | | {EXTERNAL LOCATION} | Option |