Skip to content

Commit 22d01f3

Browse files
committed
[Sema] Sink ValueMatchVisitor into applyUnboundGenericArguments
Make sure it's called for sugar code paths too. Also let's just always run it since it should be a pretty cheap check.
1 parent 8d3913d commit 22d01f3

File tree

1 file changed

+38
-36
lines changed

1 file changed

+38
-36
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -746,9 +746,30 @@ namespace {
746746
/// to see if it's a valid parameter for integer arguments or other value
747747
/// generic parameters.
748748
class ValueMatchVisitor : public TypeMatcher<ValueMatchVisitor> {
749-
public:
750749
ValueMatchVisitor() {}
751750

751+
public:
752+
static bool check(ASTContext &ctx, Type paramTy, Type argTy,
753+
SourceLoc loc) {
754+
auto matcher = ValueMatchVisitor();
755+
if (argTy->hasError() || matcher.match(paramTy, argTy))
756+
return false;
757+
758+
// If the parameter is a value, then we're trying to substitute a
759+
// non-value type like 'Int' or 'T' to our value.
760+
if (paramTy->isValueParameter()) {
761+
ctx.Diags.diagnose(loc, diag::cannot_pass_type_for_value_generic,
762+
argTy, paramTy);
763+
} else {
764+
// Otherwise, we're trying to use a value type (either an integer
765+
// directly or another generic value parameter) for a non-value
766+
// parameter.
767+
ctx.Diags.diagnose(loc, diag::value_type_used_in_type_parameter,
768+
argTy, paramTy);
769+
}
770+
return true;
771+
}
772+
752773
bool mismatch(TypeBase *firstType, TypeBase *secondType,
753774
Type sugaredFirstType) {
754775
return true;
@@ -763,6 +784,12 @@ namespace {
763784
if (secondType->is<PlaceholderType>())
764785
return true;
765786

787+
// For type variable substitutions, the constraint system should
788+
// handle any mismatches (currently this only happens for unbound
789+
// opening though).
790+
if (secondType->isTypeVariableOrMember())
791+
return true;
792+
766793
return false;
767794
}
768795

@@ -1019,11 +1046,6 @@ static Type applyGenericArguments(Type type,
10191046
return ErrorType::get(ctx);
10201047

10211048
args.push_back(substTy);
1022-
1023-
// The type we're binding to may not have value parameters, but one of the
1024-
// arguments may be a value parameter so diagnose this situation as well.
1025-
if (substTy->isValueParameter())
1026-
hasValueParam = true;
10271049
}
10281050

10291051
// Make sure we have the right number of generic arguments.
@@ -1093,31 +1115,6 @@ static Type applyGenericArguments(Type type,
10931115
}
10941116
}
10951117

1096-
if (hasValueParam) {
1097-
ValueMatchVisitor matcher;
1098-
1099-
for (auto i : indices(genericParams->getParams())) {
1100-
auto param = genericParams->getParams()[i]->getDeclaredInterfaceType();
1101-
auto arg = args[i];
1102-
1103-
if (!matcher.match(param, arg)) {
1104-
// If the parameter is a value, then we're trying to substitute a
1105-
// non-value type like 'Int' or 'T' to our value.
1106-
if (param->isValueParameter()) {
1107-
diags.diagnose(loc, diag::cannot_pass_type_for_value_generic, arg, param);
1108-
return ErrorType::get(ctx);
1109-
1110-
// Otherwise, we're trying to use a value type (either an integer
1111-
// directly or another generic value parameter) for a non-value
1112-
// parameter.
1113-
} else {
1114-
diags.diagnose(loc, diag::value_type_used_in_type_parameter, arg, param);
1115-
return ErrorType::get(ctx);
1116-
}
1117-
}
1118-
}
1119-
}
1120-
11211118
// Construct the substituted type.
11221119
const auto result = resolution.applyUnboundGenericArguments(
11231120
decl, unboundType->getParent(), loc, args);
@@ -1183,6 +1180,7 @@ Type TypeResolution::applyUnboundGenericArguments(
11831180
"invalid arguments, use applyGenericArguments to emit diagnostics "
11841181
"and collect arguments to pack generic parameters");
11851182

1183+
auto &ctx = getASTContext();
11861184
TypeSubstitutionMap subs;
11871185

11881186
// Get the interface type for the declaration. We will be substituting
@@ -1241,12 +1239,16 @@ Type TypeResolution::applyUnboundGenericArguments(
12411239
auto innerParams = decl->getGenericParams()->getParams();
12421240
for (unsigned i : indices(innerParams)) {
12431241
auto origTy = innerParams[i]->getDeclaredInterfaceType();
1244-
auto origGP = origTy->getCanonicalType()->castTo<GenericTypeParamType>();
1242+
auto paramTy = origTy->getCanonicalType()->castTo<GenericTypeParamType>();
12451243

12461244
auto substTy = genericArgs[i];
12471245

1248-
// Enter a substitution.
1249-
subs[origGP] = substTy;
1246+
// Ensure the value-ness of the argument matches the parameter.
1247+
if (ValueMatchVisitor::check(ctx, origTy, substTy, loc))
1248+
substTy = ErrorType::get(ctx);
1249+
1250+
// Enter the substitution.
1251+
subs[paramTy] = substTy;
12501252

12511253
skipRequirementsCheck |=
12521254
substTy->hasTypeVariable() || substTy->hasUnboundGenericType();
@@ -1289,13 +1291,13 @@ Type TypeResolution::applyUnboundGenericArguments(
12891291
if (loc.isValid()) {
12901292
TypeChecker::diagnoseRequirementFailure(
12911293
result.getRequirementFailureInfo(), loc, noteLoc,
1292-
UnboundGenericType::get(decl, parentTy, getASTContext()),
1294+
UnboundGenericType::get(decl, parentTy, ctx),
12931295
genericSig.getGenericParams(), substitutions);
12941296
}
12951297

12961298
LLVM_FALLTHROUGH;
12971299
case CheckRequirementsResult::SubstitutionFailure:
1298-
return ErrorType::get(getASTContext());
1300+
return ErrorType::get(ctx);
12991301
case CheckRequirementsResult::Success:
13001302
break;
13011303
}

0 commit comments

Comments
 (0)