mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Properly diagnose ambiguous .Self in T impls X where... (#7132)
A `where` expression nested inside a `T impls X` constraint makes `.Self` ambiguous on the right-hand side of the `where` if `T` is anything other than `.Self`. After the `where`, the value of a `.Self` could be `T` or could be the value of `.Self` before the `impls` constraint: the so-called top-level value of `.Self`. Implicit use of `.Self` in designators is always allowed, and they are bound (and replaced by a reference) to the inner-most possible value of `.Self`. On the right-hand side of the nested `where` above, they have the value `T as X`. `.Self impls ...` is also always allowed, since it acts more as a keyword here, and it always refers to the inner-most possible value of `.Self`. Any other explicit use of `.Self` is diagnosed when ambiguous, in any kind of constraint. This is done in the handling of `WhereExpr` since it has enough context to allow `.Self impls` (which is an explicit use) while disallowing other explicit uses. And because it has non-canonical instructions to work with, so it is able to diagnose errors with precise locations. Since `.Self` is no longer going to be marked with depth modifiers, the eval of `WhereExpr` does not need an input facet value instruction representing `.Self` to compare with, as they are now going to all be equivalent. So revert it back to just looking for the `PeriodSelf` name id, through a shared helper being introduced as `IsPeriodSelf`. And drop the period self InstId from the `WhereExpr` instruction. This causes most of the formatted SemIR changes. Move helpers for working with and replacing `.Self` to their own file, out of the `facet_type.h` header/cpp files. These are working with `.Self` facet values more than facet types, though `.Self` is a name that only exists inside the scope of a facet type.
This commit is contained in:
@@ -80,8 +80,8 @@ let U: (type where .Self impls type).missing = {};
|
||||
// CHECK:STDOUT: %.loc8_32: type = type_literal type [concrete = type]
|
||||
// CHECK:STDOUT: %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type]
|
||||
// CHECK:STDOUT: %.loc8_20: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
|
||||
// CHECK:STDOUT: %.loc8_14: type = where_expr %.Self [concrete = constants.%type] {
|
||||
// CHECK:STDOUT: requirement_base_facet_type type
|
||||
// CHECK:STDOUT: %.loc8_14: type = where_expr [concrete = constants.%type] {
|
||||
// CHECK:STDOUT: requirement_base_facet_type %.loc8_9
|
||||
// CHECK:STDOUT: requirement_impls %.loc8_20, %.loc8_32
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %missing.ref: <error> = name_ref missing, <error> [concrete = <error>]
|
||||
|
||||
+2
-2
@@ -174,8 +174,8 @@ interface A(T:! type) {
|
||||
// CHECK:STDOUT: %impl.elem0: %C = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
|
||||
// CHECK:STDOUT: %.loc16_27: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
|
||||
// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
|
||||
// CHECK:STDOUT: %.loc16_14: type = where_expr %.Self [concrete = <error>] {
|
||||
// CHECK:STDOUT: requirement_base_facet_type constants.%I.type
|
||||
// CHECK:STDOUT: %.loc16_14: type = where_expr [concrete = <error>] {
|
||||
// CHECK:STDOUT: requirement_base_facet_type %I.ref
|
||||
// CHECK:STDOUT: requirement_rewrite %impl.elem0, <error>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
|
||||
+4
-4
@@ -714,8 +714,8 @@ interface Z(T:! type) {
|
||||
// CHECK:STDOUT: %impl.elem0: type = impl_witness_access constants.%Y.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
|
||||
// CHECK:STDOUT: %.loc7_32.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
|
||||
// CHECK:STDOUT: %.loc7_32.2: type = converted %.loc7_32.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
|
||||
// CHECK:STDOUT: %.loc7_19: type = where_expr %.Self [concrete = constants.%Y_where.type] {
|
||||
// CHECK:STDOUT: requirement_base_facet_type constants.%Y.type
|
||||
// CHECK:STDOUT: %.loc7_19: type = where_expr [concrete = constants.%Y_where.type] {
|
||||
// CHECK:STDOUT: requirement_base_facet_type %Y.ref
|
||||
// CHECK:STDOUT: requirement_rewrite %impl.elem0, %.loc7_32.2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
@@ -873,8 +873,8 @@ interface Z(T:! type) {
|
||||
// CHECK:STDOUT: %Self.ref: %Z.type = name_ref Self, @Z.%Self [symbolic = %Self (constants.%Self.c59)]
|
||||
// CHECK:STDOUT: %Self.as_type.loc10_31: type = facet_access_type %Self.ref [symbolic = %Self.as_type.loc10_11.2 (constants.%Self.as_type)]
|
||||
// CHECK:STDOUT: %.loc10_31: type = converted %Self.ref, %Self.as_type.loc10_31 [symbolic = %Self.as_type.loc10_11.2 (constants.%Self.as_type)]
|
||||
// CHECK:STDOUT: %.loc10_19: type = where_expr %.Self [symbolic = %Y_where.type (constants.%Y_where.type)] {
|
||||
// CHECK:STDOUT: requirement_base_facet_type constants.%Y.type
|
||||
// CHECK:STDOUT: %.loc10_19: type = where_expr [symbolic = %Y_where.type (constants.%Y_where.type)] {
|
||||
// CHECK:STDOUT: requirement_base_facet_type %Y.ref
|
||||
// CHECK:STDOUT: requirement_rewrite %impl.elem0, %.loc10_31
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
|
||||
Reference in New Issue
Block a user