]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #43091 - aidanhs:aphs-no-docker-priv, r=alexcrichton
authorbors <bors@rust-lang.org>
Fri, 7 Jul 2017 08:13:20 +0000 (08:13 +0000)
committerbors <bors@rust-lang.org>
Fri, 7 Jul 2017 08:13:20 +0000 (08:13 +0000)
Privileged in docker run isn't necessary

Added relatively recently in https://github.com/rust-lang/rust/pull/40199/files#diff-71609a365528e4649836825d8250c241R57, but I don't see anything in that PR that requires it. If it's not strictly necessary, we shouldn't use it.

(if this lands I'll make a PR against libc which also uses privileged)

r? @alexcrichton

42 files changed:
src/ci/init_repo.sh
src/libproc_macro/quote.rs
src/librustc_errors/emitter.rs
src/librustc_errors/lib.rs
src/librustc_privacy/lib.rs
src/librustdoc/markdown.rs
src/libstd/net/tcp.rs
src/libstd/sys/redox/net/tcp.rs
src/libstd/sys/unix/net.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/net.rs
src/libstd/sys_common/net.rs
src/libsyntax/json.rs
src/libsyntax/parse/parser.rs
src/test/compile-fail/auxiliary/private-inferred-type.rs [new file with mode: 0644]
src/test/compile-fail/hygiene/auxiliary/intercrate.rs [new file with mode: 0644]
src/test/compile-fail/hygiene/fields.rs [new file with mode: 0644]
src/test/compile-fail/hygiene/impl_items.rs [new file with mode: 0644]
src/test/compile-fail/hygiene/intercrate.rs [new file with mode: 0644]
src/test/compile-fail/private-inferred-type-1.rs [new file with mode: 0644]
src/test/compile-fail/private-inferred-type-2.rs [new file with mode: 0644]
src/test/compile-fail/private-inferred-type-3.rs [new file with mode: 0644]
src/test/compile-fail/private-inferred-type.rs [new file with mode: 0644]
src/test/compile-fail/private-type-in-interface.rs [new file with mode: 0644]
src/test/run-pass/hygiene/auxiliary/intercrate.rs [deleted file]
src/test/run-pass/hygiene/fields.rs [deleted file]
src/test/run-pass/hygiene/impl_items.rs [deleted file]
src/test/run-pass/hygiene/intercrate.rs [deleted file]
src/test/ui/block-result/unexpected-return-on-unit.stderr
src/test/ui/issue-22644.rs
src/test/ui/issue-22644.stderr
src/test/ui/resolve/enums-are-namespaced-xc.stderr
src/test/ui/resolve/issue-16058.stderr
src/test/ui/resolve/issue-17518.stderr
src/test/ui/resolve/issue-21221-1.stderr
src/test/ui/resolve/issue-21221-2.stderr
src/test/ui/resolve/issue-21221-3.stderr
src/test/ui/resolve/issue-21221-4.stderr
src/test/ui/resolve/issue-3907.stderr
src/test/ui/resolve/privacy-struct-ctor.stderr
src/test/ui/span/issue-35987.stderr
src/test/ui/span/issue-39018.stderr

index f8e86986f82d075123dee5ba904b6f2fe773d054..7ffe00a807b343132e14d3658c4e6622c5b640c9 100755 (executable)
@@ -61,7 +61,8 @@ for module in $modules; do
     if [ "$module" = src/llvm ]; then
         commit="$(git ls-tree HEAD src/llvm | awk '{print $3}')"
         git rm src/llvm
-        curl -sSL -O "https://github.com/rust-lang/llvm/archive/$commit.tar.gz"
+        retry sh -c "rm -f $commit.tar.gz && \
+            curl -sSL -O https://github.com/rust-lang/llvm/archive/$commit.tar.gz"
         tar -C src/ -xf "$commit.tar.gz"
         rm "$commit.tar.gz"
         mv "src/llvm-$commit" src/llvm
index bee2c1e0eb6b608a21e273a383bea64221d4a3ba..0db2b86b15f5725109d89fa6d2522ce040e4a1a6 100644 (file)
@@ -87,7 +87,7 @@ fn expand<'cx>(&self, cx: &'cx mut ExtCtxt, _: Span, stream: TokenStream) -> Tok
         let mut info = cx.current_expansion.mark.expn_info().unwrap();
         info.callee.allow_internal_unstable = true;
         cx.current_expansion.mark.set_expn_info(info);
-        ::__internal::set_sess(cx, || quote!(::TokenStream((quote stream))))
+        ::__internal::set_sess(cx, || quote!(::TokenStream { 0: (quote stream) }))
     }
 }
 
index 4b71aa6b85f1c91c24f8dd0ea3a19fed0da9bf70..a6a45c8b5023a2d04fa94e561f28408f6babaa64 100644 (file)
@@ -1060,44 +1060,72 @@ fn emit_suggestion_default(&mut self,
                                -> io::Result<()> {
         use std::borrow::Borrow;
 
-        let primary_span = suggestion.substitution_spans().next().unwrap();
+        let primary_sub = &suggestion.substitution_parts[0];
         if let Some(ref cm) = self.cm {
             let mut buffer = StyledBuffer::new();
 
-            let lines = cm.span_to_lines(primary_span).unwrap();
+            let lines = cm.span_to_lines(primary_sub.span).unwrap();
 
             assert!(!lines.lines.is_empty());
 
             buffer.append(0, &level.to_string(), Style::Level(level.clone()));
             buffer.append(0, ": ", Style::HeaderMsg);
             self.msg_to_buffer(&mut buffer,
-                            &[(suggestion.msg.to_owned(), Style::NoStyle)],
-                            max_line_num_len,
-                            "suggestion",
-                            Some(Style::HeaderMsg));
+                               &[(suggestion.msg.to_owned(), Style::NoStyle)],
+                               max_line_num_len,
+                               "suggestion",
+                               Some(Style::HeaderMsg));
 
             let suggestions = suggestion.splice_lines(cm.borrow());
-            let mut row_num = 1;
-            for complete in suggestions.iter().take(MAX_SUGGESTIONS) {
-
-                // print the suggestion without any line numbers, but leave
-                // space for them. This helps with lining up with previous
-                // snippets from the actual error being reported.
+            let span_start_pos = cm.lookup_char_pos(primary_sub.span.lo);
+            let line_start = span_start_pos.line;
+            draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1);
+            let mut row_num = 2;
+            for (&(ref complete, show_underline), ref sub) in suggestions
+                    .iter().zip(primary_sub.substitutions.iter()).take(MAX_SUGGESTIONS)
+            {
+                let mut line_pos = 0;
+                // Only show underline if there's a single suggestion and it is a single line
                 let mut lines = complete.lines();
                 for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) {
+                    // Print the span column to avoid confusion
+                    buffer.puts(row_num,
+                                0,
+                                &((line_start + line_pos).to_string()),
+                                Style::LineNumber);
+                    // print the suggestion
                     draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
                     buffer.append(row_num, line, Style::NoStyle);
+                    line_pos += 1;
                     row_num += 1;
+                    // Only show an underline in the suggestions if the suggestion is not the
+                    // entirety of the code being shown and the displayed code is not multiline.
+                    if show_underline {
+                        draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
+                        let sub_len = sub.trim_right().len();
+                        let underline_start = span_start_pos.col.0;
+                        let underline_end = span_start_pos.col.0 + sub_len;
+                        for p in underline_start..underline_end {
+                            buffer.putc(row_num,
+                                        max_line_num_len + 3 + p,
+                                        '^',
+                                        Style::UnderlinePrimary);
+                        }
+                        row_num += 1;
+                    }
                 }
 
                 // if we elided some lines, add an ellipsis
                 if let Some(_) = lines.next() {
-                    buffer.append(row_num, "...", Style::NoStyle);
+                    buffer.puts(row_num, max_line_num_len - 1, "...", Style::LineNumber);
+                } else if !show_underline {
+                    draw_col_separator_no_space(&mut buffer, row_num, max_line_num_len + 1);
+                    row_num += 1;
                 }
             }
             if suggestions.len() > MAX_SUGGESTIONS {
                 let msg = format!("and {} other candidates", suggestions.len() - MAX_SUGGESTIONS);
-                buffer.append(row_num, &msg, Style::NoStyle);
+                buffer.puts(row_num, 0, &msg, Style::NoStyle);
             }
             emit_to_destination(&buffer.render(), level, &mut self.dst)?;
         }
