diff options
116 files changed, 1640 insertions, 546 deletions
diff --git a/Cargo.lock b/Cargo.lock index 6519ffa7169..e69b36cb983 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3165,6 +3165,7 @@ dependencies = [ "rustc_expand", "rustc_feature", "rustc_fluent_macro", + "rustc_index", "rustc_lexer", "rustc_lint_defs", "rustc_macros", @@ -4739,6 +4740,15 @@ dependencies = [ ] [[package]] +name = "sysroot" +version = "0.0.0" +dependencies = [ + "proc_macro", + "std", + "test", +] + +[[package]] name = "tar" version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4822,7 +4832,6 @@ dependencies = [ "getopts", "panic_abort", "panic_unwind", - "proc_macro", "std", ] diff --git a/Cargo.toml b/Cargo.toml index a497d7321e0..7aaa34a68e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ members = [ "compiler/rustc", "library/std", - "library/test", + "library/sysroot", "src/rustdoc-json-types", "src/tools/build_helper", "src/tools/cargotest", diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs index 6259722b694..74e6ce37e97 100644 --- a/compiler/rustc_borrowck/src/def_use.rs +++ b/compiler/rustc_borrowck/src/def_use.rs @@ -54,7 +54,7 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> { // `PlaceMention` and `AscribeUserType` both evaluate the place, which must not // contain dangling references. - PlaceContext::NonUse(NonUseContext::PlaceMention) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::PlaceMention) | PlaceContext::NonUse(NonUseContext::AscribeUserTy) | PlaceContext::MutatingUse(MutatingUseContext::AddressOf) | diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index c4c54620e04..315303b25fe 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -498,11 +498,11 @@ impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> { let next_region = self.infcx.next_region_var(origin); let vid = next_region.as_var(); - if cfg!(debug_assertions) && !self.inside_canonicalization_ctxt() { + if cfg!(debug_assertions) { debug!("inserting vid {:?} with origin {:?} into var_to_origin", vid, origin); let ctxt = get_ctxt_fn(); let mut var_to_origin = self.reg_var_to_origin.borrow_mut(); - var_to_origin.insert(vid, ctxt); + assert_eq!(var_to_origin.insert(vid, ctxt), None); } next_region @@ -520,11 +520,11 @@ impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> { let next_region = self.infcx.next_nll_region_var(origin); let vid = next_region.as_var(); - if cfg!(debug_assertions) && !self.inside_canonicalization_ctxt() { + if cfg!(debug_assertions) { debug!("inserting vid {:?} with origin {:?} into var_to_origin", vid, origin); let ctxt = get_ctxt_fn(); let mut var_to_origin = self.reg_var_to_origin.borrow_mut(); - var_to_origin.insert(vid, ctxt); + assert_eq!(var_to_origin.insert(vid, ctxt), None); } next_region diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 65573c71f14..8fbe814c856 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -76,7 +76,7 @@ pub struct RegionInferenceContext<'tcx> { /// Reverse of the SCC constraint graph -- i.e., an edge `A -> B` exists if /// `B: A`. This is used to compute the universal regions that are required /// to outlive a given SCC. Computed lazily. - rev_scc_graph: Option<Rc<ReverseSccGraph>>, + rev_scc_graph: Option<ReverseSccGraph>, /// The "R0 member of [R1..Rn]" constraints, indexed by SCC. member_constraints: Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>, @@ -813,9 +813,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { // free region that must outlive the member region `R0` (`UB: // R0`). Therefore, we need only keep an option `O` if `UB: O` // for all UB. - let rev_scc_graph = self.reverse_scc_graph(); + self.compute_reverse_scc_graph(); let universal_region_relations = &self.universal_region_relations; - for ub in rev_scc_graph.upper_bounds(scc) { + for ub in self.rev_scc_graph.as_ref().unwrap().upper_bounds(scc) { debug!(?ub); choice_regions.retain(|&o_r| universal_region_relations.outlives(ub, o_r)); } diff --git a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs index 23a59c12865..fe56bd54a3f 100644 --- a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs +++ b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs @@ -8,7 +8,6 @@ use rustc_data_structures::graph::vec_graph::VecGraph; use rustc_data_structures::graph::WithSuccessors; use rustc_middle::ty::RegionVid; use std::ops::Range; -use std::rc::Rc; pub(crate) struct ReverseSccGraph { graph: VecGraph<ConstraintSccIndex>, @@ -40,10 +39,10 @@ impl ReverseSccGraph { } impl RegionInferenceContext<'_> { - /// Compute and return the reverse SCC-based constraint graph (lazily). - pub(super) fn reverse_scc_graph(&mut self) -> Rc<ReverseSccGraph> { - if let Some(g) = &self.rev_scc_graph { - return g.clone(); + /// Compute the reverse SCC-based constraint graph (lazily). + pub(super) fn compute_reverse_scc_graph(&mut self) { + if self.rev_scc_graph.is_some() { + return; } let graph = self.constraint_sccs.reverse(); @@ -63,8 +62,6 @@ impl RegionInferenceContext<'_> { start += group_size; } - let rev_graph = Rc::new(ReverseSccGraph { graph, scc_regions, universal_regions }); - self.rev_scc_graph = Some(rev_graph.clone()); - rev_graph + self.rev_scc_graph = Some(ReverseSccGraph { graph, scc_regions, universal_regions }); } } diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index 22de7549e94..4389d2b60bc 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -109,6 +109,14 @@ impl<'a, 'tcx> MutVisitor<'tcx> for RegionRenumberer<'a, 'tcx> { } #[instrument(skip(self), level = "debug")] + fn visit_ty_const(&mut self, ct: &mut ty::Const<'tcx>, location: Location) { + let old_ct = *ct; + *ct = self.renumber_regions(old_ct, || RegionCtxt::Location(location)); + + debug!(?ct); + } + + #[instrument(skip(self), level = "debug")] fn visit_constant(&mut self, constant: &mut Constant<'tcx>, location: Location) { let literal = constant.literal; constant.literal = self.renumber_regions(literal, || RegionCtxt::Location(location)); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 601589480d1..dcabeb792be 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -772,12 +772,10 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { match context { PlaceContext::MutatingUse(_) => ty::Invariant, - PlaceContext::NonUse(StorageDead | StorageLive | PlaceMention | VarDebugInfo) => { - ty::Invariant - } + PlaceContext::NonUse(StorageDead | StorageLive | VarDebugInfo) => ty::Invariant, PlaceContext::NonMutatingUse( - Inspect | Copy | Move | SharedBorrow | ShallowBorrow | UniqueBorrow | AddressOf - | Projection, + Inspect | Copy | Move | PlaceMention | SharedBorrow | ShallowBorrow | UniqueBorrow + | AddressOf | Projection, ) => ty::Covariant, PlaceContext::NonUse(AscribeUserTy) => ty::Covariant, } @@ -1803,6 +1801,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Rvalue::Repeat(operand, len) => { self.check_operand(operand, location); + let array_ty = rvalue.ty(body.local_decls(), tcx); + self.prove_predicate( + ty::PredicateKind::WellFormed(array_ty.into()), + Locations::Single(location), + ConstraintCategory::Boring, + ); + // If the length cannot be evaluated we must assume that the length can be larger // than 1. // If the length is larger than 1, the repeat expression will need to copy the diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 7e6d17ec343..7158c62b548 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -131,9 +131,13 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> ty::BoundRegionKind::BrEnv => BoundRegionInfo::Name(sym::env), }; - if cfg!(debug_assertions) && !self.type_checker.infcx.inside_canonicalization_ctxt() { + if cfg!(debug_assertions) { let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut(); - var_to_origin.insert(reg.as_var(), RegionCtxt::Placeholder(reg_info)); + let new = RegionCtxt::Placeholder(reg_info); + let prev = var_to_origin.insert(reg.as_var(), new); + if let Some(prev) = prev { + assert_eq!(new, prev); + } } reg @@ -146,9 +150,10 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> universe, ); - if cfg!(debug_assertions) && !self.type_checker.infcx.inside_canonicalization_ctxt() { + if cfg!(debug_assertions) { let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut(); - var_to_origin.insert(reg.as_var(), RegionCtxt::Existential(None)); + let prev = var_to_origin.insert(reg.as_var(), RegionCtxt::Existential(None)); + assert_eq!(prev, None); } reg diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml index 5f6441660e3..44012e802aa 100644 --- a/compiler/rustc_builtin_macros/Cargo.toml +++ b/compiler/rustc_builtin_macros/Cargo.toml @@ -14,6 +14,7 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } +rustc_index = { path = "../rustc_index" } rustc_lexer = { path = "../rustc_lexer" } rustc_lint_defs = { path = "../rustc_lint_defs" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index ac817d9a152..bb059a120df 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -2,9 +2,10 @@ use rustc_ast as ast; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter}; use rustc_ast::tokenstream::TokenStream; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_errors::PResult; use rustc_expand::base::{self, *}; +use rustc_index::bit_set::GrowableBitSet; use rustc_parse::parser::Parser; use rustc_parse_format as parse; use rustc_session::lint; @@ -20,8 +21,8 @@ use crate::errors; pub struct AsmArgs { pub templates: Vec<P<ast::Expr>>, pub operands: Vec<(ast::InlineAsmOperand, Span)>, - named_args: FxHashMap<Symbol, usize>, - reg_args: FxHashSet<usize>, + named_args: FxIndexMap<Symbol, usize>, + reg_args: GrowableBitSet<usize>, pub clobber_abis: Vec<(Symbol, Span)>, options: ast::InlineAsmOptions, pub options_spans: Vec<Span>, @@ -56,8 +57,8 @@ pub fn parse_asm_args<'a>( let mut args = AsmArgs { templates: vec![first_template], operands: vec![], - named_args: FxHashMap::default(), - reg_args: FxHashSet::default(), + named_args: Default::default(), + reg_args: Default::default(), clobber_abis: Vec::new(), options: ast::InlineAsmOptions::empty(), options_spans: vec![], @@ -213,7 +214,7 @@ pub fn parse_asm_args<'a>( } else { if !args.named_args.is_empty() || !args.reg_args.is_empty() { let named = args.named_args.values().map(|p| args.operands[*p].1).collect(); - let explicit = args.reg_args.iter().map(|p| args.operands[*p].1).collect(); + let explicit = args.reg_args.iter().map(|p| args.operands[p].1).collect(); diag.emit_err(errors::AsmPositionalAfter { span, named, explicit }); } @@ -446,8 +447,8 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl // Register operands are implicitly used since they are not allowed to be // referenced in the template string. let mut used = vec![false; args.operands.len()]; - for pos in &args.reg_args { - used[*pos] = true; + for pos in args.reg_args.iter() { + used[pos] = true; } let named_pos: FxHashMap<usize, Symbol> = args.named_args.iter().map(|(&sym, &idx)| (idx, sym)).collect(); @@ -581,7 +582,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl parse::ArgumentIs(idx) | parse::ArgumentImplicitlyIs(idx) => { if idx >= args.operands.len() || named_pos.contains_key(&idx) - || args.reg_args.contains(&idx) + || args.reg_args.contains(idx) { let msg = format!("invalid reference to argument at index {}", idx); let mut err = ecx.struct_span_err(span, &msg); @@ -608,7 +609,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl args.operands[idx].1, "named arguments cannot be referenced by position", ); - } else if args.reg_args.contains(&idx) { + } else if args.reg_args.contains(idx) { err.span_label( args.operands[idx].1, "explicit register argument", diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 8f86ef44aa3..c7da61d72b3 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -1,7 +1,6 @@ //! This crate contains implementations of built-in macros and other code generating facilities //! injecting code into the crate before it is lowered to HIR. -#![allow(rustc::potential_query_instability)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(array_windows)] #![feature(box_patterns)] diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 0334c7ff132..569599faa36 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -203,7 +203,9 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> self.assign(local, DefLocation::Body(location)); } - PlaceContext::NonUse(_) | PlaceContext::MutatingUse(MutatingUseContext::Retag) => {} + PlaceContext::NonUse(_) + | PlaceContext::NonMutatingUse(NonMutatingUseContext::PlaceMention) + | PlaceContext::MutatingUse(MutatingUseContext::Retag) => {} PlaceContext::NonMutatingUse( NonMutatingUseContext::Copy | NonMutatingUseContext::Move, diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs index 6fa76981408..9995c08345c 100644 --- a/compiler/rustc_data_structures/src/fingerprint.rs +++ b/compiler/rustc_data_structures/src/fingerprint.rs @@ -64,6 +64,11 @@ impl Fingerprint { ) } + #[inline] + pub(crate) fn as_u128(self) -> u128 { + u128::from(self.1) << 64 | u128::from(self.0) + } + // Combines two hashes in an order independent way. Make sure this is what // you want. #[inline] diff --git a/compiler/rustc_data_structures/src/svh.rs b/compiler/rustc_data_structures/src/svh.rs index a3d2724fcdb..71679086f16 100644 --- a/compiler/rustc_data_structures/src/svh.rs +++ b/compiler/rustc_data_structures/src/svh.rs @@ -23,18 +23,18 @@ impl Svh { Svh { hash } } - pub fn as_u64(&self) -> u64 { - self.hash.to_smaller_hash().as_u64() + pub fn as_u128(self) -> u128 { + self.hash.as_u128() } - pub fn to_string(&self) -> String { - format!("{:016x}", self.hash.to_smaller_hash()) + pub fn to_hex(self) -> String { + format!("{:032x}", self.hash.as_u128()) } } impl fmt::Display for Svh { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad(&self.to_string()) + f.pad(&self.to_hex()) } } diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 283e68a68b5..1c222fb4a89 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -88,6 +88,7 @@ use rustc_span::Span; use std::borrow::Cow; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::fmt::Display; +use std::rc::Rc; /// A unit within a matcher that a `MatcherPos` can refer to. Similar to (and derived from) /// `mbe::TokenTree`, but designed specifically for fast and easy traversal during matching. @@ -257,10 +258,10 @@ struct MatcherPos { /// against the relevant metavar by the black box parser. An element will be a `MatchedSeq` if /// the corresponding metavar decl is within a sequence. /// - /// It is critical to performance that this is an `Lrc`, because it gets cloned frequently when + /// It is critical to performance that this is an `Rc`, because it gets cloned frequently when /// processing sequences. Mostly for sequence-ending possibilities that must be tried but end /// up failing. - matches: Lrc<Vec<NamedMatch>>, + matches: Rc<Vec<NamedMatch>>, } // This type is used a lot. Make sure it doesn't unintentionally get bigger. @@ -272,7 +273,7 @@ impl MatcherPos { /// and both are hot enough to be always worth inlining. #[inline(always)] fn push_match(&mut self, metavar_idx: usize, seq_depth: usize, m: NamedMatch) { - let matches = Lrc::make_mut(&mut self.matches); + let matches = Rc::make_mut(&mut self.matches); match seq_depth { 0 => { // We are not within a sequence. Just append `m`. @@ -427,7 +428,7 @@ pub struct TtParser { /// Pre-allocate an empty match array, so it can be cloned cheaply for macros with many rules /// that have no metavars. - empty_matches: Lrc<Vec<NamedMatch>>, + empty_matches: Rc<Vec<NamedMatch>>, } impl TtParser { @@ -437,7 +438,7 @@ impl TtParser { cur_mps: vec![], next_mps: vec![], bb_mps: vec![], - empty_matches: Lrc::new(vec![]), + empty_matches: Rc::new(vec![]), } } @@ -507,7 +508,7 @@ impl TtParser { // Try zero matches of this sequence, by skipping over it. self.cur_mps.push(MatcherPos { idx: idx_first_after, - matches: Lrc::clone(&mp.matches), + matches: Rc::clone(&mp.matches), }); } @@ -521,7 +522,7 @@ impl TtParser { // processed next time around the loop. let ending_mp = MatcherPos { idx: mp.idx + 1, // +1 skips the Kleene op - matches: Lrc::clone(&mp.matches), + matches: Rc::clone(&mp.matches), }; self.cur_mps.push(ending_mp); @@ -537,7 +538,7 @@ impl TtParser { // will fail quietly when it is processed next time around the loop. let ending_mp = MatcherPos { idx: mp.idx + 2, // +2 skips the separator and the Kleene op - matches: Lrc::clone(&mp.matches), + matches: Rc::clone(&mp.matches), }; self.cur_mps.push(ending_mp); @@ -587,9 +588,9 @@ impl TtParser { if *token == token::Eof { Some(match eof_mps { EofMatcherPositions::One(mut eof_mp) => { - // Need to take ownership of the matches from within the `Lrc`. - Lrc::make_mut(&mut eof_mp.matches); - let matches = Lrc::try_unwrap(eof_mp.matches).unwrap().into_iter(); + // Need to take ownership of the matches from within the `Rc`. + Rc::make_mut(&mut eof_mp.matches); + let matches = Rc::try_unwrap(eof_mp.matches).unwrap().into_iter(); self.nameize(matcher, matches) } EofMatcherPositions::Multiple => { diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index e4f225bdad7..eaa75bde6c6 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -280,3 +280,7 @@ hir_analysis_const_specialize = cannot specialize on const impl with non-const i hir_analysis_static_specialize = cannot specialize on `'static` lifetime hir_analysis_missing_tilde_const = missing `~const` qualifier for specialization + +hir_analysis_drop_impl_negative = negative `Drop` impls are not supported + +hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs index 64dff8e68b8..bae80807f71 100644 --- a/compiler/rustc_hir_analysis/src/check/dropck.rs +++ b/compiler/rustc_hir_analysis/src/check/dropck.rs @@ -1,7 +1,6 @@ // FIXME(@lcnr): Move this module out of `rustc_hir_analysis`. // // We don't do any drop checking during hir typeck. -use crate::hir::def_id::{DefId, LocalDefId}; use rustc_errors::{struct_span_err, ErrorGuaranteed}; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; @@ -9,6 +8,9 @@ use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::util::IgnoreRegions; use rustc_middle::ty::{self, Predicate, Ty, TyCtxt}; +use crate::errors; +use crate::hir::def_id::{DefId, LocalDefId}; + /// This function confirms that the `Drop` implementation identified by /// `drop_impl_did` is not any more specialized than the type it is /// attached to (Issue #8142). @@ -27,6 +29,19 @@ use rustc_middle::ty::{self, Predicate, Ty, TyCtxt}; /// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`). /// pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), ErrorGuaranteed> { + match tcx.impl_polarity(drop_impl_did) { + ty::ImplPolarity::Positive => {} + ty::ImplPolarity::Negative => { + return Err(tcx.sess.emit_err(errors::DropImplPolarity::Negative { + span: tcx.def_span(drop_impl_did), + })); + } + ty::ImplPolarity::Reservation => { + return Err(tcx.sess.emit_err(errors::DropImplPolarity::Reservation { + span: tcx.def_span(drop_impl_did), + })); + } + } let dtor_self_type = tcx.type_of(drop_impl_did).subst_identity(); let dtor_predicates = tcx.predicates_of(drop_impl_did); match dtor_self_type.kind() { diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 25ad1bed763..c0ee777722e 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -823,3 +823,17 @@ pub(crate) struct MissingTildeConst { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +pub(crate) enum DropImplPolarity { + #[diag(hir_analysis_drop_impl_negative)] + Negative { + #[primary_span] + span: Span, + }, + #[diag(hir_analysis_drop_impl_reservation)] + Reservation { + #[primary_span] + span: Span, + }, +} diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 047d8a82bfc..bba049c3819 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1426,6 +1426,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_repeat_element_needs_copy_bound(element, count, element_ty); + self.register_wf_obligation( + tcx.mk_array_with_const_len(t, count).into(), + expr.span, + traits::WellFormed(None), + ); + tcx.mk_array_with_const_len(t, count) } diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index ec6d61f9e5f..e3c688b3e98 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -346,7 +346,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Option<Svh>) { let mut new_sub_dir_name = String::from(&old_sub_dir_name[..=dash_indices[2]]); // Append the svh - base_n::push_str(svh.as_u64() as u128, INT_ENCODE_BASE, &mut new_sub_dir_name); + base_n::push_str(svh.as_u128(), INT_ENCODE_BASE, &mut new_sub_dir_name); // Create the full path let new_path = incr_comp_session_dir.parent().unwrap().join(new_sub_dir_name); diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index d240d8e491f..0c8854e962a 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -30,8 +30,6 @@ use super::*; use rustc_middle::ty::relate::{Relate, TypeRelation}; use rustc_middle::ty::{Const, ImplSubject}; -use std::cell::Cell; - /// Whether we should define opaque types or just treat them opaquely. /// /// Currently only used to prevent predicate matching from matching anything @@ -84,7 +82,6 @@ impl<'tcx> InferCtxt<'tcx> { in_snapshot: self.in_snapshot.clone(), universe: self.universe.clone(), intercrate: self.intercrate, - inside_canonicalization_ctxt: Cell::new(self.inside_canonicalization_ctxt()), } } } diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index d798202a644..427d05c8b4d 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -561,8 +561,6 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { where V: TypeFoldable<TyCtxt<'tcx>>, { - let _inside_canonical_ctxt_guard = infcx.set_canonicalization_ctxt(); - let needs_canonical_flags = if canonicalize_region_mode.any() { TypeFlags::HAS_INFER | TypeFlags::HAS_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_FREE_REGIONS` diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 1cfdb791cd6..a89b9931599 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -39,7 +39,6 @@ use rustc_span::Span; use std::cell::{Cell, RefCell}; use std::fmt; -use std::ops::Drop; use self::combine::CombineFields; use self::error_reporting::TypeErrCtxt; @@ -342,11 +341,6 @@ pub struct InferCtxt<'tcx> { /// there is no type that the user could *actually name* that /// would satisfy it. This avoids crippling inference, basically. pub intercrate: bool, - - /// Flag that is set when we enter canonicalization. Used for debugging to ensure - /// that we only collect region information for `BorrowckInferCtxt::reg_var_to_origin` - /// inside non-canonicalization contexts. - inside_canonicalization_ctxt: Cell<bool>, } /// See the `error_reporting` module for more details. @@ -638,7 +632,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> { skip_leak_check: Cell::new(false), universe: Cell::new(ty::UniverseIndex::ROOT), intercrate, - inside_canonicalization_ctxt: Cell::new(false), } } } @@ -1636,31 +1629,6 @@ impl<'tcx> InferCtxt<'tcx> { } } } - - pub fn inside_canonicalization_ctxt(&self) -> bool { - self.inside_canonicalization_ctxt.get() - } - - pub fn set_canonicalization_ctxt(&self) -> CanonicalizationCtxtGuard<'_, 'tcx> { - let prev_ctxt = self.inside_canonicalization_ctxt(); - self.inside_canonicalization_ctxt.set(true); - CanonicalizationCtxtGuard { prev_ctxt, infcx: self } - } - - fn set_canonicalization_ctxt_to(&self, ctxt: bool) { - self.inside_canonicalization_ctxt.set(ctxt); - } -} - -pub struct CanonicalizationCtxtGuard<'cx, 'tcx> { - prev_ctxt: bool, - infcx: &'cx InferCtxt<'tcx>, -} - -impl<'cx, 'tcx> Drop for CanonicalizationCtxtGuard<'cx, 'tcx> { - fn drop(&mut self) { - self.infcx.set_canonicalization_ctxt_to(self.prev_ctxt) - } } impl<'tcx> TypeErrCtxt<'_, 'tcx> { diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 9f7b26b87f4..88a0a81e276 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -30,11 +30,10 @@ use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::fold::FnMutDelegate; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; -use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; +use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, InferConst, Ty, TyCtxt}; use rustc_span::{Span, Symbol}; use std::fmt::Debug; -use std::ops::ControlFlow; use super::combine::ObligationEmittingRelation; @@ -115,11 +114,6 @@ pub trait TypeRelatingDelegate<'tcx> { fn forbid_inference_vars() -> bool; } -#[derive(Clone, Debug, Default)] -struct BoundRegionScope<'tcx> { - map: FxHashMap<ty::BoundRegion, ty::Region<'tcx>>, -} - #[derive(Copy, Clone)] struct UniversallyQuantified(bool); @@ -230,10 +224,13 @@ where ) -> RelateResult<'tcx, T> { let universe = self.infcx.probe_ty_var(for_vid).unwrap_err(); + if value.has_escaping_bound_vars() { + bug!("trying to instantiate {for_vid:?} with escaping bound vars: {value:?}"); + } + let mut generalizer = TypeGeneralizer { infcx: self.infcx, delegate: &mut self.delegate, - first_free_index: ty::INNERMOST, ambient_variance: self.ambient_variance, for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid), universe, @@ -488,13 +485,7 @@ where } if a == b { - // Subtle: if a or b has a bound variable that we are lazily - // substituting, then even if a == b, it could be that the values we - // will substitute for those bound variables are *not* the same, and - // hence returning `Ok(a)` is incorrect. - if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() { - return Ok(a); - } + return Ok(a); } match (a.kind(), b.kind()) { @@ -726,47 +717,6 @@ where } } -/// When we encounter a binder like `for<..> fn(..)`, we actually have -/// to walk the `fn` value to find all the values bound by the `for` -/// (these are not explicitly present in the ty representation right -/// now). This visitor handles that: it descends the type, tracking -/// binder depth, and finds late-bound regions targeting the -/// `for<..`>. For each of those, it creates an entry in -/// `bound_region_scope`. -struct ScopeInstantiator<'me, 'tcx> { - next_region: &'me mut dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx>, - // The debruijn index of the scope we are instantiating. - target_index: ty::DebruijnIndex, - bound_region_scope: &'me mut BoundRegionScope<'tcx>, -} - -impl<'me, 'tcx> TypeVisitor<TyCtxt<'tcx>> for ScopeInstantiator<'me, 'tcx> { - fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>( - &mut self, - t: &ty::Binder<'tcx, T>, - ) -> ControlFlow<Self::BreakTy> { - self.target_index.shift_in(1); - t.super_visit_with(self); - self.target_index.shift_out(1); - - ControlFlow::Continue(()) - } - - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { - let ScopeInstantiator { bound_region_scope, next_region, .. } = self; - - match *r { - ty::ReLateBound(debruijn, br) if debruijn == self.target_index => { - bound_region_scope.map.entry(br).or_insert_with(|| next_region(br)); - } - - _ => {} - } - - ControlFlow::Continue(()) - } -} - /// The "type generalizer" is used when handling inference variables. /// /// The basic strategy for handling a constraint like `?A <: B` is to @@ -780,11 +730,6 @@ impl<'me, 'tcx> TypeVisitor<TyCtxt<'tcx>> for ScopeInstantiator<'me, 'tcx> { /// value of `A`. Finally, we relate `&'0 u32 <: &'x u32`, which /// establishes `'0: 'x` as a constraint. /// -/// As a side-effect of this generalization procedure, we also replace -/// all the bound regions that we have traversed with concrete values, -/// so that the resulting generalized type is independent from the -/// scopes. -/// /// [blog post]: https://is.gd/0hKvIr struct TypeGeneralizer<'me, 'tcx, D> where @@ -798,8 +743,6 @@ where /// some other type. What will be the variance at this point? ambient_variance: ty::Variance, - first_free_index: ty::DebruijnIndex, - /// The vid of the type variable that is in the process of being /// instantiated. If we find this within the value we are folding, /// that means we would have created a cyclic value. @@ -939,7 +882,7 @@ where ) -> RelateResult<'tcx, ty::Region<'tcx>> { debug!("TypeGeneralizer::regions(a={:?})", a); - if let ty::ReLateBound(debruijn, _) = *a && debruijn < self.first_free_index { + if let ty::ReLateBound(..) = *a { return Ok(a); } @@ -958,7 +901,6 @@ where // FIXME(#54105) -- if the ambient variance is bivariant, // though, we may however need to check well-formedness or // risk a problem like #41677 again. - let replacement_region_vid = self.delegate.generalize_existential(self.universe); Ok(replacement_region_vid) @@ -1002,10 +944,7 @@ where T: Relate<'tcx>, { debug!("TypeGeneralizer::binders(a={:?})", a); - - self.first_free_index.shift_in(1); let result = self.relate(a.skip_binder(), a.skip_binder())?; - self.first_free_index.shift_out(1); Ok(a.rebind(result)) } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 3253d0a9057..82c66b9dfb9 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -108,11 +108,7 @@ impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> { emit_i64(i64); emit_i32(i32); emit_i16(i16); - emit_i8(i8); - emit_bool(bool); - emit_char(char); - emit_str(&str); emit_raw_bytes(&[u8]); } } @@ -837,11 +833,12 @@ fn should_encode_span(def_kind: DefKind) -> bool { | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::Impl { .. } | DefKind::Closure | DefKind::Generator => true, - DefKind::ForeignMod | DefKind::ImplTraitPlaceholder | DefKind::GlobalAsm => false, + DefKind::ForeignMod | DefKind::GlobalAsm => false, } } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 0a9fcd898b9..6718605ed0b 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -192,6 +192,14 @@ macro_rules! make_mir_visitor { self.super_constant(constant, location); } + fn visit_ty_const( + &mut self, + ct: $( & $mutability)? ty::Const<'tcx>, + location: Location, + ) { + self.super_ty_const(ct, location); + } + fn visit_span( &mut self, span: $(& $mutability)? Span, @@ -410,7 +418,7 @@ macro_rules! make_mir_visitor { StatementKind::PlaceMention(place) => { self.visit_place( place, - PlaceContext::NonUse(NonUseContext::PlaceMention), + PlaceContext::NonMutatingUse(NonMutatingUseContext::PlaceMention), location ); } @@ -625,8 +633,9 @@ macro_rules! make_mir_visitor { self.visit_operand(operand, location); } - Rvalue::Repeat(value, _) => { + Rvalue::Repeat(value, ct) => { self.visit_operand(value, location); + self.visit_ty_const($(&$mutability)? *ct, location); } Rvalue::ThreadLocalRef(_) => {} @@ -878,12 +887,20 @@ macro_rules! make_mir_visitor { self.visit_span($(& $mutability)? *span); drop(user_ty); // no visit method for this match literal { - ConstantKind::Ty(_) => {} + ConstantKind::Ty(ct) => self.visit_ty_const($(&$mutability)? *ct, location), ConstantKind::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)), ConstantKind::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)), } } + fn super_ty_const( + &mut self, + _ct: $(& $mutability)? ty::Const<'tcx>, + _location: Location, + ) { + + } + fn super_span(&mut self, _span: $(& $mutability)? Span) { } @@ -1251,6 +1268,11 @@ pub enum NonMutatingUseContext { UniqueBorrow, /// AddressOf for *const pointer. AddressOf, + /// PlaceMention statement. + /// + /// This statement is executed as a check that the `Place` is live without reading from it, + /// so it must be considered as a non-mutating use. + PlaceMention, /// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place. /// For example, the projection `x.y` is not marked as a mutation in these cases: /// ```ignore (illustrative) @@ -1301,8 +1323,6 @@ pub enum NonUseContext { AscribeUserTy, /// The data of a user variable, for debug info. VarDebugInfo, - /// PlaceMention statement. - PlaceMention, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index e56faff5ed4..220118ae5cc 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -1026,11 +1026,7 @@ impl<'a, 'tcx> Encoder for CacheEncoder<'a, 'tcx> { emit_i64(i64); emit_i32(i32); emit_i16(i16); - emit_i8(i8); - emit_bool(bool); - emit_char(char); - emit_str(&str); emit_raw_bytes(&[u8]); } } diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index 029cf793ad8..bfb740ab356 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -63,7 +63,8 @@ impl<'tcx> TyCtxt<'tcx> { Err(e) => self.tcx.const_error_with_guaranteed(c.ty(), e), Ok(Some(bac)) => { let substs = self.tcx.erase_regions(uv.substs); - bac.subst(self.tcx, substs) + let bac = bac.subst(self.tcx, substs); + return bac.fold_with(self); } Ok(None) => c, }, diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 7536903ef96..7fc75674da5 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -506,23 +506,18 @@ macro_rules! implement_ty_decoder { impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> { $crate::__impl_decoder_methods! { + read_usize -> usize; read_u128 -> u128; read_u64 -> u64; read_u32 -> u32; read_u16 -> u16; read_u8 -> u8; - read_usize -> usize; + read_isize -> isize; read_i128 -> i128; read_i64 -> i64; read_i32 -> i32; read_i16 -> i16; - read_i8 -> i8; - read_isize -> isize; - - read_bool -> bool; - read_char -> char; - read_str -> &str; } #[inline] @@ -531,13 +526,13 @@ macro_rules! implement_ty_decoder { } #[inline] - fn position(&self) -> usize { - self.opaque.position() + fn peek_byte(&self) -> u8 { + self.opaque.peek_byte() } #[inline] - fn peek_byte(&self) -> u8 { - self.opaque.peek_byte() + fn position(&self) -> usize { + self.opaque.position() } } } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index c77985c6bd6..e5b2d342452 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -360,16 +360,16 @@ impl<'tcx> TyCtxt<'tcx> { let ty = self.type_of(adt_did).subst_identity(); let mut dtor_candidate = None; self.for_each_relevant_impl(drop_trait, ty, |impl_did| { - let Some(item_id) = self.associated_item_def_ids(impl_did).first() else { - self.sess.delay_span_bug(self.def_span(impl_did), "Drop impl without drop function"); - return; - }; - if validate(self, impl_did).is_err() { // Already `ErrorGuaranteed`, no need to delay a span bug here. return; } + let Some(item_id) = self.associated_item_def_ids(impl_did).first() else { + self.sess.delay_span_bug(self.def_span(impl_did), "Drop impl without drop function"); + return; + }; + if let Some((old_item_id, _)) = dtor_candidate { self.sess .struct_span_err(self.def_span(item_id), "multiple drop impls found") diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index bc67aa476f1..aeca0073304 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -197,6 +197,7 @@ impl DefUse { | NonMutatingUseContext::Copy | NonMutatingUseContext::Inspect | NonMutatingUseContext::Move + | NonMutatingUseContext::PlaceMention | NonMutatingUseContext::ShallowBorrow | NonMutatingUseContext::SharedBorrow | NonMutatingUseContext::UniqueBorrow, diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index deec66bbaf3..7f995c69a48 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -714,13 +714,22 @@ impl CanConstProp { } } -impl Visitor<'_> for CanConstProp { +impl<'tcx> Visitor<'tcx> for CanConstProp { + fn visit_place(&mut self, place: &Place<'tcx>, mut context: PlaceContext, loc: Location) { + use rustc_middle::mir::visit::PlaceContext::*; + + // Dereferencing just read the addess of `place.local`. + if place.projection.first() == Some(&PlaceElem::Deref) { + context = NonMutatingUse(NonMutatingUseContext::Copy); + } + + self.visit_local(place.local, context, loc); + self.visit_projection(place.as_ref(), context, loc); + } + fn visit_local(&mut self, local: Local, context: PlaceContext, _: Location) { use rustc_middle::mir::visit::PlaceContext::*; match context { - // Projections are fine, because `&mut foo.x` will be caught by - // `MutatingUseContext::Borrow` elsewhere. - MutatingUse(MutatingUseContext::Projection) // These are just stores, where the storing is not propagatable, but there may be later // mutations of the same local via `Store` | MutatingUse(MutatingUseContext::Call) @@ -751,7 +760,7 @@ impl Visitor<'_> for CanConstProp { NonMutatingUse(NonMutatingUseContext::Copy) | NonMutatingUse(NonMutatingUseContext::Move) | NonMutatingUse(NonMutatingUseContext::Inspect) - | NonMutatingUse(NonMutatingUseContext::Projection) + | NonMutatingUse(NonMutatingUseContext::PlaceMention) | NonUse(_) => {} // These could be propagated with a smarter analysis or just some careful thinking about @@ -770,6 +779,8 @@ impl Visitor<'_> for CanConstProp { trace!("local {:?} can't be propagated because it's used: {:?}", local, context); self.can_const_prop[local] = ConstPropMode::NoPropagation; } + MutatingUse(MutatingUseContext::Projection) + | NonMutatingUse(NonMutatingUseContext::Projection) => bug!("visit_place should not pass {context:?} for {local:?}"), } } } diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs index 9dd39a5c9fe..72371b9950b 100644 --- a/compiler/rustc_passes/src/debugger_visualizer.rs +++ b/compiler/rustc_passes/src/debugger_visualizer.rs @@ -2,6 +2,7 @@ use hir::CRATE_HIR_ID; use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::sync::Lrc; use rustc_expand::base::resolve_path; use rustc_hir as hir; use rustc_hir::HirId; @@ -9,8 +10,6 @@ use rustc_middle::ty::TyCtxt; use rustc_middle::{query::LocalCrate, ty::query::Providers}; use rustc_span::{sym, DebuggerVisualizerFile, DebuggerVisualizerType}; -use std::sync::Arc; - use crate::errors::DebugVisualizerUnreadable; fn check_for_debugger_visualizer( @@ -52,7 +51,7 @@ fn check_for_debugger_visualizer( match std::fs::read(&file) { Ok(contents) => { debugger_visualizers - .insert(DebuggerVisualizerFile::new(Arc::from(contents), visualizer_type)); + .insert(DebuggerVisualizerFile::new(Lrc::from(contents), visualizer_type)); } Err(error) => { tcx.sess.emit_err(DebugVisualizerUnreadable { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index fd263bab78f..fae7d549592 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -550,7 +550,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let sm = self.tcx.sess.source_map(); let def_id = match outer_res { - Res::SelfTyParam { .. } => { + Res::SelfTyParam { .. } | Res::SelfCtor(_) => { err.span_label(span, "can't use `Self` here"); return err; } diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 530c188fe18..2db1d83d4fd 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -24,7 +24,6 @@ use crate::{ResolutionError, Resolver, Scope, ScopeSet, Segment, ToNameBinding, use Determinacy::*; use Namespace::*; -use RibKind::*; type Visibility = ty::Visibility<LocalDefId>; @@ -324,8 +323,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } module = match ribs[i].kind { - ModuleRibKind(module) => module, - MacroDefinition(def) if def == self.macro_def(ident.span.ctxt()) => { + RibKind::Module(module) => module, + RibKind::MacroDefinition(def) if def == self.macro_def(ident.span.ctxt()) => { // If an invocation of this macro created `ident`, give up on `ident` // and switch to `ident`'s source from the macro definition. ident.span.remove_mark(); @@ -1084,7 +1083,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let ribs = &all_ribs[rib_index + 1..]; // An invalid forward use of a generic parameter from a previous default. - if let ForwardGenericParamBanRibKind = all_ribs[rib_index].kind { + if let RibKind::ForwardGenericParamBan = all_ribs[rib_index].kind { if let Some(span) = finalize { let res_error = if rib_ident.name == kw::SelfUpper { ResolutionError::SelfInGenericParamDefault @@ -1104,14 +1103,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { for rib in ribs { match rib.kind { - NormalRibKind - | ClosureOrAsyncRibKind - | ModuleRibKind(..) - | MacroDefinition(..) - | ForwardGenericParamBanRibKind => { + RibKind::Normal + | RibKind::ClosureOrAsync + | RibKind::Module(..) + | RibKind::MacroDefinition(..) + | RibKind::ForwardGenericParamBan => { // Nothing to do. Continue. } - ItemRibKind(_) | AssocItemRibKind => { + RibKind::Item(_) | RibKind::AssocItem => { // This was an attempt to access an upvar inside a // named function item. This is not allowed, so we // report an error. @@ -1123,7 +1122,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { res_err = Some((span, CannotCaptureDynamicEnvironmentInFnItem)); } } - ConstantItemRibKind(_, item) => { + RibKind::ConstantItem(_, item) => { // Still doesn't deal with upvars if let Some(span) = finalize { let (span, resolution_error) = @@ -1152,13 +1151,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } return Res::Err; } - ConstParamTyRibKind => { + RibKind::ConstParamTy => { if let Some(span) = finalize { self.report_error(span, ParamInTyOfConstParam(rib_ident.name)); } return Res::Err; } - InlineAsmSymRibKind => { + RibKind::InlineAsmSym => { if let Some(span) = finalize { self.report_error(span, InvalidAsmSym); } @@ -1171,21 +1170,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return Res::Err; } } - Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => { + Res::Def(DefKind::TyParam, _) + | Res::SelfTyParam { .. } + | Res::SelfTyAlias { .. } + | Res::SelfCtor(_) => { for rib in ribs { let has_generic_params: HasGenericParams = match rib.kind { - NormalRibKind - | ClosureOrAsyncRibKind - | ModuleRibKind(..) - | MacroDefinition(..) - | InlineAsmSymRibKind - | AssocItemRibKind - | ForwardGenericParamBanRibKind => { + RibKind::Normal + | RibKind::ClosureOrAsync + | RibKind::Module(..) + | RibKind::MacroDefinition(..) + | RibKind::InlineAsmSym + | RibKind::AssocItem + | RibKind::ForwardGenericParamBan => { // Nothing to do. Continue. continue; } - ConstantItemRibKind(trivial, _) => { + RibKind::ConstantItem(trivial, _) => { let features = self.tcx.sess.features_untracked(); // HACK(min_const_generics): We currently only allow `N` or `{ N }`. if !(trivial == ConstantHasGenerics::Yes @@ -1226,8 +1228,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } // This was an attempt to use a type parameter outside its scope. - ItemRibKind(has_generic_params) => has_generic_params, - ConstParamTyRibKind => { + RibKind::Item(has_generic_params) => has_generic_params, + RibKind::ConstParamTy => { if let Some(span) = finalize { self.report_error( span, @@ -1253,15 +1255,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Res::Def(DefKind::ConstParam, _) => { for rib in ribs { let has_generic_params = match rib.kind { - NormalRibKind - | ClosureOrAsyncRibKind - | ModuleRibKind(..) - | MacroDefinition(..) - | InlineAsmSymRibKind - | AssocItemRibKind - | ForwardGenericParamBanRibKind => continue, - - ConstantItemRibKind(trivial, _) => { + RibKind::Normal + | RibKind::ClosureOrAsync + | RibKind::Module(..) + | RibKind::MacroDefinition(..) + | RibKind::InlineAsmSym + | RibKind::AssocItem + | RibKind::ForwardGenericParamBan => continue, + + RibKind::ConstantItem(trivial, _) => { let features = self.tcx.sess.features_untracked(); // HACK(min_const_generics): We currently only allow `N` or `{ N }`. if !(trivial == ConstantHasGenerics::Yes @@ -1284,8 +1286,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { continue; } - ItemRibKind(has_generic_params) => has_generic_params, - ConstParamTyRibKind => { + RibKind::Item(has_generic_params) => has_generic_params, + RibKind::ConstParamTy => { if let Some(span) = finalize { self.report_error( span, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 11d2b975fec..6f5d54bcf87 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -6,8 +6,6 @@ //! If you wonder why there's no `early.rs`, that's because it's split into three files - //! `build_reduced_graph.rs`, `macros.rs` and `imports.rs`. -use RibKind::*; - use crate::{path_names_to_string, rustdoc, BindingError, Finalize, LexicalScopeBinding}; use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; @@ -133,28 +131,28 @@ enum RecordPartialRes { #[derive(Copy, Clone, Debug)] pub(crate) enum RibKind<'a> { /// No restriction needs to be applied. - NormalRibKind, + Normal, /// We passed through an impl or trait and are now in one of its /// methods or associated types. Allow references to ty params that impl or trait /// binds. Disallow any other upvars (including other ty params that are /// upvars). - AssocItemRibKind, + AssocItem, /// We passed through a closure. Disallow labels. - ClosureOrAsyncRibKind, + ClosureOrAsync, /// We passed through an item scope. Disallow upvars. - ItemRibKind(HasGenericParams), + Item(HasGenericParams), /// We're in a constant item. Can't refer to dynamic stuff. /// /// The item may reference generic parameters in trivial constant expressions. /// All other constants aren't allowed to use generic params at all. - ConstantItemRibKind(ConstantHasGenerics, Option<(Ident, ConstantItemKind)>), + ConstantItem(ConstantHasGenerics, Option<(Ident, ConstantItemKind)>), /// We passed through a module. - ModuleRibKind(Module<'a>), + Module(Module<'a>), /// We passed through a `macro_rules!` statement MacroDefinition(DefId), @@ -162,15 +160,15 @@ pub(crate) enum RibKind<'a> { /// All bindings in this rib are generic parameters that can't be used /// from the default of a generic parameter because they're not declared /// before said generic parameter. Also see the `visit_generics` override. - ForwardGenericParamBanRibKind, + ForwardGenericParamBan, /// We are inside of the type of a const parameter. Can't refer to any /// parameters. - ConstParamTyRibKind, + ConstParamTy, /// We are inside a `sym` inline assembly operand. Can only refer to /// globals. - InlineAsmSymRibKind, + InlineAsmSym, } impl RibKind<'_> { @@ -178,30 +176,30 @@ impl RibKind<'_> { /// variables. pub(crate) fn contains_params(&self) -> bool { match self { - NormalRibKind - | ClosureOrAsyncRibKind - | ConstantItemRibKind(..) - | ModuleRibKind(_) - | MacroDefinition(_) - | ConstParamTyRibKind - | InlineAsmSymRibKind => false, - AssocItemRibKind | ItemRibKind(_) | ForwardGenericParamBanRibKind => true, + RibKind::Normal + | RibKind::ClosureOrAsync + | RibKind::ConstantItem(..) + | RibKind::Module(_) + | RibKind::MacroDefinition(_) + | RibKind::ConstParamTy + | RibKind::InlineAsmSym => false, + RibKind::AssocItem | RibKind::Item(_) | RibKind::ForwardGenericParamBan => true, } } /// This rib forbids referring to labels defined in upwards ribs. fn is_label_barrier(self) -> bool { match self { - NormalRibKind | MacroDefinition(..) => false, - - AssocItemRibKind - | ClosureOrAsyncRibKind - | ItemRibKind(..) - | ConstantItemRibKind(..) - | ModuleRibKind(..) - | ForwardGenericParamBanRibKind - | ConstParamTyRibKind - | InlineAsmSymRibKind => true, + RibKind::Normal | RibKind::MacroDefinition(..) => false, + + RibKind::AssocItem + | RibKind::ClosureOrAsync + | RibKind::Item(..) + | RibKind::ConstantItem(..) + | RibKind::Module(..) + | RibKind::ForwardGenericParamBan + | RibKind::ConstParamTy + | RibKind::InlineAsmSym => true, } } } @@ -702,7 +700,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, let span = ty.span.shrink_to_lo().to(path.span.shrink_to_lo()); self.with_generic_param_rib( &[], - NormalRibKind, + RibKind::Normal, LifetimeRibKind::Generics { binder: ty.id, kind: LifetimeBinderKind::PolyTrait, @@ -740,7 +738,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, let span = ty.span.shrink_to_lo().to(bare_fn.decl_span.shrink_to_lo()); self.with_generic_param_rib( &bare_fn.generic_params, - NormalRibKind, + RibKind::Normal, LifetimeRibKind::Generics { binder: ty.id, kind: LifetimeBinderKind::BareFnType, @@ -780,7 +778,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, let span = tref.span.shrink_to_lo().to(tref.trait_ref.path.span.shrink_to_lo()); self.with_generic_param_rib( &tref.bound_generic_params, - NormalRibKind, + RibKind::Normal, LifetimeRibKind::Generics { binder: tref.trait_ref.ref_id, kind: LifetimeBinderKind::PolyTrait, @@ -804,7 +802,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => { self.with_generic_param_rib( &generics.params, - ItemRibKind(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span)), LifetimeRibKind::Generics { binder: foreign_item.id, kind: LifetimeBinderKind::Item, @@ -816,7 +814,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, ForeignItemKind::Fn(box Fn { ref generics, .. }) => { self.with_generic_param_rib( &generics.params, - ItemRibKind(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span)), LifetimeRibKind::Generics { binder: foreign_item.id, kind: LifetimeBinderKind::Function, @@ -870,9 +868,9 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, debug!("(resolving function) entering function"); // Create a value rib for the function. - self.with_rib(ValueNS, ClosureOrAsyncRibKind, |this| { + self.with_rib(ValueNS, RibKind::ClosureOrAsync, |this| { // Create a label rib for the function. - this.with_label_rib(ClosureOrAsyncRibKind, |this| { + this.with_label_rib(RibKind::ClosureOrAsync, |this| { match fn_kind { FnKind::Fn(_, _, sig, _, generics, body) => { this.visit_generics(generics); @@ -1129,7 +1127,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, let span = predicate_span.shrink_to_lo().to(bounded_ty.span.shrink_to_lo()); this.with_generic_param_rib( &bound_generic_params, - NormalRibKind, + RibKind::Normal, LifetimeRibKind::Generics { binder: bounded_ty.id, kind: LifetimeBinderKind::WhereBound, @@ -1175,9 +1173,9 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) { // This is similar to the code for AnonConst. - self.with_rib(ValueNS, InlineAsmSymRibKind, |this| { - this.with_rib(TypeNS, InlineAsmSymRibKind, |this| { - this.with_label_rib(InlineAsmSymRibKind, |this| { + self.with_rib(ValueNS, RibKind::InlineAsmSym, |this| { + this.with_rib(TypeNS, RibKind::InlineAsmSym, |this| { + this.with_label_rib(RibKind::InlineAsmSym, |this| { this.smart_resolve_path(sym.id, &sym.qself, &sym.path, PathSource::Expr(None)); visit::walk_inline_asm_sym(this, sym); }); @@ -1202,7 +1200,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // although it may be useful to track other components as well for diagnostics. let graph_root = resolver.graph_root; let parent_scope = ParentScope::module(graph_root, resolver); - let start_rib_kind = ModuleRibKind(graph_root); + let start_rib_kind = RibKind::Module(graph_root); LateResolutionVisitor { r: resolver, parent_scope, @@ -1306,8 +1304,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if let Some(module) = self.r.get_module(self.r.local_def_id(id).to_def_id()) { // Move down in the graph. let orig_module = replace(&mut self.parent_scope.module, module); - self.with_rib(ValueNS, ModuleRibKind(module), |this| { - this.with_rib(TypeNS, ModuleRibKind(module), |this| { + self.with_rib(ValueNS, RibKind::Module(module), |this| { + this.with_rib(TypeNS, RibKind::Module(module), |this| { let ret = f(this); this.parent_scope.module = orig_module; ret @@ -1324,8 +1322,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // provide previous type parameters as they're built. We // put all the parameters on the ban list and then remove // them one by one as they are processed and become available. - let mut forward_ty_ban_rib = Rib::new(ForwardGenericParamBanRibKind); - let mut forward_const_ban_rib = Rib::new(ForwardGenericParamBanRibKind); + let mut forward_ty_ban_rib = Rib::new(RibKind::ForwardGenericParamBan); + let mut forward_const_ban_rib = Rib::new(RibKind::ForwardGenericParamBan); for param in params.iter() { match param.kind { GenericParamKind::Type { .. } => { @@ -1386,8 +1384,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // Const parameters can't have param bounds. assert!(param.bounds.is_empty()); - this.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind)); - this.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind)); + this.ribs[TypeNS].push(Rib::new(RibKind::ConstParamTy)); + this.ribs[ValueNS].push(Rib::new(RibKind::ConstParamTy)); this.with_lifetime_rib(LifetimeRibKind::ConstGeneric, |this| { this.visit_ty(ty) }); @@ -2072,6 +2070,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } visit::walk_ty(self, ty) } + + // A type may have an expression as a const generic argument. + // We do not want to recurse into those. + fn visit_expr(&mut self, _: &'a Expr) {} } let impl_self = self @@ -2109,7 +2111,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { for i in (0..self.label_ribs.len()).rev() { let rib = &self.label_ribs[i]; - if let MacroDefinition(def) = rib.kind { + if let RibKind::MacroDefinition(def) = rib.kind { // If an invocation of this macro created `ident`, give up on `ident` // and switch to `ident`'s source from the macro definition. if def == self.r.macro_def(label.span.ctxt()) { @@ -2157,7 +2159,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { self.with_current_self_item(item, |this| { this.with_generic_param_rib( &generics.params, - ItemRibKind(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span)), LifetimeRibKind::Generics { binder: item.id, kind: LifetimeBinderKind::Item, @@ -2238,7 +2240,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ItemKind::TyAlias(box TyAlias { ref generics, .. }) => { self.with_generic_param_rib( &generics.params, - ItemRibKind(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span)), LifetimeRibKind::Generics { binder: item.id, kind: LifetimeBinderKind::Item, @@ -2251,7 +2253,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ItemKind::Fn(box Fn { ref generics, .. }) => { self.with_generic_param_rib( &generics.params, - ItemRibKind(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span)), LifetimeRibKind::Generics { binder: item.id, kind: LifetimeBinderKind::Function, @@ -2290,7 +2292,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // Create a new rib for the trait-wide type parameters. self.with_generic_param_rib( &generics.params, - ItemRibKind(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span)), LifetimeRibKind::Generics { binder: item.id, kind: LifetimeBinderKind::Item, @@ -2311,7 +2313,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // Create a new rib for the trait-wide type parameters. self.with_generic_param_rib( &generics.params, - ItemRibKind(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span)), LifetimeRibKind::Generics { binder: item.id, kind: LifetimeBinderKind::Item, @@ -2414,11 +2416,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let mut seen_lifetimes = FxHashSet::default(); // We also can't shadow bindings from the parent item - if let AssocItemRibKind = kind { + if let RibKind::AssocItem = kind { let mut add_bindings_for_ns = |ns| { let parent_rib = self.ribs[ns] .iter() - .rfind(|r| matches!(r.kind, ItemRibKind(_))) + .rfind(|r| matches!(r.kind, RibKind::Item(_))) .expect("associated item outside of an item"); seen_bindings.extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span))); }; @@ -2507,8 +2509,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }; let res = match kind { - ItemRibKind(..) | AssocItemRibKind => Res::Def(def_kind, def_id.to_def_id()), - NormalRibKind => { + RibKind::Item(..) | RibKind::AssocItem => Res::Def(def_kind, def_id.to_def_id()), + RibKind::Normal => { if self.r.tcx.sess.features_untracked().non_lifetime_binders { Res::Def(def_kind, def_id.to_def_id()) } else { @@ -2554,7 +2556,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } fn with_static_rib(&mut self, f: impl FnOnce(&mut Self)) { - let kind = ItemRibKind(HasGenericParams::No); + let kind = RibKind::Item(HasGenericParams::No); self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f)) } @@ -2574,15 +2576,15 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { item: Option<(Ident, ConstantItemKind)>, f: impl FnOnce(&mut Self), ) { - self.with_rib(ValueNS, ConstantItemRibKind(may_use_generics, item), |this| { + self.with_rib(ValueNS, RibKind::ConstantItem(may_use_generics, item), |this| { this.with_rib( TypeNS, - ConstantItemRibKind( + RibKind::ConstantItem( may_use_generics.force_yes_if(is_repeat == IsRepeatExpr::Yes), item, ), |this| { - this.with_label_rib(ConstantItemRibKind(may_use_generics, item), f); + this.with_label_rib(RibKind::ConstantItem(may_use_generics, item), f); }, ) }); @@ -2614,7 +2616,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { |this: &mut Self, generics: &Generics, kind, item: &'ast AssocItem| { this.with_generic_param_rib( &generics.params, - AssocItemRibKind, + RibKind::AssocItem, LifetimeRibKind::Generics { binder: item.id, span: generics.span, kind }, |this| visit::walk_assoc_item(this, item, AssocCtxt::Trait), ); @@ -2695,7 +2697,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } fn with_self_rib_ns(&mut self, ns: Namespace, self_res: Res, f: impl FnOnce(&mut Self)) { - let mut self_type_rib = Rib::new(NormalRibKind); + let mut self_type_rib = Rib::new(RibKind::Normal); // Plain insert (no renaming, since types are not currently hygienic) self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res); @@ -2721,7 +2723,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // If applicable, create a rib for the type parameters. self.with_generic_param_rib( &generics.params, - ItemRibKind(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span)), LifetimeRibKind::Generics { span: generics.span, binder: item_id, @@ -2835,7 +2837,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // We also need a new scope for the impl item type parameters. self.with_generic_param_rib( &generics.params, - AssocItemRibKind, + RibKind::AssocItem, LifetimeRibKind::Generics { binder: item.id, span: generics.span, @@ -2863,7 +2865,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // We also need a new scope for the impl item type parameters. self.with_generic_param_rib( &generics.params, - AssocItemRibKind, + RibKind::AssocItem, LifetimeRibKind::Generics { binder: item.id, span: generics.span, @@ -3135,7 +3137,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } fn resolve_arm(&mut self, arm: &'ast Arm) { - self.with_rib(ValueNS, NormalRibKind, |this| { + self.with_rib(ValueNS, RibKind::Normal, |this| { this.resolve_pattern_top(&arm.pat, PatternSource::Match); walk_list!(this, visit_expr, &arm.guard); this.visit_expr(&arm.body); @@ -3857,7 +3859,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { diagnostics::signal_label_shadowing(self.r.tcx.sess, orig_span, label.ident) } - self.with_label_rib(NormalRibKind, |this| { + self.with_label_rib(RibKind::Normal, |this| { let ident = label.ident.normalize_to_macro_rules(); this.label_ribs.last_mut().unwrap().bindings.insert(ident, id); f(this); @@ -3880,11 +3882,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let mut num_macro_definition_ribs = 0; if let Some(anonymous_module) = anonymous_module { debug!("(resolving block) found anonymous module, moving down"); - self.ribs[ValueNS].push(Rib::new(ModuleRibKind(anonymous_module))); - self.ribs[TypeNS].push(Rib::new(ModuleRibKind(anonymous_module))); + self.ribs[ValueNS].push(Rib::new(RibKind::Module(anonymous_module))); + self.ribs[TypeNS].push(Rib::new(RibKind::Module(anonymous_module))); self.parent_scope.module = anonymous_module; } else { - self.ribs[ValueNS].push(Rib::new(NormalRibKind)); + self.ribs[ValueNS].push(Rib::new(RibKind::Normal)); } let prev = self.diagnostic_metadata.current_block_could_be_bare_struct_literal.take(); @@ -3901,8 +3903,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { && let ItemKind::MacroDef(..) = item.kind { num_macro_definition_ribs += 1; let res = self.r.local_def_id(item.id).to_def_id(); - self.ribs[ValueNS].push(Rib::new(MacroDefinition(res))); - self.label_ribs.push(Rib::new(MacroDefinition(res))); + self.ribs[ValueNS].push(Rib::new(RibKind::MacroDefinition(res))); + self.label_ribs.push(Rib::new(RibKind::MacroDefinition(res))); } self.visit_stmt(stmt); @@ -3989,7 +3991,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } ExprKind::If(ref cond, ref then, ref opt_else) => { - self.with_rib(ValueNS, NormalRibKind, |this| { + self.with_rib(ValueNS, RibKind::Normal, |this| { let old = this.diagnostic_metadata.in_if_condition.replace(cond); this.visit_expr(cond); this.diagnostic_metadata.in_if_condition = old; @@ -4006,7 +4008,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ExprKind::While(ref cond, ref block, label) => { self.with_resolved_label(label, expr.id, |this| { - this.with_rib(ValueNS, NormalRibKind, |this| { + this.with_rib(ValueNS, RibKind::Normal, |this| { let old = this.diagnostic_metadata.in_if_condition.replace(cond); this.visit_expr(cond); this.diagnostic_metadata.in_if_condition = old; @@ -4017,7 +4019,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ExprKind::ForLoop(ref pat, ref iter_expr, ref block, label) => { self.visit_expr(iter_expr); - self.with_rib(ValueNS, NormalRibKind, |this| { + self.with_rib(ValueNS, RibKind::Normal, |this| { this.resolve_pattern_top(pat, PatternSource::For); this.resolve_labeled_block(label, expr.id, block); }); @@ -4073,8 +4075,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ref body, .. }) => { - self.with_rib(ValueNS, NormalRibKind, |this| { - this.with_label_rib(ClosureOrAsyncRibKind, |this| { + self.with_rib(ValueNS, RibKind::Normal, |this| { + this.with_label_rib(RibKind::ClosureOrAsync, |this| { // Resolve arguments: this.resolve_params(&fn_decl.inputs); // No need to resolve return type -- @@ -4098,7 +4100,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }) => { self.with_generic_param_rib( &generic_params, - NormalRibKind, + RibKind::Normal, LifetimeRibKind::Generics { binder: expr.id, kind: LifetimeBinderKind::Closure, @@ -4109,7 +4111,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } ExprKind::Closure(..) => visit::walk_expr(self, expr), ExprKind::Async(..) => { - self.with_label_rib(ClosureOrAsyncRibKind, |this| visit::walk_expr(this, expr)); + self.with_label_rib(RibKind::ClosureOrAsync, |this| visit::walk_expr(this, expr)); } ExprKind::Repeat(ref elem, ref ct) => { self.visit_expr(elem); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index e215b6b7090..42d498c7ee0 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -605,7 +605,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } // Try to find in last block rib - if let Some(rib) = &self.last_block_rib && let RibKind::NormalRibKind = rib.kind { + if let Some(rib) = &self.last_block_rib && let RibKind::Normal = rib.kind { for (ident, &res) in &rib.bindings { if let Res::Local(_) = res && path.len() == 1 && ident.span.eq_ctxt(path[0].ident.span) && @@ -1690,7 +1690,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } // Items in scope - if let RibKind::ModuleRibKind(module) = rib.kind { + if let RibKind::Module(module) = rib.kind { // Items from this module self.r.add_module_candidates(module, &mut names, &filter_fn, Some(ctxt)); diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs index a2ec318df6d..6b559cb5b2f 100644 --- a/compiler/rustc_serialize/src/opaque.rs +++ b/compiler/rustc_serialize/src/opaque.rs @@ -265,52 +265,41 @@ impl Drop for FileEncoder { } } -macro_rules! file_encoder_write_leb128 { - ($enc:expr, $value:expr, $int_ty:ty, $fun:ident) => {{ - const MAX_ENCODED_LEN: usize = $crate::leb128::max_leb128_len::<$int_ty>(); +macro_rules! write_leb128 { + ($this_fn:ident, $int_ty:ty, $write_leb_fn:ident) => { + #[inline] + fn $this_fn(&mut self, v: $int_ty) { + const MAX_ENCODED_LEN: usize = $crate::leb128::max_leb128_len::<$int_ty>(); - // We ensure this during `FileEncoder` construction. - debug_assert!($enc.capacity() >= MAX_ENCODED_LEN); + // We ensure this during `FileEncoder` construction. + debug_assert!(self.capacity() >= MAX_ENCODED_LEN); - let mut buffered = $enc.buffered; + let mut buffered = self.buffered; - // This can't overflow. See assertion in `FileEncoder::with_capacity`. - if std::intrinsics::unlikely(buffered + MAX_ENCODED_LEN > $enc.capacity()) { - $enc.flush(); - buffered = 0; - } + // This can't overflow. See assertion in `FileEncoder::with_capacity`. + if std::intrinsics::unlikely(buffered + MAX_ENCODED_LEN > self.capacity()) { + self.flush(); + buffered = 0; + } - // SAFETY: The above check and flush ensures that there is enough - // room to write the encoded value to the buffer. - let buf = unsafe { - &mut *($enc.buf.as_mut_ptr().add(buffered) as *mut [MaybeUninit<u8>; MAX_ENCODED_LEN]) - }; + // SAFETY: The above check and flush ensures that there is enough + // room to write the encoded value to the buffer. + let buf = unsafe { + &mut *(self.buf.as_mut_ptr().add(buffered) + as *mut [MaybeUninit<u8>; MAX_ENCODED_LEN]) + }; - let encoded = leb128::$fun(buf, $value); - $enc.buffered = buffered + encoded.len(); - }}; + let encoded = leb128::$write_leb_fn(buf, v); + self.buffered = buffered + encoded.len(); + } + }; } impl Encoder for FileEncoder { - #[inline] - fn emit_usize(&mut self, v: usize) { - file_encoder_write_leb128!(self, v, usize, write_usize_leb128) - } - - #[inline] - fn emit_u128(&mut self, v: u128) { - file_encoder_write_leb128!(self, v, u128, write_u128_leb128) - } - - #[inline] - fn emit_u64(&mut self, v: u64) { - file_encoder_write_leb128!(self, v, u64, write_u64_leb128) - } - - #[inline] - fn emit_u32(&mut self, v: u32) { - file_encoder_write_leb128!(self, v, u32, write_u32_leb128) - } + write_leb128!(emit_usize, usize, write_usize_leb128); + write_leb128!(emit_u128, u128, write_u128_leb128); + write_leb128!(emit_u64, u64, write_u64_leb128); + write_leb128!(emit_u32, u32, write_u32_leb128); #[inline] fn emit_u16(&mut self, v: u16) { @@ -322,25 +311,10 @@ impl Encoder for FileEncoder { self.write_one(v); } - #[inline] - fn emit_isize(&mut self, v: isize) { - file_encoder_write_leb128!(self, v, isize, write_isize_leb128) - } - - #[inline] - fn emit_i128(&mut self, v: i128) { - file_encoder_write_leb128!(self, v, i128, write_i128_leb128) - } - - #[inline] - fn emit_i64(&mut self, v: i64) { - file_encoder_write_leb128!(self, v, i64, write_i64_leb128) - } - - #[inline] - fn emit_i32(&mut self, v: i32) { - file_encoder_write_leb128!(self, v, i32, write_i32_leb128) - } + write_leb128!(emit_isize, isize, write_isize_leb128); + write_leb128!(emit_i128, i128, write_i128_leb128); + write_leb128!(emit_i64, i64, write_i64_leb128); + write_leb128!(emit_i32, i32, write_i32_leb128); #[inline] fn emit_i16(&mut self, v: i16) { @@ -437,30 +411,19 @@ impl<'a> MemDecoder<'a> { } macro_rules! read_leb128 { - ($dec:expr, $fun:ident) => {{ leb128::$fun($dec) }}; + ($this_fn:ident, $int_ty:ty, $read_leb_fn:ident) => { + #[inline] + fn $this_fn(&mut self) -> $int_ty { + leb128::$read_leb_fn(self) + } + }; } impl<'a> Decoder for MemDecoder<'a> { - #[inline] - fn position(&self) -> usize { - // SAFETY: This type guarantees start <= current - unsafe { self.current.sub_ptr(self.start) } - } - - #[inline] - fn read_u128(&mut self) -> u128 { - read_leb128!(self, read_u128_leb128) - } - - #[inline] - fn read_u64(&mut self) -> u64 { - read_leb128!(self, read_u64_leb128) - } - - #[inline] - fn read_u32(&mut self) -> u32 { - read_leb128!(self, read_u32_leb128) - } + read_leb128!(read_usize, usize, read_usize_leb128); + read_leb128!(read_u128, u128, read_u128_leb128); + read_leb128!(read_u64, u64, read_u64_leb128); + read_leb128!(read_u32, u32, read_u32_leb128); #[inline] fn read_u16(&mut self) -> u16 { @@ -480,25 +443,10 @@ impl<'a> Decoder for MemDecoder<'a> { } } - #[inline] - fn read_usize(&mut self) -> usize { - read_leb128!(self, read_usize_leb128) - } - - #[inline] - fn read_i128(&mut self) -> i128 { - read_leb128!(self, read_i128_leb128) - } - - #[inline] - fn read_i64(&mut self) -> i64 { - read_leb128!(self, read_i64_leb128) - } - - #[inline] - fn read_i32(&mut self) -> i32 { - read_leb128!(self, read_i32_leb128) - } + read_leb128!(read_isize, isize, read_isize_leb128); + read_leb128!(read_i128, i128, read_i128_leb128); + read_leb128!(read_i64, i64, read_i64_leb128); + read_leb128!(read_i32, i32, read_i32_leb128); #[inline] fn read_i16(&mut self) -> i16 { @@ -506,11 +454,6 @@ impl<'a> Decoder for MemDecoder<'a> { } #[inline] - fn read_isize(&mut self) -> isize { - read_leb128!(self, read_isize_leb128) - } - - #[inline] fn read_raw_bytes(&mut self, bytes: usize) -> &'a [u8] { if bytes > self.remaining() { Self::decoder_exhausted(); @@ -532,6 +475,12 @@ impl<'a> Decoder for MemDecoder<'a> { // Since we just checked current == end, the current pointer must be inbounds. unsafe { *self.current } } + + #[inline] + fn position(&self) -> usize { + // SAFETY: This type guarantees start <= current + unsafe { self.current.sub_ptr(self.start) } + } } // Specializations for contiguous byte sequences follow. The default implementations for slices diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index e1bc598736f..06166cabc18 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -1,9 +1,5 @@ //! Support code for encoding and decoding types. -/* -Core encoding and decoding interfaces. -*/ - use std::alloc::Allocator; use std::borrow::Cow; use std::cell::{Cell, RefCell}; @@ -35,13 +31,13 @@ const STR_SENTINEL: u8 = 0xC1; /// really makes sense to store floating-point values at all. /// (If you need it, revert <https://github.com/rust-lang/rust/pull/109984>.) pub trait Encoder { - // Primitive types: fn emit_usize(&mut self, v: usize); fn emit_u128(&mut self, v: u128); fn emit_u64(&mut self, v: u64); fn emit_u32(&mut self, v: u32); fn emit_u16(&mut self, v: u16); fn emit_u8(&mut self, v: u8); + fn emit_isize(&mut self, v: isize); fn emit_i128(&mut self, v: i128); fn emit_i64(&mut self, v: i64); @@ -93,13 +89,13 @@ pub trait Encoder { /// really makes sense to store floating-point values at all. /// (If you need it, revert <https://github.com/rust-lang/rust/pull/109984>.) pub trait Decoder { - // Primitive types: fn read_usize(&mut self) -> usize; fn read_u128(&mut self) -> u128; fn read_u64(&mut self) -> u64; fn read_u32(&mut self) -> u32; fn read_u16(&mut self) -> u16; fn read_u8(&mut self) -> u8; + fn read_isize(&mut self) -> isize; fn read_i128(&mut self) -> i128; fn read_i64(&mut self) -> i64; diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 8a900ca427e..341cc61fd1c 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -69,7 +69,6 @@ use std::hash::Hash; use std::ops::{Add, Range, Sub}; use std::path::{Path, PathBuf}; use std::str::FromStr; -use std::sync::Arc; use md5::Digest; use md5::Md5; @@ -1269,13 +1268,13 @@ pub enum DebuggerVisualizerType { #[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable)] pub struct DebuggerVisualizerFile { /// The complete debugger visualizer source. - pub src: Arc<[u8]>, + pub src: Lrc<[u8]>, /// Indicates which visualizer type this targets. pub visualizer_type: DebuggerVisualizerType, } impl DebuggerVisualizerFile { - pub fn new(src: Arc<[u8]>, visualizer_type: DebuggerVisualizerType) -> Self { + pub fn new(src: Lrc<[u8]>, visualizer_type: DebuggerVisualizerType) -> Self { DebuggerVisualizerFile { src, visualizer_type } } } diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index a002421aeef..18f25aec5fe 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -101,6 +101,7 @@ #![feature(array_into_iter_constructors)] #![feature(array_methods)] #![feature(array_windows)] +#![feature(ascii_char)] #![feature(assert_matches)] #![feature(async_iterator)] #![feature(coerce_unsized)] diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index cf16a3424a0..b9ef76c109a 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2527,6 +2527,15 @@ impl<T: fmt::Display + ?Sized> ToString for T { } #[cfg(not(no_global_oom_handling))] +#[unstable(feature = "ascii_char", issue = "110998")] +impl ToString for core::ascii::Char { + #[inline] + fn to_string(&self) -> String { + self.as_str().to_owned() + } +} + +#[cfg(not(no_global_oom_handling))] #[stable(feature = "char_to_string_specialization", since = "1.46.0")] impl ToString for char { #[inline] diff --git a/library/core/src/array/ascii.rs b/library/core/src/array/ascii.rs new file mode 100644 index 00000000000..6750d7c0711 --- /dev/null +++ b/library/core/src/array/ascii.rs @@ -0,0 +1,34 @@ +use crate::ascii; + +#[cfg(not(test))] +impl<const N: usize> [u8; N] { + /// Converts this array of bytes into a array of ASCII characters, + /// or returns `None` if any of the characters is non-ASCII. + #[unstable(feature = "ascii_char", issue = "110998")] + #[must_use] + #[inline] + pub fn as_ascii(&self) -> Option<&[ascii::Char; N]> { + if self.is_ascii() { + // SAFETY: Just checked that it's ASCII + Some(unsafe { self.as_ascii_unchecked() }) + } else { + None + } + } + + /// Converts this array of bytes into a array of ASCII characters, + /// without checking whether they're valid. + /// + /// # Safety + /// + /// Every byte in the array must be in `0..=127`, or else this is UB. + #[unstable(feature = "ascii_char", issue = "110998")] + #[must_use] + #[inline] + pub const unsafe fn as_ascii_unchecked(&self) -> &[ascii::Char; N] { + let byte_ptr: *const [u8; N] = self; + let ascii_ptr = byte_ptr as *const [ascii::Char; N]; + // SAFETY: The caller promised all the bytes are ASCII + unsafe { &*ascii_ptr } + } +} diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 940558974e6..bdb4c975909 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -17,6 +17,7 @@ use crate::ops::{ }; use crate::slice::{Iter, IterMut}; +mod ascii; mod drain; mod equality; mod iter; diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs index 065f1b3e70e..7fd14a7e1ea 100644 --- a/library/core/src/ascii.rs +++ b/library/core/src/ascii.rs @@ -14,6 +14,10 @@ use crate::fmt; use crate::iter::FusedIterator; use crate::num::NonZeroUsize; +mod ascii_char; +#[unstable(feature = "ascii_char", issue = "110998")] +pub use ascii_char::AsciiChar as Char; + /// An iterator over the escaped version of a byte. /// /// This `struct` is created by the [`escape_default`] function. See its diff --git a/library/core/src/ascii/ascii_char.rs b/library/core/src/ascii/ascii_char.rs new file mode 100644 index 00000000000..f093a0990d1 --- /dev/null +++ b/library/core/src/ascii/ascii_char.rs @@ -0,0 +1,565 @@ +//! This uses the name `AsciiChar`, even though it's not exposed that way right now, +//! because it avoids a whole bunch of "are you sure you didn't mean `char`?" +//! suggestions from rustc if you get anything slightly wrong in here, and overall +//! helps with clarity as we're also referring to `char` intentionally in here. + +use crate::fmt; +use crate::mem::transmute; + +/// One of the 128 Unicode characters from U+0000 through U+007F, +/// often known as the [ASCII] subset. +/// +/// Officially, this is the first [block] in Unicode, _Basic Latin_. +/// For details, see the [*C0 Controls and Basic Latin*][chart] code chart. +/// +/// This block was based on older 7-bit character code standards such as +/// ANSI X3.4-1977, ISO 646-1973, and [NIST FIPS 1-2]. +/// +/// # When to use this +/// +/// The main advantage of this subset is that it's always valid UTF-8. As such, +/// the `&[ascii::Char]` -> `&str` conversion function (as well as other related +/// ones) are O(1): *no* runtime checks are needed. +/// +/// If you're consuming strings, you should usually handle Unicode and thus +/// accept `str`s, not limit yourself to `ascii::Char`s. +/// +/// However, certain formats are intentionally designed to produce ASCII-only +/// output in order to be 8-bit-clean. In those cases, it can be simpler and +/// faster to generate `ascii::Char`s instead of dealing with the variable width +/// properties of general UTF-8 encoded strings, while still allowing the result +/// to be used freely with other Rust things that deal in general `str`s. +/// +/// For example, a UUID library might offer a way to produce the string +/// representation of a UUID as an `[ascii::Char; 36]` to avoid memory +/// allocation yet still allow it to be used as UTF-8 via `as_str` without +/// paying for validation (or needing `unsafe` code) the way it would if it +/// were provided as a `[u8; 36]`. +/// +/// # Layout +/// +/// This type is guaranteed to have a size and alignment of 1 byte. +/// +/// # Names +/// +/// The variants on this type are [Unicode names][NamesList] of the characters +/// in upper camel case, with a few tweaks: +/// - For `<control>` characters, the primary alias name is used. +/// - `LATIN` is dropped, as this block has no non-latin letters. +/// - `LETTER` is dropped, as `CAPITAL`/`SMALL` suffices in this block. +/// - `DIGIT`s use a single digit rather than writing out `ZERO`, `ONE`, etc. +/// +/// [ASCII]: https://www.unicode.org/glossary/index.html#ASCII +/// [block]: https://www.unicode.org/glossary/index.html#block +/// [chart]: https://www.unicode.org/charts/PDF/U0000.pdf +/// [NIST FIPS 1-2]: https://nvlpubs.nist.gov/nistpubs/Legacy/FIPS/fipspub1-2-1977.pdf +/// [NamesList]: https://www.unicode.org/Public/15.0.0/ucd/NamesList.txt +#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[unstable(feature = "ascii_char", issue = "110998")] +#[repr(u8)] +pub enum AsciiChar { + /// U+0000 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Null = 0, + /// U+0001 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + StartOfHeading = 1, + /// U+0002 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + StartOfText = 2, + /// U+0003 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + EndOfText = 3, + /// U+0004 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + EndOfTransmission = 4, + /// U+0005 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Enquiry = 5, + /// U+0006 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Acknowledge = 6, + /// U+0007 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Bell = 7, + /// U+0008 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Backspace = 8, + /// U+0009 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CharacterTabulation = 9, + /// U+000A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LineFeed = 10, + /// U+000B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LineTabulation = 11, + /// U+000C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + FormFeed = 12, + /// U+000D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CarriageReturn = 13, + /// U+000E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + ShiftOut = 14, + /// U+000F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + ShiftIn = 15, + /// U+0010 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + DataLinkEscape = 16, + /// U+0011 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + DeviceControlOne = 17, + /// U+0012 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + DeviceControlTwo = 18, + /// U+0013 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + DeviceControlThree = 19, + /// U+0014 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + DeviceControlFour = 20, + /// U+0015 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + NegativeAcknowledge = 21, + /// U+0016 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SynchronousIdle = 22, + /// U+0017 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + EndOfTransmissionBlock = 23, + /// U+0018 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Cancel = 24, + /// U+0019 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + EndOfMedium = 25, + /// U+001A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Substitute = 26, + /// U+001B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Escape = 27, + /// U+001C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + InformationSeparatorFour = 28, + /// U+001D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + InformationSeparatorThree = 29, + /// U+001E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + InformationSeparatorTwo = 30, + /// U+001F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + InformationSeparatorOne = 31, + /// U+0020 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Space = 32, + /// U+0021 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + ExclamationMark = 33, + /// U+0022 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + QuotationMark = 34, + /// U+0023 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + NumberSign = 35, + /// U+0024 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + DollarSign = 36, + /// U+0025 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + PercentSign = 37, + /// U+0026 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Ampersand = 38, + /// U+0027 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Apostrophe = 39, + /// U+0028 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LeftParenthesis = 40, + /// U+0029 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + RightParenthesis = 41, + /// U+002A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Asterisk = 42, + /// U+002B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + PlusSign = 43, + /// U+002C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Comma = 44, + /// U+002D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + HyphenMinus = 45, + /// U+002E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + FullStop = 46, + /// U+002F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Solidus = 47, + /// U+0030 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit0 = 48, + /// U+0031 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit1 = 49, + /// U+0032 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit2 = 50, + /// U+0033 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit3 = 51, + /// U+0034 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit4 = 52, + /// U+0035 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit5 = 53, + /// U+0036 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit6 = 54, + /// U+0037 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit7 = 55, + /// U+0038 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit8 = 56, + /// U+0039 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit9 = 57, + /// U+003A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Colon = 58, + /// U+003B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Semicolon = 59, + /// U+003C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LessThanSign = 60, + /// U+003D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + EqualsSign = 61, + /// U+003E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + GreaterThanSign = 62, + /// U+003F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + QuestionMark = 63, + /// U+0040 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CommercialAt = 64, + /// U+0041 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalA = 65, + /// U+0042 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalB = 66, + /// U+0043 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalC = 67, + /// U+0044 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalD = 68, + /// U+0045 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalE = 69, + /// U+0046 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalF = 70, + /// U+0047 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalG = 71, + /// U+0048 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalH = 72, + /// U+0049 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalI = 73, + /// U+004A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalJ = 74, + /// U+004B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalK = 75, + /// U+004C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalL = 76, + /// U+004D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalM = 77, + /// U+004E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalN = 78, + /// U+004F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalO = 79, + /// U+0050 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalP = 80, + /// U+0051 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalQ = 81, + /// U+0052 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalR = 82, + /// U+0053 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalS = 83, + /// U+0054 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalT = 84, + /// U+0055 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalU = 85, + /// U+0056 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalV = 86, + /// U+0057 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalW = 87, + /// U+0058 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalX = 88, + /// U+0059 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalY = 89, + /// U+005A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalZ = 90, + /// U+005B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LeftSquareBracket = 91, + /// U+005C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + ReverseSolidus = 92, + /// U+005D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + RightSquareBracket = 93, + /// U+005E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CircumflexAccent = 94, + /// U+005F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LowLine = 95, + /// U+0060 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + GraveAccent = 96, + /// U+0061 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallA = 97, + /// U+0062 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallB = 98, + /// U+0063 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallC = 99, + /// U+0064 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallD = 100, + /// U+0065 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallE = 101, + /// U+0066 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallF = 102, + /// U+0067 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallG = 103, + /// U+0068 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallH = 104, + /// U+0069 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallI = 105, + /// U+006A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallJ = 106, + /// U+006B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallK = 107, + /// U+006C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallL = 108, + /// U+006D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallM = 109, + /// U+006E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallN = 110, + /// U+006F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallO = 111, + /// U+0070 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallP = 112, + /// U+0071 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallQ = 113, + /// U+0072 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallR = 114, + /// U+0073 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallS = 115, + /// U+0074 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallT = 116, + /// U+0075 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallU = 117, + /// U+0076 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallV = 118, + /// U+0077 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallW = 119, + /// U+0078 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallX = 120, + /// U+0079 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallY = 121, + /// U+007A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallZ = 122, + /// U+007B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LeftCurlyBracket = 123, + /// U+007C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + VerticalLine = 124, + /// U+007D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + RightCurlyBracket = 125, + /// U+007E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Tilde = 126, + /// U+007F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Delete = 127, +} + +impl AsciiChar { + /// Creates an ascii character from the byte `b`, + /// or returns `None` if it's too large. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn from_u8(b: u8) -> Option<Self> { + if b <= 127 { + // SAFETY: Just checked that `b` is in-range + Some(unsafe { Self::from_u8_unchecked(b) }) + } else { + None + } + } + + /// Creates an ASCII character from the byte `b`, + /// without checking whether it's valid. + /// + /// # Safety + /// + /// `b` must be in `0..=127`, or else this is UB. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const unsafe fn from_u8_unchecked(b: u8) -> Self { + // SAFETY: Our safety precondition is that `b` is in-range. + unsafe { transmute(b) } + } + + /// When passed the *number* `0`, `1`, …, `9`, returns the *character* + /// `'0'`, `'1'`, …, `'9'` respectively. + /// + /// If `d >= 10`, returns `None`. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn digit(d: u8) -> Option<Self> { + if d < 10 { + // SAFETY: Just checked it's in-range. + Some(unsafe { Self::digit_unchecked(d) }) + } else { + None + } + } + + /// When passed the *number* `0`, `1`, …, `9`, returns the *character* + /// `'0'`, `'1'`, …, `'9'` respectively, without checking that it's in-range. + /// + /// # Safety + /// + /// This is immediate UB if called with `d > 64`. + /// + /// If `d >= 10` and `d <= 64`, this is allowed to return any value or panic. + /// Notably, it should not be expected to return hex digits, or any other + /// reasonable extension of the decimal digits. + /// + /// (This lose safety condition is intended to simplify soundness proofs + /// when writing code using this method, since the implementation doesn't + /// need something really specific, not to make those other arguments do + /// something useful. It might be tightened before stabilization.) + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const unsafe fn digit_unchecked(d: u8) -> Self { + debug_assert!(d < 10); + + // SAFETY: `'0'` through `'9'` are U+00030 through U+0039, + // so because `d` must be 64 or less the addition can return at most + // 112 (0x70), which doesn't overflow and is within the ASCII range. + unsafe { + let byte = b'0'.unchecked_add(d); + Self::from_u8_unchecked(byte) + } + } + + /// Gets this ASCII character as a byte. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn as_u8(self) -> u8 { + self as u8 + } + + /// Gets this ASCII character as a `char` Unicode Scalar Value. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn as_char(self) -> char { + self as u8 as char + } + + /// Views this ASCII character as a one-code-unit UTF-8 `str`. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn as_str(&self) -> &str { + crate::slice::from_ref(self).as_str() + } +} + +impl [AsciiChar] { + /// Views this slice of ASCII characters as a UTF-8 `str`. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn as_str(&self) -> &str { + let ascii_ptr: *const Self = self; + let str_ptr = ascii_ptr as *const str; + // SAFETY: Each ASCII codepoint in UTF-8 is encoded as one single-byte + // code unit having the same value as the ASCII byte. + unsafe { &*str_ptr } + } + + /// Views this slice of ASCII characters as a slice of `u8` bytes. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn as_bytes(&self) -> &[u8] { + self.as_str().as_bytes() + } +} + +#[unstable(feature = "ascii_char", issue = "110998")] +impl fmt::Display for AsciiChar { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + <str as fmt::Display>::fmt(self.as_str(), f) + } +} diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 2408f178075..1dfa9c34db1 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -1,5 +1,6 @@ //! impl char {} +use crate::ascii; use crate::slice; use crate::str::from_utf8_unchecked_mut; use crate::unicode::printable::is_printable; @@ -1101,6 +1102,24 @@ impl char { *self as u32 <= 0x7F } + /// Returns `Some` if the value is within the ASCII range, + /// or `None` if it's not. + /// + /// This is preferred to [`Self::is_ascii`] when you're passing the value + /// along to something else that can take [`ascii::Char`] rather than + /// needing to check again for itself whether the value is in ASCII. + #[must_use] + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn as_ascii(&self) -> Option<ascii::Char> { + if self.is_ascii() { + // SAFETY: Just checked that this is ASCII. + Some(unsafe { ascii::Char::from_u8_unchecked(*self as u8) }) + } else { + None + } + } + /// Makes a copy of the value in its ASCII upper case equivalent. /// /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index fdd7be625ed..08444421dca 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -472,7 +472,16 @@ impl u8 { #[rustc_const_stable(feature = "const_u8_is_ascii", since = "1.43.0")] #[inline] pub const fn is_ascii(&self) -> bool { - *self & 128 == 0 + *self <= 127 + } + + /// If the value of this byte is within the ASCII range, returns it as an + /// [ASCII character](ascii::Char). Otherwise, returns `None`. + #[must_use] + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn as_ascii(&self) -> Option<ascii::Char> { + ascii::Char::from_u8(*self) } /// Makes a copy of the value in its ASCII upper case equivalent. diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index b80bfe1c92d..74a325b89d4 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -713,6 +713,32 @@ macro_rules! nonzero_signed_operations { unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) } } + /// Returns `true` if `self` is positive and `false` if the + /// number is negative. + /// + /// # Example + /// + /// ``` + /// #![feature(nonzero_negation_ops)] + /// + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + /// + /// assert!(pos_five.is_positive()); + /// assert!(!neg_five.is_positive()); + /// # Some(()) + /// # } + /// ``` + #[must_use] + #[inline] + #[unstable(feature = "nonzero_negation_ops", issue = "102443")] + pub const fn is_positive(self) -> bool { + self.get().is_positive() + } + /// Returns `true` if `self` is negative and `false` if the /// number is positive. /// diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 5e5399acc1b..7bae6692ad4 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -16,6 +16,36 @@ impl [u8] { is_ascii(self) } + /// If this slice [`is_ascii`](Self::is_ascii), returns it as a slice of + /// [ASCII characters](`ascii::Char`), otherwise returns `None`. + #[unstable(feature = "ascii_char", issue = "110998")] + #[must_use] + #[inline] + pub fn as_ascii(&self) -> Option<&[ascii::Char]> { + if self.is_ascii() { + // SAFETY: Just checked that it's ASCII + Some(unsafe { self.as_ascii_unchecked() }) + } else { + None + } + } + + /// Converts this slice of bytes into a slice of ASCII characters, + /// without checking whether they're valid. + /// + /// # Safety + /// + /// Every byte in the slice must be in `0..=127`, or else this is UB. + #[unstable(feature = "ascii_char", issue = "110998")] + #[must_use] + #[inline] + pub const unsafe fn as_ascii_unchecked(&self) -> &[ascii::Char] { + let byte_ptr: *const [u8] = self; + let ascii_ptr = byte_ptr as *const [ascii::Char]; + // SAFETY: The caller promised all the bytes are ASCII + unsafe { &*ascii_ptr } + } + /// Checks that two slices are an ASCII case-insensitive match. /// /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`, diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index a13107fd0de..66fa9cf6f64 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -16,6 +16,7 @@ mod validations; use self::pattern::Pattern; use self::pattern::{DoubleEndedSearcher, ReverseSearcher, Searcher}; +use crate::ascii; use crate::char::{self, EscapeDebugExtArgs}; use crate::mem; use crate::slice::{self, SliceIndex}; @@ -2366,6 +2367,16 @@ impl str { self.as_bytes().is_ascii() } + /// If this string slice [`is_ascii`](Self::is_ascii), returns it as a slice + /// of [ASCII characters](`ascii::Char`), otherwise returns `None`. + #[unstable(feature = "ascii_char", issue = "110998")] + #[must_use] + #[inline] + pub fn as_ascii(&self) -> Option<&[ascii::Char]> { + // Like in `is_ascii`, we can work on the bytes directly. + self.as_bytes().as_ascii() + } + /// Checks that two strings are an ASCII case-insensitive match. /// /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`, diff --git a/library/std/src/ascii.rs b/library/std/src/ascii.rs index c29f015777f..b18ab50de12 100644 --- a/library/std/src/ascii.rs +++ b/library/std/src/ascii.rs @@ -16,6 +16,9 @@ #[stable(feature = "rust1", since = "1.0.0")] pub use core::ascii::{escape_default, EscapeDefault}; +#[unstable(feature = "ascii_char", issue = "110998")] +pub use core::ascii::Char; + /// Extension methods for ASCII-subset only operations. /// /// Be aware that operations on seemingly non-ASCII characters can sometimes diff --git a/library/std/src/sys/common/thread_local/mod.rs b/library/std/src/sys/common/thread_local/mod.rs index 951d509ec95..77f64588310 100644 --- a/library/std/src/sys/common/thread_local/mod.rs +++ b/library/std/src/sys/common/thread_local/mod.rs @@ -1,5 +1,10 @@ #![unstable(feature = "thread_local_internals", reason = "should not be necessary", issue = "none")] +// There are three thread-local implementations: "static", "fast", "OS". +// The "OS" thread local key type is accessed via platform-specific API calls and is slow, while the +// "fast" key type is accessed via code generated via LLVM, where TLS keys are set up by the linker. +// "static" is for single-threaded platforms where a global static is sufficient. + cfg_if::cfg_if! { if #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] { #[doc(hidden)] diff --git a/library/std/src/sys/common/thread_local/os_local.rs b/library/std/src/sys/common/thread_local/os_local.rs index d004897df28..5d48ce1e03b 100644 --- a/library/std/src/sys/common/thread_local/os_local.rs +++ b/library/std/src/sys/common/thread_local/os_local.rs @@ -18,7 +18,7 @@ pub macro thread_local_inner { ) -> $crate::option::Option<&'static $t> { const INIT_EXPR: $t = $init; - // On platforms without `#[thread_local]` we fall back to the + // On platforms without `#[thread_local]` we fall back to the // same implementation as below for os thread locals. #[inline] const fn __init() -> $t { INIT_EXPR } diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 9cdc17a287c..f712c872708 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -193,22 +193,22 @@ pub use scoped::{scope, Scope, ScopedJoinHandle}; #[macro_use] mod local; -#[stable(feature = "rust1", since = "1.0.0")] -pub use self::local::{AccessError, LocalKey}; - -// Provide the type used by the thread_local! macro to access TLS keys. This -// needs to be kept in sync with the macro itself (in `local.rs`). -// There are three types: "static", "fast", "OS". The "OS" thread local key -// type is accessed via platform-specific API calls and is slow, while the "fast" -// key type is accessed via code generated via LLVM, where TLS keys are set up -// by the elf linker. "static" is for single-threaded platforms where a global -// static is sufficient. - -// Implementation details used by the thread_local!{} macro. -#[doc(hidden)] -#[unstable(feature = "thread_local_internals", issue = "none")] -pub mod local_impl { - pub use crate::sys::common::thread_local::{thread_local_inner, Key}; +cfg_if::cfg_if! { + if #[cfg(test)] { + // Avoid duplicating the global state assoicated with thread-locals between this crate and + // realstd. Miri relies on this. + pub use realstd::thread::{local_impl, AccessError, LocalKey}; + } else { + #[stable(feature = "rust1", since = "1.0.0")] + pub use self::local::{AccessError, LocalKey}; + + // Implementation details used by the thread_local!{} macro. + #[doc(hidden)] + #[unstable(feature = "thread_local_internals", issue = "none")] + pub mod local_impl { + pub use crate::sys::common::thread_local::{thread_local_inner, Key}; + } + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml new file mode 100644 index 00000000000..5356ee277cc --- /dev/null +++ b/library/sysroot/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "sysroot" +version = "0.0.0" +edition = "2021" + +# this is a dummy crate to ensure that all required crates appear in the sysroot +[dependencies] +proc_macro = { path = "../proc_macro" } +std = { path = "../std" } +test = { path = "../test" } + +# Forward features to the `std` crate as necessary +[features] +default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind"] +backtrace = ["std/backtrace"] +compiler-builtins-c = ["std/compiler-builtins-c"] +compiler-builtins-mem = ["std/compiler-builtins-mem"] +compiler-builtins-no-asm = ["std/compiler-builtins-no-asm"] +compiler-builtins-mangled-names = ["std/compiler-builtins-mangled-names"] +llvm-libunwind = ["std/llvm-libunwind"] +system-llvm-libunwind = ["std/system-llvm-libunwind"] +panic-unwind = ["std/panic_unwind"] +panic_immediate_abort = ["std/panic_immediate_abort"] +profiler = ["std/profiler"] +std_detect_file_io = ["std/std_detect_file_io"] +std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"] +std_detect_env_override = ["std/std_detect_env_override"] diff --git a/library/sysroot/src/lib.rs b/library/sysroot/src/lib.rs new file mode 100644 index 00000000000..71ceb580a40 --- /dev/null +++ b/library/sysroot/src/lib.rs @@ -0,0 +1 @@ +// This is intentionally empty since this crate is only used to depend on other library crates. diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml index 18cb023d274..91a1abde059 100644 --- a/library/test/Cargo.toml +++ b/library/test/Cargo.toml @@ -12,23 +12,3 @@ std = { path = "../std" } core = { path = "../core" } panic_unwind = { path = "../panic_unwind" } panic_abort = { path = "../panic_abort" } - -# not actually used but needed to always have proc_macro in the sysroot -proc_macro = { path = "../proc_macro" } - -# Forward features to the `std` crate as necessary -[features] -default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind"] -backtrace = ["std/backtrace"] -compiler-builtins-c = ["std/compiler-builtins-c"] -compiler-builtins-mem = ["std/compiler-builtins-mem"] -compiler-builtins-no-asm = ["std/compiler-builtins-no-asm"] -compiler-builtins-mangled-names = ["std/compiler-builtins-mangled-names"] -llvm-libunwind = ["std/llvm-libunwind"] -system-llvm-libunwind = ["std/system-llvm-libunwind"] -panic-unwind = ["std/panic_unwind"] -panic_immediate_abort = ["std/panic_immediate_abort"] -profiler = ["std/profiler"] -std_detect_file_io = ["std/std_detect_file_io"] -std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"] -std_detect_env_override = ["std/std_detect_env_override"] diff --git a/library/test/src/formatters/junit.rs b/library/test/src/formatters/junit.rs index 2e07ce3c099..9f5bf24367e 100644 --- a/library/test/src/formatters/junit.rs +++ b/library/test/src/formatters/junit.rs @@ -11,7 +11,7 @@ use crate::{ pub struct JunitFormatter<T> { out: OutputLocation<T>, - results: Vec<(TestDesc, TestResult, Duration)>, + results: Vec<(TestDesc, TestResult, Duration, Vec<u8>)>, } impl<T: Write> JunitFormatter<T> { @@ -26,6 +26,18 @@ impl<T: Write> JunitFormatter<T> { } } +fn str_to_cdata(s: &str) -> String { + // Drop the stdout in a cdata. Unfortunately, you can't put either of `]]>` or + // `<?'` in a CDATA block, so the escaping gets a little weird. + let escaped_output = s.replace("]]>", "]]]]><![CDATA[>"); + let escaped_output = escaped_output.replace("<?", "<]]><![CDATA[?"); + // We also smuggle newlines as 
 so as to keep all the output on one line + let escaped_output = escaped_output.replace("\n", "]]>
<![CDATA["); + // Prune empty CDATA blocks resulting from any escaping + let escaped_output = escaped_output.replace("<![CDATA[]]>", ""); + format!("<![CDATA[{}]]>", escaped_output) +} + impl<T: Write> OutputFormatter for JunitFormatter<T> { fn write_discovery_start(&mut self) -> io::Result<()> { Err(io::Error::new(io::ErrorKind::NotFound, "Not yet implemented!")) @@ -63,14 +75,14 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> { desc: &TestDesc, result: &TestResult, exec_time: Option<&time::TestExecTime>, - _stdout: &[u8], + stdout: &[u8], _state: &ConsoleTestState, ) -> io::Result<()> { // Because the testsuite node holds some of the information as attributes, we can't write it // until all of the tests have finished. Instead of writing every result as they come in, we add // them to a Vec and write them all at once when run is complete. let duration = exec_time.map(|t| t.0).unwrap_or_default(); - self.results.push((desc.clone(), result.clone(), duration)); + self.results.push((desc.clone(), result.clone(), duration, stdout.to_vec())); Ok(()) } fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> { @@ -85,7 +97,7 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> { >", state.failed, state.total, state.ignored ))?; - for (desc, result, duration) in std::mem::take(&mut self.results) { + for (desc, result, duration, stdout) in std::mem::take(&mut self.results) { let (class_name, test_name) = parse_class_name(&desc); match result { TestResult::TrIgnored => { /* no-op */ } @@ -98,6 +110,11 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> { duration.as_secs_f64() ))?; self.write_message("<failure type=\"assert\"/>")?; + if !stdout.is_empty() { + self.write_message("<system-out>")?; + self.write_message(&str_to_cdata(&String::from_utf8_lossy(&stdout)))?; + self.write_message("</system-out>")?; + } self.write_message("</testcase>")?; } @@ -110,6 +127,11 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> { duration.as_secs_f64() ))?; self.write_message(&format!("<failure message=\"{m}\" type=\"assert\"/>"))?; + if !stdout.is_empty() { + self.write_message("<system-out>")?; + self.write_message(&str_to_cdata(&String::from_utf8_lossy(&stdout)))?; + self.write_message("</system-out>")?; + } self.write_message("</testcase>")?; } @@ -136,11 +158,19 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> { TestResult::TrOk => { self.write_message(&format!( "<testcase classname=\"{}\" \ - name=\"{}\" time=\"{}\"/>", + name=\"{}\" time=\"{}\"", class_name, test_name, duration.as_secs_f64() ))?; + if stdout.is_empty() || !state.options.display_output { + self.write_message("/>")?; + } else { + self.write_message("><system-out>")?; + self.write_message(&str_to_cdata(&String::from_utf8_lossy(&stdout)))?; + self.write_message("</system-out>")?; + self.write_message("</testcase>")?; + } } } } diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 60de46ce64c..956b82385f6 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -79,7 +79,7 @@ impl Step for Std { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.all_krates("test").path("library") + run.all_krates("sysroot").path("library") } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index 7ebd0a8f270..0d9fd56b038 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -81,7 +81,7 @@ macro_rules! clean_crate_tree { clean_crate_tree! { Rustc, Mode::Rustc, "rustc-main"; - Std, Mode::Std, "test"; + Std, Mode::Std, "sysroot"; } fn clean_default(build: &Build, all: bool) { diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 7d2a6862500..966ae00fa1d 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -56,7 +56,7 @@ impl Step for Std { // When downloading stage1, the standard library has already been copied to the sysroot, so // there's no need to rebuild it. let builder = run.builder; - run.crate_or_deps("test") + run.crate_or_deps("sysroot") .path("library") .lazy_default_condition(Box::new(|| !builder.download_rustc())) } @@ -364,7 +364,7 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car .arg("--features") .arg(features) .arg("--manifest-path") - .arg(builder.src.join("library/test/Cargo.toml")); + .arg(builder.src.join("library/sysroot/Cargo.toml")); // Help the libc crate compile by assisting it in finding various // sysroot native libraries. diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 3b35ca1d15d..9cead7adc8c 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -822,6 +822,8 @@ fn copy_src_dirs( "llvm-project\\compiler-rt", "llvm-project/cmake", "llvm-project\\cmake", + "llvm-project/runtimes", + "llvm-project\\runtimes", ]; if spath.contains("llvm-project") && !spath.ends_with("llvm-project") @@ -976,6 +978,7 @@ impl Step for PlainSourceTarball { "config.example.toml", "Cargo.toml", "Cargo.lock", + ".gitmodules", ]; let src_dirs = ["src", "compiler", "library", "tests"]; diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 9ad98eb5702..8f5d9bb66e1 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -438,7 +438,7 @@ impl Step for Std { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.all_krates("test").path("library").default_condition(builder.config.docs) + run.all_krates("sysroot").path("library").default_condition(builder.config.docs) } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index aee84e9c9be..cfccb516627 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -2145,7 +2145,7 @@ impl Step for Crate { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.crate_or_deps("test") + run.crate_or_deps("sysroot") } fn make_run(run: RunConfig<'_>) { diff --git a/tests/codegen/ascii-char.rs b/tests/codegen/ascii-char.rs new file mode 100644 index 00000000000..4167becf5e9 --- /dev/null +++ b/tests/codegen/ascii-char.rs @@ -0,0 +1,37 @@ +// compile-flags: -C opt-level=1 +// ignore-debug (the extra assertions get in the way) + +#![crate_type = "lib"] +#![feature(ascii_char)] + +use std::ascii::Char as AsciiChar; + +// CHECK-LABEL: i8 @unwrap_digit_from_remainder(i32 +#[no_mangle] +pub fn unwrap_digit_from_remainder(v: u32) -> AsciiChar { + // CHECK-NOT: icmp + // CHECK-NOT: panic + + // CHECK: %[[R:.+]] = urem i32 %v, 10 + // CHECK-NEXT: %[[T:.+]] = trunc i32 %[[R]] to i8 + // CHECK-NEXT: %[[D:.+]] = or i8 %[[T]], 48 + // CHECK-NEXT: ret i8 %[[D]] + + // CHECK-NOT: icmp + // CHECK-NOT: panic + AsciiChar::digit((v % 10) as u8).unwrap() +} + +// CHECK-LABEL: i8 @unwrap_from_masked(i8 +#[no_mangle] +pub fn unwrap_from_masked(b: u8) -> AsciiChar { + // CHECK-NOT: icmp + // CHECK-NOT: panic + + // CHECK: %[[M:.+]] = and i8 %b, 127 + // CHECK-NEXT: ret i8 %[[M]] + + // CHECK-NOT: icmp + // CHECK-NOT: panic + AsciiChar::from_u8(b & 0x7f).unwrap() +} diff --git a/tests/incremental/change_crate_dep_kind.rs b/tests/incremental/change_crate_dep_kind.rs index 8c35f6ca000..f518266016e 100644 --- a/tests/incremental/change_crate_dep_kind.rs +++ b/tests/incremental/change_crate_dep_kind.rs @@ -2,6 +2,7 @@ // detected then -Zincremental-verify-ich will trigger an assertion. // ignore-wasm32-bare compiled with panic=abort by default +// needs-unwind // revisions:cfail1 cfail2 // compile-flags: -Z query-dep-graph -Cpanic=unwind // build-pass (FIXME(62277): could be check-pass?) diff --git a/tests/incremental/issue-80691-bad-eval-cache.rs b/tests/incremental/issue-80691-bad-eval-cache.rs index 1a644fd88d6..ad8a338a796 100644 --- a/tests/incremental/issue-80691-bad-eval-cache.rs +++ b/tests/incremental/issue-80691-bad-eval-cache.rs @@ -1,6 +1,7 @@ // revisions: rfail1 rfail2 // failure-status: 101 // error-pattern: not implemented +// needs-unwind -Cpanic=abort causes abort instead of exit(101) pub trait Interner { type InternedVariableKinds; diff --git a/tests/mir-opt/const_prop/address_of_pair.fn0.ConstProp.diff b/tests/mir-opt/const_prop/address_of_pair.fn0.ConstProp.diff new file mode 100644 index 00000000000..d50b12044ce --- /dev/null +++ b/tests/mir-opt/const_prop/address_of_pair.fn0.ConstProp.diff @@ -0,0 +1,46 @@ +- // MIR for `fn0` before ConstProp ++ // MIR for `fn0` after ConstProp + + fn fn0() -> bool { + let mut _0: bool; // return place in scope 0 at $DIR/address_of_pair.rs:+0:17: +0:21 + let mut _1: !; // in scope 0 at $DIR/address_of_pair.rs:+0:22: +9:2 + let mut _2: (i32, bool); // in scope 0 at $DIR/address_of_pair.rs:+1:9: +1:17 + let _4: (); // in scope 0 at $DIR/address_of_pair.rs:+4:5: +6:6 + let mut _6: bool; // in scope 0 at $DIR/address_of_pair.rs:+7:16: +7:22 + scope 1 { + debug pair => _2; // in scope 1 at $DIR/address_of_pair.rs:+1:9: +1:17 + let _3: *mut bool; // in scope 1 at $DIR/address_of_pair.rs:+2:9: +2:12 + scope 2 { + debug ptr => _3; // in scope 2 at $DIR/address_of_pair.rs:+2:9: +2:12 + let _5: bool; // in scope 2 at $DIR/address_of_pair.rs:+7:9: +7:12 + scope 3 { + } + scope 4 { + debug ret => _5; // in scope 4 at $DIR/address_of_pair.rs:+7:9: +7:12 + } + } + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/address_of_pair.rs:+1:9: +1:17 + _2 = (const 1_i32, const false); // scope 0 at $DIR/address_of_pair.rs:+1:20: +1:30 + StorageLive(_3); // scope 1 at $DIR/address_of_pair.rs:+2:9: +2:12 + _3 = &raw mut (_2.1: bool); // scope 1 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + _2 = (const 1_i32, const false); // scope 2 at $DIR/address_of_pair.rs:+3:5: +3:22 + StorageLive(_4); // scope 2 at $DIR/address_of_pair.rs:+4:5: +6:6 + (*_3) = const true; // scope 3 at $DIR/address_of_pair.rs:+5:9: +5:20 + _4 = const (); // scope 3 at $DIR/address_of_pair.rs:+4:5: +6:6 + StorageDead(_4); // scope 2 at $DIR/address_of_pair.rs:+6:5: +6:6 + StorageLive(_5); // scope 2 at $DIR/address_of_pair.rs:+7:9: +7:12 + StorageLive(_6); // scope 2 at $DIR/address_of_pair.rs:+7:16: +7:22 + _6 = (_2.1: bool); // scope 2 at $DIR/address_of_pair.rs:+7:16: +7:22 + _5 = Not(move _6); // scope 2 at $DIR/address_of_pair.rs:+7:15: +7:22 + StorageDead(_6); // scope 2 at $DIR/address_of_pair.rs:+7:21: +7:22 + _0 = _5; // scope 4 at $DIR/address_of_pair.rs:+8:12: +8:15 + StorageDead(_5); // scope 2 at $DIR/address_of_pair.rs:+9:1: +9:2 + StorageDead(_3); // scope 1 at $DIR/address_of_pair.rs:+9:1: +9:2 + StorageDead(_2); // scope 0 at $DIR/address_of_pair.rs:+9:1: +9:2 + return; // scope 0 at $DIR/address_of_pair.rs:+9:2: +9:2 + } + } + diff --git a/tests/mir-opt/const_prop/address_of_pair.rs b/tests/mir-opt/const_prop/address_of_pair.rs new file mode 100644 index 00000000000..43dc9bae625 --- /dev/null +++ b/tests/mir-opt/const_prop/address_of_pair.rs @@ -0,0 +1,17 @@ +// unit-test: ConstProp + +// EMIT_MIR address_of_pair.fn0.ConstProp.diff +pub fn fn0() -> bool { + let mut pair = (1, false); + let ptr = core::ptr::addr_of_mut!(pair.1); + pair = (1, false); + unsafe { + *ptr = true; + } + let ret = !pair.1; + return ret; +} + +pub fn main() { + println!("{}", fn0()); +} diff --git a/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff b/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff index def9fc6428f..a5f52d08957 100644 --- a/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff +++ b/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff @@ -19,8 +19,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:9: +1:14 -- _1 = (const 1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 -+ _1 = const (1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 + _1 = (const 1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 StorageLive(_2); // scope 1 at $DIR/const_prop_miscompile.rs:+2:5: +4:6 StorageLive(_3); // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22 _3 = &raw mut (_1.0: i32); // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22 diff --git a/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff b/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff index b54c10a140f..42ddc2a5620 100644 --- a/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff +++ b/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff @@ -16,8 +16,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:9: +1:14 -- _1 = (const 1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 -+ _1 = const (1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 + _1 = (const 1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 StorageLive(_2); // scope 1 at $DIR/const_prop_miscompile.rs:+2:6: +2:14 _2 = &mut (_1.0: i32); // scope 1 at $DIR/const_prop_miscompile.rs:+2:6: +2:14 (*_2) = const 5_i32; // scope 1 at $DIR/const_prop_miscompile.rs:+2:5: +2:18 diff --git a/tests/mir-opt/dead-store-elimination/place_mention.main.DeadStoreElimination.diff b/tests/mir-opt/dead-store-elimination/place_mention.main.DeadStoreElimination.diff new file mode 100644 index 00000000000..761c074ed94 --- /dev/null +++ b/tests/mir-opt/dead-store-elimination/place_mention.main.DeadStoreElimination.diff @@ -0,0 +1,25 @@ +- // MIR for `main` before DeadStoreElimination ++ // MIR for `main` after DeadStoreElimination + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/place_mention.rs:+0:11: +0:11 + let mut _1: (&str, &str); // in scope 0 at $DIR/place_mention.rs:+3:18: +3:36 + scope 1 { + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/place_mention.rs:+3:18: +3:36 + _1 = (const "Hello", const "World"); // scope 0 at $DIR/place_mention.rs:+3:18: +3:36 + // mir::Constant + // + span: $DIR/place_mention.rs:8:19: 8:26 + // + literal: Const { ty: &str, val: Value(Slice(..)) } + // mir::Constant + // + span: $DIR/place_mention.rs:8:28: 8:35 + // + literal: Const { ty: &str, val: Value(Slice(..)) } + PlaceMention(_1); // scope 0 at $DIR/place_mention.rs:+3:18: +3:36 + StorageDead(_1); // scope 0 at $DIR/place_mention.rs:+3:36: +3:37 + _0 = const (); // scope 0 at $DIR/place_mention.rs:+0:11: +4:2 + return; // scope 0 at $DIR/place_mention.rs:+4:2: +4:2 + } + } + diff --git a/tests/mir-opt/dead-store-elimination/place_mention.rs b/tests/mir-opt/dead-store-elimination/place_mention.rs new file mode 100644 index 00000000000..59dc74454a4 --- /dev/null +++ b/tests/mir-opt/dead-store-elimination/place_mention.rs @@ -0,0 +1,9 @@ +// unit-test: DeadStoreElimination +// compile-flags: -Zmir-keep-place-mention + +// EMIT_MIR place_mention.main.DeadStoreElimination.diff +fn main() { + // Verify that we account for the `PlaceMention` statement as a use of the tuple, + // and don't remove it as a dead store. + let (_, _) = ("Hello", "World"); +} diff --git a/tests/run-make/c-unwind-abi-catch-lib-panic/Makefile b/tests/run-make/c-unwind-abi-catch-lib-panic/Makefile index 9c41a5a717e..b8e0e9483cd 100644 --- a/tests/run-make/c-unwind-abi-catch-lib-panic/Makefile +++ b/tests/run-make/c-unwind-abi-catch-lib-panic/Makefile @@ -1,4 +1,5 @@ # ignore-cross-compile +# needs-unwind include ../tools.mk all: archive diff --git a/tests/run-make/c-unwind-abi-catch-panic/Makefile b/tests/run-make/c-unwind-abi-catch-panic/Makefile index 4398ac2ee24..1760ddb3061 100644 --- a/tests/run-make/c-unwind-abi-catch-panic/Makefile +++ b/tests/run-make/c-unwind-abi-catch-panic/Makefile @@ -1,4 +1,5 @@ # ignore-cross-compile +# needs-unwind include ../tools.mk all: $(call NATIVE_STATICLIB,add) diff --git a/tests/run-make/const_fn_mir/Makefile b/tests/run-make/const_fn_mir/Makefile index b2c268f0439..6d72c122723 100644 --- a/tests/run-make/const_fn_mir/Makefile +++ b/tests/run-make/const_fn_mir/Makefile @@ -1,3 +1,4 @@ +# needs-unwind -Cpanic=abort gives different MIR output include ../tools.mk all: diff --git a/tests/run-make/debug-assertions/Makefile b/tests/run-make/debug-assertions/Makefile index e83337c597f..4501459e9d1 100644 --- a/tests/run-make/debug-assertions/Makefile +++ b/tests/run-make/debug-assertions/Makefile @@ -1,4 +1,5 @@ # ignore-cross-compile +# needs-unwind include ../tools.mk all: diff --git a/tests/run-make/foreign-double-unwind/Makefile b/tests/run-make/foreign-double-unwind/Makefile index f20fe3ce66e..b5e52808d2f 100644 --- a/tests/run-make/foreign-double-unwind/Makefile +++ b/tests/run-make/foreign-double-unwind/Makefile @@ -1,4 +1,5 @@ # ignore-cross-compile +# needs-unwind include ../tools.mk all: foo diff --git a/tests/run-make/foreign-exceptions/Makefile b/tests/run-make/foreign-exceptions/Makefile index a8e20ffb1f4..56c41b274fb 100644 --- a/tests/run-make/foreign-exceptions/Makefile +++ b/tests/run-make/foreign-exceptions/Makefile @@ -1,4 +1,5 @@ # ignore-cross-compile +# needs-unwind include ../tools.mk all: foo diff --git a/tests/run-make/foreign-rust-exceptions/Makefile b/tests/run-make/foreign-rust-exceptions/Makefile index 0d007bf1c49..59cee284200 100644 --- a/tests/run-make/foreign-rust-exceptions/Makefile +++ b/tests/run-make/foreign-rust-exceptions/Makefile @@ -1,5 +1,6 @@ # ignore-cross-compile # ignore-i686-pc-windows-gnu +# needs-unwind # This test doesn't work on 32-bit MinGW as cdylib has its own copy of unwinder # so cross-DLL unwinding does not work. diff --git a/tests/run-make/libtest-json/Makefile b/tests/run-make/libtest-json/Makefile index 417637cf072..c8bc7b5dd4a 100644 --- a/tests/run-make/libtest-json/Makefile +++ b/tests/run-make/libtest-json/Makefile @@ -1,4 +1,5 @@ # ignore-cross-compile +# needs-unwind include ../tools.mk # Test expected libtest's JSON output diff --git a/tests/run-make/libtest-junit/Makefile b/tests/run-make/libtest-junit/Makefile new file mode 100644 index 00000000000..d97cafccf1f --- /dev/null +++ b/tests/run-make/libtest-junit/Makefile @@ -0,0 +1,19 @@ +# ignore-cross-compile +include ../tools.mk + +# Test expected libtest's junit output + +OUTPUT_FILE_DEFAULT := $(TMPDIR)/libtest-junit-output-default.xml +OUTPUT_FILE_STDOUT_SUCCESS := $(TMPDIR)/libtest-junit-output-stdout-success.xml + +all: f.rs validate_junit.py output-default.xml output-stdout-success.xml + $(RUSTC) --test f.rs + RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=junit > $(OUTPUT_FILE_DEFAULT) || true + RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=junit --show-output > $(OUTPUT_FILE_STDOUT_SUCCESS) || true + + cat $(OUTPUT_FILE_DEFAULT) | "$(PYTHON)" validate_junit.py + cat $(OUTPUT_FILE_STDOUT_SUCCESS) | "$(PYTHON)" validate_junit.py + + # Normalize the actual output and compare to expected output file + cat $(OUTPUT_FILE_DEFAULT) | sed 's/time="[0-9.]*"/time="$$TIME"/g' | diff output-default.xml - + cat $(OUTPUT_FILE_STDOUT_SUCCESS) | sed 's/time="[0-9.]*"/time="$$TIME"/g' | diff output-stdout-success.xml - diff --git a/tests/run-make/libtest-junit/f.rs b/tests/run-make/libtest-junit/f.rs new file mode 100644 index 00000000000..d360d77317d --- /dev/null +++ b/tests/run-make/libtest-junit/f.rs @@ -0,0 +1,23 @@ +#[test] +fn a() { + println!("print from successful test"); + // Should pass +} + +#[test] +fn b() { + println!("print from failing test"); + assert!(false); +} + +#[test] +#[should_panic] +fn c() { + assert!(false); +} + +#[test] +#[ignore = "msg"] +fn d() { + assert!(false); +} diff --git a/tests/run-make/libtest-junit/output-default.xml b/tests/run-make/libtest-junit/output-default.xml new file mode 100644 index 00000000000..d59e07b8ad8 --- /dev/null +++ b/tests/run-make/libtest-junit/output-default.xml @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8"?><testsuites><testsuite name="test" package="test" id="0" errors="0" failures="1" tests="4" skipped="1" ><testcase classname="unknown" name="a" time="$TIME"/><testcase classname="unknown" name="b" time="$TIME"><failure type="assert"/><system-out><![CDATA[print from failing test]]>
<![CDATA[thread 'b' panicked at 'assertion failed: false', f.rs:10:5]]>
<![CDATA[note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace]]>
<![CDATA[]]></system-out></testcase><testcase classname="unknown" name="c" time="$TIME"/><system-out/><system-err/></testsuite></testsuites> diff --git a/tests/run-make/libtest-junit/output-stdout-success.xml b/tests/run-make/libtest-junit/output-stdout-success.xml new file mode 100644 index 00000000000..0c300611e1f --- /dev/null +++ b/tests/run-make/libtest-junit/output-stdout-success.xml @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8"?><testsuites><testsuite name="test" package="test" id="0" errors="0" failures="1" tests="4" skipped="1" ><testcase classname="unknown" name="a" time="$TIME"><system-out><![CDATA[print from successful test]]>
<![CDATA[]]></system-out></testcase><testcase classname="unknown" name="b" time="$TIME"><failure type="assert"/><system-out><![CDATA[print from failing test]]>
<![CDATA[thread 'b' panicked at 'assertion failed: false', f.rs:10:5]]>
<![CDATA[note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace]]>
<![CDATA[]]></system-out></testcase><testcase classname="unknown" name="c" time="$TIME"><system-out><![CDATA[thread 'c' panicked at 'assertion failed: false', f.rs:16:5]]>
<![CDATA[]]></system-out></testcase><system-out/><system-err/></testsuite></testsuites> diff --git a/tests/run-make/libtest-junit/validate_junit.py b/tests/run-make/libtest-junit/validate_junit.py new file mode 100755 index 00000000000..47a8e70ccc3 --- /dev/null +++ b/tests/run-make/libtest-junit/validate_junit.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python + +import sys +import xml.etree.ElementTree as ET + +# Try to decode line in order to ensure it is a valid XML document +for line in sys.stdin: + try: + ET.fromstring(line) + except ET.ParseError as pe: + print("Invalid xml: %r" % line) + raise diff --git a/tests/run-make/static-unwinding/Makefile b/tests/run-make/static-unwinding/Makefile index dec94fb16f4..4b093f93608 100644 --- a/tests/run-make/static-unwinding/Makefile +++ b/tests/run-make/static-unwinding/Makefile @@ -1,4 +1,5 @@ # ignore-cross-compile +# needs-unwind include ../tools.mk all: diff --git a/tests/run-make/test-benches/Makefile b/tests/run-make/test-benches/Makefile index 0253a52637f..11aed2e4c79 100644 --- a/tests/run-make/test-benches/Makefile +++ b/tests/run-make/test-benches/Makefile @@ -1,6 +1,7 @@ include ../tools.mk # ignore-cross-compile +# needs-unwind #[bench] and -Zpanic-abort-tests can't be combined all: # Smoke-test that `#[bench]` isn't entirely broken. diff --git a/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-2.rs b/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-2.rs index d45a6465b76..18a99398622 100644 --- a/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-2.rs +++ b/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-2.rs @@ -2,28 +2,30 @@ #![feature(generic_const_exprs)] #![allow(incomplete_features, unused_parens, unused_braces)] -fn zero_init<const N: usize>() -> Substs1<{ (N) }> +fn zero_init<const N: usize>() -> Substs1<{{ N }}> where - [u8; { (N) }]: , + [u8; {{ N }}]: , { - Substs1([0; { (N) }]) + Substs1([0; {{ N }}]) } -struct Substs1<const N: usize>([u8; { (N) }]) +struct Substs1<const N: usize>([u8; {{ N }}]) where - [(); { (N) }]: ; + [(); {{ N }}]: ; -fn substs2<const M: usize>() -> Substs1<{ (M) }> { - zero_init::<{ (M) }>() +fn substs2<const M: usize>() -> Substs1<{{ M }}> { + zero_init::<{{ M }}>() } -fn substs3<const L: usize>() -> Substs1<{ (L) }> { - substs2::<{ (L) }>() +fn substs3<const L: usize>() -> Substs1<{{ L }}> { + substs2::<{{ L }}>() } fn main() { assert_eq!(substs3::<2>().0, [0; 2]); } -// Test that the implicit ``{ (L) }`` bound on ``substs3`` satisfies the -// ``{ (N) }`` bound on ``Substs1`` +// Test that the implicit ``{{ L }}`` bound on ``substs3`` satisfies the +// ``{{ N }}`` bound on ``Substs1`` +// FIXME(generic_const_exprs): come up with a less brittle test for this using assoc consts +// once normalization is implemented for them. diff --git a/tests/ui/const-generics/sneaky-array-repeat-expr.rs b/tests/ui/const-generics/sneaky-array-repeat-expr.rs index b147c246bda..cd1607608a6 100644 --- a/tests/ui/const-generics/sneaky-array-repeat-expr.rs +++ b/tests/ui/const-generics/sneaky-array-repeat-expr.rs @@ -10,6 +10,7 @@ impl<const N: usize> Trait<N> for () { pub const fn foo<const N: usize>() where (): Trait<N> { let bar = [(); <()>::Assoc]; //~^ error: constant expression depends on a generic parameter + //~| error: constant expression depends on a generic parameter } trait Trait2<const N: usize> { @@ -24,6 +25,7 @@ impl<const N: usize> Trait2<N> for () { pub const fn foo2<const N: usize>() where (): Trait2<N> { let bar2 = [(); <()>::Assoc2]; //~^ error: constant expression depends on a generic parameter + //~| error: constant expression depends on a generic parameter } fn main() { diff --git a/tests/ui/const-generics/sneaky-array-repeat-expr.stderr b/tests/ui/const-generics/sneaky-array-repeat-expr.stderr index 5c77375d399..e532f27a10d 100644 --- a/tests/ui/const-generics/sneaky-array-repeat-expr.stderr +++ b/tests/ui/const-generics/sneaky-array-repeat-expr.stderr @@ -7,12 +7,28 @@ LL | let bar = [(); <()>::Assoc]; = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/sneaky-array-repeat-expr.rs:25:21 + --> $DIR/sneaky-array-repeat-expr.rs:11:15 + | +LL | let bar = [(); <()>::Assoc]; + | ^^^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: constant expression depends on a generic parameter + --> $DIR/sneaky-array-repeat-expr.rs:26:21 | LL | let bar2 = [(); <()>::Assoc2]; | ^^^^^^^^^^^^ | = note: this may fail depending on what value the parameter takes -error: aborting due to 2 previous errors +error: constant expression depends on a generic parameter + --> $DIR/sneaky-array-repeat-expr.rs:26:16 + | +LL | let bar2 = [(); <()>::Assoc2]; + | ^^^^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to 4 previous errors diff --git a/tests/ui/consts/const-block-const-bound.rs b/tests/ui/consts/const-block-const-bound.rs index 42aa0216b87..3704a1a5a39 100644 --- a/tests/ui/consts/const-block-const-bound.rs +++ b/tests/ui/consts/const-block-const-bound.rs @@ -11,15 +11,9 @@ impl Drop for UnconstDrop { fn drop(&mut self) {} } -struct NonDrop; - -impl !Drop for NonDrop {} - fn main() { const { f(UnconstDrop); //~^ ERROR can't drop - f(NonDrop); - //~^ ERROR can't drop } } diff --git a/tests/ui/consts/const-block-const-bound.stderr b/tests/ui/consts/const-block-const-bound.stderr index fef4914fad5..caf24e7afcf 100644 --- a/tests/ui/consts/const-block-const-bound.stderr +++ b/tests/ui/consts/const-block-const-bound.stderr @@ -1,5 +1,5 @@ error[E0277]: can't drop `UnconstDrop` in const contexts - --> $DIR/const-block-const-bound.rs:20:9 + --> $DIR/const-block-const-bound.rs:16:9 | LL | f(UnconstDrop); | ^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `UnconstDrop` @@ -12,20 +12,6 @@ LL | &f(UnconstDrop); LL | &mut f(UnconstDrop); | ++++ -error[E0277]: can't drop `NonDrop` in const contexts - --> $DIR/const-block-const-bound.rs:22:9 - | -LL | f(NonDrop); - | ^^^^^^^^^^ the trait `~const Destruct` is not implemented for `NonDrop` - | - = note: the trait bound `NonDrop: ~const Destruct` is not satisfied -help: consider borrowing here - | -LL | &f(NonDrop); - | + -LL | &mut f(NonDrop); - | ++++ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/issue-50439.rs b/tests/ui/consts/issue-50439.rs index 0be7c405473..d42347e136e 100644 --- a/tests/ui/consts/issue-50439.rs +++ b/tests/ui/consts/issue-50439.rs @@ -22,7 +22,9 @@ impl<T: Sized> PinDropInternal for Bears<T> { where Self: ReflectDrop, { - let _ = [(); 0 - !!(<Bears<T> as ReflectDrop>::REFLECT_DROP) as usize]; //~ ERROR constant expression depends on a generic parameter + let _ = [(); 0 - !!(<Bears<T> as ReflectDrop>::REFLECT_DROP) as usize]; + //~^ ERROR constant expression depends on a generic parameter + //~| ERROR constant expression depends on a generic parameter } } diff --git a/tests/ui/consts/issue-50439.stderr b/tests/ui/consts/issue-50439.stderr index 3fbdf33b2d8..7a8cd45ecc7 100644 --- a/tests/ui/consts/issue-50439.stderr +++ b/tests/ui/consts/issue-50439.stderr @@ -6,5 +6,13 @@ LL | let _ = [(); 0 - !!(<Bears<T> as ReflectDrop>::REFLECT_DROP) as usi | = note: this may fail depending on what value the parameter takes -error: aborting due to previous error +error: constant expression depends on a generic parameter + --> $DIR/issue-50439.rs:25:17 + | +LL | let _ = [(); 0 - !!(<Bears<T> as ReflectDrop>::REFLECT_DROP) as usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to 2 previous errors diff --git a/tests/ui/dropck/negative.rs b/tests/ui/dropck/negative.rs new file mode 100644 index 00000000000..ae63632b55e --- /dev/null +++ b/tests/ui/dropck/negative.rs @@ -0,0 +1,7 @@ +#![feature(negative_impls)] + +struct NonDrop; +impl !Drop for NonDrop {} +//~^ ERROR negative `Drop` impls are not supported + +fn main() {} diff --git a/tests/ui/dropck/negative.stderr b/tests/ui/dropck/negative.stderr new file mode 100644 index 00000000000..d613e30b5ea --- /dev/null +++ b/tests/ui/dropck/negative.stderr @@ -0,0 +1,8 @@ +error: negative `Drop` impls are not supported + --> $DIR/negative.rs:4:1 + | +LL | impl !Drop for NonDrop {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/dropck/reservation.rs b/tests/ui/dropck/reservation.rs new file mode 100644 index 00000000000..f7199d4ec44 --- /dev/null +++ b/tests/ui/dropck/reservation.rs @@ -0,0 +1,10 @@ +#![feature(rustc_attrs)] + +struct ReservedDrop; +#[rustc_reservation_impl = "message"] +impl Drop for ReservedDrop { +//~^ ERROR reservation `Drop` impls are not supported + fn drop(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/dropck/reservation.stderr b/tests/ui/dropck/reservation.stderr new file mode 100644 index 00000000000..19325d6ed44 --- /dev/null +++ b/tests/ui/dropck/reservation.stderr @@ -0,0 +1,8 @@ +error: reservation `Drop` impls are not supported + --> $DIR/reservation.rs:5:1 + | +LL | impl Drop for ReservedDrop { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs b/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs index ffeabe5c2ed..776006124dc 100644 --- a/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs +++ b/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs @@ -5,10 +5,10 @@ use std::ops::Deref; pub trait Foo { - fn bar() -> impl Deref<Target = impl Sized>; + fn bar(self) -> impl Deref<Target = impl Sized>; } pub struct Foreign; impl Foo for Foreign { - fn bar() -> &'static () { &() } + fn bar(self) -> &'static () { &() } } diff --git a/tests/ui/impl-trait/in-trait/foreign-dyn-error.rs b/tests/ui/impl-trait/in-trait/foreign-dyn-error.rs new file mode 100644 index 00000000000..ecb5e62c433 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/foreign-dyn-error.rs @@ -0,0 +1,8 @@ +// aux-build: rpitit.rs + +extern crate rpitit; + +fn main() { + let _: &dyn rpitit::Foo = todo!(); + //~^ ERROR the trait `Foo` cannot be made into an object +} diff --git a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr new file mode 100644 index 00000000000..6eef392c05f --- /dev/null +++ b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr @@ -0,0 +1,15 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/foreign-dyn-error.rs:6:12 + | +LL | let _: &dyn rpitit::Foo = todo!(); + | ^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/auxiliary/rpitit.rs:8:21 + | +LL | fn bar(self) -> impl Deref<Target = impl Sized>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait cannot be made into an object because method `bar` references an `impl Trait` type in its return type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/impl-trait/in-trait/foreign.rs b/tests/ui/impl-trait/in-trait/foreign.rs index f4972d948b2..98417b343a1 100644 --- a/tests/ui/impl-trait/in-trait/foreign.rs +++ b/tests/ui/impl-trait/in-trait/foreign.rs @@ -5,17 +5,18 @@ extern crate rpitit; +use rpitit::{Foo, Foreign}; use std::sync::Arc; // Implement an RPITIT from another crate. struct Local; -impl rpitit::Foo for Local { - fn bar() -> Arc<String> { Arc::new(String::new()) } +impl Foo for Local { + fn bar(self) -> Arc<String> { Arc::new(String::new()) } } fn main() { // Witness an RPITIT from another crate. - let &() = <rpitit::Foreign as rpitit::Foo>::bar(); + let &() = Foreign.bar(); - let x: Arc<String> = <Local as rpitit::Foo>::bar(); + let x: Arc<String> = Local.bar(); } diff --git a/tests/ui/impl-trait/issues/issue-86800.rs b/tests/ui/impl-trait/issues/issue-86800.rs index 351243c6727..ec4fda322d0 100644 --- a/tests/ui/impl-trait/issues/issue-86800.rs +++ b/tests/ui/impl-trait/issues/issue-86800.rs @@ -1,14 +1,12 @@ #![feature(type_alias_impl_trait)] // edition:2021 -// unset-rustc-env:RUST_BACKTRACE // compile-flags:-Z treat-err-as-bug=1 -// error-pattern:stack backtrace: +// error-pattern: aborting due to `-Z treat-err-as-bug=1` // failure-status:101 -// normalize-stderr-test "note: .*" -> "" -// normalize-stderr-test "thread 'rustc' .*" -> "" -// normalize-stderr-test " +[0-9]+:.*\n" -> "" -// normalize-stderr-test " +at .*\n" -> "" +// normalize-stderr-test ".*note: .*\n\n" -> "" +// normalize-stderr-test "thread 'rustc' panicked.*\n" -> "" +// rustc-env:RUST_BACKTRACE=0 use std::future::Future; diff --git a/tests/ui/impl-trait/issues/issue-86800.stderr b/tests/ui/impl-trait/issues/issue-86800.stderr index f3a77383778..facab390d15 100644 --- a/tests/ui/impl-trait/issues/issue-86800.stderr +++ b/tests/ui/impl-trait/issues/issue-86800.stderr @@ -1,24 +1,12 @@ error: unconstrained opaque type - --> $DIR/issue-86800.rs:33:34 + --> $DIR/issue-86800.rs:31:34 | LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = - - -stack backtrace: - error: the compiler unexpectedly panicked. this is a bug. - - - - - - query stack during panic: #0 [type_of] computing type of `TransactionFuture::{opaque#0}` #1 [check_mod_item_types] checking item types in top-level module -#2 [analysis] running analysis passes on this crate end of query stack diff --git a/tests/ui/panics/default-backtrace-ice.rs b/tests/ui/panics/default-backtrace-ice.rs index fd86a3f9dfa..b40203c339d 100644 --- a/tests/ui/panics/default-backtrace-ice.rs +++ b/tests/ui/panics/default-backtrace-ice.rs @@ -2,8 +2,20 @@ // compile-flags:-Z treat-err-as-bug=1 // error-pattern:stack backtrace: // failure-status:101 +// ignore-msvc // normalize-stderr-test "note: .*" -> "" // normalize-stderr-test "thread 'rustc' .*" -> "" -// normalize-stderr-test " .*\n" -> "" +// normalize-stderr-test " +\d+:.*__rust_begin_short_backtrace.*" -> "(begin_short_backtrace)" +// normalize-stderr-test " +\d+:.*__rust_end_short_backtrace.*" -> "(end_short_backtrace)" +// normalize-stderr-test " +\d+:.*\n" -> "" +// normalize-stderr-test " +at .*\n" -> "" +// +// This test makes sure that full backtraces are used for ICEs when +// RUST_BACKTRACE is not set. It does this by checking for the presence of +// `__rust_{begin,end}_short_backtrace` markers, which only appear in full +// backtraces. The rest of the backtrace is filtered out. +// +// Ignored on msvc becaue the `__rust_{begin,end}_short_backtrace` symbols +// aren't reliable. fn main() { missing_ident; } diff --git a/tests/ui/panics/default-backtrace-ice.stderr b/tests/ui/panics/default-backtrace-ice.stderr index 4bd4780e25f..ddbfc4e7f3a 100644 --- a/tests/ui/panics/default-backtrace-ice.stderr +++ b/tests/ui/panics/default-backtrace-ice.stderr @@ -1,8 +1,13 @@ error[E0425]: cannot find value `missing_ident` in this scope + --> $DIR/default-backtrace-ice.rs:21:13 + | LL | fn main() { missing_ident; } + | ^^^^^^^^^^^^^ not found in this scope stack backtrace: +(end_short_backtrace) +(begin_short_backtrace) error: the compiler unexpectedly panicked. this is a bug. diff --git a/tests/ui/self/elision/nested-item.rs b/tests/ui/self/elision/nested-item.rs new file mode 100644 index 00000000000..4bcb645c60e --- /dev/null +++ b/tests/ui/self/elision/nested-item.rs @@ -0,0 +1,13 @@ +// Regression test for #110899. +// When looking for the elided lifetime for `wrap`, +// we must not consider the lifetimes in `bar` as candidates. + +fn wrap(self: Wrap<{ fn bar(&self) {} }>) -> &() { + //~^ ERROR `self` parameter is only allowed in associated functions + //~| ERROR `self` parameter is only allowed in associated functions + //~| ERROR missing lifetime specifier + //~| ERROR cannot find type `Wrap` in this scope + &() +} + +fn main() {} diff --git a/tests/ui/self/elision/nested-item.stderr b/tests/ui/self/elision/nested-item.stderr new file mode 100644 index 00000000000..752fd82332c --- /dev/null +++ b/tests/ui/self/elision/nested-item.stderr @@ -0,0 +1,38 @@ +error: `self` parameter is only allowed in associated functions + --> $DIR/nested-item.rs:5:9 + | +LL | fn wrap(self: Wrap<{ fn bar(&self) {} }>) -> &() { + | ^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/nested-item.rs:5:29 + | +LL | fn wrap(self: Wrap<{ fn bar(&self) {} }>) -> &() { + | ^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error[E0106]: missing lifetime specifier + --> $DIR/nested-item.rs:5:46 + | +LL | fn wrap(self: Wrap<{ fn bar(&self) {} }>) -> &() { + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn wrap(self: Wrap<{ fn bar(&self) {} }>) -> &'static () { + | +++++++ + +error[E0412]: cannot find type `Wrap` in this scope + --> $DIR/nested-item.rs:5:15 + | +LL | fn wrap(self: Wrap<{ fn bar(&self) {} }>) -> &() { + | ^^^^ not found in this scope + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0106, E0412. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/self/self-ctor-inner-const.rs b/tests/ui/self/self-ctor-inner-const.rs new file mode 100644 index 00000000000..b015397a5bc --- /dev/null +++ b/tests/ui/self/self-ctor-inner-const.rs @@ -0,0 +1,17 @@ +// Verify that we ban usage of `Self` as constructor from inner items. + +struct S0<T>(T); + +impl<T> S0<T> { + fn foo() { + const C: S0<u8> = Self(0); + //~^ ERROR can't use generic parameters from outer function + fn bar() -> Self { + //~^ ERROR can't use generic parameters from outer function + Self(0) + //~^ ERROR can't use generic parameters from outer function + } + } +} + +fn main() {} diff --git a/tests/ui/self/self-ctor-inner-const.stderr b/tests/ui/self/self-ctor-inner-const.stderr new file mode 100644 index 00000000000..7287c64c659 --- /dev/null +++ b/tests/ui/self/self-ctor-inner-const.stderr @@ -0,0 +1,33 @@ +error[E0401]: can't use generic parameters from outer function + --> $DIR/self-ctor-inner-const.rs:7:27 + | +LL | const C: S0<u8> = Self(0); + | ^^^^ + | | + | use of generic parameter from outer function + | can't use `Self` here + +error[E0401]: can't use generic parameters from outer function + --> $DIR/self-ctor-inner-const.rs:9:21 + | +LL | impl<T> S0<T> { + | ---- `Self` type implicitly declared here, by this `impl` +... +LL | fn bar() -> Self { + | ^^^^ + | | + | use of generic parameter from outer function + | use a type here instead + +error[E0401]: can't use generic parameters from outer function + --> $DIR/self-ctor-inner-const.rs:11:13 + | +LL | Self(0) + | ^^^^ + | | + | use of generic parameter from outer function + | can't use `Self` here + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/test-attrs/test-type.rs b/tests/ui/test-attrs/test-type.rs index f99e476eaba..8416270fd81 100644 --- a/tests/ui/test-attrs/test-type.rs +++ b/tests/ui/test-attrs/test-type.rs @@ -3,6 +3,7 @@ // check-run-results // normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" // ignore-emscripten no threads support +// needs-unwind // run-pass #[test] diff --git a/tests/ui/typeck/repeat-expr-checks-wf.rs b/tests/ui/typeck/repeat-expr-checks-wf.rs new file mode 100644 index 00000000000..b8a2a0ceb58 --- /dev/null +++ b/tests/ui/typeck/repeat-expr-checks-wf.rs @@ -0,0 +1,10 @@ +trait Foo { + const ASSOC: [u8]; +} + +fn bar<T: Foo>() { + let a = [T::ASSOC; 2]; + //~^ ERROR: the size for values of type `[u8]` cannot be known at compilation time +} + +fn main() {} diff --git a/tests/ui/typeck/repeat-expr-checks-wf.stderr b/tests/ui/typeck/repeat-expr-checks-wf.stderr new file mode 100644 index 00000000000..a821088a4b3 --- /dev/null +++ b/tests/ui/typeck/repeat-expr-checks-wf.stderr @@ -0,0 +1,12 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/repeat-expr-checks-wf.rs:6:13 + | +LL | let a = [T::ASSOC; 2]; + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: slice and array elements must have `Sized` type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. |
