Skip to content

Commit 76e407a

Browse files
authored
Refactor TypeCheckContext::scoped to take a closure (#5592)
## Description This PR refactors the interface for changing the namespace in a type checking context. This change is preparatory work for the collecting context work and will be used in upcoming PRs. No functional changes intended. ## Checklist - [x] I have linked to any relevant issues. - [x] I have commented my code, particularly in hard-to-understand areas. - [x] I have updated the documentation where relevant (API docs, the reference, and the Sway book). - [x] I have added tests that prove my fix is effective or that my feature works. - [x] I have added (or requested a maintainer to add) the necessary `Breaking*` or `New Feature` labels where relevant. - [x] I have done my best to ensure that my PR adheres to [the Fuel Labs Code Review Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md). - [x] I have requested a review from the relevant team or maintainers.
1 parent 996a351 commit 76e407a

File tree

14 files changed

+1304
-1230
lines changed

14 files changed

+1304
-1230
lines changed

sway-core/src/semantic_analysis/ast_node/code_block.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@ impl ty::TyCodeBlock {
1919
.contents
2020
.iter()
2121
.filter_map(|node| {
22-
let ctx = ctx.by_ref().scoped(&mut code_block_namespace);
23-
ty::TyAstNode::type_check(handler, ctx, node.clone()).ok()
22+
ctx.by_ref()
23+
.scoped(&mut code_block_namespace, |ctx| {
24+
ty::TyAstNode::type_check(handler, ctx, node.clone())
25+
})
26+
.ok()
2427
})
2528
.collect::<Vec<ty::TyAstNode>>();
2629

sway-core/src/semantic_analysis/ast_node/declaration/abi.rs

+140-137
Original file line numberDiff line numberDiff line change
@@ -54,61 +54,136 @@ impl ty::TyAbiDecl {
5454

5555
// A temporary namespace for checking within this scope.
5656
let mut abi_namespace = ctx.namespace.clone();
57-
let mut ctx = ctx
58-
.scoped(&mut abi_namespace)
59-
.with_abi_mode(AbiMode::ImplAbiFn(name.clone(), None))
60-
.with_self_type(Some(self_type_id));
57+
ctx.with_abi_mode(AbiMode::ImplAbiFn(name.clone(), None))
58+
.with_self_type(Some(self_type_id))
59+
.scoped(&mut abi_namespace, |mut ctx| {
60+
// Insert the "self" type param into the namespace.
61+
self_type_param.insert_self_type_into_namespace(handler, ctx.by_ref());
6162

62-
// Insert the "self" type param into the namespace.
63-
self_type_param.insert_self_type_into_namespace(handler, ctx.by_ref());
63+
// Recursively make the interface surfaces and methods of the
64+
// supertraits available to this abi.
65+
insert_supertraits_into_namespace(
66+
handler,
67+
ctx.by_ref(),
68+
self_type_id,
69+
&supertraits,
70+
&SupertraitOf::Abi(span.clone()),
71+
)?;
6472

65-
// Recursively make the interface surfaces and methods of the
66-
// supertraits available to this abi.
67-
insert_supertraits_into_namespace(
68-
handler,
69-
ctx.by_ref(),
70-
self_type_id,
71-
&supertraits,
72-
&SupertraitOf::Abi(span.clone()),
73-
)?;
73+
// Type check the interface surface.
74+
let mut new_interface_surface = vec![];
7475

75-
// Type check the interface surface.
76-
let mut new_interface_surface = vec![];
76+
let mut ids: HashSet<Ident> = HashSet::default();
7777

78-
let mut ids: HashSet<Ident> = HashSet::default();
78+
let error_on_shadowing_superabi_method =
79+
|method_name: &Ident, ctx: &mut TypeCheckContext| {
80+
if let Ok(superabi_impl_method_ref) = ctx.find_method_for_type(
81+
&Handler::default(),
82+
self_type_id,
83+
&[],
84+
&method_name.clone(),
85+
ctx.type_annotation(),
86+
&Default::default(),
87+
None,
88+
TryInsertingTraitImplOnFailure::No,
89+
) {
90+
let superabi_impl_method =
91+
ctx.engines.de().get_function(&superabi_impl_method_ref);
92+
if let Some(ty::TyDecl::AbiDecl(abi_decl)) =
93+
&superabi_impl_method.implementing_type
94+
{
95+
handler.emit_err(CompileError::AbiShadowsSuperAbiMethod {
96+
span: method_name.span(),
97+
superabi: abi_decl.name.clone(),
98+
});
99+
}
100+
}
101+
};
79102

80-
let error_on_shadowing_superabi_method =
81-
|method_name: &Ident, ctx: &mut TypeCheckContext| {
82-
if let Ok(superabi_impl_method_ref) = ctx.find_method_for_type(
83-
&Handler::default(),
84-
self_type_id,
85-
&[],
86-
&method_name.clone(),
87-
ctx.type_annotation(),
88-
&Default::default(),
89-
None,
90-
TryInsertingTraitImplOnFailure::No,
91-
) {
92-
let superabi_impl_method =
93-
ctx.engines.de().get_function(&superabi_impl_method_ref);
94-
if let Some(ty::TyDecl::AbiDecl(abi_decl)) =
95-
&superabi_impl_method.implementing_type
96-
{
97-
handler.emit_err(CompileError::AbiShadowsSuperAbiMethod {
98-
span: method_name.span(),
99-
superabi: abi_decl.name.clone(),
103+
for item in interface_surface.into_iter() {
104+
let decl_name = match item {
105+
TraitItem::TraitFn(method) => {
106+
// check that a super-trait does not define a method
107+
// with the same name as the current interface method
108+
error_on_shadowing_superabi_method(&method.name, &mut ctx);
109+
let method = ty::TyTraitFn::type_check(handler, ctx.by_ref(), method)?;
110+
for param in &method.parameters {
111+
if param.is_reference || param.is_mutable {
112+
handler.emit_err(
113+
CompileError::RefMutableNotAllowedInContractAbi {
114+
param_name: param.name.clone(),
115+
span: param.name.span(),
116+
},
117+
);
118+
}
119+
}
120+
new_interface_surface.push(ty::TyTraitInterfaceItem::TraitFn(
121+
ctx.engines.de().insert(method.clone()),
122+
));
123+
method.name.clone()
124+
}
125+
TraitItem::Constant(decl_id) => {
126+
let const_decl = engines.pe().get_constant(&decl_id).as_ref().clone();
127+
let const_decl =
128+
ty::TyConstantDecl::type_check(handler, ctx.by_ref(), const_decl)?;
129+
let decl_ref = ctx.engines.de().insert(const_decl.clone());
130+
new_interface_surface
131+
.push(ty::TyTraitInterfaceItem::Constant(decl_ref.clone()));
132+
133+
let const_name = const_decl.call_path.suffix.clone();
134+
ctx.insert_symbol(
135+
handler,
136+
const_name.clone(),
137+
ty::TyDecl::ConstantDecl(ty::ConstantDecl {
138+
name: const_name.clone(),
139+
decl_id: *decl_ref.id(),
140+
decl_span: const_decl.span.clone(),
141+
}),
142+
)?;
143+
144+
const_name
145+
}
146+
TraitItem::Type(decl_id) => {
147+
let type_decl = engines.pe().get_trait_type(&decl_id).as_ref().clone();
148+
handler.emit_err(CompileError::AssociatedTypeNotSupportedInAbi {
149+
span: type_decl.span.clone(),
150+
});
151+
152+
let type_decl =
153+
ty::TyTraitType::type_check(handler, ctx.by_ref(), type_decl)?;
154+
let decl_ref = ctx.engines().de().insert(type_decl.clone());
155+
new_interface_surface
156+
.push(ty::TyTraitInterfaceItem::Type(decl_ref.clone()));
157+
158+
type_decl.name
159+
}
160+
TraitItem::Error(_, _) => {
161+
continue;
162+
}
163+
};
164+
165+
if !ids.insert(decl_name.clone()) {
166+
handler.emit_err(CompileError::MultipleDefinitionsOfName {
167+
name: decl_name.clone(),
168+
span: decl_name.span(),
100169
});
101170
}
102171
}
103-
};
104172

105-
for item in interface_surface.into_iter() {
106-
let decl_name = match item {
107-
TraitItem::TraitFn(method) => {
108-
// check that a super-trait does not define a method
109-
// with the same name as the current interface method
173+
// Type check the items.
174+
let mut new_items = vec![];
175+
for method_id in methods.into_iter() {
176+
let method = engines.pe().get_function(&method_id);
177+
let method = ty::TyFunctionDecl::type_check(
178+
handler,
179+
ctx.by_ref(),
180+
&method,
181+
false,
182+
false,
183+
Some(self_type_param.type_id),
184+
)
185+
.unwrap_or_else(|_| ty::TyFunctionDecl::error(&method));
110186
error_on_shadowing_superabi_method(&method.name, &mut ctx);
111-
let method = ty::TyTraitFn::type_check(handler, ctx.by_ref(), method)?;
112187
for param in &method.parameters {
113188
if param.is_reference || param.is_mutable {
114189
handler.emit_err(CompileError::RefMutableNotAllowedInContractAbi {
@@ -117,100 +192,28 @@ impl ty::TyAbiDecl {
117192
});
118193
}
119194
}
120-
new_interface_surface.push(ty::TyTraitInterfaceItem::TraitFn(
121-
ctx.engines.de().insert(method.clone()),
122-
));
123-
method.name.clone()
124-
}
125-
TraitItem::Constant(decl_id) => {
126-
let const_decl = engines.pe().get_constant(&decl_id).as_ref().clone();
127-
let const_decl =
128-
ty::TyConstantDecl::type_check(handler, ctx.by_ref(), const_decl)?;
129-
let decl_ref = ctx.engines.de().insert(const_decl.clone());
130-
new_interface_surface
131-
.push(ty::TyTraitInterfaceItem::Constant(decl_ref.clone()));
132-
133-
let const_name = const_decl.call_path.suffix.clone();
134-
ctx.insert_symbol(
135-
handler,
136-
const_name.clone(),
137-
ty::TyDecl::ConstantDecl(ty::ConstantDecl {
138-
name: const_name.clone(),
139-
decl_id: *decl_ref.id(),
140-
decl_span: const_decl.span.clone(),
141-
}),
142-
)?;
143-
144-
const_name
145-
}
146-
TraitItem::Type(decl_id) => {
147-
let type_decl = engines.pe().get_trait_type(&decl_id).as_ref().clone();
148-
handler.emit_err(CompileError::AssociatedTypeNotSupportedInAbi {
149-
span: type_decl.span.clone(),
150-
});
151-
152-
let type_decl = ty::TyTraitType::type_check(handler, ctx.by_ref(), type_decl)?;
153-
let decl_ref = ctx.engines().de().insert(type_decl.clone());
154-
new_interface_surface.push(ty::TyTraitInterfaceItem::Type(decl_ref.clone()));
155-
156-
type_decl.name
157-
}
158-
TraitItem::Error(_, _) => {
159-
continue;
160-
}
161-
};
162-
163-
if !ids.insert(decl_name.clone()) {
164-
handler.emit_err(CompileError::MultipleDefinitionsOfName {
165-
name: decl_name.clone(),
166-
span: decl_name.span(),
167-
});
168-
}
169-
}
170-
171-
// Type check the items.
172-
let mut new_items = vec![];
173-
for method_id in methods.into_iter() {
174-
let method = engines.pe().get_function(&method_id);
175-
let method = ty::TyFunctionDecl::type_check(
176-
handler,
177-
ctx.by_ref(),
178-
&method,
179-
false,
180-
false,
181-
Some(self_type_param.type_id),
182-
)
183-
.unwrap_or_else(|_| ty::TyFunctionDecl::error(&method));
184-
error_on_shadowing_superabi_method(&method.name, &mut ctx);
185-
for param in &method.parameters {
186-
if param.is_reference || param.is_mutable {
187-
handler.emit_err(CompileError::RefMutableNotAllowedInContractAbi {
188-
param_name: param.name.clone(),
189-
span: param.name.span(),
190-
});
195+
if !ids.insert(method.name.clone()) {
196+
handler.emit_err(CompileError::MultipleDefinitionsOfName {
197+
name: method.name.clone(),
198+
span: method.name.span(),
199+
});
200+
}
201+
new_items.push(TyTraitItem::Fn(ctx.engines.de().insert(method)));
191202
}
192-
}
193-
if !ids.insert(method.name.clone()) {
194-
handler.emit_err(CompileError::MultipleDefinitionsOfName {
195-
name: method.name.clone(),
196-
span: method.name.span(),
197-
});
198-
}
199-
new_items.push(TyTraitItem::Fn(ctx.engines.de().insert(method)));
200-
}
201203

202-
// Compared to regular traits, we do not insert recursively methods of ABI supertraits
203-
// into the interface surface, we do not want supertrait methods to be available to
204-
// the ABI user, only the contract methods can use supertrait methods
205-
let abi_decl = ty::TyAbiDecl {
206-
interface_surface: new_interface_surface,
207-
supertraits,
208-
items: new_items,
209-
name,
210-
span,
211-
attributes,
212-
};
213-
Ok(abi_decl)
204+
// Compared to regular traits, we do not insert recursively methods of ABI supertraits
205+
// into the interface surface, we do not want supertrait methods to be available to
206+
// the ABI user, only the contract methods can use supertrait methods
207+
let abi_decl = ty::TyAbiDecl {
208+
interface_surface: new_interface_surface,
209+
supertraits,
210+
items: new_items,
211+
name,
212+
span,
213+
attributes,
214+
};
215+
Ok(abi_decl)
216+
})
214217
}
215218

216219
pub(crate) fn insert_interface_surface_and_items_into_namespace(

sway-core/src/semantic_analysis/ast_node/declaration/enum.rs

+31-27
Original file line numberDiff line numberDiff line change
@@ -23,36 +23,40 @@ impl ty::TyEnumDecl {
2323

2424
// create a namespace for the decl, used to create a scope for generics
2525
let mut decl_namespace = ctx.namespace.clone();
26-
let mut ctx = ctx.scoped(&mut decl_namespace);
27-
28-
// Type check the type parameters.
29-
let new_type_parameters =
30-
TypeParameter::type_check_type_params(handler, ctx.by_ref(), type_parameters, None)?;
26+
ctx.scoped(&mut decl_namespace, |mut ctx| {
27+
// Type check the type parameters.
28+
let new_type_parameters = TypeParameter::type_check_type_params(
29+
handler,
30+
ctx.by_ref(),
31+
type_parameters,
32+
None,
33+
)?;
3134

32-
// type check the variants
33-
let mut variants_buf = vec![];
34-
for variant in variants {
35-
variants_buf.push(
36-
match ty::TyEnumVariant::type_check(handler, ctx.by_ref(), variant.clone()) {
37-
Ok(res) => res,
38-
Err(_) => continue,
39-
},
40-
);
41-
}
35+
// type check the variants
36+
let mut variants_buf = vec![];
37+
for variant in variants {
38+
variants_buf.push(
39+
match ty::TyEnumVariant::type_check(handler, ctx.by_ref(), variant.clone()) {
40+
Ok(res) => res,
41+
Err(_) => continue,
42+
},
43+
);
44+
}
4245

43-
let mut call_path: CallPath = name.into();
44-
call_path = call_path.to_fullpath(ctx.namespace);
46+
let mut call_path: CallPath = name.into();
47+
call_path = call_path.to_fullpath(ctx.namespace);
4548

46-
// create the enum decl
47-
let decl = ty::TyEnumDecl {
48-
call_path,
49-
type_parameters: new_type_parameters,
50-
variants: variants_buf,
51-
span,
52-
attributes,
53-
visibility,
54-
};
55-
Ok(decl)
49+
// create the enum decl
50+
let decl = ty::TyEnumDecl {
51+
call_path,
52+
type_parameters: new_type_parameters,
53+
variants: variants_buf,
54+
span,
55+
attributes,
56+
visibility,
57+
};
58+
Ok(decl)
59+
})
5660
}
5761
}
5862

0 commit comments

Comments
 (0)