From e99f7ed0713087626c16de542ac24201ac4c356c Mon Sep 17 00:00:00 2001 From: Dan McGregor Date: Tue, 6 Jun 2023 10:15:11 -0600 Subject: Fix documentation build on FreeBSD After the socket ancillary data implementation was introduced, the build was broken on FreeBSD, add the same workaround as for the existing implementations. --- library/std/src/os/unix/net/ancillary.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs index 7565fbc0d09..6bd87d61ae1 100644 --- a/library/std/src/os/unix/net/ancillary.rs +++ b/library/std/src/os/unix/net/ancillary.rs @@ -11,7 +11,13 @@ use crate::slice::from_raw_parts; use crate::sys::net::Socket; // FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here? -#[cfg(all(doc, not(target_os = "linux"), not(target_os = "android"), not(target_os = "netbsd")))] +#[cfg(all( + doc, + not(target_os = "linux"), + not(target_os = "android"), + not(target_os = "netbsd"), + not(target_os = "freebsd") +))] #[allow(non_camel_case_types)] mod libc { pub use libc::c_int; -- cgit 1.4.1-3-g733a5 From 88b08582b2781339f30deedffcfc84949d4190a0 Mon Sep 17 00:00:00 2001 From: zica <9918800@gmail.com> Date: Thu, 15 Jun 2023 11:14:24 +0800 Subject: Correct types in method descriptions of `NonZero*` types --- library/core/src/num/nonzero.rs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 7f06e170ad0..5939dedbd1d 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -348,7 +348,7 @@ macro_rules! nonzero_unsigned_operations { } /// Adds an unsigned integer to a non-zero value. - #[doc = concat!("Return [`", stringify!($Int), "::MAX`] on overflow.")] + #[doc = concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")] /// /// # Examples /// @@ -579,7 +579,7 @@ macro_rules! nonzero_signed_operations { /// Checked absolute value. /// Checks for overflow and returns [`None`] if - #[doc = concat!("`self == ", stringify!($Int), "::MIN`.")] + #[doc = concat!("`self == ", stringify!($Ty), "::MIN`.")] /// The result cannot be zero. /// /// # Example @@ -800,7 +800,8 @@ macro_rules! nonzero_signed_operations { self.get().is_negative() } - /// Checked negation. Computes `-self`, returning `None` if `self == i32::MIN`. + /// Checked negation. Computes `-self`, + #[doc = concat!("returning `None` if `self == ", stringify!($Ty), "::MIN`.")] /// /// # Example /// @@ -859,8 +860,10 @@ macro_rules! nonzero_signed_operations { ((unsafe { $Ty::new_unchecked(result) }), overflow) } - /// Saturating negation. Computes `-self`, returning `MAX` if - /// `self == i32::MIN` instead of overflowing. + /// Saturating negation. Computes `-self`, + #[doc = concat!("returning [`", stringify!($Ty), "::MAX`]")] + #[doc = concat!("if `self == ", stringify!($Ty), "::MIN`")] + /// instead of overflowing. /// /// # Example /// @@ -993,7 +996,7 @@ macro_rules! nonzero_unsigned_signed_operations { } /// Multiplies two non-zero integers together. - #[doc = concat!("Return [`", stringify!($Int), "::MAX`] on overflow.")] + #[doc = concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")] /// /// # Examples /// @@ -1102,11 +1105,11 @@ macro_rules! nonzero_unsigned_signed_operations { #[doc = sign_dependent_expr!{ $signedness ? if signed { - concat!("Return [`", stringify!($Int), "::MIN`] ", - "or [`", stringify!($Int), "::MAX`] on overflow.") + concat!("Return [`", stringify!($Ty), "::MIN`] ", + "or [`", stringify!($Ty), "::MAX`] on overflow.") } if unsigned { - concat!("Return [`", stringify!($Int), "::MAX`] on overflow.") + concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.") } }] /// -- cgit 1.4.1-3-g733a5 From 9f509429cd0fc2290b523bd158953cdfcedcfb12 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 16 Jun 2023 13:43:55 +0200 Subject: Unify history interactions in search --- src/librustdoc/html/static/js/search.js | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 25259971eff..180d93b790a 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2160,6 +2160,18 @@ function initSearch(rawSearchIndex) { printTab(currentTab); } + function updateSearchHistory(url) { + if (!browserSupportsHistoryApi()) { + return; + } + const params = searchState.getQueryStringParams(); + if (!history.state && !params.search) { + history.pushState(null, "", url); + } else { + history.replaceState(null, "", url); + } + } + /** * Perform a search based on the current state of the search input element * and display the results. @@ -2196,15 +2208,7 @@ function initSearch(rawSearchIndex) { // Because searching is incremental by character, only the most // recent search query is added to the browser history. - if (browserSupportsHistoryApi()) { - const newURL = buildUrl(query.original, filterCrates); - - if (!history.state && !params.search) { - history.pushState(null, "", newURL); - } else { - history.replaceState(null, "", newURL); - } - } + updateSearchHistory(buildUrl(query.original, filterCrates)); showResults( execQuery(query, searchWords, filterCrates, window.currentCrate), @@ -2670,13 +2674,8 @@ function initSearch(rawSearchIndex) { function updateCrate(ev) { if (ev.target.value === "all crates") { // If we don't remove it from the URL, it'll be picked up again by the search. - const params = searchState.getQueryStringParams(); const query = searchState.input.value.trim(); - if (!history.state && !params.search) { - history.pushState(null, "", buildUrl(query, null)); - } else { - history.replaceState(null, "", buildUrl(query, null)); - } + updateSearchHistory(buildUrl(query, null)); } // In case you "cut" the entry from the search input, then change the crate filter // before paste back the previous search, you get the old search results without -- cgit 1.4.1-3-g733a5 From f4316392a756eae7f96952bd4ddc37e6449ef926 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 16 Jun 2023 16:56:13 +0200 Subject: Fix invalid handling of "going back in history" when "Directly go to item in search if there is only one result" setting is set to true --- src/librustdoc/html/static/js/main.js | 10 +++++++--- src/librustdoc/html/static/js/search.js | 15 ++++++++++++++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index a184b7b705e..f5296abaee6 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -277,14 +277,18 @@ function preLoadCss(cssUrl) { searchState.mouseMovedAfterSearch = false; document.title = searchState.title; }, - hideResults: () => { - switchDisplayedElement(null); + removeQueryParameters: () => { + // We change the document title. document.title = searchState.titleBeforeSearch; - // We also remove the query parameter from the URL. if (browserSupportsHistoryApi()) { history.replaceState(null, "", getNakedUrl() + window.location.hash); } }, + hideResults: () => { + switchDisplayedElement(null); + // We also remove the query parameter from the URL. + searchState.removeQueryParameters(); + }, getQueryStringParams: () => { const params = {}; window.location.search.substring(1).split("&"). diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 180d93b790a..af11b31b395 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2046,6 +2046,20 @@ function initSearch(rawSearchIndex) { if (go_to_first || (results.others.length === 1 && getSettingValue("go-to-only-result") === "true") ) { + // Needed to force re-execution of JS when coming back to a page. Let's take this + // scenario as example: + // + // 1. You have the "Directly go to item in search if there is only one result" option + // enabled. + // 2. You make a search which results only one result, leading you automatically to + // this result. + // 3. You go back to previous page. + // + // Now, without the call below, the JS will not be re-executed and the previous state + // will be used, starting search again since the search input is not empty, leading you + // back to the previous page again. + window.onunload = () => {}; + searchState.removeQueryParameters(); const elem = document.createElement("a"); elem.href = results.others[0].href; removeClass(elem, "active"); @@ -2182,7 +2196,6 @@ function initSearch(rawSearchIndex) { if (e) { e.preventDefault(); } - const query = parseQuery(searchState.input.value.trim()); let filterCrates = getFilterCrates(); -- cgit 1.4.1-3-g733a5 From ea55d25465f8dffc8283c0260f8dfa42076ba847 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 16 Jun 2023 20:41:00 +0200 Subject: Add regression test for #112676 --- tests/rustdoc-gui/setting-go-to-only-result.goml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/rustdoc-gui/setting-go-to-only-result.goml b/tests/rustdoc-gui/setting-go-to-only-result.goml index c5720b4bf1a..45e0b349051 100644 --- a/tests/rustdoc-gui/setting-go-to-only-result.goml +++ b/tests/rustdoc-gui/setting-go-to-only-result.goml @@ -34,7 +34,14 @@ go-to: "file://" + |DOC_PATH| + "/lib2/index.html" // We enter it into the search. write: (".search-input", "HasALongTraitWithParams") wait-for-document-property: {"title": "HasALongTraitWithParams in lib2 - Rust"} -assert-document-property: ({"URL": "/lib2/struct.HasALongTraitWithParams.html"}, ENDS_WITH) +assert-window-property: ({"location": "/lib2/struct.HasALongTraitWithParams.html"}, ENDS_WITH) + +// Regression test for . +// If "go-to-only-result" is enabled and you go back to history, it should not lead you back to the +// page result again automatically. +history-go-back: +wait-for-document-property: {"title": "lib2 - Rust"} +assert-window-property: ({"location": "/lib2/index.html"}, ENDS_WITH) // We try again to see if it goes to the only result go-to: "file://" + |DOC_PATH| + "/lib2/index.html?search=HasALongTraitWithParams" -- cgit 1.4.1-3-g733a5 From 4c6fd7594d6526c7ad58d3bc16e42c0dc538017a Mon Sep 17 00:00:00 2001 From: David Koloski Date: Fri, 16 Jun 2023 16:34:34 -0400 Subject: Replace fvdl with ffx, allow test without install Along with replacing fvdl uses with the equivalent ffx commands, this also switches from using the install path for libstd-*.so and libtest-*.so to using the build directory (now passed on the command line). The user no longer needs to run x.py install before running tests now, and the correct libstd and libtest are detected on run instead of startup so the test runner can handle recompilations after starting the testing environment. --- src/ci/docker/scripts/fuchsia-test-runner.py | 237 ++++++++++---------------- src/doc/rustc/src/platform-support/fuchsia.md | 19 +-- 2 files changed, 100 insertions(+), 156 deletions(-) diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py index 78a8a6662ea..73cf3de6a46 100755 --- a/src/ci/docker/scripts/fuchsia-test-runner.py +++ b/src/ci/docker/scripts/fuchsia-test-runner.py @@ -25,13 +25,9 @@ from typing import ClassVar, List, Optional @dataclass class TestEnvironment: - rust_dir: str + rust_build_dir: str sdk_dir: str target: str - package_server_pid: Optional[int] = None - emu_addr: Optional[str] = None - libstd_name: Optional[str] = None - libtest_name: Optional[str] = None verbose: bool = False @staticmethod @@ -57,7 +53,7 @@ class TestEnvironment: @classmethod def from_args(cls, args): return cls( - os.path.abspath(args.rust), + os.path.abspath(args.rust_build), os.path.abspath(args.sdk), args.target, verbose=args.verbose, @@ -68,13 +64,9 @@ class TestEnvironment: with open(cls.env_file_path(), encoding="utf-8") as f: test_env = json.loads(f.read()) return cls( - test_env["rust_dir"], + test_env["rust_build_dir"], test_env["sdk_dir"], test_env["target"], - libstd_name=test_env["libstd_name"], - libtest_name=test_env["libtest_name"], - emu_addr=test_env["emu_addr"], - package_server_pid=test_env["package_server_pid"], verbose=test_env["verbose"], ) @@ -82,18 +74,6 @@ class TestEnvironment: with open(self.env_file_path(), "w", encoding="utf-8") as f: f.write(json.dumps(self.__dict__)) - def ssh_dir(self): - return os.path.join(self.tmp_dir(), "ssh") - - def ssh_keyfile_path(self): - return os.path.join(self.ssh_dir(), "fuchsia_ed25519") - - def ssh_authfile_path(self): - return os.path.join(self.ssh_dir(), "fuchsia_authorized_keys") - - def vdl_output_path(self): - return os.path.join(self.tmp_dir(), "vdl_output") - def package_server_log_path(self): return os.path.join(self.tmp_dir(), "package_server_log") @@ -113,7 +93,9 @@ class TestEnvironment: def libs_dir(self): return os.path.join( - self.rust_dir, + self.rust_build_dir, + "host", + "stage2", "lib", ) @@ -212,21 +194,19 @@ class TestEnvironment: # Set configs configs = { "log.enabled": "true", - "ssh.pub": self.ssh_authfile_path(), - "ssh.priv": self.ssh_keyfile_path(), "test.is_isolated": "true", "test.experimental_structured_output": "true", } for key, value in configs.items(): subprocess.check_call( [ - self.tool_path("ffx"), + ffx_path, "config", "set", key, value, ], - env=self.ffx_cmd_env(), + env=ffx_env, stdout=self.subprocess_output(), stderr=self.subprocess_output(), ) @@ -248,6 +228,7 @@ class TestEnvironment: self.tool_path("ffx"), "daemon", "stop", + "-w", ], env=self.ffx_cmd_env(), stdout=self.subprocess_output(), @@ -275,87 +256,62 @@ class TestEnvironment: elif len(os.listdir(self.tmp_dir())) != 0: raise Exception(f"Temp directory is not clean (in {self.tmp_dir()})") - os.mkdir(self.ssh_dir()) os.mkdir(self.output_dir()) - # Find libstd and libtest - libstd_paths = glob.glob(os.path.join(self.rustlibs_dir(), "libstd-*.so")) - libtest_paths = glob.glob(os.path.join(self.rustlibs_dir(), "libtest-*.so")) - - if not libstd_paths: - raise Exception(f"Failed to locate libstd (in {self.rustlibs_dir()})") - - if not libtest_paths: - raise Exception(f"Failed to locate libtest (in {self.rustlibs_dir()})") + ffx_path = self.tool_path("ffx") + ffx_env = self.ffx_cmd_env() - self.libstd_name = os.path.basename(libstd_paths[0]) - self.libtest_name = os.path.basename(libtest_paths[0]) + # Start ffx isolation + self.log_info("Starting ffx isolation...") + self.start_ffx_isolation() - # Generate SSH keys for the emulator to use - self.log_info("Generating SSH keys...") + # Stop any running emulators (there shouldn't be any) subprocess.check_call( [ - "ssh-keygen", - "-N", - "", - "-t", - "ed25519", - "-f", - self.ssh_keyfile_path(), - "-C", - "Generated by fuchsia-test-runner.py", + ffx_path, + "emu", + "stop", + "--all", ], + env=ffx_env, stdout=self.subprocess_output(), stderr=self.subprocess_output(), ) - authfile_contents = subprocess.check_output( + + # Start emulator + self.log_info("Starting emulator...") + product_bundle = "terminal.qemu-" + self.triple_to_arch(self.target) + subprocess.check_call( [ - "ssh-keygen", - "-y", - "-f", - self.ssh_keyfile_path(), + ffx_path, + "product-bundle", + "get", + product_bundle, ], + env=ffx_env, + stdout=self.subprocess_output(), stderr=self.subprocess_output(), ) - with open(self.ssh_authfile_path(), "wb") as authfile: - authfile.write(authfile_contents) - - # Start ffx isolation - self.log_info("Starting ffx isolation...") - self.start_ffx_isolation() - - # Start emulator (this will generate the vdl output) - self.log_info("Starting emulator...") + # FIXME: condition --accel hyper on target arch matching host arch subprocess.check_call( [ - self.tool_path("fvdl"), - "--sdk", + ffx_path, + "emu", "start", - "--tuntap", + product_bundle, "--headless", - "--nointeractive", - "--ssh", - self.ssh_dir(), - "--vdl-output", - self.vdl_output_path(), - "--emulator-log", + "--log", self.emulator_log_path(), - "--image-name", - "qemu-" + self.triple_to_arch(self.target), + "--net", + "tap", + "--accel", + "hyper", ], + env=ffx_env, stdout=self.subprocess_output(), stderr=self.subprocess_output(), ) - # Parse vdl output for relevant information - with open(self.vdl_output_path(), encoding="utf-8") as f: - vdl_content = f.read() - matches = re.search( - r'network_address:\s+"\[([0-9a-f]{1,4}:(:[0-9a-f]{1,4}){4}%qemu)\]"', - vdl_content, - ) - self.emu_addr = matches.group(1) - # Create new package repo self.log_info("Creating package repo...") subprocess.check_call( @@ -369,55 +325,40 @@ class TestEnvironment: stderr=self.subprocess_output(), ) - # Start package server - self.log_info("Starting package server...") - with open( - self.package_server_log_path(), "w", encoding="utf-8" - ) as package_server_log: - # We want this to be a long-running process that persists after the script finishes - # pylint: disable=consider-using-with - self.package_server_pid = subprocess.Popen( - [ - self.tool_path("pm"), - "serve", - "-vt", - "-repo", - self.repo_dir(), - "-l", - ":8084", - ], - stdout=package_server_log, - stderr=package_server_log, - ).pid - - # Register package server with emulator - self.log_info("Registering package server...") - ssh_client = subprocess.check_output( + # Add repo + subprocess.check_call( [ - "ssh", - "-i", - self.ssh_keyfile_path(), - "-o", - "StrictHostKeyChecking=accept-new", - self.emu_addr, - "-f", - "echo $SSH_CLIENT", + ffx_path, + "repository", + "add-from-pm", + self.repo_dir(), + "--repository", + self.TEST_REPO_NAME, ], - text=True, + env=ffx_env, + stdout=self.subprocess_output(), + stderr=self.subprocess_output(), ) - repo_addr = ssh_client.split()[0].replace("%", "%25") - repo_url = f"http://[{repo_addr}]:8084/config.json" + + # Start repository server + subprocess.check_call( + [ffx_path, "repository", "server", "start", "--address", "[::]:0"], + env=ffx_env, + stdout=self.subprocess_output(), + stderr=self.subprocess_output(), + ) + + # Register with newly-started emulator subprocess.check_call( [ - "ssh", - "-i", - self.ssh_keyfile_path(), - "-o", - "StrictHostKeyChecking=accept-new", - self.emu_addr, - "-f", - f"pkgctl repo add url -f 1 -n {self.TEST_REPO_NAME} {repo_url}", + ffx_path, + "target", + "repository", + "register", + "--repository", + self.TEST_REPO_NAME, ], + env=ffx_env, stdout=self.subprocess_output(), stderr=self.subprocess_output(), ) @@ -471,8 +412,8 @@ class TestEnvironment: meta/package={package_dir}/meta/package meta/{package_name}.cm={package_dir}/meta/{package_name}.cm bin/{exe_name}={bin_path} - lib/{libstd_name}={rust_dir}/lib/rustlib/{rustlib_dir}/lib/{libstd_name} - lib/{libtest_name}={rust_dir}/lib/rustlib/{rustlib_dir}/lib/{libtest_name} + lib/{libstd_name}={libstd_path} + lib/{libtest_name}={libtest_path} lib/ld.so.1={sdk_dir}/arch/{target_arch}/sysroot/dist/lib/ld.so.1 lib/libfdio.so={sdk_dir}/arch/{target_arch}/dist/libfdio.so """ @@ -502,6 +443,16 @@ class TestEnvironment: bin_path = os.path.abspath(args.bin_path) + # Find libstd and libtest + libstd_paths = glob.glob(os.path.join(self.rustlibs_dir(), "libstd-*.so")) + libtest_paths = glob.glob(os.path.join(self.rustlibs_dir(), "libtest-*.so")) + + if not libstd_paths: + raise Exception(f"Failed to locate libstd (in {self.rustlibs_dir()})") + + if not libtest_paths: + raise Exception(f"Failed to locate libtest (in {self.rustlibs_dir()})") + # Build a unique, deterministic name for the test using the name of the # binary and the last 6 hex digits of the hash of the full path def path_checksum(path): @@ -604,11 +555,12 @@ class TestEnvironment: exe_name=exe_name, package_dir=package_dir, package_name=package_name, - rust_dir=self.rust_dir, - rustlib_dir=self.target, + target=self.target, sdk_dir=self.sdk_dir, - libstd_name=self.libstd_name, - libtest_name=self.libtest_name, + libstd_name=os.path.basename(libstd_paths[0]), + libtest_name=os.path.basename(libtest_paths[0]), + libstd_path=libstd_paths[0], + libtest_path=libtest_paths[0], target_arch=self.triple_to_arch(self.target), ) ) @@ -779,20 +731,15 @@ class TestEnvironment: else: self.log_debug("No ffx daemon log found") - # Stop package server - self.log_info("Stopping package server...") - os.kill(self.package_server_pid, signal.SIGTERM) - # Shut down the emulator self.log_info("Stopping emulator...") subprocess.check_call( [ - self.tool_path("fvdl"), - "--sdk", - "kill", - "--launched-proto", - self.vdl_output_path(), + self.tool_path("ffx"), + "emu", + "stop", ], + env=self.ffx_cmd_env(), stdout=self.subprocess_output(), stderr=self.subprocess_output(), ) @@ -969,8 +916,8 @@ def main(): "start", help="initializes the testing environment" ) start_parser.add_argument( - "--rust", - help="the directory of the installed Rust compiler for Fuchsia", + "--rust-build", + help="the current compiler build directory (`$RUST_SRC/build` by default)", required=True, ) start_parser.add_argument( diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md index 4d97b8c6cb9..a328c8cbfbb 100644 --- a/src/doc/rustc/src/platform-support/fuchsia.md +++ b/src/doc/rustc/src/platform-support/fuchsia.md @@ -681,12 +681,9 @@ local Rust source checkout: cd ${RUST_SRC_PATH} ``` -To run the Rust test suite on an emulated Fuchsia device, you must install the -Rust compiler locally. See "[Targeting Fuchsia with a compiler built from source](#targeting-fuchsia-with-a-compiler-built-from-source)" -for the steps to build locally. - -You'll also need to download a copy of the Fuchsia SDK. The current minimum -supported SDK version is [10.20221207.2.89][minimum_supported_sdk_version]. +To run the Rust test suite on an emulated Fuchsia device, you'll also need to +download a copy of the Fuchsia SDK. The current minimum supported SDK version is +[10.20221207.2.89][minimum_supported_sdk_version]. [minimum_supported_sdk_version]: https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core/linux-amd64/+/version:10.20221207.2.89 @@ -695,13 +692,13 @@ Fuchsia's test runner interacts with the Fuchsia emulator and is located at test environment with: ```sh -src/ci/docker/scripts/fuchsia-test-runner.py start - --rust ${RUST_SRC_PATH}/install - --sdk ${SDK_PATH} - --target {x86_64-unknown-fuchsia|aarch64-unknown-fuchsia} +src/ci/docker/scripts/fuchsia-test-runner.py start \ + --rust ${RUST_SRC_PATH}/build \ + --sdk ${SDK_PATH} \ + --target {x86_64-unknown-fuchsia|aarch64-unknown-fuchsia} \ ``` -Where `${RUST_SRC_PATH}/install` is the `prefix` set in `config.toml` and +Where `${RUST_SRC_PATH}/build` is the `build-dir` set in `config.toml` and `${SDK_PATH}` is the path to the downloaded and unzipped SDK. Once our environment is started, we can run our tests using `x.py` as usual. The -- cgit 1.4.1-3-g733a5 From 08d3065fd51db8715b4d4288bb3eff99371e66b6 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Fri, 16 Jun 2023 18:20:24 -0400 Subject: Fix --rust-build flag in docs --- src/doc/rustc/src/platform-support/fuchsia.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md index a328c8cbfbb..1b4888b3775 100644 --- a/src/doc/rustc/src/platform-support/fuchsia.md +++ b/src/doc/rustc/src/platform-support/fuchsia.md @@ -693,7 +693,7 @@ test environment with: ```sh src/ci/docker/scripts/fuchsia-test-runner.py start \ - --rust ${RUST_SRC_PATH}/build \ + --rust-build ${RUST_SRC_PATH}/build \ --sdk ${SDK_PATH} \ --target {x86_64-unknown-fuchsia|aarch64-unknown-fuchsia} \ ``` @@ -939,3 +939,4 @@ attach and load any relevant debug symbols. [gdb]: https://www.sourceware.org/gdb/ [the zxdb documentation]: https://fuchsia.dev/fuchsia-src/development/debugger [fdio]: https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/lib/fdio/ +-- -- cgit 1.4.1-3-g733a5 From 12c6f1d9588cd8775e13c6e85fa28794613f7446 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Fri, 16 Jun 2023 18:21:11 -0400 Subject: Fix edit fail --- src/doc/rustc/src/platform-support/fuchsia.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md index 1b4888b3775..f7cce35b123 100644 --- a/src/doc/rustc/src/platform-support/fuchsia.md +++ b/src/doc/rustc/src/platform-support/fuchsia.md @@ -939,4 +939,3 @@ attach and load any relevant debug symbols. [gdb]: https://www.sourceware.org/gdb/ [the zxdb documentation]: https://fuchsia.dev/fuchsia-src/development/debugger [fdio]: https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/lib/fdio/ --- -- cgit 1.4.1-3-g733a5 From 3dc793e625a1b566ca37ba0b12281f9cfb4eb473 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Thu, 15 Jun 2023 17:45:53 -0400 Subject: fix ICE on specific malformed asm clobber_abi --- compiler/rustc_builtin_macros/src/asm.rs | 6 +- tests/ui/asm/parse-error.rs | 144 +++++++++ tests/ui/asm/parse-error.stderr | 412 ++++++++++++++++++++++++++ tests/ui/asm/x86_64/parse-error.rs | 130 -------- tests/ui/asm/x86_64/parse-error.stderr | 399 ------------------------- tests/ui/asm/x86_64/x86_64_parse_error.rs | 21 ++ tests/ui/asm/x86_64/x86_64_parse_error.stderr | 44 +++ 7 files changed, 622 insertions(+), 534 deletions(-) create mode 100644 tests/ui/asm/parse-error.rs create mode 100644 tests/ui/asm/parse-error.stderr delete mode 100644 tests/ui/asm/x86_64/parse-error.rs delete mode 100644 tests/ui/asm/x86_64/parse-error.stderr create mode 100644 tests/ui/asm/x86_64/x86_64_parse_error.rs create mode 100644 tests/ui/asm/x86_64/x86_64_parse_error.stderr diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 5217e317adf..9734fc2b36d 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -379,16 +379,12 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a, } let mut new_abis = Vec::new(); - loop { + while !p.eat(&token::CloseDelim(Delimiter::Parenthesis)) { match p.parse_str_lit() { Ok(str_lit) => { new_abis.push((str_lit.symbol_unescaped, str_lit.span)); } Err(opt_lit) => { - // If the non-string literal is a closing paren then it's the end of the list and is fine - if p.eat(&token::CloseDelim(Delimiter::Parenthesis)) { - break; - } let span = opt_lit.map_or(p.token.span, |lit| lit.span); let mut err = p.sess.span_diagnostic.struct_span_err(span, "expected string literal"); diff --git a/tests/ui/asm/parse-error.rs b/tests/ui/asm/parse-error.rs new file mode 100644 index 00000000000..9e002b1550f --- /dev/null +++ b/tests/ui/asm/parse-error.rs @@ -0,0 +1,144 @@ +// needs-asm-support + +#![feature(asm_const)] + +use std::arch::{asm, global_asm}; + +fn main() { + let mut foo = 0; + let mut bar = 0; + unsafe { + asm!(); + //~^ ERROR requires at least a template string argument + asm!(foo); + //~^ ERROR asm template must be a string literal + asm!("{}" foo); + //~^ ERROR expected token: `,` + asm!("{}", foo); + //~^ ERROR expected operand, clobber_abi, options, or additional template string + asm!("{}", in foo); + //~^ ERROR expected `(`, found `foo` + asm!("{}", in(reg foo)); + //~^ ERROR expected `)`, found `foo` + asm!("{}", in(reg)); + //~^ ERROR expected expression, found end of macro arguments + asm!("{}", inout(=) foo => bar); + //~^ ERROR expected register class or explicit register + asm!("{}", inout(reg) foo =>); + //~^ ERROR expected expression, found end of macro arguments + asm!("{}", in(reg) foo => bar); + //~^ ERROR expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>` + asm!("{}", sym foo + bar); + //~^ ERROR expected a path for argument to `sym` + asm!("", options(foo)); + //~^ ERROR expected one of + asm!("", options(nomem foo)); + //~^ ERROR expected one of + asm!("", options(nomem, foo)); + //~^ ERROR expected one of + asm!("{}", options(), const foo); + //~^ ERROR attempt to use a non-constant value in a constant + + // test that asm!'s clobber_abi doesn't accept non-string literals + // see also https://github.com/rust-lang/rust/issues/112635 + asm!("", clobber_abi()); + //~^ ERROR at least one abi must be provided + asm!("", clobber_abi(foo)); + //~^ ERROR expected string literal + asm!("", clobber_abi("C" foo)); + //~^ ERROR expected one of `)` or `,`, found `foo` + asm!("", clobber_abi("C", foo)); + //~^ ERROR expected string literal + asm!("", clobber_abi(1)); + //~^ ERROR expected string literal + asm!("", clobber_abi(())); + //~^ ERROR expected string literal + asm!("", clobber_abi(uwu)); + //~^ ERROR expected string literal + asm!("", clobber_abi({})); + //~^ ERROR expected string literal + asm!("", clobber_abi(loop {})); + //~^ ERROR expected string literal + asm!("", clobber_abi(if)); + //~^ ERROR expected string literal + asm!("", clobber_abi(do)); + //~^ ERROR expected string literal + asm!("", clobber_abi(<)); + //~^ ERROR expected string literal + asm!("", clobber_abi(.)); + //~^ ERROR expected string literal + + asm!("{}", clobber_abi("C"), const foo); + //~^ ERROR attempt to use a non-constant value in a constant + asm!("", options(), clobber_abi("C")); + asm!("{}", options(), clobber_abi("C"), const foo); + //~^ ERROR attempt to use a non-constant value in a constant + asm!("{a}", a = const foo, a = const bar); + //~^ ERROR duplicate argument named `a` + //~^^ ERROR argument never used + //~^^^ ERROR attempt to use a non-constant value in a constant + //~^^^^ ERROR attempt to use a non-constant value in a constant + + asm!("", options(), ""); + //~^ ERROR expected one of + asm!("{}", in(reg) foo, "{}", out(reg) foo); + //~^ ERROR expected one of + asm!(format!("{{{}}}", 0), in(reg) foo); + //~^ ERROR asm template must be a string literal + asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); + //~^ ERROR asm template must be a string literal + asm!("{}", in(reg) _); + //~^ ERROR _ cannot be used for input operands + asm!("{}", inout(reg) _); + //~^ ERROR _ cannot be used for input operands + asm!("{}", inlateout(reg) _); + //~^ ERROR _ cannot be used for input operands + } +} + +const FOO: i32 = 1; +const BAR: i32 = 2; +global_asm!(); +//~^ ERROR requires at least a template string argument +global_asm!(FOO); +//~^ ERROR asm template must be a string literal +global_asm!("{}" FOO); +//~^ ERROR expected token: `,` +global_asm!("{}", FOO); +//~^ ERROR expected operand, options, or additional template string +global_asm!("{}", const); +//~^ ERROR expected expression, found end of macro arguments +global_asm!("{}", const(reg) FOO); +//~^ ERROR expected one of +global_asm!("", options(FOO)); +//~^ ERROR expected one of +global_asm!("", options(nomem FOO)); +//~^ ERROR expected one of +global_asm!("", options(nomem, FOO)); +//~^ ERROR expected one of +global_asm!("{}", options(), const FOO); +global_asm!("", clobber_abi(FOO)); +//~^ ERROR expected string literal +global_asm!("", clobber_abi("C" FOO)); +//~^ ERROR expected one of `)` or `,`, found `FOO` +global_asm!("", clobber_abi("C", FOO)); +//~^ ERROR expected string literal +global_asm!("{}", clobber_abi("C"), const FOO); +//~^ ERROR `clobber_abi` cannot be used with `global_asm!` +global_asm!("", options(), clobber_abi("C")); +//~^ ERROR `clobber_abi` cannot be used with `global_asm!` +global_asm!("{}", options(), clobber_abi("C"), const FOO); +//~^ ERROR `clobber_abi` cannot be used with `global_asm!` +global_asm!("", clobber_abi("C"), clobber_abi("C")); +//~^ ERROR `clobber_abi` cannot be used with `global_asm!` +global_asm!("{a}", a = const FOO, a = const BAR); +//~^ ERROR duplicate argument named `a` +//~^^ ERROR argument never used +global_asm!("", options(), ""); +//~^ ERROR expected one of +global_asm!("{}", const FOO, "{}", const FOO); +//~^ ERROR expected one of +global_asm!(format!("{{{}}}", 0), const FOO); +//~^ ERROR asm template must be a string literal +global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); +//~^ ERROR asm template must be a string literal diff --git a/tests/ui/asm/parse-error.stderr b/tests/ui/asm/parse-error.stderr new file mode 100644 index 00000000000..075d28e176a --- /dev/null +++ b/tests/ui/asm/parse-error.stderr @@ -0,0 +1,412 @@ +error: requires at least a template string argument + --> $DIR/parse-error.rs:11:9 + | +LL | asm!(); + | ^^^^^^ + +error: asm template must be a string literal + --> $DIR/parse-error.rs:13:14 + | +LL | asm!(foo); + | ^^^ + +error: expected token: `,` + --> $DIR/parse-error.rs:15:19 + | +LL | asm!("{}" foo); + | ^^^ expected `,` + +error: expected operand, clobber_abi, options, or additional template string + --> $DIR/parse-error.rs:17:20 + | +LL | asm!("{}", foo); + | ^^^ expected operand, clobber_abi, options, or additional template string + +error: expected `(`, found `foo` + --> $DIR/parse-error.rs:19:23 + | +LL | asm!("{}", in foo); + | ^^^ expected `(` + +error: expected `)`, found `foo` + --> $DIR/parse-error.rs:21:27 + | +LL | asm!("{}", in(reg foo)); + | ^^^ expected `)` + +error: expected expression, found end of macro arguments + --> $DIR/parse-error.rs:23:27 + | +LL | asm!("{}", in(reg)); + | ^ expected expression + +error: expected register class or explicit register + --> $DIR/parse-error.rs:25:26 + | +LL | asm!("{}", inout(=) foo => bar); + | ^ + +error: expected expression, found end of macro arguments + --> $DIR/parse-error.rs:27:37 + | +LL | asm!("{}", inout(reg) foo =>); + | ^ expected expression + +error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>` + --> $DIR/parse-error.rs:29:32 + | +LL | asm!("{}", in(reg) foo => bar); + | ^^ expected one of 7 possible tokens + +error: expected a path for argument to `sym` + --> $DIR/parse-error.rs:31:24 + | +LL | asm!("{}", sym foo + bar); + | ^^^^^^^^^ + +error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo` + --> $DIR/parse-error.rs:33:26 + | +LL | asm!("", options(foo)); + | ^^^ expected one of 10 possible tokens + +error: expected one of `)` or `,`, found `foo` + --> $DIR/parse-error.rs:35:32 + | +LL | asm!("", options(nomem foo)); + | ^^^ expected one of `)` or `,` + +error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo` + --> $DIR/parse-error.rs:37:33 + | +LL | asm!("", options(nomem, foo)); + | ^^^ expected one of 10 possible tokens + +error: at least one abi must be provided as an argument to `clobber_abi` + --> $DIR/parse-error.rs:44:30 + | +LL | asm!("", clobber_abi()); + | ^ + +error: expected string literal + --> $DIR/parse-error.rs:46:30 + | +LL | asm!("", clobber_abi(foo)); + | ^^^ not a string literal + +error: expected one of `)` or `,`, found `foo` + --> $DIR/parse-error.rs:48:34 + | +LL | asm!("", clobber_abi("C" foo)); + | ^^^ expected one of `)` or `,` + +error: expected string literal + --> $DIR/parse-error.rs:50:35 + | +LL | asm!("", clobber_abi("C", foo)); + | ^^^ not a string literal + +error: expected string literal + --> $DIR/parse-error.rs:52:30 + | +LL | asm!("", clobber_abi(1)); + | ^ not a string literal + +error: expected string literal + --> $DIR/parse-error.rs:54:30 + | +LL | asm!("", clobber_abi(())); + | ^ not a string literal + +error: expected string literal + --> $DIR/parse-error.rs:56:30 + | +LL | asm!("", clobber_abi(uwu)); + | ^^^ not a string literal + +error: expected string literal + --> $DIR/parse-error.rs:58:30 + | +LL | asm!("", clobber_abi({})); + | ^ not a string literal + +error: expected string literal + --> $DIR/parse-error.rs:60:30 + | +LL | asm!("", clobber_abi(loop {})); + | ^^^^ not a string literal + +error: expected string literal + --> $DIR/parse-error.rs:62:30 + | +LL | asm!("", clobber_abi(if)); + | ^^ not a string literal + +error: expected string literal + --> $DIR/parse-error.rs:64:30 + | +LL | asm!("", clobber_abi(do)); + | ^^ not a string literal + +error: expected string literal + --> $DIR/parse-error.rs:66:30 + | +LL | asm!("", clobber_abi(<)); + | ^ not a string literal + +error: expected string literal + --> $DIR/parse-error.rs:68:30 + | +LL | asm!("", clobber_abi(.)); + | ^ not a string literal + +error: duplicate argument named `a` + --> $DIR/parse-error.rs:76:36 + | +LL | asm!("{a}", a = const foo, a = const bar); + | ------------- ^^^^^^^^^^^^^ duplicate argument + | | + | previously here + +error: argument never used + --> $DIR/parse-error.rs:76:36 + | +LL | asm!("{a}", a = const foo, a = const bar); + | ^^^^^^^^^^^^^ argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` + +error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""` + --> $DIR/parse-error.rs:82:29 + | +LL | asm!("", options(), ""); + | ^^ expected one of 9 possible tokens + +error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"` + --> $DIR/parse-error.rs:84:33 + | +LL | asm!("{}", in(reg) foo, "{}", out(reg) foo); + | ^^^^ expected one of 9 possible tokens + +error: asm template must be a string literal + --> $DIR/parse-error.rs:86:14 + | +LL | asm!(format!("{{{}}}", 0), in(reg) foo); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: asm template must be a string literal + --> $DIR/parse-error.rs:88:21 + | +LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: _ cannot be used for input operands + --> $DIR/parse-error.rs:90:28 + | +LL | asm!("{}", in(reg) _); + | ^ + +error: _ cannot be used for input operands + --> $DIR/parse-error.rs:92:31 + | +LL | asm!("{}", inout(reg) _); + | ^ + +error: _ cannot be used for input operands + --> $DIR/parse-error.rs:94:35 + | +LL | asm!("{}", inlateout(reg) _); + | ^ + +error: requires at least a template string argument + --> $DIR/parse-error.rs:101:1 + | +LL | global_asm!(); + | ^^^^^^^^^^^^^ + +error: asm template must be a string literal + --> $DIR/parse-error.rs:103:13 + | +LL | global_asm!(FOO); + | ^^^ + +error: expected token: `,` + --> $DIR/parse-error.rs:105:18 + | +LL | global_asm!("{}" FOO); + | ^^^ expected `,` + +error: expected operand, options, or additional template string + --> $DIR/parse-error.rs:107:19 + | +LL | global_asm!("{}", FOO); + | ^^^ expected operand, options, or additional template string + +error: expected expression, found end of macro arguments + --> $DIR/parse-error.rs:109:24 + | +LL | global_asm!("{}", const); + | ^ expected expression + +error: expected one of `,`, `.`, `?`, or an operator, found `FOO` + --> $DIR/parse-error.rs:111:30 + | +LL | global_asm!("{}", const(reg) FOO); + | ^^^ expected one of `,`, `.`, `?`, or an operator + +error: expected one of `)`, `att_syntax`, or `raw`, found `FOO` + --> $DIR/parse-error.rs:113:25 + | +LL | global_asm!("", options(FOO)); + | ^^^ expected one of `)`, `att_syntax`, or `raw` + +error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` + --> $DIR/parse-error.rs:115:25 + | +LL | global_asm!("", options(nomem FOO)); + | ^^^^^ expected one of `)`, `att_syntax`, or `raw` + +error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` + --> $DIR/parse-error.rs:117:25 + | +LL | global_asm!("", options(nomem, FOO)); + | ^^^^^ expected one of `)`, `att_syntax`, or `raw` + +error: expected string literal + --> $DIR/parse-error.rs:120:29 + | +LL | global_asm!("", clobber_abi(FOO)); + | ^^^ not a string literal + +error: expected one of `)` or `,`, found `FOO` + --> $DIR/parse-error.rs:122:33 + | +LL | global_asm!("", clobber_abi("C" FOO)); + | ^^^ expected one of `)` or `,` + +error: expected string literal + --> $DIR/parse-error.rs:124:34 + | +LL | global_asm!("", clobber_abi("C", FOO)); + | ^^^ not a string literal + +error: `clobber_abi` cannot be used with `global_asm!` + --> $DIR/parse-error.rs:126:19 + | +LL | global_asm!("{}", clobber_abi("C"), const FOO); + | ^^^^^^^^^^^^^^^^ + +error: `clobber_abi` cannot be used with `global_asm!` + --> $DIR/parse-error.rs:128:28 + | +LL | global_asm!("", options(), clobber_abi("C")); + | ^^^^^^^^^^^^^^^^ + +error: `clobber_abi` cannot be used with `global_asm!` + --> $DIR/parse-error.rs:130:30 + | +LL | global_asm!("{}", options(), clobber_abi("C"), const FOO); + | ^^^^^^^^^^^^^^^^ + +error: `clobber_abi` cannot be used with `global_asm!` + --> $DIR/parse-error.rs:132:17 + | +LL | global_asm!("", clobber_abi("C"), clobber_abi("C")); + | ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ + +error: duplicate argument named `a` + --> $DIR/parse-error.rs:134:35 + | +LL | global_asm!("{a}", a = const FOO, a = const BAR); + | ------------- ^^^^^^^^^^^^^ duplicate argument + | | + | previously here + +error: argument never used + --> $DIR/parse-error.rs:134:35 + | +LL | global_asm!("{a}", a = const FOO, a = const BAR); + | ^^^^^^^^^^^^^ argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` + +error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `""` + --> $DIR/parse-error.rs:137:28 + | +LL | global_asm!("", options(), ""); + | ^^ expected one of `clobber_abi`, `const`, `options`, or `sym` + +error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `"{}"` + --> $DIR/parse-error.rs:139:30 + | +LL | global_asm!("{}", const FOO, "{}", const FOO); + | ^^^^ expected one of `clobber_abi`, `const`, `options`, or `sym` + +error: asm template must be a string literal + --> $DIR/parse-error.rs:141:13 + | +LL | global_asm!(format!("{{{}}}", 0), const FOO); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: asm template must be a string literal + --> $DIR/parse-error.rs:143:20 + | +LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/parse-error.rs:39:37 + | +LL | let mut foo = 0; + | ----------- help: consider using `const` instead of `let`: `const foo` +... +LL | asm!("{}", options(), const foo); + | ^^^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/parse-error.rs:71:44 + | +LL | let mut foo = 0; + | ----------- help: consider using `const` instead of `let`: `const foo` +... +LL | asm!("{}", clobber_abi("C"), const foo); + | ^^^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/parse-error.rs:74:55 + | +LL | let mut foo = 0; + | ----------- help: consider using `const` instead of `let`: `const foo` +... +LL | asm!("{}", options(), clobber_abi("C"), const foo); + | ^^^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/parse-error.rs:76:31 + | +LL | let mut foo = 0; + | ----------- help: consider using `const` instead of `let`: `const foo` +... +LL | asm!("{a}", a = const foo, a = const bar); + | ^^^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/parse-error.rs:76:46 + | +LL | let mut bar = 0; + | ----------- help: consider using `const` instead of `let`: `const bar` +... +LL | asm!("{a}", a = const foo, a = const bar); + | ^^^ non-constant value + +error: aborting due to 63 previous errors + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/asm/x86_64/parse-error.rs b/tests/ui/asm/x86_64/parse-error.rs deleted file mode 100644 index 2e714d464ae..00000000000 --- a/tests/ui/asm/x86_64/parse-error.rs +++ /dev/null @@ -1,130 +0,0 @@ -// only-x86_64 - -#![feature(asm_const)] - -use std::arch::{asm, global_asm}; - -fn main() { - let mut foo = 0; - let mut bar = 0; - unsafe { - asm!(); - //~^ ERROR requires at least a template string argument - asm!(foo); - //~^ ERROR asm template must be a string literal - asm!("{}" foo); - //~^ ERROR expected token: `,` - asm!("{}", foo); - //~^ ERROR expected operand, clobber_abi, options, or additional template string - asm!("{}", in foo); - //~^ ERROR expected `(`, found `foo` - asm!("{}", in(reg foo)); - //~^ ERROR expected `)`, found `foo` - asm!("{}", in(reg)); - //~^ ERROR expected expression, found end of macro arguments - asm!("{}", inout(=) foo => bar); - //~^ ERROR expected register class or explicit register - asm!("{}", inout(reg) foo =>); - //~^ ERROR expected expression, found end of macro arguments - asm!("{}", in(reg) foo => bar); - //~^ ERROR expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>` - asm!("{}", sym foo + bar); - //~^ ERROR expected a path for argument to `sym` - asm!("", options(foo)); - //~^ ERROR expected one of - asm!("", options(nomem foo)); - //~^ ERROR expected one of - asm!("", options(nomem, foo)); - //~^ ERROR expected one of - asm!("{}", options(), const foo); - //~^ ERROR attempt to use a non-constant value in a constant - asm!("", clobber_abi()); - //~^ ERROR at least one abi must be provided - asm!("", clobber_abi(foo)); - //~^ ERROR expected string literal - asm!("", clobber_abi("C" foo)); - //~^ ERROR expected one of `)` or `,`, found `foo` - asm!("", clobber_abi("C", foo)); - //~^ ERROR expected string literal - asm!("{}", clobber_abi("C"), const foo); - //~^ ERROR attempt to use a non-constant value in a constant - asm!("", options(), clobber_abi("C")); - asm!("{}", options(), clobber_abi("C"), const foo); - //~^ ERROR attempt to use a non-constant value in a constant - asm!("{a}", a = const foo, a = const bar); - //~^ ERROR duplicate argument named `a` - //~^^ ERROR argument never used - //~^^^ ERROR attempt to use a non-constant value in a constant - //~^^^^ ERROR attempt to use a non-constant value in a constant - asm!("", a = in("eax") foo); - //~^ ERROR explicit register arguments cannot have names - asm!("{a}", in("eax") foo, a = const bar); - //~^ ERROR attempt to use a non-constant value in a constant - asm!("{a}", in("eax") foo, a = const bar); - //~^ ERROR attempt to use a non-constant value in a constant - asm!("{1}", in("eax") foo, const bar); - //~^ ERROR positional arguments cannot follow named arguments or explicit register arguments - //~^^ ERROR attempt to use a non-constant value in a constant - asm!("", options(), ""); - //~^ ERROR expected one of - asm!("{}", in(reg) foo, "{}", out(reg) foo); - //~^ ERROR expected one of - asm!(format!("{{{}}}", 0), in(reg) foo); - //~^ ERROR asm template must be a string literal - asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); - //~^ ERROR asm template must be a string literal - asm!("{}", in(reg) _); - //~^ ERROR _ cannot be used for input operands - asm!("{}", inout(reg) _); - //~^ ERROR _ cannot be used for input operands - asm!("{}", inlateout(reg) _); - //~^ ERROR _ cannot be used for input operands - } -} - -const FOO: i32 = 1; -const BAR: i32 = 2; -global_asm!(); -//~^ ERROR requires at least a template string argument -global_asm!(FOO); -//~^ ERROR asm template must be a string literal -global_asm!("{}" FOO); -//~^ ERROR expected token: `,` -global_asm!("{}", FOO); -//~^ ERROR expected operand, options, or additional template string -global_asm!("{}", const); -//~^ ERROR expected expression, found end of macro arguments -global_asm!("{}", const(reg) FOO); -//~^ ERROR expected one of -global_asm!("", options(FOO)); -//~^ ERROR expected one of -global_asm!("", options(nomem FOO)); -//~^ ERROR expected one of -global_asm!("", options(nomem, FOO)); -//~^ ERROR expected one of -global_asm!("{}", options(), const FOO); -global_asm!("", clobber_abi(FOO)); -//~^ ERROR expected string literal -global_asm!("", clobber_abi("C" FOO)); -//~^ ERROR expected one of `)` or `,`, found `FOO` -global_asm!("", clobber_abi("C", FOO)); -//~^ ERROR expected string literal -global_asm!("{}", clobber_abi("C"), const FOO); -//~^ ERROR `clobber_abi` cannot be used with `global_asm!` -global_asm!("", options(), clobber_abi("C")); -//~^ ERROR `clobber_abi` cannot be used with `global_asm!` -global_asm!("{}", options(), clobber_abi("C"), const FOO); -//~^ ERROR `clobber_abi` cannot be used with `global_asm!` -global_asm!("", clobber_abi("C"), clobber_abi("C")); -//~^ ERROR `clobber_abi` cannot be used with `global_asm!` -global_asm!("{a}", a = const FOO, a = const BAR); -//~^ ERROR duplicate argument named `a` -//~^^ ERROR argument never used -global_asm!("", options(), ""); -//~^ ERROR expected one of -global_asm!("{}", const FOO, "{}", const FOO); -//~^ ERROR expected one of -global_asm!(format!("{{{}}}", 0), const FOO); -//~^ ERROR asm template must be a string literal -global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); -//~^ ERROR asm template must be a string literal diff --git a/tests/ui/asm/x86_64/parse-error.stderr b/tests/ui/asm/x86_64/parse-error.stderr deleted file mode 100644 index 0c9d6f71529..00000000000 --- a/tests/ui/asm/x86_64/parse-error.stderr +++ /dev/null @@ -1,399 +0,0 @@ -error: requires at least a template string argument - --> $DIR/parse-error.rs:11:9 - | -LL | asm!(); - | ^^^^^^ - -error: asm template must be a string literal - --> $DIR/parse-error.rs:13:14 - | -LL | asm!(foo); - | ^^^ - -error: expected token: `,` - --> $DIR/parse-error.rs:15:19 - | -LL | asm!("{}" foo); - | ^^^ expected `,` - -error: expected operand, clobber_abi, options, or additional template string - --> $DIR/parse-error.rs:17:20 - | -LL | asm!("{}", foo); - | ^^^ expected operand, clobber_abi, options, or additional template string - -error: expected `(`, found `foo` - --> $DIR/parse-error.rs:19:23 - | -LL | asm!("{}", in foo); - | ^^^ expected `(` - -error: expected `)`, found `foo` - --> $DIR/parse-error.rs:21:27 - | -LL | asm!("{}", in(reg foo)); - | ^^^ expected `)` - -error: expected expression, found end of macro arguments - --> $DIR/parse-error.rs:23:27 - | -LL | asm!("{}", in(reg)); - | ^ expected expression - -error: expected register class or explicit register - --> $DIR/parse-error.rs:25:26 - | -LL | asm!("{}", inout(=) foo => bar); - | ^ - -error: expected expression, found end of macro arguments - --> $DIR/parse-error.rs:27:37 - | -LL | asm!("{}", inout(reg) foo =>); - | ^ expected expression - -error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>` - --> $DIR/parse-error.rs:29:32 - | -LL | asm!("{}", in(reg) foo => bar); - | ^^ expected one of 7 possible tokens - -error: expected a path for argument to `sym` - --> $DIR/parse-error.rs:31:24 - | -LL | asm!("{}", sym foo + bar); - | ^^^^^^^^^ - -error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo` - --> $DIR/parse-error.rs:33:26 - | -LL | asm!("", options(foo)); - | ^^^ expected one of 10 possible tokens - -error: expected one of `)` or `,`, found `foo` - --> $DIR/parse-error.rs:35:32 - | -LL | asm!("", options(nomem foo)); - | ^^^ expected one of `)` or `,` - -error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo` - --> $DIR/parse-error.rs:37:33 - | -LL | asm!("", options(nomem, foo)); - | ^^^ expected one of 10 possible tokens - -error: at least one abi must be provided as an argument to `clobber_abi` - --> $DIR/parse-error.rs:41:30 - | -LL | asm!("", clobber_abi()); - | ^ - -error: expected string literal - --> $DIR/parse-error.rs:43:30 - | -LL | asm!("", clobber_abi(foo)); - | ^^^ not a string literal - -error: expected one of `)` or `,`, found `foo` - --> $DIR/parse-error.rs:45:34 - | -LL | asm!("", clobber_abi("C" foo)); - | ^^^ expected one of `)` or `,` - -error: expected string literal - --> $DIR/parse-error.rs:47:35 - | -LL | asm!("", clobber_abi("C", foo)); - | ^^^ not a string literal - -error: duplicate argument named `a` - --> $DIR/parse-error.rs:54:36 - | -LL | asm!("{a}", a = const foo, a = const bar); - | ------------- ^^^^^^^^^^^^^ duplicate argument - | | - | previously here - -error: argument never used - --> $DIR/parse-error.rs:54:36 - | -LL | asm!("{a}", a = const foo, a = const bar); - | ^^^^^^^^^^^^^ argument never used - | - = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` - -error: explicit register arguments cannot have names - --> $DIR/parse-error.rs:59:18 - | -LL | asm!("", a = in("eax") foo); - | ^^^^^^^^^^^^^^^^^ - -error: positional arguments cannot follow named arguments or explicit register arguments - --> $DIR/parse-error.rs:65:36 - | -LL | asm!("{1}", in("eax") foo, const bar); - | ------------- ^^^^^^^^^ positional argument - | | - | explicit register argument - -error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""` - --> $DIR/parse-error.rs:68:29 - | -LL | asm!("", options(), ""); - | ^^ expected one of 9 possible tokens - -error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"` - --> $DIR/parse-error.rs:70:33 - | -LL | asm!("{}", in(reg) foo, "{}", out(reg) foo); - | ^^^^ expected one of 9 possible tokens - -error: asm template must be a string literal - --> $DIR/parse-error.rs:72:14 - | -LL | asm!(format!("{{{}}}", 0), in(reg) foo); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: asm template must be a string literal - --> $DIR/parse-error.rs:74:21 - | -LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: _ cannot be used for input operands - --> $DIR/parse-error.rs:76:28 - | -LL | asm!("{}", in(reg) _); - | ^ - -error: _ cannot be used for input operands - --> $DIR/parse-error.rs:78:31 - | -LL | asm!("{}", inout(reg) _); - | ^ - -error: _ cannot be used for input operands - --> $DIR/parse-error.rs:80:35 - | -LL | asm!("{}", inlateout(reg) _); - | ^ - -error: requires at least a template string argument - --> $DIR/parse-error.rs:87:1 - | -LL | global_asm!(); - | ^^^^^^^^^^^^^ - -error: asm template must be a string literal - --> $DIR/parse-error.rs:89:13 - | -LL | global_asm!(FOO); - | ^^^ - -error: expected token: `,` - --> $DIR/parse-error.rs:91:18 - | -LL | global_asm!("{}" FOO); - | ^^^ expected `,` - -error: expected operand, options, or additional template string - --> $DIR/parse-error.rs:93:19 - | -LL | global_asm!("{}", FOO); - | ^^^ expected operand, options, or additional template string - -error: expected expression, found end of macro arguments - --> $DIR/parse-error.rs:95:24 - | -LL | global_asm!("{}", const); - | ^ expected expression - -error: expected one of `,`, `.`, `?`, or an operator, found `FOO` - --> $DIR/parse-error.rs:97:30 - | -LL | global_asm!("{}", const(reg) FOO); - | ^^^ expected one of `,`, `.`, `?`, or an operator - -error: expected one of `)`, `att_syntax`, or `raw`, found `FOO` - --> $DIR/parse-error.rs:99:25 - | -LL | global_asm!("", options(FOO)); - | ^^^ expected one of `)`, `att_syntax`, or `raw` - -error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` - --> $DIR/parse-error.rs:101:25 - | -LL | global_asm!("", options(nomem FOO)); - | ^^^^^ expected one of `)`, `att_syntax`, or `raw` - -error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` - --> $DIR/parse-error.rs:103:25 - | -LL | global_asm!("", options(nomem, FOO)); - | ^^^^^ expected one of `)`, `att_syntax`, or `raw` - -error: expected string literal - --> $DIR/parse-error.rs:106:29 - | -LL | global_asm!("", clobber_abi(FOO)); - | ^^^ not a string literal - -error: expected one of `)` or `,`, found `FOO` - --> $DIR/parse-error.rs:108:33 - | -LL | global_asm!("", clobber_abi("C" FOO)); - | ^^^ expected one of `)` or `,` - -error: expected string literal - --> $DIR/parse-error.rs:110:34 - | -LL | global_asm!("", clobber_abi("C", FOO)); - | ^^^ not a string literal - -error: `clobber_abi` cannot be used with `global_asm!` - --> $DIR/parse-error.rs:112:19 - | -LL | global_asm!("{}", clobber_abi("C"), const FOO); - | ^^^^^^^^^^^^^^^^ - -error: `clobber_abi` cannot be used with `global_asm!` - --> $DIR/parse-error.rs:114:28 - | -LL | global_asm!("", options(), clobber_abi("C")); - | ^^^^^^^^^^^^^^^^ - -error: `clobber_abi` cannot be used with `global_asm!` - --> $DIR/parse-error.rs:116:30 - | -LL | global_asm!("{}", options(), clobber_abi("C"), const FOO); - | ^^^^^^^^^^^^^^^^ - -error: `clobber_abi` cannot be used with `global_asm!` - --> $DIR/parse-error.rs:118:17 - | -LL | global_asm!("", clobber_abi("C"), clobber_abi("C")); - | ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ - -error: duplicate argument named `a` - --> $DIR/parse-error.rs:120:35 - | -LL | global_asm!("{a}", a = const FOO, a = const BAR); - | ------------- ^^^^^^^^^^^^^ duplicate argument - | | - | previously here - -error: argument never used - --> $DIR/parse-error.rs:120:35 - | -LL | global_asm!("{a}", a = const FOO, a = const BAR); - | ^^^^^^^^^^^^^ argument never used - | - = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` - -error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `""` - --> $DIR/parse-error.rs:123:28 - | -LL | global_asm!("", options(), ""); - | ^^ expected one of `clobber_abi`, `const`, `options`, or `sym` - -error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `"{}"` - --> $DIR/parse-error.rs:125:30 - | -LL | global_asm!("{}", const FOO, "{}", const FOO); - | ^^^^ expected one of `clobber_abi`, `const`, `options`, or `sym` - -error: asm template must be a string literal - --> $DIR/parse-error.rs:127:13 - | -LL | global_asm!(format!("{{{}}}", 0), const FOO); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: asm template must be a string literal - --> $DIR/parse-error.rs:129:20 - | -LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:39:37 - | -LL | let mut foo = 0; - | ----------- help: consider using `const` instead of `let`: `const foo` -... -LL | asm!("{}", options(), const foo); - | ^^^ non-constant value - -error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:49:44 - | -LL | let mut foo = 0; - | ----------- help: consider using `const` instead of `let`: `const foo` -... -LL | asm!("{}", clobber_abi("C"), const foo); - | ^^^ non-constant value - -error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:52:55 - | -LL | let mut foo = 0; - | ----------- help: consider using `const` instead of `let`: `const foo` -... -LL | asm!("{}", options(), clobber_abi("C"), const foo); - | ^^^ non-constant value - -error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:54:31 - | -LL | let mut foo = 0; - | ----------- help: consider using `const` instead of `let`: `const foo` -... -LL | asm!("{a}", a = const foo, a = const bar); - | ^^^ non-constant value - -error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:54:46 - | -LL | let mut bar = 0; - | ----------- help: consider using `const` instead of `let`: `const bar` -... -LL | asm!("{a}", a = const foo, a = const bar); - | ^^^ non-constant value - -error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:61:46 - | -LL | let mut bar = 0; - | ----------- help: consider using `const` instead of `let`: `const bar` -... -LL | asm!("{a}", in("eax") foo, a = const bar); - | ^^^ non-constant value - -error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:63:46 - | -LL | let mut bar = 0; - | ----------- help: consider using `const` instead of `let`: `const bar` -... -LL | asm!("{a}", in("eax") foo, a = const bar); - | ^^^ non-constant value - -error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:65:42 - | -LL | let mut bar = 0; - | ----------- help: consider using `const` instead of `let`: `const bar` -... -LL | asm!("{1}", in("eax") foo, const bar); - | ^^^ non-constant value - -error: aborting due to 59 previous errors - -For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/asm/x86_64/x86_64_parse_error.rs b/tests/ui/asm/x86_64/x86_64_parse_error.rs new file mode 100644 index 00000000000..715a67687d1 --- /dev/null +++ b/tests/ui/asm/x86_64/x86_64_parse_error.rs @@ -0,0 +1,21 @@ +// only-x86_64 + +#![feature(asm_const)] + +use std::arch::asm; + +fn main() { + let mut foo = 0; + let mut bar = 0; + unsafe { + asm!("", a = in("eax") foo); + //~^ ERROR explicit register arguments cannot have names + asm!("{a}", in("eax") foo, a = const bar); + //~^ ERROR attempt to use a non-constant value in a constant + asm!("{a}", in("eax") foo, a = const bar); + //~^ ERROR attempt to use a non-constant value in a constant + asm!("{1}", in("eax") foo, const bar); + //~^ ERROR positional arguments cannot follow named arguments or explicit register arguments + //~^^ ERROR attempt to use a non-constant value in a constant + } +} diff --git a/tests/ui/asm/x86_64/x86_64_parse_error.stderr b/tests/ui/asm/x86_64/x86_64_parse_error.stderr new file mode 100644 index 00000000000..f2854ae5128 --- /dev/null +++ b/tests/ui/asm/x86_64/x86_64_parse_error.stderr @@ -0,0 +1,44 @@ +error: explicit register arguments cannot have names + --> $DIR/x86_64_parse_error.rs:11:18 + | +LL | asm!("", a = in("eax") foo); + | ^^^^^^^^^^^^^^^^^ + +error: positional arguments cannot follow named arguments or explicit register arguments + --> $DIR/x86_64_parse_error.rs:17:36 + | +LL | asm!("{1}", in("eax") foo, const bar); + | ------------- ^^^^^^^^^ positional argument + | | + | explicit register argument + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/x86_64_parse_error.rs:13:46 + | +LL | let mut bar = 0; + | ----------- help: consider using `const` instead of `let`: `const bar` +... +LL | asm!("{a}", in("eax") foo, a = const bar); + | ^^^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/x86_64_parse_error.rs:15:46 + | +LL | let mut bar = 0; + | ----------- help: consider using `const` instead of `let`: `const bar` +... +LL | asm!("{a}", in("eax") foo, a = const bar); + | ^^^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/x86_64_parse_error.rs:17:42 + | +LL | let mut bar = 0; + | ----------- help: consider using `const` instead of `let`: `const bar` +... +LL | asm!("{1}", in("eax") foo, const bar); + | ^^^ non-constant value + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0435`. -- cgit 1.4.1-3-g733a5 From 3eddb2955578f6216ec8cbfce238f0286ff775bf Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 17 Jun 2023 14:38:51 +1000 Subject: Add `` to `-Zdump-mir-spanview` output --- compiler/rustc_middle/src/mir/spanview.rs | 5 +++-- tests/mir-opt/spanview_block.main.built.after.html | 3 ++- tests/mir-opt/spanview_statement.main.built.after.html | 3 ++- tests/mir-opt/spanview_terminator.main.built.after.html | 3 ++- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs index 6b036194381..730c551576a 100644 --- a/compiler/rustc_middle/src/mir/spanview.rs +++ b/compiler/rustc_middle/src/mir/spanview.rs @@ -15,8 +15,9 @@ const ANNOTATION_LEFT_BRACKET: char = '\u{298a}'; // Unicode `Z NOTATION RIGHT B const ANNOTATION_RIGHT_BRACKET: char = '\u{2989}'; // Unicode `Z NOTATION LEFT BINDING BRACKET` const NEW_LINE_SPAN: &str = "\n"; const HEADER: &str = r#" - -"#; + + +"#; const START_BODY: &str = r#" "#; const FOOTER: &str = r#" diff --git a/tests/mir-opt/spanview_block.main.built.after.html b/tests/mir-opt/spanview_block.main.built.after.html index b962d80c59e..56f4e4f9370 100644 --- a/tests/mir-opt/spanview_block.main.built.after.html +++ b/tests/mir-opt/spanview_block.main.built.after.html @@ -1,6 +1,7 @@ - + + spanview_block.main.built.after