Skip to content

Add use site diagnostics to IsUnmanaged#46114

Merged
AlekseyTs merged 7 commits intodotnet:masterfrom
RikkiGibson:isunmanaged-usesitediagnostics
Jul 25, 2020
Merged

Add use site diagnostics to IsUnmanaged#46114
AlekseyTs merged 7 commits intodotnet:masterfrom
RikkiGibson:isunmanaged-usesitediagnostics

Conversation

@RikkiGibson
Copy link
Member

Closes #46003

@RikkiGibson RikkiGibson force-pushed the isunmanaged-usesitediagnostics branch from 176f019 to 9eb4baa Compare July 18, 2020 02:30
@RikkiGibson RikkiGibson force-pushed the isunmanaged-usesitediagnostics branch from 9eb4baa to 4a10da7 Compare July 18, 2020 02:46
@RikkiGibson RikkiGibson marked this pull request as ready for review July 20, 2020 21:07
@RikkiGibson RikkiGibson requested a review from a team as a code owner July 20, 2020 21:07
@jcouv
Copy link
Member

jcouv commented Jul 21, 2020

                hasErrors = CheckManagedAddr(Compilation, operandType, node.Location, diagnostics);

Are we reporting duplicate diagnostics here?
Maybe we could avoid duplicates by doing something like if (!allowManagedAddressOf) { ... } else if (!hasErrors) { diagnostics.Add(node.Location, useSiteDiagnostics); }


Refers to: src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs:2249 in 497fb0e. [](commit_id = 497fb0e, deletion_comment = False)

{
continue;
}
F.Diagnostics.Add(hoistedLocal.Locations.FirstOrNone(), useSiteDiagnostics);
Copy link
Member

Choose a reason for hiding this comment

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

do we have a test for this case?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, although looking this scenario, it seems like the only drawback of the missing references is that we zero out a field that might not need to be zeroed out (i.e. if it is of an unmanaged type). Therefore I am considering dropping the use site diagnostics in this scenario.

Copy link
Member Author

Choose a reason for hiding this comment

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

I decided to keep the use site diagnostics here. It might end up being a breaking change, though.

Copy link
Member

@jcouv jcouv left a comment

Choose a reason for hiding this comment

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

Done with review pass (iteration 2)

@jcouv jcouv self-assigned this Jul 21, 2020
@AlekseyTs
Copy link
Contributor

                hasErrors = CheckManagedAddr(Compilation, operandType, node.Location, diagnostics);

Are we reporting duplicate diagnostics here?

Usually, we aren't concerned much about reporting duplicate use-site diagnostics, if that is the case here.


In reply to: 662108031 [](ancestors = 662108031)


Refers to: src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs:2249 in 497fb0e. [](commit_id = 497fb0e, deletion_comment = False)

@AlekseyTs
Copy link
Contributor

                hasErrors = CheckManagedAddr(Compilation, operandType, node.Location, diagnostics);

I think I see what is the concern. The CheckManagedAddr gets ManagedKind, which effectively going to report the same use-site diagnostics. I think we could avoid this with small refactoring.

  • Here we calculate ManagedKind
  • We add a overload of CheckManagedAddr that takes ManagedKind already calcualated, old overload delegates to new one.
  • We call the new overload here, thus, avoiding calculating the same information twice.

In reply to: 662112597 [](ancestors = 662112597,662108031)


Refers to: src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs:2249 in 497fb0e. [](commit_id = 497fb0e, deletion_comment = False)

@AlekseyTs
Copy link
Contributor

AlekseyTs commented Jul 21, 2020

Done with review pass (iteration 2) #Closed

}", assemblyName: "libS1").ToMetadataReference();


private static MetadataReference UnmanagedUseSiteError_Ref2 = CreateCompilation(@"
Copy link
Contributor

@AlekseyTs AlekseyTs Jul 22, 2020

Choose a reason for hiding this comment

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

static [](start = 16, length = 6)

readonly? #Closed

@AlekseyTs
Copy link
Contributor

AlekseyTs commented Jul 22, 2020

Done with review pass (iteration 3) #Closed

Copy link
Contributor

@AlekseyTs AlekseyTs left a comment

Choose a reason for hiding this comment

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

LGTM (iteration 5)

return baseKind;
}
return managedKind;
Debug.Assert(_managedKindUseSiteDiagnostics.IsDefault);
Copy link
Member Author

