]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #86817 - JohnTitor:rollup-rcysc95, r=JohnTitor
authorbors <bors@rust-lang.org>
Fri, 2 Jul 2021 20:00:51 +0000 (20:00 +0000)
committerbors <bors@rust-lang.org>
Fri, 2 Jul 2021 20:00:51 +0000 (20:00 +0000)
Rollup of 7 pull requests

Successful merges:

 - #84029 (add `track_path::path` fn for usage in `proc_macro`s)
 - #85001 (Merge `sys_common::bytestring` back into `os_str_bytes`)
 - #86308 (Docs: clarify that certain intrinsics are not unsafe)
 - #86796 (Add a regression test for issue-70703)
 - #86803 (Remove & from Command::args calls in documentation)
 - #86807 (Fix double import in wasm thread )
 - #86813 (Add a help message to `unused_doc_comments` lint)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup

30 files changed:
compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
src/etc/natvis/intrinsic.natvis
src/etc/natvis/libstd.natvis
src/test/codegen/async-fn-debug-msvc.rs
src/test/codegen/async-fn-debug.rs
src/test/codegen/fn-impl-trait-self.rs
src/test/codegen/generator-debug-msvc.rs
src/test/codegen/generator-debug.rs
src/test/debuginfo/basic-types.rs
src/test/debuginfo/function-names.rs [new file with mode: 0644]
src/test/debuginfo/generator-objects.rs
src/test/debuginfo/generic-struct.rs
src/test/debuginfo/issue-57822.rs
src/test/debuginfo/msvc-pretty-enums.rs
src/test/debuginfo/mutex.rs
src/test/debuginfo/pretty-std-collections-hash.rs
src/test/debuginfo/pretty-std.rs
src/test/debuginfo/rc_arc.rs
src/test/debuginfo/result-types.rs
src/test/debuginfo/simple-tuple.rs
src/test/debuginfo/thread.rs
src/test/debuginfo/tuple-in-tuple.rs
src/test/debuginfo/type-names.cdb.js [new file with mode: 0644]
src/test/debuginfo/type-names.rs
src/test/debuginfo/var-captured-in-nested-closure.rs
src/tools/compiletest/src/runtest.rs
src/tools/tidy/src/style.rs

index 1e70664e64d707dbc3aa9af04669b0c416a68c88..0e42931b29a976c25eee1dd96c6b71489eee826c 100644 (file)
@@ -471,21 +471,28 @@ fn trait_pointer_metadata(
     // type is assigned the correct name, size, namespace, and source location.
     // However, it does not describe the trait's methods.
 
-    let containing_scope = match trait_type.kind() {
-        ty::Dynamic(ref data, ..) => {
-            data.principal_def_id().map(|did| get_namespace_for_item(cx, did))
-        }
-        _ => {
-            bug!(
-                "debuginfo: unexpected trait-object type in \
-                  trait_pointer_metadata(): {:?}",
-                trait_type
-            );
-        }
-    };
+    let (containing_scope, trait_type_name) = match trait_object_type {
+        Some(trait_object_type) => match trait_object_type.kind() {
+            ty::Adt(def, _) => (
+                Some(get_namespace_for_item(cx, def.did)),
+                compute_debuginfo_type_name(cx.tcx, trait_object_type, false),
+            ),
+            ty::RawPtr(_) | ty::Ref(..) => {
+                (NO_SCOPE_METADATA, compute_debuginfo_type_name(cx.tcx, trait_object_type, true))
+            }
+            _ => {
+                bug!(
+                    "debuginfo: unexpected trait-object type in \
+                      trait_pointer_metadata(): {:?}",
+                    trait_object_type
+                );
+            }
+        },
 
-    let trait_object_type = trait_object_type.unwrap_or(trait_type);
-    let trait_type_name = compute_debuginfo_type_name(cx.tcx, trait_object_type, false);
+        // No object type, use the trait type directly (no scope here since the type
+        // will be wrapped in the dyn$ synthetic type).
+        None => (NO_SCOPE_METADATA, compute_debuginfo_type_name(cx.tcx, trait_type, true)),
+    };
 
     let file_metadata = unknown_file_metadata(cx);
 
@@ -525,7 +532,7 @@ fn trait_pointer_metadata(
 
     composite_type_metadata(
         cx,
-        trait_object_type,
+        trait_object_type.unwrap_or(trait_type),
         &trait_type_name[..],
         unique_type_id,
         member_descriptions,
index 2b99a2ebad979227ff6b6068f6cf69da962ff8d6..8375d4c7ca561223b1c561cfd7157a4d3f95e1c7 100644 (file)
@@ -5,7 +5,6 @@
 use self::metadata::{file_metadata, type_metadata, TypeMap};
 use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER};
 use self::namespace::mangled_name_of_instance;
-use self::type_names::compute_debuginfo_type_name;
 use self::utils::{create_DIArray, is_node_local_to_unit, DIB};
 
 use crate::abi::FnAbi;
@@ -311,10 +310,10 @@ fn dbg_scope_fn(
             llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), fn_signature)
         };
 
-        // Find the enclosing function, in case this is a closure.
-        let def_key = self.tcx().def_key(def_id);
-        let mut name = def_key.disambiguated_data.data.to_string();
+        let mut name = String::new();
+        type_names::push_item_name(self.tcx(), def_id, false, &mut name);
 
+        // Find the enclosing function, in case this is a closure.
         let enclosing_fn_def_id = self.tcx().closure_base_def_id(def_id);
 
         // Get_template_parameters() will append a `<...>` clause to the function
@@ -428,24 +427,16 @@ fn get_template_parameters<'ll, 'tcx>(
             substs: SubstsRef<'tcx>,
             name_to_append_suffix_to: &mut String,
         ) -> &'ll DIArray {
+            type_names::push_generic_params(
+                cx.tcx,
+                cx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs),
+                name_to_append_suffix_to,
+            );
+
             if substs.types().next().is_none() {
                 return create_DIArray(DIB(cx), &[]);
             }
 
-            name_to_append_suffix_to.push('<');
-            for (i, actual_type) in substs.types().enumerate() {
-                if i != 0 {
-                    name_to_append_suffix_to.push(',');
-                }
-
-                let actual_type =
-                    cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), actual_type);
-                // Add actual type name to <...> clause of function name
-                let actual_type_name = compute_debuginfo_type_name(cx.tcx(), actual_type, true);
-                name_to_append_suffix_to.push_str(&actual_type_name[..]);
-            }
-            name_to_append_suffix_to.push('>');
-
             // Again, only create type information if full debuginfo is enabled
             let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full {
                 let names = get_parameter_names(cx, generics);
index 9945d4f4282597901b1f84cf2c09d9ef0c2982a3..1cbf53869960895d01b5063211c39fb13e46fc06 100644 (file)
@@ -1,13 +1,13 @@
 // Namespace Handling.
 
 use super::utils::{debug_context, DIB};
+use rustc_codegen_ssa::debuginfo::type_names;
 use rustc_middle::ty::{self, Instance};
 
 use crate::common::CodegenCx;
 use crate::llvm;
 use crate::llvm::debuginfo::DIScope;
 use rustc_hir::def_id::DefId;
-use rustc_hir::definitions::DefPathData;
 
 pub fn mangled_name_of_instance<'a, 'tcx>(
     cx: &CodegenCx<'a, 'tcx>,
@@ -27,25 +27,18 @@ pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope {
         .parent
         .map(|parent| item_namespace(cx, DefId { krate: def_id.krate, index: parent }));
 
-    let crate_name_as_str;
-    let name_to_string;
-    let namespace_name = match def_key.disambiguated_data.data {
-        DefPathData::CrateRoot => {
-            crate_name_as_str = cx.tcx.crate_name(def_id.krate).as_str();
-            &*crate_name_as_str
-        }
-        data => {
-            name_to_string = data.to_string();
-            &*name_to_string
-        }
+    let namespace_name_string = {
+        let mut output = String::new();
+        type_names::push_item_name(cx.tcx, def_id, false, &mut output);
+        output
     };
 
     let scope = unsafe {
         llvm::LLVMRustDIBuilderCreateNameSpace(
             DIB(cx),
             parent_scope,
-            namespace_name.as_ptr().cast(),
-            namespace_name.len(),
+            namespace_name_string.as_ptr().cast(),
+            namespace_name_string.len(),
             false, // ExportSymbols (only relevant for C++ anonymous namespaces)
         )
     };
index 7b4b0821c4be8017c75e66434cc2bed946e6bd03..a97c6a6b4429f7c77ac1d626fa686a2f1af95fb3 100644 (file)
@@ -1,9 +1,22 @@
 // Type Names for Debug Info.
 
+// Notes on targetting MSVC:
+// In general, MSVC's debugger attempts to parse all arguments as C++ expressions,
+// even if the argument is explicitly a symbol name.
+// As such, there are many things that cause parsing issues:
+// * `#` is treated as a special character for macros.
+// * `{` or `<` at the beginning of a name is treated as an operator.
+// * `>>` is always treated as a right-shift.
+// * `[` in a name is treated like a regex bracket expression (match any char
+//   within the brackets).
+// * `"` is treated as the start of a string.
+
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty, TyCtxt};
+use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
+use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
+use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
 use rustc_target::abi::{TagEncoding, Variants};
 
 use std::fmt::Write;
@@ -40,7 +53,13 @@ pub fn push_debuginfo_type_name<'tcx>(
         ty::Bool => output.push_str("bool"),
         ty::Char => output.push_str("char"),
         ty::Str => output.push_str("str"),
-        ty::Never => output.push('!'),
+        ty::Never => {
+            if cpp_like_names {
+                output.push_str("never$");
+            } else {
+                output.push('!');
+            }
+        }
         ty::Int(int_ty) => output.push_str(int_ty.name_str()),
         ty::Uint(uint_ty) => output.push_str(uint_ty.name_str()),
         ty::Float(float_ty) => output.push_str(float_ty.name_str()),
@@ -50,74 +69,109 @@ pub fn push_debuginfo_type_name<'tcx>(
                 msvc_enum_fallback(tcx, t, def, substs, output, visited);
             } else {
                 push_item_name(tcx, def.did, qualified, output);
-                push_type_params(tcx, substs, output, visited);
+                push_generic_params_internal(tcx, substs, output, visited);
             }
         }
         ty::Tuple(component_types) => {
             if cpp_like_names {
-                output.push_str("tuple<");
+                output.push_str("tuple$<");
             } else {
                 output.push('(');
             }
 
             for component_type in component_types {
                 push_debuginfo_type_name(tcx, component_type.expect_ty(), true, output, visited);
-                output.push_str(", ");
+                output.push(',');
+
+                // Natvis does not always like having spaces between parts of the type name
+                // and this causes issues when we need to write a typename in natvis, for example
+                // as part of a cast like the `HashMap` visualizer does.
+                if !cpp_like_names {
+                    output.push(' ');
+                }
             }
             if !component_types.is_empty() {
                 output.pop();
-                output.pop();
+
+                if !cpp_like_names {
+                    output.pop();
+                }
             }
 
             if cpp_like_names {
-                output.push('>');
+                push_close_angle_bracket(tcx, output);
             } else {
                 output.push(')');
             }
         }
         ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => {
-            if !cpp_like_names {
+            if cpp_like_names {
+                match mutbl {
+                    hir::Mutability::Not => output.push_str("ptr_const$<"),
+                    hir::Mutability::Mut => output.push_str("ptr_mut$<"),
+                }
+            } else {
                 output.push('*');
-            }
-            match mutbl {
-                hir::Mutability::Not => output.push_str("const "),
-                hir::Mutability::Mut => output.push_str("mut "),
+                match mutbl {
+                    hir::Mutability::Not => output.push_str("const "),
+                    hir::Mutability::Mut => output.push_str("mut "),
+                }
             }
 
-            push_debuginfo_type_name(tcx, inner_type, true, output, visited);
+            push_debuginfo_type_name(tcx, inner_type, qualified, output, visited);
 
             if cpp_like_names {
-                output.push('*');
+                push_close_angle_bracket(tcx, output);
             }
         }
         ty::Ref(_, inner_type, mutbl) => {
+            // Slices and `&str` are treated like C++ pointers when computing debug
+            // info for MSVC debugger. However, wrapping these types' names in a synthetic type
+            // causes the .natvis engine for WinDbg to fail to display their data, so we opt these
+            // types out to aid debugging in MSVC.
+            let is_slice_or_str = match *inner_type.kind() {
+                ty::Slice(_) | ty::Str => true,
+                _ => false,
+            };
+
             if !cpp_like_names {
                 output.push('&');
+                output.push_str(mutbl.prefix_str());
+            } else if !is_slice_or_str {
+                match mutbl {
+                    hir::Mutability::Not => output.push_str("ref$<"),
+                    hir::Mutability::Mut => output.push_str("ref_mut$<"),
+                }
             }
-            output.push_str(mutbl.prefix_str());
 
-            push_debuginfo_type_name(tcx, inner_type, true, output, visited);
+            push_debuginfo_type_name(tcx, inner_type, qualified, output, visited);
 
-            if cpp_like_names {
-                // Slices and `&str` are treated like C++ pointers when computing debug
-                // info for MSVC debugger. However, adding '*' at the end of these types' names
-                // causes the .natvis engine for WinDbg to fail to display their data, so we opt these
-                // types out to aid debugging in MSVC.
-                match *inner_type.kind() {
-                    ty::Slice(_) | ty::Str => {}
-                    _ => output.push('*'),
-                }
+            if cpp_like_names && !is_slice_or_str {
+                push_close_angle_bracket(tcx, output);
             }
         }
         ty::Array(inner_type, len) => {
-            output.push('[');
-            push_debuginfo_type_name(tcx, inner_type, true, output, visited);
-            output.push_str(&format!("; {}", len.eval_usize(tcx, ty::ParamEnv::reveal_all())));
-            output.push(']');
+            if cpp_like_names {
+                output.push_str("array$<");
+                push_debuginfo_type_name(tcx, inner_type, true, output, visited);
+                match len.val {
+                    ty::ConstKind::Param(param) => write!(output, ",{}>", param.name).unwrap(),
+                    _ => write!(output, ",{}>", len.eval_usize(tcx, ty::ParamEnv::reveal_all()))
+                        .unwrap(),
+                }
+            } else {
+                output.push('[');
+                push_debuginfo_type_name(tcx, inner_type, true, output, visited);
+                match len.val {
+                    ty::ConstKind::Param(param) => write!(output, "; {}]", param.name).unwrap(),
+                    _ => write!(output, "; {}]", len.eval_usize(tcx, ty::ParamEnv::reveal_all()))
+                        .unwrap(),
+                }
+            }
         }
         ty::Slice(inner_type) => {
             if cpp_like_names {
-                output.push_str("slice<");
+                output.push_str("slice$<");
             } else {
                 output.push('[');
             }
@@ -125,19 +179,69 @@ pub fn push_debuginfo_type_name<'tcx>(
             push_debuginfo_type_name(tcx, inner_type, true, output, visited);
 
             if cpp_like_names {
-                output.push('>');
+                push_close_angle_bracket(tcx, output);
             } else {
                 output.push(']');
             }
         }
         ty::Dynamic(ref trait_data, ..) => {
+            if cpp_like_names {
+                output.push_str("dyn$<");
+            } else {
+                output.push_str("dyn ");
+            }
+
             if let Some(principal) = trait_data.principal() {
                 let principal =
                     tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), principal);
-                push_item_name(tcx, principal.def_id, false, output);
-                push_type_params(tcx, principal.substs, output, visited);
+                push_item_name(tcx, principal.def_id, qualified, output);
+                push_generic_params_internal(tcx, principal.substs, output, visited);
             } else {
-                output.push_str("dyn '_");
+                // The auto traits come ordered by `DefPathHash`, which guarantees stability if the
+                // environment is stable (e.g., incremental builds) but not otherwise (e.g.,
+                // updated compiler version, different target).
+                //
+                // To avoid that causing instabilities in test output, sort the auto-traits
+                // alphabetically.
+                let mut auto_traits: Vec<_> = trait_data
+                    .iter()
+                    .filter_map(|predicate| {
+                        match tcx.normalize_erasing_late_bound_regions(
+                            ty::ParamEnv::reveal_all(),
+                            predicate,
+                        ) {
+                            ty::ExistentialPredicate::AutoTrait(def_id) => {
+                                let mut name = String::new();
+                                push_item_name(tcx, def_id, true, &mut name);
+                                Some(name)
+                            }
+                            _ => None,
+                        }
+                    })
+                    .collect();
+                auto_traits.sort();
+
+                for name in auto_traits {
+                    output.push_str(&name);
+
+                    if cpp_like_names {
+                        output.push_str(", ");
+                    } else {
+                        output.push_str(" + ");
+                    }
+                }
+
+                // Remove the trailing joining characters. For cpp_like_names
+                // this is `, ` otherwise ` + `.
+                output.pop();
+                output.pop();
+                if !cpp_like_names {
+                    output.pop();
+                }
+            }
+
+            if cpp_like_names {
+                push_close_angle_bracket(tcx, output);
             }
         }
         ty::FnDef(..) | ty::FnPtr(_) => {
@@ -155,23 +259,37 @@ pub fn push_debuginfo_type_name<'tcx>(
             // use a dummy string that should make it clear
             // that something unusual is going on
             if !visited.insert(t) {
-                output.push_str("<recursive_type>");
+                output.push_str(if cpp_like_names {
+                    "recursive_type$"
+                } else {
+                    "<recursive_type>"
+                });
                 return;
             }
 
-            let sig = t.fn_sig(tcx);
-            output.push_str(sig.unsafety().prefix_str());
+            let sig =
+                tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), t.fn_sig(tcx));
 
