Auto merge of #91033 - JohnTitor:rollup-sr9zg6o, r=JohnTitor

Rollup of 8 pull requests

Successful merges:

 - #89258 (Make char conversion functions unstably const)
 - #90578 (add const generics test)
 - #90633 (Refactor single variant `Candidate` enum into a struct)
 - #90800 (bootstap: create .cargo/config only if not present)
 - #90942 (windows: Return the "Not Found" error when a path is empty)
 - #90947 (Move some tests to more reasonable directories - 9.5)
 - #90961 (Suggest removal of arguments for unit variant, not replacement)
 - #90990 (Arenas cleanup)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-11-19 06:13:29 +00:00
commit e8423e6c44
153 changed files with 325 additions and 401 deletions

View File

@ -111,7 +111,7 @@ impl<T> Default for TypedArena<T> {
// alloc() will trigger a grow().
ptr: Cell::new(ptr::null_mut()),
end: Cell::new(ptr::null_mut()),
chunks: RefCell::new(vec![]),
chunks: Default::default(),
_own: PhantomData,
}
}
@ -325,13 +325,17 @@ unsafe impl<#[may_dangle] T> Drop for TypedArena<T> {
unsafe impl<T: Send> Send for TypedArena<T> {}
/// An arena that can hold objects of multiple different types that impl `Copy`
/// and/or satisfy `!mem::needs_drop`.
pub struct DroplessArena {
/// A pointer to the start of the free space.
start: Cell<*mut u8>,
/// A pointer to the end of free space.
///
/// The allocation proceeds from the end of the chunk towards the start.
/// The allocation proceeds downwards from the end of the chunk towards the
/// start. (This is slightly simpler and faster than allocating upwards,
/// see <https://fitzgeraldnick.com/2019/11/01/always-bump-downwards.html>.)
/// When this pointer crosses the start pointer, a new chunk is allocated.
end: Cell<*mut u8>,
@ -516,10 +520,14 @@ impl DroplessArena {
}
}
// Declare an `Arena` containing one dropless arena and many typed arenas (the
// types of the typed arenas are specified by the arguments). The dropless
// arena will be used for any types that impl `Copy`, and also for any of the
// specified types that satisfy `!mem::needs_drop`.
#[rustc_macro_transparency = "semitransparent"]
pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) {
pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) {
#[derive(Default)]
pub struct Arena<$tcx> {
pub struct Arena<'tcx> {
pub dropless: $crate::DroplessArena,
$($name: $crate::TypedArena<$ty>,)*
}
@ -532,6 +540,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) {
) -> &'a mut [Self];
}
// Any type that impls `Copy` can be arena-allocated in the `DroplessArena`.
impl<'tcx, T: Copy> ArenaAllocatable<'tcx, ()> for T {
#[inline]
fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self {
@ -544,12 +553,11 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) {
) -> &'a mut [Self] {
arena.dropless.alloc_from_iter(iter)
}
}
$(
impl<$tcx> ArenaAllocatable<$tcx, $ty> for $ty {
impl<'tcx> ArenaAllocatable<'tcx, $ty> for $ty {
#[inline]
fn allocate_on<'a>(self, arena: &'a Arena<$tcx>) -> &'a mut Self {
fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self {
if !::std::mem::needs_drop::<Self>() {
arena.dropless.alloc(self)
} else {
@ -559,7 +567,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) {
#[inline]
fn allocate_from_iter<'a>(
arena: &'a Arena<$tcx>,
arena: &'a Arena<'tcx>,
iter: impl ::std::iter::IntoIterator<Item = Self>,
) -> &'a mut [Self] {
if !::std::mem::needs_drop::<Self>() {
@ -577,6 +585,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) {
value.allocate_on(self)
}
// Any type that impls `Copy` can have slices be arena-allocated in the `DroplessArena`.
#[inline]
pub fn alloc_slice<T: ::std::marker::Copy>(&self, value: &[T]) -> &mut [T] {
if value.is_empty() {

View File

@ -84,7 +84,7 @@ mod item;
mod pat;
mod path;
rustc_hir::arena_types!(rustc_arena::declare_arena, 'tcx);
rustc_hir::arena_types!(rustc_arena::declare_arena);
struct LoweringContext<'a, 'hir: 'a> {
/// Used to assign IDs to HIR nodes that do not directly correspond to AST nodes.

View File

@ -93,17 +93,8 @@ impl TempState {
/// returned value in a promoted MIR, unless it's a subset
/// of a larger candidate.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Candidate {
/// Borrow of a constant temporary, candidate for lifetime extension.
Ref(Location),
}
impl Candidate {
fn source_info(&self, body: &Body<'_>) -> SourceInfo {
match self {
Candidate::Ref(location) => *body.source_info(*location),
}
}
pub struct Candidate {
location: Location,
}
struct Collector<'a, 'tcx> {
@ -167,7 +158,7 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> {
match *rvalue {
Rvalue::Ref(..) => {
self.candidates.push(Candidate::Ref(location));
self.candidates.push(Candidate { location });
}
_ => {}
}
@ -209,36 +200,33 @@ struct Unpromotable;
impl<'tcx> Validator<'_, 'tcx> {
fn validate_candidate(&self, candidate: Candidate) -> Result<(), Unpromotable> {
match candidate {
Candidate::Ref(loc) => {
let statement = &self.body[loc.block].statements[loc.statement_index];
match &statement.kind {
StatementKind::Assign(box (_, Rvalue::Ref(_, kind, place))) => {
// We can only promote interior borrows of promotable temps (non-temps
// don't get promoted anyway).
self.validate_local(place.local)?;
let loc = candidate.location;
let statement = &self.body[loc.block].statements[loc.statement_index];
match &statement.kind {
StatementKind::Assign(box (_, Rvalue::Ref(_, kind, place))) => {
// We can only promote interior borrows of promotable temps (non-temps
// don't get promoted anyway).
self.validate_local(place.local)?;
// The reference operation itself must be promotable.
// (Needs to come after `validate_local` to avoid ICEs.)
self.validate_ref(*kind, place)?;
// The reference operation itself must be promotable.
// (Needs to come after `validate_local` to avoid ICEs.)
self.validate_ref(*kind, place)?;
// We do not check all the projections (they do not get promoted anyway),
// but we do stay away from promoting anything involving a dereference.
if place.projection.contains(&ProjectionElem::Deref) {
return Err(Unpromotable);
}
// We cannot promote things that need dropping, since the promoted value
// would not get dropped.
if self.qualif_local::<qualifs::NeedsDrop>(place.local) {
return Err(Unpromotable);
}
Ok(())
}
_ => bug!(),
// We do not check all the projections (they do not get promoted anyway),
// but we do stay away from promoting anything involving a dereference.
if place.projection.contains(&ProjectionElem::Deref) {
return Err(Unpromotable);
}
// We cannot promote things that need dropping, since the promoted value
// would not get dropped.
if self.qualif_local::<qualifs::NeedsDrop>(place.local) {
return Err(Unpromotable);
}
Ok(())
}
_ => bug!(),
}
}
@ -871,58 +859,55 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
}))
};
let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
match candidate {
Candidate::Ref(loc) => {
let statement = &mut blocks[loc.block].statements[loc.statement_index];
match statement.kind {
StatementKind::Assign(box (
_,
Rvalue::Ref(ref mut region, borrow_kind, ref mut place),
)) => {
// Use the underlying local for this (necessarily interior) borrow.
let ty = local_decls.local_decls()[place.local].ty;
let span = statement.source_info.span;
let loc = candidate.location;
let statement = &mut blocks[loc.block].statements[loc.statement_index];
match statement.kind {
StatementKind::Assign(box (
_,
Rvalue::Ref(ref mut region, borrow_kind, ref mut place),
)) => {
// Use the underlying local for this (necessarily interior) borrow.
let ty = local_decls.local_decls()[place.local].ty;
let span = statement.source_info.span;
let ref_ty = tcx.mk_ref(
tcx.lifetimes.re_erased,
ty::TypeAndMut { ty, mutbl: borrow_kind.to_mutbl_lossy() },
);
let ref_ty = tcx.mk_ref(
tcx.lifetimes.re_erased,
ty::TypeAndMut { ty, mutbl: borrow_kind.to_mutbl_lossy() },
);
*region = tcx.lifetimes.re_erased;
*region = tcx.lifetimes.re_erased;
let mut projection = vec![PlaceElem::Deref];
projection.extend(place.projection);
place.projection = tcx.intern_place_elems(&projection);
let mut projection = vec![PlaceElem::Deref];
projection.extend(place.projection);
place.projection = tcx.intern_place_elems(&projection);
// Create a temp to hold the promoted reference.
// This is because `*r` requires `r` to be a local,
// otherwise we would use the `promoted` directly.
let mut promoted_ref = LocalDecl::new(ref_ty, span);
promoted_ref.source_info = statement.source_info;
let promoted_ref = local_decls.push(promoted_ref);
assert_eq!(self.temps.push(TempState::Unpromotable), promoted_ref);
// Create a temp to hold the promoted reference.
// This is because `*r` requires `r` to be a local,
// otherwise we would use the `promoted` directly.
let mut promoted_ref = LocalDecl::new(ref_ty, span);
promoted_ref.source_info = statement.source_info;
let promoted_ref = local_decls.push(promoted_ref);
assert_eq!(self.temps.push(TempState::Unpromotable), promoted_ref);
let promoted_ref_statement = Statement {
source_info: statement.source_info,
kind: StatementKind::Assign(Box::new((
Place::from(promoted_ref),
Rvalue::Use(promoted_operand(ref_ty, span)),
))),
};
self.extra_statements.push((loc, promoted_ref_statement));
let promoted_ref_statement = Statement {
source_info: statement.source_info,
kind: StatementKind::Assign(Box::new((
Place::from(promoted_ref),
Rvalue::Use(promoted_operand(ref_ty, span)),
))),
};
self.extra_statements.push((loc, promoted_ref_statement));
Rvalue::Ref(
tcx.lifetimes.re_erased,
borrow_kind,
Place {
local: mem::replace(&mut place.local, promoted_ref),
projection: List::empty(),
},
)
}
_ => bug!(),
}
Rvalue::Ref(
tcx.lifetimes.re_erased,
borrow_kind,
Place {
local: mem::replace(&mut place.local, promoted_ref),
projection: List::empty(),
},
)
}
_ => bug!(),
}
};
@ -964,17 +949,13 @@ pub fn promote_candidates<'tcx>(
let mut extra_statements = vec![];
for candidate in candidates.into_iter().rev() {
match candidate {
Candidate::Ref(Location { block, statement_index }) => {
if let StatementKind::Assign(box (place, _)) =
&body[block].statements[statement_index].kind
{
if let Some(local) = place.as_local() {
if temps[local] == TempState::PromotedOut {
// Already promoted.
continue;
}
}
let Location { block, statement_index } = candidate.location;
if let StatementKind::Assign(box (place, _)) = &body[block].statements[statement_index].kind
{
if let Some(local) = place.as_local() {
if temps[local] == TempState::PromotedOut {
// Already promoted.
continue;
}
}
}
@ -982,7 +963,7 @@ pub fn promote_candidates<'tcx>(
// Declare return place local so that `mir::Body::new` doesn't complain.
let initial_locals = iter::once(LocalDecl::new(tcx.types.never, body.span)).collect();
let mut scope = body.source_scopes[candidate.source_info(body).scope].clone();
let mut scope = body.source_scopes[body.source_info(candidate.location).scope].clone();
scope.parent_scope = None;
let promoted = Body::new(

View File

@ -1,52 +1,52 @@
/// This declares a list of types which can be allocated by `Arena`.
/// This higher-order macro declares a list of types which can be allocated by `Arena`.
///
/// Specifying the `decode` modifier will add decode impls for `&T` and `&[T]`,
/// where `T` is the type listed. These impls will appear in the implement_ty_decoder! macro.
#[macro_export]
macro_rules! arena_types {
($macro:path, $tcx:lifetime) => (
($macro:path) => (
$macro!([
// HIR types
[] hir_krate: rustc_hir::Crate<$tcx>,
[] arm: rustc_hir::Arm<$tcx>,
[] asm_operand: (rustc_hir::InlineAsmOperand<$tcx>, Span),
[] hir_krate: rustc_hir::Crate<'tcx>,
[] arm: rustc_hir::Arm<'tcx>,
[] asm_operand: (rustc_hir::InlineAsmOperand<'tcx>, Span),
[] asm_template: rustc_ast::InlineAsmTemplatePiece,
[] attribute: rustc_ast::Attribute,
[] block: rustc_hir::Block<$tcx>,
[] bare_fn_ty: rustc_hir::BareFnTy<$tcx>,
[] body: rustc_hir::Body<$tcx>,
[] generic_arg: rustc_hir::GenericArg<$tcx>,
[] generic_args: rustc_hir::GenericArgs<$tcx>,
[] generic_bound: rustc_hir::GenericBound<$tcx>,
[] generic_param: rustc_hir::GenericParam<$tcx>,
[] expr: rustc_hir::Expr<$tcx>,
[] expr_field: rustc_hir::ExprField<$tcx>,
[] pat_field: rustc_hir::PatField<$tcx>,
[] fn_decl: rustc_hir::FnDecl<$tcx>,
[] foreign_item: rustc_hir::ForeignItem<$tcx>,
[] block: rustc_hir::Block<'tcx>,
[] bare_fn_ty: rustc_hir::BareFnTy<'tcx>,
[] body: rustc_hir::Body<'tcx>,
[] generic_arg: rustc_hir::GenericArg<'tcx>,
[] generic_args: rustc_hir::GenericArgs<'tcx>,
[] generic_bound: rustc_hir::GenericBound<'tcx>,
[] generic_param: rustc_hir::GenericParam<'tcx>,
[] expr: rustc_hir::Expr<'tcx>,
[] expr_field: rustc_hir::ExprField<'tcx>,
[] pat_field: rustc_hir::PatField<'tcx>,
[] fn_decl: rustc_hir::FnDecl<'tcx>,
[] foreign_item: rustc_hir::ForeignItem<'tcx>,
[] foreign_item_ref: rustc_hir::ForeignItemRef,
[] impl_item: rustc_hir::ImplItem<$tcx>,
[] impl_item: rustc_hir::ImplItem<'tcx>,
[] impl_item_ref: rustc_hir::ImplItemRef,
[] item: rustc_hir::Item<$tcx>,
[] inline_asm: rustc_hir::InlineAsm<$tcx>,
[] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>,
[] local: rustc_hir::Local<$tcx>,
[] mod_: rustc_hir::Mod<$tcx>,
[] owner_info: rustc_hir::OwnerInfo<$tcx>,
[] param: rustc_hir::Param<$tcx>,
[] pat: rustc_hir::Pat<$tcx>,
[] path: rustc_hir::Path<$tcx>,
[] path_segment: rustc_hir::PathSegment<$tcx>,
[] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>,
[] qpath: rustc_hir::QPath<$tcx>,
[] stmt: rustc_hir::Stmt<$tcx>,
[] field_def: rustc_hir::FieldDef<$tcx>,
[] trait_item: rustc_hir::TraitItem<$tcx>,
[] item: rustc_hir::Item<'tcx>,
[] inline_asm: rustc_hir::InlineAsm<'tcx>,
[] llvm_inline_asm: rustc_hir::LlvmInlineAsm<'tcx>,
[] local: rustc_hir::Local<'tcx>,
[] mod_: rustc_hir::Mod<'tcx>,
[] owner_info: rustc_hir::OwnerInfo<'tcx>,
[] param: rustc_hir::Param<'tcx>,
[] pat: rustc_hir::Pat<'tcx>,
[] path: rustc_hir::Path<'tcx>,
[] path_segment: rustc_hir::PathSegment<'tcx>,
[] poly_trait_ref: rustc_hir::PolyTraitRef<'tcx>,
[] qpath: rustc_hir::QPath<'tcx>,
[] stmt: rustc_hir::Stmt<'tcx>,
[] field_def: rustc_hir::FieldDef<'tcx>,
[] trait_item: rustc_hir::TraitItem<'tcx>,
[] trait_item_ref: rustc_hir::TraitItemRef,
[] ty: rustc_hir::Ty<$tcx>,
[] type_binding: rustc_hir::TypeBinding<$tcx>,
[] variant: rustc_hir::Variant<$tcx>,
[] where_predicate: rustc_hir::WherePredicate<$tcx>,
], $tcx);
[] ty: rustc_hir::Ty<'tcx>,
[] type_binding: rustc_hir::TypeBinding<'tcx>,
[] variant: rustc_hir::Variant<'tcx>,
[] where_predicate: rustc_hir::WherePredicate<'tcx>,
]);
)
}

View File

@ -1,33 +1,33 @@
/// This declares a list of types which can be allocated by `Arena`.
/// This higher-order macro declares a list of types which can be allocated by `Arena`.
///
/// Specifying the `decode` modifier will add decode impls for `&T` and `&[T]` where `T` is the type
/// listed. These impls will appear in the implement_ty_decoder! macro.
#[macro_export]
macro_rules! arena_types {
($macro:path, $tcx:lifetime) => (
($macro:path) => (
$macro!([
[] layout: rustc_target::abi::Layout,
[] fn_abi: rustc_target::abi::call::FnAbi<$tcx, rustc_middle::ty::Ty<$tcx>>,
[] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>,
// AdtDef are interned and compared by address
[] adt_def: rustc_middle::ty::AdtDef,
[] steal_thir: rustc_data_structures::steal::Steal<rustc_middle::thir::Thir<$tcx>>,
[] steal_mir: rustc_data_structures::steal::Steal<rustc_middle::mir::Body<$tcx>>,
[decode] mir: rustc_middle::mir::Body<$tcx>,
[] steal_thir: rustc_data_structures::steal::Steal<rustc_middle::thir::Thir<'tcx>>,
[] steal_mir: rustc_data_structures::steal::Steal<rustc_middle::mir::Body<'tcx>>,
[decode] mir: rustc_middle::mir::Body<'tcx>,
[] steal_promoted:
rustc_data_structures::steal::Steal<
rustc_index::vec::IndexVec<
rustc_middle::mir::Promoted,
rustc_middle::mir::Body<$tcx>
rustc_middle::mir::Body<'tcx>
>
>,
[decode] promoted:
rustc_index::vec::IndexVec<
rustc_middle::mir::Promoted,
rustc_middle::mir::Body<$tcx>
rustc_middle::mir::Body<'tcx>
>,
[decode] typeck_results: rustc_middle::ty::TypeckResults<$tcx>,
[decode] typeck_results: rustc_middle::ty::TypeckResults<'tcx>,
[decode] borrowck_result:
rustc_middle::mir::BorrowCheckResult<$tcx>,
rustc_middle::mir::BorrowCheckResult<'tcx>,
[decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult,
[decode] code_region: rustc_middle::mir::coverage::CodeRegion,
[] const_allocs: rustc_middle::mir::interpret::Allocation,
@ -78,14 +78,14 @@ macro_rules! arena_types {
[] foreign_modules: Vec<rustc_session::cstore::ForeignModule>,
[] upvars_mentioned: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>,
[] object_safety_violations: rustc_middle::traits::ObjectSafetyViolation,
[] codegen_unit: rustc_middle::mir::mono::CodegenUnit<$tcx>,
[] codegen_unit: rustc_middle::mir::mono::CodegenUnit<'tcx>,
[] attribute: rustc_ast::Attribute,
[] name_set: rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>,
[] hir_id_set: rustc_hir::HirIdSet,
// Interned types
[] tys: rustc_middle::ty::TyS<$tcx>,
[] predicates: rustc_middle::ty::PredicateInner<$tcx>,
[] tys: rustc_middle::ty::TyS<'tcx>,
[] predicates: rustc_middle::ty::PredicateInner<'tcx>,
// Note that this deliberately duplicates items in the `rustc_hir::arena`,
// since we need to allocate this type on both the `rustc_hir` arena
@ -97,8 +97,8 @@ macro_rules! arena_types {
[decode] used_trait_imports: rustc_data_structures::fx::FxHashSet<rustc_hir::def_id::LocalDefId>,
[] dep_kind: rustc_middle::dep_graph::DepKindStruct,
], $tcx);
]);
)
}
arena_types!(rustc_arena::declare_arena, 'tcx);
arena_types!(rustc_arena::declare_arena);

View File

@ -417,17 +417,17 @@ macro_rules! __impl_decoder_methods {
macro_rules! impl_arena_allocatable_decoder {
([]$args:tt) => {};
([decode $(, $attrs:ident)*]
[[$name:ident: $ty:ty], $tcx:lifetime]) => {
impl<$tcx, D: TyDecoder<$tcx>> RefDecodable<$tcx, D> for $ty {
[$name:ident: $ty:ty]) => {
impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for $ty {
#[inline]
fn decode(decoder: &mut D) -> Result<&$tcx Self, D::Error> {
fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
decode_arena_allocable(decoder)
}
}
impl<$tcx, D: TyDecoder<$tcx>> RefDecodable<$tcx, D> for [$ty] {
impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [$ty] {
#[inline]
fn decode(decoder: &mut D) -> Result<&$tcx Self, D::Error> {
fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
decode_arena_allocable_slice(decoder)
}
}
@ -438,15 +438,15 @@ macro_rules! impl_arena_allocatable_decoder {
}
macro_rules! impl_arena_allocatable_decoders {
([$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
([$($a:tt $name:ident: $ty:ty,)*]) => {
$(
impl_arena_allocatable_decoder!($a [[$name: $ty], $tcx]);
impl_arena_allocatable_decoder!($a [$name: $ty]);
)*
}
}
rustc_hir::arena_types!(impl_arena_allocatable_decoders, 'tcx);
arena_types!(impl_arena_allocatable_decoders, 'tcx);
rustc_hir::arena_types!(impl_arena_allocatable_decoders);
arena_types!(impl_arena_allocatable_decoders);
#[macro_export]
macro_rules! implement_ty_decoder {

View File

@ -349,9 +349,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::FnPtr(sig) => (sig, None),
ref t => {
let mut unit_variant = None;
let mut removal_span = call_expr.span;
if let ty::Adt(adt_def, ..) = t {
if adt_def.is_enum() {
if let hir::ExprKind::Call(expr, _) = call_expr.kind {
removal_span =
expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
unit_variant =
self.tcx.sess.source_map().span_to_snippet(expr.span).ok();
}
@ -379,14 +382,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
if let Some(ref path) = unit_variant {
err.span_suggestion(
call_expr.span,
err.span_suggestion_verbose(
removal_span,
&format!(
"`{}` is a unit variant, you need to write it \
without the parentheses",
"`{}` is a unit variant, you need to write it without the parentheses",
path
),
path.to_string(),
String::new(),
Applicability::MachineApplicable,
);
}

View File

@ -51,8 +51,13 @@ use super::MAX;
#[must_use]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_u32(i: u32) -> Option<char> {
char::try_from(i).ok()
#[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
pub const fn from_u32(i: u32) -> Option<char> {
// FIXME: once Result::ok is const fn, use it here
match char_try_from_u32(i) {
Ok(c) => Some(c),
Err(_) => None,
}
}
/// Converts a `u32` to a `char`, ignoring validity.
@ -91,7 +96,8 @@ pub fn from_u32(i: u32) -> Option<char> {
#[inline]
#[must_use]
#[stable(feature = "char_from_unchecked", since = "1.5.0")]
pub unsafe fn from_u32_unchecked(i: u32) -> char {
#[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
pub const unsafe fn from_u32_unchecked(i: u32) -> char {
// SAFETY: the caller must guarantee that `i` is a valid char value.
if cfg!(debug_assertions) { char::from_u32(i).unwrap() } else { unsafe { transmute(i) } }
}
@ -248,18 +254,23 @@ impl FromStr for char {
}
}
#[inline]
const fn char_try_from_u32(i: u32) -> Result<char, CharTryFromError> {
if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
Err(CharTryFromError(()))
} else {
// SAFETY: checked that it's a legal unicode value
Ok(unsafe { transmute(i) })
}
}
#[stable(feature = "try_from", since = "1.34.0")]
impl TryFrom<u32> for char {
type Error = CharTryFromError;
#[inline]
fn try_from(i: u32) -> Result<Self, Self::Error> {
if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
Err(CharTryFromError(()))
} else {
// SAFETY: checked that it's a legal unicode value
Ok(unsafe { transmute(i) })
}
char_try_from_u32(i)
}
}
@ -327,7 +338,8 @@ impl fmt::Display for CharTryFromError {
#[inline]
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_digit(num: u32, radix: u32) -> Option<char> {
#[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
pub const fn from_digit(num: u32, radix: u32) -> Option<char> {
if radix > 36 {
panic!("from_digit: radix is too high (maximum 36)");
}

View File

@ -136,9 +136,10 @@ impl char {
/// assert_eq!(None, c);
/// ```
#[stable(feature = "assoc_char_funcs", since = "1.52.0")]
#[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
#[must_use]
#[inline]
pub fn from_u32(i: u32) -> Option<char> {
pub const fn from_u32(i: u32) -> Option<char> {
super::convert::from_u32(i)
}
@ -178,9 +179,10 @@ impl char {
/// assert_eq!('❤', c);
/// ```
#[stable(feature = "assoc_char_funcs", since = "1.52.0")]
#[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
#[must_use]
#[inline]
pub unsafe fn from_u32_unchecked(i: u32) -> char {
pub const unsafe fn from_u32_unchecked(i: u32) -> char {
// SAFETY: the safety contract must be upheld by the caller.
unsafe { super::convert::from_u32_unchecked(i) }
}
@ -235,9 +237,10 @@ impl char {
/// let _c = char::from_digit(1, 37);
/// ```
#[stable(feature = "assoc_char_funcs", since = "1.52.0")]
#[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
#[must_use]
#[inline]
pub fn from_digit(num: u32, radix: u32) -> Option<char> {
pub const fn from_digit(num: u32, radix: u32) -> Option<char> {
super::convert::from_digit(num, radix)
}
@ -331,10 +334,11 @@ impl char {
/// let _ = '1'.to_digit(37);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub fn to_digit(self, radix: u32) -> Option<u32> {
pub const fn to_digit(self, radix: u32) -> Option<u32> {
assert!(radix <= 36, "to_digit: radix is too high (maximum 36)");
// If not a digit, a number greater than radix will be created.
let mut digit = (self as u32).wrapping_sub('0' as u32);
@ -345,7 +349,8 @@ impl char {
// Force the 6th bit to be set to ensure ascii is lower case.
digit = (self as u32 | 0b10_0000).wrapping_sub('a' as u32).saturating_add(10);
}
(digit < radix).then_some(digit)
// FIXME: once then_some is const fn, use it here
if digit < radix { Some(digit) } else { None }
}
/// Returns an iterator that yields the hexadecimal Unicode escape of a

View File

@ -105,6 +105,7 @@
#![feature(const_bigint_helper_methods)]
#![feature(const_caller_location)]
#![feature(const_cell_into_inner)]
#![feature(const_char_convert)]
#![feature(const_discriminant)]
#![feature(const_eval_select)]
#![feature(const_float_bits_conv)]

View File

@ -1430,4 +1430,8 @@ fn create_dir_long_paths() {
// This will fail if the path isn't converted to verbatim.
path.push("a");
fs::create_dir(&path).unwrap();
// #90940: Ensure an empty path returns the "Not Found" error.
let path = Path::new("");
assert_eq!(path.canonicalize().unwrap_err().kind(), crate::io::ErrorKind::NotFound);
}

View File

@ -174,8 +174,8 @@ pub(crate) fn maybe_verbatim(path: &Path) -> io::Result<Vec<u16>> {
const UNC_PREFIX: &[u16] = &[SEP, SEP, QUERY, SEP, U, N, C, SEP];
let mut path = to_u16s(path)?;
if path.starts_with(VERBATIM_PREFIX) || path.starts_with(NT_PREFIX) {
// Early return for paths that are already verbatim.
if path.starts_with(VERBATIM_PREFIX) || path.starts_with(NT_PREFIX) || path == &[0] {
// Early return for paths that are already verbatim or empty.
return Ok(path);
} else if path.len() < LEGACY_MAX_PATH {
// Early return if an absolute path is less < 260 UTF-16 code units.

View File

@ -91,7 +91,6 @@ fn verbatim() {
// Make sure opening a drive will work.
check("Z:", "Z:");
// An empty path or a path that contains null are not valid paths.
assert!(maybe_verbatim(Path::new("")).is_err());
// A path that contains null is not a valid path.
assert!(maybe_verbatim(Path::new("\0")).is_err());
}

View File

@ -1119,17 +1119,22 @@ class RustBuild(object):
raise Exception("{} not found".format(vendor_dir))
if self.use_vendored_sources:
config = ("[source.crates-io]\n"
"replace-with = 'vendored-sources'\n"
"registry = 'https://example.com'\n"
"\n"
"[source.vendored-sources]\n"
"directory = '{}/vendor'\n"
.format(self.rust_root))
if not os.path.exists('.cargo'):
os.makedirs('.cargo')
with output('.cargo/config') as cargo_config:
cargo_config.write(
"[source.crates-io]\n"
"replace-with = 'vendored-sources'\n"
"registry = 'https://example.com'\n"
"\n"
"[source.vendored-sources]\n"
"directory = '{}/vendor'\n"
.format(self.rust_root))
with output('.cargo/config') as cargo_config:
cargo_config.write(config)
else:
print('info: using vendored source, but .cargo/config is already present.')
print(' Reusing the current configuration file. But you may want to '
'configure vendoring like this:')
print(config)
else:
if os.path.exists('.cargo'):
shutil.rmtree('.cargo')

View File

@ -0,0 +1,26 @@
warning: conflicting implementations of trait `SadBee` for type `for<'a> fn(&'a ())`
--> $DIR/invariant.rs:14:1
|
LL | impl SadBee for for<'a> fn(&'a ()) {
| ---------------------------------- first implementation here
...
LL | impl SadBee for fn(&'static ()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a> fn(&'a ())`
|
= note: `#[warn(coherence_leak_check)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
error[E0308]: mismatched types
--> $DIR/invariant.rs:27:5
|
LL | v
| ^ one type is more general than the other
|
= note: expected reference `&Foo<fn(&())>`
found reference `&Foo<for<'a> fn(&'a ())>`
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0308`.

View File

@ -0,0 +1,33 @@
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
use std::marker::PhantomData;
trait SadBee {
const ASSOC: usize;
}
// fn(&'static ())` is a supertype of `for<'a> fn(&'a ())` while
// we allow two different impls for these types, leading
// to different const eval results.
impl SadBee for for<'a> fn(&'a ()) {
const ASSOC: usize = 0;
}
impl SadBee for fn(&'static ()) {
//~^ WARNING conflicting implementations of trait
//~| WARNING this was previously accepted
const ASSOC: usize = 100;
}
struct Foo<T: SadBee>([u8; <T as SadBee>::ASSOC], PhantomData<T>)
where
[(); <T as SadBee>::ASSOC]: ;
fn covariant(
v: &'static Foo<for<'a> fn(&'a ())>
) -> &'static Foo<fn(&'static ())> {
v //~ ERROR mismatched types
}
fn main() {
let y = covariant(&Foo([], PhantomData));
println!("{:?}", y.0);
}

View File

@ -0,0 +1,26 @@
warning: conflicting implementations of trait `SadBee` for type `for<'a> fn(&'a ())`
--> $DIR/invariant.rs:14:1
|
LL | impl SadBee for for<'a> fn(&'a ()) {
| ---------------------------------- first implementation here
...
LL | impl SadBee for fn(&'static ()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a> fn(&'a ())`
|
= note: `#[warn(coherence_leak_check)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
error[E0308]: mismatched types
--> $DIR/invariant.rs:27:5
|
LL | v
| ^ one type is more general than the other
|
= note: expected reference `&'static Foo<fn(&'static ())>`
found reference `&'static Foo<for<'a> fn(&'a ())>`
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0308`.

View File

@ -22,8 +22,9 @@ LL | let e4 = E::Empty4();
|
help: `E::Empty4` is a unit variant, you need to write it without the parentheses
|
LL | let e4 = E::Empty4;
| ~~~~~~~~~
LL - let e4 = E::Empty4();
LL + let e4 = E::Empty4;
|
error[E0618]: expected function, found `empty_struct::XEmpty2`
--> $DIR/empty-struct-unit-expr.rs:18:15
@ -43,8 +44,9 @@ LL | let xe4 = XE::XEmpty4();
|
help: `XE::XEmpty4` is a unit variant, you need to write it without the parentheses
|
LL | let xe4 = XE::XEmpty4;
| ~~~~~~~~~~~
LL - let xe4 = XE::XEmpty4();
LL + let xe4 = XE::XEmpty4;
|
error: aborting due to 4 previous errors

View File

@ -11,8 +11,9 @@ LL | X::Entry();
|
help: `X::Entry` is a unit variant, you need to write it without the parentheses
|
LL | X::Entry;
| ~~~~~~~~
LL - X::Entry();
LL + X::Entry;
|
error[E0618]: expected function, found `i32`
--> $DIR/E0618.rs:9:5

View File

@ -1,10 +0,0 @@
mod foo {
pub fn x(y: isize) { log(debug, y); }
//~^ ERROR cannot find function `log` in this scope
//~| ERROR cannot find value `debug` in this scope
fn z(y: isize) { log(debug, y); }
//~^ ERROR cannot find function `log` in this scope
//~| ERROR cannot find value `debug` in this scope
}
fn main() { foo::z(10); } //~ ERROR function `z` is private

View File

@ -1,40 +0,0 @@
error[E0425]: cannot find function `log` in this scope
--> $DIR/export.rs:2:26
|
LL | pub fn x(y: isize) { log(debug, y); }
| ^^^ not found in this scope
error[E0425]: cannot find value `debug` in this scope
--> $DIR/export.rs:2:30
|
LL | pub fn x(y: isize) { log(debug, y); }
| ^^^^^ not found in this scope
error[E0425]: cannot find function `log` in this scope
--> $DIR/export.rs:5:22
|
LL | fn z(y: isize) { log(debug, y); }
| ^^^ not found in this scope
error[E0425]: cannot find value `debug` in this scope
--> $DIR/export.rs:5:26
|
LL | fn z(y: isize) { log(debug, y); }
| ^^^^^ not found in this scope
error[E0603]: function `z` is private
--> $DIR/export.rs:10:18
|
LL | fn main() { foo::z(10); }
| ^ private function
|
note: the function `z` is defined here
--> $DIR/export.rs:5:5
|
LL | fn z(y: isize) { log(debug, y); }
| ^^^^^^^^^^^^^^
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0425, E0603.
For more information about an error, try `rustc --explain E0425`.

View File

@ -1,13 +0,0 @@
// run-pass
// Regression test for issue #377
struct A { a: isize }
struct V { v: isize }
pub fn main() {
let a = { let b = A {a: 3}; b };
assert_eq!(a.a, 3);
let c = { let d = V {v: 3}; d };
assert_eq!(c.v, 3);
}

View File

@ -1,9 +0,0 @@
// run-pass
// pretty-expanded FIXME #23616
fn leaky<T>(_t: T) { }
pub fn main() {
let x = Box::new(10);
leaky::<Box<isize>>(x);
}

View File

@ -1,12 +0,0 @@
// run-pass
#[derive(PartialEq, Debug)]
struct Foo(usize);
fn foo() -> Foo {
Foo(42)
}
pub fn main() {
assert_eq!(foo(), Foo(42));
}

View File

@ -1,22 +0,0 @@
// run-pass
struct X {
repr: isize
}
fn apply<T, F>(x: T, f: F) where F: FnOnce(T) {
f(x);
}
fn check_int(x: isize) {
assert_eq!(x, 22);
}
fn check_struct(x: X) {
check_int(x.repr);
}
pub fn main() {
apply(22, check_int);
apply(X {repr: 22}, check_struct);
}

View File

@ -1,51 +0,0 @@
// run-pass
#![allow(dead_code)]
// Check that functions can modify local state.
// pretty-expanded FIXME #23616
fn sums_to(v: Vec<isize> , sum: isize) -> bool {
let mut i = 0;
let mut sum0 = 0;
while i < v.len() {
sum0 += v[i];
i += 1;
}
return sum0 == sum;
}
fn sums_to_using_uniq(v: Vec<isize> , sum: isize) -> bool {
let mut i = 0;
let mut sum0: Box<_> = 0.into();
while i < v.len() {
*sum0 += v[i];
i += 1;
}
return *sum0 == sum;
}
fn sums_to_using_rec(v: Vec<isize> , sum: isize) -> bool {
let mut i = 0;
let mut sum0 = F {f: 0};
while i < v.len() {
sum0.f += v[i];
i += 1;
}
return sum0.f == sum;
}
struct F<T> { f: T }
fn sums_to_using_uniq_rec(v: Vec<isize> , sum: isize) -> bool {
let mut i = 0;
let mut sum0 = F::<Box<_>> {f: 0.into() };
while i < v.len() {
*sum0.f += v[i];
i += 1;
}
return *sum0.f == sum;
}
pub fn main() {
}

Some files were not shown because too many files have changed in this diff Show More