diff options
| author | Nicolas Koch <nioko1337@gmail.com> | 2018-05-15 15:26:11 +0200 |
|---|---|---|
| committer | Nicolas Koch <nioko1337@gmail.com> | 2018-05-15 15:26:11 +0200 |
| commit | b4b71d5d5fd8bedecbacf08ffb45c8456700151b (patch) | |
| tree | 2ada477250001a23bc2d5329ca572e15b7bf23d7 /src | |
| parent | 834ef9f08ae3429a05dead80237bb4bd04769895 (diff) | |
| parent | eca0da59850d4a9eef17c0e6c3795397102d88a3 (diff) | |
| download | rust-b4b71d5d5fd8bedecbacf08ffb45c8456700151b.tar.gz rust-b4b71d5d5fd8bedecbacf08ffb45c8456700151b.zip | |
Merge branch 'master' of https://github.com/nicokoch/rust
Diffstat (limited to 'src')
45 files changed, 456 insertions, 382 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock index 4cb82f94251..2f52c889558 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -288,12 +288,12 @@ dependencies = [ [[package]] name = "clippy" -version = "0.0.198" +version = "0.0.200" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "clippy-mini-macro-test 0.2.0", - "clippy_lints 0.0.198", + "clippy_lints 0.0.200", "compiletest_rs 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -331,7 +331,7 @@ dependencies = [ [[package]] name = "clippy_lints" -version = "0.0.198" +version = "0.0.200" dependencies = [ "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2178,6 +2178,7 @@ dependencies = [ name = "rustc_trans" version = "0.0.0" dependencies = [ + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/doc/unstable-book/src/language-features/macro-lifetime-matcher.md b/src/doc/unstable-book/src/language-features/macro-lifetime-matcher.md deleted file mode 100644 index 5b585d7f041..00000000000 --- a/src/doc/unstable-book/src/language-features/macro-lifetime-matcher.md +++ /dev/null @@ -1,14 +0,0 @@ -# `macro_lifetime_matcher` - -The tracking issue for this feature is: [#46895] - -With this feature gate enabled, the [list of fragment specifiers][frags] gains one more entry: - -* `lifetime`: a lifetime. Examples: 'static, 'a. - -A `lifetime` variable may be followed by anything. - -[#46895]: https://github.com/rust-lang/rust/issues/46895 -[frags]: ../book/first-edition/macros.html#syntactic-requirements - ------------------------- diff --git a/src/etc/generate-deriving-span-tests.py b/src/etc/generate-deriving-span-tests.py index edb9389c00c..2e9169ce5b9 100755 --- a/src/etc/generate-deriving-span-tests.py +++ b/src/etc/generate-deriving-span-tests.py @@ -122,7 +122,7 @@ traits = { for (trait, supers, errs) in [('Clone', [], 1), ('PartialEq', [], 2), - ('PartialOrd', ['PartialEq'], 5), + ('PartialOrd', ['PartialEq'], 1), ('Eq', ['PartialEq'], 1), ('Ord', ['Eq', 'PartialOrd', 'PartialEq'], 1), ('Debug', [], 1), diff --git a/src/libcompiler_builtins b/src/libcompiler_builtins -Subproject 2a2f6d96c8dc578d2474742f14c9bab0b36b040 +Subproject 4cfd7101eb549169cdaeda5313f7c39415b9d73 diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 879d38c4894..2a288ae522a 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -50,7 +50,7 @@ #![feature(from_ref)] #![feature(fs_read_write)] #![cfg_attr(windows, feature(libc))] -#![feature(macro_lifetime_matcher)] +#![cfg_attr(stage0, feature(macro_lifetime_matcher))] #![feature(macro_vis_matcher)] #![feature(never_type)] #![feature(exhaustive_patterns)] diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index b22c025e86c..bbfc6d883e9 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -888,6 +888,11 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { if x < min { min = x; } if x > max { max = x; } } + // We might have no inhabited variants, so pretend there's at least one. + if (min, max) == (i128::max_value(), i128::min_value()) { + min = 0; + max = 0; + } assert!(min <= max, "discriminant range is {}...{}", min, max); let (min_ity, signed) = Integer::repr_discr(tcx, ty, &def.repr, min, max); diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index a99e0a32e66..7ecf2eba43d 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -15,9 +15,8 @@ #![feature(box_patterns)] #![feature(fs_read_write)] #![feature(libc)] -#![feature(macro_lifetime_matcher)] +#![cfg_attr(stage0, feature(macro_lifetime_matcher))] #![feature(proc_macro_internals)] -#![feature(macro_lifetime_matcher)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(slice_sort_by_cached_key)] diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index cf12302d989..e57a793ff42 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -12,7 +12,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(custom_attribute)] -#![feature(macro_lifetime_matcher)] +#![cfg_attr(stage0, feature(macro_lifetime_matcher))] #![allow(unused_attributes)] #[macro_use] diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml index a4dd02e97b2..64d3a4f4d53 100644 --- a/src/librustc_trans/Cargo.toml +++ b/src/librustc_trans/Cargo.toml @@ -10,6 +10,7 @@ crate-type = ["dylib"] test = false [dependencies] +bitflags = "1.0.1" cc = "1.0.1" flate2 = "1.0" jobserver = "0.1.5" diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 1838dae049a..25c598c532c 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -10,7 +10,7 @@ use llvm::{self, ValueRef, AttributePlace}; use base; -use builder::Builder; +use builder::{Builder, MemFlags}; use common::{ty_fn_sig, C_usize}; use context::CodegenCx; use mir::place::PlaceRef; @@ -220,7 +220,8 @@ impl<'a, 'tcx> ArgTypeExt<'a, 'tcx> for ArgType<'tcx, Ty<'tcx>> { bx.pointercast(dst.llval, Type::i8p(cx)), bx.pointercast(llscratch, Type::i8p(cx)), C_usize(cx, self.layout.size.bytes()), - self.layout.align.min(scratch_align)); + self.layout.align.min(scratch_align), + MemFlags::empty()); bx.lifetime_end(llscratch, scratch_size); } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 0dd1adbff86..feca36fa6c2 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -53,7 +53,7 @@ use rustc_incremental; use allocator; use mir::place::PlaceRef; use attributes; -use builder::Builder; +use builder::{Builder, MemFlags}; use callee; use common::{C_bool, C_bytes_in_context, C_i32, C_usize}; use rustc_mir::monomorphize::collector::{self, MonoItemCollectionMode}; @@ -320,7 +320,7 @@ pub fn coerce_unsized_into<'a, 'tcx>(bx: &Builder<'a, 'tcx>, if src_f.layout.ty == dst_f.layout.ty { memcpy_ty(bx, dst_f.llval, src_f.llval, src_f.layout, - src_f.align.min(dst_f.align)); + src_f.align.min(dst_f.align), MemFlags::empty()); } else { coerce_unsized_into(bx, src_f, dst_f); } @@ -408,7 +408,15 @@ pub fn call_memcpy(bx: &Builder, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, - align: Align) { + align: Align, + flags: MemFlags) { + if flags.contains(MemFlags::NONTEMPORAL) { + // HACK(nox): This is inefficient but there is no nontemporal memcpy. + let val = bx.load(src, align); + let ptr = bx.pointercast(dst, val_ty(val).ptr_to()); + bx.store_with_flags(val, ptr, align, flags); + return; + } let cx = bx.cx; let ptr_width = &cx.sess().target.target.target_pointer_width; let key = format!("llvm.memcpy.p0i8.p0i8.i{}", ptr_width); @@ -417,7 +425,7 @@ pub fn call_memcpy(bx: &Builder, let dst_ptr = bx.pointercast(dst, Type::i8p(cx)); let size = bx.intcast(n_bytes, cx.isize_ty, false); let align = C_i32(cx, align.abi() as i32); - let volatile = C_bool(cx, false); + let volatile = C_bool(cx, flags.contains(MemFlags::VOLATILE)); bx.call(memcpy, &[dst_ptr, src_ptr, size, align, volatile], None); } @@ -427,13 +435,14 @@ pub fn memcpy_ty<'a, 'tcx>( src: ValueRef, layout: TyLayout<'tcx>, align: Align, + flags: MemFlags, ) { let size = layout.size.bytes(); if size == 0 { return; } - call_memcpy(bx, dst, src, C_usize(bx.cx, size), align); + call_memcpy(bx, dst, src, C_usize(bx.cx, size), align, flags); } pub fn call_memset<'a, 'tcx>(bx: &Builder<'a, 'tcx>, diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs index db803ca8209..4153c61e526 100644 --- a/src/librustc_trans/builder.rs +++ b/src/librustc_trans/builder.rs @@ -50,6 +50,13 @@ fn noname() -> *const c_char { &CNULL } +bitflags! { + pub struct MemFlags: u8 { + const VOLATILE = 1 << 0; + const NONTEMPORAL = 1 << 1; + } +} + impl<'a, 'tcx> Builder<'a, 'tcx> { pub fn new_block<'b>(cx: &'a CodegenCx<'a, 'tcx>, llfn: ValueRef, name: &'b str) -> Self { let bx = Builder::with_cx(cx); @@ -579,29 +586,39 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } pub fn store(&self, val: ValueRef, ptr: ValueRef, align: Align) -> ValueRef { - debug!("Store {:?} -> {:?}", Value(val), Value(ptr)); + self.store_with_flags(val, ptr, align, MemFlags::empty()) + } + + pub fn store_with_flags( + &self, + val: ValueRef, + ptr: ValueRef, + align: Align, + flags: MemFlags, + ) -> ValueRef { + debug!("Store {:?} -> {:?} ({:?})", Value(val), Value(ptr), flags); assert!(!self.llbuilder.is_null()); self.count_insn("store"); let ptr = self.check_store(val, ptr); unsafe { let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr); llvm::LLVMSetAlignment(store, align.abi() as c_uint); + if flags.contains(MemFlags::VOLATILE) { + llvm::LLVMSetVolatile(store, llvm::True); + } + if flags.contains(MemFlags::NONTEMPORAL) { + // According to LLVM [1] building a nontemporal store must + // *always* point to a metadata value of the integer 1. + // + // [1]: http://llvm.org/docs/LangRef.html#store-instruction + let one = C_i32(self.cx, 1); + let node = llvm::LLVMMDNodeInContext(self.cx.llcx, &one, 1); + llvm::LLVMSetMetadata(store, llvm::MD_nontemporal as c_uint, node); + } store } } - pub fn volatile_store(&self, val: ValueRef, ptr: ValueRef) -> ValueRef { - debug!("Store {:?} -> {:?}", Value(val), Value(ptr)); - assert!(!self.llbuilder.is_null()); - self.count_insn("store.volatile"); - let ptr = self.check_store(val, ptr); - unsafe { - let insn = llvm::LLVMBuildStore(self.llbuilder, val, ptr); - llvm::LLVMSetVolatile(insn, llvm::True); - insn - } - } - pub fn atomic_store(&self, val: ValueRef, ptr: ValueRef, order: AtomicOrdering, align: Align) { debug!("Store {:?} -> {:?}", Value(val), Value(ptr)); @@ -615,29 +632,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn nontemporal_store(&self, val: ValueRef, ptr: ValueRef) -> ValueRef { - debug!("Store {:?} -> {:?}", Value(val), Value(ptr)); - assert!(!self.llbuilder.is_null()); - self.count_insn("store.nontemporal"); - let ptr = self.check_store(val, ptr); - unsafe { - let insn = llvm::LLVMBuildStore(self.llbuilder, val, ptr); - - // According to LLVM [1] building a nontemporal store must *always* - // point to a metadata value of the integer 1. Who knew? - // - // [1]: http://llvm.org/docs/LangRef.html#store-instruction - let one = C_i32(self.cx, 1); - let node = llvm::LLVMMDNodeInContext(self.cx.llcx, - &one, - 1); - llvm::LLVMSetMetadata(insn, - llvm::MD_nontemporal as c_uint, - node); - insn - } - } - pub fn gep(&self, ptr: ValueRef, indices: &[ValueRef]) -> ValueRef { self.count_insn("gep"); unsafe { diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 49a207a2d8a..86aa48b6a9e 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -247,26 +247,8 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, to_immediate(bx, load, cx.layout_of(tp_ty)) }, "volatile_store" => { - let tp_ty = substs.type_at(0); let dst = args[0].deref(bx.cx); - if let OperandValue::Pair(a, b) = args[1].val { - bx.volatile_store(a, dst.project_field(bx, 0).llval); - bx.volatile_store(b, dst.project_field(bx, 1).llval); - } else { - let val = if let OperandValue::Ref(ptr, align) = args[1].val { - bx.load(ptr, align) - } else { - if dst.layout.is_zst() { - return; - } - from_immediate(bx, args[1].immediate()) - }; - let ptr = bx.pointercast(dst.llval, val_ty(val).ptr_to()); - let store = bx.volatile_store(val, ptr); - unsafe { - llvm::LLVMSetAlignment(store, cx.align_of(tp_ty).abi() as u32); - } - } + args[1].val.volatile_store(bx, dst); return; }, "prefetch_read_data" | "prefetch_write_data" | @@ -551,19 +533,9 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, } "nontemporal_store" => { - let tp_ty = substs.type_at(0); let dst = args[0].deref(bx.cx); - let val = if let OperandValue::Ref(ptr, align) = args[1].val { - bx.load(ptr, align) - } else { - from_immediate(bx, args[1].immediate()) - }; - let ptr = bx.pointercast(dst.llval, val_ty(val).ptr_to()); - let store = bx.nontemporal_store(val, ptr); - unsafe { - llvm::LLVMSetAlignment(store, cx.align_of(tp_ty).abi() as u32); - } - return + args[1].val.nontemporal_store(bx, dst); + return; } _ => { diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 30780b8c965..6db95657ce0 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -34,6 +34,7 @@ use rustc::dep_graph::WorkProduct; use syntax_pos::symbol::Symbol; +#[macro_use] extern crate bitflags; extern crate flate2; extern crate libc; #[macro_use] extern crate rustc; diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index b666c2b2115..e4989da36c0 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -17,7 +17,7 @@ use rustc::mir::interpret::EvalErrorKind; use abi::{Abi, ArgType, ArgTypeExt, FnType, FnTypeExt, LlvmType, PassMode}; use base; use callee; -use builder::Builder; +use builder::{Builder, MemFlags}; use common::{self, C_bool, C_str_slice, C_struct, C_u32, C_uint_big, C_undef}; use consts; use meth; @@ -626,7 +626,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { // have scary latent bugs around. let scratch = PlaceRef::alloca(bx, arg.layout, "arg"); - base::memcpy_ty(bx, scratch.llval, llval, op.layout, align); + base::memcpy_ty(bx, scratch.llval, llval, op.layout, align, MemFlags::empty()); (scratch.llval, scratch.align, true) } else { (llval, align, true) diff --git a/src/librustc_trans/mir/operand.rs b/src/librustc_trans/mir/operand.rs index d2bf8394296..be14da1a195 100644 --- a/src/librustc_trans/mir/operand.rs +++ b/src/librustc_trans/mir/operand.rs @@ -18,7 +18,7 @@ use rustc_data_structures::indexed_vec::Idx; use base; use common::{self, CodegenCx, C_null, C_undef, C_usize}; -use builder::Builder; +use builder::{Builder, MemFlags}; use value::Value; use type_of::LayoutLlvmExt; use type_::Type; @@ -272,6 +272,18 @@ impl<'a, 'tcx> OperandRef<'tcx> { impl<'a, 'tcx> OperandValue { pub fn store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) { + self.store_with_flags(bx, dest, MemFlags::empty()); + } + + pub fn volatile_store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) { + self.store_with_flags(bx, dest, MemFlags::VOLATILE); + } + + pub fn nontemporal_store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) { + self.store_with_flags(bx, dest, MemFlags::NONTEMPORAL); + } + + fn store_with_flags(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>, flags: MemFlags) { debug!("OperandRef::store: operand={:?}, dest={:?}", self, dest); // Avoid generating stores of zero-sized values, because the only way to have a zero-sized // value is through `undef`, and store itself is useless. @@ -279,11 +291,13 @@ impl<'a, 'tcx> OperandValue { return; } match self { - OperandValue::Ref(r, source_align) => + OperandValue::Ref(r, source_align) => { base::memcpy_ty(bx, dest.llval, r, dest.layout, - source_align.min(dest.align)), + source_align.min(dest.align), flags) + } OperandValue::Immediate(s) => { - bx.store(base::from_immediate(bx, s), dest.llval, dest.align); + let val = base::from_immediate(bx, s); + bx.store_with_flags(val, dest.llval, dest.align, flags); } OperandValue::Pair(a, b) => { for (i, &x) in [a, b].iter().enumerate() { @@ -292,7 +306,8 @@ impl<'a, 'tcx> OperandValue { if common::val_ty(x) == Type::i1(bx.cx) { llptr = bx.pointercast(llptr, Type::i8p(bx.cx)); } - bx.store(base::from_immediate(bx, x), llptr, dest.align); + let val = base::from_immediate(bx, x); + bx.store_with_flags(val, llptr, dest.align, flags); } } } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 2547952d104..35cc70b0838 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -688,7 +688,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); arm_span: arm.body.span, source: match_src }); - coercion.coerce(self, &cause, &arm.body, arm_ty, self.diverges.get()); + coercion.coerce(self, &cause, &arm.body, arm_ty); } } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index c1ef916e27d..324af7b6270 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -60,7 +60,7 @@ //! sort of a minor point so I've opted to leave it for later---after all //! we may want to adjust precisely when coercions occur. -use check::{Diverges, FnCtxt, Needs}; +use check::{FnCtxt, Needs}; use rustc::hir; use rustc::hir::def_id::DefId; @@ -800,8 +800,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { exprs: &[E], prev_ty: Ty<'tcx>, new: &hir::Expr, - new_ty: Ty<'tcx>, - new_diverges: Diverges) + new_ty: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> where E: AsCoercionSite { @@ -809,13 +808,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let new_ty = self.resolve_type_vars_with_obligations(new_ty); debug!("coercion::try_find_coercion_lub({:?}, {:?})", prev_ty, new_ty); - // Special-ish case: we can coerce any type `T` into the `!` - // type, but only if the source expression diverges. - if prev_ty.is_never() && new_diverges.always() { - debug!("permit coercion to `!` because expr diverges"); - return Ok(prev_ty); - } - // Special-case that coercion alone cannot handle: // Two function item types of differing IDs or Substs. if let (&ty::TyFnDef(..), &ty::TyFnDef(..)) = (&prev_ty.sty, &new_ty.sty) { @@ -1054,14 +1046,12 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> fcx: &FnCtxt<'a, 'gcx, 'tcx>, cause: &ObligationCause<'tcx>, expression: &'gcx hir::Expr, - expression_ty: Ty<'tcx>, - expression_diverges: Diverges) + expression_ty: Ty<'tcx>) { self.coerce_inner(fcx, cause, Some(expression), expression_ty, - expression_diverges, None, false) } @@ -1087,7 +1077,6 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> cause, None, fcx.tcx.mk_nil(), - Diverges::Maybe, Some(augment_error), label_unit_as_expected) } @@ -1100,7 +1089,6 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> cause: &ObligationCause<'tcx>, expression: Option<&'gcx hir::Expr>, mut expression_ty: Ty<'tcx>, - expression_diverges: Diverges, augment_error: Option<&mut FnMut(&mut DiagnosticBuilder)>, label_expression_as_expected: bool) { @@ -1134,15 +1122,13 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> exprs, self.merged_ty(), expression, - expression_ty, - expression_diverges), + expression_ty), Expressions::UpFront(ref coercion_sites) => fcx.try_find_coercion_lub(cause, &coercion_sites[0..self.pushed], self.merged_ty(), expression, - expression_ty, - expression_diverges), + expression_ty), } } } else { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b9c035e1ca1..b4a7de7b844 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -542,7 +542,7 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { /// you get indicates whether any subexpression that was /// evaluating up to and including `X` diverged. /// - /// We use this flag for two purposes: + /// We currently use this flag only for diagnostic purposes: /// /// - To warn about unreachable code: if, after processing a /// sub-expression but before we have applied the effects of the @@ -556,16 +556,8 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { /// foo();}` or `{return; 22}`, where we would warn on the /// `foo()` or `22`. /// - /// - To permit assignment into a local variable or other place - /// (including the "return slot") of type `!`. This is allowed - /// if **either** the type of value being assigned is `!`, which - /// means the current code is dead, **or** the expression's - /// diverging flag is true, which means that a diverging value was - /// wrapped (e.g., `let x: ! = foo(return)`). - /// - /// To repeat the last point: an expression represents dead-code - /// if, after checking it, **either** its type is `!` OR the - /// diverges flag is set to something other than `Maybe`. + /// An expression represents dead-code if, after checking it, + /// the diverges flag is set to something other than `Maybe`. diverges: Cell<Diverges>, /// Whether any child nodes have any type errors. @@ -3002,8 +2994,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { &self.cause(return_expr.span, ObligationCauseCode::ReturnType(return_expr.id)), return_expr, - return_expr_ty, - self.diverges.get()); + return_expr_ty); } @@ -3034,13 +3025,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut coerce: DynamicCoerceMany = CoerceMany::new(coerce_to_ty); let if_cause = self.cause(sp, ObligationCauseCode::IfExpression); - coerce.coerce(self, &if_cause, then_expr, then_ty, then_diverges); + coerce.coerce(self, &if_cause, then_expr, then_ty); if let Some(else_expr) = opt_else_expr { let else_ty = self.check_expr_with_expectation(else_expr, expected); let else_diverges = self.diverges.get(); - coerce.coerce(self, &if_cause, else_expr, else_ty, else_diverges); + coerce.coerce(self, &if_cause, else_expr, else_ty); // We won't diverge unless both branches do (or the condition does). self.diverges.set(cond_diverges | then_diverges & else_diverges); @@ -3081,12 +3072,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(index) = fields.iter().position(|f| f.name.to_ident() == ident) { let field = &fields[index]; let field_ty = self.field_ty(expr.span, field, substs); + // Save the index of all fields regardless of their visibility in case + // of error recovery. + self.write_field_index(expr.id, index); if field.vis.is_accessible_from(def_scope, self.tcx) { let adjustments = autoderef.adjust_steps(needs); self.apply_adjustments(base, adjustments); autoderef.finalize(); - self.write_field_index(expr.id, index); self.tcx.check_stability(field.did, Some(expr.id), expr.span); return field_ty; } @@ -3731,7 +3724,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } hir::ExprBreak(destination, ref expr_opt) => { if let Some(target_id) = destination.target_id.opt_id() { - let (e_ty, e_diverges, cause); + let (e_ty, cause); if let Some(ref e) = *expr_opt { // If this is a break with a value, we need to type-check // the expression. Get an expected type from the loop context. @@ -3750,13 +3743,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Recurse without `enclosing_breakables` borrowed. e_ty = self.check_expr_with_hint(e, coerce_to); - e_diverges = self.diverges.get(); cause = self.misc(e.span); } else { // Otherwise, this is a break *without* a value. That's // always legal, and is equivalent to `break ()`. e_ty = tcx.mk_nil(); - e_diverges = Diverges::Maybe; cause = self.misc(expr.span); } @@ -3767,7 +3758,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let ctxt = enclosing_breakables.find_breakable(target_id); if let Some(ref mut coerce) = ctxt.coerce { if let Some(ref e) = *expr_opt { - coerce.coerce(self, &cause, e, e_ty, e_diverges); + coerce.coerce(self, &cause, e, e_ty); } else { assert!(e_ty.is_nil()); coerce.coerce_forced_unit(self, &cause, &mut |_| (), true); @@ -3973,7 +3964,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { for e in args { let e_ty = self.check_expr_with_hint(e, coerce_to); let cause = self.misc(e.span); - coerce.coerce(self, &cause, e, e_ty, self.diverges.get()); + coerce.coerce(self, &cause, e, e_ty); } coerce.complete(self) } else { @@ -4384,8 +4375,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { coerce.coerce(self, &cause, tail_expr, - tail_expr_ty, - self.diverges.get()); + tail_expr_ty); } else { // Subtle: if there is no explicit tail expression, // that is typically equivalent to a tail expression diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index fe9fc3ddd68..32cfb05bbe4 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -413,9 +413,9 @@ impl ToJson for Type { match self.name { Some(ref name) => { let mut data = BTreeMap::new(); - data.insert("name".to_owned(), name.to_json()); + data.insert("n".to_owned(), name.to_json()); if let Some(ref generics) = self.generics { - data.insert("generics".to_owned(), generics.to_json()); + data.insert("g".to_owned(), generics.to_json()); } Json::Object(data) }, @@ -438,8 +438,12 @@ impl ToJson for IndexItemFunctionType { Json::Null } else { let mut data = BTreeMap::new(); - data.insert("inputs".to_owned(), self.inputs.to_json()); - data.insert("output".to_owned(), self.output.to_json()); + if !self.inputs.is_empty() { + data.insert("i".to_owned(), self.inputs.to_json()); + } + if let Some(ref output) = self.output { + data.insert("o".to_owned(), output.to_json()); + } Json::Object(data) } } @@ -789,7 +793,8 @@ fn write_shared(cx: &Context, format!( r#"var themes = document.getElementById("theme-choices"); var themePicker = document.getElementById("theme-picker"); -themePicker.onclick = function() {{ + +function switchThemeButtonState() {{ if (themes.style.display === "block") {{ themes.style.display = "none"; themePicker.style.borderBottomRightRadius = "3px"; @@ -800,12 +805,29 @@ themePicker.onclick = function() {{ themePicker.style.borderBottomLeftRadius = "0"; }} }}; + +function handleThemeButtonsBlur(e) {{ + var active = document.activeElement; + var related = e.relatedTarget; + + if (active.id !== "themePicker" && + (!active.parentNode || active.parentNode.id !== "theme-choices") && + (!related || + (related.id !== "themePicker" && + (!related.parentNode || related.parentNode.id !== "theme-choices")))) {{ + switchThemeButtonState(); + }} +}} + +themePicker.onclick = switchThemeButtonState; +themePicker.onblur = handleThemeButtonsBlur; [{}].forEach(function(item) {{ var but = document.createElement('button'); but.innerHTML = item; but.onclick = function(el) {{ switchTheme(currentTheme, mainTheme, item); }}; + but.onblur = handleThemeButtonsBlur; themes.appendChild(but); }});"#, themes.iter() @@ -879,8 +901,8 @@ themePicker.onclick = function() {{ } fn show_item(item: &IndexItem, krate: &str) -> String { - format!("{{'crate':'{}','ty':{},'name':'{}','path':'{}'{}}}", - krate, item.ty as usize, item.name, item.path, + format!("{{'crate':'{}','ty':{},'name':'{}','desc':'{}','p':'{}'{}}}", + krate, item.ty as usize, item.name, item.desc.replace("'", "\\'"), item.path, if let Some(p) = item.parent_idx { format!(",'parent':{}", p) } else { @@ -1442,7 +1464,7 @@ impl<'a> Cache { ty: item.type_(), name: item_name.to_string(), path: path.clone(), - desc: String::new(), + desc: plain_summary_line(item.doc_value()), parent: None, parent_idx: None, search_type: get_index_search_type(&item), diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 8569abeb09c..9224bd1c508 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -57,6 +57,12 @@ return this.indexOf(searchString, position) === position; }; } + if (!String.prototype.endsWith) { + String.prototype.endsWith = function(suffix, length) { + var l = length || this.length; + return this.indexOf(suffix, l - suffix.length) !== -1; + }; + } function getPageId() { var id = document.location.href.split('#')[1]; @@ -454,12 +460,16 @@ var obj = searchIndex[results[i].id]; obj.lev = results[i].lev; if (isType !== true || obj.type) { + var res = buildHrefAndPath(obj); + obj.displayPath = pathSplitter(res[0]); + obj.fullPath = obj.displayPath + obj.name; + obj.href = res[1]; out.push(obj); + if (out.length >= MAX_RESULTS) { + break; + } } } - if (out.length >= MAX_RESULTS) { - break; - } } return out; } @@ -587,8 +597,8 @@ // match as well. var lev_distance = MAX_LEV_DISTANCE + 1; if (val.generics.length > 0) { - if (obj.generics && obj.generics.length >= val.generics.length) { - var elems = obj.generics.slice(0); + if (obj.g && obj.g.length >= val.generics.length) { + var elems = obj.g.slice(0); var total = 0; var done = 0; // We need to find the type that matches the most to remove it in order @@ -620,11 +630,11 @@ // Check for type name and type generics (if any). function checkType(obj, val, literalSearch) { var lev_distance = MAX_LEV_DISTANCE + 1; - if (obj.name === val.name) { + if (obj.n === val.name) { if (literalSearch === true) { if (val.generics && val.generics.length !== 0) { - if (obj.generics && obj.length >= val.generics.length) { - var elems = obj.generics.slice(0); + if (obj.g && obj.length >= val.generics.length) { + var elems = obj.g.slice(0); var allFound = true; var x; @@ -648,7 +658,7 @@ } // If the type has generics but don't match, then it won't return at this point. // Otherwise, `checkGenerics` will return 0 and it'll return. - if (obj.generics && obj.generics.length !== 0) { + if (obj.g && obj.g.length !== 0) { var tmp_lev = checkGenerics(obj, val); if (tmp_lev <= MAX_LEV_DISTANCE) { return tmp_lev; @@ -659,22 +669,22 @@ } // Names didn't match so let's check if one of the generic types could. if (literalSearch === true) { - if (obj.generics && obj.generics.length > 0) { - for (var x = 0; x < obj.generics.length; ++x) { - if (obj.generics[x] === val.name) { + if (obj.g && obj.g.length > 0) { + for (var x = 0; x < obj.g.length; ++x) { + if (obj.g[x] === val.name) { return true; } } } return false; } - var lev_distance = Math.min(levenshtein(obj.name, val.name), lev_distance); + var lev_distance = Math.min(levenshtein(obj.n, val.name), lev_distance); if (lev_distance <= MAX_LEV_DISTANCE) { lev_distance = Math.min(checkGenerics(obj, val), lev_distance); - } else if (obj.generics && obj.generics.length > 0) { + } else if (obj.g && obj.g.length > 0) { // We can check if the type we're looking for is inside the generics! - for (var x = 0; x < obj.generics.length; ++x) { - lev_distance = Math.min(levenshtein(obj.generics[x], val.name), + for (var x = 0; x < obj.g.length; ++x) { + lev_distance = Math.min(levenshtein(obj.g[x], val.name), lev_distance); } } @@ -686,9 +696,9 @@ function findArg(obj, val, literalSearch) { var lev_distance = MAX_LEV_DISTANCE + 1; - if (obj && obj.type && obj.type.inputs.length > 0) { - for (var i = 0; i < obj.type.inputs.length; i++) { - var tmp = checkType(obj.type.inputs[i], val, literalSearch); + if (obj && obj.type && obj.type.i && obj.type.i.length > 0) { + for (var i = 0; i < obj.type.i.length; i++) { + var tmp = checkType(obj.type.i[i], val, literalSearch); if (literalSearch === true && tmp === true) { return true; } @@ -704,8 +714,8 @@ function checkReturned(obj, val, literalSearch) { var lev_distance = MAX_LEV_DISTANCE + 1; - if (obj && obj.type && obj.type.output) { - var tmp = checkType(obj.type.output, val, literalSearch); + if (obj && obj.type && obj.type.o) { + var tmp = checkType(obj.type.o, val, literalSearch); if (literalSearch === true && tmp === true) { return true; } @@ -850,7 +860,7 @@ var fullId = generateId(ty); // allow searching for void (no output) functions as well - var typeOutput = type.output ? type.output.name : ""; + var typeOutput = type.o ? type.o.name : ""; var returned = checkReturned(ty, output, true); if (output.name === "*" || returned === true) { var in_args = false; @@ -1017,6 +1027,13 @@ ALIASES[window.currentCrate][query.raw]) { var aliases = ALIASES[window.currentCrate][query.raw]; for (var i = 0; i < aliases.length; ++i) { + aliases[i].is_alias = true; + aliases[i].alias = query.raw; + aliases[i].path = aliases[i].p; + var res = buildHrefAndPath(aliases[i]); + aliases[i].displayPath = pathSplitter(res[0]); + aliases[i].fullPath = aliases[i].displayPath + aliases[i].name; + aliases[i].href = res[1]; ret['others'].unshift(aliases[i]); if (ret['others'].length > MAX_RESULTS) { ret['others'].pop(); @@ -1179,16 +1196,6 @@ }; } - function escape(content) { - var h1 = document.createElement('h1'); - h1.textContent = content; - return h1.innerHTML; - } - - function pathSplitter(path) { - return '<span>' + path.replace(/::/g, '::</span><span>'); - } - function buildHrefAndPath(item) { var displayPath; var href; @@ -1227,6 +1234,20 @@ return [displayPath, href]; } + function escape(content) { + var h1 = document.createElement('h1'); + h1.textContent = content; + return h1.innerHTML; + } + + function pathSplitter(path) { + var tmp = '<span>' + path.replace(/::/g, '::</span><span>'); + if (tmp.endsWith("<span>")) { + return tmp.slice(0, tmp.length - 6); + } + return tmp; + } + function addTab(array, query, display) { var extraStyle = ''; if (display === false) { @@ -1234,31 +1255,33 @@ } var output = ''; + var duplicates = {}; + var length = 0; if (array.length > 0) { output = '<table class="search-results"' + extraStyle + '>'; - var shown = []; array.forEach(function(item) { - var name, type, href, displayPath; - - var id_ty = item.ty + item.path + item.name; - if (shown.indexOf(id_ty) !== -1) { - return; - } + var name, type; - shown.push(id_ty); name = item.name; type = itemTypes[item.ty]; - var res = buildHrefAndPath(item); - var href = res[1]; - var displayPath = res[0]; + if (item.is_alias !== true) { + if (duplicates[item.fullPath]) { + return; + } + duplicates[item.fullPath] = true; + } + length += 1; output += '<tr class="' + type + ' result"><td>' + - '<a href="' + href + '">' + - pathSplitter(displayPath) + '<span class="' + type + '">' + + '<a href="' + item.href + '">' + + (item.is_alias === true ? + ('<span class="alias"><b>' + item.alias + ' </b></span><span ' + + 'class="grey"><i> - see </i></span>') : '') + + item.displayPath + '<span class="' + type + '">' + name + '</span></a></td><td>' + - '<a href="' + href + '">' + + '<a href="' + item.href + '">' + '<span class="desc">' + escape(item.desc) + ' </span></a></td></tr>'; }); @@ -1269,7 +1292,7 @@ encodeURIComponent('rust ' + query.query) + '">DuckDuckGo</a>?</div>'; } - return output; + return [output, length]; } function makeTabHeader(tabNb, text, nbElems) { @@ -1284,28 +1307,28 @@ if (results['others'].length === 1 && getCurrentValue('rustdoc-go-to-only-result') === "true") { var elem = document.createElement('a'); - var res = buildHrefAndPath(results['others'][0]); - elem.href = res[1]; + elem.href = results['others'][0].href; elem.style.display = 'none'; // For firefox, we need the element to be in the DOM so it can be clicked. document.body.appendChild(elem); elem.click(); } - var output, query = getQuery(search_input.value); + var query = getQuery(search_input.value); currentResults = query.id; - output = '<h1>Results for ' + escape(query.query) + + + var ret_others = addTab(results['others'], query); + var ret_in_args = addTab(results['in_args'], query, false); + var ret_returned = addTab(results['returned'], query, false); + + var output = '<h1>Results for ' + escape(query.query) + (query.type ? ' (type: ' + escape(query.type) + ')' : '') + '</h1>' + '<div id="titles">' + - makeTabHeader(0, "In Names", results['others'].length) + - makeTabHeader(1, "In Parameters", results['in_args'].length) + - makeTabHeader(2, "In Return Types", results['returned'].length) + - '</div><div id="results">'; - - output += addTab(results['others'], query); - output += addTab(results['in_args'], query, false); - output += addTab(results['returned'], query, false); - output += '</div>'; + makeTabHeader(0, "In Names", ret_others[1]) + + makeTabHeader(1, "In Parameters", ret_in_args[1]) + + makeTabHeader(2, "In Return Types", ret_returned[1]) + + '</div><div id="results">' + + ret_others[0] + ret_in_args[0] + ret_returned[0] + '</div>'; addClass(document.getElementById('main'), 'hidden'); var search = document.getElementById('search'); @@ -1347,12 +1370,13 @@ } } if (queries.length > 1) { - function getSmallest(arrays, positions) { + function getSmallest(arrays, positions, notDuplicates) { var start = null; for (var it = 0; it < positions.length; ++it) { if (arrays[it].length > positions[it] && - (start === null || start > arrays[it][positions[it]].lev)) { + (start === null || start > arrays[it][positions[it]].lev) && + !notDuplicates[arrays[it][positions[it]].fullPath]) { start = arrays[it][positions[it]].lev; } } @@ -1362,19 +1386,23 @@ function mergeArrays(arrays) { var ret = []; var positions = []; + var notDuplicates = {}; for (var x = 0; x < arrays.length; ++x) { positions.push(0); } while (ret.length < MAX_RESULTS) { - var smallest = getSmallest(arrays, positions); + var smallest = getSmallest(arrays, positions, notDuplicates); + if (smallest === null) { break; } for (x = 0; x < arrays.length && ret.length < MAX_RESULTS; ++x) { if (arrays[x].length > positions[x] && - arrays[x][positions[x]].lev === smallest) { + arrays[x][positions[x]].lev === smallest && + !notDuplicates[arrays[x][positions[x]].fullPath]) { ret.push(arrays[x][positions[x]]); + notDuplicates[arrays[x][positions[x]].fullPath] = true; positions[x] += 1; } } diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index da4be7db5aa..493a75e2521 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -382,7 +382,7 @@ kbd { } #theme-choices > button:hover, #theme-choices > button:focus { - background-color: #444; + background-color: #4e4e4e; } @media (max-width: 700px) { @@ -397,3 +397,10 @@ kbd { #all-types:hover { background-color: #606060; } + +.search-results td span.alias { + color: #fff; +} +.search-results td span.grey { + color: #ccc; +} \ No newline at end of file diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 12af01d2e24..22f4635fb02 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -390,4 +390,11 @@ kbd { } #all-types:hover { background-color: #f9f9f9; +} + +.search-results td span.alias { + color: #000; +} +.search-results td span.grey { + color: #999; } \ No newline at end of file diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 1fc5aed7e7a..e96a0e838cf 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -904,20 +904,8 @@ fn is_legal_fragment_specifier(sess: &ParseSess, frag_name: &str, frag_span: Span) -> bool { match frag_name { - "item" | "block" | "stmt" | "expr" | "pat" | + "item" | "block" | "stmt" | "expr" | "pat" | "lifetime" | "path" | "ty" | "ident" | "meta" | "tt" | "" => true, - "lifetime" => { - if !features.macro_lifetime_matcher && - !attr::contains_name(attrs, "allow_internal_unstable") { - let explain = feature_gate::EXPLAIN_LIFETIME_MATCHER; - emit_feature_err(sess, - "macro_lifetime_matcher", - frag_span, - GateIssue::Language, - explain); - } - true - }, "literal" => { if !features.macro_literal_matcher && !attr::contains_name(attrs, "allow_internal_unstable") { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 562705462e2..cb5125fe9ef 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -396,9 +396,6 @@ declare_features! ( // Termination trait in tests (RFC 1937) (active, termination_trait_test, "1.24.0", Some(48854), Some(Edition::Edition2018)), - // Allows use of the :lifetime macro fragment specifier - (active, macro_lifetime_matcher, "1.24.0", Some(46895), None), - // `extern` in paths (active, extern_in_paths, "1.23.0", Some(44660), None), @@ -598,6 +595,8 @@ declare_features! ( (accepted, dyn_trait, "1.27.0", Some(44662), None), // allow `#[must_use]` on functions; and, must-use operators (RFC 1940) (accepted, fn_must_use, "1.27.0", Some(43302), None), + // Allows use of the :lifetime macro fragment specifier + (accepted, macro_lifetime_matcher, "1.27.0", Some(34303), None), ); // If you change this, please modify src/doc/unstable-book as well. You must @@ -1331,9 +1330,6 @@ pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str = pub const EXPLAIN_VIS_MATCHER: &'static str = ":vis fragment specifier is experimental and subject to change"; -pub const EXPLAIN_LIFETIME_MATCHER: &'static str = - ":lifetime fragment specifier is experimental and subject to change"; - pub const EXPLAIN_LITERAL_MATCHER: &'static str = ":literal fragment specifier is experimental and subject to change"; diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs index d71527fd0ed..2b3930063f3 100644 --- a/src/libsyntax_ext/deriving/cmp/partial_ord.rs +++ b/src/libsyntax_ext/deriving/cmp/partial_ord.rs @@ -147,34 +147,37 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P< // as the outermost one, and the last as the innermost. false, |cx, span, old, self_f, other_fs| { - // match new { - // Some(::std::cmp::Ordering::Equal) => old, - // cmp => cmp - // } + // match new { + // Some(::std::cmp::Ordering::Equal) => old, + // cmp => cmp + // } - let new = { - let other_f = match (other_fs.len(), other_fs.get(0)) { - (1, Some(o_f)) => o_f, - _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"), - }; + let new = { + let other_f = match (other_fs.len(), other_fs.get(0)) { + (1, Some(o_f)) => o_f, + _ => { + cx.span_bug(span, + "not exactly 2 arguments in `derive(PartialOrd)`") + } + }; - let args = vec![ - cx.expr_addr_of(span, self_f), - cx.expr_addr_of(span, other_f.clone()), - ]; + let args = vec![ + cx.expr_addr_of(span, self_f), + cx.expr_addr_of(span, other_f.clone()), + ]; - cx.expr_call_global(span, partial_cmp_path.clone(), args) - }; + cx.expr_call_global(span, partial_cmp_path.clone(), args) + }; - let eq_arm = cx.arm(span, - vec![cx.pat_some(span, cx.pat_path(span, ordering.clone()))], - old); - let neq_arm = cx.arm(span, - vec![cx.pat_ident(span, test_id)], - cx.expr_ident(span, test_id)); + let eq_arm = cx.arm(span, + vec![cx.pat_some(span, cx.pat_path(span, ordering.clone()))], + old); + let neq_arm = cx.arm(span, + vec![cx.pat_ident(span, test_id)], + cx.expr_ident(span, test_id)); - cx.expr_match(span, new, vec![eq_arm, neq_arm]) - }, + cx.expr_match(span, new, vec![eq_arm, neq_arm]) + }, equals_expr.clone(), Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { if self_args.len() != 2 { @@ -189,78 +192,99 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P< } /// Strict inequality. -fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { - let strict_op = if less { BinOpKind::Lt } else { BinOpKind::Gt }; - cs_fold1(false, // need foldr, +fn cs_op(less: bool, + inclusive: bool, + cx: &mut ExtCtxt, + span: Span, + substr: &Substructure) -> P<Expr> { + let ordering_path = |cx: &mut ExtCtxt, name: &str| { + cx.expr_path(cx.path_global(span, cx.std_path(&["cmp", "Ordering", name]))) + }; + + let par_cmp = |cx: &mut ExtCtxt, span, self_f: P<Expr>, other_fs: &[P<Expr>], default| { + let other_f = match (other_fs.len(), other_fs.get(0)) { + (1, Some(o_f)) => o_f, + _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"), + }; + + // `PartialOrd::partial_cmp(self.fi, other.fi)` + let cmp_path = cx.expr_path(cx.path_global(span, cx.std_path(&["cmp", + "PartialOrd", + "partial_cmp"]))); + let cmp = cx.expr_call(span, + cmp_path, + vec![cx.expr_addr_of(span, self_f), + cx.expr_addr_of(span, other_f.clone())]); + + let default = ordering_path(cx, default); + // `Option::unwrap_or(_, Ordering::Equal)` + let unwrap_path = cx.expr_path(cx.path_global(span, cx.std_path(&["option", + "Option", + "unwrap_or"]))); + cx.expr_call(span, unwrap_path, vec![cmp, default]) + }; + + let fold = cs_fold1(false, // need foldr |cx, span, subexpr, self_f, other_fs| { - // build up a series of chain ||'s and &&'s from the inside + // build up a series of `partial_cmp`s from the inside // out (hence foldr) to get lexical ordering, i.e. for op == // `ast::lt` // // ``` - // self.f1 < other.f1 || (!(other.f1 < self.f1) && - // self.f2 < other.f2 + // Ordering::then_with( + // Option::unwrap_or( + // PartialOrd::partial_cmp(self.f1, other.f1), Ordering::Equal) + // ), + // Option::unwrap_or( + // PartialOrd::partial_cmp(self.f2, other.f2), Ordering::Greater) + // ) // ) + // == Ordering::Less // ``` // // and for op == // `ast::le` // // ``` - // self.f1 < other.f1 || (self.f1 == other.f1 && - // self.f2 <= other.f2 + // Ordering::then_with( + // Option::unwrap_or( + // PartialOrd::partial_cmp(self.f1, other.f1), Ordering::Equal) + // ), + // Option::unwrap_or( + // PartialOrd::partial_cmp(self.f2, other.f2), Ordering::Greater) + // ) // ) + // != Ordering::Greater // ``` // // The optimiser should remove the redundancy. We explicitly // get use the binops to avoid auto-deref dereferencing too many // layers of pointers, if the type includes pointers. - // - let other_f = match (other_fs.len(), other_fs.get(0)) { - (1, Some(o_f)) => o_f, - _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"), - }; - let strict_ineq = cx.expr_binary(span, strict_op, self_f.clone(), other_f.clone()); + // `Option::unwrap_or(PartialOrd::partial_cmp(self.fi, other.fi), Ordering::Equal)` + let par_cmp = par_cmp(cx, span, self_f, other_fs, "Equal"); - let deleg_cmp = if !equal { - cx.expr_unary(span, - ast::UnOp::Not, - cx.expr_binary(span, strict_op, other_f.clone(), self_f)) - } else { - cx.expr_binary(span, BinOpKind::Eq, self_f, other_f.clone()) - }; - - let and = cx.expr_binary(span, BinOpKind::And, deleg_cmp, subexpr); - cx.expr_binary(span, BinOpKind::Or, strict_ineq, and) + // `Ordering::then_with(Option::unwrap_or(..), ..)` + let then_with_path = cx.expr_path(cx.path_global(span, + cx.std_path(&["cmp", + "Ordering", + "then_with"]))); + cx.expr_call(span, then_with_path, vec![par_cmp, cx.lambda0(span, subexpr)]) }, |cx, args| { match args { Some((span, self_f, other_fs)) => { - // Special-case the base case to generate cleaner code with - // fewer operations (e.g. `<=` instead of `<` and `==`). - let other_f = match (other_fs.len(), other_fs.get(0)) { - (1, Some(o_f)) => o_f, - _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"), - }; - - let op = match (less, equal) { - (false, false) => BinOpKind::Gt, - (false, true) => BinOpKind::Ge, - (true, false) => BinOpKind::Lt, - (true, true) => BinOpKind::Le, - }; - - cx.expr_binary(span, op, self_f, other_f.clone()) - } - None => cx.expr_bool(span, equal) + let opposite = if less { "Greater" } else { "Less" }; + par_cmp(cx, span, self_f, other_fs, opposite) + }, + None => cx.expr_bool(span, inclusive) } }, Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { if self_args.len() != 2 { cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`") } else { - let op = match (less, equal) { + let op = match (less, inclusive) { (false, false) => GtOp, (false, true) => GeOp, (true, false) => LtOp, @@ -271,5 +295,16 @@ fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt, span: Span, substr: &Substru }), cx, span, - substr) + substr); + + match *substr.fields { + EnumMatching(.., ref all_fields) | + Struct(.., ref all_fields) if !all_fields.is_empty() => { + let ordering = ordering_path(cx, if less ^ inclusive { "Less" } else { "Greater" }); + let comp_op = if inclusive { BinOpKind::Ne } else { BinOpKind::Eq }; + + cx.expr_binary(span, comp_op, fold, ordering) + } + _ => fold + } } diff --git a/src/stdsimd b/src/stdsimd -Subproject 2f86c75a2479cf051b92fc98273daaf7f151e7a +Subproject a19ca1cd91cf97777af8268a6136bd2e4648e18 diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/issue_50493.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/issue_50493.rs new file mode 100644 index 00000000000..7d36517d970 --- /dev/null +++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/issue_50493.rs @@ -0,0 +1,32 @@ +// Copyright 2016 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// force-host +// no-prefer-dynamic + +#![feature(proc_macro, proc_macro_lib)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_derive(Derive)] +pub fn derive(_: TokenStream) -> TokenStream { + let code = " + fn one(r: Restricted) { + r.field; + } + fn two(r: Restricted) { + r.field; + } + "; + + code.parse().unwrap() +} diff --git a/src/test/compile-fail-fulldeps/proc-macro/issue-50493.rs b/src/test/compile-fail-fulldeps/proc-macro/issue-50493.rs new file mode 100644 index 00000000000..51112f202c8 --- /dev/null +++ b/src/test/compile-fail-fulldeps/proc-macro/issue-50493.rs @@ -0,0 +1,27 @@ +// Copyright 2016 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:issue_50493.rs +// ignore-stage1 + +#![feature(proc_macro)] + +#[macro_use] +extern crate issue_50493; + +#[derive(Derive)] //~ ERROR field `field` of struct `Restricted` is private +struct Restricted { + pub(in restricted) field: usize, //~ visibilities can only be restricted to ancestor modules +} + +mod restricted {} + +fn main() {} + diff --git a/src/test/compile-fail/coerce-to-bang.rs b/src/test/compile-fail/coerce-to-bang.rs index 62ff09f4616..8b4e2c3c051 100644 --- a/src/test/compile-fail/coerce-to-bang.rs +++ b/src/test/compile-fail/coerce-to-bang.rs @@ -56,9 +56,8 @@ fn call_foo_f() { } fn array_a() { - // Accepted: return is coerced to `!` just fine, and then `22` can be - // because we already diverged. - let x: [!; 2] = [return, 22]; + // Return is coerced to `!` just fine, but `22` cannot be. + let x: [!; 2] = [return, 22]; //~ ERROR mismatched types } fn array_b() { diff --git a/src/test/compile-fail/derives-span-PartialOrd-enum-struct-variant.rs b/src/test/compile-fail/derives-span-PartialOrd-enum-struct-variant.rs index dcf02f30830..a5df717e06b 100644 --- a/src/test/compile-fail/derives-span-PartialOrd-enum-struct-variant.rs +++ b/src/test/compile-fail/derives-span-PartialOrd-enum-struct-variant.rs @@ -17,10 +17,6 @@ struct Error; enum Enum { A { x: Error //~ ERROR -//~^ ERROR -//~^^ ERROR -//~^^^ ERROR -//~^^^^ ERROR } } diff --git a/src/test/compile-fail/derives-span-PartialOrd-enum.rs b/src/test/compile-fail/derives-span-PartialOrd-enum.rs index 7eb44c7e19e..3411d2f3119 100644 --- a/src/test/compile-fail/derives-span-PartialOrd-enum.rs +++ b/src/test/compile-fail/derives-span-PartialOrd-enum.rs @@ -17,10 +17,6 @@ struct Error; enum Enum { A( Error //~ ERROR -//~^ ERROR -//~^^ ERROR -//~^^^ ERROR -//~^^^^ ERROR ) } diff --git a/src/test/compile-fail/derives-span-PartialOrd-struct.rs b/src/test/compile-fail/derives-span-PartialOrd-struct.rs index 36dae0124ce..1feadc2fd83 100644 --- a/src/test/compile-fail/derives-span-PartialOrd-struct.rs +++ b/src/test/compile-fail/derives-span-PartialOrd-struct.rs @@ -16,10 +16,6 @@ struct Error; #[derive(PartialOrd,PartialEq)] struct Struct { x: Error //~ ERROR -//~^ ERROR -//~^^ ERROR -//~^^^ ERROR -//~^^^^ ERROR } fn main() {} diff --git a/src/test/compile-fail/derives-span-PartialOrd-tuple-struct.rs b/src/test/compile-fail/derives-span-PartialOrd-tuple-struct.rs index fd2df096754..9db0fed2d9e 100644 --- a/src/test/compile-fail/derives-span-PartialOrd-tuple-struct.rs +++ b/src/test/compile-fail/derives-span-PartialOrd-tuple-struct.rs @@ -16,10 +16,6 @@ struct Error; #[derive(PartialOrd,PartialEq)] struct Struct( Error //~ ERROR -//~^ ERROR -//~^^ ERROR -//~^^^ ERROR -//~^^^^ ERROR ); fn main() {} diff --git a/src/test/compile-fail/range_traits-1.rs b/src/test/compile-fail/range_traits-1.rs index df766e361d5..32f9b83b6e2 100644 --- a/src/test/compile-fail/range_traits-1.rs +++ b/src/test/compile-fail/range_traits-1.rs @@ -15,35 +15,21 @@ struct AllTheRanges { a: Range<usize>, //~^ ERROR PartialOrd //~^^ ERROR Ord - //~^^^ ERROR binary operation `<` cannot be applied to type - //~^^^^ ERROR binary operation `>` cannot be applied to type b: RangeTo<usize>, //~^ ERROR PartialOrd //~^^ ERROR Ord - //~^^^ ERROR binary operation `<` cannot be applied to type - //~^^^^ ERROR binary operation `>` cannot be applied to type c: RangeFrom<usize>, //~^ ERROR PartialOrd //~^^ ERROR Ord - //~^^^ ERROR binary operation `<` cannot be applied to type - //~^^^^ ERROR binary operation `>` cannot be applied to type d: RangeFull, //~^ ERROR PartialOrd //~^^ ERROR Ord - //~^^^ ERROR binary operation `<` cannot be applied to type - //~^^^^ ERROR binary operation `>` cannot be applied to type e: RangeInclusive<usize>, //~^ ERROR PartialOrd //~^^ ERROR Ord - //~^^^ ERROR binary operation `<` cannot be applied to type - //~^^^^ ERROR binary operation `>` cannot be applied to type f: RangeToInclusive<usize>, //~^ ERROR PartialOrd //~^^ ERROR Ord - //~^^^ ERROR binary operation `<` cannot be applied to type - //~^^^^ ERROR binary operation `>` cannot be applied to type - //~^^^^^ ERROR binary operation `<=` cannot be applied to type - //~^^^^^^ ERROR binary operation `>=` cannot be applied to type } fn main() {} diff --git a/src/test/ui/feature-gate-macro-lifetime-matcher.rs b/src/test/run-pass/issue-50731.rs index 0d107d283cd..06df2b989af 100644 --- a/src/test/ui/feature-gate-macro-lifetime-matcher.rs +++ b/src/test/run-pass/issue-50731.rs @@ -1,4 +1,4 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,12 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that the :lifetime macro fragment cannot be used when macro_lifetime_matcher -// feature gate is not used. - -macro_rules! m { ($lt:lifetime) => {} } -//~^ ERROR :lifetime fragment specifier is experimental and subject to change - +enum Void {} +fn foo(_: Result<(Void, u32), (Void, String)>) {} fn main() { - m!('a); + let _: fn(_) = foo; } diff --git a/src/test/run-pass/macro-lifetime-used-with-bound.rs b/src/test/run-pass/macro-lifetime-used-with-bound.rs index b0c9280b6ce..b9e1fde6b1f 100644 --- a/src/test/run-pass/macro-lifetime-used-with-bound.rs +++ b/src/test/run-pass/macro-lifetime-used-with-bound.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_lifetime_matcher)] - macro_rules! foo { ($l:lifetime, $l2:lifetime) => { fn f<$l: $l2, $l2>(arg: &$l str, arg2: &$l2 str) -> &$l str { diff --git a/src/test/run-pass/macro-lifetime-used-with-labels.rs b/src/test/run-pass/macro-lifetime-used-with-labels.rs index 8a2d76e17df..d003d7dcfb6 100644 --- a/src/test/run-pass/macro-lifetime-used-with-labels.rs +++ b/src/test/run-pass/macro-lifetime-used-with-labels.rs @@ -9,7 +9,6 @@ // except according to those terms. #![allow(unreachable_code)] -#![feature(macro_lifetime_matcher)] macro_rules! x { ($a:lifetime) => { diff --git a/src/test/run-pass/macro-lifetime-used-with-static.rs b/src/test/run-pass/macro-lifetime-used-with-static.rs index 468ee2e9436..5c1f8683e00 100644 --- a/src/test/run-pass/macro-lifetime-used-with-static.rs +++ b/src/test/run-pass/macro-lifetime-used-with-static.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_lifetime_matcher)] - macro_rules! foo { ($l:lifetime) => { fn f(arg: &$l str) -> &$l str { diff --git a/src/test/run-pass/macro-lifetime.rs b/src/test/run-pass/macro-lifetime.rs index db521ca7f10..ff5798ff78d 100644 --- a/src/test/run-pass/macro-lifetime.rs +++ b/src/test/run-pass/macro-lifetime.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_lifetime_matcher)] - macro_rules! foo { ($l:lifetime) => { fn f<$l>(arg: &$l str) -> &$l str { diff --git a/src/test/rustdoc-js/deduplication.js b/src/test/rustdoc-js/deduplication.js new file mode 100644 index 00000000000..0f29607d5c9 --- /dev/null +++ b/src/test/rustdoc-js/deduplication.js @@ -0,0 +1,21 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-order + +const QUERY = 'is_nan'; + +const EXPECTED = { + 'others': [ + { 'path': 'std::f32', 'name': 'is_nan' }, + { 'path': 'std::f64', 'name': 'is_nan' }, + { 'path': 'std::option::Option', 'name': 'is_none' }, + ], +}; diff --git a/src/test/ui/feature-gate-macro-lifetime-matcher.stderr b/src/test/ui/feature-gate-macro-lifetime-matcher.stderr deleted file mode 100644 index b7805f6f5fb..00000000000 --- a/src/test/ui/feature-gate-macro-lifetime-matcher.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: :lifetime fragment specifier is experimental and subject to change (see issue #46895) - --> $DIR/feature-gate-macro-lifetime-matcher.rs:14:19 - | -LL | macro_rules! m { ($lt:lifetime) => {} } - | ^^^^^^^^^^^^ - | - = help: add #![feature(macro_lifetime_matcher)] to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/macros/nonterminal-matching.rs b/src/test/ui/macros/nonterminal-matching.rs index 4dcb8afa94e..54d280a63e7 100644 --- a/src/test/ui/macros/nonterminal-matching.rs +++ b/src/test/ui/macros/nonterminal-matching.rs @@ -11,7 +11,7 @@ // Check that we are refusing to match on complex nonterminals for which tokens are // unavailable and we'd have to go through AST comparisons. -#![feature(decl_macro, macro_lifetime_matcher)] +#![feature(decl_macro)] macro simple_nonterminal($nt_ident: ident, $nt_lifetime: lifetime, $nt_tt: tt) { macro n(a $nt_ident b $nt_lifetime c $nt_tt d) { diff --git a/src/tools/clippy b/src/tools/clippy -Subproject 7a4c00c669b3bf0ffb24c7aa89a776cd48f1e2d +Subproject c658fc8cbcd1f199edd445a49cb43139ebdc5f0 diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 25f7a2d1294..47667d93cb7 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -160,10 +160,11 @@ function main(argv) { // execQuery first parameter is built in getQuery (which takes in the search input). // execQuery last parameter is built in buildIndex. // buildIndex requires the hashmap from search-index. - var functionsToLoad = ["levenshtein", "validateResult", "getQuery", "buildIndex", "execQuery", - "execSearch"]; + var functionsToLoad = ["buildHrefAndPath", "pathSplitter", "levenshtein", "validateResult", + "getQuery", "buildIndex", "execQuery", "execSearch"]; finalJS += 'window = { "currentCrate": "std" };\n'; + finalJS += 'var rootPath = "../";\n'; finalJS += ALIASES; finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, mainJs); finalJS += loadThings(variablesToLoad, 'variable', extractVariable, mainJs); |
