Skip to content
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

[breaking change] Report type inference errors in top-level fields #49308

Closed
chloestefantsova opened this issue Jun 22, 2022 · 25 comments · Fixed by sass/dart-sass#1813
Closed
Labels
area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. area-front-end Use area-front-end for front end / CFE / kernel format related issues. breaking-change-approved P2 A bug or feature request we're likely to work on

Comments

@chloestefantsova
Copy link
Contributor

Intended change in behavior

Both the CFE and the Analyzer don't report the error on the inferred type arguments that don't satisfy the type variable bound constraints. Consider the following program.

class TableContext {}

class Column {}

class TableSchema<F extends Column, C extends TableContext> {
  factory TableSchema({required Iterable<F> fields, C? context}) =>
      new TableSchema._();

  TableSchema._();
}

var schema1 = TableSchema(fields: []); // Here the error is reported only with the applied fix.

void method() {
  var schema2 = TableSchema(fields: []); // The error was reported here before and continues to be reported after the fix is applied.
  // The error message is: Inferred type argument 'dynamic' doesn't conform to the bound 'Column' of the type variable 'F' on 'TableSchema'.
}

Here the type arguments inferred for the initializing expressions of either the schema1 or schema2 are dynamic and TableContext, and the first of those inferred type arguments is not a subtype of the corresponding bound Column of the type variable F.

However, both the CFE and the Analyzer report the error for the initializer of schema2, but not for that of the top-level variable schema1. This proposal suggests reporting the error in all contexts, including the initializers of top-level variables as shown in the example above and other kinds of contexts, for example, initializers of static class fields.

Rationale for making the change

Disallowing programs where some types don't respect their corresponding constraints removes potential soundness issues in the type system. Additionally, the proposed change treats all types that don't satisfy the corresponding bounds uniformly.

Expected impact of this change.

Since both tools are failing to report the erroneous code as a compile-time error, some programs containing top-level fields as described in the motivational example may fail to compile after the change is implemented.

Steps for mitigating the change

One way of adjusting the code that will fail to compile after the change is implemented is to supply the type arguments that satisfy their corresponding bounds in place of the inferred ones. In the example above, the line for schema1 can be corrected as follows:

var schema1 = TableSchema<Column, TableContext>(fields: []);

The line for schema2 can be corrected in a similar way.

@chloestefantsova chloestefantsova added the breaking-change-request This tracks requests for feedback on breaking changes label Jun 22, 2022
@mraleph mraleph added area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. area-front-end Use area-front-end for front end / CFE / kernel format related issues. labels Jun 22, 2022
@keertip
Copy link
Contributor

keertip commented Jun 22, 2022

@chloestefantsova is there a timeline for this change? What is the priority?

@chloestefantsova
Copy link
Contributor Author

@chloestefantsova is there a timeline for this change? What is the priority?

I would defer to @leafpetersen and @johnniwinther to determine that.

@keertip
Copy link
Contributor

keertip commented Jun 23, 2022

/cc @leafpetersen

@jcollins-g jcollins-g added the P2 A bug or feature request we're likely to work on label Jul 14, 2022
@jcollins-g
Copy link
Contributor

Tagging @leafpetersen and @johnniwinther again for prioritization/timelines. Marking as P2 for now.

@itsjustkevin
Copy link
Contributor

@Hixie @grouma @vsmenon @leafpetersen @johnniwinther could you take a look at this breaking change request?

@grouma
Copy link
Member

grouma commented Jul 21, 2022

This seems like a beneficial change. This does not directly impact ACX but it may have some impact to internal customers. Presumably any errors caught will be fairly easy and beneficial to fix. When this is ready to land and roll into Google3 you'll want to give a heads up to @iinozemtsev.

@Hixie
Copy link
Contributor

Hixie commented Jul 21, 2022

I don't understand why the inferred type for F isn't Column?

@chloestefantsova
Copy link
Contributor Author

I don't understand why the inferred type for F isn't Column?

