diff --git a/doc/data/messages/f/function-return-not-assigned/bad.py b/doc/data/messages/f/function-return-not-assigned/bad.py
new file mode 100644
index 0000000000..779ce785d5
--- /dev/null
+++ b/doc/data/messages/f/function-return-not-assigned/bad.py
@@ -0,0 +1,5 @@
+def return_int():
+ return 1
+
+
+return_int() # [function-return-not-assigned]
diff --git a/doc/data/messages/f/function-return-not-assigned/good.py b/doc/data/messages/f/function-return-not-assigned/good.py
new file mode 100644
index 0000000000..f409a51e16
--- /dev/null
+++ b/doc/data/messages/f/function-return-not-assigned/good.py
@@ -0,0 +1,5 @@
+def return_int():
+ return 1
+
+
+_ = return_int()
diff --git a/doc/whatsnew/fragments/7935.new_check b/doc/whatsnew/fragments/7935.new_check
new file mode 100644
index 0000000000..9d80757362
--- /dev/null
+++ b/doc/whatsnew/fragments/7935.new_check
@@ -0,0 +1,3 @@
+Add ``FunctionReturnNotAssignedChecker`` extension and new ``function-return-not-assigned`` message if return value not used.
+
+Refs #7935
diff --git a/pylint/extensions/function_return_not_assigned.py b/pylint/extensions/function_return_not_assigned.py
new file mode 100644
index 0000000000..3fe3dd8d86
--- /dev/null
+++ b/pylint/extensions/function_return_not_assigned.py
@@ -0,0 +1,91 @@
+# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+# For details: https://github.com/pylint-dev/pylint/blob/main/LICENSE
+# Copyright (c) https://github.com/pylint-dev/pylint/blob/main/CONTRIBUTORS.txt
+
+"""Looks for unassigned function/method calls that have non-nullable return type."""
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+import astroid
+from astroid import nodes
+
+from pylint.checkers import BaseChecker
+from pylint.checkers.typecheck import TypeChecker
+from pylint.checkers.utils import only_required_for_messages, safe_infer
+
+if TYPE_CHECKING:
+ from pylint.lint import PyLinter
+
+
+class FunctionReturnNotAssignedChecker(BaseChecker):
+ name = "function_return_not_assigned"
+ msgs = {
+ "W5486": (
+ "Function returned value which is never used",
+ "function-return-not-assigned",
+ "Function returns non-nullable value which is never used. "
+ "Use explicit `_ = func_call()` if you are not interested in returned value",
+ )
+ }
+
+ @only_required_for_messages("function-return-not-assigned")
+ def visit_call(self, node: nodes.Call) -> None:
+ result_is_used = not isinstance(node.parent, nodes.Expr)
+
+ if result_is_used:
+ return
+
+ function_node = safe_infer(node.func)
+ funcs = (nodes.FunctionDef, astroid.UnboundMethod, astroid.BoundMethod)
+
+ # FIXME: more elegant solution probably exists
+ # methods called on instances returned by functions in some libraries
+ # are having function_node None and needs to be handled here
+ # for example:
+ # attrs.evolve returned instances
+ # instances returned by any pyrsistent method (pmap.set, pvector.append, ...)
+ if function_node is None:
+ try:
+ for n in node.func.infer():
+ if not isinstance(n, astroid.BoundMethod):
+ continue
+ function_node = n
+ break
+ except Exception: # pylint:disable=broad-exception-caught
+ pass
+
+ if not isinstance(function_node, funcs):
+ return
+
+ # Unwrap to get the actual function node object
+ if isinstance(function_node, astroid.BoundMethod) and isinstance(
+ function_node._proxied, astroid.UnboundMethod
+ ):
+ function_node = function_node._proxied._proxied
+
+ # Make sure that it's a valid function that we can analyze.
+ # Ordered from less expensive to more expensive checks.
+ if (
+ not function_node.is_function
+ or function_node.decorators
+ or TypeChecker._is_ignored_function(function_node)
+ ):
+ return
+
+ return_nodes = list(
+ function_node.nodes_of_class(nodes.Return, skip_klass=nodes.FunctionDef)
+ )
+ for ret_node in return_nodes:
+ if not (
+ isinstance(ret_node.value, nodes.Const)
+ and ret_node.value.value is None
+ or ret_node.value is None
+ ):
+ self.add_message("function-return-not-assigned", node=node)
+ return
+
+
+def register(linter: PyLinter) -> None:
+ linter.register_checker(FunctionReturnNotAssignedChecker(linter))
diff --git a/tests/functional/ext/function_return_not_assigned/function_return_not_assigned.py b/tests/functional/ext/function_return_not_assigned/function_return_not_assigned.py
new file mode 100644
index 0000000000..ac9e69ba80
--- /dev/null
+++ b/tests/functional/ext/function_return_not_assigned/function_return_not_assigned.py
@@ -0,0 +1,56 @@
+# pylint: disable=missing-function-docstring, missing-module-docstring, missing-class-docstring, expression-not-assigned, invalid-name
+from dataclasses import dataclass, replace
+
+
+def func_that_returns_something():
+ return 1
+
+
+func_that_returns_something() # [function-return-not-assigned]
+
+_ = func_that_returns_something()
+
+if func_that_returns_something():
+ pass
+
+
+def func_that_returns_none():
+ return None
+
+
+def func_with_no_explicit_return():
+ print("I am doing something")
+
+
+func_that_returns_none()
+func_with_no_explicit_return()
+
+some_var = ""
+# next line should probably raise?
+func_that_returns_something() if some_var else func_that_returns_none()
+_ = func_that_returns_something() if some_var else func_that_returns_none()
+func_with_no_explicit_return() if some_var else func_that_returns_none()
+
+
+@dataclass
+class TestClass:
+ value: int
+
+ def return_self(self):
+ return self
+
+ def return_none(self):
+ pass
+
+
+inst = TestClass(1)
+inst.return_self() # [function-return-not-assigned]
+inst.return_none()
+
+replace(inst, value=3) # [function-return-not-assigned]
+
+inst = replace(inst, value=3)
+
+inst.return_self() # [function-return-not-assigned]
+inst.return_none()
+inst = inst.return_self()
diff --git a/tests/functional/ext/function_return_not_assigned/function_return_not_assigned.rc b/tests/functional/ext/function_return_not_assigned/function_return_not_assigned.rc
new file mode 100644
index 0000000000..3b66585607
--- /dev/null
+++ b/tests/functional/ext/function_return_not_assigned/function_return_not_assigned.rc
@@ -0,0 +1,2 @@
+[MAIN]
+load-plugins=pylint.extensions.function_return_not_assigned,
diff --git a/tests/functional/ext/function_return_not_assigned/function_return_not_assigned.txt b/tests/functional/ext/function_return_not_assigned/function_return_not_assigned.txt
new file mode 100644
index 0000000000..5da590fa7a
--- /dev/null
+++ b/tests/functional/ext/function_return_not_assigned/function_return_not_assigned.txt
@@ -0,0 +1,4 @@
+function-return-not-assigned:9:0:9:29::Function returned value which is never used:UNDEFINED
+function-return-not-assigned:47:0:47:18::Function returned value which is never used:UNDEFINED
+function-return-not-assigned:50:0:50:22::Function returned value which is never used:UNDEFINED
+function-return-not-assigned:54:0:54:18::Function returned value which is never used:UNDEFINED
diff --git a/tests/functional/f/function_return_not_assigned.txt b/tests/functional/f/function_return_not_assigned.txt
new file mode 100644
index 0000000000..e69de29bb2