-            let abi = sig.abi();
-            if abi != rustc_target::spec::abi::Abi::Rust {
-                output.push_str("extern \"");
-                output.push_str(abi.name());
-                output.push_str("\" ");
-            }
+            if cpp_like_names {
+                // Format as a C++ function pointer: return_type (*)(params...)
+                if sig.output().is_unit() {
+                    output.push_str("void");
+                } else {
+                    push_debuginfo_type_name(tcx, sig.output(), true, output, visited);
+                }
+                output.push_str(" (*)(");
+            } else {
+                output.push_str(sig.unsafety.prefix_str());
+
+                if sig.abi != rustc_target::spec::abi::Abi::Rust {
+                    output.push_str("extern \"");
+                    output.push_str(sig.abi.name());
+                    output.push_str("\" ");
+                }
 
-            output.push_str("fn(");
+                output.push_str("fn(");
+            }
 
-            let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig);
             if !sig.inputs().is_empty() {
                 for &parameter_type in sig.inputs() {
                     push_debuginfo_type_name(tcx, parameter_type, true, output, visited);
@@ -191,7 +309,7 @@ pub fn push_debuginfo_type_name<'tcx>(
 
             output.push(')');
 
-            if !sig.output().is_unit() {
+            if !cpp_like_names && !sig.output().is_unit() {
                 output.push_str(" -> ");
                 push_debuginfo_type_name(tcx, sig.output(), true, output, visited);
             }
@@ -207,17 +325,14 @@ pub fn push_debuginfo_type_name<'tcx>(
             // processing
             visited.remove(t);
         }
-        ty::Closure(def_id, ..) => {
-            output.push_str(&format!(
-                "closure-{}",
-                tcx.def_key(def_id).disambiguated_data.disambiguator
-            ));
-        }
-        ty::Generator(def_id, ..) => {
-            output.push_str(&format!(
-                "generator-{}",
-                tcx.def_key(def_id).disambiguated_data.disambiguator
-            ));
+        ty::Closure(def_id, ..) | ty::Generator(def_id, ..) => {
+            let key = tcx.def_key(def_id);
+            if qualified {
+                let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
+                push_item_name(tcx, parent_def_id, true, output);
+                output.push_str("::");
+            }
+            push_unqualified_item_name(tcx, def_id, key.disambiguated_data, output);
         }
         // Type parameters from polymorphized functions.
         ty::Param(_) => {
@@ -273,7 +388,7 @@ fn msvc_enum_fallback(
 
             output.push_str("enum$<");
             push_item_name(tcx, def.did, true, output);
-            push_type_params(tcx, substs, output, visited);
+            push_generic_params_internal(tcx, substs, output, visited);
 
             let dataful_variant_name = def.variants[*dataful_variant].ident.as_str();
 
@@ -281,47 +396,116 @@ fn msvc_enum_fallback(
         } else {
             output.push_str("enum$<");
             push_item_name(tcx, def.did, true, output);
-            push_type_params(tcx, substs, output, visited);
-            output.push('>');
+            push_generic_params_internal(tcx, substs, output, visited);
+            push_close_angle_bracket(tcx, output);
         }
     }
+}
+
+pub fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) {
+    let def_key = tcx.def_key(def_id);
+    if qualified {
+        if let Some(parent) = def_key.parent {
+            push_item_name(tcx, DefId { krate: def_id.krate, index: parent }, true, output);
+            output.push_str("::");
+        }
+    }
+
+    push_unqualified_item_name(tcx, def_id, def_key.disambiguated_data, output);
+}
 
-    fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) {
-        if qualified {
+fn push_unqualified_item_name(
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+    disambiguated_data: DisambiguatedDefPathData,
+    output: &mut String,
+) {
+    let cpp_like_names = tcx.sess.target.is_like_msvc;
+
+    match disambiguated_data.data {
+        DefPathData::CrateRoot => {
             output.push_str(&tcx.crate_name(def_id.krate).as_str());
-            for path_element in tcx.def_path(def_id).data {
-                write!(output, "::{}", path_element.data).unwrap();
+        }
+        DefPathData::ClosureExpr if tcx.generator_kind(def_id).is_some() => {
+            // Generators look like closures, but we want to treat them differently
+            // in the debug info.
+            if cpp_like_names {
+                write!(output, "generator${}", disambiguated_data.disambiguator).unwrap();
+            } else {
+                write!(output, "{{generator#{}}}", disambiguated_data.disambiguator).unwrap();
             }
-        } else {
-            output.push_str(&tcx.item_name(def_id).as_str());
         }
+        _ => match disambiguated_data.data.name() {
+            DefPathDataName::Named(name) => {
+                output.push_str(&name.as_str());
+            }
+            DefPathDataName::Anon { namespace } => {
+                if cpp_like_names {
+                    write!(output, "{}${}", namespace, disambiguated_data.disambiguator).unwrap();
+                } else {
+                    write!(output, "{{{}#{}}}", namespace, disambiguated_data.disambiguator)
+                        .unwrap();
+                }
+            }
+        },
+    };
+}
+
+// Pushes the generic parameters in the given `InternalSubsts` to the output string.
+// This ignores region parameters, since they can't reliably be
+// reconstructed for items from non-local crates. For local crates, this
+// would be possible but with inlining and LTO we have to use the least
+// common denominator - otherwise we would run into conflicts.
+fn push_generic_params_internal<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    substs: SubstsRef<'tcx>,
+    output: &mut String,
+    visited: &mut FxHashSet<Ty<'tcx>>,
+) {
+    if substs.non_erasable_generics().next().is_none() {
+        return;
     }
 
-    // Pushes the type parameters in the given `InternalSubsts` to the output string.
-    // This ignores region parameters, since they can't reliably be
-    // reconstructed for items from non-local crates. For local crates, this
-    // would be possible but with inlining and LTO we have to use the least
-    // common denominator - otherwise we would run into conflicts.
-    fn push_type_params<'tcx>(
-        tcx: TyCtxt<'tcx>,
-        substs: SubstsRef<'tcx>,
-        output: &mut String,
-        visited: &mut FxHashSet<Ty<'tcx>>,
-    ) {
-        if substs.types().next().is_none() {
-            return;
-        }
+    debug_assert_eq!(substs, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs));
 
-        output.push('<');
+    output.push('<');
 
-        for type_parameter in substs.types() {
-            push_debuginfo_type_name(tcx, type_parameter, true, output, visited);
-            output.push_str(", ");
+    for type_parameter in substs.non_erasable_generics() {
+        match type_parameter {
+            GenericArgKind::Type(type_parameter) => {
+                push_debuginfo_type_name(tcx, type_parameter, true, output, visited);
+                output.push_str(", ");
+            }
+            GenericArgKind::Const(const_parameter) => match const_parameter.val {
+                ty::ConstKind::Param(param) => write!(output, "{}, ", param.name).unwrap(),
+                _ => write!(
+                    output,
+                    "0x{:x}, ",
+                    const_parameter.eval_bits(tcx, ty::ParamEnv::reveal_all(), const_parameter.ty)
+                )
+                .unwrap(),
+            },
+            other => bug!("Unexpected non-erasable generic: {:?}", other),
         }
+    }
 
-        output.pop();
-        output.pop();
+    output.pop();
+    output.pop();
 
-        output.push('>');
-    }
+    push_close_angle_bracket(tcx, output);
+}
+
+pub fn push_generic_params<'tcx>(tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, output: &mut String) {
+    let mut visited = FxHashSet::default();
+    push_generic_params_internal(tcx, substs, output, &mut visited);
+}
+
+fn push_close_angle_bracket<'tcx>(tcx: TyCtxt<'tcx>, output: &mut String) {
+    // MSVC debugger always treats `>>` as a shift, even when parsing templates,
+    // so add a space to avoid confusion.
+    if tcx.sess.target.is_like_msvc && output.ends_with('>') {
+        output.push(' ')
+    };
+
+    output.push('>');
 }
