check `mut`-restriction when tuple constructor is used as a value

* check mut restriction when tuple ctor is used as a value
* add missing stderr file for mut-restriction ctor value test
* simplify def_kind matching in tuple ctor mut restriction check

Match the DefKind::Ctor directly on the result of tcx.def_kind instead of binding it to a local first. Extend the ctor-value ui test with additional enum variants covering plain and crate-restricted fields.
* test: exercise new ctor variants
* address review: drop shell.nix, add tests
diff --git a/compiler/rustc_mir_transform/src/check_mut_restriction.rs b/compiler/rustc_mir_transform/src/check_mut_restriction.rs
index 9d6809e..96f3679 100644
--- a/compiler/rustc_mir_transform/src/check_mut_restriction.rs
+++ b/compiler/rustc_mir_transform/src/check_mut_restriction.rs
@@ -1,3 +1,4 @@
+use rustc_hir::def::{CtorOf, DefKind};
 use rustc_middle::mir::visit::{PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, TyCtxt};
@@ -34,6 +35,40 @@ fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
         self.super_statement(statement, location);
     }
 
+    // Tuple constructors used as values can bypass field mut restrictions if not checked here.
+    fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
+        if let ty::FnDef(def_id, _) = *constant.const_.ty().kind()
+            && let DefKind::Ctor(ctor_of, _) = self.tcx.def_kind(def_id)
+        {
+            let body_did = self.body.source.instance.def_id();
+            let adt_did = match ctor_of {
+                CtorOf::Struct => self.tcx.parent(def_id),
+                CtorOf::Variant => self.tcx.parent(self.tcx.parent(def_id)),
+            };
+            let adt = self.tcx.adt_def(adt_did);
+            let variant = match ctor_of {
+                CtorOf::Struct => adt.non_enum_variant(),
+                CtorOf::Variant => adt.variant_with_ctor_id(def_id),
+            };
+
+            let mut_restriction =
+                variant.fields.iter().fold(ty::RestrictionKind::Unrestricted, |acc, field| {
+                    acc.stricter_of(field.mut_restriction, self.tcx)
+                });
+            if !mut_restriction.is_allowed_in(body_did, self.tcx) {
+                self.tcx.dcx().emit_err(diagnostics::ConstructionOfTyWithMutRestrictedField {
+                    construction_span: constant.span,
+                    restriction_span: mut_restriction.expect_span(),
+                    name: variant.name,
+                    descr: adt.variant_descr(),
+                    restriction_path: mut_restriction.restriction_path(self.tcx),
+                });
+            }
+        }
+
+        self.super_const_operand(constant, location);
+    }
+
     fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
         if context.is_mutating_use() {
             let body_did = self.body.source.instance.def_id();
diff --git a/tests/ui/mut-restriction/mut-restriction-ctor-value.rs b/tests/ui/mut-restriction/mut-restriction-ctor-value.rs
new file mode 100644
index 0000000..7ca33ff
--- /dev/null
+++ b/tests/ui/mut-restriction/mut-restriction-ctor-value.rs
@@ -0,0 +1,40 @@
+//@ edition: 2018..
+#![feature(mut_restriction)]
+
+pub mod inner {
+    #[derive(Default)]
+    pub struct Wrapper(pub mut(self) u8);
+
+    pub enum EnumTup {
+        Tup(mut(self) u8),
+        Foo(u8),
+        Bar(u8, mut(crate) u8),
+    }
+
+    pub fn construct_inner() {
+        let _ = Wrapper;
+        let _ = EnumTup::Tup;
+        let _ = EnumTup::Foo;
+        let _ = EnumTup::Bar;
+    }
+}
+
+fn param_is_fn(_: fn(u8) -> inner::Wrapper) {}
+fn param_impl_fn(_: impl Fn(u8) -> inner::Wrapper) {}
+
+fn main() {
+    let _ = inner::Wrapper;
+    //~^ ERROR `Wrapper` cannot be constructed using a `struct` expression outside `crate::inner`
+
+    param_is_fn(inner::Wrapper);
+    //~^ ERROR `Wrapper` cannot be constructed using a `struct` expression outside `crate::inner`
+
+    param_impl_fn(inner::Wrapper);
+    //~^ ERROR `Wrapper` cannot be constructed using a `struct` expression outside `crate::inner`
+
+    let _ = inner::EnumTup::Tup;
+    //~^ ERROR `Tup` cannot be constructed using a `variant` expression outside `crate::inner`
+
+    let _ = inner::EnumTup::Foo;
+    let _ = inner::EnumTup::Bar;
+}
diff --git a/tests/ui/mut-restriction/mut-restriction-ctor-value.stderr b/tests/ui/mut-restriction/mut-restriction-ctor-value.stderr
new file mode 100644
index 0000000..b10a3c1
--- /dev/null
+++ b/tests/ui/mut-restriction/mut-restriction-ctor-value.stderr
@@ -0,0 +1,38 @@
+error: `Wrapper` cannot be constructed using a `struct` expression outside `crate::inner`
+  --> $DIR/mut-restriction-ctor-value.rs:26:13
+   |
+LL |     pub struct Wrapper(pub mut(self) u8);
+   |                            --------- field restricted here
+...
+LL |     let _ = inner::Wrapper;
+   |             ^^^^^^^^^^^^^^
+
+error: `Wrapper` cannot be constructed using a `struct` expression outside `crate::inner`
+  --> $DIR/mut-restriction-ctor-value.rs:29:17
+   |
+LL |     pub struct Wrapper(pub mut(self) u8);
+   |                            --------- field restricted here
+...
+LL |     param_is_fn(inner::Wrapper);
+   |                 ^^^^^^^^^^^^^^
+
+error: `Wrapper` cannot be constructed using a `struct` expression outside `crate::inner`
+  --> $DIR/mut-restriction-ctor-value.rs:32:19
+   |
+LL |     pub struct Wrapper(pub mut(self) u8);
+   |                            --------- field restricted here
+...
+LL |     param_impl_fn(inner::Wrapper);
+   |                   ^^^^^^^^^^^^^^
+
+error: `Tup` cannot be constructed using a `variant` expression outside `crate::inner`
+  --> $DIR/mut-restriction-ctor-value.rs:35:13
+   |
+LL |         Tup(mut(self) u8),
+   |             --------- field restricted here
+...
+LL |     let _ = inner::EnumTup::Tup;
+   |             ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+