]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #76658 - Aaron1011:fix/encode-dummy-loc-span, r=lcnr
authorbors <bors@rust-lang.org>
Sun, 13 Sep 2020 09:18:14 +0000 (09:18 +0000)
committerbors <bors@rust-lang.org>
Sun, 13 Sep 2020 09:18:14 +0000 (09:18 +0000)
Properly encode spans with a dummy location and non-root `SyntaxContext`

Previously, we would throw away the `SyntaxContext` of any span with a
dummy location during metadata encoding. This commit makes metadata Span
encoding consistent with incr-cache Span encoding - an 'invalid span'
tag is only used when it doesn't lose any information.

13 files changed:
compiler/rustc/Cargo.toml
compiler/rustc_driver/Cargo.toml
compiler/rustc_parse/src/lib.rs
config.toml.example
src/bootstrap/bootstrap.py
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/dist.rs
src/bootstrap/lib.rs
src/test/ui/proc-macro/issue-76182-leading-vert-pat.rs [new file with mode: 0644]
src/test/ui/proc-macro/issue-76182-leading-vert-pat.stdout [new file with mode: 0644]
src/test/ui/proc-macro/trailing-plus.rs [new file with mode: 0644]
src/test/ui/proc-macro/trailing-plus.stdout [new file with mode: 0644]

index cf011e63e02fde772502827fc03e12b24b3e49a4..6e6c0c71a1f3b61c438515ab51e93137f6739289 100644 (file)
@@ -19,3 +19,4 @@ features = ['unprefixed_malloc_on_supported_platforms']
 [features]
 jemalloc = ['jemalloc-sys']
 llvm = ['rustc_driver/llvm']
+max_level_info = ['rustc_driver/max_level_info']
index 0d9dcb262b26986b41de0f8af2a2a6c0cdc07795..adfce1008e1ed01ea37b37a526d57fd71ef6615e 100644 (file)
@@ -9,7 +9,7 @@ crate-type = ["dylib"]
 
 [dependencies]
 libc = "0.2"