index dd25f96941401f868d69e8502db9d9df14a34aa5..7fb75a263f93d04c2b83b030e383ff6e82768a0c 100644 (file)
@@ -114,8 +114,8 @@ pub fn substitution_spans<'a>(&'a self) -> impl Iterator<Item = Span> + 'a {
         self.substitution_parts.iter().map(|sub| sub.span)
     }
 
-    /// Returns the assembled code suggestions.
-    pub fn splice_lines(&self, cm: &CodeMapper) -> Vec<String> {
+    /// Returns the assembled code suggestions and wether they should be shown with an underline.
+    pub fn splice_lines(&self, cm: &CodeMapper) -> Vec<(String, bool)> {
         use syntax_pos::{CharPos, Loc, Pos};
 
         fn push_trailing(buf: &mut String,
@@ -138,7 +138,7 @@ fn push_trailing(buf: &mut String,
         }
 
         if self.substitution_parts.is_empty() {
-            return vec![String::new()];
+            return vec![(String::new(), false)];
         }
 
         let mut primary_spans: Vec<_> = self.substitution_parts
@@ -175,14 +175,25 @@ fn push_trailing(buf: &mut String,
         prev_hi.col = CharPos::from_usize(0);
 
         let mut prev_line = fm.get_line(lines.lines[0].line_index);
-        let mut bufs = vec![String::new(); self.substitutions()];
+        let mut bufs = vec![(String::new(), false); self.substitutions()];
 
         for (sp, substitutes) in primary_spans {
             let cur_lo = cm.lookup_char_pos(sp.lo);
-            for (buf, substitute) in bufs.iter_mut().zip(substitutes) {
+            for (&mut (ref mut buf, ref mut underline), substitute) in bufs.iter_mut()
+                                                                           .zip(substitutes) {
                 if prev_hi.line == cur_lo.line {
                     push_trailing(buf, prev_line.as_ref(), &prev_hi, Some(&cur_lo));
+
+                    // Only show an underline in the suggestions if the suggestion is not the
+                    // entirety of the code being shown and the displayed code is not multiline.
+                    if prev_line.as_ref().unwrap().trim().len() > 0
+                        && !substitute.ends_with('\n')
+                        && substitute.lines().count() == 1
+                    {
+                        *underline = true;
+                    }
                 } else {
+                    *underline = false;
                     push_trailing(buf, prev_line.as_ref(), &prev_hi, None);
                     // push lines between the previous and current span (if any)
                     for idx in prev_hi.line..(cur_lo.line - 1) {
@@ -200,7 +211,7 @@ fn push_trailing(buf: &mut String,
             prev_hi = cm.lookup_char_pos(sp.hi);
             prev_line = fm.get_line(prev_hi.line - 1);
         }
-        for buf in &mut bufs {
+        for &mut (ref mut buf, _) in &mut bufs {
             // if the replacement already ends with a newline, don't print the next line
             if !buf.ends_with('\n') {
                 push_trailing(buf, prev_line.as_ref(), &prev_hi, None);
index 9eb96fea52778e6677d09a28deacfd1ee99d15fe..051b89219c1f54cd8141472d03f9daacacac3348 100644 (file)
 
 #![feature(rustc_diagnostic_macros)]
 
-extern crate rustc;
+#[macro_use] extern crate rustc;
 #[macro_use] extern crate syntax;
 extern crate syntax_pos;
 
 use rustc::hir::{self, PatKind};
 use rustc::hir::def::Def;
-use rustc::hir::def_id::{LOCAL_CRATE, CrateNum, DefId};
+use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir::itemlikevisit::DeepVisitor;
 use rustc::lint;
@@ -537,6 +537,344 @@ fn visit_pat(&mut self, pat: &'tcx hir::Pat) {
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////////////////
+/// Type privacy visitor, checks types for privacy and reports violations.
+/// Both explicitly written types and inferred types of expressions and patters are checked.
+/// Checks are performed on "semantic" types regardless of names and their hygiene.
+////////////////////////////////////////////////////////////////////////////////////////////
+
+struct TypePrivacyVisitor<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    tables: &'a ty::TypeckTables<'tcx>,
+    current_item: DefId,
+    span: Span,
+}
+
+impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
+    fn def_id_visibility(&self, did: DefId) -> ty::Visibility {
+        match self.tcx.hir.as_local_node_id(did) {
+            Some(node_id) => {
+                let vis = match self.tcx.hir.get(node_id) {
+                    hir::map::NodeItem(item) => &item.vis,
+                    hir::map::NodeForeignItem(foreign_item) => &foreign_item.vis,
+                    hir::map::NodeImplItem(impl_item) => &impl_item.vis,
+                    hir::map::NodeTraitItem(..) |
+                    hir::map::NodeVariant(..) => {
+                        return self.def_id_visibility(self.tcx.hir.get_parent_did(node_id));
+                    }
+                    hir::map::NodeStructCtor(vdata) => {
+                        let struct_node_id = self.tcx.hir.get_parent(node_id);
+                        let struct_vis = match self.tcx.hir.get(struct_node_id) {
+                            hir::map::NodeItem(item) => &item.vis,
+                            node => bug!("unexpected node kind: {:?}", node),
+                        };
+                        let mut ctor_vis
+                            = ty::Visibility::from_hir(struct_vis, struct_node_id, self.tcx);
+                        for field in vdata.fields() {
+                            let field_vis = ty::Visibility::from_hir(&field.vis, node_id, self.tcx);
+                            if ctor_vis.is_at_least(field_vis, self.tcx) {
+                                ctor_vis = field_vis;
+                            }
+                        }
+                        return ctor_vis;
+                    }
+                    node => bug!("unexpected node kind: {:?}", node)
+                };
+                ty::Visibility::from_hir(vis, node_id, self.tcx)
+            }
+            None => self.tcx.sess.cstore.visibility(did),
+        }
+    }
+
+    fn item_is_accessible(&self, did: DefId) -> bool {
+        self.def_id_visibility(did).is_accessible_from(self.current_item, self.tcx)
+    }
+
+    // Take node ID of an expression or pattern and check its type for privacy.
+    fn check_expr_pat_type(&mut self, id: ast::NodeId, span: Span) -> bool {
+        self.span = span;
+        if let Some(ty) = self.tables.node_id_to_type_opt(id) {
+            if ty.visit_with(self) {
+                return true;
+            }
+        }
+        if self.tables.node_substs(id).visit_with(self) {
+            return true;
+        }
+        if let Some(adjustments) = self.tables.adjustments.get(&id) {
+            for adjustment in adjustments {
+                if adjustment.target.visit_with(self) {
+                    return true;
+                }
+            }
+        }
+        false
+    }
+
+    fn check_item(&mut self, item_id: ast::NodeId) -> &mut Self {
+        self.current_item = self.tcx.hir.local_def_id(item_id);
+        self.span = self.tcx.hir.span(item_id);
+        self
+    }
+
+    // Convenience methods for checking item interfaces
+    fn ty(&mut self) -> &mut Self {
+        self.tcx.type_of(self.current_item).visit_with(self);
+        self
+    }
+
+    fn generics(&mut self) -> &mut Self {
+        for def in &self.tcx.generics_of(self.current_item).types {
+            if def.has_default {
+                self.tcx.type_of(def.def_id).visit_with(self);
+            }
+        }
+        self
+    }
+
+    fn predicates(&mut self) -> &mut Self {
+        self.tcx.predicates_of(self.current_item).visit_with(self);
+        self
+    }
+
+    fn impl_trait_ref(&mut self) -> &mut Self {
+        self.tcx.impl_trait_ref(self.current_item).visit_with(self);
+        self
+    }
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
+    /// We want to visit items in the context of their containing
+    /// module and so forth, so supply a crate for doing a deep walk.
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+        NestedVisitorMap::All(&self.tcx.hir)
+    }
+
+    fn visit_nested_body(&mut self, body: hir::BodyId) {
+        let orig_tables = replace(&mut self.tables, self.tcx.body_tables(body));
+        let body = self.tcx.hir.body(body);
+        self.visit_body(body);
+        self.tables = orig_tables;
+    }
+
+    // Check types of expressions
+    fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
+        if self.check_expr_pat_type(expr.id, expr.span) {
+            // Do not check nested expressions if the error already happened.
+            return;
+        }
+        match expr.node {
+            hir::ExprAssign(.., ref rhs) | hir::ExprMatch(ref rhs, ..) => {
+                // Do not report duplicate errors for `x = y` and `match x { ... }`.
+                if self.check_expr_pat_type(rhs.id, rhs.span) {
+                    return;
+                }
+            }
+            hir::ExprMethodCall(name, ..) => {
+                // Method calls have to be checked specially.
+                let def_id = self.tables.type_dependent_defs[&expr.id].def_id();
+                self.span = name.span;
+                if self.tcx.type_of(def_id).visit_with(self) {
+                    return;
+                }
+            }
+            _ => {}
+        }
+
+        intravisit::walk_expr(self, expr);
+    }
+
+    fn visit_qpath(&mut self, qpath: &'tcx hir::QPath, id: ast::NodeId, span: Span) {
+        // Inherent associated constants don't have self type in substs,
+        // we have to check it additionally.
+        if let hir::QPath::TypeRelative(..) = *qpath {
+            if let Some(def) = self.tables.type_dependent_defs.get(&id).cloned() {
+                if let Some(assoc_item) = self.tcx.opt_associated_item(def.def_id()) {
+                    if let ty::ImplContainer(impl_def_id) = assoc_item.container {
+                        if self.tcx.type_of(impl_def_id).visit_with(self) {
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+
+        intravisit::walk_qpath(self, qpath, id, span);
+    }
+
+    // Check types of patterns
+    fn visit_pat(&mut self, pattern: &'tcx hir::Pat) {
+        if self.check_expr_pat_type(pattern.id, pattern.span) {
+            // Do not check nested patterns if the error already happened.
+            return;
+        }
+
+        intravisit::walk_pat(self, pattern);
+    }
+
+    fn visit_local(&mut self, local: &'tcx hir::Local) {
+        if let Some(ref init) = local.init {
+            if self.check_expr_pat_type(init.id, init.span) {
+                // Do not report duplicate errors for `let x = y`.
+                return;
+            }
+        }
+
+        intravisit::walk_local(self, local);
+    }
+
+    // Check types in item interfaces
+    fn visit_item(&mut self, item: &'tcx hir::Item) {
+        let orig_current_item = self.current_item;
+
+        match item.node {
+            hir::ItemExternCrate(..) | hir::ItemMod(..) |
+            hir::ItemUse(..) | hir::ItemGlobalAsm(..) => {}
+            hir::ItemConst(..) | hir::ItemStatic(..) |
+            hir::ItemTy(..) | hir::ItemFn(..) => {
+                self.check_item(item.id).generics().predicates().ty();
+            }
+            hir::ItemTrait(.., ref trait_item_refs) => {
+                self.check_item(item.id).generics().predicates();
+                for trait_item_ref in trait_item_refs {
+                    let mut check = self.check_item(trait_item_ref.id.node_id);
+                    check.generics().predicates();
+                    if trait_item_ref.kind != hir::AssociatedItemKind::Type ||
+                       trait_item_ref.defaultness.has_value() {
+                        check.ty();
+                    }
+                }
+            }
+            hir::ItemEnum(ref def, _) => {
+                self.check_item(item.id).generics().predicates();
+                for variant in &def.variants {
+                    for field in variant.node.data.fields() {
+                        self.check_item(field.id).ty();
+                    }
+                }
+            }
+            hir::ItemForeignMod(ref foreign_mod) => {
+                for foreign_item in &foreign_mod.items {
+                    self.check_item(foreign_item.id).generics().predicates().ty();
+                }
+            }
+            hir::ItemStruct(ref struct_def, _) |
+            hir::ItemUnion(ref struct_def, _) => {
+                self.check_item(item.id).generics().predicates();
+                for field in struct_def.fields() {
+                    self.check_item(field.id).ty();
+                }
+            }
+            hir::ItemDefaultImpl(..) => {
+                self.check_item(item.id).impl_trait_ref();
+            }
+            hir::ItemImpl(.., ref trait_ref, _, ref impl_item_refs) => {
+                {
+                    let mut check = self.check_item(item.id);
+                    check.ty().generics().predicates();
+                    if trait_ref.is_some() {
+                        check.impl_trait_ref();
+                    }
+                }
+                for impl_item_ref in impl_item_refs {
+                    let impl_item = self.tcx.hir.impl_item(impl_item_ref.id);
+                    self.check_item(impl_item.id).generics().predicates().ty();
+                }
+            }
+        }
+
+        self.current_item = self.tcx.hir.local_def_id(item.id);
+        intravisit::walk_item(self, item);
+        self.current_item = orig_current_item;
+    }
+}
+
+impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
+    fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
+        match ty.sty {
+            ty::TyAdt(&ty::AdtDef { did: def_id, .. }, ..) | ty::TyFnDef(def_id, ..) => {
+                if !self.item_is_accessible(def_id) {
+                    let msg = format!("type `{}` is private", ty);
+                    self.tcx.sess.span_err(self.span, &msg);
+                    return true;
+                }
+                if let ty::TyFnDef(..) = ty.sty {
+                    if self.tcx.fn_sig(def_id).visit_with(self) {
+                        return true;
+                    }
+                }
+                // Inherent static methods don't have self type in substs,
+                // we have to check it additionally.
+                if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) {
+                    if let ty::ImplContainer(impl_def_id) = assoc_item.container {
+                        if self.tcx.type_of(impl_def_id).visit_with(self) {
+                            return true;
+                        }
+                    }
+                }
+            }
+            ty::TyDynamic(ref predicates, ..) => {
+                let is_private = predicates.skip_binder().iter().any(|predicate| {
+                    let def_id = match *predicate {
+                        ty::ExistentialPredicate::Trait(trait_ref) => trait_ref.def_id,
+                        ty::ExistentialPredicate::Projection(proj) => proj.trait_ref.def_id,
+                        ty::ExistentialPredicate::AutoTrait(def_id) => def_id,
+                    };
+                    !self.item_is_accessible(def_id)
+                });
+                if is_private {
+                    let msg = format!("type `{}` is private", ty);
+                    self.tcx.sess.span_err(self.span, &msg);
+                    return true;
+                }
+            }
+            ty::TyAnon(def_id, ..) => {
+                for predicate in &self.tcx.predicates_of(def_id).predicates {
+                    let trait_ref = match *predicate {
+                        ty::Predicate::Trait(ref poly_trait_predicate) => {
+                            Some(poly_trait_predicate.skip_binder().trait_ref)
+                        }
+                        ty::Predicate::Projection(ref poly_projection_predicate) => {
+                            if poly_projection_predicate.skip_binder().ty.visit_with(self) {
+                                return true;
+                            }
+                            Some(poly_projection_predicate.skip_binder().projection_ty.trait_ref)
+                        }
+                        ty::Predicate::TypeOutlives(..) => None,
+                        _ => bug!("unexpected predicate: {:?}", predicate),
+                    };
+                    if let Some(trait_ref) = trait_ref {
+                        if !self.item_is_accessible(trait_ref.def_id) {
+                            let msg = format!("trait `{}` is private", trait_ref);
+                            self.tcx.sess.span_err(self.span, &msg);
+                            return true;
+                        }
+                        // `Self` here is the same `TyAnon`, so skip it to avoid infinite recursion
+                        for subst in trait_ref.substs.iter().skip(1) {
+                            if subst.visit_with(self) {
+                                return true;
+                            }
+                        }
+                    }
+                }
+            }
+            _ => {}
+        }
+
+        ty.super_visit_with(self)
+    }
+
+    fn visit_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool {
+        if !self.item_is_accessible(trait_ref.def_id) {
+            let msg = format!("trait `{}` is private", trait_ref);
+            self.tcx.sess.span_err(self.span, &msg);
+            return true;
+        }
+
+        trait_ref.super_visit_with(self)
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 /// Obsolete visitors for checking for private items in public interfaces.
 /// These visitors are supposed to be kept in frozen state and produce an
@@ -1225,6 +1563,16 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     };
     intravisit::walk_crate(&mut visitor, krate);
 
+    // Check privacy of explicitly written types and traits as well as
+    // inferred types of expressions and patterns.
+    let mut visitor = TypePrivacyVisitor {
+        tcx: tcx,
+        tables: &ty::TypeckTables::empty(),
+        current_item: DefId::local(CRATE_DEF_INDEX),
+        span: krate.span,
+    };
+    intravisit::walk_crate(&mut visitor, krate);
+
     // Build up a set of all exported items in the AST. This is a set of all
     // items which are reachable from external crates based on visibility.
     let mut visitor = EmbargoVisitor {
index 057ce69d9de8bcf925f59cb3a9c7700763202d40..57e8e88cd13dd7795944d2a44c6d12f1ab594db0 100644 (file)
@@ -163,8 +163,12 @@ pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
                                        true, opts, maybe_sysroot, None,
                                        Some(input.to_owned()),
                                        render_type);
-    old_find_testable_code(&input_str, &mut collector, DUMMY_SP);
-    find_testable_code(&input_str, &mut collector, DUMMY_SP);
+    if render_type == RenderType::Pulldown {
+        old_find_testable_code(&input_str, &mut collector, DUMMY_SP);
+        find_testable_code(&input_str, &mut collector, DUMMY_SP);
+    } else {
+        old_find_testable_code(&input_str, &mut collector, DUMMY_SP);
+    }
     test_args.insert(0, "rustdoctest".to_string());
     testing::test_main(&test_args, collector.tests,
                        testing::Options::new().display_output(display_warnings));
index 7be1fc9cd8c94e1acca2e199d0d50e9593b9c10e..fdeca8bc5cac3836f2c22e67860fe6410b3b4c6e 100644 (file)
@@ -134,6 +134,24 @@ pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
         super::each_addr(addr, net_imp::TcpStream::connect).map(TcpStream)
     }
 
+    /// Opens a TCP connection to a remote host with a timeout.
+    ///
+    /// Unlike `connect`, `connect_timeout` takes a single [`SocketAddr`] since
+    /// timeout must be applied to individual addresses.
+    ///
+    /// It is an error to pass a zero `Duration` to this function.
+    ///
+    /// Unlike other methods on `TcpStream`, this does not correspond to a
+    /// single system call. It instead calls `connect` in nonblocking mode and
+    /// then uses an OS-specific mechanism to await the completion of the
+    /// connection request.
+    ///
+    /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
+    #[unstable(feature = "tcpstream_connect_timeout", issue = "43709")]
+    pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
+        net_imp::TcpStream::connect_timeout(addr, timeout).map(TcpStream)
+    }
+
     /// Returns the socket address of the remote peer of this TCP connection.
     ///
     /// # Examples
@@ -1509,4 +1527,19 @@ fn peek() {
             t!(txdone.send(()));
         })
     }
+
+    #[test]
+    fn connect_timeout_unroutable() {
+        // this IP is unroutable, so connections should always time out.
+        let addr = "10.255.255.1:80".parse().unwrap();
+        let e = TcpStream::connect_timeout(&addr, Duration::from_millis(250)).unwrap_err();
+        assert_eq!(e.kind(), io::ErrorKind::TimedOut);
+    }
+
+    #[test]
+    fn connect_timeout_valid() {
+        let listener = TcpListener::bind("127.0.0.1:0").unwrap();
+        let addr = listener.local_addr().unwrap();
+        TcpStream::connect_timeout(&addr, Duration::from_secs(2)).unwrap();
+    }
 }
index 17673f0bd60b3b5a7525f709ce002e6825cfe55a..5d1067e4039bad6908be7af1d481cfe4df0a79fa 100644 (file)
@@ -32,6 +32,10 @@ pub fn connect(addr: &SocketAddr) -> Result<TcpStream> {
         Ok(TcpStream(File::open(&Path::new(path.as_str()), &options)?))
     }
 
+    pub fn connect_timeout(_addr: &SocketAddr, _timeout: Duration) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "TcpStream::connect_timeout not implemented"))
+    }
+
     pub fn duplicate(&self) -> Result<TcpStream> {
         Ok(TcpStream(self.0.dup(&[])?))
     }
index 8fb361a78e2d71c8cff94b0b38f48e7968d1a969..668b2f92aba0791ad9148fb2a3c1f64d683a21f3 100644 (file)
@@ -17,7 +17,8 @@
 use sys::fd::FileDesc;
 use sys_common::{AsInner, FromInner, IntoInner};
 use sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr};
-use time::Duration;
+use time::{Duration, Instant};
+use cmp;
 
 pub use sys::{cvt, cvt_r};
 pub extern crate libc as netc;
@@ -122,6 +123,70 @@ pub fn new_pair(fam: c_int, ty: c_int) -> io::Result<(Socket, Socket)> {
         }
     }
 
+    pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> {
+        self.set_nonblocking(true)?;
+        let r = unsafe {
+            let (addrp, len) = addr.into_inner();
+            cvt(libc::connect(self.0.raw(), addrp, len))
+        };
+        self.set_nonblocking(false)?;
+
+        match r {
+            Ok(_) => return Ok(()),
+            // there's no ErrorKind for EINPROGRESS :(
+            Err(ref e) if e.raw_os_error() == Some(libc::EINPROGRESS) => {}
+            Err(e) => return Err(e),
+        }
+
+        let mut pollfd = libc::pollfd {
+            fd: self.0.raw(),
+            events: libc::POLLOUT,
+            revents: 0,
+        };
+
+        if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 {
+            return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                      "cannot set a 0 duration timeout"));
+        }
+
+        let start = Instant::now();
+
+        loop {
+            let elapsed = start.elapsed();
+            if elapsed >= timeout {
+                return Err(io::Error::new(io::ErrorKind::TimedOut, "connection timed out"));
+            }
+
+            let timeout = timeout - elapsed;
+            let mut timeout = timeout.as_secs()
+                .saturating_mul(1_000)
+                .saturating_add(timeout.subsec_nanos() as u64 / 1_000_000);
+            if timeout == 0 {
+                timeout = 1;
+            }
+
+            let timeout = cmp::min(timeout, c_int::max_value() as u64) as c_int;
+
+            match unsafe { libc::poll(&mut pollfd, 1, timeout) } {
+                -1 => {
+                    let err = io::Error::last_os_error();
+                    if err.kind() != io::ErrorKind::Interrupted {
+                        return Err(err);
+                    }
+                }
+                0 => {}
+                _ => {
+                    if pollfd.revents & libc::POLLOUT == 0 {
+                        if let Some(e) = self.take_error()? {
+                            return Err(e);
+                        }
+                    }
+                    return Ok(());
+                }
+            }
+        }
+    }
+
     pub fn accept(&self, storage: *mut sockaddr, len: *mut socklen_t)
                   -> io::Result<Socket> {
         // Unfortunately the only known way right now to accept a socket and
index 1646f8cce72326e05c778bf88933b892479f6695..4785cefd6b4b7a78a8c782eb98ebab9a72b61397 100644 (file)
@@ -298,6 +298,8 @@ pub struct ipv6_mreq {
 pub const PIPE_REJECT_REMOTE_CLIENTS: DWORD = 0x00000008;
 pub const PIPE_READMODE_BYTE: DWORD = 0x00000000;
 
+pub const FD_SETSIZE: usize = 64;
+
 #[repr(C)]
 #[cfg(target_arch = "x86")]
 pub struct WSADATA {
@@ -837,6 +839,26 @@ pub struct CONSOLE_READCONSOLE_CONTROL {
 }
 pub type PCONSOLE_READCONSOLE_CONTROL = *mut CONSOLE_READCONSOLE_CONTROL;
 
+#[repr(C)]
+#[derive(Copy)]
+pub struct fd_set {
+    pub fd_count: c_uint,
+    pub fd_array: [SOCKET; FD_SETSIZE],
+}
+
+impl Clone for fd_set {
+    fn clone(&self) -> fd_set {
+        *self
+    }
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct timeval {
+    pub tv_sec: c_long,
+    pub tv_usec: c_long,
+}
+
 extern "system" {
     pub fn WSAStartup(wVersionRequested: WORD,
                       lpWSAData: LPWSADATA) -> c_int;
@@ -1125,6 +1147,11 @@ pub fn GetOverlappedResult(hFile: HANDLE,
                                lpOverlapped: LPOVERLAPPED,
                                lpNumberOfBytesTransferred: LPDWORD,
                                bWait: BOOL) -> BOOL;
+    pub fn select(nfds: c_int,
+                  readfds: *mut fd_set,
+                  writefds: *mut fd_set,
+                  exceptfds: *mut fd_set,
+                  timeout: *const timeval) -> c_int;
 }
 
 // Functions that aren't available on Windows XP, but we still use them and just
index f2a2793425d30053ef6c1af3aa2182c4f41e7351..cd8acff6b0cb8eac7f027719b39af2678be725e8 100644 (file)
@@ -12,7 +12,7 @@
 
 use cmp;
 use io::{self, Read};
-use libc::{c_int, c_void, c_ulong};
+use libc::{c_int, c_void, c_ulong, c_long};
 use mem;
 use net::{SocketAddr, Shutdown};
 use ptr;
@@ -115,6 +115,60 @@ pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> {
         Ok(socket)
     }
 
+    pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> {
+        self.set_nonblocking(true)?;
+        let r = unsafe {
+            let (addrp, len) = addr.into_inner();
+            cvt(c::connect(self.0, addrp, len))
+        };
+        self.set_nonblocking(false)?;
+
+        match r {
+            Ok(_) => return Ok(()),
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {}
+            Err(e) => return Err(e),
+        }
+
+        if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 {
+            return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                      "cannot set a 0 duration timeout"));
+        }
+
+        let mut timeout = c::timeval {
+            tv_sec: timeout.as_secs() as c_long,
+            tv_usec: (timeout.subsec_nanos() / 1000) as c_long,
+        };
+        if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
+            timeout.tv_usec = 1;
+        }
+
+        let fds = unsafe {
+            let mut fds = mem::zeroed::<c::fd_set>();
+            fds.fd_count = 1;
+            fds.fd_array[0] = self.0;
+            fds
+        };
+
+        let mut writefds = fds;
+        let mut errorfds = fds;
+
+        let n = unsafe {
+            cvt(c::select(1, ptr::null_mut(), &mut writefds, &mut errorfds, &timeout))?
+        };
+
+        match n {
+            0 => Err(io::Error::new(io::ErrorKind::TimedOut, "connection timed out")),
+            _ => {
+                if writefds.fd_count != 1 {
+                    if let Some(e) = self.take_error()? {
+                        return Err(e);
+                    }
+                }
+                Ok(())
+            }
+        }
+    }
+
     pub fn accept(&self, storage: *mut c::SOCKADDR,
                   len: *mut c_int) -> io::Result<Socket> {
         let socket = unsafe {
index 809b728379d065afc8941e296624e4013442fed2..5775dd4f1fcd44b89e170e5ce6e11b55d61f7dc1 100644 (file)
@@ -215,6 +215,14 @@ pub fn connect(addr: &SocketAddr) -> io::Result<TcpStream> {
         Ok(TcpStream { inner: sock })
     }
 
+    pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
+        init();
+
+        let sock = Socket::new(addr, c::SOCK_STREAM)?;
+        sock.connect_timeout(addr, timeout)?;
+        Ok(TcpStream { inner: sock })
+    }
+
     pub fn socket(&self) -> &Socket { &self.inner }
 
     pub fn into_socket(self) -> Socket { self.inner }
index e60edafe4ee441aba879abdf67918881685e6c8b..909b0031d615031d3d1c5e485b1905800b04b431 100644 (file)
@@ -359,7 +359,7 @@ fn map_opt_string(s: Option<String>, je: &JsonEmitter) -> Option<DiagnosticCode>
 
 impl JsonEmitter {
     fn render(&self, suggestion: &CodeSuggestion) -> Vec<String> {
-        suggestion.splice_lines(&*self.cm)
+        suggestion.splice_lines(&*self.cm).iter().map(|line| line.0.to_owned()).collect()
     }
 }
 
index c248e20b608fc4ca322ae71e29bd2ded053e889c..23d8523236977227fd8b97abec2453590e20c7e6 100644 (file)
@@ -2920,10 +2920,6 @@ fn parse_assoc_op_as(&mut self, lhs: P<Expr>, lhs_span: Span) -> PResult<'a, P<E
                         err.cancel();
                         let codemap = self.sess.codemap();
                         let suggestion_span = lhs_span.to(self.prev_span);
-                        let suggestion = match codemap.span_to_snippet(suggestion_span) {
-                            Ok(lstring) => format!("({})", lstring),
-                            _ => format!("(<expression> as <type>)")
-                        };
                         let warn_message = match codemap.span_to_snippet(self.prev_span) {
                             Ok(lstring) => format!("`{}`", lstring),
                             _ => "a type".to_string(),
@@ -2934,6 +2930,10 @@ fn parse_assoc_op_as(&mut self, lhs: P<Expr>, lhs_span: Span) -> PResult<'a, P<E
                         let mut err = self.sess.span_diagnostic.struct_span_err(sp, &msg);
                         err.span_label(sp, "interpreted as generic argument");
                         err.span_label(self.span, "not interpreted as comparison");
+                        let suggestion = match codemap.span_to_snippet(suggestion_span) {
+                            Ok(lstring) => format!("({})", lstring),
+                            _ => format!("(<expression> as <type>)")
+                        };
                         err.span_suggestion(suggestion_span,
                                             "if you want to compare the casted value then write:",
                                             suggestion);
diff --git a/src/test/compile-fail/auxiliary/private-inferred-type.rs b/src/test/compile-fail/auxiliary/private-inferred-type.rs
new file mode 100644 (file)
index 0000000..7627f5d
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright 2017 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.
+
+#![feature(decl_macro)]
+
+fn priv_fn() {}
+enum PrivEnum { Variant }
+pub enum PubEnum { Variant }
+trait PrivTrait { fn method() {} }
+impl PrivTrait for u8 {}
+pub trait PubTrait { fn method() {} }
+impl PubTrait for u8 {}
+struct PrivTupleStruct(u8);
+pub struct PubTupleStruct(u8);
+impl PubTupleStruct { fn method() {} }
+
+struct Priv;
+pub type Alias = Priv;
+pub struct Pub<T = Alias>(pub T);
+
+impl Pub<Priv> {
+    pub fn static_method() {}
+}
+impl Pub<u8> {
+    fn priv_method(&self) {}
+}
+
+pub macro m() {
+    priv_fn;
+    PrivEnum::Variant;
+    PubEnum::Variant;
+    <u8 as PrivTrait>::method;
+    <u8 as PubTrait>::method;
+    PrivTupleStruct;
+    PubTupleStruct;
+    Pub(0u8).priv_method();
+}
diff --git a/src/test/compile-fail/hygiene/auxiliary/intercrate.rs b/src/test/compile-fail/hygiene/auxiliary/intercrate.rs
new file mode 100644 (file)
index 0000000..aa67e5c
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2017 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.
+
+#![feature(decl_macro)]
+
+pub mod foo {
+    pub use self::bar::m;
+    mod bar {
+        fn f() -> u32 { 1 }
+        pub macro m() {
+            f();
+        }
+    }
+}
diff --git a/src/test/compile-fail/hygiene/fields.rs b/src/test/compile-fail/hygiene/fields.rs
new file mode 100644 (file)
index 0000000..6421777
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2017 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.
+
+// ignore-pretty pretty-printing is unhygienic
+
+#![feature(decl_macro)]
+
+mod foo {
+    struct S { x: u32 }
+    struct T(u32);
+
+    pub macro m($S:ident, $x:ident) {{
+        struct $S {
+            $x: u32,
+            x: i32,
+        }
+
+        let s = S { x: 0 }; //~ ERROR type `foo::S` is private
+        let _ = s.x; //~ ERROR type `foo::S` is private
+
+        let t = T(0); //~ ERROR type `foo::T` is private
+        let _ = t.0; //~ ERROR type `foo::T` is private
+
+        let s = $S { $x: 0, x: 1 };
+        assert_eq!((s.$x, s.x), (0, 1));
+        s
+    }}
+}
+
+fn main() {
+    let s = foo::m!(S, x);
+    assert_eq!(s.x, 0);
+}
diff --git a/src/test/compile-fail/hygiene/impl_items.rs b/src/test/compile-fail/hygiene/impl_items.rs
new file mode 100644 (file)
index 0000000..445aa62
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright 2017 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.
+
+// ignore-pretty pretty-printing is unhygienic
+
+#![feature(decl_macro)]
+
+mod foo {
+    struct S;
+    impl S {
+        fn f(&self) {}
+    }
+
+    pub macro m() {
+        let _: () = S.f(); //~ ERROR type `fn(&foo::S) {foo::S::f}` is private
+    }
+}
+
+struct S;
+
+macro m($f:ident) {
+    impl S {
+        fn f(&self) -> u32 { 0 }
+        fn $f(&self) -> i32 { 0 }
+    }
+    fn f() {
+        let _: u32 = S.f();
+        let _: i32 = S.$f();
+    }
+}
+
+m!(f);
+
+fn main() {
+    let _: i32 = S.f();
+    foo::m!();
+}
diff --git a/src/test/compile-fail/hygiene/intercrate.rs b/src/test/compile-fail/hygiene/intercrate.rs
new file mode 100644 (file)
index 0000000..50fc985
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2017 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.
+
+// ignore-pretty pretty-printing is unhygienic
+
+// aux-build:intercrate.rs
+
+// error-pattern:type `fn() -> u32 {intercrate::foo::bar::f}` is private
+
+#![feature(decl_macro)]
+
+extern crate intercrate;
+
+fn main() {
+    assert_eq!(intercrate::foo::m!(), 1);
+}
diff --git a/src/test/compile-fail/private-inferred-type-1.rs b/src/test/compile-fail/private-inferred-type-1.rs
new file mode 100644 (file)
index 0000000..ba8b3d1
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2017 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.
+
+trait Arr0 {
+    fn arr0_secret(&self);
+}
+trait TyParam {
+    fn ty_param_secret(&self);
+}
+
+mod m {
+    struct Priv;
+
+    impl ::Arr0 for [Priv; 0] { fn arr0_secret(&self) {} }
+    impl ::TyParam for Option<Priv> { fn ty_param_secret(&self) {} }
+}
+
+fn main() {
+    [].arr0_secret(); //~ ERROR type `m::Priv` is private
+    None.ty_param_secret(); //~ ERROR type `m::Priv` is private
+}
diff --git a/src/test/compile-fail/private-inferred-type-2.rs b/src/test/compile-fail/private-inferred-type-2.rs
new file mode 100644 (file)
index 0000000..e981f12
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2017 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.
+
+// aux-build:private-inferred-type.rs
+
+extern crate private_inferred_type as ext;
+
+mod m {
+    struct Priv;
+    pub struct Pub<T>(pub T);
+
+    impl Pub<Priv> {
+        pub fn get_priv() -> Priv { Priv }
+        pub fn static_method() {}
+    }
+}
+
+fn main() {
+    m::Pub::get_priv; //~ ERROR type `m::Priv` is private
+    m::Pub::static_method; //~ ERROR type `m::Priv` is private
+    ext::Pub::static_method; //~ ERROR type `ext::Priv` is private
+}
diff --git a/src/test/compile-fail/private-inferred-type-3.rs b/src/test/compile-fail/private-inferred-type-3.rs
new file mode 100644 (file)
index 0000000..fdd9166
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2017 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.
+
+// aux-build:private-inferred-type.rs
+
+// error-pattern:type `fn() {ext::priv_fn}` is private
+// error-pattern:type `ext::PrivEnum` is private
+// error-pattern:type `fn() {<u8 as ext::PrivTrait>::method}` is private
+// error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct::{{constructor}}}` is pr
+// error-pattern:type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct::{{constructor}}}` is priv
+// error-pattern:type `fn(&ext::Pub<u8>) {<ext::Pub<u8>>::priv_method}` is private
+
+#![feature(decl_macro)]
+
+extern crate private_inferred_type as ext;
+
+fn main() {
+    ext::m!();
+}
diff --git a/src/test/compile-fail/private-inferred-type.rs b/src/test/compile-fail/private-inferred-type.rs
new file mode 100644 (file)
index 0000000..1408910
--- /dev/null
@@ -0,0 +1,139 @@
+// Copyright 2017 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.
+
+#![feature(associated_consts)]
+#![feature(conservative_impl_trait)]
+#![feature(decl_macro)]
+
+mod m {
+    fn priv_fn() {}
+    enum PrivEnum { Variant }
+    pub enum PubEnum { Variant }
+    trait PrivTrait { fn method() {} }
+    impl PrivTrait for u8 {}
+    pub trait PubTrait { fn method() {} }
+    impl PubTrait for u8 {}
+    struct PrivTupleStruct(u8);
+    pub struct PubTupleStruct(u8);
+    impl PubTupleStruct { fn method() {} }
+
+    struct Priv;
+    pub type Alias = Priv;
+    pub struct Pub<T = Alias>(pub T);
+
+    impl Pub<Priv> {
+        pub fn static_method() {}
+        pub const INHERENT_ASSOC_CONST: u8 = 0;
+    }
+    impl<T> Pub<T> {
+        pub fn static_method_generic_self() {}
+        pub const INHERENT_ASSOC_CONST_GENERIC_SELF: u8 = 0;
+    }
+    impl Pub<u8> {
+        fn priv_method(&self) {}
+        pub fn method_with_substs<T>(&self) {}
+        pub fn method_with_priv_params(&self, _: Priv) {}
+    }
+    impl TraitWithAssocConst for Priv {}
+    impl TraitWithAssocTy for Priv { type AssocTy = u8; }
+
+    pub macro m() {
+        priv_fn; //~ ERROR type `fn() {m::priv_fn}` is private
+        PrivEnum::Variant; //~ ERROR type `m::PrivEnum` is private
+        PubEnum::Variant; // OK
+        <u8 as PrivTrait>::method; //~ ERROR type `fn() {<u8 as m::PrivTrait>::method}` is private
+        <u8 as PubTrait>::method; // OK
+        PrivTupleStruct;
+        //~^ ERROR type `fn(u8) -> m::PrivTupleStruct {m::PrivTupleStruct::{{constructor}}}` is priv
+        PubTupleStruct;
+        //~^ ERROR type `fn(u8) -> m::PubTupleStruct {m::PubTupleStruct::{{constructor}}}` is privat
+        Pub(0u8).priv_method();
+        //~^ ERROR type `fn(&m::Pub<u8>) {<m::Pub<u8>>::priv_method}` is private
+    }
+
+    trait Trait {}
+    pub trait TraitWithTyParam<T> {}
+    pub trait TraitWithTyParam2<T> { fn pub_method() {} }
+    pub trait TraitWithAssocTy { type AssocTy; }
+    pub trait TraitWithAssocConst { const TRAIT_ASSOC_CONST: u8 = 0; }
+    impl Trait for u8 {}
+    impl<T> TraitWithTyParam<T> for u8 {}
+    impl TraitWithTyParam2<Priv> for u8 {}
+    impl TraitWithAssocTy for u8 { type AssocTy = Priv; }
+
+    pub fn leak_anon1() -> impl Trait + 'static { 0 }
+    pub fn leak_anon2() -> impl TraitWithTyParam<Alias> { 0 }
+    pub fn leak_anon3() -> impl TraitWithAssocTy<AssocTy = Alias> { 0 }
+
+    pub fn leak_dyn1() -> Box<Trait + 'static> { Box::new(0) }
+    pub fn leak_dyn2() -> Box<TraitWithTyParam<Alias>> { Box::new(0) }
+    pub fn leak_dyn3() -> Box<TraitWithAssocTy<AssocTy = Alias>> { Box::new(0) }
+}
+
+mod adjust {
+    // Construct a chain of derefs with a private type in the middle
+    use std::ops::Deref;
+
+    pub struct S1;
+    struct S2;
+    pub type S2Alias = S2;
+    pub struct S3;
+
+    impl Deref for S1 {
+        type Target = S2Alias;
+        fn deref(&self) -> &Self::Target { loop {} }
+    }
+    impl Deref for S2 {
+        type Target = S3;
+        fn deref(&self) -> &Self::Target { loop {} }
+    }
+
+    impl S3 {
+        pub fn method_s3(&self) {}
+    }
+}
+
+fn main() {
+    let _: m::Alias; //~ ERROR type `m::Priv` is private
+    let _: <m::Alias as m::TraitWithAssocTy>::AssocTy; // FIXME
+    m::Alias {}; //~ ERROR type `m::Priv` is private
+    m::Pub { 0: m::Alias {} }; //~ ERROR type `m::Priv` is private
+    m::Pub { 0: loop {} }; // FIXME
+    m::Pub::static_method; //~ ERROR type `m::Priv` is private
+    m::Pub::INHERENT_ASSOC_CONST; //~ ERROR type `m::Priv` is private
+    m::Pub(0u8).method_with_substs::<m::Alias>(); //~ ERROR type `m::Priv` is private
+    m::Pub(0u8).method_with_priv_params(loop{}); //~ ERROR type `m::Priv` is private
+    <m::Alias as m::TraitWithAssocConst>::TRAIT_ASSOC_CONST; //~ ERROR type `m::Priv` is private
+    <m::Pub<m::Alias>>::INHERENT_ASSOC_CONST; //~ ERROR type `m::Priv` is private
+    <m::Pub<m::Alias>>::INHERENT_ASSOC_CONST_GENERIC_SELF; //~ ERROR type `m::Priv` is private
+    <m::Pub<m::Alias>>::static_method_generic_self; //~ ERROR type `m::Priv` is private
+    use m::TraitWithTyParam2;
+    u8::pub_method; //~ ERROR type `m::Priv` is private
+
+    adjust::S1.method_s3(); //~ ERROR type `adjust::S2` is private
+
+    m::m!();
+
+    m::leak_anon1(); //~ ERROR trait `m::Trait` is private
+    m::leak_anon2(); //~ ERROR type `m::Priv` is private
+    m::leak_anon3(); //~ ERROR type `m::Priv` is private
+
+    m::leak_dyn1(); //~ ERROR type `m::Trait + 'static` is private
+    m::leak_dyn2(); //~ ERROR type `m::Priv` is private
+    m::leak_dyn3(); //~ ERROR type `m::Priv` is private
+
+    // Check that messages are not duplicated for various kinds of assignments
+    let a = m::Alias {}; //~ ERROR type `m::Priv` is private
+    let mut b = a; //~ ERROR type `m::Priv` is private
+    b = a; //~ ERROR type `m::Priv` is private
+    match a { //~ ERROR type `m::Priv` is private
+        _ => {}
+    }
+}
diff --git a/src/test/compile-fail/private-type-in-interface.rs b/src/test/compile-fail/private-type-in-interface.rs
new file mode 100644 (file)
index 0000000..925d692
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2017 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.
+
+// aux-build:private-inferred-type.rs
+
+#![feature(conservative_impl_trait)]
+
+extern crate private_inferred_type as ext;
+
+mod m {
+    struct Priv;
+    pub type Alias = Priv;
+
+    pub trait Trait { type X; }
+    impl Trait for Priv { type X = u8; }
+}
+
+fn f(_: m::Alias) {} //~ ERROR type `m::Priv` is private
+                     //~^ ERROR type `m::Priv` is private
+fn f_ext(_: ext::Alias) {} //~ ERROR type `ext::Priv` is private
+                           //~^ ERROR type `ext::Priv` is private
+
+trait Tr1 {}
+impl m::Alias {} //~ ERROR type `m::Priv` is private
+impl Tr1 for ext::Alias {} //~ ERROR type `ext::Priv` is private
+                           //~^ ERROR type `ext::Priv` is private
+type A = <m::Alias as m::Trait>::X; //~ ERROR type `m::Priv` is private
+
+trait Tr2<T> {}
+impl<T> Tr2<T> for u8 {}
+fn g() -> impl Tr2<m::Alias> { 0 } //~ ERROR type `m::Priv` is private
+fn g_ext() -> impl Tr2<ext::Alias> { 0 } //~ ERROR type `ext::Priv` is private
+
+fn main() {}
diff --git a/src/test/run-pass/hygiene/auxiliary/intercrate.rs b/src/test/run-pass/hygiene/auxiliary/intercrate.rs
deleted file mode 100644 (file)
index aa67e5c..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2017 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.
-
-#![feature(decl_macro)]
-
-pub mod foo {
-    pub use self::bar::m;
-    mod bar {
-        fn f() -> u32 { 1 }
-        pub macro m() {
-            f();
-        }
-    }
-}
diff --git a/src/test/run-pass/hygiene/fields.rs b/src/test/run-pass/hygiene/fields.rs
deleted file mode 100644 (file)
index d7f99ba..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2017 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.
-
-// ignore-pretty pretty-printing is unhygienic
-
-#![feature(decl_macro)]
-
-mod foo {
-    struct S { x: u32 }
-    struct T(u32);
-
-    pub macro m($S:ident, $x:ident) {{
-        struct $S {
-            $x: u32,
-            x: i32,
-        }
-
-        let s = S { x: 0 };
-        let _ = s.x;
-
-        let t = T(0);
-        let _ = t.0;
-
-        let s = $S { $x: 0, x: 1 };
-        assert_eq!((s.$x, s.x), (0, 1));
-        s
-    }}
-}
-
-fn main() {
-    let s = foo::m!(S, x);
-    assert_eq!(s.x, 0);
-}
diff --git a/src/test/run-pass/hygiene/impl_items.rs b/src/test/run-pass/hygiene/impl_items.rs
deleted file mode 100644 (file)
index a5780a5..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2017 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.
-
-// ignore-pretty pretty-printing is unhygienic
-
-#![feature(decl_macro)]
-
-mod foo {
-    struct S;
-    impl S {
-        fn f(&self) {}
-    }
-
-    pub macro m() {
-        let _: () = S.f();
-    }
-}
-
-struct S;
-
-macro m($f:ident) {
-    impl S {
-        fn f(&self) -> u32 { 0 }
-        fn $f(&self) -> i32 { 0 }
-    }
-    fn f() {
-        let _: u32 = S.f();
-        let _: i32 = S.$f();
-    }
-}
-
-m!(f);
-
-fn main() {
-    let _: i32 = S.f();
-    foo::m!();
-}
diff --git a/src/test/run-pass/hygiene/intercrate.rs b/src/test/run-pass/hygiene/intercrate.rs
deleted file mode 100644 (file)
index 3a75085..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2017 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.
-
-// ignore-pretty pretty-printing is unhygienic
-
-// aux-build:intercrate.rs
-
-#![feature(decl_macro)]
-
-extern crate intercrate;
-
-fn main() {
-    assert_eq!(intercrate::foo::m!(), 1);
-}
index 68afd2084f10568dbcf09cacddc4afb3c25b1c8b..c8743c72e3107d10e17a0238469b7f9b34478cc3 100644 (file)
@@ -7,9 +7,13 @@ error[E0308]: mismatched types
    = note: expected type `()`
               found type `usize`
 help: did you mean to add a semicolon here?
-   |     foo();
+   |
+19 |     foo();
+   |          ^
 help: possibly return type missing here?
-   | fn bar() -> usize {
+   |
+18 | fn bar() -> usize {
+   |          ^^^^^^^^
 
 error: aborting due to previous error
 
index 9269180396c5481ccaef648a9d640af194f5af37..e8a2db4048c4d73a5f18fd56e443dc6370f008e5 100644 (file)
@@ -14,5 +14,18 @@ fn main() {
 
     println!("{}", a as usize > b);
     println!("{}", a as usize < b);
-    println!("{}", a as usize < 4);
+    println!("{}", a
+                   as
+                   usize
+                   <
+                   4);
+    println!("{}", a
+
+
+                   as
+
+
+                   usize
+                   <
+                   5);
 }
index 22c16ada05de468757a87ec79f787039a724def9..af61571625b71d51d906248184c70d5187c442fa 100644 (file)
@@ -7,18 +7,42 @@ error: `<` is interpreted as a start of generic arguments for `usize`, not a com
    |                               not interpreted as comparison
    |
 help: if you want to compare the casted value then write:
-   |     println!("{}", (a as usize) < b);
+   |
+16 |     println!("{}", (a as usize) < b);
+   |                    ^^^^^^^^^^^^
 
 error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison
-  --> $DIR/issue-22644.rs:17:33
+  --> $DIR/issue-22644.rs:21:20
    |
-17 |     println!("{}", a as usize < 4);
-   |                               - ^ interpreted as generic argument
-   |                               |
-   |                               not interpreted as comparison
+20 |                    <
+   |                    - not interpreted as comparison
+21 |                    4);
+   |                    ^ interpreted as generic argument
+   |
+help: if you want to compare the casted value then write:
+   |
+17 |     println!("{}", (a
+18 |                    as
+19 |                    usize)
+   |
+
+error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison
+  --> $DIR/issue-22644.rs:30:20
+   |
+29 |                    <
+   |                    - not interpreted as comparison
+30 |                    5);
+   |                    ^ interpreted as generic argument
    |
 help: if you want to compare the casted value then write:
-   |     println!("{}", (a as usize) < 4);
+   |
+22 |     println!("{}", (a
+23 | 
+24 | 
+25 |                    as
+26 | 
+27 | 
+ ...
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
index 17c5d5d15d40479415e0c5503c248ace94e25045..4b32ecff2fbdf7afcd91422b4e6b651ea98c771b 100644 (file)
@@ -5,7 +5,9 @@ error[E0425]: cannot find value `A` in module `namespaced_enums`
    |                               ^ not found in `namespaced_enums`
    |
 help: possible candidate is found in another module, you can import it into scope
-   | use namespaced_enums::Foo::A;
+   |
+12 | use namespaced_enums::Foo::A;
+   |
 
 error[E0425]: cannot find function `B` in module `namespaced_enums`
   --> $DIR/enums-are-namespaced-xc.rs:18:31
@@ -14,7 +16,9 @@ error[E0425]: cannot find function `B` in module `namespaced_enums`
    |                               ^ not found in `namespaced_enums`
    |
 help: possible candidate is found in another module, you can import it into scope
-   | use namespaced_enums::Foo::B;
+   |
+12 | use namespaced_enums::Foo::B;
+   |
 
 error[E0422]: cannot find struct, variant or union type `C` in module `namespaced_enums`
   --> $DIR/enums-are-namespaced-xc.rs:21:31
@@ -23,7 +27,9 @@ error[E0422]: cannot find struct, variant or union type `C` in module `namespace
    |                               ^ not found in `namespaced_enums`
    |
 help: possible candidate is found in another module, you can import it into scope
-   | use namespaced_enums::Foo::C;
+   |
+12 | use namespaced_enums::Foo::C;
+   |
 
 error: aborting due to 3 previous errors
 
index 63d2ce109142c70116181304aad38511fcb51325..6d7406f891c50c98402feb914db854053278f4f9 100644 (file)
@@ -5,9 +5,13 @@ error[E0574]: expected struct, variant or union type, found enum `Result`
    |         ^^^^^^ not a struct, variant or union type
    |
 help: possible better candidates are found in other modules, you can import them into scope
-   | use std::fmt::Result;
-   | use std::io::Result;
-   | use std::thread::Result;
+   |
+12 | use std::fmt::Result;
+   |
+12 | use std::io::Result;
+   |
+12 | use std::thread::Result;
+   |
 
 error: aborting due to previous error
 
index c0438abfe43b45cd5458eb302868063ff96c15df..2f94dbdc2c596ec35db8f91dbf3f469d7f73e3a5 100644 (file)
@@ -5,7 +5,9 @@ error[E0422]: cannot find struct, variant or union type `E` in this scope
    |     ^ not found in this scope
    |
 help: possible candidate is found in another module, you can import it into scope
-   | use SomeEnum::E;
+   |
+11 | use SomeEnum::E;
+   |
 
 error: aborting due to previous error
 
index 7315d295f7b8427a9c84cafe3cfa3a37539d3d89..ddaee451e90e86626b67b457bacc532041df4290 100644 (file)
@@ -5,9 +5,13 @@ error[E0405]: cannot find trait `Mul` in this scope
    |      ^^^ not found in this scope
    |
 help: possible candidates are found in other modules, you can import them into scope
-   | use mul1::Mul;
-   | use mul2::Mul;
-   | use std::ops::Mul;
+   |
+11 | use mul1::Mul;
+   |
+11 | use mul2::Mul;
+   |
+11 | use std::ops::Mul;
+   |
 
 error[E0412]: cannot find type `Mul` in this scope
   --> $DIR/issue-21221-1.rs:72:16
@@ -16,10 +20,15 @@ error[E0412]: cannot find type `Mul` in this scope
    |                ^^^ not found in this scope
    |
 help: possible candidates are found in other modules, you can import them into scope
-   | use mul1::Mul;
-   | use mul2::Mul;
-   | use mul3::Mul;
-   | use mul4::Mul;
+   |
+11 | use mul1::Mul;
+   |
+11 | use mul2::Mul;
+   |
+11 | use mul3::Mul;
+   |
+11 | use mul4::Mul;
+   |
 and 2 other candidates
 
 error[E0405]: cannot find trait `ThisTraitReallyDoesntExistInAnyModuleReally` in this scope
@@ -35,7 +44,9 @@ error[E0405]: cannot find trait `Div` in this scope
    |      ^^^ not found in this scope
    |
 help: possible candidate is found in another module, you can import it into scope
-   | use std::ops::Div;
+   |
+11 | use std::ops::Div;
+   |
 
 error: cannot continue compilation due to previous error
 
index b35f1bd26706ccfc5bafcf5b03018d13ac9159a8..a759116c6acff9c80708b67f0f41c22a3533bcd0 100644 (file)
@@ -5,7 +5,9 @@ error[E0405]: cannot find trait `T` in this scope
    |      ^ not found in this scope
    |
 help: possible candidate is found in another module, you can import it into scope
-   | use foo::bar::T;
+   |
+11 | use foo::bar::T;
+   |
 
 error[E0601]: main function not found
 
index a4a2496b19ae4c0b85c070945fa4fff4d35e0f54..f4d183192b6cb583551d3e6e6c60cbf1a041f069 100644 (file)
@@ -5,7 +5,9 @@ error[E0405]: cannot find trait `OuterTrait` in this scope
    |      ^^^^^^^^^^ not found in this scope
    |
 help: possible candidate is found in another module, you can import it into scope
-   | use issue_21221_3::outer::OuterTrait;
+   |
+16 | use issue_21221_3::outer::OuterTrait;
+   |
 
 error: cannot continue compilation due to previous error
 
index dc2f22717313320616be267464421c8f15841708..eb71ee893ce710a3f9e33c252d4f455c9e6fe537 100644 (file)
@@ -5,7 +5,9 @@ error[E0405]: cannot find trait `T` in this scope
    |      ^ not found in this scope
    |
 help: possible candidate is found in another module, you can import it into scope
-   | use issue_21221_4::T;
+   |
+16 | use issue_21221_4::T;
+   |
 
 error: cannot continue compilation due to previous error
 
index 0bf39dc55cee76a5b30d073f3c532380d2b7c5af..70b4599dbf8cbbd84d619995bd4aca845c55596a 100644 (file)
@@ -5,7 +5,9 @@ error[E0404]: expected trait, found type alias `Foo`
    |      ^^^ type aliases cannot be used for traits
    |
 help: possible better candidate is found in another module, you can import it into scope
-   | use issue_3907::Foo;
+   |
+12 | use issue_3907::Foo;
+   |
 
 error: cannot continue compilation due to previous error
 
index 18efb17dd4657fa851f202e5acbfb26b58476127..57b143d34dbd20ef602f50944186aa9448a9dada 100644 (file)
@@ -9,7 +9,9 @@ error[E0423]: expected value, found struct `Z`
    |         constructor is not visible here due to private fields
    |
 help: possible better candidate is found in another module, you can import it into scope
-   | use m::n::Z;
+   |
+15 | use m::n::Z;
+   |
 
 error[E0423]: expected value, found struct `S`
   --> $DIR/privacy-struct-ctor.rs:36:5
@@ -21,7 +23,9 @@ error[E0423]: expected value, found struct `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
-   | use m::S;
+   |
+13 | use m::S;
+   |
 
 error[E0423]: expected value, found struct `xcrate::S`
   --> $DIR/privacy-struct-ctor.rs:42:5
@@ -33,7 +37,9 @@ error[E0423]: expected value, found struct `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
-   | use m::S;
+   |
+13 | use m::S;
+   |
 
 error[E0603]: tuple struct `Z` is private
   --> $DIR/privacy-struct-ctor.rs:25:9
index a2597aba0bd295af2c3efe6c5821cb24027572ba..0cd7e1046f6ccc3010f997457b33c52b220a1b25 100644 (file)
@@ -5,7 +5,9 @@ error[E0404]: expected trait, found type parameter `Add`
    |                     ^^^ not a trait
    |
 help: possible better candidate is found in another module, you can import it into scope
-   | use std::ops::Add;
+   |
+11 | use std::ops::Add;
+   |
 
 error[E0601]: main function not found
 
index cd3a41b037c7996e8fa529e8fc805b9bca3e4c61..a0445eaee9162dd519724f16bbc8a098ee465096 100644 (file)
@@ -5,7 +5,9 @@ error[E0369]: binary operation `+` cannot be applied to type `&'static str`
    |             ^^^^^^^^^^^^^^^^^^^ `+` can't be used to concatenate two `&str` strings
    |
 help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left.
-   |     let x = "Hello ".to_owned() + "World!";
+   |
+12 |     let x = "Hello ".to_owned() + "World!";
+   |             ^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: binary operation `+` cannot be applied to type `World`
   --> $DIR/issue-39018.rs:17:13