Skip to content

Rollup of 10 pull requests #59550

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 35 commits into from
Mar 30, 2019
Merged
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
4187560
Add comments for new `AdtDef` functions.
davidtwco Mar 22, 2019
4e7ec07
Account for short-hand field syntax when suggesting borrow
estebank Mar 27, 2019
a51ca02
Expand test
estebank Mar 27, 2019
e3918cf
Recover from parse error in tuple syntax
estebank Mar 27, 2019
8fd3be5
fix broken download link in the armhf-gnu image
pietroalbini Mar 28, 2019
3a88cd7
Implement `#[non_exhaustive]` on variants.
davidtwco Mar 22, 2019
b7dc8e7
fix text after rebase
estebank Mar 29, 2019
9ea6790
Deduplicate parse recovery code
estebank Mar 29, 2019
07857f7
review comments
estebank Mar 28, 2019
e995fa8
implement `AsRawFd` for stdio locks
euclio Mar 29, 2019
1893841
Update documentation.
davidtwco Mar 23, 2019
49a6da2
Support non-exhaustive enum variants in rustdoc.
davidtwco Mar 23, 2019
ff33b27
Whitelist `rustc_on_unimplemented` to avoid erroneous flagging as an …
pnkfelix Mar 29, 2019
3592079
revert change to test file as per review request
estebank Mar 29, 2019
0b96697
Regression test for incremental treatment of rustc_on_unimplemented.
pnkfelix Mar 29, 2019
7642f10
Whitelist rustc_layout_scalar_valid_range_{start,end} so incr comp do…
pnkfelix Mar 29, 2019
cbbd4d5
Regression test for incremental treatment of rustc_scalar_valid_range…
pnkfelix Mar 29, 2019
f10e444
Edited the dbg! docs stating that dbg! works the same way in release …
Mar 29, 2019
9240092
Adjusted the indentation.
Mar 29, 2019
fe210d0
Update src/libstd/macros.rs
Centril Mar 29, 2019
8705de4
Update src/libstd/macros.rs
Centril Mar 29, 2019
ddfa47f
Fix incorrect code
estebank Mar 29, 2019
9e4ec7a
Collapse blanket impls in the same way as normal impls
laurmaedje Mar 29, 2019
b6fb3e3
In doc examples, don't ignore read/write results
mbrubeck Mar 29, 2019
7ce0b67
Fix OnceWith docstring.
goffrie Mar 29, 2019
d050a15
Rollup merge of #59376 - davidtwco:finally-rfc-2008-variants, r=petro…
Centril Mar 30, 2019
c28704c
Rollup merge of #59453 - estebank:recover-tuple-parse, r=petrochenkov
Centril Mar 30, 2019
41e64b6
Rollup merge of #59455 - estebank:borrow-sugg-shorthand-field, r=davi…
Centril Mar 30, 2019
3de2821
Rollup merge of #59499 - pietroalbini:fix-arm-broken-link, r=alexcric…
Centril Mar 30, 2019
1b1b864
Rollup merge of #59512 - euclio:stdio-locks, r=sfackler
Centril Mar 30, 2019
11e1b3e
Rollup merge of #59525 - pnkfelix:whitelist-some-rustc-attrs, r=petro…
Centril Mar 30, 2019
183afcd
Rollup merge of #59528 - DevQps:improve-dbg-macro-docs, r=Centril
Centril Mar 30, 2019
931151f
Rollup merge of #59532 - mbrubeck:docs, r=Centril
Centril Mar 30, 2019
ca14c56
Rollup merge of #59534 - laurmaedje:collapse-blanket-impls, r=Guillau…
Centril Mar 30, 2019
62a78c4
Rollup merge of #59537 - goffrie:patch-3, r=Centril
Centril Mar 30, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/ci/docker/armhf-gnu/Dockerfile
Original file line number Diff line number Diff line change
@@ -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
11 changes: 6 additions & 5 deletions src/doc/unstable-book/src/language-features/non-exhaustive.md
Original file line number Diff line number Diff line change
@@ -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;
```

4 changes: 2 additions & 2 deletions src/libcore/iter/sources.rs
Original file line number Diff line number Diff line change
@@ -375,8 +375,8 @@ pub fn once<T>(value: T) -> Once<T> {
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.
14 changes: 12 additions & 2 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
@@ -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) => {
9 changes: 7 additions & 2 deletions src/librustc_metadata/encoder.rs
Original file line number Diff line number Diff line change
@@ -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(),
9 changes: 0 additions & 9 deletions src/librustc_passes/ast_validation.rs
Original file line number Diff line number Diff line change
@@ -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);
}
21 changes: 20 additions & 1 deletion src/librustc_privacy/lib.rs
Original file line number Diff line number Diff line change
@@ -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) {
10 changes: 9 additions & 1 deletion src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
@@ -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.
71 changes: 55 additions & 16 deletions src/librustc_typeck/check/demand.rs
Original file line number Diff line number Diff line change
@@ -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)
},
));
}
}
13 changes: 7 additions & 6 deletions src/librustc_typeck/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -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.
3 changes: 3 additions & 0 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
@@ -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
}
15 changes: 14 additions & 1 deletion src/librustdoc/html/render.rs
Original file line number Diff line number Diff line change
@@ -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, "<div class='docblock non-exhaustive non-exhaustive-{}'>", {
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, "</code></span>")?;
document(w, cx, variant)?;
document_non_exhaustive(w, variant)?;

use crate::clean::{Variant, VariantKind};
if let clean::VariantItem(Variant {
13 changes: 13 additions & 0 deletions src/librustdoc/html/static/main.js
Original file line number Diff line number Diff line change
@@ -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");
}
}
}

25 changes: 19 additions & 6 deletions src/libstd/io/mod.rs
Original file line number Diff line number Diff line change
@@ -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 {
8 changes: 7 additions & 1 deletion src/libstd/macros.rs
Original file line number Diff line number Diff line change
@@ -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 {
15 changes: 15 additions & 0 deletions src/libstd/sys/redox/ext/io.rs
Original file line number Diff line number Diff line change
@@ -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 {
15 changes: 15 additions & 0 deletions src/libstd/sys/unix/ext/io.rs
Original file line number Diff line number Diff line change
@@ -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 }
}
21 changes: 21 additions & 0 deletions src/libstd/sys/windows/ext/io.rs
Original file line number Diff line number Diff line change
@@ -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 {
16 changes: 15 additions & 1 deletion src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
@@ -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 \
83 changes: 57 additions & 26 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
@@ -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<Expr>>,
) -> P<Expr> {
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<P<Pat>>, Option<usize>, 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)
}
27 changes: 27 additions & 0 deletions src/test/incremental/issue-59523-on-implemented-is-not-unused.rs
Original file line number Diff line number Diff line change
@@ -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<Idx: ?Sized> {
type Output: ?Sized;
fn index(&self, index: Idx) -> &Self::Output;
}

#[rustc_on_unimplemented = "a usize is required to index into a slice"]
impl Index<usize> for [i32] {
type Output = i32;
fn index(&self, index: usize) -> &i32 {
&self[index]
}
}

fn main() {
Index::<usize>::index(&[1, 2, 3] as &[i32], 2);
}
Original file line number Diff line number Diff line change
@@ -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;
}
10 changes: 0 additions & 10 deletions src/test/run-pass/rfcs/rfc-2008-non-exhaustive/auxiliary/enums.rs

This file was deleted.

This file was deleted.

This file was deleted.

53 changes: 0 additions & 53 deletions src/test/run-pass/rfcs/rfc-2008-non-exhaustive/enums.rs

This file was deleted.

20 changes: 0 additions & 20 deletions src/test/run-pass/rfcs/rfc-2008-non-exhaustive/structs.rs

This file was deleted.

22 changes: 0 additions & 22 deletions src/test/run-pass/rfcs/rfc-2008-non-exhaustive/variants.rs

This file was deleted.

18 changes: 18 additions & 0 deletions src/test/ui/deref-suggestion.rs
Original file line number Diff line number Diff line change
@@ -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
}
56 changes: 52 additions & 4 deletions src/test/ui/deref-suggestion.stderr
Original file line number Diff line number Diff line change
@@ -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`.
8 changes: 7 additions & 1 deletion src/test/ui/issues/issue-34334.rs
Original file line number Diff line number Diff line change
@@ -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
}
43 changes: 40 additions & 3 deletions src/test/ui/issues/issue-34334.stderr
Original file line number Diff line number Diff line change
@@ -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`.
2 changes: 1 addition & 1 deletion src/test/ui/parser/pat-tuple-1.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
fn main() {
match 0 {
match (0, 1) {
(, ..) => {} //~ ERROR expected pattern, found `,`
}
}
2 changes: 1 addition & 1 deletion src/test/ui/parser/pat-tuple-5.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
fn main() {
match 0 {
match (0, 1) {
(pat ..) => {} //~ ERROR unexpected token: `)`
}
}
14 changes: 14 additions & 0 deletions src/test/ui/parser/recover-from-bad-variant.rs
Original file line number Diff line number Diff line change
@@ -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) => {}
}
}
23 changes: 23 additions & 0 deletions src/test/ui/parser/recover-from-bad-variant.stderr
Original file line number Diff line number Diff line change
@@ -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: `<expr>: <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`.
12 changes: 12 additions & 0 deletions src/test/ui/parser/recover-tuple-pat.rs
Original file line number Diff line number Diff line change
@@ -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) => {}
}
}
24 changes: 24 additions & 0 deletions src/test/ui/parser/recover-tuple-pat.stderr
Original file line number Diff line number Diff line change
@@ -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`.
11 changes: 11 additions & 0 deletions src/test/ui/parser/recover-tuple.rs
Original file line number Diff line number Diff line change
@@ -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)) {}
18 changes: 18 additions & 0 deletions src/test/ui/parser/recover-tuple.stderr
Original file line number Diff line number Diff line change
@@ -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`.
5 changes: 4 additions & 1 deletion src/test/ui/parser/trait-object-lifetime-parens.rs
Original file line number Diff line number Diff line change
@@ -6,7 +6,10 @@ fn f<'a, T: Trait + ('a)>() {} //~ ERROR parenthesized lifetime bounds are not s

fn check<'a>() {
let _: Box<Trait + ('a)>; //~ 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() {}
17 changes: 16 additions & 1 deletion src/test/ui/parser/trait-object-lifetime-parens.stderr
Original file line number Diff line number Diff line change
@@ -10,6 +10,21 @@ error: parenthesized lifetime bounds are not supported
LL | let _: Box<Trait + ('a)>;
| ^^^^ 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

44 changes: 44 additions & 0 deletions src/test/ui/rfc-2008-non-exhaustive/enum.rs
Original file line number Diff line number Diff line change
@@ -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 } => {},
_ => {}
};

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// run-pass

#![feature(non_exhaustive)]

#[non_exhaustive]
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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;
| ^^^^^^^^^^^^^^
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// run-pass

#![allow(unused_variables)]
#![feature(non_exhaustive)]

Original file line number Diff line number Diff line change
@@ -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
}
}
52 changes: 52 additions & 0 deletions src/test/ui/rfc-2008-non-exhaustive/variant.stderr
Original file line number Diff line number Diff line change
@@ -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`.
17 changes: 0 additions & 17 deletions src/test/ui/rfc-2008-non-exhaustive/variants_create.rs

This file was deleted.

20 changes: 0 additions & 20 deletions src/test/ui/rfc-2008-non-exhaustive/variants_create.stderr

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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,