Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
3 changes: 3 additions & 0 deletions sway-core/src/language/ty/expression/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,9 @@ impl TyExpression {
pub(crate) fn gather_mutability(&self) -> VariableMutability {
match &self.expression {
TyExpressionVariant::VariableExpression { mutability, .. } => *mutability,
TyExpressionVariant::ConstantExpression { .. } => VariableMutability::Immutable,
TyExpressionVariant::StructFieldAccess { prefix, .. }
| TyExpressionVariant::TupleElemAccess { prefix, .. } => prefix.gather_mutability(),
_ => VariableMutability::Immutable,
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,30 @@ pub(crate) fn type_check_method_application(
);
}

// check for matching mutability of arguments
for (index, arg) in args_buf.iter().enumerate() {
let param_index = if method.is_contract_call {
if index == 0 {
continue;
}
index - 1
Comment thread
cursor[bot] marked this conversation as resolved.
Outdated
} else {
index
};
if let Some(param) = method.parameters.get(param_index) {
if param.is_self() {
continue;
}
let param_mutability =
ty::VariableMutability::new_from_ref_mut(param.is_reference, param.is_mutable);
if param_mutability.is_mutable() && arg.gather_mutability().is_immutable() {
handler.emit_err(CompileError::ImmutableArgumentToMutableParameter {
span: arg.span.clone(),
});
}
}
}

// check the method visibility
if span.source_id() != method.span.source_id() && method.visibility.is_private() {
return Err(handler.emit_err(CompileError::CallingPrivateLibraryMethod {
Expand Down Expand Up @@ -1049,3 +1073,4 @@ pub(crate) fn monomorphize_method(

Ok(decl_ref)
}

3 changes: 2 additions & 1 deletion sway-lib-std/src/hash.sw
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ impl Hasher {
/// Note that the length of `bytes` is not appended to the
/// `Hasher`, just the content.
pub fn write(ref mut self, bytes: Bytes) {
self.bytes.append(bytes);
let mut b = bytes;
self.bytes.append(b);
}

/// Appends bytes from the `slice` to this `Hasher`.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[[package]]
name = "ref_mut_method_mismatch"
source = "member"
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[project]
authors = ["Fuel Labs <contact@fuel.sh>"]
entry = "main.sw"
license = "Apache-2.0"
name = "ref_mut_method_mismatch"
implicit-std = false
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
script;

struct Point {
x: u64,
y: u64,
}

impl Point {
fn mutate(self, ref mut _v: u64) { }
}

const MY_CONST: u64 = 10;

fn main() {
// immutable variable
let x = 42u64;
Point { x: 1, y: 2 }.mutate(x);

// struct field access on immutable binding
let p = Point { x: 1, y: 2 };
Point { x: 1, y: 2 }.mutate(p.x);

// tuple element access on immutable binding
let t = (1u64, 2u64);
Point { x: 1, y: 2 }.mutate(t.0);

// constant
Point { x: 1, y: 2 }.mutate(MY_CONST);

// mutable variable — should NOT error
let mut m = 99u64;
Point { x: 1, y: 2 }.mutate(m);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
category = "fail"

# immutable variable
# check: $()Point { x: 1, y: 2 }.mutate(x);
# nextln: $()Cannot pass immutable argument to mutable parameter.

# struct field access
# check: $()Point { x: 1, y: 2 }.mutate(p.x);
# nextln: $()Cannot pass immutable argument to mutable parameter.

# tuple element access
# check: $()Point { x: 1, y: 2 }.mutate(t.0);
# nextln: $()Cannot pass immutable argument to mutable parameter.

# constant
# check: $()Point { x: 1, y: 2 }.mutate(MY_CONST);
# nextln: $()Cannot pass immutable argument to mutable parameter.
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ pub fn run_all_tests() -> u64 {
assert(items_1_trait_teststruct_1_res);


let hasher = mk_hasher();
let mut hasher = mk_hasher();
teststruct_1.hash(hasher);


Expand Down
Loading