diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 6f1d69821f56c..6c4956663841c 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -70,7 +70,6 @@ #![feature(bound_cloned)] #![feature(cfg_target_has_atomic)] #![feature(concat_idents)] -#![feature(const_fn)] #![feature(const_if_match)] #![feature(const_panic)] #![feature(const_fn_union)] diff --git a/src/libcore/result.rs b/src/libcore/result.rs index aa57c7788c60c..c657ce33f60ad 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -1136,7 +1136,7 @@ impl Result { /// /// Leaves the original `Result` in-place, creating a new one containing a reference to the /// `Ok` type's `Deref::Target` type. - pub fn as_deref_ok(&self) -> Result<&T::Target, &E> { + pub fn as_deref(&self) -> Result<&T::Target, &E> { self.as_ref().map(|t| t.deref()) } } @@ -1152,24 +1152,13 @@ impl Result { } } -#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] -impl Result { - /// Converts from `Result` (or `&Result`) to `Result<&T::Target, &E::Target>`. - /// - /// Leaves the original `Result` in-place, creating a new one containing a reference to both - /// the `Ok` and `Err` types' `Deref::Target` types. - pub fn as_deref(&self) -> Result<&T::Target, &E::Target> { - self.as_ref().map(|t| t.deref()).map_err(|e| e.deref()) - } -} - #[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] impl Result { /// Converts from `Result` (or `&mut Result`) to `Result<&mut T::Target, &mut E>`. /// /// Leaves the original `Result` in-place, creating a new one containing a mutable reference to /// the `Ok` type's `Deref::Target` type. - pub fn as_deref_mut_ok(&mut self) -> Result<&mut T::Target, &mut E> { + pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E> { self.as_mut().map(|t| t.deref_mut()) } } @@ -1185,18 +1174,6 @@ impl Result { } } -#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] -impl Result { - /// Converts from `Result` (or `&mut Result`) to - /// `Result<&mut T::Target, &mut E::Target>`. - /// - /// Leaves the original `Result` in-place, creating a new one containing a mutable reference to - /// both the `Ok` and `Err` types' `Deref::Target` types. - pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E::Target> { - self.as_mut().map(|t| t.deref_mut()).map_err(|e| e.deref_mut()) - } -} - impl Result, E> { /// Transposes a `Result` of an `Option` into an `Option` of a `Result`. /// diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 09b54857f7dec..86cf6fc104c83 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -31,7 +31,6 @@ #![feature(slice_internals)] #![feature(slice_partition_dedup)] #![feature(int_error_matching)] -#![feature(const_fn)] #![feature(array_value_iter)] #![feature(iter_partition_in_place)] #![feature(iter_is_partitioned)] diff --git a/src/libcore/tests/result.rs b/src/libcore/tests/result.rs index 254d4539eaccf..c835313aae703 100644 --- a/src/libcore/tests/result.rs +++ b/src/libcore/tests/result.rs @@ -236,31 +236,17 @@ fn test_try() { #[test] fn test_result_as_deref() { - // &Result::Ok(T).as_deref_ok() -> + // &Result::Ok(T).as_deref() -> // Result<&T::Deref::Target, &E>::Ok(&*T) let ref_ok = &Result::Ok::<&i32, u8>(&42); let expected_result = Result::Ok::<&i32, &u8>(&42); - assert_eq!(ref_ok.as_deref_ok(), expected_result); - - let ref_ok = &Result::Ok::(String::from("a result")); - let expected_result = Result::Ok::<&str, &u32>("a result"); - assert_eq!(ref_ok.as_deref_ok(), expected_result); - - let ref_ok = &Result::Ok::, u32>(vec![1, 2, 3, 4, 5]); - let expected_result = Result::Ok::<&[i32], &u32>([1, 2, 3, 4, 5].as_slice()); - assert_eq!(ref_ok.as_deref_ok(), expected_result); - - // &Result::Ok(T).as_deref() -> - // Result<&T::Deref::Target, &E::Deref::Target>::Ok(&*T) - let ref_ok = &Result::Ok::<&i32, &u8>(&42); - let expected_result = Result::Ok::<&i32, &u8>(&42); assert_eq!(ref_ok.as_deref(), expected_result); - let ref_ok = &Result::Ok::(String::from("a result")); + let ref_ok = &Result::Ok::(String::from("a result")); let expected_result = Result::Ok::<&str, &u32>("a result"); assert_eq!(ref_ok.as_deref(), expected_result); - let ref_ok = &Result::Ok::, &u32>(vec![1, 2, 3, 4, 5]); + let ref_ok = &Result::Ok::, u32>(vec![1, 2, 3, 4, 5]); let expected_result = Result::Ok::<&[i32], &u32>([1, 2, 3, 4, 5].as_slice()); assert_eq!(ref_ok.as_deref(), expected_result); @@ -281,19 +267,21 @@ fn test_result_as_deref() { // &Result::Err(T).as_deref_err() -> // Result<&T, &E::Deref::Target>::Err(&*E) let ref_err = &Result::Err::<&u8, &i32>(&41); - let expected_result = Result::Err::<&u8, &i32>(&41); + let expected_result = Result::Err::<&u8, &&i32>(&&41); assert_eq!(ref_err.as_deref(), expected_result); - let ref_err = &Result::Err::<&u32, String>(String::from("an error")); - let expected_result = Result::Err::<&u32, &str>("an error"); + let s = String::from("an error"); + let ref_err = &Result::Err::<&u32, String>(s.clone()); + let expected_result = Result::Err::<&u32, &String>(&s); assert_eq!(ref_err.as_deref(), expected_result); - let ref_err = &Result::Err::<&u32, Vec>(vec![5, 4, 3, 2, 1]); - let expected_result = Result::Err::<&u32, &[i32]>([5, 4, 3, 2, 1].as_slice()); + let v = vec![5, 4, 3, 2, 1]; + let ref_err = &Result::Err::<&u32, Vec>(v.clone()); + let expected_result = Result::Err::<&u32, &Vec>(&v); assert_eq!(ref_err.as_deref(), expected_result); // The following cases test calling `as_deref_*` with the wrong variant (i.e. - // `as_deref_ok()` with a `Result::Err()`, or `as_deref_err()` with a `Result::Ok()`. + // `as_deref()` with a `Result::Err()`, or `as_deref_err()` with a `Result::Ok()`. // While uncommon, these cases are supported to ensure that an `as_deref_*` // call can still be made even when one of the Result types does not implement // `Deref` (for example, std::io::Error). @@ -312,56 +300,38 @@ fn test_result_as_deref() { let expected_result = Result::Ok::<&[i32; 5], &u32>(&[1, 2, 3, 4, 5]); assert_eq!(ref_ok.as_deref_err(), expected_result); - // &Result::Err(E).as_deref_ok() -> + // &Result::Err(E).as_deref() -> // Result<&T::Deref::Target, &E>::Err(&E) let ref_err = &Result::Err::<&u8, i32>(41); let expected_result = Result::Err::<&u8, &i32>(&41); - assert_eq!(ref_err.as_deref_ok(), expected_result); + assert_eq!(ref_err.as_deref(), expected_result); let ref_err = &Result::Err::<&u32, &str>("an error"); let expected_result = Result::Err::<&u32, &&str>(&"an error"); - assert_eq!(ref_err.as_deref_ok(), expected_result); + assert_eq!(ref_err.as_deref(), expected_result); let ref_err = &Result::Err::<&u32, [i32; 5]>([5, 4, 3, 2, 1]); let expected_result = Result::Err::<&u32, &[i32; 5]>(&[5, 4, 3, 2, 1]); - assert_eq!(ref_err.as_deref_ok(), expected_result); + assert_eq!(ref_err.as_deref(), expected_result); } #[test] fn test_result_as_deref_mut() { - // &mut Result::Ok(T).as_deref_mut_ok() -> + // &mut Result::Ok(T).as_deref_mut() -> // Result<&mut T::Deref::Target, &mut E>::Ok(&mut *T) let mut val = 42; let mut expected_val = 42; let mut_ok = &mut Result::Ok::<&mut i32, u8>(&mut val); let expected_result = Result::Ok::<&mut i32, &mut u8>(&mut expected_val); - assert_eq!(mut_ok.as_deref_mut_ok(), expected_result); - - let mut expected_string = String::from("a result"); - let mut_ok = &mut Result::Ok::(expected_string.clone()); - let expected_result = Result::Ok::<&mut str, &mut u32>(expected_string.deref_mut()); - assert_eq!(mut_ok.as_deref_mut_ok(), expected_result); - - let mut expected_vec = vec![1, 2, 3, 4, 5]; - let mut_ok = &mut Result::Ok::, u32>(expected_vec.clone()); - let expected_result = Result::Ok::<&mut [i32], &mut u32>(expected_vec.as_mut_slice()); - assert_eq!(mut_ok.as_deref_mut_ok(), expected_result); - - // &mut Result::Ok(T).as_deref_mut() -> - // Result<&mut T::Deref::Target, &mut E::Deref::Target>::Ok(&mut *T) - let mut val = 42; - let mut expected_val = 42; - let mut_ok = &mut Result::Ok::<&mut i32, &mut u8>(&mut val); - let expected_result = Result::Ok::<&mut i32, &mut u8>(&mut expected_val); assert_eq!(mut_ok.as_deref_mut(), expected_result); let mut expected_string = String::from("a result"); - let mut_ok = &mut Result::Ok::(expected_string.clone()); + let mut_ok = &mut Result::Ok::(expected_string.clone()); let expected_result = Result::Ok::<&mut str, &mut u32>(expected_string.deref_mut()); assert_eq!(mut_ok.as_deref_mut(), expected_result); let mut expected_vec = vec![1, 2, 3, 4, 5]; - let mut_ok = &mut Result::Ok::, &mut u32>(expected_vec.clone()); + let mut_ok = &mut Result::Ok::, u32>(expected_vec.clone()); let expected_result = Result::Ok::<&mut [i32], &mut u32>(expected_vec.as_mut_slice()); assert_eq!(mut_ok.as_deref_mut(), expected_result); @@ -386,23 +356,22 @@ fn test_result_as_deref_mut() { // &mut Result::Err(T).as_deref_mut_err() -> // Result<&mut T, &mut E::Deref::Target>::Err(&mut *E) let mut val = 41; - let mut expected_val = 41; - let mut_err = &mut Result::Err::<&mut u8, &mut i32>(&mut val); - let expected_result = Result::Err::<&mut u8, &mut i32>(&mut expected_val); + let mut_err = &mut Result::Err::<&mut u8, i32>(val); + let expected_result = Result::Err::<&mut u8, &mut i32>(&mut val); assert_eq!(mut_err.as_deref_mut(), expected_result); let mut expected_string = String::from("an error"); let mut_err = &mut Result::Err::<&mut u32, String>(expected_string.clone()); - let expected_result = Result::Err::<&mut u32, &mut str>(expected_string.as_mut_str()); + let expected_result = Result::Err::<&mut u32, &mut String>(&mut expected_string); assert_eq!(mut_err.as_deref_mut(), expected_result); let mut expected_vec = vec![5, 4, 3, 2, 1]; let mut_err = &mut Result::Err::<&mut u32, Vec>(expected_vec.clone()); - let expected_result = Result::Err::<&mut u32, &mut [i32]>(expected_vec.as_mut_slice()); + let expected_result = Result::Err::<&mut u32, &mut Vec>(&mut expected_vec); assert_eq!(mut_err.as_deref_mut(), expected_result); // The following cases test calling `as_deref_mut_*` with the wrong variant (i.e. - // `as_deref_mut_ok()` with a `Result::Err()`, or `as_deref_mut_err()` with a `Result::Ok()`. + // `as_deref_mut()` with a `Result::Err()`, or `as_deref_mut_err()` with a `Result::Ok()`. // While uncommon, these cases are supported to ensure that an `as_deref_mut_*` // call can still be made even when one of the Result types does not implement // `Deref` (for example, std::io::Error). @@ -426,22 +395,22 @@ fn test_result_as_deref_mut() { let expected_result = Result::Ok::<&mut [i32; 5], &mut u32>(&mut expected_arr); assert_eq!(mut_ok.as_deref_mut_err(), expected_result); - // &mut Result::Err(E).as_deref_mut_ok() -> + // &mut Result::Err(E).as_deref_mut() -> // Result<&mut T::Deref::Target, &mut E>::Err(&mut E) let mut expected_val = 41; let mut_err = &mut Result::Err::<&mut u8, i32>(expected_val.clone()); let expected_result = Result::Err::<&mut u8, &mut i32>(&mut expected_val); - assert_eq!(mut_err.as_deref_mut_ok(), expected_result); + assert_eq!(mut_err.as_deref_mut(), expected_result); let string = String::from("an error"); let expected_string = string.clone(); let mut ref_str = expected_string.as_ref(); let mut_err = &mut Result::Err::<&mut u32, &str>(string.as_str()); let expected_result = Result::Err::<&mut u32, &mut &str>(&mut ref_str); - assert_eq!(mut_err.as_deref_mut_ok(), expected_result); + assert_eq!(mut_err.as_deref_mut(), expected_result); let mut expected_arr = [5, 4, 3, 2, 1]; let mut_err = &mut Result::Err::<&mut u32, [i32; 5]>(expected_arr.clone()); let expected_result = Result::Err::<&mut u32, &mut [i32; 5]>(&mut expected_arr); - assert_eq!(mut_err.as_deref_mut_ok(), expected_result); + assert_eq!(mut_err.as_deref_mut(), expected_result); } diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 0b74a104da44b..c51db695a5b15 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -21,7 +21,6 @@ #![feature(nll)] #![feature(staged_api)] #![feature(allow_internal_unstable)] -#![feature(const_fn)] #![feature(decl_macro)] #![feature(extern_types)] #![feature(in_band_lifetimes)] diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index cf424ffe7b293..3c0160a04527e 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -31,7 +31,6 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(const_fn)] #![feature(const_transmute)] #![feature(core_intrinsics)] #![feature(drain_filter)] diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs index ee020c7e589ab..9a229e709a5e5 100644 --- a/src/librustc_ast_lowering/expr.rs +++ b/src/librustc_ast_lowering/expr.rs @@ -202,7 +202,12 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::Mac(_) => panic!("Shouldn't exist here"), }; - hir::Expr { hir_id: self.lower_node_id(e.id), kind, span: e.span, attrs: e.attrs.clone() } + hir::Expr { + hir_id: self.lower_node_id(e.id), + kind, + span: e.span, + attrs: e.attrs.iter().map(|a| self.lower_attr(a)).collect::>().into(), + } } fn lower_unop(&mut self, u: UnOp) -> hir::UnOp { diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index 1e396d6fe8e47..e6f4535a38dba 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -8,37 +8,25 @@ use rustc_span::Span; use syntax::ast::{self, AssocTyConstraint, AssocTyConstraintKind, NodeId}; use syntax::ast::{GenericParam, GenericParamKind, PatKind, RangeEnd, VariantData}; use syntax::attr; -use syntax::sess::{feature_err, leveled_feature_err, GateStrength, ParseSess}; +use syntax::sess::{feature_err, feature_err_issue, ParseSess}; use syntax::visit::{self, FnKind, Visitor}; use log::debug; macro_rules! gate_feature_fn { - ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{ - let (cx, has_feature, span, name, explain, level) = - (&*$cx, $has_feature, $span, $name, $explain, $level); + ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{ + let (cx, has_feature, span, name, explain) = (&*$cx, $has_feature, $span, $name, $explain); let has_feature: bool = has_feature(&$cx.features); debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature); if !has_feature && !span.allows_unstable($name) { - leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level) - .emit(); + feature_err_issue(cx.parse_sess, name, span, GateIssue::Language, explain).emit(); } }}; } -macro_rules! gate_feature { +macro_rules! gate_feature_post { ($cx: expr, $feature: ident, $span: expr, $explain: expr) => { - gate_feature_fn!( - $cx, - |x: &Features| x.$feature, - $span, - sym::$feature, - $explain, - GateStrength::Hard - ) - }; - ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => { - gate_feature_fn!($cx, |x: &Features| x.$feature, $span, sym::$feature, $explain, $level) + gate_feature_fn!($cx, |x: &Features| x.$feature, $span, sym::$feature, $explain) }; } @@ -51,21 +39,6 @@ struct PostExpansionVisitor<'a> { features: &'a Features, } -macro_rules! gate_feature_post { - ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{ - let (cx, span) = ($cx, $span); - if !span.allows_unstable(sym::$feature) { - gate_feature!(cx, $feature, span, $explain) - } - }}; - ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{ - let (cx, span) = ($cx, $span); - if !span.allows_unstable(sym::$feature) { - gate_feature!(cx, $feature, span, $explain, $level) - } - }}; -} - impl<'a> PostExpansionVisitor<'a> { fn check_abi(&self, abi: ast::StrLit) { let ast::StrLit { symbol_unescaped, span, .. } = abi; @@ -257,7 +230,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).map(|a| **a); // Check feature gates for built-in attributes. if let Some((.., AttributeGate::Gated(_, name, descr, has_feature))) = attr_info { - gate_feature_fn!(self, has_feature, attr.span, name, descr, GateStrength::Hard); + gate_feature_fn!(self, has_feature, attr.span, name, descr); } // Check unstable flavors of the `#[doc]` attribute. if attr.check_name(sym::doc) { @@ -265,7 +238,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { macro_rules! gate_doc { ($($name:ident => $feature:ident)*) => { $(if nested_meta.check_name(sym::$name) { let msg = concat!("`#[doc(", stringify!($name), ")]` is experimental"); - gate_feature!(self, $feature, attr.span, msg); + gate_feature_post!(self, $feature, attr.span, msg); })* }} @@ -666,7 +639,7 @@ pub fn check_crate( macro_rules! gate_all { ($gate:ident, $msg:literal) => { for span in spans.get(&sym::$gate).unwrap_or(&vec![]) { - gate_feature!(&visitor, $gate, *span, $msg); + gate_feature_post!(&visitor, $gate, *span, $msg); } }; } @@ -688,7 +661,7 @@ pub fn check_crate( // disabling these uses of early feature-gatings. if false { for span in spans.get(&sym::$gate).unwrap_or(&vec![]) { - gate_feature!(&visitor, $gate, *span, $msg); + gate_feature_post!(&visitor, $gate, *span, $msg); } } }; diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index cb44a56d07516..d3b524c1a1e70 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -13,7 +13,7 @@ //! but one `llvm::Type` corresponds to many `Ty`s; for instance, `tup(int, int, //! int)` and `rec(x=int, y=int, z=int)` will have the same `llvm::Type`. -use super::{LlvmCodegenBackend, ModuleLlvm}; +use super::ModuleLlvm; use crate::builder::Builder; use crate::common; @@ -29,7 +29,6 @@ use rustc::middle::exported_symbols; use rustc::mir::mono::{Linkage, Visibility}; use rustc::session::config::DebugInfo; use rustc::ty::TyCtxt; -use rustc_codegen_ssa::back::write::submit_codegened_module_to_llvm; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_codegen_ssa::traits::*; @@ -100,8 +99,7 @@ pub fn iter_globals(llmod: &'ll llvm::Module) -> ValueIter<'ll> { pub fn compile_codegen_unit( tcx: TyCtxt<'tcx>, cgu_name: Symbol, - tx_to_llvm_workers: &std::sync::mpsc::Sender>, -) { +) -> (ModuleCodegen, u64) { let prof_timer = tcx.prof.generic_activity("codegen_module"); let start_time = Instant::now(); @@ -115,8 +113,6 @@ pub fn compile_codegen_unit( // the time we needed for codegenning it. let cost = time_to_codegen.as_secs() * 1_000_000_000 + time_to_codegen.subsec_nanos() as u64; - submit_codegened_module_to_llvm(&LlvmCodegenBackend(()), tx_to_llvm_workers, module, cost); - fn module_codegen(tcx: TyCtxt<'_>, cgu_name: Symbol) -> ModuleCodegen { let cgu = tcx.codegen_unit(cgu_name); // Instantiate monomorphizations without filling out definitions yet... @@ -164,6 +160,8 @@ pub fn compile_codegen_unit( kind: ModuleKind::Regular, } } + + (module, cost) } pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) { diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 35c71a6675683..a6168128c4d44 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -19,6 +19,7 @@ #![feature(link_args)] #![feature(static_nobundle)] #![feature(trusted_len)] +#![recursion_limit = "256"] use back::write::{create_informational_target_machine, create_target_machine}; use rustc_span::symbol::Symbol; @@ -108,9 +109,8 @@ impl ExtraBackendMethods for LlvmCodegenBackend { &self, tcx: TyCtxt<'_>, cgu_name: Symbol, - tx: &std::sync::mpsc::Sender>, - ) { - base::compile_codegen_unit(tcx, cgu_name, tx); + ) -> (ModuleCodegen, u64) { + base::compile_codegen_unit(tcx, cgu_name) } fn target_machine_factory( &self, diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index ab5d67e57831b..efd560071202c 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -14,8 +14,8 @@ //! int)` and `rec(x=int, y=int, z=int)` will have the same `llvm::Type`. use crate::back::write::{ - start_async_codegen, submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm, - OngoingCodegen, + start_async_codegen, submit_codegened_module_to_llvm, submit_post_lto_module_to_llvm, + submit_pre_lto_module_to_llvm, OngoingCodegen, }; use crate::common::{IntPredicate, RealPredicate, TypeKind}; use crate::meth; @@ -40,6 +40,7 @@ use rustc::ty::{self, Instance, Ty, TyCtxt}; use rustc_codegen_utils::{check_for_rustc_errors_attr, symbol_names_test}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::profiling::print_time_passes_entry; +use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_index::vec::Idx; @@ -606,20 +607,83 @@ pub fn codegen_crate( codegen_units }; - let mut total_codegen_time = Duration::new(0, 0); + let total_codegen_time = Lock::new(Duration::new(0, 0)); - for cgu in codegen_units.into_iter() { + // The non-parallel compiler can only translate codegen units to LLVM IR + // on a single thread, leading to a staircase effect where the N LLVM + // threads have to wait on the single codegen threads to generate work + // for them. The parallel compiler does not have this restriction, so + // we can pre-load the LLVM queue in parallel before handing off + // coordination to the OnGoingCodegen scheduler. + // + // This likely is a temporary measure. Once we don't have to support the + // non-parallel compiler anymore, we can compile CGUs end-to-end in + // parallel and get rid of the complicated scheduling logic. + let pre_compile_cgus = |cgu_reuse: &[CguReuse]| { + if cfg!(parallel_compiler) { + tcx.sess.time("compile_first_CGU_batch", || { + // Try to find one CGU to compile per thread. + let cgus: Vec<_> = cgu_reuse + .iter() + .enumerate() + .filter(|&(_, reuse)| reuse == &CguReuse::No) + .take(tcx.sess.threads()) + .collect(); + + // Compile the found CGUs in parallel. + par_iter(cgus) + .map(|(i, _)| { + let start_time = Instant::now(); + let module = backend.compile_codegen_unit(tcx, codegen_units[i].name()); + let mut time = total_codegen_time.lock(); + *time += start_time.elapsed(); + (i, module) + }) + .collect() + }) + } else { + FxHashMap::default() + } + }; + + let mut cgu_reuse = Vec::new(); + let mut pre_compiled_cgus: Option> = None; + + for (i, cgu) in codegen_units.iter().enumerate() { ongoing_codegen.wait_for_signal_to_codegen_item(); ongoing_codegen.check_for_errors(tcx.sess); - let cgu_reuse = determine_cgu_reuse(tcx, &cgu); + // Do some setup work in the first iteration + if pre_compiled_cgus.is_none() { + // Calculate the CGU reuse + cgu_reuse = tcx.sess.time("find_cgu_reuse", || { + codegen_units.iter().map(|cgu| determine_cgu_reuse(tcx, &cgu)).collect() + }); + // Pre compile some CGUs + pre_compiled_cgus = Some(pre_compile_cgus(&cgu_reuse)); + } + + let cgu_reuse = cgu_reuse[i]; tcx.sess.cgu_reuse_tracker.set_actual_reuse(&cgu.name().as_str(), cgu_reuse); match cgu_reuse { CguReuse::No => { - let start_time = Instant::now(); - backend.compile_codegen_unit(tcx, cgu.name(), &ongoing_codegen.coordinator_send); - total_codegen_time += start_time.elapsed(); + let (module, cost) = + if let Some(cgu) = pre_compiled_cgus.as_mut().unwrap().remove(&i) { + cgu + } else { + let start_time = Instant::now(); + let module = backend.compile_codegen_unit(tcx, cgu.name()); + let mut time = total_codegen_time.lock(); + *time += start_time.elapsed(); + module + }; + submit_codegened_module_to_llvm( + &backend, + &ongoing_codegen.coordinator_send, + module, + cost, + ); false } CguReuse::PreLto => { @@ -652,7 +716,11 @@ 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.into_inner(), + ); ::rustc_incremental::assert_module_sources::assert_module_sources(tcx); diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs index e0d0a2f32f331..bc3a75250bf70 100644 --- a/src/librustc_codegen_ssa/traits/backend.rs +++ b/src/librustc_codegen_ssa/traits/backend.rs @@ -1,5 +1,6 @@ use super::write::WriteBackendMethods; use super::CodegenObject; +use crate::ModuleCodegen; use rustc::middle::cstore::EncodedMetadata; use rustc::session::{config, Session}; @@ -10,7 +11,6 @@ use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_span::symbol::Symbol; use syntax::expand::allocator::AllocatorKind; -use std::sync::mpsc; use std::sync::Arc; pub trait BackendTypes { @@ -34,7 +34,7 @@ impl<'tcx, T> Backend<'tcx> for T where { } -pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Send { +pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Send + Sync { fn new_metadata(&self, sess: TyCtxt<'_>, mod_name: &str) -> Self::Module; fn write_compressed_metadata<'tcx>( &self, @@ -48,12 +48,13 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se mods: &mut Self::Module, kind: AllocatorKind, ); + /// This generates the codegen unit and returns it along with + /// a `u64` giving an estimate of the unit's processing cost. fn compile_codegen_unit( &self, tcx: TyCtxt<'_>, cgu_name: Symbol, - tx_to_llvm_workers: &mpsc::Sender>, - ); + ) -> (ModuleCodegen, u64); // If find_features is true this won't access `sess.crate_types` by assuming // that `is_pie_binary` is false. When we discover LLVM target features // `sess.crate_types` is uninitialized so we cannot access it. diff --git a/src/librustc_error_codes/error_codes/E0185.md b/src/librustc_error_codes/error_codes/E0185.md index f0ad2af144aa0..944a93ed14e6c 100644 --- a/src/librustc_error_codes/error_codes/E0185.md +++ b/src/librustc_error_codes/error_codes/E0185.md @@ -2,7 +2,7 @@ An associated function for a trait was defined to be static, but an implementation of the trait declared the same function to be a method (i.e., to take a `self` parameter). -Here's an example of this error: +Erroneous code example: ```compile_fail,E0185 trait Foo { @@ -17,3 +17,19 @@ impl Foo for Bar { fn foo(&self) {} } ``` + +When a type implements a trait's associated function, it has to use the same +signature. So in this case, since `Foo::foo` does not take any argument and +does not return anything, its implementation on `Bar` should be the same: + +``` +trait Foo { + fn foo(); +} + +struct Bar; + +impl Foo for Bar { + fn foo() {} // ok! +} +``` diff --git a/src/librustc_hir/lib.rs b/src/librustc_hir/lib.rs index 66494d0fa736c..f54fa291bd6e8 100644 --- a/src/librustc_hir/lib.rs +++ b/src/librustc_hir/lib.rs @@ -3,7 +3,7 @@ //! [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html #![feature(crate_visibility_modifier)] -#![feature(const_fn)] +#![feature(const_fn)] // For the unsizing cast on `&[]` #![feature(in_band_lifetimes)] #![feature(specialization)] #![recursion_limit = "256"] diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 36c6568029d5f..d2565bf9c63d4 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -13,7 +13,6 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(box_syntax)] #![feature(crate_visibility_modifier)] #![feature(core_intrinsics)] -#![feature(const_fn)] #![feature(decl_macro)] #![feature(drain_filter)] #![feature(exhaustive_patterns)] diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 41fbfd22e50af..511a5fbc61795 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -194,7 +194,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIdMap, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_index::bit_set::GrowableBitSet; - +use smallvec::SmallVec; use std::iter; #[derive(PartialEq)] @@ -227,12 +227,7 @@ impl<'tcx> InliningMap<'tcx> { } } - fn record_accesses(&mut self, source: MonoItem<'tcx>, new_targets: I) - where - I: Iterator, bool)> + ExactSizeIterator, - { - assert!(!self.index.contains_key(&source)); - + fn record_accesses(&mut self, source: MonoItem<'tcx>, new_targets: &[(MonoItem<'tcx>, bool)]) { let start_index = self.targets.len(); let new_items_count = new_targets.len(); let new_items_count_total = new_items_count + self.targets.len(); @@ -240,15 +235,15 @@ impl<'tcx> InliningMap<'tcx> { self.targets.reserve(new_items_count); self.inlines.ensure(new_items_count_total); - for (i, (target, inline)) in new_targets.enumerate() { - self.targets.push(target); - if inline { + for (i, (target, inline)) in new_targets.iter().enumerate() { + self.targets.push(*target); + if *inline { self.inlines.insert(i + start_index); } } let end_index = self.targets.len(); - self.index.insert(source, (start_index, end_index)); + assert!(self.index.insert(source, (start_index, end_index)).is_none()); } // Internally iterate over all items referenced by `source` which will be @@ -403,10 +398,15 @@ fn record_accesses<'tcx>( mono_item.instantiation_mode(tcx) == InstantiationMode::LocalCopy }; - let accesses = - callees.into_iter().map(|mono_item| (*mono_item, is_inlining_candidate(mono_item))); + // We collect this into a `SmallVec` to avoid calling `is_inlining_candidate` in the lock. + // FIXME: Call `is_inlining_candidate` when pushing to `neighbors` in `collect_items_rec` + // instead to avoid creating this `SmallVec`. + let accesses: SmallVec<[_; 128]> = callees + .into_iter() + .map(|mono_item| (*mono_item, is_inlining_candidate(mono_item))) + .collect(); - inlining_map.lock_mut().record_accesses(caller, accesses); + inlining_map.lock_mut().record_accesses(caller, &accesses); } fn check_recursion_limit<'tcx>( diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 8fa41cab19076..0def51a6a33e5 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -104,6 +104,7 @@ use rustc::ty::print::characteristic_def_id_of_type; use rustc::ty::query::Providers; use rustc::ty::{self, DefIdTree, InstanceDef, TyCtxt}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::sync; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_span::symbol::Symbol; @@ -796,6 +797,8 @@ where I: Iterator>, 'tcx: 'a, { + let _prof_timer = tcx.prof.generic_activity("assert_symbols_are_distinct"); + let mut symbols: Vec<_> = mono_items.map(|mono_item| (mono_item, mono_item.symbol_name(tcx))).collect(); @@ -869,18 +872,23 @@ fn collect_and_partition_mono_items( tcx.sess.abort_if_errors(); - assert_symbols_are_distinct(tcx, items.iter()); - - let strategy = if tcx.sess.opts.incremental.is_some() { - PartitioningStrategy::PerModule - } else { - PartitioningStrategy::FixedUnitCount(tcx.sess.codegen_units()) - }; - - let codegen_units = partition(tcx, items.iter().cloned(), strategy, &inlining_map) - .into_iter() - .map(Arc::new) - .collect::>(); + let (codegen_units, _) = tcx.sess.time("partition_and_assert_distinct_symbols", || { + sync::join( + || { + let strategy = if tcx.sess.opts.incremental.is_some() { + PartitioningStrategy::PerModule + } else { + PartitioningStrategy::FixedUnitCount(tcx.sess.codegen_units()) + }; + + partition(tcx, items.iter().cloned(), strategy, &inlining_map) + .into_iter() + .map(Arc::new) + .collect::>() + }, + || assert_symbols_are_distinct(tcx, items.iter()), + ) + }); let mono_items: DefIdSet = items .iter() diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index fcdabb29cd0e2..c2c1625001d0f 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -281,8 +281,22 @@ fn check_place( Ok(()) } -/// Returns whether `allow_internal_unstable(..., , ...)` is present. +/// Returns `true` if the given feature gate is allowed within the function with the given `DefId`. fn feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bool { + // All features require that the corresponding gate be enabled, + // even if the function has `#[allow_internal_unstable(the_gate)]`. + if !tcx.features().enabled(feature_gate) { + return false; + } + + // If this crate is not using stability attributes, or this function is not claiming to be a + // stable `const fn`, that is all that is required. + if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) { + return true; + } + + // However, we cannot allow stable `const fn`s to use unstable features without an explicit + // opt-in via `allow_internal_unstable`. attr::allow_internal_unstable(&tcx.get_attrs(def_id), &tcx.sess.diagnostic()) .map_or(false, |mut features| features.any(|name| name == feature_gate)) } diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index b0c78ad7e4bcc..dd2b6ab997196 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1966,7 +1966,7 @@ impl<'a> Parser<'a> { limits: RangeLimits, ) -> PResult<'a, ExprKind> { if end.is_none() && limits == RangeLimits::Closed { - self.error_inclusive_range_with_no_end(self.token.span); + self.error_inclusive_range_with_no_end(self.prev_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 50756ddec9f2d..0c2cfc20daf0f 100644 --- a/src/librustc_parse/parser/pat.rs +++ b/src/librustc_parse/parser/pat.rs @@ -661,14 +661,34 @@ impl<'a> Parser<'a> { 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`)") + .span_suggestion_short( + span, + "use `..` instead", + "..".to_string(), + Applicability::MachineApplicable, + ) + .note("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)") .emit(); } - /// 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> { + /// Parse a range-to pattern, `..X` or `..=X` where `X` remains to be parsed. + /// + /// The form `...X` is prohibited to reduce confusion with the potential + /// expression syntax `...expr` for splatting in expressions. + fn parse_pat_range_to(&mut self, mut 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)); + if let RangeEnd::Included(ref mut syn @ RangeSyntax::DotDotDot) = &mut re.node { + *syn = RangeSyntax::DotDotEq; + self.struct_span_err(re.span, "range-to patterns with `...` are not allowed") + .span_suggestion_short( + re.span, + "use `..=` instead", + "..=".to_string(), + Applicability::MachineApplicable, + ) + .emit(); + } Ok(PatKind::Range(None, Some(end), re)) } diff --git a/src/librustc_session/parse.rs b/src/librustc_session/parse.rs index 946e77d35595e..a98cf929095ea 100644 --- a/src/librustc_session/parse.rs +++ b/src/librustc_session/parse.rs @@ -62,16 +62,6 @@ impl GatedSpans { } } -/// The strenght of a feature gate. -/// Either it is a `Hard` error, or only a `Soft` warning. -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum GateStrength { - /// A hard error. (Most feature gates should use this.) - Hard, - /// Only a warning. (Use this only as backwards-compatibility demands.) - Soft, -} - /// Construct a diagnostic for a language feature error due to the given `span`. /// The `feature`'s `Symbol` is the one you used in `active.rs` and `rustc_span::symbols`. pub fn feature_err<'a>( @@ -94,26 +84,7 @@ pub fn feature_err_issue<'a>( issue: GateIssue, explain: &str, ) -> DiagnosticBuilder<'a> { - leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard) -} - -/// Construct a diagnostic for a feature gate error / warning. -/// -/// You should typically just use `feature_err` instead. -pub fn leveled_feature_err<'a>( - sess: &'a ParseSess, - feature: Symbol, - span: impl Into, - issue: GateIssue, - explain: &str, - level: GateStrength, -) -> DiagnosticBuilder<'a> { - let diag = &sess.span_diagnostic; - - let mut err = match level { - GateStrength::Hard => diag.struct_span_err_with_code(span, explain, error_code!(E0658)), - GateStrength::Soft => diag.struct_span_warn(span, explain), - }; + let mut err = sess.span_diagnostic.struct_span_err_with_code(span, explain, error_code!(E0658)); if let Some(n) = find_feature_issue(feature, issue) { err.note(&format!( @@ -127,13 +98,6 @@ pub fn leveled_feature_err<'a>( err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature)); } - // If we're on stable and only emitting a "soft" warning, add a note to - // clarify that the feature isn't "on" (rather than being on but - // warning-worthy). - if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft { - err.help("a nightly build of the compiler is required to enable this feature"); - } - err } diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index 8cca59df33846..1dc7fc5aa3ad1 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -5,7 +5,6 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] -#![feature(const_fn)] #![feature(crate_visibility_modifier)] #![feature(nll)] #![feature(optin_builtin_traits)] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index b15dae452ff05..0fcbd4e0b58c6 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -12,7 +12,6 @@ #![feature(test)] #![feature(ptr_offset_from)] #![feature(crate_visibility_modifier)] -#![feature(const_fn)] #![feature(drain_filter)] #![feature(never_type)] #![feature(unicode_internals)] diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index a96fee0cf8f16..0184a3214b5b4 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -7,7 +7,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))] #![feature(bool_to_option)] #![feature(box_syntax)] -#![feature(const_fn)] +#![feature(const_fn)] // For the `transmute` in `P::new` #![feature(const_transmute)] #![feature(crate_visibility_modifier)] #![feature(label_break_value)] diff --git a/src/test/ui/consts/const-mut-refs/const_mut_refs.rs b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs index 33abfec02a87a..99006a20b1bcb 100644 --- a/src/test/ui/consts/const-mut-refs/const_mut_refs.rs +++ b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs @@ -1,7 +1,6 @@ // run-pass #![feature(const_mut_refs)] -#![feature(const_fn)] struct Foo { x: usize diff --git a/src/test/ui/consts/control-flow/exhaustive-c-like-enum-match.rs b/src/test/ui/consts/control-flow/exhaustive-c-like-enum-match.rs index 7887fd12e5764..6bbbdd972a26c 100644 --- a/src/test/ui/consts/control-flow/exhaustive-c-like-enum-match.rs +++ b/src/test/ui/consts/control-flow/exhaustive-c-like-enum-match.rs @@ -3,7 +3,6 @@ // check-pass #![feature(const_if_match)] -#![feature(const_fn)] enum E { A, diff --git a/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr b/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr index 95096723b3c95..21e3f2af15ad6 100644 --- a/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr +++ b/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr @@ -1,5 +1,5 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/feature-gate-const-if-match.rs:109:1 + --> $DIR/feature-gate-const-if-match.rs:108:1 | LL | / fn main() { LL | | let _ = [0; { diff --git a/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs b/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs index e4b65257531fd..00576d50ac66b 100644 --- a/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs +++ b/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs @@ -6,7 +6,6 @@ #![feature(rustc_attrs)] #![cfg_attr(if_match, feature(const_if_match))] -#![feature(const_fn)] const _: i32 = if true { //[stock]~ ERROR `if` is not allowed in a `const` 5 diff --git a/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr b/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr index e846ee4ab6a41..d3c6a51923ffb 100644 --- a/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr +++ b/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr @@ -1,5 +1,5 @@ error[E0658]: `if` is not allowed in a `const` - --> $DIR/feature-gate-const-if-match.rs:11:16 + --> $DIR/feature-gate-const-if-match.rs:10:16 | LL | const _: i32 = if true { | ________________^ @@ -13,7 +13,7 @@ LL | | }; = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `if` is not allowed in a `const` - --> $DIR/feature-gate-const-if-match.rs:17:16 + --> $DIR/feature-gate-const-if-match.rs:16:16 | LL | const _: i32 = if let Some(true) = Some(false) { | ________________^ @@ -27,7 +27,7 @@ LL | | }; = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `match` is not allowed in a `const` - --> $DIR/feature-gate-const-if-match.rs:23:16 + --> $DIR/feature-gate-const-if-match.rs:22:16 | LL | const _: i32 = match 1 { | ________________^ @@ -41,7 +41,7 @@ LL | | }; = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `if` is not allowed in a `static` - --> $DIR/feature-gate-const-if-match.rs:30:13 + --> $DIR/feature-gate-const-if-match.rs:29:13 | LL | let x = if true { 0 } else { 1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -50,7 +50,7 @@ LL | let x = if true { 0 } else { 1 }; = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `match` is not allowed in a `static` - --> $DIR/feature-gate-const-if-match.rs:32:13 + --> $DIR/feature-gate-const-if-match.rs:31:13 | LL | let x = match x { 0 => 1, _ => 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -59,7 +59,7 @@ LL | let x = match x { 0 => 1, _ => 0 }; = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `if` is not allowed in a `static` - --> $DIR/feature-gate-const-if-match.rs:34:5 + --> $DIR/feature-gate-const-if-match.rs:33:5 | LL | if let Some(x) = Some(x) { x } else { 1 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -68,7 +68,7 @@ LL | if let Some(x) = Some(x) { x } else { 1 } = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `if` is not allowed in a `static mut` - --> $DIR/feature-gate-const-if-match.rs:39:13 + --> $DIR/feature-gate-const-if-match.rs:38:13 | LL | let x = if true { 0 } else { 1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | let x = if true { 0 } else { 1 }; = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `match` is not allowed in a `static mut` - --> $DIR/feature-gate-const-if-match.rs:41:13 + --> $DIR/feature-gate-const-if-match.rs:40:13 | LL | let x = match x { 0 => 1, _ => 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -86,7 +86,7 @@ LL | let x = match x { 0 => 1, _ => 0 }; = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `if` is not allowed in a `static mut` - --> $DIR/feature-gate-const-if-match.rs:43:5 + --> $DIR/feature-gate-const-if-match.rs:42:5 | LL | if let Some(x) = Some(x) { x } else { 1 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -95,7 +95,7 @@ LL | if let Some(x) = Some(x) { x } else { 1 } = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `if` is not allowed in a `const fn` - --> $DIR/feature-gate-const-if-match.rs:48:5 + --> $DIR/feature-gate-const-if-match.rs:47:5 | LL | if true { 5 } else { 6 } | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -104,7 +104,7 @@ LL | if true { 5 } else { 6 } = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `if` is not allowed in a `const fn` - --> $DIR/feature-gate-const-if-match.rs:52:5 + --> $DIR/feature-gate-const-if-match.rs:51:5 | LL | / if let Some(true) = a { LL | | 0 @@ -117,7 +117,7 @@ LL | | } = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `match` is not allowed in a `const fn` - --> $DIR/feature-gate-const-if-match.rs:60:5 + --> $DIR/feature-gate-const-if-match.rs:59:5 | LL | / match i { LL | | i if i > 10 => i, @@ -130,7 +130,7 @@ LL | | } = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `if` is not allowed in a `const fn` - --> $DIR/feature-gate-const-if-match.rs:91:17 + --> $DIR/feature-gate-const-if-match.rs:90:17 | LL | let x = if y { 0 } else { 1 }; | ^^^^^^^^^^^^^^^^^^^^^ @@ -139,7 +139,7 @@ LL | let x = if y { 0 } else { 1 }; = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `match` is not allowed in a `const fn` - --> $DIR/feature-gate-const-if-match.rs:93:17 + --> $DIR/feature-gate-const-if-match.rs:92:17 | LL | let x = match x { 0 => 1, _ => 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -148,7 +148,7 @@ LL | let x = match x { 0 => 1, _ => 0 }; = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `if` is not allowed in a `const fn` - --> $DIR/feature-gate-const-if-match.rs:95:9 + --> $DIR/feature-gate-const-if-match.rs:94:9 | LL | if let Some(x) = Some(x) { x } else { 1 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL | if let Some(x) = Some(x) { x } else { 1 } = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `if` is not allowed in a `const` - --> $DIR/feature-gate-const-if-match.rs:111:17 + --> $DIR/feature-gate-const-if-match.rs:110:17 | LL | let x = if false { 0 } else { 1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -166,7 +166,7 @@ LL | let x = if false { 0 } else { 1 }; = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `match` is not allowed in a `const` - --> $DIR/feature-gate-const-if-match.rs:113:17 + --> $DIR/feature-gate-const-if-match.rs:112:17 | LL | let x = match x { 0 => 1, _ => 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -175,7 +175,7 @@ LL | let x = match x { 0 => 1, _ => 0 }; = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `if` is not allowed in a `const` - --> $DIR/feature-gate-const-if-match.rs:115:9 + --> $DIR/feature-gate-const-if-match.rs:114:9 | LL | if let Some(x) = Some(x) { x } else { 1 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -184,7 +184,7 @@ LL | if let Some(x) = Some(x) { x } else { 1 } = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `if` is not allowed in a `const` - --> $DIR/feature-gate-const-if-match.rs:68:21 + --> $DIR/feature-gate-const-if-match.rs:67:21 | LL | const IF: i32 = if true { 5 } else { 6 }; | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -193,7 +193,7 @@ LL | const IF: i32 = if true { 5 } else { 6 }; = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `if` is not allowed in a `const` - --> $DIR/feature-gate-const-if-match.rs:71:25 + --> $DIR/feature-gate-const-if-match.rs:70:25 | LL | const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -202,7 +202,7 @@ LL | const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 }; = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `match` is not allowed in a `const` - --> $DIR/feature-gate-const-if-match.rs:74:24 + --> $DIR/feature-gate-const-if-match.rs:73:24 | LL | const MATCH: i32 = match 0 { 1 => 2, _ => 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -211,7 +211,7 @@ LL | const MATCH: i32 = match 0 { 1 => 2, _ => 0 }; = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `if` is not allowed in a `const` - --> $DIR/feature-gate-const-if-match.rs:79:21 + --> $DIR/feature-gate-const-if-match.rs:78:21 | LL | const IF: i32 = if true { 5 } else { 6 }; | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -220,7 +220,7 @@ LL | const IF: i32 = if true { 5 } else { 6 }; = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `if` is not allowed in a `const` - --> $DIR/feature-gate-const-if-match.rs:82:25 + --> $DIR/feature-gate-const-if-match.rs:81:25 | LL | const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -229,7 +229,7 @@ LL | const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 }; = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `match` is not allowed in a `const` - --> $DIR/feature-gate-const-if-match.rs:85:24 + --> $DIR/feature-gate-const-if-match.rs:84:24 | LL | const MATCH: i32 = match 0 { 1 => 2, _ => 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -238,7 +238,7 @@ LL | const MATCH: i32 = match 0 { 1 => 2, _ => 0 }; = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0019]: constant contains unimplemented expression type - --> $DIR/feature-gate-const-if-match.rs:115:21 + --> $DIR/feature-gate-const-if-match.rs:114:21 | LL | if let Some(x) = Some(x) { x } else { 1 } | ^ diff --git a/src/test/ui/consts/control-flow/short-circuit-let.rs b/src/test/ui/consts/control-flow/short-circuit-let.rs index 4b20a2124c356..8cee2a54f56d3 100644 --- a/src/test/ui/consts/control-flow/short-circuit-let.rs +++ b/src/test/ui/consts/control-flow/short-circuit-let.rs @@ -4,7 +4,6 @@ #![feature(const_if_match)] #![feature(const_panic)] -#![feature(const_fn)] const X: i32 = { let mut x = 0; diff --git a/src/test/ui/consts/control-flow/single_variant_match_ice.rs b/src/test/ui/consts/control-flow/single_variant_match_ice.rs index bb0fce66c4d89..823605ff034f1 100644 --- a/src/test/ui/consts/control-flow/single_variant_match_ice.rs +++ b/src/test/ui/consts/control-flow/single_variant_match_ice.rs @@ -1,6 +1,6 @@ // check-pass -#![feature(const_if_match, const_fn)] +#![feature(const_if_match)] enum Foo { Prob, diff --git a/src/test/ui/error-codes/E0586.stderr b/src/test/ui/error-codes/E0586.stderr index d1e7e3f47442f..0bbf9a6080349 100644 --- a/src/test/ui/error-codes/E0586.stderr +++ b/src/test/ui/error-codes/E0586.stderr @@ -1,10 +1,10 @@ error[E0586]: inclusive range with no end - --> $DIR/E0586.rs:3:22 + --> $DIR/E0586.rs:3:19 | LL | let x = &tmp[1..=]; - | ^ + | ^^^ help: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error: aborting due to previous error 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 index 4cb8230a7b620..1733012b9c54f 100644 --- 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 @@ -8,6 +8,7 @@ fn foo() { //~^ ERROR half-open range patterns are unstable if let ...5 = 0 {} //~^ ERROR half-open range patterns are unstable + //~| ERROR range-to patterns with `...` are not allowed if let ..5 = 0 {} //~^ ERROR half-open range patterns are unstable if let 5.. = 0 {} 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 index 68ba654de76da..99db339cf74e1 100644 --- 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 @@ -1,18 +1,24 @@ +error: range-to patterns with `...` are not allowed + --> $DIR/feature-gate-half-open-range-patterns.rs:9:12 + | +LL | if let ...5 = 0 {} + | ^^^ help: use `..=` instead + error[E0586]: inclusive range with no end - --> $DIR/feature-gate-half-open-range-patterns.rs:15:13 + --> $DIR/feature-gate-half-open-range-patterns.rs:16:13 | LL | if let 5..= = 0 {} - | ^^^ + | ^^^ help: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: 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 + --> $DIR/feature-gate-half-open-range-patterns.rs:19:13 | LL | if let 5... = 0 {} - | ^^^ + | ^^^ help: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: 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 @@ -33,7 +39,7 @@ LL | if let ...5 = 0 {} = 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 + --> $DIR/feature-gate-half-open-range-patterns.rs:12:12 | LL | if let ..5 = 0 {} | ^^^ @@ -42,7 +48,7 @@ LL | if let ..5 = 0 {} = 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 + --> $DIR/feature-gate-half-open-range-patterns.rs:14:12 | LL | if let 5.. = 0 {} | ^^^ @@ -51,7 +57,7 @@ LL | if let 5.. = 0 {} = 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 + --> $DIR/feature-gate-half-open-range-patterns.rs:16:12 | LL | if let 5..= = 0 {} | ^^^^ @@ -60,7 +66,7 @@ LL | if let 5..= = 0 {} = 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 + --> $DIR/feature-gate-half-open-range-patterns.rs:19:12 | LL | if let 5... = 0 {} | ^^^^ @@ -68,7 +74,7 @@ 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 +error: aborting due to 9 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-inclusive-dotdotdot-bad-syntax.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs new file mode 100644 index 0000000000000..daed775cf7c01 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs @@ -0,0 +1,32 @@ +// Test that `...X` range-to patterns are syntactically invalid. +// +// See https://github.com/rust-lang/rust/pull/67258#issuecomment-565656155 +// for the reason why. To summarize, we might want to introduce `...expr` as +// an expression form for splatting (or "untupling") in an expression context. +// While there is no syntactic ambiguity with `...X` in a pattern context, +// there's a potential confusion factor here, and we would prefer to keep patterns +// and expressions in-sync. As such, we do not allow `...X` in patterns either. + +#![feature(half_open_range_patterns)] + +fn main() {} + +#[cfg(FALSE)] +fn syntax() { + match scrutinee { + ...X => {} //~ ERROR range-to patterns with `...` are not allowed + ...0 => {} //~ ERROR range-to patterns with `...` are not allowed + ...'a' => {} //~ ERROR range-to patterns with `...` are not allowed + ...0.0f32 => {} //~ ERROR range-to patterns with `...` are not allowed + } +} + +fn syntax2() { + macro_rules! mac { + ($e:expr) => { + let ...$e; //~ ERROR range-to patterns with `...` are not allowed + } + } + + mac!(0); +} diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr new file mode 100644 index 0000000000000..ba2e7ea8b5354 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr @@ -0,0 +1,35 @@ +error: range-to patterns with `...` are not allowed + --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:17:9 + | +LL | ...X => {} + | ^^^ help: use `..=` instead + +error: range-to patterns with `...` are not allowed + --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:18:9 + | +LL | ...0 => {} + | ^^^ help: use `..=` instead + +error: range-to patterns with `...` are not allowed + --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:19:9 + | +LL | ...'a' => {} + | ^^^ help: use `..=` instead + +error: range-to patterns with `...` are not allowed + --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:20:9 + | +LL | ...0.0f32 => {} + | ^^^ help: use `..=` instead + +error: range-to patterns with `...` are not allowed + --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:27:17 + | +LL | let ...$e; + | ^^^ help: use `..=` instead +... +LL | mac!(0); + | -------- in this macro invocation + +error: aborting due to 5 previous errors + 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 index 03166e3675571..9ace0c357b2d4 100644 --- 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 @@ -13,3 +13,14 @@ fn foo() { if let X... = 1 {} //~ ERROR inclusive range with no end if let X..= = 1 {} //~ ERROR inclusive range with no end } + +fn bar() { + macro_rules! mac { + ($e:expr) => { + let $e...; //~ ERROR inclusive range with no end + let $e..=; //~ ERROR inclusive range with no end + } + } + + mac!(0); +} 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 index 2b4d95f684284..2bdb8ea57668a 100644 --- 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 @@ -2,34 +2,56 @@ error[E0586]: inclusive range with no end --> $DIR/half-open-range-pats-inclusive-no-end.rs:10:13 | LL | if let 0... = 1 {} - | ^^^ + | ^^^ help: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: 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: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: 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: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: 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: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: aborting due to 4 previous errors +error[E0586]: inclusive range with no end + --> $DIR/half-open-range-pats-inclusive-no-end.rs:20:19 + | +LL | let $e...; + | ^^^ help: use `..` instead +... +LL | mac!(0); + | -------- in this macro invocation + | + = note: 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:21:19 + | +LL | let $e..=; + | ^^^ help: use `..` instead +... +LL | mac!(0); + | -------- in this macro invocation + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +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-ref-ambiguous-interp.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs index e9a5361e63d27..f054bbea4e3e7 100644 --- 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 @@ -20,5 +20,7 @@ fn syntax() { &..=0 | _ => {} //~^ ERROR the range pattern here has ambiguous interpretation &...0 | _ => {} + //~^ ERROR the range pattern here has ambiguous interpretation + //~| ERROR range-to patterns with `...` are not allowed } } 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 index 5d3aded022224..a5f7c390627ba 100644 --- 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 @@ -8,9 +8,9 @@ error[E0586]: inclusive range with no end --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:10:11 | LL | &0..= | _ => {} - | ^^^ + | ^^^ help: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: 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 @@ -22,9 +22,9 @@ error[E0586]: inclusive range with no end --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:13:11 | LL | &0... | _ => {} - | ^^^ + | ^^^ help: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: 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 @@ -38,6 +38,18 @@ error: the range pattern here has ambiguous interpretation LL | &..=0 | _ => {} | ^^^^ help: add parentheses to clarify the precedence: `(..=0)` -error: aborting due to 6 previous errors +error: range-to patterns with `...` are not allowed + --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:22:10 + | +LL | &...0 | _ => {} + | ^^^ help: use `..=` instead + +error: the range pattern here has ambiguous interpretation + --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:22:10 + | +LL | &...0 | _ => {} + | ^^^^ help: add parentheses to clarify the precedence: `(..=0)` + +error: aborting due to 8 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-syntactic-pass.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs index a663acd2d191c..8bb98d3b5c56f 100644 --- 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 @@ -11,22 +11,20 @@ fn main() {} fn syntax() { match scrutinee { X.. | 0.. | 'a'.. | 0.0f32.. => {} - ..=X | ...X | ..X => {} - ..=0 | ...0 | ..0 => {} - ..='a' | ...'a' | ..'a' => {} - ..=0.0f32 | ...0.0f32 | ..0.0f32 => {} + ..=X | ..X => {} + ..=0 | ..0 => {} + ..='a' | ..'a' => {} + ..=0.0f32 | ..0.0f32 => {} } +} +fn syntax2() { macro_rules! mac { ($e:expr) => { - let ..$e; - let ...$e; - let ..=$e; - let $e..; - let $e...; - let $e..=; + match 0u8 { ..$e => {}, _ => {} } + match 0u8 { ..=$e => {}, _ => {} } + match 0u8 { $e.. => {}, _ => {} } } } - - mac!(0); + mac!(42u8); } diff --git a/src/test/ui/impossible_range.rs b/src/test/ui/impossible_range.rs index 6345af001112f..21e5c03eb1605 100644 --- a/src/test/ui/impossible_range.rs +++ b/src/test/ui/impossible_range.rs @@ -1,4 +1,4 @@ -// Make sure that invalid ranges generate an error during HIR lowering, not an ICE +// Make sure that invalid ranges generate an error during parsing, not an ICE pub fn main() { ..; @@ -6,12 +6,12 @@ pub fn main() { ..1; 0..1; ..=; //~ERROR inclusive range with no end - //~^HELP bounded at the end + //~^HELP use `..` instead } fn _foo1() { ..=1; 0..=1; 0..=; //~ERROR inclusive range with no end - //~^HELP bounded at the end + //~^HELP use `..` instead } diff --git a/src/test/ui/impossible_range.stderr b/src/test/ui/impossible_range.stderr index 091fe37c7a1f7..ea2ab0f299d1b 100644 --- a/src/test/ui/impossible_range.stderr +++ b/src/test/ui/impossible_range.stderr @@ -1,18 +1,18 @@ error[E0586]: inclusive range with no end - --> $DIR/impossible_range.rs:8:8 + --> $DIR/impossible_range.rs:8:5 | LL | ..=; - | ^ + | ^^^ help: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error[E0586]: inclusive range with no end - --> $DIR/impossible_range.rs:15:9 + --> $DIR/impossible_range.rs:15:6 | LL | 0..=; - | ^ + | ^^^ help: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error: aborting due to 2 previous errors diff --git a/src/test/ui/internal/internal-unstable-const.rs b/src/test/ui/internal/internal-unstable-const.rs new file mode 100644 index 0000000000000..ce306c845175a --- /dev/null +++ b/src/test/ui/internal/internal-unstable-const.rs @@ -0,0 +1,10 @@ +#![feature(staged_api)] +#![feature(const_if_match)] + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "rust1", since = "1.0.0")] +const fn foo() -> i32 { + if true { 4 } else { 5 } //~ loops and conditional expressions are not stable in const fn +} + +fn main() {} diff --git a/src/test/ui/internal/internal-unstable-const.stderr b/src/test/ui/internal/internal-unstable-const.stderr new file mode 100644 index 0000000000000..58bbe798b00b6 --- /dev/null +++ b/src/test/ui/internal/internal-unstable-const.stderr @@ -0,0 +1,12 @@ +error[E0723]: loops and conditional expressions are not stable in const fn + --> $DIR/internal-unstable-const.rs:7:5 + | +LL | if true { 4 } else { 5 } + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563 + = help: add `#![feature(const_fn)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0723`. diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr index 48a662e98b547..1d98361c46198 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref_err` found for enum `std::result::Result --> $DIR/result-as_deref_err.rs:4:28 | LL | let _result = &Err(41).as_deref_err(); - | ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_ok` + | ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut` | = note: the method `as_deref_err` exists but the following trait bounds were not satisfied: `{integer} : std::ops::Deref` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr index 8a5c2f4006051..950a050ea9f81 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref_mut_err` found for enum `std::result::Re --> $DIR/result-as_deref_mut_err.rs:4:32 | LL | let _result = &mut Err(41).as_deref_mut_err(); - | ^^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut_ok` + | ^^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut` | = note: the method `as_deref_mut_err` exists but the following trait bounds were not satisfied: `{integer} : std::ops::DerefMut` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.rs deleted file mode 100644 index 54b695a0865f1..0000000000000 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![feature(inner_deref)] - -fn main() { - let _result = &mut Ok(42).as_deref_mut_ok(); -//~^ ERROR no method named `as_deref_mut_ok` found -} diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr deleted file mode 100644 index af8d657999cb0..0000000000000 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0599]: no method named `as_deref_mut_ok` found for enum `std::result::Result<{integer}, _>` in the current scope - --> $DIR/result-as_deref_mut_ok.rs:4:31 - | -LL | let _result = &mut Ok(42).as_deref_mut_ok(); - | ^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut_err` - | - = note: the method `as_deref_mut_ok` exists but the following trait bounds were not satisfied: - `{integer} : std::ops::DerefMut` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.rs deleted file mode 100644 index ebb0500e8190f..0000000000000 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![feature(inner_deref)] - -fn main() { - let _result = &Ok(42).as_deref_ok(); -//~^ ERROR no method named `as_deref_ok` found -} diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr deleted file mode 100644 index 145e610d52c7c..0000000000000 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0599]: no method named `as_deref_ok` found for enum `std::result::Result<{integer}, _>` in the current scope - --> $DIR/result-as_deref_ok.rs:4:27 - | -LL | let _result = &Ok(42).as_deref_ok(); - | ^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_err` - | - = note: the method `as_deref_ok` exists but the following trait bounds were not satisfied: - `{integer} : std::ops::Deref` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/macros/issue-68058.rs b/src/test/ui/macros/issue-68058.rs new file mode 100644 index 0000000000000..24da2620c2eaf --- /dev/null +++ b/src/test/ui/macros/issue-68058.rs @@ -0,0 +1,14 @@ +// check-pass + +macro_rules! foo { + ($doc: expr) => { + fn f() { + #[doc = $doc] + () + } + }; +} + +foo!("doc"); + +fn main() {} 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 654b49ab62022..4775b9b7bc003 100644 --- a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr +++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr @@ -342,9 +342,9 @@ 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: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: 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:94:38 @@ -356,9 +356,9 @@ 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: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: 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:97:38 @@ -376,9 +376,9 @@ 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: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: 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:102:38 diff --git a/src/test/ui/parser/range_inclusive.rs b/src/test/ui/parser/range_inclusive.rs index bc61c5b49ea87..7c3b906b47f9f 100644 --- a/src/test/ui/parser/range_inclusive.rs +++ b/src/test/ui/parser/range_inclusive.rs @@ -2,5 +2,5 @@ pub fn main() { for _ in 1..= {} //~ERROR inclusive range with no end - //~^HELP bounded at the end + //~^HELP use `..` instead } diff --git a/src/test/ui/parser/range_inclusive.stderr b/src/test/ui/parser/range_inclusive.stderr index 12b7edae79f52..1dd4799459681 100644 --- a/src/test/ui/parser/range_inclusive.stderr +++ b/src/test/ui/parser/range_inclusive.stderr @@ -1,10 +1,10 @@ error[E0586]: inclusive range with no end - --> $DIR/range_inclusive.rs:4:19 + --> $DIR/range_inclusive.rs:4:15 | LL | for _ in 1..= {} - | ^ + | ^^^ help: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error: aborting due to previous error diff --git a/src/test/ui/parser/recover-range-pats.rs b/src/test/ui/parser/recover-range-pats.rs index a5aae2861b282..e07ea6221d7c9 100644 --- a/src/test/ui/parser/recover-range-pats.rs +++ b/src/test/ui/parser/recover-range-pats.rs @@ -107,15 +107,15 @@ fn inclusive_to() { fn inclusive2_to() { if let ...3 = 0 {} - //~^ ERROR `...` range patterns are deprecated + //~^ ERROR range-to patterns with `...` are not allowed if let ...Y = 0 {} - //~^ ERROR `...` range patterns are deprecated + //~^ ERROR range-to patterns with `...` are not allowed if let ...true = 0 {} - //~^ ERROR `...` range patterns are deprecated + //~^ ERROR range-to patterns with `...` are not allowed //~| ERROR only char and numeric types if let ....3 = 0 {} //~^ ERROR float literals must have an integer part - //~| ERROR `...` range patterns are deprecated + //~| ERROR range-to patterns with `...` are not allowed //~| ERROR mismatched types } @@ -135,7 +135,7 @@ fn with_macro_expr_var() { ($e:expr) => { let ..$e; let ...$e; - //~^ ERROR `...` range patterns are deprecated + //~^ ERROR range-to patterns with `...` are not allowed let ..=$e; let $e..; 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 d3d3169022a65..f43f9bf301218 100644 --- a/src/test/ui/parser/recover-range-pats.stderr +++ b/src/test/ui/parser/recover-range-pats.stderr @@ -44,25 +44,25 @@ error[E0586]: inclusive range with no end --> $DIR/recover-range-pats.rs:69:13 | LL | if let 0..= = 0 {} - | ^^^ + | ^^^ help: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error[E0586]: inclusive range with no end --> $DIR/recover-range-pats.rs:70:13 | LL | if let X..= = 0 {} - | ^^^ + | ^^^ help: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error[E0586]: inclusive range with no end --> $DIR/recover-range-pats.rs:71:16 | LL | if let true..= = 0 {} - | ^^^ + | ^^^ help: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: 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:73:12 @@ -74,33 +74,33 @@ error[E0586]: inclusive range with no end --> $DIR/recover-range-pats.rs:73:14 | LL | if let .0..= = 0 {} - | ^^^ + | ^^^ help: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error[E0586]: inclusive range with no end --> $DIR/recover-range-pats.rs:79:13 | LL | if let 0... = 0 {} - | ^^^ + | ^^^ help: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error[E0586]: inclusive range with no end --> $DIR/recover-range-pats.rs:80:13 | LL | if let X... = 0 {} - | ^^^ + | ^^^ help: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error[E0586]: inclusive range with no end --> $DIR/recover-range-pats.rs:81:16 | LL | if let true... = 0 {} - | ^^^ + | ^^^ help: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: 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:83:12 @@ -112,9 +112,9 @@ error[E0586]: inclusive range with no end --> $DIR/recover-range-pats.rs:83:14 | LL | if let .0... = 0 {} - | ^^^ + | ^^^ help: use `..` instead | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: 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:93:15 @@ -128,33 +128,66 @@ error: float literals must have an integer part LL | if let ..=.0 = 0 {} | ^^ help: must have an integer part: `0.0` +error: range-to patterns with `...` are not allowed + --> $DIR/recover-range-pats.rs:109:12 + | +LL | if let ...3 = 0 {} + | ^^^ help: use `..=` instead + +error: range-to patterns with `...` are not allowed + --> $DIR/recover-range-pats.rs:111:12 + | +LL | if let ...Y = 0 {} + | ^^^ help: use `..=` instead + +error: range-to patterns with `...` are not allowed + --> $DIR/recover-range-pats.rs:113:12 + | +LL | if let ...true = 0 {} + | ^^^ help: use `..=` instead + error: float literals must have an integer part --> $DIR/recover-range-pats.rs:116:15 | LL | if let ....3 = 0 {} | ^^ help: must have an integer part: `0.3` +error: range-to patterns with `...` are not allowed + --> $DIR/recover-range-pats.rs:116:12 + | +LL | if let ....3 = 0 {} + | ^^^ help: use `..=` instead + +error: range-to patterns with `...` are not allowed + --> $DIR/recover-range-pats.rs:137:17 + | +LL | let ...$e; + | ^^^ help: use `..=` instead +... +LL | mac!(0); + | -------- in this macro invocation + error[E0586]: inclusive range with no end --> $DIR/recover-range-pats.rs:141:19 | LL | let $e...; - | ^^^ + | ^^^ help: use `..` instead ... LL | mac!(0); | -------- in this macro invocation | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error[E0586]: inclusive range with no end --> $DIR/recover-range-pats.rs:142:19 | LL | let $e..=; - | ^^^ + | ^^^ help: use `..` instead ... LL | mac!(0); | -------- in this macro invocation | - = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error: `...` range patterns are deprecated --> $DIR/recover-range-pats.rs:42:13 @@ -210,30 +243,6 @@ error: `...` range patterns are deprecated LL | if let X... .0 = 0 {} | ^^^ help: use `..=` for an inclusive range -error: `...` range patterns are deprecated - --> $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:111:12 - | -LL | if let ...Y = 0 {} - | ^^^ help: use `..=` for an inclusive range - -error: `...` range patterns are deprecated - --> $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:116:12 - | -LL | if let ....3 = 0 {} - | ^^^ help: use `..=` for an inclusive range - error: `...` range patterns are deprecated --> $DIR/recover-range-pats.rs:126:20 | @@ -243,15 +252,6 @@ LL | let $e1...$e2; LL | mac2!(0, 1); | ------------ in this macro invocation -error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:137:17 - | -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:20:12 |