Auto merge of #143459 - matthiaskrgr:rollup-gsv6uzl, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - rust-lang/rust#141532 (std: sys: net: uefi: tcp4: Implement write) - rust-lang/rust#143085 (Port `#[non_exhaustive]` to the new attribute parsing infrastructure) - rust-lang/rust#143372 (Remove names_imported_by_glob_use query.) - rust-lang/rust#143386 (Assign dependency bump PRs to me) - rust-lang/rust#143406 (Remove some unnecessary `unsafe` in VecCache) - rust-lang/rust#143408 (mbe: Gracefully handle macro rules that end after `=>`) - rust-lang/rust#143414 (remove special-casing of boxes from match exhaustiveness/usefulness analysis) - rust-lang/rust#143444 (clean up GVN TypeId test) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
d98a5da813
39 changed files with 387 additions and 182 deletions
1
.github/workflows/dependencies.yml
vendored
1
.github/workflows/dependencies.yml
vendored
|
|
@ -19,6 +19,7 @@ env:
|
|||
PR_TITLE: Weekly `cargo update`
|
||||
PR_MESSAGE: |
|
||||
Automation to keep dependencies in `Cargo.lock` current.
|
||||
r? dep-bumps
|
||||
|
||||
The following is the output from `cargo update`:
|
||||
COMMIT_MESSAGE: "cargo update \n\n"
|
||||
|
|
|
|||
|
|
@ -284,6 +284,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[no_mangle]`
|
||||
NoMangle(Span),
|
||||
|
||||
/// Represents `#[non_exhaustive]`
|
||||
NonExhaustive(Span),
|
||||
|
||||
/// Represents `#[optimize(size|speed)]`
|
||||
Optimize(OptimizeAttr, Span),
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ impl AttributeKind {
|
|||
Naked(..) => No,
|
||||
NoImplicitPrelude(..) => No,
|
||||
NoMangle(..) => No,
|
||||
NonExhaustive(..) => Yes,
|
||||
Optimize(..) => No,
|
||||
PassByValue(..) => Yes,
|
||||
PubTransparent(..) => Yes,
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ pub(crate) mod lint_helpers;
|
|||
pub(crate) mod loop_match;
|
||||
pub(crate) mod must_use;
|
||||
pub(crate) mod no_implicit_prelude;
|
||||
pub(crate) mod non_exhaustive;
|
||||
pub(crate) mod repr;
|
||||
pub(crate) mod rustc_internal;
|
||||
pub(crate) mod semantics;
|
||||
|
|
|
|||
13
compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs
Normal file
13
compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
use rustc_attr_data_structures::AttributeKind;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
||||
use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
|
||||
use crate::context::Stage;
|
||||
|
||||
pub(crate) struct NonExhaustiveParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for NonExhaustiveParser {
|
||||
const PATH: &[Symbol] = &[sym::non_exhaustive];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::NonExhaustive;
|
||||
}
|
||||
|
|
@ -27,6 +27,7 @@ use crate::attributes::lint_helpers::{AsPtrParser, PassByValueParser, PubTranspa
|
|||
use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
|
||||
use crate::attributes::must_use::MustUseParser;
|
||||
use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
|
||||
use crate::attributes::non_exhaustive::NonExhaustiveParser;
|
||||
use crate::attributes::repr::{AlignParser, ReprParser};
|
||||
use crate::attributes::rustc_internal::{
|
||||
RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
|
||||
|
|
@ -144,6 +145,7 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<MayDangleParser>>,
|
||||
Single<WithoutArgs<NoImplicitPreludeParser>>,
|
||||
Single<WithoutArgs<NoMangleParser>>,
|
||||
Single<WithoutArgs<NonExhaustiveParser>>,
|
||||
Single<WithoutArgs<PassByValueParser>>,
|
||||
Single<WithoutArgs<PubTransparentParser>>,
|
||||
Single<WithoutArgs<TrackCallerParser>>,
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ impl SlotIndex {
|
|||
index_in_bucket: idx as usize,
|
||||
};
|
||||
}
|
||||
// SAFETY: We already ruled out idx 0, so `checked_ilog2` can't return `None`.
|
||||
let bucket = unsafe { idx.checked_ilog2().unwrap_unchecked() as usize };
|
||||
// We already ruled out idx 0, so this `ilog2` never panics (and the check optimizes away)
|
||||
let bucket = idx.ilog2() as usize;
|
||||
let entries = 1 << bucket;
|
||||
SlotIndex {
|
||||
bucket_idx: bucket - FIRST_BUCKET_SHIFT + 1,
|
||||
|
|
|
|||
|
|
@ -411,6 +411,15 @@ pub fn compile_declarative_macro(
|
|||
if let Err(e) = p.expect(exp!(FatArrow)) {
|
||||
return dummy_syn_ext(e.emit());
|
||||
}
|
||||
if p.token == token::Eof {
|
||||
let err_sp = p.token.span.shrink_to_hi();
|
||||
let guar = sess
|
||||
.dcx()
|
||||
.struct_span_err(err_sp, "macro definition ended unexpectedly")
|
||||
.with_span_label(err_sp, "expected right-hand side of macro rule")
|
||||
.emit();
|
||||
return dummy_syn_ext(guar);
|
||||
}
|
||||
let rhs_tt = p.parse_token_tree();
|
||||
let rhs_tt = mbe::quoted::parse(
|
||||
&TokenStream::new(vec![rhs_tt]),
|
||||
|
|
|
|||
|
|
@ -779,9 +779,11 @@ fn lower_variant<'tcx>(
|
|||
fields,
|
||||
parent_did.to_def_id(),
|
||||
recovered,
|
||||
adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive)
|
||||
|| variant_did
|
||||
.is_some_and(|variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)),
|
||||
adt_kind == AdtKind::Struct
|
||||
&& find_attr!(tcx.get_all_attrs(parent_did), AttributeKind::NonExhaustive(..))
|
||||
|| variant_did.is_some_and(|variant_did| {
|
||||
find_attr!(tcx.get_all_attrs(variant_did), AttributeKind::NonExhaustive(..))
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2264,9 +2264,6 @@ rustc_queries! {
|
|||
query maybe_unused_trait_imports(_: ()) -> &'tcx FxIndexSet<LocalDefId> {
|
||||
desc { "fetching potentially unused trait imports" }
|
||||
}
|
||||
query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx FxIndexSet<Symbol> {
|
||||
desc { |tcx| "finding names imported by glob use for `{}`", tcx.def_path_str(def_id) }
|
||||
}
|
||||
|
||||
query stability_index(_: ()) -> &'tcx stability::Index {
|
||||
arena_cache
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use std::ops::Range;
|
|||
use std::str;
|
||||
|
||||
use rustc_abi::{FIRST_VARIANT, ReprOptions, VariantIdx};
|
||||
use rustc_attr_data_structures::{AttributeKind, find_attr};
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::intern::Interned;
|
||||
|
|
@ -278,7 +279,9 @@ impl AdtDefData {
|
|||
debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
|
||||
let mut flags = AdtFlags::NO_ADT_FLAGS;
|
||||
|
||||
if kind == AdtKind::Enum && tcx.has_attr(did, sym::non_exhaustive) {
|
||||
if kind == AdtKind::Enum
|
||||
&& find_attr!(tcx.get_all_attrs(did), AttributeKind::NonExhaustive(..))
|
||||
{
|
||||
debug!("found non-exhaustive variant list for {:?}", did);
|
||||
flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3417,10 +3417,6 @@ pub struct DeducedParamAttrs {
|
|||
pub fn provide(providers: &mut Providers) {
|
||||
providers.maybe_unused_trait_imports =
|
||||
|tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports;
|
||||
providers.names_imported_by_glob_use = |tcx, id| {
|
||||
tcx.arena.alloc(tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default())
|
||||
};
|
||||
|
||||
providers.extern_mod_stmt_cnum =
|
||||
|tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned();
|
||||
providers.is_panic_runtime =
|
||||
|
|
|
|||
|
|
@ -319,9 +319,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
}
|
||||
PatKind::Deref { subpattern }
|
||||
}
|
||||
hir::PatKind::Box(subpattern) => {
|
||||
PatKind::Deref { subpattern: self.lower_pattern(subpattern) }
|
||||
}
|
||||
hir::PatKind::Box(subpattern) => PatKind::DerefPattern {
|
||||
subpattern: self.lower_pattern(subpattern),
|
||||
borrow: hir::ByRef::No,
|
||||
},
|
||||
|
||||
hir::PatKind::Slice(prefix, slice, suffix) => {
|
||||
self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix)
|
||||
|
|
|
|||
|
|
@ -303,6 +303,7 @@ fn emit_malformed_attribute(
|
|||
| sym::rustc_allow_const_fn_unstable
|
||||
| sym::naked
|
||||
| sym::no_mangle
|
||||
| sym::non_exhaustive
|
||||
| sym::must_use
|
||||
| sym::track_caller
|
||||
| sym::link_name
|
||||
|
|
|
|||
|
|
@ -194,6 +194,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
Attribute::Parsed(AttributeKind::TrackCaller(attr_span)) => {
|
||||
self.check_track_caller(hir_id, *attr_span, attrs, span, target)
|
||||
}
|
||||
Attribute::Parsed(AttributeKind::NonExhaustive(attr_span)) => {
|
||||
self.check_non_exhaustive(hir_id, *attr_span, span, target, item)
|
||||
}
|
||||
Attribute::Parsed(
|
||||
AttributeKind::RustcLayoutScalarValidRangeStart(_num, attr_span)
|
||||
| AttributeKind::RustcLayoutScalarValidRangeEnd(_num, attr_span),
|
||||
|
|
@ -237,7 +240,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
[sym::no_sanitize, ..] => {
|
||||
self.check_no_sanitize(attr, span, target)
|
||||
}
|
||||
[sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target, item),
|
||||
[sym::marker, ..] => self.check_marker(hir_id, attr, span, target),
|
||||
[sym::thread_local, ..] => self.check_thread_local(attr, span, target),
|
||||
[sym::doc, ..] => self.check_doc_attrs(
|
||||
|
|
@ -779,7 +781,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
fn check_non_exhaustive(
|
||||
&self,
|
||||
hir_id: HirId,
|
||||
attr: &Attribute,
|
||||
attr_span: Span,
|
||||
span: Span,
|
||||
target: Target,
|
||||
item: Option<ItemLike<'_>>,
|
||||
|
|
@ -794,7 +796,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
&& fields.iter().any(|f| f.default.is_some())
|
||||
{
|
||||
self.dcx().emit_err(errors::NonExhaustiveWithDefaultFieldValues {
|
||||
attr_span: attr.span(),
|
||||
attr_span,
|
||||
defn_span: span,
|
||||
});
|
||||
}
|
||||
|
|
@ -805,13 +807,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
// erroneously allowed it and some crates used it accidentally, to be compatible
|
||||
// with crates depending on them, we can't throw an error here.
|
||||
Target::Field | Target::Arm | Target::MacroDef => {
|
||||
self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "non_exhaustive");
|
||||
self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "non_exhaustive");
|
||||
}
|
||||
_ => {
|
||||
self.dcx().emit_err(errors::NonExhaustiveWrongLocation {
|
||||
attr_span: attr.span(),
|
||||
defn_span: span,
|
||||
});
|
||||
self.dcx()
|
||||
.emit_err(errors::NonExhaustiveWrongLocation { attr_span, defn_span: span });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -221,27 +221,19 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
|||
let slice = match ctor {
|
||||
Struct | Variant(_) | UnionField => match ty.kind() {
|
||||
ty::Tuple(fs) => reveal_and_alloc(cx, fs.iter()),
|
||||
ty::Adt(adt, args) => {
|
||||
if adt.is_box() {
|
||||
// The only legal patterns of type `Box` (outside `std`) are `_` and box
|
||||
// patterns. If we're here we can assume this is a box pattern.
|
||||
reveal_and_alloc(cx, once(args.type_at(0)))
|
||||
} else {
|
||||
let variant =
|
||||
&adt.variant(RustcPatCtxt::variant_index_for_adt(&ctor, *adt));
|
||||
let tys = cx.variant_sub_tys(ty, variant).map(|(field, ty)| {
|
||||
let is_visible =
|
||||
adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
|
||||
let is_uninhabited = cx.is_uninhabited(*ty);
|
||||
let is_unstable =
|
||||
cx.tcx.lookup_stability(field.did).is_some_and(|stab| {
|
||||
stab.is_unstable() && stab.feature != sym::rustc_private
|
||||
});
|
||||
let skip = is_uninhabited && (!is_visible || is_unstable);
|
||||
(ty, PrivateUninhabitedField(skip))
|
||||
ty::Adt(adt, _) => {
|
||||
let variant = &adt.variant(RustcPatCtxt::variant_index_for_adt(&ctor, *adt));
|
||||
let tys = cx.variant_sub_tys(ty, variant).map(|(field, ty)| {
|
||||
let is_visible =
|
||||
adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
|
||||
let is_uninhabited = cx.is_uninhabited(*ty);
|
||||
let is_unstable = cx.tcx.lookup_stability(field.did).is_some_and(|stab| {
|
||||
stab.is_unstable() && stab.feature != sym::rustc_private
|
||||
});
|
||||
cx.dropless_arena.alloc_from_iter(tys)
|
||||
}
|
||||
let skip = is_uninhabited && (!is_visible || is_unstable);
|
||||
(ty, PrivateUninhabitedField(skip))
|
||||
});
|
||||
cx.dropless_arena.alloc_from_iter(tys)
|
||||
}
|
||||
_ => bug!("Unexpected type for constructor `{ctor:?}`: {ty:?}"),
|
||||
},
|
||||
|
|
@ -273,14 +265,8 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
|||
Struct | Variant(_) | UnionField => match ty.kind() {
|
||||
ty::Tuple(fs) => fs.len(),
|
||||
ty::Adt(adt, ..) => {
|
||||
if adt.is_box() {
|
||||
// The only legal patterns of type `Box` (outside `std`) are `_` and box
|
||||
// patterns. If we're here we can assume this is a box pattern.
|
||||
1
|
||||
} else {
|
||||
let variant_idx = RustcPatCtxt::variant_index_for_adt(&ctor, *adt);
|
||||
adt.variant(variant_idx).fields.len()
|
||||
}
|
||||
let variant_idx = RustcPatCtxt::variant_index_for_adt(&ctor, *adt);
|
||||
adt.variant(variant_idx).fields.len()
|
||||
}
|
||||
_ => bug!("Unexpected type for constructor `{ctor:?}`: {ty:?}"),
|
||||
},
|
||||
|
|
@ -470,8 +456,6 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
|||
fields = vec![self.lower_pat(subpattern).at_index(0)];
|
||||
arity = 1;
|
||||
ctor = match ty.kind() {
|
||||
// This is a box pattern.
|
||||
ty::Adt(adt, ..) if adt.is_box() => Struct,
|
||||
ty::Ref(..) => Ref,
|
||||
_ => span_bug!(
|
||||
pat.span,
|
||||
|
|
@ -501,28 +485,6 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
|||
.map(|ipat| self.lower_pat(&ipat.pattern).at_index(ipat.field.index()))
|
||||
.collect();
|
||||
}
|
||||
ty::Adt(adt, _) if adt.is_box() => {
|
||||
// The only legal patterns of type `Box` (outside `std`) are `_` and box
|
||||
// patterns. If we're here we can assume this is a box pattern.
|
||||
// FIXME(Nadrieril): A `Box` can in theory be matched either with `Box(_,
|
||||
// _)` or a box pattern. As a hack to avoid an ICE with the former, we
|
||||
// ignore other fields than the first one. This will trigger an error later
|
||||
// anyway.
|
||||
// See https://github.com/rust-lang/rust/issues/82772,
|
||||
// explanation: https://github.com/rust-lang/rust/pull/82789#issuecomment-796921977
|
||||
// The problem is that we can't know from the type whether we'll match
|
||||
// normally or through box-patterns. We'll have to figure out a proper
|
||||
// solution when we introduce generalized deref patterns. Also need to
|
||||
// prevent mixing of those two options.
|
||||
let pattern = subpatterns.into_iter().find(|pat| pat.field.index() == 0);
|
||||
if let Some(pat) = pattern {
|
||||
fields = vec![self.lower_pat(&pat.pattern).at_index(0)];
|
||||
} else {
|
||||
fields = vec![];
|
||||
}
|
||||
ctor = Struct;
|
||||
arity = 1;
|
||||
}
|
||||
ty::Adt(adt, _) => {
|
||||
ctor = match pat.kind {
|
||||
PatKind::Leaf { .. } if adt.is_union() => UnionField,
|
||||
|
|
@ -825,11 +787,6 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
|||
Bool(b) => b.to_string(),
|
||||
Str(s) => s.to_string(),
|
||||
IntRange(range) => return self.print_pat_range(range, *pat.ty()),
|
||||
Struct if pat.ty().is_box() => {
|
||||
// Outside of the `alloc` crate, the only way to create a struct pattern
|
||||
// of type `Box` is to use a `box` pattern via #[feature(box_patterns)].
|
||||
format!("box {}", print(&pat.fields[0]))
|
||||
}
|
||||
Struct | Variant(_) | UnionField => {
|
||||
let enum_info = match *pat.ty().kind() {
|
||||
ty::Adt(adt_def, _) if adt_def.is_enum() => EnumInfo::Enum {
|
||||
|
|
@ -866,6 +823,14 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
|||
print::write_ref_like(&mut s, pat.ty().inner(), &print(&pat.fields[0])).unwrap();
|
||||
s
|
||||
}
|
||||
DerefPattern(_) if pat.ty().is_box() && !self.tcx.features().deref_patterns() => {
|
||||
// FIXME(deref_patterns): Remove this special handling once `box_patterns` is gone.
|
||||
// HACK(@dianne): `box _` syntax is exposed on stable in diagnostics, e.g. to
|
||||
// witness non-exhaustiveness of `match Box::new(0) { Box { .. } if false => {} }`.
|
||||
// To avoid changing diagnostics before deref pattern syntax is finalized, let's use
|
||||
// `box _` syntax unless `deref_patterns` is enabled.
|
||||
format!("box {}", print(&pat.fields[0]))
|
||||
}
|
||||
DerefPattern(_) => format!("deref!({})", print(&pat.fields[0])),
|
||||
Slice(slice) => {
|
||||
let (prefix_len, has_dot_dot) = match slice.kind {
|
||||
|
|
@ -964,12 +929,8 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
|
|||
ty: &Self::Ty,
|
||||
) -> fmt::Result {
|
||||
if let ty::Adt(adt, _) = ty.kind() {
|
||||
if adt.is_box() {
|
||||
write!(f, "Box")?
|
||||
} else {
|
||||
let variant = adt.variant(Self::variant_index_for_adt(ctor, *adt));
|
||||
write!(f, "{}", variant.name)?;
|
||||
}
|
||||
let variant = adt.variant(Self::variant_index_for_adt(ctor, *adt));
|
||||
write!(f, "{}", variant.name)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use rustc_ast::{
|
|||
self as ast, CRATE_NODE_ID, Crate, ItemKind, MetaItemInner, MetaItemKind, ModKind, NodeId, Path,
|
||||
};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_attr_data_structures::{self as attr, Stability};
|
||||
use rustc_attr_data_structures::{self as attr, AttributeKind, Stability, find_attr};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||
use rustc_errors::codes::*;
|
||||
|
|
@ -1998,9 +1998,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
// Otherwise, point out if the struct has any private fields.
|
||||
if let Some(def_id) = res.opt_def_id()
|
||||
&& !def_id.is_local()
|
||||
&& let Some(attr) = self.tcx.get_attr(def_id, sym::non_exhaustive)
|
||||
&& let Some(attr_span) = find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::NonExhaustive(span) => *span)
|
||||
{
|
||||
non_exhaustive = Some(attr.span());
|
||||
non_exhaustive = Some(attr_span);
|
||||
} else if let Some(span) = ctor_fields_span {
|
||||
let label = errors::ConstructorPrivateIfAnyFieldPrivate { span };
|
||||
err.subdiagnostic(label);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use crate::time::Duration;
|
|||
mod tcp;
|
||||
pub(crate) mod tcp4;
|
||||
|
||||
pub struct TcpStream(#[expect(dead_code)] tcp::Tcp);
|
||||
pub struct TcpStream(tcp::Tcp);
|
||||
|
||||
impl TcpStream {
|
||||
pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
|
||||
|
|
@ -54,12 +54,13 @@ impl TcpStream {
|
|||
false
|
||||
}
|
||||
|
||||
pub fn write(&self, _: &[u8]) -> io::Result<usize> {
|
||||
unsupported()
|
||||
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.0.write(buf)
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
unsupported()
|
||||
pub fn write_vectored(&self, buf: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
// FIXME: UEFI does support vectored write, so implement that.
|
||||
crate::io::default_write_vectored(|b| self.write(b), buf)
|
||||
}
|
||||
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use crate::io;
|
|||
use crate::net::SocketAddr;
|
||||
|
||||
pub(crate) enum Tcp {
|
||||
V4(#[expect(dead_code)] tcp4::Tcp4),
|
||||
V4(tcp4::Tcp4),
|
||||
}
|
||||
|
||||
impl Tcp {
|
||||
|
|
@ -18,4 +18,10 @@ impl Tcp {
|
|||
SocketAddr::V6(_) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
match self {
|
||||
Self::V4(client) => client.write(buf),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,6 +88,46 @@ impl Tcp4 {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
let evt = unsafe { self.create_evt() }?;
|
||||
let completion_token =
|
||||
tcp4::CompletionToken { event: evt.as_ptr(), status: Status::SUCCESS };
|
||||
let data_len = u32::try_from(buf.len()).unwrap_or(u32::MAX);
|
||||
|
||||
let fragment = tcp4::FragmentData {
|
||||
fragment_length: data_len,
|
||||
fragment_buffer: buf.as_ptr().cast::<crate::ffi::c_void>().cast_mut(),
|
||||
};
|
||||
let mut tx_data = tcp4::TransmitData {
|
||||
push: r_efi::efi::Boolean::FALSE,
|
||||
urgent: r_efi::efi::Boolean::FALSE,
|
||||
data_length: data_len,
|
||||
fragment_count: 1,
|
||||
fragment_table: [fragment],
|
||||
};
|
||||
|
||||
let protocol = self.protocol.as_ptr();
|
||||
let mut token = tcp4::IoToken {
|
||||
completion_token,
|
||||
packet: tcp4::IoTokenPacket {
|
||||
tx_data: (&raw mut tx_data).cast::<tcp4::TransmitData<0>>(),
|
||||
},
|
||||
};
|
||||
|
||||
let r = unsafe { ((*protocol).transmit)(protocol, &mut token) };
|
||||
if r.is_error() {
|
||||
return Err(io::Error::from_raw_os_error(r.as_usize()));
|
||||
}
|
||||
|
||||
self.wait_for_flag();
|
||||
|
||||
if completion_token.status.is_error() {
|
||||
Err(io::Error::from_raw_os_error(completion_token.status.as_usize()))
|
||||
} else {
|
||||
Ok(data_len as usize)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn create_evt(&self) -> io::Result<helpers::OwnedEvent> {
|
||||
self.flag.store(false, Ordering::Relaxed);
|
||||
helpers::OwnedEvent::new(
|
||||
|
|
|
|||
|
|
@ -621,7 +621,7 @@ impl Item {
|
|||
}
|
||||
|
||||
pub(crate) fn is_non_exhaustive(&self) -> bool {
|
||||
self.attrs.other_attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
|
||||
find_attr!(&self.attrs.other_attrs, AttributeKind::NonExhaustive(..))
|
||||
}
|
||||
|
||||
/// Returns a documentation-level item type from the item.
|
||||
|
|
@ -776,6 +776,8 @@ impl Item {
|
|||
} else if let hir::Attribute::Parsed(AttributeKind::ExportName { name, .. }) = attr
|
||||
{
|
||||
Some(format!("#[export_name = \"{name}\"]"))
|
||||
} else if let hir::Attribute::Parsed(AttributeKind::NonExhaustive(..)) = attr {
|
||||
Some("#[non_exhaustive]".to_string())
|
||||
} else if is_json {
|
||||
match attr {
|
||||
// rustdoc-json stores this in `Item::deprecation`, so we
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ use rustc_errors::Applicability;
|
|||
use rustc_hir::{Item, ItemKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::sym;
|
||||
use rustc_attr_data_structures::AttributeKind;
|
||||
use rustc_attr_data_structures::find_attr;
|
||||
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -85,7 +87,7 @@ impl LateLintPass<'_> for ExhaustiveItems {
|
|||
};
|
||||
if cx.effective_visibilities.is_exported(item.owner_id.def_id)
|
||||
&& let attrs = cx.tcx.hir_attrs(item.hir_id())
|
||||
&& !attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
|
||||
&& !find_attr!(attrs, AttributeKind::NonExhaustive(..))
|
||||
&& fields.iter().all(|f| cx.tcx.visibility(f.def_id).is_public())
|
||||
{
|
||||
span_lint_and_then(cx, lint, item.span, msg, |diag| {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ use clippy_utils::is_doc_hidden;
|
|||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::source::snippet_indent;
|
||||
use itertools::Itertools;
|
||||
use rustc_ast::attr;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
|
||||
|
|
@ -12,7 +11,9 @@ use rustc_hir::{Expr, ExprKind, Item, ItemKind, QPath, TyKind, VariantData};
|
|||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::{Span, sym};
|
||||
use rustc_span::Span;
|
||||
use rustc_attr_data_structures::find_attr;
|
||||
use rustc_attr_data_structures::AttributeKind;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -93,7 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive {
|
|||
.then_some((v.def_id, v.span))
|
||||
});
|
||||
if let Ok((id, span)) = iter.exactly_one()
|
||||
&& !attr::contains_name(cx.tcx.hir_attrs(item.hir_id()), sym::non_exhaustive)
|
||||
&& !find_attr!(cx.tcx.hir_attrs(item.hir_id()), AttributeKind::NonExhaustive(..))
|
||||
{
|
||||
self.potential_enums.push((item.owner_id.def_id, id, item.span, span));
|
||||
}
|
||||
|
|
@ -113,10 +114,10 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive {
|
|||
item.span,
|
||||
"this seems like a manual implementation of the non-exhaustive pattern",
|
||||
|diag| {
|
||||
if let Some(non_exhaustive) =
|
||||
attr::find_by_name(cx.tcx.hir_attrs(item.hir_id()), sym::non_exhaustive)
|
||||
if let Some(non_exhaustive_span) =
|
||||
find_attr!(cx.tcx.hir_attrs(item.hir_id()), AttributeKind::NonExhaustive(span) => *span)
|
||||
{
|
||||
diag.span_note(non_exhaustive.span(), "the struct is already non-exhaustive");
|
||||
diag.span_note(non_exhaustive_span, "the struct is already non-exhaustive");
|
||||
} else {
|
||||
let indent = snippet_indent(cx, item.span).unwrap_or_default();
|
||||
diag.span_suggestion_verbose(
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ impl LateLintPass<'_> for WildcardImports {
|
|||
}
|
||||
if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind
|
||||
&& (self.warn_on_all || !self.check_exceptions(cx, item, use_path.segments))
|
||||
&& let used_imports = cx.tcx.names_imported_by_glob_use(item.owner_id.def_id)
|
||||
&& let Some(used_imports) = cx.tcx.resolutions(()).glob_map.get(&item.owner_id.def_id)
|
||||
&& !used_imports.is_empty() // Already handled by `unused_imports`
|
||||
&& !used_imports.contains(&kw::Underscore)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,9 +7,10 @@ use rustc_middle::ty::{AdtDef, TyCtxt};
|
|||
use rustc_session::Session;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use std::str::FromStr;
|
||||
|
||||
use rustc_attr_data_structures::find_attr;
|
||||
use crate::source::SpanRangeExt;
|
||||
use crate::{sym, tokenize_with_text};
|
||||
use rustc_attr_data_structures::AttributeKind;
|
||||
|
||||
/// Deprecation status of attributes known by Clippy.
|
||||
pub enum DeprecationStatus {
|
||||
|
|
@ -165,13 +166,13 @@ pub fn is_doc_hidden(attrs: &[impl AttributeExt]) -> bool {
|
|||
|
||||
pub fn has_non_exhaustive_attr(tcx: TyCtxt<'_>, adt: AdtDef<'_>) -> bool {
|
||||
adt.is_variant_list_non_exhaustive()
|
||||
|| tcx.has_attr(adt.did(), sym::non_exhaustive)
|
||||
|| find_attr!(tcx.get_all_attrs(adt.did()), AttributeKind::NonExhaustive(..))
|
||||
|| adt.variants().iter().any(|variant_def| {
|
||||
variant_def.is_field_list_non_exhaustive() || tcx.has_attr(variant_def.def_id, sym::non_exhaustive)
|
||||
variant_def.is_field_list_non_exhaustive() || find_attr!(tcx.get_all_attrs(variant_def.def_id), AttributeKind::NonExhaustive(..))
|
||||
})
|
||||
|| adt
|
||||
.all_fields()
|
||||
.any(|field_def| tcx.has_attr(field_def.did, sym::non_exhaustive))
|
||||
.any(|field_def| find_attr!(tcx.get_all_attrs(field_def.did), AttributeKind::NonExhaustive(..)))
|
||||
}
|
||||
|
||||
/// Checks if the given span contains a `#[cfg(..)]` attribute
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
- // MIR for `no_optimize` before GVN
|
||||
+ // MIR for `no_optimize` after GVN
|
||||
|
||||
fn no_optimize() -> bool {
|
||||
let mut _0: bool;
|
||||
|
||||
bb0: {
|
||||
_0 = Eq(const no_optimize::<T>::{constant#0}, const no_optimize::<T>::{constant#1});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
- // MIR for `optimize_false` before GVN
|
||||
+ // MIR for `optimize_false` after GVN
|
||||
|
||||
fn optimize_false() -> bool {
|
||||
let mut _0: bool;
|
||||
|
||||
bb0: {
|
||||
- _0 = Eq(const optimize_false::<T>::{constant#0}, const optimize_false::<T>::{constant#1});
|
||||
+ _0 = const false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
- // MIR for `optimize_true` before GVN
|
||||
+ // MIR for `optimize_true` after GVN
|
||||
|
||||
fn optimize_true() -> bool {
|
||||
let mut _0: bool;
|
||||
|
||||
bb0: {
|
||||
- _0 = Eq(const optimize_true::<T>::{constant#0}, const optimize_true::<T>::{constant#1});
|
||||
+ _0 = const true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
57
tests/mir-opt/gvn_const_eval_polymorphic.rs
Normal file
57
tests/mir-opt/gvn_const_eval_polymorphic.rs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
//@ test-mir-pass: GVN
|
||||
//@ compile-flags: --crate-type lib
|
||||
|
||||
//! Regressions test for a mis-optimization where some functions
|
||||
//! (`type_id` / `type_name` / `needs_drop`) could be evaluated in
|
||||
//! a generic context, even though their value depends on some type
|
||||
//! parameter `T`.
|
||||
//!
|
||||
//! In particular, `type_name_of_val(&generic::<T>)` was incorrectly
|
||||
//! evaluated to the string "crate_name::generic::<T>", and
|
||||
//! `no_optimize` was incorrectly optimized to `false`.
|
||||
|
||||
#![feature(const_type_name)]
|
||||
|
||||
fn generic<T>() {}
|
||||
|
||||
const fn type_name_contains_i32<T>(_: &T) -> bool {
|
||||
let pattern = b"i32";
|
||||
let name = std::any::type_name::<T>().as_bytes();
|
||||
let mut i = 0;
|
||||
'outer: while i < name.len() - pattern.len() + 1 {
|
||||
let mut j = 0;
|
||||
while j < pattern.len() {
|
||||
if name[i + j] != pattern[j] {
|
||||
i += 1;
|
||||
continue 'outer;
|
||||
}
|
||||
j += 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
// EMIT_MIR gvn_const_eval_polymorphic.optimize_true.GVN.diff
|
||||
fn optimize_true<T>() -> bool {
|
||||
// CHECK-LABEL: fn optimize_true(
|
||||
// CHECK: _0 = const true;
|
||||
// CHECK-NEXT: return;
|
||||
(const { type_name_contains_i32(&generic::<i32>) }) == const { true }
|
||||
}
|
||||
|
||||
// EMIT_MIR gvn_const_eval_polymorphic.optimize_false.GVN.diff
|
||||
fn optimize_false<T>() -> bool {
|
||||
// CHECK-LABEL: fn optimize_false(
|
||||
// CHECK: _0 = const false;
|
||||
// CHECK-NEXT: return;
|
||||
(const { type_name_contains_i32(&generic::<i64>) }) == const { true }
|
||||
}
|
||||
|
||||
// EMIT_MIR gvn_const_eval_polymorphic.no_optimize.GVN.diff
|
||||
fn no_optimize<T>() -> bool {
|
||||
// CHECK-LABEL: fn no_optimize(
|
||||
// CHECK: _0 = Eq(const no_optimize::<T>::{constant#0}, const no_optimize::<T>::{constant#1});
|
||||
// CHECK-NEXT: return;
|
||||
(const { type_name_contains_i32(&generic::<T>) }) == const { true }
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
- // MIR for `cursed_is_i32` before GVN
|
||||
+ // MIR for `cursed_is_i32` after GVN
|
||||
|
||||
fn cursed_is_i32() -> bool {
|
||||
let mut _0: bool;
|
||||
|
||||
bb0: {
|
||||
_0 = Eq(const cursed_is_i32::<T>::{constant#0}, const cursed_is_i32::<T>::{constant#1});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
//@ test-mir-pass: GVN
|
||||
//@ compile-flags: -C opt-level=2
|
||||
|
||||
#![feature(core_intrinsics)]
|
||||
|
||||
fn generic<T>() {}
|
||||
|
||||
const fn type_id_of_val<T: 'static>(_: &T) -> u128 {
|
||||
std::intrinsics::type_id::<T>()
|
||||
}
|
||||
|
||||
// EMIT_MIR gvn_type_id_polymorphic.cursed_is_i32.GVN.diff
|
||||
fn cursed_is_i32<T: 'static>() -> bool {
|
||||
// CHECK-LABEL: fn cursed_is_i32(
|
||||
// CHECK: _0 = Eq(const cursed_is_i32::<T>::{constant#0}, const cursed_is_i32::<T>::{constant#1});
|
||||
// CHECK-NEXT: return;
|
||||
(const { type_id_of_val(&generic::<T>) } == const { type_id_of_val(&generic::<i32>) })
|
||||
}
|
||||
|
||||
fn main() {
|
||||
dbg!(cursed_is_i32::<i32>());
|
||||
}
|
||||
|
|
@ -206,12 +206,6 @@ error: malformed `automatically_derived` attribute input
|
|||
LL | #[automatically_derived = 18]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[automatically_derived]`
|
||||
|
||||
error: malformed `non_exhaustive` attribute input
|
||||
--> $DIR/malformed-attrs.rs:196:1
|
||||
|
|
||||
LL | #[non_exhaustive = 1]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[non_exhaustive]`
|
||||
|
||||
error: malformed `thread_local` attribute input
|
||||
--> $DIR/malformed-attrs.rs:202:1
|
||||
|
|
||||
|
|
@ -552,6 +546,15 @@ LL | #[rustc_layout_scalar_valid_range_end]
|
|||
| expected this to be a list
|
||||
| help: must be of the form: `#[rustc_layout_scalar_valid_range_end(end)]`
|
||||
|
||||
error[E0565]: malformed `non_exhaustive` attribute input
|
||||
--> $DIR/malformed-attrs.rs:196:1
|
||||
|
|
||||
LL | #[non_exhaustive = 1]
|
||||
| ^^^^^^^^^^^^^^^^^---^
|
||||
| | |
|
||||
| | didn't expect any arguments here
|
||||
| help: must be of the form: `#[non_exhaustive]`
|
||||
|
||||
error: attribute should be applied to `const fn`
|
||||
--> $DIR/malformed-attrs.rs:34:1
|
||||
|
|
||||
|
|
|
|||
|
|
@ -65,18 +65,6 @@ LL | #[should_panic]
|
|||
| ^^^^^^^^^^^^^^^
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr-duplicate.rs:66:1
|
||||
|
|
||||
LL | #[non_exhaustive]
|
||||
| ^^^^^^^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
note: attribute also specified here
|
||||
--> $DIR/unused-attr-duplicate.rs:65:1
|
||||
|
|
||||
LL | #[non_exhaustive]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr-duplicate.rs:70:1
|
||||
|
|
||||
|
|
@ -190,6 +178,18 @@ LL | #[must_use]
|
|||
| ^^^^^^^^^^^
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr-duplicate.rs:66:1
|
||||
|
|
||||
LL | #[non_exhaustive]
|
||||
| ^^^^^^^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
note: attribute also specified here
|
||||
--> $DIR/unused-attr-duplicate.rs:65:1
|
||||
|
|
||||
LL | #[non_exhaustive]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr-duplicate.rs:74:1
|
||||
|
|
||||
|
|
|
|||
22
tests/ui/parser/macro/bad-macro-definition.rs
Normal file
22
tests/ui/parser/macro/bad-macro-definition.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#![crate_type = "lib"]
|
||||
|
||||
macro_rules! a { {} => }
|
||||
//~^ ERROR: macro definition ended unexpectedly
|
||||
|
||||
macro_rules! b { 0 => }
|
||||
//~^ ERROR: macro definition ended unexpectedly
|
||||
//~| ERROR: invalid macro matcher
|
||||
|
||||
macro_rules! c { x => }
|
||||
//~^ ERROR: macro definition ended unexpectedly
|
||||
//~| ERROR: invalid macro matcher
|
||||
|
||||
macro_rules! d { _ => }
|
||||
//~^ ERROR: macro definition ended unexpectedly
|
||||
//~| ERROR: invalid macro matcher
|
||||
|
||||
macro_rules! e { {} }
|
||||
//~^ ERROR: expected `=>`, found end of macro arguments
|
||||
|
||||
macro_rules! f {}
|
||||
//~^ ERROR: macros must contain at least one rule
|
||||
56
tests/ui/parser/macro/bad-macro-definition.stderr
Normal file
56
tests/ui/parser/macro/bad-macro-definition.stderr
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
error: macro definition ended unexpectedly
|
||||
--> $DIR/bad-macro-definition.rs:3:23
|
||||
|
|
||||
LL | macro_rules! a { {} => }
|
||||
| ^ expected right-hand side of macro rule
|
||||
|
||||
error: invalid macro matcher; matchers must be contained in balanced delimiters
|
||||
--> $DIR/bad-macro-definition.rs:6:18
|
||||
|
|
||||
LL | macro_rules! b { 0 => }
|
||||
| ^
|
||||
|
||||
error: macro definition ended unexpectedly
|
||||
--> $DIR/bad-macro-definition.rs:6:22
|
||||
|
|
||||
LL | macro_rules! b { 0 => }
|
||||
| ^ expected right-hand side of macro rule
|
||||
|
||||
error: invalid macro matcher; matchers must be contained in balanced delimiters
|
||||
--> $DIR/bad-macro-definition.rs:10:18
|
||||
|
|
||||
LL | macro_rules! c { x => }
|
||||
| ^
|
||||
|
||||
error: macro definition ended unexpectedly
|
||||
--> $DIR/bad-macro-definition.rs:10:22
|
||||
|
|
||||
LL | macro_rules! c { x => }
|
||||
| ^ expected right-hand side of macro rule
|
||||
|
||||
error: invalid macro matcher; matchers must be contained in balanced delimiters
|
||||
--> $DIR/bad-macro-definition.rs:14:18
|
||||
|
|
||||
LL | macro_rules! d { _ => }
|
||||
| ^
|
||||
|
||||
error: macro definition ended unexpectedly
|
||||
--> $DIR/bad-macro-definition.rs:14:22
|
||||
|
|
||||
LL | macro_rules! d { _ => }
|
||||
| ^ expected right-hand side of macro rule
|
||||
|
||||
error: expected `=>`, found end of macro arguments
|
||||
--> $DIR/bad-macro-definition.rs:18:20
|
||||
|
|
||||
LL | macro_rules! e { {} }
|
||||
| ^ expected `=>`
|
||||
|
||||
error: macros must contain at least one rule
|
||||
--> $DIR/bad-macro-definition.rs:21:1
|
||||
|
|
||||
LL | macro_rules! f {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
|
|
@ -1,8 +1,11 @@
|
|||
error: malformed `non_exhaustive` attribute input
|
||||
error[E0565]: malformed `non_exhaustive` attribute input
|
||||
--> $DIR/invalid-attribute.rs:1:1
|
||||
|
|
||||
LL | #[non_exhaustive(anything)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[non_exhaustive]`
|
||||
| ^^^^^^^^^^^^^^^^----------^
|
||||
| | |
|
||||
| | didn't expect any arguments here
|
||||
| help: must be of the form: `#[non_exhaustive]`
|
||||
|
||||
error[E0701]: attribute should be applied to a struct or enum
|
||||
--> $DIR/invalid-attribute.rs:5:1
|
||||
|
|
@ -27,4 +30,5 @@ LL | | }
|
|||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0701`.
|
||||
Some errors have detailed explanations: E0565, E0701.
|
||||
For more information about an error, try `rustc --explain E0565`.
|
||||
|
|
|
|||
|
|
@ -27,7 +27,11 @@ fn main() {
|
|||
|
||||
let x: Result<Box<NotSoSecretlyEmpty>, &[Result<!, !>]> = Err(&[]);
|
||||
match x {
|
||||
Ok(box _) => (), //~ ERROR unreachable pattern
|
||||
Ok(box _) => (), // We'd get a non-exhaustiveness error if this arm was removed; don't lint.
|
||||
Err(&[]) => (),
|
||||
Err(&[..]) => (),
|
||||
}
|
||||
match x { //~ ERROR non-exhaustive patterns
|
||||
Err(&[]) => (),
|
||||
Err(&[..]) => (),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,26 @@
|
|||
error: unreachable pattern
|
||||
--> $DIR/uninhabited-patterns.rs:30:9
|
||||
error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
|
||||
--> $DIR/uninhabited-patterns.rs:34:11
|
||||
|
|
||||
LL | Ok(box _) => (),
|
||||
| ^^^^^^^^^-------
|
||||
LL | match x {
|
||||
| ^ pattern `Ok(_)` not covered
|
||||
|
|
||||
note: `Result<Box<NotSoSecretlyEmpty>, &[Result<!, !>]>` defined here
|
||||
--> $SRC_DIR/core/src/result.rs:LL:COL
|
||||
::: $SRC_DIR/core/src/result.rs:LL:COL
|
||||
|
|
||||
= note: not covered
|
||||
= note: the matched value is of type `Result<Box<NotSoSecretlyEmpty>, &[Result<!, !>]>`
|
||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
||||
|
|
||||
LL ~ Err(&[..]) => (),
|
||||
LL ~ Ok(_) => todo!(),
|
||||
|
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/uninhabited-patterns.rs:43:9
|
||||
|
|
||||
LL | Err(Ok(_y)) => (),
|
||||
| ^^^^^^^^^^^-------
|
||||
| |
|
||||
| matches no values because `NotSoSecretlyEmpty` is uninhabited
|
||||
| help: remove the match arm
|
||||
|
|
@ -15,18 +33,7 @@ LL | #![deny(unreachable_patterns)]
|
|||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/uninhabited-patterns.rs:39:9
|
||||
|
|
||||
LL | Err(Ok(_y)) => (),
|
||||
| ^^^^^^^^^^^-------
|
||||
| |
|
||||
| matches no values because `NotSoSecretlyEmpty` is uninhabited
|
||||
| help: remove the match arm
|
||||
|
|
||||
= note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/uninhabited-patterns.rs:42:15
|
||||
--> $DIR/uninhabited-patterns.rs:46:15
|
||||
|
|
||||
LL | while let Some(_y) = foo() {
|
||||
| ^^^^^^^^ matches no values because `NotSoSecretlyEmpty` is uninhabited
|
||||
|
|
@ -35,3 +42,4 @@ LL | while let Some(_y) = foo() {
|
|||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0004`.
|
||||
|
|
|
|||
|
|
@ -1404,6 +1404,9 @@ project-exploit-mitigations = [
|
|||
compiletest = [
|
||||
"@jieyouxu",
|
||||
]
|
||||
dep-bumps = [
|
||||
"@clubby789",
|
||||
]
|
||||
|
||||
[assign.owners]
|
||||
"/.github/workflows" = ["infra-ci"]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue