Merge branch 'master' of https://github.com/nicokoch/rust
This commit is contained in:
commit
b4b71d5d5f
45 changed files with 440 additions and 369 deletions
7
src/Cargo.lock
generated
7
src/Cargo.lock
generated
|
|
@ -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)",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
------------------------
|
||||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 2a2f6d96c8dc578d2474742f14c9bab0b36b0408
|
||||
Subproject commit 4cfd7101eb549169cdaeda5313f7c39415b9d736
|
||||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
_ => {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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 name, type;
|
||||
|
||||
var id_ty = item.ty + item.path + item.name;
|
||||
if (shown.indexOf(id_ty) !== -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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") {
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 2f86c75a2479cf051b92fc98273daaf7f151e7a1
|
||||
Subproject commit a19ca1cd91cf97777af8268a6136bd2e4648e189
|
||||
|
|
@ -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()
|
||||
}
|
||||
27
src/test/compile-fail-fulldeps/proc-macro/issue-50493.rs
Normal file
27
src/test/compile-fail-fulldeps/proc-macro/issue-50493.rs
Normal file
|
|
@ -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() {}
|
||||
|
||||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -17,10 +17,6 @@ struct Error;
|
|||
enum Enum {
|
||||
A {
|
||||
x: Error //~ ERROR
|
||||
//~^ ERROR
|
||||
//~^^ ERROR
|
||||
//~^^^ ERROR
|
||||
//~^^^^ ERROR
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,10 +17,6 @@ struct Error;
|
|||
enum Enum {
|
||||
A(
|
||||
Error //~ ERROR
|
||||
//~^ ERROR
|
||||
//~^^ ERROR
|
||||
//~^^^ ERROR
|
||||
//~^^^^ ERROR
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,10 +16,6 @@ struct Error;
|
|||
#[derive(PartialOrd,PartialEq)]
|
||||
struct Struct {
|
||||
x: Error //~ ERROR
|
||||
//~^ ERROR
|
||||
//~^^ ERROR
|
||||
//~^^^ ERROR
|
||||
//~^^^^ ERROR
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,6 @@ struct Error;
|
|||
#[derive(PartialOrd,PartialEq)]
|
||||
struct Struct(
|
||||
Error //~ ERROR
|
||||
//~^ ERROR
|
||||
//~^^ ERROR
|
||||
//~^^^ ERROR
|
||||
//~^^^^ ERROR
|
||||
);
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
// except according to those terms.
|
||||
|
||||
#![allow(unreachable_code)]
|
||||
#![feature(macro_lifetime_matcher)]
|
||||
|
||||
macro_rules! x {
|
||||
($a:lifetime) => {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
21
src/test/rustdoc-js/deduplication.js
Normal file
21
src/test/rustdoc-js/deduplication.js
Normal file
|
|
@ -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' },
|
||||
],
|
||||
};
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 7a4c00c669b3bf0ffb24c7aa89a776cd48f1e2d0
|
||||
Subproject commit c658fc8cbcd1f199edd445a49cb43139ebdc5f02
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue