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

ctx tweak #703

Merged
merged 1 commit into from
Jun 1, 2022
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
27 changes: 0 additions & 27 deletions crates/analyzer/src/namespace/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,33 +379,6 @@ pub struct EventField {
pub is_indexed: bool,
}

impl FunctionSignature {
/// Parameters without `ctx`, if it is a contract function that declares it.
///
/// This is used when calling a contract method externally.
pub fn external_params(&self) -> &[FunctionParam] {
if self.ctx_decl.is_some() {
&self.params[1..]
} else {
&self.params
}
}

/// Parameter types without `ctx`, if it is a contract function that
/// declares it.
///
/// This is used when calling a contract method externally.
///
/// # Panics
/// Panics if any param type is an `Err`
pub fn external_param_types(&self) -> Vec<Type> {
self.external_params()
.iter()
.map(|param| param.typ.clone().expect("fn param type error"))
.collect()
}
}

impl Type {
pub fn name(&self) -> SmolStr {
match self {
Expand Down
1 change: 1 addition & 0 deletions crates/analyzer/src/traversal/call_args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ pub fn validate_named_args(
params: &[impl LabeledParameter],
) -> Result<(), FatalError> {
validate_arg_count(context, name, name_span, args, params.len(), "argument");
// TODO: if the first arg is missing, every other arg will get a label and type error

for (index, (param, arg)) in params.iter().zip(args.kind.iter()).enumerate() {
let expected_label = param.label();
Expand Down
68 changes: 8 additions & 60 deletions crates/analyzer/src/traversal/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1147,15 +1147,9 @@ fn expr_call_type_constructor(
_ => {}
}

if matches!(typ, Type::Contract(_)) {
validate_arg_count(context, &format!("{}", typ), name_span, args, 2, "argument");
expect_no_label_on_arg(context, args, 0);
expect_no_label_on_arg(context, args, 1);
} else {
// These all expect 1 arg, for now.
validate_arg_count(context, &format!("{}", typ), name_span, args, 1, "argument");
expect_no_label_on_arg(context, args, 0);
}
// These all expect 1 arg, for now.
validate_arg_count(context, &format!("{}", typ), name_span, args, 1, "argument");
expect_no_label_on_arg(context, args, 0);

let expr_attrs = match &typ {
Type::String(string_type) => {
Expand All @@ -1166,50 +1160,10 @@ fn expr_call_type_constructor(
ExpressionAttributes::new(typ.clone(), Location::Memory)
}
Type::Contract(_) => {
if let Some(first_arg) = &args.kind.get(0) {
let first_arg_attr = assignable_expr(context, &first_arg.kind.value, None)?;
if let Some(context_type) = context.get_context_type() {
if first_arg_attr.typ != Type::Struct(context_type.clone()) {
context.type_error(
"type mismatch",
first_arg.span,
&context_type,
&first_arg_attr.typ,
);
}
} else {
context.fancy_error(
"`Context` is not defined",
vec![
Label::primary(
args.span,
"`ctx` must be defined and passed into the contract constructor",
),
Label::secondary(
context.parent_function().name_span(context.db()),
"Note: declare `ctx` in this function signature",
),
Label::secondary(
context.parent_function().name_span(context.db()),
"Example: `pub fn foo(ctx: Context, ...)`",
),
],
vec![
"Note: import context with `use std::context::Context`".into(),
"Example: MyContract(ctx, contract_address)".into(),
],
);
}
}
if let Some(second_arg) = &args.kind.get(1) {
let second_arg_attr = assignable_expr(context, &second_arg.kind.value, None)?;
if second_arg_attr.typ != Type::Base(Base::Address) {
context.type_error(
"type mismatch",
second_arg.span,
&Base::Address,
&second_arg_attr.typ,
);
if let Some(arg) = &args.kind.get(0) {
let arg_attr = assignable_expr(context, &arg.kind.value, None)?;
if arg_attr.typ != Type::Base(Base::Address) {
context.type_error("type mismatch", arg.span, &Base::Address, &arg_attr.typ);
}
}
ExpressionAttributes::new(typ.clone(), Location::Value)
Expand Down Expand Up @@ -1397,13 +1351,7 @@ fn expr_call_method(
}

let sig = method.signature(context.db());

let params = if is_self {
&sig.params
} else {
sig.external_params()
};
validate_named_args(context, &field.kind, field.span, args, params)?;
validate_named_args(context, &field.kind, field.span, args, &sig.params)?;

let calltype = match class {
Class::Contract(contract) => {
Expand Down
3 changes: 1 addition & 2 deletions crates/analyzer/tests/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ test_stmt! { break_without_loop, "break" }
test_stmt! { break_without_loop_2, "if true { break }" }
test_stmt! { call_undefined_function_on_contract, "self.doesnt_exist()" }
test_stmt! { call_address_with_wrong_type, "address(true)" }
test_stmt! { call_address_with_label, "address(val: 0)" }
test_stmt! { call_keccak_without_parameter, "keccak256()" }
test_stmt! { call_keccak_with_wrong_type, "keccak256(true)" }
test_stmt! { call_keccak_with_2_args, "keccak256(1, 2)" }
Expand Down Expand Up @@ -323,12 +324,10 @@ test_file! { ctx_init }
test_file! { ctx_pure }
test_file! { ctx_undeclared }
test_file! { ctx_missing_internal_call }
test_file! { ctx_passed_external_call }
test_file! { ctx_missing_create }
test_file! { ctx_missing_load }
test_file! { ctx_missing_event }
test_file! { ctx_builtins_param_incorrect_type }
test_file! { ctx_undefined_contract_init }
test_file! { ctx_undefined_create }
test_file! { ctx_undefined_create2 }
test_file! { ctx_undefined_event }
65 changes: 24 additions & 41 deletions crates/analyzer/tests/snapshots/analysis__external_contract.snap
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,8 @@ note:
┌─ external_contract.fe:24:5
24 │ ╭ pub fn call_emit_event(ctx: Context, foo_address: address, my_num: u256, my_addrs: Array<address, 5>, my_string: String<11>) {
25 │ │ let foo: Foo = Foo(ctx, foo_address)
26 │ │ foo.emit_event(my_num, my_addrs, my_string)
25 │ │ let foo: Foo = Foo(foo_address)
26 │ │ foo.emit_event(ctx, my_num, my_addrs, my_string)
27 │ │ }
│ ╰─────^ attributes hash: 11744736773867210426
Expand Down Expand Up @@ -324,62 +324,47 @@ note:
note:
┌─ external_contract.fe:25:13
25let foo: Foo = Foo(ctx, foo_address)
25let foo: Foo = Foo(foo_address)
^^^ Foo

note:
┌─ external_contract.fe:25:28
25let foo: Foo = Foo(ctx, foo_address)
^^^ ^^^^^^^^^^^ address: Value
│ │
Context: Memory
25let foo: Foo = Foo(foo_address)
^^^^^^^^^^^ address: Value

note:
┌─ external_contract.fe:25:24
25let foo: Foo = Foo(ctx, foo_address)
^^^^^^^^^^^^^^^^^^^^^ Foo: Value
26foo.emit_event(my_num, my_addrs, my_string)
^^^ ^^^^^^ ^^^^^^^^ ^^^^^^^^^ String<11>: Memory
│ │ │ │
│ │ │ Array<address, 5>: Memory
│ │ u256: Value
25let foo: Foo = Foo(foo_address)
^^^^^^^^^^^^^^^^ Foo: Value
26foo.emit_event(ctx, my_num, my_addrs, my_string)
^^^ ^^^ ^^^^^^ ^^^^^^^^ ^^^^^^^^^ String<11>: Memory
│ │ │ │ │
│ │ │ │ Array<address, 5>: Memory
│ │ │ u256: Value
│ │ Context: Memory
Foo: Value

note:
┌─ external_contract.fe:26:9
26foo.emit_event(my_num, my_addrs, my_string)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (): Value
26foo.emit_event(ctx, my_num, my_addrs, my_string)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (): Value

note:
┌─ external_contract.fe:29:5
29 │ ╭ pub fn call_build_array(ctx: Context, foo_address: address, a: u256, b: u256) -> Array<u256, 3> {
30 │ │ let foo: Foo = Foo(ctx, foo_address)
29 │ ╭ pub fn call_build_array(foo_address: address, a: u256, b: u256) -> Array<u256, 3> {
30 │ │ let foo: Foo = Foo(foo_address)
31 │ │ return foo.build_array(a, b)
32 │ │ }
│ ╰─────^ attributes hash: 14801245347360386258
│ ╰─────^ attributes hash: 4627171240003453976
= FunctionSignature {
self_decl: None,
ctx_decl: Some(
Mutable,
),
ctx_decl: None,
params: [
FunctionParam {
label: None,
name: "ctx",
typ: Ok(
Struct(
Struct {
name: "Context",
field_count: 0,
},
),
),
},
FunctionParam {
label: None,
name: "foo_address",
Expand Down Expand Up @@ -427,22 +412,20 @@ note:
note:
┌─ external_contract.fe:30:13
30let foo: Foo = Foo(ctx, foo_address)
30let foo: Foo = Foo(foo_address)
^^^ Foo

note:
┌─ external_contract.fe:30:28
30let foo: Foo = Foo(ctx, foo_address)
^^^ ^^^^^^^^^^^ address: Value
│ │
Context: Memory
30let foo: Foo = Foo(foo_address)
^^^^^^^^^^^ address: Value

note:
┌─ external_contract.fe:30:24
30let foo: Foo = Foo(ctx, foo_address)
^^^^^^^^^^^^^^^^^^^^^ Foo: Value
30let foo: Foo = Foo(foo_address)
^^^^^^^^^^^^^^^^ Foo: Value
31return foo.build_array(a, b)
^^^ ^ ^ u256: Value
│ │ │
Expand Down
35 changes: 10 additions & 25 deletions crates/analyzer/tests/snapshots/analysis__two_contracts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -159,31 +159,17 @@ note:
note:
┌─ two_contracts.fe:23:5
23 │ ╭ pub fn set_foo_addr(self, ctx: Context, _ addr: address) {
24 │ │ self.other = Foo(ctx, addr)
23 │ ╭ pub fn set_foo_addr(self, _ addr: address) {
24 │ │ self.other = Foo(addr)
25 │ │ }
│ ╰─────^ attributes hash: 736575608159807992
│ ╰─────^ attributes hash: 3263176293298741376
= FunctionSignature {
self_decl: Some(
Mutable,
),
ctx_decl: Some(
Mutable,
),
ctx_decl: None,
params: [
FunctionParam {
label: None,
name: "ctx",
typ: Ok(
Struct(
Struct {
name: "Context",
field_count: 0,
},
),
),
},
FunctionParam {
label: Some(
"_",
Expand All @@ -206,23 +192,22 @@ note:
note:
┌─ two_contracts.fe:24:9
24self.other = Foo(ctx, addr)
24self.other = Foo(addr)
^^^^ Bar: Value

note:
┌─ two_contracts.fe:24:9
24self.other = Foo(ctx, addr)
^^^^^^^^^^ ^^^ ^^^^ address: Value
│ │ │
│ │ Context: Memory
24self.other = Foo(addr)
^^^^^^^^^^ ^^^^ address: Value
│ │
Foo: Storage { nonce: Some(0) }

note:
┌─ two_contracts.fe:24:22
24self.other = Foo(ctx, addr)
^^^^^^^^^^^^^^ Foo: Value
24self.other = Foo(addr)
^^^^^^^^^ Foo: Value

note:
┌─ two_contracts.fe:27:5
Expand Down
Loading