Skip to content

Refine parameter type 'inout' diagnostics #9147

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 5, 2017

Conversation

CodaFi
Copy link
Contributor

@CodaFi CodaFi commented May 1, 2017

  • Subscripts' parameter lists may not contain inout arguments, but we
    were rejecting them at call sites. Teach the type checker to reject
    them during type resolution instead.

  • We assumed a syntactic check for inout/var parameters would suffice
    given that a parameter unified to an InOutType. However, closures
    passed to function parameters with inout parameters in their parameter
    lists can also cause this case to appear, and we would emit a
    SourceLoc-less diagnostic. Instead, do not attempt this recovery path
    if the user did not actually write ‘var’ or ‘inout’ on the parameter
    type.

Resolves SR-4751, SR-4214, SR-3644, and SR-2354.

@CodaFi CodaFi requested review from jtbandes and jrose-apple May 1, 2017 03:25
@CodaFi
Copy link
Contributor Author

CodaFi commented May 1, 2017

@swift-ci please smoke test

}

// expected-error@+1 {{expression type '(inout MutableSubscripts) -> ()' is ambiguous without more context}}
let closure = { val in val.x = 7 } as (inout MutableSubscripts) -> ()
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this an error?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because the parameter is assumed immutable unless the user actually writes inout or var - supposedly (see FIXME below). This one usually manifests itself with anonymous arguments that need to be converted to named arguments because we don't like inferring inout on closure parameters. @xedin was looking into this at one point IIRC

Copy link
Contributor

Choose a reason for hiding this comment

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

Right, we infer it inconsistently now, which is terrible, and then give a bad diagnostic in the non-inferred cases, which @CodaFi has improved. There are a handful of bugs about this.

@@ -491,6 +491,9 @@ enum TypeResolutionFlags : unsigned {

/// Whether we are checking the underlying type of a typealias.
TR_TypeAliasUnderlyingType = 0x4000000,

/// Whether we are checking the parameter list of a subscript.
TR_SubscriptParameters = 0x8000000,
Copy link
Contributor

Choose a reason for hiding this comment

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

You could use this to resolve property types also, and remove the non-materializable check there.

@slavapestov
Copy link
Contributor

Looks good, I'm a little concerned about the proliferation of TR_ flags we've been experiencing lately but I don't really have a good solution to that.

@CodaFi
Copy link
Contributor Author

CodaFi commented May 1, 2017

I really want to find time to completely rewrite this file... In the meantime I'll look into the non-materializable checks.

@slavapestov
Copy link
Contributor

In the constraint solver, we use the notion of a locator to make context-sensitive decisions, among other things. I wonder if instead of TR_ flags we could pass in something like a 'TypeReprLocator'. Type resolution could then reach into the locator to ask questions about what kind of decl it's resolving, if its a top-level TypeRepr or nested inside of another type constructor, etc. Might be cleaner than passing around various flags and remembering to set them.

// inout is only valid for (non-subscript) function parameters.
if (options.contains(TR_SubscriptParameters) ||
(!(options & TR_FunctionInput) &&
!(options & TR_ImmediateFunctionInput))) {
Copy link
Member

Choose a reason for hiding this comment

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

Weird mix of contains and & here.

@CodaFi CodaFi force-pushed the mutatis-mutandis branch 2 times, most recently from f0fcaf9 to a397ba6 Compare May 3, 2017 21:11
- Subscripts parameter lists may not contain inout arguments, but we
were rejecting this at the call site.  Teach the type checker to reject
them during type resolution instead.

- We assumed a syntactic check for inout/var parameters would suffice
given that a parameter unified to an InoutType.  However, closures
passed to function parameters with inout parameters in their parameter
lists can also cause this case to appear, and we would emit a
SourceLoc-less diagnostic.  Instead, do not attempt this recovery path
if the user did not actually write ‘var’ or ‘inout’ on the parameter
type.
@CodaFi CodaFi force-pushed the mutatis-mutandis branch from a397ba6 to 1020954 Compare May 4, 2017 23:27
@CodaFi
Copy link
Contributor Author

CodaFi commented May 4, 2017

@swift-ci please smoke test

@CodaFi
Copy link
Contributor Author

CodaFi commented May 5, 2017

@slavapestov I tried to plumb things through and it wound up being a little more than I anticipated. I'll save simplifying this code path for another date and get these in now.

⛵️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants