diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index aca6fb201388..676d2c784ace 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -672,6 +672,7 @@ impl<'a, T: ?Sized> Pin<&'a T> { #[stable(feature = "pin", since = "1.33.0")] pub unsafe fn map_unchecked(self, func: F) -> Pin<&'a U> where + U: ?Sized, F: FnOnce(&T) -> &U, { let pointer = &*self.pointer; @@ -763,6 +764,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { #[stable(feature = "pin", since = "1.33.0")] pub unsafe fn map_unchecked_mut(self, func: F) -> Pin<&'a mut U> where + U: ?Sized, F: FnOnce(&mut T) -> &mut U, { let pointer = Pin::get_unchecked_mut(self); diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index e18ab7848fea..46c5ee272d23 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -1270,7 +1270,7 @@ pub fn map_crate<'hir>( definitions, }; - sess.time("validate HIR map", || { + sess.time("validate_HIR_map", || { hir_id_validator::check_crate(&map); }); diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index d01927b91b95..5d968811addd 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -198,7 +198,7 @@ impl<'sess> OnDiskCache<'sess> { // Encode query results. let mut query_result_index = EncodedQueryResultIndex::new(); - tcx.sess.time("encode query results", || { + tcx.sess.time("encode_query_results", || { let enc = &mut encoder; let qri = &mut query_result_index; @@ -1053,8 +1053,8 @@ where Q: super::config::QueryDescription<'tcx, Value: Encodable>, E: 'a + TyEncoder, { - let desc = &format!("encode_query_results for {}", ::std::any::type_name::()); - let _timer = tcx.sess.prof.generic_pass(desc); + let desc = &format!("encode_query_results_for_{}", ::std::any::type_name::()); + let _timer = tcx.sess.prof.extra_verbose_generic_activity(desc); let shards = Q::query_cache(tcx).lock_shards(); assert!(shards.iter().all(|shard| shard.active.is_empty())); diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index ddff8258c6d8..8d22ac9dbbe9 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -3,18 +3,18 @@ use crate::hir::map::DefPathData; use crate::ich::NodeIdHashingMode; use crate::mir::interpret::{sign_extend, truncate}; -use crate::ty::layout::{Integer, IntegerExt}; +use crate::ty::layout::{Integer, IntegerExt, Size}; use crate::ty::query::TyCtxtAt; use crate::ty::subst::{GenericArgKind, InternalSubsts, Subst, SubstsRef}; use crate::ty::TyKind::*; use crate::ty::{self, DefIdTree, GenericParamDefKind, Ty, TyCtxt, TypeFoldable}; use crate::util::common::ErrorReported; +use rustc_apfloat::Float as _; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; - -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_macros::HashStable; use rustc_span::Span; use std::{cmp, fmt}; @@ -43,26 +43,38 @@ impl<'tcx> fmt::Display for Discr<'tcx> { } } +fn signed_min(size: Size) -> i128 { + sign_extend(1_u128 << (size.bits() - 1), size) as i128 +} + +fn signed_max(size: Size) -> i128 { + i128::max_value() >> (128 - size.bits()) +} + +fn unsigned_max(size: Size) -> u128 { + u128::max_value() >> (128 - size.bits()) +} + +fn int_size_and_signed<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (Size, bool) { + let (int, signed) = match ty.kind { + Int(ity) => (Integer::from_attr(&tcx, SignedInt(ity)), true), + Uint(uty) => (Integer::from_attr(&tcx, UnsignedInt(uty)), false), + _ => bug!("non integer discriminant"), + }; + (int.size(), signed) +} + impl<'tcx> Discr<'tcx> { /// Adds `1` to the value and wraps around if the maximum for the type is reached. pub fn wrap_incr(self, tcx: TyCtxt<'tcx>) -> Self { self.checked_add(tcx, 1).0 } pub fn checked_add(self, tcx: TyCtxt<'tcx>, n: u128) -> (Self, bool) { - let (int, signed) = match self.ty.kind { - Int(ity) => (Integer::from_attr(&tcx, SignedInt(ity)), true), - Uint(uty) => (Integer::from_attr(&tcx, UnsignedInt(uty)), false), - _ => bug!("non integer discriminant"), - }; - - let size = int.size(); - let bit_size = int.size().bits(); - let shift = 128 - bit_size; - if signed { - let sext = |u| sign_extend(u, size) as i128; - let min = sext(1_u128 << (bit_size - 1)); - let max = i128::max_value() >> shift; - let val = sext(self.val); + let (size, signed) = int_size_and_signed(tcx, self.ty); + let (val, oflo) = if signed { + let min = signed_min(size); + let max = signed_max(size); + let val = sign_extend(self.val, size) as i128; assert!(n < (i128::max_value() as u128)); let n = n as i128; let oflo = val > max - n; @@ -70,14 +82,15 @@ impl<'tcx> Discr<'tcx> { // zero the upper bits let val = val as u128; let val = truncate(val, size); - (Self { val: val as u128, ty: self.ty }, oflo) + (val, oflo) } else { - let max = u128::max_value() >> shift; + let max = unsigned_max(size); let val = self.val; let oflo = val > max - n; let val = if oflo { n - (max - val) - 1 } else { val + n }; - (Self { val: val, ty: self.ty }, oflo) - } + (val, oflo) + }; + (Self { val, ty: self.ty }, oflo) } } @@ -621,6 +634,44 @@ impl<'tcx> TyCtxt<'tcx> { } impl<'tcx> ty::TyS<'tcx> { + /// Returns the maximum value for the given numeric type (including `char`s) + /// or returns `None` if the type is not numeric. + pub fn numeric_max_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<'tcx>> { + let val = match self.kind { + ty::Int(_) | ty::Uint(_) => { + let (size, signed) = int_size_and_signed(tcx, self); + let val = if signed { signed_max(size) as u128 } else { unsigned_max(size) }; + Some(val) + } + ty::Char => Some(std::char::MAX as u128), + ty::Float(fty) => Some(match fty { + ast::FloatTy::F32 => ::rustc_apfloat::ieee::Single::INFINITY.to_bits(), + ast::FloatTy::F64 => ::rustc_apfloat::ieee::Double::INFINITY.to_bits(), + }), + _ => None, + }; + val.map(|v| ty::Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self))) + } + + /// Returns the minimum value for the given numeric type (including `char`s) + /// or returns `None` if the type is not numeric. + pub fn numeric_min_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<'tcx>> { + let val = match self.kind { + ty::Int(_) | ty::Uint(_) => { + let (size, signed) = int_size_and_signed(tcx, self); + let val = if signed { truncate(signed_min(size) as u128, size) } else { 0 }; + Some(val) + } + ty::Char => Some(0), + ty::Float(fty) => Some(match fty { + ast::FloatTy::F32 => (-::rustc_apfloat::ieee::Single::INFINITY).to_bits(), + ast::FloatTy::F64 => (-::rustc_apfloat::ieee::Double::INFINITY).to_bits(), + }), + _ => None, + }; + val.map(|v| ty::Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self))) + } + /// Checks whether values of this type `T` are *moved* or *copied* /// when referenced -- this amounts to a check for whether `T: /// Copy`, but note that we **don't** consider lifetimes when diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 385153b62ce8..936438e20387 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -2706,9 +2706,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)), PatKind::Ref(ref inner, mutbl) => hir::PatKind::Ref(self.lower_pat(inner), mutbl), PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => hir::PatKind::Range( - self.lower_expr(e1), - self.lower_expr(e2), - self.lower_range_end(end), + e1.as_deref().map(|e| self.lower_expr(e)), + e2.as_deref().map(|e| self.lower_expr(e)), + self.lower_range_end(end, e2.is_some()), ), PatKind::Slice(ref pats) => self.lower_pat_slice(pats), PatKind::Rest => { @@ -2885,10 +2885,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::PatKind::Wild } - fn lower_range_end(&mut self, e: &RangeEnd) -> hir::RangeEnd { + fn lower_range_end(&mut self, e: &RangeEnd, has_end: bool) -> hir::RangeEnd { match *e { - RangeEnd::Included(_) => hir::RangeEnd::Included, - RangeEnd::Excluded => hir::RangeEnd::Excluded, + RangeEnd::Excluded if has_end => hir::RangeEnd::Excluded, + // No end; so `X..` behaves like `RangeFrom`. + RangeEnd::Excluded | RangeEnd::Included(_) => hir::RangeEnd::Included, } } diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index 3134ae5922c9..b5895b53698d 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -120,12 +120,13 @@ fn prepare_lto( info!("adding bytecode {}", name); let bc_encoded = data.data(); - let (bc, id) = cgcx.prof.generic_pass(&format!("decode {}", name)).run(|| { - match DecodedBytecode::new(bc_encoded) { + let (bc, id) = cgcx + .prof + .extra_verbose_generic_activity(&format!("decode {}", name)) + .run(|| match DecodedBytecode::new(bc_encoded) { Ok(b) => Ok((b.bytecode(), b.identifier().to_string())), Err(e) => Err(diag_handler.fatal(&e)), - } - })?; + })?; let bc = SerializedModule::FromRlib(bc); upstream_modules.push((bc, CString::new(id).unwrap())); } @@ -280,8 +281,9 @@ fn fat_lto( // save and persist everything with the original module. let mut linker = Linker::new(llmod); for (bc_decoded, name) in serialized_modules { + let _timer = cgcx.prof.generic_activity("LLVM_fat_lto_link_module"); info!("linking {:?}", name); - cgcx.prof.generic_pass(&format!("ll link {:?}", name)).run(|| { + cgcx.prof.extra_verbose_generic_activity(&format!("ll link {:?}", name)).run(|| { let data = bc_decoded.data(); linker.add(&data).map_err(|()| { let msg = format!("failed to load bc of {:?}", name); @@ -633,7 +635,7 @@ pub(crate) fn run_pass_manager( } cgcx.prof - .generic_pass("LTO passes") + .extra_verbose_generic_activity("LTO_passes") .run(|| llvm::LLVMRunPassManager(pm, module.module_llvm.llmod())); llvm::LLVMDisposePassManager(pm); diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index afdfb36c2a9f..4be7b84660d0 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -424,13 +424,23 @@ pub(crate) unsafe fn optimize( // Finally, run the actual optimization passes { + let _timer = cgcx.prof.generic_activity("LLVM_module_optimize_function_passes"); let desc = &format!("llvm function passes [{}]", module_name.unwrap()); - let _timer = if config.time_module { Some(cgcx.prof.generic_pass(desc)) } else { None }; + let _timer = if config.time_module { + Some(cgcx.prof.extra_verbose_generic_activity(desc)) + } else { + None + }; llvm::LLVMRustRunFunctionPassManager(fpm, llmod); } { + let _timer = cgcx.prof.generic_activity("LLVM_module_optimize_module_passes"); let desc = &format!("llvm module passes [{}]", module_name.unwrap()); - let _timer = if config.time_module { Some(cgcx.prof.generic_pass(desc)) } else { None }; + let _timer = if config.time_module { + Some(cgcx.prof.extra_verbose_generic_activity(desc)) + } else { + None + }; llvm::LLVMRunPassManager(mpm, llmod); } @@ -556,7 +566,11 @@ pub(crate) unsafe fn codegen( { let desc = &format!("codegen passes [{}]", module_name.unwrap()); - let _timer = if config.time_module { Some(cgcx.prof.generic_pass(desc)) } else { None }; + let _timer = if config.time_module { + Some(cgcx.prof.extra_verbose_generic_activity(desc)) + } else { + None + }; if config.emit_ir { let _timer = cgcx.prof.generic_activity("LLVM_module_codegen_emit_ir"); diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 349cff79c784..35c71a667568 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -283,7 +283,7 @@ impl CodegenBackend for LlvmCodegenBackend { rustc_codegen_ssa::back::write::dump_incremental_data(&codegen_results); } - sess.time("serialize work products", move || { + sess.time("serialize_work_products", move || { rustc_incremental::save_work_product_index(sess, &dep_graph, work_products) }); @@ -300,7 +300,7 @@ impl CodegenBackend for LlvmCodegenBackend { // Run the linker on any artifacts that resulted from the LLVM run. // This should produce either a finished executable or library. - sess.time("linking", || { + sess.time("link_crate", || { use crate::back::archive::LlvmArchiveBuilder; use rustc_codegen_ssa::back::link::link_binary; diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index a53402ebb5c7..253225f308e8 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -577,7 +577,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( let mut i = 0; loop { i += 1; - prog = sess.time("running linker", || exec_linker(sess, &mut cmd, out_filename, tmpdir)); + prog = sess.time("run_linker", || exec_linker(sess, &mut cmd, out_filename, tmpdir)); let output = match prog { Ok(ref output) => output, Err(_) => break, @@ -1562,7 +1562,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( let name = cratepath.file_name().unwrap().to_str().unwrap(); let name = &name[3..name.len() - 5]; // chop off lib/.rlib - sess.prof.generic_pass(&format!("altering {}.rlib", name)).run(|| { + sess.prof.extra_verbose_generic_activity(&format!("altering {}.rlib", name)).run(|| { let mut archive = ::new(sess, &dst, Some(cratepath)); archive.update_symbols(); diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index edd0fa504270..a406b5f103b9 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -345,7 +345,7 @@ fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel if is_extern && !std_internal { let target = &tcx.sess.target.target.llvm_target; // WebAssembly cannot export data symbols, so reduce their export level - if target.contains("wasm32") || target.contains("emscripten") { + if target.contains("emscripten") { if let Some(Node::Item(&hir::Item { kind: hir::ItemKind::Static(..), .. })) = tcx.hir().get_if_local(sym_def_id) { diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 32ba2dd65a3f..1ce0a29d55d9 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -1511,7 +1511,7 @@ fn start_executing_work( llvm_start_time: &mut Option>, ) { if config.time_module && llvm_start_time.is_none() { - *llvm_start_time = Some(prof.generic_pass("LLVM passes")); + *llvm_start_time = Some(prof.extra_verbose_generic_activity("LLVM_passes")); } } } diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index ededb36c7127..c83810907277 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -566,7 +566,7 @@ pub fn codegen_crate( cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string(); let mut modules = backend.new_metadata(tcx, &llmod_id); tcx.sess - .time("write allocator module", || backend.codegen_allocator(tcx, &mut modules, kind)); + .time("write_allocator_module", || backend.codegen_allocator(tcx, &mut modules, kind)); Some(ModuleCodegen { name: llmod_id, module_llvm: modules, kind: ModuleKind::Allocator }) } else { @@ -582,7 +582,7 @@ pub fn codegen_crate( let metadata_cgu_name = cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")).to_string(); let mut metadata_llvm_module = backend.new_metadata(tcx, &metadata_cgu_name); - tcx.sess.time("write compressed metadata", || { + tcx.sess.time("write_compressed_metadata", || { backend.write_compressed_metadata( tcx, &ongoing_codegen.metadata, @@ -652,7 +652,7 @@ pub fn codegen_crate( // Since the main thread is sometimes blocked during codegen, we keep track // -Ztime-passes output manually. - print_time_passes_entry(tcx.sess.time_passes(), "codegen to LLVM IR", total_codegen_time); + print_time_passes_entry(tcx.sess.time_passes(), "codegen_to_LLVM_IR", total_codegen_time); ::rustc_incremental::assert_module_sources::assert_module_sources(tcx); @@ -712,9 +712,9 @@ impl Drop for AbortCodegenOnDrop { } fn assert_and_save_dep_graph(tcx: TyCtxt<'_>) { - tcx.sess.time("assert dep graph", || ::rustc_incremental::assert_dep_graph(tcx)); + tcx.sess.time("assert_dep_graph", || ::rustc_incremental::assert_dep_graph(tcx)); - tcx.sess.time("serialize dep graph", || ::rustc_incremental::save_dep_graph(tcx)); + tcx.sess.time("serialize_dep_graph", || ::rustc_incremental::save_dep_graph(tcx)); } impl CrateInfo { diff --git a/src/librustc_data_structures/profiling.rs b/src/librustc_data_structures/profiling.rs index 840a2603deb7..a9d3a2668aab 100644 --- a/src/librustc_data_structures/profiling.rs +++ b/src/librustc_data_structures/profiling.rs @@ -8,8 +8,6 @@ use std::thread::ThreadId; use std::time::{Duration, Instant}; use std::u32; -use crate::cold_path; - use measureme::StringId; /// MmapSerializatioSink is faster on macOS and Linux @@ -44,15 +42,11 @@ bitflags::bitflags! { const QUERY_CACHE_HITS = 1 << 2; const QUERY_BLOCKED = 1 << 3; const INCR_CACHE_LOADS = 1 << 4; - const SPARSE_PASS = 1 << 5; - const GENERIC_PASS = 1 << 6; const DEFAULT = Self::GENERIC_ACTIVITIES.bits | Self::QUERY_PROVIDERS.bits | Self::QUERY_BLOCKED.bits | - Self::INCR_CACHE_LOADS.bits | - Self::SPARSE_PASS.bits | - Self::GENERIC_PASS.bits; + Self::INCR_CACHE_LOADS.bits; // empty() and none() aren't const-fns unfortunately const NONE = 0; @@ -63,8 +57,6 @@ bitflags::bitflags! { const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[ ("none", EventFilter::NONE), ("all", EventFilter::ALL), - ("sparse-pass", EventFilter::SPARSE_PASS), - ("generic-pass", EventFilter::GENERIC_PASS), ("generic-activity", EventFilter::GENERIC_ACTIVITIES), ("query-provider", EventFilter::QUERY_PROVIDERS), ("query-cache-hit", EventFilter::QUERY_CACHE_HITS), @@ -89,101 +81,86 @@ pub struct SelfProfilerRef { // actually enabled. event_filter_mask: EventFilter, - // Print sparse passes to stdout - verbose_sparse: bool, + // Print verbose generic activities to stdout + print_verbose_generic_activities: bool, - // Print generic passes to stdout - verbose_generic: bool, + // Print extra verbose generic activities to stdout + print_extra_verbose_generic_activities: bool, } impl SelfProfilerRef { pub fn new( profiler: Option>, - verbose_sparse: bool, - verbose_generic: bool, + print_verbose_generic_activities: bool, + print_extra_verbose_generic_activities: bool, ) -> SelfProfilerRef { // If there is no SelfProfiler then the filter mask is set to NONE, // ensuring that nothing ever tries to actually access it. - let mut event_filter_mask = + let event_filter_mask = profiler.as_ref().map(|p| p.event_filter_mask).unwrap_or(EventFilter::NONE); - if verbose_sparse { - event_filter_mask |= EventFilter::SPARSE_PASS; - } - - if verbose_generic { - event_filter_mask |= EventFilter::GENERIC_PASS; + SelfProfilerRef { + profiler, + event_filter_mask, + print_verbose_generic_activities, + print_extra_verbose_generic_activities, } - - SelfProfilerRef { profiler, event_filter_mask, verbose_sparse, verbose_generic } } + // This shim makes sure that calls only get executed if the filter mask + // lets them pass. It also contains some trickery to make sure that + // code is optimized for non-profiling compilation sessions, i.e. anything + // past the filter check is never inlined so it doesn't clutter the fast + // path. #[inline(always)] fn exec(&self, event_filter: EventFilter, f: F) -> TimingGuard<'_> where F: for<'a> FnOnce(&'a SelfProfiler) -> TimingGuard<'a>, { - self.handle_event( - event_filter, - || f(self.profiler.as_ref().unwrap()), - || TimingGuard::none(), - ) - } + #[inline(never)] + fn cold_call(profiler_ref: &SelfProfilerRef, f: F) -> TimingGuard<'_> + where + F: for<'a> FnOnce(&'a SelfProfiler) -> TimingGuard<'a>, + { + let profiler = profiler_ref.profiler.as_ref().unwrap(); + f(&**profiler) + } - // This shim makes sure that cold calls only get executed if the filter mask - // lets them pass. It also contains some trickery to make sure that - // code is optimized for non-profiling compilation sessions, i.e. anything - // past the filter check is never inlined so it doesn't clutter the fast - // path. - #[inline(always)] - fn handle_event( - &self, - event_filter: EventFilter, - cold: impl FnOnce() -> R, - hot: impl FnOnce() -> R, - ) -> R { if unlikely!(self.event_filter_mask.contains(event_filter)) { - cold_path(|| cold()) + cold_call(self, f) } else { - hot() + TimingGuard::none() } } - /// Start profiling a sparse pass. Profiling continues until the - /// VerboseTimingGuard returned from this call is dropped. + /// Start profiling a verbose generic activity. Profiling continues until the + /// VerboseTimingGuard returned from this call is dropped. In addition to recording + /// a measureme event, "verbose" generic activities also print a timing entry to + /// stdout if the compiler is invoked with -Ztime or -Ztime-passes. #[inline(always)] - pub fn sparse_pass<'a>(&'a self, event_id: &'a str) -> VerboseTimingGuard<'a> { - self.handle_event( - EventFilter::SPARSE_PASS, - || { - VerboseTimingGuard::start( - self.profiler - .as_ref() - .map(|profiler| (&**profiler, profiler.sparse_pass_event_kind)), - event_id, - self.verbose_sparse, - ) - }, - || VerboseTimingGuard::none(), + pub fn verbose_generic_activity<'a>(&'a self, event_id: &'a str) -> VerboseTimingGuard<'a> { + VerboseTimingGuard::start( + event_id, + self.print_verbose_generic_activities, + self.generic_activity(event_id), ) } - /// Start profiling a generic pass. Profiling continues until the - /// VerboseTimingGuard returned from this call is dropped. + /// Start profiling a extra verbose generic activity. Profiling continues until the + /// VerboseTimingGuard returned from this call is dropped. In addition to recording + /// a measureme event, "extra verbose" generic activities also print a timing entry to + /// stdout if the compiler is invoked with -Ztime-passes. #[inline(always)] - pub fn generic_pass<'a>(&'a self, event_id: &'a str) -> VerboseTimingGuard<'a> { - self.handle_event( - EventFilter::GENERIC_PASS, - || { - VerboseTimingGuard::start( - self.profiler - .as_ref() - .map(|profiler| (&**profiler, profiler.generic_pass_event_kind)), - event_id, - self.verbose_generic, - ) - }, - || VerboseTimingGuard::none(), + pub fn extra_verbose_generic_activity<'a>( + &'a self, + event_id: &'a str, + ) -> VerboseTimingGuard<'a> { + // FIXME: This does not yet emit a measureme event + // because callers encode arguments into `event_id`. + VerboseTimingGuard::start( + event_id, + self.print_extra_verbose_generic_activities, + TimingGuard::none(), ) } @@ -267,8 +244,6 @@ pub struct SelfProfiler { profiler: Profiler, event_filter_mask: EventFilter, query_event_kind: StringId, - sparse_pass_event_kind: StringId, - generic_pass_event_kind: StringId, generic_activity_event_kind: StringId, incremental_load_result_event_kind: StringId, query_blocked_event_kind: StringId, @@ -289,8 +264,6 @@ impl SelfProfiler { let profiler = Profiler::new(&path)?; let query_event_kind = profiler.alloc_string("Query"); - let sparse_pass_event_kind = profiler.alloc_string("SparsePass"); - let generic_pass_event_kind = profiler.alloc_string("GenericPass"); let generic_activity_event_kind = profiler.alloc_string("GenericActivity"); let incremental_load_result_event_kind = profiler.alloc_string("IncrementalLoadResult"); let query_blocked_event_kind = profiler.alloc_string("QueryBlocked"); @@ -333,8 +306,6 @@ impl SelfProfiler { profiler, event_filter_mask, query_event_kind, - sparse_pass_event_kind, - generic_pass_event_kind, generic_activity_event_kind, incremental_load_result_event_kind, query_blocked_event_kind, @@ -386,19 +357,11 @@ pub struct VerboseTimingGuard<'a> { } impl<'a> VerboseTimingGuard<'a> { - pub fn start( - profiler: Option<(&'a SelfProfiler, StringId)>, - event_id: &'a str, - verbose: bool, - ) -> Self { - let _guard = profiler.map_or(TimingGuard::none(), |(profiler, event_kind)| { - let event = profiler.profiler.alloc_string(event_id); - TimingGuard::start(profiler, event_kind, event) - }); + pub fn start(event_id: &'a str, verbose: bool, _guard: TimingGuard<'a>) -> Self { VerboseTimingGuard { event_id, _guard, - start: if verbose { Some(Instant::now()) } else { None }, + start: if unlikely!(verbose) { Some(Instant::now()) } else { None }, } } @@ -407,10 +370,6 @@ impl<'a> VerboseTimingGuard<'a> { let _timer = self; f() } - - fn none() -> Self { - VerboseTimingGuard { event_id: "", start: None, _guard: TimingGuard::none() } - } } impl Drop for VerboseTimingGuard<'_> { diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 8fbdf44de048..a5277bcd120e 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -369,7 +369,7 @@ pub fn run_compiler( queries.global_ctxt()?.peek_mut().enter(|tcx| { let result = tcx.analysis(LOCAL_CRATE); - sess.time("save analysis", || { + sess.time("save_analysis", || { save::process_crate( tcx, &expanded_crate, diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 8cb1684491bb..506bdb407136 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -534,6 +534,9 @@ declare_features! ( /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used. (active, cfg_sanitize, "1.41.0", Some(39699), None), + /// Allows using `..X`, `..=X`, `...X`, and `X..` as a pattern. + (active, half_open_range_patterns, "1.41.0", Some(67264), None), + /// Allows using `&mut` in constant functions. (active, const_mut_refs, "1.41.0", Some(57349), None), diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 2303a85df4ac..6fb4b57a2a88 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -905,7 +905,7 @@ pub enum PatKind<'hir> { Lit(&'hir Expr<'hir>), /// A range pattern (e.g., `1..=2` or `1..2`). - Range(&'hir Expr<'hir>, &'hir Expr<'hir>, RangeEnd), + Range(Option<&'hir Expr<'hir>>, Option<&'hir Expr<'hir>>, RangeEnd), /// A slice pattern, `[before_0, ..., before_n, (slice, after_0, ..., after_n)?]`. /// diff --git a/src/librustc_hir/intravisit.rs b/src/librustc_hir/intravisit.rs index 4664340b15fb..3dbc5253a9ab 100644 --- a/src/librustc_hir/intravisit.rs +++ b/src/librustc_hir/intravisit.rs @@ -766,8 +766,8 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) { } PatKind::Lit(ref expression) => visitor.visit_expr(expression), PatKind::Range(ref lower_bound, ref upper_bound, _) => { - visitor.visit_expr(lower_bound); - visitor.visit_expr(upper_bound) + walk_list!(visitor, visit_expr, lower_bound); + walk_list!(visitor, visit_expr, upper_bound); } PatKind::Wild => (), PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => { diff --git a/src/librustc_hir/print.rs b/src/librustc_hir/print.rs index 571bab2cb83f..759f423070aa 100644 --- a/src/librustc_hir/print.rs +++ b/src/librustc_hir/print.rs @@ -1767,13 +1767,17 @@ impl<'a> State<'a> { } PatKind::Lit(ref e) => self.print_expr(&e), PatKind::Range(ref begin, ref end, ref end_kind) => { - self.print_expr(&begin); - self.s.space(); + if let Some(expr) = begin { + self.print_expr(expr); + self.s.space(); + } match *end_kind { RangeEnd::Included => self.s.word("..."), RangeEnd::Excluded => self.s.word(".."), } - self.print_expr(&end); + if let Some(expr) = end { + self.print_expr(expr); + } } PatKind::Slice(ref before, ref slice, ref after) => { self.s.word("["); diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index cb06dae6ac91..0732ddd3261a 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -159,7 +159,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { } MaybeAsync::Async(std::thread::spawn(move || { - let _prof_timer = prof.generic_pass("background load prev dep-graph"); + let _prof_timer = prof.generic_activity("incr_comp_load_dep_graph"); match load_data(report_incremental_info, &path) { LoadResult::DataOutOfDate => LoadResult::DataOutOfDate, diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index 9487f02aa8e0..588e639f2894 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -32,15 +32,15 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) { join( move || { if tcx.sess.opts.debugging_opts.incremental_queries { - sess.time("persist query result cache", || { + sess.time("incr_comp_persist_result_cache", || { save_in(sess, query_cache_path, |e| encode_query_cache(tcx, e)); }); } }, || { - sess.time("persist dep-graph", || { + sess.time("incr_comp_persist_dep_graph", || { save_in(sess, dep_graph_path, |e| { - sess.time("encode dep-graph", || encode_dep_graph(tcx, e)) + sess.time("incr_comp_encode_dep_graph", || encode_dep_graph(tcx, e)) }); }); }, @@ -142,7 +142,8 @@ fn encode_dep_graph(tcx: TyCtxt<'_>, encoder: &mut Encoder) { tcx.sess.opts.dep_tracking_hash().encode(encoder).unwrap(); // Encode the graph data. - let serialized_graph = tcx.sess.time("getting serialized graph", || tcx.dep_graph.serialize()); + let serialized_graph = + tcx.sess.time("incr_comp_serialize_dep_graph", || tcx.dep_graph.serialize()); if tcx.sess.opts.debugging_opts.incremental_info { #[derive(Clone)] @@ -223,7 +224,7 @@ fn encode_dep_graph(tcx: TyCtxt<'_>, encoder: &mut Encoder) { println!("[incremental]"); } - tcx.sess.time("encoding serialized graph", || { + tcx.sess.time("incr_comp_encode_serialized_dep_graph", || { serialized_graph.encode(encoder).unwrap(); }); } @@ -244,7 +245,7 @@ fn encode_work_product_index( } fn encode_query_cache(tcx: TyCtxt<'_>, encoder: &mut Encoder) { - tcx.sess.time("serialize query result cache", || { + tcx.sess.time("incr_comp_serialize_result_cache", || { tcx.serialize_query_result_cache(encoder).unwrap(); }) } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 6e776e7d5542..a7e174f04553 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -54,7 +54,7 @@ use std::rc::Rc; use std::{env, fs, iter, mem}; pub fn parse<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> { - let krate = sess.time("parsing", || match input { + let krate = sess.time("parse_crate", || match input { Input::File(file) => parse_crate_from_file(file, &sess.parse_sess), Input::Str { input, name } => { parse_crate_from_source_str(name.clone(), input.clone(), &sess.parse_sess) @@ -155,7 +155,7 @@ pub fn register_plugins<'a>( mut krate: ast::Crate, crate_name: &str, ) -> Result<(ast::Crate, Lrc)> { - krate = sess.time("attributes injection", || { + krate = sess.time("attributes_injection", || { rustc_builtin_macros::cmdline_attrs::inject( krate, &sess.parse_sess, @@ -180,9 +180,7 @@ pub fn register_plugins<'a>( rustc_incremental::prepare_session_directory(sess, &crate_name, disambiguator); if sess.opts.incremental.is_some() { - sess.time("garbage-collect incremental cache directory", || { - let _prof_timer = - sess.prof.generic_activity("incr_comp_garbage_collect_session_directories"); + sess.time("incr_comp_garbage_collect_session_directories", || { if let Err(e) = rustc_incremental::garbage_collect_session_directories(sess) { warn!( "Error while trying to garbage collect incremental \ @@ -193,7 +191,7 @@ pub fn register_plugins<'a>( }); } - sess.time("recursion limit", || { + sess.time("recursion_limit", || { middle::recursion_limit::update_limits(sess, &krate); }); @@ -204,8 +202,8 @@ pub fn register_plugins<'a>( register_lints(&sess, &mut lint_store); let registrars = - sess.time("plugin loading", || plugin::load::load_plugins(sess, metadata_loader, &krate)); - sess.time("plugin registration", || { + sess.time("plugin_loading", || plugin::load::load_plugins(sess, metadata_loader, &krate)); + sess.time("plugin_registration", || { let mut registry = plugin::Registry { lint_store: &mut lint_store }; for registrar in registrars { registrar(&mut registry); @@ -223,7 +221,7 @@ fn configure_and_expand_inner<'a>( resolver_arenas: &'a ResolverArenas<'a>, metadata_loader: &'a MetadataLoaderDyn, ) -> Result<(ast::Crate, Resolver<'a>)> { - sess.time("pre-AST-expansion lint checks", || { + sess.time("pre_AST_expansion_lint_checks", || { rustc_lint::check_ast_crate( sess, lint_store, @@ -237,7 +235,7 @@ fn configure_and_expand_inner<'a>( let mut resolver = Resolver::new(sess, &krate, crate_name, metadata_loader, &resolver_arenas); rustc_builtin_macros::register_builtin_macros(&mut resolver, sess.edition()); - krate = sess.time("crate injection", || { + krate = sess.time("crate_injection", || { let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| Symbol::intern(s)); let (krate, name) = rustc_builtin_macros::standard_library_imports::inject( krate, @@ -254,7 +252,7 @@ fn configure_and_expand_inner<'a>( util::check_attr_crate_type(&krate.attrs, &mut resolver.lint_buffer()); // Expand all macros - krate = sess.time("expansion", || { + krate = sess.time("macro_expand_crate", || { // Windows dlls do not have rpaths, so they don't know how to find their // dependencies. It's up to us to tell the system where to find all the // dependent dlls. Note that this uses cfg!(windows) as opposed to @@ -299,11 +297,11 @@ fn configure_and_expand_inner<'a>( let mut ecx = ExtCtxt::new(&sess.parse_sess, cfg, &mut resolver); // Expand macros now! - let krate = sess.time("expand crate", || ecx.monotonic_expander().expand_crate(krate)); + let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate)); // The rest is error reporting - sess.time("check unused macros", || { + sess.time("check_unused_macros", || { ecx.check_unused_macros(); }); @@ -322,7 +320,7 @@ fn configure_and_expand_inner<'a>( krate }); - sess.time("maybe building test harness", || { + sess.time("maybe_building_test_harness", || { rustc_builtin_macros::test_harness::inject( &sess.parse_sess, &mut resolver, @@ -346,7 +344,7 @@ fn configure_and_expand_inner<'a>( util::ReplaceBodyWithLoop::new(&mut resolver).visit_crate(&mut krate); } - let has_proc_macro_decls = sess.time("AST validation", || { + let has_proc_macro_decls = sess.time("AST_validation", || { ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer()) }); @@ -368,7 +366,7 @@ fn configure_and_expand_inner<'a>( msg.warn("The generated documentation may be incorrect"); msg.emit() } else { - krate = sess.time("maybe creating a macro crate", || { + krate = sess.time("maybe_create_a_macro_crate", || { let num_crate_types = crate_types.len(); let is_test_crate = sess.opts.test; rustc_builtin_macros::proc_macro_harness::inject( @@ -398,12 +396,10 @@ fn configure_and_expand_inner<'a>( println!("{}", json::as_json(&krate)); } - sess.time("name resolution", || { - resolver.resolve_crate(&krate); - }); + resolver.resolve_crate(&krate); // Needs to go *after* expansion to be able to check the results of macro expansion. - sess.time("complete gated feature checking", || { + sess.time("complete_gated_feature_checking", || { syntax::feature_gate::check_crate( &krate, &sess.parse_sess, @@ -432,24 +428,22 @@ pub fn lower_to_hir<'res, 'tcx>( arena: &'tcx Arena<'tcx>, ) -> Result> { // Lower AST to HIR. - let hir_forest = sess.time("lowering AST -> HIR", || { - let hir_crate = rustc_ast_lowering::lower_crate( - sess, - &dep_graph, - &krate, - resolver, - rustc_parse::nt_to_tokenstream, - arena, - ); + let hir_crate = rustc_ast_lowering::lower_crate( + sess, + &dep_graph, + &krate, + resolver, + rustc_parse::nt_to_tokenstream, + arena, + ); - if sess.opts.debugging_opts.hir_stats { - hir_stats::print_hir_stats(&hir_crate); - } + if sess.opts.debugging_opts.hir_stats { + hir_stats::print_hir_stats(&hir_crate); + } - map::Forest::new(hir_crate, &dep_graph) - }); + let hir_forest = map::Forest::new(hir_crate, &dep_graph); - sess.time("early lint checks", || { + sess.time("early_lint_checks", || { rustc_lint::check_ast_crate( sess, lint_store, @@ -723,12 +717,9 @@ pub fn create_global_ctxt<'tcx>( let defs = mem::take(&mut resolver_outputs.definitions); // Construct the HIR map. - let hir_map = sess.time("indexing HIR", || { - map::map_crate(sess, &*resolver_outputs.cstore, &hir_forest, defs) - }); + let hir_map = map::map_crate(sess, &*resolver_outputs.cstore, &hir_forest, defs); - let query_result_on_disk_cache = - sess.time("load query result cache", || rustc_incremental::load_query_result_cache(sess)); + let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess); let codegen_backend = compiler.codegen_backend(); let mut local_providers = ty::query::Providers::default(); @@ -761,7 +752,7 @@ pub fn create_global_ctxt<'tcx>( // Do some initialization of the DepGraph that can only be done with the tcx available. ty::tls::enter_global(&gcx, |tcx| { - tcx.sess.time("dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx)); + tcx.sess.time("dep_graph_tcx_init", || rustc_incremental::dep_graph_tcx_init(tcx)); }); QueryContext(gcx) @@ -775,17 +766,17 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { let sess = tcx.sess; let mut entry_point = None; - sess.time("misc checking 1", || { + sess.time("misc_checking_1", || { parallel!( { entry_point = sess - .time("looking for entry point", || rustc_passes::entry::find_entry_point(tcx)); + .time("looking_for_entry_point", || rustc_passes::entry::find_entry_point(tcx)); - sess.time("looking for plugin registrar", || { + sess.time("looking_for_plugin_registrar", || { plugin::build::find_plugin_registrar(tcx) }); - sess.time("looking for derive registrar", || proc_macro_decls::find(tcx)); + sess.time("looking_for_derive_registrar", || proc_macro_decls::find(tcx)); }, { par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { @@ -802,17 +793,17 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { // passes are timed inside typeck typeck::check_crate(tcx)?; - sess.time("misc checking 2", || { + sess.time("misc_checking_2", || { parallel!( { - sess.time("match checking", || { + sess.time("match_checking", || { tcx.par_body_owners(|def_id| { tcx.ensure().check_match(def_id); }); }); }, { - sess.time("liveness checking + intrinsic checking", || { + sess.time("liveness_and_intrinsic_checking", || { par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { // this must run before MIR dump, because // "not all control paths return a value" is reported here. @@ -828,21 +819,21 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { ); }); - sess.time("MIR borrow checking", || { + sess.time("MIR_borrow_checking", || { tcx.par_body_owners(|def_id| tcx.ensure().mir_borrowck(def_id)); }); - sess.time("dumping Chalk-like clauses", || { + sess.time("dumping_chalk_like_clauses", || { rustc_traits::lowering::dump_program_clauses(tcx); }); - sess.time("MIR effect checking", || { + sess.time("MIR_effect_checking", || { for def_id in tcx.body_owners() { mir::transform::check_unsafety::check_unsafety(tcx, def_id) } }); - sess.time("layout testing", || layout_test::test_layout(tcx)); + sess.time("layout_testing", || layout_test::test_layout(tcx)); // Avoid overwhelming user with errors if borrow checking failed. // I'm not sure how helpful this is, to be honest, but it avoids a @@ -853,28 +844,25 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { return Err(ErrorReported); } - sess.time("misc checking 3", || { + sess.time("misc_checking_3", || { parallel!( { - sess.time("privacy access levels", || { - tcx.ensure().privacy_access_levels(LOCAL_CRATE); - }); + tcx.ensure().privacy_access_levels(LOCAL_CRATE); + parallel!( { - sess.time("private in public", || { - tcx.ensure().check_private_in_public(LOCAL_CRATE); - }); + tcx.ensure().check_private_in_public(LOCAL_CRATE); }, { - sess.time("death checking", || rustc_passes::dead::check_crate(tcx)); + sess.time("death_checking", || rustc_passes::dead::check_crate(tcx)); }, { - sess.time("unused lib feature checking", || { + sess.time("unused_lib_feature_checking", || { rustc_passes::stability::check_unused_or_stable_features(tcx) }); }, { - sess.time("lint checking", || { + sess.time("lint_checking", || { rustc_lint::check_crate(tcx, || { rustc_lint::BuiltinCombinedLateLintPass::new() }); @@ -883,7 +871,7 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { ); }, { - sess.time("privacy checking modules", || { + sess.time("privacy_checking_modules", || { par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { tcx.ensure().check_mod_privacy(tcx.hir().local_def_id(module)); }); @@ -926,6 +914,8 @@ fn encode_and_write_metadata( MetadataKind::Uncompressed | MetadataKind::Compressed => tcx.encode_metadata(), }; + let _prof_timer = tcx.sess.prof.generic_activity("write_crate_metadata"); + let need_metadata_file = tcx.sess.opts.output_types.contains_key(&OutputType::Metadata); if need_metadata_file { let crate_name = &tcx.crate_name(LOCAL_CRATE).as_str(); @@ -968,10 +958,9 @@ pub fn start_codegen<'tcx>( tcx.print_debug_stats(); } - let (metadata, need_metadata_module) = - tcx.sess.time("metadata encoding and writing", || encode_and_write_metadata(tcx, outputs)); + let (metadata, need_metadata_module) = encode_and_write_metadata(tcx, outputs); - let codegen = tcx.sess.time("codegen", move || { + let codegen = tcx.sess.time("codegen_crate", move || { codegen_backend.codegen_crate(tcx, metadata, need_metadata_module) }); diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 2de0e1ecccc8..6033569d765b 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -195,7 +195,7 @@ impl<'tcx> Queries<'tcx> { None => DepGraph::new_disabled(), Some(future) => { let (prev_graph, prev_work_products) = - self.session().time("blocked while dep-graph loading finishes", || { + self.session().time("blocked_on_dep_graph_loading", || { future .open() .unwrap_or_else(|e| rustc_incremental::LoadResult::Error { diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 23740af52597..c8a595267569 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -46,7 +46,6 @@ use syntax::ast::{self, Expr}; use syntax::attr::{self, HasAttrs}; use syntax::errors::{Applicability, DiagnosticBuilder}; use syntax::print::pprust::{self, expr_to_string}; -use syntax::ptr::P; use syntax::tokenstream::{TokenStream, TokenTree}; use syntax::visit::FnKind; @@ -1309,11 +1308,13 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns { /// If `pat` is a `...` pattern, return the start and end of the range, as well as the span /// corresponding to the ellipsis. - fn matches_ellipsis_pat(pat: &ast::Pat) -> Option<(&P, &P, Span)> { + fn matches_ellipsis_pat(pat: &ast::Pat) -> Option<(Option<&Expr>, &Expr, Span)> { match &pat.kind { - PatKind::Range(a, b, Spanned { span, node: RangeEnd::Included(DotDotDot), .. }) => { - Some((a, b, *span)) - } + PatKind::Range( + a, + Some(b), + Spanned { span, node: RangeEnd::Included(DotDotDot) }, + ) => Some((a.as_deref(), b, *span)), _ => None, } } @@ -1328,11 +1329,16 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns { let suggestion = "use `..=` for an inclusive range"; if parenthesise { self.node_id = Some(pat.id); + let end = expr_to_string(&end); + let replace = match start { + Some(start) => format!("&({}..={})", expr_to_string(&start), end), + None => format!("&(..={})", end), + }; let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, msg); err.span_suggestion( pat.span, suggestion, - format!("&({}..={})", expr_to_string(&start), expr_to_string(&end)), + replace, Applicability::MachineApplicable, ); err.emit(); diff --git a/src/librustc_lint/early.rs b/src/librustc_lint/early.rs index a09956854594..67c0c98b2038 100644 --- a/src/librustc_lint/early.rs +++ b/src/librustc_lint/early.rs @@ -350,16 +350,19 @@ pub fn check_ast_crate( } } else { for pass in &mut passes { - buffered = sess.time(&format!("running lint: {}", pass.name()), || { - early_lint_crate( - sess, - lint_store, - krate, - EarlyLintPassObjects { lints: slice::from_mut(pass) }, - buffered, - pre_expansion, - ) - }); + buffered = sess + .prof + .extra_verbose_generic_activity(&format!("running lint: {}", pass.name())) + .run(|| { + early_lint_crate( + sess, + lint_store, + krate, + EarlyLintPassObjects { lints: slice::from_mut(pass) }, + buffered, + pre_expansion, + ) + }); } } diff --git a/src/librustc_lint/late.rs b/src/librustc_lint/late.rs index a37e3be9ced9..07c3b95d6997 100644 --- a/src/librustc_lint/late.rs +++ b/src/librustc_lint/late.rs @@ -434,18 +434,27 @@ fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, b late_lint_pass_crate(tcx, builtin_lints); } else { for pass in &mut passes { - tcx.sess.time(&format!("running late lint: {}", pass.name()), || { - late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) }); - }); + tcx.sess + .prof + .extra_verbose_generic_activity(&format!("running late lint: {}", pass.name())) + .run(|| { + late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) }); + }); } let mut passes: Vec<_> = tcx.lint_store.late_module_passes.iter().map(|pass| (pass)()).collect(); for pass in &mut passes { - tcx.sess.time(&format!("running late module lint: {}", pass.name()), || { - late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) }); - }); + tcx.sess + .prof + .extra_verbose_generic_activity(&format!( + "running late module lint: {}", + pass.name() + )) + .run(|| { + late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) }); + }); } } } @@ -457,13 +466,13 @@ pub fn check_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( ) { join( || { - tcx.sess.time("crate lints", || { + tcx.sess.time("crate_lints", || { // Run whole crate non-incremental lints late_lint_crate(tcx, builtin_lints()); }); }, || { - tcx.sess.time("module lints", || { + tcx.sess.time("module_lints", || { // Run per-module lints par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { tcx.ensure().lint_mod(tcx.hir().local_def_id(module)); diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 611d3f5b832d..2598ce2391fb 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -429,14 +429,87 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, ) -> (PatKind<'tcx>, Option>) { match self.lower_lit(expr) { - PatKind::AscribeUserType { - ascription: lo_ascription, - subpattern: Pat { kind: box kind, .. }, - } => (kind, Some(lo_ascription)), + PatKind::AscribeUserType { ascription, subpattern: Pat { kind: box kind, .. } } => { + (kind, Some(ascription)) + } kind => (kind, None), } } + fn lower_pattern_range( + &mut self, + ty: Ty<'tcx>, + lo: &'tcx ty::Const<'tcx>, + hi: &'tcx ty::Const<'tcx>, + end: RangeEnd, + span: Span, + ) -> PatKind<'tcx> { + assert_eq!(lo.ty, ty); + assert_eq!(hi.ty, ty); + let cmp = compare_const_vals(self.tcx, lo, hi, self.param_env, ty); + match (end, cmp) { + // `x..y` where `x < y`. + // Non-empty because the range includes at least `x`. + (RangeEnd::Excluded, Some(Ordering::Less)) => PatKind::Range(PatRange { lo, hi, end }), + // `x..y` where `x >= y`. The range is empty => error. + (RangeEnd::Excluded, _) => { + struct_span_err!( + self.tcx.sess, + span, + E0579, + "lower range bound must be less than upper" + ) + .emit(); + PatKind::Wild + } + // `x..=y` where `x == y`. + (RangeEnd::Included, Some(Ordering::Equal)) => PatKind::Constant { value: lo }, + // `x..=y` where `x < y`. + (RangeEnd::Included, Some(Ordering::Less)) => PatKind::Range(PatRange { lo, hi, end }), + // `x..=y` where `x > y` hence the range is empty => error. + (RangeEnd::Included, _) => { + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0030, + "lower range bound must be less than or equal to upper" + ); + err.span_label(span, "lower bound larger than upper bound"); + if self.tcx.sess.teach(&err.get_code().unwrap()) { + err.note( + "When matching against a range, the compiler \ + verifies that the range is non-empty. Range \ + patterns include both end-points, so this is \ + equivalent to requiring the start of the range \ + to be less than or equal to the end of the range.", + ); + } + err.emit(); + PatKind::Wild + } + } + } + + fn normalize_range_pattern_ends( + &self, + ty: Ty<'tcx>, + lo: Option<&PatKind<'tcx>>, + hi: Option<&PatKind<'tcx>>, + ) -> Option<(&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>)> { + match (lo, hi) { + (Some(PatKind::Constant { value: lo }), Some(PatKind::Constant { value: hi })) => { + Some((lo, hi)) + } + (Some(PatKind::Constant { value: lo }), None) => { + Some((lo, ty.numeric_max_val(self.tcx)?)) + } + (None, Some(PatKind::Constant { value: hi })) => { + Some((ty.numeric_min_val(self.tcx)?, hi)) + } + _ => None, + } + } + fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> { let mut ty = self.tables.node_type(pat.hir_id); @@ -451,65 +524,20 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { hir::PatKind::Lit(ref value) => self.lower_lit(value), hir::PatKind::Range(ref lo_expr, ref hi_expr, end) => { - let (lo, lo_ascription) = self.lower_range_expr(lo_expr); - let (hi, hi_ascription) = self.lower_range_expr(hi_expr); - - let mut kind = match (lo, hi) { - (PatKind::Constant { value: lo }, PatKind::Constant { value: hi }) => { - assert_eq!(lo.ty, ty); - assert_eq!(hi.ty, ty); - let cmp = compare_const_vals(self.tcx, lo, hi, self.param_env, ty); - match (end, cmp) { - (RangeEnd::Excluded, Some(Ordering::Less)) => { - PatKind::Range(PatRange { lo, hi, end }) - } - (RangeEnd::Excluded, _) => { - struct_span_err!( - self.tcx.sess, - lo_expr.span, - E0579, - "lower range bound must be less than upper", - ) - .emit(); - PatKind::Wild - } - (RangeEnd::Included, Some(Ordering::Equal)) => { - PatKind::Constant { value: lo } - } - (RangeEnd::Included, Some(Ordering::Less)) => { - PatKind::Range(PatRange { lo, hi, end }) - } - (RangeEnd::Included, _) => { - let mut err = struct_span_err!( - self.tcx.sess, - lo_expr.span, - E0030, - "lower range bound must be less than or equal to upper" - ); - err.span_label(lo_expr.span, "lower bound larger than upper bound"); - if self.tcx.sess.teach(&err.get_code().unwrap()) { - err.note( - "When matching against a range, the compiler \ - verifies that the range is non-empty. Range \ - patterns include both end-points, so this is \ - equivalent to requiring the start of the range \ - to be less than or equal to the end of the range.", - ); - } - err.emit(); - PatKind::Wild - } - } - } - ref pats => { - self.tcx.sess.delay_span_bug( - pat.span, - &format!( - "found bad range pattern `{:?}` outside of error recovery", - pats, - ), + let (lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref()); + let lo_span = lo_expr.map_or(pat.span, |e| e.span); + let lo = lo_expr.map(|e| self.lower_range_expr(e)); + let hi = hi_expr.map(|e| self.lower_range_expr(e)); + + let (lp, hp) = (lo.as_ref().map(|x| &x.0), hi.as_ref().map(|x| &x.0)); + let mut kind = match self.normalize_range_pattern_ends(ty, lp, hp) { + Some((lc, hc)) => self.lower_pattern_range(ty, lc, hc, end, lo_span), + None => { + let msg = &format!( + "found bad range pattern `{:?}` outside of error recovery", + (&lo, &hi), ); - + self.tcx.sess.delay_span_bug(pat.span, msg); PatKind::Wild } }; @@ -517,12 +545,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // If we are handling a range with associated constants (e.g. // `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated // constants somewhere. Have them on the range pattern. - for ascription in &[lo_ascription, hi_ascription] { - if let Some(ascription) = ascription { - kind = PatKind::AscribeUserType { - ascription: *ascription, - subpattern: Pat { span: pat.span, ty, kind: Box::new(kind) }, - }; + for end in &[lo, hi] { + if let Some((_, Some(ascription))) = end { + let subpattern = Pat { span: pat.span, ty, kind: Box::new(kind) }; + kind = PatKind::AscribeUserType { ascription: *ascription, subpattern }; } } diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 0943be9d95c3..41fbfd22e50a 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -283,10 +283,8 @@ pub fn collect_crate_mono_items( ) -> (FxHashSet>, InliningMap<'_>) { let _prof_timer = tcx.prof.generic_activity("monomorphization_collector"); - let roots = tcx.sess.time("collecting roots", || { - let _prof_timer = tcx.prof.generic_activity("monomorphization_collector_root_collections"); - collect_roots(tcx, mode) - }); + let roots = + tcx.sess.time("monomorphization_collector_root_collections", || collect_roots(tcx, mode)); debug!("building mono item graph, beginning at roots"); @@ -297,7 +295,7 @@ pub fn collect_crate_mono_items( let visited: MTRef<'_, _> = &mut visited; let inlining_map: MTRef<'_, _> = &mut inlining_map; - tcx.sess.time("collecting mono items", || { + tcx.sess.time("monomorphization_collector_graph_walk", || { par_iter(roots).for_each(|root| { let mut recursion_depths = DefIdMap::default(); collect_items_rec(tcx, root, visited, &mut recursion_depths, inlining_map); diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index c004417b3373..8fa41cab1907 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -865,9 +865,7 @@ fn collect_and_partition_mono_items( } }; - let (items, inlining_map) = tcx.sess.time("monomorphization collection", || { - collector::collect_crate_mono_items(tcx, collection_mode) - }); + let (items, inlining_map) = collector::collect_crate_mono_items(tcx, collection_mode); tcx.sess.abort_if_errors(); @@ -879,12 +877,10 @@ fn collect_and_partition_mono_items( PartitioningStrategy::FixedUnitCount(tcx.sess.codegen_units()) }; - let codegen_units = tcx.sess.time("codegen unit partitioning", || { - partition(tcx, items.iter().cloned(), strategy, &inlining_map) - .into_iter() - .map(Arc::new) - .collect::>() - }); + let codegen_units = partition(tcx, items.iter().cloned(), strategy, &inlining_map) + .into_iter() + .map(Arc::new) + .collect::>(); let mono_items: DefIdSet = items .iter() diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 9abfbc698c5c..d321383424ca 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -51,7 +51,6 @@ pub enum Error { secondary_path: String, }, UselessDocComment, - InclusiveRangeWithNoEnd, } impl Error { @@ -102,11 +101,6 @@ impl Error { ); err } - Error::InclusiveRangeWithNoEnd => { - let mut err = struct_span_err!(handler, sp, E0586, "inclusive range with no end",); - err.help("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)"); - err - } } } } diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 90f15375aec4..2d6a94ce620c 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1,4 +1,3 @@ -use super::diagnostics::Error; use super::pat::{GateOr, PARAM_EXPECTED}; use super::{BlockMode, Parser, PathStyle, PrevTokenKind, Restrictions, TokenType}; use super::{SemiColonMode, SeqSep, TokenExpectType}; @@ -1967,7 +1966,8 @@ impl<'a> Parser<'a> { limits: RangeLimits, ) -> PResult<'a, ExprKind> { if end.is_none() && limits == RangeLimits::Closed { - Err(self.span_fatal_err(self.token.span, Error::InclusiveRangeWithNoEnd)) + self.error_inclusive_range_with_no_end(self.token.span); + Ok(ExprKind::Err) } else { Ok(ExprKind::Range(start, end, limits)) } diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs index bf7f5735f134..50756ddec9f2 100644 --- a/src/librustc_parse/parser/pat.rs +++ b/src/librustc_parse/parser/pat.rs @@ -1,6 +1,6 @@ use super::{Parser, PathStyle}; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; -use rustc_errors::{Applicability, DiagnosticBuilder, PResult}; +use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult}; use rustc_span::source_map::{respan, Span, Spanned}; use rustc_span::symbol::{kw, sym}; use syntax::ast::{self, AttrVec, Attribute, FieldPat, Mac, Pat, PatKind, RangeEnd, RangeSyntax}; @@ -281,91 +281,73 @@ impl<'a> Parser<'a> { maybe_whole!(self, NtPat, |x| x); let lo = self.token.span; - let pat = match self.token.kind { - token::BinOp(token::And) | token::AndAnd => self.parse_pat_deref(expected)?, - token::OpenDelim(token::Paren) => self.parse_pat_tuple_or_parens()?, - token::OpenDelim(token::Bracket) => { - // Parse `[pat, pat,...]` as a slice pattern. - let (pats, _) = - self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat_with_or_inner())?; - PatKind::Slice(pats) - } - token::DotDot => { - self.bump(); - if self.is_pat_range_end_start() { - // Parse `..42` for recovery. - self.parse_pat_range_to(RangeEnd::Excluded, "..")? - } else { - // A rest pattern `..`. - PatKind::Rest - } - } - token::DotDotEq => { - // Parse `..=42` for recovery. - self.bump(); - self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotEq), "..=")? - } - token::DotDotDot => { - // Parse `...42` for recovery. - self.bump(); - self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotDot), "...")? + + let pat = if self.check(&token::BinOp(token::And)) || self.token.kind == token::AndAnd { + self.parse_pat_deref(expected)? + } else if self.check(&token::OpenDelim(token::Paren)) { + self.parse_pat_tuple_or_parens()? + } else if self.check(&token::OpenDelim(token::Bracket)) { + // Parse `[pat, pat,...]` as a slice pattern. + let (pats, _) = + self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat_with_or_inner())?; + PatKind::Slice(pats) + } else if self.check(&token::DotDot) && !self.is_pat_range_end_start(1) { + // A rest pattern `..`. + self.bump(); // `..` + PatKind::Rest + } else if let Some(form) = self.parse_range_end() { + self.parse_pat_range_to(form)? // `..=X`, `...X`, or `..X`. + } else if self.eat_keyword(kw::Underscore) { + // Parse _ + PatKind::Wild + } else if self.eat_keyword(kw::Mut) { + self.parse_pat_ident_mut()? + } else if self.eat_keyword(kw::Ref) { + // Parse ref ident @ pat / ref mut ident @ pat + let mutbl = self.parse_mutability(); + self.parse_pat_ident(BindingMode::ByRef(mutbl))? + } else if self.eat_keyword(kw::Box) { + // Parse `box pat` + let pat = self.parse_pat_with_range_pat(false, None)?; + self.sess.gated_spans.gate(sym::box_patterns, lo.to(self.prev_span)); + PatKind::Box(pat) + } else if self.can_be_ident_pat() { + // Parse `ident @ pat` + // This can give false positives and parse nullary enums, + // they are dealt with later in resolve. + self.parse_pat_ident(BindingMode::ByValue(Mutability::Not))? + } else if self.is_start_of_pat_with_path() { + // Parse pattern starting with a path + let (qself, path) = if self.eat_lt() { + // Parse a qualified path + let (qself, path) = self.parse_qpath(PathStyle::Expr)?; + (Some(qself), path) + } else { + // Parse an unqualified path + (None, self.parse_path(PathStyle::Expr)?) + }; + let span = lo.to(self.prev_span); + + if qself.is_none() && self.check(&token::Not) { + self.parse_pat_mac_invoc(path)? + } else if let Some(form) = self.parse_range_end() { + let begin = self.mk_expr(span, ExprKind::Path(qself, path), AttrVec::new()); + self.parse_pat_range_begin_with(begin, form)? + } else if self.check(&token::OpenDelim(token::Brace)) { + self.parse_pat_struct(qself, path)? + } else if self.check(&token::OpenDelim(token::Paren)) { + self.parse_pat_tuple_struct(qself, path)? + } else { + PatKind::Path(qself, path) } - // At this point, token != `&`, `&&`, `(`, `[`, `..`, `..=`, or `...`. - _ => { - if self.eat_keyword(kw::Underscore) { - // Parse _ - PatKind::Wild - } else if self.eat_keyword(kw::Mut) { - self.parse_pat_ident_mut()? - } else if self.eat_keyword(kw::Ref) { - // Parse ref ident @ pat / ref mut ident @ pat - let mutbl = self.parse_mutability(); - self.parse_pat_ident(BindingMode::ByRef(mutbl))? - } else if self.eat_keyword(kw::Box) { - // Parse `box pat` - let pat = self.parse_pat_with_range_pat(false, None)?; - self.sess.gated_spans.gate(sym::box_patterns, lo.to(self.prev_span)); - PatKind::Box(pat) - } else if self.can_be_ident_pat() { - // Parse `ident @ pat` - // This can give false positives and parse nullary enums, - // they are dealt with later in resolve. - self.parse_pat_ident(BindingMode::ByValue(Mutability::Not))? - } else if self.is_start_of_pat_with_path() { - // Parse pattern starting with a path - let (qself, path) = if self.eat_lt() { - // Parse a qualified path - let (qself, path) = self.parse_qpath(PathStyle::Expr)?; - (Some(qself), path) - } else { - // Parse an unqualified path - (None, self.parse_path(PathStyle::Expr)?) - }; - match self.token.kind { - token::Not if qself.is_none() => self.parse_pat_mac_invoc(path)?, - token::DotDotDot | token::DotDotEq | token::DotDot => { - self.parse_pat_range_starting_with_path(lo, qself, path)? - } - token::OpenDelim(token::Brace) => self.parse_pat_struct(qself, path)?, - token::OpenDelim(token::Paren) => { - self.parse_pat_tuple_struct(qself, path)? - } - _ => PatKind::Path(qself, path), - } - } else { - // Try to parse everything else as literal with optional minus - match self.parse_literal_maybe_minus() { - Ok(begin) - if self.check(&token::DotDot) - || self.check(&token::DotDotEq) - || self.check(&token::DotDotDot) => - { - self.parse_pat_range_starting_with_lit(begin)? - } - Ok(begin) => PatKind::Lit(begin), - Err(err) => return self.fatal_unexpected_non_pat(err, expected), - } - } + } else { + // Try to parse everything else as literal with optional minus + match self.parse_literal_maybe_minus() { + Ok(begin) => match self.parse_range_end() { + Some(form) => self.parse_pat_range_begin_with(begin, form)?, + None => PatKind::Lit(begin), + }, + Err(err) => return self.fatal_unexpected_non_pat(err, expected), } }; @@ -374,7 +356,7 @@ impl<'a> Parser<'a> { let pat = self.recover_intersection_pat(pat)?; if !allow_range_pat { - self.ban_pat_range_if_ambiguous(&pat)? + self.ban_pat_range_if_ambiguous(&pat) } Ok(pat) @@ -441,26 +423,25 @@ impl<'a> Parser<'a> { } /// Ban a range pattern if it has an ambiguous interpretation. - fn ban_pat_range_if_ambiguous(&self, pat: &Pat) -> PResult<'a, ()> { + fn ban_pat_range_if_ambiguous(&self, pat: &Pat) { match pat.kind { PatKind::Range( .., Spanned { node: RangeEnd::Included(RangeSyntax::DotDotDot), .. }, - ) => return Ok(()), + ) => return, PatKind::Range(..) => {} - _ => return Ok(()), + _ => return, } - let mut err = - self.struct_span_err(pat.span, "the range pattern here has ambiguous interpretation"); - err.span_suggestion( - pat.span, - "add parentheses to clarify the precedence", - format!("({})", pprust::pat_to_string(&pat)), - // "ambiguous interpretation" implies that we have to be guessing - Applicability::MaybeIncorrect, - ); - Err(err) + self.struct_span_err(pat.span, "the range pattern here has ambiguous interpretation") + .span_suggestion( + pat.span, + "add parentheses to clarify the precedence", + format!("({})", pprust::pat_to_string(&pat)), + // "ambiguous interpretation" implies that we have to be guessing + Applicability::MaybeIncorrect, + ) + .emit(); } /// Parse `&pat` / `&mut pat`. @@ -618,51 +599,6 @@ impl<'a> Parser<'a> { Ok(PatKind::Mac(mac)) } - fn excluded_range_end(&self, span: Span) -> RangeEnd { - self.sess.gated_spans.gate(sym::exclusive_range_pattern, span); - RangeEnd::Excluded - } - - /// Parse a range pattern `$path $form $end?` where `$form = ".." | "..." | "..=" ;`. - /// The `$path` has already been parsed and the next token is the `$form`. - fn parse_pat_range_starting_with_path( - &mut self, - lo: Span, - qself: Option, - path: Path, - ) -> PResult<'a, PatKind> { - let (end_kind, form) = match self.token.kind { - token::DotDot => (self.excluded_range_end(self.token.span), ".."), - token::DotDotDot => (RangeEnd::Included(RangeSyntax::DotDotDot), "..."), - token::DotDotEq => (RangeEnd::Included(RangeSyntax::DotDotEq), "..="), - _ => panic!("can only parse `..`/`...`/`..=` for ranges (checked above)"), - }; - let op_span = self.token.span; - // Parse range - let span = lo.to(self.prev_span); - let begin = self.mk_expr(span, ExprKind::Path(qself, path), AttrVec::new()); - self.bump(); - let end = self.parse_pat_range_end_opt(&begin, form)?; - Ok(PatKind::Range(begin, end, respan(op_span, end_kind))) - } - - /// Parse a range pattern `$literal $form $end?` where `$form = ".." | "..." | "..=" ;`. - /// The `$path` has already been parsed and the next token is the `$form`. - fn parse_pat_range_starting_with_lit(&mut self, begin: P) -> PResult<'a, PatKind> { - let op_span = self.token.span; - let (end_kind, form) = if self.eat(&token::DotDotDot) { - (RangeEnd::Included(RangeSyntax::DotDotDot), "...") - } else if self.eat(&token::DotDotEq) { - (RangeEnd::Included(RangeSyntax::DotDotEq), "..=") - } else if self.eat(&token::DotDot) { - (self.excluded_range_end(op_span), "..") - } else { - panic!("impossible case: we already matched on a range-operator token") - }; - let end = self.parse_pat_range_end_opt(&begin, form)?; - Ok(PatKind::Range(begin, end, respan(op_span, end_kind))) - } - fn fatal_unexpected_non_pat( &mut self, mut err: DiagnosticBuilder<'a>, @@ -684,57 +620,66 @@ impl<'a> Parser<'a> { Err(err) } - /// Is the current token suitable as the start of a range patterns end? - fn is_pat_range_end_start(&self) -> bool { - self.token.is_path_start() // e.g. `MY_CONST`; - || self.token == token::Dot // e.g. `.5` for recovery; - || self.token.can_begin_literal_or_bool() // e.g. `42`. - || self.token.is_whole_expr() - } - - /// Parse a range-to pattern, e.g. `..X` and `..=X` for recovery. - fn parse_pat_range_to(&mut self, re: RangeEnd, form: &str) -> PResult<'a, PatKind> { - let lo = self.prev_span; - let end = self.parse_pat_range_end()?; - let range_span = lo.to(end.span); - let begin = self.mk_expr(range_span, ExprKind::Err, AttrVec::new()); - - self.struct_span_err(range_span, &format!("`{}X` range patterns are not supported", form)) - .span_suggestion( - range_span, - "try using the minimum value for the type", - format!("MIN{}{}", form, pprust::expr_to_string(&end)), - Applicability::HasPlaceholders, - ) - .emit(); - - Ok(PatKind::Range(begin, end, respan(lo, re))) + /// Parses the range pattern end form `".." | "..." | "..=" ;`. + fn parse_range_end(&mut self) -> Option> { + let re = if self.eat(&token::DotDotDot) { + RangeEnd::Included(RangeSyntax::DotDotDot) + } else if self.eat(&token::DotDotEq) { + RangeEnd::Included(RangeSyntax::DotDotEq) + } else if self.eat(&token::DotDot) { + self.sess.gated_spans.gate(sym::exclusive_range_pattern, self.prev_span); + RangeEnd::Excluded + } else { + return None; + }; + Some(respan(self.prev_span, re)) } - /// Parse the end of a `X..Y`, `X..=Y`, or `X...Y` range pattern or recover - /// if that end is missing treating it as `X..`, `X..=`, or `X...` respectively. - fn parse_pat_range_end_opt(&mut self, begin: &Expr, form: &str) -> PResult<'a, P> { - if self.is_pat_range_end_start() { + /// Parse a range pattern `$begin $form $end?` where `$form = ".." | "..." | "..=" ;`. + /// `$begin $form` has already been parsed. + fn parse_pat_range_begin_with( + &mut self, + begin: P, + re: Spanned, + ) -> PResult<'a, PatKind> { + let end = if self.is_pat_range_end_start(0) { // Parsing e.g. `X..=Y`. - self.parse_pat_range_end() + Some(self.parse_pat_range_end()?) } else { // Parsing e.g. `X..`. - let range_span = begin.span.to(self.prev_span); + self.sess.gated_spans.gate(sym::half_open_range_patterns, begin.span.to(re.span)); + if let RangeEnd::Included(_) = re.node { + // FIXME(Centril): Consider semantic errors instead in `ast_validation`. + // Possibly also do this for `X..=` in *expression* contexts. + self.error_inclusive_range_with_no_end(re.span); + } + None + }; + Ok(PatKind::Range(Some(begin), end, re)) + } - self.struct_span_err( - range_span, - &format!("`X{}` range patterns are not supported", form), - ) - .span_suggestion( - range_span, - "try using the maximum value for the type", - format!("{}{}MAX", pprust::expr_to_string(&begin), form), - Applicability::HasPlaceholders, - ) + pub(super) fn error_inclusive_range_with_no_end(&self, span: Span) { + use rustc_error_codes::E0586; + struct_span_err!(self.sess.span_diagnostic, span, E0586, "inclusive range with no end") + .help("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)") .emit(); + } - Ok(self.mk_expr(range_span, ExprKind::Err, AttrVec::new())) - } + /// Parse a range-to pattern, e.g. `..X` and `..=X` where `X` remains to be parsed. + fn parse_pat_range_to(&mut self, re: Spanned) -> PResult<'a, PatKind> { + let end = self.parse_pat_range_end()?; + self.sess.gated_spans.gate(sym::half_open_range_patterns, re.span.to(self.prev_span)); + Ok(PatKind::Range(None, Some(end), re)) + } + + /// Is the token `dist` away from the current suitable as the start of a range patterns end? + fn is_pat_range_end_start(&self, dist: usize) -> bool { + self.look_ahead(dist, |t| { + t.is_path_start() // e.g. `MY_CONST`; + || t.kind == token::Dot // e.g. `.5` for recovery; + || t.can_begin_literal_or_bool() // e.g. `42`. + || t.is_whole_expr() + }) } fn parse_pat_range_end(&mut self) -> PResult<'a, P> { diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 5000cd5f52f6..4f9c874ab5ac 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -847,8 +847,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_expr_within_pat(expr, false); } PatKind::Range(ref start, ref end, _) => { - self.check_expr_within_pat(start, true); - self.check_expr_within_pat(end, true); + if let Some(expr) = start { + self.check_expr_within_pat(expr, true); + } + if let Some(expr) = end { + self.check_expr_within_pat(expr, true); + } } _ => {} } diff --git a/src/librustc_session/utils.rs b/src/librustc_session/utils.rs index 7806f5e8753f..fda11b647490 100644 --- a/src/librustc_session/utils.rs +++ b/src/librustc_session/utils.rs @@ -2,11 +2,11 @@ use crate::session::Session; use rustc_data_structures::profiling::VerboseTimingGuard; impl Session { - pub fn timer<'a>(&'a self, what: &'a str) -> VerboseTimingGuard<'a> { - self.prof.sparse_pass(what) + pub fn timer<'a>(&'a self, what: &'static str) -> VerboseTimingGuard<'a> { + self.prof.verbose_generic_activity(what) } - pub fn time(&self, what: &str, f: impl FnOnce() -> R) -> R { - self.prof.sparse_pass(what).run(f) + pub fn time(&self, what: &'static str, f: impl FnOnce() -> R) -> R { + self.prof.verbose_generic_activity(what).run(f) } } diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 40abc8b2179b..09096c8484b4 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -341,6 +341,7 @@ symbols! { global_allocator, global_asm, globs, + half_open_range_patterns, hash, Hash, HashSet, diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 58c722f1da6f..c2db165e29d1 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -135,12 +135,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = match pat.kind { PatKind::Wild => expected, PatKind::Lit(lt) => self.check_pat_lit(pat.span, lt, expected, ti), - PatKind::Range(begin, end, _) => { - match self.check_pat_range(pat.span, begin, end, expected, ti) { - None => return, - Some(ty) => ty, - } - } + PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti), PatKind::Binding(ba, var_id, _, sub) => { self.check_pat_ident(pat, ba, var_id, sub, expected, def_bm, ti) } @@ -395,39 +390,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_range( &self, span: Span, - lhs: &'tcx hir::Expr<'tcx>, - rhs: &'tcx hir::Expr<'tcx>, + lhs: Option<&'tcx hir::Expr<'tcx>>, + rhs: Option<&'tcx hir::Expr<'tcx>>, expected: Ty<'tcx>, ti: TopInfo<'tcx>, - ) -> Option> { - let lhs_ty = self.check_expr(lhs); - let rhs_ty = self.check_expr(rhs); - - // Check that both end-points are of numeric or char type. - let numeric_or_char = |ty: Ty<'_>| ty.is_numeric() || ty.is_char() || ty.references_error(); - let lhs_fail = !numeric_or_char(lhs_ty); - let rhs_fail = !numeric_or_char(rhs_ty); - - if lhs_fail || rhs_fail { - self.emit_err_pat_range(span, lhs.span, rhs.span, lhs_fail, rhs_fail, lhs_ty, rhs_ty); - return None; + ) -> Ty<'tcx> { + let calc_side = |opt_expr: Option<&'tcx hir::Expr<'tcx>>| match opt_expr { + None => (None, None), + Some(expr) => { + let ty = self.check_expr(expr); + // Check that the end-point is of numeric or char type. + let fail = !(ty.is_numeric() || ty.is_char() || ty.references_error()); + (Some(ty), Some((fail, ty, expr.span))) + } + }; + let (lhs_ty, lhs) = calc_side(lhs); + let (rhs_ty, rhs) = calc_side(rhs); + + if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) { + // There exists a side that didn't meet our criteria that the end-point + // be of a numeric or char type, as checked in `calc_side` above. + self.emit_err_pat_range(span, lhs, rhs); + return self.tcx.types.err; } - // Now that we know the types can be unified we find the unified type and use - // it to type the entire expression. - let common_type = self.resolve_vars_if_possible(&lhs_ty); + // Now that we know the types can be unified we find the unified type + // and use it to type the entire expression. + let common_type = self.resolve_vars_if_possible(&lhs_ty.or(rhs_ty).unwrap_or(expected)); // Subtyping doesn't matter here, as the value is some kind of scalar. - let demand_eqtype = |x_span, y_span, x_ty, y_ty| { - self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti).map(|mut err| { - self.endpoint_has_type(&mut err, y_span, y_ty); - err.emit(); - }); + let demand_eqtype = |x, y| { + if let Some((_, x_ty, x_span)) = x { + self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti).map(|mut err| { + if let Some((_, y_ty, y_span)) = y { + self.endpoint_has_type(&mut err, y_span, y_ty); + } + err.emit(); + }); + } }; - demand_eqtype(lhs.span, rhs.span, lhs_ty, rhs_ty); - demand_eqtype(rhs.span, lhs.span, rhs_ty, lhs_ty); + demand_eqtype(lhs, rhs); + demand_eqtype(rhs, lhs); - Some(common_type) + common_type } fn endpoint_has_type(&self, err: &mut DiagnosticBuilder<'_>, span: Span, ty: Ty<'_>) { @@ -439,21 +444,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn emit_err_pat_range( &self, span: Span, - begin_span: Span, - end_span: Span, - lhs_fail: bool, - rhs_fail: bool, - lhs_ty: Ty<'tcx>, - rhs_ty: Ty<'tcx>, + lhs: Option<(bool, Ty<'tcx>, Span)>, + rhs: Option<(bool, Ty<'tcx>, Span)>, ) { - let span = if lhs_fail && rhs_fail { - span - } else if lhs_fail { - begin_span - } else { - end_span + let span = match (lhs, rhs) { + (Some((true, ..)), Some((true, ..))) => span, + (Some((true, _, sp)), _) => sp, + (_, Some((true, _, sp))) => sp, + _ => span_bug!(span, "emit_err_pat_range: no side failed or exists but still error?"), }; - let mut err = struct_span_err!( self.tcx.sess, span, @@ -461,17 +460,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "only char and numeric types are allowed in range patterns" ); let msg = |ty| format!("this is of type `{}` but it should be `char` or numeric", ty); - let mut one_side_err = |first_span, first_ty, second_span, second_ty: Ty<'_>| { + let mut one_side_err = |first_span, first_ty, second: Option<(bool, Ty<'tcx>, Span)>| { err.span_label(first_span, &msg(first_ty)); - self.endpoint_has_type(&mut err, second_span, second_ty); + if let Some((_, ty, sp)) = second { + self.endpoint_has_type(&mut err, sp, ty); + } }; - if lhs_fail && rhs_fail { - err.span_label(begin_span, &msg(lhs_ty)); - err.span_label(end_span, &msg(rhs_ty)); - } else if lhs_fail { - one_side_err(begin_span, lhs_ty, end_span, rhs_ty); - } else { - one_side_err(end_span, rhs_ty, begin_span, lhs_ty); + match (lhs, rhs) { + (Some((true, lhs_ty, lhs_sp)), Some((true, rhs_ty, rhs_sp))) => { + err.span_label(lhs_sp, &msg(lhs_ty)); + err.span_label(rhs_sp, &msg(rhs_ty)); + } + (Some((true, lhs_ty, lhs_sp)), rhs) => one_side_err(lhs_sp, lhs_ty, rhs), + (lhs, Some((true, rhs_ty, rhs_sp))) => one_side_err(rhs_sp, rhs_ty, lhs), + _ => span_bug!(span, "Impossible, verified above."), } if self.tcx.sess.teach(&err.get_code().unwrap()) { err.note( diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 1a008ef23fc7..ca10601f4135 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -146,8 +146,8 @@ pub fn check_coherence(tcx: TyCtxt<'_>) { tcx.ensure().coherent_trait(trait_def_id); } - tcx.sess.time("unsafety checking", || unsafety::check(tcx)); - tcx.sess.time("orphan checking", || orphan::check(tcx)); + tcx.sess.time("unsafety_checking", || unsafety::check(tcx)); + tcx.sess.time("orphan_checking", || orphan::check(tcx)); // these queries are executed for side-effects (error reporting): tcx.ensure().crate_inherent_impls(LOCAL_CRATE); diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index bc48e046a0cb..0d9940cbf92c 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -309,7 +309,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { // have valid types and not error // FIXME(matthewjasper) We shouldn't need to do this. tcx.sess.track_errors(|| { - tcx.sess.time("type collecting", || { + tcx.sess.time("type_collecting", || { for &module in tcx.hir().krate().modules.keys() { tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module)); } @@ -318,35 +318,35 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { if tcx.features().rustc_attrs { tcx.sess.track_errors(|| { - tcx.sess.time("outlives testing", || outlives::test::test_inferred_outlives(tcx)); + tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx)); })?; } tcx.sess.track_errors(|| { - tcx.sess.time("impl wf inference", || impl_wf_check::impl_wf_check(tcx)); + tcx.sess.time("impl_wf_inference", || impl_wf_check::impl_wf_check(tcx)); })?; tcx.sess.track_errors(|| { - tcx.sess.time("coherence checking", || coherence::check_coherence(tcx)); + tcx.sess.time("coherence_checking", || coherence::check_coherence(tcx)); })?; if tcx.features().rustc_attrs { tcx.sess.track_errors(|| { - tcx.sess.time("variance testing", || variance::test::test_variance(tcx)); + tcx.sess.time("variance_testing", || variance::test::test_variance(tcx)); })?; } tcx.sess.track_errors(|| { - tcx.sess.time("wf checking", || check::check_wf_new(tcx)); + tcx.sess.time("wf_checking", || check::check_wf_new(tcx)); })?; - tcx.sess.time("item-types checking", || { + tcx.sess.time("item_types_checking", || { for &module in tcx.hir().krate().modules.keys() { tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module)); } }); - tcx.sess.time("item-bodies checking", || tcx.typeck_item_bodies(LOCAL_CRATE)); + tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(LOCAL_CRATE)); check_unused::check_crate(tcx); check_for_entry_fn(tcx); diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 566e5146cf85..b48700fb9442 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -631,6 +631,38 @@ where self.map.raw_entry_mut().from_key(&value).or_insert(value, ()).0 } + /// Inserts an owned copy of the given `value` into the set if it is not + /// present, then returns a reference to the value in the set. + /// + /// # Examples + /// + /// ``` + /// #![feature(hash_set_entry)] + /// + /// use std::collections::HashSet; + /// + /// let mut set: HashSet = ["cat", "dog", "horse"] + /// .iter().map(|&pet| pet.to_owned()).collect(); + /// + /// assert_eq!(set.len(), 3); + /// for &pet in &["cat", "dog", "fish"] { + /// let value = set.get_or_insert_owned(pet); + /// assert_eq!(value, pet); + /// } + /// assert_eq!(set.len(), 4); // a new "fish" was inserted + /// ``` + #[inline] + #[unstable(feature = "hash_set_entry", issue = "60896")] + pub fn get_or_insert_owned(&mut self, value: &Q) -> &T + where + T: Borrow, + Q: Hash + Eq + ToOwned, + { + // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with + // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`. + self.map.raw_entry_mut().from_key(value).or_insert_with(|| (value.to_owned(), ())).0 + } + /// Inserts a value computed from `f` into the set if the given `value` is /// not present, then returns a reference to the value in the set. /// diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 47070261385a..2f45756bc68c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -649,7 +649,7 @@ pub enum PatKind { Lit(P), /// A range pattern (e.g., `1...2`, `1..=2` or `1..2`). - Range(P, P, Spanned), + Range(Option>, Option>, Spanned), /// A slice pattern `[a, b, c]`. Slice(Vec>), diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index 26545bfa61b6..8580bfa1b329 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -909,6 +909,7 @@ pub fn check_crate( gate_all!(or_patterns, "or-patterns syntax is experimental"); gate_all!(const_extern_fn, "`const extern fn` definitions are unstable"); gate_all!(raw_ref_op, "raw address of syntax is experimental"); + gate_all!(half_open_range_patterns, "half-open range patterns are unstable"); // All uses of `gate_all!` below this point were added in #65742, // and subsequently disabled (with the non-early gating readded). diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 1413f1566d04..f73d85374e2d 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -1074,8 +1074,8 @@ pub fn noop_visit_pat(pat: &mut P, vis: &mut T) { PatKind::Box(inner) => vis.visit_pat(inner), PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner), PatKind::Range(e1, e2, Spanned { span: _, node: _ }) => { - vis.visit_expr(e1); - vis.visit_expr(e2); + visit_opt(e1, |e| vis.visit_expr(e)); + visit_opt(e2, |e| vis.visit_expr(e)); vis.visit_span(span); } PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index dd9976510dcc..11c8cb8ef750 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2329,14 +2329,18 @@ impl<'a> State<'a> { } PatKind::Lit(ref e) => self.print_expr(&**e), PatKind::Range(ref begin, ref end, Spanned { node: ref end_kind, .. }) => { - self.print_expr(begin); - self.s.space(); + if let Some(e) = begin { + self.print_expr(e); + self.s.space(); + } match *end_kind { RangeEnd::Included(RangeSyntax::DotDotDot) => self.s.word("..."), RangeEnd::Included(RangeSyntax::DotDotEq) => self.s.word("..="), RangeEnd::Excluded => self.s.word(".."), } - self.print_expr(end); + if let Some(e) = end { + self.print_expr(e); + } } PatKind::Slice(ref elts) => { self.s.word("["); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index ebb49abebb01..3c2ebacbc4e3 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -492,8 +492,8 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { } PatKind::Lit(ref expression) => visitor.visit_expr(expression), PatKind::Range(ref lower_bound, ref upper_bound, _) => { - visitor.visit_expr(lower_bound); - visitor.visit_expr(upper_bound); + walk_list!(visitor, visit_expr, lower_bound); + walk_list!(visitor, visit_expr, upper_bound); } PatKind::Wild | PatKind::Rest => {} PatKind::Tuple(ref elems) | PatKind::Slice(ref elems) | PatKind::Or(ref elems) => { diff --git a/src/test/run-make/wasm-export-all-symbols/bar.rs b/src/test/run-make/wasm-export-all-symbols/bar.rs index c5de87e8e723..ac9c20a57e5a 100644 --- a/src/test/run-make/wasm-export-all-symbols/bar.rs +++ b/src/test/run-make/wasm-export-all-symbols/bar.rs @@ -2,3 +2,6 @@ #[no_mangle] pub extern fn foo() {} + +#[no_mangle] +pub static FOO: u64 = 42; diff --git a/src/test/run-make/wasm-export-all-symbols/verify.js b/src/test/run-make/wasm-export-all-symbols/verify.js index 7b6fc7a45682..72db3356f563 100644 --- a/src/test/run-make/wasm-export-all-symbols/verify.js +++ b/src/test/run-make/wasm-export-all-symbols/verify.js @@ -9,16 +9,20 @@ console.log('exports', list); const my_exports = {}; let nexports = 0; + for (const entry of list) { - if (entry.kind !== 'function') - continue; - my_exports[entry.name] = true; - nexports += 1; + if (entry.kind == 'function'){ + nexports += 1; + } + my_exports[entry.name] = entry.kind; } -if (my_exports.foo === undefined) +if (my_exports.foo != "function") throw new Error("`foo` wasn't defined"); +if (my_exports.FOO != "global") + throw new Error("`FOO` wasn't defined"); + if (my_exports.main === undefined) { if (nexports != 1) throw new Error("should only have one function export"); diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.rs b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs similarity index 59% rename from src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.rs rename to src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs index d97b693f5209..3f4c17836c4f 100644 --- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.rs +++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs @@ -1,10 +1,10 @@ +#![feature(half_open_range_patterns)] #![feature(exclusive_range_pattern)] fn main() { match [5..4, 99..105, 43..44] { [_, 99.., _] => {}, - //~^ ERROR `X..` range patterns are not supported - //~| ERROR mismatched types + //~^ ERROR mismatched types _ => {}, } } diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr similarity index 57% rename from src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr rename to src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr index 76ae7241ff27..a6f8563a0478 100644 --- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr +++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr @@ -1,11 +1,5 @@ -error: `X..` range patterns are not supported - --> $DIR/exclusive_range_pattern_syntax_collision.rs:5:13 - | -LL | [_, 99.., _] => {}, - | ^^^^ help: try using the maximum value for the type: `99..MAX` - error[E0308]: mismatched types - --> $DIR/exclusive_range_pattern_syntax_collision.rs:5:13 + --> $DIR/exclusive_range_pattern_syntax_collision.rs:6:13 | LL | match [5..4, 99..105, 43..44] { | ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]` @@ -15,6 +9,6 @@ LL | [_, 99.., _] => {}, = note: expected struct `std::ops::Range<{integer}>` found type `{integer}` -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.rs b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs similarity index 58% rename from src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.rs rename to src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs index 09f459c9862e..dedc85491b4a 100644 --- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.rs +++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs @@ -1,10 +1,10 @@ +#![feature(half_open_range_patterns)] #![feature(exclusive_range_pattern)] fn main() { match [5..4, 99..105, 43..44] { [_, 99..] => {}, - //~^ ERROR `X..` range patterns are not supported - //~| ERROR pattern requires 2 elements but array has 3 + //~^ ERROR pattern requires 2 elements but array has 3 //~| ERROR mismatched types _ => {}, } diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr similarity index 62% rename from src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr rename to src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr index 5c96f8041feb..4e0102c930da 100644 --- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr +++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr @@ -1,17 +1,11 @@ -error: `X..` range patterns are not supported - --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:13 - | -LL | [_, 99..] => {}, - | ^^^^ help: try using the maximum value for the type: `99..MAX` - error[E0527]: pattern requires 2 elements but array has 3 - --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:9 + --> $DIR/exclusive_range_pattern_syntax_collision2.rs:6:9 | LL | [_, 99..] => {}, | ^^^^^^^^^ expected 3 elements error[E0308]: mismatched types - --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:13 + --> $DIR/exclusive_range_pattern_syntax_collision2.rs:6:13 | LL | match [5..4, 99..105, 43..44] { | ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]` @@ -21,7 +15,7 @@ LL | [_, 99..] => {}, = note: expected struct `std::ops::Range<{integer}>` found type `{integer}` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0308, E0527. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs similarity index 69% rename from src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs rename to src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs index 1557f592b2a9..6a9b562cc3a3 100644 --- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs +++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs @@ -1,10 +1,10 @@ +#![feature(half_open_range_patterns)] #![feature(exclusive_range_pattern)] fn main() { match [5..4, 99..105, 43..44] { [..9, 99..100, _] => {}, - //~^ ERROR `..X` range patterns are not supported - //~| ERROR mismatched types + //~^ ERROR mismatched types //~| ERROR mismatched types //~| ERROR mismatched types _ => {}, diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr similarity index 75% rename from src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr rename to src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr index 17e10324db18..665eef2fcb96 100644 --- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr +++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr @@ -1,11 +1,5 @@ -error: `..X` range patterns are not supported - --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:10 - | -LL | [..9, 99..100, _] => {}, - | ^^^ help: try using the minimum value for the type: `MIN..9` - error[E0308]: mismatched types - --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:12 + --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:12 | LL | match [5..4, 99..105, 43..44] { | ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]` @@ -16,7 +10,7 @@ LL | [..9, 99..100, _] => {}, found type `{integer}` error[E0308]: mismatched types - --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:15 + --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:15 | LL | match [5..4, 99..105, 43..44] { | ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]` @@ -29,7 +23,7 @@ LL | [..9, 99..100, _] => {}, found type `{integer}` error[E0308]: mismatched types - --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:19 + --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:19 | LL | match [5..4, 99..105, 43..44] { | ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]` @@ -41,6 +35,6 @@ LL | [..9, 99..100, _] => {}, = note: expected struct `std::ops::Range<{integer}>` found type `{integer}` -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs new file mode 100644 index 000000000000..4cb8230a7b62 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs @@ -0,0 +1,21 @@ +#![feature(exclusive_range_pattern)] + +fn main() {} + +#[cfg(FALSE)] +fn foo() { + if let ..=5 = 0 {} + //~^ ERROR half-open range patterns are unstable + if let ...5 = 0 {} + //~^ ERROR half-open range patterns are unstable + if let ..5 = 0 {} + //~^ ERROR half-open range patterns are unstable + if let 5.. = 0 {} + //~^ ERROR half-open range patterns are unstable + if let 5..= = 0 {} + //~^ ERROR half-open range patterns are unstable + //~| ERROR inclusive range with no end + if let 5... = 0 {} + //~^ ERROR half-open range patterns are unstable + //~| ERROR inclusive range with no end +} diff --git a/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr new file mode 100644 index 000000000000..68ba654de76d --- /dev/null +++ b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr @@ -0,0 +1,74 @@ +error[E0586]: inclusive range with no end + --> $DIR/feature-gate-half-open-range-patterns.rs:15:13 + | +LL | if let 5..= = 0 {} + | ^^^ + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error[E0586]: inclusive range with no end + --> $DIR/feature-gate-half-open-range-patterns.rs:18:13 + | +LL | if let 5... = 0 {} + | ^^^ + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error[E0658]: half-open range patterns are unstable + --> $DIR/feature-gate-half-open-range-patterns.rs:7:12 + | +LL | if let ..=5 = 0 {} + | ^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/67264 + = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable + +error[E0658]: half-open range patterns are unstable + --> $DIR/feature-gate-half-open-range-patterns.rs:9:12 + | +LL | if let ...5 = 0 {} + | ^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/67264 + = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable + +error[E0658]: half-open range patterns are unstable + --> $DIR/feature-gate-half-open-range-patterns.rs:11:12 + | +LL | if let ..5 = 0 {} + | ^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/67264 + = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable + +error[E0658]: half-open range patterns are unstable + --> $DIR/feature-gate-half-open-range-patterns.rs:13:12 + | +LL | if let 5.. = 0 {} + | ^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/67264 + = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable + +error[E0658]: half-open range patterns are unstable + --> $DIR/feature-gate-half-open-range-patterns.rs:15:12 + | +LL | if let 5..= = 0 {} + | ^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/67264 + = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable + +error[E0658]: half-open range patterns are unstable + --> $DIR/feature-gate-half-open-range-patterns.rs:18:12 + | +LL | if let 5... = 0 {} + | ^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/67264 + = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0586, E0658. +For more information about an error, try `rustc --explain E0586`. diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs new file mode 100644 index 000000000000..7cddf5f652a3 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs @@ -0,0 +1,8 @@ +#![feature(half_open_range_patterns)] +#![feature(exclusive_range_pattern)] + +fn main() { + let "a".. = "a"; //~ ERROR only char and numeric types are allowed in range patterns + let .."a" = "a"; //~ ERROR only char and numeric types are allowed in range patterns + let ..="a" = "a"; //~ ERROR only char and numeric types are allowed in range patterns +} diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr new file mode 100644 index 000000000000..68ca3637150d --- /dev/null +++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr @@ -0,0 +1,21 @@ +error[E0029]: only char and numeric types are allowed in range patterns + --> $DIR/half-open-range-pats-bad-types.rs:5:9 + | +LL | let "a".. = "a"; + | ^^^ this is of type `&'static str` but it should be `char` or numeric + +error[E0029]: only char and numeric types are allowed in range patterns + --> $DIR/half-open-range-pats-bad-types.rs:6:11 + | +LL | let .."a" = "a"; + | ^^^ this is of type `&'static str` but it should be `char` or numeric + +error[E0029]: only char and numeric types are allowed in range patterns + --> $DIR/half-open-range-pats-bad-types.rs:7:12 + | +LL | let ..="a" = "a"; + | ^^^ this is of type `&'static str` but it should be `char` or numeric + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0029`. diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs new file mode 100644 index 000000000000..b135891d0b82 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs @@ -0,0 +1,168 @@ +// Test various non-exhaustive matches for `X..`, `..=X` and `..X` ranges. + +#![feature(half_open_range_patterns)] +#![feature(exclusive_range_pattern)] +#![allow(illegal_floating_point_literal_pattern)] + +fn main() {} + +macro_rules! m { + ($s:expr, $($t:tt)+) => { + match $s { $($t)+ => {} } + } +} + +fn floats() { + m!(0f32, core::f32::NEG_INFINITY..); //~ ERROR non-exhaustive patterns: `_` not covered + m!(0f32, ..core::f32::INFINITY); //~ ERROR non-exhaustive patterns: `_` not covered +} + +fn khar() { + const ALMOST_MAX: char = '\u{10fffe}'; + const ALMOST_MIN: char = '\u{1}'; + const VAL: char = 'a'; + const VAL_1: char = 'b'; + const VAL_2: char = 'c'; + m!('a', ..core::char::MAX); //~ ERROR non-exhaustive patterns + m!('a', ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!('a', ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!('a', ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!('a', ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!('a', ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns +} + +mod unsigned { + fn u8() { + const ALMOST_MAX: u8 = core::u8::MAX - 1; + const ALMOST_MIN: u8 = core::u8::MIN + 1; + const VAL: u8 = 42; + const VAL_1: u8 = VAL + 1; + const VAL_2: u8 = VAL + 2; + m!(0, ..core::u8::MAX); //~ ERROR non-exhaustive patterns + m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns + } + fn u16() { + const ALMOST_MAX: u16 = core::u16::MAX - 1; + const ALMOST_MIN: u16 = core::u16::MIN + 1; + const VAL: u16 = 42; + const VAL_1: u16 = VAL + 1; + const VAL_2: u16 = VAL + 2; + m!(0, ..core::u16::MAX); //~ ERROR non-exhaustive patterns + m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns + } + fn u32() { + const ALMOST_MAX: u32 = core::u32::MAX - 1; + const ALMOST_MIN: u32 = core::u32::MIN + 1; + const VAL: u32 = 42; + const VAL_1: u32 = VAL + 1; + const VAL_2: u32 = VAL + 2; + m!(0, ..core::u32::MAX); //~ ERROR non-exhaustive patterns + m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns + } + fn u64() { + const ALMOST_MAX: u64 = core::u64::MAX - 1; + const ALMOST_MIN: u64 = core::u64::MIN + 1; + const VAL: u64 = 42; + const VAL_1: u64 = VAL + 1; + const VAL_2: u64 = VAL + 2; + m!(0, ..core::u64::MAX); //~ ERROR non-exhaustive patterns + m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns + } + fn u128() { + const ALMOST_MAX: u128 = core::u128::MAX - 1; + const ALMOST_MIN: u128 = core::u128::MIN + 1; + const VAL: u128 = 42; + const VAL_1: u128 = VAL + 1; + const VAL_2: u128 = VAL + 2; + m!(0, ..core::u128::MAX); //~ ERROR non-exhaustive patterns + m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns + } +} + +mod signed { + fn i8() { + const ALMOST_MAX: i8 = core::i8::MAX - 1; + const ALMOST_MIN: i8 = core::i8::MIN + 1; + const VAL: i8 = 42; + const VAL_1: i8 = VAL + 1; + const VAL_2: i8 = VAL + 2; + m!(0, ..core::i8::MAX); //~ ERROR non-exhaustive patterns + m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns + } + fn i16() { + const ALMOST_MAX: i16 = core::i16::MAX - 1; + const ALMOST_MIN: i16 = core::i16::MIN + 1; + const VAL: i16 = 42; + const VAL_1: i16 = VAL + 1; + const VAL_2: i16 = VAL + 2; + m!(0, ..core::i16::MAX); //~ ERROR non-exhaustive patterns + m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns + } + fn i32() { + const ALMOST_MAX: i32 = core::i32::MAX - 1; + const ALMOST_MIN: i32 = core::i32::MIN + 1; + const VAL: i32 = 42; + const VAL_1: i32 = VAL + 1; + const VAL_2: i32 = VAL + 2; + m!(0, ..core::i32::MAX); //~ ERROR non-exhaustive patterns + m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns + } + fn i64() { + const ALMOST_MAX: i64 = core::i64::MAX - 1; + const ALMOST_MIN: i64 = core::i64::MIN + 1; + const VAL: i64 = 42; + const VAL_1: i64 = VAL + 1; + const VAL_2: i64 = VAL + 2; + m!(0, ..core::i64::MAX); //~ ERROR non-exhaustive patterns + m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns + } + fn i128() { + const ALMOST_MAX: i128 = core::i128::MAX - 1; + const ALMOST_MIN: i128 = core::i128::MIN + 1; + const VAL: i128 = 42; + const VAL_1: i128 = VAL + 1; + const VAL_2: i128 = VAL + 2; + m!(0, ..core::i128::MAX); //~ ERROR non-exhaustive patterns + m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns + } +} diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr new file mode 100644 index 000000000000..26d0cf9e9ecb --- /dev/null +++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr @@ -0,0 +1,547 @@ +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:16:8 + | +LL | m!(0f32, core::f32::NEG_INFINITY..); + | ^^^^ pattern `_` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:17:8 + | +LL | m!(0f32, ..core::f32::INFINITY); + | ^^^^ pattern `_` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:26:8 + | +LL | m!('a', ..core::char::MAX); + | ^^^ pattern `'\u{10ffff}'` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `'\u{10fffe}'..='\u{10ffff}'` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:27:8 + | +LL | m!('a', ..ALMOST_MAX); + | ^^^ pattern `'\u{10fffe}'..='\u{10ffff}'` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `'\u{0}'` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:28:8 + | +LL | m!('a', ALMOST_MIN..); + | ^^^ pattern `'\u{0}'` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:29:8 + | +LL | m!('a', ..=ALMOST_MAX); + | ^^^ pattern `'\u{10ffff}'` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `'b'` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:30:8 + | +LL | m!('a', ..=VAL | VAL_2..); + | ^^^ pattern `'b'` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `'b'` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:31:8 + | +LL | m!('a', ..VAL_1 | VAL_2..); + | ^^^ pattern `'b'` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::u8::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:41:12 + | +LL | m!(0, ..core::u8::MAX); + | ^ pattern `std::u8::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `254u8..=std::u8::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:42:12 + | +LL | m!(0, ..ALMOST_MAX); + | ^ pattern `254u8..=std::u8::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `0u8` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:43:12 + | +LL | m!(0, ALMOST_MIN..); + | ^ pattern `0u8` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::u8::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:44:12 + | +LL | m!(0, ..=ALMOST_MAX); + | ^ pattern `std::u8::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `43u8` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:45:12 + | +LL | m!(0, ..=VAL | VAL_2..); + | ^ pattern `43u8` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `43u8` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:46:12 + | +LL | m!(0, ..VAL_1 | VAL_2..); + | ^ pattern `43u8` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::u16::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:54:12 + | +LL | m!(0, ..core::u16::MAX); + | ^ pattern `std::u16::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `65534u16..=std::u16::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:55:12 + | +LL | m!(0, ..ALMOST_MAX); + | ^ pattern `65534u16..=std::u16::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `0u16` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:56:12 + | +LL | m!(0, ALMOST_MIN..); + | ^ pattern `0u16` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::u16::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:57:12 + | +LL | m!(0, ..=ALMOST_MAX); + | ^ pattern `std::u16::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `43u16` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:58:12 + | +LL | m!(0, ..=VAL | VAL_2..); + | ^ pattern `43u16` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `43u16` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:59:12 + | +LL | m!(0, ..VAL_1 | VAL_2..); + | ^ pattern `43u16` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::u32::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:67:12 + | +LL | m!(0, ..core::u32::MAX); + | ^ pattern `std::u32::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `4294967294u32..=std::u32::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:68:12 + | +LL | m!(0, ..ALMOST_MAX); + | ^ pattern `4294967294u32..=std::u32::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `0u32` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:69:12 + | +LL | m!(0, ALMOST_MIN..); + | ^ pattern `0u32` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::u32::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:70:12 + | +LL | m!(0, ..=ALMOST_MAX); + | ^ pattern `std::u32::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `43u32` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:71:12 + | +LL | m!(0, ..=VAL | VAL_2..); + | ^ pattern `43u32` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `43u32` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:72:12 + | +LL | m!(0, ..VAL_1 | VAL_2..); + | ^ pattern `43u32` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::u64::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:80:12 + | +LL | m!(0, ..core::u64::MAX); + | ^ pattern `std::u64::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `18446744073709551614u64..=std::u64::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:81:12 + | +LL | m!(0, ..ALMOST_MAX); + | ^ pattern `18446744073709551614u64..=std::u64::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `0u64` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:82:12 + | +LL | m!(0, ALMOST_MIN..); + | ^ pattern `0u64` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::u64::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:83:12 + | +LL | m!(0, ..=ALMOST_MAX); + | ^ pattern `std::u64::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `43u64` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:84:12 + | +LL | m!(0, ..=VAL | VAL_2..); + | ^ pattern `43u64` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `43u64` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:85:12 + | +LL | m!(0, ..VAL_1 | VAL_2..); + | ^ pattern `43u64` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::u128::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12 + | +LL | m!(0, ..core::u128::MAX); + | ^ pattern `std::u128::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211454u128..=std::u128::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12 + | +LL | m!(0, ..ALMOST_MAX); + | ^ pattern `340282366920938463463374607431768211454u128..=std::u128::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `0u128` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:95:12 + | +LL | m!(0, ALMOST_MIN..); + | ^ pattern `0u128` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::u128::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:96:12 + | +LL | m!(0, ..=ALMOST_MAX); + | ^ pattern `std::u128::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `43u128` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:97:12 + | +LL | m!(0, ..=VAL | VAL_2..); + | ^ pattern `43u128` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `43u128` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:98:12 + | +LL | m!(0, ..VAL_1 | VAL_2..); + | ^ pattern `43u128` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::i8::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:109:12 + | +LL | m!(0, ..core::i8::MAX); + | ^ pattern `std::i8::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `126i8..=std::i8::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:110:12 + | +LL | m!(0, ..ALMOST_MAX); + | ^ pattern `126i8..=std::i8::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::i8::MIN` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:111:12 + | +LL | m!(0, ALMOST_MIN..); + | ^ pattern `std::i8::MIN` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::i8::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:112:12 + | +LL | m!(0, ..=ALMOST_MAX); + | ^ pattern `std::i8::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `43i8` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:113:12 + | +LL | m!(0, ..=VAL | VAL_2..); + | ^ pattern `43i8` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `43i8` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:114:12 + | +LL | m!(0, ..VAL_1 | VAL_2..); + | ^ pattern `43i8` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::i16::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:122:12 + | +LL | m!(0, ..core::i16::MAX); + | ^ pattern `std::i16::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `32766i16..=std::i16::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:123:12 + | +LL | m!(0, ..ALMOST_MAX); + | ^ pattern `32766i16..=std::i16::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::i16::MIN` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:124:12 + | +LL | m!(0, ALMOST_MIN..); + | ^ pattern `std::i16::MIN` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::i16::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:125:12 + | +LL | m!(0, ..=ALMOST_MAX); + | ^ pattern `std::i16::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `43i16` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:126:12 + | +LL | m!(0, ..=VAL | VAL_2..); + | ^ pattern `43i16` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `43i16` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:127:12 + | +LL | m!(0, ..VAL_1 | VAL_2..); + | ^ pattern `43i16` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::i32::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:135:12 + | +LL | m!(0, ..core::i32::MAX); + | ^ pattern `std::i32::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `2147483646i32..=std::i32::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:136:12 + | +LL | m!(0, ..ALMOST_MAX); + | ^ pattern `2147483646i32..=std::i32::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::i32::MIN` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:137:12 + | +LL | m!(0, ALMOST_MIN..); + | ^ pattern `std::i32::MIN` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::i32::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:138:12 + | +LL | m!(0, ..=ALMOST_MAX); + | ^ pattern `std::i32::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `43i32` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:139:12 + | +LL | m!(0, ..=VAL | VAL_2..); + | ^ pattern `43i32` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `43i32` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:140:12 + | +LL | m!(0, ..VAL_1 | VAL_2..); + | ^ pattern `43i32` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::i64::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:148:12 + | +LL | m!(0, ..core::i64::MAX); + | ^ pattern `std::i64::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `9223372036854775806i64..=std::i64::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:149:12 + | +LL | m!(0, ..ALMOST_MAX); + | ^ pattern `9223372036854775806i64..=std::i64::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::i64::MIN` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:150:12 + | +LL | m!(0, ALMOST_MIN..); + | ^ pattern `std::i64::MIN` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::i64::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:151:12 + | +LL | m!(0, ..=ALMOST_MAX); + | ^ pattern `std::i64::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `43i64` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:152:12 + | +LL | m!(0, ..=VAL | VAL_2..); + | ^ pattern `43i64` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `43i64` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:153:12 + | +LL | m!(0, ..VAL_1 | VAL_2..); + | ^ pattern `43i64` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::i128::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12 + | +LL | m!(0, ..core::i128::MAX); + | ^ pattern `std::i128::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `170141183460469231731687303715884105726i128..=std::i128::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12 + | +LL | m!(0, ..ALMOST_MAX); + | ^ pattern `170141183460469231731687303715884105726i128..=std::i128::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::i128::MIN` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:163:12 + | +LL | m!(0, ALMOST_MIN..); + | ^ pattern `std::i128::MIN` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `std::i128::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:164:12 + | +LL | m!(0, ..=ALMOST_MAX); + | ^ pattern `std::i128::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `43i128` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:165:12 + | +LL | m!(0, ..=VAL | VAL_2..); + | ^ pattern `43i128` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `43i128` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:166:12 + | +LL | m!(0, ..VAL_1 | VAL_2..); + | ^ pattern `43i128` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to 68 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs new file mode 100644 index 000000000000..efac0df2a430 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs @@ -0,0 +1,49 @@ +// check-pass + +// Test various exhaustive matches for `X..`, `..=X` and `..X` ranges. + +#![feature(half_open_range_patterns)] +#![feature(exclusive_range_pattern)] + +fn main() {} + +macro_rules! m { + ($s:expr, $($t:tt)+) => { + match $s { $($t)+ => {} } + } +} + +macro_rules! test_int { + ($s:expr, $min:path, $max:path) => { + m!($s, $min..); + m!($s, $min..5 | 5..); + m!($s, ..5 | 5..); + m!($s, ..=4 | 5..); + m!($s, ..=$max); + m!($s, ..$max | $max); + m!(($s, true), (..5, true) | (5.., true) | ($min.., false)); + } +} + +fn unsigned_int() { + test_int!(0u8, core::u8::MIN, core::u8::MAX); + test_int!(0u16, core::u16::MIN, core::u16::MAX); + test_int!(0u32, core::u32::MIN, core::u32::MAX); + test_int!(0u64, core::u64::MIN, core::u64::MAX); + test_int!(0u128, core::u128::MIN, core::u128::MAX); +} + +fn signed_int() { + test_int!(0i8, core::i8::MIN, core::i8::MAX); + test_int!(0i16, core::i16::MIN, core::i16::MAX); + test_int!(0i32, core::i32::MIN, core::i32::MAX); + test_int!(0i64, core::i64::MIN, core::i64::MAX); + test_int!(0i128, core::i128::MIN, core::i128::MAX); +} + +fn khar() { + m!('a', ..=core::char::MAX); + m!('a', '\u{0}'..); + m!('a', ..='\u{D7FF}' | '\u{E000}'..); + m!('a', ..'\u{D7FF}' | '\u{D7FF}' | '\u{E000}'..); +} diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.rs new file mode 100644 index 000000000000..495e2ff899ec --- /dev/null +++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.rs @@ -0,0 +1,28 @@ +#![feature(half_open_range_patterns)] +#![feature(exclusive_range_pattern)] +#![allow(illegal_floating_point_literal_pattern)] + +macro_rules! m { + ($s:expr, $($t:tt)+) => { + match $s { $($t)+ => {} } + } +} + +fn main() { + m!(0, ..core::u8::MIN); //~ ERROR lower range bound must be less than upper + m!(0, ..core::u16::MIN); //~ ERROR lower range bound must be less than upper + m!(0, ..core::u32::MIN); //~ ERROR lower range bound must be less than upper + m!(0, ..core::u64::MIN); //~ ERROR lower range bound must be less than upper + m!(0, ..core::u128::MIN); //~ ERROR lower range bound must be less than upper + + m!(0, ..core::i8::MIN); //~ ERROR lower range bound must be less than upper + m!(0, ..core::i16::MIN); //~ ERROR lower range bound must be less than upper + m!(0, ..core::i32::MIN); //~ ERROR lower range bound must be less than upper + m!(0, ..core::i64::MIN); //~ ERROR lower range bound must be less than upper + m!(0, ..core::i128::MIN); //~ ERROR lower range bound must be less than upper + + m!(0f32, ..core::f32::NEG_INFINITY); //~ ERROR lower range bound must be less than upper + m!(0f64, ..core::f64::NEG_INFINITY); //~ ERROR lower range bound must be less than upper + + m!('a', ..'\u{0}'); //~ ERROR lower range bound must be less than upper +} diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.stderr new file mode 100644 index 000000000000..0893279d304a --- /dev/null +++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.stderr @@ -0,0 +1,81 @@ +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-hair-lower-empty.rs:12:11 + | +LL | m!(0, ..core::u8::MIN); + | ^^^^^^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-hair-lower-empty.rs:13:11 + | +LL | m!(0, ..core::u16::MIN); + | ^^^^^^^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-hair-lower-empty.rs:14:11 + | +LL | m!(0, ..core::u32::MIN); + | ^^^^^^^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-hair-lower-empty.rs:15:11 + | +LL | m!(0, ..core::u64::MIN); + | ^^^^^^^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-hair-lower-empty.rs:16:11 + | +LL | m!(0, ..core::u128::MIN); + | ^^^^^^^^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-hair-lower-empty.rs:18:11 + | +LL | m!(0, ..core::i8::MIN); + | ^^^^^^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-hair-lower-empty.rs:19:11 + | +LL | m!(0, ..core::i16::MIN); + | ^^^^^^^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-hair-lower-empty.rs:20:11 + | +LL | m!(0, ..core::i32::MIN); + | ^^^^^^^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-hair-lower-empty.rs:21:11 + | +LL | m!(0, ..core::i64::MIN); + | ^^^^^^^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-hair-lower-empty.rs:22:11 + | +LL | m!(0, ..core::i128::MIN); + | ^^^^^^^^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-hair-lower-empty.rs:24:14 + | +LL | m!(0f32, ..core::f32::NEG_INFINITY); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-hair-lower-empty.rs:25:14 + | +LL | m!(0f64, ..core::f64::NEG_INFINITY); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-hair-lower-empty.rs:27:13 + | +LL | m!('a', ..'\u{0}'); + | ^^^^^^^^^ + +error: aborting due to 13 previous errors + +For more information about this error, try `rustc --explain E0579`. diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs new file mode 100644 index 000000000000..03166e367557 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs @@ -0,0 +1,15 @@ +// Test `X...` and `X..=` range patterns not being allowed syntactically. +// FIXME(Centril): perhaps these should be semantic restrictions. + +#![feature(half_open_range_patterns)] + +fn main() {} + +#[cfg(FALSE)] +fn foo() { + if let 0... = 1 {} //~ ERROR inclusive range with no end + if let 0..= = 1 {} //~ ERROR inclusive range with no end + const X: u8 = 0; + if let X... = 1 {} //~ ERROR inclusive range with no end + if let X..= = 1 {} //~ ERROR inclusive range with no end +} diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr new file mode 100644 index 000000000000..2b4d95f68428 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr @@ -0,0 +1,35 @@ +error[E0586]: inclusive range with no end + --> $DIR/half-open-range-pats-inclusive-no-end.rs:10:13 + | +LL | if let 0... = 1 {} + | ^^^ + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error[E0586]: inclusive range with no end + --> $DIR/half-open-range-pats-inclusive-no-end.rs:11:13 + | +LL | if let 0..= = 1 {} + | ^^^ + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error[E0586]: inclusive range with no end + --> $DIR/half-open-range-pats-inclusive-no-end.rs:13:13 + | +LL | if let X... = 1 {} + | ^^^ + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error[E0586]: inclusive range with no end + --> $DIR/half-open-range-pats-inclusive-no-end.rs:14:13 + | +LL | if let X..= = 1 {} + | ^^^ + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0586`. diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs new file mode 100644 index 000000000000..e9a5361e63d2 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs @@ -0,0 +1,24 @@ +#![feature(half_open_range_patterns)] + +fn main() {} + +#[cfg(FALSE)] +fn syntax() { + match &0 { + &0.. | _ => {} + //~^ ERROR the range pattern here has ambiguous interpretation + &0..= | _ => {} + //~^ ERROR the range pattern here has ambiguous interpretation + //~| ERROR inclusive range with no end + &0... | _ => {} + //~^ ERROR inclusive range with no end + } + + match &0 { + &..0 | _ => {} + //~^ ERROR the range pattern here has ambiguous interpretation + &..=0 | _ => {} + //~^ ERROR the range pattern here has ambiguous interpretation + &...0 | _ => {} + } +} diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr new file mode 100644 index 000000000000..5d3aded02222 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr @@ -0,0 +1,43 @@ +error: the range pattern here has ambiguous interpretation + --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:8:10 + | +LL | &0.. | _ => {} + | ^^^ help: add parentheses to clarify the precedence: `(0 ..)` + +error[E0586]: inclusive range with no end + --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:10:11 + | +LL | &0..= | _ => {} + | ^^^ + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error: the range pattern here has ambiguous interpretation + --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:10:10 + | +LL | &0..= | _ => {} + | ^^^^ help: add parentheses to clarify the precedence: `(0 ..=)` + +error[E0586]: inclusive range with no end + --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:13:11 + | +LL | &0... | _ => {} + | ^^^ + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error: the range pattern here has ambiguous interpretation + --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:18:10 + | +LL | &..0 | _ => {} + | ^^^ help: add parentheses to clarify the precedence: `(..0)` + +error: the range pattern here has ambiguous interpretation + --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:20:10 + | +LL | &..=0 | _ => {} + | ^^^^ help: add parentheses to clarify the precedence: `(..=0)` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0586`. diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-semantics.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-semantics.rs new file mode 100644 index 000000000000..416c59af3fd3 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-semantics.rs @@ -0,0 +1,160 @@ +// run-pass + +// Test half-open range patterns against their expression equivalents +// via `.contains(...)` and make sure the dynamic semantics match. + +#![feature(half_open_range_patterns)] +#![feature(exclusive_range_pattern)] +#![allow(illegal_floating_point_literal_pattern)] +#![allow(unreachable_patterns)] + +macro_rules! yes { + ($scrutinee:expr, $($t:tt)+) => { + { + let m = match $scrutinee { $($t)+ => true, _ => false, }; + let c = ($($t)+).contains(&$scrutinee); + assert_eq!(m, c); + m + } + } +} + +fn range_to_inclusive() { + // `..=X` (`RangeToInclusive`-equivalent): + //--------------------------------------- + + // u8; `..=X` + assert!(yes!(core::u8::MIN, ..=core::u8::MIN)); + assert!(yes!(core::u8::MIN, ..=5)); + assert!(yes!(5u8, ..=5)); + assert!(!yes!(6u8, ..=5)); + + // i16; `..=X` + assert!(yes!(core::i16::MIN, ..=core::i16::MIN)); + assert!(yes!(core::i16::MIN, ..=0)); + assert!(yes!(core::i16::MIN, ..=-5)); + assert!(yes!(-5, ..=-5)); + assert!(!yes!(-4, ..=-5)); + + // char; `..=X` + assert!(yes!('\u{0}', ..='\u{0}')); + assert!(yes!('\u{0}', ..='a')); + assert!(yes!('a', ..='a')); + assert!(!yes!('b', ..='a')); + + // f32; `..=X` + assert!(yes!(core::f32::NEG_INFINITY, ..=core::f32::NEG_INFINITY)); + assert!(yes!(core::f32::NEG_INFINITY, ..=1.0f32)); + assert!(yes!(1.5f32, ..=1.5f32)); + assert!(!yes!(1.6f32, ..=-1.5f32)); + + // f64; `..=X` + assert!(yes!(core::f64::NEG_INFINITY, ..=core::f64::NEG_INFINITY)); + assert!(yes!(core::f64::NEG_INFINITY, ..=1.0f64)); + assert!(yes!(1.5f64, ..=1.5f64)); + assert!(!yes!(1.6f64, ..=-1.5f64)); +} + +fn range_to() { + // `..X` (`RangeTo`-equivalent): + //----------------------------- + + // u8; `..X` + assert!(yes!(0u8, ..1)); + assert!(yes!(0u8, ..5)); + assert!(!yes!(5u8, ..5)); + assert!(!yes!(6u8, ..5)); + + // u8; `..X` + const NU8: u8 = core::u8::MIN + 1; + assert!(yes!(core::u8::MIN, ..NU8)); + assert!(yes!(0u8, ..5)); + assert!(!yes!(5u8, ..5)); + assert!(!yes!(6u8, ..5)); + + // i16; `..X` + const NI16: i16 = core::i16::MIN + 1; + assert!(yes!(core::i16::MIN, ..NI16)); + assert!(yes!(core::i16::MIN, ..5)); + assert!(yes!(-6, ..-5)); + assert!(!yes!(-5, ..-5)); + + // char; `..X` + assert!(yes!('\u{0}', ..'\u{1}')); + assert!(yes!('\u{0}', ..'a')); + assert!(yes!('a', ..'b')); + assert!(!yes!('a', ..'a')); + assert!(!yes!('b', ..'a')); + + // f32; `..X` + assert!(yes!(core::f32::NEG_INFINITY, ..1.0f32)); + assert!(!yes!(1.5f32, ..1.5f32)); + const E32: f32 = 1.5f32 + core::f32::EPSILON; + assert!(yes!(1.5f32, ..E32)); + assert!(!yes!(1.6f32, ..1.5f32)); + + // f64; `..X` + assert!(yes!(core::f64::NEG_INFINITY, ..1.0f64)); + assert!(!yes!(1.5f64, ..1.5f64)); + const E64: f64 = 1.5f64 + core::f64::EPSILON; + assert!(yes!(1.5f64, ..E64)); + assert!(!yes!(1.6f64, ..1.5f64)); +} + +fn range_from() { + // `X..` (`RangeFrom`-equivalent): + //-------------------------------- + + // u8; `X..` + assert!(yes!(core::u8::MIN, core::u8::MIN..)); + assert!(yes!(core::u8::MAX, core::u8::MIN..)); + assert!(!yes!(core::u8::MIN, 1..)); + assert!(!yes!(4, 5..)); + assert!(yes!(5, 5..)); + assert!(yes!(6, 5..)); + assert!(yes!(core::u8::MAX, core::u8::MAX..)); + + // i16; `X..` + assert!(yes!(core::i16::MIN, core::i16::MIN..)); + assert!(yes!(core::i16::MAX, core::i16::MIN..)); + const NI16: i16 = core::i16::MIN + 1; + assert!(!yes!(core::i16::MIN, NI16..)); + assert!(!yes!(-4, 5..)); + assert!(yes!(-4, -4..)); + assert!(yes!(-3, -4..)); + assert!(yes!(core::i16::MAX, core::i16::MAX..)); + + // char; `X..` + assert!(yes!('\u{0}', '\u{0}'..)); + assert!(yes!(core::char::MAX, '\u{0}'..)); + assert!(yes!('a', 'a'..)); + assert!(yes!('b', 'a'..)); + assert!(!yes!('a', 'b'..)); + assert!(yes!(core::char::MAX, core::char::MAX..)); + + // f32; `X..` + assert!(yes!(core::f32::NEG_INFINITY, core::f32::NEG_INFINITY..)); + assert!(yes!(core::f32::INFINITY, core::f32::NEG_INFINITY..)); + assert!(!yes!(core::f32::NEG_INFINITY, 1.0f32..)); + assert!(yes!(core::f32::INFINITY, 1.0f32..)); + assert!(!yes!(1.0f32 - core::f32::EPSILON, 1.0f32..)); + assert!(yes!(1.0f32, 1.0f32..)); + assert!(yes!(core::f32::INFINITY, 1.0f32..)); + assert!(yes!(core::f32::INFINITY, core::f32::INFINITY..)); + + // f64; `X..` + assert!(yes!(core::f64::NEG_INFINITY, core::f64::NEG_INFINITY..)); + assert!(yes!(core::f64::INFINITY, core::f64::NEG_INFINITY..)); + assert!(!yes!(core::f64::NEG_INFINITY, 1.0f64..)); + assert!(yes!(core::f64::INFINITY, 1.0f64..)); + assert!(!yes!(1.0f64 - core::f64::EPSILON, 1.0f64..)); + assert!(yes!(1.0f64, 1.0f64..)); + assert!(yes!(core::f64::INFINITY, 1.0f64..)); + assert!(yes!(core::f64::INFINITY, core::f64::INFINITY..)); +} + +fn main() { + range_to_inclusive(); + range_to(); + range_from(); +} diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs new file mode 100644 index 000000000000..a663acd2d191 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs @@ -0,0 +1,32 @@ +// check-pass + +// Test the parsing of half-open ranges. + +#![feature(exclusive_range_pattern)] +#![feature(half_open_range_patterns)] + +fn main() {} + +#[cfg(FALSE)] +fn syntax() { + match scrutinee { + X.. | 0.. | 'a'.. | 0.0f32.. => {} + ..=X | ...X | ..X => {} + ..=0 | ...0 | ..0 => {} + ..='a' | ...'a' | ..'a' => {} + ..=0.0f32 | ...0.0f32 | ..0.0f32 => {} + } + + macro_rules! mac { + ($e:expr) => { + let ..$e; + let ...$e; + let ..=$e; + let $e..; + let $e...; + let $e..=; + } + } + + mac!(0); +} diff --git a/src/test/ui/half-open-range-patterns/pat-tuple-4.rs b/src/test/ui/half-open-range-patterns/pat-tuple-4.rs new file mode 100644 index 000000000000..bd795368205f --- /dev/null +++ b/src/test/ui/half-open-range-patterns/pat-tuple-4.rs @@ -0,0 +1,13 @@ +// check-pass + +#![feature(half_open_range_patterns)] +#![feature(exclusive_range_pattern)] + +fn main() { + const PAT: u8 = 1; + + match 0 { + (.. PAT) => {} + _ => {} + } +} diff --git a/src/test/ui/half-open-range-patterns/pat-tuple-5.rs b/src/test/ui/half-open-range-patterns/pat-tuple-5.rs new file mode 100644 index 000000000000..613d907cfe32 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/pat-tuple-5.rs @@ -0,0 +1,10 @@ +#![feature(half_open_range_patterns)] +#![feature(exclusive_range_pattern)] + +fn main() { + const PAT: u8 = 1; + + match (0, 1) { + (PAT ..) => {} //~ ERROR mismatched types + } +} diff --git a/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr b/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr new file mode 100644 index 000000000000..307ad711b74d --- /dev/null +++ b/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/pat-tuple-5.rs:8:10 + | +LL | match (0, 1) { + | ------ this expression has type `({integer}, {integer})` +LL | (PAT ..) => {} + | ^^^ expected tuple, found `u8` + | + = note: expected tuple `({integer}, {integer})` + found type `u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-41255.rs b/src/test/ui/issues/issue-41255.rs index 60fdf7c3e8a4..609a2520bcb7 100644 --- a/src/test/ui/issues/issue-41255.rs +++ b/src/test/ui/issues/issue-41255.rs @@ -1,6 +1,7 @@ // Matching against float literals should result in a linter error #![feature(exclusive_range_pattern)] +#![feature(half_open_range_patterns)] #![allow(unused)] #![forbid(illegal_floating_point_literal_pattern)] @@ -23,6 +24,16 @@ fn main() { //~| WARNING hard error //~| ERROR floating-point types cannot be used in patterns //~| WARNING hard error + + ..71.0 => {} + //~^ ERROR floating-point types cannot be used in patterns + //~| WARNING hard error + ..=72.0 => {} + //~^ ERROR floating-point types cannot be used in patterns + //~| WARNING hard error + 71.0.. => {} + //~^ ERROR floating-point types cannot be used in patterns + //~| WARNING hard error _ => {}, }; let y = 5.0; diff --git a/src/test/ui/issues/issue-41255.stderr b/src/test/ui/issues/issue-41255.stderr index c334742cfc4a..034e11d80c43 100644 --- a/src/test/ui/issues/issue-41255.stderr +++ b/src/test/ui/issues/issue-41255.stderr @@ -1,11 +1,11 @@ error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:10:9 + --> $DIR/issue-41255.rs:11:9 | LL | 5.0 => {}, | ^^^ | note: lint level defined here - --> $DIR/issue-41255.rs:5:11 + --> $DIR/issue-41255.rs:6:11 | LL | #![forbid(illegal_floating_point_literal_pattern)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL | #![forbid(illegal_floating_point_literal_pattern)] = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:14:9 + --> $DIR/issue-41255.rs:15:9 | LL | 5.0f32 => {}, | ^^^^^^ @@ -22,7 +22,7 @@ LL | 5.0f32 => {}, = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:16:10 + --> $DIR/issue-41255.rs:17:10 | LL | -5.0 => {}, | ^^^ @@ -31,7 +31,7 @@ LL | -5.0 => {}, = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:18:9 + --> $DIR/issue-41255.rs:19:9 | LL | 1.0 .. 33.0 => {}, | ^^^ @@ -40,7 +40,7 @@ LL | 1.0 .. 33.0 => {}, = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:18:16 + --> $DIR/issue-41255.rs:19:16 | LL | 1.0 .. 33.0 => {}, | ^^^^ @@ -49,7 +49,7 @@ LL | 1.0 .. 33.0 => {}, = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:22:9 + --> $DIR/issue-41255.rs:23:9 | LL | 39.0 ..= 70.0 => {}, | ^^^^ @@ -58,7 +58,7 @@ LL | 39.0 ..= 70.0 => {}, = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:22:18 + --> $DIR/issue-41255.rs:23:18 | LL | 39.0 ..= 70.0 => {}, | ^^^^ @@ -67,7 +67,34 @@ LL | 39.0 ..= 70.0 => {}, = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:31:10 + --> $DIR/issue-41255.rs:28:11 + | +LL | ..71.0 => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:31:12 + | +LL | ..=72.0 => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:34:9 + | +LL | 71.0.. => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:42:10 | LL | (3.14, 1) => {}, | ^^^^ @@ -76,7 +103,7 @@ LL | (3.14, 1) => {}, = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:38:18 + --> $DIR/issue-41255.rs:49:18 | LL | Foo { x: 2.0 } => {}, | ^^^ @@ -85,7 +112,7 @@ LL | Foo { x: 2.0 } => {}, = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:10:9 + --> $DIR/issue-41255.rs:11:9 | LL | 5.0 => {}, | ^^^ @@ -93,5 +120,5 @@ LL | 5.0 => {}, = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #41620 -error: aborting due to 10 previous errors +error: aborting due to 13 previous errors diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.rs b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs index f6d2bee0e156..118bff8144c7 100644 --- a/src/test/ui/parser/attr-stmt-expr-attr-bad.rs +++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs @@ -1,3 +1,5 @@ +#![feature(half_open_range_patterns)] + fn main() {} #[cfg(FALSE)] fn e() { let _ = box #![attr] 0; } @@ -90,15 +92,15 @@ fn main() {} // note: requires parens in patterns to allow disambiguation #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } -//~^ ERROR `X..=` range patterns are not supported +//~^ ERROR inclusive range with no end //~| ERROR expected one of `=>`, `if`, or `|`, found `#` #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } -//~^ ERROR `X..=` range patterns are not supported +//~^ ERROR inclusive range with no end //~| ERROR expected one of `=>`, `if`, or `|`, found `#` #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } } //~^ ERROR unexpected token: `#` #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } -//~^ ERROR `X..=` range patterns are not supported +//~^ ERROR inclusive range with no end //~| ERROR expected one of `=>`, `if`, or `|`, found `#` #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); } diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr index 0123006418a3..654b49ab6202 100644 --- a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr +++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr @@ -1,5 +1,5 @@ error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:3:36 + --> $DIR/attr-stmt-expr-attr-bad.rs:5:36 | LL | #[cfg(FALSE)] fn e() { let _ = box #![attr] 0; } | ^^^^^^^^ @@ -7,19 +7,19 @@ LL | #[cfg(FALSE)] fn e() { let _ = box #![attr] 0; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: expected expression, found `]` - --> $DIR/attr-stmt-expr-attr-bad.rs:5:40 + --> $DIR/attr-stmt-expr-attr-bad.rs:7:40 | LL | #[cfg(FALSE)] fn e() { let _ = [#[attr]]; } | ^ expected expression error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:7:35 + --> $DIR/attr-stmt-expr-attr-bad.rs:9:35 | LL | #[cfg(FALSE)] fn e() { let _ = foo#[attr](); } | ^ expected one of 7 possible tokens error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:9:36 + --> $DIR/attr-stmt-expr-attr-bad.rs:11:36 | LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); } | ^^^^^^^^ @@ -27,13 +27,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: expected expression, found `)` - --> $DIR/attr-stmt-expr-attr-bad.rs:9:44 + --> $DIR/attr-stmt-expr-attr-bad.rs:11:44 | LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); } | ^ expected expression error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:12:38 + --> $DIR/attr-stmt-expr-attr-bad.rs:14:38 | LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); } | ^^^^^^^^ @@ -41,13 +41,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: expected expression, found `)` - --> $DIR/attr-stmt-expr-attr-bad.rs:12:46 + --> $DIR/attr-stmt-expr-attr-bad.rs:14:46 | LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); } | ^ expected expression error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:15:36 + --> $DIR/attr-stmt-expr-attr-bad.rs:17:36 | LL | #[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; } | ^^^^^^^^ @@ -55,7 +55,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:17:33 + --> $DIR/attr-stmt-expr-attr-bad.rs:19:33 | LL | #[cfg(FALSE)] fn e() { let _ = !#![attr] 0; } | ^^^^^^^^ @@ -63,7 +63,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = !#![attr] 0; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:19:33 + --> $DIR/attr-stmt-expr-attr-bad.rs:21:33 | LL | #[cfg(FALSE)] fn e() { let _ = -#![attr] 0; } | ^^^^^^^^ @@ -71,13 +71,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = -#![attr] 0; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:21:34 + --> $DIR/attr-stmt-expr-attr-bad.rs:23:34 | LL | #[cfg(FALSE)] fn e() { let _ = x #![attr] as Y; } | ^ expected one of 7 possible tokens error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:23:35 + --> $DIR/attr-stmt-expr-attr-bad.rs:25:35 | LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] foo; } | ^^^^^^^^ @@ -85,7 +85,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] foo; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:25:40 + --> $DIR/attr-stmt-expr-attr-bad.rs:27:40 | LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; } | ^^^^^^^^ @@ -93,7 +93,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:27:35 + --> $DIR/attr-stmt-expr-attr-bad.rs:29:35 | LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; } | ^^^^^^^^ @@ -101,7 +101,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:29:40 + --> $DIR/attr-stmt-expr-attr-bad.rs:31:40 | LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; } | ^^^^^^^^ @@ -109,19 +109,19 @@ LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: expected expression, found `..` - --> $DIR/attr-stmt-expr-attr-bad.rs:31:40 + --> $DIR/attr-stmt-expr-attr-bad.rs:33:40 | LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..#[attr] 0; } | ^^ expected expression error: expected expression, found `..` - --> $DIR/attr-stmt-expr-attr-bad.rs:33:40 + --> $DIR/attr-stmt-expr-attr-bad.rs:35:40 | LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..; } | ^^ expected expression error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:35:41 + --> $DIR/attr-stmt-expr-attr-bad.rs:37:41 | LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; } | ^^^^^^^^ @@ -129,7 +129,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:37:45 + --> $DIR/attr-stmt-expr-attr-bad.rs:39:45 | LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; } | ^^^^^^^^ @@ -137,13 +137,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: attributes are not yet allowed on `if` expressions - --> $DIR/attr-stmt-expr-attr-bad.rs:39:32 + --> $DIR/attr-stmt-expr-attr-bad.rs:41:32 | LL | #[cfg(FALSE)] fn e() { let _ = #[attr] if 0 {}; } | ^^^^^^^ error: expected `{`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:41:37 + --> $DIR/attr-stmt-expr-attr-bad.rs:43:37 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; } | -- ^ --- help: try placing this code inside a block: `{ {}; }` @@ -152,7 +152,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; } | this `if` expression has a condition, but no block error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:43:38 + --> $DIR/attr-stmt-expr-attr-bad.rs:45:38 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; } | ^^^^^^^^ @@ -160,13 +160,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:45:40 + --> $DIR/attr-stmt-expr-attr-bad.rs:47:40 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; } | ^ expected one of `.`, `;`, `?`, `else`, or an operator error: expected `{`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:47:45 + --> $DIR/attr-stmt-expr-attr-bad.rs:49:45 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; } | ^ --- help: try placing this code inside a block: `{ {}; }` @@ -174,7 +174,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; } | expected `{` error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:49:46 + --> $DIR/attr-stmt-expr-attr-bad.rs:51:46 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; } | ^^^^^^^^ @@ -182,13 +182,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: attributes are not yet allowed on `if` expressions - --> $DIR/attr-stmt-expr-attr-bad.rs:51:45 + --> $DIR/attr-stmt-expr-attr-bad.rs:53:45 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; } | ^^^^^^^ error: expected `{`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:51:45 + --> $DIR/attr-stmt-expr-attr-bad.rs:53:45 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; } | ^ -------- help: try placing this code inside a block: `{ if 0 {}; }` @@ -196,7 +196,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; } | expected `{` error: expected `{`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:54:50 + --> $DIR/attr-stmt-expr-attr-bad.rs:56:50 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; } | -- ^ --- help: try placing this code inside a block: `{ {}; }` @@ -205,7 +205,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; } | this `if` expression has a condition, but no block error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:56:51 + --> $DIR/attr-stmt-expr-attr-bad.rs:58:51 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; } | ^^^^^^^^ @@ -213,13 +213,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: attributes are not yet allowed on `if` expressions - --> $DIR/attr-stmt-expr-attr-bad.rs:58:32 + --> $DIR/attr-stmt-expr-attr-bad.rs:60:32 | LL | #[cfg(FALSE)] fn e() { let _ = #[attr] if let _ = 0 {}; } | ^^^^^^^ error: expected `{`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:60:45 + --> $DIR/attr-stmt-expr-attr-bad.rs:62:45 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; } | -- ^ --- help: try placing this code inside a block: `{ {}; }` @@ -228,7 +228,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; } | this `if` expression has a condition, but no block error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:62:46 + --> $DIR/attr-stmt-expr-attr-bad.rs:64:46 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; } | ^^^^^^^^ @@ -236,13 +236,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:64:48 + --> $DIR/attr-stmt-expr-attr-bad.rs:66:48 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; } | ^ expected one of `.`, `;`, `?`, `else`, or an operator error: expected `{`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:66:53 + --> $DIR/attr-stmt-expr-attr-bad.rs:68:53 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; } | ^ --- help: try placing this code inside a block: `{ {}; }` @@ -250,7 +250,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; } | expected `{` error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:68:54 + --> $DIR/attr-stmt-expr-attr-bad.rs:70:54 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; } | ^^^^^^^^ @@ -258,13 +258,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: attributes are not yet allowed on `if` expressions - --> $DIR/attr-stmt-expr-attr-bad.rs:70:53 + --> $DIR/attr-stmt-expr-attr-bad.rs:72:53 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; } | ^^^^^^^ error: expected `{`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:70:53 + --> $DIR/attr-stmt-expr-attr-bad.rs:72:53 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; } | ^ ---------------- help: try placing this code inside a block: `{ if let _ = 0 {}; }` @@ -272,7 +272,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {} | expected `{` error: expected `{`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:73:66 + --> $DIR/attr-stmt-expr-attr-bad.rs:75:66 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; } | -- ^ --- help: try placing this code inside a block: `{ {}; }` @@ -281,7 +281,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {} | this `if` expression has a condition, but no block error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:75:67 + --> $DIR/attr-stmt-expr-attr-bad.rs:77:67 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; } | ^^^^^^^^ @@ -289,7 +289,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]} = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: an inner attribute is not permitted following an outer attribute - --> $DIR/attr-stmt-expr-attr-bad.rs:78:32 + --> $DIR/attr-stmt-expr-attr-bad.rs:80:32 | LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; } | ------- ^^^^^^^^ not permitted following an outer attibute @@ -299,7 +299,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: an inner attribute is not permitted following an outer attribute - --> $DIR/attr-stmt-expr-attr-bad.rs:80:32 + --> $DIR/attr-stmt-expr-attr-bad.rs:82:32 | LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; } | ------- ^^^^^^^^ not permitted following an outer attibute @@ -309,7 +309,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: an inner attribute is not permitted following an outer attribute - --> $DIR/attr-stmt-expr-attr-bad.rs:82:32 + --> $DIR/attr-stmt-expr-attr-bad.rs:84:32 | LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); } | ------- ^^^^^^^^ not permitted following an outer attibute @@ -319,7 +319,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: an inner attribute is not permitted following an outer attribute - --> $DIR/attr-stmt-expr-attr-bad.rs:84:32 + --> $DIR/attr-stmt-expr-attr-bad.rs:86:32 | LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; } | ------- ^^^^^^^^ not permitted following an outer attibute @@ -329,7 +329,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: an inner attribute is not permitted following an outer attribute - --> $DIR/attr-stmt-expr-attr-bad.rs:86:32 + --> $DIR/attr-stmt-expr-attr-bad.rs:88:32 | LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; } | ------- ^^^^^^^^ not permitted following an outer attibute @@ -338,83 +338,90 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; } | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. -error: `X..=` range patterns are not supported - --> $DIR/attr-stmt-expr-attr-bad.rs:92:34 +error[E0586]: inclusive range with no end + --> $DIR/attr-stmt-expr-attr-bad.rs:94:35 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } - | ^^^^ help: try using the maximum value for the type: `0..=MAX` + | ^^^ + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error: expected one of `=>`, `if`, or `|`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:92:38 + --> $DIR/attr-stmt-expr-attr-bad.rs:94:38 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } | ^ expected one of `=>`, `if`, or `|` -error: `X..=` range patterns are not supported - --> $DIR/attr-stmt-expr-attr-bad.rs:95:34 +error[E0586]: inclusive range with no end + --> $DIR/attr-stmt-expr-attr-bad.rs:97:35 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } - | ^^^^ help: try using the maximum value for the type: `0..=MAX` + | ^^^ + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error: expected one of `=>`, `if`, or `|`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:95:38 + --> $DIR/attr-stmt-expr-attr-bad.rs:97:38 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } | ^ expected one of `=>`, `if`, or `|` error: unexpected token: `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:98:39 + --> $DIR/attr-stmt-expr-attr-bad.rs:100:39 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } } | ^ -error: `X..=` range patterns are not supported - --> $DIR/attr-stmt-expr-attr-bad.rs:100:34 +error[E0586]: inclusive range with no end + --> $DIR/attr-stmt-expr-attr-bad.rs:102:35 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } - | ^^^^ help: try using the maximum value for the type: `0..=MAX` + | ^^^ + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error: expected one of `=>`, `if`, or `|`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:100:38 + --> $DIR/attr-stmt-expr-attr-bad.rs:102:38 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } | ^ expected one of `=>`, `if`, or `|` error: unexpected token: `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:104:34 + --> $DIR/attr-stmt-expr-attr-bad.rs:106:34 | LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); } | ^ error: expected one of `.`, `;`, `?`, or an operator, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:104:34 + --> $DIR/attr-stmt-expr-attr-bad.rs:106:34 | LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); } | ^ expected one of `.`, `;`, `?`, or an operator error: unexpected token: `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:107:34 + --> $DIR/attr-stmt-expr-attr-bad.rs:109:34 | LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); } | ^ error: expected one of `.`, `;`, `?`, or an operator, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:107:34 + --> $DIR/attr-stmt-expr-attr-bad.rs:109:34 | LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); } | ^ expected one of `.`, `;`, `?`, or an operator error: expected statement after outer attribute - --> $DIR/attr-stmt-expr-attr-bad.rs:112:44 + --> $DIR/attr-stmt-expr-attr-bad.rs:114:44 | LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } } | ^ error: expected statement after outer attribute - --> $DIR/attr-stmt-expr-attr-bad.rs:114:45 + --> $DIR/attr-stmt-expr-attr-bad.rs:116:45 | LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr] } } } | ^ error: aborting due to 57 previous errors +For more information about this error, try `rustc --explain E0586`. diff --git a/src/test/ui/parser/issue-63115-range-pat-interpolated.rs b/src/test/ui/parser/issue-63115-range-pat-interpolated.rs index a7d10ca9320a..8efb3c73f034 100644 --- a/src/test/ui/parser/issue-63115-range-pat-interpolated.rs +++ b/src/test/ui/parser/issue-63115-range-pat-interpolated.rs @@ -1,6 +1,7 @@ // check-pass #![feature(exclusive_range_pattern)] +#![feature(half_open_range_patterns)] #![allow(ellipsis_inclusive_range_patterns)] @@ -10,6 +11,11 @@ fn main() { if let 2...$e = 3 {} if let 2..=$e = 3 {} if let 2..$e = 3 {} + if let ..$e = 3 {} + if let ..=$e = 3 {} + if let $e.. = 5 {} + if let $e..5 = 4 {} + if let $e..=5 = 4 {} } } mac_expr!(4); diff --git a/src/test/ui/parser/issue-66357-unexpected-unreachable.rs b/src/test/ui/parser/issue-66357-unexpected-unreachable.rs index 1730adfa9141..5ec143fae234 100644 --- a/src/test/ui/parser/issue-66357-unexpected-unreachable.rs +++ b/src/test/ui/parser/issue-66357-unexpected-unreachable.rs @@ -1,3 +1,5 @@ +// ignore-tidy-linelength + // The problem in #66357 was that the call trace: // // - parse_fn_block_decl @@ -11,4 +13,4 @@ fn f() { |[](* } //~^ ERROR expected one of `,` or `:`, found `(` -//~| ERROR expected one of `)`, `-`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` +//~| ERROR expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` diff --git a/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr b/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr index 00d84e2afe35..c3810999d239 100644 --- a/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr +++ b/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr @@ -1,11 +1,11 @@ error: expected one of `,` or `:`, found `(` - --> $DIR/issue-66357-unexpected-unreachable.rs:12:13 + --> $DIR/issue-66357-unexpected-unreachable.rs:14:13 | LL | fn f() { |[](* } | ^ expected one of `,` or `:` -error: expected one of `)`, `-`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` - --> $DIR/issue-66357-unexpected-unreachable.rs:12:14 +error: expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` + --> $DIR/issue-66357-unexpected-unreachable.rs:14:14 | LL | fn f() { |[](* } | -^ help: `)` may belong here diff --git a/src/test/ui/parser/pat-tuple-4.rs b/src/test/ui/parser/pat-tuple-4.rs deleted file mode 100644 index 2f03160430a2..000000000000 --- a/src/test/ui/parser/pat-tuple-4.rs +++ /dev/null @@ -1,11 +0,0 @@ -fn main() { - const PAT: u8 = 0; - - match 0 { - (.. PAT) => {} - //~^ ERROR `..X` range patterns are not supported - //~| ERROR exclusive range pattern syntax is experimental - } -} - -const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types diff --git a/src/test/ui/parser/pat-tuple-4.stderr b/src/test/ui/parser/pat-tuple-4.stderr deleted file mode 100644 index 6c64290e144c..000000000000 --- a/src/test/ui/parser/pat-tuple-4.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error: `..X` range patterns are not supported - --> $DIR/pat-tuple-4.rs:5:10 - | -LL | (.. PAT) => {} - | ^^^^^^ help: try using the minimum value for the type: `MIN..PAT` - -error[E0658]: exclusive range pattern syntax is experimental - --> $DIR/pat-tuple-4.rs:5:10 - | -LL | (.. PAT) => {} - | ^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/37854 - = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable - -error[E0308]: mismatched types - --> $DIR/pat-tuple-4.rs:11:30 - | -LL | const RECOVERY_WITNESS: () = 0; - | ^ expected `()`, found integer - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0308, E0658. -For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/pat-tuple-5.rs b/src/test/ui/parser/pat-tuple-5.rs deleted file mode 100644 index 5334ef93bb3b..000000000000 --- a/src/test/ui/parser/pat-tuple-5.rs +++ /dev/null @@ -1,10 +0,0 @@ -fn main() { - const PAT: u8 = 0; - - match (0, 1) { - (PAT ..) => {} - //~^ ERROR `X..` range patterns are not supported - //~| ERROR exclusive range pattern syntax is experimental - //~| ERROR mismatched types - } -} diff --git a/src/test/ui/parser/pat-tuple-5.stderr b/src/test/ui/parser/pat-tuple-5.stderr deleted file mode 100644 index 8ff4f948a05e..000000000000 --- a/src/test/ui/parser/pat-tuple-5.stderr +++ /dev/null @@ -1,30 +0,0 @@ -error: `X..` range patterns are not supported - --> $DIR/pat-tuple-5.rs:5:10 - | -LL | (PAT ..) => {} - | ^^^^^^ help: try using the maximum value for the type: `PAT..MAX` - -error[E0658]: exclusive range pattern syntax is experimental - --> $DIR/pat-tuple-5.rs:5:10 - | -LL | (PAT ..) => {} - | ^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/37854 - = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable - -error[E0308]: mismatched types - --> $DIR/pat-tuple-5.rs:5:10 - | -LL | match (0, 1) { - | ------ this expression has type `({integer}, {integer})` -LL | (PAT ..) => {} - | ^^^ expected tuple, found `u8` - | - = note: expected tuple `({integer}, {integer})` - found type `u8` - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0308, E0658. -For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/recover-range-pats.rs b/src/test/ui/parser/recover-range-pats.rs index 260e10831597..a5aae2861b28 100644 --- a/src/test/ui/parser/recover-range-pats.rs +++ b/src/test/ui/parser/recover-range-pats.rs @@ -4,6 +4,7 @@ // 2. Or at least we have parser recovery if they don't. #![feature(exclusive_range_pattern)] +#![feature(half_open_range_patterns)] #![deny(ellipsis_inclusive_range_patterns)] fn main() {} @@ -55,68 +56,64 @@ fn inclusive2_from_to() { } fn exclusive_from() { - if let 0.. = 0 {} //~ ERROR `X..` range patterns are not supported - if let X.. = 0 {} //~ ERROR `X..` range patterns are not supported - if let true.. = 0 {} //~ ERROR `X..` range patterns are not supported + if let 0.. = 0 {} + if let X.. = 0 {} + if let true.. = 0 {} //~^ ERROR only char and numeric types - if let .0.. = 0 {} //~ ERROR `X..` range patterns are not supported + if let .0.. = 0 {} //~^ ERROR float literals must have an integer part //~| ERROR mismatched types } fn inclusive_from() { - if let 0..= = 0 {} //~ ERROR `X..=` range patterns are not supported - if let X..= = 0 {} //~ ERROR `X..=` range patterns are not supported - if let true..= = 0 {} //~ ERROR `X..=` range patterns are not supported + if let 0..= = 0 {} //~ ERROR inclusive range with no end + if let X..= = 0 {} //~ ERROR inclusive range with no end + if let true..= = 0 {} //~ ERROR inclusive range with no end //~| ERROR only char and numeric types - if let .0..= = 0 {} //~ ERROR `X..=` range patterns are not supported + if let .0..= = 0 {} //~ ERROR inclusive range with no end //~^ ERROR float literals must have an integer part //~| ERROR mismatched types } fn inclusive2_from() { - if let 0... = 0 {} //~ ERROR `X...` range patterns are not supported - //~^ ERROR `...` range patterns are deprecated - if let X... = 0 {} //~ ERROR `X...` range patterns are not supported - //~^ ERROR `...` range patterns are deprecated - if let true... = 0 {} //~ ERROR `X...` range patterns are not supported - //~^ ERROR `...` range patterns are deprecated + if let 0... = 0 {} //~ ERROR inclusive range with no end + if let X... = 0 {} //~ ERROR inclusive range with no end + if let true... = 0 {} //~ ERROR inclusive range with no end //~| ERROR only char and numeric types - if let .0... = 0 {} //~ ERROR `X...` range patterns are not supported + if let .0... = 0 {} //~ ERROR inclusive range with no end //~^ ERROR float literals must have an integer part - //~| ERROR `...` range patterns are deprecated //~| ERROR mismatched types } fn exclusive_to() { - if let ..0 = 0 {} //~ ERROR `..X` range patterns are not supported - if let ..Y = 0 {} //~ ERROR `..X` range patterns are not supported - if let ..true = 0 {} //~ ERROR `..X` range patterns are not supported - //~| ERROR only char and numeric types - if let .. .0 = 0 {} //~ ERROR `..X` range patterns are not supported + if let ..0 = 0 {} + if let ..Y = 0 {} + if let ..true = 0 {} + //~^ ERROR only char and numeric types + if let .. .0 = 0 {} //~^ ERROR float literals must have an integer part //~| ERROR mismatched types } fn inclusive_to() { - if let ..=3 = 0 {} //~ ERROR `..=X` range patterns are not supported - if let ..=Y = 0 {} //~ ERROR `..=X` range patterns are not supported - if let ..=true = 0 {} //~ ERROR `..=X` range patterns are not supported - //~| ERROR only char and numeric types - if let ..=.0 = 0 {} //~ ERROR `..=X` range patterns are not supported + if let ..=3 = 0 {} + if let ..=Y = 0 {} + if let ..=true = 0 {} + //~^ ERROR only char and numeric types + if let ..=.0 = 0 {} //~^ ERROR float literals must have an integer part //~| ERROR mismatched types } fn inclusive2_to() { - if let ...3 = 0 {} //~ ERROR `...X` range patterns are not supported + if let ...3 = 0 {} //~^ ERROR `...` range patterns are deprecated - if let ...Y = 0 {} //~ ERROR `...X` range patterns are not supported + if let ...Y = 0 {} //~^ ERROR `...` range patterns are deprecated - if let ...true = 0 {} //~ ERROR `...X` range patterns are not supported + if let ...true = 0 {} //~^ ERROR `...` range patterns are deprecated //~| ERROR only char and numeric types - if let ....3 = 0 {} //~ ERROR `...X` range patterns are not supported + if let ....3 = 0 {} //~^ ERROR float literals must have an integer part //~| ERROR `...` range patterns are deprecated //~| ERROR mismatched types @@ -136,14 +133,13 @@ fn with_macro_expr_var() { macro_rules! mac { ($e:expr) => { - let ..$e; //~ ERROR `..X` range patterns are not supported - let ...$e; //~ ERROR `...X` range patterns are not supported - //~^ ERROR `...` range patterns are deprecated - let ..=$e; //~ ERROR `..=X` range patterns are not supported - let $e..; //~ ERROR `X..` range patterns are not supported - let $e...; //~ ERROR `X...` range patterns are not supported + let ..$e; + let ...$e; //~^ ERROR `...` range patterns are deprecated - let $e..=; //~ ERROR `X..=` range patterns are not supported + let ..=$e; + let $e..; + let $e...; //~ ERROR inclusive range with no end + let $e..=; //~ ERROR inclusive range with no end } } diff --git a/src/test/ui/parser/recover-range-pats.stderr b/src/test/ui/parser/recover-range-pats.stderr index 3fed64c191a8..d3d3169022a6 100644 --- a/src/test/ui/parser/recover-range-pats.stderr +++ b/src/test/ui/parser/recover-range-pats.stderr @@ -1,377 +1,241 @@ error: float literals must have an integer part - --> $DIR/recover-range-pats.rs:21:12 + --> $DIR/recover-range-pats.rs:22:12 | LL | if let .0..Y = 0 {} | ^^ help: must have an integer part: `0.0` error: float literals must have an integer part - --> $DIR/recover-range-pats.rs:23:16 + --> $DIR/recover-range-pats.rs:24:16 | LL | if let X.. .0 = 0 {} | ^^ help: must have an integer part: `0.0` error: float literals must have an integer part - --> $DIR/recover-range-pats.rs:34:12 + --> $DIR/recover-range-pats.rs:35:12 | LL | if let .0..=Y = 0 {} | ^^ help: must have an integer part: `0.0` error: float literals must have an integer part - --> $DIR/recover-range-pats.rs:36:16 + --> $DIR/recover-range-pats.rs:37:16 | LL | if let X..=.0 = 0 {} | ^^ help: must have an integer part: `0.0` error: float literals must have an integer part - --> $DIR/recover-range-pats.rs:49:12 + --> $DIR/recover-range-pats.rs:50:12 | LL | if let .0...Y = 0 {} | ^^ help: must have an integer part: `0.0` error: float literals must have an integer part - --> $DIR/recover-range-pats.rs:52:17 + --> $DIR/recover-range-pats.rs:53:17 | LL | if let X... .0 = 0 {} | ^^ help: must have an integer part: `0.0` -error: `X..` range patterns are not supported - --> $DIR/recover-range-pats.rs:58:12 - | -LL | if let 0.. = 0 {} - | ^^^ help: try using the maximum value for the type: `0..MAX` - -error: `X..` range patterns are not supported - --> $DIR/recover-range-pats.rs:59:12 - | -LL | if let X.. = 0 {} - | ^^^ help: try using the maximum value for the type: `X..MAX` - -error: `X..` range patterns are not supported - --> $DIR/recover-range-pats.rs:60:12 - | -LL | if let true.. = 0 {} - | ^^^^^^ help: try using the maximum value for the type: `true..MAX` - error: float literals must have an integer part - --> $DIR/recover-range-pats.rs:62:12 + --> $DIR/recover-range-pats.rs:63:12 | LL | if let .0.. = 0 {} | ^^ help: must have an integer part: `0.0` -error: `X..` range patterns are not supported - --> $DIR/recover-range-pats.rs:62:12 - | -LL | if let .0.. = 0 {} - | ^^^^ help: try using the maximum value for the type: `0.0..MAX` - -error: `X..=` range patterns are not supported - --> $DIR/recover-range-pats.rs:68:12 +error[E0586]: inclusive range with no end + --> $DIR/recover-range-pats.rs:69:13 | LL | if let 0..= = 0 {} - | ^^^^ help: try using the maximum value for the type: `0..=MAX` + | ^^^ + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: `X..=` range patterns are not supported - --> $DIR/recover-range-pats.rs:69:12 +error[E0586]: inclusive range with no end + --> $DIR/recover-range-pats.rs:70:13 | LL | if let X..= = 0 {} - | ^^^^ help: try using the maximum value for the type: `X..=MAX` + | ^^^ + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: `X..=` range patterns are not supported - --> $DIR/recover-range-pats.rs:70:12 +error[E0586]: inclusive range with no end + --> $DIR/recover-range-pats.rs:71:16 | LL | if let true..= = 0 {} - | ^^^^^^^ help: try using the maximum value for the type: `true..=MAX` + | ^^^ + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error: float literals must have an integer part - --> $DIR/recover-range-pats.rs:72:12 + --> $DIR/recover-range-pats.rs:73:12 | LL | if let .0..= = 0 {} | ^^ help: must have an integer part: `0.0` -error: `X..=` range patterns are not supported - --> $DIR/recover-range-pats.rs:72:12 +error[E0586]: inclusive range with no end + --> $DIR/recover-range-pats.rs:73:14 | LL | if let .0..= = 0 {} - | ^^^^^ help: try using the maximum value for the type: `0.0..=MAX` + | ^^^ + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: `X...` range patterns are not supported - --> $DIR/recover-range-pats.rs:78:12 +error[E0586]: inclusive range with no end + --> $DIR/recover-range-pats.rs:79:13 | LL | if let 0... = 0 {} - | ^^^^ help: try using the maximum value for the type: `0...MAX` + | ^^^ + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: `X...` range patterns are not supported - --> $DIR/recover-range-pats.rs:80:12 +error[E0586]: inclusive range with no end + --> $DIR/recover-range-pats.rs:80:13 | LL | if let X... = 0 {} - | ^^^^ help: try using the maximum value for the type: `X...MAX` + | ^^^ + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: `X...` range patterns are not supported - --> $DIR/recover-range-pats.rs:82:12 +error[E0586]: inclusive range with no end + --> $DIR/recover-range-pats.rs:81:16 | LL | if let true... = 0 {} - | ^^^^^^^ help: try using the maximum value for the type: `true...MAX` + | ^^^ + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error: float literals must have an integer part - --> $DIR/recover-range-pats.rs:85:12 + --> $DIR/recover-range-pats.rs:83:12 | LL | if let .0... = 0 {} | ^^ help: must have an integer part: `0.0` -error: `X...` range patterns are not supported - --> $DIR/recover-range-pats.rs:85:12 +error[E0586]: inclusive range with no end + --> $DIR/recover-range-pats.rs:83:14 | LL | if let .0... = 0 {} - | ^^^^^ help: try using the maximum value for the type: `0.0...MAX` - -error: `..X` range patterns are not supported - --> $DIR/recover-range-pats.rs:92:12 - | -LL | if let ..0 = 0 {} - | ^^^ help: try using the minimum value for the type: `MIN..0` - -error: `..X` range patterns are not supported - --> $DIR/recover-range-pats.rs:93:12 + | ^^^ | -LL | if let ..Y = 0 {} - | ^^^ help: try using the minimum value for the type: `MIN..Y` - -error: `..X` range patterns are not supported - --> $DIR/recover-range-pats.rs:94:12 - | -LL | if let ..true = 0 {} - | ^^^^^^ help: try using the minimum value for the type: `MIN..true` + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error: float literals must have an integer part - --> $DIR/recover-range-pats.rs:96:15 + --> $DIR/recover-range-pats.rs:93:15 | LL | if let .. .0 = 0 {} | ^^ help: must have an integer part: `0.0` -error: `..X` range patterns are not supported - --> $DIR/recover-range-pats.rs:96:12 - | -LL | if let .. .0 = 0 {} - | ^^^^^ help: try using the minimum value for the type: `MIN..0.0` - -error: `..=X` range patterns are not supported - --> $DIR/recover-range-pats.rs:102:12 - | -LL | if let ..=3 = 0 {} - | ^^^^ help: try using the minimum value for the type: `MIN..=3` - -error: `..=X` range patterns are not supported - --> $DIR/recover-range-pats.rs:103:12 - | -LL | if let ..=Y = 0 {} - | ^^^^ help: try using the minimum value for the type: `MIN..=Y` - -error: `..=X` range patterns are not supported - --> $DIR/recover-range-pats.rs:104:12 - | -LL | if let ..=true = 0 {} - | ^^^^^^^ help: try using the minimum value for the type: `MIN..=true` - error: float literals must have an integer part - --> $DIR/recover-range-pats.rs:106:15 + --> $DIR/recover-range-pats.rs:103:15 | LL | if let ..=.0 = 0 {} | ^^ help: must have an integer part: `0.0` -error: `..=X` range patterns are not supported - --> $DIR/recover-range-pats.rs:106:12 - | -LL | if let ..=.0 = 0 {} - | ^^^^^ help: try using the minimum value for the type: `MIN..=0.0` - -error: `...X` range patterns are not supported - --> $DIR/recover-range-pats.rs:112:12 - | -LL | if let ...3 = 0 {} - | ^^^^ help: try using the minimum value for the type: `MIN...3` - -error: `...X` range patterns are not supported - --> $DIR/recover-range-pats.rs:114:12 - | -LL | if let ...Y = 0 {} - | ^^^^ help: try using the minimum value for the type: `MIN...Y` - -error: `...X` range patterns are not supported - --> $DIR/recover-range-pats.rs:116:12 - | -LL | if let ...true = 0 {} - | ^^^^^^^ help: try using the minimum value for the type: `MIN...true` - error: float literals must have an integer part - --> $DIR/recover-range-pats.rs:119:15 + --> $DIR/recover-range-pats.rs:116:15 | LL | if let ....3 = 0 {} | ^^ help: must have an integer part: `0.3` -error: `...X` range patterns are not supported - --> $DIR/recover-range-pats.rs:119:12 - | -LL | if let ....3 = 0 {} - | ^^^^^ help: try using the minimum value for the type: `MIN...0.3` - -error: `..X` range patterns are not supported - --> $DIR/recover-range-pats.rs:139:17 - | -LL | let ..$e; - | ^^ help: try using the minimum value for the type: `MIN..0` -... -LL | mac!(0); - | -------- in this macro invocation - -error: `...X` range patterns are not supported - --> $DIR/recover-range-pats.rs:140:17 - | -LL | let ...$e; - | ^^^ help: try using the minimum value for the type: `MIN...0` -... -LL | mac!(0); - | -------- in this macro invocation - -error: `..=X` range patterns are not supported - --> $DIR/recover-range-pats.rs:142:17 - | -LL | let ..=$e; - | ^^^ help: try using the minimum value for the type: `MIN..=0` -... -LL | mac!(0); - | -------- in this macro invocation - -error: `X..` range patterns are not supported - --> $DIR/recover-range-pats.rs:143:19 - | -LL | let $e..; - | ^^ help: try using the maximum value for the type: `0..MAX` -... -LL | mac!(0); - | -------- in this macro invocation - -error: `X...` range patterns are not supported - --> $DIR/recover-range-pats.rs:144:19 +error[E0586]: inclusive range with no end + --> $DIR/recover-range-pats.rs:141:19 | LL | let $e...; - | ^^^ help: try using the maximum value for the type: `0...MAX` + | ^^^ ... LL | mac!(0); | -------- in this macro invocation + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: `X..=` range patterns are not supported - --> $DIR/recover-range-pats.rs:146:19 +error[E0586]: inclusive range with no end + --> $DIR/recover-range-pats.rs:142:19 | LL | let $e..=; - | ^^^ help: try using the maximum value for the type: `0..=MAX` + | ^^^ ... LL | mac!(0); | -------- in this macro invocation + | + = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:41:13 + --> $DIR/recover-range-pats.rs:42:13 | LL | if let 0...3 = 0 {} | ^^^ help: use `..=` for an inclusive range | note: lint level defined here - --> $DIR/recover-range-pats.rs:7:9 + --> $DIR/recover-range-pats.rs:8:9 | LL | #![deny(ellipsis_inclusive_range_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:42:13 + --> $DIR/recover-range-pats.rs:43:13 | LL | if let 0...Y = 0 {} | ^^^ help: use `..=` for an inclusive range error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:43:13 + --> $DIR/recover-range-pats.rs:44:13 | LL | if let X...3 = 0 {} | ^^^ help: use `..=` for an inclusive range error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:44:13 + --> $DIR/recover-range-pats.rs:45:13 | LL | if let X...Y = 0 {} | ^^^ help: use `..=` for an inclusive range error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:45:16 + --> $DIR/recover-range-pats.rs:46:16 | LL | if let true...Y = 0 {} | ^^^ help: use `..=` for an inclusive range error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:47:13 + --> $DIR/recover-range-pats.rs:48:13 | LL | if let X...true = 0 {} | ^^^ help: use `..=` for an inclusive range error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:49:14 + --> $DIR/recover-range-pats.rs:50:14 | LL | if let .0...Y = 0 {} | ^^^ help: use `..=` for an inclusive range error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:52:13 + --> $DIR/recover-range-pats.rs:53:13 | LL | if let X... .0 = 0 {} | ^^^ help: use `..=` for an inclusive range error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:78:13 - | -LL | if let 0... = 0 {} - | ^^^ help: use `..=` for an inclusive range - -error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:80:13 - | -LL | if let X... = 0 {} - | ^^^ help: use `..=` for an inclusive range - -error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:82:16 - | -LL | if let true... = 0 {} - | ^^^ help: use `..=` for an inclusive range - -error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:85:14 - | -LL | if let .0... = 0 {} - | ^^^ help: use `..=` for an inclusive range - -error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:112:12 + --> $DIR/recover-range-pats.rs:109:12 | LL | if let ...3 = 0 {} | ^^^ help: use `..=` for an inclusive range error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:114:12 + --> $DIR/recover-range-pats.rs:111:12 | LL | if let ...Y = 0 {} | ^^^ help: use `..=` for an inclusive range error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:116:12 + --> $DIR/recover-range-pats.rs:113:12 | LL | if let ...true = 0 {} | ^^^ help: use `..=` for an inclusive range error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:119:12 + --> $DIR/recover-range-pats.rs:116:12 | LL | if let ....3 = 0 {} | ^^^ help: use `..=` for an inclusive range error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:129:20 + --> $DIR/recover-range-pats.rs:126:20 | LL | let $e1...$e2; | ^^^ help: use `..=` for an inclusive range @@ -380,7 +244,7 @@ LL | mac2!(0, 1); | ------------ in this macro invocation error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:140:17 + --> $DIR/recover-range-pats.rs:137:17 | LL | let ...$e; | ^^^ help: use `..=` for an inclusive range @@ -388,17 +252,8 @@ LL | let ...$e; LL | mac!(0); | -------- in this macro invocation -error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:144:19 - | -LL | let $e...; - | ^^^ help: use `..=` for an inclusive range -... -LL | mac!(0); - | -------- in this macro invocation - error[E0029]: only char and numeric types are allowed in range patterns - --> $DIR/recover-range-pats.rs:19:12 + --> $DIR/recover-range-pats.rs:20:12 | LL | if let true..Y = 0 {} | ^^^^ - this is of type `u8` @@ -406,7 +261,7 @@ LL | if let true..Y = 0 {} | this is of type `bool` but it should be `char` or numeric error[E0029]: only char and numeric types are allowed in range patterns - --> $DIR/recover-range-pats.rs:20:15 + --> $DIR/recover-range-pats.rs:21:15 | LL | if let X..true = 0 {} | - ^^^^ this is of type `bool` but it should be `char` or numeric @@ -414,7 +269,7 @@ LL | if let X..true = 0 {} | this is of type `u8` error[E0308]: mismatched types - --> $DIR/recover-range-pats.rs:21:12 + --> $DIR/recover-range-pats.rs:22:12 | LL | if let .0..Y = 0 {} | ^^ - this is of type `u8` @@ -422,7 +277,7 @@ LL | if let .0..Y = 0 {} | expected integer, found floating-point number error[E0308]: mismatched types - --> $DIR/recover-range-pats.rs:23:16 + --> $DIR/recover-range-pats.rs:24:16 | LL | if let X.. .0 = 0 {} | - ^^ - this expression has type `u8` @@ -431,7 +286,7 @@ LL | if let X.. .0 = 0 {} | this is of type `u8` error[E0029]: only char and numeric types are allowed in range patterns - --> $DIR/recover-range-pats.rs:32:12 + --> $DIR/recover-range-pats.rs:33:12 | LL | if let true..=Y = 0 {} | ^^^^ - this is of type `u8` @@ -439,7 +294,7 @@ LL | if let true..=Y = 0 {} | this is of type `bool` but it should be `char` or numeric error[E0029]: only char and numeric types are allowed in range patterns - --> $DIR/recover-range-pats.rs:33:16 + --> $DIR/recover-range-pats.rs:34:16 | LL | if let X..=true = 0 {} | - ^^^^ this is of type `bool` but it should be `char` or numeric @@ -447,7 +302,7 @@ LL | if let X..=true = 0 {} | this is of type `u8` error[E0308]: mismatched types - --> $DIR/recover-range-pats.rs:34:12 + --> $DIR/recover-range-pats.rs:35:12 | LL | if let .0..=Y = 0 {} | ^^ - this is of type `u8` @@ -455,7 +310,7 @@ LL | if let .0..=Y = 0 {} | expected integer, found floating-point number error[E0308]: mismatched types - --> $DIR/recover-range-pats.rs:36:16 + --> $DIR/recover-range-pats.rs:37:16 | LL | if let X..=.0 = 0 {} | - ^^ - this expression has type `u8` @@ -464,7 +319,7 @@ LL | if let X..=.0 = 0 {} | this is of type `u8` error[E0029]: only char and numeric types are allowed in range patterns - --> $DIR/recover-range-pats.rs:45:12 + --> $DIR/recover-range-pats.rs:46:12 | LL | if let true...Y = 0 {} | ^^^^ - this is of type `u8` @@ -472,7 +327,7 @@ LL | if let true...Y = 0 {} | this is of type `bool` but it should be `char` or numeric error[E0029]: only char and numeric types are allowed in range patterns - --> $DIR/recover-range-pats.rs:47:16 + --> $DIR/recover-range-pats.rs:48:16 | LL | if let X...true = 0 {} | - ^^^^ this is of type `bool` but it should be `char` or numeric @@ -480,7 +335,7 @@ LL | if let X...true = 0 {} | this is of type `u8` error[E0308]: mismatched types - --> $DIR/recover-range-pats.rs:49:12 + --> $DIR/recover-range-pats.rs:50:12 | LL | if let .0...Y = 0 {} | ^^ - this is of type `u8` @@ -488,7 +343,7 @@ LL | if let .0...Y = 0 {} | expected integer, found floating-point number error[E0308]: mismatched types - --> $DIR/recover-range-pats.rs:52:17 + --> $DIR/recover-range-pats.rs:53:17 | LL | if let X... .0 = 0 {} | - ^^ - this expression has type `u8` @@ -497,78 +352,78 @@ LL | if let X... .0 = 0 {} | this is of type `u8` error[E0029]: only char and numeric types are allowed in range patterns - --> $DIR/recover-range-pats.rs:60:12 + --> $DIR/recover-range-pats.rs:61:12 | LL | if let true.. = 0 {} | ^^^^ this is of type `bool` but it should be `char` or numeric error[E0308]: mismatched types - --> $DIR/recover-range-pats.rs:62:12 + --> $DIR/recover-range-pats.rs:63:12 | LL | if let .0.. = 0 {} | ^^ expected integer, found floating-point number error[E0029]: only char and numeric types are allowed in range patterns - --> $DIR/recover-range-pats.rs:70:12 + --> $DIR/recover-range-pats.rs:71:12 | LL | if let true..= = 0 {} | ^^^^ this is of type `bool` but it should be `char` or numeric error[E0308]: mismatched types - --> $DIR/recover-range-pats.rs:72:12 + --> $DIR/recover-range-pats.rs:73:12 | LL | if let .0..= = 0 {} | ^^ expected integer, found floating-point number error[E0029]: only char and numeric types are allowed in range patterns - --> $DIR/recover-range-pats.rs:82:12 + --> $DIR/recover-range-pats.rs:81:12 | LL | if let true... = 0 {} | ^^^^ this is of type `bool` but it should be `char` or numeric error[E0308]: mismatched types - --> $DIR/recover-range-pats.rs:85:12 + --> $DIR/recover-range-pats.rs:83:12 | LL | if let .0... = 0 {} | ^^ expected integer, found floating-point number error[E0029]: only char and numeric types are allowed in range patterns - --> $DIR/recover-range-pats.rs:94:14 + --> $DIR/recover-range-pats.rs:91:14 | LL | if let ..true = 0 {} | ^^^^ this is of type `bool` but it should be `char` or numeric error[E0308]: mismatched types - --> $DIR/recover-range-pats.rs:96:15 + --> $DIR/recover-range-pats.rs:93:15 | LL | if let .. .0 = 0 {} | ^^ expected integer, found floating-point number error[E0029]: only char and numeric types are allowed in range patterns - --> $DIR/recover-range-pats.rs:104:15 + --> $DIR/recover-range-pats.rs:101:15 | LL | if let ..=true = 0 {} | ^^^^ this is of type `bool` but it should be `char` or numeric error[E0308]: mismatched types - --> $DIR/recover-range-pats.rs:106:15 + --> $DIR/recover-range-pats.rs:103:15 | LL | if let ..=.0 = 0 {} | ^^ expected integer, found floating-point number error[E0029]: only char and numeric types are allowed in range patterns - --> $DIR/recover-range-pats.rs:116:15 + --> $DIR/recover-range-pats.rs:113:15 | LL | if let ...true = 0 {} | ^^^^ this is of type `bool` but it should be `char` or numeric error[E0308]: mismatched types - --> $DIR/recover-range-pats.rs:119:15 + --> $DIR/recover-range-pats.rs:116:15 | LL | if let ....3 = 0 {} | ^^ expected integer, found floating-point number -error: aborting due to 85 previous errors +error: aborting due to 60 previous errors -Some errors have detailed explanations: E0029, E0308. +Some errors have detailed explanations: E0029, E0308, E0586. For more information about an error, try `rustc --explain E0029`. diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 003f51a0f43b..2663b3d160a7 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -67,6 +67,7 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[ ("powerpc", "powerpc"), ("powerpc64", "powerpc64"), ("powerpc64le", "powerpc64"), + ("riscv64gc", "riscv64"), ("s390x", "s390x"), ("sparc", "sparc"), ("sparc64", "sparc64"),