4
4
5
5
#include " toolchain/check/function.h"
6
6
7
+ #include " toolchain/check/subst.h"
8
+
7
9
namespace Carbon ::Check {
8
10
9
11
// Returns true if there was an error in declaring the function, which will have
@@ -31,7 +33,8 @@ static auto CheckRedeclParam(Context& context,
31
33
llvm::StringLiteral param_diag_label,
32
34
int32_t param_index,
33
35
SemIR::InstId new_param_ref_id,
34
- SemIR::InstId prev_param_ref_id) -> bool {
36
+ SemIR::InstId prev_param_ref_id,
37
+ Substitutions substitutions) -> bool {
35
38
// TODO: Consider differentiating between type and name mistakes. For now,
36
39
// taking the simpler approach because I also think we may want to refactor
37
40
// params.
@@ -52,7 +55,8 @@ static auto CheckRedeclParam(Context& context,
52
55
auto new_param_ref = context.insts ().Get (new_param_ref_id);
53
56
auto prev_param_ref = context.insts ().Get (prev_param_ref_id);
54
57
if (new_param_ref.kind () != prev_param_ref.kind () ||
55
- new_param_ref.type_id () != prev_param_ref.type_id ()) {
58
+ new_param_ref.type_id () !=
59
+ SubstType (context, prev_param_ref.type_id (), substitutions)) {
56
60
diagnose ();
57
61
return false ;
58
62
}
@@ -90,7 +94,8 @@ static auto CheckRedeclParams(Context& context, SemIR::InstId new_decl_id,
90
94
SemIR::InstBlockId new_param_refs_id,
91
95
SemIR::InstId prev_decl_id,
92
96
SemIR::InstBlockId prev_param_refs_id,
93
- llvm::StringLiteral param_diag_label) -> bool {
97
+ llvm::StringLiteral param_diag_label,
98
+ Substitutions substitutions) -> bool {
94
99
// This will often occur for empty params.
95
100
if (new_param_refs_id == prev_param_refs_id) {
96
101
return true ;
@@ -116,7 +121,7 @@ static auto CheckRedeclParams(Context& context, SemIR::InstId new_decl_id,
116
121
for (auto [index, new_param_ref_id, prev_param_ref_id] :
117
122
llvm::enumerate (new_param_ref_ids, prev_param_ref_ids)) {
118
123
if (!CheckRedeclParam (context, param_diag_label, index, new_param_ref_id,
119
- prev_param_ref_id)) {
124
+ prev_param_ref_id, substitutions )) {
120
125
return false ;
121
126
}
122
127
}
@@ -125,21 +130,26 @@ static auto CheckRedeclParams(Context& context, SemIR::InstId new_decl_id,
125
130
126
131
// Returns false if the provided function declarations differ.
127
132
static auto CheckRedecl (Context& context, const SemIR::Function& new_function,
128
- const SemIR::Function& prev_function) -> bool {
133
+ const SemIR::Function& prev_function,
134
+ Substitutions substitutions) -> bool {
129
135
if (FunctionDeclHasError (context, new_function) ||
130
136
FunctionDeclHasError (context, prev_function)) {
131
137
return false ;
132
138
}
133
- if (!CheckRedeclParams (context, new_function. decl_id ,
134
- new_function.implicit_param_refs_id ,
135
- prev_function.decl_id ,
136
- prev_function. implicit_param_refs_id , " implicit " ) ||
139
+ if (!CheckRedeclParams (
140
+ context, new_function. decl_id , new_function.implicit_param_refs_id ,
141
+ prev_function.decl_id , prev_function. implicit_param_refs_id ,
142
+ " implicit " , substitutions ) ||
137
143
!CheckRedeclParams (context, new_function.decl_id ,
138
144
new_function.param_refs_id , prev_function.decl_id ,
139
- prev_function.param_refs_id , " " )) {
145
+ prev_function.param_refs_id , " " , substitutions )) {
140
146
return false ;
141
147
}
142
- if (new_function.return_type_id != prev_function.return_type_id ) {
148
+ auto prev_return_type_id =
149
+ prev_function.return_type_id .is_valid ()
150
+ ? SubstType (context, prev_function.return_type_id , substitutions)
151
+ : SemIR::TypeId::Invalid;
152
+ if (new_function.return_type_id != prev_return_type_id) {
143
153
CARBON_DIAGNOSTIC (
144
154
FunctionRedeclReturnTypeDiffers, Error,
145
155
" Function redeclaration differs because return type is `{0}`." ,
@@ -154,12 +164,12 @@ static auto CheckRedecl(Context& context, const SemIR::Function& new_function,
154
164
new_function.return_type_id )
155
165
: context.emitter ().Build (new_function.decl_id ,
156
166
FunctionRedeclReturnTypeDiffersNoReturn);
157
- if (prev_function. return_type_id .is_valid ()) {
167
+ if (prev_return_type_id .is_valid ()) {
158
168
CARBON_DIAGNOSTIC (FunctionRedeclReturnTypePrevious, Note,
159
169
" Previously declared with return type `{0}`." ,
160
170
SemIR::TypeId);
161
171
diag.Note (prev_function.decl_id , FunctionRedeclReturnTypePrevious,
162
- prev_function. return_type_id );
172
+ prev_return_type_id );
163
173
} else {
164
174
CARBON_DIAGNOSTIC (FunctionRedeclReturnTypePreviousNoReturn, Note,
165
175
" Previously declared with no return type." );
@@ -173,10 +183,12 @@ static auto CheckRedecl(Context& context, const SemIR::Function& new_function,
173
183
return true ;
174
184
}
175
185
176
- auto CheckFunctionRedecl (Context& context, SemIR::FunctionId new_function_id,
177
- SemIR::FunctionId prev_function_id) -> bool {
186
+ auto CheckFunctionTypeMatches (Context& context,
187
+ SemIR::FunctionId new_function_id,
188
+ SemIR::FunctionId prev_function_id,
189
+ Substitutions substitutions) -> bool {
178
190
return CheckRedecl (context, context.functions ().Get (new_function_id),
179
- context.functions ().Get (prev_function_id));
191
+ context.functions ().Get (prev_function_id), substitutions );
180
192
}
181
193
182
194
auto MergeFunctionRedecl (Context& context, Parse::NodeId node_id,
@@ -186,7 +198,7 @@ auto MergeFunctionRedecl(Context& context, Parse::NodeId node_id,
186
198
auto & prev_function = context.functions ().Get (prev_function_id);
187
199
188
200
// TODO: Disallow redeclarations within classes?
189
- if (!CheckRedecl (context, new_function, prev_function)) {
201
+ if (!CheckRedecl (context, new_function, prev_function, {} )) {
190
202
return false ;
191
203
}
192
204
0 commit comments