Skip to content

Commit 057d1ea

Browse files
committed
Removes TraitMap::insert_for_type.
Some use cases require the compiler to call insert_implementation_for_type on every call of find_method_for_type. This would double the compile time of a simple script. To avoid this we removed the TraitMap::insert_for_type. The TraitMap now only stores the original implementations and uses a less restrictive unify_check to get those that match the concrete implementations. This reduces significantly the size of the TraitMap and speeds up the lookup times. On the other hand, it also introduces a type substitution on every find_method_for_type. A future PR will address the performance of doing type substitutions.
1 parent 8c5afa3 commit 057d1ea

File tree

22 files changed

+745
-652
lines changed

22 files changed

+745
-652
lines changed

sway-core/src/language/ty/declaration/function.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,81 @@ impl DisplayWithEngines for TyFunctionDecl {
133133
}
134134
}
135135

136+
impl DeclRefFunction {
137+
/// Makes method with a copy of type_id.
138+
/// This avoids altering the type_id already in the type map.
139+
/// Without this it is possible to retrieve a method from the type map unify its types and
140+
/// the second time it won't be possible to retrieve the same method.
141+
pub fn get_method_safe_to_unify(&self, engines: &Engines, type_id: TypeId) -> Self {
142+
let decl_engine = engines.de();
143+
144+
let mut method = (*decl_engine.get_function(self)).clone();
145+
146+
if let Some(method_implementing_for_typeid) = method.implementing_for_typeid {
147+
let mut type_id_type_subst_map = TypeSubstMap::new();
148+
match &method.implementing_type {
149+
Some(TyDecl::ImplSelfOrTrait(t)) => {
150+
let impl_self_or_trait = &*engines.de().get(&t.decl_id);
151+
let mut type_id_type_parameters = vec![];
152+
type_id.extract_type_parameters(
153+
engines,
154+
0,
155+
&mut type_id_type_parameters,
156+
impl_self_or_trait.implementing_for.type_id,
157+
);
158+
159+
for impl_type_parameter in impl_self_or_trait.impl_type_parameters.clone() {
160+
let matches = type_id_type_parameters
161+
.iter()
162+
.filter(|(_, orig_tp)| {
163+
engines.te().get(orig_tp.type_id).eq(
164+
&*engines.te().get(impl_type_parameter.type_id),
165+
&PartialEqWithEnginesContext::new(engines),
166+
)
167+
})
168+
.collect::<Vec<_>>();
169+
if matches.len() > 0 {
170+
type_id_type_subst_map
171+
.insert(impl_type_parameter.type_id, matches[0].0.type_id);
172+
}
173+
if engines
174+
.te()
175+
.get(impl_self_or_trait.implementing_for.initial_type_id)
176+
.eq(
177+
&*engines.te().get(impl_type_parameter.initial_type_id),
178+
&PartialEqWithEnginesContext::new(engines),
179+
)
180+
{
181+
type_id_type_subst_map.insert(impl_type_parameter.type_id, type_id);
182+
}
183+
}
184+
}
185+
_ => {}
186+
}
187+
188+
let mut method_type_subst_map = TypeSubstMap::new();
189+
method_type_subst_map.extend(&type_id_type_subst_map);
190+
method_type_subst_map.insert(method_implementing_for_typeid, type_id);
191+
192+
method.subst(&SubstTypesContext::new(
193+
engines,
194+
&method_type_subst_map,
195+
true,
196+
));
197+
198+
return engines
199+
.de()
200+
.insert(
201+
method.clone(),
202+
engines.de().get_parsed_decl_id(self.id()).as_ref(),
203+
)
204+
.with_parent(decl_engine, self.id().into());
205+
}
206+
207+
self.clone()
208+
}
209+
}
210+
136211
impl Named for TyFunctionDecl {
137212
fn name(&self) -> &Ident {
138213
&self.name
@@ -481,6 +556,25 @@ impl TyFunctionDecl {
481556
_ => Some(false),
482557
}
483558
}
559+
560+
pub fn is_from_blanket_impl(&self, engines: &Engines) -> bool {
561+
if let Some(TyDecl::ImplSelfOrTrait(existing_impl_trait)) = self.implementing_type.clone() {
562+
let existing_trait_decl = engines
563+
.de()
564+
.get_impl_self_or_trait(&existing_impl_trait.decl_id);
565+
if !existing_trait_decl.impl_type_parameters.is_empty()
566+
&& matches!(
567+
*engines
568+
.te()
569+
.get(existing_trait_decl.implementing_for.type_id),
570+
TypeInfo::UnknownGeneric { .. }
571+
)
572+
{
573+
return true;
574+
}
575+
}
576+
false
577+
}
484578
}
485579

486580
#[derive(Debug, Clone, Serialize, Deserialize)]

