Skip to content

Make more dependent-type-finder operations public through SymbolFinder.#43622

Merged
CyrusNajmabadi merged 56 commits intodotnet:masterfrom
CyrusNajmabadi:depTypeFinder
Apr 30, 2020
Merged

Make more dependent-type-finder operations public through SymbolFinder.#43622
CyrusNajmabadi merged 56 commits intodotnet:masterfrom
CyrusNajmabadi:depTypeFinder

Conversation

@CyrusNajmabadi
Copy link
Contributor

@CyrusNajmabadi CyrusNajmabadi commented Apr 23, 2020

Followup to #43593. That PR should go in first before this is reviewed.

This is a precursor to moving these operations OOP.

This shoudl be reviewed one commit at a time.

@CyrusNajmabadi CyrusNajmabadi marked this pull request as ready for review April 23, 2020 22:23
@CyrusNajmabadi CyrusNajmabadi requested a review from a team as a code owner April 23, 2020 22:23
@CyrusNajmabadi CyrusNajmabadi requested a review from a team April 23, 2020 22:23
@CyrusNajmabadi CyrusNajmabadi changed the title WIP: Make more dependent-type-finder operations public through SymbolFinder. Make more dependent-type-finder operations public through SymbolFinder. Apr 23, 2020
Solution solution,
IImmutableSet<Project> projects,
bool transitive,
CancellationToken cancellationToken)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renamed these to 'Descend' or 'Add' to better help explain what they're doing. 'Find' was fairly generic.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This helped, thanks!

Solution solution,
IImmutableSet<Project> projects,
bool transitive,
CancellationToken cancellationToken)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renamed this for clarity. 'Find' was a little vague. i think 'DescendInheritanceTree' gives more of an intuition about what is going on here.

Comment on lines +70 to +72
// Only classes/struct implement interface types. Derived interfaces can be found with
// FindDerivedInterfacesAsync.
return allTypes.WhereAsArray(t => t.TypeKind == TypeKind.Class || t.TypeKind == TypeKind.Struct);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enums or delegates don't count? C# interactive says:

> enum E { A, B, C }
> E.A is IComparable
true

Although I could imagine there's some complicated conversion going on and it strictly not an implementation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very interesting case! It will come down to: does the compiler model this in the .Interfaces list of the enum. if so, then i should find these. if not, then i think it's fine not to.

Comment on lines +476 to +477
if (!(reference is PortableExecutableReference peReference))
continue;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? I see AddMatchingMetadataTypesInMetadataReferenceAsync is requiring a PortableExecutableReference for the index, but if there's other types of references do we still need to process those without the index?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. The short answer is: no, there are no other types of refernces we need to process.

The long answer is:

There are effectively two types of references we ever care about "CompilationReference" and "PEReference". The latter is what we traditionally consider as a DLL, whereas the former is for a P2P reference. For the former, we're already processing the other projects higher up directly as we walk that project, so we don't want to walk again through the compilation reference.

@@ -631,61 +521,37 @@ private static async Task FindImmediateMatchingMetadataTypesInMetadataReferenceA
// our criteria.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it seems a bit funky to me that it seems like we lost the information in the index about how it was related and now we're trying to recover that information again. Was there a specific reason for that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great question! first, know that this is an index over metadata, and that index is built independent of that DLL's context in some containing project. THe way the index is built is to actually crack it open directly, read the tables and build information out of that. So the index doesn't store "this ISymbol derives from this other ISymbol", instead it stores "I remember that a type called 'FileStream' derived from a type called 'Stream'".

The goal of hte index was to be fast and lightweight and unencumbered from concerns like retargetting. Instead, it just stores basic data pulled out of the metadata tables in a lightweight fashion.

It's actually just like how the source-index works, just a little faster and more accurate because we can look at real md tokens.

Solution solution,
IImmutableSet<Project> projects,
bool transitive,
CancellationToken cancellationToken)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This helped, thanks!

return ImmutableArray<ISymbol>.Empty;
var types = await DependentTypeFinder.FindAndCacheDerivedClassesAsync(
type, solution, projects, transitive, cancellationToken).ConfigureAwait(false);
return types.WhereAsArray(t => IsAccessible(t));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the accessibility check out here rather than inside the DependentTypeFinder code?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's a good question.... let me noodle on it. This maintains the semantics from before, but i think we could potentially safely move this down.

Copy link
Contributor Author

@CyrusNajmabadi CyrusNajmabadi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c

@CyrusNajmabadi CyrusNajmabadi merged commit 83cd26a into dotnet:master Apr 30, 2020
@ghost ghost added this to the Next milestone Apr 30, 2020
@CyrusNajmabadi CyrusNajmabadi deleted the depTypeFinder branch April 30, 2020 00:30
Comment on lines +14 to +15
/// Special comparer we need for our cache keys. Necessary because <see cref="IImmutableSet{T}"/> uses
/// reference equality and not value-equality semantics.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@CyrusNajmabadi ImmutableHashSet<T> uses EqualityComparer<T>.Default unless some other comparer has been specified.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you point me to where you see that being done for testing if two sets are .equals? Note that this is not about the elements of the set themselves but about checking if the two entire sets are. Equals when used as part of a tuple.

@sharwell
Copy link
Contributor

@CyrusNajmabadi @jinujoseph Can we port this one to 16.7 Preview 1? Otherwise it will be a dogfood blocker for me and I'll be stuck on 16.6 until 16.7 Preview 2 is released.

@CyrusNajmabadi
Copy link
Contributor Author

Sure, I can do that if @jinujoseph is ok with it

@jinujoseph
Copy link
Contributor

@CyrusNajmabadi @sharwell Do you anticipate any risk with this change?

@CyrusNajmabadi
Copy link
Contributor Author

Yes. There's definitely some risk here. This changes a bunch of core algorithms that many other features layer on top of. We have lots of testing, but risk is always there

@jinujoseph
Copy link
Contributor

@CyrusNajmabadi let's keep in master then.
@sharwell sorry you may have to update your extension in the meantime.

@JoeRobich JoeRobich modified the milestones: Next, 16.7.P2 May 18, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants