diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 2ac2d789b2d34..42db64c791518 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -2373,7 +2373,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let span = self.tcx.def_span(generator_did); // Do not ICE on closure typeck (#66868). - if let None = self.tcx.hir().as_local_hir_id(generator_did) { + if self.tcx.hir().as_local_hir_id(generator_did).is_none() { return false; } diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index a1e6eb69b9d0d..1141239e49a53 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -530,11 +530,12 @@ where // This can only be reached in ConstProp and non-rustc-MIR. throw_ub!(BoundsCheckFailed { len: min_length as u64, index: n as u64 }); } - assert!(offset < min_length); let index = if from_end { + assert!(0 < offset && offset - 1 < min_length); n - u64::from(offset) } else { + assert!(offset < min_length); u64::from(offset) }; diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 898ab6ae32211..dd1bef0c297a9 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -345,7 +345,7 @@ struct DiagnosticMetadata { /// The current self item if inside an ADT (used for better errors). current_self_item: Option, - /// The current enclosing funciton (used for better errors). + /// The current enclosing function (used for better errors). current_function: Option, /// A list of labels as of yet unused. Labels will be removed from this map when diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 6fb5c2f2de31f..a1cbcac1a9a76 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -259,6 +259,56 @@ impl<'a> LateResolutionVisitor<'a, '_> { } return (err, candidates); } + + // Check if the first argument is `self` and suggest calling a method. + let mut has_self_arg = None; + if let PathSource::Expr(parent) = source { + match &parent.map(|p| &p.kind) { + Some(ExprKind::Call(_, args)) if args.len() > 0 => { + let mut expr_kind = &args[0].kind; + loop { + match expr_kind { + ExprKind::Path(_, arg_name) if arg_name.segments.len() == 1 => { + if arg_name.segments[0].ident.name == kw::SelfLower { + let call_span = parent.unwrap().span; + let args_span = if args.len() > 1 { + Some(Span::new( + args[1].span.lo(), + args.last().unwrap().span.hi(), + call_span.ctxt(), + )) + } else { + None + }; + has_self_arg = Some((call_span, args_span)); + } + break; + }, + ExprKind::AddrOf(_, _, expr) => expr_kind = &expr.kind, + _ => break, + } + } + } + _ => (), + } + }; + + if let Some((call_span, args_span)) = has_self_arg { + let mut args_snippet: String = String::from(""); + if let Some(args_span) = args_span { + if let Ok(snippet) = self.r.session.source_map().span_to_snippet(args_span) { + args_snippet = snippet; + } + } + + err.span_suggestion( + call_span, + &format!("try calling `{}` as a method", ident), + format!("self.{}({})", path_str, args_snippet), + Applicability::MachineApplicable, + ); + return (err, candidates); + } } // Try Levenshtein algorithm. diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 1459e8f37cd32..8ccb74d6f15d3 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -138,6 +138,22 @@ function getSearchElement() { } } + function showSearchResults(search) { + if (search === null || typeof search === 'undefined') { + search = getSearchElement(); + } + addClass(main, "hidden"); + removeClass(search, "hidden"); + } + + function hideSearchResults(search) { + if (search === null || typeof search === 'undefined') { + search = getSearchElement(); + } + addClass(search, "hidden"); + removeClass(main, "hidden"); + } + // used for special search precedence var TY_PRIMITIVE = itemTypes.indexOf("primitive"); var TY_KEYWORD = itemTypes.indexOf("keyword"); @@ -169,8 +185,7 @@ function getSearchElement() { if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) { // This block occurs when clicking on an element in the navbar while // in a search. - addClass(search, "hidden"); - removeClass(main, "hidden"); + hideSearchResults(search); var hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1); if (browserSupportsHistoryApi()) { history.replaceState(hash, "", "?search=#" + hash); @@ -331,8 +346,7 @@ function getSearchElement() { displayHelp(false, ev, help); } else if (hasClass(search, "hidden") === false) { ev.preventDefault(); - addClass(search, "hidden"); - removeClass(main, "hidden"); + hideSearchResults(search); document.title = titleBeforeSearch; } defocusSearchBar(); @@ -390,8 +404,8 @@ function getSearchElement() { return null; } - document.onkeypress = handleShortcut; - document.onkeydown = handleShortcut; + document.addEventListener("keypress", handleShortcut); + document.addEventListener("keydown", handleShortcut); var handleSourceHighlight = (function() { var prev_line_id = 0; @@ -430,7 +444,7 @@ function getSearchElement() { } })(); - document.onclick = function(ev) { + document.addEventListener("click", function(ev) { if (hasClass(ev.target, "collapse-toggle")) { collapseDocs(ev.target, "toggle"); } else if (hasClass(ev.target.parentNode, "collapse-toggle")) { @@ -452,7 +466,7 @@ function getSearchElement() { expandSection(a.hash.replace(/^#/, "")); } } - }; + }); var x = document.getElementsByClassName("version-selector"); if (x.length > 0) { @@ -1264,8 +1278,7 @@ function getSearchElement() { } dst = dst[0]; if (window.location.pathname === dst.pathname) { - addClass(getSearchElement(), "hidden"); - removeClass(main, "hidden"); + hideSearchResults(); document.location.href = dst.href; } }; @@ -1340,8 +1353,6 @@ function getSearchElement() { e.preventDefault(); } else if (e.which === 16) { // shift // Does nothing, it's just to avoid losing "focus" on the highlighted element. - } else if (e.which === 27) { // escape - handleEscape(e); } else if (actives[currentTab].length > 0) { removeClass(actives[currentTab][0], "highlighted"); } @@ -1491,10 +1502,9 @@ function getSearchElement() { "
" + ret_others[0] + ret_in_args[0] + ret_returned[0] + "
"; - addClass(main, "hidden"); var search = getSearchElement(); - removeClass(search, "hidden"); search.innerHTML = output; + showSearchResults(search); var tds = search.getElementsByTagName("td"); var td_width = 0; if (tds.length > 0) { @@ -1699,13 +1709,7 @@ function getSearchElement() { if (browserSupportsHistoryApi()) { history.replaceState("", window.currentCrate + " - Rust", "?search="); } - if (hasClass(main, "content")) { - removeClass(main, "hidden"); - } - var search_c = getSearchElement(); - if (hasClass(search_c, "content")) { - addClass(search_c, "hidden"); - } + hideSearchResults(); } else { searchTimeout = setTimeout(search, 500); } @@ -1718,6 +1722,10 @@ function getSearchElement() { search(); }; search_input.onchange = function(e) { + if (e.target !== document.activeElement) { + // To prevent doing anything when it's from a blur event. + return; + } // Do NOT e.preventDefault() here. It will prevent pasting. clearTimeout(searchTimeout); // zero-timeout necessary here because at the time of event handler execution the @@ -1741,19 +1749,8 @@ function getSearchElement() { // Store the previous so we can revert back to it later. var previousTitle = document.title; - window.onpopstate = function(e) { + window.addEventListener("popstate", function(e) { var params = getQueryStringParams(); - // When browsing back from search results the main page - // visibility must be reset. - if (!params.search) { - if (hasClass(main, "content")) { - removeClass(main, "hidden"); - } - var search_c = getSearchElement(); - if (hasClass(search_c, "content")) { - addClass(search_c, "hidden"); - } - } // Revert to the previous title manually since the History // API ignores the title parameter. document.title = previousTitle; @@ -1765,18 +1762,21 @@ function getSearchElement() { // perform the search. This will empty the bar if there's // nothing there, which lets you really go back to a // previous state with nothing in the bar. - if (params.search) { + if (params.search && params.search.length > 0) { search_input.value = params.search; + // Some browsers fire "onpopstate" for every page load + // (Chrome), while others fire the event only when actually + // popping a state (Firefox), which is why search() is + // called both here and at the end of the startSearch() + // function. + search(e); } else { search_input.value = ""; + // When browsing back from search results the main page + // visibility must be reset. + hideSearchResults(); } - // Some browsers fire "onpopstate" for every page load - // (Chrome), while others fire the event only when actually - // popping a state (Firefox), which is why search() is - // called both here and at the end of the startSearch() - // function. - search(); - }; + }); } search(); } @@ -2522,9 +2522,9 @@ function getSearchElement() { } function putBackSearch(search_input) { - if (search_input.value !== "") { - addClass(main, "hidden"); - removeClass(getSearchElement(), "hidden"); + var search = getSearchElement(); + if (search_input.value !== "" && hasClass(search, "hidden")) { + showSearchResults(search); if (browserSupportsHistoryApi()) { history.replaceState(search_input.value, "", @@ -2541,10 +2541,9 @@ function getSearchElement() { var params = getQueryStringParams(); if (params && params.search) { - addClass(main, "hidden"); var search = getSearchElement(); - removeClass(search, "hidden"); search.innerHTML = "<h3 style=\"text-align: center;\">Loading search results...</h3>"; + showSearchResults(search); } var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0]; diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index 1492f70436c26..9787cbb556bd2 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -72,7 +72,7 @@ use core::convert::TryInto; /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct Cursor<T> { inner: T, pos: u64, @@ -942,4 +942,16 @@ mod tests { c.set_position(<usize>::max_value() as u64 + 1); assert!(c.write_all(&[1, 2, 3]).is_err()); } + + #[test] + fn test_partial_eq() { + assert_eq!(Cursor::new(Vec::<u8>::new()), Cursor::new(Vec::<u8>::new())); + } + + #[test] + fn test_eq() { + struct AssertEq<T: Eq>(pub T); + + let _: AssertEq<Cursor<Vec<u8>>> = AssertEq(Cursor::new(Vec::new())); + } } diff --git a/src/test/ui/const-generics/issues/issue-61747.rs b/src/test/ui/const-generics/issues/issue-61747.rs new file mode 100644 index 0000000000000..64674bb894e1f --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-61747.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +struct Const<const N: usize>; + +impl<const C: usize> Const<{C}> { + fn successor() -> Const<{C + 1}> { + Const + } +} + +fn main() { + let _x: Const::<2> = Const::<1>::successor(); +} diff --git a/src/test/ui/const-generics/issues/issue-61747.stderr b/src/test/ui/const-generics/issues/issue-61747.stderr new file mode 100644 index 0000000000000..ccf36a7f805ec --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-61747.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue-61747.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/const-generics/issues/issue-66205.rs b/src/test/ui/const-generics/issues/issue-66205.rs new file mode 100644 index 0000000000000..2e47b4d1882f2 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-66205.rs @@ -0,0 +1,10 @@ +// check-pass + +#![allow(incomplete_features, dead_code, unconditional_recursion)] +#![feature(const_generics)] + +fn fact<const N: usize>() { + fact::<{ N - 1 }>(); +} + +fn main() {} diff --git a/src/test/ui/consts/const_prop_slice_pat_ice.rs b/src/test/ui/consts/const_prop_slice_pat_ice.rs new file mode 100644 index 0000000000000..5fec36e44bd8c --- /dev/null +++ b/src/test/ui/consts/const_prop_slice_pat_ice.rs @@ -0,0 +1,9 @@ +// check-pass +#![feature(slice_patterns)] + +fn main() { + match &[0, 1] as &[i32] { + [a @ .., x] => {} + &[] => {} + } +} diff --git a/src/test/ui/generic-associated-types/issue-67424.rs b/src/test/ui/generic-associated-types/issue-67424.rs new file mode 100644 index 0000000000000..9b616b8abc2ee --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-67424.rs @@ -0,0 +1,13 @@ +// Fixed by #67160 + +trait Trait1 { + type A; +} + +trait Trait2 { + type Type1<B>: Trait1<A=B>; + //~^ ERROR: generic associated types are unstable + //~| ERROR: type-generic associated types are not yet implemented +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-67424.stderr b/src/test/ui/generic-associated-types/issue-67424.stderr new file mode 100644 index 0000000000000..59ff8ac0a3a70 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-67424.stderr @@ -0,0 +1,20 @@ +error[E0658]: generic associated types are unstable + --> $DIR/issue-67424.rs:8:5 + | +LL | type Type1<B>: Trait1<A=B>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/44265 + = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable + +error: type-generic associated types are not yet implemented + --> $DIR/issue-67424.rs:8:5 + | +LL | type Type1<B>: Trait1<A=B>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/44265 + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.rs b/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.rs new file mode 100644 index 0000000000000..48a8e04829a0a --- /dev/null +++ b/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.rs @@ -0,0 +1,14 @@ +// Regression test for #66270, fixed by #66246 + +struct Bug { + incorrect_field: 0, + //~^ ERROR expected type +} + +struct Empty {} + +fn main() { + let Bug { + any_field: Empty {}, + } = Bug {}; +} diff --git a/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr b/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr new file mode 100644 index 0000000000000..fef0f3c0e06ef --- /dev/null +++ b/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr @@ -0,0 +1,8 @@ +error: expected type, found `0` + --> $DIR/issue-66270-pat-struct-parser-recovery.rs:4:22 + | +LL | incorrect_field: 0, + | ^ expected type + +error: aborting due to previous error + diff --git a/src/test/ui/self/suggest-self-2.rs b/src/test/ui/self/suggest-self-2.rs new file mode 100644 index 0000000000000..d6bf543352701 --- /dev/null +++ b/src/test/ui/self/suggest-self-2.rs @@ -0,0 +1,25 @@ +struct Foo {} + +impl Foo { + fn foo(&self) { + bar(self); + //~^ ERROR cannot find function `bar` in this scope + //~| HELP try calling `bar` as a method + + bar(&&self, 102); + //~^ ERROR cannot find function `bar` in this scope + //~| HELP try calling `bar` as a method + + bar(&mut self, 102, &"str"); + //~^ ERROR cannot find function `bar` in this scope + //~| HELP try calling `bar` as a method + + bar(); + //~^ ERROR cannot find function `bar` in this scope + + self.bar(); + //~^ ERROR no method named `bar` found for type + } +} + +fn main() {} diff --git a/src/test/ui/self/suggest-self-2.stderr b/src/test/ui/self/suggest-self-2.stderr new file mode 100644 index 0000000000000..452c31275153a --- /dev/null +++ b/src/test/ui/self/suggest-self-2.stderr @@ -0,0 +1,40 @@ +error[E0425]: cannot find function `bar` in this scope + --> $DIR/suggest-self-2.rs:5:9 + | +LL | bar(self); + | ^^^------ + | | + | help: try calling `bar` as a method: `self.bar()` + +error[E0425]: cannot find function `bar` in this scope + --> $DIR/suggest-self-2.rs:9:9 + | +LL | bar(&&self, 102); + | ^^^------------- + | | + | help: try calling `bar` as a method: `self.bar(102)` + +error[E0425]: cannot find function `bar` in this scope + --> $DIR/suggest-self-2.rs:13:9 + | +LL | bar(&mut self, 102, &"str"); + | ^^^------------------------ + | | + | help: try calling `bar` as a method: `self.bar(102, &"str")` + +error[E0425]: cannot find function `bar` in this scope + --> $DIR/suggest-self-2.rs:17:9 + | +LL | bar(); + | ^^^ not found in this scope + +error[E0599]: no method named `bar` found for type `&Foo` in the current scope + --> $DIR/suggest-self-2.rs:20:14 + | +LL | self.bar(); + | ^^^ method not found in `&Foo` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0425, E0599. +For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/typeck/auxiliary/issue_66868_closure_typeck.rs b/src/test/ui/typeck/auxiliary/issue_66868_closure_typeck.rs new file mode 100644 index 0000000000000..bbeb7d431f6d6 --- /dev/null +++ b/src/test/ui/typeck/auxiliary/issue_66868_closure_typeck.rs @@ -0,0 +1,25 @@ +// edition:2018 + +#![crate_type = "lib"] + +use std::{ + future::Future, + pin::Pin, + sync::RwLock, + task::{Context, Poll}, +}; + +struct S {} + +impl Future for S { + type Output = (); + fn poll(self: Pin<&mut Self>, _: &mut Context) -> Poll<Self::Output> { + Poll::Pending + } +} + +pub async fn f() { + let fo = RwLock::new(S {}); + + (&mut *fo.write().unwrap()).await; +} diff --git a/src/test/ui/typeck/issue-66868-closure-typeck.rs b/src/test/ui/typeck/issue-66868-closure-typeck.rs new file mode 100644 index 0000000000000..322b5c82ec07d --- /dev/null +++ b/src/test/ui/typeck/issue-66868-closure-typeck.rs @@ -0,0 +1,15 @@ +// Fixed by #67071 +// aux-build: issue_66868_closure_typeck.rs +// edition:2018 + +extern crate issue_66868_closure_typeck; + +pub fn g<T>(task: T) +where + T: Send, +{ +} + +fn main() { + g(issue_66868_closure_typeck::f()); //~ ERROR: cannot be sent between threads safely +} diff --git a/src/test/ui/typeck/issue-66868-closure-typeck.stderr b/src/test/ui/typeck/issue-66868-closure-typeck.stderr new file mode 100644 index 0000000000000..42322df2eafa8 --- /dev/null +++ b/src/test/ui/typeck/issue-66868-closure-typeck.stderr @@ -0,0 +1,22 @@ +error[E0277]: `std::sync::RwLockWriteGuard<'_, issue_66868_closure_typeck::S>` cannot be sent between threads safely + --> $DIR/issue-66868-closure-typeck.rs:14:5 + | +LL | pub fn g<T>(task: T) + | - +LL | where +LL | T: Send, + | ---- required by this bound in `g` +... +LL | g(issue_66868_closure_typeck::f()); + | ^ `std::sync::RwLockWriteGuard<'_, issue_66868_closure_typeck::S>` cannot be sent between threads safely + | + = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::sync::RwLockWriteGuard<'_, issue_66868_closure_typeck::S>` + = note: required because it appears within the type `for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5> {std::sync::RwLock<issue_66868_closure_typeck::S>, &'r std::sync::RwLock<issue_66868_closure_typeck::S>, std::sync::RwLock<issue_66868_closure_typeck::S>, std::result::Result<std::sync::RwLockWriteGuard<'s, issue_66868_closure_typeck::S>, std::sync::PoisonError<std::sync::RwLockWriteGuard<'t0, issue_66868_closure_typeck::S>>>, &'t1 mut std::sync::RwLockWriteGuard<'t2, issue_66868_closure_typeck::S>, std::sync::RwLockWriteGuard<'t3, issue_66868_closure_typeck::S>, issue_66868_closure_typeck::S, &'t4 mut issue_66868_closure_typeck::S, &'t5 mut issue_66868_closure_typeck::S, ()}` + = note: required because it appears within the type `[static generator@DefId(15:16 ~ issue_66868_closure_typeck[8787]::f[0]::{{closure}}[0]) for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5> {std::sync::RwLock<issue_66868_closure_typeck::S>, &'r std::sync::RwLock<issue_66868_closure_typeck::S>, std::sync::RwLock<issue_66868_closure_typeck::S>, std::result::Result<std::sync::RwLockWriteGuard<'s, issue_66868_closure_typeck::S>, std::sync::PoisonError<std::sync::RwLockWriteGuard<'t0, issue_66868_closure_typeck::S>>>, &'t1 mut std::sync::RwLockWriteGuard<'t2, issue_66868_closure_typeck::S>, std::sync::RwLockWriteGuard<'t3, issue_66868_closure_typeck::S>, issue_66868_closure_typeck::S, &'t4 mut issue_66868_closure_typeck::S, &'t5 mut issue_66868_closure_typeck::S, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@DefId(15:16 ~ issue_66868_closure_typeck[8787]::f[0]::{{closure}}[0]) for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5> {std::sync::RwLock<issue_66868_closure_typeck::S>, &'r std::sync::RwLock<issue_66868_closure_typeck::S>, std::sync::RwLock<issue_66868_closure_typeck::S>, std::result::Result<std::sync::RwLockWriteGuard<'s, issue_66868_closure_typeck::S>, std::sync::PoisonError<std::sync::RwLockWriteGuard<'t0, issue_66868_closure_typeck::S>>>, &'t1 mut std::sync::RwLockWriteGuard<'t2, issue_66868_closure_typeck::S>, std::sync::RwLockWriteGuard<'t3, issue_66868_closure_typeck::S>, issue_66868_closure_typeck::S, &'t4 mut issue_66868_closure_typeck::S, &'t5 mut issue_66868_closure_typeck::S, ()}]>` + = note: required because it appears within the type `impl std::future::Future` + = note: required because it appears within the type `impl std::future::Future` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`.