Auto merge of #47116 - estebank:non-accessible-ctor, r=petrochenkov

Tweaks to invalid ctor messages

 - Do not suggest using a constructor that isn't accessible
 - Suggest the appropriate syntax (`()`/`{}` as appropriate)
 - Add note when trying to use `Self` as a ctor

CC #22488, fix #47085.
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 231a32c..5429dbc 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -898,7 +898,7 @@
     }
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 enum PathResult<'a> {
     Module(Module<'a>),
     NonModule(PathResolution),
@@ -2568,7 +2568,8 @@
             let code = source.error_code(def.is_some());
             let (base_msg, fallback_label, base_span) = if let Some(def) = def {
                 (format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str),
-                 format!("not a {}", expected), span)
+                 format!("not a {}", expected),
+                 span)
             } else {
                 let item_str = path[path.len() - 1].node;
                 let item_span = path[path.len() - 1].span;
@@ -2585,7 +2586,8 @@
                     (mod_prefix, format!("`{}`", names_to_string(mod_path)))
                 };
                 (format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str),
-                 format!("not found in {}", mod_str), item_span)
+                 format!("not found in {}", mod_str),
+                 item_span)
             };
             let code = DiagnosticId::Error(code.into());
             let mut err = this.session.struct_span_err_with_code(base_span, &base_msg, code);
@@ -2700,20 +2702,37 @@
                         }
                         return (err, candidates);
                     },
-                    _ if ns == ValueNS && is_struct_like(def) => {
-                        if let Def::Struct(def_id) = def {
-                            if let Some((ctor_def, ctor_vis))
-                                    = this.struct_constructors.get(&def_id).cloned() {
-                                if is_expected(ctor_def) && !this.is_accessible(ctor_vis) {
-                                    err.span_label(span, format!("constructor is not visible \
-                                                                   here due to private fields"));
-                                }
+                    (Def::Struct(def_id), _) if ns == ValueNS => {
+                        if let Some((ctor_def, ctor_vis))
+                                = this.struct_constructors.get(&def_id).cloned() {
+                            let accessible_ctor = this.is_accessible(ctor_vis);
+                            if is_expected(ctor_def) && !accessible_ctor {
+                                err.span_label(span, format!("constructor is not visible \
+                                                              here due to private fields"));
                             }
+                        } else {
+                            err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?",
+                                                         path_str));
                         }
+                        return (err, candidates);
+                    }
+                    (Def::Union(..), _) |
+                    (Def::Variant(..), _) |
+                    (Def::VariantCtor(_, CtorKind::Fictive), _) if ns == ValueNS => {
                         err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?",
                                                      path_str));
                         return (err, candidates);
                     }
+                    (Def::SelfTy(..), _) if ns == ValueNS => {
+                        err.span_label(span, fallback_label);
+                        err.note("can't use `Self` as a constructor, you must use the \
+                                  implemented struct");
+                        return (err, candidates);
+                    }
+                    (Def::TyAlias(_), _) | (Def::AssociatedTy(..), _) if ns == ValueNS => {
+                        err.note("can't use a type alias as a constructor");
+                        return (err, candidates);
+                    }
                     _ => {}
                 }
             }
@@ -3965,13 +3984,6 @@
     }
 }
 
-fn is_struct_like(def: Def) -> bool {
-    match def {
-        Def::VariantCtor(_, CtorKind::Fictive) => true,
-        _ => PathSource::Struct.is_expected(def),
-    }
-}
-
 fn is_self_type(path: &[SpannedIdent], namespace: Namespace) -> bool {
     namespace == TypeNS && path.len() == 1 && path[0].node.name == keywords::SelfType.name()
 }
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index df1694a..5c5e5f2 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -210,15 +210,25 @@
                         }
                     }
                 }
