diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index d508616e4b1cc..c805522fbf588 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -46,24 +46,32 @@ pub fn install(build: &Build, stage: u32, host: &str) { let empty_dir = build.out.join("tmp/empty_dir"); t!(fs::create_dir_all(&empty_dir)); if build.config.docs { - install_sh(&build, "docs", "rust-docs", stage, host, &prefix, - &docdir, &libdir, &mandir, &empty_dir); + install_sh(&build, "docs", "rust-docs", &build.rust_package_vers(), + stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir); } for target in build.config.target.iter() { - install_sh(&build, "std", "rust-std", stage, target, &prefix, - &docdir, &libdir, &mandir, &empty_dir); + install_sh(&build, "std", "rust-std", &build.rust_package_vers(), + stage, target, &prefix, &docdir, &libdir, &mandir, &empty_dir); } - install_sh(&build, "rustc", "rustc", stage, host, &prefix, - &docdir, &libdir, &mandir, &empty_dir); + if build.config.extended { + install_sh(&build, "cargo", "cargo", &build.cargo_package_vers(), + stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir); + install_sh(&build, "rls", "rls", &build.rls_package_vers(), + stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir); + } + + install_sh(&build, "rustc", "rustc", &build.rust_package_vers(), + stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir); + t!(fs::remove_dir_all(&empty_dir)); } -fn install_sh(build: &Build, package: &str, name: &str, stage: u32, host: &str, +fn install_sh(build: &Build, package: &str, name: &str, version: &str, stage: u32, host: &str, prefix: &Path, docdir: &Path, libdir: &Path, mandir: &Path, empty_dir: &Path) { println!("Install {} stage{} ({})", package, stage, host); - let package_name = format!("{}-{}-{}", name, build.rust_package_vers(), host); + let package_name = format!("{}-{}-{}", name, version, host); let mut cmd = Command::new("sh"); cmd.current_dir(empty_dir) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index bbfab38895004..43726ea1c43a7 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -1048,6 +1048,11 @@ impl Build { self.package_vers(&self.release_num("cargo")) } + /// Returns the value of `package_vers` above for rls + fn rls_package_vers(&self) -> String { + self.package_vers(&self.release_num("rls")) + } + /// Returns the `version` string associated with this compiler for Rust /// itself. /// diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index d811e1122c42f..35e1b9c677614 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -575,6 +575,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .dep(|s| s.name("libstd-tool")) .run(move |s| compile::tool(build, s.stage, s.target, "qemu-test-client")); rules.build("tool-cargo", "cargo") + .default(build.config.extended) .dep(|s| s.name("maybe-clean-tools")) .dep(|s| s.name("libstd-tool")) .dep(|s| s.stage(0).host(s.target).name("openssl")) @@ -588,6 +589,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .run(move |s| compile::tool(build, s.stage, s.target, "cargo")); rules.build("tool-rls", "rls") .host(true) + .default(build.config.extended) .dep(|s| s.name("librustc-tool")) .dep(|s| s.stage(0).host(s.target).name("openssl")) .dep(move |s| { diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 60171f1a4289a..0358319256760 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -22,7 +22,7 @@ // are *mostly* used as a part of that interface, but these should // probably get a better home if someone can find one. -use hir::def::{self, Def}; +use hir::def; use hir::def_id::{CrateNum, DefId, DefIndex}; use hir::map as hir_map; use hir::map::definitions::{Definitions, DefKey, DisambiguatedDefPathData}; @@ -181,7 +181,6 @@ pub trait CrateStore { fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc; // item info - fn describe_def(&self, def: DefId) -> Option; fn def_span(&self, sess: &Session, def: DefId) -> Span; fn stability(&self, def: DefId) -> Option; fn deprecation(&self, def: DefId) -> Option; @@ -313,7 +312,6 @@ impl CrateStore for DummyCrateStore { fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc { bug!("crate_data_as_rc_any") } // item info - fn describe_def(&self, def: DefId) -> Option { bug!("describe_def") } fn def_span(&self, sess: &Session, def: DefId) -> Span { bug!("def_span") } fn stability(&self, def: DefId) -> Option { bug!("stability") } fn deprecation(&self, def: DefId) -> Option { bug!("deprecation") } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 677eca10d7bae..9db6dffb0e8cc 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -451,7 +451,10 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // So peel off one-level, turning the &T into T. match base_ty.builtin_deref(false, ty::NoPreference) { Some(t) => t.ty, - None => { return Err(()); } + None => { + debug!("By-ref binding of non-derefable type {:?}", base_ty); + return Err(()); + } } } _ => base_ty, @@ -1039,6 +1042,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { match base_cmt.ty.builtin_index() { Some(ty) => (ty, ElementKind::VecElement), None => { + debug!("Explicit index of non-indexable type {:?}", base_cmt); return Err(()); } } @@ -1154,7 +1158,10 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) | PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => { match path.def { - Def::Err => return Err(()), + Def::Err => { + debug!("access to unresolvable pattern {:?}", pat); + return Err(()) + } Def::Variant(variant_did) | Def::VariantCtor(variant_did, ..) => { // univariant enums do not need downcasts diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 7431eb3fe96ef..1ac7f4fcc95c2 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -432,7 +432,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // (See issue #38412) fn skip_stability_check_due_to_privacy(self, mut def_id: DefId) -> bool { // Check if `def_id` is a trait method. - match self.sess.cstore.describe_def(def_id) { + match self.describe_def(def_id) { Some(Def::Method(_)) | Some(Def::AssociatedTy(_)) | Some(Def::AssociatedConst(_)) => { diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index c80ae87d941ff..096d69aa3760a 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -10,6 +10,7 @@ use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig}; use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use hir::def::Def; use hir; use middle::const_val; use middle::privacy::AccessLevels; @@ -264,6 +265,12 @@ impl<'tcx> QueryDescription for queries::symbol_name<'tcx> { } } +impl<'tcx> QueryDescription for queries::describe_def<'tcx> { + fn describe(_: TyCtxt, _: DefId) -> String { + bug!("describe_def") + } +} + macro_rules! define_maps { (<$tcx:tt> $($(#[$attr:meta])* @@ -538,7 +545,9 @@ define_maps! { <'tcx> pub mir_shims: mir_shim_dep_node(ty::InstanceDef<'tcx>) -> &'tcx RefCell>, pub def_symbol_name: SymbolName(DefId) -> ty::SymbolName, - pub symbol_name: symbol_name_dep_node(ty::Instance<'tcx>) -> ty::SymbolName + pub symbol_name: symbol_name_dep_node(ty::Instance<'tcx>) -> ty::SymbolName, + + pub describe_def: meta_data_node(DefId) -> Option } fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode { @@ -570,3 +579,7 @@ fn typeck_item_bodies_dep_node(_: CrateNum) -> DepNode { fn const_eval_dep_node((def_id, _): (DefId, &Substs)) -> DepNode { DepNode::ConstEval(def_id) } + +fn meta_data_node(def_id: DefId) -> DepNode { + DepNode::MetaData(def_id) +} \ No newline at end of file diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index de207df7d15eb..238791fb6edb3 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2385,7 +2385,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// ID of the impl that the method belongs to. Otherwise, return `None`. pub fn impl_of_method(self, def_id: DefId) -> Option { let item = if def_id.krate != LOCAL_CRATE { - if let Some(Def::Method(_)) = self.sess.cstore.describe_def(def_id) { + if let Some(Def::Method(_)) = self.describe_def(def_id) { Some(self.associated_item(def_id)) } else { None diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index 3678c2e55c1fd..ebe2de5840954 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -11,6 +11,7 @@ use borrowck::BorrowckCtxt; use rustc::middle::mem_categorization as mc; use rustc::middle::mem_categorization::Categorization; +use rustc::middle::mem_categorization::NoteClosureEnv; use rustc::middle::mem_categorization::InteriorOffsetKind as Kind; use rustc::ty; use syntax::ast; @@ -71,10 +72,12 @@ fn report_move_errors<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, let mut err = report_cannot_move_out_of(bccx, error.move_from.clone()); let mut is_first_note = true; for move_to in &error.move_to_places { - err = note_move_destination(err, move_to.span, - move_to.name, is_first_note); + err = note_move_destination(err, move_to.span, move_to.name, is_first_note); is_first_note = false; } + if let NoteClosureEnv(upvar_id) = error.move_from.note { + err.span_label(bccx.tcx.hir.span(upvar_id.var_id), &"captured outer variable"); + } err.emit(); } } diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 9470316c7e7e0..8b1aa0708807b 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -68,7 +68,7 @@ pub fn lookup_const_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _ => Some((def_id, substs)) } } else { - match tcx.sess.cstore.describe_def(def_id) { + match tcx.describe_def(def_id) { Some(Def::AssociatedConst(_)) => { // As mentioned in the comments above for in-crate // constants, we only try to find the expression for a diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index da29e354a7014..cc8012d965a76 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -375,6 +375,9 @@ impl Handler { panic!(ExplicitBug); } pub fn delay_span_bug>(&self, sp: S, msg: &str) { + if self.treat_err_as_bug { + self.span_bug(sp, msg); + } let mut delayed = self.delayed_span_bug.borrow_mut(); *delayed = Some((sp.into(), msg.to_string())); } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index ddb3332be3731..839caca2ee914 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -17,7 +17,7 @@ use rustc::dep_graph::DepTrackingMapConfig; use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind, ExternCrate, NativeLibrary, LinkMeta, LinkagePreference, LoadedMacro, EncodedMetadata}; -use rustc::hir::def::{self, Def}; +use rustc::hir::def; use rustc::middle::lang_items; use rustc::session::Session; use rustc::ty::{self, TyCtxt}; @@ -113,6 +113,7 @@ provide! { <'tcx> tcx, def_id, cdata closure_type => { cdata.closure_ty(def_id.index, tcx) } inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) } is_foreign_item => { cdata.is_foreign_item(def_id.index) } + describe_def => { cdata.get_def(def_id.index) } } impl CrateStore for cstore::CStore { @@ -120,11 +121,6 @@ impl CrateStore for cstore::CStore { self.get_crate_data(krate) } - fn describe_def(&self, def: DefId) -> Option { - self.dep_graph.read(DepNode::MetaData(def)); - self.get_crate_data(def.krate).get_def(def.index) - } - fn def_span(&self, sess: &Session, def: DefId) -> Span { self.dep_graph.read(DepNode::MetaData(def)); self.get_crate_data(def.krate).get_span(def.index, sess) diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index a38840552c23c..2e84aff49859d 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -788,16 +788,18 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait", trait_c.name); - // Add a label to the Span containing just the type of the item - let trait_c_node_id = tcx.hir.as_local_node_id(trait_c.def_id).unwrap(); - let trait_c_span = match tcx.hir.expect_trait_item(trait_c_node_id).node { - TraitItemKind::Const(ref ty, _) => ty.span, - _ => bug!("{:?} is not a trait const", trait_c), - }; + let trait_c_node_id = tcx.hir.as_local_node_id(trait_c.def_id); + let trait_c_span = trait_c_node_id.map(|trait_c_node_id| { + // Add a label to the Span containing just the type of the const + match tcx.hir.expect_trait_item(trait_c_node_id).node { + TraitItemKind::Const(ref ty, _) => ty.span, + _ => bug!("{:?} is not a trait const", trait_c), + } + }); infcx.note_type_err(&mut diag, &cause, - Some((trait_c_span, format!("type in trait"))), + trait_c_span.map(|span| (span, format!("type in trait"))), Some(infer::ValuePairs::Types(ExpectedFound { expected: trait_ty, found: impl_ty, diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index f0a74ea4be92c..e81805b96609b 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -516,6 +516,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { }; let index_expr_ty = self.node_ty(index_expr.id); + let adjusted_base_ty = self.resolve_type_vars_if_possible(&adjusted_base_ty); + let index_expr_ty = self.resolve_type_vars_if_possible(&index_expr_ty); let result = self.try_index_step(ty::MethodCall::expr(expr.id), expr, @@ -531,6 +533,15 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { let expr_ty = self.node_ty(expr.id); self.demand_suptype(expr.span, expr_ty, return_ty); + } else { + // We could not perform a mutable index. Re-apply the + // immutable index adjustments - borrowck will detect + // this as an error. + if let Some(adjustment) = adjustment { + self.apply_adjustment(expr.id, adjustment); + } + self.tcx.sess.delay_span_bug( + expr.span, "convert_lvalue_derefs_to_mutable failed"); } } hir::ExprUnary(hir::UnDeref, ref base_expr) => { diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 8def11295fda8..34229f80769ab 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -72,24 +72,23 @@ pub struct TcpStream(net_imp::TcpStream); /// /// # Examples /// -/// ```no_run +/// ``` +/// # use std::io; /// use std::net::{TcpListener, TcpStream}; /// -/// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); -/// /// fn handle_client(stream: TcpStream) { /// // ... /// } /// +/// # fn process() -> io::Result<()> { +/// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); +/// /// // accept connections and process them serially /// for stream in listener.incoming() { -/// match stream { -/// Ok(stream) => { -/// handle_client(stream); -/// } -/// Err(e) => { /* connection failed */ } -/// } +/// handle_client(stream?); /// } +/// # Ok(()) +/// # } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct TcpListener(net_imp::TcpListener); diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 6c8839224f77d..2cb649ce67b9c 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -297,12 +297,14 @@ mod sync; mod mpsc_queue; mod spsc_queue; -/// The receiving-half of Rust's channel type. This half can only be owned by -/// one thread. +/// The receiving half of Rust's [`channel`][] (or [`sync_channel`]) type. +/// This half can only be owned by one thread. /// /// Messages sent to the channel can be retrieved using [`recv`]. /// -/// [`recv`]: ../../../std/sync/mpsc/struct.Receiver.html#method.recv +/// [`channel`]: fn.channel.html +/// [`sync_channel`]: fn.sync_channel.html +/// [`recv`]: struct.Receiver.html#method.recv /// /// # Examples /// @@ -336,51 +338,128 @@ unsafe impl Send for Receiver { } #[stable(feature = "rust1", since = "1.0.0")] impl !Sync for Receiver { } -/// An iterator over messages on a receiver, this iterator will block whenever -/// [`next`] is called, waiting for a new message, and [`None`] will be returned +/// An iterator over messages on a [`Receiver`], created by [`iter`]. +/// +/// This iterator will block whenever [`next`] is called, +/// waiting for a new message, and [`None`] will be returned /// when the corresponding channel has hung up. /// +/// [`iter`]: struct.Receiver.html#method.iter +/// [`Receiver`]: struct.Receiver.html /// [`next`]: ../../../std/iter/trait.Iterator.html#tymethod.next /// [`None`]: ../../../std/option/enum.Option.html#variant.None +/// +/// # Examples +/// +/// ```rust +/// use std::sync::mpsc::channel; +/// use std::thread; +/// +/// let (send, recv) = channel(); +/// +/// thread::spawn(move || { +/// send.send(1u8).unwrap(); +/// send.send(2u8).unwrap(); +/// send.send(3u8).unwrap(); +/// }); +/// +/// for x in recv.iter() { +/// println!("Got: {}", x); +/// } +/// ``` #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] pub struct Iter<'a, T: 'a> { rx: &'a Receiver } -/// An iterator that attempts to yield all pending values for a receiver. -/// [`None`] will be returned when there are no pending values remaining or if -/// the corresponding channel has hung up. +/// An iterator that attempts to yield all pending values for a [`Receiver`], +/// created by [`try_iter`]. +/// +/// [`None`] will be returned when there are no pending values remaining or +/// if the corresponding channel has hung up. /// -/// This Iterator will never block the caller in order to wait for data to +/// This iterator will never block the caller in order to wait for data to /// become available. Instead, it will return [`None`]. /// +/// [`Receiver`]: struct.Receiver.html +/// [`try_iter`]: struct.Receiver.html#method.try_iter /// [`None`]: ../../../std/option/enum.Option.html#variant.None +/// +/// # Examples +/// +/// ```rust +/// use std::sync::mpsc::channel; +/// use std::thread; +/// use std::time::Duration; +/// +/// let (sender, receiver) = channel(); +/// +/// // Nothing is in the buffer yet +/// assert!(receiver.try_iter().next().is_none()); +/// println!("Nothing in the buffer..."); +/// +/// thread::spawn(move || { +/// sender.send(1).unwrap(); +/// sender.send(2).unwrap(); +/// sender.send(3).unwrap(); +/// }); +/// +/// println!("Going to sleep..."); +/// thread::sleep(Duration::from_secs(2)); // block for two seconds +/// +/// for x in receiver.try_iter() { +/// println!("Got: {}", x); +/// } +/// ``` #[stable(feature = "receiver_try_iter", since = "1.15.0")] #[derive(Debug)] pub struct TryIter<'a, T: 'a> { rx: &'a Receiver } -/// An owning iterator over messages on a receiver, this iterator will block -/// whenever [`next`] is called, waiting for a new message, and [`None`] will be -/// returned when the corresponding channel has hung up. +/// An owning iterator over messages on a [`Receiver`], +/// created by **Receiver::into_iter**. +/// +/// This iterator will block whenever [`next`] +/// is called, waiting for a new message, and [`None`] will be +/// returned if the corresponding channel has hung up. /// +/// [`Receiver`]: struct.Receiver.html /// [`next`]: ../../../std/iter/trait.Iterator.html#tymethod.next /// [`None`]: ../../../std/option/enum.Option.html#variant.None /// +/// # Examples +/// +/// ```rust +/// use std::sync::mpsc::channel; +/// use std::thread; +/// +/// let (send, recv) = channel(); +/// +/// thread::spawn(move || { +/// send.send(1u8).unwrap(); +/// send.send(2u8).unwrap(); +/// send.send(3u8).unwrap(); +/// }); +/// +/// for x in recv.into_iter() { +/// println!("Got: {}", x); +/// } +/// ``` #[stable(feature = "receiver_into_iter", since = "1.1.0")] #[derive(Debug)] pub struct IntoIter { rx: Receiver } -/// The sending-half of Rust's asynchronous channel type. This half can only be +/// The sending-half of Rust's asynchronous [`channel`] type. This half can only be /// owned by one thread, but it can be cloned to send to other threads. /// /// Messages can be sent through this channel with [`send`]. /// -/// [`send`]: ../../../std/sync/mpsc/struct.Sender.html#method.send +/// [`channel`]: fn.channel.html +/// [`send`]: struct.Sender.html#method.send /// /// # Examples /// @@ -419,12 +498,55 @@ unsafe impl Send for Sender { } #[stable(feature = "rust1", since = "1.0.0")] impl !Sync for Sender { } -/// The sending-half of Rust's synchronous channel type. This half can only be -/// owned by one thread, but it can be cloned to send to other threads. +/// The sending-half of Rust's synchronous [`sync_channel`] type. +/// This half can only be owned by one thread, but it can be cloned +/// to send to other threads. +/// +/// Messages can be sent through this channel with [`send`] or [`try_send`]. +/// +/// [`send`] will block if there is no space in the internal buffer. +/// +/// [`sync_channel`]: fn.sync_channel.html +/// [`send`]: struct.SyncSender.html#method.send +/// [`try_send`]: struct.SyncSender.html#method.try_send +/// +/// # Examples +/// +/// ```rust +/// use std::sync::mpsc::sync_channel; +/// use std::thread; /// -/// [`send`]: ../../../std/sync/mpsc/struct.Sender.html#method.send -/// [`SyncSender::send`]: ../../../std/sync/mpsc/struct.SyncSender.html#method.send +/// // Create a sync_channel with buffer size 2 +/// let (sync_sender, receiver) = sync_channel(2); +/// let sync_sender2 = sync_sender.clone(); /// +/// // First thread owns sync_sender +/// thread::spawn(move || { +/// sync_sender.send(1).unwrap(); +/// sync_sender.send(2).unwrap(); +/// }); +/// +/// // Second thread owns sync_sender2 +/// thread::spawn(move || { +/// sync_sender2.send(3).unwrap(); +/// // thread will now block since the buffer is full +/// println!("Thread unblocked!"); +/// }); +/// +/// let mut msg; +/// +/// msg = receiver.recv().unwrap(); +/// println!("message {} received", msg); +/// +/// // "Thread unblocked!" will be printed now +/// +/// msg = receiver.recv().unwrap(); +/// println!("message {} received", msg); +/// +/// msg = receiver.recv().unwrap(); +/// +/// println!("message {} received", msg); +/// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct SyncSender { inner: Arc>, @@ -823,8 +945,9 @@ impl SyncSender { /// Note that a successful send does *not* guarantee that the receiver will /// ever see the data if there is a buffer on this channel. Items may be /// enqueued in the internal buffer for the receiver to receive at a later - /// time. If the buffer size is 0, however, it can be guaranteed that the - /// receiver has indeed received the data if this function returns success. + /// time. If the buffer size is 0, however, the channel becomes a rendezvous + /// channel and it guarantees that the receiver has indeed received + /// the data if this function returns success. /// /// This function will never panic, but it may return [`Err`] if the /// [`Receiver`] has disconnected and is no longer able to receive @@ -832,6 +955,27 @@ impl SyncSender { /// /// [`Err`]: ../../../std/result/enum.Result.html#variant.Err /// [`Receiver`]: ../../../std/sync/mpsc/struct.Receiver.html + /// + /// # Examples + /// + /// ```rust + /// use std::sync::mpsc::sync_channel; + /// use std::thread; + /// + /// // Create a rendezvous sync_channel with buffer size 0 + /// let (sync_sender, receiver) = sync_channel(0); + /// + /// thread::spawn(move || { + /// println!("sending message..."); + /// sync_sender.send(1).unwrap(); + /// // Thread is now blocked until the message is received + /// + /// println!("...message received!"); + /// }); + /// + /// let msg = receiver.recv().unwrap(); + /// assert_eq!(1, msg); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn send(&self, t: T) -> Result<(), SendError> { self.inner.send(t).map_err(SendError) @@ -844,11 +988,48 @@ impl SyncSender { /// data. Compared with [`send`], this function has two failure cases /// instead of one (one for disconnection, one for a full buffer). /// - /// See [`SyncSender::send`] for notes about guarantees of whether the + /// See [`send`] for notes about guarantees of whether the /// receiver has received the data or not if this function is successful. /// - /// [`send`]: ../../../std/sync/mpsc/struct.Sender.html#method.send - /// [`SyncSender::send`]: ../../../std/sync/mpsc/struct.SyncSender.html#method.send + /// [`send`]: ../../../std/sync/mpsc/struct.SyncSender.html#method.send + /// + /// # Examples + /// + /// ```rust + /// use std::sync::mpsc::sync_channel; + /// use std::thread; + /// + /// // Create a sync_channel with buffer size 1 + /// let (sync_sender, receiver) = sync_channel(1); + /// let sync_sender2 = sync_sender.clone(); + /// + /// // First thread owns sync_sender + /// thread::spawn(move || { + /// sync_sender.send(1).unwrap(); + /// sync_sender.send(2).unwrap(); + /// // Thread blocked + /// }); + /// + /// // Second thread owns sync_sender2 + /// thread::spawn(move || { + /// // This will return an error and send + /// // no message if the buffer is full + /// sync_sender2.try_send(3).is_err(); + /// }); + /// + /// let mut msg; + /// msg = receiver.recv().unwrap(); + /// println!("message {} received", msg); + /// + /// msg = receiver.recv().unwrap(); + /// println!("message {} received", msg); + /// + /// // Third message may have never been sent + /// match receiver.try_recv() { + /// Ok(msg) => println!("message {} received", msg), + /// Err(_) => println!("the third message was never sent"), + /// } + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn try_send(&self, t: T) -> Result<(), TrySendError> { self.inner.try_send(t) @@ -894,6 +1075,21 @@ impl Receiver { /// /// This is useful for a flavor of "optimistic check" before deciding to /// block on a receiver. + /// + /// Compared with [`recv`], this function has two failure cases instead of one + /// (one for disconnection, one for an empty buffer). + /// + /// [`recv`]: struct.Receiver.html#method.recv + /// + /// # Examples + /// + /// ```rust + /// use std::sync::mpsc::{Receiver, channel}; + /// + /// let (_, receiver): (_, Receiver) = channel(); + /// + /// assert!(receiver.try_recv().is_err()); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn try_recv(&self) -> Result { loop { @@ -949,8 +1145,8 @@ impl Receiver { /// /// This function will always block the current thread if there is no data /// available and it's possible for more data to be sent. Once a message is - /// sent to the corresponding [`Sender`], then this receiver will wake up and - /// return that message. + /// sent to the corresponding [`Sender`][] (or [`SyncSender`]), then this + /// receiver will wake up and return that message. /// /// If the corresponding [`Sender`] has disconnected, or it disconnects while /// this call is blocking, this call will wake up and return [`Err`] to @@ -958,7 +1154,8 @@ impl Receiver { /// However, since channels are buffered, messages sent before the disconnect /// will still be properly received. /// - /// [`Sender`]: ../../../std/sync/mpsc/struct.Sender.html + /// [`Sender`]: struct.Sender.html + /// [`SyncSender`]: struct.SyncSender.html /// [`Err`]: ../../../std/result/enum.Result.html#variant.Err /// /// # Examples @@ -1040,8 +1237,8 @@ impl Receiver { /// /// This function will always block the current thread if there is no data /// available and it's possible for more data to be sent. Once a message is - /// sent to the corresponding [`Sender`], then this receiver will wake up and - /// return that message. + /// sent to the corresponding [`Sender`][] (or [`SyncSender`]), then this + /// receiver will wake up and return that message. /// /// If the corresponding [`Sender`] has disconnected, or it disconnects while /// this call is blocking, this call will wake up and return [`Err`] to @@ -1049,7 +1246,8 @@ impl Receiver { /// However, since channels are buffered, messages sent before the disconnect /// will still be properly received. /// - /// [`Sender`]: ../../../std/sync/mpsc/struct.Sender.html + /// [`Sender`]: struct.Sender.html + /// [`SyncSender`]: struct.SyncSender.html /// [`Err`]: ../../../std/result/enum.Result.html#variant.Err /// /// # Examples @@ -1163,6 +1361,33 @@ impl Receiver { /// user by waiting for values. /// /// [`panic!`]: ../../../std/macro.panic.html + /// + /// # Examples + /// + /// ```rust + /// use std::sync::mpsc::channel; + /// use std::thread; + /// use std::time::Duration; + /// + /// let (sender, receiver) = channel(); + /// + /// // Nothing is in the buffer yet + /// assert!(receiver.try_iter().next().is_none()); + /// println!("Nothing in the buffer..."); + /// + /// thread::spawn(move || { + /// sender.send(1).unwrap(); + /// sender.send(2).unwrap(); + /// sender.send(3).unwrap(); + /// }); + /// + /// println!("Going to sleep..."); + /// thread::sleep(Duration::from_secs(2)); // block for two seconds + /// + /// for x in receiver.try_iter() { + /// println!("Got: {}", x); + /// } + /// ``` #[stable(feature = "receiver_try_iter", since = "1.15.0")] pub fn try_iter(&self) -> TryIter { TryIter { rx: self } diff --git a/src/test/compile-fail/auxiliary/issue_41549.rs b/src/test/compile-fail/auxiliary/issue_41549.rs new file mode 100644 index 0000000000000..77b203997b42a --- /dev/null +++ b/src/test/compile-fail/auxiliary/issue_41549.rs @@ -0,0 +1,15 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(associated_consts)] + +pub trait Trait { + const CONST: u32; +} diff --git a/src/test/compile-fail/issue-41549.rs b/src/test/compile-fail/issue-41549.rs new file mode 100644 index 0000000000000..c4aab4bcabf63 --- /dev/null +++ b/src/test/compile-fail/issue-41549.rs @@ -0,0 +1,23 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:issue_41549.rs + +#![feature(associated_consts)] + +extern crate issue_41549; + +struct S; + +impl issue_41549::Trait for S { + const CONST: () = (); //~ ERROR incompatible type for trait +} + +fn main() {} diff --git a/src/test/run-pass/issue-41498.rs b/src/test/run-pass/issue-41498.rs new file mode 100644 index 0000000000000..66fd30bdbbbe4 --- /dev/null +++ b/src/test/run-pass/issue-41498.rs @@ -0,0 +1,26 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// regression test for issue #41498. + +struct S; +impl S { + fn mutate(&mut self) {} +} + +fn call_and_ref T>(x: &mut Option, f: F) -> &mut T { + *x = Some(f()); + x.as_mut().unwrap() +} + +fn main() { + let mut n = None; + call_and_ref(&mut n, || [S])[0].mutate(); +} diff --git a/src/test/compile-fail/borrowck/borrowck-in-static.rs b/src/test/ui/borrowck/borrowck-in-static.rs similarity index 94% rename from src/test/compile-fail/borrowck/borrowck-in-static.rs rename to src/test/ui/borrowck/borrowck-in-static.rs index 16b0e8638de39..9244c12347d95 100644 --- a/src/test/compile-fail/borrowck/borrowck-in-static.rs +++ b/src/test/ui/borrowck/borrowck-in-static.rs @@ -11,7 +11,7 @@ // check that borrowck looks inside consts/statics static FN : &'static (Fn() -> (BoxBox>) + Sync) = &|| { - let x = Box::new(0); + let x = Box::new(0); //~ NOTE moved Box::new(|| x) //~ ERROR cannot move out of captured outer variable }; diff --git a/src/test/ui/borrowck/borrowck-in-static.stderr b/src/test/ui/borrowck/borrowck-in-static.stderr new file mode 100644 index 0000000000000..6083a82b1b6de --- /dev/null +++ b/src/test/ui/borrowck/borrowck-in-static.stderr @@ -0,0 +1,10 @@ +error[E0507]: cannot move out of captured outer variable in an `Fn` closure + --> $DIR/borrowck-in-static.rs:15:17 + | +14 | let x = Box::new(0); //~ NOTE moved + | - captured outer variable +15 | Box::new(|| x) //~ ERROR cannot move out of captured outer variable + | ^ cannot move out of captured outer variable in an `Fn` closure + +error: aborting due to previous error + diff --git a/src/test/compile-fail/unboxed-closures-move-upvar-from-non-once-ref-closure.rs b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs similarity index 93% rename from src/test/compile-fail/unboxed-closures-move-upvar-from-non-once-ref-closure.rs rename to src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs index cd9f1636c3f4d..9c89c26de006a 100644 --- a/src/test/compile-fail/unboxed-closures-move-upvar-from-non-once-ref-closure.rs +++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs @@ -16,7 +16,7 @@ fn call(f: F) where F : Fn() { } fn main() { - let y = vec![format!("World")]; + let y = vec![format!("World")]; //~ NOTE moved call(|| { y.into_iter(); //~^ ERROR cannot move out of captured outer variable in an `Fn` closure diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr new file mode 100644 index 0000000000000..dbfcb2e0c2f95 --- /dev/null +++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr @@ -0,0 +1,11 @@ +error[E0507]: cannot move out of captured outer variable in an `Fn` closure + --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:21:9 + | +19 | let y = vec![format!("World")]; //~ NOTE moved + | - captured outer variable +20 | call(|| { +21 | y.into_iter(); + | ^ cannot move out of captured outer variable in an `Fn` closure + +error: aborting due to previous error + diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs index 6264d11186452..29fea052b06c2 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs @@ -21,8 +21,11 @@ struct Test<'a> { fn call(mut f: F) where F: FnMut(Fn) { f(Box::new(|| { //~^ ERROR: cannot borrow `f` as mutable more than once + //~| NOTE first mutable borrow occurs here + //~| NOTE second mutable borrow occurs here f((Box::new(|| {}))) })); + //~^ NOTE first borrow ends here } fn test1() { @@ -32,7 +35,10 @@ fn test1() { } fn test2(f: &F) where F: FnMut() { - (*f)(); //~ ERROR: cannot borrow immutable borrowed content `*f` as mutable + //~^ NOTE use `&mut F` here to make mutable + (*f)(); + //~^ ERROR cannot borrow immutable borrowed content `*f` as mutable + //~| NOTE cannot borrow as mutable } fn test3(f: &mut F) where F: FnMut() { @@ -40,7 +46,10 @@ fn test3(f: &mut F) where F: FnMut() { } fn test4(f: &Test) { - f.f.call_mut(()) //~ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable + //~^ NOTE use `&mut Test` here to make mutable + f.f.call_mut(()) + //~^ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable + //~| NOTE cannot borrow as mutable } fn test5(f: &mut Test) { @@ -57,10 +66,14 @@ fn test6() { fn test7() { fn foo(_: F) where F: FnMut(Box, isize) {} let mut f = |g: Box, b: isize| {}; + //~^ NOTE moved f(Box::new(|a| { + //~^ NOTE borrow of `f` occurs here foo(f); //~^ ERROR cannot move `f` into closure because it is borrowed //~| ERROR cannot move out of captured outer variable in an `FnMut` closure + //~| NOTE move into closure occurs here + //~| NOTE cannot move out of captured outer variable in an `FnMut` closure }), 3); } diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr index 58b3f205fe352..4ece8bc6af10f 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr @@ -5,40 +5,46 @@ error[E0499]: cannot borrow `f` as mutable more than once at a time | - ^^ second mutable borrow occurs here | | | first mutable borrow occurs here -23 | //~^ ERROR: cannot borrow `f` as mutable more than once -24 | f((Box::new(|| {}))) +... +26 | f((Box::new(|| {}))) | - borrow occurs due to use of `f` in closure -25 | })); +27 | })); | - first borrow ends here error: cannot borrow immutable borrowed content `*f` as mutable - --> $DIR/borrowck-call-is-borrow-issue-12224.rs:35:5 + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:39:5 | -34 | fn test2(f: &F) where F: FnMut() { +37 | fn test2(f: &F) where F: FnMut() { | -- use `&mut F` here to make mutable -35 | (*f)(); //~ ERROR: cannot borrow immutable borrowed content `*f` as mutable +38 | //~^ NOTE use `&mut F` here to make mutable +39 | (*f)(); | ^^^^ cannot borrow as mutable error: cannot borrow immutable `Box` content `*f.f` as mutable - --> $DIR/borrowck-call-is-borrow-issue-12224.rs:43:5 + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:50:5 | -42 | fn test4(f: &Test) { +48 | fn test4(f: &Test) { | ----- use `&mut Test` here to make mutable -43 | f.f.call_mut(()) //~ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable +49 | //~^ NOTE use `&mut Test` here to make mutable +50 | f.f.call_mut(()) | ^^^ cannot borrow as mutable error[E0504]: cannot move `f` into closure because it is borrowed - --> $DIR/borrowck-call-is-borrow-issue-12224.rs:61:13 + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:72:13 | -60 | f(Box::new(|a| { +70 | f(Box::new(|a| { | - borrow of `f` occurs here -61 | foo(f); +71 | //~^ NOTE borrow of `f` occurs here +72 | foo(f); | ^ move into closure occurs here error[E0507]: cannot move out of captured outer variable in an `FnMut` closure - --> $DIR/borrowck-call-is-borrow-issue-12224.rs:61:13 + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:72:13 | -61 | foo(f); +68 | let mut f = |g: Box, b: isize| {}; + | ----- captured outer variable +... +72 | foo(f); | ^ cannot move out of captured outer variable in an `FnMut` closure error: aborting due to 5 previous errors