From 684cda3d5390c2c0350902820b85fec4ef85a665 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 18 Oct 2024 08:33:10 -0700 Subject: [PATCH] Don't deduce values for explicitly-specified generic bindings. (#4415) Distinguish between deduction against a symbolic binding pattern and deduction against a symbolic binding name. In the former case, the value is being explicitly specified and must be constant. In the latter case we encountered a use of the binding name as a subexpression, and should deduce against it if it's not explicitly specified. --- toolchain/check/deduce.cpp | 133 ++++++--- .../check/testdata/class/generic/call.carbon | 21 +- .../testdata/function/generic/deduce.carbon | 254 +++++++++++++++--- .../interface/no_prelude/generic.carbon | 7 +- toolchain/check/testdata/struct/import.carbon | 16 +- toolchain/check/testdata/tuple/import.carbon | 18 +- .../testdata/where_expr/constraints.carbon | 49 ++-- toolchain/diagnostics/diagnostic_kind.def | 1 + 8 files changed, 379 insertions(+), 120 deletions(-) diff --git a/toolchain/check/deduce.cpp b/toolchain/check/deduce.cpp index 88c466505660..fa1c86b3168a 100644 --- a/toolchain/check/deduce.cpp +++ b/toolchain/check/deduce.cpp @@ -4,6 +4,7 @@ #include "toolchain/check/deduce.h" +#include "llvm/ADT/SmallBitVector.h" #include "toolchain/base/kind_switch.h" #include "toolchain/check/context.h" #include "toolchain/check/convert.h" @@ -183,6 +184,8 @@ class DeductionContext { llvm::SmallVector result_arg_ids_; llvm::SmallVector substitutions_; SemIR::CompileTimeBindIndex first_deduced_index_; + // Non-deduced indexes, indexed by parameter index - first_deduced_index_. + llvm::SmallBitVector non_deduced_indexes_; }; } // namespace @@ -231,12 +234,33 @@ DeductionContext::DeductionContext(Context& context, SemIR::LocId loc_id, } first_deduced_index_ = SemIR::CompileTimeBindIndex(args.size()); } + + non_deduced_indexes_.resize(result_arg_ids_.size() - + first_deduced_index_.index); } auto DeductionContext::Deduce() -> bool { while (!worklist_.Done()) { auto [param_id, arg_id, needs_substitution] = worklist_.PopNext(); + auto note_initializing_param = [&](auto& builder) { + if (auto param = + context().insts().TryGetAs( + param_id)) { + CARBON_DIAGNOSTIC(InitializingGenericParam, Note, + "initializing generic parameter `{0}` declared here", + SemIR::NameId); + builder.Note( + param_id, InitializingGenericParam, + context().entity_names().Get(param->entity_name_id).name_id); + } else { + NoteGenericHere(context(), generic_id_, builder); + } + }; + + // TODO: Bail out if there's nothing to deduce: if we're not in a pattern + // and the parameter doesn't have a symbolic constant value. + // If the parameter has a symbolic type, deduce against that. auto param_type_id = context().insts().Get(param_id).type_id(); if (param_type_id.AsConstantId().is_symbolic()) { @@ -246,54 +270,70 @@ auto DeductionContext::Deduce() -> bool { } else { // The argument needs to have the same type as the parameter. // TODO: Suppress diagnostics here if diagnose_ is false. - DiagnosticAnnotationScope annotate_diagnostics( - &context().emitter(), [&](auto& builder) { - if (auto param = - context().insts().TryGetAs( - param_id)) { - CARBON_DIAGNOSTIC( - InitializingGenericParam, Note, - "initializing generic parameter `{0}` declared here", - SemIR::NameId); - builder.Note( - param_id, InitializingGenericParam, - context().entity_names().Get(param->entity_name_id).name_id); - } - }); + // TODO: Only do this when deducing against a symbolic pattern. + DiagnosticAnnotationScope annotate_diagnostics(&context().emitter(), + note_initializing_param); arg_id = ConvertToValueOfType(context(), loc_id_, arg_id, param_type_id); if (arg_id == SemIR::InstId::BuiltinError) { return false; } } - // If the parameter is a symbolic constant, deduce against it. Otherwise, we - // assume there is nothing to deduce. - // TODO: This won't do the right thing in a template deduction. - auto param_const_id = context().constant_values().Get(param_id); - if (!param_const_id.is_valid() || !param_const_id.is_symbolic()) { - continue; - } - // Attempt to match `param_inst` against `arg_id`. If the match succeeds, // this should `continue` the outer loop. On `break`, we will try to desugar // the parameter to continue looking for a match. - auto param_inst = context().insts().Get( - context().constant_values().GetInstId(param_const_id)); + auto param_inst = context().insts().Get(param_id); CARBON_KIND_SWITCH(param_inst) { - // Deducing a symbolic binding from an argument with a constant value - // deduces the binding as having that constant value. - case SemIR::InstKind::SymbolicBindingPattern: - case SemIR::InstKind::BindSymbolicName: { - auto entity_name_id = SemIR::EntityNameId::Invalid; - if (auto bind = param_inst.TryAs()) { - entity_name_id = bind->entity_name_id; - } else { - entity_name_id = - param_inst.As().entity_name_id; - } - auto& entity_name = context().entity_names().Get(entity_name_id); + // Deducing a symbolic binding pattern from an argument deduces the + // binding as having that constant value. For example, deducing + // `(T:! type)` against `(i32)` deduces `T` to be `i32`. This only arises + // when initializing a generic parameter from an explicitly specified + // argument, and in this case, the argument is required to be a + // compile-time constant. + case CARBON_KIND(SemIR::SymbolicBindingPattern bind): { + auto& entity_name = context().entity_names().Get(bind.entity_name_id); auto index = entity_name.bind_index; - if (!index.is_valid() || index < first_deduced_index_) { + if (!index.is_valid()) { + break; + } + CARBON_CHECK( + index >= first_deduced_index_ && + static_cast(index.index) < result_arg_ids_.size(), + "Unexpected index {0} for symbolic binding pattern; " + "expected to be in range [{1}, {2})", + index.index, first_deduced_index_.index, result_arg_ids_.size()); + CARBON_CHECK(!result_arg_ids_[index.index].is_valid(), + "Deduced a value for parameter prior to its declaration"); + + auto arg_const_inst_id = + context().constant_values().GetConstantInstId(arg_id); + if (!arg_const_inst_id.is_valid()) { + if (diagnose_) { + CARBON_DIAGNOSTIC(CompTimeArgumentNotConstant, Error, + "argument for generic parameter is not a " + "compile-time constant"); + auto diag = + context().emitter().Build(loc_id_, CompTimeArgumentNotConstant); + note_initializing_param(diag); + diag.Emit(); + } + return false; + } + + result_arg_ids_[index.index] = arg_const_inst_id; + // This parameter index should not be deduced if it appears later. + non_deduced_indexes_[index.index - first_deduced_index_.index] = true; + continue; + } + + // Deducing a symbolic binding appearing within an expression against a + // constant value deduces the binding as having that value. For example, + // deducing `[T:! type](x: T)` against `("foo")` deduces `T` as `String`. + case CARBON_KIND(SemIR::BindSymbolicName bind): { + auto& entity_name = context().entity_names().Get(bind.entity_name_id); + auto index = entity_name.bind_index; + if (!index.is_valid() || index < first_deduced_index_ || + non_deduced_indexes_[index.index - first_deduced_index_.index]) { break; } @@ -324,6 +364,11 @@ auto DeductionContext::Deduce() -> bool { continue; } + case CARBON_KIND(SemIR::ParamPattern pattern): { + Add(pattern.subpattern_id, arg_id, needs_substitution); + continue; + } + // Various kinds of parameter should match an argument of the same form, // if the operands all match. case SemIR::ArrayType::Kind: @@ -358,6 +403,20 @@ auto DeductionContext::Deduce() -> bool { break; } + // We didn't manage to deduce against the syntactic form of the parameter. + // Convert it to a canonical constant value and try deducing against that. + auto param_const_id = context().constant_values().Get(param_id); + if (!param_const_id.is_valid() || !param_const_id.is_symbolic()) { + // It's not a symbolic constant. There's nothing here to deduce. + continue; + } + auto param_const_inst_id = + context().constant_values().GetInstId(param_const_id); + if (param_const_inst_id != param_id) { + Add(param_const_inst_id, arg_id, needs_substitution); + continue; + } + // If we've not yet substituted into the parameter, do so now and try again. if (needs_substitution) { param_const_id = SubstConstant(context(), param_const_id, substitutions_); diff --git a/toolchain/check/testdata/class/generic/call.carbon b/toolchain/check/testdata/class/generic/call.carbon index 1a60c3732c6a..93dde3195523 100644 --- a/toolchain/check/testdata/class/generic/call.carbon +++ b/toolchain/check/testdata/class/generic/call.carbon @@ -55,12 +55,15 @@ library "[[@TEST_NAME]]"; class Class(T:! type, N:! i32) {} -// CHECK:STDERR: fail_no_conversion.carbon:[[@LINE+6]]:8: error: cannot implicitly convert from `i32` to `type` +// CHECK:STDERR: fail_no_conversion.carbon:[[@LINE+9]]:8: error: cannot implicitly convert from `i32` to `type` // CHECK:STDERR: var a: Class(5, i32*); // CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: fail_no_conversion.carbon:[[@LINE+3]]:8: note: type `i32` does not implement interface `ImplicitAs` +// CHECK:STDERR: fail_no_conversion.carbon:[[@LINE+6]]:8: note: type `i32` does not implement interface `ImplicitAs` // CHECK:STDERR: var a: Class(5, i32*); // CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: fail_no_conversion.carbon:[[@LINE-8]]:1: note: while deducing parameters of generic declared here +// CHECK:STDERR: class Class(T:! type, N:! i32) {} +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var a: Class(5, i32*); // --- call_in_nested_return_type.carbon @@ -463,15 +466,15 @@ class Outer(T:! type) { // CHECK:STDOUT: %N.loc4_23.1: i32 = bind_symbolic_name N, 1, %param.loc4_23 [symbolic = %N.loc4_23.2 (constants.%N)] // CHECK:STDOUT: } // CHECK:STDOUT: %Class.ref: %Class.type = name_ref Class, %Class.decl [template = constants.%Class.1] -// CHECK:STDOUT: %.loc12_14: i32 = int_literal 5 [template = constants.%.4] +// CHECK:STDOUT: %.loc15_14: i32 = int_literal 5 [template = constants.%.4] // CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc12_20.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc12_20.2: type = converted %int.make_type_32, %.loc12_20.1 [template = i32] -// CHECK:STDOUT: %.loc12_20.3: type = ptr_type i32 [template = constants.%.5] +// CHECK:STDOUT: %.loc15_20.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc15_20.2: type = converted %int.make_type_32, %.loc15_20.1 [template = i32] +// CHECK:STDOUT: %.loc15_20.3: type = ptr_type i32 [template = constants.%.5] // CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(type) [template = constants.%ImplicitAs.type.3] -// CHECK:STDOUT: %.loc12_13.1: %.8 = specific_constant imports.%import_ref.4, @ImplicitAs(type) [template = constants.%.9] -// CHECK:STDOUT: %Convert.ref: %.8 = name_ref Convert, %.loc12_13.1 [template = constants.%.9] -// CHECK:STDOUT: %.loc12_13.2: type = converted %.loc12_14, [template = ] +// CHECK:STDOUT: %.loc15_13.1: %.8 = specific_constant imports.%import_ref.4, @ImplicitAs(type) [template = constants.%.9] +// CHECK:STDOUT: %Convert.ref: %.8 = name_ref Convert, %.loc15_13.1 [template = constants.%.9] +// CHECK:STDOUT: %.loc15_13.2: type = converted %.loc15_14, [template = ] // CHECK:STDOUT: %a.var: ref = var a // CHECK:STDOUT: %a: ref = bind_name a, %a.var // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/function/generic/deduce.carbon b/toolchain/check/testdata/function/generic/deduce.carbon index 9fc67825b2cb..3bf496628de9 100644 --- a/toolchain/check/testdata/function/generic/deduce.carbon +++ b/toolchain/check/testdata/function/generic/deduce.carbon @@ -22,23 +22,38 @@ fn CallExplicitGenericParamWithGenericArg(T:! type) -> {.a: T}* { return ExplicitGenericParam({.a: T}); } -// --- fail_todo_explicit_vs_deduced.carbon +// --- fail_deduce_explicit_non_constant.carbon + +library "[[@TEST_NAME]]"; + +fn ExplicitGenericParam(T:! type) -> T* { return ExplicitGenericParam(T); } + +fn CallExplicitGenericParamConst(T:! type) { + ExplicitGenericParam(T); +} + +fn CallExplicitGenericParamNonConst(T: type) { + // CHECK:STDERR: fail_deduce_explicit_non_constant.carbon:[[@LINE+7]]:3: error: argument for generic parameter is not a compile-time constant + // CHECK:STDERR: ExplicitGenericParam(T); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_deduce_explicit_non_constant.carbon:[[@LINE-10]]:25: note: initializing generic parameter `T` declared here + // CHECK:STDERR: fn ExplicitGenericParam(T:! type) -> T* { return ExplicitGenericParam(T); } + // CHECK:STDERR: ^ + // CHECK:STDERR: + ExplicitGenericParam(T); +} + +// --- explicit_vs_deduced.carbon library "[[@TEST_NAME]]"; class A {} -fn ExplicitAndAlsoDeduced(T:! type, x: T) -> T*; +fn ExplicitAndAlsoDeduced(T:! type, x: T) -> T* { + return ExplicitAndAlsoDeduced(T, x); +} -// TODO: This should presumably be accepted. We shouldn't deduce values for parameters with explicitly-specified values. -fn CallExplicitAndAlsoDeduced(n: i32) -> i32* { - // CHECK:STDERR: fail_todo_explicit_vs_deduced.carbon:[[@LINE+7]]:10: error: inconsistent deductions for value of generic parameter `T` - // CHECK:STDERR: return ExplicitAndAlsoDeduced(A, {}); - // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~ - // CHECK:STDERR: fail_todo_explicit_vs_deduced.carbon:[[@LINE-7]]:1: note: while deducing parameters of generic declared here - // CHECK:STDERR: fn ExplicitAndAlsoDeduced(T:! type, x: T) -> T*; - // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // CHECK:STDERR: +fn CallExplicitAndAlsoDeduced() -> A* { return ExplicitAndAlsoDeduced(A, {}); } @@ -294,7 +309,142 @@ fn CallImplicitNotDeducible() { // CHECK:STDOUT: %.loc4_39.2 => constants.%.7 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_explicit_vs_deduced.carbon +// CHECK:STDOUT: --- fail_deduce_explicit_non_constant.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %T.patt.1: type = symbolic_binding_pattern T, 0 [symbolic] +// CHECK:STDOUT: %.1: type = ptr_type %T [symbolic] +// CHECK:STDOUT: %ExplicitGenericParam.type: type = fn_type @ExplicitGenericParam [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %ExplicitGenericParam: %ExplicitGenericParam.type = struct_value () [template] +// CHECK:STDOUT: %.3: = specific_function %ExplicitGenericParam, @ExplicitGenericParam(%T) [symbolic] +// CHECK:STDOUT: %T.patt.2: type = symbolic_binding_pattern T, 0 [symbolic] +// CHECK:STDOUT: %CallExplicitGenericParamConst.type: type = fn_type @CallExplicitGenericParamConst [template] +// CHECK:STDOUT: %CallExplicitGenericParamConst: %CallExplicitGenericParamConst.type = struct_value () [template] +// CHECK:STDOUT: %CallExplicitGenericParamNonConst.type: type = fn_type @CallExplicitGenericParamNonConst [template] +// CHECK:STDOUT: %CallExplicitGenericParamNonConst: %CallExplicitGenericParamNonConst.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .ExplicitGenericParam = %ExplicitGenericParam.decl +// CHECK:STDOUT: .CallExplicitGenericParamConst = %CallExplicitGenericParamConst.decl +// CHECK:STDOUT: .CallExplicitGenericParamNonConst = %CallExplicitGenericParamNonConst.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %ExplicitGenericParam.decl: %ExplicitGenericParam.type = fn_decl @ExplicitGenericParam [template = constants.%ExplicitGenericParam] { +// CHECK:STDOUT: %T.patt.loc4_25.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_25.2 (constants.%T.patt.1)] +// CHECK:STDOUT: %T.param_patt: type = param_pattern %T.patt.loc4_25.1, runtime_param [symbolic = %T.patt.loc4_25.2 (constants.%T.patt.1)] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.ref.loc4_38: type = name_ref T, %T.loc4_25.1 [symbolic = %T.loc4_25.2 (constants.%T)] +// CHECK:STDOUT: %.loc4_39.1: type = ptr_type %T [symbolic = %.loc4_39.2 (constants.%.1)] +// CHECK:STDOUT: %return: ref @ExplicitGenericParam.%.loc4_39.2 (%.1) = var +// CHECK:STDOUT: %param: type = param runtime_param +// CHECK:STDOUT: %T.loc4_25.1: type = bind_symbolic_name T, 0, %param [symbolic = %T.loc4_25.2 (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %CallExplicitGenericParamConst.decl: %CallExplicitGenericParamConst.type = fn_decl @CallExplicitGenericParamConst [template = constants.%CallExplicitGenericParamConst] { +// CHECK:STDOUT: %T.patt.loc6_34.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc6_34.2 (constants.%T.patt.2)] +// CHECK:STDOUT: %T.param_patt: type = param_pattern %T.patt.loc6_34.1, runtime_param [symbolic = %T.patt.loc6_34.2 (constants.%T.patt.2)] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %param: type = param runtime_param +// CHECK:STDOUT: %T.loc6_34.1: type = bind_symbolic_name T, 0, %param [symbolic = %T.loc6_34.2 (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %CallExplicitGenericParamNonConst.decl: %CallExplicitGenericParamNonConst.type = fn_decl @CallExplicitGenericParamNonConst [template = constants.%CallExplicitGenericParamNonConst] { +// CHECK:STDOUT: %T.patt: type = binding_pattern T +// CHECK:STDOUT: %T.param_patt: type = param_pattern %T.patt, runtime_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %param: type = param runtime_param0 +// CHECK:STDOUT: %T: type = bind_name T, %param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @ExplicitGenericParam(%T.loc4_25.1: type) { +// CHECK:STDOUT: %T.loc4_25.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_25.2 (constants.%T)] +// CHECK:STDOUT: %T.patt.loc4_25.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_25.2 (constants.%T.patt.1)] +// CHECK:STDOUT: %.loc4_39.2: type = ptr_type @ExplicitGenericParam.%T.loc4_25.2 (%T) [symbolic = %.loc4_39.2 (constants.%.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.loc4_50.2: = specific_function constants.%ExplicitGenericParam, @ExplicitGenericParam(%T.loc4_25.2) [symbolic = %.loc4_50.2 (constants.%.3)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%T.param_patt: type) -> @ExplicitGenericParam.%.loc4_39.2 (%.1) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %ExplicitGenericParam.ref: %ExplicitGenericParam.type = name_ref ExplicitGenericParam, file.%ExplicitGenericParam.decl [template = constants.%ExplicitGenericParam] +// CHECK:STDOUT: %T.ref.loc4_71: type = name_ref T, %T.loc4_25.1 [symbolic = %T.loc4_25.2 (constants.%T)] +// CHECK:STDOUT: %.loc4_50.1: = specific_function %ExplicitGenericParam.ref, @ExplicitGenericParam(constants.%T) [symbolic = %.loc4_50.2 (constants.%.3)] +// CHECK:STDOUT: %ExplicitGenericParam.call: init @ExplicitGenericParam.%.loc4_39.2 (%.1) = call %.loc4_50.1() +// CHECK:STDOUT: %.loc4_73.1: @ExplicitGenericParam.%.loc4_39.2 (%.1) = value_of_initializer %ExplicitGenericParam.call +// CHECK:STDOUT: %.loc4_73.2: @ExplicitGenericParam.%.loc4_39.2 (%.1) = converted %ExplicitGenericParam.call, %.loc4_73.1 +// CHECK:STDOUT: return %.loc4_73.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @CallExplicitGenericParamConst(%T.loc6_34.1: type) { +// CHECK:STDOUT: %T.loc6_34.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc6_34.2 (constants.%T)] +// CHECK:STDOUT: %T.patt.loc6_34.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc6_34.2 (constants.%T.patt.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.loc7_3.2: = specific_function constants.%ExplicitGenericParam, @ExplicitGenericParam(%T.loc6_34.2) [symbolic = %.loc7_3.2 (constants.%.3)] +// CHECK:STDOUT: %.loc7_23: type = ptr_type @CallExplicitGenericParamConst.%T.loc6_34.2 (%T) [symbolic = %.loc7_23 (constants.%.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%T.param_patt: type) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %ExplicitGenericParam.ref: %ExplicitGenericParam.type = name_ref ExplicitGenericParam, file.%ExplicitGenericParam.decl [template = constants.%ExplicitGenericParam] +// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc6_34.1 [symbolic = %T.loc6_34.2 (constants.%T)] +// CHECK:STDOUT: %.loc7_3.1: = specific_function %ExplicitGenericParam.ref, @ExplicitGenericParam(constants.%T) [symbolic = %.loc7_3.2 (constants.%.3)] +// CHECK:STDOUT: %ExplicitGenericParam.call: init @CallExplicitGenericParamConst.%.loc7_23 (%.1) = call %.loc7_3.1() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @CallExplicitGenericParamNonConst(%T.param_patt: type) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %ExplicitGenericParam.ref: %ExplicitGenericParam.type = name_ref ExplicitGenericParam, file.%ExplicitGenericParam.decl [template = constants.%ExplicitGenericParam] +// CHECK:STDOUT: %T.ref: type = name_ref T, %T +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ExplicitGenericParam(constants.%T) { +// CHECK:STDOUT: %T.loc4_25.2 => constants.%T +// CHECK:STDOUT: %T.patt.loc4_25.2 => constants.%T +// CHECK:STDOUT: %.loc4_39.2 => constants.%.1 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.loc4_50.2 => constants.%.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ExplicitGenericParam(@ExplicitGenericParam.%T.loc4_25.2) { +// CHECK:STDOUT: %T.loc4_25.2 => constants.%T +// CHECK:STDOUT: %T.patt.loc4_25.2 => constants.%T +// CHECK:STDOUT: %.loc4_39.2 => constants.%.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @CallExplicitGenericParamConst(constants.%T) { +// CHECK:STDOUT: %T.loc6_34.2 => constants.%T +// CHECK:STDOUT: %T.patt.loc6_34.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ExplicitGenericParam(@CallExplicitGenericParamConst.%T.loc6_34.2) { +// CHECK:STDOUT: %T.loc4_25.2 => constants.%T +// CHECK:STDOUT: %T.patt.loc4_25.2 => constants.%T +// CHECK:STDOUT: %.loc4_39.2 => constants.%.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- explicit_vs_deduced.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %A: type = class_type @A [template] @@ -306,16 +456,17 @@ fn CallImplicitNotDeducible() { // CHECK:STDOUT: %ExplicitAndAlsoDeduced.type: type = fn_type @ExplicitAndAlsoDeduced [template] // CHECK:STDOUT: %.4: type = tuple_type () [template] // CHECK:STDOUT: %ExplicitAndAlsoDeduced: %ExplicitAndAlsoDeduced.type = struct_value () [template] -// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] -// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] -// CHECK:STDOUT: %.5: type = ptr_type i32 [template] +// CHECK:STDOUT: %.5: = specific_function %ExplicitAndAlsoDeduced, @ExplicitAndAlsoDeduced(%T) [symbolic] +// CHECK:STDOUT: %.6: type = ptr_type %A [template] // CHECK:STDOUT: %CallExplicitAndAlsoDeduced.type: type = fn_type @CallExplicitAndAlsoDeduced [template] // CHECK:STDOUT: %CallExplicitAndAlsoDeduced: %CallExplicitAndAlsoDeduced.type = struct_value () [template] +// CHECK:STDOUT: %.7: = specific_function %ExplicitAndAlsoDeduced, @ExplicitAndAlsoDeduced(%A) [template] +// CHECK:STDOUT: %.8: type = ptr_type %.1 [template] +// CHECK:STDOUT: %struct: %A = struct_value () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: .Int32 = %import_ref // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/operators // CHECK:STDOUT: import Core//prelude/types @@ -325,7 +476,6 @@ fn CallImplicitNotDeducible() { // CHECK:STDOUT: import Core//prelude/operators/comparison // CHECK:STDOUT: import Core//prelude/types/bool // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref: %Int32.type = import_ref Core//prelude/types, inst+9, loaded [template = constants.%Int32] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -352,20 +502,10 @@ fn CallImplicitNotDeducible() { // CHECK:STDOUT: %param.loc6_37: @ExplicitAndAlsoDeduced.%T.loc6_27.2 (%T) = param runtime_param0 // CHECK:STDOUT: %x: @ExplicitAndAlsoDeduced.%T.loc6_27.2 (%T) = bind_name x, %param.loc6_37 // CHECK:STDOUT: } -// CHECK:STDOUT: %CallExplicitAndAlsoDeduced.decl: %CallExplicitAndAlsoDeduced.type = fn_decl @CallExplicitAndAlsoDeduced [template = constants.%CallExplicitAndAlsoDeduced] { -// CHECK:STDOUT: %n.patt: i32 = binding_pattern n -// CHECK:STDOUT: %n.param_patt: i32 = param_pattern %n.patt, runtime_param0 -// CHECK:STDOUT: } { -// CHECK:STDOUT: %int.make_type_32.loc9_34: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc9_34.1: type = value_of_initializer %int.make_type_32.loc9_34 [template = i32] -// CHECK:STDOUT: %.loc9_34.2: type = converted %int.make_type_32.loc9_34, %.loc9_34.1 [template = i32] -// CHECK:STDOUT: %int.make_type_32.loc9_42: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc9_45.1: type = value_of_initializer %int.make_type_32.loc9_42 [template = i32] -// CHECK:STDOUT: %.loc9_45.2: type = converted %int.make_type_32.loc9_42, %.loc9_45.1 [template = i32] -// CHECK:STDOUT: %.loc9_45.3: type = ptr_type i32 [template = constants.%.5] -// CHECK:STDOUT: %return: ref %.5 = var -// CHECK:STDOUT: %param: i32 = param runtime_param0 -// CHECK:STDOUT: %n: i32 = bind_name n, %param +// CHECK:STDOUT: %CallExplicitAndAlsoDeduced.decl: %CallExplicitAndAlsoDeduced.type = fn_decl @CallExplicitAndAlsoDeduced [template = constants.%CallExplicitAndAlsoDeduced] {} { +// CHECK:STDOUT: %A.ref.loc10: type = name_ref A, file.%A.decl [template = constants.%A] +// CHECK:STDOUT: %.loc10: type = ptr_type %A [template = constants.%.6] +// CHECK:STDOUT: %return: ref %.6 = var // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -381,23 +521,61 @@ fn CallImplicitNotDeducible() { // CHECK:STDOUT: %T.patt.loc6_27.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc6_27.2 (constants.%T.patt)] // CHECK:STDOUT: %.loc6_47.2: type = ptr_type @ExplicitAndAlsoDeduced.%T.loc6_27.2 (%T) [symbolic = %.loc6_47.2 (constants.%.3)] // CHECK:STDOUT: -// CHECK:STDOUT: fn(%T.param_patt: type, %x.param_patt: @ExplicitAndAlsoDeduced.%T.loc6_27.2 (%T)) -> @ExplicitAndAlsoDeduced.%.loc6_47.2 (%.3); +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.loc7_10.2: = specific_function constants.%ExplicitAndAlsoDeduced, @ExplicitAndAlsoDeduced(%T.loc6_27.2) [symbolic = %.loc7_10.2 (constants.%.5)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%T.param_patt: type, %x.param_patt: @ExplicitAndAlsoDeduced.%T.loc6_27.2 (%T)) -> @ExplicitAndAlsoDeduced.%.loc6_47.2 (%.3) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %ExplicitAndAlsoDeduced.ref: %ExplicitAndAlsoDeduced.type = name_ref ExplicitAndAlsoDeduced, file.%ExplicitAndAlsoDeduced.decl [template = constants.%ExplicitAndAlsoDeduced] +// CHECK:STDOUT: %T.ref.loc7: type = name_ref T, %T.loc6_27.1 [symbolic = %T.loc6_27.2 (constants.%T)] +// CHECK:STDOUT: %x.ref: @ExplicitAndAlsoDeduced.%T.loc6_27.2 (%T) = name_ref x, %x +// CHECK:STDOUT: %.loc7_10.1: = specific_function %ExplicitAndAlsoDeduced.ref, @ExplicitAndAlsoDeduced(constants.%T) [symbolic = %.loc7_10.2 (constants.%.5)] +// CHECK:STDOUT: %ExplicitAndAlsoDeduced.call: init @ExplicitAndAlsoDeduced.%.loc6_47.2 (%.3) = call %.loc7_10.1(%x.ref) +// CHECK:STDOUT: %.loc7_38.1: @ExplicitAndAlsoDeduced.%.loc6_47.2 (%.3) = value_of_initializer %ExplicitAndAlsoDeduced.call +// CHECK:STDOUT: %.loc7_38.2: @ExplicitAndAlsoDeduced.%.loc6_47.2 (%.3) = converted %ExplicitAndAlsoDeduced.call, %.loc7_38.1 +// CHECK:STDOUT: return %.loc7_38.2 +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; -// CHECK:STDOUT: -// CHECK:STDOUT: fn @CallExplicitAndAlsoDeduced(%n.param_patt: i32) -> %.5 { +// CHECK:STDOUT: fn @CallExplicitAndAlsoDeduced() -> %.6 { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %ExplicitAndAlsoDeduced.ref: %ExplicitAndAlsoDeduced.type = name_ref ExplicitAndAlsoDeduced, file.%ExplicitAndAlsoDeduced.decl [template = constants.%ExplicitAndAlsoDeduced] -// CHECK:STDOUT: %A.ref: type = name_ref A, file.%A.decl [template = constants.%A] -// CHECK:STDOUT: %.loc17: %.1 = struct_literal () -// CHECK:STDOUT: return +// CHECK:STDOUT: %A.ref.loc11: type = name_ref A, file.%A.decl [template = constants.%A] +// CHECK:STDOUT: %.loc11_37.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc11_10: = specific_function %ExplicitAndAlsoDeduced.ref, @ExplicitAndAlsoDeduced(constants.%A) [template = constants.%.7] +// CHECK:STDOUT: %.loc11_37.2: ref %A = temporary_storage +// CHECK:STDOUT: %.loc11_37.3: init %A = class_init (), %.loc11_37.2 [template = constants.%struct] +// CHECK:STDOUT: %.loc11_37.4: ref %A = temporary %.loc11_37.2, %.loc11_37.3 +// CHECK:STDOUT: %.loc11_37.5: ref %A = converted %.loc11_37.1, %.loc11_37.4 +// CHECK:STDOUT: %.loc11_37.6: %A = bind_value %.loc11_37.5 +// CHECK:STDOUT: %ExplicitAndAlsoDeduced.call: init %.6 = call %.loc11_10(%.loc11_37.6) +// CHECK:STDOUT: %.loc11_39.1: %.6 = value_of_initializer %ExplicitAndAlsoDeduced.call +// CHECK:STDOUT: %.loc11_39.2: %.6 = converted %ExplicitAndAlsoDeduced.call, %.loc11_39.1 +// CHECK:STDOUT: return %.loc11_39.2 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @ExplicitAndAlsoDeduced(constants.%T) { // CHECK:STDOUT: %T.loc6_27.2 => constants.%T // CHECK:STDOUT: %T.patt.loc6_27.2 => constants.%T // CHECK:STDOUT: %.loc6_47.2 => constants.%.3 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.loc7_10.2 => constants.%.5 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ExplicitAndAlsoDeduced(@ExplicitAndAlsoDeduced.%T.loc6_27.2) { +// CHECK:STDOUT: %T.loc6_27.2 => constants.%T +// CHECK:STDOUT: %T.patt.loc6_27.2 => constants.%T +// CHECK:STDOUT: %.loc6_47.2 => constants.%.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ExplicitAndAlsoDeduced(constants.%A) { +// CHECK:STDOUT: %T.loc6_27.2 => constants.%A +// CHECK:STDOUT: %T.patt.loc6_27.2 => constants.%A +// CHECK:STDOUT: %.loc6_47.2 => constants.%.6 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.loc7_10.2 => constants.%.7 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- deduce_implicit.carbon diff --git a/toolchain/check/testdata/interface/no_prelude/generic.carbon b/toolchain/check/testdata/interface/no_prelude/generic.carbon index 56798e572d8b..8e5a53adf2e0 100644 --- a/toolchain/check/testdata/interface/no_prelude/generic.carbon +++ b/toolchain/check/testdata/interface/no_prelude/generic.carbon @@ -49,9 +49,12 @@ class B {} fn F(T:! Generic(A)); fn G(T:! Generic(B)) { // TODO: Include generic arguments in the type name. - // CHECK:STDERR: fail_mismatched_args.carbon:[[@LINE+3]]:3: error: package `Core` implicitly referenced here, but not found + // CHECK:STDERR: fail_mismatched_args.carbon:[[@LINE+6]]:3: error: package `Core` implicitly referenced here, but not found // CHECK:STDERR: F(T); // CHECK:STDERR: ^~ + // CHECK:STDERR: fail_mismatched_args.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here + // CHECK:STDERR: fn F(T:! Generic(A)); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~ F(T); } @@ -488,7 +491,7 @@ fn G(T:! Generic(B)) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] // CHECK:STDOUT: %T.ref: %Generic.type.4 = name_ref T, %T.loc10_6.1 [symbolic = %T.loc10_6.2 (constants.%T.3)] -// CHECK:STDOUT: %.loc15: %Generic.type.3 = converted %T.ref, [template = ] +// CHECK:STDOUT: %.loc18: %Generic.type.3 = converted %T.ref, [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/struct/import.carbon b/toolchain/check/testdata/struct/import.carbon index 033214614e0c..516d9e41de32 100644 --- a/toolchain/check/testdata/struct/import.carbon +++ b/toolchain/check/testdata/struct/import.carbon @@ -30,9 +30,13 @@ var c: C({.a = 1, .b = 2}) = F(); // --- fail_bad_type.impl.carbon impl package Implicit; -// CHECK:STDERR: fail_bad_type.impl.carbon:[[@LINE+4]]:14: error: missing value for field `a` in struct initialization +// CHECK:STDERR: fail_bad_type.impl.carbon:[[@LINE+8]]:14: error: missing value for field `a` in struct initialization // CHECK:STDERR: var c_bad: C({.c = 1, .d = 2}) = F(); // CHECK:STDERR: ^~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_bad_type.impl.carbon:[[@LINE-4]]:6: in import +// CHECK:STDERR: implicit.carbon:8:1: note: while deducing parameters of generic declared here +// CHECK:STDERR: class C(S:! {.a: i32, .b: i32}) {} +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: var c_bad: C({.c = 1, .d = 2}) = F(); @@ -430,9 +434,9 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: %default.import = import // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %C.ref: %C.type = name_ref C, imports.%import_ref.3 [template = constants.%C.1] -// CHECK:STDOUT: %.loc7_20: i32 = int_literal 1 [template = constants.%.5] -// CHECK:STDOUT: %.loc7_28: i32 = int_literal 2 [template = constants.%.6] -// CHECK:STDOUT: %.loc7_29: %.7 = struct_literal (%.loc7_20, %.loc7_28) +// CHECK:STDOUT: %.loc11_20: i32 = int_literal 1 [template = constants.%.5] +// CHECK:STDOUT: %.loc11_28: i32 = int_literal 2 [template = constants.%.6] +// CHECK:STDOUT: %.loc11_29: %.7 = struct_literal (%.loc11_20, %.loc11_28) // CHECK:STDOUT: %c_bad.var: ref = var c_bad // CHECK:STDOUT: %c_bad: ref = bind_name c_bad, %c_bad.var // CHECK:STDOUT: } @@ -454,8 +458,8 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %F.ref: %F.type = name_ref F, imports.%import_ref.4 [template = constants.%F] -// CHECK:STDOUT: %.loc7: ref %C.3 = temporary_storage -// CHECK:STDOUT: %F.call: init %C.3 = call %F.ref() to %.loc7 +// CHECK:STDOUT: %.loc11: ref %C.3 = temporary_storage +// CHECK:STDOUT: %F.call: init %C.3 = call %F.ref() to %.loc11 // CHECK:STDOUT: assign file.%c_bad.var, // CHECK:STDOUT: return // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/tuple/import.carbon b/toolchain/check/testdata/tuple/import.carbon index 06aaf181f73b..cb2a0d95fa03 100644 --- a/toolchain/check/testdata/tuple/import.carbon +++ b/toolchain/check/testdata/tuple/import.carbon @@ -31,9 +31,13 @@ var c: C((1, 2)) = F(); impl package Implicit; -// CHECK:STDERR: fail_bad_type.impl.carbon:[[@LINE+4]]:14: error: cannot initialize tuple of 2 elements from tuple with 3 elements +// CHECK:STDERR: fail_bad_type.impl.carbon:[[@LINE+8]]:14: error: cannot initialize tuple of 2 elements from tuple with 3 elements // CHECK:STDERR: var c_bad: C((1, 2, 3)) = F(); // CHECK:STDERR: ^~~~~~~~~ +// CHECK:STDERR: fail_bad_type.impl.carbon:[[@LINE-5]]:6: in import +// CHECK:STDERR: implicit.carbon:7:1: note: while deducing parameters of generic declared here +// CHECK:STDERR: class C(X:! (i32, i32)) {} +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: var c_bad: C((1, 2, 3)) = F(); @@ -470,10 +474,10 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: %default.import = import // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %C.ref: %C.type = name_ref C, imports.%import_ref.3 [template = constants.%C.1] -// CHECK:STDOUT: %.loc8_15: i32 = int_literal 1 [template = constants.%.5] -// CHECK:STDOUT: %.loc8_18: i32 = int_literal 2 [template = constants.%.6] -// CHECK:STDOUT: %.loc8_21: i32 = int_literal 3 [template = constants.%.7] -// CHECK:STDOUT: %.loc8_22: %.8 = tuple_literal (%.loc8_15, %.loc8_18, %.loc8_21) +// CHECK:STDOUT: %.loc12_15: i32 = int_literal 1 [template = constants.%.5] +// CHECK:STDOUT: %.loc12_18: i32 = int_literal 2 [template = constants.%.6] +// CHECK:STDOUT: %.loc12_21: i32 = int_literal 3 [template = constants.%.7] +// CHECK:STDOUT: %.loc12_22: %.8 = tuple_literal (%.loc12_15, %.loc12_18, %.loc12_21) // CHECK:STDOUT: %c_bad.var: ref = var c_bad // CHECK:STDOUT: %c_bad: ref = bind_name c_bad, %c_bad.var // CHECK:STDOUT: } @@ -495,8 +499,8 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %F.ref: %F.type = name_ref F, imports.%import_ref.4 [template = constants.%F] -// CHECK:STDOUT: %.loc8: ref %C.3 = temporary_storage -// CHECK:STDOUT: %F.call: init %C.3 = call %F.ref() to %.loc8 +// CHECK:STDOUT: %.loc12: ref %C.3 = temporary_storage +// CHECK:STDOUT: %F.call: init %C.3 = call %F.ref() to %.loc12 // CHECK:STDOUT: assign file.%c_bad.var, // CHECK:STDOUT: return // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/where_expr/constraints.carbon b/toolchain/check/testdata/where_expr/constraints.carbon index 13bda5e35afd..b77ce7af8b59 100644 --- a/toolchain/check/testdata/where_expr/constraints.carbon +++ b/toolchain/check/testdata/where_expr/constraints.carbon @@ -128,12 +128,16 @@ impl C as J {} // TODO: Should report that `C` does not meet the constraint. fn DoesNotImplI() { - // CHECK:STDERR: fail_todo_enforce_constraint.carbon:[[@LINE+7]]:3: error: cannot implicitly convert from `type` to `J` + // CHECK:STDERR: fail_todo_enforce_constraint.carbon:[[@LINE+11]]:3: error: cannot implicitly convert from `type` to `J` // CHECK:STDERR: Impls(C); // CHECK:STDERR: ^~~~~~ - // CHECK:STDERR: fail_todo_enforce_constraint.carbon:[[@LINE+4]]:3: note: type `type` does not implement interface `ImplicitAs` + // CHECK:STDERR: fail_todo_enforce_constraint.carbon:[[@LINE+8]]:3: note: type `type` does not implement interface `ImplicitAs` // CHECK:STDERR: Impls(C); // CHECK:STDERR: ^~~~~~ + // CHECK:STDERR: fail_todo_enforce_constraint.carbon:[[@LINE-14]]:1: in import + // CHECK:STDERR: state_constraints.carbon:13:1: note: while deducing parameters of generic declared here + // CHECK:STDERR: fn Impls(V:! J where .Self impls I); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: Impls(C); } @@ -142,12 +146,15 @@ fn EmptyStruct(Y:! J where .Self == {}); // TODO: Should report that `C` does not meeet the constraint. fn NotEmptyStruct() { - // CHECK:STDERR: fail_todo_enforce_constraint.carbon:[[@LINE+6]]:3: error: cannot implicitly convert from `type` to `J` + // CHECK:STDERR: fail_todo_enforce_constraint.carbon:[[@LINE+9]]:3: error: cannot implicitly convert from `type` to `J` // CHECK:STDERR: EmptyStruct(C); // CHECK:STDERR: ^~~~~~~~~~~~ - // CHECK:STDERR: fail_todo_enforce_constraint.carbon:[[@LINE+3]]:3: note: type `type` does not implement interface `ImplicitAs` + // CHECK:STDERR: fail_todo_enforce_constraint.carbon:[[@LINE+6]]:3: note: type `type` does not implement interface `ImplicitAs` // CHECK:STDERR: EmptyStruct(C); // CHECK:STDERR: ^~~~~~~~~~~~ + // CHECK:STDERR: fail_todo_enforce_constraint.carbon:[[@LINE-10]]:1: note: while deducing parameters of generic declared here + // CHECK:STDERR: fn EmptyStruct(Y:! J where .Self == {}); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EmptyStruct(C); } @@ -1305,18 +1312,18 @@ fn NotEmptyStruct() { // CHECK:STDOUT: } // CHECK:STDOUT: %DoesNotImplI.decl: %DoesNotImplI.type = fn_decl @DoesNotImplI [template = constants.%DoesNotImplI] {} {} // CHECK:STDOUT: %EmptyStruct.decl: %EmptyStruct.type = fn_decl @EmptyStruct [template = constants.%EmptyStruct] { -// CHECK:STDOUT: %Y.patt.loc22_16.1: %J.type = symbolic_binding_pattern Y, 0 [symbolic = %Y.patt.loc22_16.2 (constants.%Y.patt)] -// CHECK:STDOUT: %Y.param_patt: %J.type = param_pattern %Y.patt.loc22_16.1, runtime_param [symbolic = %Y.patt.loc22_16.2 (constants.%Y.patt)] +// CHECK:STDOUT: %Y.patt.loc26_16.1: %J.type = symbolic_binding_pattern Y, 0 [symbolic = %Y.patt.loc26_16.2 (constants.%Y.patt)] +// CHECK:STDOUT: %Y.param_patt: %J.type = param_pattern %Y.patt.loc26_16.1, runtime_param [symbolic = %Y.patt.loc26_16.2 (constants.%Y.patt)] // CHECK:STDOUT: } { // CHECK:STDOUT: %J.ref: type = name_ref J, imports.%import_ref.1 [template = constants.%J.type] // CHECK:STDOUT: %.Self: %J.type = bind_symbolic_name .Self, 0 [symbolic = constants.%.Self] // CHECK:STDOUT: %.Self.ref: %J.type = name_ref .Self, %.Self [symbolic = constants.%.Self] -// CHECK:STDOUT: %.loc22_38: %.1 = struct_literal () -// CHECK:STDOUT: %.loc22_22: type = where_expr %.Self [template = constants.%J.type] { -// CHECK:STDOUT: requirement_equivalent %.Self.ref, %.loc22_38 +// CHECK:STDOUT: %.loc26_38: %.1 = struct_literal () +// CHECK:STDOUT: %.loc26_22: type = where_expr %.Self [template = constants.%J.type] { +// CHECK:STDOUT: requirement_equivalent %.Self.ref, %.loc26_38 // CHECK:STDOUT: } // CHECK:STDOUT: %param: %J.type = param runtime_param -// CHECK:STDOUT: %Y.loc22_16.1: %J.type = bind_symbolic_name Y, 0, %param [symbolic = %Y.loc22_16.2 (constants.%Y)] +// CHECK:STDOUT: %Y.loc26_16.1: %J.type = bind_symbolic_name Y, 0, %param [symbolic = %Y.loc26_16.2 (constants.%Y)] // CHECK:STDOUT: } // CHECK:STDOUT: %NotEmptyStruct.decl: %NotEmptyStruct.type = fn_decl @NotEmptyStruct [template = constants.%NotEmptyStruct] {} {} // CHECK:STDOUT: } @@ -1366,9 +1373,9 @@ fn NotEmptyStruct() { // CHECK:STDOUT: %Impls.ref: %Impls.type = name_ref Impls, imports.%import_ref.4 [template = constants.%Impls] // CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] // CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(constants.%J.type) [template = constants.%ImplicitAs.type.3] -// CHECK:STDOUT: %.loc19_8.1: %.7 = specific_constant imports.%import_ref.9, @ImplicitAs(constants.%J.type) [template = constants.%.8] -// CHECK:STDOUT: %Convert.ref: %.7 = name_ref Convert, %.loc19_8.1 [template = constants.%.8] -// CHECK:STDOUT: %.loc19_8.2: %J.type = converted %C.ref, [template = ] +// CHECK:STDOUT: %.loc23_8.1: %.7 = specific_constant imports.%import_ref.9, @ImplicitAs(constants.%J.type) [template = constants.%.8] +// CHECK:STDOUT: %Convert.ref: %.7 = name_ref Convert, %.loc23_8.1 [template = constants.%.8] +// CHECK:STDOUT: %.loc23_8.2: %J.type = converted %C.ref, [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: @@ -1387,9 +1394,9 @@ fn NotEmptyStruct() { // CHECK:STDOUT: fn[%self.param_patt: @Convert.%Self (%Self.3)]() -> @Convert.%Dest (%Dest); // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: generic fn @EmptyStruct(%Y.loc22_16.1: %J.type) { -// CHECK:STDOUT: %Y.loc22_16.2: %J.type = bind_symbolic_name Y, 0 [symbolic = %Y.loc22_16.2 (constants.%Y)] -// CHECK:STDOUT: %Y.patt.loc22_16.2: %J.type = symbolic_binding_pattern Y, 0 [symbolic = %Y.patt.loc22_16.2 (constants.%Y.patt)] +// CHECK:STDOUT: generic fn @EmptyStruct(%Y.loc26_16.1: %J.type) { +// CHECK:STDOUT: %Y.loc26_16.2: %J.type = bind_symbolic_name Y, 0 [symbolic = %Y.loc26_16.2 (constants.%Y)] +// CHECK:STDOUT: %Y.patt.loc26_16.2: %J.type = symbolic_binding_pattern Y, 0 [symbolic = %Y.patt.loc26_16.2 (constants.%Y.patt)] // CHECK:STDOUT: // CHECK:STDOUT: fn(%Y.param_patt: %J.type); // CHECK:STDOUT: } @@ -1399,9 +1406,9 @@ fn NotEmptyStruct() { // CHECK:STDOUT: %EmptyStruct.ref: %EmptyStruct.type = name_ref EmptyStruct, file.%EmptyStruct.decl [template = constants.%EmptyStruct] // CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] // CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(constants.%J.type) [template = constants.%ImplicitAs.type.3] -// CHECK:STDOUT: %.loc32_14.1: %.7 = specific_constant imports.%import_ref.9, @ImplicitAs(constants.%J.type) [template = constants.%.8] -// CHECK:STDOUT: %Convert.ref: %.7 = name_ref Convert, %.loc32_14.1 [template = constants.%.8] -// CHECK:STDOUT: %.loc32_14.2: %J.type = converted %C.ref, [template = ] +// CHECK:STDOUT: %.loc39_14.1: %.7 = specific_constant imports.%import_ref.9, @ImplicitAs(constants.%J.type) [template = constants.%.8] +// CHECK:STDOUT: %Convert.ref: %.7 = name_ref Convert, %.loc39_14.1 [template = constants.%.8] +// CHECK:STDOUT: %.loc39_14.2: %J.type = converted %C.ref, [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: @@ -1445,7 +1452,7 @@ fn NotEmptyStruct() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @EmptyStruct(constants.%Y) { -// CHECK:STDOUT: %Y.loc22_16.2 => constants.%Y -// CHECK:STDOUT: %Y.patt.loc22_16.2 => constants.%Y +// CHECK:STDOUT: %Y.loc26_16.2 => constants.%Y +// CHECK:STDOUT: %Y.patt.loc26_16.2 => constants.%Y // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index 36a9594ecfba..92321735454d 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -228,6 +228,7 @@ CARBON_DIAGNOSTIC_KIND(DeductionIncomplete) CARBON_DIAGNOSTIC_KIND(DeductionInconsistent) CARBON_DIAGNOSTIC_KIND(DeductionGenericHere) CARBON_DIAGNOSTIC_KIND(InitializingGenericParam) +CARBON_DIAGNOSTIC_KIND(CompTimeArgumentNotConstant) // Export checking. CARBON_DIAGNOSTIC_KIND(ExportNotImportedEntity)