Skip to content

[TypeChecker] Don't try to validate generic requirements when unbound… #25181

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
Jun 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions lib/Sema/TypeCheckType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,10 @@ Type TypeChecker::applyUnboundGenericArguments(
// generic arguments.
auto resultType = decl->getDeclaredInterfaceType();

bool hasTypeVariable = false;
// If types involved in requirements check have either type variables
// or unbound generics, let's skip the check here, and let the solver
// do it when missing types are deduced.
bool skipRequirementsCheck = false;

// Get the substitutions for outer generic parameters from the parent
// type.
Expand All @@ -822,7 +825,7 @@ Type TypeChecker::applyUnboundGenericArguments(
}

subs = parentType->getContextSubstitutions(decl->getDeclContext());
hasTypeVariable |= parentType->hasTypeVariable();
skipRequirementsCheck |= parentType->hasTypeVariable();
}

SourceLoc noteLoc = decl->getLoc();
Expand All @@ -839,13 +842,14 @@ Type TypeChecker::applyUnboundGenericArguments(
subs[origTy->getCanonicalType()->castTo<GenericTypeParamType>()] =
substTy;

hasTypeVariable |= substTy->hasTypeVariable();
skipRequirementsCheck |=
substTy->hasTypeVariable() || substTy->hasUnboundGenericType();
}

// Check the generic arguments against the requirements of the declaration's
// generic signature.
auto dc = resolution.getDeclContext();
if (!hasTypeVariable &&
if (!skipRequirementsCheck &&
resolution.getStage() > TypeResolutionStage::Structural) {
auto result =
checkGenericArguments(dc, loc, noteLoc, unboundType,
Expand Down
1 change: 0 additions & 1 deletion test/Constraints/generics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,6 @@ class GenericClass<A> {}
func genericFunc<T>(t: T) {
_ = [T: GenericClass] // expected-error {{generic parameter 'A' could not be inferred}}
// expected-note@-1 {{explicitly specify the generic arguments to fix this issue}}
// expected-error@-2 {{type 'T' does not conform to protocol 'Hashable'}}
}

struct SR_3525<T> {}
Expand Down
24 changes: 24 additions & 0 deletions test/Constraints/protocols.swift
Original file line number Diff line number Diff line change
Expand Up @@ -377,3 +377,27 @@ func testClonableExistential(_ v: Clonable, _ vv: Clonable.Type) {
let _ = v.veryBadClonerFn() // expected-error {{member 'veryBadClonerFn' cannot be used on value of protocol type 'Clonable'; use a generic constraint instead}}

}


// rdar://problem/50099849

protocol Trivial {
associatedtype T
}

func rdar_50099849() {
struct A : Trivial {
typealias T = A
}

struct B<C : Trivial> : Trivial { // expected-note {{'C' declared as parameter to type 'B'}}
typealias T = C.T
}

struct C<W: Trivial, Z: Trivial> : Trivial where W.T == Z.T {
typealias T = W.T
}

let _ = C<A, B>() // expected-error {{generic parameter 'C' could not be inferred}}
// expected-note@-1 {{explicitly specify the generic arguments to fix this issue}} {{17-17=<<#C: Trivial#>>}}
}