-
Notifications
You must be signed in to change notification settings - Fork 432
/
snapshot.rs
89 lines (84 loc) · 3.09 KB
/
snapshot.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
use crate::extensions::lib_func::{
LibfuncSignature, OutputVarInfo, ParamSignature, SierraApChange, SignatureOnlyGenericLibfunc,
SignatureSpecializationContext,
};
use crate::extensions::type_specialization_context::TypeSpecializationContext;
use crate::extensions::types::{
GenericTypeArgGenericType, GenericTypeArgGenericTypeWrapper, TypeInfo,
};
use crate::extensions::{
args_as_single_type, NamedType, OutputVarReferenceInfo, SpecializationError,
};
use crate::ids::{ConcreteTypeId, GenericTypeId};
use crate::program::GenericArg;
/// Type for a type's snapshot.
#[derive(Default)]
pub struct SnapshotTypeWrapped {}
impl GenericTypeArgGenericType for SnapshotTypeWrapped {
const ID: GenericTypeId = GenericTypeId::new_inline("Snapshot");
fn calc_info(
&self,
_context: &dyn TypeSpecializationContext,
long_id: crate::program::ConcreteTypeLongId,
TypeInfo { zero_sized, storable, duplicatable, .. }: TypeInfo,
) -> Result<TypeInfo, SpecializationError> {
// Duplicatable types are their own snapshot - as the snapshot itself is useless if we can
// dup the value already.
if storable && !duplicatable {
Ok(TypeInfo {
long_id,
zero_sized,
storable: true,
droppable: true,
duplicatable: true,
})
} else {
Err(SpecializationError::UnsupportedGenericArg)
}
}
}
pub type SnapshotType = GenericTypeArgGenericTypeWrapper<SnapshotTypeWrapped>;
/// Returns the type snapshot for a given type `T`.
/// For duplicatable returns `T` itself, as a regular dup is already a snapshot.
pub fn snapshot_ty(
context: &dyn SignatureSpecializationContext,
ty: ConcreteTypeId,
) -> Result<ConcreteTypeId, SpecializationError> {
if context.get_type_info(ty.clone())?.duplicatable {
Ok(ty)
} else {
context.get_wrapped_concrete_type(SnapshotType::id(), ty)
}
}
/// Libfunc for taking a snapshot `Snapshot<T>` from a T.
#[derive(Default)]
pub struct SnapshotTakeLibfunc {}
impl SignatureOnlyGenericLibfunc for SnapshotTakeLibfunc {
const STR_ID: &'static str = "snapshot_take";
fn specialize_signature(
&self,
context: &dyn SignatureSpecializationContext,
args: &[GenericArg],
) -> Result<LibfuncSignature, SpecializationError> {
let ty = args_as_single_type(args)?;
Ok(LibfuncSignature::new_non_branch_ex(
vec![ParamSignature {
ty: ty.clone(),
allow_deferred: true,
allow_add_const: true,
allow_const: true,
}],
vec![
OutputVarInfo {
ty: ty.clone(),
ref_info: OutputVarReferenceInfo::SameAsParam { param_idx: 0 },
},
OutputVarInfo {
ty: snapshot_ty(context, ty)?,
ref_info: OutputVarReferenceInfo::SameAsParam { param_idx: 0 },
},
],
SierraApChange::Known { new_vars_only: true },
))
}
}