Skip to content

Commit

Permalink
Add TypeInfo::UntypedEnum and TypeInfo::UntypedStruct.
Browse files Browse the repository at this point in the history
  • Loading branch information
tritao committed Oct 20, 2024
1 parent 029c593 commit 1c3d9e1
Show file tree
Hide file tree
Showing 13 changed files with 306 additions and 35 deletions.
8 changes: 8 additions & 0 deletions sway-core/src/abi_generation/abi_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,14 @@ impl TypeInfo {
Numeric => "u64".into(), // u64 is the default
Contract => "contract".into(),
ErrorRecovery(_) => "unknown due to error".into(),
UntypedEnum(decl_id) => {
let decl = engines.pe().get_enum(decl_id);
format!("untyped enum {}", decl.name)
}
UntypedStruct(decl_id) => {
let decl = engines.pe().get_struct(decl_id);
format!("untyped struct {}", decl.name)
}
Enum(decl_ref) => {
let decl = decl_engine.get_enum(decl_ref);
let type_params = if (ctx.abi_root_type_without_generic_type_parameters && is_root)
Expand Down
8 changes: 8 additions & 0 deletions sway-core/src/abi_generation/evm_abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,14 @@ pub fn abi_str(type_info: &TypeInfo, engines: &Engines) -> String {
Numeric => "u64".into(), // u64 is the default
Contract => "contract".into(),
ErrorRecovery(_) => "unknown due to error".into(),
UntypedEnum(decl_id) => {
let decl = engines.pe().get_enum(decl_id);
format!("untyped enum {}", decl.name)
}
UntypedStruct(decl_id) => {
let decl = engines.pe().get_struct(decl_id);
format!("untyped struct {}", decl.name)
}
Enum(decl_ref) => {
let decl = decl_engine.get_enum(decl_ref);
format!("enum {}", decl.call_path.suffix)
Expand Down
1 change: 1 addition & 0 deletions sway-core/src/decl_engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub use engine::*;
pub(crate) use id::*;
pub use interface_decl_id::*;
pub(crate) use mapping::*;
pub use parsed_engine::*;
pub use r#ref::*;
pub(crate) use replace_decls::*;
use sway_types::Ident;
Expand Down
22 changes: 20 additions & 2 deletions sway-core/src/decl_engine/parsed_engine.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::{
concurrent_slab::ConcurrentSlab,
decl_engine::*,
language::parsed::{
AbiDeclaration, ConfigurableDeclaration, ConstantDeclaration, EnumDeclaration, EnumVariant,
FunctionDeclaration, ImplSelfOrTrait, StorageDeclaration, StructDeclaration,
Expand Down Expand Up @@ -47,7 +46,7 @@ pub trait ParsedDeclEngineReplace<T> {

#[allow(unused)]
pub trait ParsedDeclEngineIndex<T>:
ParsedDeclEngineGet<DeclId<T>, T> + ParsedDeclEngineInsert<T> + ParsedDeclEngineReplace<T>
ParsedDeclEngineGet<ParsedDeclId<T>, T> + ParsedDeclEngineInsert<T> + ParsedDeclEngineReplace<T>
{
}

Expand Down Expand Up @@ -136,6 +135,25 @@ macro_rules! decl_engine_clear {
};
}

macro_rules! decl_engine_index {
($slab:ident, $decl:ty) => {
impl ParsedDeclEngineIndex<$decl> for ParsedDeclEngine {}
};
}
decl_engine_index!(variable_slab, VariableDeclaration);
decl_engine_index!(function_slab, FunctionDeclaration);
decl_engine_index!(trait_slab, TraitDeclaration);
decl_engine_index!(trait_fn_slab, TraitFn);
decl_engine_index!(trait_type_slab, TraitTypeDeclaration);
decl_engine_index!(impl_self_or_trait_slab, ImplSelfOrTrait);
decl_engine_index!(struct_slab, StructDeclaration);
decl_engine_index!(storage_slab, StorageDeclaration);
decl_engine_index!(abi_slab, AbiDeclaration);
decl_engine_index!(configurable_slab, ConfigurableDeclaration);
decl_engine_index!(constant_slab, ConstantDeclaration);
decl_engine_index!(enum_slab, EnumDeclaration);
decl_engine_index!(type_alias_slab, TypeAliasDeclaration);

decl_engine_clear!(
variable_slab, VariableDeclaration;
function_slab, FunctionDeclaration;
Expand Down
21 changes: 20 additions & 1 deletion sway-core/src/decl_engine/parsed_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@ use std::hash::{DefaultHasher, Hasher};
use std::marker::PhantomData;
use std::{fmt, hash::Hash};

use crate::engine_threading::{EqWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext};
use sway_types::{Named, Spanned};

use crate::engine_threading::{
EqWithEngines, HashWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext,
};
use crate::Engines;

use super::parsed_engine::{ParsedDeclEngine, ParsedDeclEngineGet, ParsedDeclEngineIndex};
use super::DeclUniqueId;

pub type ParsedDeclIdIndexType = usize;
Expand Down Expand Up @@ -61,6 +67,19 @@ impl<T> Hash for ParsedDeclId<T> {
}
}

impl<T> HashWithEngines for ParsedDeclId<T>
where
ParsedDeclEngine: ParsedDeclEngineIndex<T>,
T: Named + Spanned + HashWithEngines,
{
fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
let decl_engine = engines.pe();
let decl = decl_engine.get(self);
decl.name().hash(state);
decl.hash(state, engines);
}
}

impl<T> PartialOrd for ParsedDeclId<T> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
Expand Down
2 changes: 2 additions & 0 deletions sway-core/src/ir_generation/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ fn convert_resolved_type_info(
TypeInfo::Custom { .. } => reject_type!("Custom"),
TypeInfo::Contract => reject_type!("Contract"),
TypeInfo::ContractCaller { .. } => reject_type!("ContractCaller"),
TypeInfo::UntypedEnum(_) => reject_type!("UntypedEnum"),
TypeInfo::UntypedStruct(_) => reject_type!("UntypedStruct"),
TypeInfo::Unknown => reject_type!("Unknown"),
TypeInfo::UnknownGeneric { .. } => reject_type!("Generic"),
TypeInfo::Placeholder(_) => reject_type!("Placeholder"),
Expand Down
4 changes: 3 additions & 1 deletion sway-core/src/semantic_analysis/namespace/trait_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,7 @@ impl TraitMap {
},
} in impls.iter()
{
if !type_info.can_change(decl_engine) && *type_id == *map_type_id {
if !type_info.can_change(engines) && *type_id == *map_type_id {
trait_map.insert_inner(
map_trait_name.clone(),
impl_span.clone(),
Expand Down Expand Up @@ -1542,6 +1542,8 @@ impl TraitMap {
Contract => TypeRootFilter::Contract,
ErrorRecovery(_) => TypeRootFilter::ErrorRecovery,
Tuple(fields) => TypeRootFilter::Tuple(fields.len()),
UntypedEnum(decl_id) => TypeRootFilter::Enum(*decl_id),
UntypedStruct(decl_id) => TypeRootFilter::Struct(*decl_id),
Enum(decl_id) => {
// TODO Remove unwrap once #6475 is fixed
TypeRootFilter::Enum(engines.de().get_parsed_decl_id(decl_id).unwrap())
Expand Down
2 changes: 2 additions & 0 deletions sway-core/src/semantic_analysis/node_dependencies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,8 @@ fn type_info_name(type_info: &TypeInfo) -> String {
TypeInfo::ContractCaller { abi_name, .. } => {
return format!("contract caller {abi_name}");
}
TypeInfo::UntypedEnum(_) => "untyped enum",
TypeInfo::UntypedStruct(_) => "untyped struct",
TypeInfo::Struct { .. } => "struct",
TypeInfo::Enum { .. } => "enum",
TypeInfo::Array(..) => "array",
Expand Down
2 changes: 1 addition & 1 deletion sway-core/src/semantic_analysis/type_check_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,7 @@ impl<'a> TypeCheckContext<'a> {
let coercion_check = UnifyCheck::coercion(self.engines);

// default numeric types to u64
if type_engine.contains_numeric(decl_engine, type_id) {
if type_engine.contains_numeric(self.engines, type_id) {
// While collecting unification we don't decay numeric and will ignore this error.
if self.collecting_unifications {
return Err(handler.emit_err(CompileError::MethodNotFound {
Expand Down
49 changes: 36 additions & 13 deletions sway-core/src/type_system/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,7 @@ impl TypeEngine {
});
match raw_entry {
RawEntryMut::Occupied(o) => return *o.get(),
RawEntryMut::Vacant(_) if ty.can_change(engines.de()) => {
TypeId::new(self.slab.insert(tsi))
}
RawEntryMut::Vacant(_) if ty.can_change(engines) => TypeId::new(self.slab.insert(tsi)),
RawEntryMut::Vacant(v) => {
let type_id = TypeId::new(self.slab.insert(tsi.clone()));
v.insert_with_hasher(ty_hash, tsi, type_id, make_hasher(&hash_builder, engines));
Expand Down Expand Up @@ -332,33 +330,48 @@ impl TypeEngine {
}

/// Return whether a given type still contains undecayed references to [TypeInfo::Numeric]
pub(crate) fn contains_numeric(&self, decl_engine: &DeclEngine, type_id: TypeId) -> bool {
pub(crate) fn contains_numeric(&self, engines: &Engines, type_id: TypeId) -> bool {
let decl_engine = engines.de();
match &&*self.get(type_id) {
TypeInfo::UntypedEnum(decl_id) => {
engines
.pe()
.get_enum(decl_id)
.variants
.iter()
.all(|variant_type| {
self.contains_numeric(engines, variant_type.type_argument.type_id)
})
}
TypeInfo::UntypedStruct(decl_id) => engines
.pe()
.get_struct(decl_id)
.fields
.iter()
.any(|field| self.contains_numeric(engines, field.type_argument.type_id)),
TypeInfo::Enum(decl_ref) => {
decl_engine
.get_enum(decl_ref)
.variants
.iter()
.all(|variant_type| {
self.contains_numeric(decl_engine, variant_type.type_argument.type_id)
self.contains_numeric(engines, variant_type.type_argument.type_id)
})
}
TypeInfo::Struct(decl_ref) => decl_engine
.get_struct(decl_ref)
.fields
.iter()
.any(|field| self.contains_numeric(decl_engine, field.type_argument.type_id)),
.any(|field| self.contains_numeric(engines, field.type_argument.type_id)),
TypeInfo::Tuple(fields) => fields
.iter()
.any(|field_type| self.contains_numeric(decl_engine, field_type.type_id)),
TypeInfo::Array(elem_ty, _length) => {
self.contains_numeric(decl_engine, elem_ty.type_id)
}
TypeInfo::Ptr(targ) => self.contains_numeric(decl_engine, targ.type_id),
TypeInfo::Slice(targ) => self.contains_numeric(decl_engine, targ.type_id),
.any(|field_type| self.contains_numeric(engines, field_type.type_id)),
TypeInfo::Array(elem_ty, _length) => self.contains_numeric(engines, elem_ty.type_id),
TypeInfo::Ptr(targ) => self.contains_numeric(engines, targ.type_id),
TypeInfo::Slice(targ) => self.contains_numeric(engines, targ.type_id),
TypeInfo::Ref {
referenced_type, ..
} => self.contains_numeric(decl_engine, referenced_type.type_id),
} => self.contains_numeric(engines, referenced_type.type_id),
TypeInfo::Unknown
| TypeInfo::Never
| TypeInfo::UnknownGeneric { .. }
Expand Down Expand Up @@ -393,6 +406,16 @@ impl TypeEngine {
let decl_engine = engines.de();

match &&*self.get(type_id) {
TypeInfo::UntypedEnum(decl_id) => {
for variant_type in &engines.pe().get_enum(decl_id).variants {
self.decay_numeric(handler, engines, variant_type.type_argument.type_id, span)?;
}
}
TypeInfo::UntypedStruct(decl_id) => {
for field in &engines.pe().get_struct(decl_id).fields {
self.decay_numeric(handler, engines, field.type_argument.type_id, span)?;
}
}
TypeInfo::Enum(decl_ref) => {
for variant_type in &decl_engine.get_enum(decl_ref).variants {
self.decay_numeric(handler, engines, variant_type.type_argument.type_id, span)?;
Expand Down
50 changes: 50 additions & 0 deletions sway-core/src/type_system/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,56 @@ impl TypeId {
| TypeInfo::Contract
| TypeInfo::ErrorRecovery(_)
| TypeInfo::TraitType { .. } => {}
TypeInfo::UntypedEnum(decl_id) => {
let enum_decl = engines.pe().get_enum(decl_id);
for type_param in &enum_decl.type_parameters {
extend(
&mut found,
type_param.type_id.extract_any_including_self(
engines,
filter_fn,
type_param.trait_constraints.clone(),
depth + 1,
),
);
}
for variant in &enum_decl.variants {
extend(
&mut found,
variant.type_argument.type_id.extract_any_including_self(
engines,
filter_fn,
vec![],
depth + 1,
),
);
}
}
TypeInfo::UntypedStruct(decl_id) => {
let struct_decl = engines.pe().get_struct(decl_id);
for type_param in &struct_decl.type_parameters {
extend(
&mut found,
type_param.type_id.extract_any_including_self(
engines,
filter_fn,
type_param.trait_constraints.clone(),
depth + 1,
),
);
}
for field in &struct_decl.fields {
extend(
&mut found,
field.type_argument.type_id.extract_any_including_self(
engines,
filter_fn,
vec![],
depth + 1,
),
);
}
}
TypeInfo::Enum(enum_ref) => {
let enum_decl = decl_engine.get_enum(enum_ref);
for type_param in &enum_decl.type_parameters {
Expand Down
Loading

0 comments on commit 1c3d9e1

Please sign in to comment.