Skip to content

Commit 6f6edf8

Browse files
committed
diagnostic-note-identifying
1 parent a0be89a commit 6f6edf8

File tree

7 files changed

+115
-68
lines changed

7 files changed

+115
-68
lines changed

toolchain/check/diagnostic_emitter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ auto DiagnosticEmitter::ConvertArg(llvm::Any arg) const -> llvm::Any {
115115
sem_ir_->types().GetInstId(*type_id)) +
116116
"`";
117117
}
118+
if (auto* facet_type_id = llvm::any_cast<SemIR::FacetTypeId>(&arg)) {
119+
return "`" + StringifyFacetType(*sem_ir_, *facet_type_id) + "`";
120+
}
118121
if (auto* specific_id = llvm::any_cast<SemIR::SpecificId>(&arg)) {
119122
return "`" + StringifySpecific(*sem_ir_, *specific_id) + "`";
120123
}

toolchain/check/testdata/generic/identify_specific_facet_type.carbon

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,16 @@ library "[[@TEST_NAME]]";
1818

1919
interface K(T:! type) {}
2020
constraint J(N:! i32) {
21-
// CHECK:STDERR: fail_error_in_identifying_require_facet_type.carbon:[[@LINE+3]]:30: error: array bound of -1 is negative [ArrayBoundNegative]
21+
// CHECK:STDERR: fail_error_in_identifying_require_facet_type.carbon:[[@LINE+6]]:30: error: array bound of -1 is negative [ArrayBoundNegative]
2222
// CHECK:STDERR: require impls K(array(i32, N));
2323
// CHECK:STDERR: ^
24+
// CHECK:STDERR: fail_error_in_identifying_require_facet_type.carbon:[[@LINE+3]]:3: note: in `require` used here [ResolvingSpecificHere]
25+
// CHECK:STDERR: require impls K(array(i32, N));
26+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2427
require impls K(array(i32, N));
2528
}
2629

27-
// CHECK:STDERR: fail_error_in_identifying_require_facet_type.carbon:[[@LINE+8]]:12: note: in `require` used here [ResolvingSpecificHere]
30+
// CHECK:STDERR: fail_error_in_identifying_require_facet_type.carbon:[[@LINE+8]]:12: note: identifying facet type `J(-1)` here [IdentifyingFacetTypeHere]
2831
// CHECK:STDERR: impl {} as J(-1) {}
2932
// CHECK:STDERR: ^~~~~
3033
// CHECK:STDERR:
@@ -42,13 +45,16 @@ library "[[@TEST_NAME]]";
4245

4346
interface K(T:! type) {}
4447
constraint J(N:! i32) {
45-
// CHECK:STDERR: fail_error_in_identifying_extend_require_facet_type.carbon:[[@LINE+3]]:37: error: array bound of -1 is negative [ArrayBoundNegative]
48+
// CHECK:STDERR: fail_error_in_identifying_extend_require_facet_type.carbon:[[@LINE+6]]:37: error: array bound of -1 is negative [ArrayBoundNegative]
4649
// CHECK:STDERR: extend require impls K(array(i32, N));
4750
// CHECK:STDERR: ^
51+
// CHECK:STDERR: fail_error_in_identifying_extend_require_facet_type.carbon:[[@LINE+3]]:3: note: in `require` used here [ResolvingSpecificHere]
52+
// CHECK:STDERR: extend require impls K(array(i32, N));
53+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4854
extend require impls K(array(i32, N));
4955
}
5056

51-
// CHECK:STDERR: fail_error_in_identifying_extend_require_facet_type.carbon:[[@LINE+8]]:12: note: in `require` used here [ResolvingSpecificHere]
57+
// CHECK:STDERR: fail_error_in_identifying_extend_require_facet_type.carbon:[[@LINE+8]]:12: note: identifying facet type `J(-1)` here [IdentifyingFacetTypeHere]
5258
// CHECK:STDERR: impl {} as J(-1) {}
5359
// CHECK:STDERR: ^~~~~
5460
// CHECK:STDERR:

