Skip to content

Commit

Permalink
Extend #[deprecated] support
Browse files Browse the repository at this point in the history
Add support for the `#[deprecated]` attribute to functions, enums,
struct items, enum variants and propagate deprecation check exhaustively
throughout expressions variants.

Partially addresses #6942.

Support for deprecating traits, abis and the methods thereof in their
definitions is still missing, as well as scrutinees and storage fields.
  • Loading branch information
IGI-111 committed Feb 24, 2025
1 parent 69ac39e commit 170f80f
Show file tree
Hide file tree
Showing 10 changed files with 348 additions and 24 deletions.
15 changes: 14 additions & 1 deletion sway-core/src/language/ty/code_block.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
decl_engine::*, engine_threading::*, language::ty::*, semantic_analysis::TypeCheckContext,
type_system::*,
transform::AllowDeprecatedState, type_system::*,
};
use serde::{Deserialize, Serialize};
use std::hash::Hasher;
Expand All @@ -13,6 +13,19 @@ pub struct TyCodeBlock {
pub(crate) whole_block_span: Span,
}

impl TyCodeBlock {
pub(crate) fn check_deprecated(
&self,
engines: &Engines,
handler: &Handler,
allow_deprecated: &mut AllowDeprecatedState,
) {
for n in self.contents.iter() {
n.check_deprecated(engines, handler, allow_deprecated);
}
}
}

