diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index c24a1d8eb529f..0d37711d72e67 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2143,9 +2143,12 @@ impl<'tcx> TyS<'tcx> { } /// Returns the type of metadata for (potentially fat) pointers to this type. - pub fn ptr_metadata_ty(&'tcx self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - // FIXME: should this normalize? - let tail = tcx.struct_tail_without_normalization(self); + pub fn ptr_metadata_ty( + &'tcx self, + tcx: TyCtxt<'tcx>, + normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, + ) -> Ty<'tcx> { + let tail = tcx.struct_tail_with_normalize(self, normalize); match tail.kind() { // Sized types ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 669065598f149..8793264a47fbb 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -192,7 +192,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn struct_tail_with_normalize( self, mut ty: Ty<'tcx>, - normalize: impl Fn(Ty<'tcx>) -> Ty<'tcx>, + mut normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, ) -> Ty<'tcx> { let recursion_limit = self.recursion_limit(); for iteration in 0.. { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 5730502313838..1b02511fd7c2f 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -520,9 +520,16 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { } fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, _: NodeId) { let rib_kind = match fn_kind { - // Bail if there's no body. - FnKind::Fn(.., None) => return visit::walk_fn(self, fn_kind, sp), - FnKind::Fn(FnCtxt::Free | FnCtxt::Foreign, ..) => FnItemRibKind, + // Bail if the function is foreign, and thus cannot validly have + // a body, or if there's no body for some other reason. + FnKind::Fn(FnCtxt::Foreign, _, sig, ..) | FnKind::Fn(_, _, sig, .., None) => { + // We don't need to deal with patterns in parameters, because + // they are not possible for foreign or bodiless functions. + self.visit_fn_header(&sig.header); + visit::walk_fn_decl(self, &sig.decl); + return; + } + FnKind::Fn(FnCtxt::Free, ..) => FnItemRibKind, FnKind::Fn(FnCtxt::Assoc(_), ..) => NormalRibKind, FnKind::Closure(..) => ClosureOrAsyncRibKind, }; diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 23f615a96185d..bcb7e2100ab81 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1400,8 +1400,17 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // Any type with multiple potential metadata types is therefore not eligible. let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty()); - // FIXME: should this normalize? - let tail = selcx.tcx().struct_tail_without_normalization(self_ty); + let tail = selcx.tcx().struct_tail_with_normalize(self_ty, |ty| { + normalize_with_depth( + selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + ty, + ) + .value + }); + match tail.kind() { ty::Bool | ty::Char @@ -1435,7 +1444,12 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) - | ty::Error(_) => false, + | ty::Error(_) => { + if tail.has_infer_types() { + candidate_set.mark_ambiguous(); + } + false + }, } } super::ImplSource::Param(..) => { @@ -1640,18 +1654,30 @@ fn confirm_pointee_candidate<'cx, 'tcx>( _: ImplSourcePointeeData, ) -> Progress<'tcx> { let tcx = selcx.tcx(); - let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty()); - let substs = tcx.mk_substs([self_ty.into()].iter()); + let mut obligations = vec![]; + let metadata_ty = self_ty.ptr_metadata_ty(tcx, |ty| { + normalize_with_depth_to( + selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + ty, + &mut obligations, + ) + }); + + let substs = tcx.mk_substs([self_ty.into()].iter()); let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None); let predicate = ty::ProjectionPredicate { projection_ty: ty::ProjectionTy { substs, item_def_id: metadata_def_id }, - ty: self_ty.ptr_metadata_ty(tcx), + ty: metadata_ty, }; confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false) + .with_addl_obligations(obligations) } fn confirm_fn_pointer_candidate<'cx, 'tcx>( diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index d075658f51a3e..9d4f9af91a5e1 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -348,7 +348,6 @@ extern "Rust" { // This is the magic symbol to call the global alloc error handler. rustc generates // it to call `__rg_oom` if there is a `#[alloc_error_handler]`, or to call the // default implementations below (`__rdl_oom`) otherwise. - #[rustc_allocator_nounwind] fn __rust_alloc_error_handler(size: usize, align: usize) -> !; } @@ -367,7 +366,6 @@ extern "Rust" { #[stable(feature = "global_alloc", since = "1.28.0")] #[rustc_const_unstable(feature = "const_alloc_error", issue = "92523")] #[cfg(all(not(no_global_oom_handling), not(test)))] -#[rustc_allocator_nounwind] #[cold] pub const fn handle_alloc_error(layout: Layout) -> ! { const fn ct_error(_: Layout) -> ! { @@ -398,13 +396,13 @@ pub mod __alloc_error_handler { // if there is no `#[alloc_error_handler]` #[rustc_std_internal_symbol] - pub unsafe extern "C" fn __rdl_oom(size: usize, _align: usize) -> ! { + pub unsafe extern "C-unwind" fn __rdl_oom(size: usize, _align: usize) -> ! { panic!("memory allocation of {} bytes failed", size) } // if there is an `#[alloc_error_handler]` #[rustc_std_internal_symbol] - pub unsafe extern "C" fn __rg_oom(size: usize, align: usize) -> ! { + pub unsafe extern "C-unwind" fn __rg_oom(size: usize, align: usize) -> ! { let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; extern "Rust" { #[lang = "oom"] diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 7e663fab16af5..95da9971993e0 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -168,6 +168,7 @@ #![cfg_attr(test, feature(test))] #![feature(unboxed_closures)] #![feature(unsized_fn_params)] +#![feature(c_unwind)] // // Rustdoc features: #![feature(doc_cfg)] diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 7d005666a74a6..989ec0639cd6b 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1045,6 +1045,10 @@ pub const fn discriminant(v: &T) -> Discriminant { /// return value is unspecified. Equally, if `T` is an enum with more variants than `usize::MAX` /// the return value is unspecified. Uninhabited variants will be counted. /// +/// Note that an enum may be expanded with additional variants in the future +/// as a non-breaking change, for example if it is marked `#[non_exhaustive]`, +/// which will change the result of this function. +/// /// # Examples /// /// ``` diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index c4a232ef36c61..85ceede5b9e3a 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -628,6 +628,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use = "this returns the result of the operation, without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn recip(self) -> f32 { @@ -684,6 +685,7 @@ impl f32 { /// ``` /// /// If one of the arguments is NaN, then the other argument is returned. + #[must_use = "this returns the result of the comparison, without modifying either input"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn max(self, other: f32) -> f32 { @@ -703,6 +705,7 @@ impl f32 { /// ``` /// /// If one of the arguments is NaN, then the other argument is returned. + #[must_use = "this returns the result of the comparison, without modifying either input"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn min(self, other: f32) -> f32 { @@ -726,6 +729,7 @@ impl f32 { /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0. /// Note that this follows the semantics specified in IEEE 754-2019. + #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] pub fn maximum(self, other: f32) -> f32 { @@ -757,6 +761,7 @@ impl f32 { /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0. /// Note that this follows the semantics specified in IEEE 754-2019. + #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] pub fn minimum(self, other: f32) -> f32 { diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 85ee6aa2cb8c3..4049c95b130f2 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -643,6 +643,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use = "this returns the result of the operation, without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn recip(self) -> f64 { @@ -700,6 +701,7 @@ impl f64 { /// ``` /// /// If one of the arguments is NaN, then the other argument is returned. + #[must_use = "this returns the result of the comparison, without modifying either input"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn max(self, other: f64) -> f64 { @@ -719,6 +721,7 @@ impl f64 { /// ``` /// /// If one of the arguments is NaN, then the other argument is returned. + #[must_use = "this returns the result of the comparison, without modifying either input"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn min(self, other: f64) -> f64 { @@ -742,6 +745,7 @@ impl f64 { /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0. /// Note that this follows the semantics specified in IEEE 754-2019. + #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] pub fn maximum(self, other: f64) -> f64 { @@ -773,6 +777,7 @@ impl f64 { /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0. /// Note that this follows the semantics specified in IEEE 754-2019. + #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] pub fn minimum(self, other: f64) -> f64 { diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index c27e42a266220..66333e2b99214 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -17,12 +17,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ pkg-config \ mingw-w64 -RUN curl -sL https://nodejs.org/dist/v14.4.0/node-v14.4.0-linux-x64.tar.xz | tar -xJ -ENV PATH="/node-v14.4.0-linux-x64/bin:${PATH}" +RUN curl -sL https://nodejs.org/dist/v16.9.0/node-v16.9.0-linux-x64.tar.xz | tar -xJ +ENV PATH="/node-v16.9.0-linux-x64/bin:${PATH}" # Install es-check # Pin its version to prevent unrelated CI failures due to future es-check versions. -RUN npm install es-check@5.2.3 -g -RUN npm install eslint@7.20.0 -g +RUN npm install es-check@6.1.1 -g +RUN npm install eslint@8.6.0 -g COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh @@ -40,5 +40,5 @@ ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \ /scripts/validate-toolstate.sh && \ /scripts/validate-error-codes.sh && \ # Runs checks to ensure that there are no ES5 issues in our JS code. - es-check es5 ../src/librustdoc/html/static/js/*.js && \ + es-check es6 ../src/librustdoc/html/static/js/*.js && \ eslint ../src/librustdoc/html/static/js/*.js diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index d82c65398b835..6600e483146e7 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -545,6 +545,10 @@ nav.sub { position: relative; } +.search-loading { + text-align: center; +} + #results > table { width: 100%; table-layout: fixed; @@ -862,18 +866,24 @@ h2.small-section-header > .anchor { display: inline-flex; width: calc(100% - 63px); } +.search-results-title { + display: inline; +} +#search-settings { + font-size: 1.5rem; + font-weight: 500; + margin-bottom: 20px; +} #crate-search { min-width: 115px; margin-top: 5px; - padding: 6px; - padding-right: 19px; - flex: none; + margin-left: 0.2em; + padding-left: 0.3em; + padding-right: 23px; border: 0; - border-right: 0; - border-radius: 4px 0 0 4px; + border-radius: 4px; outline: none; cursor: pointer; - border-right: 1px solid; -moz-appearance: none; -webkit-appearance: none; /* Removes default arrow from firefox */ diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index f81f6d5d61fed..f41c1bd817ab2 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -289,8 +289,8 @@ function hideThemeButtonState() { var params = searchState.getQueryStringParams(); if (params.search !== undefined) { var search = searchState.outputElement(); - search.innerHTML = "