toolchain/check/type_completion.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,7 @@ static auto RequireIdentifiedNamedConstraints(
811811
// introduce new generic bindings, the specific for the RequireImpls can be
812812
// constructed from the enclosing one.
813813
static auto GetRequireImplsSpecificFromEnclosingSpecific(
814-
Context& context, SemIR::LocId loc_id, const SemIR::RequireImpls& require,
814+
Context& context, const SemIR::RequireImpls& require,
815815
SemIR::SpecificId enclosing_specific_id) -> SemIR::SpecificId {
816816
auto enclosing_specific_args_id =
817817
context.specifics().GetArgsOrEmpty(enclosing_specific_id);
@@ -836,7 +836,8 @@ static auto GetRequireImplsSpecificFromEnclosingSpecific(
836836
CARBON_CHECK(context.insts().Is<SemIR::SymbolicBinding>(self_inst_id));
837837
arg_ids.push_back(self_inst_id);
838838

839-
return MakeSpecific(context, loc_id, require.generic_id, arg_ids);
839+
return MakeSpecific(context, SemIR::LocId(require.decl_id),
840+
require.generic_id, arg_ids);
840841
}
841842

842843
// Returns the `facet_type` mapped into `specific_id`. If an error results, it
@@ -903,14 +904,23 @@ auto RequireIdentifiedFacetType(Context& context, SemIR::LocId loc_id,
903904
}
904905
llvm::append_range(self_impls, facet_type_info.self_impls_constraints);
905906

907+
Diagnostics::AnnotationScope annotate_diagnostics(
908+
&context.emitter(), [&](auto& builder) {
909+
CARBON_DIAGNOSTIC(IdentifyingFacetTypeHere, Note,
910+
"identifying facet type {0} here",
911+
SemIR::FacetTypeId);
912+
builder.Note(loc_id, IdentifyingFacetTypeHere,
913+
facet_type.facet_type_id);
914+
});
915+
906916
for (auto extends : facet_type_info.extend_named_constraints) {
907917
const auto& constraint =
908918
context.named_constraints().Get(extends.named_constraint_id);
909919
for (auto require_impls_id : context.require_impls_blocks().Get(
910920
constraint.require_impls_block_id)) {
911921
const auto& require = context.require_impls().Get(require_impls_id);
912922
auto require_specific_id = GetRequireImplsSpecificFromEnclosingSpecific(
913-
context, loc_id, require, extends.specific_id);
923+
context, require, extends.specific_id);
914924
auto facet_type_id = TryGetFacetTypeInSpecific(
915925
context, require.facet_type_inst_id, require_specific_id);
916926
if (facet_type_id.has_value()) {
@@ -930,7 +940,7 @@ auto RequireIdentifiedFacetType(Context& context, SemIR::LocId loc_id,
930940
constraint.require_impls_block_id)) {
931941
const auto& require = context.require_impls().Get(require_impls_id);
932942
auto require_specific_id = GetRequireImplsSpecificFromEnclosingSpecific(
933-
context, loc_id, require, impls.specific_id);
943+
context, require, impls.specific_id);
934944
auto facet_type_id = TryGetFacetTypeInSpecific(
935945
context, require.facet_type_inst_id, require_specific_id);
936946
if (facet_type_id.has_value()) {

toolchain/diagnostics/diagnostic_kind.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,9 @@ CARBON_DIAGNOSTIC_KIND(FacetTypeConstraintCycle)
530530
// Facet type combination.
531531
CARBON_DIAGNOSTIC_KIND(FacetTypeRequiredForTypeAndOperator)
532532

533+
// Facet type completeness.
534+
CARBON_DIAGNOSTIC_KIND(IdentifyingFacetTypeHere)
535+
533536
// Generics.
534537
CARBON_DIAGNOSTIC_KIND(GenericMissingExplicitParameters)
535538

toolchain/sem_ir/ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ struct AssociatedConstantId : public IdBase<AssociatedConstantId> {
354354
// The ID of a `FacetTypeInfo`.
355355
struct FacetTypeId : public IdBase<FacetTypeId> {
356356
static constexpr llvm::StringLiteral Label = "facet_type";
357+
using DiagnosticType = Diagnostics::TypeInfo<std::string>;
357358

358359
using IdBase::IdBase;
359360
};

toolchain/sem_ir/stringify.cpp

Lines changed: 77 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ class StepStack {
4848
public:
4949
// An individual step in the stack, which stringifies some component of a type
5050
// name.
51-
using Step = std::variant<InstId, llvm::StringRef, NameId, ElementIndex>;
51+
using Step =
52+
std::variant<InstId, llvm::StringRef, NameId, ElementIndex, FacetTypeId>;
5253

5354
// Support `Push` for a qualified name. e.g., `A.B.C`.
5455
using QualifiedNameItem = std::pair<NameScopeId, NameId>;
@@ -74,6 +75,9 @@ class StepStack {
7475
auto PushElementIndex(ElementIndex element_index) -> void {
7576
steps_.push_back(element_index);
7677
}
78+
auto PushFacetType(FacetTypeId facet_type_id) -> void {
79+
steps_.push_back(facet_type_id);
80+
}
7781

7882
// Pushes all components of a qualified name (`A.B.C`) onto the stack.
7983
auto PushQualifiedName(NameScopeId name_scope_id, NameId name_id) -> void {
@@ -335,64 +339,7 @@ class Stringifier {
335339
}
336340

337341
auto StringifyInst(InstId /*inst_id*/, FacetType inst) -> void {
338-
const FacetTypeInfo& facet_type_info =
339-
sem_ir_->facet_types().Get(inst.facet_type_id);
340-
// Output `where` restrictions.
341-
bool some_where = false;
342-
if (facet_type_info.other_requirements) {
343-
step_stack_->PushString("...");
344-
some_where = true;
345-
}
346-
if (facet_type_info.builtin_constraint_mask.HasAnyOf(
347-
SemIR::BuiltinConstraintMask::TypeCanDestroy)) {
348-
if (some_where) {
349-
step_stack_->PushString(" and");
350-
}
351-
step_stack_->PushString(" .Self impls Core.CanDestroy");
352-
some_where = true;
353-
}
354-
for (auto rewrite : llvm::reverse(facet_type_info.rewrite_constraints)) {
355-
if (some_where) {
356-
step_stack_->PushString(" and");
357-
}
358-
step_stack_->Push(" ", rewrite.lhs_id, " = ", rewrite.rhs_id);
359-
some_where = true;
360-
}
361-
if (!facet_type_info.self_impls_constraints.empty() ||
362-
!facet_type_info.self_impls_named_constraints.empty()) {
363-
if (some_where) {
364-
step_stack_->PushString(" and");
365-
}
366-
llvm::ListSeparator sep(" & ");
367-
for (auto impls :
368-
llvm::reverse(facet_type_info.self_impls_named_constraints)) {
369-
step_stack_->Push(impls, &sep);
370-
}
371-
for (auto impls : llvm::reverse(facet_type_info.self_impls_constraints)) {
372-
step_stack_->Push(impls, &sep);
373-
}
374-
step_stack_->PushString(" .Self impls ");
375-
some_where = true;
376-
}
377-
// TODO: Other restrictions from facet_type_info.
378-
if (some_where) {
379-
step_stack_->PushString(" where");
380-
}
381-
382-
// Output extend interface and named constraint requirements.
383-
if (facet_type_info.extend_constraints.empty() &&
384-
facet_type_info.extend_named_constraints.empty()) {
385-
step_stack_->PushString("type");
386-
return;
387-
}
388-
llvm::ListSeparator sep(" & ");
389-
for (auto extend :
390-
llvm::reverse(facet_type_info.extend_named_constraints)) {
391-
step_stack_->Push(extend, &sep);
392-
}
393-
for (auto extend : llvm::reverse(facet_type_info.extend_constraints)) {
394-
step_stack_->Push(extend, &sep);
395-
}
342+
step_stack_->PushFacetType(inst.facet_type_id);
396343
}
397344

398345
auto StringifyInst(InstId /*inst_id*/, FacetValue inst) -> void {
@@ -721,6 +668,67 @@ class Stringifier {
721668
*out_ << "<vtable ptr>";
722669
}
723670

671+
auto StringifyFacetType(FacetTypeId facet_type_id) -> void {
672+
const FacetTypeInfo& facet_type_info =
673+
sem_ir_->facet_types().Get(facet_type_id);
674+
// Output `where` restrictions.
675+
bool some_where = false;
676+
if (facet_type_info.other_requirements) {
677+
step_stack_->PushString("...");
678+
some_where = true;
679+
}
680+
if (facet_type_info.builtin_constraint_mask.HasAnyOf(
681+
SemIR::BuiltinConstraintMask::TypeCanDestroy)) {
682+
if (some_where) {
683+
step_stack_->PushString(" and");
684+
}
685+
step_stack_->PushString(" .Self impls Core.CanDestroy");
686+
some_where = true;
687+
}
688+
for (auto rewrite : llvm::reverse(facet_type_info.rewrite_constraints)) {
689+
if (some_where) {
690+
step_stack_->PushString(" and");
691+
}
692+
step_stack_->Push(" ", rewrite.lhs_id, " = ", rewrite.rhs_id);
693+
some_where = true;
694+
}
695+
if (!facet_type_info.self_impls_constraints.empty() ||
696+
!facet_type_info.self_impls_named_constraints.empty()) {
697+
if (some_where) {
698+
step_stack_->PushString(" and");
699+
}
700+
llvm::ListSeparator sep(" & ");
701+
for (auto impls :
702+
llvm::reverse(facet_type_info.self_impls_named_constraints)) {
703+
step_stack_->Push(impls, &sep);
704+
}
705+
for (auto impls : llvm::reverse(facet_type_info.self_impls_constraints)) {
706+
step_stack_->Push(impls, &sep);
707+
}
708+
step_stack_->PushString(" .Self impls ");
709+
some_where = true;
710+
}
711+
// TODO: Other restrictions from facet_type_info.
712+
if (some_where) {
713+
step_stack_->PushString(" where");
714+
}
715+
716+
// Output extend interface and named constraint requirements.
717+
if (facet_type_info.extend_constraints.empty() &&
718+
facet_type_info.extend_named_constraints.empty()) {
719+
step_stack_->PushString("type");
720+
return;
721+
}
722+
llvm::ListSeparator sep(" & ");
723+
for (auto extend :
724+
llvm::reverse(facet_type_info.extend_named_constraints)) {
725+
step_stack_->Push(extend, &sep);
726+
}
727+
for (auto extend : llvm::reverse(facet_type_info.extend_constraints)) {
728+
step_stack_->Push(extend, &sep);
729+
}
730+
}
731+
724732
private:
725733
const File* sem_ir_;
726734
StepStack* step_stack_;
@@ -763,6 +771,9 @@ static auto Stringify(const File& sem_ir, StepStack& step_stack)
763771
case CARBON_KIND(ElementIndex element_index):
764772
out << element_index.index;
765773
break;
774+
case CARBON_KIND(FacetTypeId facet_type_id):
775+
stringifier.StringifyFacetType(facet_type_id);
776+
break;
766777
}
767778
}
768779

@@ -841,4 +852,11 @@ auto StringifySpecificInterface(const File& sem_ir,
841852
}
842853
}
843854

855+
auto StringifyFacetType(const File& sem_ir, FacetTypeId facet_type_id)
856+
-> std::string {
857+
StepStack step_stack(&sem_ir);
858+
step_stack.PushFacetType(facet_type_id);
859+
return Stringify(sem_ir, step_stack);
860+
}
861+
844862
} // namespace Carbon::SemIR

toolchain/sem_ir/stringify.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,20 @@ auto StringifySpecific(const File& sem_ir, SpecificId specific_id)
2626
-> std::string;
2727

2828
// Produces a string version of the name of a specific interface. If the
29-
// interface is not generic, this is just the name of the interface. Otheewise,
29+
// interface is not generic, this is just the name of the interface. Otherwise,
3030
// it is the interface name and its generic arguments. Generally, this should
3131
// not be called directly. To format a string into a diagnostic, use a
3232
// diagnostic parameter of type `SpecificInterface`.
3333
auto StringifySpecificInterface(const File& sem_ir,
3434
SpecificInterface specific_interface)
3535
-> std::string;
3636

37+
// Produces a string version of the facet type. This contains the name of the
38+
// interfaces or named constraints that the facet type names, and any
39+
// requirements such as rewrites.
40+
auto StringifyFacetType(const File& sem_ir, FacetTypeId facet_type_id)
41+
-> std::string;
42+
3743
} // namespace Carbon::SemIR
3844

3945
#endif // CARBON_TOOLCHAIN_SEM_IR_STRINGIFY_H_

0 commit comments

Comments
 (0)