diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index 2f9e2de12..9a5ccc586 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -1806,7 +1806,7 @@ the following methods.
 - `build_root()`: returns a string with the absolute path to the build
   root directory. *(deprecated since 0.56.0)*: this function will return the
   build root of the parent project if called from a subproject, which is usually
-  not what you want. Try using `current_build_dir()`.
+  not what you want. Try using `current_build_dir()` or `project_build_root()`.
 
 - `source_root()`: returns a string with the absolute path to the
   source root directory. Note: you should use the `files()` function
@@ -1814,7 +1814,13 @@ the following methods.
   constructing paths manually with `meson.source_root()`.
   *(deprecated since 0.56.0)*: This function will return the source root of the
   parent project if called from a subproject, which is usually not what you want.
-  Try using `current_source_dir()`.
+  Try using `current_source_dir()` or `project_source_root()`.
+
+- `project_build_root()` *(since 0.56.0)*: returns a string with the absolute path
+  to the build root directory of the current (sub)project.
+
+- `project_source_root()` *(since 0.56.0)*: returns a string with the absolute path
+  to the source root directory of the current (sub)project.
 
 - `current_build_dir()`: returns a string with the absolute path to the
   current build directory.
diff --git a/docs/markdown/snippets/deprecate_source_build_root.md b/docs/markdown/snippets/deprecate_source_build_root.md
index 05b6b9197..1cebef4a7 100644
--- a/docs/markdown/snippets/deprecate_source_build_root.md
+++ b/docs/markdown/snippets/deprecate_source_build_root.md
@@ -3,3 +3,8 @@
 Those function are common source of issue when used in a subproject because they
 point to the parent project root which is rarely what is expected and is a
 violation of subproject isolation.
+
+`meson.current_source_dir()` and `meson.current_build_dir()` should be used instead
+and have been available in all Meson versions. New functions `meson.project_source_root()`
+and `meson.project_build_root()` have been added in Meson 0.56.0 to get the root
+of the current (sub)project.
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 7df557171..0e5e0f842 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -1924,6 +1924,8 @@ class MesonMain(InterpreterObject):
                              'current_build_dir': self.current_build_dir_method,
                              'source_root': self.source_root_method,
                              'build_root': self.build_root_method,
+                             'project_source_root': self.project_source_root_method,
+                             'project_build_root': self.project_build_root_method,
                              'add_install_script': self.add_install_script_method,
                              'add_postconf_script': self.add_postconf_script_method,
                              'add_dist_script': self.add_dist_script_method,
@@ -2071,6 +2073,26 @@ class MesonMain(InterpreterObject):
     def build_root_method(self, args, kwargs):
         return self.interpreter.environment.build_dir
 
+    @noPosargs
+    @permittedKwargs({})
+    @FeatureNew('meson.project_source_root', '0.56.0')
+    def project_source_root_method(self, args, kwargs):
+        src = self.interpreter.environment.source_dir
+        sub = self.interpreter.root_subdir
+        if sub == '':
+            return src
+        return os.path.join(src, sub)
+
+    @noPosargs
+    @permittedKwargs({})
+    @FeatureNew('meson.project_build_root', '0.56.0')
+    def project_build_root_method(self, args, kwargs):
+        src = self.interpreter.environment.build_dir
+        sub = self.interpreter.root_subdir
+        if sub == '':
+            return src
+        return os.path.join(src, sub)
+
     @noPosargs
     @permittedKwargs({})
     @FeatureDeprecated('meson.has_exe_wrapper', '0.55.0', 'use meson.can_run_host_binaries instead.')
diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py
index 1524409de..d3f8181e3 100644
--- a/mesonbuild/interpreterbase.py
+++ b/mesonbuild/interpreterbase.py
@@ -464,6 +464,7 @@ class InterpreterBase:
         self.funcs = {}    # type: T.Dict[str, T.Callable[[mparser.BaseNode, T.List[TYPE_nvar], T.Dict[str, TYPE_nvar]], TYPE_var]]
         self.builtin = {}  # type: T.Dict[str, InterpreterObject]
         self.subdir = subdir
