diff --git a/.gitmodules b/.gitmodules index 1dcf9ed319f14..31db0772cfb6b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,13 +3,13 @@ url = https://github.com/rust-lang/rust-installer.git [submodule "src/doc/nomicon"] path = src/doc/nomicon - url = https://github.com/rust-lang-nursery/nomicon.git + url = https://github.com/rust-lang/nomicon.git [submodule "src/tools/cargo"] path = src/tools/cargo url = https://github.com/rust-lang/cargo.git [submodule "src/doc/reference"] path = src/doc/reference - url = https://github.com/rust-lang-nursery/reference.git + url = https://github.com/rust-lang/reference.git [submodule "src/doc/book"] path = src/doc/book url = https://github.com/rust-lang/book.git @@ -36,7 +36,7 @@ url = https://github.com/rust-lang/rustc-guide.git [submodule "src/doc/edition-guide"] path = src/doc/edition-guide - url = https://github.com/rust-lang-nursery/edition-guide.git + url = https://github.com/rust-lang/edition-guide.git [submodule "src/llvm-project"] path = src/llvm-project url = https://github.com/rust-lang/llvm-project.git diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index aba8e84d58be5..fac6ff0f06b6d 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -118,26 +118,16 @@ //! //! let mut counter = Counter::new(); //! -//! let x = counter.next().unwrap(); -//! println!("{}", x); -//! -//! let x = counter.next().unwrap(); -//! println!("{}", x); -//! -//! let x = counter.next().unwrap(); -//! println!("{}", x); -//! -//! let x = counter.next().unwrap(); -//! println!("{}", x); -//! -//! let x = counter.next().unwrap(); -//! println!("{}", x); +//! assert_eq!(counter.next(), Some(1)); +//! assert_eq!(counter.next(), Some(2)); +//! assert_eq!(counter.next(), Some(3)); +//! assert_eq!(counter.next(), Some(4)); +//! assert_eq!(counter.next(), Some(5)); +//! assert_eq!(counter.next(), None); //! ``` //! -//! This will print `1` through `5`, each on their own line. -//! -//! Calling `next()` this way gets repetitive. Rust has a construct which can -//! call `next()` on your iterator, until it reaches `None`. Let's go over that +//! Calling [`next`] this way gets repetitive. Rust has a construct which can +//! call [`next`] on your iterator, until it reaches `None`. Let's go over that //! next. //! //! Also note that `Iterator` provides a default implementation of methods such as `nth` and `fold` @@ -253,20 +243,23 @@ //! ``` //! //! The idiomatic way to write a [`map`] for its side effects is to use a -//! `for` loop instead: +//! `for` loop or call the [`for_each`] method: //! //! ``` //! let v = vec![1, 2, 3, 4, 5]; //! +//! v.iter().for_each(|x| println!("{}", x)); +//! // or //! for x in &v { //! println!("{}", x); //! } //! ``` //! //! [`map`]: trait.Iterator.html#method.map +//! [`for_each`]: trait.Iterator.html#method.for_each //! -//! The two most common ways to evaluate an iterator are to use a `for` loop -//! like this, or using the [`collect`] method to produce a new collection. +//! Another common way to evaluate an iterator is to use the [`collect`] +//! method to produce a new collection. //! //! [`collect`]: trait.Iterator.html#method.collect //! diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 22e7573eca65b..5730088c4d9a9 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -466,11 +466,10 @@ impl f32 { /// # Examples /// /// ``` - /// #![feature(float_to_from_bytes)] /// let bytes = 12.5f32.to_be_bytes(); /// assert_eq!(bytes, [0x41, 0x48, 0x00, 0x00]); /// ``` - #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[inline] pub fn to_be_bytes(self) -> [u8; 4] { self.to_bits().to_be_bytes() @@ -482,11 +481,10 @@ impl f32 { /// # Examples /// /// ``` - /// #![feature(float_to_from_bytes)] /// let bytes = 12.5f32.to_le_bytes(); /// assert_eq!(bytes, [0x00, 0x00, 0x48, 0x41]); /// ``` - #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[inline] pub fn to_le_bytes(self) -> [u8; 4] { self.to_bits().to_le_bytes() @@ -504,7 +502,6 @@ impl f32 { /// # Examples /// /// ``` - /// #![feature(float_to_from_bytes)] /// let bytes = 12.5f32.to_ne_bytes(); /// assert_eq!( /// bytes, @@ -515,7 +512,7 @@ impl f32 { /// } /// ); /// ``` - #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[inline] pub fn to_ne_bytes(self) -> [u8; 4] { self.to_bits().to_ne_bytes() @@ -526,11 +523,10 @@ impl f32 { /// # Examples /// /// ``` - /// #![feature(float_to_from_bytes)] /// let value = f32::from_be_bytes([0x41, 0x48, 0x00, 0x00]); /// assert_eq!(value, 12.5); /// ``` - #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[inline] pub fn from_be_bytes(bytes: [u8; 4]) -> Self { Self::from_bits(u32::from_be_bytes(bytes)) @@ -541,11 +537,10 @@ impl f32 { /// # Examples /// /// ``` - /// #![feature(float_to_from_bytes)] /// let value = f32::from_le_bytes([0x00, 0x00, 0x48, 0x41]); /// assert_eq!(value, 12.5); /// ``` - #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[inline] pub fn from_le_bytes(bytes: [u8; 4]) -> Self { Self::from_bits(u32::from_le_bytes(bytes)) @@ -563,7 +558,6 @@ impl f32 { /// # Examples /// /// ``` - /// #![feature(float_to_from_bytes)] /// let value = f32::from_ne_bytes(if cfg!(target_endian = "big") { /// [0x41, 0x48, 0x00, 0x00] /// } else { @@ -571,7 +565,7 @@ impl f32 { /// }); /// assert_eq!(value, 12.5); /// ``` - #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[inline] pub fn from_ne_bytes(bytes: [u8; 4]) -> Self { Self::from_bits(u32::from_ne_bytes(bytes)) diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index bbe1d04078060..2bdeda340dce0 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -479,11 +479,10 @@ impl f64 { /// # Examples /// /// ``` - /// #![feature(float_to_from_bytes)] /// let bytes = 12.5f64.to_be_bytes(); /// assert_eq!(bytes, [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); /// ``` - #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[inline] pub fn to_be_bytes(self) -> [u8; 8] { self.to_bits().to_be_bytes() @@ -495,11 +494,10 @@ impl f64 { /// # Examples /// /// ``` - /// #![feature(float_to_from_bytes)] /// let bytes = 12.5f64.to_le_bytes(); /// assert_eq!(bytes, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]); /// ``` - #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[inline] pub fn to_le_bytes(self) -> [u8; 8] { self.to_bits().to_le_bytes() @@ -517,7 +515,6 @@ impl f64 { /// # Examples /// /// ``` - /// #![feature(float_to_from_bytes)] /// let bytes = 12.5f64.to_ne_bytes(); /// assert_eq!( /// bytes, @@ -528,7 +525,7 @@ impl f64 { /// } /// ); /// ``` - #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[inline] pub fn to_ne_bytes(self) -> [u8; 8] { self.to_bits().to_ne_bytes() @@ -539,11 +536,10 @@ impl f64 { /// # Examples /// /// ``` - /// #![feature(float_to_from_bytes)] /// let value = f64::from_be_bytes([0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); /// assert_eq!(value, 12.5); /// ``` - #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[inline] pub fn from_be_bytes(bytes: [u8; 8]) -> Self { Self::from_bits(u64::from_be_bytes(bytes)) @@ -554,11 +550,10 @@ impl f64 { /// # Examples /// /// ``` - /// #![feature(float_to_from_bytes)] /// let value = f64::from_le_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]); /// assert_eq!(value, 12.5); /// ``` - #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[inline] pub fn from_le_bytes(bytes: [u8; 8]) -> Self { Self::from_bits(u64::from_le_bytes(bytes)) @@ -576,7 +571,6 @@ impl f64 { /// # Examples /// /// ``` - /// #![feature(float_to_from_bytes)] /// let value = f64::from_ne_bytes(if cfg!(target_endian = "big") { /// [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] /// } else { @@ -584,7 +578,7 @@ impl f64 { /// }); /// assert_eq!(value, 12.5); /// ``` - #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[inline] pub fn from_ne_bytes(bytes: [u8; 8]) -> Self { Self::from_bits(u64::from_ne_bytes(bytes)) diff --git a/src/libcore/ops/try.rs b/src/libcore/ops/try.rs index 76fec1020f1ef..e8f35f8cf2450 100644 --- a/src/libcore/ops/try.rs +++ b/src/libcore/ops/try.rs @@ -5,7 +5,7 @@ /// extracting those success or failure values from an existing instance and /// creating a new instance from a success or failure value. #[unstable(feature = "try_trait", issue = "42327")] -#[rustc_on_unimplemented( +#[cfg_attr(bootstrap, rustc_on_unimplemented( on(all( any(from_method="from_error", from_method="from_ok"), from_desugaring="QuestionMark"), @@ -17,7 +17,20 @@ message="the `?` operator can only be applied to values \ that implement `{Try}`", label="the `?` operator cannot be applied to type `{Self}`") -)] +))] +#[cfg_attr(not(bootstrap), rustc_on_unimplemented( +on(all( +any(from_method="from_error", from_method="from_ok"), +from_desugaring="QuestionMark"), +message="the `?` operator can only be used in {ItemContext} \ + that returns `Result` or `Option` \ + (or another type that implements `{Try}`)", +label="cannot use the `?` operator in {ItemContext} that returns `{Self}`"), +on(all(from_method="into_result", from_desugaring="QuestionMark"), +message="the `?` operator can only be applied to values \ + that implement `{Try}`", +label="the `?` operator cannot be applied to type `{Self}`") +))] #[doc(alias = "?")] pub trait Try { /// The type of this value when viewed as successful. diff --git a/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs b/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs index 9c362a5e20791..f4751e591bf3c 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -62,7 +62,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { &self, arg: &'tcx hir::Ty, br: &ty::BoundRegion, - ) -> Option<(&'tcx hir::Ty)> { + ) -> Option<&'tcx hir::Ty> { let mut nested_visitor = FindNestedTypeVisitor { tcx: self.tcx(), bound_region: *br, diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 8bf4765111d36..81f0853201c08 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -312,6 +312,9 @@ impl Session { pub fn has_errors(&self) -> bool { self.diagnostic().has_errors() } + pub fn has_errors_or_delayed_span_bugs(&self) -> bool { + self.diagnostic().has_errors_or_delayed_span_bugs() + } pub fn abort_if_errors(&self) { self.diagnostic().abort_if_errors(); } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index b55c0f29a70ec..1f7bce1c644c5 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -226,13 +226,26 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { 0, &mut obligations ); + + debug!("report_projection_error obligation.cause={:?} obligation.param_env={:?}", + obligation.cause, obligation.param_env); + + debug!("report_projection_error normalized_ty={:?} data.ty={:?}", + normalized_ty, data.ty); + + let is_normalized_ty_expected = match &obligation.cause.code { + ObligationCauseCode::ItemObligation(_) | + ObligationCauseCode::BindingObligation(_, _) | + ObligationCauseCode::ObjectCastObligation(_) => false, + _ => true, + }; + if let Err(error) = self.at(&obligation.cause, obligation.param_env) - .eq(normalized_ty, data.ty) + .eq_exp(is_normalized_ty_expected, normalized_ty, data.ty) { - values = Some(infer::ValuePairs::Types(ExpectedFound { - expected: normalized_ty, - found: data.ty, - })); + values = Some(infer::ValuePairs::Types( + ExpectedFound::new(is_normalized_ty_expected, normalized_ty, data.ty))); + err_buf = error; err = &err_buf; } @@ -353,6 +366,52 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } + fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> { + self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| { + match gen_kind { + hir::GeneratorKind::Gen => "a generator", + hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block", + hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function", + hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure", + } + }) + } + + /// Used to set on_unimplemented's `ItemContext` + /// to be the enclosing (async) block/function/closure + fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str> { + let hir = &self.tcx.hir(); + let node = hir.find(hir_id)?; + if let hir::Node::Item( + hir::Item{kind: hir::ItemKind::Fn(_ ,fn_header ,_ , body_id), .. }) = &node { + self.describe_generator(*body_id).or_else(|| + Some(if let hir::FnHeader{ asyncness: hir::IsAsync::Async, .. } = fn_header { + "an async function" + } else { + "a function" + }) + ) + } else if let hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Closure(_is_move, _, body_id, _, gen_movability), .. }) = &node { + self.describe_generator(*body_id).or_else(|| + Some(if gen_movability.is_some() { + "an async closure" + } else { + "a closure" + }) + ) + } else if let hir::Node::Expr(hir::Expr { .. }) = &node { + let parent_hid = hir.get_parent_node(hir_id); + if parent_hid != hir_id { + return self.describe_enclosure(parent_hid); + } else { + None + } + } else { + None + } + } + fn on_unimplemented_note( &self, trait_ref: ty::PolyTraitRef<'tcx>, @@ -363,6 +422,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let trait_ref = *trait_ref.skip_binder(); let mut flags = vec![]; + flags.push((sym::item_context, + self.describe_enclosure(obligation.cause.body_id).map(|s|s.to_owned()))); + match obligation.cause.code { ObligationCauseCode::BuiltinDerivedObligation(..) | ObligationCauseCode::ImplDerivedObligation(..) => {} diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index c1c814f9b0371..b39c00a56e349 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -248,6 +248,8 @@ impl<'tcx> OnUnimplementedFormatString { Position::ArgumentNamed(s) if s == sym::from_method => (), // `{from_desugaring}` is allowed Position::ArgumentNamed(s) if s == sym::from_desugaring => (), + // `{ItemContext}` is allowed + Position::ArgumentNamed(s) if s == sym::item_context => (), // So is `{A}` if A is a type parameter Position::ArgumentNamed(s) => match generics.params.iter().find(|param| { param.name == s @@ -296,6 +298,7 @@ impl<'tcx> OnUnimplementedFormatString { let s = self.0.as_str(); let parser = Parser::new(&s, None, vec![], false); + let item_context = (options.get(&sym::item_context)).unwrap_or(&empty_string); parser.map(|p| match p { Piece::String(s) => s, @@ -311,6 +314,8 @@ impl<'tcx> OnUnimplementedFormatString { } else if s == sym::from_desugaring || s == sym::from_method { // don't break messages using these two arguments incorrectly &empty_string + } else if s == sym::item_context { + &item_context } else { bug!("broken on_unimplemented {:?} for {:?}: \ no argument matching {:?}", diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 25e953ee257ec..3d28beefb3413 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1514,8 +1514,14 @@ impl<'tcx> TyCtxt<'tcx> { CrateType::Executable | CrateType::Staticlib | CrateType::ProcMacro | - CrateType::Dylib | CrateType::Cdylib => false, + + // FIXME rust-lang/rust#64319, rust-lang/rust#64872: + // We want to block export of generics from dylibs, + // but we must fix rust-lang/rust#65890 before we can + // do that robustly. + CrateType::Dylib => true, + CrateType::Rlib => true, } }) diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index ff87f0b1547ce..999cc40658503 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -14,7 +14,6 @@ use rustc::middle::dependency_format::Linkage; use rustc::session::Session; use rustc::session::config::{self, CrateType, OptLevel, DebugInfo, LinkerPluginLto, Lto}; -use rustc::middle::exported_symbols::ExportedSymbol; use rustc::ty::TyCtxt; use rustc_target::spec::{LinkerFlavor, LldFlavor}; use rustc_serialize::{json, Encoder}; @@ -1112,20 +1111,10 @@ fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec { continue; } - // Do not export generic symbols from upstream crates in linked - // artifact (notably the `dylib` crate type). The main reason - // for this is that `symbol_name` is actually wrong for generic - // symbols because it guesses the name we'd give them locally - // rather than the name it has upstream (depending on - // `share_generics` settings and such). - // - // To fix that issue we just say that linked artifacts, aka - // `dylib`s, never export generic symbols and they aren't - // available to downstream crates. (the not available part is - // handled elsewhere). - if let ExportedSymbol::Generic(..) = symbol { - continue; - } + // FIXME rust-lang/rust#64319, rust-lang/rust#64872: + // We want to block export of generics from dylibs, + // but we must fix rust-lang/rust#65890 before we can + // do that robustly. symbols.push(symbol.symbol_name(tcx).to_string()); } diff --git a/src/librustc_data_structures/owning_ref/mod.rs b/src/librustc_data_structures/owning_ref/mod.rs index b835b1706b85f..0213eb4f2a2a4 100644 --- a/src/librustc_data_structures/owning_ref/mod.rs +++ b/src/librustc_data_structures/owning_ref/mod.rs @@ -1046,14 +1046,14 @@ unsafe impl CloneStableAddress for OwningRef where O: CloneStableAddress {} unsafe impl Send for OwningRef - where O: Send, for<'a> (&'a T): Send {} + where O: Send, for<'a> &'a T: Send {} unsafe impl Sync for OwningRef - where O: Sync, for<'a> (&'a T): Sync {} + where O: Sync, for<'a> &'a T: Sync {} unsafe impl Send for OwningRefMut - where O: Send, for<'a> (&'a mut T): Send {} + where O: Send, for<'a> &'a mut T: Send {} unsafe impl Sync for OwningRefMut - where O: Sync, for<'a> (&'a mut T): Sync {} + where O: Sync, for<'a> &'a mut T: Sync {} impl Debug for dyn Erased { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index d111471f53d7d..6a19f52897e5d 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -492,10 +492,10 @@ impl Once { assert!(self.try_set(value).is_none()); } - /// Tries to initialize the inner value by calling the closure while ensuring that no-one else - /// can access the value in the mean time by holding a lock for the duration of the closure. - /// If the value was already initialized the closure is not called and `false` is returned, - /// otherwise if the value from the closure initializes the inner value, `true` is returned + /// Initializes the inner value if it wasn't already done by calling the provided closure. It + /// ensures that no-one else can access the value in the mean time by holding a lock for the + /// duration of the closure. + /// A reference to the inner value is returned. #[inline] pub fn init_locking T>(&self, f: F) -> &T { { diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 63df052a22504..9743cf0d805a3 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -704,6 +704,9 @@ impl Handler { pub fn has_errors(&self) -> bool { self.inner.borrow().has_errors() } + pub fn has_errors_or_delayed_span_bugs(&self) -> bool { + self.inner.borrow().has_errors_or_delayed_span_bugs() + } pub fn print_error_count(&self, registry: &Registry) { self.inner.borrow_mut().print_error_count(registry) @@ -862,6 +865,9 @@ impl HandlerInner { fn has_errors(&self) -> bool { self.err_count() > 0 } + fn has_errors_or_delayed_span_bugs(&self) -> bool { + self.has_errors() || !self.delayed_span_bugs.is_empty() + } fn abort_if_errors_and_should_abort(&mut self) { self.emit_stashed_diagnostics(); diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs index 511175de5d8d1..cbebdeb602cc0 100644 --- a/src/librustc_incremental/persist/fs.rs +++ b/src/librustc_incremental/persist/fs.rs @@ -307,7 +307,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) { let incr_comp_session_dir: PathBuf = sess.incr_comp_session_dir().clone(); - if sess.has_errors() { + if sess.has_errors_or_delayed_span_bugs() { // If there have been any errors during compilation, we don't want to // publish this session directory. Rather, we'll just delete it. diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index f5935c9969baa..ecc66e60175f0 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -22,6 +22,10 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) { if sess.opts.incremental.is_none() { return; } + // This is going to be deleted in finalize_session_directory, so let's not create it + if sess.has_errors_or_delayed_span_bugs() { + return; + } let query_cache_path = query_cache_path(sess); let dep_graph_path = dep_graph_path(sess); @@ -60,6 +64,10 @@ pub fn save_work_product_index(sess: &Session, if sess.opts.incremental.is_none() { return; } + // This is going to be deleted in finalize_session_directory, so let's not create it + if sess.has_errors_or_delayed_span_bugs() { + return; + } debug!("save_work_product_index()"); dep_graph.assert_ignored(); diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 7c19449f96b86..e3c3966c2f5e0 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1125,8 +1125,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds { .map(|pred| pred.span()).collect(); let mut err = cx.struct_span_lint(TYPE_ALIAS_BOUNDS, spans, "where clauses are not enforced in type aliases"); - err.help("the clause will not be checked when the type alias is used, \ - and should be removed"); + err.span_suggestion( + type_alias_generics.where_clause.span_for_predicates_or_empty_place(), + "the clause will not be checked when the type alias is used, and should be removed", + String::new(), + Applicability::MachineApplicable, + ); if !suggested_changing_assoc_types { TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err); suggested_changing_assoc_types = true; @@ -1136,14 +1140,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds { // The parameters must not have bounds for param in type_alias_generics.params.iter() { let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect(); + let suggestion = spans.iter().map(|sp| { + let start = param.span.between(*sp); // Include the `:` in `T: Bound`. + (start.to(*sp), String::new()) + }).collect(); if !spans.is_empty() { let mut err = cx.struct_span_lint( TYPE_ALIAS_BOUNDS, spans, "bounds on generic parameters are not enforced in type aliases", ); - err.help("the bound will not be checked when the type alias is used, \ - and should be removed"); + let msg = "the bound will not be checked when the type alias is used, \ + and should be removed"; + err.multipart_suggestion(&msg, suggestion, Applicability::MachineApplicable); if !suggested_changing_assoc_types { TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err); suggested_changing_assoc_types = true; diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 9a826de4b6eaf..af43030d0f2ae 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -598,6 +598,25 @@ impl EarlyLintPass for UnusedParens { fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) { self.check_unused_parens_pat(cx, &arm.pat, false, false); } + + fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) { + if let &ast::TyKind::Paren(ref r) = &ty.kind { + match &r.kind { + &ast::TyKind::TraitObject(..) => {} + &ast::TyKind::ImplTrait(_, ref bounds) if bounds.len() > 1 => {} + _ => { + let pattern_text = if let Ok(snippet) = cx.sess().source_map() + .span_to_snippet(ty.span) { + snippet + } else { + pprust::ty_to_string(ty) + }; + + Self::remove_outer_parens(cx, ty.span, &pattern_text, "type", (false, false)); + } + } + } + } } declare_lint! { diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 2e6ed1d187a68..de187a3f5e0dc 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -9,7 +9,6 @@ use rustc::ty::query::QueryConfig; use rustc::middle::cstore::{CrateSource, CrateStore, DepKind, EncodedMetadata, NativeLibraryKind}; use rustc::middle::exported_symbols::ExportedSymbol; use rustc::middle::stability::DeprecationEntry; -use rustc::middle::dependency_format::Linkage; use rustc::hir::def; use rustc::hir; use rustc::session::{CrateDisambiguator, Session}; @@ -235,26 +234,11 @@ provide! { <'tcx> tcx, def_id, other, cdata, used_crate_source => { Lrc::new(cdata.source.clone()) } exported_symbols => { - let mut syms = cdata.exported_symbols(tcx); - - // When linked into a dylib crates don't export their generic symbols, - // so if that's happening then we can't load upstream monomorphizations - // from this crate. - let formats = tcx.dependency_formats(LOCAL_CRATE); - let remove_generics = formats.iter().any(|(_ty, list)| { - match list.get(def_id.krate.as_usize() - 1) { - Some(Linkage::IncludedFromDylib) | Some(Linkage::Dynamic) => true, - _ => false, - } - }); - if remove_generics { - syms.retain(|(sym, _threshold)| { - match sym { - ExportedSymbol::Generic(..) => false, - _ => return true, - } - }); - } + let syms = cdata.exported_symbols(tcx); + + // FIXME rust-lang/rust#64319, rust-lang/rust#64872: We want + // to block export of generics from dylibs, but we must fix + // rust-lang/rust#65890 before we can do that robustly. Arc::new(syms) } diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index a46a1cc5647a9..1be1fcef61b6e 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -29,7 +29,7 @@ pub(super) struct Prefixes<'cx, 'tcx> { body: &'cx Body<'tcx>, tcx: TyCtxt<'tcx>, kind: PrefixSet, - next: Option<(PlaceRef<'cx, 'tcx>)>, + next: Option>, } #[derive(Copy, Clone, PartialEq, Eq, Debug)] diff --git a/src/librustc_mir/error_codes.rs b/src/librustc_mir/error_codes.rs index 419c905cb5127..c119ca536fb52 100644 --- a/src/librustc_mir/error_codes.rs +++ b/src/librustc_mir/error_codes.rs @@ -2545,7 +2545,7 @@ There are some known bugs that trigger this message. // E0471, // constant evaluation error (in pattern) // E0385, // {} in an aliasable location E0521, // borrowed data escapes outside of closure - E0526, // shuffle indices are not constant +// E0526, // shuffle indices are not constant E0594, // cannot assign to {} // E0598, // lifetime of {} is too short to guarantee its contents can be... E0625, // thread-local statics cannot be accessed at compile-time diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 8def717f1580a..83f3aafc55cb1 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -80,6 +80,17 @@ pub enum Candidate { Argument { bb: BasicBlock, index: usize }, } +impl Candidate { + /// Returns `true` if we should use the "explicit" rules for promotability for this `Candidate`. + fn forces_explicit_promotion(&self) -> bool { + match self { + Candidate::Ref(_) | + Candidate::Repeat(_) => false, + Candidate::Argument { .. } => true, + } + } +} + fn args_required_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { let attrs = tcx.get_attrs(def_id); let attr = attrs.iter().find(|a| a.check_name(sym::rustc_args_required_const))?; @@ -727,16 +738,22 @@ pub fn validate_candidates( }; candidates.iter().copied().filter(|&candidate| { - validator.explicit = match candidate { - Candidate::Ref(_) | - Candidate::Repeat(_) => false, - Candidate::Argument { .. } => true, - }; + validator.explicit = candidate.forces_explicit_promotion(); // FIXME(eddyb) also emit the errors for shuffle indices // and `#[rustc_args_required_const]` arguments here. - validator.validate_candidate(candidate).is_ok() + let is_promotable = validator.validate_candidate(candidate).is_ok(); + match candidate { + Candidate::Argument { bb, index } if !is_promotable => { + let span = body[bb].terminator().source_info.span; + let msg = format!("argument {} is required to be a constant", index + 1); + tcx.sess.span_err(span, &msg); + } + _ => () + } + + is_promotable }).collect() } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 3702dd9ad493f..f488b457334e5 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1606,20 +1606,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { // This is not a problem, because the argument explicitly // requests constness, in contrast to regular promotion // which happens even without the user requesting it. - // We can error out with a hard error if the argument is not - // constant here. + // + // `promote_consts` is responsible for emitting the error if + // the argument is not promotable. if !IsNotPromotable::in_operand(self, arg) { debug!("visit_terminator_kind: candidate={:?}", candidate); self.promotion_candidates.push(candidate); - } else { - if is_shuffle { - span_err!(self.tcx.sess, self.span, E0526, - "shuffle indices are not constant"); - } else { - self.tcx.sess.span_err(self.span, - &format!("argument {} is required to be a constant", - i + 1)); - } } } } diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index b14913cd4fdde..c59959ae4f4c5 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1850,6 +1850,34 @@ fn main() {} ``` "##, +E0578: r##" +A module cannot be found and therefore, the visibility cannot be determined. + +Erroneous code example: + +```compile_fail,E0578,edition2018 +foo!(); + +pub (in ::Sea) struct Shark; // error! + +fn main() {} +``` + +Because of the call to the `foo` macro, the compiler guesses that the missing +module could be inside it and fails because the macro definition cannot be +found. + +To fix this error, please be sure that the module is in scope: + +```edition2018 +pub mod Sea { + pub (in crate::Sea) struct Shark; +} + +fn main() {} +``` +"##, + E0603: r##" A private item was used outside its scope. @@ -2017,5 +2045,4 @@ fn main() {} // E0427, merged into 530 // E0467, removed // E0470, removed - E0578, } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index caa7f08f68cff..ab34f8daad719 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -322,9 +322,26 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { continue; } + // In order to correctly resolve intra-doc-links we need to + // pick a base AST node to work from. If the documentation for + // this module came from an inner comment (//!) then we anchor + // our name resolution *inside* the module. If, on the other + // hand it was an outer comment (///) then we anchor the name + // resolution in the parent module on the basis that the names + // used are more likely to be intended to be parent names. For + // this, we set base_node to None for inner comments since + // we've already pushed this node onto the resolution stack but + // for outer comments we explicitly try and resolve against the + // parent_node first. + let base_node = if item.is_mod() && item.attrs.inner_docs { + None + } else { + parent_node + }; + match kind { Some(ns @ ValueNS) => { - if let Ok(res) = self.resolve(path_str, ns, ¤t_item, parent_node) { + if let Ok(res) = self.resolve(path_str, ns, ¤t_item, base_node) { res } else { resolution_failure(cx, &item, path_str, &dox, link_range); @@ -335,7 +352,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } } Some(ns @ TypeNS) => { - if let Ok(res) = self.resolve(path_str, ns, ¤t_item, parent_node) { + if let Ok(res) = self.resolve(path_str, ns, ¤t_item, base_node) { res } else { resolution_failure(cx, &item, path_str, &dox, link_range); @@ -348,10 +365,10 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { let candidates = PerNS { macro_ns: macro_resolve(cx, path_str).map(|res| (res, None)), type_ns: self - .resolve(path_str, TypeNS, ¤t_item, parent_node) + .resolve(path_str, TypeNS, ¤t_item, base_node) .ok(), value_ns: self - .resolve(path_str, ValueNS, ¤t_item, parent_node) + .resolve(path_str, ValueNS, ¤t_item, base_node) .ok() .and_then(|(res, fragment)| { // Constructors are picked up in the type namespace. diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 6b0225a1b443a..de2f12c9f33ef 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1818,7 +1818,7 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> { type Item = &'a K; #[inline] - fn next(&mut self) -> Option<(&'a K)> { + fn next(&mut self) -> Option<&'a K> { self.inner.next().map(|(k, _)| k) } #[inline] @@ -1841,7 +1841,7 @@ impl<'a, K, V> Iterator for Values<'a, K, V> { type Item = &'a V; #[inline] - fn next(&mut self) -> Option<(&'a V)> { + fn next(&mut self) -> Option<&'a V> { self.inner.next().map(|(_, v)| v) } #[inline] @@ -1864,7 +1864,7 @@ impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { type Item = &'a mut V; #[inline] - fn next(&mut self) -> Option<(&'a mut V)> { + fn next(&mut self) -> Option<&'a mut V> { self.inner.next().map(|(_, v)| v) } #[inline] diff --git a/src/libstd/sys/vxworks/ext/io.rs b/src/libstd/sys/vxworks/ext/io.rs index 6bcc59495e363..df6255a3e9e03 100644 --- a/src/libstd/sys/vxworks/ext/io.rs +++ b/src/libstd/sys/vxworks/ext/io.rs @@ -6,7 +6,8 @@ use crate::fs; use crate::os::raw; use crate::sys; use crate::io; -use crate::sys_common::{AsInner, FromInner, IntoInner}; +use crate::sys_common::{self, AsInner, FromInner, IntoInner}; +use crate::net; /// Raw file descriptors. #[stable(feature = "rust1", since = "1.0.0")] @@ -110,3 +111,61 @@ impl<'a> AsRawFd for io::StdoutLock<'a> { impl<'a> AsRawFd for io::StderrLock<'a> { fn as_raw_fd(&self) -> RawFd { libc::STDERR_FILENO } } + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRawFd for net::TcpStream { + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRawFd for net::TcpListener { + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRawFd for net::UdpSocket { + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } +} + +#[stable(feature = "from_raw_os", since = "1.1.0")] +impl FromRawFd for net::TcpStream { + unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream { + let socket = sys::net::Socket::from_inner(fd); + net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(socket)) + } +} + +#[stable(feature = "from_raw_os", since = "1.1.0")] +impl FromRawFd for net::TcpListener { + unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener { + let socket = sys::net::Socket::from_inner(fd); + net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(socket)) + } +} + +#[stable(feature = "from_raw_os", since = "1.1.0")] +impl FromRawFd for net::UdpSocket { + unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket { + let socket = sys::net::Socket::from_inner(fd); + net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket)) + } +} + +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawFd for net::TcpStream { + fn into_raw_fd(self) -> RawFd { + self.into_inner().into_socket().into_inner() + } +} +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawFd for net::TcpListener { + fn into_raw_fd(self) -> RawFd { + self.into_inner().into_socket().into_inner() + } +} +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawFd for net::UdpSocket { + fn into_raw_fd(self) -> RawFd { + self.into_inner().into_socket().into_inner() + } +} diff --git a/src/libstd/sys/vxworks/ext/mod.rs b/src/libstd/sys/vxworks/ext/mod.rs index c2ebc38c30039..d0f467b303ff9 100644 --- a/src/libstd/sys/vxworks/ext/mod.rs +++ b/src/libstd/sys/vxworks/ext/mod.rs @@ -1,4 +1,3 @@ -// Uhhh #![stable(feature = "rust1", since = "1.0.0")] #![allow(missing_docs)] @@ -7,7 +6,6 @@ pub mod ffi; pub mod fs; pub mod raw; pub mod process; -pub mod net; #[stable(feature = "rust1", since = "1.0.0")] pub mod prelude { diff --git a/src/libstd/sys/vxworks/ext/net.rs b/src/libstd/sys/vxworks/ext/net.rs deleted file mode 100644 index 3f0a7e9e84319..0000000000000 --- a/src/libstd/sys/vxworks/ext/net.rs +++ /dev/null @@ -1,1825 +0,0 @@ -#![stable(feature = "unix_socket", since = "1.10.0")] - -//! Unix-specific networking functionality - -#[cfg(unix)] -use libc; - -use crate::ascii; -use crate::ffi::OsStr; -use crate::fmt; -use crate::io::{self, Initializer, IoSlice, IoSliceMut}; -use crate::mem; -use crate::net::{self, Shutdown}; -use crate::os::unix::ffi::OsStrExt; -use crate::os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd}; -use crate::path::Path; -use crate::time::Duration; -use crate::sys::{self, cvt}; -use crate::sys::net::Socket; -use crate::sys_common::{self, AsInner, FromInner, IntoInner}; - -const MSG_NOSIGNAL: libc::c_int = 0x0; - -fn sun_path_offset(addr: &libc::sockaddr_un) -> usize { - // Work with an actual instance of the type since using a null pointer is UB - let base = addr as *const _ as usize; - let path = &addr.sun_path as *const _ as usize; - path - base -} - -unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> { - let mut addr: libc::sockaddr_un = mem::zeroed(); - addr.sun_family = libc::AF_UNIX as libc::sa_family_t; - - let bytes = path.as_os_str().as_bytes(); - - if bytes.contains(&0) { - return Err(io::Error::new(io::ErrorKind::InvalidInput, - "paths may not contain interior null bytes")); - } - - if bytes.len() >= addr.sun_path.len() { - return Err(io::Error::new(io::ErrorKind::InvalidInput, - "path must be shorter than SUN_LEN")); - } - for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) { - *dst = *src as libc::c_char; - } - // null byte for pathname addresses is already there because we zeroed the - // struct - - let mut len = sun_path_offset(&addr) + bytes.len(); - match bytes.get(0) { - Some(&0) | None => {} - Some(_) => len += 1, - } - Ok((addr, len as libc::socklen_t)) -} - -enum AddressKind<'a> { - Unnamed, - Pathname(&'a Path), - Abstract(&'a [u8]), -} - -/// An address associated with a Unix socket. -/// -/// # Examples -/// -/// ``` -/// use std::os::unix::net::UnixListener; -/// -/// let socket = match UnixListener::bind("/tmp/sock") { -/// Ok(sock) => sock, -/// Err(e) => { -/// println!("Couldn't bind: {:?}", e); -/// return -/// } -/// }; -/// let addr = socket.local_addr().expect("Couldn't get local address"); -/// ``` -#[derive(Clone)] -#[stable(feature = "unix_socket", since = "1.10.0")] -pub struct SocketAddr { - addr: libc::sockaddr_un, - len: libc::socklen_t, -} - -impl SocketAddr { - fn new(f: F) -> io::Result - where F: FnOnce(*mut libc::sockaddr, *mut libc::socklen_t) -> libc::c_int - { - unsafe { - let mut addr: libc::sockaddr_un = mem::zeroed(); - let mut len = mem::size_of::() as libc::socklen_t; - cvt(f(&mut addr as *mut _ as *mut _, &mut len))?; - SocketAddr::from_parts(addr, len) - } - } - - fn from_parts(addr: libc::sockaddr_un, mut len: libc::socklen_t) -> io::Result { - if len == 0 { - // When there is a datagram from unnamed unix socket - // linux returns zero bytes of address - len = sun_path_offset(&addr) as libc::socklen_t; // i.e., zero-length address - } else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t { - return Err(io::Error::new(io::ErrorKind::InvalidInput, - "file descriptor did not correspond to a Unix socket")); - } - - Ok(SocketAddr { - addr, - len, - }) - } - - /// Returns `true` if the address is unnamed. - /// - /// # Examples - /// - /// A named address: - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let socket = UnixListener::bind("/tmp/sock").unwrap(); - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// assert_eq!(addr.is_unnamed(), false); - /// ``` - /// - /// An unnamed address: - /// - /// ``` - /// use std::os::unix::net::UnixDatagram; - /// - /// let socket = UnixDatagram::unbound().unwrap(); - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// assert_eq!(addr.is_unnamed(), true); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn is_unnamed(&self) -> bool { - if let AddressKind::Unnamed = self.address() { - true - } else { - false - } - } - - /// Returns the contents of this address if it is a `pathname` address. - /// - /// # Examples - /// - /// With a pathname: - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// use std::path::Path; - /// - /// let socket = UnixListener::bind("/tmp/sock").unwrap(); - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock"))); - /// ``` - /// - /// Without a pathname: - /// - /// ``` - /// use std::os::unix::net::UnixDatagram; - /// - /// let socket = UnixDatagram::unbound().unwrap(); - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// assert_eq!(addr.as_pathname(), None); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn as_pathname(&self) -> Option<&Path> { - if let AddressKind::Pathname(path) = self.address() { - Some(path) - } else { - None - } - } - - fn address<'a>(&'a self) -> AddressKind<'a> { - let len = self.len as usize - sun_path_offset(&self.addr); - let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) }; - - if self.addr.sun_path[0] == 0 { - AddressKind::Abstract(&path[1..len]) - } else { - AddressKind::Pathname(OsStr::from_bytes(&path[..len - 1]).as_ref()) - } - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl fmt::Debug for SocketAddr { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.address() { - AddressKind::Unnamed => write!(fmt, "(unnamed)"), - AddressKind::Abstract(name) => write!(fmt, "{} (abstract)", AsciiEscaped(name)), - AddressKind::Pathname(path) => write!(fmt, "{:?} (pathname)", path), - } - } -} - -struct AsciiEscaped<'a>(&'a [u8]); - -impl<'a> fmt::Display for AsciiEscaped<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(fmt, "\"")?; - for byte in self.0.iter().cloned().flat_map(ascii::escape_default) { - write!(fmt, "{}", byte as char)?; - } - write!(fmt, "\"") - } -} - -/// A Unix stream socket. -/// -/// # Examples -/// -/// ```no_run -/// use std::os::unix::net::UnixStream; -/// use std::io::prelude::*; -/// -/// let mut stream = UnixStream::connect("/path/to/my/socket").unwrap(); -/// stream.write_all(b"hello world").unwrap(); -/// let mut response = String::new(); -/// stream.read_to_string(&mut response).unwrap(); -/// println!("{}", response); -/// ``` -#[stable(feature = "unix_socket", since = "1.10.0")] -pub struct UnixStream(Socket); - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl fmt::Debug for UnixStream { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut builder = fmt.debug_struct("UnixStream"); - builder.field("fd", self.0.as_inner()); - if let Ok(addr) = self.local_addr() { - builder.field("local", &addr); - } - if let Ok(addr) = self.peer_addr() { - builder.field("peer", &addr); - } - builder.finish() - } -} - -impl UnixStream { - /// Connects to the socket named by `path`. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = match UnixStream::connect("/tmp/sock") { - /// Ok(sock) => sock, - /// Err(e) => { - /// println!("Couldn't connect: {:?}", e); - /// return - /// } - /// }; - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn connect>(path: P) -> io::Result { - fn inner(path: &Path) -> io::Result { - unsafe { - let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; - let (addr, len) = sockaddr_un(path)?; - - cvt(libc::connect(*inner.as_inner(), &addr as *const _ as *const _, len))?; - Ok(UnixStream(inner)) - } - } - inner(path.as_ref()) - } - - /// Creates an unnamed pair of connected sockets. - /// - /// Returns two `UnixStream`s which are connected to each other. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let (sock1, sock2) = match UnixStream::pair() { - /// Ok((sock1, sock2)) => (sock1, sock2), - /// Err(e) => { - /// println!("Couldn't create a pair of sockets: {:?}", e); - /// return - /// } - /// }; - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn pair() -> io::Result<(UnixStream, UnixStream)> { - let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_STREAM)?; - Ok((UnixStream(i1), UnixStream(i2))) - } - - /// Creates a new independently owned handle to the underlying socket. - /// - /// The returned `UnixStream` is a reference to the same stream that this - /// object references. Both handles will read and write the same stream of - /// data, and options set on one stream will be propagated to the other - /// stream. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// let sock_copy = socket.try_clone().expect("Couldn't clone socket"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn try_clone(&self) -> io::Result { - self.0.duplicate().map(UnixStream) - } - - /// Returns the socket address of the local half of this connection. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn local_addr(&self) -> io::Result { - SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) - } - - /// Returns the socket address of the remote half of this connection. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// let addr = socket.peer_addr().expect("Couldn't get peer address"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn peer_addr(&self) -> io::Result { - SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) }) - } - - /// Sets the read timeout for the socket. - /// - /// If the provided value is [`None`], then [`read`] calls will block - /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method. - /// - /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err - /// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read - /// [`Duration`]: ../../../../std/time/struct.Duration.html - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); - /// ``` - /// - /// An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method: - /// - /// ```no_run - /// use std::io; - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); - /// let err = result.unwrap_err(); - /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { - self.0.set_timeout(timeout, libc::SO_RCVTIMEO) - } - - /// Sets the write timeout for the socket. - /// - /// If the provided value is [`None`], then [`write`] calls will block - /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is - /// passed to this method. - /// - /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err - /// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write - /// [`Duration`]: ../../../../std/time/struct.Duration.html - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); - /// ``` - /// - /// An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method: - /// - /// ```no_run - /// use std::io; - /// use std::net::UdpSocket; - /// use std::time::Duration; - /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); - /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); - /// let err = result.unwrap_err(); - /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { - self.0.set_timeout(timeout, libc::SO_SNDTIMEO) - } - - /// Returns the read timeout of this socket. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); - /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0))); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn read_timeout(&self) -> io::Result> { - self.0.timeout(libc::SO_RCVTIMEO) - } - - /// Returns the write timeout of this socket. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); - /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0))); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn write_timeout(&self) -> io::Result> { - self.0.timeout(libc::SO_SNDTIMEO) - } - - /// Moves the socket into or out of nonblocking mode. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_nonblocking(true).expect("Couldn't set nonblocking"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - self.0.set_nonblocking(nonblocking) - } - - /// Returns the value of the `SO_ERROR` option. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// if let Ok(Some(err)) = socket.take_error() { - /// println!("Got error: {:?}", err); - /// } - /// ``` - /// - /// # Platform specific - /// On Redox this always returns `None`. - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn take_error(&self) -> io::Result> { - self.0.take_error() - } - - /// Shuts down the read, write, or both halves of this connection. - /// - /// This function will cause all pending and future I/O calls on the - /// specified portions to immediately return with an appropriate value - /// (see the documentation of [`Shutdown`]). - /// - /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::net::Shutdown; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { - self.0.shutdown(how) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl io::Read for UnixStream { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - io::Read::read(&mut &*self, buf) - } - - fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { - io::Read::read_vectored(&mut &*self, bufs) - } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl<'a> io::Read for &'a UnixStream { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) - } - - fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { - self.0.read_vectored(bufs) - } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl io::Write for UnixStream { - fn write(&mut self, buf: &[u8]) -> io::Result { - io::Write::write(&mut &*self, buf) - } - - fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { - io::Write::write_vectored(&mut &*self, bufs) - } - - fn flush(&mut self) -> io::Result<()> { - io::Write::flush(&mut &*self) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl<'a> io::Write for &'a UnixStream { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.0.write(buf) - } - - fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { - self.0.write_vectored(bufs) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl AsRawFd for UnixStream { - fn as_raw_fd(&self) -> RawFd { - *self.0.as_inner() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl FromRawFd for UnixStream { - unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { - UnixStream(Socket::from_inner(fd)) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl IntoRawFd for UnixStream { - fn into_raw_fd(self) -> RawFd { - self.0.into_inner() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl AsRawFd for net::TcpStream { - fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl AsRawFd for net::TcpListener { - fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl AsRawFd for net::UdpSocket { - fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } -} - -#[stable(feature = "from_raw_os", since = "1.1.0")] -impl FromRawFd for net::TcpStream { - unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream { - let socket = sys::net::Socket::from_inner(fd); - net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(socket)) - } -} - -#[stable(feature = "from_raw_os", since = "1.1.0")] -impl FromRawFd for net::TcpListener { - unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener { - let socket = sys::net::Socket::from_inner(fd); - net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(socket)) - } -} - -#[stable(feature = "from_raw_os", since = "1.1.0")] -impl FromRawFd for net::UdpSocket { - unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket { - let socket = sys::net::Socket::from_inner(fd); - net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket)) - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawFd for net::TcpStream { - fn into_raw_fd(self) -> RawFd { - self.into_inner().into_socket().into_inner() - } -} -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawFd for net::TcpListener { - fn into_raw_fd(self) -> RawFd { - self.into_inner().into_socket().into_inner() - } -} -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawFd for net::UdpSocket { - fn into_raw_fd(self) -> RawFd { - self.into_inner().into_socket().into_inner() - } -} - -/// A structure representing a Unix domain socket server. -/// -/// # Examples -/// -/// ```no_run -/// use std::thread; -/// use std::os::unix::net::{UnixStream, UnixListener}; -/// -/// fn handle_client(stream: UnixStream) { -/// // ... -/// } -/// -/// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); -/// -/// // accept connections and process them, spawning a new thread for each one -/// for stream in listener.incoming() { -/// match stream { -/// Ok(stream) => { -/// /* connection succeeded */ -/// thread::spawn(|| handle_client(stream)); -/// } -/// Err(err) => { -/// /* connection failed */ -/// break; -/// } -/// } -/// } -/// ``` -#[stable(feature = "unix_socket", since = "1.10.0")] -pub struct UnixListener(Socket); - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl fmt::Debug for UnixListener { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut builder = fmt.debug_struct("UnixListener"); - builder.field("fd", self.0.as_inner()); - if let Ok(addr) = self.local_addr() { - builder.field("local", &addr); - } - builder.finish() - } -} - -impl UnixListener { - /// Creates a new `UnixListener` bound to the specified socket. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = match UnixListener::bind("/path/to/the/socket") { - /// Ok(sock) => sock, - /// Err(e) => { - /// println!("Couldn't connect: {:?}", e); - /// return - /// } - /// }; - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn bind>(path: P) -> io::Result { - fn inner(path: &Path) -> io::Result { - unsafe { - let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; - let (addr, len) = sockaddr_un(path)?; - - cvt(libc::bind(*inner.as_inner(), &addr as *const _ as *const _, len as _))?; - cvt(libc::listen(*inner.as_inner(), 128))?; - - Ok(UnixListener(inner)) - } - } - inner(path.as_ref()) - } - - /// Accepts a new incoming connection to this listener. - /// - /// This function will block the calling thread until a new Unix connection - /// is established. When established, the corresponding [`UnixStream`] and - /// the remote peer's address will be returned. - /// - /// [`UnixStream`]: ../../../../std/os/unix/net/struct.UnixStream.html - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// match listener.accept() { - /// Ok((socket, addr)) => println!("Got a client: {:?}", addr), - /// Err(e) => println!("accept function failed: {:?}", e), - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { - let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() }; - let mut len = mem::size_of_val(&storage) as libc::socklen_t; - let sock = self.0.accept(&mut storage as *mut _ as *mut _, &mut len)?; - let addr = SocketAddr::from_parts(storage, len)?; - Ok((UnixStream(sock), addr)) - } - - /// Creates a new independently owned handle to the underlying socket. - /// - /// The returned `UnixListener` is a reference to the same socket that this - /// object references. Both handles can be used to accept incoming - /// connections and options set on one listener will affect the other. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// let listener_copy = listener.try_clone().expect("try_clone failed"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn try_clone(&self) -> io::Result { - self.0.duplicate().map(UnixListener) - } - - /// Returns the local socket address of this listener. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// let addr = listener.local_addr().expect("Couldn't get local address"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn local_addr(&self) -> io::Result { - SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) - } - - /// Moves the socket into or out of nonblocking mode. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// listener.set_nonblocking(true).expect("Couldn't set non blocking"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - self.0.set_nonblocking(nonblocking) - } - - /// Returns the value of the `SO_ERROR` option. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/tmp/sock").unwrap(); - /// - /// if let Ok(Some(err)) = listener.take_error() { - /// println!("Got error: {:?}", err); - /// } - /// ``` - /// - /// # Platform specific - /// On Redox this always returns `None`. - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn take_error(&self) -> io::Result> { - self.0.take_error() - } - - /// Returns an iterator over incoming connections. - /// - /// The iterator will never return [`None`] and will also not yield the - /// peer's [`SocketAddr`] structure. - /// - /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`SocketAddr`]: struct.SocketAddr.html - /// - /// # Examples - /// - /// ```no_run - /// use std::thread; - /// use std::os::unix::net::{UnixStream, UnixListener}; - /// - /// fn handle_client(stream: UnixStream) { - /// // ... - /// } - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// for stream in listener.incoming() { - /// match stream { - /// Ok(stream) => { - /// thread::spawn(|| handle_client(stream)); - /// } - /// Err(err) => { - /// break; - /// } - /// } - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn incoming<'a>(&'a self) -> Incoming<'a> { - Incoming { listener: self } - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl AsRawFd for UnixListener { - fn as_raw_fd(&self) -> RawFd { - *self.0.as_inner() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl FromRawFd for UnixListener { - unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { - UnixListener(Socket::from_inner(fd)) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl IntoRawFd for UnixListener { - fn into_raw_fd(self) -> RawFd { - self.0.into_inner() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl<'a> IntoIterator for &'a UnixListener { - type Item = io::Result; - type IntoIter = Incoming<'a>; - - fn into_iter(self) -> Incoming<'a> { - self.incoming() - } -} - -/// An iterator over incoming connections to a [`UnixListener`]. -/// -/// It will never return [`None`]. -/// -/// [`None`]: ../../../../std/option/enum.Option.html#variant.None -/// [`UnixListener`]: struct.UnixListener.html -/// -/// # Examples -/// -/// ```no_run -/// use std::thread; -/// use std::os::unix::net::{UnixStream, UnixListener}; -/// -/// fn handle_client(stream: UnixStream) { -/// // ... -/// } -/// -/// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); -/// -/// for stream in listener.incoming() { -/// match stream { -/// Ok(stream) => { -/// thread::spawn(|| handle_client(stream)); -/// } -/// Err(err) => { -/// break; -/// } -/// } -/// } -/// ``` -#[derive(Debug)] -#[stable(feature = "unix_socket", since = "1.10.0")] -pub struct Incoming<'a> { - listener: &'a UnixListener, -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl<'a> Iterator for Incoming<'a> { - type Item = io::Result; - - fn next(&mut self) -> Option> { - Some(self.listener.accept().map(|s| s.0)) - } - - fn size_hint(&self) -> (usize, Option) { - (usize::max_value(), None) - } -} - -/// A Unix datagram socket. -/// -/// # Examples -/// -/// ```no_run -/// use std::os::unix::net::UnixDatagram; -/// -/// let socket = UnixDatagram::bind("/path/to/my/socket").unwrap(); -/// socket.send_to(b"hello world", "/path/to/other/socket").unwrap(); -/// let mut buf = [0; 100]; -/// let (count, address) = socket.recv_from(&mut buf).unwrap(); -/// println!("socket {:?} sent {:?}", address, &buf[..count]); -/// ``` -#[stable(feature = "unix_socket", since = "1.10.0")] -pub struct UnixDatagram(Socket); - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl fmt::Debug for UnixDatagram { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut builder = fmt.debug_struct("UnixDatagram"); - builder.field("fd", self.0.as_inner()); - if let Ok(addr) = self.local_addr() { - builder.field("local", &addr); - } - if let Ok(addr) = self.peer_addr() { - builder.field("peer", &addr); - } - builder.finish() - } -} - -impl UnixDatagram { - /// Creates a Unix datagram socket bound to the given path. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// let sock = match UnixDatagram::bind("/path/to/the/socket") { - /// Ok(sock) => sock, - /// Err(e) => { - /// println!("Couldn't bind: {:?}", e); - /// return - /// } - /// }; - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn bind>(path: P) -> io::Result { - fn inner(path: &Path) -> io::Result { - unsafe { - let socket = UnixDatagram::unbound()?; - let (addr, len) = sockaddr_un(path)?; - - cvt(libc::bind(*socket.0.as_inner(), &addr as *const _ as *const _, len as _))?; - - Ok(socket) - } - } - inner(path.as_ref()) - } - - /// Creates a Unix Datagram socket which is not bound to any address. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// let sock = match UnixDatagram::unbound() { - /// Ok(sock) => sock, - /// Err(e) => { - /// println!("Couldn't unbound: {:?}", e); - /// return - /// } - /// }; - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn unbound() -> io::Result { - let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_DGRAM)?; - Ok(UnixDatagram(inner)) - } - - /// Creates an unnamed pair of connected sockets. - /// - /// Returns two `UnixDatagrams`s which are connected to each other. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// let (sock1, sock2) = match UnixDatagram::pair() { - /// Ok((sock1, sock2)) => (sock1, sock2), - /// Err(e) => { - /// println!("Couldn't unbound: {:?}", e); - /// return - /// } - /// }; - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> { - let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_DGRAM)?; - Ok((UnixDatagram(i1), UnixDatagram(i2))) - } - - /// Connects the socket to the specified address. - /// - /// The [`send`] method may be used to send data to the specified address. - /// [`recv`] and [`recv_from`] will only receive data from that address. - /// - /// [`send`]: #method.send - /// [`recv`]: #method.recv - /// [`recv_from`]: #method.recv_from - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// let sock = UnixDatagram::unbound().unwrap(); - /// match sock.connect("/path/to/the/socket") { - /// Ok(sock) => sock, - /// Err(e) => { - /// println!("Couldn't connect: {:?}", e); - /// return - /// } - /// }; - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn connect>(&self, path: P) -> io::Result<()> { - fn inner(d: &UnixDatagram, path: &Path) -> io::Result<()> { - unsafe { - let (addr, len) = sockaddr_un(path)?; - - cvt(libc::connect(*d.0.as_inner(), &addr as *const _ as *const _, len))?; - - Ok(()) - } - } - inner(self, path.as_ref()) - } - - /// Creates a new independently owned handle to the underlying socket. - /// - /// The returned `UnixDatagram` is a reference to the same socket that this - /// object references. Both handles can be used to accept incoming - /// connections and options set on one side will affect the other. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap(); - /// - /// let sock_copy = sock.try_clone().expect("try_clone failed"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn try_clone(&self) -> io::Result { - self.0.duplicate().map(UnixDatagram) - } - - /// Returns the address of this socket. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap(); - /// - /// let addr = sock.local_addr().expect("Couldn't get local address"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn local_addr(&self) -> io::Result { - SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) - } - - /// Returns the address of this socket's peer. - /// - /// The [`connect`] method will connect the socket to a peer. - /// - /// [`connect`]: #method.connect - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// let sock = UnixDatagram::unbound().unwrap(); - /// sock.connect("/path/to/the/socket").unwrap(); - /// - /// let addr = sock.peer_addr().expect("Couldn't get peer address"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn peer_addr(&self) -> io::Result { - SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) }) - } - - /// Receives data from the socket. - /// - /// On success, returns the number of bytes read and the address from - /// whence the data came. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// let sock = UnixDatagram::unbound().unwrap(); - /// let mut buf = vec![0; 10]; - /// match sock.recv_from(buf.as_mut_slice()) { - /// Ok((size, sender)) => println!("received {} bytes from {:?}", size, sender), - /// Err(e) => println!("recv_from function failed: {:?}", e), - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - let mut count = 0; - let addr = SocketAddr::new(|addr, len| { - unsafe { - count = libc::recvfrom(*self.0.as_inner(), - buf.as_mut_ptr() as *mut _, - buf.len(), - 0, - addr, - len); - if count > 0 { - 1 - } else if count == 0 { - 0 - } else { - -1 - } - } - })?; - - Ok((count as usize, addr)) - } - - /// Receives data from the socket. - /// - /// On success, returns the number of bytes read. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap(); - /// let mut buf = vec![0; 10]; - /// sock.recv(buf.as_mut_slice()).expect("recv function failed"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn recv(&self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) - } - - /// Sends data on the socket to the specified address. - /// - /// On success, returns the number of bytes written. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// let sock = UnixDatagram::unbound().unwrap(); - /// sock.send_to(b"omelette au fromage", "/some/sock").expect("send_to function failed"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn send_to>(&self, buf: &[u8], path: P) -> io::Result { - fn inner(d: &UnixDatagram, buf: &[u8], path: &Path) -> io::Result { - unsafe { - let (addr, len) = sockaddr_un(path)?; - - let count = cvt(libc::sendto(*d.0.as_inner(), - buf.as_ptr() as *const _, - buf.len(), - MSG_NOSIGNAL, - &addr as *const _ as *const _, - len))?; - Ok(count as usize) - } - } - inner(self, buf, path.as_ref()) - } - - /// Sends data on the socket to the socket's peer. - /// - /// The peer address may be set by the `connect` method, and this method - /// will return an error if the socket has not already been connected. - /// - /// On success, returns the number of bytes written. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// let sock = UnixDatagram::unbound().unwrap(); - /// sock.connect("/some/sock").expect("Couldn't connect"); - /// sock.send(b"omelette au fromage").expect("send_to function failed"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn send(&self, buf: &[u8]) -> io::Result { - self.0.write(buf) - } - - /// Sets the read timeout for the socket. - /// - /// If the provided value is [`None`], then [`recv`] and [`recv_from`] calls will - /// block indefinitely. An [`Err`] is returned if the zero [`Duration`] - /// is passed to this method. - /// - /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err - /// [`recv`]: #method.recv - /// [`recv_from`]: #method.recv_from - /// [`Duration`]: ../../../../std/time/struct.Duration.html - /// - /// # Examples - /// - /// ``` - /// use std::os::unix::net::UnixDatagram; - /// use std::time::Duration; - /// - /// let sock = UnixDatagram::unbound().unwrap(); - /// sock.set_read_timeout(Some(Duration::new(1, 0))).expect("set_read_timeout function failed"); - /// ``` - /// - /// An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method: - /// - /// ```no_run - /// use std::io; - /// use std::os::unix::net::UnixDatagram; - /// use std::time::Duration; - /// - /// let socket = UnixDatagram::unbound().unwrap(); - /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); - /// let err = result.unwrap_err(); - /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { - self.0.set_timeout(timeout, libc::SO_RCVTIMEO) - } - - /// Sets the write timeout for the socket. - /// - /// If the provided value is [`None`], then [`send`] and [`send_to`] calls will - /// block indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method. - /// - /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`send`]: #method.send - /// [`send_to`]: #method.send_to - /// [`Duration`]: ../../../../std/time/struct.Duration.html - /// - /// # Examples - /// - /// ``` - /// use std::os::unix::net::UnixDatagram; - /// use std::time::Duration; - /// - /// let sock = UnixDatagram::unbound().unwrap(); - /// sock.set_write_timeout(Some(Duration::new(1, 0))) - /// .expect("set_write_timeout function failed"); - /// ``` - /// - /// An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method: - /// - /// ```no_run - /// use std::io; - /// use std::os::unix::net::UnixDatagram; - /// use std::time::Duration; - /// - /// let socket = UnixDatagram::unbound().unwrap(); - /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); - /// let err = result.unwrap_err(); - /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { - self.0.set_timeout(timeout, libc::SO_SNDTIMEO) - } - - /// Returns the read timeout of this socket. - /// - /// # Examples - /// - /// ``` - /// use std::os::unix::net::UnixDatagram; - /// use std::time::Duration; - /// - /// let sock = UnixDatagram::unbound().unwrap(); - /// sock.set_read_timeout(Some(Duration::new(1, 0))).expect("set_read_timeout function failed"); - /// assert_eq!(sock.read_timeout().unwrap(), Some(Duration::new(1, 0))); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn read_timeout(&self) -> io::Result> { - self.0.timeout(libc::SO_RCVTIMEO) - } - - /// Returns the write timeout of this socket. - /// - /// # Examples - /// - /// ``` - /// use std::os::unix::net::UnixDatagram; - /// use std::time::Duration; - /// - /// let sock = UnixDatagram::unbound().unwrap(); - /// sock.set_write_timeout(Some(Duration::new(1, 0))) - /// .expect("set_write_timeout function failed"); - /// assert_eq!(sock.write_timeout().unwrap(), Some(Duration::new(1, 0))); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn write_timeout(&self) -> io::Result> { - self.0.timeout(libc::SO_SNDTIMEO) - } - - /// Moves the socket into or out of nonblocking mode. - /// - /// # Examples - /// - /// ``` - /// use std::os::unix::net::UnixDatagram; - /// - /// let sock = UnixDatagram::unbound().unwrap(); - /// sock.set_nonblocking(true).expect("set_nonblocking function failed"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - self.0.set_nonblocking(nonblocking) - } - - /// Returns the value of the `SO_ERROR` option. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// let sock = UnixDatagram::unbound().unwrap(); - /// if let Ok(Some(err)) = sock.take_error() { - /// println!("Got error: {:?}", err); - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn take_error(&self) -> io::Result> { - self.0.take_error() - } - - /// Shut down the read, write, or both halves of this connection. - /// - /// This function will cause all pending and future I/O calls on the - /// specified portions to immediately return with an appropriate value - /// (see the documentation of [`Shutdown`]). - /// - /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// use std::net::Shutdown; - /// - /// let sock = UnixDatagram::unbound().unwrap(); - /// sock.shutdown(Shutdown::Both).expect("shutdown function failed"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { - self.0.shutdown(how) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl AsRawFd for UnixDatagram { - fn as_raw_fd(&self) -> RawFd { - *self.0.as_inner() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl FromRawFd for UnixDatagram { - unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram { - UnixDatagram(Socket::from_inner(fd)) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl IntoRawFd for UnixDatagram { - fn into_raw_fd(self) -> RawFd { - self.0.into_inner() - } -} - -#[cfg(all(test, not(target_os = "emscripten")))] -mod test { - use crate::thread; - use crate::io::{self, ErrorKind}; - use crate::io::prelude::*; - use crate::time::Duration; - use crate::sys_common::io::test::tmpdir; - - use super::*; - - macro_rules! or_panic { - ($e:expr) => { - match $e { - Ok(e) => e, - Err(e) => panic!("{}", e), - } - } - } - - #[test] - fn basic() { - let dir = tmpdir(); - let socket_path = dir.path().join("sock"); - let msg1 = b"hello"; - let msg2 = b"world!"; - - let listener = or_panic!(UnixListener::bind(&socket_path)); - let thread = thread::spawn(move || { - let mut stream = or_panic!(listener.accept()).0; - let mut buf = [0; 5]; - or_panic!(stream.read(&mut buf)); - assert_eq!(&msg1[..], &buf[..]); - or_panic!(stream.write_all(msg2)); - }); - - let mut stream = or_panic!(UnixStream::connect(&socket_path)); - assert_eq!(Some(&*socket_path), - stream.peer_addr().unwrap().as_pathname()); - or_panic!(stream.write_all(msg1)); - let mut buf = vec![]; - or_panic!(stream.read_to_end(&mut buf)); - assert_eq!(&msg2[..], &buf[..]); - drop(stream); - - thread.join().unwrap(); - } - - #[test] - fn vectored() { - let (mut s1, mut s2) = or_panic!(UnixStream::pair()); - - let len = or_panic!(s1.write_vectored( - &[IoSlice::new(b"hello"), IoSlice::new(b" "), IoSlice::new(b"world!")], - )); - assert_eq!(len, 12); - - let mut buf1 = [0; 6]; - let mut buf2 = [0; 7]; - let len = or_panic!(s2.read_vectored( - &mut [IoSliceMut::new(&mut buf1), IoSliceMut::new(&mut buf2)], - )); - assert_eq!(len, 12); - assert_eq!(&buf1, b"hello "); - assert_eq!(&buf2, b"world!\0"); - } - - #[test] - fn pair() { - let msg1 = b"hello"; - let msg2 = b"world!"; - - let (mut s1, mut s2) = or_panic!(UnixStream::pair()); - let thread = thread::spawn(move || { - // s1 must be moved in or the test will hang! - let mut buf = [0; 5]; - or_panic!(s1.read(&mut buf)); - assert_eq!(&msg1[..], &buf[..]); - or_panic!(s1.write_all(msg2)); - }); - - or_panic!(s2.write_all(msg1)); - let mut buf = vec![]; - or_panic!(s2.read_to_end(&mut buf)); - assert_eq!(&msg2[..], &buf[..]); - drop(s2); - - thread.join().unwrap(); - } - - #[test] - fn try_clone() { - let dir = tmpdir(); - let socket_path = dir.path().join("sock"); - let msg1 = b"hello"; - let msg2 = b"world"; - - let listener = or_panic!(UnixListener::bind(&socket_path)); - let thread = thread::spawn(move || { - let mut stream = or_panic!(listener.accept()).0; - or_panic!(stream.write_all(msg1)); - or_panic!(stream.write_all(msg2)); - }); - - let mut stream = or_panic!(UnixStream::connect(&socket_path)); - let mut stream2 = or_panic!(stream.try_clone()); - - let mut buf = [0; 5]; - or_panic!(stream.read(&mut buf)); - assert_eq!(&msg1[..], &buf[..]); - or_panic!(stream2.read(&mut buf)); - assert_eq!(&msg2[..], &buf[..]); - - thread.join().unwrap(); - } - - #[test] - fn iter() { - let dir = tmpdir(); - let socket_path = dir.path().join("sock"); - - let listener = or_panic!(UnixListener::bind(&socket_path)); - let thread = thread::spawn(move || { - for stream in listener.incoming().take(2) { - let mut stream = or_panic!(stream); - let mut buf = [0]; - or_panic!(stream.read(&mut buf)); - } - }); - - for _ in 0..2 { - let mut stream = or_panic!(UnixStream::connect(&socket_path)); - or_panic!(stream.write_all(&[0])); - } - - thread.join().unwrap(); - } - - #[test] - fn long_path() { - let dir = tmpdir(); - let socket_path = dir.path() - .join("asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfa\ - sasdfasdfasdasdfasdfasdfadfasdfasdfasdfasdfasdf"); - match UnixStream::connect(&socket_path) { - Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {} - Err(e) => panic!("unexpected error {}", e), - Ok(_) => panic!("unexpected success"), - } - - match UnixListener::bind(&socket_path) { - Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {} - Err(e) => panic!("unexpected error {}", e), - Ok(_) => panic!("unexpected success"), - } - - match UnixDatagram::bind(&socket_path) { - Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {} - Err(e) => panic!("unexpected error {}", e), - Ok(_) => panic!("unexpected success"), - } - } - - #[test] - fn timeouts() { - let dir = tmpdir(); - let socket_path = dir.path().join("sock"); - - let _listener = or_panic!(UnixListener::bind(&socket_path)); - - let stream = or_panic!(UnixStream::connect(&socket_path)); - let dur = Duration::new(15410, 0); - - assert_eq!(None, or_panic!(stream.read_timeout())); - - or_panic!(stream.set_read_timeout(Some(dur))); - assert_eq!(Some(dur), or_panic!(stream.read_timeout())); - - assert_eq!(None, or_panic!(stream.write_timeout())); - - or_panic!(stream.set_write_timeout(Some(dur))); - assert_eq!(Some(dur), or_panic!(stream.write_timeout())); - - or_panic!(stream.set_read_timeout(None)); - assert_eq!(None, or_panic!(stream.read_timeout())); - - or_panic!(stream.set_write_timeout(None)); - assert_eq!(None, or_panic!(stream.write_timeout())); - } - - #[test] - fn test_read_timeout() { - let dir = tmpdir(); - let socket_path = dir.path().join("sock"); - - let _listener = or_panic!(UnixListener::bind(&socket_path)); - - let mut stream = or_panic!(UnixStream::connect(&socket_path)); - or_panic!(stream.set_read_timeout(Some(Duration::from_millis(1000)))); - - let mut buf = [0; 10]; - let kind = stream.read_exact(&mut buf).err().expect("expected error").kind(); - assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut, - "unexpected_error: {:?}", kind); - } - - #[test] - fn test_read_with_timeout() { - let dir = tmpdir(); - let socket_path = dir.path().join("sock"); - - let listener = or_panic!(UnixListener::bind(&socket_path)); - - let mut stream = or_panic!(UnixStream::connect(&socket_path)); - or_panic!(stream.set_read_timeout(Some(Duration::from_millis(1000)))); - - let mut other_end = or_panic!(listener.accept()).0; - or_panic!(other_end.write_all(b"hello world")); - - let mut buf = [0; 11]; - or_panic!(stream.read(&mut buf)); - assert_eq!(b"hello world", &buf[..]); - - let kind = stream.read_exact(&mut buf).err().expect("expected error").kind(); - assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut, - "unexpected_error: {:?}", kind); - } - - // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors - // when passed zero Durations - #[test] - fn test_unix_stream_timeout_zero_duration() { - let dir = tmpdir(); - let socket_path = dir.path().join("sock"); - - let listener = or_panic!(UnixListener::bind(&socket_path)); - let stream = or_panic!(UnixStream::connect(&socket_path)); - - let result = stream.set_write_timeout(Some(Duration::new(0, 0))); - let err = result.unwrap_err(); - assert_eq!(err.kind(), ErrorKind::InvalidInput); - - let result = stream.set_read_timeout(Some(Duration::new(0, 0))); - let err = result.unwrap_err(); - assert_eq!(err.kind(), ErrorKind::InvalidInput); - - drop(listener); - } - - #[test] - fn test_unix_datagram() { - let dir = tmpdir(); - let path1 = dir.path().join("sock1"); - let path2 = dir.path().join("sock2"); - - let sock1 = or_panic!(UnixDatagram::bind(&path1)); - let sock2 = or_panic!(UnixDatagram::bind(&path2)); - - let msg = b"hello world"; - or_panic!(sock1.send_to(msg, &path2)); - let mut buf = [0; 11]; - or_panic!(sock2.recv_from(&mut buf)); - assert_eq!(msg, &buf[..]); - } - - #[test] - fn test_unnamed_unix_datagram() { - let dir = tmpdir(); - let path1 = dir.path().join("sock1"); - - let sock1 = or_panic!(UnixDatagram::bind(&path1)); - let sock2 = or_panic!(UnixDatagram::unbound()); - - let msg = b"hello world"; - or_panic!(sock2.send_to(msg, &path1)); - let mut buf = [0; 11]; - let (usize, addr) = or_panic!(sock1.recv_from(&mut buf)); - assert_eq!(usize, 11); - assert!(addr.is_unnamed()); - assert_eq!(msg, &buf[..]); - } - - #[test] - fn test_connect_unix_datagram() { - let dir = tmpdir(); - let path1 = dir.path().join("sock1"); - let path2 = dir.path().join("sock2"); - - let bsock1 = or_panic!(UnixDatagram::bind(&path1)); - let bsock2 = or_panic!(UnixDatagram::bind(&path2)); - let sock = or_panic!(UnixDatagram::unbound()); - or_panic!(sock.connect(&path1)); - - // Check send() - let msg = b"hello there"; - or_panic!(sock.send(msg)); - let mut buf = [0; 11]; - let (usize, addr) = or_panic!(bsock1.recv_from(&mut buf)); - assert_eq!(usize, 11); - assert!(addr.is_unnamed()); - assert_eq!(msg, &buf[..]); - - // Changing default socket works too - or_panic!(sock.connect(&path2)); - or_panic!(sock.send(msg)); - or_panic!(bsock2.recv_from(&mut buf)); - } - - #[test] - fn test_unix_datagram_recv() { - let dir = tmpdir(); - let path1 = dir.path().join("sock1"); - - let sock1 = or_panic!(UnixDatagram::bind(&path1)); - let sock2 = or_panic!(UnixDatagram::unbound()); - or_panic!(sock2.connect(&path1)); - - let msg = b"hello world"; - or_panic!(sock2.send(msg)); - let mut buf = [0; 11]; - let size = or_panic!(sock1.recv(&mut buf)); - assert_eq!(size, 11); - assert_eq!(msg, &buf[..]); - } - - #[test] - fn datagram_pair() { - let msg1 = b"hello"; - let msg2 = b"world!"; - - let (s1, s2) = or_panic!(UnixDatagram::pair()); - let thread = thread::spawn(move || { - // s1 must be moved in or the test will hang! - let mut buf = [0; 5]; - or_panic!(s1.recv(&mut buf)); - assert_eq!(&msg1[..], &buf[..]); - or_panic!(s1.send(msg2)); - }); - - or_panic!(s2.send(msg1)); - let mut buf = [0; 6]; - or_panic!(s2.recv(&mut buf)); - assert_eq!(&msg2[..], &buf[..]); - drop(s2); - - thread.join().unwrap(); - } - - // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors - // when passed zero Durations - #[test] - fn test_unix_datagram_timeout_zero_duration() { - let dir = tmpdir(); - let path = dir.path().join("sock"); - - let datagram = or_panic!(UnixDatagram::bind(&path)); - - let result = datagram.set_write_timeout(Some(Duration::new(0, 0))); - let err = result.unwrap_err(); - assert_eq!(err.kind(), ErrorKind::InvalidInput); - - let result = datagram.set_read_timeout(Some(Duration::new(0, 0))); - let err = result.unwrap_err(); - assert_eq!(err.kind(), ErrorKind::InvalidInput); - } - - #[test] - fn abstract_namespace_not_allowed() { - assert!(UnixStream::connect("\0asdf").is_err()); - } -} diff --git a/src/libsyntax/error_codes.rs b/src/libsyntax/error_codes.rs index 17ea476752064..941df5ea57087 100644 --- a/src/libsyntax/error_codes.rs +++ b/src/libsyntax/error_codes.rs @@ -487,7 +487,6 @@ Erroneous code example: // `test_2018_feature` is // included in the Rust 2018 edition ``` - "##, E0725: r##" @@ -505,6 +504,20 @@ Delete the offending feature attribute, or add it to the list of allowed features in the `-Z allow_features` flag. "##, +E0743: r##" +C-variadic has been used on a non-foreign function. + +Erroneous code example: + +```compile_fail,E0743 +fn foo2(x: u8, ...) {} // error! +``` + +Only foreign functions can use C-variadic (`...`). It is used to give an +undefined number of parameters to a given function (like `printf` in C). The +equivalent in Rust would be to use macros directly. +"##, + ; E0539, // incorrect meta item diff --git a/src/libsyntax/parse/parser/ty.rs b/src/libsyntax/parse/parser/ty.rs index 86c94b680b2c9..e8f718a24835c 100644 --- a/src/libsyntax/parse/parser/ty.rs +++ b/src/libsyntax/parse/parser/ty.rs @@ -197,8 +197,11 @@ impl<'a> Parser<'a> { self.eat(&token::DotDotDot); TyKind::CVarArgs } else { - return Err(self.fatal( - "only foreign functions are allowed to be C-variadic" + return Err(struct_span_fatal!( + self.sess.span_diagnostic, + self.token.span, + E0743, + "only foreign functions are allowed to be C-variadic", )); } } else { diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 8ba161f55c1ff..57131ffe18cb3 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -370,6 +370,7 @@ symbols! { issue_5723_bootstrap, issue_tracker_base_url, item, + item_context: "ItemContext", item_like_imports, iter, Iterator, diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs index f24d957d67b75..b8db16f8f2ac8 100644 --- a/src/libunwind/build.rs +++ b/src/libunwind/build.rs @@ -56,12 +56,18 @@ mod llvm_libunwind { pub fn compile() { let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap(); let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap(); + let target_endian_little = env::var("CARGO_CFG_TARGET_ENDIAN").unwrap() != "big"; let cfg = &mut cc::Build::new(); cfg.cpp(true); cfg.cpp_set_stdlib(None); cfg.warnings(false); + // libunwind expects a __LITTLE_ENDIAN__ macro to be set for LE archs, cf. #65765 + if target_endian_little { + cfg.define("__LITTLE_ENDIAN__", Some("1")); + } + if target_env == "msvc" { // Don't pull in extra libraries on MSVC cfg.flag("/Zl"); diff --git a/src/test/run-make-fulldeps/issue-64319/Makefile b/src/test/run-make-fulldeps/issue-64319/Makefile deleted file mode 100644 index b2c6b8b3cbbf2..0000000000000 --- a/src/test/run-make-fulldeps/issue-64319/Makefile +++ /dev/null @@ -1,39 +0,0 @@ --include ../tools.mk - -# Different optimization levels imply different values for `-Zshare-generics`, -# so try out a whole bunch of combinations to make sure everything is compatible -all: - # First up, try some defaults - $(RUSTC) --crate-type rlib foo.rs - $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 - - # Next try mixing up some things explicitly - $(RUSTC) --crate-type rlib foo.rs -Z share-generics=no - $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no - $(RUSTC) --crate-type rlib foo.rs -Z share-generics=no - $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes - $(RUSTC) --crate-type rlib foo.rs -Z share-generics=yes - $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no - $(RUSTC) --crate-type rlib foo.rs -Z share-generics=yes - $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes - - # Now combine a whole bunch of options together - $(RUSTC) --crate-type rlib foo.rs - $(RUSTC) --crate-type dylib bar.rs - $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no - $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes - $(RUSTC) --crate-type dylib bar.rs -C opt-level=1 - $(RUSTC) --crate-type dylib bar.rs -C opt-level=1 -Z share-generics=no - $(RUSTC) --crate-type dylib bar.rs -C opt-level=1 -Z share-generics=yes - $(RUSTC) --crate-type dylib bar.rs -C opt-level=2 - $(RUSTC) --crate-type dylib bar.rs -C opt-level=2 -Z share-generics=no - $(RUSTC) --crate-type dylib bar.rs -C opt-level=2 -Z share-generics=yes - $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 - $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 -Z share-generics=no - $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 -Z share-generics=yes - $(RUSTC) --crate-type dylib bar.rs -C opt-level=s - $(RUSTC) --crate-type dylib bar.rs -C opt-level=s -Z share-generics=no - $(RUSTC) --crate-type dylib bar.rs -C opt-level=s -Z share-generics=yes - $(RUSTC) --crate-type dylib bar.rs -C opt-level=z - $(RUSTC) --crate-type dylib bar.rs -C opt-level=z -Z share-generics=no - $(RUSTC) --crate-type dylib bar.rs -C opt-level=z -Z share-generics=yes diff --git a/src/test/run-make-fulldeps/issue-64319/bar.rs b/src/test/run-make-fulldeps/issue-64319/bar.rs deleted file mode 100644 index 3895c0b6cdbb3..0000000000000 --- a/src/test/run-make-fulldeps/issue-64319/bar.rs +++ /dev/null @@ -1,5 +0,0 @@ -extern crate foo; - -pub fn bar() { - foo::foo(); -} diff --git a/src/test/run-make-fulldeps/issue-64319/foo.rs b/src/test/run-make-fulldeps/issue-64319/foo.rs deleted file mode 100644 index c54a238e9add7..0000000000000 --- a/src/test/run-make-fulldeps/issue-64319/foo.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub fn foo() { - bar::(); -} - -pub fn bar() { - baz(); -} - -fn baz() {} diff --git a/src/test/run-make-fulldeps/symbol-visibility/Makefile b/src/test/run-make-fulldeps/symbol-visibility/Makefile index 840fe801a953c..7901866015bf2 100644 --- a/src/test/run-make-fulldeps/symbol-visibility/Makefile +++ b/src/test/run-make-fulldeps/symbol-visibility/Makefile @@ -79,12 +79,12 @@ all: # Check that a Rust dylib exports its monomorphic functions, including generics this time [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_c_function_from_rust_dylib)" -eq "1" ] [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_rust_function_from_rust_dylib)" -eq "1" ] - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rust_dylib)" -eq "0" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rust_dylib)" -eq "1" ] # Check that a Rust dylib exports the monomorphic functions from its dependencies [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_c_function_from_rlib)" -eq "1" ] [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_rust_function_from_rlib)" -eq "1" ] - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rlib)" -eq "0" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rlib)" -eq "1" ] # Check that an executable does not export any dynamic symbols [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -c public_c_function_from_rlib)" -eq "0" ] diff --git a/src/test/rustdoc/issue-55364.rs b/src/test/rustdoc/issue-55364.rs new file mode 100644 index 0000000000000..200a29fc7eea3 --- /dev/null +++ b/src/test/rustdoc/issue-55364.rs @@ -0,0 +1,88 @@ +// ignore-tidy-linelength + +// First a module with inner documentation + +// @has issue_55364/subone/index.html +// These foo/bar links in the module's documentation should refer inside `subone` +// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subone/fn.foo.html"]' 'foo' +// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subone/fn.bar.html"]' 'bar' +pub mod subone { + //! See either [foo] or [bar]. + + // This should refer to subone's `bar` + // @has issue_55364/subone/fn.foo.html + // @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subone/fn.bar.html"]' 'bar' + /// See [bar] + pub fn foo() {} + // This should refer to subone's `foo` + // @has issue_55364/subone/fn.bar.html + // @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subone/fn.foo.html"]' 'foo' + /// See [foo] + pub fn bar() {} +} + +// A module with outer documentation + +// @has issue_55364/subtwo/index.html +// These foo/bar links in the module's documentation should not reference inside `subtwo` +// @!has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subtwo/fn.foo.html"]' 'foo' +// @!has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subtwo/fn.bar.html"]' 'bar' +// Instead it should be referencing the top level functions +// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/fn.foo.html"]' 'foo' +// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/fn.bar.html"]' 'bar' +// Though there should be such links later +// @has - '//section[@id="main"]/table//tr[@class="module-item"]/td/a[@class="fn"][@href="fn.foo.html"]' 'foo' +// @has - '//section[@id="main"]/table//tr[@class="module-item"]/td/a[@class="fn"][@href="fn.bar.html"]' 'bar' +/// See either [foo] or [bar]. +pub mod subtwo { + + // Despite the module's docs referring to the top level foo/bar, + // this should refer to subtwo's `bar` + // @has issue_55364/subtwo/fn.foo.html + // @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subtwo/fn.bar.html"]' 'bar' + /// See [bar] + pub fn foo() {} + // Despite the module's docs referring to the top level foo/bar, + // this should refer to subtwo's `foo` + // @has issue_55364/subtwo/fn.bar.html + // @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subtwo/fn.foo.html"]' 'foo' + /// See [foo] + pub fn bar() {} +} + +// These are the function referred to by the module above with outer docs + +/// See [bar] +pub fn foo() {} +/// See [foo] +pub fn bar() {} + +// This module refers to the outer foo/bar by means of `super::` + +// @has issue_55364/subthree/index.html +// This module should also refer to the top level foo/bar +// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/fn.foo.html"]' 'foo' +// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/fn.bar.html"]' 'bar' +pub mod subthree { + //! See either [foo][super::foo] or [bar][super::bar] +} + +// Next we go *deeper* - In order to ensure it's not just "this or parent" +// we test `crate::` and a `super::super::...` chain +// @has issue_55364/subfour/subfive/subsix/subseven/subeight/index.html +// @has - '//section[@id="main"]/table//tr[@class="module-item"]/td[@class="docblock-short"]//a[@href="../../../../../../issue_55364/subone/fn.foo.html"]' 'other foo' +// @has - '//section[@id="main"]/table//tr[@class="module-item"]/td[@class="docblock-short"]//a[@href="../../../../../../issue_55364/subtwo/fn.bar.html"]' 'other bar' +pub mod subfour { + pub mod subfive { + pub mod subsix { + pub mod subseven { + pub mod subeight { + /// See [other foo][crate::subone::foo] + pub fn foo() {} + /// See [other bar][super::super::super::super::super::subtwo::bar] + pub fn bar() {} + } + } + } + } +} diff --git a/src/test/ui/alignment-gep-tup-like-1.rs b/src/test/ui/alignment-gep-tup-like-1.rs index c51c56b089926..adbd05ed8c175 100644 --- a/src/test/ui/alignment-gep-tup-like-1.rs +++ b/src/test/ui/alignment-gep-tup-like-1.rs @@ -28,7 +28,7 @@ fn f(a: A, b: u16) -> Box+'static> { box Invoker { a: a, b: b, - } as (Box+'static>) + } as Box+'static> } pub fn main() { diff --git a/src/test/ui/as-precedence.rs b/src/test/ui/as-precedence.rs index a9f6fceb08ff0..feb0cb30ccacc 100644 --- a/src/test/ui/as-precedence.rs +++ b/src/test/ui/as-precedence.rs @@ -1,5 +1,6 @@ // run-pass +#[allow(unused_parens)] fn main() { assert_eq!(3 as usize * 3, 9); assert_eq!(3 as (usize) * 3, 9); diff --git a/src/test/ui/associated-type-bounds/type-alias.stderr b/src/test/ui/associated-type-bounds/type-alias.stderr index a3fa97f54e385..7f58f7f73e38c 100644 --- a/src/test/ui/associated-type-bounds/type-alias.stderr +++ b/src/test/ui/associated-type-bounds/type-alias.stderr @@ -5,7 +5,10 @@ LL | type _TaWhere1 where T: Iterator = T; | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(type_alias_bounds)]` on by default - = help: the clause will not be checked when the type alias is used, and should be removed +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | type _TaWhere1 = T; + | -- warning: where clauses are not enforced in type aliases --> $DIR/type-alias.rs:6:25 @@ -13,7 +16,10 @@ warning: where clauses are not enforced in type aliases LL | type _TaWhere2 where T: Iterator = T; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the clause will not be checked when the type alias is used, and should be removed +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | type _TaWhere2 = T; + | -- warning: where clauses are not enforced in type aliases --> $DIR/type-alias.rs:7:25 @@ -21,7 +27,10 @@ warning: where clauses are not enforced in type aliases LL | type _TaWhere3 where T: Iterator = T; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the clause will not be checked when the type alias is used, and should be removed +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | type _TaWhere3 = T; + | -- warning: where clauses are not enforced in type aliases --> $DIR/type-alias.rs:8:25 @@ -29,7 +38,10 @@ warning: where clauses are not enforced in type aliases LL | type _TaWhere4 where T: Iterator = T; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the clause will not be checked when the type alias is used, and should be removed +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | type _TaWhere4 = T; + | -- warning: where clauses are not enforced in type aliases --> $DIR/type-alias.rs:9:25 @@ -37,7 +49,10 @@ warning: where clauses are not enforced in type aliases LL | type _TaWhere5 where T: Iterator Into<&'a u8>> = T; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the clause will not be checked when the type alias is used, and should be removed +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | type _TaWhere5 = T; + | -- warning: where clauses are not enforced in type aliases --> $DIR/type-alias.rs:10:25 @@ -45,7 +60,10 @@ warning: where clauses are not enforced in type aliases LL | type _TaWhere6 where T: Iterator> = T; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the clause will not be checked when the type alias is used, and should be removed +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | type _TaWhere6 = T; + | -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias.rs:12:20 @@ -53,7 +71,10 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type _TaInline1> = T; | ^^^^^^^^^^^^^^^^^^^^ | - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type _TaInline1 = T; + | -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias.rs:13:20 @@ -61,7 +82,10 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type _TaInline2> = T; | ^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type _TaInline2 = T; + | -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias.rs:14:20 @@ -69,7 +93,10 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type _TaInline3> = T; | ^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type _TaInline3 = T; + | -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias.rs:15:20 @@ -77,7 +104,10 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type _TaInline4> = T; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type _TaInline4 = T; + | -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias.rs:16:20 @@ -85,7 +115,10 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type _TaInline5 Into<&'a u8>>> = T; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type _TaInline5 = T; + | -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias.rs:17:20 @@ -93,5 +126,8 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type _TaInline6>> = T; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type _TaInline6 = T; + | -- diff --git a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr index 6a2135ca46445..800b762911a62 100644 --- a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr +++ b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr @@ -5,10 +5,10 @@ LL | fn blue_car>(c: C) { | -------- ---------- required by this bound in `blue_car` ... LL | fn b() { blue_car(ModelT); } - | ^^^^^^^^ expected struct `Black`, found struct `Blue` + | ^^^^^^^^ expected struct `Blue`, found struct `Black` | - = note: expected type `Black` - found type `Blue` + = note: expected type `Blue` + found type `Black` error[E0271]: type mismatch resolving `::Color == Black` --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:32:10 @@ -17,10 +17,10 @@ LL | fn black_car>(c: C) { | --------- ----------- required by this bound in `black_car` ... LL | fn c() { black_car(ModelU); } - | ^^^^^^^^^ expected struct `Blue`, found struct `Black` + | ^^^^^^^^^ expected struct `Black`, found struct `Blue` | - = note: expected type `Blue` - found type `Black` + = note: expected type `Black` + found type `Blue` error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/associated-types-eq-3.rs b/src/test/ui/associated-types/associated-types-eq-3.rs index 9366148b587d2..22e04a8f15ca8 100644 --- a/src/test/ui/associated-types/associated-types-eq-3.rs +++ b/src/test/ui/associated-types/associated-types-eq-3.rs @@ -37,8 +37,8 @@ pub fn main() { let a = 42; foo1(a); //~^ ERROR type mismatch resolving - //~| expected usize, found struct `Bar` + //~| expected struct `Bar`, found usize baz(&a); //~^ ERROR type mismatch resolving - //~| expected usize, found struct `Bar` + //~| expected struct `Bar`, found usize } diff --git a/src/test/ui/associated-types/associated-types-eq-3.stderr b/src/test/ui/associated-types/associated-types-eq-3.stderr index 83d89924944ab..0f2bc84aa1c59 100644 --- a/src/test/ui/associated-types/associated-types-eq-3.stderr +++ b/src/test/ui/associated-types/associated-types-eq-3.stderr @@ -16,19 +16,19 @@ LL | fn foo1>(x: I) { | ---- ----- required by this bound in `foo1` ... LL | foo1(a); - | ^^^^ expected usize, found struct `Bar` + | ^^^^ expected struct `Bar`, found usize | - = note: expected type `usize` - found type `Bar` + = note: expected type `Bar` + found type `usize` error[E0271]: type mismatch resolving `::A == Bar` --> $DIR/associated-types-eq-3.rs:41:9 | LL | baz(&a); - | ^^ expected usize, found struct `Bar` + | ^^ expected struct `Bar`, found usize | - = note: expected type `usize` - found type `Bar` + = note: expected type `Bar` + found type `usize` = note: required for the cast to the object type `dyn Foo` error: aborting due to 3 previous errors diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index 45b6cc9ba5f98..a8c239389e977 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -7,10 +7,10 @@ LL | where T : for<'x> TheTrait<&'x isize, A = &'x isize> | ------------- required by this bound in `foo` ... LL | foo::(); - | ^^^^^^^^^^^^^^^^^ expected usize, found isize + | ^^^^^^^^^^^^^^^^^ expected isize, found usize | - = note: expected type `&usize` - found type `&isize` + = note: expected type `&isize` + found type `&usize` error[E0271]: type mismatch resolving `for<'x> >::A == &'x usize` --> $DIR/associated-types-eq-hr.rs:86:5 @@ -21,10 +21,10 @@ LL | where T : for<'x> TheTrait<&'x isize, A = &'x usize> | ------------- required by this bound in `bar` ... LL | bar::(); - | ^^^^^^^^^^^^^^^^ expected isize, found usize + | ^^^^^^^^^^^^^^^^ expected usize, found isize | - = note: expected type `&isize` - found type `&usize` + = note: expected type `&usize` + found type `&isize` error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied --> $DIR/associated-types-eq-hr.rs:91:17 diff --git a/src/test/ui/associated-types/associated-types-issue-20346.stderr b/src/test/ui/associated-types/associated-types-issue-20346.stderr index c8f8725afc45c..b763b82d540cc 100644 --- a/src/test/ui/associated-types/associated-types-issue-20346.stderr +++ b/src/test/ui/associated-types/associated-types-issue-20346.stderr @@ -5,10 +5,10 @@ LL | fn is_iterator_of>(_: &I) {} | -------------- ------ required by this bound in `is_iterator_of` ... LL | is_iterator_of::, _>(&adapter); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found enum `std::option::Option` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::option::Option`, found type parameter | - = note: expected type `T` - found type `std::option::Option` + = note: expected type `std::option::Option` + found type `T` = help: type parameters must be constrained to match other types = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters diff --git a/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr b/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr index c7de186c1d3e0..e3a2b5edf3f1b 100644 --- a/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr +++ b/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr @@ -2,28 +2,28 @@ error[E0271]: type mismatch resolving `::Y == i32` --> $DIR/associated-types-multiple-types-one-trait.rs:13:5 | LL | want_y(t); - | ^^^^^^ expected associated type, found i32 + | ^^^^^^ expected i32, found associated type ... LL | fn want_y>(t: &T) { } | ------ ----- required by this bound in `want_y` | - = note: expected type `::Y` - found type `i32` - = note: consider constraining the associated type `::Y` to `i32` or calling a method that returns `::Y` + = note: expected type `i32` + found type `::Y` + = note: consider constraining the associated type `::Y` to `i32` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0271]: type mismatch resolving `::X == u32` --> $DIR/associated-types-multiple-types-one-trait.rs:18:5 | LL | want_x(t); - | ^^^^^^ expected associated type, found u32 + | ^^^^^^ expected u32, found associated type ... LL | fn want_x>(t: &T) { } | ------ ----- required by this bound in `want_x` | - = note: expected type `::X` - found type `u32` - = note: consider constraining the associated type `::X` to `u32` or calling a method that returns `::X` + = note: expected type `u32` + found type `::X` + = note: consider constraining the associated type `::X` to `u32` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr index aff067c289107..02a6ac12dd927 100644 --- a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr +++ b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr @@ -2,10 +2,10 @@ error[E0271]: type mismatch resolving ` as std::iter::It --> $DIR/associated-types-overridden-binding-2.rs:6:43 | LL | let _: &dyn I32Iterator = &vec![42].into_iter(); - | ^^^^^^^^^^^^^^^^^^^^^ expected u32, found i32 + | ^^^^^^^^^^^^^^^^^^^^^ expected i32, found u32 | - = note: expected type `u32` - found type `i32` + = note: expected type `i32` + found type `u32` = note: required for the cast to the object type `dyn std::iter::Iterator` error: aborting due to previous error diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr index a9b0e7ae7795d..6bef9dca265e7 100644 --- a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr +++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr @@ -33,10 +33,10 @@ error[E0271]: type mismatch resolving ` $DIR/async-block-control-flow-static-semantics.rs:18:39 | LL | let _: &dyn Future = █ - | ^^^^^^ expected u8, found () + | ^^^^^^ expected (), found u8 | - = note: expected type `u8` - found type `()` + = note: expected type `()` + found type `u8` = note: required for the cast to the object type `dyn std::future::Future` error[E0308]: mismatched types @@ -59,10 +59,10 @@ error[E0271]: type mismatch resolving ` $DIR/async-block-control-flow-static-semantics.rs:27:39 | LL | let _: &dyn Future = █ - | ^^^^^^ expected u8, found () + | ^^^^^^ expected (), found u8 | - = note: expected type `u8` - found type `()` + = note: expected type `()` + found type `u8` = note: required for the cast to the object type `dyn std::future::Future` error[E0308]: mismatched types diff --git a/src/test/ui/async-await/try-on-option-in-async.rs b/src/test/ui/async-await/try-on-option-in-async.rs new file mode 100644 index 0000000000000..51ac522017cb3 --- /dev/null +++ b/src/test/ui/async-await/try-on-option-in-async.rs @@ -0,0 +1,27 @@ +#![feature(try_trait, async_closure)] +// edition:2018 +fn main() {} + +async fn an_async_block() -> u32 { + async { + let x: Option = None; + x?; //~ ERROR the `?` operator + 22 + }.await +} + +async fn async_closure_containing_fn() -> u32 { + let async_closure = async || { + let x: Option = None; + x?; //~ ERROR the `?` operator + 22_u32 + }; + + async_closure().await +} + +async fn an_async_function() -> u32 { + let x: Option = None; + x?; //~ ERROR the `?` operator + 22 +} diff --git a/src/test/ui/async-await/try-on-option-in-async.stderr b/src/test/ui/async-await/try-on-option-in-async.stderr new file mode 100644 index 0000000000000..7d31f60efdc6a --- /dev/null +++ b/src/test/ui/async-await/try-on-option-in-async.stderr @@ -0,0 +1,30 @@ +error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `std::ops::Try`) + --> $DIR/try-on-option-in-async.rs:8:9 + | +LL | x?; + | ^^ cannot use the `?` operator in an async block that returns `{integer}` + | + = help: the trait `std::ops::Try` is not implemented for `{integer}` + = note: required by `std::ops::Try::from_error` + +error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `std::ops::Try`) + --> $DIR/try-on-option-in-async.rs:16:9 + | +LL | x?; + | ^^ cannot use the `?` operator in an async closure that returns `u32` + | + = help: the trait `std::ops::Try` is not implemented for `u32` + = note: required by `std::ops::Try::from_error` + +error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `std::ops::Try`) + --> $DIR/try-on-option-in-async.rs:25:5 + | +LL | x?; + | ^^ cannot use the `?` operator in an async function that returns `u32` + | + = help: the trait `std::ops::Try` is not implemented for `u32` + = note: required by `std::ops::Try::from_error` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/close-over-big-then-small-data.rs b/src/test/ui/close-over-big-then-small-data.rs index 40e5f500df4a8..4d6edf4ecb0f3 100644 --- a/src/test/ui/close-over-big-then-small-data.rs +++ b/src/test/ui/close-over-big-then-small-data.rs @@ -30,7 +30,7 @@ fn f(a: A, b: u16) -> Box+'static> { box Invoker { a: a, b: b, - } as (Box+'static>) + } as Box+'static> } pub fn main() { diff --git a/src/test/ui/cross-crate/issue-64872/auxiliary/a_def_obj.rs b/src/test/ui/cross-crate/issue-64872/auxiliary/a_def_obj.rs new file mode 100644 index 0000000000000..82bb95f1ef2b3 --- /dev/null +++ b/src/test/ui/cross-crate/issue-64872/auxiliary/a_def_obj.rs @@ -0,0 +1,16 @@ +// compile-flags: -C debuginfo=2 + +// no-prefer-dynamic +#![crate_type = "rlib"] + +pub trait Object { fn method(&self) { } } + +impl Object for u32 { } +impl Object for () { } +impl Object for &T { } + +pub fn unused() { + let ref u = 0_u32; + let _d = &u as &dyn crate::Object; + _d.method() +} diff --git a/src/test/ui/cross-crate/issue-64872/auxiliary/b_reexport_obj.rs b/src/test/ui/cross-crate/issue-64872/auxiliary/b_reexport_obj.rs new file mode 100644 index 0000000000000..21c0274b991fc --- /dev/null +++ b/src/test/ui/cross-crate/issue-64872/auxiliary/b_reexport_obj.rs @@ -0,0 +1,7 @@ +// compile-flags: -C debuginfo=2 -C prefer-dynamic + +#![crate_type="dylib"] + +extern crate a_def_obj; + +pub use a_def_obj::Object; diff --git a/src/test/ui/cross-crate/issue-64872/auxiliary/c_another_vtable_for_obj.rs b/src/test/ui/cross-crate/issue-64872/auxiliary/c_another_vtable_for_obj.rs new file mode 100644 index 0000000000000..611238f56173a --- /dev/null +++ b/src/test/ui/cross-crate/issue-64872/auxiliary/c_another_vtable_for_obj.rs @@ -0,0 +1,12 @@ +// no-prefer-dynamic +// compile-flags: -C debuginfo=2 +#![crate_type="rlib"] + +extern crate b_reexport_obj; +use b_reexport_obj::Object; + +pub fn another_dyn_debug() { + let ref u = 1_u32; + let _d = &u as &dyn crate::Object; + _d.method() +} diff --git a/src/test/ui/cross-crate/issue-64872/auxiliary/d_chain_of_rlibs_and_dylibs.rs b/src/test/ui/cross-crate/issue-64872/auxiliary/d_chain_of_rlibs_and_dylibs.rs new file mode 100644 index 0000000000000..8d73f9b666f1e --- /dev/null +++ b/src/test/ui/cross-crate/issue-64872/auxiliary/d_chain_of_rlibs_and_dylibs.rs @@ -0,0 +1,9 @@ +// compile-flags: -C debuginfo=2 -C prefer-dynamic + +#![crate_type="rlib"] + +extern crate c_another_vtable_for_obj; + +pub fn chain() { + c_another_vtable_for_obj::another_dyn_debug(); +} diff --git a/src/test/ui/cross-crate/issue-64872/issue-64872.rs b/src/test/ui/cross-crate/issue-64872/issue-64872.rs new file mode 100644 index 0000000000000..20fe2053cc7c3 --- /dev/null +++ b/src/test/ui/cross-crate/issue-64872/issue-64872.rs @@ -0,0 +1,17 @@ +// run-pass + +// note that these aux-build directives must be in this order: the +// later crates depend on the earlier ones. (The particular bug that +// is being exercised here used to exhibit itself during the build of +// `chain_of_rlibs_and_dylibs.dylib`) + +// aux-build:a_def_obj.rs +// aux-build:b_reexport_obj.rs +// aux-build:c_another_vtable_for_obj.rs +// aux-build:d_chain_of_rlibs_and_dylibs.rs + +extern crate d_chain_of_rlibs_and_dylibs; + +pub fn main() { + d_chain_of_rlibs_and_dylibs::chain(); +} diff --git a/src/test/ui/error-codes/E0271.stderr b/src/test/ui/error-codes/E0271.stderr index c56853f45a0b0..378e5e3630641 100644 --- a/src/test/ui/error-codes/E0271.stderr +++ b/src/test/ui/error-codes/E0271.stderr @@ -5,10 +5,10 @@ LL | fn foo(t: T) where T: Trait { | --- ------------------ required by this bound in `foo` ... LL | foo(3_i8); - | ^^^ expected reference, found u32 + | ^^^ expected u32, found reference | - = note: expected type `&'static str` - found type `u32` + = note: expected type `u32` + found type `&'static str` error: aborting due to previous error diff --git a/src/test/ui/functions-closures/closure-to-fn-coercion.rs b/src/test/ui/functions-closures/closure-to-fn-coercion.rs index 4f43c2bb53847..87ba488b5aef2 100644 --- a/src/test/ui/functions-closures/closure-to-fn-coercion.rs +++ b/src/test/ui/functions-closures/closure-to-fn-coercion.rs @@ -10,7 +10,7 @@ const BAR: [fn(&mut u32); 5] = [ |v: &mut u32| *v += 3, |v: &mut u32| *v += 4, ]; -fn func_specific() -> (fn() -> u32) { +fn func_specific() -> fn() -> u32 { || return 42 } diff --git a/src/test/ui/invalid/invalid-variadic-function.stderr b/src/test/ui/invalid/invalid-variadic-function.stderr index b2dbf8b919084..fd20bd84edc46 100644 --- a/src/test/ui/invalid/invalid-variadic-function.stderr +++ b/src/test/ui/invalid/invalid-variadic-function.stderr @@ -1,4 +1,4 @@ -error: only foreign functions are allowed to be C-variadic +error[E0743]: only foreign functions are allowed to be C-variadic --> $DIR/invalid-variadic-function.rs:1:26 | LL | extern "C" fn foo(x: u8, ...); @@ -12,3 +12,4 @@ LL | extern "C" fn foo(x: u8, ...); error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0743`. diff --git a/src/test/ui/issues/issue-24204.stderr b/src/test/ui/issues/issue-24204.stderr index 9658f6980be2f..9c53c1b86ceaf 100644 --- a/src/test/ui/issues/issue-24204.stderr +++ b/src/test/ui/issues/issue-24204.stderr @@ -5,10 +5,10 @@ LL | trait Trait: Sized { | ------------------ required by `Trait` ... LL | fn test>(b: i32) -> T where T::A: MultiDispatch { T::new(b) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found type parameter + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found associated type | - = note: expected type `<::A as MultiDispatch>::O` - found type `T` + = note: expected type `T` + found type `<::A as MultiDispatch>::O` = note: you might be missing a type parameter or trait bound error: aborting due to previous error diff --git a/src/test/ui/lint/lint-unnecessary-parens.rs b/src/test/ui/lint/lint-unnecessary-parens.rs index 811bc87eb0e2e..9f42b855a870d 100644 --- a/src/test/ui/lint/lint-unnecessary-parens.rs +++ b/src/test/ui/lint/lint-unnecessary-parens.rs @@ -13,6 +13,18 @@ fn bar(y: bool) -> X { return (X { y }); //~ ERROR unnecessary parentheses around `return` value } +fn unused_parens_around_return_type() -> (u32) { //~ ERROR unnecessary parentheses around type + panic!() +} + +trait Trait { + fn test(&self); +} + +fn passes_unused_parens_lint() -> &'static (dyn Trait) { + panic!() +} + fn main() { foo(); bar((true)); //~ ERROR unnecessary parentheses around function argument diff --git a/src/test/ui/lint/lint-unnecessary-parens.stderr b/src/test/ui/lint/lint-unnecessary-parens.stderr index 83b247a4a6053..adc1069b64d62 100644 --- a/src/test/ui/lint/lint-unnecessary-parens.stderr +++ b/src/test/ui/lint/lint-unnecessary-parens.stderr @@ -16,26 +16,32 @@ error: unnecessary parentheses around `return` value LL | return (X { y }); | ^^^^^^^^^ help: remove these parentheses +error: unnecessary parentheses around type + --> $DIR/lint-unnecessary-parens.rs:16:42 + | +LL | fn unused_parens_around_return_type() -> (u32) { + | ^^^^^ help: remove these parentheses + error: unnecessary parentheses around function argument - --> $DIR/lint-unnecessary-parens.rs:18:9 + --> $DIR/lint-unnecessary-parens.rs:30:9 | LL | bar((true)); | ^^^^^^ help: remove these parentheses error: unnecessary parentheses around `if` condition - --> $DIR/lint-unnecessary-parens.rs:20:8 + --> $DIR/lint-unnecessary-parens.rs:32:8 | LL | if (true) {} | ^^^^^^ help: remove these parentheses error: unnecessary parentheses around `while` condition - --> $DIR/lint-unnecessary-parens.rs:21:11 + --> $DIR/lint-unnecessary-parens.rs:33:11 | LL | while (true) {} | ^^^^^^ help: remove these parentheses warning: denote infinite loops with `loop { ... }` - --> $DIR/lint-unnecessary-parens.rs:21:5 + --> $DIR/lint-unnecessary-parens.rs:33:5 | LL | while (true) {} | ^^^^^^^^^^^^ help: use `loop` @@ -43,46 +49,46 @@ LL | while (true) {} = note: `#[warn(while_true)]` on by default error: unnecessary parentheses around `match` head expression - --> $DIR/lint-unnecessary-parens.rs:23:11 + --> $DIR/lint-unnecessary-parens.rs:35:11 | LL | match (true) { | ^^^^^^ help: remove these parentheses error: unnecessary parentheses around `let` head expression - --> $DIR/lint-unnecessary-parens.rs:26:16 + --> $DIR/lint-unnecessary-parens.rs:38:16 | LL | if let 1 = (1) {} | ^^^ help: remove these parentheses error: unnecessary parentheses around `let` head expression - --> $DIR/lint-unnecessary-parens.rs:27:19 + --> $DIR/lint-unnecessary-parens.rs:39:19 | LL | while let 1 = (2) {} | ^^^ help: remove these parentheses error: unnecessary parentheses around method argument - --> $DIR/lint-unnecessary-parens.rs:41:24 + --> $DIR/lint-unnecessary-parens.rs:53:24 | LL | X { y: false }.foo((true)); | ^^^^^^ help: remove these parentheses error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:43:18 + --> $DIR/lint-unnecessary-parens.rs:55:18 | LL | let mut _a = (0); | ^^^ help: remove these parentheses error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:44:10 + --> $DIR/lint-unnecessary-parens.rs:56:10 | LL | _a = (0); | ^^^ help: remove these parentheses error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:45:11 + --> $DIR/lint-unnecessary-parens.rs:57:11 | LL | _a += (1); | ^^^ help: remove these parentheses -error: aborting due to 12 previous errors +error: aborting due to 13 previous errors diff --git a/src/test/ui/parser/variadic-ffi-3.stderr b/src/test/ui/parser/variadic-ffi-3.stderr index 8ea4d194396fa..aeeebdb991483 100644 --- a/src/test/ui/parser/variadic-ffi-3.stderr +++ b/src/test/ui/parser/variadic-ffi-3.stderr @@ -1,4 +1,4 @@ -error: only foreign functions are allowed to be C-variadic +error[E0743]: only foreign functions are allowed to be C-variadic --> $DIR/variadic-ffi-3.rs:1:18 | LL | fn foo(x: isize, ...) { @@ -6,3 +6,4 @@ LL | fn foo(x: isize, ...) { error: aborting due to previous error +For more information about this error, try `rustc --explain E0743`. diff --git a/src/test/ui/parser/variadic-ffi-4.stderr b/src/test/ui/parser/variadic-ffi-4.stderr index 69fbf84869c13..da83276c72dd1 100644 --- a/src/test/ui/parser/variadic-ffi-4.stderr +++ b/src/test/ui/parser/variadic-ffi-4.stderr @@ -1,4 +1,4 @@ -error: only foreign functions are allowed to be C-variadic +error[E0743]: only foreign functions are allowed to be C-variadic --> $DIR/variadic-ffi-4.rs:1:29 | LL | extern "C" fn foo(x: isize, ...) { @@ -6,3 +6,4 @@ LL | extern "C" fn foo(x: isize, ...) { error: aborting due to previous error +For more information about this error, try `rustc --explain E0743`. diff --git a/src/test/ui/privacy/private-in-public-warn.stderr b/src/test/ui/privacy/private-in-public-warn.stderr index 9741f3b6d0d41..40aa47a7246c4 100644 --- a/src/test/ui/privacy/private-in-public-warn.stderr +++ b/src/test/ui/privacy/private-in-public-warn.stderr @@ -340,7 +340,10 @@ LL | pub type Alias = T; | ^^^^^^ | = note: `#[warn(type_alias_bounds)]` on by default - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | pub type Alias = T; + | -- warning: where clauses are not enforced in type aliases --> $DIR/private-in-public-warn.rs:75:29 @@ -348,7 +351,10 @@ warning: where clauses are not enforced in type aliases LL | pub type Alias where T: PrivTr = T; | ^^^^^^^^^ | - = help: the clause will not be checked when the type alias is used, and should be removed +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | pub type Alias = T; + | -- error: aborting due to 36 previous errors diff --git a/src/test/ui/resolve/visibility-indeterminate.stderr b/src/test/ui/resolve/visibility-indeterminate.stderr index b9678291ee40b..84d82ce852240 100644 --- a/src/test/ui/resolve/visibility-indeterminate.stderr +++ b/src/test/ui/resolve/visibility-indeterminate.stderr @@ -12,3 +12,4 @@ LL | foo!(); error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0578`. diff --git a/src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed b/src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed index 89607af260a52..0f26a975a370f 100644 --- a/src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed +++ b/src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed @@ -15,7 +15,7 @@ fn october<'b, T>(s: &'b T) -> &'b T { s } -fn november<'a>(s: &'a str) -> (&'a str) { +fn november<'a>(s: &'a str) -> &'a str { //~^ ERROR lifetime parameter `'b` never used //~| HELP elide the unused lifetime s diff --git a/src/test/ui/single-use-lifetime/zero-uses-in-fn.rs b/src/test/ui/single-use-lifetime/zero-uses-in-fn.rs index be0bdb9b62851..7f9504fe5a90a 100644 --- a/src/test/ui/single-use-lifetime/zero-uses-in-fn.rs +++ b/src/test/ui/single-use-lifetime/zero-uses-in-fn.rs @@ -15,7 +15,7 @@ fn october<'a, 'b, T>(s: &'b T) -> &'b T { s } -fn november<'a, 'b>(s: &'a str) -> (&'a str) { +fn november<'a, 'b>(s: &'a str) -> &'a str { //~^ ERROR lifetime parameter `'b` never used //~| HELP elide the unused lifetime s diff --git a/src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr b/src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr index 2ccba796d4229..b9c3bd89748ff 100644 --- a/src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr +++ b/src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr @@ -21,7 +21,7 @@ LL | fn october<'a, 'b, T>(s: &'b T) -> &'b T { error: lifetime parameter `'b` never used --> $DIR/zero-uses-in-fn.rs:18:17 | -LL | fn november<'a, 'b>(s: &'a str) -> (&'a str) { +LL | fn november<'a, 'b>(s: &'a str) -> &'a str { | --^^ | | | help: elide the unused lifetime diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.stderr index 0eb0769c57071..cb8bad6d9e74d 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.stderr @@ -31,7 +31,10 @@ LL | type Y where i32: Foo = (); | ^^^^^^^^ | = note: `#[warn(type_alias_bounds)]` on by default - = help: the clause will not be checked when the type alias is used, and should be removed +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | type Y = (); + | -- warning: Trait bound i32: Foo does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent.rs:22:19 diff --git a/src/test/ui/try-on-option-diagnostics.rs b/src/test/ui/try-on-option-diagnostics.rs new file mode 100644 index 0000000000000..65d5e29ec2f13 --- /dev/null +++ b/src/test/ui/try-on-option-diagnostics.rs @@ -0,0 +1,18 @@ +#![feature(try_trait)] +// edition:2018 +fn main() {} + +fn a_function() -> u32 { + let x: Option = None; + x?; //~ ERROR the `?` operator + 22 +} + +fn a_closure() -> u32 { + let a_closure = || { + let x: Option = None; + x?; //~ ERROR the `?` operator + 22 + }; + a_closure() +} diff --git a/src/test/ui/try-on-option-diagnostics.stderr b/src/test/ui/try-on-option-diagnostics.stderr new file mode 100644 index 0000000000000..4dd515e1b5a45 --- /dev/null +++ b/src/test/ui/try-on-option-diagnostics.stderr @@ -0,0 +1,21 @@ +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`) + --> $DIR/try-on-option-diagnostics.rs:7:5 + | +LL | x?; + | ^^ cannot use the `?` operator in a function that returns `u32` + | + = help: the trait `std::ops::Try` is not implemented for `u32` + = note: required by `std::ops::Try::from_error` + +error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `std::ops::Try`) + --> $DIR/try-on-option-diagnostics.rs:14:9 + | +LL | x?; + | ^^ cannot use the `?` operator in a closure that returns `{integer}` + | + = help: the trait `std::ops::Try` is not implemented for `{integer}` + = note: required by `std::ops::Try::from_error` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type/type-alias-bounds.stderr b/src/test/ui/type/type-alias-bounds.stderr index dbb7b92563ab8..c381d30c64f14 100644 --- a/src/test/ui/type/type-alias-bounds.stderr +++ b/src/test/ui/type/type-alias-bounds.stderr @@ -5,7 +5,10 @@ LL | type SVec = Vec; | ^^^^ ^^^^ | = note: `#[warn(type_alias_bounds)]` on by default - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type SVec = Vec; + | -- -- warning: where clauses are not enforced in type aliases --> $DIR/type-alias-bounds.rs:10:21 @@ -13,7 +16,10 @@ warning: where clauses are not enforced in type aliases LL | type S2Vec where T: Send = Vec; | ^^^^^^^ | - = help: the clause will not be checked when the type alias is used, and should be removed +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | type S2Vec = Vec; + | -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias-bounds.rs:12:19 @@ -21,7 +27,10 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type VVec<'b, 'a: 'b + 'b> = (&'b u32, Vec<&'a i32>); | ^^ ^^ | - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type VVec<'b, 'a> = (&'b u32, Vec<&'a i32>); + | -- -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias-bounds.rs:14:18 @@ -29,7 +38,10 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type WVec<'b, T: 'b + 'b> = (&'b u32, Vec); | ^^ ^^ | - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type WVec<'b, T> = (&'b u32, Vec); + | -- -- warning: where clauses are not enforced in type aliases --> $DIR/type-alias-bounds.rs:16:25 @@ -37,7 +49,10 @@ warning: where clauses are not enforced in type aliases LL | type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec); | ^^^^^ ^^^^^ | - = help: the clause will not be checked when the type alias is used, and should be removed +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | type W2Vec<'b, T> = (&'b u32, Vec); + | -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias-bounds.rs:47:12 @@ -45,12 +60,15 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type T1 = U::Assoc; | ^^^^^ | - = help: the bound will not be checked when the type alias is used, and should be removed help: use fully disambiguated paths (i.e., `::Assoc`) to refer to associated types in type aliases --> $DIR/type-alias-bounds.rs:47:21 | LL | type T1 = U::Assoc; | ^^^^^^^^ +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type T1 = U::Assoc; + | -- warning: where clauses are not enforced in type aliases --> $DIR/type-alias-bounds.rs:48:18 @@ -58,12 +76,15 @@ warning: where clauses are not enforced in type aliases LL | type T2 where U: Bound = U::Assoc; | ^^^^^^^^ | - = help: the clause will not be checked when the type alias is used, and should be removed help: use fully disambiguated paths (i.e., `::Assoc`) to refer to associated types in type aliases --> $DIR/type-alias-bounds.rs:48:29 | LL | type T2 where U: Bound = U::Assoc; | ^^^^^^^^ +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | type T2 = U::Assoc; + | -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias-bounds.rs:56:12 @@ -71,7 +92,10 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type T5 = ::Assoc; | ^^^^^ | - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type T5 = ::Assoc; + | -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias-bounds.rs:57:12 @@ -79,5 +103,8 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type T6 = ::std::vec::Vec; | ^^^^^ | - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type T6 = ::std::vec::Vec; + | -- diff --git a/src/tools/tidy/src/error_codes_check.rs b/src/tools/tidy/src/error_codes_check.rs index 159baff184d1b..bd58de81c778a 100644 --- a/src/tools/tidy/src/error_codes_check.rs +++ b/src/tools/tidy/src/error_codes_check.rs @@ -40,7 +40,6 @@ const WHITELIST: &[&str] = &[ "E0514", "E0519", "E0523", - "E0526", "E0554", "E0570", "E0629",