|
|
@@ -173,6 +173,7 @@ static auto IsTypeOfType(Nonnull<const Value*> value) -> bool {
|
|
|
case Value::Kind::AlternativeConstructorValue:
|
|
|
case Value::Kind::ContinuationValue:
|
|
|
case Value::Kind::StringValue:
|
|
|
+ case Value::Kind::UninitializedValue:
|
|
|
case Value::Kind::ImplWitness:
|
|
|
case Value::Kind::SymbolicWitness:
|
|
|
case Value::Kind::ParameterizedEntityName:
|
|
|
@@ -230,6 +231,7 @@ static auto IsType(Nonnull<const Value*> value, bool concrete = false) -> bool {
|
|
|
case Value::Kind::AlternativeConstructorValue:
|
|
|
case Value::Kind::ContinuationValue:
|
|
|
case Value::Kind::StringValue:
|
|
|
+ case Value::Kind::UninitializedValue:
|
|
|
case Value::Kind::ImplWitness:
|
|
|
case Value::Kind::SymbolicWitness:
|
|
|
case Value::Kind::ParameterizedEntityName:
|
|
|
@@ -852,7 +854,8 @@ auto TypeChecker::ArgumentDeduction(
|
|
|
case Value::Kind::AddrValue:
|
|
|
case Value::Kind::AlternativeConstructorValue:
|
|
|
case Value::Kind::ContinuationValue:
|
|
|
- case Value::Kind::StringValue: {
|
|
|
+ case Value::Kind::StringValue:
|
|
|
+ case Value::Kind::UninitializedValue: {
|
|
|
// Argument deduction within the parameters of a parameterized class type
|
|
|
// or interface type can compare values, rather than types.
|
|
|
// TODO: Deduce within the values where possible.
|
|
|
@@ -1155,6 +1158,7 @@ auto TypeChecker::Substitute(
|
|
|
case Value::Kind::AlternativeConstructorValue:
|
|
|
case Value::Kind::ContinuationValue:
|
|
|
case Value::Kind::StringValue:
|
|
|
+ case Value::Kind::UninitializedValue:
|
|
|
// This can happen when substituting into the arguments of a class or
|
|
|
// interface.
|
|
|
// TODO: Implement substitution for these cases.
|
|
|
@@ -2719,24 +2723,29 @@ auto TypeChecker::TypeCheckStmt(Nonnull<Statement*> s,
|
|
|
}
|
|
|
case StatementKind::VariableDefinition: {
|
|
|
auto& var = cast<VariableDefinition>(*s);
|
|
|
- CARBON_RETURN_IF_ERROR(TypeCheckExp(&var.init(), impl_scope));
|
|
|
- const Value& rhs_ty = var.init().static_type();
|
|
|
- // TODO: If the pattern contains a binding that implies a new impl is
|
|
|
- // available, should that remain in scope for as long as its binding?
|
|
|
- // ```
|
|
|
- // var a: (T:! Widget) = ...;
|
|
|
- // // Is the `impl T as Widget` in scope here?
|
|
|
- // a.(Widget.F)();
|
|
|
- // ```
|
|
|
ImplScope var_scope;
|
|
|
var_scope.AddParent(&impl_scope);
|
|
|
- CARBON_RETURN_IF_ERROR(TypeCheckPattern(&var.pattern(), &rhs_ty,
|
|
|
- var_scope, var.value_category()));
|
|
|
- CARBON_ASSIGN_OR_RETURN(
|
|
|
- Nonnull<Expression*> converted_init,
|
|
|
- ImplicitlyConvert("initializer of variable", impl_scope, &var.init(),
|
|
|
- &var.pattern().static_type()));
|
|
|
- var.set_init(converted_init);
|
|
|
+ if (var.has_init()) {
|
|
|
+ CARBON_RETURN_IF_ERROR(TypeCheckExp(&var.init(), impl_scope));
|
|
|
+ const Value& rhs_ty = var.init().static_type();
|
|
|
+ // TODO: If the pattern contains a binding that implies a new impl is
|
|
|
+ // available, should that remain in scope for as long as its binding?
|
|
|
+ // ```
|
|
|
+ // var a: (T:! Widget) = ...;
|
|
|
+ // // Is the `impl T as Widget` in scope here?
|
|
|
+ // a.(Widget.F)();
|
|
|
+ // ```
|
|
|
+ CARBON_RETURN_IF_ERROR(TypeCheckPattern(
|
|
|
+ &var.pattern(), &rhs_ty, var_scope, var.value_category()));
|
|
|
+ CARBON_ASSIGN_OR_RETURN(
|
|
|
+ Nonnull<Expression*> converted_init,
|
|
|
+ ImplicitlyConvert("initializer of variable", impl_scope,
|
|
|
+ &var.init(), &var.pattern().static_type()));
|
|
|
+ var.set_init(converted_init);
|
|
|
+ } else {
|
|
|
+ CARBON_RETURN_IF_ERROR(TypeCheckPattern(
|
|
|
+ &var.pattern(), std::nullopt, var_scope, var.value_category()));
|
|
|
+ }
|
|
|
return Success();
|
|
|
}
|
|
|
case StatementKind::Assign: {
|
|
|
@@ -3548,6 +3557,7 @@ static bool IsValidTypeForAliasTarget(Nonnull<const Value*> type) {
|
|
|
case Value::Kind::AlternativeConstructorValue:
|
|
|
case Value::Kind::ContinuationValue:
|
|
|
case Value::Kind::StringValue:
|
|
|
+ case Value::Kind::UninitializedValue:
|
|
|
CARBON_FATAL() << "type of alias target is not a type";
|
|
|
|
|
|
case Value::Kind::AutoType:
|