Keep buildtype the same even if user changes debug and/or optimization.
diff --git a/docs/markdown/snippets/buildtyperemains.md b/docs/markdown/snippets/buildtyperemains.md
new file mode 100644
index 0000000..4eb6243
--- /dev/null
+++ b/docs/markdown/snippets/buildtyperemains.md
@@ -0,0 +1,10 @@
+## Buildtype remains even if dependent options are changed
+
+Setting the `buildtype' option to a value sets the `debug` and
+`optimization` options to predefined values. Traditionally setting the
+options to other values would then change the buildtype to `custom`.
+This is confusing and means that you can't use, for example, debug
+level `g` in `debug` buildtype even though it would make sense under
+many circumstances. Starting with the buildtype is only changed when
+the user explicitly sets it. Setting the build type sets the other
+options to their default values as before.
\ No newline at end of file
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index f2aba80..455d2f1 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -582,8 +582,35 @@
 
         if key.name == 'buildtype':
             self._set_others_from_buildtype(value)
-        elif key.name in {'debug', 'optimization'}:
-            self._set_buildtype_from_others()
+
+    def get_nondefault_buildtype_args(self):
+        result= []
+        value = self.options[OptionKey('buildtype')].value
+        if value == 'plain':
+            opt = '0'
+            debug = False
+        elif value == 'debug':
+            opt = '0'
+            debug = True
+        elif value == 'debugoptimized':
+            opt = '2'
+            debug = True
+        elif value == 'release':
+            opt = '3'
+            debug = False
+        elif value == 'minsize':
+            opt = 's'
+            debug = True
+        else:
+            assert(value == 'custom')
+            return []
+        actual_opt = self.options[OptionKey('optimization')].value
+        actual_debug = self.options[OptionKey('debug')].value
+        if actual_opt != opt:
+            result.append(('optimization', actual_opt, opt))
+        if actual_debug != debug:
+            result.append(('debug', actual_debug, debug))
+        return result
 
     def _set_others_from_buildtype(self, value: str) -> None:
         if value == 'plain':
@@ -607,23 +634,6 @@
         self.options[OptionKey('optimization')].set_value(opt)
         self.options[OptionKey('debug')].set_value(debug)
 
-    def _set_buildtype_from_others(self) -> None:
-        opt = self.options[OptionKey('optimization')].value
-        debug = self.options[OptionKey('debug')].value
-        if opt == '0' and not debug:
-            mode = 'plain'
-        elif opt == '0' and debug:
-            mode = 'debug'
-        elif opt == '2' and debug:
-            mode = 'debugoptimized'
-        elif opt == '3' and not debug:
-            mode = 'release'
-        elif opt == 's' and debug:
-            mode = 'minsize'
-        else:
-            mode = 'custom'
-        self.options[OptionKey('buildtype')].set_value(mode)
-
     @staticmethod
     def is_per_machine_option(optname: OptionKey) -> bool:
         if optname.name in BUILTIN_OPTIONS_PER_MACHINE:
diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py
index 686a336..5233d88 100644
--- a/mesonbuild/mconf.py
+++ b/mesonbuild/mconf.py
@@ -243,6 +243,17 @@
             print('')
             print_default_values_warning()
 
+        self.print_nondefault_buildtype_options()
+
+    def print_nondefault_buildtype_options(self):
+        mismatching = self.coredata.get_nondefault_buildtype_args()
+        if not mismatching:
+            return
+        print("\nThe following option(s) have a different value than the build type default\n")
+        print(f'               current   default')
+        for m in mismatching:
+            print(f'{m[0]:21}{m[1]:10}{m[2]:10}')
+
 def run(options):
     coredata.parse_cmd_line_options(options)
     builddir = os.path.abspath(os.path.realpath(options.builddir))
diff --git a/run_unittests.py b/run_unittests.py
index bf6a7ad..a27c113 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -3923,51 +3923,13 @@
         self.setconf('-Ddebug=false')
         opts = self.get_opts_as_dict()
         self.assertEqual(opts['debug'], False)
-        self.assertEqual(opts['buildtype'], 'plain')
-        self.assertEqual(opts['optimization'], '0')
-
-        # Setting optimizations to 3 should cause buildtype
-        # to go to release mode.
-        self.setconf('-Doptimization=3')
-        opts = self.get_opts_as_dict()
-        self.assertEqual(opts['buildtype'], 'release')
-        self.assertEqual(opts['debug'], False)
-        self.assertEqual(opts['optimization'], '3')
-
-        # Going to debug build type should reset debugging
-        # and optimization
-        self.setconf('-Dbuildtype=debug')
-        opts = self.get_opts_as_dict()
         self.assertEqual(opts['buildtype'], 'debug')
-        self.assertEqual(opts['debug'], True)
         self.assertEqual(opts['optimization'], '0')
-
-        # Command-line parsing of buildtype settings should be the same as
-        # setting with `meson configure`.
-        #
-        # Setting buildtype should set optimization/debug
-        self.new_builddir()
-        self.init(testdir, extra_args=['-Dbuildtype=debugoptimized'])
+        self.setconf('-Doptimization=g')
         opts = self.get_opts_as_dict()
-        self.assertEqual(opts['debug'], True)
-        self.assertEqual(opts['optimization'], '2')
-        self.assertEqual(opts['buildtype'], 'debugoptimized')
-        # Setting optimization/debug should set buildtype
-        self.new_builddir()
-        self.init(testdir, extra_args=['-Doptimization=2', '-Ddebug=true'])
-        opts = self.get_opts_as_dict()
-        self.assertEqual(opts['debug'], True)
-        self.assertEqual(opts['optimization'], '2')
-        self.assertEqual(opts['buildtype'], 'debugoptimized')
-        # Setting both buildtype and debug on the command-line should work, and
-        # should warn not to do that. Also test that --debug is parsed as -Ddebug=true
-        self.new_builddir()
-        out = self.init(testdir, extra_args=['-Dbuildtype=debugoptimized', '--debug'])
-        self.assertRegex(out, 'Recommend using either.*buildtype.*debug.*redundant')
-        opts = self.get_opts_as_dict()
-        self.assertEqual(opts['debug'], True)
-        self.assertEqual(opts['optimization'], '2')
-        self.assertEqual(opts['buildtype'], 'debugoptimized')
+        self.assertEqual(opts['debug'], False)
+        self.assertEqual(opts['buildtype'], 'debug')
+        self.assertEqual(opts['optimization'], 'g')
 
     @skipIfNoPkgconfig
     @unittest.skipIf(is_windows(), 'Help needed with fixing this test on windows')