Skip to content

Commit 2174ec9

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 b392f4f commit 2174ec9

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
@@ -745,9 +745,30 @@ namespace {
745745
/// to see if it's a valid parameter for integer arguments or other value
746746
/// generic parameters.
747747
class ValueMatchVisitor : public TypeMatcher<ValueMatchVisitor> {
748-
public:
749748
ValueMatchVisitor() {}
750749

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

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

@@ -1018,11 +1045,6 @@ static Type applyGenericArguments(Type type,
10181045
return ErrorType::get(ctx);
10191046

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

10281050
// Make sure we have the right number of generic arguments.
@@ -1092,31 +1114,6 @@ static Type applyGenericArguments(Type type,
10921114
}
10931115
}
10941116

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

1182+
auto &ctx = getASTContext();
11851183
TypeSubstitutionMap subs;
11861184

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

12451243
auto substTy = genericArgs[i];
12461244

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

12501252
skipRequirementsCheck |=
12511253
substTy->hasTypeVariable() || substTy->hasUnboundGenericType();
@@ -1288,13 +1290,13 @@ Type TypeResolution::applyUnboundGenericArguments(
12881290
if (loc.isValid()) {
12891291
TypeChecker::diagnoseRequirementFailure(
12901292
result.getRequirementFailureInfo(), loc, noteLoc,
1291-
UnboundGenericType::get(decl, parentTy, getASTContext()),
1293+
UnboundGenericType::get(decl, parentTy, ctx),
12921294
genericSig.getGenericParams(), substitutions);
12931295
}
12941296

12951297
LLVM_FALLTHROUGH;
12961298
case CheckRequirementsResult::SubstitutionFailure:
1297-
return ErrorType::get(getASTContext());
1299+
return ErrorType::get(ctx);
12981300
case CheckRequirementsResult::Success:
12991301
break;
13001302
}

0 commit comments

Comments
 (0)