Skip to content

Sema: Don't construct naked ErrorTypes in valid code #8642

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 7 commits into from
May 18, 2017
Merged

Sema: Don't construct naked ErrorTypes in valid code #8642

merged 7 commits into from
May 18, 2017

Conversation

beccadax
Copy link
Contributor

@beccadax beccadax commented Apr 8, 2017

This is an update of #8341 to fix the tests it broke. To quote @slavapestov there:

It is useful to set a breakpoint on ErrorType::get(ASTContext)
to see what is going wrong immediately instead of after the
fact when an ErrorType pops up where you don't expect it.

Unfortunately associated type inference, domain shrinking and
the type cleanup RAII utility would all build ErrorTypes even
with valid code.

Refactor things a bit so that this is no longer the case; at
least now the standard library and overlays build with
'assert(false)' inserted into ErrorType::get(ASTContext).

ErrorType::get(Type) is still expected to come up in associated
type inference since it is used as a signal while sorting
through potential type witness candidates.

The initial patch tripped several assertions in places where AST nodes which were previously assigned ErrorType were now null. In some places, I propagated already-constructed ErrorTypes which were the underlying cause of the problem; in others, I assigned ErrorTypes later; in still others, I simply made the code tolerate null types. I've also rebased it on top of a more recent commit in master to make it easier to merge.

This all seems to work on macOS, but I'm not set up to test on Linux.

@@ -1345,8 +1345,10 @@ namespace {
// We may, alternatively, want to use a type variable in that case,
// and possibly infer the type of the variable that way.
CS.getTypeChecker().validateDecl(E->getDecl());
if (E->getDecl()->isInvalid())
if (E->getDecl()->isInvalid()) {
CS.setType(E, E->getDecl()->getInterfaceType());
Copy link
Contributor

Choose a reason for hiding this comment

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

The fixme notes spawning and solving a type variable here would potentially provide better diagnostics instead of no diagnostics.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If I understand the code correctly, this will only happen if the variable's declaration is erroneous, and the idea is that we might be able to guess the type here so we can add it to the diagnosis there. But that seems really difficult to accomplish—by this point, the error at the declaration site should already have been diagnosed. Even if we did decide to do it, I think that's probably better done as a separate patch; I'm just trying to maintain the status quo in this PR.

@@ -1751,19 +1752,19 @@ void ConstraintSystem::shrink(Expr *expr) {
if (auto array = dyn_cast<ArraySliceType>(base)) {
auto elementType = array->getBaseType();
// If base type is invalid let's return error type.
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be asserted as an invariant @slavapestov?

Copy link
Contributor

Choose a reason for hiding this comment

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

Why would it be an invariant? An array slice type can end up with an error type inside of it

@slavapestov
Copy link
Contributor

This looks good, but I want @rudkx to take a look at the Expr::setType() calls and advise which ones need to use the typemap instead.

@slavapestov
Copy link
Contributor

@swift-ci Please smoke test

Copy link
Contributor

@rudkx rudkx left a comment

Choose a reason for hiding this comment

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

Type setting changes LGTM.

@slavapestov
Copy link
Contributor

@breantdax Do you want to rebase and we can merge this in?

@slavapestov slavapestov self-assigned this May 10, 2017
slavapestov and others added 7 commits May 9, 2017 20:14
It is useful to set a breakpoint on ErrorType::get(ASTContext)
to see what is going wrong immediately instead of after the
fact when an ErrorType pops up where you don't expect it.

Unfortunately associated type inference, domain shrinking and
the type cleanup RAII utility would all build ErrorTypes even
with valid code.

Refactor things a bit so that this is no longer the case; at
least now the standard library and overlays build with
'assert(false)' inserted into ErrorType::get(ASTContext).

ErrorType::get(Type) is still expected to come up in associated
type inference since it is used as a signal while sorting
through potential type witness candidates.
Fixes crash in test/ClangImporter/objc_bridging_generics.swift.
As well as anywhere else we `coerceToMaterializable`.

Fixes:

* test/IDE/complete_crashes.swift
* test/IDE/complete_enum_elements.swift
* test/IDE/complete_pattern.swift
* test/IDE/complete_unresolved_members.swift
* test/IDE/complete_value_expr.swift
* test/Parse/implicit_getter_incomplete.swift
* test/Parse/invalid.swift
* test/Parse/switch.swift
* test/SourceKit/Indexing/index_enum_case.swift
This prevents one invalid declaration from causing cascades of subsequent errors.

Fixes:
* test/NameBinding/scope_map_lookup.swift
* test/decl/var/variables.swift
When the initialization expression on a variable declaration fails, give it an ErrorType so Swift does not redundantly diagnose its un-inferrable type.

Fixes:

* test/NameBinding/stdlib.swift
* test/decl/typealias/protocol.swift

Would also have redundantly fixed the same tests as 2e875e7e, but the targeted solution there is cleaner.
A malformed initializer or increment expression would come out of TypeChecker::typeCheckExpression() with no type, which `checkIgnoredExpr()` was not expecting.

Fixes:

* test/Parse/foreach.swift
* test/Parse/recovery.swift
* test/Parse/toplevel_library_invalid.swift
* test/IDE/complete_stmt_controlling_expr.swift
* validation-test/compiler_crashers_fixed/01736-void.swift
* validation-test/compiler_crashers_fixed/00587-swift-pattern-foreachvariable.swift
@beccadax
Copy link
Contributor Author

@slavapestov Rebased. Test failures on my machine are the same as on master.

@slavapestov
Copy link
Contributor

@swift-ci Please smoke test and merge

@swift-ci swift-ci merged commit 1a07230 into swiftlang:master May 18, 2017
@beccadax beccadax deleted the error-type-debugging-fix branch June 17, 2017 03:55
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