From 5e9bfcd6d6342240200ec38f65ef75e96daa1b7a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 9 Sep 2015 11:02:52 +0200 Subject: [PATCH 1/8] Add new error code for trait privacy error --- src/librustc_privacy/diagnostics.rs | 38 +++++++++++++++++++++++++++++ src/librustc_privacy/lib.rs | 4 +-- 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 src/librustc_privacy/diagnostics.rs diff --git a/src/librustc_privacy/diagnostics.rs b/src/librustc_privacy/diagnostics.rs new file mode 100644 index 0000000000000..ff4163a53a1ab --- /dev/null +++ b/src/librustc_privacy/diagnostics.rs @@ -0,0 +1,38 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(non_snake_case)] + +register_long_diagnostics! { + +E0445: r##" +A private trait was used on a "public" type. Erroneous code example: + +``` +trait Foo { + fn dummy(&self) { } +} + +pub trait Bar : Foo {} // error: private trait in exported type parameter bound +``` + +To solve this error, please ensure the trait is accessible at the same level of +the type(s) on which it's implemented. Example: + +``` +pub trait Foo { // we set the Foo trait public + fn dummy(&self) { } +} + +pub trait Bar : Foo {} // ok! +``` +"##, + +} \ No newline at end of file diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 7f72ccb51e60d..9d0c1a560da4b 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1193,8 +1193,8 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> { if !self.tcx.sess.features.borrow().visible_private_types && self.path_is_private_type(trait_ref.trait_ref.ref_id) { let span = trait_ref.trait_ref.path.span; - self.tcx.sess.span_err(span, "private trait in exported type \ - parameter bound"); + span_err!(self.tcx.sess, span, E0445, + "private trait in exported type parameter bound"); } } } From c4a3936327f2f1082e3ac52e3dc7b250e3a04506 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 9 Sep 2015 11:08:35 +0200 Subject: [PATCH 2/8] Add error code for privacy error on exported signature --- src/librustc_privacy/diagnostics.rs | 27 +++++++++++++++++++++++++++ src/librustc_privacy/lib.rs | 3 ++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/librustc_privacy/diagnostics.rs b/src/librustc_privacy/diagnostics.rs index ff4163a53a1ab..cdd6af2d13d93 100644 --- a/src/librustc_privacy/diagnostics.rs +++ b/src/librustc_privacy/diagnostics.rs @@ -35,4 +35,31 @@ pub trait Bar : Foo {} // ok! ``` "##, +E0446: r##" +A private type was used in an exported type signature. Erroneous code example: + +``` +mod Foo { + struct Bar(u32); + + pub fn bar() -> Bar { // error: private type in exported type signature + Bar(0) + } +} +``` + +To solve this error, please ensure the type is accessible at the same level of +the exported type signature. Example: + +``` +mod Foo { + pub struct Bar(u32); // we set the Bar type public + + pub fn bar() -> Bar { // ok! + Bar(0) + } +} +``` +"##, + } \ No newline at end of file diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 9d0c1a560da4b..7b14ef134eb1c 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1435,7 +1435,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { if let hir::TyPath(_, ref p) = t.node { if !self.tcx.sess.features.borrow().visible_private_types && self.path_is_private_type(t.id) { - self.tcx.sess.span_err(p.span, "private type in exported type signature"); + span_err!(self.tcx.sess, p.span, E0446, + "private type in exported type signature"); } } visit::walk_ty(self, t) From 42e16223cfbe9fc1ee22cde8e698914eaf8dab55 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 9 Sep 2015 11:15:33 +0200 Subject: [PATCH 3/8] Add new error code for visibility inside a function --- src/librustc_privacy/diagnostics.rs | 26 +++++++++++++++++++++----- src/librustc_privacy/lib.rs | 3 ++- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/librustc_privacy/diagnostics.rs b/src/librustc_privacy/diagnostics.rs index cdd6af2d13d93..2c6931fafdeeb 100644 --- a/src/librustc_privacy/diagnostics.rs +++ b/src/librustc_privacy/diagnostics.rs @@ -13,7 +13,8 @@ register_long_diagnostics! { E0445: r##" -A private trait was used on a "public" type. Erroneous code example: +A private trait was used on a public type parameter bound. Erroneous code +examples: ``` trait Foo { @@ -23,8 +24,9 @@ trait Foo { pub trait Bar : Foo {} // error: private trait in exported type parameter bound ``` -To solve this error, please ensure the trait is accessible at the same level of -the type(s) on which it's implemented. Example: +To solve this error, please ensure that the trait is also public and accessible +at the same level of the public functions or types which are bound on it. +Example: ``` pub trait Foo { // we set the Foo trait public @@ -48,8 +50,8 @@ mod Foo { } ``` -To solve this error, please ensure the type is accessible at the same level of -the exported type signature. Example: +To solve this error, please ensure that the type is also public and accessible +at the same level of the public functions or types which use it. Example: ``` mod Foo { @@ -62,4 +64,18 @@ mod Foo { ``` "##, +E0447: r##" +The `pub` keyword was used inside a function. Erroneous code example: + +``` +fn foo() { + pub struct Bar; // error: visibility has no effect inside functions +} +``` + +Since we cannot access inside function's elements, the visibility of its +elements does not impact outer code. So using the `pub` keyword in this context +is invalid. +"##, + } \ No newline at end of file diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 7b14ef134eb1c..584fe21fae105 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1098,7 +1098,8 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { let tcx = self.tcx; fn check_inherited(tcx: &ty::ctxt, sp: Span, vis: hir::Visibility) { if vis != hir::Inherited { - tcx.sess.span_err(sp, "visibility has no effect inside functions"); + span_err!(tcx.sess, sp, E0447, + "visibility has no effect inside functions"); } } let check_struct = |def: &hir::StructDef| { From bda7ec0755e7eda62ff3e5d26365f6fd0cc7e4fb Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 9 Sep 2015 11:47:00 +0200 Subject: [PATCH 4/8] Add error code for enum item visibility error --- src/librustc_privacy/diagnostics.rs | 25 +++++++++++++++++++++++++ src/librustc_privacy/lib.rs | 6 ++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/librustc_privacy/diagnostics.rs b/src/librustc_privacy/diagnostics.rs index 2c6931fafdeeb..97933f1a8b0ea 100644 --- a/src/librustc_privacy/diagnostics.rs +++ b/src/librustc_privacy/diagnostics.rs @@ -78,4 +78,29 @@ elements does not impact outer code. So using the `pub` keyword in this context is invalid. "##, +E0448: r##" +The `pub` keyword was used inside a public enum. Erroneous code example: + +``` +pub enum Foo { + pub Bar, // error: unnecessary `pub` visibility +} +``` + +Since the enum is already public, adding `pub` on one its elements is +unnecessary. Example: + +``` +enum Foo { + pub Bar, // ok! +} + +// or: + +pub enum Foo { + Bar, // ok! +} +``` +"##, + } \ No newline at end of file diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 584fe21fae105..ab04f1201400d 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -50,6 +50,8 @@ use rustc::front::map as ast_map; use syntax::ast; use syntax::codemap::Span; +pub mod diagnostics; + type Context<'a, 'tcx> = (&'a ty::MethodMap<'tcx>, &'a def::ExportMap); /// Result of a checking operation - None => no errors were found. Some => an @@ -1076,8 +1078,8 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { match v.node.vis { hir::Public => { if item.vis == hir::Public { - tcx.sess.span_err(v.span, "unnecessary `pub` \ - visibility"); + span_err!(tcx.sess, v.span, E0448, + "unnecessary `pub` visibility"); } } hir::Inherited => {} From 6090cea18479f3a3bf12fe63034966cbe6eed2f7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 9 Sep 2015 11:58:27 +0200 Subject: [PATCH 5/8] Add error code for unnecessary visibility qualifier --- src/librustc_privacy/diagnostics.rs | 22 ++++++++++++++++++++++ src/librustc_privacy/lib.rs | 3 ++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/librustc_privacy/diagnostics.rs b/src/librustc_privacy/diagnostics.rs index 97933f1a8b0ea..78f5cc4bbf250 100644 --- a/src/librustc_privacy/diagnostics.rs +++ b/src/librustc_privacy/diagnostics.rs @@ -103,4 +103,26 @@ pub enum Foo { ``` "##, +E0449: r##" +A visibility qualifier was used when it was unnecessary. Erroneous code +examples: + +``` +struct Bar; + +trait Foo { + fn foo(); +} + +pub impl Bar {} // error: unnecessary visibility qualifier + +pub impl Foo for Bar { // error: unnecessary visibility qualifier + pub fn foo() {} // error: unnecessary visibility qualifier +} +``` + +To fix this error, please remove the visibility qualifier when it is not +required. +"##, + } \ No newline at end of file diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index ab04f1201400d..2dbab840ba26b 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1045,7 +1045,8 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { let tcx = self.tcx; let check_inherited = |sp: Span, vis: hir::Visibility, note: &str| { if vis != hir::Inherited { - tcx.sess.span_err(sp, "unnecessary visibility qualifier"); + span_err!(tcx.sess, sp, E0449, + "unnecessary visibility qualifier"); if !note.is_empty() { tcx.sess.span_note(sp, note); } From a056d5869e808b7f26cb536eca1aadda26a8188f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 9 Sep 2015 12:08:21 +0200 Subject: [PATCH 6/8] Add error code for tuple struct constructor error --- src/librustc_privacy/diagnostics.rs | 24 ++++++++++++++++++++++++ src/librustc_privacy/lib.rs | 6 +++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/librustc_privacy/diagnostics.rs b/src/librustc_privacy/diagnostics.rs index 78f5cc4bbf250..ac83ee2b02936 100644 --- a/src/librustc_privacy/diagnostics.rs +++ b/src/librustc_privacy/diagnostics.rs @@ -125,4 +125,28 @@ To fix this error, please remove the visibility qualifier when it is not required. "##, +E0450: r##" +A tuple constructor was invoked while some of its fields are private. Erroneous +code example: + +``` +mod Bar { + pub struct Foo(isize); +} + +let f = Bar::Foo(0); // error: cannot invoke tuple struct constructor with + // private fields +``` + +To solve this issue, please ensure that all tuple's fields are public. Example: + +``` +mod Bar { + pub struct Foo(pub isize); // we set its field to public +} + +let f = Bar::Foo(0); // ok! +``` +"##, + } \ No newline at end of file diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 2dbab840ba26b..9f5387dd9d6c6 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -931,9 +931,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { }); if any_priv { - self.tcx.sess.span_err(expr.span, - "cannot invoke tuple struct constructor \ - with private fields"); + span_err!(self.tcx.sess, expr.span, E0450, + "cannot invoke tuple struct constructor with private \ + fields"); } } } From dc6c11816c3188f952690a7b4a58dd253044ca43 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Thu, 10 Sep 2015 05:48:08 +0200 Subject: [PATCH 7/8] reference: using periods here is unusual --- src/doc/reference.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 900d1306e050c..ce5ed1b38206d 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2055,31 +2055,31 @@ arbitrarily complex configurations through nesting. The following configurations must be defined by the implementation: -* `debug_assertions`. Enabled by default when compiling without optimizations. +* `debug_assertions` - Enabled by default when compiling without optimizations. This can be used to enable extra debugging code in development but not in production. For example, it controls the behavior of the standard library's `debug_assert!` macro. -* `target_arch = "..."`. Target CPU architecture, such as `"x86"`, `"x86_64"` +* `target_arch = "..."` - Target CPU architecture, such as `"x86"`, `"x86_64"` `"mips"`, `"powerpc"`, `"arm"`, or `"aarch64"`. -* `target_endian = "..."`. Endianness of the target CPU, either `"little"` or +* `target_endian = "..."` - Endianness of the target CPU, either `"little"` or `"big"`. -* `target_env = ".."` - an option provided by the compiler by default +* `target_env = ".."` - An option provided by the compiler by default describing the runtime environment of the target platform. Some examples of this are `musl` for builds targeting the MUSL libc implementation, `msvc` for Windows builds targeting MSVC, and `gnu` frequently the rest of the time. This option may also be blank on some platforms. -* `target_family = "..."`. Operating system family of the target, e. g. +* `target_family = "..."` - Operating system family of the target, e. g. `"unix"` or `"windows"`. The value of this configuration option is defined as a configuration itself, like `unix` or `windows`. -* `target_os = "..."`. Operating system of the target, examples include +* `target_os = "..."` - Operating system of the target, examples include `"windows"`, `"macos"`, `"ios"`, `"linux"`, `"android"`, `"freebsd"`, `"dragonfly"`, `"bitrig"` , `"openbsd"` or `"netbsd"`. -* `target_pointer_width = "..."`. Target pointer width in bits. This is set +* `target_pointer_width = "..."` - Target pointer width in bits. This is set to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for 64-bit pointers. -* `test`. Enabled when compiling the test harness (using the `--test` flag). -* `unix`. See `target_family`. -* `windows`. See `target_family`. +* `test` - Enabled when compiling the test harness (using the `--test` flag). +* `unix` - See `target_family`. +* `windows` - See `target_family`. You can also set another attribute based on a `cfg` variable with `cfg_attr`: From 0477976867ddf3198ea62efdc2043e38b96eedd5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 9 Sep 2015 12:16:43 +0200 Subject: [PATCH 8/8] Add error code for private struct field issue --- src/librustc_privacy/diagnostics.rs | 93 +++++++++++++++++++++++++++-- src/librustc_privacy/lib.rs | 3 +- 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/src/librustc_privacy/diagnostics.rs b/src/librustc_privacy/diagnostics.rs index ac83ee2b02936..0f9f00e1b49a9 100644 --- a/src/librustc_privacy/diagnostics.rs +++ b/src/librustc_privacy/diagnostics.rs @@ -22,6 +22,8 @@ trait Foo { } pub trait Bar : Foo {} // error: private trait in exported type parameter bound +pub struct Bar(pub T); // same error +pub fn foo (t: T) {} // same error ``` To solve this error, please ensure that the trait is also public and accessible @@ -34,6 +36,8 @@ pub trait Foo { // we set the Foo trait public } pub trait Bar : Foo {} // ok! +pub struct Bar(pub T); // ok! +pub fn foo (t: T) {} // ok! ``` "##, @@ -73,8 +77,8 @@ fn foo() { } ``` -Since we cannot access inside function's elements, the visibility of its -elements does not impact outer code. So using the `pub` keyword in this context +Since we cannot access items defined inside a function, the visibility of its +items does not impact outer code. So using the `pub` keyword in this context is invalid. "##, @@ -122,7 +126,25 @@ pub impl Foo for Bar { // error: unnecessary visibility qualifier ``` To fix this error, please remove the visibility qualifier when it is not -required. +required. Example: + +``` +struct Bar; + +trait Foo { + fn foo(); +} + +// Directly implemented methods share the visibility of the type itself, +// so `pub` is unnecessary here +impl Bar {} + +// Trait methods share the visibility of the trait, so `pub` is +// unnecessary in either case +pub impl Foo for Bar { + pub fn foo() {} +} +``` "##, E0450: r##" @@ -138,7 +160,9 @@ let f = Bar::Foo(0); // error: cannot invoke tuple struct constructor with // private fields ``` -To solve this issue, please ensure that all tuple's fields are public. Example: +To solve this issue, please ensure that all of the fields of the tuple struct +are public. Alternatively, provide a new() method to the tuple struct to +construct it from a given inner value. Example: ``` mod Bar { @@ -146,7 +170,66 @@ mod Bar { } let f = Bar::Foo(0); // ok! + +// or: +mod bar { + pub struct Foo(isize); + + impl Foo { + pub fn new(x: isize) { + Foo(x) + } + } +} + +let f = bar::Foo::new(1); +``` +"##, + +E0451: r##" +A struct constructor with private fields was invoked. Erroneous code example: + +``` +mod Bar { + pub struct Foo { + pub a: isize, + b: isize, + } +} + +let f = Bar::Foo{ a: 0, b: 0 }; // error: field `b` of struct `Bar::Foo` + // is private +``` + +To fix this error, please ensure that all the fields of the struct, or +implement a function for easy instantiation. Examples: + +``` +mod Bar { + pub struct Foo { + pub a: isize, + pub b: isize, // we set `b` field public + } +} + +let f = Bar::Foo{ a: 0, b: 0 }; // ok! + +// or: +mod Bar { + pub struct Foo { + pub a: isize, + b: isize, // still private + } + + impl Foo { + pub fn new() -> Foo { // we create a method to instantiate `Foo` + Foo { a: 0, b: 0 } + } + } +} + +let f = Bar::Foo::new(); // ok! ``` "##, -} \ No newline at end of file +} diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 9f5387dd9d6c6..48efd34e21220 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -717,7 +717,8 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { UnnamedField(idx) => format!("field #{} of {} is private", idx + 1, struct_desc), }; - self.tcx.sess.span_err(span, &msg[..]); + span_err!(self.tcx.sess, span, E0451, + "{}", &msg[..]); } // Given the ID of a method, checks to ensure it's in scope.