-tracing = { version = "0.1.18", features = ["release_max_level_info"]  }
+tracing = { version = "0.1.18" }
 tracing-subscriber = { version = "0.2.10", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
 rustc_middle = { path = "../rustc_middle" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
@@ -38,3 +38,4 @@ winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"]
 
 [features]
 llvm = ['rustc_interface/llvm']
+max_level_info = ['tracing/max_level_info']
index dedb9850b5a19f75a160250f5ea4615585511abe..0becdf24c532be6ab438641ba27847f884004688 100644 (file)
@@ -364,6 +364,12 @@ fn semantic_tree(tree: &TokenTree) -> bool {
                 | token::CloseDelim(DelimToken::NoDelim)
                 // The pretty printer collapses many semicolons into one.
                 | token::Semi
+                // We don't preserve leading `|` tokens in patterns, so
+                // we ignore them entirely
+                | token::BinOp(token::BinOpToken::Or)
+                // We don't preserve trailing '+' tokens in trait bounds,
+                // so we ignore them entirely
+                | token::BinOp(token::BinOpToken::Plus)
                 // The pretty printer can turn `$crate` into `::crate_name`
                 | token::ModSep = token.kind {
                 return false;
index 2d5b3136450b923130238a8c1ee2380d7f989124..39c94d41e3a7f5f65c82a3e74c1c2d56425adc0b 100644 (file)
 # =============================================================================
 [llvm]
 
+# Whether to use Rust CI built LLVM instead of locally building it.
+#
+# Unless you're developing for a target where Rust CI doesn't build a compiler
+# toolchain or changing LLVM locally, you probably want to set this to true.
+#
+# It's currently false by default due to being newly added; please file bugs if
+# enabling this did not work for you on Linux (macOS and Windows support is
+# coming soon).
+#
+# We also currently only support this when building LLVM for the build triple.
+#
+# Note that many of the LLVM options are not currently supported for
+# downloading. Currently only the "assertions" option can be toggled.
+#download-ci-llvm = false
+
 # Indicates whether LLVM rebuild should be skipped when running bootstrap. If
 # this is `false` then the compiler's LLVM will be rebuilt whenever the built
 # version doesn't have the correct hash. If it is `true` then LLVM will never
 # binary, otherwise they are omitted.
 #
 # Defaults to rust.debug value
-#debug-assertions = false
+#debug-assertions = debug
 
 # Whether or not debug assertions are enabled for the standard library.
 # Overrides the `debug-assertions` option, if defined.
 #
 # Defaults to rust.debug-assertions value
-#debug-assertions-std = false
+#debug-assertions-std = debug-assertions
+
+# Whether or not to leave debug! and trace! calls in the rust binary.
+# Overrides the `debug-assertions` option, if defined.
+# 
+# Defaults to rust.debug-assertions value
+#debug-logging = debug-assertions
 
 # Debuginfo level for most of Rust code, corresponds to the `-C debuginfo=N` option of `rustc`.
 # `0` - no debug info
index 955c72856dcfab0feba764bbce73b7b47d1ed9f4..44a17f75451a92d520f2d822642769117647dc1c 100644 (file)
@@ -14,8 +14,17 @@ import tempfile
 
 from time import time
 
-
-def get(url, path, verbose=False):
+def support_xz():
+    try:
+        with tempfile.NamedTemporaryFile(delete=False) as temp_file:
+            temp_path = temp_file.name
+        with tarfile.open(temp_path, "w:xz"):
+            pass
+        return True
+    except tarfile.CompressionError:
+        return False
+
+def get(url, path, verbose=False, do_verify=True):
     suffix = '.sha256'
     sha_url = url + suffix
     with tempfile.NamedTemporaryFile(delete=False) as temp_file:
@@ -24,19 +33,20 @@ def get(url, path, verbose=False):
         sha_path = sha_file.name
 
     try:
-        download(sha_path, sha_url, False, verbose)
-        if os.path.exists(path):
-            if verify(path, sha_path, False):
-                if verbose:
-                    print("using already-download file", path)
-                return
-            else:
-                if verbose:
-                    print("ignoring already-download file",
-                          path, "due to failed verification")
-                os.unlink(path)
+        if do_verify:
+            download(sha_path, sha_url, False, verbose)
+            if os.path.exists(path):
+                if verify(path, sha_path, False):
+                    if verbose:
+                        print("using already-download file", path)
+                    return
+                else:
+                    if verbose:
+                        print("ignoring already-download file",
+                            path, "due to failed verification")
+                    os.unlink(path)
         download(temp_path, url, True, verbose)
-        if not verify(temp_path, sha_path, verbose):
+        if do_verify and not verify(temp_path, sha_path, verbose):
             raise RuntimeError("failed verification")
         if verbose:
             print("moving {} to {}".format(temp_path, path))
@@ -365,16 +375,6 @@ class RustBuild(object):
         cargo_channel = self.cargo_channel
         rustfmt_channel = self.rustfmt_channel
 
-        def support_xz():
-            try:
-                with tempfile.NamedTemporaryFile(delete=False) as temp_file:
-                    temp_path = temp_file.name
-                with tarfile.open(temp_path, "w:xz"):
-                    pass
-                return True
-            except tarfile.CompressionError:
-                return False
-
         if self.rustc().startswith(self.bin_root()) and \
                 (not os.path.exists(self.rustc()) or
                  self.program_out_of_date(self.rustc_stamp())):
@@ -423,6 +423,19 @@ class RustBuild(object):
                 with output(self.rustfmt_stamp()) as rustfmt_stamp:
                     rustfmt_stamp.write(self.date + self.rustfmt_channel)
 
+        if self.downloading_llvm():
+            llvm_sha = subprocess.check_output(["git", "log", "--author=bors",
+                "--format=%H", "-n1"]).decode(sys.getdefaultencoding()).strip()
+            llvm_assertions = self.get_toml('assertions', 'llvm') == 'true'
+            if self.program_out_of_date(self.llvm_stamp(), llvm_sha + str(llvm_assertions)):
+                self._download_ci_llvm(llvm_sha, llvm_assertions)
+                with output(self.llvm_stamp()) as llvm_stamp:
+                    llvm_stamp.write(self.date + llvm_sha + str(llvm_assertions))
+
+    def downloading_llvm(self):
+        opt = self.get_toml('download-ci-llvm', 'llvm')
+        return opt == "true"
+
     def _download_stage0_helper(self, filename, pattern, tarball_suffix, date=None):
         if date is None:
             date = self.date
@@ -437,6 +450,25 @@ class RustBuild(object):
             get("{}/{}".format(url, filename), tarball, verbose=self.verbose)
         unpack(tarball, tarball_suffix, self.bin_root(), match=pattern, verbose=self.verbose)
 
+    def _download_ci_llvm(self, llvm_sha, llvm_assertions):
+        cache_prefix = "llvm-{}-{}".format(llvm_sha, llvm_assertions)
+        cache_dst = os.path.join(self.build_dir, "cache")
+        rustc_cache = os.path.join(cache_dst, cache_prefix)
+        if not os.path.exists(rustc_cache):
+            os.makedirs(rustc_cache)
+
+        url = "https://ci-artifacts.rust-lang.org/rustc-builds/{}".format(llvm_sha)
+        if llvm_assertions:
+            url = url.replace('rustc-builds', 'rustc-builds-alt')
+        tarball_suffix = '.tar.xz' if support_xz() else '.tar.gz'
+        filename = "rust-dev-nightly-" + self.build + tarball_suffix
+        tarball = os.path.join(rustc_cache, filename)
+        if not os.path.exists(tarball):
+            get("{}/{}".format(url, filename), tarball, verbose=self.verbose, do_verify=False)
+        unpack(tarball, tarball_suffix, self.llvm_root(),
+                match="rust-dev",
+                verbose=self.verbose)
+
     def fix_bin_or_dylib(self, fname):
         """Modifies the interpreter section of 'fname' to fix the dynamic linker,
         or the RPATH section, to fix the dynamic library search path
@@ -558,6 +590,17 @@ class RustBuild(object):
         """
         return os.path.join(self.bin_root(), '.rustfmt-stamp')
 
+    def llvm_stamp(self):
+        """Return the path for .rustfmt-stamp
+
+        >>> rb = RustBuild()
+        >>> rb.build_dir = "build"
+        >>> rb.llvm_stamp() == os.path.join("build", "ci-llvm", ".llvm-stamp")
+        True
+        """
+        return os.path.join(self.llvm_root(), '.llvm-stamp')
+
+
     def program_out_of_date(self, stamp_path, extra=""):
         """Check if the given program stamp is out of date"""
         if not os.path.exists(stamp_path) or self.clean:
@@ -581,6 +624,22 @@ class RustBuild(object):
         """
         return os.path.join(self.build_dir, self.build, "stage0")
 
+    def llvm_root(self):
+        """Return the CI LLVM root directory
+
+        >>> rb = RustBuild()
+        >>> rb.build_dir = "build"
+        >>> rb.llvm_root() == os.path.join("build", "ci-llvm")
+        True
+
+        When the 'build' property is given should be a nested directory:
+
+        >>> rb.build = "devel"
+        >>> rb.llvm_root() == os.path.join("build", "devel", "ci-llvm")
+        True
+        """
+        return os.path.join(self.build_dir, self.build, "ci-llvm")
+
     def get_toml(self, key, section=None):
         """Returns the value of the given key in config.toml, otherwise returns None
 
index e0dddda83b98feefb9972f748f8cd314b59c5c29..08907edef1d1e52b5984070e2a60775ff8bf9d02 100644 (file)
@@ -593,7 +593,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
             let file = compiler_file(builder, builder.cxx(target).unwrap(), target, "libstdc++.a");
             cargo.env("LLVM_STATIC_STDCPP", file);
         }
-        if builder.config.llvm_link_shared || builder.config.llvm_thin_lto {
+        if builder.config.llvm_link_shared {
             cargo.env("LLVM_LINK_SHARED", "1");
         }
         if builder.config.llvm_use_libcxx {
index 5a79d3db5c90536b73f1ed9f620bfd8ba0edde62..7c8c729b5bfab56021247432c4dc0a1efd6280e3 100644 (file)
 use crate::cache::{Interned, INTERNER};
 use crate::flags::Flags;
 pub use crate::flags::Subcommand;
+use crate::util::exe;
 use build_helper::t;
 use serde::Deserialize;
 
+macro_rules! check_ci_llvm {
+    ($name:expr) => {
+        assert!(
+            $name.is_none(),
+            "setting {} is incompatible with download-ci-llvm.",
+            stringify!($name)
+        );
+    };
+}
+
 /// Global configuration for the entire build and/or bootstrap.
 ///
 /// This structure is derived from a combination of both `config.toml` and
@@ -84,6 +95,7 @@ pub struct Config {
     pub llvm_version_suffix: Option<String>,
     pub llvm_use_linker: Option<String>,
     pub llvm_allow_old_toolchain: Option<bool>,
+    pub llvm_from_ci: bool,
 
     pub use_lld: bool,
     pub lld_enabled: bool,
@@ -100,6 +112,7 @@ pub struct Config {
     pub rust_codegen_units_std: Option<u32>,
     pub rust_debug_assertions: bool,
     pub rust_debug_assertions_std: bool,
+    pub rust_debug_logging: bool,
     pub rust_debuginfo_level_rustc: u32,
     pub rust_debuginfo_level_std: u32,
     pub rust_debuginfo_level_tools: u32,
@@ -344,6 +357,7 @@ struct Llvm {
     use_libcxx: Option<bool>,
     use_linker: Option<String>,
     allow_old_toolchain: Option<bool>,
+    download_ci_llvm: Option<bool>,
 }
 
 #[derive(Deserialize, Default, Clone)]
@@ -379,6 +393,7 @@ struct Rust {
     codegen_units_std: Option<u32>,
     debug_assertions: Option<bool>,
     debug_assertions_std: Option<bool>,
+    debug_logging: Option<bool>,
     debuginfo_level: Option<u32>,
     debuginfo_level_rustc: Option<u32>,
     debuginfo_level_std: Option<u32>,
@@ -587,6 +602,7 @@ pub fn parse(args: &[String]) -> Config {
         let mut debug = None;
         let mut debug_assertions = None;
         let mut debug_assertions_std = None;
+        let mut debug_logging = None;
         let mut debuginfo_level = None;
         let mut debuginfo_level_rustc = None;
         let mut debuginfo_level_std = None;
@@ -624,12 +640,50 @@ pub fn parse(args: &[String]) -> Config {
             set(&mut config.llvm_use_libcxx, llvm.use_libcxx);
             config.llvm_use_linker = llvm.use_linker.clone();
             config.llvm_allow_old_toolchain = llvm.allow_old_toolchain;
+            config.llvm_from_ci = llvm.download_ci_llvm.unwrap_or(false);
+
+            if config.llvm_from_ci {
+                // None of the LLVM options, except assertions, are supported
+                // when using downloaded LLVM. We could just ignore these but
+                // that's potentially confusing, so force them to not be
+                // explicitly set. The defaults and CI defaults don't
+                // necessarily match but forcing people to match (somewhat
+                // arbitrary) CI configuration locally seems bad/hard.
+                check_ci_llvm!(llvm.optimize);
+                check_ci_llvm!(llvm.thin_lto);
+                check_ci_llvm!(llvm.release_debuginfo);
+                check_ci_llvm!(llvm.link_shared);
+                check_ci_llvm!(llvm.static_libstdcpp);
+                check_ci_llvm!(llvm.targets);
+                check_ci_llvm!(llvm.experimental_targets);
+                check_ci_llvm!(llvm.link_jobs);
+                check_ci_llvm!(llvm.link_shared);
+                check_ci_llvm!(llvm.clang_cl);
+                check_ci_llvm!(llvm.version_suffix);
+                check_ci_llvm!(llvm.cflags);
+                check_ci_llvm!(llvm.cxxflags);
+                check_ci_llvm!(llvm.ldflags);
+                check_ci_llvm!(llvm.use_libcxx);
+                check_ci_llvm!(llvm.use_linker);
+                check_ci_llvm!(llvm.allow_old_toolchain);
+
+                // CI-built LLVM is shared
+                config.llvm_link_shared = true;
+            }
+
+            if config.llvm_thin_lto {
+                // If we're building with ThinLTO on, we want to link to LLVM
+                // shared, to avoid re-doing ThinLTO (which happens in the link
+                // step) with each stage.
+                config.llvm_link_shared = true;
+            }
         }
 
         if let Some(ref rust) = toml.rust {
             debug = rust.debug;
             debug_assertions = rust.debug_assertions;
             debug_assertions_std = rust.debug_assertions_std;
+            debug_logging = rust.debug_logging;
             debuginfo_level = rust.debuginfo_level;
             debuginfo_level_rustc = rust.debuginfo_level_rustc;
             debuginfo_level_std = rust.debuginfo_level_std;
@@ -706,6 +760,20 @@ pub fn parse(args: &[String]) -> Config {
             }
         }
 
+        if config.llvm_from_ci {
+            let triple = &config.build.triple;
+            let mut build_target = config
+                .target_config
+                .entry(config.build)
+                .or_insert_with(|| Target::from_triple(&triple));
+
+            check_ci_llvm!(build_target.llvm_config);
+            check_ci_llvm!(build_target.llvm_filecheck);
+            let ci_llvm_bin = config.out.join(&*config.build.triple).join("ci-llvm/bin");
+            build_target.llvm_config = Some(ci_llvm_bin.join(exe("llvm-config", config.build)));
+            build_target.llvm_filecheck = Some(ci_llvm_bin.join(exe("FileCheck", config.build)));
+        }
+
         if let Some(ref t) = toml.dist {
             config.dist_sign_folder = t.sign_folder.clone().map(PathBuf::from);
             config.dist_gpg_password_file = t.gpg_password_file.clone().map(PathBuf::from);
@@ -733,6 +801,8 @@ pub fn parse(args: &[String]) -> Config {
         config.rust_debug_assertions_std =
             debug_assertions_std.unwrap_or(config.rust_debug_assertions);
 
+        config.rust_debug_logging = debug_logging.unwrap_or(config.rust_debug_assertions);
+
         let with_defaults = |debuginfo_level_specific: Option<u32>| {
             debuginfo_level_specific.or(debuginfo_level).unwrap_or(if debug == Some(true) {
                 1
index e22cdb13928364e7d6ee5882a5a6e6b0bd4b706b..cf73e570fa56f7e432a2f78b13bc80b3e6390600 100644 (file)
@@ -2382,26 +2382,32 @@ fn run(self, builder: &Builder<'_>) {
 /// Note: This function does not yet support Windows, but we also don't support
 ///       linking LLVM tools dynamically on Windows yet.
 fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir: &Path) {
-    let src_libdir = builder.llvm_out(target).join("lib");
+    if !builder.config.llvm_link_shared {
+        // We do not need to copy LLVM files into the sysroot if it is not
+        // dynamically linked; it is already included into librustc_llvm
+        // statically.
+        return;
+    }
 
+    // On macOS for some reason the llvm-config binary behaves differently and
+    // and fails on missing .a files if run without --link-shared. If run with
+    // that option, it still fails, but because we only ship a libLLVM.dylib
+    // rather than libLLVM-11-rust-....dylib file.
+    //
+    // For now just don't use llvm-config here on macOS; that will fail to
+    // support CI-built LLVM, but until we work out the different behavior that
+    // is fine as it is off by default.
     if target.contains("apple-darwin") {
+        let src_libdir = builder.llvm_out(target).join("lib");
         let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
         if llvm_dylib_path.exists() {
             builder.install(&llvm_dylib_path, dst_libdir, 0o644);
         }
-        return;
-    }
-
-    // Usually libLLVM.so is a symlink to something like libLLVM-6.0.so.
-    // Since tools link to the latter rather than the former, we have to
-    // follow the symlink to find out what to distribute.
-    let llvm_dylib_path = src_libdir.join("libLLVM.so");
-    if llvm_dylib_path.exists() {
-        let llvm_dylib_path = llvm_dylib_path.canonicalize().unwrap_or_else(|e| {
-            panic!("dist: Error calling canonicalize path `{}`: {}", llvm_dylib_path.display(), e);
-        });
-
-        builder.install(&llvm_dylib_path, dst_libdir, 0o644);
+    } else if let Ok(llvm_config) = crate::native::prebuilt_llvm_config(builder, target) {
+        let files = output(Command::new(llvm_config).arg("--libfiles"));
+        for file in files.lines() {
+            builder.install(Path::new(file), dst_libdir, 0o644);
+        }
     }
 }
 
index f0224d88226fb45299f2e336a0709273f509ec55..91b85f5af1d4bd39e64a4b3cb2bb2355cc236bb5 100644 (file)
@@ -541,6 +541,16 @@ fn rustc_features(&self) -> String {
         if self.config.llvm_enabled() {
             features.push_str(" llvm");
         }
+
+        // If debug logging is on, then we want the default for tracing:
+        // https://github.com/tokio-rs/tracing/blob/3dd5c03d907afdf2c39444a29931833335171554/tracing/src/level_filters.rs#L26
+        // which is everything (including debug/trace/etc.)
+        // if its unset, if debug_assertions is on, then debug_logging will also be on
+        // as well as tracing *ignoring* this feature when debug_assertions is on
+        if !self.config.rust_debug_logging {
+            features.push_str(" max_level_info");
+        }
+
         features
     }
 
@@ -611,6 +621,10 @@ fn md_doc_out(&self, target: TargetSelection) -> Interned<PathBuf> {
     ///
     /// If no custom `llvm-config` was specified then Rust's llvm will be used.
     fn is_rust_llvm(&self, target: TargetSelection) -> bool {
+        if self.config.llvm_from_ci && target == self.config.build {
+            return true;
+        }
+
         match self.config.target_config.get(&target) {
             Some(ref c) => c.llvm_config.is_none(),
             None => true,
diff --git a/src/test/ui/proc-macro/issue-76182-leading-vert-pat.rs b/src/test/ui/proc-macro/issue-76182-leading-vert-pat.rs
new file mode 100644 (file)
index 0000000..7d31de1
--- /dev/null
@@ -0,0 +1,16 @@
+// check-pass
+// aux-build:test-macros.rs
+// compile-flags: -Z span-debug
+//
+// Regression test for issue #76182
+// Tests that we properly handle patterns with a leading vert
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+extern crate test_macros;
+
+#[test_macros::print_attr]
+fn main() {
+    match () { | () => () }
+}
diff --git a/src/test/ui/proc-macro/issue-76182-leading-vert-pat.stdout b/src/test/ui/proc-macro/issue-76182-leading-vert-pat.stdout
new file mode 100644 (file)
index 0000000..5493f9c
--- /dev/null
@@ -0,0 +1,62 @@
+PRINT-ATTR INPUT (DISPLAY): fn main() { match() { | () => () } }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "fn",
+        span: $DIR/issue-76182-leading-vert-pat.rs:14:1: 14:3 (#0),
+    },
+    Ident {
+        ident: "main",
+        span: $DIR/issue-76182-leading-vert-pat.rs:14:4: 14:8 (#0),
+    },
+    Group {
+        delimiter: Parenthesis,
+        stream: TokenStream [],
+        span: $DIR/issue-76182-leading-vert-pat.rs:14:8: 14:10 (#0),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [
+            Ident {
+                ident: "match",
+                span: $DIR/issue-76182-leading-vert-pat.rs:15:5: 15:10 (#0),
+            },
+            Group {
+                delimiter: Parenthesis,
+                stream: TokenStream [],
+                span: $DIR/issue-76182-leading-vert-pat.rs:15:11: 15:13 (#0),
+            },
+            Group {
+                delimiter: Brace,
+                stream: TokenStream [
+                    Punct {
+                        ch: '|',
+                        spacing: Alone,
+                        span: $DIR/issue-76182-leading-vert-pat.rs:15:16: 15:17 (#0),
+                    },
+                    Group {
+                        delimiter: Parenthesis,
+                        stream: TokenStream [],
+                        span: $DIR/issue-76182-leading-vert-pat.rs:15:18: 15:20 (#0),
+                    },
+                    Punct {
+                        ch: '=',
+                        spacing: Joint,
+                        span: $DIR/issue-76182-leading-vert-pat.rs:15:21: 15:23 (#0),
+                    },
+                    Punct {
+                        ch: '>',
+                        spacing: Alone,
+                        span: $DIR/issue-76182-leading-vert-pat.rs:15:21: 15:23 (#0),
+                    },
+                    Group {
+                        delimiter: Parenthesis,
+                        stream: TokenStream [],
+                        span: $DIR/issue-76182-leading-vert-pat.rs:15:24: 15:26 (#0),
+                    },
+                ],
+                span: $DIR/issue-76182-leading-vert-pat.rs:15:14: 15:28 (#0),
+            },
+        ],
+        span: $DIR/issue-76182-leading-vert-pat.rs:14:11: 16:2 (#0),
+    },
+]
diff --git a/src/test/ui/proc-macro/trailing-plus.rs b/src/test/ui/proc-macro/trailing-plus.rs
new file mode 100644 (file)
index 0000000..4f61de4
--- /dev/null
@@ -0,0 +1,14 @@
+// check-pass
+// aux-build:test-macros.rs
+// compile-flags: -Z span-debug
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+extern crate test_macros;
+
+#[test_macros::print_attr]
+fn foo<T>() where T: Copy + {
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/trailing-plus.stdout b/src/test/ui/proc-macro/trailing-plus.stdout
new file mode 100644 (file)
index 0000000..d60f400
--- /dev/null
@@ -0,0 +1,57 @@
+PRINT-ATTR INPUT (DISPLAY): fn foo < T > () where T : Copy + { }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "fn",
+        span: $DIR/trailing-plus.rs:11:1: 11:3 (#0),
+    },
+    Ident {
+        ident: "foo",
+        span: $DIR/trailing-plus.rs:11:4: 11:7 (#0),
+    },
+    Punct {
+        ch: '<',
+        spacing: Alone,
+        span: $DIR/trailing-plus.rs:11:7: 11:8 (#0),
+    },
+    Ident {
+        ident: "T",
+        span: $DIR/trailing-plus.rs:11:8: 11:9 (#0),
+    },
+    Punct {
+        ch: '>',
+        spacing: Alone,
+        span: $DIR/trailing-plus.rs:11:9: 11:10 (#0),
+    },
+    Group {
+        delimiter: Parenthesis,
+        stream: TokenStream [],
+        span: $DIR/trailing-plus.rs:11:10: 11:12 (#0),
+    },
+    Ident {
+        ident: "where",
+        span: $DIR/trailing-plus.rs:11:13: 11:18 (#0),
+    },
+    Ident {
+        ident: "T",
+        span: $DIR/trailing-plus.rs:11:19: 11:20 (#0),
+    },
+    Punct {
+        ch: ':',
+        spacing: Alone,
+        span: $DIR/trailing-plus.rs:11:20: 11:21 (#0),
+    },
+    Ident {
+        ident: "Copy",
+        span: $DIR/trailing-plus.rs:11:22: 11:26 (#0),
+    },
+    Punct {
+        ch: '+',
+        spacing: Alone,
+        span: $DIR/trailing-plus.rs:11:27: 11:28 (#0),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [],
+        span: $DIR/trailing-plus.rs:11:29: 12:2 (#0),
+    },
+]