-                let mut err = type_error_struct!(self.tcx.sess, call_expr.span, callee_ty, E0618,
-                                                 "expected function, found `{}`",
-                                                 if let Some(ref path) = unit_variant {
-                                                     path.to_string()
-                                                 } else {
-                                                     callee_ty.to_string()
-                                                 });
-                if let Some(path) = unit_variant {
-                    err.help(&format!("did you mean to write `{}`?", path));
+
+                let mut err = type_error_struct!(
+                    self.tcx.sess,
+                    call_expr.span,
+                    callee_ty,
+                    E0618,
+                    "expected function, found {}",
+                    match unit_variant {
+                        Some(ref path) => format!("enum variant `{}`", path),
+                        None => format!("`{}`", callee_ty),
+                    });
+
+                err.span_label(call_expr.span, "not a function");
+
+                if let Some(ref path) = unit_variant {
+                    err.span_suggestion(call_expr.span,
+                                        &format!("`{}` is a unit variant, you need to write it \
+                                                  without the parenthesis", path),
+                                        path.to_string());
                 }
 
                 if let hir::ExprCall(ref expr, _) = call_expr.node {
@@ -235,7 +245,11 @@
                         _ => self.tcx.hir.span_if_local(def.def_id())
                     };
                     if let Some(span) = def_span {
-                        err.span_note(span, "defined here");
+                        let name = match unit_variant {
+                            Some(path) => path,
+                            None => callee_ty.to_string(),
+                        };
+                        err.span_label(span, format!("`{}` defined here", name));
                     }
                 }
 
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 734287f..570eecf 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -518,7 +518,10 @@
                                            self_descr);
             err.span_label(impl_m_span, format!("`{}` used in impl", self_descr));
             if let Some(span) = tcx.hir.span_if_local(trait_m.def_id) {
-                err.span_label(span, format!("trait declared without `{}`", self_descr));
+                err.span_label(span, format!("trait method declared without `{}`", self_descr));
+            } else {
+                err.note_trait_signature(trait_m.name.to_string(),
+                                         trait_m.signature(&tcx));
             }
             err.emit();
             return Err(ErrorReported);
@@ -533,8 +536,7 @@
                                             not in the impl",
                                            trait_m.name,
                                            self_descr);