sway-core/src/language/ty/expression/expression_variant.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use crate::{
33
engine_threading::*,
44
has_changes,
55
language::{ty::*, *},
6-
namespace::TryInsertingTraitImplOnFailure,
76
semantic_analysis::{
87
TyNodeDepGraphEdge, TyNodeDepGraphEdgeInfo, TypeCheckAnalysis, TypeCheckAnalysisContext,
98
TypeCheckContext, TypeCheckFinalization, TypeCheckFinalizationContext,
@@ -833,7 +832,6 @@ impl ReplaceDecls for TyExpressionVariant {
833832
.map(|a| a.1.return_type)
834833
.collect::<VecDeque<_>>(),
835834
None,
836-
TryInsertingTraitImplOnFailure::Yes,
837835
)?;
838836
method = (*decl_engine.get(&implementing_type_method_ref)).clone();
839837
}

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{
99
DeclId,
1010
},
1111
language::ty::{TyAbiDecl, TyFunctionDecl},
12-
namespace::{IsExtendingExistingImpl, IsImplSelf, TryInsertingTraitImplOnFailure},
12+
namespace::{IsExtendingExistingImpl, IsImplSelf},
1313
semantic_analysis::{
1414
symbol_collection_context::SymbolCollectionContext, TypeCheckAnalysis,
1515
TypeCheckAnalysisContext, TypeCheckFinalization, TypeCheckFinalizationContext,
@@ -113,7 +113,6 @@ impl ty::TyAbiDecl {
113113
ctx.type_annotation(),
114114
&Default::default(),
115115
None,
116-
TryInsertingTraitImplOnFailure::No,
117116
) {
118117
let superabi_impl_method =
119118
ctx.engines.de().get_function(&superabi_impl_method_ref);
@@ -279,7 +278,6 @@ impl ty::TyAbiDecl {
279278
ctx.type_annotation(),
280279
&Default::default(),
281280
None,
282-
TryInsertingTraitImplOnFailure::No,
283281
) {
284282
let superabi_method =
285283
ctx.engines.de().get_function(&superabi_method_ref);
@@ -354,7 +352,6 @@ impl ty::TyAbiDecl {
354352
ctx.type_annotation(),
355353
&Default::default(),
356354
None,
357-
TryInsertingTraitImplOnFailure::No,
358355
) {
359356
let superabi_impl_method =
360357
ctx.engines.de().get_function(&superabi_impl_method_ref);

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::{
2222
},
2323
*,
2424
},
25-
namespace::{IsExtendingExistingImpl, IsImplSelf, TraitMap, TryInsertingTraitImplOnFailure},
25+
namespace::{IsExtendingExistingImpl, IsImplSelf, TraitMap},
2626
semantic_analysis::{
2727
symbol_collection_context::SymbolCollectionContext, AbiMode, ConstShadowingMode,
2828
TyNodeDepGraphNodeId, TypeCheckAnalysis, TypeCheckAnalysisContext, TypeCheckContext,
@@ -692,7 +692,6 @@ fn type_check_trait_implementation(
692692
let type_engine = ctx.engines.te();
693693
let decl_engine = ctx.engines.de();
694694
let engines = ctx.engines();
695-
let code_block_first_pass = ctx.code_block_first_pass();
696695

697696
// Check to see if the type that we are implementing for implements the
698697
// supertraits of this trait.
@@ -709,8 +708,6 @@ fn type_check_trait_implementation(
709708
.collect::<Vec<_>>(),
710709
block_span,
711710
engines,
712-
TryInsertingTraitImplOnFailure::Yes,
713-
code_block_first_pass.into(),
714711
)
715712
})?;
716713

sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use crate::{
88
ty::{self, TyDecl, TyExpression, TyFunctionSig},
99
*,
1010
},
11-
namespace::TryInsertingTraitImplOnFailure,
1211
semantic_analysis::*,
1312
type_system::*,
1413
};
@@ -36,6 +35,7 @@ pub(crate) fn type_check_method_application(
3635
let type_engine = ctx.engines.te();
3736
let decl_engine = ctx.engines.de();
3837
let engines = ctx.engines();
38+
let coercion_check = UnifyCheck::coercion(engines);
3939

4040
// type check the function arguments (1st pass)
4141
// Some arguments may fail on this first pass because they may require the type_annotation to the parameter type.
@@ -120,34 +120,46 @@ pub(crate) fn type_check_method_application(
120120
// type check the function arguments (2nd pass)
121121
let mut args_buf = VecDeque::new();
122122
for (arg, index, arg_opt) in izip!(arguments.iter(), 0.., args_opt_buf.iter().cloned()) {
123-
if let (Some(arg), false) = arg_opt {
124-
args_buf.push_back(arg);
123+
let param_index = if method.is_contract_call {
124+
if index == 0 {
125+
continue;
126+
}
127+
index - 1 //contract call methods don't have self parameter.
125128
} else {
126-
// We type check the argument expression again this time throwing out the error.
127-
let param_index = if method.is_contract_call {
128-
index - 1 //contract call methods don't have self parameter.
129-
} else {
130-
index
131-
};
129+
index
130+
};
132131

133-
let ctx = if let Some(param) = method.parameters.get(param_index) {
134-
// We now try to type check it again, this time with the type annotation.
135-
ctx.by_ref()
136-
.with_help_text(
137-
"Function application argument type must match function parameter type.",
138-
)
139-
.with_type_annotation(param.type_argument.type_id)
132+
if let (Some(arg), false) = arg_opt {
133+
if let Some(param) = method.parameters.get(param_index) {
134+
// If argument type is compcoerces to resolved method parameter type skip second type_check.
135+
if coercion_check.check(arg.return_type, param.type_argument.type_id) {
136+
args_buf.push_back(arg);
137+
continue;
138+
}
140139
} else {
141-
ctx.by_ref()
142-
.with_help_text("")
143-
.with_type_annotation(type_engine.new_unknown())
144-
};
145-
146-
args_buf.push_back(
147-
ty::TyExpression::type_check(handler, ctx, arg)
148-
.unwrap_or_else(|err| ty::TyExpression::error(err, span.clone(), engines)),
149-
);
140+
args_buf.push_back(arg);
141+
continue;
142+
}
150143
}
144+
145+
// We type check the argument expression again this time throwing out the error.
146+
let ctx = if let Some(param) = method.parameters.get(param_index) {
147+
// We now try to type check it again, this time with the type annotation.
148+
ctx.by_ref()
149+
.with_help_text(
150+
"Function application argument type must match function parameter type.",
151+
)
152+
.with_type_annotation(param.type_argument.type_id)
153+
} else {
154+
ctx.by_ref()
155+
.with_help_text("")
156+
.with_type_annotation(type_engine.new_unknown())
157+
};
158+
159+
args_buf.push_back(
160+
ty::TyExpression::type_check(handler, ctx, arg)
161+
.unwrap_or_else(|err| ty::TyExpression::error(err, span.clone(), engines)),
162+
);
151163
}
152164

153165
// check the method visibility
@@ -821,7 +833,6 @@ pub(crate) fn resolve_method_name(
821833
ctx.type_annotation(),
822834
&arguments_types,
823835
None,
824-
TryInsertingTraitImplOnFailure::Yes,
825836
)?;
826837

827838
(decl_ref, type_id)
@@ -866,7 +877,6 @@ pub(crate) fn resolve_method_name(
866877
ctx.type_annotation(),
867878
&arguments_types,
868879
None,
869-
TryInsertingTraitImplOnFailure::Yes,
870880
)?;
871881

872882
(decl_ref, type_id)
@@ -890,7 +900,6 @@ pub(crate) fn resolve_method_name(
890900
ctx.type_annotation(),
891901
&arguments_types,
892902
None,
893-
TryInsertingTraitImplOnFailure::Yes,
894903
)?;
895904

896905
(decl_ref, type_id)
@@ -915,7 +924,6 @@ pub(crate) fn resolve_method_name(
915924
ctx.type_annotation(),
916925
&arguments_types,
917926
Some(*as_trait),
918-
TryInsertingTraitImplOnFailure::Yes,
919927
)?;
920928

921929
(decl_ref, type_id)

sway-core/src/semantic_analysis/ast_node/expression/typed_expression/struct_instantiation.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,11 +339,13 @@ fn collect_struct_constructors(
339339
.filter_map(|item| match item {
340340
ResolvedTraitImplItem::Parsed(_) => unreachable!(),
341341
ResolvedTraitImplItem::Typed(item) => match item {
342-
ty::TyTraitItem::Fn(fn_decl_id) => Some(fn_decl_id),
342+
ty::TyTraitItem::Fn(fn_decl_id) => {
343+
Some(fn_decl_id.get_method_safe_to_unify(engines, struct_type_id))
344+
}
343345
_ => None,
344346
},
345347
})
346-
.map(|fn_decl_id| engines.de().get_function(fn_decl_id))
348+
.map(|fn_decl_id| engines.de().get_function(&fn_decl_id))
347349
.filter(|fn_decl| {
348350
matches!(fn_decl.visibility, Visibility::Public)
349351
&& fn_decl

sway-core/src/semantic_analysis/namespace/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ pub use module::Module;
1313
pub use namespace::Namespace;
1414
pub use root::ResolvedDeclaration;
1515
pub use root::Root;
16-
pub(super) use trait_map::CodeBlockFirstPass;
1716
pub(crate) use trait_map::IsExtendingExistingImpl;
1817
pub(crate) use trait_map::IsImplSelf;
1918
pub(super) use trait_map::ResolvedTraitImplItem;

sway-core/src/semantic_analysis/namespace/root.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -560,11 +560,7 @@ impl Root {
560560
src_mod
561561
.root_items()
562562
.implemented_traits
563-
.filter_by_type_item_import(
564-
type_id,
565-
engines,
566-
super::CodeBlockFirstPass::No,
567-
),
563+
.filter_by_type_item_import(type_id, engines),
568564
engines,
569565
);
570566
}

0 commit comments

Comments
 (0)