index 89280149a035140cd8943ab18a8664040d97aaeb..cf887ffb0c01ed77341c1e028be7557997a91e04 100644 (file)
@@ -15,7 +15,7 @@
       </Synthetic>
     </Expand>
   </Type>
-  <Type Name="slice&lt;*&gt;">
+  <Type Name="slice$&lt;*&gt;">
     <DisplayString>{{ len={length} }}</DisplayString>
     <Expand>
       <Item Name="[len]" ExcludeView="simple">length</Item>
       </ArrayItems>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;&gt;">
+  <Type Name="tuple$&lt;&gt;">
     <DisplayString>()</DisplayString>
   </Type>
-  <Type Name="tuple&lt;*&gt;">
+  <Type Name="tuple$&lt;*&gt;">
     <DisplayString>({__0})</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;*,*&gt;">
+  <Type Name="tuple$&lt;*,*&gt;">
     <DisplayString>({__0}, {__1})</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
       <Item Name="[1]">__1</Item>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;*,*,*&gt;">
+  <Type Name="tuple$&lt;*,*,*&gt;">
     <DisplayString>({__0}, {__1}, {__2})</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
@@ -49,7 +49,7 @@
       <Item Name="[2]">__2</Item>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;*,*,*,*&gt;">
+  <Type Name="tuple$&lt;*,*,*,*&gt;">
     <DisplayString>({__0}, {__1}, {__2}, {__3})</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
@@ -58,7 +58,7 @@
       <Item Name="[3]">__3</Item>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;*,*,*,*,*&gt;">
+  <Type Name="tuple$&lt;*,*,*,*,*&gt;">
     <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4})</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
@@ -68,7 +68,7 @@
       <Item Name="[4]">__4</Item>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;*,*,*,*,*,*&gt;">
+  <Type Name="tuple$&lt;*,*,*,*,*,*&gt;">
     <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5})</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
@@ -79,7 +79,7 @@
       <Item Name="[5]">__5</Item>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;*,*,*,*,*,*,*&gt;">
+  <Type Name="tuple$&lt;*,*,*,*,*,*,*&gt;">
     <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6})</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
@@ -91,7 +91,7 @@
       <Item Name="[6]">__6</Item>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;*,*,*,*,*,*,*,*&gt;">
+  <Type Name="tuple$&lt;*,*,*,*,*,*,*,*&gt;">
     <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7})</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
       <Item Name="[7]">__7</Item>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;*,*,*,*,*,*,*,*,*&gt;">
+  <Type Name="tuple$&lt;*,*,*,*,*,*,*,*,*&gt;">
     <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8})</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
       <Item Name="[8]">__8</Item>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;*,*,*,*,*,*,*,*,*,*&gt;">
+  <Type Name="tuple$&lt;*,*,*,*,*,*,*,*,*,*&gt;">
     <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8}, {__9})</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
       <Item Name="[9]">__9</Item>
     </Expand>
   </Type>
-  <Type Name="tuple&lt;*,*,*,*,*,*,*,*,*,*,*&gt;">
+  <Type Name="tuple$&lt;*,*,*,*,*,*,*,*,*,*,*&gt;">
     <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8}, {__9}, ...)</DisplayString>
     <Expand>
       <Item Name="[0]">__0</Item>
index 2c05f9d7c12e5c095a2dad6656f85267de9195e3..3ccd2e9c30ed5ff98df837d6bf5ad7f6cdd55bd3 100644 (file)
@@ -41,7 +41,7 @@
           <If Condition="(base.table.table.ctrl.pointer[i] &amp; 0x80) == 0">
             <!-- Bucket is populated -->
             <Exec>n--</Exec>
-            <Item Name="{((tuple&lt;$T1, $T2&gt;*)base.table.table.ctrl.pointer)[-(i + 1)].__0}">((tuple&lt;$T1, $T2&gt;*)base.table.table.ctrl.pointer)[-(i + 1)].__1</Item>
+            <Item Name="{((tuple$&lt;$T1, $T2&gt;*)base.table.table.ctrl.pointer)[-(i + 1)].__0}">((tuple$&lt;$T1, $T2&gt;*)base.table.table.ctrl.pointer)[-(i + 1)].__1</Item>
           </If>
           <Exec>i++</Exec>
         </Loop>
