Skip to content

Commit

Permalink
Fix use-after-free printing the name of an interface that might have …
Browse files Browse the repository at this point in the history
…been invalidated by lazy import. (#4509)

While here, also change the diagnostic emission to pass the interface
type rather than the interface name. This prepares us to include the
arguments in the diagnostic.
  • Loading branch information
zygoloid authored Nov 12, 2024
1 parent 4f474fa commit de9b7d2
Show file tree
Hide file tree
Showing 4 changed files with 451 additions and 7 deletions.
6 changes: 6 additions & 0 deletions toolchain/check/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1299,6 +1299,12 @@ auto Context::GetGenericInterfaceType(SemIR::InterfaceId interface_id,
*this, interface_id, enclosing_specific_id);
}

auto Context::GetInterfaceType(SemIR::InterfaceId interface_id,
SemIR::SpecificId specific_id) -> SemIR::TypeId {
return GetTypeImpl<SemIR::FacetType>(
*this, FacetTypeFromInterface(interface_id, specific_id).facet_type_id);
}

auto Context::GetPointerType(SemIR::TypeId pointee_type_id) -> SemIR::TypeId {
return GetTypeImpl<SemIR::PointerType>(*this, pointee_type_id);
}
Expand Down
4 changes: 4 additions & 0 deletions toolchain/check/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,10 @@ class Context {
SemIR::SpecificId enclosing_specific_id)
-> SemIR::TypeId;

// Gets the facet type corresponding to a particular interface.
auto GetInterfaceType(SemIR::InterfaceId interface_id,
SemIR::SpecificId specific_id) -> SemIR::TypeId;

// Returns a pointer type whose pointee type is `pointee_type_id`.
auto GetPointerType(SemIR::TypeId pointee_type_id) -> SemIR::TypeId;

Expand Down
15 changes: 8 additions & 7 deletions toolchain/check/member_access.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,28 +193,29 @@ static auto PerformImplLookup(
return SemIR::InstId::BuiltinError;
}

auto& interface = context.interfaces().Get(interface_type->interface_id);
auto witness_id =
LookupInterfaceWitness(context, loc_id, type_const_id,
assoc_type.interface_type_id.AsConstantId());
if (!witness_id.is_valid()) {
auto interface_type_id = context.GetInterfaceType(
interface_type->interface_id, interface_type->specific_id);
if (missing_impl_diagnoser) {
// TODO: Pass in the expression whose type we are printing.
CARBON_DIAGNOSTIC(MissingImplInMemberAccessNote, Note,
"type {1} does not implement interface `{0}`",
SemIR::NameId, SemIR::TypeId);
"type {1} does not implement interface {0}",
SemIR::TypeId, SemIR::TypeId);
missing_impl_diagnoser()
.Note(loc_id, MissingImplInMemberAccessNote, interface.name_id,
.Note(loc_id, MissingImplInMemberAccessNote, interface_type_id,
context.GetTypeIdForTypeConstant(type_const_id))
.Emit();
} else {
// TODO: Pass in the expression whose type we are printing.
CARBON_DIAGNOSTIC(MissingImplInMemberAccess, Error,
"cannot access member of interface `{0}` in type {1} "
"cannot access member of interface {0} in type {1} "
"that does not implement that interface",
SemIR::NameId, SemIR::TypeId);
SemIR::TypeId, SemIR::TypeId);
context.emitter().Emit(loc_id, MissingImplInMemberAccess,
interface.name_id,
interface_type_id,
context.GetTypeIdForTypeConstant(type_const_id));
}
return SemIR::InstId::BuiltinError;
Expand Down
Loading

0 comments on commit de9b7d2

Please sign in to comment.