impl Default for TyCodeBlock {
fn default() -> Self {
Self {
Expand Down
215 changes: 198 additions & 17 deletions sway-core/src/language/ty/expression/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,81 @@ impl TyExpression {
}

match &self.expression {
TyExpressionVariant::Literal(..) => {}
TyExpressionVariant::FunctionApplication {
call_path,
fn_ref,
arguments,
..
} => {
for (_, expr) in arguments.iter() {
expr.check_deprecated(engines, handler, allow_deprecated);
}

let fn_ty = engines.de().get(fn_ref);
if let Some(TyDecl::ImplSelfOrTrait(t)) = &fn_ty.implementing_type {
let t = &engines.de().get(&t.decl_id).implementing_for;
if let TypeInfo::Struct(struct_id) = &*engines.te().get(t.type_id) {
let s = engines.de().get(struct_id);
emit_warning_if_deprecated(
&s.attributes,
&call_path.span(),
handler,
"deprecated struct",
allow_deprecated,
);
}
}

emit_warning_if_deprecated(
&fn_ty.attributes,
&call_path.span(),
handler,
"deprecated function",
allow_deprecated,
);
}
TyExpressionVariant::LazyOperator { lhs, rhs, .. } => {
lhs.check_deprecated(engines, handler, allow_deprecated);
rhs.check_deprecated(engines, handler, allow_deprecated);
}
TyExpressionVariant::ConstantExpression { span, decl, .. } => {
emit_warning_if_deprecated(
&decl.attributes,
span,
handler,
"deprecated constant",
allow_deprecated,
);
}
TyExpressionVariant::ConfigurableExpression { span, decl, .. } => {
emit_warning_if_deprecated(
&decl.attributes,
span,
handler,
"deprecated configurable",
allow_deprecated,
);
}
TyExpressionVariant::VariableExpression { .. } => {}
TyExpressionVariant::Tuple { fields } => {
for e in fields.iter() {
e.check_deprecated(engines, handler, allow_deprecated);
}
}
TyExpressionVariant::ArrayExplicit { contents, .. } => {
for e in contents.iter() {
e.check_deprecated(engines, handler, allow_deprecated);
}
}
TyExpressionVariant::ArrayRepeat { value, length, .. } => {
value.check_deprecated(engines, handler, allow_deprecated);
length.check_deprecated(engines, handler, allow_deprecated);
}
TyExpressionVariant::ArrayIndex { prefix, index } => {
prefix.check_deprecated(engines, handler, allow_deprecated);
index.check_deprecated(engines, handler, allow_deprecated);
}
TyExpressionVariant::StructExpression {
struct_id,
instantiation_span,
Expand All @@ -451,26 +526,132 @@ impl TyExpression {
allow_deprecated,
);
}
TyExpressionVariant::FunctionApplication {
call_path, fn_ref, ..
TyExpressionVariant::CodeBlock(block) => {
block.check_deprecated(engines, handler, allow_deprecated);
}
TyExpressionVariant::FunctionParameter => {}
TyExpressionVariant::MatchExp {
desugared,
//scrutinees,
..
} => {
if let Some(TyDecl::ImplSelfOrTrait(t)) =
&engines.de().get(fn_ref).implementing_type
{
let t = &engines.de().get(&t.decl_id).implementing_for;
if let TypeInfo::Struct(struct_id) = &*engines.te().get(t.type_id) {
let s = engines.de().get(struct_id);
emit_warning_if_deprecated(
&s.attributes,
&call_path.span(),
handler,
"deprecated struct",
allow_deprecated,
);
}
desugared.check_deprecated(engines, handler, allow_deprecated);
// TODO: check scrutinees if necessary
}
TyExpressionVariant::IfExp {
condition,
then,
r#else,
} => {
condition.check_deprecated(engines, handler, allow_deprecated);
then.check_deprecated(engines, handler, allow_deprecated);
if let Some(e) = r#else {
e.check_deprecated(engines, handler, allow_deprecated);
}
}
_ => {}
TyExpressionVariant::AsmExpression { .. } => {}
TyExpressionVariant::StructFieldAccess {
prefix,
field_to_access,
field_instantiation_span,
..
} => {
prefix.check_deprecated(engines, handler, allow_deprecated);
emit_warning_if_deprecated(
&field_to_access.attributes,
field_instantiation_span,
handler,
"deprecated struct field",
allow_deprecated,
);
}
TyExpressionVariant::TupleElemAccess { prefix, .. } => {
prefix.check_deprecated(engines, handler, allow_deprecated);
}
TyExpressionVariant::EnumInstantiation {
enum_ref,
tag,
contents,
variant_instantiation_span,
..
} => {
let enum_ty = engines.de().get(enum_ref);
emit_warning_if_deprecated(
&enum_ty.attributes,
variant_instantiation_span,
handler,
"deprecated enum",
allow_deprecated,
);
if let Some(variant_decl) = enum_ty.variants.get(*tag) {
emit_warning_if_deprecated(
&variant_decl.attributes,
variant_instantiation_span,
handler,
"deprecated enum variant",
allow_deprecated,
);
}
if let Some(expr) = contents {
expr.check_deprecated(engines, handler, allow_deprecated);
}
}
TyExpressionVariant::AbiCast { address, .. } => {
// TODO: check abi name?
address.check_deprecated(engines, handler, allow_deprecated);
}
TyExpressionVariant::StorageAccess(access) => {
// TODO: check storage access?
if let Some(expr) = &access.key_expression {
expr.check_deprecated(engines, handler, allow_deprecated);
}
}
TyExpressionVariant::IntrinsicFunction(kind) => {
for arg in kind.arguments.iter() {
arg.check_deprecated(engines, handler, allow_deprecated);
}
}
TyExpressionVariant::AbiName(..) => {}
TyExpressionVariant::EnumTag { exp } => {
exp.check_deprecated(engines, handler, allow_deprecated);
}
TyExpressionVariant::UnsafeDowncast {
exp,
//variant,
..
} => {
exp.check_deprecated(engines, handler, allow_deprecated);
// TODO: maybe check variant?
}
TyExpressionVariant::WhileLoop { condition, body } => {
condition.check_deprecated(engines, handler, allow_deprecated);
body.check_deprecated(engines, handler, allow_deprecated);
}
TyExpressionVariant::ForLoop { desugared } => {
desugared.check_deprecated(engines, handler, allow_deprecated);
}
TyExpressionVariant::Break => {}
TyExpressionVariant::Continue => {}
TyExpressionVariant::Reassignment(reass) => {
if let TyReassignmentTarget::Deref(expr) = &reass.lhs {
expr.check_deprecated(engines, handler, allow_deprecated);
}
reass
.rhs
.check_deprecated(engines, handler, allow_deprecated);
}
TyExpressionVariant::ImplicitReturn(expr) => {
expr.check_deprecated(engines, handler, allow_deprecated);
}
TyExpressionVariant::Return(expr) => {
expr.check_deprecated(engines, handler, allow_deprecated);
}
TyExpressionVariant::Ref(expr) => {
expr.check_deprecated(engines, handler, allow_deprecated);
}
TyExpressionVariant::Deref(expr) => {
expr.check_deprecated(engines, handler, allow_deprecated);
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions sway-lib-std/src/ecr.sw
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ pub fn ed_verify(public_key: b256, signature: B512, msg: Bytes) -> Result<bool,
/// }
/// ```
#[deprecated(note = "std::ecr has been replaced by std::crypto, and is no longer maintained")]
#[allow(deprecated)]
pub fn ec_recover_address(signature: B512, msg_hash: b256) -> Result<Address, EcRecoverError> {
let pub_key_result = ec_recover(signature, msg_hash);

Expand Down Expand Up @@ -263,6 +264,7 @@ pub fn ec_recover_address(signature: B512, msg_hash: b256) -> Result<Address, Ec
/// }
/// ```
#[deprecated(note = "std::ecr has been replaced by std::crypto, and is no longer maintained")]
#[allow(deprecated)]
pub fn ec_recover_address_r1(signature: B512, msg_hash: b256) -> Result<Address, EcRecoverError> {
let pub_key_result = ec_recover_r1(signature, msg_hash);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ output:
Building test/src/e2e_vm_tests/test_programs/should_fail/array_wrong_elements_types
Compiling library core (sway-lib-core)
Compiling library std (sway-lib-std)
warning
--> sway-lib-std/src/vm/evm/ecr.sw:43:26
|
41 | msg_hash: b256,
42 | ) -> Result<EvmAddress, EcRecoverError> {
43 | let pub_key_result = ec_recover(signature, msg_hash);
| ---------- deprecated function: std::ecr has been replaced by std::crypto, and is no longer maintained
44 |
45 | match pub_key_result {
|
____

Compiled library "std" with 1 warning.
Compiling script array_wrong_elements_types (test/src/e2e_vm_tests/test_programs/should_fail/array_wrong_elements_types)
error
--> test/src/e2e_vm_tests/test_programs/should_fail/array_wrong_elements_types/src/main.sw:41:27
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ output:
Building test/src/e2e_vm_tests/test_programs/should_fail/contract_implements_multiple_abis_with_same_methods
Compiling library core (sway-lib-core)
Compiling library std (sway-lib-std)
warning
--> sway-lib-std/src/vm/evm/ecr.sw:43:26
|
41 | msg_hash: b256,
42 | ) -> Result<EvmAddress, EcRecoverError> {
43 | let pub_key_result = ec_recover(signature, msg_hash);
| ---------- deprecated function: std::ecr has been replaced by std::crypto, and is no longer maintained
44 |
45 | match pub_key_result {
|
____

Compiled library "std" with 1 warning.
Compiling contract contract_implements_multiple_abis_with_same_methods (test/src/e2e_vm_tests/test_programs/should_fail/contract_implements_multiple_abis_with_same_methods)
error: Multiple contracts methods with the same name.
--> test/src/e2e_vm_tests/test_programs/should_fail/contract_implements_multiple_abis_with_same_methods/src/main.sw:14:8
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ output:
Building test/src/e2e_vm_tests/test_programs/should_fail/language/const_generics
Compiling library core (sway-lib-core)
Compiling library std (sway-lib-std)
warning
--> sway-lib-std/src/vm/evm/ecr.sw:43:26
|
41 | msg_hash: b256,
42 | ) -> Result<EvmAddress, EcRecoverError> {
43 | let pub_key_result = ec_recover(signature, msg_hash);
| ---------- deprecated function: std::ecr has been replaced by std::crypto, and is no longer maintained
44 |
45 | match pub_key_result {
|
____

Compiled library "std" with 1 warning.
Compiling script const_generics (test/src/e2e_vm_tests/test_programs/should_fail/language/const_generics)
error
--> test/src/e2e_vm_tests/test_programs/should_fail/language/const_generics/src/main.sw:7:15
Expand All @@ -29,6 +42,19 @@ output:
Building test/src/e2e_vm_tests/test_programs/should_fail/language/const_generics
Compiling library core (sway-lib-core)
Compiling library std (sway-lib-std)
warning
--> sway-lib-std/src/vm/evm/ecr.sw:43:26
|
41 | msg_hash: b256,
42 | ) -> Result<EvmAddress, EcRecoverError> {
43 | let pub_key_result = ec_recover(signature, msg_hash);
| ---------- deprecated function: std::ecr has been replaced by std::crypto, and is no longer maintained
44 |
45 | match pub_key_result {
|
____

Compiled library "std" with 1 warning.
Compiling script const_generics (test/src/e2e_vm_tests/test_programs/should_fail/language/const_generics)
error
--> test/src/e2e_vm_tests/test_programs/should_fail/language/const_generics/src/main.sw:7:15
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ output:
Building test/src/e2e_vm_tests/test_programs/should_fail/type_check_analyze_errors
Compiling library core (sway-lib-core)
Compiling library std (sway-lib-std)
warning
--> sway-lib-std/src/vm/evm/ecr.sw:43:26
|
41 | msg_hash: b256,
42 | ) -> Result<EvmAddress, EcRecoverError> {
43 | let pub_key_result = ec_recover(signature, msg_hash);
| ---------- deprecated function: std::ecr has been replaced by std::crypto, and is no longer maintained
44 |
45 | match pub_key_result {
|
____

Compiled library "std" with 1 warning.
Compiling script type_check_analyze_errors (test/src/e2e_vm_tests/test_programs/should_fail/type_check_analyze_errors)
error
--> test/src/e2e_vm_tests/test_programs/should_fail/type_check_analyze_errors/src/main.sw:5:14
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,19 @@ output:
library {
}

warning
--> sway-lib-std/src/vm/evm/ecr.sw:43:26
|
41 | msg_hash: b256,
42 | ) -> Result<EvmAddress, EcRecoverError> {
43 | let pub_key_result = ec_recover(signature, msg_hash);
| ---------- deprecated function: std::ecr has been replaced by std::crypto, and is no longer maintained
44 |
45 | match pub_key_result {
|
____

Compiled library "std" with 1 warning.
Compiling script configurable_dedup_decode (test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_dedup_decode)
// IR: Final
script {
Expand Down
Loading

0 comments on commit 170f80f

Please sign in to comment.