Skip to content

[Type checker] Reduce/isolate reuse of parent generic environments #6086

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

Conversation

DougGregor
Copy link
Member

The type checker is still reusing the archetypes from parent contexts in nested generic contexts, which is is both a mess (semantically) and means that we cannot add any new requirements to those archetypes, a source of numerous bugs. Take a few more concrete steps toward eliminating this reuse of parent archetypes:

  • Set the contextual type of the implicit self parameter late, after we've had a change to create the generic environment for a function
  • Type-check the definitions of typealias declarations with the typealias as the context, so we're in the right generic environment for generic typealias declarations
  • Eliminate PartialGenericTypeToArchetypeResolver, which handled the weird case of pulling archetypes from an outer context rather than the current context. Instead, be explicit about the places where we reuse archetypes by explicitly telling the archetype builder to reuse the parent archetypes.

@DougGregor
Copy link
Member Author

@swift-ci please smoke test and merge

@@ -6820,6 +6833,25 @@ void TypeChecker::checkDeclCircularity(NominalTypeDecl *decl) {
}
}

/// Determine whether the given variable is the implicit 'self' parameter for
/// a function, and return that function if so.
static AbstractFunctionDecl *isImplicitSelfParam(VarDecl *var){
Copy link
Contributor

Choose a reason for hiding this comment

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

We already have VarDecl::isSelfParameter()...

Copy link
Member Author

Choose a reason for hiding this comment

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

Ugh! I was looking for that on ParamDecl. Thank you

@@ -357,6 +357,12 @@ AbstractFunctionDecl *DeclContext::getInnermostMethodContext() {
}
}

bool DeclContext::isTypeContext() const {
return (getContextKind() == DeclContextKind::GenericTypeDecl &&
Copy link
Contributor

@slavapestov slavapestov Dec 6, 2016

Choose a reason for hiding this comment

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

maybe just isa<NominalTypeDecl>(this) then...

@@ -103,7 +103,7 @@ void IterativeTypeChecker::processResolveInheritedClauseEntry(

// Validate the type of this inherited clause entry.
// FIXME: Recursion into existing type checker.
PartialGenericTypeToArchetypeResolver resolver;
GenericTypeToArchetypeResolver resolver(dc->getGenericEnvironmentOfContext());
Copy link
Contributor

Choose a reason for hiding this comment

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

There's a constructor that takes a dc too, it's nicer

if (TC.validateType(typeAliasDecl->getUnderlyingTypeLoc(),
typeAliasDecl->getDeclContext(),
options, nullptr, &unsatisfiedDependency)) {
options, &resolver, &unsatisfiedDependency)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

If the parameter is always non-null, it could be a reference

@@ -151,4 +151,4 @@ struct S4<Q>: P4 {
init(_: Q) { }
}

extension S4 where T : P5 {} // expected-error{{type 'T' in conformance requirement does not refer to a generic parameter or associated type}}
extension S4 where T : P5 {}
Copy link
Contributor

Choose a reason for hiding this comment

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

Heh

checkGenericParamList(&builder, genericParams, parentSig, parentEnv,
nullptr);
Copy link
Contributor

Choose a reason for hiding this comment

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

reference instead of pointer maybe?

We cannot properly determine the context type of any parameter
(including 'self') until after we have determined the generic
environment for the enclosing function.
DeclContext's nomenclature around "type contexts" is confusing,
because it essentially means "nominal type contexts", e.g.,
struct/class/enum/protocol and extensions thereof. This implies the
presence of a 'Self' type, the ability to have members, etc.

However, typealiases are also currently classified as "type
contexts", despite not having a reasonable 'Self' type, which breaks
in various places. Stop classifying typealiases as "type contexts".
Typealiases were getting type-checked in their parent's context, not
their own context. For non-generic typealiases this is fine, because
the generic environment is inherited. Generic typealiases, on the
other hand, have their own generic environment that should be used. Do
so.
This method gets the GenericTypeDecl for a typealias, nominal type, or
extension thereof. While the result is typed as GenericTypeDecl, it's
not always generic, so rename it accordingly.

An audit of the callers illustrated that they should be using
different entrypoints anyway, so fix all of the callers and make this
function private.
…solver.

PartialGenericTypeToArchetypeResolver is (eventually) going
away. Isolate it's use to those places where we still rely on its odd
behavior.
Stop using PartialGenericTypeToArchetypeResolver in extensions. It
means Yet Another ArchetypeBuilder pass (for now).
The GenericTypeOrArchetypeResolver changes are effectively porting
some existing hacks from the now-dead
PartialGenericTypeOrArchetypeResolver, which dodges some regressions
in the compiler-crashers suite and fixes 11 new crashers. There is
undoubtedly a more principled approach to fix these problems, most of
which now step from recursively looking for a generic environment that
isn't there, but doing so requires improvements to our name lookup.
…vironment.

This routine was passing a 'null' generic environment when it should,
in fact, provide the generic environment for its context. Fixes a
code-completion regression introduced by the removal of
PartialGenericTypeToArchetypeResolver.
@DougGregor DougGregor force-pushed the baby-steps-away-from-parent-environment branch from 592d9a6 to 553216a Compare December 6, 2016 06:45
@DougGregor
Copy link
Member Author

@swift-ci please smoke test

1 similar comment
@DougGregor
Copy link
Member Author

@swift-ci please smoke test

@DougGregor
Copy link
Member Author

Linux build failed with something unrelated in LLVM:

buildnode/jenkins/workspace/swift-PR-Linux-smoke-test/branch-master/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp:40:22: error: no member named 'Mang' in 'llvm::AsmPrinter'
Mangler *Mang = AP.Mang;

macOS build failed with an exception

@DougGregor
Copy link
Member Author

@swift-ci please smoke test

@DougGregor
Copy link
Member Author

@swift-ci please smoke test macOS

@DougGregor
Copy link
Member Author

@swift-ci please smoke test Linux

@DougGregor DougGregor merged commit 7907962 into swiftlang:master Dec 6, 2016
@DougGregor DougGregor deleted the baby-steps-away-from-parent-environment branch December 6, 2016 07:17
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.

2 participants