-            err.span_label(impl_m_span,
-                           format!("expected `{}` in impl", self_descr));
+            err.span_label(impl_m_span, format!("expected `{}` in impl", self_descr));
             if let Some(span) = tcx.hir.span_if_local(trait_m.def_id) {
                 err.span_label(span, format!("`{}` used in trait", self_descr));
             } else {
diff --git a/src/test/compile-fail/E0185.rs b/src/test/compile-fail/E0185.rs
index be54c37..0cd3d00 100644
--- a/src/test/compile-fail/E0185.rs
+++ b/src/test/compile-fail/E0185.rs
@@ -9,14 +9,16 @@
 // except according to those terms.
 
 trait Foo {
-    fn foo(); //~ trait declared without `&self`
+    fn foo();
+    //~^ NOTE trait method declared without `&self`
 }
 
 struct Bar;
 
 impl Foo for Bar {
-    fn foo(&self) {} //~ ERROR E0185
-    //~^ `&self` used in impl
+    fn foo(&self) {}
+    //~^ ERROR E0185
+    //~| NOTE `&self` used in impl
 }
 
 fn main() {
diff --git a/src/test/compile-fail/E0618.rs b/src/test/compile-fail/E0618.rs
index f28ac20..f46bdb9 100644
--- a/src/test/compile-fail/E0618.rs
+++ b/src/test/compile-fail/E0618.rs
@@ -13,7 +13,9 @@
 }
 
 fn main() {
-    X::Entry(); //~ ERROR expected function, found `X::Entry` [E0618]
+    X::Entry();
+    //~^ ERROR expected function, found enum variant `X::Entry` [E0618]
     let x = 0i32;
-    x(); //~ ERROR expected function, found `i32` [E0618]
+    x();
+    //~^ ERROR expected function, found `i32` [E0618]
 }
diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr
index 7c88d78..3b4f514 100644
--- a/src/test/ui/block-result/issue-20862.stderr
+++ b/src/test/ui/block-result/issue-20862.stderr
@@ -13,7 +13,7 @@
   --> $DIR/issue-20862.rs:17:13
    |
 17 |     let x = foo(5)(2);
-   |             ^^^^^^^^^
+   |             ^^^^^^^^^ not a function
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/empty-struct-unit-expr.rs b/src/test/ui/empty-struct-unit-expr.rs
index c339601..941292a 100644
--- a/src/test/ui/empty-struct-unit-expr.rs
+++ b/src/test/ui/empty-struct-unit-expr.rs
@@ -24,8 +24,8 @@
 fn main() {
     let e2 = Empty2(); //~ ERROR expected function, found `Empty2`
     let e4 = E::Empty4();
-    //~^ ERROR expected function, found `E::Empty4` [E0618]
+    //~^ ERROR expected function, found enum variant `E::Empty4` [E0618]
     let xe2 = XEmpty2(); //~ ERROR expected function, found `empty_struct::XEmpty2`
     let xe4 = XE::XEmpty4();
-    //~^ ERROR expected function, found `XE::XEmpty4` [E0618]
+    //~^ ERROR expected function, found enum variant `XE::XEmpty4` [E0618]
 }
diff --git a/src/test/ui/empty-struct-unit-expr.stderr b/src/test/ui/empty-struct-unit-expr.stderr
index 3ce63ed..aa242a5 100644
--- a/src/test/ui/empty-struct-unit-expr.stderr
+++ b/src/test/ui/empty-struct-unit-expr.stderr
@@ -1,41 +1,40 @@
 error[E0618]: expected function, found `Empty2`
   --> $DIR/empty-struct-unit-expr.rs:25:14
    |
-25 |     let e2 = Empty2(); //~ ERROR expected function, found `Empty2`
-   |              ^^^^^^^^
-   |
-note: defined here
-  --> $DIR/empty-struct-unit-expr.rs:18:1
-   |
 18 | struct Empty2;
-   | ^^^^^^^^^^^^^^
+   | -------------- `Empty2` defined here
+...
+25 |     let e2 = Empty2(); //~ ERROR expected function, found `Empty2`
+   |              ^^^^^^^^ not a function
 
-error[E0618]: expected function, found `E::Empty4`
+error[E0618]: expected function, found enum variant `E::Empty4`
   --> $DIR/empty-struct-unit-expr.rs:26:14
    |
-26 |     let e4 = E::Empty4();
-   |              ^^^^^^^^^^^
-   |
-   = help: did you mean to write `E::Empty4`?
-note: defined here
-  --> $DIR/empty-struct-unit-expr.rs:21:5
-   |
 21 |     Empty4
-   |     ^^^^^^
+   |     ------ `E::Empty4` defined here
+...
+26 |     let e4 = E::Empty4();
+   |              ^^^^^^^^^^^ not a function
+help: `E::Empty4` is a unit variant, you need to write it without the parenthesis
+   |
+26 |     let e4 = E::Empty4;
+   |              ^^^^^^^^^
 
 error[E0618]: expected function, found `empty_struct::XEmpty2`
   --> $DIR/empty-struct-unit-expr.rs:28:15
    |
 28 |     let xe2 = XEmpty2(); //~ ERROR expected function, found `empty_struct::XEmpty2`
-   |               ^^^^^^^^^
+   |               ^^^^^^^^^ not a function
 
-error[E0618]: expected function, found `XE::XEmpty4`
+error[E0618]: expected function, found enum variant `XE::XEmpty4`
   --> $DIR/empty-struct-unit-expr.rs:29:15
    |
 29 |     let xe4 = XE::XEmpty4();
-   |               ^^^^^^^^^^^^^
+   |               ^^^^^^^^^^^^^ not a function
+help: `XE::XEmpty4` is a unit variant, you need to write it without the parenthesis
    |
-   = help: did you mean to write `XE::XEmpty4`?
+29 |     let xe4 = XE::XEmpty4;
+   |               ^^^^^^^^^^^
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/issue-10969.stderr b/src/test/ui/issue-10969.stderr
index 8aea63e..68127b2 100644
--- a/src/test/ui/issue-10969.stderr
+++ b/src/test/ui/issue-10969.stderr
@@ -1,26 +1,18 @@
 error[E0618]: expected function, found `i32`
   --> $DIR/issue-10969.rs:12:5
    |
-12 |     i(); //~ERROR expected function, found `i32`
-   |     ^^^
-   |
-note: defined here
-  --> $DIR/issue-10969.rs:11:9
-   |
 11 | fn func(i: i32) {
-   |         ^
+   |         - `i32` defined here
+12 |     i(); //~ERROR expected function, found `i32`
+   |     ^^^ not a function
 
 error[E0618]: expected function, found `i32`
   --> $DIR/issue-10969.rs:16:5
    |
-16 |     i(); //~ERROR expected function, found `i32`
-   |     ^^^
-   |
-note: defined here
-  --> $DIR/issue-10969.rs:15:9
-   |
 15 |     let i = 0i32;
-   |         ^
+   |         - `i32` defined here
+16 |     i(); //~ERROR expected function, found `i32`
+   |     ^^^ not a function
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/resolve/privacy-enum-ctor.rs b/src/test/ui/resolve/privacy-enum-ctor.rs
new file mode 100644
index 0000000..08480a0
--- /dev/null
+++ b/src/test/ui/resolve/privacy-enum-ctor.rs
@@ -0,0 +1,81 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod m {
+    pub enum E {
+        Fn(u8),
+        Struct {
+            s: u8,
+        },
+        Unit,
+    }
+
+    pub mod n {
+        pub(in m) enum Z {
+            Fn(u8),
+            Struct {
+                s: u8,
+            },
+            Unit,
+        }
+    }
+
+    use m::n::Z; // OK, only the type is imported
+
+    fn f() {
+        n::Z;
+        //~^ ERROR expected value, found enum `n::Z`
+        Z;
+        //~^ ERROR expected value, found enum `Z`
+        let _: Z = Z::Fn;
+        //~^ ERROR mismatched types
+        let _: Z = Z::Struct;
+        //~^ ERROR expected value, found struct variant `Z::Struct`
+        let _ = Z::Unit();
+        //~^ ERROR expected function, found enum variant `Z::Unit`
+        let _ = Z::Unit {};
+        // This is ok, it is equivalent to not having braces
+    }
+}
+
+use m::E; // OK, only the type is imported
+
+fn main() {
+    let _: E = m::E;
+    //~^ ERROR expected value, found enum `m::E`
+    let _: E = m::E::Fn;
+    //~^ ERROR mismatched types
+    let _: E = m::E::Struct;
+    //~^ ERROR expected value, found struct variant `m::E::Struct`
+    let _: E = m::E::Unit();
+    //~^ ERROR expected function, found enum variant `m::E::Unit`
+    let _: E = E;
+    //~^ ERROR expected value, found enum `E`
+    let _: E = E::Fn;
+    //~^ ERROR mismatched types
+    let _: E = E::Struct;
+    //~^ ERROR expected value, found struct variant `E::Struct`
+    let _: E = E::Unit();
+    //~^ ERROR expected function, found enum variant `E::Unit`
+    let _: Z = m::n::Z;
+    //~^ ERROR cannot find type `Z` in this scope
+    //~| ERROR expected value, found enum `m::n::Z`
+    //~| ERROR enum `Z` is private
+    let _: Z = m::n::Z::Fn;
+    //~^ ERROR cannot find type `Z` in this scope
+    //~| ERROR enum `Z` is private
+    let _: Z = m::n::Z::Struct;
+    //~^ ERROR cannot find type `Z` in this scope
+    //~| ERROR expected value, found struct variant `m::n::Z::Struct`
+    //~| ERROR enum `Z` is private
+    let _: Z = m::n::Z::Unit {};
+    //~^ ERROR cannot find type `Z` in this scope
+    //~| ERROR enum `Z` is private
+}
diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr
new file mode 100644
index 0000000..c4f6d1f
--- /dev/null
+++ b/src/test/ui/resolve/privacy-enum-ctor.stderr
@@ -0,0 +1,225 @@
+error[E0423]: expected value, found enum `n::Z`
+  --> $DIR/privacy-enum-ctor.rs:33:9
+   |
+33 |         n::Z;
+   |         ^^^^
+   |
+   = note: did you mean to use one of the following variants?
+           - `m::Z::Fn`
+           - `m::Z::Struct`
+           - `m::Z::Unit`
+
+error[E0423]: expected value, found enum `Z`
+  --> $DIR/privacy-enum-ctor.rs:35:9
+   |
+35 |         Z;
+   |         ^ did you mean `f`?
+   |
+   = note: did you mean to use one of the following variants?
+           - `m::Z::Fn`
+           - `m::Z::Struct`
+           - `m::Z::Unit`
+
+error[E0423]: expected value, found struct variant `Z::Struct`
+  --> $DIR/privacy-enum-ctor.rs:39:20
+   |
+39 |         let _: Z = Z::Struct;
+   |                    ^^^^^^^^^ did you mean `Z::Struct { /* fields */ }`?
+
+error[E0423]: expected value, found enum `m::E`
+  --> $DIR/privacy-enum-ctor.rs:51:16
+   |
+51 |     let _: E = m::E;
+   |                ^^^-
+   |                   |
+   |                   did you mean `f`?
+   |
+   = note: did you mean to use one of the following variants?
+           - `E::Fn`
+           - `E::Struct`
+           - `E::Unit`
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+48 | use std::f32::consts::E;
+   |
+48 | use std::f64::consts::E;
+   |
+
+error[E0423]: expected value, found struct variant `m::E::Struct`
+  --> $DIR/privacy-enum-ctor.rs:55:16
+   |
+55 |     let _: E = m::E::Struct;
+   |                ^^^^^^^^^^^^ did you mean `m::E::Struct { /* fields */ }`?
+
+error[E0423]: expected value, found enum `E`
+  --> $DIR/privacy-enum-ctor.rs:59:16
+   |
+59 |     let _: E = E;
+   |                ^
+   |
+   = note: did you mean to use one of the following variants?
+           - `E::Fn`
+           - `E::Struct`
+           - `E::Unit`
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+48 | use std::f32::consts::E;
+   |
+48 | use std::f64::consts::E;
+   |
+
+error[E0423]: expected value, found struct variant `E::Struct`
+  --> $DIR/privacy-enum-ctor.rs:63:16
+   |
+63 |     let _: E = E::Struct;
+   |                ^^^^^^^^^ did you mean `E::Struct { /* fields */ }`?
+
+error[E0412]: cannot find type `Z` in this scope
+  --> $DIR/privacy-enum-ctor.rs:67:12
+   |
+67 |     let _: Z = m::n::Z;
+   |            ^ did you mean `E`?
+help: possible candidate is found in another module, you can import it into scope
+   |
+48 | use m::n::Z;
+   |
+
+error[E0423]: expected value, found enum `m::n::Z`
+  --> $DIR/privacy-enum-ctor.rs:67:16
+   |
+67 |     let _: Z = m::n::Z;
+   |                ^^^^^^^
+   |
+   = note: did you mean to use one of the following variants?
+           - `m::Z::Fn`
+           - `m::Z::Struct`
+           - `m::Z::Unit`
+
+error[E0412]: cannot find type `Z` in this scope
+  --> $DIR/privacy-enum-ctor.rs:71:12
+   |
+71 |     let _: Z = m::n::Z::Fn;
+   |            ^ did you mean `E`?
+help: possible candidate is found in another module, you can import it into scope
+   |
+48 | use m::n::Z;
+   |
+
+error[E0412]: cannot find type `Z` in this scope
+  --> $DIR/privacy-enum-ctor.rs:74:12
+   |
+74 |     let _: Z = m::n::Z::Struct;
+   |            ^ did you mean `E`?
+help: possible candidate is found in another module, you can import it into scope
+   |
+48 | use m::n::Z;
+   |
+
+error[E0423]: expected value, found struct variant `m::n::Z::Struct`
+  --> $DIR/privacy-enum-ctor.rs:74:16
+   |
+74 |     let _: Z = m::n::Z::Struct;
+   |                ^^^^^^^^^^^^^^^ did you mean `m::n::Z::Struct { /* fields */ }`?
+
+error[E0412]: cannot find type `Z` in this scope
+  --> $DIR/privacy-enum-ctor.rs:78:12
+   |
+78 |     let _: Z = m::n::Z::Unit {};
+   |            ^ did you mean `E`?
+help: possible candidate is found in another module, you can import it into scope
+   |
+48 | use m::n::Z;
+   |
+
+error[E0603]: enum `Z` is private
+  --> $DIR/privacy-enum-ctor.rs:67:16
+   |
+67 |     let _: Z = m::n::Z;
+   |                ^^^^^^^
+
+error[E0603]: enum `Z` is private
+  --> $DIR/privacy-enum-ctor.rs:71:16
+   |
+71 |     let _: Z = m::n::Z::Fn;
+   |                ^^^^^^^^^^^
+
+error[E0603]: enum `Z` is private
+  --> $DIR/privacy-enum-ctor.rs:74:16
+   |
+74 |     let _: Z = m::n::Z::Struct;
+   |                ^^^^^^^^^^^^^^^
+
+error[E0603]: enum `Z` is private
+  --> $DIR/privacy-enum-ctor.rs:78:16
+   |
+78 |     let _: Z = m::n::Z::Unit {};
+   |                ^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/privacy-enum-ctor.rs:37:20
+   |
+37 |         let _: Z = Z::Fn;
+   |                    ^^^^^ expected enum `m::n::Z`, found fn item
+   |
+   = note: expected type `m::n::Z`
+              found type `fn(u8) -> m::n::Z {m::n::Z::Fn}`
+
+error[E0618]: expected function, found enum variant `Z::Unit`
+  --> $DIR/privacy-enum-ctor.rs:41:17
+   |
+26 |             Unit,
+   |             ---- `Z::Unit` defined here
+...
+41 |         let _ = Z::Unit();
+   |                 ^^^^^^^^^ not a function
+help: `Z::Unit` is a unit variant, you need to write it without the parenthesis
+   |
+41 |         let _ = Z::Unit;
+   |                 ^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/privacy-enum-ctor.rs:53:16
+   |
+53 |     let _: E = m::E::Fn;
+   |                ^^^^^^^^ expected enum `m::E`, found fn item
+   |
+   = note: expected type `m::E`
+              found type `fn(u8) -> m::E {m::E::Fn}`
+
+error[E0618]: expected function, found enum variant `m::E::Unit`
+  --> $DIR/privacy-enum-ctor.rs:57:16
+   |
+17 |         Unit,
+   |         ---- `m::E::Unit` defined here
+...
+57 |     let _: E = m::E::Unit();
+   |                ^^^^^^^^^^^^ not a function
+help: `m::E::Unit` is a unit variant, you need to write it without the parenthesis
+   |
+57 |     let _: E = m::E::Unit;
+   |                ^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/privacy-enum-ctor.rs:61:16
+   |
+61 |     let _: E = E::Fn;
+   |                ^^^^^ expected enum `m::E`, found fn item
+   |
+   = note: expected type `m::E`
+              found type `fn(u8) -> m::E {m::E::Fn}`
+
+error[E0618]: expected function, found enum variant `E::Unit`
+  --> $DIR/privacy-enum-ctor.rs:65:16
+   |
+17 |         Unit,
+   |         ---- `E::Unit` defined here
+...
+65 |     let _: E = E::Unit();
+   |                ^^^^^^^^^ not a function
+help: `E::Unit` is a unit variant, you need to write it without the parenthesis
+   |
+65 |     let _: E = E::Unit;
+   |                ^^^^^^^
+
+error: aborting due to 23 previous errors
+
diff --git a/src/test/ui/resolve/privacy-struct-ctor.rs b/src/test/ui/resolve/privacy-struct-ctor.rs
index eb6edae..9029eeb 100644
--- a/src/test/ui/resolve/privacy-struct-ctor.rs
+++ b/src/test/ui/resolve/privacy-struct-ctor.rs
@@ -14,6 +14,9 @@
 
 mod m {
     pub struct S(u8);
+    pub struct S2 {
+        s: u8
+    }
 
     pub mod n {
         pub(in m) struct Z(pub(in m::n) u8);
@@ -22,22 +25,33 @@
     use m::n::Z; // OK, only the type is imported
 
     fn f() {
-        n::Z; //~ ERROR tuple struct `Z` is private
+        n::Z;
+        //~^ ERROR tuple struct `Z` is private
         Z;
         //~^ ERROR expected value, found struct `Z`
     }
 }
 
 use m::S; // OK, only the type is imported
+use m::S2; // OK, only the type is imported
 
 fn main() {
-    m::S; //~ ERROR tuple struct `S` is private
+    m::S;
+    //~^ ERROR tuple struct `S` is private
+    let _: S = m::S(2);
+    //~^ ERROR tuple struct `S` is private
     S;
     //~^ ERROR expected value, found struct `S`
-    m::n::Z; //~ ERROR tuple struct `Z` is private
+    m::n::Z;
+    //~^ ERROR tuple struct `Z` is private
 
-    xcrate::m::S; //~ ERROR tuple struct `S` is private
+    S2;
+    //~^ ERROR expected value, found struct `S2`
+
+    xcrate::m::S;
+    //~^ ERROR tuple struct `S` is private
     xcrate::S;
     //~^ ERROR expected value, found struct `xcrate::S`
-    xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private
+    xcrate::m::n::Z;
+    //~^ ERROR tuple struct `Z` is private
 }
diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr
index 39bedf5..e97a4e4 100644
--- a/src/test/ui/resolve/privacy-struct-ctor.stderr
+++ b/src/test/ui/resolve/privacy-struct-ctor.stderr
@@ -1,72 +1,77 @@
 error[E0423]: expected value, found struct `Z`
-  --> $DIR/privacy-struct-ctor.rs:26:9
+  --> $DIR/privacy-struct-ctor.rs:30:9
    |
-26 |         Z;
+30 |         Z;
    |         ^
    |         |
    |         did you mean `S`?
    |         constructor is not visible here due to private fields
-   |         did you mean `Z { /* fields */ }`?
 help: possible better candidate is found in another module, you can import it into scope
    |
-22 |     use m::n::Z;
+25 |     use m::n::Z;
    |
 
 error[E0423]: expected value, found struct `S`
-  --> $DIR/privacy-struct-ctor.rs:35:5
+  --> $DIR/privacy-struct-ctor.rs:43:5
    |
-35 |     S;
-   |     ^
-   |     |
-   |     constructor is not visible here due to private fields
-   |     did you mean `S { /* fields */ }`?
+43 |     S;
+   |     ^ constructor is not visible here due to private fields
 help: possible better candidate is found in another module, you can import it into scope
    |
-31 | use m::S;
+35 | use m::S;
    |
 
+error[E0423]: expected value, found struct `S2`
+  --> $DIR/privacy-struct-ctor.rs:48:5
+   |
+48 |     S2;
+   |     ^^ did you mean `S2 { /* fields */ }`?
+
 error[E0423]: expected value, found struct `xcrate::S`
-  --> $DIR/privacy-struct-ctor.rs:40:5
+  --> $DIR/privacy-struct-ctor.rs:53:5
    |
-40 |     xcrate::S;
-   |     ^^^^^^^^^
-   |     |
-   |     constructor is not visible here due to private fields
-   |     did you mean `xcrate::S { /* fields */ }`?
+53 |     xcrate::S;
+   |     ^^^^^^^^^ constructor is not visible here due to private fields
 help: possible better candidate is found in another module, you can import it into scope
    |
-31 | use m::S;
+35 | use m::S;
    |
 
 error[E0603]: tuple struct `Z` is private
-  --> $DIR/privacy-struct-ctor.rs:25:9
+  --> $DIR/privacy-struct-ctor.rs:28:9
    |
-25 |         n::Z; //~ ERROR tuple struct `Z` is private
+28 |         n::Z;
    |         ^^^^
 
 error[E0603]: tuple struct `S` is private
-  --> $DIR/privacy-struct-ctor.rs:34:5
-   |
-34 |     m::S; //~ ERROR tuple struct `S` is private
-   |     ^^^^
-
-error[E0603]: tuple struct `Z` is private
-  --> $DIR/privacy-struct-ctor.rs:37:5
-   |
-37 |     m::n::Z; //~ ERROR tuple struct `Z` is private
-   |     ^^^^^^^
-
-error[E0603]: tuple struct `S` is private
   --> $DIR/privacy-struct-ctor.rs:39:5
    |
-39 |     xcrate::m::S; //~ ERROR tuple struct `S` is private
+39 |     m::S;
+   |     ^^^^
+
+error[E0603]: tuple struct `S` is private
+  --> $DIR/privacy-struct-ctor.rs:41:16
+   |
+41 |     let _: S = m::S(2);
+   |                ^^^^
+
+error[E0603]: tuple struct `Z` is private
+  --> $DIR/privacy-struct-ctor.rs:45:5
+   |
+45 |     m::n::Z;
+   |     ^^^^^^^
+
+error[E0603]: tuple struct `S` is private
+  --> $DIR/privacy-struct-ctor.rs:51:5
+   |
+51 |     xcrate::m::S;
    |     ^^^^^^^^^^^^
 
 error[E0603]: tuple struct `Z` is private
-  --> $DIR/privacy-struct-ctor.rs:42:5
+  --> $DIR/privacy-struct-ctor.rs:55:5
    |
-42 |     xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private
+55 |     xcrate::m::n::Z;
    |     ^^^^^^^^^^^^^^^
 
-error: aborting due to 8 previous errors
+error: aborting due to 10 previous errors
 
diff --git a/src/test/ui/resolve/tuple-struct-alias.stderr b/src/test/ui/resolve/tuple-struct-alias.stderr
index aea9fc3..843d7c2 100644
--- a/src/test/ui/resolve/tuple-struct-alias.stderr
+++ b/src/test/ui/resolve/tuple-struct-alias.stderr
@@ -2,31 +2,33 @@
   --> $DIR/tuple-struct-alias.rs:16:17
    |
 16 |         let s = Self(0, 1); //~ ERROR expected function
-   |                 ^^^^ did you mean `Self { /* fields */ }`?
+   |                 ^^^^ not a function
+   |
+   = note: can't use `Self` as a constructor, you must use the implemented struct
 
 error[E0532]: expected tuple struct/variant, found self type `Self`
   --> $DIR/tuple-struct-alias.rs:18:13
    |
 18 |             Self(..) => {} //~ ERROR expected tuple struct/variant
-   |             ^^^^ did you mean `Self { /* fields */ }`?
+   |             ^^^^ not a tuple struct/variant
+   |
+   = note: can't use `Self` as a constructor, you must use the implemented struct
 
 error[E0423]: expected function, found type alias `A`
   --> $DIR/tuple-struct-alias.rs:24:13
    |
 24 |     let s = A(0, 1); //~ ERROR expected function
-   |             ^
-   |             |
-   |             did you mean `S`?
-   |             did you mean `A { /* fields */ }`?
+   |             ^ did you mean `S`?
+   |
+   = note: can't use a type alias as a constructor
 
 error[E0532]: expected tuple struct/variant, found type alias `A`
   --> $DIR/tuple-struct-alias.rs:26:9
    |
 26 |         A(..) => {} //~ ERROR expected tuple struct/variant
-   |         ^
-   |         |
-   |         did you mean `S`?
-   |         did you mean `A { /* fields */ }`?
+   |         ^ did you mean `S`?
+   |
+   = note: can't use a type alias as a constructor
 
 error: aborting due to 4 previous errors