Repository: carbon-language/carbon-lang
File: toolchain/check/handle_impl.cpp (C++)

Code before:
        }
      } else if (self_type.type_id != SemIR::ErrorInst::TypeId) {
        // Otherwise, the self-type is an error.
        diag.Emit();
        class_scope->name_scope->set_has_error();
        self_type.inst_id = SemIR::ErrorInst::TypeInstId;
      }
    }
  }

  // Introduce `Self`. Note that we add this name lexically rather than adding
  // to the `NameScopeId` of the `impl`, because this happens before we enter
  // the `impl` scope or even identify which `impl` we're declaring.
  // TODO: Revisit this once #3714 is resolved.
  AddNameToLookup(context, SemIR::NameId::SelfType, self_type.inst_id);
  context.node_stack().Push(node_id, self_type.inst_id);
  return true;
}

auto HandleParseNode(Context& context, Parse::ImplDefaultSelfAsId node_id)
    -> bool {
  auto self_inst_id = SemIR::TypeInstId::None;

  auto class_scope =
      TryAsClassScope(context, context.decl_name_stack().PeekParentScopeId());
  if (class_scope) {
    auto self_type_id = GetImplDefaultSelfType(context, *class_scope);
    // Build the implicit access to the enclosing `Self`.
    // TODO: Consider calling `HandleNameAsExpr` to build this implicit `Self`
    // expression. We've already done the work to check that the enclosing
    // context is a class and found its `Self`, so additionally performing an
    // unqualified name lookup would be redundant work, but would avoid
    // duplicating the handling of the `Self` expression.
    self_inst_id = AddTypeInst(
        context, node_id,
        SemIR::NameRef{.type_id = SemIR::TypeType::TypeId,
                       .name_id = SemIR::NameId::SelfType,
                       .value_id = context.types().GetInstId(self_type_id)});
  } else {
    CARBON_DIAGNOSTIC(ImplAsOutsideClass, Error,
                      "`impl as` can only be used in a class");
    context.emitter().Emit(node_id, ImplAsOutsideClass);
    self_inst_id = SemIR::ErrorInst::TypeInstId;
  }

  // There's no need to push `Self` into scope here, because we can find it in
  // the parent class scope.
  context.node_stack().Push(node_id, self_inst_id);
  return true;
}


Review comment (suggestion):
```suggestion
  if (auto class_scope =
          TryAsClassScope(context, context.decl_name_stack().PeekParentScopeId())) {
```

Code after:
      } else if (self_type.type_id != SemIR::ErrorInst::TypeId) {
        // Otherwise, the self-type is an error.
        diag.Emit();
        class_scope->name_scope->set_has_error();
        self_type.inst_id = SemIR::ErrorInst::TypeInstId;
      }
    }
  }

  // Introduce `Self`. Note that we add this name lexically rather than adding
  // to the `NameScopeId` of the `impl`, because this happens before we enter
  // the `impl` scope or even identify which `impl` we're declaring.
  // TODO: Revisit this once #3714 is resolved.
  AddNameToLookup(context, SemIR::NameId::SelfType, self_type.inst_id);
  context.node_stack().Push(node_id, self_type.inst_id);
  return true;
}

auto HandleParseNode(Context& context, Parse::ImplDefaultSelfAsId node_id)
    -> bool {
  auto self_inst_id = SemIR::TypeInstId::None;

  if (auto class_scope = TryAsClassScope(
          context, context.decl_name_stack().PeekParentScopeId())) {
    auto self_type_id = GetImplDefaultSelfType(context, *class_scope);
    // Build the implicit access to the enclosing `Self`.
    // TODO: Consider calling `HandleNameAsExpr` to build this implicit `Self`
    // expression. We've already done the work to check that the enclosing
    // context is a class and found its `Self`, so additionally performing an
    // unqualified name lookup would be redundant work, but would avoid
    // duplicating the handling of the `Self` expression.
    self_inst_id = AddTypeInst(
        context, node_id,
        SemIR::NameRef{.type_id = SemIR::TypeType::TypeId,
                       .name_id = SemIR::NameId::SelfType,
                       .value_id = context.types().GetInstId(self_type_id)});
  } else {
    CARBON_DIAGNOSTIC(ImplAsOutsideClass, Error,
                      "`impl as` can only be used in a class");
    context.emitter().Emit(node_id, ImplAsOutsideClass);
    self_inst_id = SemIR::ErrorInst::TypeInstId;
  }

  // There's no need to push `Self` into scope here, because we can find it in
  // the parent class scope.
  context.node_stack().Push(node_id, self_inst_id);
  return true;
}

// Pops the parameters of an `impl`, forming a `NameComponent` with no
// associated name that describes them.