From cd94222da2cbc95b7577d77b536bd4d3acf90d1a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 10 Nov 2015 00:38:07 +0100 Subject: [PATCH 1/7] Add E0321 error explanation --- src/librustc_typeck/diagnostics.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 4f39ed43b44..2d7178bd55c 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -2677,6 +2677,28 @@ defined. For more information see the [opt-in builtin traits RFC](https://github .com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md). "##, +E0321: r##" +A cross-crate opt-out trait was implemented on something which wasn't a struct +or enum type. Erroneous code example: + +``` +#![feature(optin_builtin_traits)] + +struct Foo; + +impl !Sync for Foo {} + +unsafe impl Send for &'static Foo { +// error: cross-crate traits with a default impl, like `core::marker::Send`, +// can only be implemented for a struct/enum type, not +// `&'static Foo` +``` + +Only structs and enums are permitted to impl Send, Sync, and other opt-out +trait, and the struct or enum must be local to the current crate. So, for +example, `unsafe impl Send for Rc` is not allowed. +"##, + E0322: r##" The `Sized` trait is a special trait built-in to the compiler for types with a constant size known at compile-time. This trait is automatically implemented @@ -3463,7 +3485,6 @@ register_diagnostics! { // E0246, // invalid recursive type // E0319, // trait impls for defaulted traits allowed just for structs/enums E0320, // recursive overflow during dropck - E0321, // extended coherence rules for defaulted traits violated E0328, // cannot implement Unsize explicitly E0374, // the trait `CoerceUnsized` may only be implemented for a coercion // between structures with one field being coerced, none found From 44fd0b91fb86d28731b223b5d2c7d17d04531e52 Mon Sep 17 00:00:00 2001 From: Kohei Hasegawa Date: Thu, 12 Nov 2015 00:47:42 +0900 Subject: [PATCH 2/7] docs: Fix variable name --- src/libcore/macros.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 5b5f59d5ddb..579232e5a5d 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -308,27 +308,27 @@ macro_rules! unreachable { /// /// ``` /// # trait Foo { -/// # fn foo(&self); /// # fn bar(&self); +/// # fn baz(&self); /// # } /// struct MyStruct; /// /// impl Foo for MyStruct { -/// fn foo(&self) { +/// fn bar(&self) { /// // implementation goes here /// } /// -/// fn bar(&self) { -/// // let's not worry about implementing bar() for now +/// fn baz(&self) { +/// // let's not worry about implementing baz() for now /// unimplemented!(); /// } /// } /// /// fn main() { /// let s = MyStruct; -/// s.foo(); +/// s.bar(); /// -/// // we aren't even using bar() yet, so this is fine. +/// // we aren't even using baz() yet, so this is fine. /// } /// ``` #[macro_export] From fc60b2c73e8c8b00152a1305cd27239b50fdd267 Mon Sep 17 00:00:00 2001 From: arcnmx Date: Wed, 11 Nov 2015 12:02:55 -0500 Subject: [PATCH 3/7] Prefer raw::c_char or libc::c_char and fix arm --- src/libstd/ffi/c_str.rs | 67 ++++++++++++++++++----------------------- src/libstd/os/raw.rs | 8 +++-- 2 files changed, 36 insertions(+), 39 deletions(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 89427f7851b..2802ecfbb8d 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -21,6 +21,7 @@ use libc; use mem; use ops::Deref; use option::Option::{self, Some, None}; +use os::raw::c_char; use result::Result::{self, Ok, Err}; use slice; use str::{self, Utf8Error}; @@ -36,8 +37,8 @@ use vec::Vec; /// /// A `CString` is created from either a byte slice or a byte vector. After /// being created, a `CString` predominately inherits all of its methods from -/// the `Deref` implementation to `[libc::c_char]`. Note that the underlying -/// array is represented as an array of `libc::c_char` as opposed to `u8`. A +/// the `Deref` implementation to `[os::raw::c_char]`. Note that the underlying +/// array is represented as an array of `os::raw::c_char` as opposed to `u8`. A /// `u8` slice can be obtained with the `as_bytes` method. Slices produced from /// a `CString` do *not* contain the trailing nul terminator unless otherwise /// specified. @@ -45,14 +46,12 @@ use vec::Vec; /// # Examples /// /// ```no_run -/// # #![feature(libc)] -/// # extern crate libc; /// # fn main() { /// use std::ffi::CString; -/// use libc; +/// use std::os::raw::c_char; /// /// extern { -/// fn my_printer(s: *const libc::c_char); +/// fn my_printer(s: *const c_char); /// } /// /// let c_to_print = CString::new("Hello, world!").unwrap(); @@ -83,11 +82,10 @@ pub struct CString { /// Inspecting a foreign C string /// /// ```no_run -/// # #![feature(libc)] -/// extern crate libc; /// use std::ffi::CStr; +/// use std::os::raw::c_char; /// -/// extern { fn my_string() -> *const libc::c_char; } +/// extern { fn my_string() -> *const c_char; } /// /// fn main() { /// unsafe { @@ -100,12 +98,11 @@ pub struct CString { /// Passing a Rust-originating C string /// /// ```no_run -/// # #![feature(libc)] -/// extern crate libc; /// use std::ffi::{CString, CStr}; +/// use std::os::raw::c_char; /// /// fn work(data: &CStr) { -/// extern { fn work_with(data: *const libc::c_char); } +/// extern { fn work_with(data: *const c_char); } /// /// unsafe { work_with(data.as_ptr()) } /// } @@ -119,11 +116,10 @@ pub struct CString { /// Converting a foreign C string into a Rust `String` /// /// ```no_run -/// # #![feature(libc)] -/// extern crate libc; /// use std::ffi::CStr; +/// use std::os::raw::c_char; /// -/// extern { fn my_string() -> *const libc::c_char; } +/// extern { fn my_string() -> *const c_char; } /// /// fn my_string_safe() -> String { /// unsafe { @@ -139,10 +135,10 @@ pub struct CString { #[stable(feature = "rust1", since = "1.0.0")] pub struct CStr { // FIXME: this should not be represented with a DST slice but rather with - // just a raw `libc::c_char` along with some form of marker to make + // just a raw `c_char` along with some form of marker to make // this an unsized type. Essentially `sizeof(&CStr)` should be the // same as `sizeof(&c_char)` but `CStr` should be an unsized type. - inner: [libc::c_char] + inner: [c_char] } /// An error returned from `CString::new` to indicate that a nul byte was found @@ -169,11 +165,10 @@ impl CString { /// # Examples /// /// ```no_run - /// # #![feature(libc)] - /// extern crate libc; /// use std::ffi::CString; + /// use std::os::raw::c_char; /// - /// extern { fn puts(s: *const libc::c_char); } + /// extern { fn puts(s: *const c_char); } /// /// fn main() { /// let to_print = CString::new("Hello!").unwrap(); @@ -220,7 +215,7 @@ impl CString { #[unstable(feature = "cstr_memory2", reason = "recently added", issue = "27769")] #[deprecated(since = "1.4.0", reason = "renamed to from_raw")] - pub unsafe fn from_ptr(ptr: *const libc::c_char) -> CString { + pub unsafe fn from_ptr(ptr: *const c_char) -> CString { CString::from_raw(ptr as *mut _) } @@ -230,7 +225,7 @@ impl CString { /// `into_raw`. The length of the string will be recalculated /// using the pointer. #[stable(feature = "cstr_memory", since = "1.4.0")] - pub unsafe fn from_raw(ptr: *mut libc::c_char) -> CString { + pub unsafe fn from_raw(ptr: *mut c_char) -> CString { let len = libc::strlen(ptr) + 1; // Including the NUL byte let slice = slice::from_raw_parts(ptr, len as usize); CString { inner: mem::transmute(slice) } @@ -247,7 +242,7 @@ impl CString { #[unstable(feature = "cstr_memory2", reason = "recently added", issue = "27769")] #[deprecated(since = "1.4.0", reason = "renamed to into_raw")] - pub fn into_ptr(self) -> *const libc::c_char { + pub fn into_ptr(self) -> *const c_char { self.into_raw() as *const _ } @@ -260,8 +255,8 @@ impl CString { /// /// Failure to call `from_raw` will lead to a memory leak. #[stable(feature = "cstr_memory", since = "1.4.0")] - pub fn into_raw(self) -> *mut libc::c_char { - Box::into_raw(self.inner) as *mut libc::c_char + pub fn into_raw(self) -> *mut c_char { + Box::into_raw(self.inner) as *mut c_char } /// Converts the `CString` into a `String` if it contains valid Unicode data. @@ -426,15 +421,13 @@ impl CStr { /// # Examples /// /// ```no_run - /// # #![feature(libc)] - /// # extern crate libc; /// # fn main() { /// use std::ffi::CStr; + /// use std::os::raw::c_char; /// use std::str; - /// use libc; /// /// extern { - /// fn my_string() -> *const libc::c_char; + /// fn my_string() -> *const c_char; /// } /// /// unsafe { @@ -445,7 +438,7 @@ impl CStr { /// # } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn from_ptr<'a>(ptr: *const libc::c_char) -> &'a CStr { + pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr { let len = libc::strlen(ptr); mem::transmute(slice::from_raw_parts(ptr, len as usize + 1)) } @@ -456,7 +449,7 @@ impl CStr { /// to a contiguous region of memory terminated with a 0 byte to represent /// the end of the string. #[stable(feature = "rust1", since = "1.0.0")] - pub fn as_ptr(&self) -> *const libc::c_char { + pub fn as_ptr(&self) -> *const c_char { self.inner.as_ptr() } @@ -560,14 +553,14 @@ impl ToOwned for CStr { mod tests { use prelude::v1::*; use super::*; - use libc; + use os::raw::c_char; use borrow::Cow::{Borrowed, Owned}; use hash::{SipHasher, Hash, Hasher}; #[test] fn c_to_rust() { let data = b"123\0"; - let ptr = data.as_ptr() as *const libc::c_char; + let ptr = data.as_ptr() as *const c_char; unsafe { assert_eq!(CStr::from_ptr(ptr).to_bytes(), b"123"); assert_eq!(CStr::from_ptr(ptr).to_bytes_with_nul(), b"123\0"); @@ -616,13 +609,13 @@ mod tests { #[test] fn to_str() { let data = b"123\xE2\x80\xA6\0"; - let ptr = data.as_ptr() as *const libc::c_char; + let ptr = data.as_ptr() as *const c_char; unsafe { assert_eq!(CStr::from_ptr(ptr).to_str(), Ok("123…")); assert_eq!(CStr::from_ptr(ptr).to_string_lossy(), Borrowed("123…")); } let data = b"123\xE2\0"; - let ptr = data.as_ptr() as *const libc::c_char; + let ptr = data.as_ptr() as *const c_char; unsafe { assert!(CStr::from_ptr(ptr).to_str().is_err()); assert_eq!(CStr::from_ptr(ptr).to_string_lossy(), Owned::(format!("123\u{FFFD}"))); @@ -632,7 +625,7 @@ mod tests { #[test] fn to_owned() { let data = b"123\0"; - let ptr = data.as_ptr() as *const libc::c_char; + let ptr = data.as_ptr() as *const c_char; let owned = unsafe { CStr::from_ptr(ptr).to_owned() }; assert_eq!(owned.as_bytes_with_nul(), data); @@ -641,7 +634,7 @@ mod tests { #[test] fn equal_hash() { let data = b"123\xE2\xFA\xA6\0"; - let ptr = data.as_ptr() as *const libc::c_char; + let ptr = data.as_ptr() as *const c_char; let cstr: &'static CStr = unsafe { CStr::from_ptr(ptr) }; let mut s = SipHasher::new_with_keys(0, 0); diff --git a/src/libstd/os/raw.rs b/src/libstd/os/raw.rs index 60069cf7bc3..f5d23442562 100644 --- a/src/libstd/os/raw.rs +++ b/src/libstd/os/raw.rs @@ -12,9 +12,13 @@ #![stable(feature = "raw_os", since = "1.1.0")] -#[cfg(any(target_arch = "aarch64", target_os = "android"))] +#[cfg(all(not(target_os = "ios"), not(target_os = "macos"), + any(target_arch = "aarch64", target_arch = "arm", + target_os = "android")))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8; -#[cfg(not(any(target_arch = "aarch64", target_os = "android")))] +#[cfg(any(target_os = "ios", target_os = "macos", + not(any(target_arch = "aarch64", target_arch = "arm", + target_os = "android"))))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8; #[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8; #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8; From d8062a9317a3113a9d0447895a2d12899072a6c8 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 12 Nov 2015 00:46:57 +0530 Subject: [PATCH 4/7] Add more comprehensive diagnostics for irrefutable pattern error with constants Fixes #7526 --- src/librustc_resolve/lib.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e9a0efe76cb..aa5824b96a1 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -153,7 +153,7 @@ pub enum ResolutionError<'a> { /// error E0413: declaration shadows an enum variant or unit-like struct in scope DeclarationShadowsEnumVariantOrUnitLikeStruct(Name), /// error E0414: only irrefutable patterns allowed here - OnlyIrrefutablePatternsAllowedHere, + OnlyIrrefutablePatternsAllowedHere(DefId, Name), /// error E0415: identifier is bound more than once in this parameter list IdentifierBoundMoreThanOnceInParameterList(&'a str), /// error E0416: identifier is bound more than once in the same pattern @@ -283,8 +283,16 @@ fn resolve_error<'b, 'a:'b, 'tcx:'a>(resolver: &'b Resolver<'a, 'tcx>, span: syn scope", name); }, - ResolutionError::OnlyIrrefutablePatternsAllowedHere => { + ResolutionError::OnlyIrrefutablePatternsAllowedHere(did, name) => { span_err!(resolver.session, span, E0414, "only irrefutable patterns allowed here"); + resolver.session.span_note(span, "there already is a constant in scope sharing the same name as this pattern"); + if let Some(sp) = resolver.ast_map.span_if_local(did) { + resolver.session.span_note(sp, "constant defined here"); + } + if let Some(directive) = resolver.current_module.import_resolutions.borrow().get(&name) { + let item = resolver.ast_map.expect_item(directive.value_id); + resolver.session.span_note(item.span, "constant imported here"); + } }, ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => { span_err!(resolver.session, span, E0415, @@ -632,7 +640,7 @@ enum NameSearchType { #[derive(Copy, Clone)] enum BareIdentifierPatternResolution { FoundStructOrEnumVariant(Def, LastPrivate), - FoundConst(Def, LastPrivate), + FoundConst(Def, LastPrivate, Name), BareIdentifierPatternUnresolved } @@ -2685,7 +2693,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { renamed) ); } - FoundConst(def, lp) if const_ok => { + FoundConst(def, lp, _) if const_ok => { debug!("(resolving pattern) resolving `{}` to \ constant", renamed); @@ -2700,11 +2708,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { depth: 0 }); } - FoundConst(..) => { + FoundConst(def, _, name) => { resolve_error( self, pattern.span, - ResolutionError::OnlyIrrefutablePatternsAllowedHere + ResolutionError::OnlyIrrefutablePatternsAllowedHere(def.def_id(), name) ); } BareIdentifierPatternUnresolved => { @@ -2929,7 +2937,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return FoundStructOrEnumVariant(def, LastMod(AllPublic)); } def @ DefConst(..) | def @ DefAssociatedConst(..) => { - return FoundConst(def, LastMod(AllPublic)); + return FoundConst(def, LastMod(AllPublic), name); } DefStatic(..) => { resolve_error(self, From 9be0ba5cc0e27e32e4d55332118f9891e97e5423 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 12 Nov 2015 00:48:02 +0530 Subject: [PATCH 5/7] Add test for constant pattern diagnostics --- .../compile-fail/const-pattern-irrefutable.rs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/test/compile-fail/const-pattern-irrefutable.rs diff --git a/src/test/compile-fail/const-pattern-irrefutable.rs b/src/test/compile-fail/const-pattern-irrefutable.rs new file mode 100644 index 00000000000..2d345d9142b --- /dev/null +++ b/src/test/compile-fail/const-pattern-irrefutable.rs @@ -0,0 +1,28 @@ +// Copyright 2015 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. + +mod foo { + const b: u8 = 2; //~ NOTE constant defined here + const d: u8 = 2; //~ NOTE constant defined here +} + +use foo::b as c; //~ NOTE constant imported here +use foo::d; //~ NOTE constant imported here + +const a: u8 = 2; //~ NOTE constant defined here + +fn main() { + let a = 4; //~ ERROR only irrefutable + //~^ NOTE there already is a constant in scope + let c = 4; //~ ERROR only irrefutable + //~^ NOTE there already is a constant in scope + let d = 4; //~ ERROR only irrefutable + //~^ NOTE there already is a constant in scope +} From f9f734748cf3ac6bc5155afe288c0689cb57b918 Mon Sep 17 00:00:00 2001 From: arcnmx Date: Wed, 11 Nov 2015 14:25:18 -0500 Subject: [PATCH 6/7] Cleaner c_char cfg logic --- src/libstd/ffi/c_str.rs | 9 ++++----- src/libstd/os/raw.rs | 12 ++++++------ 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 2802ecfbb8d..42fd2321f01 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -37,11 +37,10 @@ use vec::Vec; /// /// A `CString` is created from either a byte slice or a byte vector. After /// being created, a `CString` predominately inherits all of its methods from -/// the `Deref` implementation to `[os::raw::c_char]`. Note that the underlying -/// array is represented as an array of `os::raw::c_char` as opposed to `u8`. A -/// `u8` slice can be obtained with the `as_bytes` method. Slices produced from -/// a `CString` do *not* contain the trailing nul terminator unless otherwise -/// specified. +/// the `Deref` implementation to `[c_char]`. Note that the underlying array +/// is represented as an array of `c_char` as opposed to `u8`. A `u8` slice +/// can be obtained with the `as_bytes` method. Slices produced from a `CString` +/// do *not* contain the trailing nul terminator unless otherwise specified. /// /// # Examples /// diff --git a/src/libstd/os/raw.rs b/src/libstd/os/raw.rs index f5d23442562..17d6b2605c6 100644 --- a/src/libstd/os/raw.rs +++ b/src/libstd/os/raw.rs @@ -12,13 +12,13 @@ #![stable(feature = "raw_os", since = "1.1.0")] -#[cfg(all(not(target_os = "ios"), not(target_os = "macos"), - any(target_arch = "aarch64", target_arch = "arm", - target_os = "android")))] +#[cfg(any(target_os = "android", + all(target_os = "linux", any(target_arch = "aarch64", + target_arch = "arm"))))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8; -#[cfg(any(target_os = "ios", target_os = "macos", - not(any(target_arch = "aarch64", target_arch = "arm", - target_os = "android"))))] +#[cfg(not(any(target_os = "android", + all(target_os = "linux", any(target_arch = "aarch64", + target_arch = "arm")))))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8; #[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8; #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8; From 26705657e4c5e65af270352cc296290cd2108e3f Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 12 Nov 2015 02:08:37 +0530 Subject: [PATCH 7/7] Fixup tidy --- src/librustc_resolve/lib.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index aa5824b96a1..80062b371a3 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -285,11 +285,14 @@ fn resolve_error<'b, 'a:'b, 'tcx:'a>(resolver: &'b Resolver<'a, 'tcx>, span: syn }, ResolutionError::OnlyIrrefutablePatternsAllowedHere(did, name) => { span_err!(resolver.session, span, E0414, "only irrefutable patterns allowed here"); - resolver.session.span_note(span, "there already is a constant in scope sharing the same name as this pattern"); + resolver.session.span_note(span, "there already is a constant in scope \ + sharing the same name as this pattern"); if let Some(sp) = resolver.ast_map.span_if_local(did) { resolver.session.span_note(sp, "constant defined here"); } - if let Some(directive) = resolver.current_module.import_resolutions.borrow().get(&name) { + if let Some(directive) = resolver.current_module + .import_resolutions + .borrow().get(&name) { let item = resolver.ast_map.expect_item(directive.value_id); resolver.session.span_note(item.span, "constant imported here"); } @@ -2712,7 +2715,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error( self, pattern.span, - ResolutionError::OnlyIrrefutablePatternsAllowedHere(def.def_id(), name) + ResolutionError::OnlyIrrefutablePatternsAllowedHere(def.def_id(), + name) ); } BareIdentifierPatternUnresolved => {