Choose a reason for hiding this comment

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

This assertion does not pass reliably, probably because it is essentially an assertion that this thread is the first one to try and populate the ManagedKind on this symbol. This code works by basically letting threads that race to initialize this value overwrite one another, so the assertion is not actually valid.

@AlekseyTs
Copy link
Contributor

@RikkiGibson Is something holding this PR other than the second sign-off? Consider pushing this PR through sooner rather than later. I am planning to do an integration to UsedAssemblyReferences branch soon.

@RikkiGibson
Copy link
Member Author

This is ready to merge once we get a second sign-off. Please review @dotnet/roslyn-compiler

@jaredpar
Copy link
Member

Looking. Got interrupted earlier. Will try and finish soonish.

continue;
}

fieldType.AddUseSiteDiagnostics(ref useSiteDiagnostics);
Copy link
Member

@jaredpar jaredpar Jul 24, 2020

Choose a reason for hiding this comment

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

Does this mean that we will get say obsolete warnings when we use a struct in a place where we checked the unmanaged constraint? #Resolved

Copy link
Contributor

Choose a reason for hiding this comment

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

Does this mean that we will get say obsolete warnings when we use a struct in a place where we checked the unmanaged constraint?

Obsolete warnings are not reported through the use-site diagnostics mechanism.


In reply to: 460266173 [](ancestors = 460266173)

Copy link
Contributor

Choose a reason for hiding this comment

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

Reference unification warnings could be reported


In reply to: 460271139 [](ancestors = 460271139,460266173)

}

bool ITypeSymbol.IsUnmanagedType => !UnderlyingTypeSymbol.IsManagedType;
bool ITypeSymbol.IsUnmanagedType => !UnderlyingTypeSymbol.IsManagedTypeNoUseSiteDiagnostics;
Copy link
Member

@jaredpar jaredpar Jul 24, 2020

Choose a reason for hiding this comment

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

Seems like there is a gap now between what we have interntally and what we expose through the public API. Is there a need to give this info to our API consumers? #Resolved

Copy link
Contributor

Choose a reason for hiding this comment

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

Seems like there is a gap now between what we have interntally and what we expose through the public API. Is there a need to give this info to our API consumers?

We have a bunch of API like that. We do not expose use-site diagnostics or any other diagnostics for any of them. They do not return diagnostics. APIs that return diagnostics will incorporate use-site diagnostics naturally.


In reply to: 460266634 [](ancestors = 460266634)

_flags.SetManagedKind(managedKind);
}

Thread.MemoryBarrier();
Copy link
Member

@jaredpar jaredpar Jul 24, 2020

Choose a reason for hiding this comment

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

What protection do you believe this is giving you here? #Resolved

Copy link
Contributor

Choose a reason for hiding this comment

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

Does this mean that we will get say obsolete warnings when we use a struct in a place where we checked the unmanaged constraint?

The intent is to ensure that below we are dealing with the latest value of the _managedKindUseSiteDiagnostics field, since we are reading and updating two fields separately.


In reply to: 460267538 [](ancestors = 460267538)

Copy link
Member

@jaredpar jaredpar Jul 24, 2020

Choose a reason for hiding this comment

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

Don't think the MemoryBarrier will provide that. The barrier controls read / write reordering from within a thread. It doesn't do anything to guarantee the synchronization of writes from other threads for this thread.

Stated another way. Lets say Thread 1 is the one which enters the if (managedKind ==) above and T2 skips the if and goes straight to this line. In T1 the order of writes is indeed _managedKindUseSiteDiagnostics and then _flags. That does not mean the order in which the writes become visible to T2 is the same. The order in which the writes become visible could be _flags then _managedKindUseSiteDiagnostics. The MemoryBarrier doesn't help here because all it does is control the order of read / writes within T2. It doesn't control whether or not those reads are consistent with the writse from T1.

It's possible I'm remembering part of this wrong but pretty much whenever u have to depend on the ordering of writes between threads there is usually this type of gap.

Copy link
Contributor

Choose a reason for hiding this comment

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

The barrier controls read / write reordering from within a thread.

That is what we are going after. Not any syncronization


In reply to: 460274273 [](ancestors = 460274273)

Copy link
Member

Choose a reason for hiding this comment

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

