diff --git a/src/ci/docker/armhf-gnu/Dockerfile b/src/ci/docker/armhf-gnu/Dockerfile index 2b7624d53ee05..e4c2097f970a9 100644 --- a/src/ci/docker/armhf-gnu/Dockerfile +++ b/src/ci/docker/armhf-gnu/Dockerfile @@ -71,7 +71,8 @@ COPY scripts/qemu-bare-bones-addentropy.c /tmp/addentropy.c RUN arm-linux-gnueabihf-gcc addentropy.c -o rootfs/addentropy -static # TODO: What is this?! -RUN curl -O http://ftp.nl.debian.org/debian/dists/jessie/main/installer-armhf/current/images/device-tree/vexpress-v2p-ca15-tc1.dtb +# Source of the file: https://github.com/vfdev-5/qemu-rpi2-vexpress/raw/master/vexpress-v2p-ca15-tc1.dtb +RUN curl -O https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/vexpress-v2p-ca15-tc1.dtb COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/doc/unstable-book/src/language-features/non-exhaustive.md b/src/doc/unstable-book/src/language-features/non-exhaustive.md index f9840e1b83f2b..907147c17ef8e 100644 --- a/src/doc/unstable-book/src/language-features/non-exhaustive.md +++ b/src/doc/unstable-book/src/language-features/non-exhaustive.md @@ -7,10 +7,12 @@ The tracking issue for this feature is: [#44109] ------------------------ The `non_exhaustive` gate allows you to use the `#[non_exhaustive]` attribute -on structs and enums. When applied within a crate, users of the crate will need -to use the `_` pattern when matching enums and use the `..` pattern when -matching structs. Structs marked as `non_exhaustive` will not be able to be -created normally outside of the defining crate. This is demonstrated below: +on structs, enums and enum variants. When applied within a crate, users of the +crate will need to use the `_` pattern when matching enums and use the `..` +pattern when matching structs. Enum variants cannot be matched against. +Structs and enum variants marked as `non_exhaustive` will not be able to +be created normally outside of the defining crate. This is demonstrated +below: ```rust,ignore (pseudo-Rust) use std::error::Error as StdError; @@ -72,4 +74,3 @@ let config = Config { window_width: 640, window_height: 480 }; // when marked non_exhaustive. let &Config { window_width, window_height, .. } = config; ``` - diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index ffc24df3ed42e..7934e5880d7d2 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -375,8 +375,8 @@ pub fn once(value: T) -> Once { Once { inner: Some(value).into_iter() } } -/// An iterator that repeats elements of type `A` endlessly by -/// applying the provided closure `F: FnMut() -> A`. +/// An iterator that yields a single element of type `A` by +/// applying the provided closure `F: FnOnce() -> A`. /// /// This `struct` is created by the [`once_with`] function. /// See its documentation for more. diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index f0045136f41bf..102057c1380ac 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1869,6 +1869,11 @@ impl<'a, 'gcx, 'tcx> VariantDef { if adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, "non_exhaustive") { debug!("found non-exhaustive field list for {:?}", parent_did); flags = flags | VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE; + } else if let Some(variant_did) = variant_did { + if tcx.has_attr(variant_did, "non_exhaustive") { + debug!("found non-exhaustive field list for {:?}", variant_did); + flags = flags | VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE; + } } VariantDef { @@ -2146,6 +2151,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { debug!("found non-exhaustive variant list for {:?}", did); flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE; } + flags |= match kind { AdtKind::Enum => AdtFlags::IS_ENUM, AdtKind::Union => AdtFlags::IS_UNION, @@ -2299,21 +2305,25 @@ impl<'a, 'gcx, 'tcx> AdtDef { self.variants.iter().all(|v| v.fields.is_empty()) } + /// Return a `VariantDef` given a variant id. pub fn variant_with_id(&self, vid: DefId) -> &VariantDef { self.variants.iter().find(|v| v.def_id == vid) .expect("variant_with_id: unknown variant") } + /// Return a `VariantDef` given a constructor id. pub fn variant_with_ctor_id(&self, cid: DefId) -> &VariantDef { self.variants.iter().find(|v| v.ctor_def_id == Some(cid)) .expect("variant_with_ctor_id: unknown variant") } + /// Return the index of `VariantDef` given a variant id. pub fn variant_index_with_id(&self, vid: DefId) -> VariantIdx { self.variants.iter_enumerated().find(|(_, v)| v.def_id == vid) .expect("variant_index_with_id: unknown variant").0 } + /// Return the index of `VariantDef` given a constructor id. pub fn variant_index_with_ctor_id(&self, cid: DefId) -> VariantIdx { self.variants.iter_enumerated().find(|(_, v)| v.ctor_def_id == Some(cid)) .expect("variant_index_with_ctor_id: unknown variant").0 @@ -2930,8 +2940,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - // Returns `ty::VariantDef` if `def` refers to a struct, - // or variant or their constructors, panics otherwise. + /// Returns `ty::VariantDef` if `def` refers to a struct, + /// or variant or their constructors, panics otherwise. pub fn expect_variant_def(self, def: Def) -> &'tcx VariantDef { match def { Def::Variant(did) => { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 9c908176a6d3a..796d2f6a18ba3 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -643,13 +643,18 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } }; - // Variant constructors have the same visibility as the parent enums. + // Variant constructors have the same visibility as the parent enums, unless marked as + // non-exhaustive, in which case they are lowered to `pub(crate)`. let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap(); let enum_vis = &tcx.hir().expect_item_by_hir_id(enum_id).vis; + let mut ctor_vis = ty::Visibility::from_hir(enum_vis, enum_id, tcx); + if variant.is_field_list_non_exhaustive() && ctor_vis == ty::Visibility::Public { + ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); + } Entry { kind: EntryKind::Variant(self.lazy(&data)), - visibility: self.lazy(&ty::Visibility::from_hir(enum_vis, enum_id, tcx)), + visibility: self.lazy(&ctor_vis), span: self.lazy(&tcx.def_span(def_id)), attributes: LazySeq::empty(), children: LazySeq::empty(), diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 4e2aefe623167..741264d1dbe18 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -192,14 +192,6 @@ impl<'a> AstValidator<'a> { } } - fn invalid_non_exhaustive_attribute(&self, variant: &Variant) { - let has_non_exhaustive = attr::contains_name(&variant.node.attrs, "non_exhaustive"); - if has_non_exhaustive { - self.err_handler().span_err(variant.span, - "#[non_exhaustive] is not yet supported on variants"); - } - } - fn invalid_visibility(&self, vis: &Visibility, note: Option<&str>) { if let VisibilityKind::Inherited = vis.node { return @@ -608,7 +600,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } ItemKind::Enum(ref def, _) => { for variant in &def.variants { - self.invalid_non_exhaustive_attribute(variant); for field in variant.node.data.fields() { self.invalid_visibility(&field.vis, None); } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index adb1a4b130887..030883c0159fb 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -244,7 +244,26 @@ fn def_id_visibility<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) match tcx.hir().get_by_hir_id(parent_hir_id) { Node::Variant(..) => { let parent_did = tcx.hir().local_def_id_from_hir_id(parent_hir_id); - return def_id_visibility(tcx, parent_did); + let (mut ctor_vis, mut span, mut descr) = def_id_visibility( + tcx, parent_did, + ); + + let adt_def = tcx.adt_def(tcx.hir().get_parent_did_by_hir_id(hir_id)); + let ctor_did = tcx.hir().local_def_id_from_hir_id( + vdata.ctor_hir_id().unwrap()); + let variant = adt_def.variant_with_ctor_id(ctor_did); + + if variant.is_field_list_non_exhaustive() && + ctor_vis == ty::Visibility::Public + { + ctor_vis = ty::Visibility::Restricted( + DefId::local(CRATE_DEF_INDEX)); + let attrs = tcx.get_attrs(variant.def_id); + span = attr::find_by_name(&attrs, "non_exhaustive").unwrap().span; + descr = "crate-visible"; + } + + return (ctor_vis, span, descr); } Node::Item(..) => { let item = match tcx.hir().get_by_hir_id(parent_hir_id) { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index f55425c3168ec..7ce264db755db 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -588,6 +588,14 @@ impl<'a> Resolver<'a> { let def = Def::Variant(def_id); self.define(parent, ident, TypeNS, (def, vis, variant.span, expansion)); + // If the variant is marked as non_exhaustive then lower the visibility to within the + // crate. + let mut ctor_vis = vis; + let has_non_exhaustive = attr::contains_name(&variant.node.attrs, "non_exhaustive"); + if has_non_exhaustive && vis == ty::Visibility::Public { + ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); + } + // Define a constructor name in the value namespace. // Braced variants, unlike structs, generate unusable names in // value namespace, they are reserved for possible future use. @@ -597,7 +605,7 @@ impl<'a> Resolver<'a> { let ctor_def_id = self.definitions.local_def_id(ctor_node_id); let ctor_kind = CtorKind::from_ast(&variant.node.data); let ctor_def = Def::Ctor(ctor_def_id, CtorOf::Variant, ctor_kind); - self.define(parent, ident, ValueNS, (ctor_def, vis, variant.span, expansion)); + self.define(parent, ident, ValueNS, (ctor_def, ctor_vis, variant.span, expansion)); } /// Constructs the reduced graph for one foreign item. diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 1fc63a9302204..8739147c621e6 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -270,6 +270,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { None } + fn is_hir_id_from_struct_pattern_shorthand_field(&self, hir_id: hir::HirId, sp: Span) -> bool { + let cm = self.sess().source_map(); + let parent_id = self.tcx.hir().get_parent_node_by_hir_id(hir_id); + if let Some(parent) = self.tcx.hir().find_by_hir_id(parent_id) { + // Account for fields + if let Node::Expr(hir::Expr { + node: hir::ExprKind::Struct(_, fields, ..), .. + }) = parent { + if let Ok(src) = cm.span_to_snippet(sp) { + for field in fields { + if field.ident.as_str() == src.as_str() && field.is_shorthand { + return true; + } + } + } + } + } + false + } + /// This function is used to determine potential "simple" improvements or users' errors and /// provide them useful help. For example: /// @@ -299,6 +319,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return None; } + let is_struct_pat_shorthand_field = self.is_hir_id_from_struct_pattern_shorthand_field( + expr.hir_id, + sp, + ); + match (&expected.sty, &checked_ty.sty) { (&ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.sty, &check.sty) { (&ty::Str, &ty::Array(arr, _)) | @@ -337,12 +362,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // bar(&x); // error, expected &mut // ``` let ref_ty = match mutability { - hir::Mutability::MutMutable => self.tcx.mk_mut_ref( - self.tcx.mk_region(ty::ReStatic), - checked_ty), - hir::Mutability::MutImmutable => self.tcx.mk_imm_ref( - self.tcx.mk_region(ty::ReStatic), - checked_ty), + hir::Mutability::MutMutable => { + self.tcx.mk_mut_ref(self.tcx.mk_region(ty::ReStatic), checked_ty) + } + hir::Mutability::MutImmutable => { + self.tcx.mk_imm_ref(self.tcx.mk_region(ty::ReStatic), checked_ty) + } }; if self.can_coerce(ref_ty, expected) { if let Ok(src) = cm.span_to_snippet(sp) { @@ -363,14 +388,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(sugg) = self.can_use_as_ref(expr) { return Some(sugg); } + let field_name = if is_struct_pat_shorthand_field { + format!("{}: ", sugg_expr) + } else { + String::new() + }; return Some(match mutability { - hir::Mutability::MutMutable => { - (sp, "consider mutably borrowing here", format!("&mut {}", - sugg_expr)) - } - hir::Mutability::MutImmutable => { - (sp, "consider borrowing here", format!("&{}", sugg_expr)) - } + hir::Mutability::MutMutable => ( + sp, + "consider mutably borrowing here", + format!("{}&mut {}", field_name, sugg_expr), + ), + hir::Mutability::MutImmutable => ( + sp, + "consider borrowing here", + format!("{}&{}", field_name, sugg_expr), + ), }); } } @@ -411,12 +444,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { checked, sp) { // do not suggest if the span comes from a macro (#52783) - if let (Ok(code), - true) = (cm.span_to_snippet(sp), sp == expr.span) { + if let (Ok(code), true) = ( + cm.span_to_snippet(sp), + sp == expr.span, + ) { return Some(( sp, "consider dereferencing the borrow", - format!("*{}", code), + if is_struct_pat_shorthand_field { + format!("{}: *{}", code, code) + } else { + format!("*{}", code) + }, )); } } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index cde37fb23c320..22f24df450f46 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4341,11 +4341,12 @@ foo.method(); // Ok! "##, E0638: r##" -This error indicates that the struct or enum must be matched non-exhaustively -as it has been marked as `non_exhaustive`. +This error indicates that the struct, enum or enum variant must be matched +non-exhaustively as it has been marked as `non_exhaustive`. When applied within a crate, downstream users of the crate will need to use the `_` pattern when matching enums and use the `..` pattern when matching structs. +Downstream crates cannot match against non-exhaustive enum variants. For example, in the below example, since the enum is marked as `non_exhaustive`, it is required that downstream crates match non-exhaustively @@ -4390,10 +4391,10 @@ Similarly, for structs, match with `..` to avoid this error. "##, E0639: r##" -This error indicates that the struct or enum cannot be instantiated from -outside of the defining crate as it has been marked as `non_exhaustive` and as -such more fields/variants may be added in future that could cause adverse side -effects for this code. +This error indicates that the struct, enum or enum variant cannot be +instantiated from outside of the defining crate as it has been marked +as `non_exhaustive` and as such more fields/variants may be added in +future that could cause adverse side effects for this code. It is recommended that you look for a `new` function or equivalent in the crate's documentation. diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 396488c981dfd..a403f0845ceef 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -421,6 +421,9 @@ impl Item { pub fn is_enum(&self) -> bool { self.type_() == ItemType::Enum } + pub fn is_variant(&self) -> bool { + self.type_() == ItemType::Variant + } pub fn is_associated_type(&self) -> bool { self.type_() == ItemType::AssociatedType } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 866d8fe682a7b..9220d2feed2d2 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2604,7 +2604,15 @@ fn document_non_exhaustive_header(item: &clean::Item) -> &str { fn document_non_exhaustive(w: &mut fmt::Formatter<'_>, item: &clean::Item) -> fmt::Result { if item.is_non_exhaustive() { write!(w, "
", { - if item.is_struct() { "struct" } else if item.is_enum() { "enum" } else { "type" } + if item.is_struct() { + "struct" + } else if item.is_enum() { + "enum" + } else if item.is_variant() { + "variant" + } else { + "type" + } })?; if item.is_struct() { @@ -2617,6 +2625,10 @@ fn document_non_exhaustive(w: &mut fmt::Formatter<'_>, item: &clean::Item) -> fm write!(w, "Non-exhaustive enums could have additional variants added in future. \ Therefore, when matching against variants of non-exhaustive enums, an \ extra wildcard arm must be added to account for any future variants.")?; + } else if item.is_variant() { + write!(w, "Non-exhaustive enum variants could have additional fields added in future. \ + Therefore, non-exhaustive enum variants cannot be constructed in external \ + crates and cannot be matched against.")?; } else { write!(w, "This type will require a wildcard arm in any match statements or \ constructors.")?; @@ -3679,6 +3691,7 @@ fn item_enum(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, } write!(w, "")?; document(w, cx, variant)?; + document_non_exhaustive(w, variant)?; use crate::clean::{Variant, VariantKind}; if let clean::VariantItem(Variant { diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index aad7eb627bfe2..412029cf3765f 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -2071,6 +2071,14 @@ if (!DOMTokenList.prototype.remove) { collapser(e, collapse); }); } + + var blanket_list = document.getElementById("blanket-implementations-list"); + + if (blanket_list !== null) { + onEachLazy(blanket_list.getElementsByClassName("collapse-toggle"), function(e) { + collapser(e, collapse); + }); + } } } @@ -2263,6 +2271,8 @@ if (!DOMTokenList.prototype.remove) { otherMessage += "struct"; } else if (hasClass(e, "non-exhaustive-enum")) { otherMessage += "enum"; + } else if (hasClass(e, "non-exhaustive-variant")) { + otherMessage += "enum variant"; } else if (hasClass(e, "non-exhaustive-type")) { otherMessage += "type"; } @@ -2280,6 +2290,9 @@ if (!DOMTokenList.prototype.remove) { if (hasClass(e, "type-decl") === true && showItemDeclarations === true) { collapseDocs(e.previousSibling.childNodes[0], "toggle"); } + if (hasClass(e, "non-exhaustive") === true) { + collapseDocs(e.previousSibling.childNodes[0], "toggle"); + } } } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 14c850b6b0547..14a16f3fc0f04 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -24,9 +24,9 @@ //! let mut buffer = [0; 10]; //! //! // read up to 10 bytes -//! f.read(&mut buffer)?; +//! let n = f.read(&mut buffer)?; //! -//! println!("The bytes: {:?}", buffer); +//! println!("The bytes: {:?}", &buffer[..n]); //! Ok(()) //! } //! ``` @@ -56,9 +56,9 @@ //! f.seek(SeekFrom::End(-10))?; //! //! // read up to 10 bytes -//! f.read(&mut buffer)?; +//! let n = f.read(&mut buffer)?; //! -//! println!("The bytes: {:?}", buffer); +//! println!("The bytes: {:?}", &buffer[..n]); //! Ok(()) //! } //! ``` @@ -537,7 +537,9 @@ pub trait Read { /// let mut buffer = [0; 10]; /// /// // read up to 10 bytes - /// f.read(&mut buffer[..])?; + /// let n = f.read(&mut buffer[..])?; + /// + /// println!("The bytes: {:?}", &buffer[..n]); /// Ok(()) /// } /// ``` @@ -1062,12 +1064,23 @@ impl Initializer { /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { +/// let data = b"some bytes"; +/// +/// let mut pos = 0; /// let mut buffer = File::create("foo.txt")?; /// -/// buffer.write(b"some bytes")?; +/// while pos < data.len() { +/// let bytes_written = buffer.write(&data[pos..])?; +/// pos += bytes_written; +/// } /// Ok(()) /// } /// ``` +/// +/// The trait also provides convenience methods like [`write_all`], which calls +/// `write` in a loop until its entire input has been written. +/// +/// [`write_all`]: #method.write_all #[stable(feature = "rust1", since = "1.0.0")] #[doc(spotlight)] pub trait Write { diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index d5afd069d7f29..0e0292277e19f 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -233,10 +233,14 @@ macro_rules! eprintln { /// to give up ownership, you can instead borrow with `dbg!(&expr)` /// for some expression `expr`. /// +/// The `dbg!` macro works exactly the same in release builds. +/// This is useful when debugging issues that only occur in release +/// builds or when debugging in release mode is significantly faster. +/// /// Note that the macro is intended as a debugging tool and therefore you /// should avoid having uses of it in version control for longer periods. /// Use cases involving debug output that should be added to version control -/// may be better served by macros such as `debug!` from the `log` crate. +/// are better served by macros such as [`debug!`][debug-log] from the [`log`][log] crate. /// /// # Stability /// @@ -311,6 +315,8 @@ macro_rules! eprintln { /// file and line whenever it's reached. /// /// [stderr]: https://en.wikipedia.org/wiki/Standard_streams#Standard_error_(stderr) +/// [debug-log]: https://docs.rs/log/*/log/macro.debug.html +/// [log]: https://docs.rs/log/ #[macro_export] #[stable(feature = "dbg_macro", since = "1.32.0")] macro_rules! dbg { diff --git a/src/libstd/sys/redox/ext/io.rs b/src/libstd/sys/redox/ext/io.rs index f431f96c541f7..c21d216478fb7 100644 --- a/src/libstd/sys/redox/ext/io.rs +++ b/src/libstd/sys/redox/ext/io.rs @@ -115,6 +115,21 @@ impl AsRawFd for io::Stderr { fn as_raw_fd(&self) -> RawFd { 2 } } +#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] +impl<'a> AsRawFd for io::StdinLock<'a> { + fn as_raw_fd(&self) -> RawFd { 0 } +} + +#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] +impl<'a> AsRawFd for io::StdoutLock<'a> { + fn as_raw_fd(&self) -> RawFd { 1 } +} + +#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] +impl<'a> AsRawFd for io::StderrLock<'a> { + fn as_raw_fd(&self) -> RawFd { 2 } +} + #[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawFd for net::TcpStream { unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream { diff --git a/src/libstd/sys/unix/ext/io.rs b/src/libstd/sys/unix/ext/io.rs index 1a0b3b8962bd1..6bcc59495e363 100644 --- a/src/libstd/sys/unix/ext/io.rs +++ b/src/libstd/sys/unix/ext/io.rs @@ -95,3 +95,18 @@ impl AsRawFd for io::Stdout { impl AsRawFd for io::Stderr { fn as_raw_fd(&self) -> RawFd { libc::STDERR_FILENO } } + +#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] +impl<'a> AsRawFd for io::StdinLock<'a> { + fn as_raw_fd(&self) -> RawFd { libc::STDIN_FILENO } +} + +#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] +impl<'a> AsRawFd for io::StdoutLock<'a> { + fn as_raw_fd(&self) -> RawFd { libc::STDOUT_FILENO } +} + +#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] +impl<'a> AsRawFd for io::StderrLock<'a> { + fn as_raw_fd(&self) -> RawFd { libc::STDERR_FILENO } +} diff --git a/src/libstd/sys/windows/ext/io.rs b/src/libstd/sys/windows/ext/io.rs index 1a7d734b89e4b..ec47c2e9d5afd 100644 --- a/src/libstd/sys/windows/ext/io.rs +++ b/src/libstd/sys/windows/ext/io.rs @@ -83,6 +83,27 @@ impl AsRawHandle for io::Stderr { } } +#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] +impl<'a> AsRawHandle for io::StdinLock<'a> { + fn as_raw_handle(&self) -> RawHandle { + unsafe { c::GetStdHandle(c::STD_INPUT_HANDLE) as RawHandle } + } +} + +#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] +impl<'a> AsRawHandle for io::StdoutLock<'a> { + fn as_raw_handle(&self) -> RawHandle { + unsafe { c::GetStdHandle(c::STD_OUTPUT_HANDLE) as RawHandle } + } +} + +#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] +impl<'a> AsRawHandle for io::StderrLock<'a> { + fn as_raw_handle(&self) -> RawHandle { + unsafe { c::GetStdHandle(c::STD_ERROR_HANDLE) as RawHandle } + } +} + #[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawHandle for fs::File { unsafe fn from_raw_handle(handle: RawHandle) -> fs::File { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 96c89d3176ab6..dcb55fb572f33 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -906,7 +906,7 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu not currently handle destructors.", cfg_fn!(thread_local))), - ("rustc_on_unimplemented", Normal, template!(List: + ("rustc_on_unimplemented", Whitelisted, template!(List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#, NameValueStr: "message"), Gated(Stability::Unstable, @@ -962,6 +962,20 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), + ("rustc_layout_scalar_valid_range_start", Whitelisted, template!(List: "value"), + Gated(Stability::Unstable, + "rustc_attrs", + "the `#[rustc_layout_scalar_valid_range_start]` attribute \ + is just used to enable niche optimizations in libcore \ + and will never be stable", + cfg_fn!(rustc_attrs))), + ("rustc_layout_scalar_valid_range_end", Whitelisted, template!(List: "value"), + Gated(Stability::Unstable, + "rustc_attrs", + "the `#[rustc_layout_scalar_valid_range_end]` attribute \ + is just used to enable niche optimizations in libcore \ + and will never be stable", + cfg_fn!(rustc_attrs))), ("rustc_regions", Normal, template!(Word), Gated(Stability::Unstable, "rustc_attrs", "the `#[rustc_regions]` attribute \ diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 79c1f0cb4cc3c..ae8e57d54de31 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2626,7 +2626,13 @@ impl<'a> Parser<'a> { let mut trailing_comma = false; let mut recovered = false; while self.token != token::CloseDelim(token::Paren) { - es.push(self.parse_expr()?); + es.push(match self.parse_expr() { + Ok(es) => es, + Err(err) => { + // recover from parse error in tuple list + return Ok(self.recover_seq_parse_error(token::Paren, lo, Err(err))); + } + }); recovered = self.expect_one_of( &[], &[token::Comma, token::CloseDelim(token::Paren)], @@ -3237,36 +3243,54 @@ impl<'a> Parser<'a> { } if self.expr_is_complete(&e) { break; } match self.token { - // expr(...) - token::OpenDelim(token::Paren) => { - let es = self.parse_unspanned_seq( - &token::OpenDelim(token::Paren), - &token::CloseDelim(token::Paren), - SeqSep::trailing_allowed(token::Comma), - |p| Ok(p.parse_expr()?) - )?; - hi = self.prev_span; - - let nd = self.mk_call(e, es); - e = self.mk_expr(lo.to(hi), nd, ThinVec::new()); - } + // expr(...) + token::OpenDelim(token::Paren) => { + let seq = self.parse_unspanned_seq( + &token::OpenDelim(token::Paren), + &token::CloseDelim(token::Paren), + SeqSep::trailing_allowed(token::Comma), + |p| Ok(p.parse_expr()?) + ).map(|es| { + let nd = self.mk_call(e, es); + let hi = self.prev_span; + self.mk_expr(lo.to(hi), nd, ThinVec::new()) + }); + e = self.recover_seq_parse_error(token::Paren, lo, seq); + } - // expr[...] - // Could be either an index expression or a slicing expression. - token::OpenDelim(token::Bracket) => { - self.bump(); - let ix = self.parse_expr()?; - hi = self.span; - self.expect(&token::CloseDelim(token::Bracket))?; - let index = self.mk_index(e, ix); - e = self.mk_expr(lo.to(hi), index, ThinVec::new()) - } - _ => return Ok(e) + // expr[...] + // Could be either an index expression or a slicing expression. + token::OpenDelim(token::Bracket) => { + self.bump(); + let ix = self.parse_expr()?; + hi = self.span; + self.expect(&token::CloseDelim(token::Bracket))?; + let index = self.mk_index(e, ix); + e = self.mk_expr(lo.to(hi), index, ThinVec::new()) + } + _ => return Ok(e) } } return Ok(e); } + fn recover_seq_parse_error( + &mut self, + delim: token::DelimToken, + lo: Span, + result: PResult<'a, P>, + ) -> P { + match result { + Ok(x) => x, + Err(mut err) => { + err.emit(); + // recover from parse error + self.consume_block(delim); + self.mk_expr(lo.to(self.prev_span), ExprKind::Err, ThinVec::new()) + } + } + } + crate fn process_potential_macro_variable(&mut self) { let (token, span) = match self.token { token::Dollar if self.span.ctxt() != syntax_pos::hygiene::SyntaxContext::empty() && @@ -4253,7 +4277,14 @@ impl<'a> Parser<'a> { // Trailing commas are significant because (p) and (p,) are different patterns. fn parse_parenthesized_pat_list(&mut self) -> PResult<'a, (Vec>, Option, bool)> { self.expect(&token::OpenDelim(token::Paren))?; - let result = self.parse_pat_list()?; + let result = match self.parse_pat_list() { + Ok(result) => result, + Err(mut err) => { // recover from parse error in tuple pattern list + err.emit(); + self.consume_block(token::Paren); + return Ok((vec![], Some(0), false)); + } + }; self.expect(&token::CloseDelim(token::Paren))?; Ok(result) } diff --git a/src/test/incremental/issue-59523-on-implemented-is-not-unused.rs b/src/test/incremental/issue-59523-on-implemented-is-not-unused.rs new file mode 100644 index 0000000000000..3d16a1543f43a --- /dev/null +++ b/src/test/incremental/issue-59523-on-implemented-is-not-unused.rs @@ -0,0 +1,27 @@ +// We should not see the unused_attributes lint fire for +// rustc_on_unimplemented, but with this bug we are seeing it fire (on +// subsequent runs) if incremental compilation is enabled. + +// revisions: rpass1 rpass2 +// compile-pass + +#![feature(on_unimplemented)] +#![deny(unused_attributes)] + +#[rustc_on_unimplemented = "invalid"] +trait Index { + type Output: ?Sized; + fn index(&self, index: Idx) -> &Self::Output; +} + +#[rustc_on_unimplemented = "a usize is required to index into a slice"] +impl Index for [i32] { + type Output = i32; + fn index(&self, index: usize) -> &i32 { + &self[index] + } +} + +fn main() { + Index::::index(&[1, 2, 3] as &[i32], 2); +} diff --git a/src/test/incremental/issue-59524-layout-scalar-valid-range-is-not-unused.rs b/src/test/incremental/issue-59524-layout-scalar-valid-range-is-not-unused.rs new file mode 100644 index 0000000000000..e4802cba9b6d7 --- /dev/null +++ b/src/test/incremental/issue-59524-layout-scalar-valid-range-is-not-unused.rs @@ -0,0 +1,19 @@ +// We should not see the unused_attributes lint fire for +// rustc_layout_scalar_valid_range_start, but with this bug we are +// seeing it fire (on subsequent runs) if incremental compilation is +// enabled. + +// revisions: rpass1 rpass2 +// compile-pass + +#![feature(rustc_attrs)] +#![deny(unused_attributes)] + +#[rustc_layout_scalar_valid_range_start(10)] +#[rustc_layout_scalar_valid_range_end(30)] +struct RestrictedRange(u32); +const OKAY_RANGE: RestrictedRange = unsafe { RestrictedRange(20) }; + +fn main() { + OKAY_RANGE.0; +} diff --git a/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/auxiliary/enums.rs b/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/auxiliary/enums.rs deleted file mode 100644 index b3e2fa2c6208e..0000000000000 --- a/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/auxiliary/enums.rs +++ /dev/null @@ -1,10 +0,0 @@ -// run-pass -#![crate_type = "rlib"] -#![feature(non_exhaustive)] - -#[non_exhaustive] -pub enum NonExhaustiveEnum { - Unit, - Tuple(u32), - Struct { field: u32 } -} diff --git a/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/auxiliary/structs.rs b/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/auxiliary/structs.rs deleted file mode 100644 index 08b14d0df9408..0000000000000 --- a/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/auxiliary/structs.rs +++ /dev/null @@ -1,14 +0,0 @@ -// run-pass -#![feature(non_exhaustive)] - -#[non_exhaustive] -pub struct NormalStruct { - pub first_field: u16, - pub second_field: u16, -} - -#[non_exhaustive] -pub struct UnitStruct; - -#[non_exhaustive] -pub struct TupleStruct (pub u16, pub u16); diff --git a/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/auxiliary/variants.rs b/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/auxiliary/variants.rs deleted file mode 100644 index 56a73d8ab6088..0000000000000 --- a/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/auxiliary/variants.rs +++ /dev/null @@ -1,9 +0,0 @@ -// run-pass -#![crate_type = "rlib"] -#![feature(non_exhaustive)] - -pub enum NonExhaustiveVariants { - #[non_exhaustive] Unit, - #[non_exhaustive] Tuple(u32), - #[non_exhaustive] Struct { field: u32 } -} diff --git a/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/enums.rs b/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/enums.rs deleted file mode 100644 index f7e9c53849612..0000000000000 --- a/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/enums.rs +++ /dev/null @@ -1,53 +0,0 @@ -// run-pass -// aux-build:enums.rs -extern crate enums; - -// ignore-pretty issue #37199 - -use enums::NonExhaustiveEnum; - -fn main() { - let enum_unit = NonExhaustiveEnum::Unit; - - match enum_unit { - NonExhaustiveEnum::Unit => 1, - NonExhaustiveEnum::Tuple(_) => 2, - // This particular arm tests that a enum marked as non-exhaustive - // will not error if its variants are matched exhaustively. - NonExhaustiveEnum::Struct { field } => field, - _ => 0 // no error with wildcard - }; - - match enum_unit { - _ => "no error with only wildcard" - }; - - - // issue #53549 - check that variant constructors can still be called normally. - - match NonExhaustiveEnum::Unit { - NonExhaustiveEnum::Unit => {}, - _ => {} - }; - - match NonExhaustiveEnum::Tuple(2) { - NonExhaustiveEnum::Tuple(2) => {}, - _ => {} - }; - - match (NonExhaustiveEnum::Unit {}) { - NonExhaustiveEnum::Unit {} => {}, - _ => {} - }; - - match (NonExhaustiveEnum::Tuple { 0: 2 }) { - NonExhaustiveEnum::Tuple { 0: 2 } => {}, - _ => {} - }; - - match (NonExhaustiveEnum::Struct { field: 2 }) { - NonExhaustiveEnum::Struct { field: 2 } => {}, - _ => {} - }; - -} diff --git a/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/structs.rs b/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/structs.rs deleted file mode 100644 index 3cd7234269e1d..0000000000000 --- a/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/structs.rs +++ /dev/null @@ -1,20 +0,0 @@ -// run-pass -#![allow(dead_code)] -#![allow(unused_variables)] -// aux-build:structs.rs -extern crate structs; - -use structs::{NormalStruct, UnitStruct, TupleStruct}; - -// We only test matching here as we cannot create non-exhaustive -// structs from another crate. ie. they'll never pass in run-pass tests. - -fn match_structs(ns: NormalStruct, ts: TupleStruct, us: UnitStruct) { - let NormalStruct { first_field, second_field, .. } = ns; - - let TupleStruct { 0: first, 1: second, .. } = ts; - - let UnitStruct { .. } = us; -} - -fn main() { } diff --git a/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/variants.rs b/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/variants.rs deleted file mode 100644 index 90b8219e2a3c0..0000000000000 --- a/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/variants.rs +++ /dev/null @@ -1,22 +0,0 @@ -// run-pass -// aux-build:variants.rs -extern crate variants; - -use variants::NonExhaustiveVariants; - -/* - * The initial implementation of #[non_exhaustive] (RFC 2008) does not include support for - * variants. See issue #44109 and PR 45394. - */ -// ignore-test - -fn main() { - let variant_tuple = NonExhaustiveVariants::Tuple { 0: 340 }; - let variant_struct = NonExhaustiveVariants::Struct { field: 340 }; - - match variant_struct { - NonExhaustiveVariants::Unit => "", - NonExhaustiveVariants::Struct { field, .. } => "", - NonExhaustiveVariants::Tuple(fe_tpl, ..) => "" - }; -} diff --git a/src/test/ui/deref-suggestion.rs b/src/test/ui/deref-suggestion.rs index 83e54b64f47c9..580410aecf4f8 100644 --- a/src/test/ui/deref-suggestion.rs +++ b/src/test/ui/deref-suggestion.rs @@ -15,6 +15,14 @@ fn foo4(u: &u32) { //~^ ERROR mismatched types } +struct S<'a> { + u: &'a u32, +} + +struct R { + i: u32, +} + fn main() { let s = String::new(); let r_s = &s; @@ -27,4 +35,14 @@ fn main() { foo4(&0); assert_eq!(3i32, &3i32); //~^ ERROR mismatched types + let u = 3; + let s = S { u }; + //~^ ERROR mismatched types + let s = S { u: u }; + //~^ ERROR mismatched types + let i = &4; + let r = R { i }; + //~^ ERROR mismatched types + let r = R { i: i }; + //~^ ERROR mismatched types } diff --git a/src/test/ui/deref-suggestion.stderr b/src/test/ui/deref-suggestion.stderr index 8f061b3416e13..9c49f541c9309 100644 --- a/src/test/ui/deref-suggestion.stderr +++ b/src/test/ui/deref-suggestion.stderr @@ -23,7 +23,7 @@ LL | foo3(u); found type `&u32` error[E0308]: mismatched types - --> $DIR/deref-suggestion.rs:22:9 + --> $DIR/deref-suggestion.rs:30:9 | LL | foo(&"aaa".to_owned()); | ^^^^^^^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | foo(&"aaa".to_owned()); found type `&std::string::String` error[E0308]: mismatched types - --> $DIR/deref-suggestion.rs:24:9 + --> $DIR/deref-suggestion.rs:32:9 | LL | foo(&mut "aaa".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^ @@ -59,7 +59,7 @@ LL | foo3(borrow!(0)); found type `&{integer}` error[E0308]: mismatched types - --> $DIR/deref-suggestion.rs:28:5 + --> $DIR/deref-suggestion.rs:36:5 | LL | assert_eq!(3i32, &3i32); | ^^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found &i32 @@ -68,6 +68,54 @@ LL | assert_eq!(3i32, &3i32); found type `&i32` = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -error: aborting due to 6 previous errors +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:39:17 + | +LL | let s = S { u }; + | ^ + | | + | expected &u32, found integer + | help: consider borrowing here: `u: &u` + | + = note: expected type `&u32` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:41:20 + | +LL | let s = S { u: u }; + | ^ + | | + | expected &u32, found integer + | help: consider borrowing here: `&u` + | + = note: expected type `&u32` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:44:17 + | +LL | let r = R { i }; + | ^ + | | + | expected u32, found &{integer} + | help: consider dereferencing the borrow: `i: *i` + | + = note: expected type `u32` + found type `&{integer}` + +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:46:20 + | +LL | let r = R { i: i }; + | ^ + | | + | expected u32, found &{integer} + | help: consider dereferencing the borrow: `*i` + | + = note: expected type `u32` + found type `&{integer}` + +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-34334.rs b/src/test/ui/issues/issue-34334.rs index 5c4f5c86a7fde..928d217441ef2 100644 --- a/src/test/ui/issues/issue-34334.rs +++ b/src/test/ui/issues/issue-34334.rs @@ -1,4 +1,10 @@ fn main () { - let sr: Vec<(u32, _, _) = vec![]; //~ ERROR expected one of `,` or `>`, found `=` + let sr: Vec<(u32, _, _) = vec![]; + //~^ ERROR expected one of `,` or `>`, found `=` + //~| ERROR expected value, found struct `Vec` + //~| ERROR mismatched types + //~| ERROR invalid left-hand side expression + //~| ERROR expected expression, found reserved identifier `_` let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); + //~^ ERROR no method named `iter` found for type `()` in the current scope } diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr index 1b0babf939044..51ea0c6a90894 100644 --- a/src/test/ui/issues/issue-34334.stderr +++ b/src/test/ui/issues/issue-34334.stderr @@ -1,10 +1,47 @@ +error: expected expression, found reserved identifier `_` + --> $DIR/issue-34334.rs:2:23 + | +LL | let sr: Vec<(u32, _, _) = vec![]; + | ^ expected expression + error: expected one of `,` or `>`, found `=` --> $DIR/issue-34334.rs:2:29 | LL | let sr: Vec<(u32, _, _) = vec![]; - | -- ^ expected one of `,` or `>` here - | | + | --- ^ expected one of `,` or `>` here + | | | + | | help: use `=` if you meant to assign | while parsing the type for `sr` -error: aborting due to previous error +error[E0423]: expected value, found struct `Vec` + --> $DIR/issue-34334.rs:2:13 + | +LL | let sr: Vec<(u32, _, _) = vec![]; + | ^^^ did you mean `Vec { /* fields */ }`? + +error[E0308]: mismatched types + --> $DIR/issue-34334.rs:2:31 + | +LL | let sr: Vec<(u32, _, _) = vec![]; + | ^^^^^^ expected bool, found struct `std::vec::Vec` + | + = note: expected type `bool` + found type `std::vec::Vec<_>` + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error[E0070]: invalid left-hand side expression + --> $DIR/issue-34334.rs:2:13 + | +LL | let sr: Vec<(u32, _, _) = vec![]; + | ^^^^^^^^^^^^^^^^^^^^^^^^ left-hand of expression not valid + +error[E0599]: no method named `iter` found for type `()` in the current scope + --> $DIR/issue-34334.rs:8:36 + | +LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); + | ^^^^ + +error: aborting due to 6 previous errors +Some errors occurred: E0070, E0308, E0423, E0599. +For more information about an error, try `rustc --explain E0070`. diff --git a/src/test/ui/parser/pat-tuple-1.rs b/src/test/ui/parser/pat-tuple-1.rs index 213fbe371d435..0e49b547f7d0f 100644 --- a/src/test/ui/parser/pat-tuple-1.rs +++ b/src/test/ui/parser/pat-tuple-1.rs @@ -1,5 +1,5 @@ fn main() { - match 0 { + match (0, 1) { (, ..) => {} //~ ERROR expected pattern, found `,` } } diff --git a/src/test/ui/parser/pat-tuple-5.rs b/src/test/ui/parser/pat-tuple-5.rs index 03176abaf49a8..d4f05a5eb523e 100644 --- a/src/test/ui/parser/pat-tuple-5.rs +++ b/src/test/ui/parser/pat-tuple-5.rs @@ -1,5 +1,5 @@ fn main() { - match 0 { + match (0, 1) { (pat ..) => {} //~ ERROR unexpected token: `)` } } diff --git a/src/test/ui/parser/recover-from-bad-variant.rs b/src/test/ui/parser/recover-from-bad-variant.rs new file mode 100644 index 0000000000000..35088fb306882 --- /dev/null +++ b/src/test/ui/parser/recover-from-bad-variant.rs @@ -0,0 +1,14 @@ +enum Enum { + Foo { a: usize, b: usize }, + Bar(usize, usize), +} + +fn main() { + let x = Enum::Foo(a: 3, b: 4); + //~^ ERROR expected type, found `3` + match x { + Enum::Foo(a, b) => {} + //~^ ERROR expected tuple struct/variant, found struct variant `Enum::Foo` + Enum::Bar(a, b) => {} + } +} diff --git a/src/test/ui/parser/recover-from-bad-variant.stderr b/src/test/ui/parser/recover-from-bad-variant.stderr new file mode 100644 index 0000000000000..1eba6d7d52877 --- /dev/null +++ b/src/test/ui/parser/recover-from-bad-variant.stderr @@ -0,0 +1,23 @@ +error: expected type, found `3` + --> $DIR/recover-from-bad-variant.rs:7:26 + | +LL | let x = Enum::Foo(a: 3, b: 4); + | ^ expecting a type here because of type ascription + | + = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `: ` +note: this expression expects an ascribed type after the colon + --> $DIR/recover-from-bad-variant.rs:7:23 + | +LL | let x = Enum::Foo(a: 3, b: 4); + | ^ + = help: this might be indicative of a syntax error elsewhere + +error[E0532]: expected tuple struct/variant, found struct variant `Enum::Foo` + --> $DIR/recover-from-bad-variant.rs:10:9 + | +LL | Enum::Foo(a, b) => {} + | ^^^^^^^^^ did you mean `Enum::Foo { /* fields */ }`? + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0532`. diff --git a/src/test/ui/parser/recover-tuple-pat.rs b/src/test/ui/parser/recover-tuple-pat.rs new file mode 100644 index 0000000000000..488e8db6b8789 --- /dev/null +++ b/src/test/ui/parser/recover-tuple-pat.rs @@ -0,0 +1,12 @@ +fn main() { + let x = (1, 2, 3, 4); + match x { + (1, .., 4) => {} + (1, .=., 4) => { let _: usize = ""; } + //~^ ERROR expected pattern, found `.` + //~| ERROR mismatched types + (.=., 4) => {} + //~^ ERROR expected pattern, found `.` + (1, 2, 3, 4) => {} + } +} diff --git a/src/test/ui/parser/recover-tuple-pat.stderr b/src/test/ui/parser/recover-tuple-pat.stderr new file mode 100644 index 0000000000000..5919aa72355ac --- /dev/null +++ b/src/test/ui/parser/recover-tuple-pat.stderr @@ -0,0 +1,24 @@ +error: expected pattern, found `.` + --> $DIR/recover-tuple-pat.rs:5:13 + | +LL | (1, .=., 4) => { let _: usize = ""; } + | ^ expected pattern + +error: expected pattern, found `.` + --> $DIR/recover-tuple-pat.rs:8:10 + | +LL | (.=., 4) => {} + | ^ expected pattern + +error[E0308]: mismatched types + --> $DIR/recover-tuple-pat.rs:5:41 + | +LL | (1, .=., 4) => { let _: usize = ""; } + | ^^ expected usize, found reference + | + = note: expected type `usize` + found type `&'static str` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/recover-tuple.rs b/src/test/ui/parser/recover-tuple.rs new file mode 100644 index 0000000000000..59e2695dec6dc --- /dev/null +++ b/src/test/ui/parser/recover-tuple.rs @@ -0,0 +1,11 @@ +fn main() { + // no complaints about the tuple not matching the expected type + let x: (usize, usize, usize) = (3, .=.); + //~^ ERROR expected expression, found `.` + // verify that the parser recovers: + let y: usize = ""; //~ ERROR mismatched types + // no complaints about the type + foo(x); +} + +fn foo(_: (usize, usize, usize)) {} diff --git a/src/test/ui/parser/recover-tuple.stderr b/src/test/ui/parser/recover-tuple.stderr new file mode 100644 index 0000000000000..4252fc1fd1e1b --- /dev/null +++ b/src/test/ui/parser/recover-tuple.stderr @@ -0,0 +1,18 @@ +error: expected expression, found `.` + --> $DIR/recover-tuple.rs:3:40 + | +LL | let x: (usize, usize, usize) = (3, .=.); + | ^ expected expression + +error[E0308]: mismatched types + --> $DIR/recover-tuple.rs:6:20 + | +LL | let y: usize = ""; + | ^^ expected usize, found reference + | + = note: expected type `usize` + found type `&'static str` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/trait-object-lifetime-parens.rs b/src/test/ui/parser/trait-object-lifetime-parens.rs index b188e14778be5..43f6497f7e71c 100644 --- a/src/test/ui/parser/trait-object-lifetime-parens.rs +++ b/src/test/ui/parser/trait-object-lifetime-parens.rs @@ -6,7 +6,10 @@ fn f<'a, T: Trait + ('a)>() {} //~ ERROR parenthesized lifetime bounds are not s fn check<'a>() { let _: Box; //~ ERROR parenthesized lifetime bounds are not supported - let _: Box<('a) + Trait>; //~ ERROR expected type, found `'a` + let _: Box<('a) + Trait>; + //~^ ERROR expected type, found `'a` + //~| ERROR expected `:`, found `)` + //~| ERROR chained comparison operators require parentheses } fn main() {} diff --git a/src/test/ui/parser/trait-object-lifetime-parens.stderr b/src/test/ui/parser/trait-object-lifetime-parens.stderr index 084e6d5b11fcd..a31b7aea8fee6 100644 --- a/src/test/ui/parser/trait-object-lifetime-parens.stderr +++ b/src/test/ui/parser/trait-object-lifetime-parens.stderr @@ -10,6 +10,21 @@ error: parenthesized lifetime bounds are not supported LL | let _: Box; | ^^^^ help: remove the parentheses +error: expected `:`, found `)` + --> $DIR/trait-object-lifetime-parens.rs:9:19 + | +LL | let _: Box<('a) + Trait>; + | ^ expected `:` + +error: chained comparison operators require parentheses + --> $DIR/trait-object-lifetime-parens.rs:9:15 + | +LL | let _: Box<('a) + Trait>; + | ^^^^^^^^^^^^^^^ + | + = help: use `::<...>` instead of `<...>` if you meant to specify type arguments + = help: or use `(...)` if you meant to specify fn arguments + error: expected type, found `'a` --> $DIR/trait-object-lifetime-parens.rs:9:17 | @@ -18,5 +33,5 @@ LL | let _: Box<('a) + Trait>; | | | while parsing the type for `_` -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum.rs b/src/test/ui/rfc-2008-non-exhaustive/enum.rs index d9b1a9895104c..7423a970e2e3b 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/enum.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/enum.rs @@ -12,4 +12,48 @@ fn main() { NonExhaustiveEnum::Tuple(_) => "second", NonExhaustiveEnum::Struct { .. } => "third" }; + + // Everything below this is expected to compile successfully. + + let enum_unit = NonExhaustiveEnum::Unit; + + match enum_unit { + NonExhaustiveEnum::Unit => 1, + NonExhaustiveEnum::Tuple(_) => 2, + // This particular arm tests that a enum marked as non-exhaustive + // will not error if its variants are matched exhaustively. + NonExhaustiveEnum::Struct { field } => field, + _ => 0 // no error with wildcard + }; + + match enum_unit { + _ => "no error with only wildcard" + }; + + // #53549: Check that variant constructors can still be called normally. + match NonExhaustiveEnum::Unit { + NonExhaustiveEnum::Unit => {}, + _ => {} + }; + + match NonExhaustiveEnum::Tuple(2) { + NonExhaustiveEnum::Tuple(2) => {}, + _ => {} + }; + + match (NonExhaustiveEnum::Unit {}) { + NonExhaustiveEnum::Unit {} => {}, + _ => {} + }; + + match (NonExhaustiveEnum::Tuple { 0: 2 }) { + NonExhaustiveEnum::Tuple { 0: 2 } => {}, + _ => {} + }; + + match (NonExhaustiveEnum::Struct { field: 2 }) { + NonExhaustiveEnum::Struct { field: 2 } => {}, + _ => {} + }; + } diff --git a/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/enums_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate.rs similarity index 99% rename from src/test/run-pass/rfcs/rfc-2008-non-exhaustive/enums_same_crate.rs rename to src/test/ui/rfc-2008-non-exhaustive/enum_same_crate.rs index 384e099275e9b..a3626bf60b260 100644 --- a/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/enums_same_crate.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate.rs @@ -1,4 +1,5 @@ // run-pass + #![feature(non_exhaustive)] #[non_exhaustive] diff --git a/src/test/ui/rfc-2008-non-exhaustive/structs.rs b/src/test/ui/rfc-2008-non-exhaustive/struct.rs similarity index 73% rename from src/test/ui/rfc-2008-non-exhaustive/structs.rs rename to src/test/ui/rfc-2008-non-exhaustive/struct.rs index 303d71d12df33..94ac588d24083 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/structs.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/struct.rs @@ -35,3 +35,15 @@ fn main() { let UnitStruct { } = us; //~^ ERROR `..` required with struct marked as non-exhaustive } + +// Everything below this is expected to compile successfully. + +// We only test matching here as we cannot create non-exhaustive +// structs from another crate. ie. they'll never pass in run-pass tests. +fn match_structs(ns: NormalStruct, ts: TupleStruct, us: UnitStruct) { + let NormalStruct { first_field, second_field, .. } = ns; + + let TupleStruct { 0: first, 1: second, .. } = ts; + + let UnitStruct { .. } = us; +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/structs.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr similarity index 88% rename from src/test/ui/rfc-2008-non-exhaustive/structs.stderr rename to src/test/ui/rfc-2008-non-exhaustive/struct.stderr index 6213c392a9b47..ecfad88a82552 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/structs.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr @@ -1,29 +1,29 @@ error[E0423]: expected function, found struct `TupleStruct` - --> $DIR/structs.rs:20:14 + --> $DIR/struct.rs:20:14 | LL | let ts = TupleStruct(640, 480); | ^^^^^^^^^^^ constructor is not visible here due to private fields error[E0423]: expected value, found struct `UnitStruct` - --> $DIR/structs.rs:29:14 + --> $DIR/struct.rs:29:14 | LL | let us = UnitStruct; | ^^^^^^^^^^ constructor is not visible here due to private fields error[E0603]: tuple struct `TupleStruct` is private - --> $DIR/structs.rs:23:32 + --> $DIR/struct.rs:23:32 | LL | let ts_explicit = structs::TupleStruct(640, 480); | ^^^^^^^^^^^ error[E0603]: unit struct `UnitStruct` is private - --> $DIR/structs.rs:32:32 + --> $DIR/struct.rs:32:32 | LL | let us_explicit = structs::UnitStruct; | ^^^^^^^^^^ error[E0639]: cannot create non-exhaustive struct using struct expression - --> $DIR/structs.rs:7:14 + --> $DIR/struct.rs:7:14 | LL | let fr = FunctionalRecord { | ______________^ @@ -35,25 +35,25 @@ LL | | }; | |_____^ error[E0639]: cannot create non-exhaustive struct using struct expression - --> $DIR/structs.rs:14:14 + --> $DIR/struct.rs:14:14 | LL | let ns = NormalStruct { first_field: 640, second_field: 480 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0638]: `..` required with struct marked as non-exhaustive - --> $DIR/structs.rs:17:9 + --> $DIR/struct.rs:17:9 | LL | let NormalStruct { first_field, second_field } = ns; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0638]: `..` required with struct marked as non-exhaustive - --> $DIR/structs.rs:26:9 + --> $DIR/struct.rs:26:9 | LL | let TupleStruct { 0: first_field, 1: second_field } = ts; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0638]: `..` required with struct marked as non-exhaustive - --> $DIR/structs.rs:35:9 + --> $DIR/struct.rs:35:9 | LL | let UnitStruct { } = us; | ^^^^^^^^^^^^^^ diff --git a/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/structs_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/structs_same_crate.rs similarity index 99% rename from src/test/run-pass/rfcs/rfc-2008-non-exhaustive/structs_same_crate.rs rename to src/test/ui/rfc-2008-non-exhaustive/structs_same_crate.rs index 5e71cce1297cb..2b1d7d9ac5030 100644 --- a/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/structs_same_crate.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/structs_same_crate.rs @@ -1,4 +1,5 @@ // run-pass + #![allow(unused_variables)] #![feature(non_exhaustive)] diff --git a/src/test/ui/rfc-2008-non-exhaustive/variants.rs b/src/test/ui/rfc-2008-non-exhaustive/variant.rs similarity index 50% rename from src/test/ui/rfc-2008-non-exhaustive/variants.rs rename to src/test/ui/rfc-2008-non-exhaustive/variant.rs index 373bbc3547f38..bc346aea51cfc 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/variants.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/variant.rs @@ -1,26 +1,33 @@ // aux-build:variants.rs + extern crate variants; use variants::NonExhaustiveVariants; -/* - * The initial implementation of #[non_exhaustive] (RFC 2008) does not include support for - * variants. See issue #44109 and PR 45394. - */ -// ignore-test - fn main() { let variant_struct = NonExhaustiveVariants::Struct { field: 640 }; //~^ ERROR cannot create non-exhaustive variant - let variant_tuple = NonExhaustiveVariants::Tuple { 0: 640 }; - //~^ ERROR cannot create non-exhaustive variant + let variant_tuple = NonExhaustiveVariants::Tuple(640); + //~^ ERROR tuple variant `Tuple` is private [E0603] + + let variant_unit = NonExhaustiveVariants::Unit; + //~^ ERROR unit variant `Unit` is private [E0603] match variant_struct { NonExhaustiveVariants::Unit => "", + //~^ ERROR unit variant `Unit` is private [E0603] NonExhaustiveVariants::Tuple(fe_tpl) => "", - //~^ ERROR `..` required with variant marked as non-exhaustive + //~^ ERROR tuple variant `Tuple` is private [E0603] NonExhaustiveVariants::Struct { field } => "" //~^ ERROR `..` required with variant marked as non-exhaustive }; + + if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct { + //~^ ERROR tuple variant `Tuple` is private [E0603] + } + + if let NonExhaustiveVariants::Struct { field } = variant_struct { + //~^ ERROR `..` required with variant marked as non-exhaustive + } } diff --git a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr new file mode 100644 index 0000000000000..edfca78915017 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr @@ -0,0 +1,52 @@ +error[E0603]: tuple variant `Tuple` is private + --> $DIR/variant.rs:11:48 + | +LL | let variant_tuple = NonExhaustiveVariants::Tuple(640); + | ^^^^^ + +error[E0603]: unit variant `Unit` is private + --> $DIR/variant.rs:14:47 + | +LL | let variant_unit = NonExhaustiveVariants::Unit; + | ^^^^ + +error[E0603]: unit variant `Unit` is private + --> $DIR/variant.rs:18:32 + | +LL | NonExhaustiveVariants::Unit => "", + | ^^^^ + +error[E0603]: tuple variant `Tuple` is private + --> $DIR/variant.rs:20:32 + | +LL | NonExhaustiveVariants::Tuple(fe_tpl) => "", + | ^^^^^ + +error[E0603]: tuple variant `Tuple` is private + --> $DIR/variant.rs:26:35 + | +LL | if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct { + | ^^^^^ + +error[E0639]: cannot create non-exhaustive variant using struct expression + --> $DIR/variant.rs:8:26 + | +LL | let variant_struct = NonExhaustiveVariants::Struct { field: 640 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0638]: `..` required with variant marked as non-exhaustive + --> $DIR/variant.rs:22:9 + | +LL | NonExhaustiveVariants::Struct { field } => "" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0638]: `..` required with variant marked as non-exhaustive + --> $DIR/variant.rs:30:12 + | +LL | if let NonExhaustiveVariants::Struct { field } = variant_struct { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors + +Some errors occurred: E0603, E0638, E0639. +For more information about an error, try `rustc --explain E0603`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/variants_create.rs b/src/test/ui/rfc-2008-non-exhaustive/variants_create.rs deleted file mode 100644 index 9ed244144dff9..0000000000000 --- a/src/test/ui/rfc-2008-non-exhaustive/variants_create.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![feature(non_exhaustive)] - -/* - * The initial implementation of #[non_exhaustive] (RFC 2008) does not include support for - * variants. See issue #44109 and PR 45394. - */ - -pub enum NonExhaustiveVariants { - #[non_exhaustive] Unit, - //~^ ERROR #[non_exhaustive] is not yet supported on variants - #[non_exhaustive] Tuple(u32), - //~^ ERROR #[non_exhaustive] is not yet supported on variants - #[non_exhaustive] Struct { field: u32 } - //~^ ERROR #[non_exhaustive] is not yet supported on variants -} - -fn main() { } diff --git a/src/test/ui/rfc-2008-non-exhaustive/variants_create.stderr b/src/test/ui/rfc-2008-non-exhaustive/variants_create.stderr deleted file mode 100644 index 5b099d58ec467..0000000000000 --- a/src/test/ui/rfc-2008-non-exhaustive/variants_create.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: #[non_exhaustive] is not yet supported on variants - --> $DIR/variants_create.rs:9:23 - | -LL | #[non_exhaustive] Unit, - | ^^^^ - -error: #[non_exhaustive] is not yet supported on variants - --> $DIR/variants_create.rs:11:23 - | -LL | #[non_exhaustive] Tuple(u32), - | ^^^^^^^^^^ - -error: #[non_exhaustive] is not yet supported on variants - --> $DIR/variants_create.rs:13:23 - | -LL | #[non_exhaustive] Struct { field: u32 } - | ^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - diff --git a/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/variants_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/variants_same_crate.rs similarity index 76% rename from src/test/run-pass/rfcs/rfc-2008-non-exhaustive/variants_same_crate.rs rename to src/test/ui/rfc-2008-non-exhaustive/variants_same_crate.rs index 603e69b9ff9b0..470a5ea9833ad 100644 --- a/src/test/run-pass/rfcs/rfc-2008-non-exhaustive/variants_same_crate.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/variants_same_crate.rs @@ -1,11 +1,6 @@ // run-pass -#![feature(non_exhaustive)] -/* - * The initial implementation of #[non_exhaustive] (RFC 2008) does not include support for - * variants. See issue #44109 and PR 45394. - */ -// ignore-test +#![feature(non_exhaustive)] pub enum NonExhaustiveVariants { #[non_exhaustive] Unit,