As I understand it, it's a limitation of the constraint generation algorithm currently used by the type inference. It doesn't take the bounds of the type variables into account in some cases, which results in dynamic being inferred in this particular example. Basically, the list literal [] remains unconstrained, which gives <dynamic>[], and that dynamic is then used as the value for F.

@Hixie
Copy link
Contributor

Hixie commented Jul 21, 2022

But even if the inference doesn't figure out the type of the list literal, surely there's no point ever inferring a type that isn't valid. Should the types the inference system considers be limited to the types that will fulfill the bounds?

I guess what I'm saying is I would expect the error to be that the List isn't valid for the Iterable<Column> fields parameter to the TableSchema<Column, TableContext> factory constructor.

@chloestefantsova
Copy link
Contributor Author

Yes, I agree, the error message emitted by the compiler is less helpful than it could have been. The Analyzer provides more context in this case, explaining the logic behind the inference:

  error • Couldn't infer type parameter 'F'.

Tried to infer 'dynamic' for 'F' which doesn't work:
  Type parameter 'F' is declared to extend 'Column' producing 'Column'.
The type 'dynamic' was inferred from:
  Parameter 'fields' declared as     'Iterable<F>'
                     but argument is 'List<dynamic>'.

Consider passing explicit type argument(s) to the generic.

@Hixie
Copy link
Contributor

Hixie commented Jul 22, 2022

Ironically while it's one of the most helpful analyzer messages it's also one of my least favourites because it contains newlines and so messes up the layout of many things that process analyzer output. :-)

@johnniwinther
Copy link
Member

Change LGTM. Regarding timeline: The CFE has the fix ready, so we can land this ASAP. I don't know how difficult this is to fix in the analyzer.

@itsjustkevin itsjustkevin added breaking-change-approved and removed breaking-change-request This tracks requests for feedback on breaking changes labels Aug 12, 2022
@leafpetersen
Copy link
Member

@srawlins @bwilkerson @scheglov Is the analyzer side of this something we can get done for the second beta for 2.19 (October 5 is the cutoff date)?

@srawlins
Copy link
Member

I expect we could do this in September without messing up other priorities too much

@johnniwinther
Copy link
Member

@srawlins Can you make this change before October 5? The CFE already has fix for this (a reverted CL that I need to rebase).

@srawlins
Copy link
Member

Sorry this fell off my radar. @scheglov should have the most context of whether we could do this in the next week. WDYT, @scheglov ? I could also take a look.

@scheglov
Copy link
Contributor

I don't have any specific knowledge about inference here, so if you can do it, go for it.

@srawlins
Copy link
Member

srawlins commented Oct 5, 2022

@johnniwinther I guess we missed the Beta 2 cutoff last week, but I can still land this by tomorrow. Should I do that? https://dart-review.googlesource.com/c/sdk/+/262540

@johnniwinther
Copy link
Member

I haven't relanded the CL in CFE either. Let's land this for Beta 3, i.e. when the candidate for Beta 2 has been picked, which I don't know if it has yet.

@srawlins
Copy link
Member

srawlins commented Oct 5, 2022

I think you're right; branch alignment is this week.

@srawlins
Copy link
Member

srawlins commented Oct 5, 2022

Oops I am seeing breakages in google3. At least one anyway in the sass package; I'll start mailing fixes today.

@srawlins
Copy link
Member

srawlins commented Oct 6, 2022

@johnniwinther can you review go/dart-could-not-infer-top-level-lsc as a "Domain Reviewer" and then I can fix all of the internal errors (in every case by adding an explicit type argument).

@srawlins
Copy link
Member

I think I've cleaned up google3 and Sass, the only 3p package that seems to be affected. Running another check in google3 today before landing.

@johnniwinther
Copy link
Member

@srawlins Sounds good. Let me know when the analyzer change has landed, then I'll revive and land the CFE fix.

@srawlins
Copy link
Member

Landed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. area-front-end Use area-front-end for front end / CFE / kernel format related issues. breaking-change-approved P2 A bug or feature request we're likely to work on
Projects
None yet
Development

Successfully merging a pull request may close this issue.