I think there is a race then. Even if we use the barrier to ensure the thread can't reorder it's reads of _flags and _managedKindUseSiteDiagnostics we can't guarantee the visibility of the writes from the other thread are both visible.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's possible I'm remembering part of this wrong but pretty much whenever u have to depend on the ordering of writes between threads there is usually this type of gap.

I think ideally we need a volatile read here, but, I guess we don't have one, for an immutable array

I think there is a race then. Even if we use the barrier to ensure the thread can't reorder it's reads of _flags and _managedKindUseSiteDiagnostics we can't guarantee the visibility of the writes from the other thread are both visible.

I was suggesting an alternative to check both values in the if above, this would guarantee that we have non-default value here


In reply to: 460275688 [](ancestors = 460275688)

Copy link
Member

Choose a reason for hiding this comment

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

Agree I think either of those would work.

get
{
HashSet<DiagnosticInfo>? useSiteDiagnostics = null;
return GetManagedKind(ref useSiteDiagnostics);
Copy link
Member

Choose a reason for hiding this comment

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

Wish we had done ref var in the same way we did out var

Copy link
Member Author

Choose a reason for hiding this comment

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

It's not too late! For C# Next that is.

Copy link
Member

@jaredpar jaredpar left a comment

Choose a reason for hiding this comment

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

Good once we merge the changes to th

@AlekseyTs AlekseyTs merged commit c2faa09 into dotnet:master Jul 25, 2020
@ghost ghost added this to the Next milestone Jul 25, 2020
@RikkiGibson RikkiGibson deleted the isunmanaged-usesitediagnostics branch July 25, 2020 02:04
333fred added a commit to 333fred/roslyn that referenced this pull request Jul 28, 2020
…-pointers

* upstream/master: (207 commits)
  Update argument state when parameter has not-null type (dotnet#46072)
  Fix TypeWithAnnotations.ToTypeWithState() for (untyped) null literal (dotnet#46344)
  Update README (dotnet#46136)
  Revert "Revert "Support nullable annotations on unconstrained type parameters""
  Revert "Support nullable annotations on unconstrained type parameters (dotnet#45993)"
  Fix type in publish data
  Update VSIXExpInstaller version to one available on ADO
  Update publish data for 16.8
  Update version of RichCodeNav.EnvVarDump
  A fixed initializer must be bound to its natural type (dotnet#46293)
  Update features merged into 16.7p4 (dotnet#46229)
  Async-streams: disposal should continue without jump within a finally (dotnet#46188)
  Recommend default in type constraint, but not record (dotnet#46311)
  Add use site diagnostics to IsUnmanaged (dotnet#46114)
  Add another flaky test.
  Ensure NuGet connections use TLS 1.2
  Update to Microsoft.CodeAnalysis.Testing 1.0.1-beta1.20374.2
  Skip flaky test.
  Fix build break. (dotnet#46303)
  Skip a flaky test Relates to dotnet#46304
  ...
333fred added a commit to 333fred/roslyn that referenced this pull request Jul 28, 2020
…to function-pointer-type-lookup

* upstream/features/function-pointers: (212 commits)
  Correct public API number.
  Update argument state when parameter has not-null type (dotnet#46072)
  Fix TypeWithAnnotations.ToTypeWithState() for (untyped) null literal (dotnet#46344)
  Update README (dotnet#46136)
  Revert "Revert "Support nullable annotations on unconstrained type parameters""
  Revert "Support nullable annotations on unconstrained type parameters (dotnet#45993)"
  Fix type in publish data
  Update VSIXExpInstaller version to one available on ADO
  Update publish data for 16.8
  Update version of RichCodeNav.EnvVarDump
  A fixed initializer must be bound to its natural type (dotnet#46293)
  Update features merged into 16.7p4 (dotnet#46229)
  Async-streams: disposal should continue without jump within a finally (dotnet#46188)
  Recommend default in type constraint, but not record (dotnet#46311)
  Add use site diagnostics to IsUnmanaged (dotnet#46114)
  Add another flaky test.
  Ensure NuGet connections use TLS 1.2
  Update to Microsoft.CodeAnalysis.Testing 1.0.1-beta1.20374.2
  Skip flaky test.
  Fix build break. (dotnet#46303)
  ...
@RikkiGibson RikkiGibson modified the milestones: Next, 16.8.P2 Aug 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

LocalInputEntityStruct is considered unmanaged in source but not from metadata

4 participants