Skip to content

Disallow generating IEquatable for Ref Struct#41680

Merged
CyrusNajmabadi merged 13 commits intodotnet:masterfrom
ThadHouse:refstructdisallowIEquatable
May 3, 2020
Merged

Disallow generating IEquatable for Ref Struct#41680
CyrusNajmabadi merged 13 commits intodotnet:masterfrom
ThadHouse:refstructdisallowIEquatable

Conversation

@ThadHouse
Copy link
Contributor

@ThadHouse ThadHouse commented Feb 14, 2020

Unlike Equals(object), which discussion seems to prefer generating broken code, generating IEquatable is always invalid

This PR makes it so IEquatable can not be generated as a fix for ref structs.

Fixes #25708

Unlike Equals(object), which discussion seems to prefer generating broken code, generating IEquatable is always invalid

This PR makes it so IEquatable can not be generated as a fix for ref structs
@ThadHouse ThadHouse requested a review from a team as a code owner February 14, 2020 00:31
if (containingType.IsRefLikeType)
{
statements.Add(factory.ReturnStatement(factory.FalseLiteralExpression()));
statements.ToImmutableAndFree();
Copy link
Member

Choose a reason for hiding this comment

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

either the return value should be consumed or this builder should be freed in a different place.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed. Also fixed the tests to actually pass, was waiting for the solution to load.

@CyrusNajmabadi
Copy link
Contributor

Can you add Fixes #BugNumber on the first line of your post? it will hook up all teh github goodness here.

Copy link
Contributor

@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.

Small nits.

@sharwell sharwell added the Need Design Review The end user experience design needs to be reviewed and approved. label Feb 14, 2020
@sharwell
Copy link
Contributor

sharwell commented Feb 14, 2020

Next design meeting we will review whether this should silently ignore the "Generate IEquatable<T>" box, or if it should disable it from the start.

It certainly seems like we want to avoid generating this code, but also we want to avoid having users confused by the behavior.

@ThadHouse
Copy link
Contributor Author

ThadHouse commented Feb 14, 2020

@sharwell

Based on discussions and the code, where the skip was added it will disable the "Generate IEquatable" box. It's never added as a picker option if the if statement is not entered. The same mechanism is used to disable the box if IEquatable is already implemented, but not the other overloads.

@sharwell
Copy link
Contributor

@ThadHouse That sounds like what we want. Can you include some screenshots?

Copy link
Contributor

@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.

great comments, thanks.

@jinujoseph jinujoseph added Area-IDE Community The pull request was submitted by a contributor who is not a Microsoft employee. labels Feb 24, 2020
@RikkiGibson
Copy link
Member

@ThadHouse @CyrusNajmabadi @sharwell Are we still interested in taking this change?

@sharwell
Copy link
Contributor

sharwell commented Apr 29, 2020

@RikkiGibson I think yes. If someone gets a chance to include a screenshot for this, it would be good. I can try to get one added today.

Also I linked this to the underlying issue #25708

@sharwell sharwell removed the Need Design Review The end user experience design needs to be reviewed and approved. label Apr 29, 2020
Comment on lines 144 to 145
Copy link
Contributor

@sharwell sharwell Apr 30, 2020

Choose a reason for hiding this comment

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

📝 It seems like it would be easier to read this method in the following form:

if (containingType.IsRefLikeType)
{
  // A ref struct can never implement an interface, therefore never add IEquatable to the selection
  // options if the type is a ref struct.
  constructedType = null;
  return false;
}

var equatableTypeOpt = semanticModel.Compilation.GetTypeByMetadataName(typeof(IEquatable<>).FullName);
if (equatableTypeOpt != null)
{
  constructedType = equatableTypeOpt.Construct(containingType);
  return !containingType.AllInterfaces.Contains(constructedType);
}

constructedType = null;
return false;

Copy link
Contributor

Choose a reason for hiding this comment

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

I can see how this merge conflict resolution is the correct one (the PR originally implemented the check in the same form you used), but perhaps it could be simplified in a follow-up commit?

@tannergooding
Copy link
Member

Is there an option for generating "effectively" IEquatable<T>? That is doing everything but adding the interface?

@CyrusNajmabadi CyrusNajmabadi merged commit 36f7191 into dotnet:master May 3, 2020
@ghost ghost added this to the Next milestone May 3, 2020
@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

Area-IDE Community The pull request was submitted by a contributor who is not a Microsoft employee.

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

"Generate Equals" refactorings produce faulty code when using ref structs

7 participants