+        self.root_subdir = subdir
         self.subproject = subproject
         self.variables = {}  # type: T.Dict[str, TYPE_var]
         self.argument_depth = 0
diff --git a/test cases/common/227 fs module/meson.build b/test cases/common/227 fs module/meson.build
index cff0987e1..f090d354c 100644
--- a/test cases/common/227 fs module/meson.build	
+++ b/test cases/common/227 fs module/meson.build	
@@ -96,6 +96,9 @@ f1 = 'meson.build'
 f2 = 'subdir/../meson.build'
 assert(fs.is_samepath(f1, f2), 'is_samepath not detercting same files')
 assert(fs.is_samepath(meson.source_root(), 'subdir/..'), 'is_samepath not detecting same directory')
+assert(fs.is_samepath(meson.project_source_root(), 'subdir/..'), 'is_samepath not detecting same directory')
+# This fails with python3.5. It can be uncommented when we depend on python >= 3.6
+#assert(fs.is_samepath(meson.project_build_root(), meson.current_build_dir() / 'subdir/..'), 'is_samepath not detecting same directory')
 assert(not fs.is_samepath(f1, 'subdir/subdirfile.txt'), 'is_samepath known bad comparison')
 assert(not fs.is_samepath('not-a-path', f2), 'is_samepath should not error if path(s) do not exist')
 
@@ -111,3 +114,5 @@ assert(fs.stem('foo/bar/baz.dll') == 'baz', 'failed to get stem with suffix')
 assert(fs.stem('foo/bar/baz.dll.a') == 'baz.dll', 'failed to get stem with compound suffix')
 
 subdir('subdir')
+
+subproject('subbie')
diff --git a/test cases/common/227 fs module/subdir/meson.build b/test cases/common/227 fs module/subdir/meson.build
index ec6f1029d..dc04b4124 100644
--- a/test cases/common/227 fs module/subdir/meson.build	
+++ b/test cases/common/227 fs module/subdir/meson.build	
@@ -1 +1,3 @@
 assert(fs.exists('subdirfile.txt'), 'Subdir file lookup is broken.')
+assert(fs.is_samepath(meson.project_source_root(), '..'), 'is_samepath not detecting same directory')
+assert(fs.is_samepath(meson.project_build_root(), meson.current_build_dir() / '..'), 'is_samepath not detecting same directory')
diff --git a/test cases/common/227 fs module/subprojects/subbie/meson.build b/test cases/common/227 fs module/subprojects/subbie/meson.build
index 55fc28636..ca6d36b4a 100644
--- a/test cases/common/227 fs module/subprojects/subbie/meson.build	
+++ b/test cases/common/227 fs module/subprojects/subbie/meson.build	
@@ -3,7 +3,7 @@ project('subbie')
 fs = import('fs')
 
 assert(fs.exists('subprojectfile.txt'), 'Subproject root file not found.')
+assert(fs.is_samepath(meson.project_source_root(), meson.current_source_dir()), 'is_samepath not detecting same directory')
+assert(fs.is_samepath(meson.project_build_root(), meson.current_build_dir()), 'is_samepath not detecting same directory')
 
 subdir('subsub')
-
-subproject('subbie')
diff --git a/test cases/common/227 fs module/subprojects/subbie/subsub/meson.build b/test cases/common/227 fs module/subprojects/subbie/subsub/meson.build
index cf9a271e3..4ac68aea5 100644
--- a/test cases/common/227 fs module/subprojects/subbie/subsub/meson.build	
+++ b/test cases/common/227 fs module/subprojects/subbie/subsub/meson.build	
@@ -1 +1,3 @@
 assert(fs.exists('subsubfile.txt'), 'Subproject subdir lookup failed.')
+assert(fs.is_samepath(meson.project_source_root(), meson.current_source_dir() / '..'), 'is_samepath not detecting same directory')
+assert(fs.is_samepath(meson.project_build_root(), meson.current_build_dir() / '..'), 'is_samepath not detecting same directory')