Skip to content

Commit

Permalink
Use the scoped copy pattern in type checking TypeBinding.
Browse files Browse the repository at this point in the history
  • Loading branch information
emilyaherbert committed Mar 20, 2023
1 parent 45f779c commit 4f8264a
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 85 deletions.
19 changes: 19 additions & 0 deletions sway-core/src/decl_engine/ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ impl<I> DeclRef<I> {
&self.subst_list
}

pub(crate) fn subst_list_mut(&mut self) -> &mut TypeSubstList {
&mut self.subst_list
}

pub fn decl_span(&self) -> &Span {
&self.decl_span
}
Expand Down Expand Up @@ -172,3 +176,18 @@ impl ReplaceFunctionImplementingType for DeclRefFunction {
decl_engine.replace(self.id, decl);
}
}

impl<T> CreateCopy<DeclRef<DeclId<T>>> for DeclRef<DeclId<T>> {
fn scoped_copy(&self, engines: Engines<'_>) -> Self {
DeclRef {
name: self.name.clone(),
id: self.id,
subst_list: self.subst_list.scoped_copy(engines),
decl_span: self.decl_span.clone(),
}
}

fn unscoped_copy(&self) -> Self {
self.clone()
}
}
21 changes: 20 additions & 1 deletion sway-core/src/semantic_analysis/type_check_context.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
decl_engine::DeclEngine,
decl_engine::{DeclEngine, DeclId, DeclRef},
engine_threading::*,
language::{parsed::TreeType, Purity},
namespace::Path,
Expand Down Expand Up @@ -237,6 +237,25 @@ impl<'a> TypeCheckContext<'a> {

// Provide some convenience functions around the inner context.

pub(crate) fn combine_type_subst_list_and_args<T>(
&mut self,
decl_ref: &mut DeclRef<DeclId<T>>,
type_args: &mut [TypeArgument],
enforce_type_args: EnforceTypeArguments,
call_site_span: &Span,
) -> CompileResult<()> {
let mod_path = self.namespace.mod_path.clone();
self.type_engine.combine_type_subst_list_and_args(
self.namespace,
self.decl_engine,
&mod_path,
decl_ref,
type_args,
enforce_type_args,
call_site_span,
)
}

/// Short-hand for calling the `monomorphize` function in the type engine
pub(crate) fn monomorphize<T>(
&mut self,
Expand Down
59 changes: 22 additions & 37 deletions sway-core/src/type_system/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,20 +240,19 @@ impl TypeCheckTypeBinding<ty::TyFunctionDeclaration> for TypeBinding<CallPath> {
errors
);
// Check to see if this is a fn declaration.
let fn_ref = check!(
let mut fn_ref = check!(
unknown_decl.to_fn_ref(),
return err(warnings, errors),
warnings,
errors
);
// Get a new copy from the declaration engine.
let mut new_copy = decl_engine.get_function(fn_ref.id());
)
.scoped_copy(engines);
match self.type_arguments {
// Monomorphize the copy, in place.
TypeArgs::Regular(_) => {
// Monomorphize the copy, in place.
check!(
ctx.monomorphize(
&mut new_copy,
ctx.combine_type_subst_list_and_args(
&mut fn_ref,
self.type_arguments.to_vec_mut(),
EnforceTypeArguments::No,
&self.span
Expand All @@ -264,7 +263,7 @@ impl TypeCheckTypeBinding<ty::TyFunctionDeclaration> for TypeBinding<CallPath> {
);
}
TypeArgs::Prefix(_) => {
// Resolve the type arguments without monomorphizing.
// Resolve the type arguments without using the fn.
for type_argument in self.type_arguments.to_vec_mut().iter_mut() {
check!(
ctx.resolve_type(
Expand All @@ -280,9 +279,7 @@ impl TypeCheckTypeBinding<ty::TyFunctionDeclaration> for TypeBinding<CallPath> {
}
}
}
// Insert the new copy into the declaration engine.
let new_fn_ref = ctx.decl_engine.insert(new_copy, todo!());
ok((new_fn_ref, None), warnings, errors)
ok((fn_ref, None), warnings, errors)
}
}

Expand All @@ -306,18 +303,16 @@ impl TypeCheckTypeBinding<ty::TyStructDeclaration> for TypeBinding<CallPath> {
errors
);
// Check to see if this is a struct declaration.
let struct_ref = check!(
let mut struct_ref = check!(
unknown_decl.to_struct_ref(engines),
return err(warnings, errors),
warnings,
errors
);
// Get a new copy from the declaration engine.
let mut new_copy = decl_engine.get_struct(struct_ref.id());
// Monomorphize the copy, in place.
)
.scoped_copy(engines);
check!(
ctx.monomorphize(
&mut new_copy,
ctx.combine_type_subst_list_and_args(
&mut struct_ref,
self.type_arguments.to_vec_mut(),
EnforceTypeArguments::No,
&self.span
Expand All @@ -326,13 +321,11 @@ impl TypeCheckTypeBinding<ty::TyStructDeclaration> for TypeBinding<CallPath> {
warnings,
errors
);
// Insert the new copy into the declaration engine.
let new_struct_ref = ctx.decl_engine.insert(new_copy, todo!());
// Take any trait items that apply to the old type and copy them to the new type.
let type_id = type_engine.insert(decl_engine, TypeInfo::Struct(new_struct_ref.clone()));
let type_id = type_engine.insert(decl_engine, TypeInfo::Struct(struct_ref.clone()));
ctx.namespace
.insert_trait_implementation_for_type(engines, type_id);
ok((new_struct_ref, Some(type_id)), warnings, errors)
ok((struct_ref, Some(type_id)), warnings, errors)
}
}

Expand All @@ -356,18 +349,16 @@ impl TypeCheckTypeBinding<ty::TyEnumDeclaration> for TypeBinding<CallPath> {
errors
);
// Check to see if this is a enum declaration.
let enum_ref = check!(
let mut enum_ref = check!(
unknown_decl.to_enum_ref(engines),
return err(warnings, errors),
warnings,
errors
);
// Get a new copy from the declaration engine.
let mut new_copy = decl_engine.get_enum(enum_ref.id());
// Monomorphize the copy, in place.
)
.scoped_copy(engines);
check!(
ctx.monomorphize(
&mut new_copy,
ctx.combine_type_subst_list_and_args(
&mut enum_ref,
self.type_arguments.to_vec_mut(),
EnforceTypeArguments::No,
&self.span
Expand All @@ -376,13 +367,11 @@ impl TypeCheckTypeBinding<ty::TyEnumDeclaration> for TypeBinding<CallPath> {
warnings,
errors
);
// Insert the new copy into the declaration engine.
let new_enum_ref = ctx.decl_engine.insert(new_copy, todo!());
// Take any trait items that apply to the old type and copy them to the new type.
let type_id = type_engine.insert(decl_engine, TypeInfo::Enum(new_enum_ref.clone()));
let type_id = type_engine.insert(decl_engine, TypeInfo::Enum(enum_ref.clone()));
ctx.namespace
.insert_trait_implementation_for_type(engines, type_id);
ok((new_enum_ref, Some(type_id)), warnings, errors)
ok((enum_ref, Some(type_id)), warnings, errors)
}
}

Expand All @@ -393,9 +382,7 @@ impl TypeCheckTypeBinding<ty::TyConstantDeclaration> for TypeBinding<CallPath> {
) -> CompileResult<(DeclRef<DeclId<ty::TyConstantDeclaration>>, Option<TypeId>)> {
let mut warnings = vec![];
let mut errors = vec![];

let engines = ctx.engines();

// Grab the declaration.
let unknown_decl = check!(
ctx.namespace
Expand All @@ -405,15 +392,13 @@ impl TypeCheckTypeBinding<ty::TyConstantDeclaration> for TypeBinding<CallPath> {
warnings,
errors
);

// Check to see if this is a const declaration.
let const_ref = check!(
unknown_decl.to_const_ref(),
return err(warnings, errors),
warnings,
errors
);

ok((const_ref, None), warnings, errors)
}
}
104 changes: 71 additions & 33 deletions sway-core/src/type_system/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,47 @@ impl TypeEngine {
}
}

#[allow(clippy::too_many_arguments)]
pub(crate) fn combine_type_subst_list_and_args<T>(
&self,
namespace: &mut Namespace,
decl_engine: &DeclEngine,
mod_path: &Path,
decl_ref: &mut DeclRef<DeclId<T>>,
type_args: &mut [TypeArgument],
enforce_type_args: EnforceTypeArguments,
call_site_span: &Span,
) -> CompileResult<()> {
let mut warnings = vec![];
let mut errors = vec![];
check!(
self.resolve_type_args(
namespace,
decl_engine,
mod_path,
type_args,
enforce_type_args
),
return err(warnings, errors),
warnings,
errors
);
check!(
self.compare_type_subst_list_and_args(
decl_ref.subst_list(),
type_args,
enforce_type_args,
decl_ref.name(),
call_site_span
),
return err(warnings, errors),
warnings,
errors
);
decl_ref.subst_list_mut().apply_type_args(type_args);
ok((), warnings, errors)
}

/// Resolve the type of the given [TypeId], replacing any instances of
/// [TypeInfo::Custom] with either a monomorphized struct, monomorphized
/// enum, or a reference to a type parameter.
Expand All @@ -313,7 +354,7 @@ impl TypeEngine {
&self,
decl_engine: &DeclEngine,
type_id: TypeId,
span: &Span,
call_site_span: &Span,
enforce_type_args: EnforceTypeArguments,
type_info_prefix: Option<&Path>,
namespace: &mut Namespace,
Expand All @@ -329,19 +370,6 @@ impl TypeEngine {
type_arguments,
} => {
let mut type_args = type_arguments.unwrap_or_default();
check!(
self.resolve_type_args(
namespace,
decl_engine,
mod_path,
&mut type_args,
enforce_type_args
),
return err(warnings, errors),
warnings,
errors
);

match namespace
.root()
.resolve_call_path_with_visibility_check(engines, module_path, &call_path)
Expand All @@ -354,21 +382,26 @@ impl TypeEngine {
type_subst_list,
decl_span,
}) => {
let mut struct_ref = DeclRef::new(
name,
decl_id,
type_subst_list.scoped_copy(engines),
decl_span,
);
check!(
self.compare_type_subst_list_and_args(
type_subst_list.inner(),
&type_args,
self.combine_type_subst_list_and_args(
namespace,
decl_engine,
mod_path,
&mut struct_ref,
&mut type_args,
enforce_type_args,
&name,
span
call_site_span
),
return err(warnings, errors),
warnings,
errors
);
let mut type_subst_list = type_subst_list.scoped_copy(engines);
type_subst_list.apply_type_args(type_args);
let struct_ref = DeclRef::new(name, decl_id, type_subst_list, decl_span);
let type_id = self.insert(decl_engine, TypeInfo::Struct(struct_ref));
namespace.insert_trait_implementation_for_type(engines, type_id);
type_id
Expand All @@ -379,22 +412,27 @@ impl TypeEngine {
type_subst_list,
decl_span,
}) => {
let mut enum_ref = DeclRef::new(
name,
decl_id,
type_subst_list.scoped_copy(engines),
decl_span,
);
check!(
self.compare_type_subst_list_and_args(
type_subst_list.inner(),
&type_args,
self.combine_type_subst_list_and_args(
namespace,
decl_engine,
mod_path,
&mut enum_ref,
&mut type_args,
enforce_type_args,
&name,
span
call_site_span
),
return err(warnings, errors),
warnings,
errors
);
let mut type_subst_list = type_subst_list.scoped_copy(engines);
type_subst_list.apply_type_args(type_args);
let struct_ref = DeclRef::new(name, decl_id, type_subst_list, decl_span);
let type_id = self.insert(decl_engine, TypeInfo::Enum(struct_ref));
let type_id = self.insert(decl_engine, TypeInfo::Enum(enum_ref));
namespace.insert_trait_implementation_for_type(engines, type_id);
type_id
}
Expand Down Expand Up @@ -427,7 +465,7 @@ impl TypeEngine {
self.resolve(
decl_engine,
elem_ty.type_id,
span,
call_site_span,
enforce_type_args,
None,
namespace,
Expand All @@ -445,7 +483,7 @@ impl TypeEngine {
self.resolve(
decl_engine,
type_argument.type_id,
span,
call_site_span,
enforce_type_args,
None,
namespace,
Expand Down
2 changes: 1 addition & 1 deletion sway-core/src/type_system/substitute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ impl TypeSubstList {
self.list.get(index)
}

pub(crate) fn apply_type_args(&mut self, type_args: Vec<TypeArgument>) {
pub(crate) fn apply_type_args(&mut self, type_args: &[TypeArgument]) {
self.list
.iter_mut()
.zip(type_args.iter())
Expand Down
Loading

0 comments on commit 4f8264a

Please sign in to comment.