handle missing addr in self pointer pattern (#3369)

Add validation to `CheckAddrSelfAccess` to additionally check for
situations where `addr` is potentially missing. I also updated the name
of the function since `me` was renamed to `self`.

Closes #3367
This commit is contained in:
Jacob Schneider
2023-11-06 17:51:08 +00:00
committed by GitHub
parent fc1d71d382
commit a4c0febc0f
3 changed files with 48 additions and 17 deletions
+23 -13
View File
@@ -2733,19 +2733,29 @@ static auto IsInstanceMember(Nonnull<const Element*> element) {
}
}
auto TypeChecker::CheckAddrMeAccess(
auto TypeChecker::CheckAddrSelfAccess(
Nonnull<MemberAccessExpression*> access,
Nonnull<const FunctionDeclaration*> func_decl, const Bindings& bindings,
const ImplScope& impl_scope) -> ErrorOr<Success> {
if (func_decl->is_method() &&
func_decl->self_pattern().kind() == PatternKind::AddrPattern) {
if (!func_decl->is_method()) {
return Success();
}
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> self_type,
Substitute(bindings, &func_decl->self_pattern().static_type()));
if (self_type->kind() == Value::Kind::PointerType &&
access->object().static_type().kind() != Value::Kind::PointerType) {
return ProgramError(access->source_loc())
<< "method " << *access
<< " does not match the target function's self pattern (did you "
"forget an `addr`?)";
}
if (func_decl->self_pattern().kind() == PatternKind::AddrPattern) {
access->set_is_addr_me_method();
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> me_type,
Substitute(bindings, &func_decl->self_pattern().static_type()));
CARBON_RETURN_IF_ERROR(
ExpectExactType(access->source_loc(), "method access, receiver type",
me_type, &access->object().static_type(), impl_scope));
CARBON_RETURN_IF_ERROR(ExpectExactType(
access->source_loc(), "method access, receiver type", self_type,
&access->object().static_type(), impl_scope));
if (access->object().expression_category() !=
ExpressionCategory::Reference) {
return ProgramError(access->source_loc())
@@ -2916,7 +2926,7 @@ auto TypeChecker::TypeCheckExpImpl(Nonnull<Expression*> e,
break;
case DeclarationKind::FunctionDeclaration: {
const auto* func_decl = cast<FunctionDeclaration>(member);
CARBON_RETURN_IF_ERROR(CheckAddrMeAccess(
CARBON_RETURN_IF_ERROR(CheckAddrSelfAccess(
&access, func_decl, t_class.bindings(), impl_scope));
if (access.is_type_access()) {
access.set_static_type(field_type);
@@ -3000,7 +3010,7 @@ auto TypeChecker::TypeCheckExpImpl(Nonnull<Expression*> e,
if (const auto* func_decl =
dyn_cast<FunctionDeclaration>(result.member)) {
CARBON_RETURN_IF_ERROR(
CheckAddrMeAccess(&access, func_decl, bindings, impl_scope));
CheckAddrSelfAccess(&access, func_decl, bindings, impl_scope));
if (access.is_type_access()) {
access.set_static_type(inst_member_type);
} else {
@@ -3344,8 +3354,8 @@ auto TypeChecker::TypeCheckExpImpl(Nonnull<Expression*> e,
}
access.set_expression_category(ExpressionCategory::Value);
CARBON_RETURN_IF_ERROR(
CheckAddrMeAccess(&access, cast<FunctionDeclaration>(*decl),
bindings_for_member(), impl_scope));
CheckAddrSelfAccess(&access, cast<FunctionDeclaration>(*decl),
bindings_for_member(), impl_scope));
return Success();
}
break;
+4 -4
View File
@@ -182,10 +182,10 @@ class TypeChecker {
// Checks a member access that might be accessing a function taking `addr
// self: Self*`. If it does, this function marks the member access accordingly
// and ensures the object argument is a reference expression.
auto CheckAddrMeAccess(Nonnull<MemberAccessExpression*> access,
Nonnull<const FunctionDeclaration*> func_decl,
const Bindings& bindings, const ImplScope& impl_scope)
-> ErrorOr<Success>;
auto CheckAddrSelfAccess(Nonnull<MemberAccessExpression*> access,
Nonnull<const FunctionDeclaration*> func_decl,
const Bindings& bindings,
const ImplScope& impl_scope) -> ErrorOr<Success>;
// Traverses the AST rooted at `e`, populating the static_type() of all nodes
// and ensuring they follow Carbon's typing rules.
+21
View File
@@ -0,0 +1,21 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
package ExplorerTest api;
class Foo {
fn Bar[self: Foo*]() {
self->x += 1;
}
var x: i32;
}
fn Main() -> i32 {
var foo: Foo = {.x = 0};
// CHECK:STDERR: COMPILATION ERROR: fail_missing_addr.carbon:[[@LINE+1]]: method foo.Bar does not match the target function's self pattern (did you forget an `addr`?)
foo.Bar();
return 0;
}