diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index b89976eca26c4..b6764c1aaeab6 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -287,10 +287,6 @@ fn main() { cmd.arg("--cfg").arg("parallel_queries"); } - if env::var_os("RUSTC_VERIFY_LLVM_IR").is_some() { - cmd.arg("-Z").arg("verify-llvm-ir"); - } - if env::var_os("RUSTC_DENY_WARNINGS").is_some() && env::var_os("RUSTC_EXTERNAL_TOOL").is_none() { cmd.arg("-Dwarnings"); diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index b842bc43f5baa..aa4e44df2ef94 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1000,10 +1000,6 @@ impl<'a> Builder<'a> { cargo.env("RUSTC_BACKTRACE_ON_ICE", "1"); } - if self.config.rust_verify_llvm_ir { - cargo.env("RUSTC_VERIFY_LLVM_IR", "1"); - } - cargo.env("RUSTC_VERBOSE", self.verbosity.to_string()); // in std, we want to avoid denying warnings for stage 0 as that makes cfg's painful. diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 7d235743c2c46..69d45acdedaf9 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -569,6 +569,9 @@ pub fn rustc_cargo_env(builder: &Builder, cargo: &mut Command) { if builder.config.rustc_parallel_queries { cargo.env("RUSTC_PARALLEL_QUERIES", "1"); } + if builder.config.rust_verify_llvm_ir { + cargo.env("RUSTC_VERIFY_LLVM_IR", "1"); + } } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 633c15b54b9ef..80c89b9ff3826 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -812,8 +812,7 @@ default_test!(Incremental { default_test!(Debuginfo { path: "src/test/debuginfo", - // What this runs varies depending on the native platform being apple - mode: "debuginfo-XXX", + mode: "debuginfo", suite: "debuginfo" }); @@ -950,18 +949,11 @@ impl Step for Compiletest { return; } - if mode == "debuginfo-XXX" { - return if builder.config.build.contains("apple") { - builder.ensure(Compiletest { - mode: "debuginfo-lldb", - ..self - }); - } else { - builder.ensure(Compiletest { - mode: "debuginfo-gdb", - ..self - }); - }; + if mode == "debuginfo" { + return builder.ensure(Compiletest { + mode: "debuginfo-both", + ..self + }); } builder.ensure(dist::DebuggerScripts { diff --git a/src/ci/run.sh b/src/ci/run.sh index a9e506645f189..42561cf95d3ac 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -61,6 +61,7 @@ if [ "$DEPLOY$DEPLOY_ALT" != "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-assertions" elif [ "$DEPLOY_ALT" != "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-assertions" + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.verify-llvm-ir" fi else # We almost always want debug assertions enabled, but sometimes this takes too @@ -74,6 +75,8 @@ else if [ "$NO_LLVM_ASSERTIONS" = "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-assertions" fi + + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.verify-llvm-ir" fi if [ "$RUST_RELEASE_CHANNEL" = "nightly" ] || [ "$DIST_REQUIRE_ALL_TOOLS" = "" ]; then diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index e2b001832fe31..b60c55240140e 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -10,6 +10,11 @@ This flag will print out help information for `rustc`. This flag can turn on or off various `#[cfg]` settings. +The value can either be a single identifier or two identifiers separated by `=`. + +For examples, `--cfg 'verbose'` or `--cfg 'feature="serde"'`. These correspond +to `#[cfg(verbose)]` and `#[cfg(feature = "serde")]` respectively. + ## `-L`: add a directory to the library search path When looking for external crates, a directory passed to this flag will be searched. diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index a2e68a223f16b..b857964ccb3c3 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -335,8 +335,7 @@ //! //! Each argument being formatted can be transformed by a number of formatting //! parameters (corresponding to `format_spec` in the syntax above). These -//! parameters affect the string representation of what's being formatted. This -//! syntax draws heavily from Python's, so it may seem a bit familiar. +//! parameters affect the string representation of what's being formatted. //! //! ## Fill/Alignment //! diff --git a/src/librustc/build.rs b/src/librustc/build.rs index 4df5f0e64050c..bde503d86de73 100644 --- a/src/librustc/build.rs +++ b/src/librustc/build.rs @@ -8,8 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::env; + fn main() { println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-env-changed=CFG_LIBDIR_RELATIVE"); println!("cargo:rerun-if-env-changed=CFG_COMPILER_HOST_TRIPLE"); + println!("cargo:rerun-if-env-changed=RUSTC_VERIFY_LLVM_IR"); + + if env::var_os("RUSTC_VERIFY_LLVM_IR").is_some() { + println!("cargo:rustc-cfg=always_verify_llvm_ir"); + } } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 1ca60d54f7a3d..2b90a27b6a8ce 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -525,6 +525,7 @@ impl Session { } pub fn verify_llvm_ir(&self) -> bool { self.opts.debugging_opts.verify_llvm_ir + || cfg!(always_verify_llvm_ir) } pub fn borrowck_stats(&self) -> bool { self.opts.debugging_opts.borrowck_stats diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index c4f39ffcd2067..14e4ddfcdd636 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -369,16 +369,16 @@ define_queries! { <'tcx> -> Lrc, [] fn is_object_safe: ObjectSafety(DefId) -> bool, - // Get the ParameterEnvironment for a given item; this environment - // will be in "user-facing" mode, meaning that it is suitabe for - // type-checking etc, and it does not normalize specializable - // associated types. This is almost always what you want, - // unless you are doing MIR optimizations, in which case you - // might want to use `reveal_all()` method to change modes. + /// Get the ParameterEnvironment for a given item; this environment + /// will be in "user-facing" mode, meaning that it is suitabe for + /// type-checking etc, and it does not normalize specializable + /// associated types. This is almost always what you want, + /// unless you are doing MIR optimizations, in which case you + /// might want to use `reveal_all()` method to change modes. [] fn param_env: ParamEnv(DefId) -> ty::ParamEnv<'tcx>, - // Trait selection queries. These are best used by invoking `ty.moves_by_default()`, - // `ty.is_copy()`, etc, since that will prune the environment where possible. + /// Trait selection queries. These are best used by invoking `ty.moves_by_default()`, + /// `ty.is_copy()`, etc, since that will prune the environment where possible. [] fn is_copy_raw: is_copy_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool, [] fn is_sized_raw: is_sized_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool, [] fn is_freeze_raw: is_freeze_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool, diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index df9c4e874bd95..169bd9a8466a0 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -756,7 +756,7 @@ impl Builder<'a, 'll, 'tcx> { // Ask LLVM to verify that the constraints are well-formed. let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons); debug!("Constraint verification result: {:?}", constraints_ok); - if constraints_ok == llvm::True { + if constraints_ok { let v = llvm::LLVMRustInlineAsm( fty, asm, cons, volatile, alignstack, dia); Some(self.call(v, inputs, None)) diff --git a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs index 0484837a48d7d..56352ae963f20 100644 --- a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs +++ b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs @@ -37,7 +37,7 @@ pub struct MirDebugScope<'ll> { impl MirDebugScope<'ll> { pub fn is_valid(&self) -> bool { - !self.scope_metadata.is_none() + self.scope_metadata.is_some() } } diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 6eff086a2ba05..f5e5287cd42c5 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -163,10 +163,10 @@ impl TypeMap<'ll, 'tcx> { fn get_unique_type_id_of_type<'a>(&mut self, cx: &CodegenCx<'a, 'tcx>, type_: Ty<'tcx>) -> UniqueTypeId { // Let's see if we already have something in the cache - match self.type_to_unique_id.get(&type_).cloned() { - Some(unique_type_id) => return unique_type_id, - None => { /* generate one */} - }; + if let Some(unique_type_id) = self.type_to_unique_id.get(&type_).cloned() { + return unique_type_id; + } + // if not, generate one // The hasher we are using to generate the UniqueTypeId. We want // something that provides more than the 64 bits of the DefaultHasher. @@ -286,11 +286,11 @@ impl RecursiveTypeDescription<'ll, 'tcx> { // unique id can be found in the type map macro_rules! return_if_metadata_created_in_meantime { ($cx: expr, $unique_type_id: expr) => ( - match debug_context($cx).type_map - .borrow() - .find_metadata_for_unique_id($unique_type_id) { - Some(metadata) => return MetadataCreationResult::new(metadata, true), - None => { /* proceed normally */ } + if let Some(metadata) = debug_context($cx).type_map + .borrow() + .find_metadata_for_unique_id($unique_type_id) + { + return MetadataCreationResult::new(metadata, true); } ) } @@ -352,7 +352,7 @@ fn vec_slice_metadata( let member_descriptions = vec![ MemberDescription { - name: "data_ptr".to_string(), + name: "data_ptr".to_owned(), type_metadata: data_ptr_metadata, offset: Size::ZERO, size: pointer_size, @@ -360,7 +360,7 @@ fn vec_slice_metadata( flags: DIFlags::FlagZero, }, MemberDescription { - name: "length".to_string(), + name: "length".to_owned(), type_metadata: type_metadata(cx, cx.tcx.types.usize, span), offset: pointer_size, size: usize_size, @@ -458,7 +458,7 @@ fn trait_pointer_metadata( let vtable_field = layout.field(cx, 1); let member_descriptions = vec![ MemberDescription { - name: "pointer".to_string(), + name: "pointer".to_owned(), type_metadata: type_metadata(cx, cx.tcx.mk_mut_ptr(cx.tcx.types.u8), syntax_pos::DUMMY_SP), @@ -468,7 +468,7 @@ fn trait_pointer_metadata( flags: DIFlags::FlagArtificial, }, MemberDescription { - name: "vtable".to_string(), + name: "vtable".to_owned(), type_metadata: type_metadata(cx, vtable_field.ty, syntax_pos::DUMMY_SP), offset: layout.fields.offset(1), size: vtable_field.size, @@ -543,12 +543,12 @@ pub fn type_metadata( _ => { let pointee_metadata = type_metadata(cx, ty, usage_site_span); - match debug_context(cx).type_map - .borrow() - .find_metadata_for_unique_id(unique_type_id) { - Some(metadata) => return Err(metadata), - None => { /* proceed normally */ } - }; + if let Some(metadata) = debug_context(cx).type_map + .borrow() + .find_metadata_for_unique_id(unique_type_id) + { + return Err(metadata); + } Ok(MetadataCreationResult::new(pointer_type_metadata(cx, t, pointee_metadata), false)) @@ -577,12 +577,12 @@ pub fn type_metadata( } ty::Dynamic(..) => { MetadataCreationResult::new( - trait_pointer_metadata(cx, t, None, unique_type_id), - false) + trait_pointer_metadata(cx, t, None, unique_type_id), + false) } ty::Foreign(..) => { MetadataCreationResult::new( - foreign_type_metadata(cx, t, unique_type_id), + foreign_type_metadata(cx, t, unique_type_id), false) } ty::RawPtr(ty::TypeAndMut{ty, ..}) | @@ -603,12 +603,12 @@ pub fn type_metadata( unique_type_id, t.fn_sig(cx.tcx), usage_site_span).metadata; - match debug_context(cx).type_map - .borrow() - .find_metadata_for_unique_id(unique_type_id) { - Some(metadata) => return metadata, - None => { /* proceed normally */ } - }; + if let Some(metadata) = debug_context(cx).type_map + .borrow() + .find_metadata_for_unique_id(unique_type_id) + { + return metadata; + } // This is actually a function pointer, so wrap it in pointer DI MetadataCreationResult::new(pointer_type_metadata(cx, t, fn_metadata), false) @@ -641,16 +641,16 @@ pub fn type_metadata( } AdtKind::Union => { prepare_union_metadata(cx, - t, - unique_type_id, - usage_site_span).finalize(cx) + t, + unique_type_id, + usage_site_span).finalize(cx) } AdtKind::Enum => { prepare_enum_metadata(cx, - t, - def.did, - unique_type_id, - usage_site_span).finalize(cx) + t, + def.did, + unique_type_id, + usage_site_span).finalize(cx) } }, ty::Tuple(ref elements) => { @@ -938,7 +938,7 @@ enum MemberDescriptionFactory<'ll, 'tcx> { impl MemberDescriptionFactory<'ll, 'tcx> { fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) - -> Vec> { + -> Vec> { match *self { StructMDF(ref this) => { this.create_member_descriptions(cx) @@ -972,7 +972,7 @@ struct StructMemberDescriptionFactory<'tcx> { impl<'tcx> StructMemberDescriptionFactory<'tcx> { fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) - -> Vec> { + -> Vec> { let layout = cx.layout_of(self.ty); self.variant.fields.iter().enumerate().map(|(i, f)| { let name = if self.variant.ctor_kind == CtorKind::Fn { @@ -1042,7 +1042,7 @@ struct TupleMemberDescriptionFactory<'tcx> { impl<'tcx> TupleMemberDescriptionFactory<'tcx> { fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) - -> Vec> { + -> Vec> { let layout = cx.layout_of(self.ty); self.component_types.iter().enumerate().map(|(i, &component_type)| { let (size, align) = cx.size_and_align_of(component_type); @@ -1096,7 +1096,7 @@ struct UnionMemberDescriptionFactory<'tcx> { impl<'tcx> UnionMemberDescriptionFactory<'tcx> { fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) - -> Vec> { + -> Vec> { self.variant.fields.iter().enumerate().map(|(i, f)| { let field = self.layout.field(cx, i); let (size, align) = field.size_and_align(); @@ -1165,7 +1165,7 @@ struct EnumMemberDescriptionFactory<'ll, 'tcx> { impl EnumMemberDescriptionFactory<'ll, 'tcx> { fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) - -> Vec> { + -> Vec> { let adt = &self.enum_type.ty_adt_def().unwrap(); match self.layout.variants { layout::Variants::Single { .. } if adt.variants.is_empty() => vec![], @@ -1357,7 +1357,7 @@ fn describe_enum_variant( // We have the layout of an enum variant, we need the layout of the outer enum let enum_layout = cx.layout_of(layout.ty); (Some(enum_layout.fields.offset(0)), - Some(("RUST$ENUM$DISR".to_string(), enum_layout.field(cx, 0).ty))) + Some(("RUST$ENUM$DISR".to_owned(), enum_layout.field(cx, 0).ty))) } _ => (None, None), }; @@ -1471,9 +1471,8 @@ fn prepare_enum_metadata( } }; - match (&layout.abi, discriminant_type_metadata) { - (&layout::Abi::Scalar(_), Some(discr)) => return FinalMetadata(discr), - _ => {} + if let (&layout::Abi::Scalar(_), Some(discr)) = (&layout.abi, discriminant_type_metadata) { + return FinalMetadata(discr); } let (enum_type_size, enum_type_align) = layout.size_and_align(); @@ -1546,7 +1545,7 @@ fn composite_type_metadata( composite_type_metadata, member_descriptions); - return composite_type_metadata; + composite_type_metadata } fn set_members_of_composite_type(cx: &CodegenCx<'ll, '_>, @@ -1634,7 +1633,7 @@ fn create_struct_stub( unique_type_id.as_ptr()) }; - return metadata_stub; + metadata_stub } fn create_union_stub( @@ -1670,7 +1669,7 @@ fn create_union_stub( unique_type_id.as_ptr()) }; - return metadata_stub; + metadata_stub } /// Creates debug information for the given global variable. diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index 7b0c413e85761..acb79d6f568cc 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -271,16 +271,14 @@ pub fn create_function_debug_context( let mut flags = DIFlags::FlagPrototyped; let local_id = cx.tcx.hir.as_local_node_id(def_id); - match *cx.sess().entry_fn.borrow() { - Some((id, _, _)) => { - if local_id == Some(id) { - flags = flags | DIFlags::FlagMainSubprogram; - } + if let Some((id, _, _)) = *cx.sess().entry_fn.borrow() { + if local_id == Some(id) { + flags |= DIFlags::FlagMainSubprogram; } - None => {} - }; + } + if cx.layout_of(sig.output()).abi.is_uninhabited() { - flags = flags | DIFlags::FlagNoReturn; + flags |= DIFlags::FlagNoReturn; } let fn_metadata = unsafe { @@ -371,7 +369,7 @@ pub fn create_function_debug_context( } } - return create_DIArray(DIB(cx), &signature[..]); + create_DIArray(DIB(cx), &signature[..]) } fn get_template_parameters( @@ -428,7 +426,7 @@ pub fn create_function_debug_context( vec![] }; - return create_DIArray(DIB(cx), &template_params[..]); + create_DIArray(DIB(cx), &template_params[..]) } fn get_parameter_names(cx: &CodegenCx, diff --git a/src/librustc_codegen_llvm/debuginfo/source_loc.rs b/src/librustc_codegen_llvm/debuginfo/source_loc.rs index c59b5e2b8f5f5..60ebcb888166f 100644 --- a/src/librustc_codegen_llvm/debuginfo/source_loc.rs +++ b/src/librustc_codegen_llvm/debuginfo/source_loc.rs @@ -56,11 +56,8 @@ pub fn set_source_location( /// switches source location emitting on and must therefore be called before the /// first real statement/expression of the function is codegened. pub fn start_emitting_source_locations(dbg_context: &FunctionDebugContext<'ll>) { - match *dbg_context { - FunctionDebugContext::RegularContext(ref data) => { - data.source_locations_enabled.set(true) - }, - _ => { /* safe to ignore */ } + if let FunctionDebugContext::RegularContext(ref data) = *dbg_context { + data.source_locations_enabled.set(true); } } diff --git a/src/librustc_codegen_llvm/debuginfo/type_names.rs b/src/librustc_codegen_llvm/debuginfo/type_names.rs index 06b9318a5e830..f5abb527e430f 100644 --- a/src/librustc_codegen_llvm/debuginfo/type_names.rs +++ b/src/librustc_codegen_llvm/debuginfo/type_names.rs @@ -177,7 +177,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ty::GeneratorWitness(..) | ty::Param(_) => { bug!("debuginfo: Trying to create type name for \ - unexpected type: {:?}", t); + unexpected type: {:?}", t); } } diff --git a/src/librustc_codegen_llvm/llvm/archive_ro.rs b/src/librustc_codegen_llvm/llvm/archive_ro.rs index 4cbf0d92d7b99..e0a9f31e508ba 100644 --- a/src/librustc_codegen_llvm/llvm/archive_ro.rs +++ b/src/librustc_codegen_llvm/llvm/archive_ro.rs @@ -40,7 +40,7 @@ impl ArchiveRO { return unsafe { let s = path2cstr(dst); let ar = super::LLVMRustOpenArchive(s.as_ptr()).ok_or_else(|| { - super::last_error().unwrap_or("failed to open archive".to_string()) + super::last_error().unwrap_or("failed to open archive".to_owned()) })?; Ok(ArchiveRO { raw: ar }) }; diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 6108af6c884cb..0b98fa4eaf551 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -1212,8 +1212,8 @@ extern "C" { Dialect: AsmDialect) -> &Value; pub fn LLVMRustInlineAsmVerify(Ty: &Type, - Constraints: *const c_char) - -> Bool; + Constraints: *const c_char) + -> bool; pub fn LLVMRustDebugMetadataVersion() -> u32; pub fn LLVMRustVersionMajor() -> u32; diff --git a/src/librustc_codegen_llvm/meth.rs b/src/librustc_codegen_llvm/meth.rs index db06b87f44e1e..29c2e71960c2c 100644 --- a/src/librustc_codegen_llvm/meth.rs +++ b/src/librustc_codegen_llvm/meth.rs @@ -94,6 +94,10 @@ pub fn get_vtable( }); let (size, align) = cx.size_and_align_of(ty); + // ///////////////////////////////////////////////////////////////////////////////////////////// + // If you touch this code, be sure to also make the corresponding changes to + // `get_vtable` in rust_mir/interpret/traits.rs + // ///////////////////////////////////////////////////////////////////////////////////////////// let components: Vec<_> = [ callee::get_fn(cx, monomorphize::resolve_drop_in_place(cx.tcx, ty)), C_usize(cx, size.bytes()), diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs index 5be176f75c96a..68e30227185c0 100644 --- a/src/librustc_codegen_llvm/mir/block.rs +++ b/src/librustc_codegen_llvm/mir/block.rs @@ -125,10 +125,10 @@ impl FunctionCx<'a, 'll, 'tcx> { this.unreachable_block() }; let invokeret = bx.invoke(fn_ptr, - &llargs, - ret_bx, - llblock(this, cleanup), - cleanup_bundle); + &llargs, + ret_bx, + llblock(this, cleanup), + cleanup_bundle); fn_ty.apply_attrs_callsite(&bx, invokeret); if let Some((ret_dest, target)) = destination { @@ -213,7 +213,8 @@ impl FunctionCx<'a, 'll, 'tcx> { } else { let (otherwise, targets) = targets.split_last().unwrap(); let switch = bx.switch(discr.immediate(), - llblock(self, *otherwise), values.len()); + llblock(self, *otherwise), + values.len()); let switch_llty = bx.cx.layout_of(switch_ty).immediate_llvm_type(bx.cx); for (&value, target) in values.iter().zip(targets) { let llval = C_uint_big(switch_llty, value); @@ -387,8 +388,8 @@ impl FunctionCx<'a, 'll, 'tcx> { let msg_str = Symbol::intern(str).as_str(); let msg_str = C_str_slice(bx.cx, msg_str); let msg_file_line_col = C_struct(bx.cx, - &[msg_str, filename, line, col], - false); + &[msg_str, filename, line, col], + false); let msg_file_line_col = consts::addr_of(bx.cx, msg_file_line_col, align, @@ -509,8 +510,8 @@ impl FunctionCx<'a, 'll, 'tcx> { let msg_str = Symbol::intern(&str).as_str(); let msg_str = C_str_slice(bx.cx, msg_str); let msg_file_line_col = C_struct(bx.cx, - &[msg_str, filename, line, col], - false); + &[msg_str, filename, line, col], + false); let msg_file_line_col = consts::addr_of(bx.cx, msg_file_line_col, align, @@ -619,7 +620,7 @@ impl FunctionCx<'a, 'll, 'tcx> { let callee_ty = instance.as_ref().unwrap().ty(bx.cx.tcx); codegen_intrinsic_call(&bx, callee_ty, &fn_ty, &args, dest, - terminator.source_info.span); + terminator.source_info.span); if let ReturnDest::IndirectOperand(dst, _) = ret_dest { self.store_return(&bx, ret_dest, &fn_ty.ret, dst.llval); @@ -756,7 +757,7 @@ impl FunctionCx<'a, 'll, 'tcx> { // Have to load the argument, maybe while casting it. if let PassMode::Cast(ty) = arg.mode { llval = bx.load(bx.pointercast(llval, ty.llvm_type(bx.cx).ptr_to()), - align.min(arg.layout.align)); + align.min(arg.layout.align)); } else { // We can't use `PlaceRef::load` here because the argument // may have a type we don't treat as immediate, but the ABI @@ -778,10 +779,10 @@ impl FunctionCx<'a, 'll, 'tcx> { } fn codegen_arguments_untupled(&mut self, - bx: &Builder<'a, 'll, 'tcx>, - operand: &mir::Operand<'tcx>, - llargs: &mut Vec<&'ll Value>, - args: &[ArgType<'tcx, Ty<'tcx>>]) { + bx: &Builder<'a, 'll, 'tcx>, + operand: &mir::Operand<'tcx>, + llargs: &mut Vec<&'ll Value>, + args: &[ArgType<'tcx, Ty<'tcx>>]) { let tuple = self.codegen_operand(bx, operand); // Handle both by-ref and immediate tuples. @@ -933,8 +934,8 @@ impl FunctionCx<'a, 'll, 'tcx> { } fn codegen_transmute(&mut self, bx: &Builder<'a, 'll, 'tcx>, - src: &mir::Operand<'tcx>, - dst: &mir::Place<'tcx>) { + src: &mir::Operand<'tcx>, + dst: &mir::Place<'tcx>) { if let mir::Place::Local(index) = *dst { match self.locals[index] { LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place), @@ -961,8 +962,8 @@ impl FunctionCx<'a, 'll, 'tcx> { } fn codegen_transmute_into(&mut self, bx: &Builder<'a, 'll, 'tcx>, - src: &mir::Operand<'tcx>, - dst: PlaceRef<'ll, 'tcx>) { + src: &mir::Operand<'tcx>, + dst: PlaceRef<'ll, 'tcx>) { let src = self.codegen_operand(bx, src); let llty = src.layout.llvm_type(bx.cx); let cast_ptr = bx.pointercast(dst.llval, llty.ptr_to()); diff --git a/src/librustc_codegen_llvm/mir/mod.rs b/src/librustc_codegen_llvm/mir/mod.rs index c61a326e7c839..a6e2ccf92e4e3 100644 --- a/src/librustc_codegen_llvm/mir/mod.rs +++ b/src/librustc_codegen_llvm/mir/mod.rs @@ -162,16 +162,16 @@ impl FunctionCx<'a, 'll, 'tcx> { // corresponding to span's containing source scope. If so, we need to create a DIScope // "extension" into that file. fn scope_metadata_for_loc(&self, scope_id: mir::SourceScope, pos: BytePos) - -> Option<&'ll DIScope> { + -> Option<&'ll DIScope> { let scope_metadata = self.scopes[scope_id].scope_metadata; if pos < self.scopes[scope_id].file_start_pos || pos >= self.scopes[scope_id].file_end_pos { let cm = self.cx.sess().source_map(); let defining_crate = self.debug_context.get_ref(DUMMY_SP).defining_crate; Some(debuginfo::extend_scope_to_file(self.cx, - scope_metadata.unwrap(), - &cm.lookup_char_pos(pos).file, - defining_crate)) + scope_metadata.unwrap(), + &cm.lookup_char_pos(pos).file, + defining_crate)) } else { scope_metadata } diff --git a/src/librustc_data_structures/bit_set.rs b/src/librustc_data_structures/bit_set.rs index 1fba57fa541f0..28aad49b09b99 100644 --- a/src/librustc_data_structures/bit_set.rs +++ b/src/librustc_data_structures/bit_set.rs @@ -423,15 +423,6 @@ pub enum HybridBitSet { } impl HybridBitSet { - // FIXME: This function is used in conjunction with `mem::replace()` in - // several pieces of awful code below. I can't work out how else to appease - // the borrow checker. - fn dummy() -> Self { - // The cheapest HybridBitSet to construct, which is only used to get - // around the borrow checker. - HybridBitSet::Sparse(SparseBitSet::new_empty(0)) - } - pub fn new_empty(domain_size: usize) -> Self { HybridBitSet::Sparse(SparseBitSet::new_empty(domain_size)) } @@ -487,20 +478,14 @@ impl HybridBitSet { // that doesn't matter because `elem` is already present. false } - HybridBitSet::Sparse(_) => { + HybridBitSet::Sparse(sparse) => { // The set is sparse and full. Convert to a dense set. - match mem::replace(self, HybridBitSet::dummy()) { - HybridBitSet::Sparse(sparse) => { - let mut dense = sparse.to_dense(); - let changed = dense.insert(elem); - assert!(changed); - *self = HybridBitSet::Dense(dense); - changed - } - _ => unreachable!() - } + let mut dense = sparse.to_dense(); + let changed = dense.insert(elem); + assert!(changed); + *self = HybridBitSet::Dense(dense); + changed } - HybridBitSet::Dense(dense) => dense.insert(elem), } } @@ -525,33 +510,26 @@ impl HybridBitSet { pub fn union(&mut self, other: &HybridBitSet) -> bool { match self { - HybridBitSet::Sparse(_) => { + HybridBitSet::Sparse(self_sparse) => { match other { HybridBitSet::Sparse(other_sparse) => { // Both sets are sparse. Add the elements in - // `other_sparse` to `self_hybrid` one at a time. This - // may or may not cause `self_hybrid` to be densified. + // `other_sparse` to `self` one at a time. This + // may or may not cause `self` to be densified. assert_eq!(self.domain_size(), other.domain_size()); - let mut self_hybrid = mem::replace(self, HybridBitSet::dummy()); let mut changed = false; for elem in other_sparse.iter() { - changed |= self_hybrid.insert(*elem); + changed |= self.insert(*elem); } - *self = self_hybrid; changed } HybridBitSet::Dense(other_dense) => { // `self` is sparse and `other` is dense. Densify // `self` and then do the bitwise union. - match mem::replace(self, HybridBitSet::dummy()) { - HybridBitSet::Sparse(self_sparse) => { - let mut new_dense = self_sparse.to_dense(); - let changed = new_dense.union(other_dense); - *self = HybridBitSet::Dense(new_dense); - changed - } - _ => unreachable!() - } + let mut new_dense = self_sparse.to_dense(); + let changed = new_dense.union(other_dense); + *self = HybridBitSet::Dense(new_dense); + changed } } } diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index bcf3772213014..a316fc5ca1029 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -92,12 +92,12 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> { mir::BorrowKind::Mut { .. } => "mut ", }; let region = self.region.to_string(); - let region = if region.len() > 0 { - format!("{} ", region) + let separator = if !region.is_empty() { + " " } else { - region + "" }; - write!(w, "&{}{}{:?}", region, kind, self.borrowed_place) + write!(w, "&{}{}{}{:?}", region, separator, kind, self.borrowed_place) } } @@ -244,7 +244,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { K: Clone + Eq + Hash, V: Eq + Hash, { - map.entry(k.clone()).or_insert(FxHashSet()).insert(v); + map.entry(k.clone()).or_default().insert(v); } } @@ -261,57 +261,53 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { // ... check whether we (earlier) saw a 2-phase borrow like // // TMP = &mut place - match self.pending_activations.get(temp) { - Some(&borrow_index) => { - let borrow_data = &mut self.idx_vec[borrow_index]; - - // Watch out: the use of TMP in the borrow itself - // doesn't count as an activation. =) - if borrow_data.reserve_location == location && context == PlaceContext::Store { - return; - } + if let Some(&borrow_index) = self.pending_activations.get(temp) { + let borrow_data = &mut self.idx_vec[borrow_index]; - if let TwoPhaseActivation::ActivatedAt(other_location) = - borrow_data.activation_location { - span_bug!( - self.mir.source_info(location).span, - "found two uses for 2-phase borrow temporary {:?}: \ - {:?} and {:?}", - temp, - location, - other_location, - ); - } + // Watch out: the use of TMP in the borrow itself + // doesn't count as an activation. =) + if borrow_data.reserve_location == location && context == PlaceContext::Store { + return; + } - // Otherwise, this is the unique later use - // that we expect. - borrow_data.activation_location = match context { - // The use of TMP in a shared borrow does not - // count as an actual activation. - PlaceContext::Borrow { kind: mir::BorrowKind::Shared, .. } - | PlaceContext::Borrow { kind: mir::BorrowKind::Shallow, .. } => { - TwoPhaseActivation::NotActivated - } - _ => { - // Double check: This borrow is indeed a two-phase borrow (that is, - // we are 'transitioning' from `NotActivated` to `ActivatedAt`) and - // we've not found any other activations (checked above). - assert_eq!( - borrow_data.activation_location, - TwoPhaseActivation::NotActivated, - "never found an activation for this borrow!", - ); - - self.activation_map - .entry(location) - .or_default() - .push(borrow_index); - TwoPhaseActivation::ActivatedAt(location) - } - }; + if let TwoPhaseActivation::ActivatedAt(other_location) = + borrow_data.activation_location { + span_bug!( + self.mir.source_info(location).span, + "found two uses for 2-phase borrow temporary {:?}: \ + {:?} and {:?}", + temp, + location, + other_location, + ); } - None => {} + // Otherwise, this is the unique later use + // that we expect. + borrow_data.activation_location = match context { + // The use of TMP in a shared borrow does not + // count as an actual activation. + PlaceContext::Borrow { kind: mir::BorrowKind::Shared, .. } + | PlaceContext::Borrow { kind: mir::BorrowKind::Shallow, .. } => { + TwoPhaseActivation::NotActivated + } + _ => { + // Double check: This borrow is indeed a two-phase borrow (that is, + // we are 'transitioning' from `NotActivated` to `ActivatedAt`) and + // we've not found any other activations (checked above). + assert_eq!( + borrow_data.activation_location, + TwoPhaseActivation::NotActivated, + "never found an activation for this borrow!", + ); + + self.activation_map + .entry(location) + .or_default() + .push(borrow_index); + TwoPhaseActivation::ActivatedAt(location) + } + }; } } } diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 546746aa72ebb..759b842e9dfee 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -77,9 +77,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if move_out_indices.is_empty() { let root_place = self.prefixes(&used_place, PrefixSet::All).last().unwrap(); - if self.uninitialized_error_reported - .contains(&root_place.clone()) - { + if self.uninitialized_error_reported.contains(root_place) { debug!( "report_use_of_moved_or_uninitialized place: error about {:?} suppressed", root_place @@ -188,11 +186,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let tables = self.infcx.tcx.typeck_tables_of(id); let node_id = self.infcx.tcx.hir.as_local_node_id(id).unwrap(); let hir_id = self.infcx.tcx.hir.node_to_hir_id(node_id); - if tables.closure_kind_origins().get(hir_id).is_some() { - false - } else { - true - } + + tables.closure_kind_origins().get(hir_id).is_none() } _ => true, }; @@ -582,7 +577,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { fn report_local_value_does_not_live_long_enough( &mut self, context: Context, - name: &String, + name: &str, scope_tree: &Lrc, borrow: &BorrowData<'tcx>, drop_span: Span, @@ -1195,10 +1190,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Place::Static(ref static_) => self.describe_field_from_ty(&static_.ty, field), Place::Projection(ref proj) => match proj.elem { ProjectionElem::Deref => self.describe_field(&proj.base, field), - ProjectionElem::Downcast(def, variant_index) => format!( - "{}", - def.variants[variant_index].fields[field.index()].ident - ), + ProjectionElem::Downcast(def, variant_index) => + def.variants[variant_index].fields[field.index()].ident.to_string(), ProjectionElem::Field(_, field_type) => { self.describe_field_from_ty(&field_type, field) } @@ -1366,191 +1359,184 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "annotate_argument_and_return_for_borrow: location={:?}", location ); - match &self.mir[location.block] - .statements - .get(location.statement_index) + if let Some(&Statement { kind: StatementKind::Assign(ref reservation, _), ..}) + = &self.mir[location.block].statements.get(location.statement_index) { - Some(&Statement { - kind: StatementKind::Assign(ref reservation, _), - .. - }) => { + debug!( + "annotate_argument_and_return_for_borrow: reservation={:?}", + reservation + ); + // Check that the initial assignment of the reserve location is into a temporary. + let mut target = *match reservation { + Place::Local(local) if self.mir.local_kind(*local) == LocalKind::Temp => local, + _ => return None, + }; + + // Next, look through the rest of the block, checking if we are assigning the + // `target` (that is, the place that contains our borrow) to anything. + let mut annotated_closure = None; + for stmt in &self.mir[location.block].statements[location.statement_index + 1..] { debug!( - "annotate_argument_and_return_for_borrow: reservation={:?}", - reservation + "annotate_argument_and_return_for_borrow: target={:?} stmt={:?}", + target, stmt ); - // Check that the initial assignment of the reserve location is into a temporary. - let mut target = *match reservation { - Place::Local(local) if self.mir.local_kind(*local) == LocalKind::Temp => local, - _ => return None, - }; - - // Next, look through the rest of the block, checking if we are assigning the - // `target` (that is, the place that contains our borrow) to anything. - let mut annotated_closure = None; - for stmt in &self.mir[location.block].statements[location.statement_index + 1..] { + if let StatementKind::Assign(Place::Local(assigned_to), box rvalue) = &stmt.kind + { debug!( - "annotate_argument_and_return_for_borrow: target={:?} stmt={:?}", - target, stmt + "annotate_argument_and_return_for_borrow: assigned_to={:?} \ + rvalue={:?}", + assigned_to, rvalue ); - if let StatementKind::Assign(Place::Local(assigned_to), box rvalue) = &stmt.kind + // Check if our `target` was captured by a closure. + if let Rvalue::Aggregate( + box AggregateKind::Closure(def_id, substs), + operands, + ) = rvalue { - debug!( - "annotate_argument_and_return_for_borrow: assigned_to={:?} \ - rvalue={:?}", - assigned_to, rvalue - ); - // Check if our `target` was captured by a closure. - if let Rvalue::Aggregate( - box AggregateKind::Closure(def_id, substs), - operands, - ) = rvalue - { - for operand in operands { - let assigned_from = match operand { - Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { - assigned_from - } - _ => continue, - }; - debug!( - "annotate_argument_and_return_for_borrow: assigned_from={:?}", + for operand in operands { + let assigned_from = match operand { + Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { assigned_from - ); - - // Find the local from the operand. - let assigned_from_local = match assigned_from.local() { - Some(local) => local, - None => continue, - }; - - if assigned_from_local != target { - continue; } + _ => continue, + }; + debug!( + "annotate_argument_and_return_for_borrow: assigned_from={:?}", + assigned_from + ); - // If a closure captured our `target` and then assigned - // into a place then we should annotate the closure in - // case it ends up being assigned into the return place. - annotated_closure = self.annotate_fn_sig( - *def_id, - self.infcx.closure_sig(*def_id, *substs), - ); - debug!( - "annotate_argument_and_return_for_borrow: \ - annotated_closure={:?} assigned_from_local={:?} \ - assigned_to={:?}", - annotated_closure, assigned_from_local, assigned_to - ); - - if *assigned_to == mir::RETURN_PLACE { - // If it was assigned directly into the return place, then - // return now. - return annotated_closure; - } else { - // Otherwise, update the target. - target = *assigned_to; - } + // Find the local from the operand. + let assigned_from_local = match assigned_from.local() { + Some(local) => local, + None => continue, + }; + + if assigned_from_local != target { + continue; } - // If none of our closure's operands matched, then skip to the next - // statement. - continue; + // If a closure captured our `target` and then assigned + // into a place then we should annotate the closure in + // case it ends up being assigned into the return place. + annotated_closure = self.annotate_fn_sig( + *def_id, + self.infcx.closure_sig(*def_id, *substs), + ); + debug!( + "annotate_argument_and_return_for_borrow: \ + annotated_closure={:?} assigned_from_local={:?} \ + assigned_to={:?}", + annotated_closure, assigned_from_local, assigned_to + ); + + if *assigned_to == mir::RETURN_PLACE { + // If it was assigned directly into the return place, then + // return now. + return annotated_closure; + } else { + // Otherwise, update the target. + target = *assigned_to; + } } - // Otherwise, look at other types of assignment. - let assigned_from = match rvalue { - Rvalue::Ref(_, _, assigned_from) => assigned_from, - Rvalue::Use(operand) => match operand { - Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { - assigned_from - } - _ => continue, - }, - _ => continue, - }; - debug!( - "annotate_argument_and_return_for_borrow: \ - assigned_from={:?}", - assigned_from, - ); + // If none of our closure's operands matched, then skip to the next + // statement. + continue; + } - // Find the local from the rvalue. - let assigned_from_local = match assigned_from.local() { - Some(local) => local, - None => continue, - }; - debug!( - "annotate_argument_and_return_for_borrow: \ - assigned_from_local={:?}", - assigned_from_local, - ); + // Otherwise, look at other types of assignment. + let assigned_from = match rvalue { + Rvalue::Ref(_, _, assigned_from) => assigned_from, + Rvalue::Use(operand) => match operand { + Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { + assigned_from + } + _ => continue, + }, + _ => continue, + }; + debug!( + "annotate_argument_and_return_for_borrow: \ + assigned_from={:?}", + assigned_from, + ); - // Check if our local matches the target - if so, we've assigned our - // borrow to a new place. - if assigned_from_local != target { - continue; - } + // Find the local from the rvalue. + let assigned_from_local = match assigned_from.local() { + Some(local) => local, + None => continue, + }; + debug!( + "annotate_argument_and_return_for_borrow: \ + assigned_from_local={:?}", + assigned_from_local, + ); - // If we assigned our `target` into a new place, then we should - // check if it was the return place. - debug!( - "annotate_argument_and_return_for_borrow: \ - assigned_from_local={:?} assigned_to={:?}", - assigned_from_local, assigned_to - ); - if *assigned_to == mir::RETURN_PLACE { - // If it was then return the annotated closure if there was one, - // else, annotate this function. - return annotated_closure.or_else(fallback); - } + // Check if our local matches the target - if so, we've assigned our + // borrow to a new place. + if assigned_from_local != target { + continue; + } - // If we didn't assign into the return place, then we just update - // the target. - target = *assigned_to; + // If we assigned our `target` into a new place, then we should + // check if it was the return place. + debug!( + "annotate_argument_and_return_for_borrow: \ + assigned_from_local={:?} assigned_to={:?}", + assigned_from_local, assigned_to + ); + if *assigned_to == mir::RETURN_PLACE { + // If it was then return the annotated closure if there was one, + // else, annotate this function. + return annotated_closure.or_else(fallback); } + + // If we didn't assign into the return place, then we just update + // the target. + target = *assigned_to; } + } - // Check the terminator if we didn't find anything in the statements. - let terminator = &self.mir[location.block].terminator(); + // Check the terminator if we didn't find anything in the statements. + let terminator = &self.mir[location.block].terminator(); + debug!( + "annotate_argument_and_return_for_borrow: target={:?} terminator={:?}", + target, terminator + ); + if let TerminatorKind::Call { + destination: Some((Place::Local(assigned_to), _)), + args, + .. + } = &terminator.kind + { debug!( - "annotate_argument_and_return_for_borrow: target={:?} terminator={:?}", - target, terminator + "annotate_argument_and_return_for_borrow: assigned_to={:?} args={:?}", + assigned_to, args ); - if let TerminatorKind::Call { - destination: Some((Place::Local(assigned_to), _)), - args, - .. - } = &terminator.kind - { + for operand in args { + let assigned_from = match operand { + Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { + assigned_from + } + _ => continue, + }; debug!( - "annotate_argument_and_return_for_borrow: assigned_to={:?} args={:?}", - assigned_to, args + "annotate_argument_and_return_for_borrow: assigned_from={:?}", + assigned_from, ); - for operand in args { - let assigned_from = match operand { - Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { - assigned_from - } - _ => continue, - }; + + if let Some(assigned_from_local) = assigned_from.local() { debug!( - "annotate_argument_and_return_for_borrow: assigned_from={:?}", - assigned_from, + "annotate_argument_and_return_for_borrow: assigned_from_local={:?}", + assigned_from_local, ); - if let Some(assigned_from_local) = assigned_from.local() { - debug!( - "annotate_argument_and_return_for_borrow: assigned_from_local={:?}", - assigned_from_local, - ); - - if *assigned_to == mir::RETURN_PLACE && assigned_from_local == target { - return annotated_closure.or_else(fallback); - } + if *assigned_to == mir::RETURN_PLACE && assigned_from_local == target { + return annotated_closure.or_else(fallback); } } } } - _ => {} } // If we haven't found an assignment into the return place, then we need not add @@ -1605,13 +1591,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // Need to use the `rustc::ty` types to compare against the // `return_region`. Then use the `rustc::hir` type to get only // the lifetime span. - match &fn_decl.inputs[index].node { - hir::TyKind::Rptr(lifetime, _) => { - // With access to the lifetime, we can get - // the span of it. - arguments.push((*argument, lifetime.span)); - } - _ => bug!("ty type is a ref but hir type is not"), + if let hir::TyKind::Rptr(lifetime, _) = &fn_decl.inputs[index].node { + // With access to the lifetime, we can get + // the span of it. + arguments.push((*argument, lifetime.span)); + } else { + bug!("ty type is a ref but hir type is not"); } } } @@ -1794,8 +1779,8 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { ty::RegionKind::RePlaceholder(ty::Placeholder { name: br, .. }), _, _, - ) => with_highlight_region_for_bound_region(*br, counter, || format!("{}", ty)), - _ => format!("{}", ty), + ) => with_highlight_region_for_bound_region(*br, counter, || ty.to_string()), + _ => ty.to_string(), } } @@ -1806,9 +1791,9 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { ty::TyKind::Ref(region, _, _) => match region { ty::RegionKind::ReLateBound(_, br) | ty::RegionKind::RePlaceholder(ty::Placeholder { name: br, .. }) => { - with_highlight_region_for_bound_region(*br, counter, || format!("{}", region)) + with_highlight_region_for_bound_region(*br, counter, || region.to_string()) } - _ => format!("{}", region), + _ => region.to_string(), }, _ => bug!("ty for annotation of borrow region is not a reference"), } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 98663270882af..a7b356c146163 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -284,7 +284,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( let temporary_used_locals: FxHashSet = mbcx .used_mut .iter() - .filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable.is_some()) + .filter(|&local| mbcx.mir.local_decls[*local].is_user_variable.is_none()) .cloned() .collect(); mbcx.gather_used_muts(temporary_used_locals); @@ -342,7 +342,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( diag.buffer(&mut mbcx.errors_buffer); } - if mbcx.errors_buffer.len() > 0 { + if !mbcx.errors_buffer.is_empty() { mbcx.errors_buffer.sort_by_key(|diag| diag.span.primary_span()); if tcx.migrate_borrowck() { @@ -1009,13 +1009,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { return Control::Continue; } + error_reported = true; match kind { ReadKind::Copy => { - error_reported = true; this.report_use_while_mutably_borrowed(context, place_span, borrow) } ReadKind::Borrow(bk) => { - error_reported = true; this.report_conflicting_borrow(context, place_span, bk, &borrow) } } @@ -1045,13 +1044,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Read(..) | Write(..) => {} } + error_reported = true; match kind { WriteKind::MutableBorrow(bk) => { - error_reported = true; this.report_conflicting_borrow(context, place_span, bk, &borrow) } WriteKind::StorageDeadOrDrop => { - error_reported = true; this.report_borrowed_value_does_not_live_long_enough( context, borrow, @@ -1059,11 +1057,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Some(kind)) } WriteKind::Mutate => { - error_reported = true; this.report_illegal_mutation_of_borrowed(context, place_span, borrow) } WriteKind::Move => { - error_reported = true; this.report_move_out_while_borrowed(context, place_span, &borrow) } } @@ -1593,7 +1589,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Place::Local(_) => panic!("should have move path for every Local"), Place::Projection(_) => panic!("PrefixSet::All meant don't stop for Projection"), Place::Promoted(_) | - Place::Static(_) => return Err(NoMovePathFound::ReachedStatic), + Place::Static(_) => Err(NoMovePathFound::ReachedStatic), } } @@ -1885,7 +1881,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } // at this point, we have set up the error reporting state. - if previously_initialized { + return if previously_initialized { self.report_mutability_error( place, span, @@ -1893,10 +1889,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { error_access, location, ); - return true; + true } else { - return false; - } + false + }; } fn is_local_ever_initialized(&self, @@ -1911,7 +1907,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { return Some(index); } } - return None; + None } /// Adds the place into the used mutable variables set @@ -2171,7 +2167,7 @@ impl ContextKind { fn new(self, loc: Location) -> Context { Context { kind: self, - loc: loc, + loc, } } } diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index ea62694f8be75..a556199b875bf 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -331,7 +331,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { _ => { let source = self.borrowed_content_source(place); self.infcx.tcx.cannot_move_out_of( - span, &format!("{}", source), origin + span, &source.to_string(), origin ) }, } @@ -469,9 +469,9 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { let binding_span = bind_to.source_info.span; if j == 0 { - err.span_label(binding_span, format!("data moved here")); + err.span_label(binding_span, "data moved here"); } else { - err.span_label(binding_span, format!("...and here")); + err.span_label(binding_span, "...and here"); } if binds_to.len() == 1 { diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 5ab1605d7f07a..30f4fc9d5ea23 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -408,7 +408,6 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { .map(|replacement| (pattern_span, replacement)) } - // ClearCrossCrate::Set(mir::BindingForm::RefForGuard) => unreachable!(), ClearCrossCrate::Clear => bug!("saw cleared local state"), @@ -505,7 +504,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { ); let extra = if found { - String::from("") + String::new() } else { format!(", but it is not implemented for `{}`", substs.type_at(0)) @@ -573,7 +572,7 @@ fn suggest_ampmut<'cx, 'gcx, 'tcx>( opt_ty_info: Option, ) -> (Span, String) { let locations = mir.find_assignments(local); - if locations.len() > 0 { + if !locations.is_empty() { let assignment_rhs_span = mir.source_info(locations[0]).span; if let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span) { if let (true, Some(ws_pos)) = ( @@ -584,7 +583,7 @@ fn suggest_ampmut<'cx, 'gcx, 'tcx>( let ty = &src[ws_pos..]; return (assignment_rhs_span, format!("&{} mut {}", lt_name, ty)); } else if src.starts_with('&') { - let borrowed_expr = src[1..].to_string(); + let borrowed_expr = &src[1..]; return (assignment_rhs_span, format!("&mut {}", borrowed_expr)); } } diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs index 30b263a923a7f..495e84528a3c3 100644 --- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs +++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs @@ -141,6 +141,7 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx if let Some(all_facts) = self.all_facts { if let Place::Local(temp) = place { if let Some(borrow_indices) = self.borrow_set.local_map.get(temp) { + all_facts.killed.reserve(borrow_indices.len()); for &borrow_index in borrow_indices { let location_index = self.location_table.mid_index(location); all_facts.killed.push((borrow_index, location_index)); @@ -164,7 +165,9 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx self.location_table.mid_index(location), )); - for successor_block in terminator.successors() { + let successor_blocks = terminator.successors(); + all_facts.cfg_edge.reserve(successor_blocks.size_hint().0); + for successor_block in successor_blocks { all_facts.cfg_edge.push(( self.location_table.mid_index(location), self.location_table diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index 307112f8ba16a..a0f832c544934 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -87,9 +87,9 @@ impl<'tcx> BorrowExplanation<'tcx> { // Otherwise, just report the whole type (and use // the intentionally fuzzy phrase "destructor") ty::Closure(..) => - ("destructor", format!("closure")), + ("destructor", "closure".to_owned()), ty::Generator(..) => - ("destructor", format!("generator")), + ("destructor", "generator".to_owned()), _ => ("destructor", format!("type `{}`", local_decl.ty)), }; @@ -279,9 +279,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { pending_locations.push(target.start_location()); }, TerminatorKind::SwitchInt { ref targets, .. } => { - for target in targets { - pending_locations.push(target.start_location()); - } + pending_locations.extend( + targets.into_iter().map(|target| target.start_location())); }, TerminatorKind::Drop { target, unwind, .. } | TerminatorKind::DropAndReplace { target, unwind, .. } | @@ -303,9 +302,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { }, TerminatorKind::FalseEdges { real_target, ref imaginary_targets, .. } => { pending_locations.push(real_target.start_location()); - for target in imaginary_targets { - pending_locations.push(target.start_location()); - } + pending_locations.extend( + imaginary_targets.into_iter().map(|target| target.start_location())); }, _ => {}, } @@ -441,17 +439,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Operand::Move(Place::Local(from)) if *from == target => { debug!("was_captured_by_trait_object: ty={:?}", ty); // Check the type for a trait object. - match ty.sty { + return match ty.sty { // `&dyn Trait` - ty::TyKind::Ref(_, ty, _) if ty.is_trait() => return true, + ty::TyKind::Ref(_, ty, _) if ty.is_trait() => true, // `Box` _ if ty.is_box() && ty.boxed_ty().is_trait() => - return true, + true, // `dyn Trait` - _ if ty.is_trait() => return true, + _ if ty.is_trait() => true, // Anything else. - _ => return false, - } + _ => false, + }; }, _ => return false, }, @@ -466,32 +464,29 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let terminator = block.terminator(); debug!("was_captured_by_trait_object: terminator={:?}", terminator); - match &terminator.kind { - TerminatorKind::Call { - destination: Some((Place::Local(dest), block)), - args, - .. - } => { - debug!( - "was_captured_by_trait_object: target={:?} dest={:?} args={:?}", - target, dest, args - ); - // Check if one of the arguments to this function is the target place. - let found_target = args.iter().any(|arg| { - if let Operand::Move(Place::Local(potential)) = arg { - *potential == target - } else { - false - } - }); - - // If it is, follow this to the next block and update the target. - if found_target { - target = *dest; - queue.push(block.start_location()); + if let TerminatorKind::Call { + destination: Some((Place::Local(dest), block)), + args, + .. + } = &terminator.kind { + debug!( + "was_captured_by_trait_object: target={:?} dest={:?} args={:?}", + target, dest, args + ); + // Check if one of the arguments to this function is the target place. + let found_target = args.iter().any(|arg| { + if let Operand::Move(Place::Local(potential)) = arg { + *potential == target + } else { + false } - }, - _ => {}, + }); + + // If it is, follow this to the next block and update the target. + if found_target { + target = *dest; + queue.push(block.start_location()); + } } } diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs index a9b5531bae519..002f35880ae6b 100644 --- a/src/librustc_mir/borrow_check/nll/invalidation.rs +++ b/src/librustc_mir/borrow_check/nll/invalidation.rs @@ -35,7 +35,7 @@ pub(super) fn generate_invalidates<'cx, 'gcx, 'tcx>( mir: &Mir<'tcx>, borrow_set: &BorrowSet<'tcx>, ) { - if !all_facts.is_some() { + if all_facts.is_none() { // Nothing to do if we don't have any facts return; } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs index ee900afc44de8..268a37c708681 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs @@ -36,12 +36,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { let outlived_by = self.universal_region_relations.regions_outlived_by(region); writeln!( out, - "| {r:rw$} | {c:cw$} | {ob}", - r = format!("{:?}", region), + "| {r:rw$?} | {c:cw$?} | {ob:?}", + r = region, rw = REGION_WIDTH, - c = format!("{:?}", classification), + c = classification, cw = 8, // "External" at most - ob = format!("{:?}", outlived_by) + ob = outlived_by )?; } } @@ -51,8 +51,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { for region in self.regions() { writeln!( out, - "| {r:rw$} | {ui:4?} | {v}", - r = format!("{:?}", region), + "| {r:rw$?} | {ui:4?} | {v}", + r = region, rw = REGION_WIDTH, ui = self.region_universe(region), v = self.region_value_str(region), diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs index 8191dd720e7b2..5ff50c606d641 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs @@ -550,7 +550,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let span = infcx.tcx.def_span(*did); if let Ok(snippet) = infcx.tcx.sess.source_map().span_to_snippet(span) { let suggestable_fr_name = if fr_name.was_named() { - format!("{}", fr_name) + fr_name.to_string() } else { "'_".to_string() }; diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index 65ba2f537bf21..e07dfda406b19 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -462,9 +462,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { argument_hir_ty: &hir::Ty, counter: &mut usize, ) -> Option { - let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty)> = &mut Vec::new(); - - search_stack.push((argument_ty, argument_hir_ty)); + let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty)> = + &mut vec![(argument_ty, argument_hir_ty)]; while let Some((ty, hir_ty)) = search_stack.pop() { match (&ty.sty, &hir_ty.node) { @@ -567,10 +566,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { | hir::LifetimeName::Underscore => { let region_name = self.synthesize_region_name(counter); let ampersand_span = lifetime.span; - return Some(RegionName { + Some(RegionName { name: region_name, source: RegionNameSource::MatchedAdtAndSegment(ampersand_span), - }); + }) } hir::LifetimeName::Implicit => { @@ -585,7 +584,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // T>`. We don't consider this a match; instead we let // the "fully elaborated" type fallback above handle // it. - return None; + None } } } diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index f4ddfa5293e1e..f5e824b762888 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -327,12 +327,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } (_, &ty::Dynamic(ref data, _)) => { // Initial cast from sized to dyn trait - let trait_ref = data.principal().with_self_ty( - *self.tcx, - src_pointee_ty, - ); - let trait_ref = self.tcx.erase_regions(&trait_ref); - let vtable = self.get_vtable(src_pointee_ty, trait_ref)?; + let vtable = self.get_vtable(src_pointee_ty, data.principal())?; let ptr = self.read_value(src)?.to_scalar_ptr()?; let val = Value::new_dyn_trait(ptr, vtable); self.write_value(val, dest) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 85a8376134aa4..cf5358a989672 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -27,6 +27,7 @@ use rustc::mir::interpret::{ EvalResult, EvalErrorKind, truncate, sign_extend, }; +use rustc_data_structures::fx::FxHashMap; use syntax::source_map::{self, Span}; @@ -50,6 +51,9 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> { /// The virtual call stack. pub(crate) stack: Vec>, + + /// A cache for deduplicating vtables + pub(super) vtables: FxHashMap<(Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>), AllocId>, } /// A stack frame. @@ -209,6 +213,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc param_env, memory: Memory::new(tcx, memory_data), stack: Vec::new(), + vtables: FxHashMap::default(), } } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index c72a5894b6ac7..2d6b19ca4a7fc 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -688,9 +688,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> rval: OpTy<'tcx, M::PointerTag>, ) -> EvalResult<'tcx, (u128, usize)> { trace!("read_discriminant_value {:#?}", rval.layout); - if rval.layout.abi.is_uninhabited() { - return err!(Unreachable); - } match rval.layout.variants { layout::Variants::Single { index } => { diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index 227c85772d228..2b0febc1ce717 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -24,20 +24,32 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> pub fn get_vtable( &mut self, ty: Ty<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, + poly_trait_ref: ty::PolyExistentialTraitRef<'tcx>, ) -> EvalResult<'tcx, Pointer> { - debug!("get_vtable(trait_ref={:?})", trait_ref); + debug!("get_vtable(trait_ref={:?})", poly_trait_ref); - // FIXME: Cache this! + let (ty, poly_trait_ref) = self.tcx.erase_regions(&(ty, poly_trait_ref)); - let layout = self.layout_of(trait_ref.self_ty())?; + if let Some(&vtable) = self.vtables.get(&(ty, poly_trait_ref)) { + return Ok(Pointer::from(vtable).with_default_tag()); + } + + let trait_ref = poly_trait_ref.with_self_ty(*self.tcx, ty); + let trait_ref = self.tcx.erase_regions(&trait_ref); + + let methods = self.tcx.vtable_methods(trait_ref); + + let layout = self.layout_of(ty)?; assert!(!layout.is_unsized(), "can't create a vtable for an unsized type"); let size = layout.size.bytes(); let align = layout.align.abi(); let ptr_size = self.pointer_size(); let ptr_align = self.tcx.data_layout.pointer_align; - let methods = self.tcx.vtable_methods(trait_ref); + // ///////////////////////////////////////////////////////////////////////////////////////// + // If you touch this code, be sure to also make the corresponding changes to + // `get_vtable` in rust_codegen_llvm/meth.rs + // ///////////////////////////////////////////////////////////////////////////////////////// let vtable = self.memory.allocate( ptr_size * (3 + methods.len() as u64), ptr_align, @@ -64,6 +76,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } self.memory.mark_immutable(vtable.alloc_id)?; + assert!(self.vtables.insert((ty, poly_trait_ref), vtable.alloc_id).is_none()); Ok(vtable) } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 86fe584dc3a40..ac0616e50b091 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1980,9 +1980,15 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } if !module.no_implicit_prelude { - // `record_used` means that we don't try to load crates during speculative resolution - if record_used && ns == TypeNS && self.extern_prelude.contains(&ident.name) { - let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span); + if ns == TypeNS && self.extern_prelude.contains(&ident.name) { + let crate_id = if record_used { + self.crate_loader.process_path_extern(ident.name, ident.span) + } else if let Some(crate_id) = + self.crate_loader.maybe_process_path_extern(ident.name, ident.span) { + crate_id + } else { + return None; + }; let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); self.populate_module_if_necessary(&crate_root); diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 7643aade83b7d..445fc2e833a3f 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -553,6 +553,9 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: f.write_str(name) } clean::ResolvedPath{ did, ref typarams, ref path, is_generic } => { + if typarams.is_some() { + f.write_str("dyn ")?; + } // Paths like T::Output and Self::Output should be rendered with all segments resolved_path(f, did, path, is_generic, use_absolute)?; tybounds(f, typarams) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 582f31ce7c716..6868c7707adc8 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -83,6 +83,7 @@ pub fn render(
\ \ \ diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js index 4ef8349fa9ce9..e10e330402f5e 100644 --- a/src/librustdoc/html/static/storage.js +++ b/src/librustdoc/html/static/storage.js @@ -26,8 +26,26 @@ function onEach(arr, func) { return false; } +function usableLocalStorage() { + // Check if the browser supports localStorage at all: + if (typeof(Storage) === "undefined") { + return false; + } + // Check if we can access it; this access will fail if the browser + // preferences deny access to localStorage, e.g., to prevent storage of + // "cookies" (or cookie-likes, as is the case here). + try { + window.localStorage; + } catch(err) { + // Storage is supported, but browser preferences deny access to it. + return false; + } + + return true; +} + function updateLocalStorage(name, value) { - if (typeof(Storage) !== "undefined") { + if (usableLocalStorage()) { localStorage[name] = value; } else { // No Web Storage support so we do nothing @@ -35,7 +53,7 @@ function updateLocalStorage(name, value) { } function getCurrentValue(name) { - if (typeof(Storage) !== "undefined" && localStorage[name] !== undefined) { + if (usableLocalStorage() && localStorage[name] !== undefined) { return localStorage[name]; } return null; diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 796b2bd3eed87..c1f0a6fecefe9 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -650,15 +650,17 @@ pub fn panicking() -> bool { panicking::panicking() } -/// Puts the current thread to sleep for the specified amount of time. +/// Puts the current thread to sleep for at least the specified amount of time. /// /// The thread may sleep longer than the duration specified due to scheduling -/// specifics or platform-dependent functionality. +/// specifics or platform-dependent functionality. It will never sleep less. /// /// # Platform-specific behavior /// -/// On Unix platforms this function will not return early due to a -/// signal being received or a spurious wakeup. +/// On Unix platforms, the underlying syscall may be interrupted by a +/// spurious wakeup or signal handler. To ensure the sleep occurs for at least +/// the specified duration, this function may invoke that system call multiple +/// times. /// /// # Examples /// @@ -674,17 +676,19 @@ pub fn sleep_ms(ms: u32) { sleep(Duration::from_millis(ms as u64)) } -/// Puts the current thread to sleep for the specified amount of time. +/// Puts the current thread to sleep for at least the specified amount of time. /// /// The thread may sleep longer than the duration specified due to scheduling -/// specifics or platform-dependent functionality. +/// specifics or platform-dependent functionality. It will never sleep less. /// /// # Platform-specific behavior /// -/// On Unix platforms this function will not return early due to a -/// signal being received or a spurious wakeup. Platforms which do not support -/// nanosecond precision for sleeping will have `dur` rounded up to the nearest -/// granularity of time they can sleep for. +/// On Unix platforms, the underlying syscall may be interrupted by a +/// spurious wakeup or signal handler. To ensure the sleep occurs for at least +/// the specified duration, this function may invoke that system call multiple +/// times. +/// Platforms which do not support nanosecond precision for sleeping will +/// have `dur` rounded up to the nearest granularity of time they can sleep for. /// /// # Examples /// diff --git a/src/test/debuginfo/lexical-scope-with-macro.rs b/src/test/debuginfo/lexical-scope-with-macro.rs index 4e88f65ad1d00..d11a42bb0ed13 100644 --- a/src/test/debuginfo/lexical-scope-with-macro.rs +++ b/src/test/debuginfo/lexical-scope-with-macro.rs @@ -9,7 +9,7 @@ // except according to those terms. // min-lldb-version: 310 -// ignore-macos FIXME #48807 +// ignore-lldb FIXME #48807 // compile-flags:-g -Zdebug-macros diff --git a/src/test/run-pass/extern/extern-prelude-no-speculative.rs b/src/test/run-pass/extern/extern-prelude-no-speculative.rs index 6ca1815a1917e..372f34454de92 100644 --- a/src/test/run-pass/extern/extern-prelude-no-speculative.rs +++ b/src/test/run-pass/extern/extern-prelude-no-speculative.rs @@ -10,7 +10,7 @@ // run-pass #![allow(unused_variables)] -// compile-flags: --extern LooksLikeExternCrate=/path/to/nowhere +// compile-flags: --extern LooksLikeExternCrate mod m { pub struct LooksLikeExternCrate; diff --git a/src/test/rustdoc/assoc-consts.rs b/src/test/rustdoc/assoc-consts.rs index 71e7db5f4a543..cbb2a00214a5a 100644 --- a/src/test/rustdoc/assoc-consts.rs +++ b/src/test/rustdoc/assoc-consts.rs @@ -52,7 +52,7 @@ pub fn f(_: &(ToString + 'static)) {} impl Bar { // @has assoc_consts/struct.Bar.html '//*[@id="associatedconstant.F"]' \ - // "const F: fn(_: &(ToString + 'static))" + // "const F: fn(_: &(dyn ToString + 'static))" pub const F: fn(_: &(ToString + 'static)) = f; } diff --git a/src/test/rustdoc/inline_cross/issue-32881.rs b/src/test/rustdoc/inline_cross/issue-32881.rs index 948061bdcbed5..c55a69bcb7bc5 100644 --- a/src/test/rustdoc/inline_cross/issue-32881.rs +++ b/src/test/rustdoc/inline_cross/issue-32881.rs @@ -15,8 +15,8 @@ extern crate rustdoc_trait_object_impl; // @has issue_32881/trait.Bar.html -// @has - '//code' "impl<'a> Bar" -// @has - '//code' "impl<'a> Debug for Bar" +// @has - '//code' "impl<'a> dyn Bar" +// @has - '//code' "impl<'a> Debug for dyn Bar" pub use rustdoc_trait_object_impl::Bar; diff --git a/src/test/rustdoc/test-parens.rs b/src/test/rustdoc/test-parens.rs index 792dc9c218d56..0c9452fa1e1af 100644 --- a/src/test/rustdoc/test-parens.rs +++ b/src/test/rustdoc/test-parens.rs @@ -11,5 +11,5 @@ #![crate_name = "foo"] // @has foo/fn.foo.html -// @has - '//*[@class="rust fn"]' "_: &(ToString + 'static)" +// @has - '//*[@class="rust fn"]' "_: &(dyn ToString + 'static)" pub fn foo(_: &(ToString + 'static)) {} diff --git a/src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.rs b/src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.rs new file mode 100644 index 0000000000000..0749900986d2e --- /dev/null +++ b/src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.rs @@ -0,0 +1,22 @@ +#![feature(nll)] + +#![allow(dead_code)] + +#[derive(Debug)] +struct Value; +impl Value { + fn as_array(&self) -> Option<&Vec> { + None + } +} + +fn foo(val: Value) { + let _reviewers_original: Vec = match val.as_array() { + Some(array) => { + *array + } + None => vec![] + }; +} + +fn main() { } diff --git a/src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr b/src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr new file mode 100644 index 0000000000000..6a12016b2a5e3 --- /dev/null +++ b/src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr @@ -0,0 +1,12 @@ +error[E0507]: cannot move out of borrowed content + --> $DIR/issue-54597-reject-move-out-of-borrow-via-pat.rs:16:13 + | +LL | *array + | ^^^^^^ + | | + | cannot move out of borrowed content + | help: consider removing the `*`: `array` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/impl-trait/auxiliary/extra-item.rs b/src/test/ui/impl-trait/auxiliary/extra-item.rs new file mode 100644 index 0000000000000..8eaeafa5207df --- /dev/null +++ b/src/test/ui/impl-trait/auxiliary/extra-item.rs @@ -0,0 +1 @@ +pub trait MyTrait {} diff --git a/src/test/ui/impl-trait/extra-item.rs b/src/test/ui/impl-trait/extra-item.rs new file mode 100644 index 0000000000000..d82237ccecc7d --- /dev/null +++ b/src/test/ui/impl-trait/extra-item.rs @@ -0,0 +1,10 @@ +// aux-build:extra-item.rs +// compile-flags:--extern extra_item + +struct S; + +impl extra_item::MyTrait for S { + fn extra() {} //~ ERROR method `extra` is not a member of trait `extra_item::MyTrait` +} + +fn main() {} diff --git a/src/test/ui/impl-trait/extra-item.stderr b/src/test/ui/impl-trait/extra-item.stderr new file mode 100644 index 0000000000000..de3c7ba5d3118 --- /dev/null +++ b/src/test/ui/impl-trait/extra-item.stderr @@ -0,0 +1,9 @@ +error[E0407]: method `extra` is not a member of trait `extra_item::MyTrait` + --> $DIR/extra-item.rs:7:5 + | +LL | fn extra() {} //~ ERROR method `extra` is not a member of trait `extra_item::MyTrait` + | ^^^^^^^^^^^^^ not a member of trait `extra_item::MyTrait` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0407`. diff --git a/src/test/ui/issues/issue-34229.rs b/src/test/ui/issues/issue-34229.rs new file mode 100644 index 0000000000000..bcdfcc767fb9e --- /dev/null +++ b/src/test/ui/issues/issue-34229.rs @@ -0,0 +1,4 @@ +#[derive(PartialEq)] struct Comparable; +#[derive(PartialEq, PartialOrd)] struct Nope(Comparable); + +fn main() {} diff --git a/src/test/ui/issues/issue-34229.stderr b/src/test/ui/issues/issue-34229.stderr new file mode 100644 index 0000000000000..c57f80cd4091c --- /dev/null +++ b/src/test/ui/issues/issue-34229.stderr @@ -0,0 +1,12 @@ +error[E0277]: can't compare `Comparable` with `Comparable` + --> $DIR/issue-34229.rs:2:46 + | +LL | #[derive(PartialEq, PartialOrd)] struct Nope(Comparable); + | ^^^^^^^^^^ no implementation for `Comparable < Comparable` and `Comparable > Comparable` + | + = help: the trait `std::cmp::PartialOrd` is not implemented for `Comparable` + = note: required by `std::cmp::PartialOrd::partial_cmp` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 7006fb9427e1c..fab2ea7ba6c36 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -25,6 +25,7 @@ pub enum Mode { RunPass, RunPassValgrind, Pretty, + DebugInfoBoth, DebugInfoGdb, DebugInfoLldb, Codegen, @@ -60,6 +61,7 @@ impl FromStr for Mode { "run-pass" => Ok(RunPass), "run-pass-valgrind" => Ok(RunPassValgrind), "pretty" => Ok(Pretty), + "debuginfo-both" => Ok(DebugInfoBoth), "debuginfo-lldb" => Ok(DebugInfoLldb), "debuginfo-gdb" => Ok(DebugInfoGdb), "codegen" => Ok(Codegen), @@ -83,6 +85,7 @@ impl fmt::Display for Mode { RunPass => "run-pass", RunPassValgrind => "run-pass-valgrind", Pretty => "pretty", + DebugInfoBoth => "debuginfo-both", DebugInfoGdb => "debuginfo-gdb", DebugInfoLldb => "debuginfo-lldb", Codegen => "codegen", diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 688f2babe6e8c..06eeef61a194d 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -19,10 +19,62 @@ use util; use extract_gdb_version; +/// Whether to ignore the test. +#[derive(Clone, Copy, PartialEq, Debug)] +pub enum Ignore { + /// Run it. + Run, + /// Ignore it totally. + Ignore, + /// Ignore only the gdb test, but run the lldb test. + IgnoreGdb, + /// Ignore only the lldb test, but run the gdb test. + IgnoreLldb, +} + +impl Ignore { + pub fn can_run_gdb(&self) -> bool { + *self == Ignore::Run || *self == Ignore::IgnoreLldb + } + + pub fn can_run_lldb(&self) -> bool { + *self == Ignore::Run || *self == Ignore::IgnoreGdb + } + + pub fn no_gdb(&self) -> Ignore { + match *self { + Ignore::Run => Ignore::IgnoreGdb, + Ignore::IgnoreGdb => Ignore::IgnoreGdb, + _ => Ignore::Ignore, + } + } + + pub fn no_lldb(&self) -> Ignore { + match *self { + Ignore::Run => Ignore::IgnoreLldb, + Ignore::IgnoreLldb => Ignore::IgnoreLldb, + _ => Ignore::Ignore, + } + } +} + +/// The result of parse_cfg_name_directive. +#[derive(Clone, Copy, PartialEq, Debug)] +enum ParsedNameDirective { + /// No match. + NoMatch, + /// Match. + Match, + /// Mode was DebugInfoBoth and this matched gdb. + MatchGdb, + /// Mode was DebugInfoBoth and this matched lldb. + MatchLldb, +} + /// Properties which must be known very early, before actually running /// the test. pub struct EarlyProps { - pub ignore: bool, + pub ignore: Ignore, pub should_fail: bool, pub aux: Vec, pub revisions: Vec, @@ -31,20 +83,55 @@ pub struct EarlyProps { impl EarlyProps { pub fn from_file(config: &Config, testfile: &Path) -> Self { let mut props = EarlyProps { - ignore: false, + ignore: Ignore::Run, should_fail: false, aux: Vec::new(), revisions: vec![], }; + if config.mode == common::DebugInfoBoth { + if config.lldb_python_dir.is_none() { + props.ignore = props.ignore.no_lldb(); + } + if config.gdb_version.is_none() { + props.ignore = props.ignore.no_gdb(); + } + } + iter_header(testfile, None, &mut |ln| { // we should check if any only- exists and if it exists // and does not matches the current platform, skip the test - props.ignore = props.ignore || config.parse_cfg_name_directive(ln, "ignore") - || (config.has_cfg_prefix(ln, "only") - && !config.parse_cfg_name_directive(ln, "only")) - || ignore_gdb(config, ln) || ignore_lldb(config, ln) - || ignore_llvm(config, ln); + if props.ignore != Ignore::Ignore { + props.ignore = match config.parse_cfg_name_directive(ln, "ignore") { + ParsedNameDirective::Match => Ignore::Ignore, + ParsedNameDirective::NoMatch => props.ignore, + ParsedNameDirective::MatchGdb => props.ignore.no_gdb(), + ParsedNameDirective::MatchLldb => props.ignore.no_lldb(), + }; + + if config.has_cfg_prefix(ln, "only") { + props.ignore = match config.parse_cfg_name_directive(ln, "only") { + ParsedNameDirective::Match => props.ignore, + ParsedNameDirective::NoMatch => Ignore::Ignore, + ParsedNameDirective::MatchLldb => props.ignore.no_gdb(), + ParsedNameDirective::MatchGdb => props.ignore.no_lldb(), + }; + } + + if ignore_llvm(config, ln) { + props.ignore = Ignore::Ignore; + } + } + + if (config.mode == common::DebugInfoGdb || config.mode == common::DebugInfoBoth) && + props.ignore.can_run_gdb() && ignore_gdb(config, ln) { + props.ignore = props.ignore.no_gdb(); + } + + if (config.mode == common::DebugInfoLldb || config.mode == common::DebugInfoBoth) && + props.ignore.can_run_lldb() && ignore_lldb(config, ln) { + props.ignore = props.ignore.no_lldb(); + } if let Some(s) = config.parse_aux_build(ln) { props.aux.push(s); @@ -60,10 +147,6 @@ impl EarlyProps { return props; fn ignore_gdb(config: &Config, line: &str) -> bool { - if config.mode != common::DebugInfoGdb { - return false; - } - if let Some(actual_version) = config.gdb_version { if line.starts_with("min-gdb-version") { let (start_ver, end_ver) = extract_gdb_version_range(line); @@ -120,10 +203,6 @@ impl EarlyProps { } fn ignore_lldb(config: &Config, line: &str) -> bool { - if config.mode != common::DebugInfoLldb { - return false; - } - if let Some(ref actual_version) = config.lldb_version { if line.starts_with("min-lldb-version") { let min_version = line.trim_right() @@ -604,7 +683,7 @@ impl Config { } fn parse_custom_normalization(&self, mut line: &str, prefix: &str) -> Option<(String, String)> { - if self.parse_cfg_name_directive(line, prefix) { + if self.parse_cfg_name_directive(line, prefix) == ParsedNameDirective::Match { let from = match parse_normalization_string(&mut line) { Some(s) => s, None => return None, @@ -620,35 +699,59 @@ impl Config { } /// Parses a name-value directive which contains config-specific information, e.g. `ignore-x86` - /// or `normalize-stderr-32bit`. Returns `true` if the line matches it. - fn parse_cfg_name_directive(&self, line: &str, prefix: &str) -> bool { + /// or `normalize-stderr-32bit`. + fn parse_cfg_name_directive(&self, line: &str, prefix: &str) -> ParsedNameDirective { if line.starts_with(prefix) && line.as_bytes().get(prefix.len()) == Some(&b'-') { let name = line[prefix.len() + 1..] .split(&[':', ' '][..]) .next() .unwrap(); - name == "test" || + if name == "test" || util::matches_os(&self.target, name) || // target name == util::get_arch(&self.target) || // architecture name == util::get_pointer_width(&self.target) || // pointer width name == self.stage_id.split('-').next().unwrap() || // stage Some(name) == util::get_env(&self.target) || // env - match self.mode { - common::DebugInfoGdb => name == "gdb", - common::DebugInfoLldb => name == "lldb", - common::Pretty => name == "pretty", - _ => false, - } || (self.target != self.host && name == "cross-compile") || match self.compare_mode { Some(CompareMode::Nll) => name == "compare-mode-nll", Some(CompareMode::Polonius) => name == "compare-mode-polonius", None => false, } || - (cfg!(debug_assertions) && name == "debug") + (cfg!(debug_assertions) && name == "debug") { + ParsedNameDirective::Match + } else { + match self.mode { + common::DebugInfoBoth => { + if name == "gdb" { + ParsedNameDirective::MatchGdb + } else if name == "lldb" { + ParsedNameDirective::MatchLldb + } else { + ParsedNameDirective::NoMatch + } + }, + common::DebugInfoGdb => if name == "gdb" { + ParsedNameDirective::Match + } else { + ParsedNameDirective::NoMatch + }, + common::DebugInfoLldb => if name == "lldb" { + ParsedNameDirective::Match + } else { + ParsedNameDirective::NoMatch + }, + common::Pretty => if name == "pretty" { + ParsedNameDirective::Match + } else { + ParsedNameDirective::NoMatch + }, + _ => ParsedNameDirective::NoMatch, + } + } } else { - false + ParsedNameDirective::NoMatch } } diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index f46e031d768bd..c931d3c0e30b7 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -32,7 +32,7 @@ extern crate rustfix; use common::CompareMode; use common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS}; use common::{Config, TestPaths}; -use common::{DebugInfoGdb, DebugInfoLldb, Mode, Pretty}; +use common::{DebugInfoBoth, DebugInfoGdb, DebugInfoLldb, Mode, Pretty}; use filetime::FileTime; use getopts::Options; use std::env; @@ -44,7 +44,7 @@ use std::process::Command; use test::ColorConfig; use util::logv; -use self::header::EarlyProps; +use self::header::{EarlyProps, Ignore}; pub mod common; pub mod errors; @@ -425,7 +425,7 @@ pub fn opt_str2(maybestr: Option) -> String { pub fn run_tests(config: &Config) { if config.target.contains("android") { - if let DebugInfoGdb = config.mode { + if config.mode == DebugInfoGdb || config.mode == DebugInfoBoth { println!( "{} debug-info test uses tcp 5039 port.\ please reserve it", @@ -443,7 +443,9 @@ pub fn run_tests(config: &Config) { } match config.mode { - DebugInfoLldb => { + // Note that we don't need to emit the gdb warning when + // DebugInfoBoth, so it is ok to list that here. + DebugInfoBoth | DebugInfoLldb => { if let Some(lldb_version) = config.lldb_version.as_ref() { if is_blacklisted_lldb_version(&lldb_version[..]) { println!( @@ -647,15 +649,18 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> Vec Vec, ) -> test::TestFn { - let config = config.clone(); + let mut config = config.clone(); + if config.mode == DebugInfoBoth { + // If both gdb and lldb were ignored, then the test as a whole + // would be ignored. + if !ignore.can_run_gdb() { + config.mode = DebugInfoLldb; + } else if !ignore.can_run_lldb() { + config.mode = DebugInfoGdb; + } + } + let testpaths = testpaths.clone(); let revision = revision.cloned(); test::DynTestFn(Box::new(move || { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index c69956030c0b3..8c3b1bb4df333 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -11,7 +11,7 @@ use common::CompareMode; use common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT}; use common::{output_base_dir, output_base_name, output_testname_unique}; -use common::{Codegen, CodegenUnits, DebugInfoGdb, DebugInfoLldb, Rustdoc}; +use common::{Codegen, CodegenUnits, DebugInfoBoth, DebugInfoGdb, DebugInfoLldb, Rustdoc}; use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind}; use common::{Config, TestPaths}; use common::{Incremental, MirOpt, RunMake, Ui}; @@ -225,19 +225,20 @@ pub fn run(config: Config, testpaths: &TestPaths, revision: Option<&str>) { pub fn compute_stamp_hash(config: &Config) -> String { let mut hash = DefaultHasher::new(); config.stage_id.hash(&mut hash); - match config.mode { - DebugInfoGdb => match config.gdb { + + if config.mode == DebugInfoGdb || config.mode == DebugInfoBoth { + match config.gdb { None => env::var_os("PATH").hash(&mut hash), Some(ref s) if s.is_empty() => env::var_os("PATH").hash(&mut hash), Some(ref s) => s.hash(&mut hash), - }, - DebugInfoLldb => { - env::var_os("PATH").hash(&mut hash); - env::var_os("PYTHONPATH").hash(&mut hash); - }, + }; + } + + if config.mode == DebugInfoLldb || config.mode == DebugInfoBoth { + env::var_os("PATH").hash(&mut hash); + env::var_os("PYTHONPATH").hash(&mut hash); + } - _ => {}, - }; format!("{:x}", hash.finish()) } @@ -268,6 +269,10 @@ impl<'test> TestCx<'test> { RunFail => self.run_rfail_test(), RunPassValgrind => self.run_valgrind_test(), Pretty => self.run_pretty_test(), + DebugInfoBoth => { + self.run_debuginfo_gdb_test(); + self.run_debuginfo_lldb_test(); + }, DebugInfoGdb => self.run_debuginfo_gdb_test(), DebugInfoLldb => self.run_debuginfo_lldb_test(), Codegen => self.run_codegen_test(), @@ -640,6 +645,7 @@ impl<'test> TestCx<'test> { let config = Config { target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags), host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags), + mode: DebugInfoGdb, ..self.config.clone() }; @@ -910,6 +916,7 @@ impl<'test> TestCx<'test> { let config = Config { target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags), host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags), + mode: DebugInfoLldb, ..self.config.clone() }; @@ -1774,7 +1781,7 @@ impl<'test> TestCx<'test> { rustc.arg(dir_opt); } - RunFail | RunPassValgrind | Pretty | DebugInfoGdb | DebugInfoLldb + RunFail | RunPassValgrind | Pretty | DebugInfoBoth | DebugInfoGdb | DebugInfoLldb | Codegen | Rustdoc | RunMake | CodegenUnits => { // do not use JSON output }