@@ -190,6 +190,33 @@ abstract class ItemNode extends Locatable {
190190 this = result .( CrateItemNode ) .getASourceFile ( )
191191 }
192192
193+ /**
194+ * Gets the canonical path of this item, if any.
195+ *
196+ * See [The Rust Reference][1] for more details.
197+ *
198+ * [1]: https://doc.rust-lang.org/reference/paths.html#canonical-paths
199+ */
200+ cached
201+ abstract string getCanonicalPath ( Crate c ) ;
202+
203+ /** Gets the canonical path prefix that this node provides for `child`. */
204+ pragma [ nomagic]
205+ string getCanonicalPathPrefixFor ( Crate c , ItemNode child ) {
206+ child .getImmediateParent ( ) = this and
207+ result = this .getCanonicalPath ( c )
208+ }
209+
210+ /** Gets the canonical path prefix of this node, if any. */
211+ pragma [ nomagic]
212+ final string getCanonicalPathPrefix ( Crate c ) {
213+ result = any ( ItemNode parent ) .getCanonicalPathPrefixFor ( c , this )
214+ }
215+
216+ /** Gets the canonical path prefix of this node, if any. */
217+ pragma [ nomagic]
218+ final Crate getACanonicalPathCrate ( ) { exists ( this .getCanonicalPathPrefix ( result ) ) }
219+
193220 /** Gets the location of this item. */
194221 Location getLocation ( ) { result = super .getLocation ( ) }
195222}
@@ -226,6 +253,8 @@ private class SourceFileItemNode extends ModuleLikeNode, SourceFile {
226253 override predicate isPublic ( ) { any ( ) }
227254
228255 override TypeParam getTypeParam ( int i ) { none ( ) }
256+
257+ override string getCanonicalPath ( Crate c ) { none ( ) }
229258}
230259
231260class CrateItemNode extends ItemNode instanceof Crate {
@@ -273,12 +302,44 @@ class CrateItemNode extends ItemNode instanceof Crate {
273302 override predicate isPublic ( ) { any ( ) }
274303
275304 override TypeParam getTypeParam ( int i ) { none ( ) }
305+
306+ override string getCanonicalPath ( Crate c ) { c = this and result = Crate .super .getName ( ) }
307+
308+ override string getCanonicalPathPrefixFor ( Crate c , ItemNode child ) {
309+ exists ( ModuleLikeNode m |
310+ result = this .getCanonicalPath ( c ) and
311+ m = this .getModuleNode ( )
312+ |
313+ child = m
314+ or
315+ child .getImmediateParent ( ) = m .( SourceFile ) and
316+ not m = child .( SourceFileItemNode ) .getSuper ( )
317+ )
318+ }
276319}
277320
278321/** An item that can occur in a trait or an `impl` block. */
279322abstract private class AssocItemNode extends ItemNode , AssocItem {
280323 /** Holds if this associated item has an implementation. */
281324 abstract predicate hasImplementation ( ) ;
325+
326+ bindingset [ c]
327+ private string getCanonicalPathPart ( Crate c , int i ) {
328+ i = 0 and
329+ result = this .getCanonicalPathPrefix ( c )
330+ or
331+ i = 1 and
332+ result = "::"
333+ or
334+ i = 2 and
335+ result = this .getName ( )
336+ }
337+
338+ language [ monotonicAggregates]
339+ override string getCanonicalPath ( Crate c ) {
340+ c = this .getACanonicalPathCrate ( ) and
341+ result = strictconcat ( int i | i in [ 0 .. 2 ] | this .getCanonicalPathPart ( c , i ) order by i )
342+ }
282343}
283344
284345private class ConstItemNode extends AssocItemNode instanceof Const {
@@ -301,6 +362,24 @@ private class EnumItemNode extends ItemNode instanceof Enum {
301362 override Visibility getVisibility ( ) { result = Enum .super .getVisibility ( ) }
302363
303364 override TypeParam getTypeParam ( int i ) { result = super .getGenericParamList ( ) .getTypeParam ( i ) }
365+
366+ bindingset [ c]
367+ private string getCanonicalPathPart ( Crate c , int i ) {
368+ i = 0 and
369+ result = this .getCanonicalPathPrefix ( c )
370+ or
371+ i = 1 and
372+ result = "::"
373+ or
374+ i = 2 and
375+ result = this .getName ( )
376+ }
377+
378+ language [ monotonicAggregates]
379+ override string getCanonicalPath ( Crate c ) {
380+ c = this .getACanonicalPathCrate ( ) and
381+ result = strictconcat ( int i | i in [ 0 .. 2 ] | this .getCanonicalPathPart ( c , i ) order by i )
382+ }
304383}
305384
306385private class VariantItemNode extends ItemNode instanceof Variant {
@@ -315,6 +394,24 @@ private class VariantItemNode extends ItemNode instanceof Variant {
315394 }
316395
317396 override Visibility getVisibility ( ) { result = Variant .super .getVisibility ( ) }
397+
398+ bindingset [ c]
399+ private string getCanonicalPathPart ( Crate c , int i ) {
400+ i = 0 and
401+ result = this .getCanonicalPathPrefix ( c )
402+ or
403+ i = 1 and
404+ result = "::"
405+ or
406+ i = 2 and
407+ result = this .getName ( )
408+ }
409+
410+ language [ monotonicAggregates]
411+ override string getCanonicalPath ( Crate c ) {
412+ c = this .getACanonicalPathCrate ( ) and
413+ result = strictconcat ( int i | i in [ 0 .. 2 ] | this .getCanonicalPathPart ( c , i ) order by i )
414+ }
318415}
319416
320417class FunctionItemNode extends AssocItemNode instanceof Function {
@@ -436,6 +533,47 @@ class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
436533 override TypeParam getTypeParam ( int i ) { result = super .getGenericParamList ( ) .getTypeParam ( i ) }
437534
438535 override Visibility getVisibility ( ) { result = Impl .super .getVisibility ( ) }
536+
537+ pragma [ nomagic]
538+ private string getCanonicalPathTraitPart ( Crate c ) {
539+ exists ( Crate c2 | result = this .resolveTraitTy ( ) .getCanonicalPath ( c2 ) |
540+ c = c2
541+ or
542+ c2 = c .getADependency ( )
543+ )
544+ }
545+
546+ bindingset [ c]
547+ private string getCanonicalPathPart ( Crate c , int i ) {
548+ i = 0 and
549+ result = "<"
550+ or
551+ i = 1 and
552+ result = this .resolveSelfTy ( ) .getCanonicalPath ( c )
553+ or
554+ if exists ( this .getTraitPath ( ) )
555+ then
556+ i = 2 and
557+ result = " as "
558+ or
559+ i = 3 and
560+ result = this .getCanonicalPathTraitPart ( c )
561+ or
562+ i = 4 and
563+ result = ">"
564+ else (
565+ i = 2 and
566+ result = ">"
567+ )
568+ }
569+
570+ language [ monotonicAggregates]
571+ override string getCanonicalPath ( Crate c ) {
572+ c = this .getACanonicalPathCrate ( ) and
573+ exists ( int m | if exists ( this .getTraitPath ( ) ) then m = 4 else m = 2 |
574+ result = strictconcat ( int i | i in [ 0 .. m ] | this .getCanonicalPathPart ( c , i ) order by i )
575+ )
576+ }
439577}
440578
441579private class MacroCallItemNode extends AssocItemNode instanceof MacroCall {
@@ -448,6 +586,8 @@ private class MacroCallItemNode extends AssocItemNode instanceof MacroCall {
448586 override TypeParam getTypeParam ( int i ) { none ( ) }
449587
450588 override Visibility getVisibility ( ) { none ( ) }
589+
590+ override string getCanonicalPath ( Crate c ) { none ( ) }
451591}
452592
453593private class ModuleItemNode extends ModuleLikeNode instanceof Module {
@@ -458,6 +598,44 @@ private class ModuleItemNode extends ModuleLikeNode instanceof Module {
458598 override Visibility getVisibility ( ) { result = Module .super .getVisibility ( ) }
459599
460600 override TypeParam getTypeParam ( int i ) { none ( ) }
601+
602+ bindingset [ c]
603+ private string getCanonicalPathPart ( Crate c , int i ) {
604+ i = 0 and
605+ result = this .getCanonicalPathPrefix ( c )
606+ or
607+ i = 1 and
608+ result = "::"
609+ or
610+ i = 2 and
611+ result = this .getName ( )
612+ }
613+
614+ language [ monotonicAggregates]
615+ override string getCanonicalPath ( Crate c ) {
616+ c = this .getACanonicalPathCrate ( ) and
617+ result = strictconcat ( int i | i in [ 0 .. 2 ] | this .getCanonicalPathPart ( c , i ) order by i )
618+ }
619+
620+ pragma [ nomagic]
621+ private ItemNode getACanonicalPathChild ( ) {
622+ exists ( SourceFile f |
623+ fileImport ( this , f ) and
624+ sourceFileEdge ( f , _, result )
625+ )
626+ or
627+ this = result .getImmediateParent ( )
628+ or
629+ exists ( ItemNode mid |
630+ mid = this .getACanonicalPathChild ( ) and
631+ mid .( MacroCallItemNode ) = result .getImmediateParent ( )
632+ )
633+ }
634+
635+ override string getCanonicalPathPrefixFor ( Crate c , ItemNode child ) {
636+ child = this .getACanonicalPathChild ( ) and
637+ result = this .getCanonicalPath ( c )
638+ }
461639}
462640
463641private class StructItemNode extends ItemNode instanceof Struct {
@@ -473,6 +651,24 @@ private class StructItemNode extends ItemNode instanceof Struct {
473651 override Visibility getVisibility ( ) { result = Struct .super .getVisibility ( ) }
474652
475653 override TypeParam getTypeParam ( int i ) { result = super .getGenericParamList ( ) .getTypeParam ( i ) }
654+
655+ bindingset [ c]
656+ private string getCanonicalPathPart ( Crate c , int i ) {
657+ i = 0 and
658+ result = this .getCanonicalPathPrefix ( c )
659+ or
660+ i = 1 and
661+ result = "::"
662+ or
663+ i = 2 and
664+ result = this .getName ( )
665+ }
666+
667+ language [ monotonicAggregates]
668+ override string getCanonicalPath ( Crate c ) {
669+ c = this .getACanonicalPathCrate ( ) and
670+ result = strictconcat ( int i | i in [ 0 .. 2 ] | this .getCanonicalPathPart ( c , i ) order by i )
671+ }
476672}
477673
478674class TraitItemNode extends ImplOrTraitItemNode instanceof Trait {
@@ -492,6 +688,36 @@ class TraitItemNode extends ImplOrTraitItemNode instanceof Trait {
492688 override Visibility getVisibility ( ) { result = Trait .super .getVisibility ( ) }
493689
494690 override TypeParam getTypeParam ( int i ) { result = super .getGenericParamList ( ) .getTypeParam ( i ) }
691+
692+ bindingset [ c]
693+ private string getCanonicalPathPart ( Crate c , int i ) {
694+ i = 0 and
695+ result = "<_ as "
696+ or
697+ i = 1 and
698+ result = this .getCanonicalPathPrefix ( c )
699+ or
700+ i = 2 and
701+ result = "::"
702+ or
703+ i = 3 and
704+ result = this .getName ( )
705+ or
706+ i = 4 and
707+ result = ">"
708+ }
709+
710+ language [ monotonicAggregates]
711+ override string getCanonicalPath ( Crate c ) {
712+ c = this .getACanonicalPathCrate ( ) and
713+ result = strictconcat ( int i | i in [ 1 .. 3 ] | this .getCanonicalPathPart ( c , i ) order by i )
714+ }
715+
716+ language [ monotonicAggregates]
717+ override string getCanonicalPathPrefixFor ( Crate c , ItemNode child ) {
718+ result = strictconcat ( int i | i in [ 0 .. 4 ] | this .getCanonicalPathPart ( c , i ) order by i ) and
719+ child = this .getAnAssocItem ( )
720+ }
495721}
496722
497723class TypeAliasItemNode extends AssocItemNode instanceof TypeAlias {
@@ -514,6 +740,24 @@ private class UnionItemNode extends ItemNode instanceof Union {
514740 override Visibility getVisibility ( ) { result = Union .super .getVisibility ( ) }
515741
516742 override TypeParam getTypeParam ( int i ) { result = super .getGenericParamList ( ) .getTypeParam ( i ) }
743+
744+ bindingset [ c]
745+ private string getCanonicalPathPart ( Crate c , int i ) {
746+ i = 0 and
747+ result = this .getCanonicalPathPrefix ( c )
748+ or
749+ i = 1 and
750+ result = "::"
751+ or
752+ i = 2 and
753+ result = this .getName ( )
754+ }
755+
756+ language [ monotonicAggregates]
757+ override string getCanonicalPath ( Crate c ) {
758+ c = this .getACanonicalPathCrate ( ) and
759+ result = strictconcat ( int i | i in [ 0 .. 2 ] | this .getCanonicalPathPart ( c , i ) order by i )
760+ }
517761}
518762
519763private class UseItemNode extends ItemNode instanceof Use {
@@ -524,6 +768,8 @@ private class UseItemNode extends ItemNode instanceof Use {
524768 override Visibility getVisibility ( ) { result = Use .super .getVisibility ( ) }
525769
526770 override TypeParam getTypeParam ( int i ) { none ( ) }
771+
772+ override string getCanonicalPath ( Crate c ) { none ( ) }
527773}
528774
529775private class BlockExprItemNode extends ItemNode instanceof BlockExpr {
@@ -534,6 +780,8 @@ private class BlockExprItemNode extends ItemNode instanceof BlockExpr {
534780 override Visibility getVisibility ( ) { none ( ) }
535781
536782 override TypeParam getTypeParam ( int i ) { none ( ) }
783+
784+ override string getCanonicalPath ( Crate c ) { none ( ) }
537785}
538786
539787private class TypeParamItemNode extends ItemNode instanceof TypeParam {
@@ -589,6 +837,8 @@ private class TypeParamItemNode extends ItemNode instanceof TypeParam {
589837 override TypeParam getTypeParam ( int i ) { none ( ) }
590838
591839 override Location getLocation ( ) { result = TypeParam .super .getName ( ) .getLocation ( ) }
840+
841+ override string getCanonicalPath ( Crate c ) { none ( ) }
592842}
593843
594844/** Holds if `item` has the name `name` and is a top-level item inside `f`. */
0 commit comments