index e410180bfff6fa837640c4411e42b69a5aa0b170..8efa1b15b3fff17b1080641fc7ccad92e18ae9eb 100644 (file)
@@ -17,7 +17,7 @@ async fn async_fn_test() {
 // FIXME: No way to reliably check the filename.
 
 // CHECK-DAG:  [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test"
-// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0"
+// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator$0"
 // CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]],
 // For brevity, we only check the struct name and members of the last variant.
 // CHECK-SAME: file: [[FILE:![0-9]*]], line: 11,
index 7de115f7e9194d7d062c3346f2d76fd64e3e579a..39319a3ea722cbfea9603e354b70ada40cd13284 100644 (file)
@@ -17,7 +17,7 @@ async fn async_fn_test() {
 // FIXME: No way to reliably check the filename.
 
 // CHECK-DAG:  [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test"
-// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[ASYNC_FN]]
+// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{generator#0}", scope: [[ASYNC_FN]]
 // CHECK:      [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[ASYNC_FN]],
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: discriminator: [[DISC:![0-9]*]]
index f9113d50197c19950fead49653da4d78b495b374..4bd811bed10e5d2999a7551e860e4f902548632c 100644 (file)
@@ -1,7 +1,8 @@
 // compile-flags: -g
 //
 // CHECK-LABEL: @main
-// CHECK: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "fn() -> <recursive_type>",{{.*}}
+// MSVC: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "recursive_type$ (*)()",{{.*}}
+// NONMSVC: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "fn() -> <recursive_type>",{{.*}}
 //
 // CHECK: {{.*}}DISubroutineType{{.*}}
 // CHECK: {{.*}}DIBasicType(name: "<recur_type>", encoding: DW_ATE_unsigned)
index 7edb07d224c3646865aaa169f27c6b11a0a06826..e2ba4ad30894d151ac92c3c1354af26bb3bc9998 100644 (file)
@@ -21,7 +21,7 @@ fn generator_test() -> impl Generator<Yield = i32, Return = ()> {
 // FIXME: No way to reliably check the filename.
 
 // CHECK-DAG:  [[GEN_FN:!.*]] = !DINamespace(name: "generator_test"
-// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0"
+// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator$0"
 // CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]],
 // For brevity, we only check the struct name and members of the last variant.
 // CHECK-SAME: file: [[FILE:![0-9]*]], line: 14,
index 8b87a2f0646044af947a3639e32637aaeec6e82f..ea324695c15d79d83fc65d94eb4f8f64b72f2db9 100644 (file)
@@ -21,7 +21,7 @@ fn generator_test() -> impl Generator<Yield = i32, Return = ()> {
 // FIXME: No way to reliably check the filename.
 
 // CHECK-DAG:  [[GEN_FN:!.*]] = !DINamespace(name: "generator_test"
-// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[GEN_FN]]
+// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{generator#0}", scope: [[GEN_FN]]
 // CHECK:      [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[GEN_FN]],
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: discriminator: [[DISC:![0-9]*]]
index 3721b87678d55f3bdb19645f45885cac59d3aa5e..c35c32554983a6976d08789fb606d422d7713dd8 100644 (file)
@@ -6,9 +6,8 @@
 
 // min-lldb-version: 310
 
-// This fails on lldb 6.0.1 on x86-64 Fedora 28; so mark it macOS-only
-// for now.
-// only-macos
+// This fails on lldb 6.0.1 on x86-64 Fedora 28; so ignore Linux for now.
+// ignore-linux
 
 // compile-flags:-g
 
@@ -44,6 +43,9 @@
 // gdb-check:$13 = 2.5
 // gdb-command:print f64
 // gdb-check:$14 = 3.5
+// gdb-command:print s
+// gdbg-check:$15 = {data_ptr = [...] "Hello, World!", length = 13}
+// gdbr-check:$15 = "Hello, World!"
 
 
 // === LLDB TESTS ==================================================================================
 // lldbg-check:[...]$12 = 3.5
 // lldbr-check:(f64) f64 = 3.5
 
+
+// === CDB TESTS ===================================================================================
+
+// cdb-command:g
+// cdb-command:dx b
+// cdb-check:b                : false [Type: bool]
+// cdb-command:dx i
+// cdb-check:i                : -1 [Type: [...]]
+// The variable 'c' doesn't appear for some reason...
+// cdb-command:dx i8
+// cdb-check:i8               : 68 [Type: char]
+// cdb-command:dx i16
+// cdb-check:i16              : -16 [Type: short]
+// cdb-command:dx i32
+// cdb-check:i32              : -32 [Type: int]
+// cdb-command:dx i64
+// cdb-check:i64              : -64 [Type: __int64]
+// cdb-command:dx u
+// cdb-check:u                : 0x1 [Type: [...]]
+// cdb-command:dx u8
+// cdb-check:u8               : 0x64 [Type: unsigned char]
+// cdb-command:dx u16
+// cdb-check:u16              : 0x10 [Type: unsigned short]
+// cdb-command:dx u32
+// cdb-check:u32              : 0x20 [Type: unsigned int]
+// cdb-command:dx u64
+// cdb-check:u64              : 0x40 [Type: unsigned __int64]
+// cdb-command:dx f32
+// cdb-check:f32              : 2.500000 [Type: float]
+// cdb-command:dx f64
+// cdb-check:f64              : 3.500000 [Type: double]
+// cdb-command:.enable_unicode 1
+// cdb-command:dx  s
+// cdb-check:s                : "Hello, World!" [Type: str]
+
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
@@ -113,6 +150,7 @@ fn main() {
     let u64: u64 = 64;
     let f32: f32 = 2.5;
     let f64: f64 = 3.5;
+    let s: &str = "Hello, World!";
     _zzz(); // #break
 }
 
diff --git a/src/test/debuginfo/function-names.rs b/src/test/debuginfo/function-names.rs
new file mode 100644 (file)
index 0000000..26317f5
--- /dev/null
@@ -0,0 +1,175 @@
+// Function names are formatted differently in old versions of GDB
+// min-gdb-version: 9.2
+
+// compile-flags:-g
+
+// === GDB TESTS ===================================================================================
+
+// Top-level function
+// gdb-command:info functions -q function_names::main
+// gdb-check:[...]static fn function_names::main();
+// gdb-command:info functions -q function_names::generic_func<*
+// gdb-check:[...]static fn function_names::generic_func(i32) -> i32;
+
+// Implementations
+// gdb-command:info functions -q function_names::.*::impl_function.*
+// gdb-check:[...]static fn function_names::GenericStruct<T1,T2>::impl_function();
+// gdb-check:[...]static fn function_names::Mod1::TestStruct2::impl_function();
+// gdb-check:[...]static fn function_names::TestStruct1::impl_function();
+
+// Trait implementations
+// gdb-command:info functions -q function_names::.*::trait_function.*
+// gdb-check:[...]static fn <function_names::GenericStruct<T,i32> as function_names::TestTrait1>::trait_function();
+// gdb-check:[...]static fn <function_names::GenericStruct<[T; N],f32> as function_names::TestTrait1>::trait_function();
+// gdb-check:[...]static fn <function_names::Mod1::TestStruct2 as function_names::Mod1::TestTrait2>::trait_function();
+// gdb-check:[...]static fn <function_names::TestStruct1 as function_names::TestTrait1>::trait_function();
+
+// Closure
+// gdb-command:info functions -q function_names::.*::{{closure.*
+// gdb-check:[...]static fn function_names::GenericStruct<T1,T2>::impl_function::{{closure}}(*mut function_names::{impl#2}::impl_function::{closure#0});
+// gdb-check:[...]static fn function_names::generic_func::{{closure}}(*mut function_names::generic_func::{closure#0});
+// gdb-check:[...]static fn function_names::main::{{closure}}(*mut function_names::main::{closure#0});
+
+// Generator
+// Generators don't seem to appear in GDB's symbol table.
+
+// === CDB TESTS ===================================================================================
+
+// Top-level function
+// cdb-command:x a!function_names::main
+// cdb-check:[...] a!function_names::main (void)
+// cdb-command:x a!function_names::generic_func<*
+// cdb-check:[...] a!function_names::generic_func<i32> (int)
+
+// Implementations
+// cdb-command:x a!function_names::*::impl_function*
+// cdb-check:[...] a!function_names::Mod1::TestStruct2::impl_function (void)
+// cdb-check:[...] a!function_names::TestStruct1::impl_function (void)
+// cdb-check:[...] a!function_names::GenericStruct<i32, i32>::impl_function<i32, i32> (void)
+
+// Trait implementations
+// cdb-command:x a!function_names::*::trait_function*
+// cdb-check:[...] a!function_names::impl$6::trait_function<i32, 0x1> (void)
+// cdb-check:[...] a!function_names::impl$3::trait_function<i32> (void)
+// cdb-check:[...] a!function_names::impl$1::trait_function (void)
+// cdb-check:[...] a!function_names::impl$5::trait_function3<function_names::TestStruct1> (void)
+// cdb-check:[...] a!function_names::Mod1::impl$1::trait_function (void)
+
+// Closure
+// cdb-command:x a!function_names::*::closure*
+// cdb-check:[...] a!function_names::main::closure$0 (void)
+// cdb-check:[...] a!function_names::generic_func::closure$0<i32> (void)
+// cdb-check:[...] a!function_names::impl$2::impl_function::closure$0<i32, i32> (void)
+
+// Generator
+// cdb-command:x a!function_names::*::generator*
+// cdb-check:[...] a!function_names::main::generator$1 (void)
+
+#![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
+#![omit_gdb_pretty_printer_section]
+#![feature(generators, generator_trait)]
+
+use Mod1::TestTrait2;
+use std::ops::Generator;
+use std::pin::Pin;
+
+fn main() {
+    // Implementations
+    TestStruct1::impl_function();
+    Mod1::TestStruct2::impl_function();
+    GenericStruct::<i32, i32>::impl_function();
+
+    // Trait implementations
+    TestStruct1::trait_function();
+    Mod1::TestStruct2::trait_function();
+    GenericStruct::<i32, i32>::trait_function();
+    GenericStruct::<[i32; 1], f32>::trait_function();
+    GenericStruct::<TestStruct1, usize>::trait_function3();
+
+    // Generic function
+    let _ = generic_func(42);
+
+    // Closure
+    let closure = || { TestStruct1 };
+    closure();
+
+    // Generator
+    let mut generator = || { yield; return; };
+    Pin::new(&mut generator).resume(());
+}
+
+struct TestStruct1;
+trait TestTrait1 {
+    fn trait_function();
+}
+
+// Implementation
+impl TestStruct1 {
+    pub fn impl_function() {}
+}
+
+// Implementation for a trait
+impl TestTrait1 for TestStruct1 {
+    fn trait_function() {}
+}
+
+// Implementation and implementation within a mod
+mod Mod1 {
+    pub struct TestStruct2;
+    pub trait TestTrait2 {
+        fn trait_function();
+    }
+
+    impl TestStruct2 {
+        pub fn impl_function() {}
+    }
+
+    impl TestTrait2 for TestStruct2 {
+        fn trait_function() {}
+    }
+}
+
+struct GenericStruct<T1, T2>(std::marker::PhantomData<(T1, T2)>);
+
+// Generic implementation
+impl<T1, T2> GenericStruct<T1, T2> {
+    pub fn impl_function() {
+        // Closure in a generic implementation
+        let closure = || { TestStruct1 };
+        closure();
+    }
+}
+
+// Generic trait implementation
+impl<T> TestTrait1 for GenericStruct<T, i32> {
+    fn trait_function() {}
+}
+
+// Implementation based on associated type
+trait TestTrait3 {
+    type AssocType;
+    fn trait_function3();
+}
+impl TestTrait3 for TestStruct1 {
+    type AssocType = usize;
+    fn trait_function3() {}
+}
+impl<T: TestTrait3> TestTrait3 for GenericStruct<T, T::AssocType> {
+    type AssocType = T::AssocType;
+    fn trait_function3() {}
+}
+
+// Generic trait implementation with const generics
+impl<T, const N: usize> TestTrait1 for GenericStruct<[T; N], f32> {
+    fn trait_function() {}
+}
+
+// Generic function
+fn generic_func<T>(value: T) -> T {
+    // Closure in a generic function
+    let closure = || { TestStruct1 };
+    closure();
+
+    value
+}
index 1beed1c835d977d566d388f019057a1d6722eb25..7ac3304aa963491547aa53342567595888610237 100644 (file)
 
 // gdb-command:run
 // gdb-command:print b
-// gdb-check:$1 = generator_objects::main::generator-0::Unresumed(0x[...])
+// gdb-check:$1 = generator_objects::main::{generator#0}::Unresumed(0x[...])
 // gdb-command:continue
 // gdb-command:print b
-// gdb-check:$2 = generator_objects::main::generator-0::Suspend0{c: 6, d: 7, __0: 0x[...]}
+// gdb-check:$2 = generator_objects::main::{generator#0}::Suspend0{c: 6, d: 7, __0: 0x[...]}
 // gdb-command:continue
 // gdb-command:print b
-// gdb-check:$3 = generator_objects::main::generator-0::Suspend1{c: 7, d: 8, __0: 0x[...]}
+// gdb-check:$3 = generator_objects::main::{generator#0}::Suspend1{c: 7, d: 8, __0: 0x[...]}
 // gdb-command:continue
 // gdb-command:print b
-// gdb-check:$4 = generator_objects::main::generator-0::Returned(0x[...])
+// gdb-check:$4 = generator_objects::main::{generator#0}::Returned(0x[...])
 
 // === LLDB TESTS ==================================================================================
 
 // lldb-command:run
 // lldb-command:print b
-// lldbg-check:(generator_objects::main::generator-0) $0 =
+// lldbg-check:(generator_objects::main::{generator#0}) $0 =
 // lldb-command:continue
 // lldb-command:print b
-// lldbg-check:(generator_objects::main::generator-0) $1 =
+// lldbg-check:(generator_objects::main::{generator#0}) $1 =
 // lldb-command:continue
 // lldb-command:print b
-// lldbg-check:(generator_objects::main::generator-0) $2 =
+// lldbg-check:(generator_objects::main::{generator#0}) $2 =
 // lldb-command:continue
 // lldb-command:print b
-// lldbg-check:(generator_objects::main::generator-0) $3 =
+// lldbg-check:(generator_objects::main::{generator#0}) $3 =
 
 #![feature(omit_gdb_pretty_printer_section, generators, generator_trait)]
 #![omit_gdb_pretty_printer_section]
index 170a610c621c035ddc44ce36c6fad533e2372858..c0135de1219d37530e06cd8c0aa5724e2e20a299 100644 (file)
 // lldbg-check:[...]$3 = AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>> { key: 6.5, value: AGenericStruct<i32, f64> { key: 7, value: 8.5 } }
 // lldbr-check:(generic_struct::AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>>) float_int_float = AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>> { key: 6.5, value: AGenericStruct<i32, f64> { key: 7, value: 8.5 } }
 
+// === CDB TESTS ===================================================================================
+
+// cdb-command:g
+
+// cdb-command:dx int_int
+// cdb-check:int_int          [Type: generic_struct::AGenericStruct<i32, i32>]
+// cdb-check:[...]key              : 0 [Type: int]
+// cdb-check:[...]value            : 1 [Type: int]
+// cdb-command:dx int_float
+// cdb-check:int_float        [Type: generic_struct::AGenericStruct<i32, f64>]
+// cdb-check:[...]key              : 2 [Type: int]
+// cdb-check:[...]value            : 3.500000 [Type: double]
+// cdb-command:dx float_int
+// cdb-check:float_int        [Type: generic_struct::AGenericStruct<f64, i32>]
+// cdb-check:[...]key              : 4.500000 [Type: double]
+// cdb-check:[...]value            : 5 [Type: int]
+// cdb-command:dx float_int_float
+// cdb-check:float_int_float  [Type: generic_struct::AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64> >]
+// cdb-check:[...]key              : 6.500000 [Type: double]
+// cdb-check:[...]value            [Type: generic_struct::AGenericStruct<i32, f64>]
+
 
 #![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
index 6b2b12edda5d7a710c48862caaed0560b263be0c..f6d2146fe11fa43654053d80df0a9ae6004a800c 100644 (file)
 // gdb-command:run
 
 // gdb-command:print g
-// gdb-check:$1 = issue_57822::main::closure-1 (issue_57822::main::closure-0 (1))
+// gdb-check:$1 = issue_57822::main::{closure#1} (issue_57822::main::{closure#0} (1))
 
 // gdb-command:print b
-// gdb-check:$2 = issue_57822::main::generator-3::Unresumed(issue_57822::main::generator-2::Unresumed(2))
+// gdb-check:$2 = issue_57822::main::{generator#3}::Unresumed(issue_57822::main::{generator#2}::Unresumed(2))
 
 // === LLDB TESTS ==================================================================================
 
 // lldb-command:run
 
 // lldb-command:print g
-// lldbg-check:(issue_57822::main::closure-1) $0 = { 0 = { 0 = 1 } }
+// lldbg-check:(issue_57822::main::{closure#1}) $0 = { 0 = { 0 = 1 } }
 
 // lldb-command:print b
-// lldbg-check:(issue_57822::main::generator-3) $1 =
+// lldbg-check:(issue_57822::main::{generator#3}) $1 =
 
 #![feature(omit_gdb_pretty_printer_section, generators, generator_trait)]
 #![omit_gdb_pretty_printer_section]
index 550cc66f3899c01407419469880ccffc6c7a34ff..cf3be2e71967402ea02991b82282ceb2e12ace23 100644 (file)
@@ -1,5 +1,4 @@
 // only-cdb
-// ignore-tidy-linelength
 // compile-flags:-g
 
 // cdb-command: g
@@ -8,16 +7,16 @@
 //       so the best we can do is to make sure we are generating the right debuginfo
 
 // cdb-command: dx -r2 a,!
-// cdb-check:a,!              [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>]
-// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Some]
+// cdb-check:a,!              [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>]
+// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Some]
 // cdb-check:        [+0x000] __0              : Low (0x2) [Type: msvc_pretty_enums::CStyleEnum]
-// cdb-check:    [+0x000] discriminant     : 0x2 [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Discriminant$]
+// cdb-check:    [+0x000] discriminant     : 0x2 [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Discriminant$]
 
 // cdb-command: dx -r2 b,!
-// cdb-check:b,!              [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>]
-// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Some]
+// cdb-check:b,!              [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>]
+// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Some]
 // cdb-check:        [+0x000] __0              : 0x11 [Type: msvc_pretty_enums::CStyleEnum]
-// cdb-check:    [+0x000] discriminant     : None (0x11) [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Discriminant$]
+// cdb-check:    [+0x000] discriminant     : None (0x11) [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Discriminant$]
 
 // cdb-command: dx -r2 c,!
 // cdb-check:c,!              [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
 // cdb-check:    [+0x000] discriminant     : Tag2 (0x13) [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$]
 
 // cdb-command: dx -r2 f,!
-// cdb-check:f,!              [Type: enum$<core::option::Option<u32*>, 1, [...], Some>]
-// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Some]
+// cdb-check:f,!              [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
+// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Some]
 // cdb-check:        [+0x000] __0              : 0x[...] : 0x1 [Type: unsigned int *]
-// cdb-check:    [+0x000] discriminant     : 0x[...] [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Discriminant$]
+// cdb-check:    [+0x000] discriminant     : 0x[...] [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Discriminant$]
 
 // cdb-command: dx -r2 g,!
-// cdb-check:g,!              [Type: enum$<core::option::Option<u32*>, 1, [...], Some>]
-// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Some]
+// cdb-check:g,!              [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
+// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Some]
 // cdb-check:        [+0x000] __0              : 0x0 [Type: unsigned int *]
-// cdb-check:    [+0x000] discriminant     : None (0x0) [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Discriminant$]
+// cdb-check:    [+0x000] discriminant     : None (0x0) [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Discriminant$]
 
 // cdb-command: dx h
-// cdb-check:h                : Some [Type: enum$<core::option::Option<u32>>]
+// cdb-check:h                : Some [Type: enum$<core::option::Option<u32> >]
 // cdb-check:    [+0x000] variant$         : Some (0x1) [Type: core::option::Option]
 // cdb-check:    [+0x004] __0              : 0xc [Type: unsigned int]
 
 // cdb-command: dx i
-// cdb-check:i                : None [Type: enum$<core::option::Option<u32>>]
+// cdb-check:i                : None [Type: enum$<core::option::Option<u32> >]
 // cdb-check:    [+0x000] variant$         : None (0x0) [Type: core::option::Option]
 
 // cdb-command: dx j
index 969099359ab08d5469fdc721cafeca77a660dffd..40bea30f1252ca853d300202ae31eeb532b206ae 100644 (file)
@@ -3,7 +3,6 @@
 // cdb-only
 // min-cdb-version: 10.0.21287.1005
 // compile-flags:-g
-// ignore-tidy-linelength
 
 // === CDB TESTS ==================================================================================
 //
@@ -22,7 +21,7 @@
 
 //
 // cdb-command:dx lock,d
-// cdb-check:lock,d           : Ok [Type: enum$<core::result::Result<std::sync::mutex::MutexGuard<i32>, enum$<std::sync::poison::TryLockError<std::sync::mutex::MutexGuard<i32>>, 0, 1, Poisoned>>>]
+// cdb-check:lock,d           : Ok [Type: enum$<core::result::Result<std::sync::mutex::MutexGuard<i32>, enum$<std::sync::poison::TryLockError<std::sync::mutex::MutexGuard<i32> >, 0, 1, Poisoned> > >]
 // cdb-check:    [...] variant$         : Ok (0) [Type: core::result::Result]
 // cdb-check:    [...] __0              [Type: std::sync::mutex::MutexGuard<i32>]
 
index 7115aec1041af49774955f1a9733de8572c90d92..ede15578712578cd476dbf73100e473872887414 100644 (file)
@@ -77,6 +77,8 @@
 // cdb-command: dx hash_map,d
 // cdb-check:    ["0xe"]          : 14 [Type: unsigned __int64]
 
+// cdb-command: dx x
+
 #![allow(unused_variables)]
 use std::collections::HashSet;
 use std::collections::HashMap;
@@ -95,6 +97,9 @@ fn main() {
         hash_map.insert(i as u64, i as u64);
     }
 
+    let x = &(123u64, 456u64);
+    let string = "awefawefawe".to_string();
+
     zzz(); // #break
 }
 
index aeee1e6258de6d59c3b3cb62cd5267c3ae2a1ea1..a7f384c05007d2556ab1197a5ec4a8007e25ba04 100644 (file)
@@ -1,7 +1,6 @@
 // ignore-freebsd: gdb package too new
 // only-cdb // "Temporarily" ignored on GDB/LLDB due to debuginfo tests being disabled, see PR 47155
 // ignore-android: FIXME(#10381)
-// ignore-tidy-linelength
 // compile-flags:-g
 // min-gdb-version: 7.7
 // min-lldb-version: 310
@@ -72,7 +71,7 @@
 // cdb-command: g
 
 // cdb-command: dx slice,d
-// cdb-check:slice,d          : { len=4 } [Type: slice<i32>]
+// cdb-check:slice,d          : { len=4 } [Type: slice$<i32>]
 // cdb-check:    [len]            : 4 [Type: [...]]
 // cdb-check:    [0]              : 0 [Type: int]
 // cdb-check:    [1]              : 1 [Type: int]
 // NOTE: OsString doesn't have a .natvis entry yet.
 
 // cdb-command: dx some
-// cdb-check:some             : Some [Type: enum$<core::option::Option<i16>>]
+// cdb-check:some             : Some [Type: enum$<core::option::Option<i16> >]
 // cdb-check:    [...] variant$         : Some (0x1) [Type: core::option::Option]
 // cdb-check:    [...] __0              : 8 [Type: short]
 
 // cdb-command: dx none
-// cdb-check:none             : None [Type: enum$<core::option::Option<i64>>]
+// cdb-check:none             : None [Type: enum$<core::option::Option<i64> >]
 // cdb-check:    [...] variant$         : None (0x0) [Type: core::option::Option]
 
 // cdb-command: dx some_string
index 9f1e856ab42ed7f348df2cd2d1f67f248c83ac41..6e558bd3c13aa847e34a2f07abb3e943fddb7945 100644 (file)
@@ -1,6 +1,5 @@
 // pretty-printers are not loaded
 // compile-flags:-g
-// ignore-tidy-linelength
 
 // min-gdb-version: 8.1
 // min-cdb-version: 10.0.18317.1001
@@ -36,7 +35,7 @@
 
 // cdb-command:dx w1,d
 // cdb-check:w1,d             [Type: alloc::rc::Weak<i32>]
-// cdb-check:    [...] ptr              : [...] [Type: core::ptr::non_null::NonNull<alloc::rc::RcBox<i32>>]
+// cdb-check:    [...] ptr              : [...] [Type: core::ptr::non_null::NonNull<alloc::rc::RcBox<i32> >]
 
 // cdb-command:dx a,d
 // cdb-check:a,d              : 42 [Type: alloc::sync::Arc<i32>]
index 18eae7f301fbb843dcd7b60dbda408704d9e057a..a075c437c463b588a21b412819d19a3d62b7aef8 100644 (file)
@@ -7,11 +7,11 @@
 // cdb-command: g
 
 // cdb-command: dx x,d
-// cdb-check:x,d              : Ok [Type: enum$<core::result::Result<i32, str>>]
+// cdb-check:x,d              : Ok [Type: enum$<core::result::Result<i32, str> >]
 // cdb-check:    [...] __0              : -3 [Type: int]
 
 // cdb-command: dx y
-// cdb-check:y                : Err [Type: enum$<core::result::Result<i32, str>>]
+// cdb-check:y                : Err [Type: enum$<core::result::Result<i32, str> >]
 // cdb-check:    [...] __0              : "Some error message" [Type: str]
 
 fn main()
index b7fcfeef090aa590dc4e41c63a68ba840323a14c..0807cfedce01d844522bc05b2b0dcfaf4d1346c8 100644 (file)
 // cdb-command: g
 
 // cdb-command:dx noPadding8,d
-// cdb-check:noPadding8,d [...]: (-100, 100) [Type: tuple<i8, u8>]
+// cdb-check:noPadding8,d [...]: (-100, 100) [Type: tuple$<i8,u8>]
 // cdb-check:[...][0]              : -100 [Type: [...]]
 // cdb-check:[...][1]              : 100 [Type: [...]]
 // cdb-command:dx noPadding16,d
-// cdb-check:noPadding16,d [...]: (0, 1, 2) [Type: tuple<i16, i16, u16>]
+// cdb-check:noPadding16,d [...]: (0, 1, 2) [Type: tuple$<i16,i16,u16>]
 // cdb-check:[...][0]              : 0 [Type: [...]]
 // cdb-check:[...][1]              : 1 [Type: [...]]
 // cdb-check:[...][2]              : 2 [Type: [...]]
 // cdb-command:dx noPadding32,d
-// cdb-check:noPadding32,d [...]: (3, 4.5[...], 5) [Type: tuple<i32, f32, u32>]
+// cdb-check:noPadding32,d [...]: (3, 4.5[...], 5) [Type: tuple$<i32,f32,u32>]
 // cdb-check:[...][0]              : 3 [Type: [...]]
 // cdb-check:[...][1]              : 4.5[...] [Type: [...]]
 // cdb-check:[...][2]              : 5 [Type: [...]]
 // cdb-command:dx noPadding64,d
-// cdb-check:noPadding64,d [...]: (6, 7.5[...], 8) [Type: tuple<i64, f64, u64>]
+// cdb-check:noPadding64,d [...]: (6, 7.5[...], 8) [Type: tuple$<i64,f64,u64>]
 // cdb-check:[...][0]              : 6 [Type: [...]]
 // cdb-check:[...][1]              : 7.500000 [Type: [...]]
 // cdb-check:[...][2]              : 8 [Type: [...]]
 
 // cdb-command:dx internalPadding1,d
-// cdb-check:internalPadding1,d [...]: (9, 10) [Type: tuple<i16, i32>]
+// cdb-check:internalPadding1,d [...]: (9, 10) [Type: tuple$<i16,i32>]
 // cdb-check:[...][0]              : 9 [Type: short]
 // cdb-check:[...][1]              : 10 [Type: int]
 // cdb-command:dx internalPadding2,d
-// cdb-check:internalPadding2,d [...]: (11, 12, 13, 14) [Type: tuple<i16, i32, u32, u64>]
+// cdb-check:internalPadding2,d [...]: (11, 12, 13, 14) [Type: tuple$<i16,i32,u32,u64>]
 // cdb-check:[...][0]              : 11 [Type: [...]]
 // cdb-check:[...][1]              : 12 [Type: [...]]
 // cdb-check:[...][2]              : 13 [Type: [...]]
 // cdb-check:[...][3]              : 14 [Type: [...]]
 
 // cdb-command:dx paddingAtEnd,d
-// cdb-check:paddingAtEnd,d [...]: (15, 16) [Type: tuple<i32, i16>]
+// cdb-check:paddingAtEnd,d [...]: (15, 16) [Type: tuple$<i32,i16>]
 // cdb-check:[...][0]              : 15 [Type: [...]]
 // cdb-check:[...][1]              : 16 [Type: [...]]
 
index af35ad6af0710f58108628c6db2a41e0328e2a18..531c37a3421198939bb94ed5a983cd24d1eae917 100644 (file)
@@ -9,8 +9,8 @@
 // cdb-command:g
 //
 // cdb-command:dx join_handle,d
-// cdb-check:join_handle,d    [Type: std::thread::JoinHandle<tuple<>>]
-// cdb-check:    [...] __0              [Type: std::thread::JoinInner<tuple<>>]
+// cdb-check:join_handle,d    [Type: std::thread::JoinHandle<tuple$<> >]
+// cdb-check:    [...] __0              [Type: std::thread::JoinInner<tuple$<> >]
 //
 // cdb-command:dx t,d
 // cdb-check:t,d              : [...] [Type: std::thread::Thread *]
index 0447d8e9ddeb0d8d1caf255cf497b54d5de39cea..578db74e9eeb640b783d152ec8fa1b265660706b 100644 (file)
 // cdb-command: g
 
 // cdb-command:dx no_padding1,d
-// cdb-check:no_padding1,d [...]: ((0, 1), 2, 3) [Type: tuple<tuple<u32, u32>, u32, u32>]
-// cdb-check:[...][0]              : (0, 1) [Type: tuple<u32, u32>]
+// cdb-check:no_padding1,d [...]: ((0, 1), 2, 3) [Type: tuple$<tuple$<u32,u32>,u32,u32>]
+// cdb-check:[...][0]              : (0, 1) [Type: tuple$<u32,u32>]
 // cdb-check:[...][1]              : 2 [Type: [...]]
 // cdb-check:[...][2]              : 3 [Type: [...]]
 // cdb-command:dx no_padding1.__0,d
-// cdb-check:no_padding1.__0,d [...]: (0, 1) [Type: tuple<u32, u32>]
+// cdb-check:no_padding1.__0,d [...]: (0, 1) [Type: tuple$<u32,u32>]
 // cdb-check:[...][0]              : 0 [Type: [...]]
 // cdb-check:[...][1]              : 1 [Type: [...]]
 // cdb-command:dx no_padding2,d
-// cdb-check:no_padding2,d [...]: (4, (5, 6), 7) [Type: tuple<u32, tuple<u32, u32>, u32>]
+// cdb-check:no_padding2,d [...]: (4, (5, 6), 7) [Type: tuple$<u32,tuple$<u32,u32>,u32>]
 // cdb-check:[...][0]              : 4 [Type: [...]]
-// cdb-check:[...][1]              : (5, 6) [Type: tuple<u32, u32>]
+// cdb-check:[...][1]              : (5, 6) [Type: tuple$<u32,u32>]
 // cdb-check:[...][2]              : 7 [Type: [...]]
 // cdb-command:dx no_padding2.__1,d
-// cdb-check:no_padding2.__1,d [...]: (5, 6) [Type: tuple<u32, u32>]
+// cdb-check:no_padding2.__1,d [...]: (5, 6) [Type: tuple$<u32,u32>]
 // cdb-check:[...][0]              : 5 [Type: [...]]
 // cdb-check:[...][1]              : 6 [Type: [...]]
 // cdb-command:dx no_padding3,d
-// cdb-check:no_padding3,d [...]: (8, 9, (10, 11)) [Type: tuple<u32, u32, tuple<u32, u32>>]
+// cdb-check:no_padding3,d [...]: (8, 9, (10, 11)) [Type: tuple$<u32,u32,tuple$<u32,u32> >]
 // cdb-check:[...][0]              : 8 [Type: [...]]
 // cdb-check:[...][1]              : 9 [Type: [...]]
-// cdb-check:[...][2]              : (10, 11) [Type: tuple<u32, u32>]
+// cdb-check:[...][2]              : (10, 11) [Type: tuple$<u32,u32>]
 // cdb-command:dx no_padding3.__2,d
-// cdb-check:no_padding3.__2,d [...]: (10, 11) [Type: tuple<u32, u32>]
+// cdb-check:no_padding3.__2,d [...]: (10, 11) [Type: tuple$<u32,u32>]
 // cdb-check:[...][0]              : 10 [Type: [...]]
 // cdb-check:[...][1]              : 11 [Type: [...]]
 
 // cdb-command:dx internal_padding1,d
-// cdb-check:internal_padding1,d [...]: (12, (13, 14)) [Type: tuple<i16, tuple<i32, i32>>]
+// cdb-check:internal_padding1,d [...]: (12, (13, 14)) [Type: tuple$<i16,tuple$<i32,i32> >]
 // cdb-check:[...][0]              : 12 [Type: [...]]
-// cdb-check:[...][1]              : (13, 14) [Type: tuple<i32, i32>]
+// cdb-check:[...][1]              : (13, 14) [Type: tuple$<i32,i32>]
 // cdb-command:dx internal_padding1.__1,d
-// cdb-check:internal_padding1.__1,d [...]: (13, 14) [Type: tuple<i32, i32>]
+// cdb-check:internal_padding1.__1,d [...]: (13, 14) [Type: tuple$<i32,i32>]
 // cdb-check:[...][0]              : 13 [Type: [...]]
 // cdb-check:[...][1]              : 14 [Type: [...]]
 // cdb-command:dx internal_padding2,d
-// cdb-check:internal_padding2,d [...]: (15, (16, 17)) [Type: tuple<i16, tuple<i16, i32>>]
+// cdb-check:internal_padding2,d [...]: (15, (16, 17)) [Type: tuple$<i16,tuple$<i16,i32> >]
 // cdb-check:[...][0]              : 15 [Type: [...]]
-// cdb-check:[...][1]              : (16, 17) [Type: tuple<i16, i32>]
+// cdb-check:[...][1]              : (16, 17) [Type: tuple$<i16,i32>]
 // cdb-command:dx internal_padding2.__1,d
-// cdb-check:internal_padding2.__1,d [...]: (16, 17) [Type: tuple<i16, i32>]
+// cdb-check:internal_padding2.__1,d [...]: (16, 17) [Type: tuple$<i16,i32>]
 // cdb-check:[...][0]              : 16 [Type: [...]]
 // cdb-check:[...][1]              : 17 [Type: [...]]
 
 // cdb-command:dx padding_at_end1,d
-// cdb-check:padding_at_end1,d [...]: (18, (19, 20)) [Type: tuple<i32, tuple<i32, i16>>]
+// cdb-check:padding_at_end1,d [...]: (18, (19, 20)) [Type: tuple$<i32,tuple$<i32,i16> >]
 // cdb-check:[...][0]              : 18 [Type: [...]]
-// cdb-check:[...][1]              : (19, 20) [Type: tuple<i32, i16>]
+// cdb-check:[...][1]              : (19, 20) [Type: tuple$<i32,i16>]
 // cdb-command:dx padding_at_end1.__1,d
-// cdb-check:padding_at_end1.__1,d [...][Type: tuple<i32, i16>]
+// cdb-check:padding_at_end1.__1,d [...][Type: tuple$<i32,i16>]
 // cdb-check:[...][0]              : 19 [Type: [...]]
 // cdb-check:[...][1]              : 20 [Type: [...]]
 // cdb-command:dx padding_at_end2,d
-// cdb-check:padding_at_end2,d [...]: ((21, 22), 23) [Type: tuple<tuple<i32, i16>, i32>]
-// cdb-check:[...][0]              : (21, 22) [Type: tuple<i32, i16>]
+// cdb-check:padding_at_end2,d [...]: ((21, 22), 23) [Type: tuple$<tuple$<i32,i16>,i32>]
+// cdb-check:[...][0]              : (21, 22) [Type: tuple$<i32,i16>]
 // cdb-check:[...][1]              : 23 [Type: [...]]
 // cdb-command:dx padding_at_end2.__0,d
-// cdb-check:padding_at_end2.__0,d [...]: (21, 22) [Type: tuple<i32, i16>]
+// cdb-check:padding_at_end2.__0,d [...]: (21, 22) [Type: tuple$<i32,i16>]
 // cdb-check:[...][0]              : 21 [Type: [...]]
 // cdb-check:[...][1]              : 22 [Type: [...]]
 
diff --git a/src/test/debuginfo/type-names.cdb.js b/src/test/debuginfo/type-names.cdb.js
new file mode 100644 (file)
index 0000000..8f8b20b
--- /dev/null
@@ -0,0 +1,17 @@
+// Helper functions for running the type-names.rs test under CDB
+
+// CDB exposes an "object model" via JavaScript that allows you to inspect debugging info - in this
+// case we want to ask the object model for the return and parameter types for a local variable
+// that is a function pointer to make sure that we are emitting the function pointer type in such a
+// way that CDB understands how to parse it.
+
+"use strict";
+
+function getFunctionDetails(name)
+{
+    var localVariable = host.currentThread.Stack.Frames[0].LocalVariables[name];
+    var functionPointerType = localVariable.targetType.genericArguments[0];
+    var functionType = functionPointerType.baseType;
+    host.diagnostics.debugLog("Return Type: ", functionType.functionReturnType, "\n");
+    host.diagnostics.debugLog("Parameter Types: ", functionType.functionParameterTypes, "\n");
+}
index cc4a4476d160e13d49ffb8a625ead39a35f24c9e..d1f322fa76cca23c17e0316540b32851f6161542 100644 (file)
 // ignore-lldb
-// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
+
+// GDB changed the way that it formatted Foreign types
+// min-gdb-version: 9.2
 
 // compile-flags:-g
 
+// === GDB TESTS ===================================================================================
+
 // gdb-command:run
 
 // STRUCTS
 // gdb-command:whatis simple_struct
-// gdbg-check:type = struct Struct1
-// gdbr-check:type = type_names::Struct1
+// gdb-check:type = type_names::Struct1
 
 // gdb-command:whatis generic_struct1
-// gdbg-check:type = struct GenericStruct<type_names::mod1::Struct2, type_names::mod1::mod2::Struct3>
-// gdbr-check:type = type_names::GenericStruct<type_names::mod1::Struct2, type_names::mod1::mod2::Struct3>
+// gdb-check:type = type_names::GenericStruct<type_names::mod1::Struct2, type_names::mod1::mod2::Struct3>
 
 // gdb-command:whatis generic_struct2
-// gdbg-check:type = struct GenericStruct<type_names::Struct1, extern "fastcall" fn(isize) -> usize>
-// gdbr-check:type = type_names::GenericStruct<type_names::Struct1, extern "fastcall" fn(isize) -> usize>
+// gdb-check:type = type_names::GenericStruct<type_names::Struct1, extern "fastcall" fn(isize) -> usize>
 
 // gdb-command:whatis mod_struct
-// gdbg-check:type = struct Struct2
-// gdbr-check:type = type_names::mod1::Struct2
+// gdb-check:type = type_names::mod1::Struct2
 
 // ENUMS
 // gdb-command:whatis simple_enum_1
-// gdbg-check:type = union Enum1
-// gdbr-check:type = type_names::Enum1
+// gdb-check:type = type_names::Enum1
 
 // gdb-command:whatis simple_enum_2
-// gdbg-check:type = union Enum1
-// gdbr-check:type = type_names::Enum1
+// gdb-check:type = type_names::Enum1
 
 // gdb-command:whatis simple_enum_3
-// gdbg-check:type = union Enum2
-// gdbr-check:type = type_names::mod1::Enum2
+// gdb-check:type = type_names::mod1::Enum2
 
 // gdb-command:whatis generic_enum_1
-// gdbg-check:type = union Enum3<type_names::mod1::Struct2>
-// gdbr-check:type = type_names::mod1::mod2::Enum3<type_names::mod1::Struct2>
+// gdb-check:type = type_names::mod1::mod2::Enum3
 
 // gdb-command:whatis generic_enum_2
-// gdbg-check:type = union Enum3<type_names::Struct1>
-// gdbr-check:type = type_names::mod1::mod2::Enum3<type_names::Struct1>
+// gdb-check:type = type_names::mod1::mod2::Enum3
 
 // TUPLES
 // gdb-command:whatis tuple1
-// gdbg-check:type = struct (u32, type_names::Struct1, type_names::mod1::mod2::Enum3<type_names::mod1::Struct2>)
-// gdbr-check:type = (u32, type_names::Struct1, type_names::mod1::mod2::Enum3<type_names::mod1::Struct2>)
+// gdb-check:type = (u32, type_names::Struct1, type_names::mod1::mod2::Enum3<type_names::mod1::Struct2>)
 
 // gdb-command:whatis tuple2
-// gdbg-check:type = struct ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char)
-// gdbr-check:type = ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char)
+// gdb-check:type = ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char)
 
 // BOX
 // gdb-command:whatis box1
-// gdbg-check:type = struct (alloc::boxed::Box<f32>, i32)
-// gdbr-check:type = (alloc::boxed::Box<f32>, i32)
+// gdb-check:type = (alloc::boxed::Box<f32, alloc::alloc::Global>, i32)
 
 // gdb-command:whatis box2
-// gdbg-check:type = struct (alloc::boxed::Box<type_names::mod1::mod2::Enum3<f32>>, i32)
-// gdbr-check:type = (alloc::boxed::Box<type_names::mod1::mod2::Enum3<f32>>, i32)
+// gdb-check:type = (alloc::boxed::Box<type_names::mod1::mod2::Enum3<f32>, alloc::alloc::Global>, i32)
 
 // REFERENCES
 // gdb-command:whatis ref1
-// gdbg-check:type = struct (&type_names::Struct1, i32)
-// gdbr-check:type = (&type_names::Struct1, i32)
+// gdb-check:type = (&type_names::Struct1, i32)
 
 // gdb-command:whatis ref2
-// gdbg-check:type = struct (&type_names::GenericStruct<char, type_names::Struct1>, i32)
-// gdbr-check:type = (&type_names::GenericStruct<char, type_names::Struct1>, i32)
+// gdb-check:type = (&type_names::GenericStruct<char, type_names::Struct1>, i32)
 
 // gdb-command:whatis mut_ref1
-// gdbg-check:type = struct (&mut type_names::Struct1, i32)
-// gdbr-check:type = (&mut type_names::Struct1, i32)
+// gdb-check:type = (&mut type_names::Struct1, i32)
 
 // gdb-command:whatis mut_ref2
-// gdbg-check:type = struct (&mut type_names::GenericStruct<type_names::mod1::Enum2, f64>, i32)
-// gdbr-check:type = (&mut type_names::GenericStruct<type_names::mod1::Enum2, f64>, i32)
+// gdb-check:type = (&mut type_names::GenericStruct<type_names::mod1::Enum2, f64>, i32)
 
 // RAW POINTERS
 // gdb-command:whatis mut_ptr1
-// gdbg-check:type = struct (*mut type_names::Struct1, isize)
-// gdbr-check:type = (*mut type_names::Struct1, isize)
+// gdb-check:type = (*mut type_names::Struct1, isize)
 
 // gdb-command:whatis mut_ptr2
-// gdbg-check:type = struct (*mut isize, isize)
-// gdbr-check:type = (*mut isize, isize)
+// gdb-check:type = (*mut isize, isize)
 
 // gdb-command:whatis mut_ptr3
-// gdbg-check:type = struct (*mut type_names::mod1::mod2::Enum3<type_names::Struct1>, isize)
-// gdbr-check:type = (*mut type_names::mod1::mod2::Enum3<type_names::Struct1>, isize)
+// gdb-check:type = (*mut type_names::mod1::mod2::Enum3<type_names::Struct1>, isize)
 
 // gdb-command:whatis const_ptr1
-// gdbg-check:type = struct (*const type_names::Struct1, isize)
-// gdbr-check:type = (*const type_names::Struct1, isize)
+// gdb-check:type = (*const type_names::Struct1, isize)
 
 // gdb-command:whatis const_ptr2
-// gdbg-check:type = struct (*const isize, isize)
-// gdbr-check:type = (*const isize, isize)
+// gdb-check:type = (*const isize, isize)
 
 // gdb-command:whatis const_ptr3
-// gdbg-check:type = struct (*const type_names::mod1::mod2::Enum3<type_names::Struct1>, isize)
-// gdbr-check:type = (*const type_names::mod1::mod2::Enum3<type_names::Struct1>, isize)
+// gdb-check:type = (*const type_names::mod1::mod2::Enum3<type_names::Struct1>, isize)
 
 // VECTORS
 // gdb-command:whatis fixed_size_vec1
-// gdbg-check:type = struct ([type_names::Struct1; 3], i16)
-// gdbr-check:type = ([type_names::Struct1; 3], i16)
+// gdb-check:type = ([type_names::Struct1; 3], i16)
 
 // gdb-command:whatis fixed_size_vec2
-// gdbg-check:type = struct ([usize; 3], i16)
-// gdbr-check:type = ([usize; 3], i16)
+// gdb-check:type = ([usize; 3], i16)
 
 // gdb-command:whatis slice1
-// gdbg-check:type = struct &[usize]
-// gdbr-check:type = &[usize]
+// gdb-check:type = &[usize]
 
 // gdb-command:whatis slice2
-// gdbg-check:type = struct &[type_names::mod1::Enum2]
-// gdbr-check:type = &[type_names::mod1::Enum2]
+// gdb-check:type = &[type_names::mod1::Enum2]
 
 // TRAITS
 // gdb-command:whatis box_trait
-// gdbg-check:type = struct Box<Trait1>
-// gdbr-check:type = type_names::Box<Trait1>
+// gdb-check:type = alloc::boxed::Box<dyn type_names::Trait1, alloc::alloc::Global>
 
 // gdb-command:whatis ref_trait
-// gdbg-check:type = struct &Trait1
-// gdbr-check:type = type_names::&Trait1
+// gdb-check:type = &dyn type_names::Trait1
 
 // gdb-command:whatis mut_ref_trait
-// gdbg-check:type = struct &mut Trait1
-// gdbr-check:type = type_names::&mut Trait1
+// gdb-check:type = &mut dyn type_names::Trait1
 
 // gdb-command:whatis generic_box_trait
-// gdbg-check:type = struct Box<Trait2<i32, type_names::mod1::Struct2>>
-// gdbr-check:type = type_names::Box<Trait2<i32, type_names::mod1::Struct2>>
+// gdb-check:type = alloc::boxed::Box<dyn type_names::Trait2<i32, type_names::mod1::Struct2>, alloc::alloc::Global>
 
 // gdb-command:whatis generic_ref_trait
-// gdbg-check:type = struct &Trait2<type_names::Struct1, type_names::Struct1>
-// gdbr-check:type = type_names::&Trait2<type_names::Struct1, type_names::Struct1>
+// gdb-check:type = &dyn type_names::Trait2<type_names::Struct1, type_names::Struct1>
 
 // gdb-command:whatis generic_mut_ref_trait
-// gdbg-check:type = struct &mut Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize>>
-// gdbr-check:type = type_names::&mut Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize>>
+// gdb-check:type = &mut dyn type_names::Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize>>
+
+// gdb-command:whatis no_principal_trait
+// gdb-check:type = alloc::boxed::Box<dyn core::marker::Send + core::marker::Sync, alloc::alloc::Global>
 
 // BARE FUNCTIONS
 // gdb-command:whatis rust_fn
-// gdbg-check:type = struct (fn(core::option::Option<isize>, core::option::Option<&type_names::mod1::Struct2>), usize)
-// gdbr-check:type = (fn(core::option::Option<isize>, core::option::Option<&type_names::mod1::Struct2>), usize)
+// gdb-check:type = (fn(core::option::Option<isize>, core::option::Option<&type_names::mod1::Struct2>), usize)
 
 // gdb-command:whatis extern_c_fn
-// gdbg-check:type = struct (extern "C" fn(isize), usize)
-// gdbr-check:type = (extern "C" fn(isize), usize)
+// gdb-check:type = (extern "C" fn(isize), usize)
 
 // gdb-command:whatis unsafe_fn
-// gdbg-check:type = struct (unsafe fn(core::result::Result<char, f64>), usize)
-// gdbr-check:type = (unsafe fn(core::result::Result<char, f64>), usize)
-
-// gdb-command:whatis extern_stdcall_fn
-// gdbg-check:type = struct (extern "stdcall" fn(), usize)
-// gdbr-check:type = (extern "stdcall" fn(), usize)
+// gdb-check:type = (unsafe fn(core::result::Result<char, f64>), usize)
 
 // gdb-command:whatis rust_fn_with_return_value
-// gdbg-check:type = struct (fn(f64) -> usize, usize)
-// gdbr-check:type = (fn(f64) -> usize, usize)
+// gdb-check:type = (fn(f64) -> usize, usize)
 
 // gdb-command:whatis extern_c_fn_with_return_value
-// gdbg-check:type = struct (extern "C" fn() -> type_names::Struct1, usize)
-// gdbr-check:type = (extern "C" fn() -> type_names::Struct1, usize)
+// gdb-check:type = (extern "C" fn() -> type_names::Struct1, usize)
 
 // gdb-command:whatis unsafe_fn_with_return_value
-// gdbg-check:type = struct (unsafe fn(type_names::GenericStruct<u16, u8>) -> type_names::mod1::Struct2, usize)
-// gdbr-check:type = (unsafe fn(type_names::GenericStruct<u16, u8>) -> type_names::mod1::Struct2, usize)
-
-// gdb-command:whatis extern_stdcall_fn_with_return_value
-// gdbg-check:type = struct (extern "stdcall" fn(alloc::boxed::Box<isize>) -> usize, usize)
-// gdbr-check:type = (extern "stdcall" fn(alloc::boxed::Box<isize>) -> usize, usize)
+// gdb-check:type = (unsafe fn(type_names::GenericStruct<u16, u8>) -> type_names::mod1::Struct2, usize)
 
 // gdb-command:whatis generic_function_int
-// gdbg-check:type = struct (fn(isize) -> isize, usize)
-// gdbr-check:type = (fn(isize) -> isize, usize)
+// gdb-check:type = (fn(isize) -> isize, usize)
 
 // gdb-command:whatis generic_function_struct3
-// gdbg-check:type = struct (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize)
-// gdbr-check:type = (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize)
+// gdb-check:type = (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize)
 
 // gdb-command:whatis variadic_function
-// gdbg-check:type = struct (unsafe extern "C" fn(*const u8, ...) -> isize, usize)
-// gdbr-check:type = (unsafe extern "C" fn(*const u8, ...) -> isize, usize)
+// gdb-check:type = (unsafe extern "C" fn(*const u8, ...) -> isize, usize)
 
 // CLOSURES
 // gdb-command:whatis closure1
-// gdbg-check:type = struct (closure, usize)
-// gdbr-check:type = (closure, usize)
+// gdb-check:type = (type_names::main::{closure#0}, usize)
 
 // gdb-command:whatis closure2
-// gdbg-check:type = struct (closure, usize)
-// gdbr-check:type = (closure, usize)
+// gdb-check:type = (type_names::main::{closure#1}, usize)
+
+// FOREIGN TYPES
+// gdb-command:whatis foreign1
+// gdb-check:type = *mut ForeignType1
+
+// gdb-command:whatis foreign2
+// gdb-check:type = *mut ForeignType2
+
+// === CDB TESTS ==================================================================================
+
+// cdb-command: g
+
+// STRUCTS
+// 0-sized structs appear to be optimized away in some cases, so only check the structs that do
+// actually appear.
+// cdb-command:dv /t *_struct
+// cdb-check:struct type_names::GenericStruct<enum$<type_names::mod1::Enum2>, f64> mut_generic_struct = [...]
+
+// ENUMS
+// cdb-command:dv /t *_enum_*
+// cdb-check:union enum$<type_names::Enum1> simple_enum_1 = [...]
+// cdb-check:union enum$<type_names::Enum1> simple_enum_2 = [...]
+// cdb-check:type_names::mod1::Enum2 simple_enum_3 = [...]
+// cdb-check:type_names::mod1::mod2::Enum3 generic_enum_1 = [...]
+// cdb-check:type_names::mod1::mod2::Enum3 generic_enum_2 = [...]
+
+// TUPLES
+// cdb-command:dv /t tuple*
+// cdb-check:struct tuple$<u32,type_names::Struct1,enum$<type_names::mod1::mod2::Enum3<type_names::mod1::Struct2> > > tuple1 = [...]
+// cdb-check:struct tuple$<tuple$<type_names::Struct1,type_names::mod1::mod2::Struct3>,enum$<type_names::mod1::Enum2>,char> tuple2 = [...]
+
+// BOX
+// cdb-command:dv /t box*
+// cdb-check:struct tuple$<alloc::boxed::Box<f32, alloc::alloc::Global>,i32> box1 = [...]
+// cdb-check:struct tuple$<alloc::boxed::Box<enum$<type_names::mod1::mod2::Enum3<f32> >, alloc::alloc::Global>,i32> box2 = [...]
+
+// REFERENCES
+// cdb-command:dv /t *ref*
+// cdb-check:struct tuple$<ref$<type_names::Struct1>,i32> ref1 = [...]
+// cdb-check:struct tuple$<ref$<type_names::GenericStruct<char, type_names::Struct1> >,i32> ref2 = [...]
+// cdb-check:struct tuple$<ref_mut$<type_names::Struct1>,i32> mut_ref1 = [...]
+// cdb-check:struct tuple$<ref_mut$<type_names::GenericStruct<enum$<type_names::mod1::Enum2>, f64> >,i32> mut_ref2 = [...]
+
+// RAW POINTERS
+// cdb-command:dv /t *_ptr*
+// cdb-check:struct tuple$<ptr_mut$<type_names::Struct1>,isize> mut_ptr1 = [...]
+// cdb-check:struct tuple$<ptr_mut$<isize>,isize> mut_ptr2 = [...]
+// cdb-check:struct tuple$<ptr_mut$<enum$<type_names::mod1::mod2::Enum3<type_names::Struct1> > >,isize> mut_ptr3 = [...]
+// cdb-check:struct tuple$<ptr_const$<type_names::Struct1>,isize> const_ptr1 = [...]
+// cdb-check:struct tuple$<ptr_const$<isize>,isize> const_ptr2 = [...]
+// cdb-check:struct tuple$<ptr_const$<enum$<type_names::mod1::mod2::Enum3<type_names::Struct1> > >,isize> const_ptr3 = [...]
+
+// VECTORS
+// cdb-command:dv /t *vec*
+// cdb-check:struct tuple$<array$<type_names::Struct1,3>,i16> fixed_size_vec1 = [...]
+// cdb-check:struct tuple$<array$<usize,3>,i16> fixed_size_vec2 = [...]
+// cdb-check:struct alloc::vec::Vec<usize, alloc::alloc::Global> vec1 = [...]
+// cdb-check:struct alloc::vec::Vec<enum$<type_names::mod1::Enum2>, alloc::alloc::Global> vec2 = [...]
+// cdb-command:dv /t slice*
+// cdb-check:struct slice$<usize> slice1 = [...]
+// cdb-check:struct slice$<enum$<type_names::mod1::Enum2> > slice2 = [...]
+
+// TRAITS
+// cdb-command:dv /t *_trait
+// cdb-check:struct ref_mut$<dyn$<type_names::Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize> > > > generic_mut_ref_trait = [...]
+// cdb-check:struct ref$<dyn$<type_names::Trait2<type_names::Struct1, type_names::Struct1> > > generic_ref_trait = [...]
+// cdb-check:struct alloc::boxed::Box<dyn$<type_names::Trait2<i32, type_names::mod1::Struct2> >, alloc::alloc::Global> generic_box_trait = [...]
+// cdb-check:struct alloc::boxed::Box<dyn$<type_names::Trait1>, alloc::alloc::Global> box_trait = [...]
+// cdb-check:struct ref$<dyn$<type_names::Trait1> > ref_trait = [...]
+// cdb-check:struct ref_mut$<dyn$<type_names::Trait1> > mut_ref_trait = [...]
+// cdb-check:struct alloc::boxed::Box<dyn$<core::marker::Send, core::marker::Sync>, alloc::alloc::Global> no_principal_trait = [...]
+// cdb-check:struct ref$<dyn$<type_names::Trait3> > has_associated_type_trait = struct ref$<dyn$<type_names::Trait3> >
+
+// BARE FUNCTIONS
+// cdb-command:dv /t *_fn*
+// cdb-check:struct tuple$<type_names::mod1::Struct2 (*)(type_names::GenericStruct<u16, u8>),usize> unsafe_fn_with_return_value = [...]
+// cdb-check:struct tuple$<type_names::Struct1 (*)(),usize> extern_c_fn_with_return_value = [...]
+// cdb-check:struct tuple$<usize (*)(f64),usize> rust_fn_with_return_value = [...]
+// cdb-check:struct tuple$<void (*)(enum$<core::result::Result<char, f64> >),usize> unsafe_fn = [...]
+// cdb-check:struct tuple$<void (*)(isize),usize> extern_c_fn = [...]
+// cdb-check:struct tuple$<void (*)(enum$<core::option::Option<isize> >, enum$<core::option::Option<ref$<type_names::mod1::Struct2> >, 1, [...], Some>),usize> rust_fn = [...]
+// cdb-command:dv /t *_function*
+// cdb-check:struct tuple$<isize (*)(ptr_const$<u8>, ...),usize> variadic_function = [...]
+// cdb-check:struct tuple$<type_names::mod1::mod2::Struct3 (*)(type_names::mod1::mod2::Struct3),usize> generic_function_struct3 = [...]
+// cdb-check:struct tuple$<isize (*)(isize),usize> generic_function_int = [...]
+// cdb-command:dx Debugger.State.Scripts.@"type-names.cdb".Contents.getFunctionDetails("rust_fn")
+// cdb-check:Return Type: void
+// cdb-check:Parameter Types: enum$<core::option::Option<isize> >,enum$<core::option::Option<ref$<type_names::mod1::Struct2> >, 1, [...], Some>
+// cdb-command:dx Debugger.State.Scripts.@"type-names.cdb".Contents.getFunctionDetails("rust_fn_with_return_value")
+// cdb-check:Return Type: usize
+// cdb-check:Parameter Types: f64
+// cdb-command:dx Debugger.State.Scripts.@"type-names.cdb".Contents.getFunctionDetails("extern_c_fn_with_return_value")
+// cdb-check:Return Type: type_names::Struct1
+// cdb-check:Parameter Types:
+
+// CLOSURES
+// cdb-command:dv /t closure*
+// cdb-check:struct tuple$<type_names::main::closure$1,usize> closure2 = [...]
+// cdb-check:struct tuple$<type_names::main::closure$0,usize> closure1 = [...]
+
+// FOREIGN TYPES
+// cdb-command:dv /t foreign*
+// cdb-check:struct ForeignType2 * foreign2 = [...]
+// cdb-check:struct ForeignType1 * foreign1 = [...]
 
 #![feature(box_syntax)]
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
+#![feature(extern_types)]
 
 use self::Enum1::{Variant1, Variant2};
 use std::marker::PhantomData;
@@ -216,6 +276,8 @@ enum Enum1 {
     Variant2(isize),
 }
 
+extern { type ForeignType1; }
+
 mod mod1 {
     pub use self::Enum2::{Variant1, Variant2};
     pub struct Struct2;
@@ -234,6 +296,8 @@ pub enum Enum3<T> {
             Variant2(T),
         }
     }
+
+    extern { pub type ForeignType2; }
 }
 
 trait Trait1 {
@@ -242,14 +306,20 @@ fn dummy(&self) {}
 trait Trait2<T1, T2> {
     fn dummy(&self, _: T1, _: T2) {}
 }
+trait Trait3 {
+    type AssocType;
+    fn dummy(&self) {}
+}
 
 impl Trait1 for isize {}
 impl<T1, T2> Trait2<T1, T2> for isize {}
+impl Trait3 for isize {
+    type AssocType = isize;
+}
 
 fn rust_fn(_: Option<isize>, _: Option<&mod1::Struct2>) {}
 extern "C" fn extern_c_fn(_: isize) {}
 unsafe fn unsafe_fn(_: Result<char, f64>) {}
-extern "stdcall" fn extern_stdcall_fn() {}
 
 fn rust_fn_with_return_value(_: f64) -> usize {
     4
@@ -260,9 +330,6 @@ extern "C" fn extern_c_fn_with_return_value() -> Struct1 {
 unsafe fn unsafe_fn_with_return_value(_: GenericStruct<u16, u8>) -> mod1::Struct2 {
     mod1::Struct2
 }
-extern "stdcall" fn extern_stdcall_fn_with_return_value(_: Box<isize>) -> usize {
-    0
-}
 
 fn generic_function<T>(x: T) -> T {
     x
@@ -333,28 +400,28 @@ fn main() {
     let slice2 = &*vec2;
 
     // Trait Objects
-    let box_trait = (box 0_isize) as Box<Trait1>;
-    let ref_trait = &0_isize as &Trait1;
+    let box_trait = (box 0_isize) as Box<dyn Trait1>;
+    let ref_trait = &0_isize as &dyn Trait1;
     let mut mut_int1 = 0_isize;
-    let mut_ref_trait = (&mut mut_int1) as &mut Trait1;
+    let mut_ref_trait = (&mut mut_int1) as &mut dyn Trait1;
+    let no_principal_trait = (box 0_isize) as Box<dyn Send + Sync>;
+    let has_associated_type_trait = &0_isize as &dyn Trait3<AssocType = isize>;
 
-    let generic_box_trait = (box 0_isize) as Box<Trait2<i32, mod1::Struct2>>;
-    let generic_ref_trait = (&0_isize) as &Trait2<Struct1, Struct1>;
+    let generic_box_trait = (box 0_isize) as Box<dyn Trait2<i32, mod1::Struct2>>;
+    let generic_ref_trait = (&0_isize) as &dyn Trait2<Struct1, Struct1>;
 
     let mut generic_mut_ref_trait_impl = 0_isize;
     let generic_mut_ref_trait = (&mut generic_mut_ref_trait_impl)
-        as &mut Trait2<mod1::mod2::Struct3, GenericStruct<usize, isize>>;
+        as &mut dyn Trait2<mod1::mod2::Struct3, GenericStruct<usize, isize>>;
 
     // Bare Functions
     let rust_fn = (rust_fn, 0_usize);
     let extern_c_fn = (extern_c_fn, 0_usize);
     let unsafe_fn = (unsafe_fn, 0_usize);
-    let extern_stdcall_fn = (extern_stdcall_fn, 0_usize);
 
     let rust_fn_with_return_value = (rust_fn_with_return_value, 0_usize);
     let extern_c_fn_with_return_value = (extern_c_fn_with_return_value, 0_usize);
     let unsafe_fn_with_return_value = (unsafe_fn_with_return_value, 0_usize);
-    let extern_stdcall_fn_with_return_value = (extern_stdcall_fn_with_return_value, 0_usize);
 
     let generic_function_int = (generic_function::<isize>, 0_usize);
     let generic_function_struct3 = (generic_function::<mod1::mod2::Struct3>, 0_usize);
@@ -370,6 +437,10 @@ fn main() {
     let closure1 = (|x: isize| {}, 0_usize);
     let closure2 = (|x: i8, y: f32| (x as f32) + y, 0_usize);
 
+    // Foreign Types
+    let foreign1 = unsafe{ 0 as *const ForeignType1 };
+    let foreign2 = unsafe{ 0 as *const mod1::ForeignType2 };
+
     zzz(); // #break
 }
 
index 695cdc4f41fa30f53361bebd46fc9bc46dd95a8b..a2778fc6090d2bf77716bc59817bd59ed43f2848 100644 (file)
 // cdb-command: dx closure_local
 // cdb-check:closure_local    : 8 [Type: [...]]
 // cdb-command: dx nested_closure
-// cdb-check:nested_closure   [Type: var_captured_in_nested_closure::main::{{closure}}::closure-0]
+// cdb-check:nested_closure   [Type: var_captured_in_nested_closure::main::closure$0::closure$0]
 
 // cdb-command: g
 
index 6a1faee1d8e097bd01d80cbc03a0c7203d6bf635..49731b2d7dc04f858b8393b96d70c076a4fd57b9 100644 (file)
@@ -778,6 +778,14 @@ fn run_debuginfo_cdb_test_no_opt(&self) {
         script_str.push_str("version\n"); // List CDB (and more) version info in test output
         script_str.push_str(".nvlist\n"); // List loaded `*.natvis` files, bulk of custom MSVC debug
 
+        // If a .js file exists next to the source file being tested, then this is a JavaScript
+        // debugging extension that needs to be loaded.
+        let mut js_extension = self.testpaths.file.clone();
+        js_extension.set_extension("cdb.js");
+        if js_extension.exists() {
+            script_str.push_str(&format!(".scriptload \"{}\"\n", js_extension.to_string_lossy()));
+        }
+
         // Set breakpoints on every line that contains the string "#break"
         let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy();
         for line in &breakpoint_lines {
@@ -2329,13 +2337,17 @@ fn verify_with_filecheck(&self, output: &Path) -> ProcRes {
         // useful flag.
         //
         // For now, though…
-        if let Some(rev) = self.revision {
-            let prefixes = format!("CHECK,{}", rev);
-            if self.config.llvm_version.unwrap_or(0) >= 130000 {
-                filecheck.args(&["--allow-unused-prefixes", "--check-prefixes", &prefixes]);
-            } else {
-                filecheck.args(&["--check-prefixes", &prefixes]);
-            }
+        let prefix_for_target =
+            if self.config.target.contains("msvc") { "MSVC" } else { "NONMSVC" };
+        let prefixes = if let Some(rev) = self.revision {
+            format!("CHECK,{},{}", prefix_for_target, rev)
+        } else {
+            format!("CHECK,{}", prefix_for_target)
+        };
+        if self.config.llvm_version.unwrap_or(0) >= 130000 {
+            filecheck.args(&["--allow-unused-prefixes", "--check-prefixes", &prefixes]);
+        } else {
+            filecheck.args(&["--check-prefixes", &prefixes]);
         }
         self.compose_and_run(filecheck, "", None, None)
     }
index 3d5f39e8c90493eca270481998ddd6b2e051e1fe..15ed2f7a0a9756f8816578fb1363e3290f1a861c 100644 (file)
@@ -52,6 +52,7 @@
     "// error-pattern",
     "// gdb",
     "// lldb",
+    "// cdb",
     "// normalize-stderr-test",
 ];