function.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "toolchain/check/function.h"
  5. #include "toolchain/check/merge.h"
  6. #include "toolchain/check/type_completion.h"
  7. #include "toolchain/sem_ir/ids.h"
  8. namespace Carbon::Check {
  9. auto CheckFunctionTypeMatches(Context& context,
  10. const SemIR::Function& new_function,
  11. const SemIR::Function& prev_function,
  12. SemIR::SpecificId prev_specific_id,
  13. bool check_syntax, bool check_self) -> bool {
  14. // TODO: When check_syntax is false, the functions should be allowed to have
  15. // different signatures as long as we can synthesize a suitable thunk. i.e.,
  16. // when there's an implicit conversion from the original parameter types to
  17. // the overriding parameter types, and from the overriding return type to the
  18. // original return type.
  19. // Also, build that thunk.
  20. if (!CheckRedeclParamsMatch(context, DeclParams(new_function),
  21. DeclParams(prev_function), prev_specific_id,
  22. /*diagnose=*/true, check_syntax, check_self)) {
  23. return false;
  24. }
  25. // TODO: Pass a specific ID for `prev_function` instead of substitutions and
  26. // use it here.
  27. auto new_return_type_id =
  28. new_function.GetDeclaredReturnType(context.sem_ir());
  29. auto prev_return_type_id =
  30. prev_function.GetDeclaredReturnType(context.sem_ir(), prev_specific_id);
  31. if (new_return_type_id == SemIR::ErrorInst::TypeId ||
  32. prev_return_type_id == SemIR::ErrorInst::TypeId) {
  33. return false;
  34. }
  35. if (!context.types().AreEqualAcrossDeclarations(new_return_type_id,
  36. prev_return_type_id)) {
  37. CARBON_DIAGNOSTIC(
  38. FunctionRedeclReturnTypeDiffers, Error,
  39. "function redeclaration differs because return type is {0}",
  40. SemIR::TypeId);
  41. CARBON_DIAGNOSTIC(
  42. FunctionRedeclReturnTypeDiffersNoReturn, Error,
  43. "function redeclaration differs because no return type is provided");
  44. auto diag =
  45. new_return_type_id.has_value()
  46. ? context.emitter().Build(new_function.latest_decl_id(),
  47. FunctionRedeclReturnTypeDiffers,
  48. new_return_type_id)
  49. : context.emitter().Build(new_function.latest_decl_id(),
  50. FunctionRedeclReturnTypeDiffersNoReturn);
  51. if (prev_return_type_id.has_value()) {
  52. CARBON_DIAGNOSTIC(FunctionRedeclReturnTypePrevious, Note,
  53. "previously declared with return type {0}",
  54. SemIR::TypeId);
  55. diag.Note(prev_function.latest_decl_id(),
  56. FunctionRedeclReturnTypePrevious, prev_return_type_id);
  57. } else {
  58. CARBON_DIAGNOSTIC(FunctionRedeclReturnTypePreviousNoReturn, Note,
  59. "previously declared with no return type");
  60. diag.Note(prev_function.latest_decl_id(),
  61. FunctionRedeclReturnTypePreviousNoReturn);
  62. }
  63. diag.Emit();
  64. return false;
  65. }
  66. return true;
  67. }
  68. auto CheckFunctionReturnType(Context& context, SemIR::LocId loc_id,
  69. const SemIR::Function& function,
  70. SemIR::SpecificId specific_id)
  71. -> SemIR::ReturnTypeInfo {
  72. auto return_info = SemIR::ReturnTypeInfo::ForFunction(context.sem_ir(),
  73. function, specific_id);
  74. // If we couldn't determine the return information due to the return type
  75. // being incomplete, try to complete it now.
  76. if (return_info.init_repr.kind == SemIR::InitRepr::Incomplete) {
  77. auto diagnose_incomplete_return_type = [&] {
  78. CARBON_DIAGNOSTIC(IncompleteTypeInFunctionReturnType, Error,
  79. "function returns incomplete type {0}", SemIR::TypeId);
  80. return context.emitter().Build(loc_id, IncompleteTypeInFunctionReturnType,
  81. return_info.type_id);
  82. };
  83. auto diagnose_abstract_return_type = [&] {
  84. CARBON_DIAGNOSTIC(AbstractTypeInFunctionReturnType, Error,
  85. "function returns abstract type {0}", SemIR::TypeId);
  86. return context.emitter().Build(loc_id, AbstractTypeInFunctionReturnType,
  87. return_info.type_id);
  88. };
  89. // TODO: Consider suppressing the diagnostic if we've already diagnosed a
  90. // definition or call to this function.
  91. if (RequireConcreteType(context, return_info.type_id, loc_id,
  92. diagnose_incomplete_return_type,
  93. diagnose_abstract_return_type)) {
  94. return_info = SemIR::ReturnTypeInfo::ForFunction(context.sem_ir(),
  95. function, specific_id);
  96. }
  97. }
  98. return return_info;
  99. }
  100. } // namespace Carbon::Check