diff --git a/toolchain/check/name_lookup.cpp b/toolchain/check/name_lookup.cpp index 571a2c174568..036cd3cd49e6 100644 --- a/toolchain/check/name_lookup.cpp +++ b/toolchain/check/name_lookup.cpp @@ -21,6 +21,7 @@ #include "toolchain/sem_ir/generic.h" #include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/name_scope.h" +#include "toolchain/sem_ir/typed_insts.h" namespace Carbon::Check { @@ -323,15 +324,16 @@ auto AppendLookupScopesForConstant(Context& context, SemIR::LocId loc_id, llvm::SmallVector* scopes) -> bool { auto lookup_inst_id = context.constant_values().GetInstId(lookup_const_id); - auto lookup = context.insts().Get(lookup_inst_id); - if (auto ns = lookup.TryAs()) { + if (auto ns = context.insts().TryGetAs(lookup_inst_id)) { scopes->push_back(LookupScope{.name_scope_id = ns->name_scope_id, .specific_id = SemIR::SpecificId::None, .self_const_id = SemIR::ConstantId::None}); return true; } - if (auto class_ty = lookup.TryAs()) { + + if (auto class_ty = + context.insts().TryGetAs(lookup_inst_id)) { if (!extended_scope) { // TODO: Allow name lookup into classes that are being defined even if // they are not complete. @@ -351,8 +353,14 @@ auto AppendLookupScopesForConstant(Context& context, SemIR::LocId loc_id, .self_const_id = self_type_const_id}); return true; } - // Extended scopes may point to a FacetType. - if (auto facet_type = lookup.TryAs()) { + + // Extended scopes may point to a FacetType. If it has constraints, collect + // the extended ones as scopes. + auto lookup_type_id = + context.types().TryGetTypeIdForTypeInstId(lookup_inst_id); + if (lookup_type_id.has_value() && + context.types().IsConstrainedFacetType(lookup_type_id)) { + auto facet_type = context.types().GetAs(lookup_type_id); if (!extended_scope) { // TODO: Allow name lookup into facet types that are being defined even if // they are not complete. @@ -378,7 +386,7 @@ auto AppendLookupScopesForConstant(Context& context, SemIR::LocId loc_id, } auto declared_facet_type = - context.declared_facet_types().Get(facet_type->declared_facet_type_id); + context.declared_facet_types().Get(facet_type.declared_facet_type_id); // Name lookup into "extend" constraints but not "self impls" constraints. for (const auto& extend : declared_facet_type.extend_constraints) { auto& interface = context.interfaces().Get(extend.interface_id); @@ -413,6 +421,7 @@ auto AppendLookupScopesForConstant(Context& context, SemIR::LocId loc_id, } return true; } + if (lookup_const_id == SemIR::ErrorInst::ConstantId) { // Lookup into this scope should fail without producing an error. scopes->push_back(LookupScope{.name_scope_id = SemIR::NameScopeId::None, @@ -420,6 +429,7 @@ auto AppendLookupScopesForConstant(Context& context, SemIR::LocId loc_id, .self_const_id = SemIR::ConstantId::None}); return true; } + // TODO: Per the design, if `base_id` is any kind of type, then lookup should // treat it as a name scope, even if it doesn't have members. For example, // `(i32*).X` should fail because there's no name `X` in `i32*`, not because diff --git a/toolchain/check/testdata/facet/aggregate_through_access.carbon b/toolchain/check/testdata/facet/aggregate_through_access.carbon index f9292742f8da..280e30e9c06b 100644 --- a/toolchain/check/testdata/facet/aggregate_through_access.carbon +++ b/toolchain/check/testdata/facet/aggregate_through_access.carbon @@ -32,7 +32,7 @@ interface Z { let X: type; } -// CHECK:STDERR: fail_todo_struct_access_through_witness.carbon:[[@LINE+4]]:43: error: member name `t` not found [MemberNameNotFound] +// CHECK:STDERR: fail_todo_struct_access_through_witness.carbon:[[@LINE+4]]:43: error: type `type` does not support qualified expressions [QualifiedExprUnsupported] // CHECK:STDERR: fn F(generic T: Z where .X = {.t: ()}) -> T.X.t { // CHECK:STDERR: ^~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/facet/runtime_value.carbon b/toolchain/check/testdata/facet/runtime_value.carbon index d56fa28a0ea0..54bfb7bfb7b7 100644 --- a/toolchain/check/testdata/facet/runtime_value.carbon +++ b/toolchain/check/testdata/facet/runtime_value.carbon @@ -148,7 +148,7 @@ fn F(T: Z) { library "[[@TEST_NAME]]"; fn F(T: type) { - // CHECK:STDERR: fail_member_access_runtime_type.carbon:[[@LINE+4]]:3: error: member name `G` not found [MemberNameNotFound] + // CHECK:STDERR: fail_member_access_runtime_type.carbon:[[@LINE+4]]:3: error: type `type` does not support qualified expressions [QualifiedExprUnsupported] // CHECK:STDERR: T.G(); // CHECK:STDERR: ^~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/interface/fail_lookup_in_type_type.carbon b/toolchain/check/testdata/interface/fail_lookup_in_type_type.carbon index 378e7e6ba47b..34a2cbbc6029 100644 --- a/toolchain/check/testdata/interface/fail_lookup_in_type_type.carbon +++ b/toolchain/check/testdata/interface/fail_lookup_in_type_type.carbon @@ -16,7 +16,7 @@ library "[[@TEST_NAME]]"; -// CHECK:STDERR: fail_lookup_in_type.carbon:[[@LINE+4]]:8: error: member name `not_found` not found [MemberNameNotFound] +// CHECK:STDERR: fail_lookup_in_type.carbon:[[@LINE+4]]:8: error: type `type` does not support qualified expressions [QualifiedExprUnsupported] // CHECK:STDERR: let T: type.not_found = {}; // CHECK:STDERR: ^~~~~~~~~~~~~~ // CHECK:STDERR: @@ -26,7 +26,7 @@ let T: type.not_found = {}; library "[[@TEST_NAME]]"; -// CHECK:STDERR: fail_lookup_type_where.carbon:[[@LINE+4]]:8: error: member name `missing` not found [MemberNameNotFound] +// CHECK:STDERR: fail_lookup_type_where.carbon:[[@LINE+4]]:8: error: type `type` does not support qualified expressions [QualifiedExprUnsupported] // CHECK:STDERR: let U: (type where .Self impls type).missing = {}; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -44,10 +44,7 @@ let U: (type where .Self impls type).missing = {}; // CHECK:STDOUT: package: = namespace [concrete] { // CHECK:STDOUT: .T = %T // CHECK:STDOUT: } -// CHECK:STDOUT: %.1: = splice_block [concrete = ] { -// CHECK:STDOUT: %.loc8: type = type_literal type [concrete = type] -// CHECK:STDOUT: %not_found.ref: = name_ref not_found, [concrete = ] -// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc8: type = type_literal type [concrete = type] // CHECK:STDOUT: %T: = wrapper_binding T, [concrete = ] // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %T.patt: = value_binding_pattern T [concrete = ] @@ -88,7 +85,6 @@ let U: (type where .Self impls type).missing = {}; // CHECK:STDOUT: %base_facet_type = requirement_base_facet_type %.loc8_9 [concrete] // CHECK:STDOUT: %impls.loc8_26.2 = requirement_impls %.Self.ref.loc8_20.2, %.loc8_32 [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %missing.ref: = name_ref missing, [concrete = ] // CHECK:STDOUT: } // CHECK:STDOUT: %U: = wrapper_binding U, [concrete = ] // CHECK:STDOUT: name_binding_decl {