" + - searchState.loadingText + "

"; + search.innerHTML = "

" + + searchState.loadingText + "

"; searchState.showResults(search); loadSearch(); } diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index cf320f7b4958a..e859431e1f189 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1085,7 +1085,7 @@ window.initSearch = function(rawSearchIndex) { return ""; } - function showResults(results, go_to_first) { + function showResults(results, go_to_first, filterCrates) { var search = searchState.outputElement(); if (go_to_first || (results.others.length === 1 && getSettingValue("go-to-only-result") === "true" @@ -1126,9 +1126,16 @@ window.initSearch = function(rawSearchIndex) { } } - var output = "

Results for " + escape(query.query) + + let crates = ``; + var output = `
+

Results for ${escape(query.query)} ` + (query.type ? " (type: " + escape(query.type) + ")" : "") + "

" + - "
" + + ` in ${crates} ` + + `
` + makeTabHeader(0, "In Names", ret_others[1]) + makeTabHeader(1, "In Parameters", ret_in_args[1]) + makeTabHeader(2, "In Return Types", ret_returned[1]) + @@ -1141,6 +1148,7 @@ window.initSearch = function(rawSearchIndex) { resultsElem.appendChild(ret_returned[0]); search.innerHTML = output; + document.getElementById("crate-search").addEventListener("input", updateCrate); search.appendChild(resultsElem); // Reset focused elements. searchState.focusedByTab = [null, null, null]; @@ -1316,7 +1324,8 @@ window.initSearch = function(rawSearchIndex) { } var filterCrates = getFilterCrates(); - showResults(execSearch(query, searchWords, filterCrates), params["go_to_first"]); + showResults(execSearch(query, searchWords, filterCrates), + params["go_to_first"], filterCrates); } function buildIndex(rawSearchIndex) { @@ -1552,19 +1561,6 @@ window.initSearch = function(rawSearchIndex) { } }); - - var selectCrate = document.getElementById("crate-search"); - if (selectCrate) { - selectCrate.onchange = function() { - updateLocalStorage("rustdoc-saved-filter-crate", selectCrate.value); - // 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 - // the filter. To prevent this, we need to remove the previous results. - currentResults = null; - search(undefined, true); - }; - } - // Push and pop states are used to add search results to the browser // history. if (searchState.browserSupportsHistoryApi()) { @@ -1616,6 +1612,15 @@ window.initSearch = function(rawSearchIndex) { }; } + function updateCrate(ev) { + updateLocalStorage("rustdoc-saved-filter-crate", ev.target.value); + // 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 + // the filter. To prevent this, we need to remove the previous results. + currentResults = null; + search(undefined, true); + } + searchWords = buildIndex(rawSearchIndex); registerSearchEvents(); // If there's a search term in the URL, execute the search now. diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index 00b46b1ba918b..5cade1b1a4c73 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -105,11 +105,7 @@
{#- -#}
{#- -#}
{#- -#} -
{%- if layout.generate_search_filter -%} - {#- -#} - {%- endif -%} +
h1" // The search element is empty before the first search +wait-for: "#search h1" // The search element is empty before the first search assert-attribute: ("#search", {"class": "content"}) assert-attribute: ("#main-content", {"class": "content hidden"}) press-key: "Escape" diff --git a/src/test/rustdoc-gui/search-filter.goml b/src/test/rustdoc-gui/search-filter.goml index 7a8f8ca5311ad..e5cdf3ea7a169 100644 --- a/src/test/rustdoc-gui/search-filter.goml +++ b/src/test/rustdoc-gui/search-filter.goml @@ -5,14 +5,12 @@ write: (".search-input", "test") wait-for: "#titles" assert-text: ("#results .externcrate", "test_docs") -goto: file://|DOC_PATH|/test_docs/index.html +wait-for: "#crate-search" // We now want to change the crate filter. click: "#crate-search" // We select "lib2" option then press enter to change the filter. press-key: "ArrowDown" press-key: "Enter" -// We now make the search again. -write: (".search-input", "test") // Waiting for the search results to appear... wait-for: "#titles" // We check that there is no more "test_docs" appearing. diff --git a/src/test/rustdoc-gui/toggle-docs-mobile.goml b/src/test/rustdoc-gui/toggle-docs-mobile.goml index b370dd012fae1..6e0ad8e0fa7fb 100644 --- a/src/test/rustdoc-gui/toggle-docs-mobile.goml +++ b/src/test/rustdoc-gui/toggle-docs-mobile.goml @@ -1,12 +1,12 @@ goto: file://|DOC_PATH|/test_docs/struct.Foo.html size: (433, 600) assert-attribute: (".top-doc", {"open": ""}) -click: (4, 280) // This is the position of the top doc comment toggle +click: (4, 240) // This is the position of the top doc comment toggle assert-attribute-false: (".top-doc", {"open": ""}) -click: (4, 280) +click: (4, 240) assert-attribute: (".top-doc", {"open": ""}) // To ensure that the toggle isn't over the text, we check that the toggle isn't clicked. -click: (3, 280) +click: (3, 240) assert-attribute: (".top-doc", {"open": ""}) // Assert the position of the toggle on the top doc block. diff --git a/src/test/ui/foreign/issue-91370-foreign-fn-block-impl.rs b/src/test/ui/foreign/issue-91370-foreign-fn-block-impl.rs new file mode 100644 index 0000000000000..2ac3ca29355d8 --- /dev/null +++ b/src/test/ui/foreign/issue-91370-foreign-fn-block-impl.rs @@ -0,0 +1,12 @@ +// Regression test for issue #91370. + +extern { + //~^ `extern` blocks define existing foreign functions + fn f() { + //~^ incorrect function inside `extern` block + //~| cannot have a body + impl Copy for u8 {} + } +} + +fn main() {} diff --git a/src/test/ui/foreign/issue-91370-foreign-fn-block-impl.stderr b/src/test/ui/foreign/issue-91370-foreign-fn-block-impl.stderr new file mode 100644 index 0000000000000..4fb2f8c659c53 --- /dev/null +++ b/src/test/ui/foreign/issue-91370-foreign-fn-block-impl.stderr @@ -0,0 +1,21 @@ +error: incorrect function inside `extern` block + --> $DIR/issue-91370-foreign-fn-block-impl.rs:5:8 + | +LL | extern { + | ------ `extern` blocks define existing foreign functions and functions inside of them cannot have a body +LL | +LL | fn f() { + | ________^___- + | | | + | | cannot have a body +LL | | +LL | | +LL | | impl Copy for u8 {} +LL | | } + | |_____- help: remove the invalid body: `;` + | + = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to previous error + diff --git a/src/test/ui/traits/pointee-deduction.rs b/src/test/ui/traits/pointee-deduction.rs new file mode 100644 index 0000000000000..f888246967d3d --- /dev/null +++ b/src/test/ui/traits/pointee-deduction.rs @@ -0,0 +1,22 @@ +// run-pass + +#![feature(ptr_metadata)] + +use std::alloc::Layout; +use std::ptr::Pointee; + +trait Foo { + type Bar; +} + +impl Foo for () { + type Bar = (); +} + +struct Wrapper1(::Bar); +struct Wrapper2( as Pointee>::Metadata); + +fn main() { + let _: Wrapper2<()> = Wrapper2(()); + let _ = Layout::new::>(); +}