diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 5fdc6e0092064..e4c1cdb79fd24 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -610,7 +610,6 @@ static HOST_COMPILETESTS: &[Test] = &[ mode: "incremental", suite: "incremental-fulldeps", }, - Test { path: "src/test/run-make", mode: "run-make", suite: "run-make" }, Test { path: "src/test/rustdoc", mode: "rustdoc", suite: "rustdoc" }, Test { path: "src/test/pretty", mode: "pretty", suite: "pretty" }, @@ -619,6 +618,7 @@ static HOST_COMPILETESTS: &[Test] = &[ Test { path: "src/test/run-pass-valgrind/pretty", mode: "pretty", suite: "run-pass-valgrind" }, Test { path: "src/test/run-pass-fulldeps/pretty", mode: "pretty", suite: "run-pass-fulldeps" }, Test { path: "src/test/run-fail-fulldeps/pretty", mode: "pretty", suite: "run-fail-fulldeps" }, + Test { path: "src/test/run-make", mode: "run-make", suite: "run-make" }, ]; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] diff --git a/src/doc/unstable-book/src/language-features/match-beginning-vert.md b/src/doc/unstable-book/src/language-features/match-beginning-vert.md deleted file mode 100644 index f0a51af7fd1c8..0000000000000 --- a/src/doc/unstable-book/src/language-features/match-beginning-vert.md +++ /dev/null @@ -1,23 +0,0 @@ -# `match_beginning_vert` - -The tracking issue for this feature is [#44101]. - -With this feature enabled, you are allowed to add a '|' to the beginning of a -match arm: - -```rust -#![feature(match_beginning_vert)] - -enum Foo { A, B, C } - -fn main() { - let x = Foo::A; - match x { - | Foo::A - | Foo::B => println!("AB"), - | Foo::C => println!("C"), - } -} -``` - -[#44101]: https://github.com/rust-lang/rust/issues/44101 \ No newline at end of file diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 338e5c7fd95b4..566bfe2a3fb5e 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -367,9 +367,36 @@ impl TypeId { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(stage0)] pub fn of() -> TypeId { TypeId { t: unsafe { intrinsics::type_id::() }, } } + + /// Returns the `TypeId` of the type this generic function has been + /// instantiated with. + /// + /// # Examples + /// + /// ``` + /// use std::any::{Any, TypeId}; + /// + /// fn is_string(_s: &T) -> bool { + /// TypeId::of::() == TypeId::of::() + /// } + /// + /// fn main() { + /// assert_eq!(is_string(&0), false); + /// assert_eq!(is_string(&"cookie monster".to_string()), true); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature="const_type_id")] + #[cfg(not(stage0))] + pub const fn of() -> TypeId { + TypeId { + t: unsafe { intrinsics::type_id::() }, + } + } } diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 2e1f925c49a36..59a296c2a762c 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -91,6 +91,7 @@ #![feature(untagged_unions)] #![feature(unwind_attributes)] #![feature(doc_spotlight)] +#![feature(rustc_const_unstable)] #[prelude_import] #[allow(unused)] diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 3b644aa13f321..c0feb8ad02078 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1825,7 +1825,7 @@ pub struct Location { /// the location is within this block pub block: BasicBlock, - /// the location is the start of the this statement; or, if `statement_index` + /// the location is the start of the statement; or, if `statement_index` /// == num-statements, then the start of the terminator. pub statement_index: usize, } diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 1d2813e4f6704..8e4ec93c14bae 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -327,6 +327,10 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, return Ok(mk_const(Integral(Usize(ConstUsize::new(align, tcx.sess.target.usize_ty).unwrap())))); } + "type_id" => { + let type_id = tcx.type_id_hash(substs.type_at(0)); + return Ok(mk_const(Integral(U64(type_id)))); + } _ => signal!(e, TypeckError) } } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index ef6475f9ee4c7..56f863ab3aa84 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -302,19 +302,38 @@ impl EarlyLintPass for UnusedParens { Assign(_, ref value) => (value, "assigned value", false), AssignOp(.., ref value) => (value, "assigned value", false), InPlace(_, ref value) => (value, "emplacement value", false), - Call(_, ref args) => { - for arg in args { - self.check_unused_parens_core(cx, arg, "function argument", false) + // either function/method call, or something this lint doesn't care about + ref call_or_other => { + let args_to_check; + let call_kind; + match *call_or_other { + Call(_, ref args) => { + call_kind = "function"; + args_to_check = &args[..]; + }, + MethodCall(_, ref args) => { + call_kind = "method"; + // first "argument" is self (which sometimes needs parens) + args_to_check = &args[1..]; + } + // actual catch-all arm + _ => { return; } } - return; - }, - MethodCall(_, ref args) => { - for arg in &args[1..] { // first "argument" is self (which sometimes needs parens) - self.check_unused_parens_core(cx, arg, "method argument", false) + // Don't lint if this is a nested macro expansion: otherwise, the lint could + // trigger in situations that macro authors shouldn't have to care about, e.g., + // when a parenthesized token tree matched in one macro expansion is matched as + // an expression in another and used as a fn/method argument (Issue #47775) + if e.span.ctxt().outer().expn_info() + .map_or(false, |info| info.call_site.ctxt().outer() + .expn_info().is_some()) { + return; + } + let msg = format!("{} argument", call_kind); + for arg in args_to_check { + self.check_unused_parens_core(cx, arg, &msg, false); } return; } - _ => return, }; self.check_unused_parens_core(cx, &value, msg, struct_lit_needs_parens); } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index fb2ab43fbbb3a..c0c680a4ddcbc 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -374,13 +374,20 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { } }; if let PlaceContext::Copy = context { - let ty = place_ty.to_ty(self.tcx()); - if self.cx - .infcx - .type_moves_by_default(self.cx.param_env, ty, DUMMY_SP) - { - span_mirbug!(self, place, "attempted copy of non-Copy type ({:?})", ty); - } + let tcx = self.tcx(); + let trait_ref = ty::TraitRef { + def_id: tcx.lang_items().copy_trait().unwrap(), + substs: tcx.mk_substs_trait(place_ty.to_ty(tcx), &[]), + }; + + // In order to have a Copy operand, the type T of the value must be Copy. Note that we + // prove that T: Copy, rather than using the type_moves_by_default test. This is + // important because type_moves_by_default ignores the resulting region obligations and + // assumes they pass. This can result in bounds from Copy impls being unsoundly ignored + // (e.g., #29149). Note that we decide to use Copy before knowing whether the bounds + // fully apply: in effect, the rule is that if a value of some type could implement + // Copy, then it must. + self.cx.prove_trait_ref(trait_ref, location); } place_ty } diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs index 2913f72460e3e..d3b084fde6ab8 100644 --- a/src/librustc_mir/interpret/const_eval.rs +++ b/src/librustc_mir/interpret/const_eval.rs @@ -243,6 +243,12 @@ impl<'tcx> super::Machine<'tcx> for CompileTimeEvaluator { ecx.write_primval(dest, PrimVal::from_u128(size), dest_layout.ty)?; } + "type_id" => { + let ty = substs.type_at(0); + let type_id = ecx.tcx.type_id_hash(ty) as u128; + ecx.write_primval(dest, PrimVal::from_u128(type_id), dest_layout.ty)?; + } + name => return Err(ConstEvalError::NeedsRfc(format!("calling intrinsic `{}`", name)).into()), } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index b896e6ca85343..da76adfd48f3f 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -737,7 +737,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { Abi::PlatformIntrinsic => { assert!(!self.tcx.is_const_fn(def_id)); match &self.tcx.item_name(def_id)[..] { - "size_of" | "min_align_of" => is_const_fn = Some(def_id), + "size_of" | "min_align_of" | "type_id" => is_const_fn = Some(def_id), name if name.starts_with("simd_shuffle") => { is_shuffle = true; diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index a3e55205dd875..cd1975488a24a 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -411,6 +411,11 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { self.cx.align_of(substs.type_at(0)).abi()); Ok(Const::new(llval, tcx.types.usize)) } + "type_id" => { + let llval = C_u64(self.cx, + self.cx.tcx.type_id_hash(substs.type_at(0))); + Ok(Const::new(llval, tcx.types.u64)) + } _ => span_bug!(span, "{:?} in constant", terminator.kind) } } else if let Some((op, is_checked)) = self.is_binop_lang_item(def_id) { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0929b833c1965..7c9a49c82a939 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2447,7 +2447,12 @@ impl Clean for hir::Ty { let def_id = cx.tcx.hir.body_owner_def_id(n); let param_env = cx.tcx.param_env(def_id); let substs = Substs::identity_for_item(cx.tcx, def_id); - let n = cx.tcx.const_eval(param_env.and((def_id, substs))).unwrap(); + let n = cx.tcx.const_eval(param_env.and((def_id, substs))).unwrap_or_else(|_| { + cx.tcx.mk_const(ty::Const { + val: ConstVal::Unevaluated(def_id, substs), + ty: cx.tcx.types.usize + }) + }); let n = if let ConstVal::Integral(ConstInt::Usize(n)) = n.val { n.to_string() } else if let ConstVal::Unevaluated(def_id, _) = n.val { @@ -2577,7 +2582,9 @@ impl<'tcx> Clean for Ty<'tcx> { let mut n = cx.tcx.lift(&n).unwrap(); if let ConstVal::Unevaluated(def_id, substs) = n.val { let param_env = cx.tcx.param_env(def_id); - n = cx.tcx.const_eval(param_env.and((def_id, substs))).unwrap() + if let Ok(new_n) = cx.tcx.const_eval(param_env.and((def_id, substs))) { + n = new_n; + } }; let n = if let ConstVal::Integral(ConstInt::Usize(n)) = n.val { n.to_string() diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index d1f3ccbd2c6e0..5cea389531f94 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -482,20 +482,42 @@ impl File { self.inner.file_attr().map(Metadata) } - /// Creates a new independently owned handle to the underlying file. - /// - /// The returned `File` is a reference to the same state that this object - /// references. Both handles will read and write with the same cursor - /// position. + /// Create a new `File` instance that shares the same underlying file handle + /// as the existing `File` instance. Reads, writes, and seeks will affect + /// both `File` instances simultaneously. /// /// # Examples /// + /// Create two handles for a file named `foo.txt`: + /// /// ```no_run /// use std::fs::File; /// /// # fn foo() -> std::io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let file_copy = f.try_clone()?; + /// let mut file = File::open("foo.txt")?; + /// let file_copy = file.try_clone()?; + /// # Ok(()) + /// # } + /// ``` + /// + /// Assuming there’s a file named `foo.txt` with contents `abcdef\n`, create + /// two handles, seek one of them, and read the remaining bytes from the + /// other handle: + /// + /// ```no_run + /// use std::fs::File; + /// use std::io::SeekFrom; + /// use std::io::prelude::*; + /// + /// # fn foo() -> std::io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// let mut file_copy = file.try_clone()?; + /// + /// file.seek(SeekFrom::Start(3))?; + /// + /// let mut contents = vec![]; + /// file_copy.read_to_end(&mut contents)?; + /// assert_eq!(contents, b"def\n"); /// # Ok(()) /// # } /// ``` @@ -1001,7 +1023,7 @@ impl Metadata { self.0.accessed().map(FromInner::from_inner) } - /// Returns the creation time listed in the this metadata. + /// Returns the creation time listed in this metadata. /// /// The returned value corresponds to the `birthtime` field of `stat` on /// Unix platforms and the `ftCreationTime` field on Windows platforms. diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs index c980ae75261ca..78a3b82546e3a 100644 --- a/src/libstd/sys/cloudabi/thread.rs +++ b/src/libstd/sys/cloudabi/thread.rs @@ -111,10 +111,11 @@ impl Drop for Thread { #[cfg_attr(test, allow(dead_code))] pub mod guard { - pub unsafe fn current() -> Option { + pub type Guard = !; + pub unsafe fn current() -> Option { None } - pub unsafe fn init() -> Option { + pub unsafe fn init() -> Option { None } } diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs index c4aad8d86f8b1..c4719a94c7e9d 100644 --- a/src/libstd/sys/redox/thread.rs +++ b/src/libstd/sys/redox/thread.rs @@ -88,6 +88,7 @@ impl Thread { } pub mod guard { - pub unsafe fn current() -> Option { None } - pub unsafe fn init() -> Option { None } + pub type Guard = !; + pub unsafe fn current() -> Option { None } + pub unsafe fn init() -> Option { None } } diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index 51adbc24ae047..40453f9b8a15b 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -57,9 +57,6 @@ mod imp { use sys_common::thread_info; - // This is initialized in init() and only read from after - static mut PAGE_SIZE: usize = 0; - #[cfg(any(target_os = "linux", target_os = "android"))] unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize { #[repr(C)] @@ -102,12 +99,12 @@ mod imp { _data: *mut libc::c_void) { use sys_common::util::report_overflow; - let guard = thread_info::stack_guard().unwrap_or(0); + let guard = thread_info::stack_guard().unwrap_or(0..0); let addr = siginfo_si_addr(info); // If the faulting address is within the guard page, then we print a // message saying so and abort. - if guard != 0 && guard - PAGE_SIZE <= addr && addr < guard { + if guard.start <= addr && addr < guard.end { report_overflow(); rtabort!("stack overflow"); } else { @@ -123,8 +120,6 @@ mod imp { static mut MAIN_ALTSTACK: *mut libc::c_void = ptr::null_mut(); pub unsafe fn init() { - PAGE_SIZE = ::sys::os::page_size(); - let mut action: sigaction = mem::zeroed(); action.sa_flags = SA_SIGINFO | SA_ONSTACK; action.sa_sigaction = signal_handler as sighandler_t; diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 525882c1e1ebb..72cdb9440b8e7 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -205,8 +205,10 @@ impl Drop for Thread { not(target_os = "solaris")))] #[cfg_attr(test, allow(dead_code))] pub mod guard { - pub unsafe fn current() -> Option { None } - pub unsafe fn init() -> Option { None } + use ops::Range; + pub type Guard = Range; + pub unsafe fn current() -> Option { None } + pub unsafe fn init() -> Option { None } } @@ -222,14 +224,43 @@ pub mod guard { use libc; use libc::mmap; use libc::{PROT_NONE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED}; + use ops::Range; use sys::os; - #[cfg(any(target_os = "macos", - target_os = "bitrig", - target_os = "openbsd", - target_os = "solaris"))] + // This is initialized in init() and only read from after + static mut PAGE_SIZE: usize = 0; + + pub type Guard = Range; + + #[cfg(target_os = "solaris")] + unsafe fn get_stack_start() -> Option<*mut libc::c_void> { + let mut current_stack: libc::stack_t = ::mem::zeroed(); + assert_eq!(libc::stack_getbounds(&mut current_stack), 0); + Some(current_stack.ss_sp) + } + + #[cfg(target_os = "macos")] unsafe fn get_stack_start() -> Option<*mut libc::c_void> { - current().map(|s| s as *mut libc::c_void) + let stackaddr = libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize - + libc::pthread_get_stacksize_np(libc::pthread_self()); + Some(stackaddr as *mut libc::c_void) + } + + #[cfg(any(target_os = "openbsd", target_os = "bitrig"))] + unsafe fn get_stack_start() -> Option<*mut libc::c_void> { + let mut current_stack: libc::stack_t = ::mem::zeroed(); + assert_eq!(libc::pthread_stackseg_np(libc::pthread_self(), + &mut current_stack), 0); + + let extra = if cfg!(target_os = "bitrig") {3} else {1} * PAGE_SIZE; + let stackaddr = if libc::pthread_main_np() == 1 { + // main thread + current_stack.ss_sp as usize - current_stack.ss_size + extra + } else { + // new thread + current_stack.ss_sp as usize - current_stack.ss_size + }; + Some(stackaddr as *mut libc::c_void) } #[cfg(any(target_os = "android", target_os = "freebsd", @@ -253,8 +284,9 @@ pub mod guard { ret } - pub unsafe fn init() -> Option { - let psize = os::page_size(); + pub unsafe fn init() -> Option { + PAGE_SIZE = os::page_size(); + let mut stackaddr = get_stack_start()?; // Ensure stackaddr is page aligned! A parent process might @@ -263,9 +295,9 @@ pub mod guard { // stackaddr < stackaddr + stacksize, so if stackaddr is not // page-aligned, calculate the fix such that stackaddr < // new_page_aligned_stackaddr < stackaddr + stacksize - let remainder = (stackaddr as usize) % psize; + let remainder = (stackaddr as usize) % PAGE_SIZE; if remainder != 0 { - stackaddr = ((stackaddr as usize) + psize - remainder) + stackaddr = ((stackaddr as usize) + PAGE_SIZE - remainder) as *mut libc::c_void; } @@ -280,60 +312,42 @@ pub mod guard { // Instead, we'll just note where we expect rlimit to start // faulting, so our handler can report "stack overflow", and // trust that the kernel's own stack guard will work. - Some(stackaddr as usize) + let stackaddr = stackaddr as usize; + Some(stackaddr - PAGE_SIZE..stackaddr) } else { // Reallocate the last page of the stack. // This ensures SIGBUS will be raised on // stack overflow. - let result = mmap(stackaddr, psize, PROT_NONE, + let result = mmap(stackaddr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); if result != stackaddr || result == MAP_FAILED { panic!("failed to allocate a guard page"); } + let guardaddr = stackaddr as usize; let offset = if cfg!(target_os = "freebsd") { 2 } else { 1 }; - Some(stackaddr as usize + offset * psize) + Some(guardaddr..guardaddr + offset * PAGE_SIZE) } } - #[cfg(target_os = "solaris")] - pub unsafe fn current() -> Option { - let mut current_stack: libc::stack_t = ::mem::zeroed(); - assert_eq!(libc::stack_getbounds(&mut current_stack), 0); - Some(current_stack.ss_sp as usize) - } - - #[cfg(target_os = "macos")] - pub unsafe fn current() -> Option { - Some(libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize - - libc::pthread_get_stacksize_np(libc::pthread_self())) - } - - #[cfg(any(target_os = "openbsd", target_os = "bitrig"))] - pub unsafe fn current() -> Option { - let mut current_stack: libc::stack_t = ::mem::zeroed(); - assert_eq!(libc::pthread_stackseg_np(libc::pthread_self(), - &mut current_stack), 0); - - let extra = if cfg!(target_os = "bitrig") {3} else {1} * os::page_size(); - Some(if libc::pthread_main_np() == 1 { - // main thread - current_stack.ss_sp as usize - current_stack.ss_size + extra - } else { - // new thread - current_stack.ss_sp as usize - current_stack.ss_size - }) + #[cfg(any(target_os = "macos", + target_os = "bitrig", + target_os = "openbsd", + target_os = "solaris"))] + pub unsafe fn current() -> Option { + let stackaddr = get_stack_start()? as usize; + Some(stackaddr - PAGE_SIZE..stackaddr) } #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux", target_os = "netbsd", target_os = "l4re"))] - pub unsafe fn current() -> Option { + pub unsafe fn current() -> Option { let mut ret = None; let mut attr: libc::pthread_attr_t = ::mem::zeroed(); assert_eq!(libc::pthread_attr_init(&mut attr), 0); @@ -352,12 +366,23 @@ pub mod guard { assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr, &mut size), 0); + let stackaddr = stackaddr as usize; ret = if cfg!(target_os = "freebsd") { - Some(stackaddr as usize - guardsize) + // FIXME does freebsd really fault *below* the guard addr? + let guardaddr = stackaddr - guardsize; + Some(guardaddr - PAGE_SIZE..guardaddr) } else if cfg!(target_os = "netbsd") { - Some(stackaddr as usize) + Some(stackaddr - guardsize..stackaddr) + } else if cfg!(all(target_os = "linux", target_env = "gnu")) { + // glibc used to include the guard area within the stack, as noted in the BUGS + // section of `man pthread_attr_getguardsize`. This has been corrected starting + // with glibc 2.27, and in some distro backports, so the guard is now placed at the + // end (below) the stack. There's no easy way for us to know which we have at + // runtime, so we'll just match any fault in the range right above or below the + // stack base to call that fault a stack overflow. + Some(stackaddr - guardsize..stackaddr + guardsize) } else { - Some(stackaddr as usize + guardsize) + Some(stackaddr..stackaddr + guardsize) }; } assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs index 13980e0cc19d1..6a066509b492a 100644 --- a/src/libstd/sys/wasm/thread.rs +++ b/src/libstd/sys/wasm/thread.rs @@ -43,6 +43,7 @@ impl Thread { } pub mod guard { - pub unsafe fn current() -> Option { None } - pub unsafe fn init() -> Option { None } + pub type Guard = !; + pub unsafe fn current() -> Option { None } + pub unsafe fn init() -> Option { None } } diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index 74786d092855f..43abfbb1f645e 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -93,6 +93,7 @@ impl Thread { #[cfg_attr(test, allow(dead_code))] pub mod guard { - pub unsafe fn current() -> Option { None } - pub unsafe fn init() -> Option { None } + pub type Guard = !; + pub unsafe fn current() -> Option { None } + pub unsafe fn init() -> Option { None } } diff --git a/src/libstd/sys_common/thread_info.rs b/src/libstd/sys_common/thread_info.rs index 7970042b1d67d..6a2b6742367a5 100644 --- a/src/libstd/sys_common/thread_info.rs +++ b/src/libstd/sys_common/thread_info.rs @@ -11,10 +11,11 @@ #![allow(dead_code)] // stack_guard isn't used right now on all platforms use cell::RefCell; +use sys::thread::guard::Guard; use thread::Thread; struct ThreadInfo { - stack_guard: Option, + stack_guard: Option, thread: Thread, } @@ -38,11 +39,11 @@ pub fn current_thread() -> Option { ThreadInfo::with(|info| info.thread.clone()) } -pub fn stack_guard() -> Option { - ThreadInfo::with(|info| info.stack_guard).and_then(|o| o) +pub fn stack_guard() -> Option { + ThreadInfo::with(|info| info.stack_guard.clone()).and_then(|o| o) } -pub fn set(stack_guard: Option, thread: Thread) { +pub fn set(stack_guard: Option, thread: Thread) { THREAD_INFO.with(|c| assert!(c.borrow().is_none())); THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{ stack_guard, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 73810b3fe81d7..c7ab6158256ba 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -883,7 +883,6 @@ pub struct Arm { pub pats: Vec>, pub guard: Option>, pub body: P, - pub beginning_vert: Option, // For RFC 1925 feature gate } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index cf63592c2ece2..2e6de96d65a6d 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -883,7 +883,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> { pats, guard: None, body: expr, - beginning_vert: None, } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 3e523fca92a03..3e858c3b923a1 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -386,9 +386,6 @@ declare_features! ( // allow `#[must_use]` on functions and comparison operators (RFC 1940) (active, fn_must_use, "1.21.0", Some(43302)), - // allow '|' at beginning of match arms (RFC 1925) - (active, match_beginning_vert, "1.21.0", Some(44101)), - // Future-proofing enums/structs with #[non_exhaustive] attribute (RFC 2008) (active, non_exhaustive, "1.22.0", Some(44109)), @@ -545,6 +542,8 @@ declare_features! ( (accepted, abi_sysv64, "1.24.0", Some(36167)), // Allows `repr(align(16))` struct attribute (RFC 1358) (accepted, repr_align, "1.24.0", Some(33626)), + // allow '|' at beginning of match arms (RFC 1925) + (accepted, match_beginning_vert, "1.25.0", Some(44101)), ); // If you change this, please modify src/doc/unstable-book as well. You must @@ -1683,11 +1682,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } fn visit_arm(&mut self, arm: &'a ast::Arm) { - if let Some(span) = arm.beginning_vert { - gate_feature_post!(&self, match_beginning_vert, - span, - "Use of a '|' at the beginning of a match arm is experimental") - } visit::walk_arm(self, arm) } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 0f8fe57e380e5..921ed3565a471 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -340,14 +340,13 @@ pub fn fold_thin_attrs(attrs: ThinVec, fld: &mut T) -> Thi fold_attrs(attrs.into(), fld).into() } -pub fn noop_fold_arm(Arm {attrs, pats, guard, body, beginning_vert}: Arm, +pub fn noop_fold_arm(Arm {attrs, pats, guard, body}: Arm, fld: &mut T) -> Arm { Arm { attrs: fold_attrs(attrs, fld), pats: pats.move_map(|x| fld.fold_pat(x)), guard: guard.map(|x| fld.fold_expr(x)), body: fld.fold_expr(body), - beginning_vert, } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b3c485a85c063..764b3d0a848ee 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3398,11 +3398,7 @@ impl<'a> Parser<'a> { let attrs = self.parse_outer_attributes()?; // Allow a '|' before the pats (RFC 1925) - let beginning_vert = if self.eat(&token::BinOp(token::Or)) { - Some(self.prev_span) - } else { - None - }; + self.eat(&token::BinOp(token::Or)); let pats = self.parse_pats()?; let guard = if self.eat_keyword(keywords::If) { Some(self.parse_expr()?) @@ -3426,7 +3422,6 @@ impl<'a> Parser<'a> { pats, guard, body: expr, - beginning_vert, }) } diff --git a/src/test/codegen/stack-probes.rs b/src/test/codegen/stack-probes.rs index 5b26dade9aff0..4a489f1edb3b8 100644 --- a/src/test/codegen/stack-probes.rs +++ b/src/test/codegen/stack-probes.rs @@ -15,7 +15,7 @@ // ignore-wasm // ignore-emscripten // ignore-windows -// no-system-llvm +// min-system-llvm-version 5.0 // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/compile-fail/const-typeid-of.rs b/src/test/compile-fail/const-typeid-of.rs new file mode 100644 index 0000000000000..401125cef09d8 --- /dev/null +++ b/src/test/compile-fail/const-typeid-of.rs @@ -0,0 +1,18 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::any::TypeId; + +struct A; + +fn main() { + const A_ID: TypeId = TypeId::of::(); + //~^ ERROR `std::any::TypeId::of` is not yet stable as a const fn +} diff --git a/src/test/compile-fail/nll/do-not-ignore-lifetime-bounds-in-copy.rs b/src/test/compile-fail/nll/do-not-ignore-lifetime-bounds-in-copy.rs new file mode 100644 index 0000000000000..2a4295fd90a26 --- /dev/null +++ b/src/test/compile-fail/nll/do-not-ignore-lifetime-bounds-in-copy.rs @@ -0,0 +1,23 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that the 'static bound from the Copy impl is respected. Regression test for #29149. + +#![feature(nll)] + +#[derive(Clone)] struct Foo<'a>(&'a u32); +impl Copy for Foo<'static> {} + +fn main() { + let s = 2; + let a = Foo(&s); //~ ERROR `s` does not live long enough [E0597] + drop(a); + drop(a); +} diff --git a/src/test/run-pass/const-typeid-of.rs b/src/test/run-pass/const-typeid-of.rs new file mode 100644 index 0000000000000..ce29e55c6d720 --- /dev/null +++ b/src/test/run-pass/const-typeid-of.rs @@ -0,0 +1,43 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(core_intrinsics)] +#![feature(const_type_id)] + +use std::any::TypeId; + +struct A; + +static ID_ISIZE: TypeId = TypeId::of::(); + +pub fn main() { + assert_eq!(ID_ISIZE, TypeId::of::()); + + // sanity test of TypeId + const T: (TypeId, TypeId, TypeId) = (TypeId::of::(), + TypeId::of::<&'static str>(), + TypeId::of::()); + let (d, e, f) = (TypeId::of::(), TypeId::of::<&'static str>(), + TypeId::of::()); + + assert!(T.0 != T.1); + assert!(T.0 != T.2); + assert!(T.1 != T.2); + + assert_eq!(T.0, d); + assert_eq!(T.1, e); + assert_eq!(T.2, f); + + // Check fn pointer against collisions + const F: (TypeId, TypeId) = (TypeId::of:: A) -> A>(), + TypeId::of:: A, A) -> A>()); + + assert!(F.0 != F.1); +} diff --git a/src/test/run-pass/match-beginning-vert.rs b/src/test/run-pass/match-beginning-vert.rs new file mode 100644 index 0000000000000..cdacfb2f05729 --- /dev/null +++ b/src/test/run-pass/match-beginning-vert.rs @@ -0,0 +1,28 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +enum Foo { + A, + B, + C, + D, + E, +} +use Foo::*; + +fn main() { + for foo in &[A, B, C, D, E] { + match *foo { + | A => println!("A"), + | B | C if 1 < 2 => println!("BC!"), + | _ => {}, + } + } +} diff --git a/src/test/run-pass/stack-probes-lto.rs b/src/test/run-pass/stack-probes-lto.rs index 22555c8d6a779..4deced1297bd1 100644 --- a/src/test/run-pass/stack-probes-lto.rs +++ b/src/test/run-pass/stack-probes-lto.rs @@ -15,7 +15,7 @@ // ignore-emscripten no processes // ignore-musl FIXME #31506 // ignore-pretty -// no-system-llvm +// min-system-llvm-version 5.0 // compile-flags: -C lto // no-prefer-dynamic diff --git a/src/test/run-pass/stack-probes.rs b/src/test/run-pass/stack-probes.rs index 248ad7019261d..4224a65ffd7c7 100644 --- a/src/test/run-pass/stack-probes.rs +++ b/src/test/run-pass/stack-probes.rs @@ -14,7 +14,7 @@ // ignore-cloudabi no processes // ignore-emscripten no processes // ignore-musl FIXME #31506 -// no-system-llvm +// min-system-llvm-version 5.0 use std::mem; use std::process::Command; diff --git a/src/test/rustdoc/const-evalutation-ice.rs b/src/test/rustdoc/const-evalutation-ice.rs new file mode 100644 index 0000000000000..9fed67ee583d2 --- /dev/null +++ b/src/test/rustdoc/const-evalutation-ice.rs @@ -0,0 +1,22 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Just check if we don't get an ICE for the _S type. + +#![feature(const_size_of)] + +use std::cell::Cell; +use std::mem; + +pub struct S { + s: Cell +} + +pub type _S = [usize; 0 - (mem::size_of::() != 4) as usize]; diff --git a/src/test/ui/feature-gate-match_beginning_vert.rs b/src/test/ui/feature-gate-match_beginning_vert.rs deleted file mode 100644 index 9085563c99d6d..0000000000000 --- a/src/test/ui/feature-gate-match_beginning_vert.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_code)] -enum Foo { - A, - B, - C, - D, - E, -} -use Foo::*; - -fn main() { - let x = Foo::A; - match x { - | A => println!("A"), - //~^ ERROR: Use of a '|' at the beginning of a match arm is experimental (see issue #44101) - | B | C => println!("BC!"), - //~^ ERROR: Use of a '|' at the beginning of a match arm is experimental (see issue #44101) - | _ => {}, - //~^ ERROR: Use of a '|' at the beginning of a match arm is experimental (see issue #44101) - }; - match x { - A | B | C => println!("ABC!"), - _ => {}, - }; -} - diff --git a/src/test/ui/feature-gate-match_beginning_vert.stderr b/src/test/ui/feature-gate-match_beginning_vert.stderr deleted file mode 100644 index 1d45dedb4971c..0000000000000 --- a/src/test/ui/feature-gate-match_beginning_vert.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error[E0658]: Use of a '|' at the beginning of a match arm is experimental (see issue #44101) - --> $DIR/feature-gate-match_beginning_vert.rs:24:9 - | -24 | | A => println!("A"), - | ^ - | - = help: add #![feature(match_beginning_vert)] to the crate attributes to enable - -error[E0658]: Use of a '|' at the beginning of a match arm is experimental (see issue #44101) - --> $DIR/feature-gate-match_beginning_vert.rs:26:9 - | -26 | | B | C => println!("BC!"), - | ^ - | - = help: add #![feature(match_beginning_vert)] to the crate attributes to enable - -error[E0658]: Use of a '|' at the beginning of a match arm is experimental (see issue #44101) - --> $DIR/feature-gate-match_beginning_vert.rs:28:9 - | -28 | | _ => {}, - | ^ - | - = help: add #![feature(match_beginning_vert)] to the crate attributes to enable - -error: aborting due to 3 previous errors - diff --git a/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs b/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs new file mode 100644 index 0000000000000..b4e6c5074e3d3 --- /dev/null +++ b/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs @@ -0,0 +1,40 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// must-compile-successfully + +#![warn(unused_parens)] + +macro_rules! the_worship_the_heart_lifts_above { + ( @as_expr, $e:expr) => { $e }; + ( @generate_fn, $name:tt) => { + #[allow(dead_code)] fn the_moth_for_the_star<'a>() -> Option<&'a str> { + Some(the_worship_the_heart_lifts_above!( @as_expr, $name )) + } + }; + ( $name:ident ) => { the_worship_the_heart_lifts_above!( @generate_fn, (stringify!($name))); } + // ↑ Notably, this does 𝘯𝘰𝘵 warn: we're declining to lint unused parens in + // function/method arguments inside of nested macros because of situations + // like those reported in Issue #47775 +} + +macro_rules! and_the_heavens_reject_not { + () => { + // ↓ But let's test that we still lint for unused parens around + // function args inside of simple, one-deep macros. + #[allow(dead_code)] fn the_night_for_the_morrow() -> Option { Some((2)) } + //~^ WARN unnecessary parentheses around function argument + } +} + +the_worship_the_heart_lifts_above!(rah); +and_the_heavens_reject_not!(); + +fn main() {} diff --git a/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.stderr b/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.stderr new file mode 100644 index 0000000000000..097ec1b1c8010 --- /dev/null +++ b/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.stderr @@ -0,0 +1,15 @@ +warning: unnecessary parentheses around function argument + --> $DIR/issue-47775-nested-macro-unnecessary-parens-arg.rs:32:83 + | +32 | #[allow(dead_code)] fn the_night_for_the_morrow() -> Option { Some((2)) } + | ^^^ help: remove these parentheses +... +38 | and_the_heavens_reject_not!(); + | ------------------------------ in this macro invocation + | +note: lint level defined here + --> $DIR/issue-47775-nested-macro-unnecessary-parens-arg.rs:13:9 + | +13 | #![warn(unused_parens)] + | ^^^^^^^^^^^^^ + diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index ff662736bdd1b..80750f9a3fee0 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -167,7 +167,7 @@ impl EarlyProps { .expect("Malformed llvm version directive"); // Ignore if using system LLVM and actual version // is smaller the minimum required version - !(config.system_llvm && &actual_version[..] < min_version) + config.system_llvm && &actual_version[..] < min_version } else { false } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index abf62a060b83b..46df211cbaf65 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -79,7 +79,7 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec { if lines_since_mismatch >= context_size && lines_since_mismatch > 0 { @@ -91,7 +91,8 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec { @@ -104,8 +105,7 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec {