Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TypeInfo::UntypedEnum and TypeInfo::UntypedStruct. #6633

Merged
merged 4 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -882,7 +882,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 @@ -1548,6 +1548,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 @@ -820,7 +820,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
Loading