diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs index d0081fba437..09461c86d88 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs @@ -732,6 +732,15 @@ impl ty::TyExpression { span, } } + // `self` and `Self` are inserted into the namespace as a generic type parameter + // (`GenericTypeForFunctionScope`). When `self` is used as a value but the enclosing + // function has no `self` parameter, resolution falls through to that type parameter. + // Reporting it as "actually a generic type parameter" is misleading, so emit a + // dedicated error pointing at the missing `self` parameter instead. + Some(ty::TyDecl::GenericTypeForFunctionScope(_)) if name.as_str() == "self" => { + let err = handler.emit_err(CompileError::SelfParameterNotAvailable { span }); + ty::TyExpression::error(err, name.span(), engines) + } Some(a) => { let err = handler.emit_err(CompileError::NotAVariable { name: name.clone(), diff --git a/sway-error/src/error.rs b/sway-error/src/error.rs index 2fdb25dfcc4..f8183e893e2 100644 --- a/sway-error/src/error.rs +++ b/sway-error/src/error.rs @@ -83,6 +83,10 @@ pub enum CompileError { what_it_is: &'static str, span: Span, }, + #[error( + "\"self\" is not available here because the enclosing function does not have a \"self\" parameter." + )] + SelfParameterNotAvailable { span: Span }, #[error("{feature} is currently not implemented.")] Unimplemented { /// The description of the unimplemented feature, @@ -1261,6 +1265,7 @@ impl Spanned for CompileError { ModuleDepGraphCyclicReference { .. } => Span::dummy(), UnknownVariable { span, .. } => span.clone(), NotAVariable { span, .. } => span.clone(), + SelfParameterNotAvailable { span, .. } => span.clone(), Unimplemented { span, .. } => span.clone(), TypeError(err) => err.span(), ParseError { span, .. } => span.clone(), diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/self_used_without_self_parameter/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_fail/self_used_without_self_parameter/Forc.lock new file mode 100644 index 00000000000..8492fd22f24 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/self_used_without_self_parameter/Forc.lock @@ -0,0 +1,3 @@ +[[package]] +name = 'self_used_without_self_parameter' +source = 'member' diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/self_used_without_self_parameter/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_fail/self_used_without_self_parameter/Forc.toml new file mode 100644 index 00000000000..82631962e21 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/self_used_without_self_parameter/Forc.toml @@ -0,0 +1,6 @@ +[project] +name = "self_used_without_self_parameter" +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +implicit-std = false diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/self_used_without_self_parameter/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_fail/self_used_without_self_parameter/src/main.sw new file mode 100644 index 00000000000..b7752d34441 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/self_used_without_self_parameter/src/main.sw @@ -0,0 +1,17 @@ +library; + +struct S {} + +impl S { + fn use_self_method() { + let _ = self.x(); + } + + fn use_self_value() { + let _ = self; + } + + fn x(self) -> u64 { + 0 + } +} diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/self_used_without_self_parameter/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/self_used_without_self_parameter/test.toml new file mode 100644 index 00000000000..fa5a9d67c5d --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/self_used_without_self_parameter/test.toml @@ -0,0 +1,7 @@ +category = "fail" + +# check: $()let _ = self.x(); +# nextln: $()"self" is not available here because the enclosing function does not have a "self" parameter. + +# check: $()let _ = self; +# nextln: $()"self" is not available here because the enclosing function does not have a "self" parameter.