mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-16 17:03:35 +00:00
Auto merge of #94148 - matthiaskrgr:rollup-jgea68f, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #92902 (Improve the documentation of drain members) - #93658 (Stabilize `#[cfg(panic = "...")]`) - #93954 (rustdoc-json: buffer output) - #93979 (Add debug assertions to validate NUL terminator in c strings) - #93990 (pre #89862 cleanup) - #94006 (Use a `Field` in `ConstraintCategory::ClosureUpvar`) - #94086 (Fix ScalarInt to char conversion) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
e08d569360
@ -5,6 +5,7 @@ use rustc_infer::infer::{
|
||||
error_reporting::nice_region_error::NiceRegionError,
|
||||
error_reporting::unexpected_hidden_region_diagnostic, NllRegionVariableOrigin,
|
||||
};
|
||||
use rustc_middle::hir::place::PlaceBase;
|
||||
use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
|
||||
use rustc_middle::ty::subst::{InternalSubsts, Subst};
|
||||
use rustc_middle::ty::{self, RegionVid, Ty};
|
||||
@ -421,17 +422,26 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
|
||||
diag.span_label(*span, message);
|
||||
|
||||
// FIXME(project-rfc-2229#48): This should store a captured_place not a hir id
|
||||
if let ReturnConstraint::ClosureUpvar(upvar) = kind {
|
||||
if let ReturnConstraint::ClosureUpvar(upvar_field) = kind {
|
||||
let def_id = match self.regioncx.universal_regions().defining_ty {
|
||||
DefiningTy::Closure(def_id, _) => def_id,
|
||||
ty => bug!("unexpected DefiningTy {:?}", ty),
|
||||
};
|
||||
|
||||
let upvar_def_span = self.infcx.tcx.hir().span(upvar);
|
||||
let upvar_span = self.infcx.tcx.upvars_mentioned(def_id).unwrap()[&upvar].span;
|
||||
diag.span_label(upvar_def_span, "variable defined here");
|
||||
diag.span_label(upvar_span, "variable captured here");
|
||||
let captured_place = &self.upvars[upvar_field.index()].place;
|
||||
let defined_hir = match captured_place.place.base {
|
||||
PlaceBase::Local(hirid) => Some(hirid),
|
||||
PlaceBase::Upvar(upvar) => Some(upvar.var_path.hir_id),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if defined_hir.is_some() {
|
||||
let upvars_map = self.infcx.tcx.upvars_mentioned(def_id).unwrap();
|
||||
let upvar_def_span = self.infcx.tcx.hir().span(defined_hir.unwrap());
|
||||
let upvar_span = upvars_map.get(&defined_hir.unwrap()).unwrap().span;
|
||||
diag.span_label(upvar_def_span, "variable defined here");
|
||||
diag.span_label(upvar_span, "variable captured here");
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(fr_span) = self.give_region_a_name(*outlived_fr).unwrap().span() {
|
||||
|
@ -2530,9 +2530,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
body,
|
||||
);
|
||||
let category = if let Some(field) = field {
|
||||
let var_hir_id = self.borrowck_context.upvars[field.index()].place.get_root_variable();
|
||||
// FIXME(project-rfc-2229#8): Use Place for better diagnostics
|
||||
ConstraintCategory::ClosureUpvar(var_hir_id)
|
||||
ConstraintCategory::ClosureUpvar(field)
|
||||
} else {
|
||||
ConstraintCategory::Boring
|
||||
};
|
||||
|
@ -70,6 +70,8 @@ declare_features! (
|
||||
(accepted, cfg_attr_multi, "1.33.0", Some(54881), None),
|
||||
/// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests.
|
||||
(accepted, cfg_doctest, "1.40.0", Some(62210), None),
|
||||
/// Enables `#[cfg(panic = "...")]` config key.
|
||||
(accepted, cfg_panic, "1.60.0", Some(77443), None),
|
||||
/// Allows `cfg(target_feature = "...")`.
|
||||
(accepted, cfg_target_feature, "1.27.0", Some(29717), None),
|
||||
/// Allows `cfg(target_vendor = "...")`.
|
||||
|
@ -306,8 +306,6 @@ declare_features! (
|
||||
(active, c_variadic, "1.34.0", Some(44930), None),
|
||||
/// Allows capturing disjoint fields in a closure/generator (RFC 2229).
|
||||
(incomplete, capture_disjoint_fields, "1.49.0", Some(53488), None),
|
||||
/// Enables `#[cfg(panic = "...")]` config key.
|
||||
(active, cfg_panic, "1.49.0", Some(77443), None),
|
||||
/// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
|
||||
(active, cfg_sanitize, "1.41.0", Some(39699), None),
|
||||
/// Allows `cfg(target_abi = "...")`.
|
||||
|
@ -34,7 +34,6 @@ const GATED_CFGS: &[GatedCfg] = &[
|
||||
(sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
|
||||
(sym::sanitize, sym::cfg_sanitize, cfg_fn!(cfg_sanitize)),
|
||||
(sym::version, sym::cfg_version, cfg_fn!(cfg_version)),
|
||||
(sym::panic, sym::cfg_panic, cfg_fn!(cfg_panic)),
|
||||
];
|
||||
|
||||
/// Find a gated cfg determined by the `pred`icate which is given the cfg's name.
|
||||
|
@ -497,16 +497,32 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
let ty_to_string = |ty: Ty<'tcx>| -> String {
|
||||
let mut s = String::new();
|
||||
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
let ty_vars = inner.type_variables();
|
||||
let getter = move |ty_vid| {
|
||||
let var_origin = ty_vars.var_origin(ty_vid);
|
||||
if let TypeVariableOriginKind::TypeParameterDefinition(name, _) = var_origin.kind {
|
||||
return Some(name.to_string());
|
||||
let ty_getter = move |ty_vid| {
|
||||
if let TypeVariableOriginKind::TypeParameterDefinition(name, _) =
|
||||
self.inner.borrow_mut().type_variables().var_origin(ty_vid).kind
|
||||
{
|
||||
Some(name.to_string())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
None
|
||||
};
|
||||
printer.name_resolver = Some(Box::new(&getter));
|
||||
printer.ty_infer_name_resolver = Some(Box::new(ty_getter));
|
||||
let const_getter = move |ct_vid| {
|
||||
if let ConstVariableOriginKind::ConstParameterDefinition(name, _) = self
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.const_unification_table()
|
||||
.probe_value(ct_vid)
|
||||
.origin
|
||||
.kind
|
||||
{
|
||||
return Some(name.to_string());
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
printer.const_infer_name_resolver = Some(Box::new(const_getter));
|
||||
|
||||
let _ = if let ty::FnDef(..) = ty.kind() {
|
||||
// We don't want the regular output for `fn`s because it includes its path in
|
||||
// invalid pseudo-syntax, we want the `fn`-pointer output instead.
|
||||
|
@ -341,7 +341,7 @@ pub enum ConstraintCategory {
|
||||
/// like `Foo { field: my_val }`)
|
||||
Usage,
|
||||
OpaqueType,
|
||||
ClosureUpvar(hir::HirId),
|
||||
ClosureUpvar(Field),
|
||||
|
||||
/// A constraint from a user-written predicate
|
||||
/// with the provided span, written on the item
|
||||
@ -363,7 +363,7 @@ pub enum ConstraintCategory {
|
||||
#[derive(TyEncodable, TyDecodable, HashStable)]
|
||||
pub enum ReturnConstraint {
|
||||
Normal,
|
||||
ClosureUpvar(hir::HirId),
|
||||
ClosureUpvar(Field),
|
||||
}
|
||||
|
||||
/// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
|
||||
|
@ -294,12 +294,22 @@ impl From<char> for ScalarInt {
|
||||
}
|
||||
}
|
||||
|
||||
/// Error returned when a conversion from ScalarInt to char fails.
|
||||
#[derive(Debug)]
|
||||
pub struct CharTryFromScalarInt;
|
||||
|
||||
impl TryFrom<ScalarInt> for char {
|
||||
type Error = Size;
|
||||
type Error = CharTryFromScalarInt;
|
||||
|
||||
#[inline]
|
||||
fn try_from(int: ScalarInt) -> Result<Self, Size> {
|
||||
int.to_bits(Size::from_bytes(std::mem::size_of::<char>()))
|
||||
.map(|u| char::from_u32(u.try_into().unwrap()).unwrap())
|
||||
fn try_from(int: ScalarInt) -> Result<Self, Self::Error> {
|
||||
let Ok(bits) = int.to_bits(Size::from_bytes(std::mem::size_of::<char>())) else {
|
||||
return Err(CharTryFromScalarInt);
|
||||
};
|
||||
match char::from_u32(bits.try_into().unwrap()) {
|
||||
Some(c) => Ok(c),
|
||||
None => Err(CharTryFromScalarInt),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -606,7 +606,7 @@ pub trait PrettyPrinter<'tcx>:
|
||||
ty::Infer(infer_ty) => {
|
||||
let verbose = self.tcx().sess.verbose();
|
||||
if let ty::TyVar(ty_vid) = infer_ty {
|
||||
if let Some(name) = self.infer_ty_name(ty_vid) {
|
||||
if let Some(name) = self.ty_infer_name(ty_vid) {
|
||||
p!(write("{}", name))
|
||||
} else {
|
||||
if verbose {
|
||||
@ -1015,7 +1015,11 @@ pub trait PrettyPrinter<'tcx>:
|
||||
}
|
||||
}
|
||||
|
||||
fn infer_ty_name(&self, _: ty::TyVid) -> Option<String> {
|
||||
fn ty_infer_name(&self, _: ty::TyVid) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
fn const_infer_name(&self, _: ty::ConstVid<'tcx>) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
@ -1203,7 +1207,14 @@ pub trait PrettyPrinter<'tcx>:
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::ConstKind::Infer(..) => print_underscore!(),
|
||||
ty::ConstKind::Infer(infer_ct) => {
|
||||
match infer_ct {
|
||||
ty::InferConst::Var(ct_vid)
|
||||
if let Some(name) = self.const_infer_name(ct_vid) =>
|
||||
p!(write("{}", name)),
|
||||
_ => print_underscore!(),
|
||||
}
|
||||
}
|
||||
ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)),
|
||||
ty::ConstKind::Value(value) => {
|
||||
return self.pretty_print_const_value(value, ct.ty(), print_ty);
|
||||
@ -1559,7 +1570,8 @@ pub struct FmtPrinterData<'a, 'tcx, F> {
|
||||
|
||||
pub region_highlight_mode: RegionHighlightMode<'tcx>,
|
||||
|
||||
pub name_resolver: Option<Box<&'a dyn Fn(ty::TyVid) -> Option<String>>>,
|
||||
pub ty_infer_name_resolver: Option<Box<dyn Fn(ty::TyVid) -> Option<String> + 'a>>,
|
||||
pub const_infer_name_resolver: Option<Box<dyn Fn(ty::ConstVid<'tcx>) -> Option<String> + 'a>>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, F> Deref for FmtPrinter<'a, 'tcx, F> {
|
||||
@ -1588,7 +1600,8 @@ impl<'a, 'tcx, F> FmtPrinter<'a, 'tcx, F> {
|
||||
binder_depth: 0,
|
||||
printed_type_count: 0,
|
||||
region_highlight_mode: RegionHighlightMode::new(tcx),
|
||||
name_resolver: None,
|
||||
ty_infer_name_resolver: None,
|
||||
const_infer_name_resolver: None,
|
||||
}))
|
||||
}
|
||||
}
|
||||
@ -1843,8 +1856,12 @@ impl<'tcx, F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> {
|
||||
}
|
||||
|
||||
impl<'tcx, F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> {
|
||||
fn infer_ty_name(&self, id: ty::TyVid) -> Option<String> {
|
||||
self.0.name_resolver.as_ref().and_then(|func| func(id))
|
||||
fn ty_infer_name(&self, id: ty::TyVid) -> Option<String> {
|
||||
self.0.ty_infer_name_resolver.as_ref().and_then(|func| func(id))
|
||||
}
|
||||
|
||||
fn const_infer_name(&self, id: ty::ConstVid<'tcx>) -> Option<String> {
|
||||
self.0.const_infer_name_resolver.as_ref().and_then(|func| func(id))
|
||||
}
|
||||
|
||||
fn print_value_path(
|
||||
|
@ -17,7 +17,7 @@ use rustc_data_structures::intern::Interned;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_errors::ErrorReported;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_query_system::ich::NodeIdHashingMode;
|
||||
@ -146,6 +146,37 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
hasher.finish()
|
||||
}
|
||||
|
||||
pub fn res_generics_def_id(self, res: Res) -> Option<DefId> {
|
||||
match res {
|
||||
Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => {
|
||||
Some(self.parent(def_id).and_then(|def_id| self.parent(def_id)).unwrap())
|
||||
}
|
||||
Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Struct, _), def_id) => {
|
||||
Some(self.parent(def_id).unwrap())
|
||||
}
|
||||
// Other `DefKind`s don't have generics and would ICE when calling
|
||||
// `generics_of`.
|
||||
Res::Def(
|
||||
DefKind::Struct
|
||||
| DefKind::Union
|
||||
| DefKind::Enum
|
||||
| DefKind::Trait
|
||||
| DefKind::OpaqueTy
|
||||
| DefKind::TyAlias
|
||||
| DefKind::ForeignTy
|
||||
| DefKind::TraitAlias
|
||||
| DefKind::AssocTy
|
||||
| DefKind::Fn
|
||||
| DefKind::AssocFn
|
||||
| DefKind::AssocConst
|
||||
| DefKind::Impl,
|
||||
def_id,
|
||||
) => Some(def_id),
|
||||
Res::Err => None,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_error_field(self, ty: Ty<'tcx>) -> bool {
|
||||
if let ty::Adt(def, substs) = *ty.kind() {
|
||||
for field in def.all_fields() {
|
||||
|
@ -1,7 +1,6 @@
|
||||
use rustc_errors::{Applicability, ErrorReported, StashKey};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::CtorOf;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::intravisit;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
@ -9,7 +8,7 @@ use rustc_hir::{HirId, Node};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::ty::subst::InternalSubsts;
|
||||
use rustc_middle::ty::util::IntTypeExt;
|
||||
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeFolder};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
@ -198,38 +197,9 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
|
||||
// Try to use the segment resolution if it is valid, otherwise we
|
||||
// default to the path resolution.
|
||||
let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res);
|
||||
let generics = match res {
|
||||
Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => tcx
|
||||
.generics_of(tcx.parent(def_id).and_then(|def_id| tcx.parent(def_id)).unwrap()),
|
||||
Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Struct, _), def_id) => {
|
||||
tcx.generics_of(tcx.parent(def_id).unwrap())
|
||||
}
|
||||
// Other `DefKind`s don't have generics and would ICE when calling
|
||||
// `generics_of`.
|
||||
Res::Def(
|
||||
DefKind::Struct
|
||||
| DefKind::Union
|
||||
| DefKind::Enum
|
||||
| DefKind::Trait
|
||||
| DefKind::OpaqueTy
|
||||
| DefKind::TyAlias
|
||||
| DefKind::ForeignTy
|
||||
| DefKind::TraitAlias
|
||||
| DefKind::AssocTy
|
||||
| DefKind::Fn
|
||||
| DefKind::AssocFn
|
||||
| DefKind::AssocConst
|
||||
| DefKind::Impl,
|
||||
def_id,
|
||||
) => tcx.generics_of(def_id),
|
||||
Res::Err => {
|
||||
tcx.sess.delay_span_bug(tcx.def_span(def_id), "anon const with Res::Err");
|
||||
return None;
|
||||
}
|
||||
_ => {
|
||||
// If the user tries to specify generics on a type that does not take them,
|
||||
// e.g. `usize<T>`, we may hit this branch, in which case we treat it as if
|
||||
// no arguments have been passed. An error should already have been emitted.
|
||||
let generics = match tcx.res_generics_def_id(res) {
|
||||
Some(def_id) => tcx.generics_of(def_id),
|
||||
None => {
|
||||
tcx.sess.delay_span_bug(
|
||||
tcx.def_span(def_id),
|
||||
&format!("unexpected anon const res {:?} in path: {:?}", res, path),
|
||||
|
@ -746,9 +746,12 @@ impl<T: Ord> BinaryHeap<T> {
|
||||
self.rebuild_tail(start);
|
||||
}
|
||||
|
||||
/// Returns an iterator which retrieves elements in heap order.
|
||||
/// The retrieved elements are removed from the original heap.
|
||||
/// The remaining elements will be removed on drop in heap order.
|
||||
/// Clears the binary heap, returning an iterator over the removed elements
|
||||
/// in heap order. If the iterator is dropped before being fully consumed,
|
||||
/// it drops the remaining elements in heap order.
|
||||
///
|
||||
/// The returned iterator keeps a mutable borrow on the heap to optimize
|
||||
/// its implementation.
|
||||
///
|
||||
/// Note:
|
||||
/// * `.drain_sorted()` is *O*(*n* \* log(*n*)); much slower than `.drain()`.
|
||||
@ -1158,9 +1161,12 @@ impl<T> BinaryHeap<T> {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
/// Clears the binary heap, returning an iterator over the removed elements.
|
||||
/// Clears the binary heap, returning an iterator over the removed elements
|
||||
/// in arbitrary order. If the iterator is dropped before being fully
|
||||
/// consumed, it drops the remaining elements in arbitrary order.
|
||||
///
|
||||
/// The elements are removed in arbitrary order.
|
||||
/// The returned iterator keeps a mutable borrow on the heap to optimize
|
||||
/// its implementation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -1215,21 +1215,25 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
||||
unsafe { IterMut::new(ring, tail, head, PhantomData) }
|
||||
}
|
||||
|
||||
/// Creates a draining iterator that removes the specified range in the
|
||||
/// deque and yields the removed items.
|
||||
/// Removes the specified range from the deque in bulk, returning all
|
||||
/// removed elements as an iterator. If the iterator is dropped before
|
||||
/// being fully consumed, it drops the remaining removed elements.
|
||||
///
|
||||
/// Note 1: The element range is removed even if the iterator is not
|
||||
/// consumed until the end.
|
||||
/// The returned iterator keeps a mutable borrow on the queue to optimize
|
||||
/// its implementation.
|
||||
///
|
||||
/// Note 2: It is unspecified how many elements are removed from the deque,
|
||||
/// if the `Drain` value is not dropped, but the borrow it holds expires
|
||||
/// (e.g., due to `mem::forget`).
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the starting point is greater than the end point or if
|
||||
/// the end point is greater than the length of the deque.
|
||||
///
|
||||
/// # Leaking
|
||||
///
|
||||
/// If the returned iterator goes out of scope without being dropped (due to
|
||||
/// [`mem::forget`], for example), the deque may have lost and leaked
|
||||
/// elements arbitrarily, including elements outside the range.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
@ -1240,7 +1244,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
||||
/// assert_eq!(drained, [3]);
|
||||
/// assert_eq!(deque, [1, 2]);
|
||||
///
|
||||
/// // A full range clears all contents
|
||||
/// // A full range clears all contents, like `clear()` does
|
||||
/// deque.drain(..);
|
||||
/// assert!(deque.is_empty());
|
||||
/// ```
|
||||
|
@ -1628,17 +1628,24 @@ impl String {
|
||||
self.vec.clear()
|
||||
}
|
||||
|
||||
/// Creates a draining iterator that removes the specified range in the `String`
|
||||
/// and yields the removed `chars`.
|
||||
/// Removes the specified range from the string in bulk, returning all
|
||||
/// removed characters as an iterator.
|
||||
///
|
||||
/// Note: The element range is removed even if the iterator is not
|
||||
/// consumed until the end.
|
||||
/// The returned iterator keeps a mutable borrow on the string to optimize
|
||||
/// its implementation.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the starting point or end point do not lie on a [`char`]
|
||||
/// boundary, or if they're out of bounds.
|
||||
///
|
||||
/// # Leaking
|
||||
///
|
||||
/// If the returned iterator goes out of scope without being dropped (due to
|
||||
/// [`core::mem::forget`], for example), the string may still contain a copy
|
||||
/// of any drained characters, or may have lost characters arbitrarily,
|
||||
/// including characters outside the range.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
@ -1652,7 +1659,7 @@ impl String {
|
||||
/// assert_eq!(t, "α is alpha, ");
|
||||
/// assert_eq!(s, "β is beta");
|
||||
///
|
||||
/// // A full range clears the string
|
||||
/// // A full range clears the string, like `clear()` does
|
||||
/// s.drain(..);
|
||||
/// assert_eq!(s, "");
|
||||
/// ```
|
||||
|
@ -1799,19 +1799,24 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||
self.len += count;
|
||||
}
|
||||
|
||||
/// Creates a draining iterator that removes the specified range in the vector
|
||||
/// and yields the removed items.
|
||||
/// Removes the specified range from the vector in bulk, returning all
|
||||
/// removed elements as an iterator. If the iterator is dropped before
|
||||
/// being fully consumed, it drops the remaining removed elements.
|
||||
///
|
||||
/// When the iterator **is** dropped, all elements in the range are removed
|
||||
/// from the vector, even if the iterator was not fully consumed. If the
|
||||
/// iterator **is not** dropped (with [`mem::forget`] for example), it is
|
||||
/// unspecified how many elements are removed.
|
||||
/// The returned iterator keeps a mutable borrow on the vector to optimize
|
||||
/// its implementation.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the starting point is greater than the end point or if
|
||||
/// the end point is greater than the length of the vector.
|
||||
///
|
||||
/// # Leaking
|
||||
///
|
||||
/// If the returned iterator goes out of scope without being dropped (due to
|
||||
/// [`mem::forget`], for example), the vector may have lost and leaked
|
||||
/// elements arbitrarily, including elements outside the range.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
@ -1820,7 +1825,7 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||
/// assert_eq!(v, &[1]);
|
||||
/// assert_eq!(u, &[2, 3]);
|
||||
///
|
||||
/// // A full range clears the vector
|
||||
/// // A full range clears the vector, like `clear()` does
|
||||
/// v.drain(..);
|
||||
/// assert_eq!(v, &[]);
|
||||
/// ```
|
||||
|
@ -6,7 +6,7 @@
|
||||
#![feature(bool_to_option)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(cell_update)]
|
||||
#![feature(cfg_panic)]
|
||||
#![cfg_attr(bootstrap, feature(cfg_panic))]
|
||||
#![cfg_attr(bootstrap, feature(cfg_target_has_atomic))]
|
||||
#![feature(const_assume)]
|
||||
#![feature(const_black_box)]
|
||||
|
@ -547,6 +547,10 @@ impl<K, V, S> HashMap<K, V, S> {
|
||||
/// Clears the map, returning all key-value pairs as an iterator. Keeps the
|
||||
/// allocated memory for reuse.
|
||||
///
|
||||
/// If the returned iterator is dropped before being fully consumed, it
|
||||
/// drops the remaining key-value pairs. The returned iterator keeps a
|
||||
/// mutable borrow on the vector to optimize its implementation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
@ -227,7 +227,12 @@ impl<T, S> HashSet<T, S> {
|
||||
self.base.is_empty()
|
||||
}
|
||||
|
||||
/// Clears the set, returning all elements in an iterator.
|
||||
/// Clears the set, returning all elements as an iterator. Keeps the
|
||||
/// allocated memory for reuse.
|
||||
///
|
||||
/// If the returned iterator is dropped before being fully consumed, it
|
||||
/// drops the remaining elements. The returned iterator keeps a mutable
|
||||
/// borrow on the vector to optimize its implementation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -382,7 +382,7 @@ impl CString {
|
||||
let bytes: Vec<u8> = self.into();
|
||||
match memchr::memchr(0, &bytes) {
|
||||
Some(i) => Err(NulError(i, bytes)),
|
||||
None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
|
||||
None => Ok(unsafe { CString::_from_vec_unchecked(bytes) }),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -405,7 +405,7 @@ impl CString {
|
||||
// This allows better optimizations if lto enabled.
|
||||
match memchr::memchr(0, bytes) {
|
||||
Some(i) => Err(NulError(i, buffer)),
|
||||
None => Ok(unsafe { CString::from_vec_unchecked(buffer) }),
|
||||
None => Ok(unsafe { CString::_from_vec_unchecked(buffer) }),
|
||||
}
|
||||
}
|
||||
|
||||
@ -451,10 +451,15 @@ impl CString {
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
|
||||
pub unsafe fn from_vec_unchecked(v: Vec<u8>) -> Self {
|
||||
debug_assert!(memchr::memchr(0, &v).is_none());
|
||||
unsafe { Self::_from_vec_unchecked(v) }
|
||||
}
|
||||
|
||||
unsafe fn _from_vec_unchecked(mut v: Vec<u8>) -> Self {
|
||||
v.reserve_exact(1);
|
||||
v.push(0);
|
||||
CString { inner: v.into_boxed_slice() }
|
||||
Self { inner: v.into_boxed_slice() }
|
||||
}
|
||||
|
||||
/// Retakes ownership of a `CString` that was transferred to C via
|
||||
@ -578,7 +583,7 @@ impl CString {
|
||||
pub fn into_string(self) -> Result<String, IntoStringError> {
|
||||
String::from_utf8(self.into_bytes()).map_err(|e| IntoStringError {
|
||||
error: e.utf8_error(),
|
||||
inner: unsafe { CString::from_vec_unchecked(e.into_bytes()) },
|
||||
inner: unsafe { Self::_from_vec_unchecked(e.into_bytes()) },
|
||||
})
|
||||
}
|
||||
|
||||
@ -735,6 +740,11 @@ impl CString {
|
||||
#[must_use]
|
||||
#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")]
|
||||
pub unsafe fn from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
|
||||
debug_assert!(memchr::memchr(0, &v).unwrap() + 1 == v.len());
|
||||
unsafe { Self::_from_vec_with_nul_unchecked(v) }
|
||||
}
|
||||
|
||||
unsafe fn _from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
|
||||
Self { inner: v.into_boxed_slice() }
|
||||
}
|
||||
|
||||
@ -778,7 +788,7 @@ impl CString {
|
||||
Some(nul_pos) if nul_pos + 1 == v.len() => {
|
||||
// SAFETY: We know there is only one nul byte, at the end
|
||||
// of the vec.
|
||||
Ok(unsafe { Self::from_vec_with_nul_unchecked(v) })
|
||||
Ok(unsafe { Self::_from_vec_with_nul_unchecked(v) })
|
||||
}
|
||||
Some(nul_pos) => Err(FromVecWithNulError {
|
||||
error_kind: FromBytesWithNulErrorKind::InteriorNul(nul_pos),
|
||||
@ -811,7 +821,7 @@ impl ops::Deref for CString {
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &CStr {
|
||||
unsafe { CStr::from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) }
|
||||
unsafe { CStr::_from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -928,7 +938,7 @@ impl From<Vec<NonZeroU8>> for CString {
|
||||
};
|
||||
// SAFETY: `v` cannot contain null bytes, given the type-level
|
||||
// invariant of `NonZeroU8`.
|
||||
CString::from_vec_unchecked(v)
|
||||
Self::_from_vec_unchecked(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1225,7 +1235,7 @@ impl CStr {
|
||||
unsafe {
|
||||
let len = sys::strlen(ptr);
|
||||
let ptr = ptr as *const u8;
|
||||
CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
|
||||
Self::_from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1268,7 +1278,7 @@ impl CStr {
|
||||
Some(nul_pos) if nul_pos + 1 == bytes.len() => {
|
||||
// SAFETY: We know there is only one nul byte, at the end
|
||||
// of the byte slice.
|
||||
Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) })
|
||||
Ok(unsafe { Self::_from_bytes_with_nul_unchecked(bytes) })
|
||||
}
|
||||
Some(nul_pos) => Err(FromBytesWithNulError::interior_nul(nul_pos)),
|
||||
None => Err(FromBytesWithNulError::not_nul_terminated()),
|
||||
@ -1297,12 +1307,19 @@ impl CStr {
|
||||
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
|
||||
#[rustc_const_stable(feature = "const_cstr_unchecked", since = "1.59.0")]
|
||||
pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
|
||||
// We're in a const fn, so this is the best we can do
|
||||
debug_assert!(!bytes.is_empty() && bytes[bytes.len() - 1] == 0);
|
||||
unsafe { Self::_from_bytes_with_nul_unchecked(bytes) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
const unsafe fn _from_bytes_with_nul_unchecked(bytes: &[u8]) -> &Self {
|
||||
// SAFETY: Casting to CStr is safe because its internal representation
|
||||
// is a [u8] too (safe only inside std).
|
||||
// Dereferencing the obtained pointer is safe because it comes from a
|
||||
// reference. Making a reference is then safe because its lifetime
|
||||
// is bound by the lifetime of the given `bytes`.
|
||||
unsafe { &*(bytes as *const [u8] as *const CStr) }
|
||||
unsafe { &*(bytes as *const [u8] as *const Self) }
|
||||
}
|
||||
|
||||
/// Returns the inner pointer to this C string.
|
||||
@ -1566,7 +1583,7 @@ impl ops::Index<ops::RangeFrom<usize>> for CStr {
|
||||
// byte, since otherwise we could get an empty string that doesn't end
|
||||
// in a null.
|
||||
if index.start < bytes.len() {
|
||||
unsafe { CStr::from_bytes_with_nul_unchecked(&bytes[index.start..]) }
|
||||
unsafe { CStr::_from_bytes_with_nul_unchecked(&bytes[index.start..]) }
|
||||
} else {
|
||||
panic!(
|
||||
"index out of bounds: the len is {} but the index is {}",
|
||||
|
@ -32,14 +32,6 @@ fn build_with_zero2() {
|
||||
assert!(CString::new(vec![0]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_with_zero3() {
|
||||
unsafe {
|
||||
let s = CString::from_vec_unchecked(vec![0]);
|
||||
assert_eq!(s.as_bytes(), b"\0");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn formatted() {
|
||||
let s = CString::new(&b"abc\x01\x02\n\xE2\x80\xA6\xFF"[..]).unwrap();
|
||||
|
@ -1,38 +0,0 @@
|
||||
# `cfg_panic`
|
||||
|
||||
The tracking issue for this feature is: [#77443]
|
||||
|
||||
[#77443]: https://github.com/rust-lang/rust/issues/77443
|
||||
|
||||
------------------------
|
||||
|
||||
The `cfg_panic` feature makes it possible to execute different code
|
||||
depending on the panic strategy.
|
||||
|
||||
Possible values at the moment are `"unwind"` or `"abort"`, although
|
||||
it is possible that new panic strategies may be added to Rust in the
|
||||
future.
|
||||
|
||||
## Examples
|
||||
|
||||
```rust
|
||||
#![feature(cfg_panic)]
|
||||
|
||||
#[cfg(panic = "unwind")]
|
||||
fn a() {
|
||||
// ...
|
||||
}
|
||||
|
||||
#[cfg(not(panic = "unwind"))]
|
||||
fn a() {
|
||||
// ...
|
||||
}
|
||||
|
||||
fn b() {
|
||||
if cfg!(panic = "abort") {
|
||||
// ...
|
||||
} else {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
@ -8,6 +8,7 @@ mod conversions;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::fs::{create_dir_all, File};
|
||||
use std::io::{BufWriter, Write};
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
|
||||
@ -213,7 +214,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
|
||||
let mut index = (*self.index).clone().into_inner();
|
||||
index.extend(self.get_trait_items());
|
||||
// This needs to be the default HashMap for compatibility with the public interface for
|
||||
// rustdoc-json
|
||||
// rustdoc-json-types
|
||||
#[allow(rustc::default_hash_types)]
|
||||
let output = types::Crate {
|
||||
root: types::Id(String::from("0:0")),
|
||||
@ -263,8 +264,10 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
|
||||
let mut p = out_dir;
|
||||
p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
|
||||
p.set_extension("json");
|
||||
let file = try_err!(File::create(&p), p);
|
||||
serde_json::ser::to_writer(&file, &output).unwrap();
|
||||
let mut file = BufWriter::new(try_err!(File::create(&p), p));
|
||||
serde_json::ser::to_writer(&mut file, &output).unwrap();
|
||||
try_err!(file.flush(), p);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -5,39 +5,53 @@
|
||||
let mut _0: (); // return place in scope 0 at $DIR/invalid_constant.rs:15:11: 15:11
|
||||
let _1: std::option::Option<()>; // in scope 0 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
let mut _2: std::option::Option<std::option::Option<()>>; // in scope 0 at $DIR/invalid_constant.rs:16:7: 16:11
|
||||
scope 1 (inlined f) { // at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
debug x => _2; // in scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
let mut _3: isize; // in scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
let _4: std::option::Option<()>; // in scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
scope 2 {
|
||||
debug y => _4; // in scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
let _3: main::Union; // in scope 0 at $DIR/invalid_constant.rs:22:9: 22:22
|
||||
scope 1 {
|
||||
debug _invalid_char => _3; // in scope 1 at $DIR/invalid_constant.rs:22:9: 22:22
|
||||
}
|
||||
scope 2 (inlined f) { // at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
debug x => _2; // in scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
let mut _4: isize; // in scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
let _5: std::option::Option<()>; // in scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
scope 3 {
|
||||
debug y => _5; // in scope 3 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
discriminant(_2) = 0; // scope 0 at $DIR/invalid_constant.rs:16:7: 16:11
|
||||
- _3 = discriminant(_2); // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
- switchInt(move _3) -> [0_isize: bb3, otherwise: bb2]; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
+ _3 = const 0_isize; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
+ switchInt(const 0_isize) -> [0_isize: bb3, otherwise: bb2]; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
- _4 = discriminant(_2); // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
- switchInt(move _4) -> [0_isize: bb3, otherwise: bb2]; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
+ _4 = const 0_isize; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
+ switchInt(const 0_isize) -> [0_isize: bb3, otherwise: bb2]; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
}
|
||||
|
||||
bb1: {
|
||||
nop; // scope 0 at $DIR/invalid_constant.rs:15:11: 17:2
|
||||
return; // scope 0 at $DIR/invalid_constant.rs:17:2: 17:2
|
||||
- _3 = const { Union { int: 0x110001 } }; // scope 0 at $DIR/invalid_constant.rs:22:25: 22:58
|
||||
+ _3 = const main::Union { int: 1114113_u32, chr: {transmute(0x00110001): char} }; // scope 0 at $DIR/invalid_constant.rs:22:25: 22:58
|
||||
// ty::Const
|
||||
// + ty: main::Union
|
||||
- // + val: Unevaluated(main::{constant#0}, [main::Union], None)
|
||||
+ // + val: Value(Scalar(0x00110001))
|
||||
// mir::Constant
|
||||
// + span: $DIR/invalid_constant.rs:22:25: 22:58
|
||||
- // + literal: Const { ty: main::Union, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:8 ~ invalid_constant[726d]::main::{constant#0}), const_param_did: None }, substs: [main::Union], promoted: None }) }
|
||||
+ // + literal: Const { ty: main::Union, val: Value(Scalar(0x00110001)) }
|
||||
nop; // scope 0 at $DIR/invalid_constant.rs:15:11: 23:2
|
||||
return; // scope 0 at $DIR/invalid_constant.rs:23:2: 23:2
|
||||
}
|
||||
|
||||
bb2: {
|
||||
- _4 = ((_2 as Some).0: std::option::Option<()>); // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
- _1 = _4; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
+ _4 = const Scalar(0x02): Option::<()>; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
- _5 = ((_2 as Some).0: std::option::Option<()>); // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
- _1 = _5; // scope 3 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
+ _5 = const Scalar(0x02): Option::<()>; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
+ // ty::Const
|
||||
+ // + ty: std::option::Option<()>
|
||||
+ // + val: Value(Scalar(0x02))
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/invalid_constant.rs:16:5: 16:12
|
||||
+ // + literal: Const { ty: std::option::Option<()>, val: Value(Scalar(0x02)) }
|
||||
+ _1 = const Scalar(0x02): Option::<()>; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
+ _1 = const Scalar(0x02): Option::<()>; // scope 3 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
+ // ty::Const
|
||||
+ // + ty: std::option::Option<()>
|
||||
+ // + val: Value(Scalar(0x02))
|
||||
@ -48,7 +62,7 @@
|
||||
}
|
||||
|
||||
bb3: {
|
||||
discriminant(_1) = 0; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
discriminant(_1) = 0; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
|
||||
goto -> bb1; // scope 0 at $DIR/invalid_constant.rs:9:17: 9:21
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
// by constant propagation. Regression test for issue #93688.
|
||||
//
|
||||
// compile-flags: -Copt-level=0 -Zinline-mir
|
||||
|
||||
#![feature(inline_const)]
|
||||
#[inline(always)]
|
||||
pub fn f(x: Option<Option<()>>) -> Option<()> {
|
||||
match x {
|
||||
@ -14,4 +14,10 @@ pub fn f(x: Option<Option<()>>) -> Option<()> {
|
||||
// EMIT_MIR invalid_constant.main.ConstProp.diff
|
||||
fn main() {
|
||||
f(None);
|
||||
|
||||
union Union {
|
||||
int: u32,
|
||||
chr: char,
|
||||
}
|
||||
let _invalid_char = const { Union { int: 0x110001 } };
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
// build-pass
|
||||
// compile-flags: -C panic=abort
|
||||
// no-prefer-dynamic
|
||||
#![feature(cfg_panic)]
|
||||
|
||||
|
||||
#[cfg(panic = "unwind")]
|
||||
pub fn bad() -> i32 { }
|
||||
|
@ -4,7 +4,7 @@
|
||||
// ignore-emscripten no panic_unwind implementation
|
||||
// ignore-wasm32 no panic_unwind implementation
|
||||
// ignore-wasm64 no panic_unwind implementation
|
||||
#![feature(cfg_panic)]
|
||||
|
||||
|
||||
#[cfg(panic = "abort")]
|
||||
pub fn bad() -> i32 { }
|
||||
|
@ -9,5 +9,5 @@ impl<const N: u32> Foo<N> {
|
||||
fn main() {
|
||||
let foo = Foo::<1>::foo();
|
||||
let foo = Foo::foo();
|
||||
//~^ error: type annotations needed for `Foo<{_: u32}>`
|
||||
//~^ error: type annotations needed for `Foo<N>`
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0282]: type annotations needed for `Foo<{_: u32}>`
|
||||
error[E0282]: type annotations needed for `Foo<N>`
|
||||
--> $DIR/doesnt_infer.rs:11:15
|
||||
|
|
||||
LL | let foo = Foo::foo();
|
||||
|
@ -4,5 +4,5 @@ use std::simd::Mask;
|
||||
|
||||
fn main() {
|
||||
let y = Mask::<_, _>::splat(false);
|
||||
//~^ error: type annotations needed for `Mask<_, {_: usize}>`
|
||||
//~^ ERROR: type annotations needed for
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0283]: type annotations needed for `Mask<_, {_: usize}>`
|
||||
error[E0283]: type annotations needed for `Mask<_, LANES>`
|
||||
--> $DIR/issue-91614.rs:6:13
|
||||
|
|
||||
LL | let y = Mask::<_, _>::splat(false);
|
||||
|
@ -1,11 +0,0 @@
|
||||
#[cfg(panic = "unwind")]
|
||||
//~^ ERROR `cfg(panic)` is experimental and subject to change
|
||||
fn foo() -> bool { true }
|
||||
#[cfg(not(panic = "unwind"))]
|
||||
//~^ ERROR `cfg(panic)` is experimental and subject to change
|
||||
fn foo() -> bool { false }
|
||||
|
||||
|
||||
fn main() {
|
||||
assert!(foo());
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
error[E0658]: `cfg(panic)` is experimental and subject to change
|
||||
--> $DIR/feature-gate-cfg-panic.rs:1:7
|
||||
|
|
||||
LL | #[cfg(panic = "unwind")]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #77443 <https://github.com/rust-lang/rust/issues/77443> for more information
|
||||
= help: add `#![feature(cfg_panic)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `cfg(panic)` is experimental and subject to change
|
||||
--> $DIR/feature-gate-cfg-panic.rs:4:11
|
||||
|
|
||||
LL | #[cfg(not(panic = "unwind"))]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #77443 <https://github.com/rust-lang/rust/issues/77443> for more information
|
||||
= help: add `#![feature(cfg_panic)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -1,5 +1,4 @@
|
||||
// run-pass
|
||||
#![feature(cfg_panic)]
|
||||
|
||||
fn main() {
|
||||
named_argument_takes_precedence_to_captured();
|
||||
|
@ -4,7 +4,6 @@
|
||||
// entering the catch_unwind.
|
||||
//
|
||||
// run-pass
|
||||
#![feature(cfg_panic)]
|
||||
|
||||
use std::panic::catch_unwind;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user