function.cpp 4.9 KB

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