Allow &mut calls on Trivial extern types only.

Previously we allowed extern types to be used as un-pinned
reference parameters only if there happened to be some other
use of the type in some way which required it to be Trivial.

With this change,
* Opaque extern types must always be pinned when used as mutable
  reference parameters;
* Trivial extern types need never be pinned when used as mutable
  reference parameters.
diff --git a/syntax/check.rs b/syntax/check.rs
index 3b7b513..80426f9 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -189,7 +189,7 @@
             cx.error(
                 ty,
                 format!(
-                    "mutable reference to C++ type requires a pin -- use Pin<&mut {}>",
+                    "mutable reference to C++ type requires a pin -- use Pin<&mut {}> or declare the type Trivial in a cxx::ExternType impl",
                     requires_pin,
                 ),
             );
@@ -332,6 +332,10 @@
             TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.name.rust),
             TrivialReason::BoxTarget => format!("Box<{}>", ety.name.rust),
             TrivialReason::VecElement => format!("a vector element in Vec<{}>", ety.name.rust),
+            TrivialReason::UnpinnedMutableReferenceFunctionArgument(efn) => format!(
+                "a non-pinned mutable reference argument of {}",
+                efn.name.rust
+            ),
         };
         let msg = format!(
             "needs a cxx::ExternType impl in order to be used as {}",
@@ -385,7 +389,7 @@
             cx.error(
                 span,
                 format!(
-                    "mutable reference to C++ type requires a pin -- use `self: Pin<&mut {}>`",
+                    "mutable reference to opaque C++ type requires a pin -- use `self: Pin<&mut {}>` or declare the type Trivial in a cxx::ExternType impl",
                     receiver.ty.rust,
                 ),
             );
diff --git a/syntax/types.rs b/syntax/types.rs
index 72216b3..ddd3c42 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -170,14 +170,13 @@
         // the APIs above, in case some function or struct references a type
         // which is declared subsequently.
         let mut required_trivial = Map::new();
-        let mut insist_alias_types_are_trivial = |ty: &'a Type, reason| {
-            if let Type::Ident(ident) = ty {
-                if cxx.contains(&ident.rust)
-                    && !structs.contains_key(&ident.rust)
-                    && !enums.contains_key(&ident.rust)
-                {
-                    required_trivial.entry(&ident.rust).or_insert(reason);
-                }
+
+        let mut insist_extern_types_are_trivial = |ident: &'a RustName, reason| {
+            if cxx.contains(&ident.rust)
+                && !structs.contains_key(&ident.rust)
+                && !enums.contains_key(&ident.rust)
+            {
+                required_trivial.entry(&ident.rust).or_insert(reason);
             }
         };
         for api in apis {
@@ -185,17 +184,23 @@
                 Api::Struct(strct) => {
                     let reason = TrivialReason::StructField(strct);
                     for field in &strct.fields {
-                        insist_alias_types_are_trivial(&field.ty, reason);
+                        if let Type::Ident(ident) = &field.ty {
+                            insist_extern_types_are_trivial(&ident, reason);
+                        }
                     }
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                     let reason = TrivialReason::FunctionArgument(efn);
                     for arg in &efn.args {
-                        insist_alias_types_are_trivial(&arg.ty, reason);
+                        if let Type::Ident(ident) = &arg.ty {
+                            insist_extern_types_are_trivial(&ident, reason);
+                        }
                     }
                     if let Some(ret) = &efn.ret {
                         let reason = TrivialReason::FunctionReturn(efn);
-                        insist_alias_types_are_trivial(&ret, reason);
+                        if let Type::Ident(ident) = &ret {
+                            insist_extern_types_are_trivial(&ident, reason);
+                        }
                     }
                 }
                 _ => {}
@@ -205,11 +210,37 @@
             match ty {
                 Type::RustBox(ty) => {
                     let reason = TrivialReason::BoxTarget;
-                    insist_alias_types_are_trivial(&ty.inner, reason);
+                    if let Type::Ident(ident) = &ty.inner {
+                        insist_extern_types_are_trivial(&ident, reason);
+                    }
                 }
                 Type::RustVec(ty) => {
                     let reason = TrivialReason::VecElement;
-                    insist_alias_types_are_trivial(&ty.inner, reason);
+                    if let Type::Ident(ident) = &ty.inner {
+                        insist_extern_types_are_trivial(&ident, reason);
+                    }
+                }
+                _ => {}
+            }
+        }
+        for api in apis {
+            match api {
+                Api::CxxFunction(efn) | Api::RustFunction(efn) => {
+                    let reason = TrivialReason::UnpinnedMutableReferenceFunctionArgument(efn);
+                    if let Some(receiver) = &efn.receiver {
+                        if receiver.mutable && !receiver.pinned {
+                            insist_extern_types_are_trivial(&receiver.ty, reason);
+                        }
+                    }
+                    for arg in &efn.args {
+                        if let Type::Ref(reff) = &arg.ty {
+                            if reff.mutable && !reff.pinned {
+                                if let Type::Ident(ident) = &reff.inner {
+                                    insist_extern_types_are_trivial(&ident, reason);
+                                }
+                            }
+                        }
+                    }
                 }
                 _ => {}
             }
@@ -310,6 +341,7 @@
     FunctionReturn(&'a ExternFn),
     BoxTarget,
     VecElement,
+    UnpinnedMutableReferenceFunctionArgument(&'a ExternFn),
 }
 
 fn duplicate_name(cx: &mut Errors, sp: impl ToTokens, ident: &Ident) {