diff --git a/Cargo.lock b/Cargo.lock index 3f8bf0ac8e890..e2a16d56e49ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3257,6 +3257,7 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", + "rustc_lexer", "rustc_macros", "rustc_serialize", "rustc_session", diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index 786d1b6ba82f2..de707a71a8c9e 100644 --- a/library/alloc/src/vec.rs +++ b/library/alloc/src/vec.rs @@ -2269,7 +2269,7 @@ impl Vec { /// with the given `replace_with` iterator and yields the removed items. /// `replace_with` does not need to be the same length as `range`. /// - /// The element range is removed even if the iterator is not consumed until the end. + /// `range` is removed even if the iterator is not consumed until the end. /// /// It is unspecified how many elements are removed from the vector /// if the `Splice` value is leaked. diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index a16970e9fd180..ac20897d258fb 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -662,6 +662,11 @@ impl *const T { /// will only affect the pointer part, whereas for (thin) pointers to /// sized types, this has the same effect as a simple assignment. /// + /// The resulting pointer will have provenance of `val`, i.e., for a fat + /// pointer, this operation is semantically the same as creating a new + /// fat pointer with the data pointer value of `val` but the metadata of + /// `self`. + /// /// # Examples /// /// This function is primarily useful for allowing byte-wise pointer @@ -673,13 +678,17 @@ impl *const T { /// let arr: [i32; 3] = [1, 2, 3]; /// let mut ptr = &arr[0] as *const dyn Debug; /// let thin = ptr as *const u8; - /// ptr = ptr.set_ptr_value(unsafe { thin.add(8).cast() }); - /// assert_eq!(unsafe { *(ptr as *const i32) }, 3); + /// unsafe { + /// ptr = ptr.set_ptr_value(thin.add(8)); + /// # assert_eq!(*(ptr as *const i32), 3); + /// println!("{:?}", &*ptr); // will print "3" + /// } /// ``` #[unstable(feature = "set_ptr_value", issue = "75091")] + #[must_use = "returns a new pointer rather than modifying its argument"] #[inline] - pub fn set_ptr_value(mut self, val: *const ()) -> Self { - let thin = &mut self as *mut *const T as *mut *const (); + pub fn set_ptr_value(mut self, val: *const u8) -> Self { + let thin = &mut self as *mut *const T as *mut *const u8; // SAFETY: In case of a thin pointer, this operations is identical // to a simple assignment. In case of a fat pointer, with the current // fat pointer layout implementation, the first field of such a diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index b47f90c599629..df00139118aa4 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -718,6 +718,11 @@ impl *mut T { /// will only affect the pointer part, whereas for (thin) pointers to /// sized types, this has the same effect as a simple assignment. /// + /// The resulting pointer will have provenance of `val`, i.e., for a fat + /// pointer, this operation is semantically the same as creating a new + /// fat pointer with the data pointer value of `val` but the metadata of + /// `self`. + /// /// # Examples /// /// This function is primarily useful for allowing byte-wise pointer @@ -729,13 +734,17 @@ impl *mut T { /// let mut arr: [i32; 3] = [1, 2, 3]; /// let mut ptr = &mut arr[0] as *mut dyn Debug; /// let thin = ptr as *mut u8; - /// ptr = ptr.set_ptr_value(unsafe { thin.add(8).cast() }); - /// assert_eq!(unsafe { *(ptr as *mut i32) }, 3); + /// unsafe { + /// ptr = ptr.set_ptr_value(thin.add(8)); + /// # assert_eq!(*(ptr as *mut i32), 3); + /// println!("{:?}", &*ptr); // will print "3" + /// } /// ``` #[unstable(feature = "set_ptr_value", issue = "75091")] + #[must_use = "returns a new pointer rather than modifying its argument"] #[inline] - pub fn set_ptr_value(mut self, val: *mut ()) -> Self { - let thin = &mut self as *mut *mut T as *mut *mut (); + pub fn set_ptr_value(mut self, val: *mut u8) -> Self { + let thin = &mut self as *mut *mut T as *mut *mut u8; // SAFETY: In case of a thin pointer, this operations is identical // to a simple assignment. In case of a fat pointer, with the current // fat pointer layout implementation, the first field of such a diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 5d103e6403750..ccaacbf1a58a9 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -767,10 +767,8 @@ impl Ipv4Addr { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn to_ipv6_compatible(&self) -> Ipv6Addr { - let octets = self.octets(); - Ipv6Addr::from([ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, octets[0], octets[1], octets[2], octets[3], - ]) + let [a, b, c, d] = self.octets(); + Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d]) } /// Converts this address to an IPv4-mapped [IPv6 address]. @@ -789,10 +787,8 @@ impl Ipv4Addr { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn to_ipv6_mapped(&self) -> Ipv6Addr { - let octets = self.octets(); - Ipv6Addr::from([ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, octets[0], octets[1], octets[2], octets[3], - ]) + let [a, b, c, d] = self.octets(); + Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d]) } } @@ -1498,11 +1494,12 @@ impl Ipv6Addr { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn to_ipv4(&self) -> Option { - match self.segments() { - [0, 0, 0, 0, 0, f, g, h] if f == 0 || f == 0xffff => { - Some(Ipv4Addr::new((g >> 8) as u8, g as u8, (h >> 8) as u8, h as u8)) - } - _ => None, + if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() { + let [a, b] = ab.to_be_bytes(); + let [c, d] = cd.to_be_bytes(); + Some(Ipv4Addr::new(a, b, c, d)) + } else { + None } } diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 0ff77de003d31..165ecc7918044 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -490,15 +490,17 @@ jobs: # 32/64-bit MinGW builds. # - # We are using MinGW with posix threads since LLVM does not compile with - # the win32 threads version due to missing support for C++'s std::thread. + # We are using MinGW with POSIX threads since LLVM requires + # C++'s std::thread which is disabled in libstdc++ with win32 threads. + # FIXME: Libc++ doesn't have this limitation so we can avoid + # winpthreads if we switch to it. # - # Instead of relying on the MinGW version installed on appveryor we download - # and install one ourselves so we won't be surprised by changes to appveyor's + # Instead of relying on the MinGW version installed on CI we download + # and install one ourselves so we won't be surprised by changes to CI's # build image. # # Finally, note that the downloads below are all in the `rust-lang-ci` S3 - # bucket, but they cleraly didn't originate there! The downloads originally + # bucket, but they clearly didn't originate there! The downloads originally # came from the mingw-w64 SourceForge download site. Unfortunately # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. diff --git a/src/librustc_attr/Cargo.toml b/src/librustc_attr/Cargo.toml index 496becb8f1b59..35bdf747f08d7 100644 --- a/src/librustc_attr/Cargo.toml +++ b/src/librustc_attr/Cargo.toml @@ -16,6 +16,7 @@ rustc_errors = { path = "../librustc_errors" } rustc_span = { path = "../librustc_span" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_feature = { path = "../librustc_feature" } +rustc_lexer = { path = "../librustc_lexer" } rustc_macros = { path = "../librustc_macros" } rustc_session = { path = "../librustc_session" } rustc_ast = { path = "../librustc_ast" } diff --git a/src/librustc_attr/builtin.rs b/src/librustc_attr/builtin.rs index 552584bb4d0b9..5f131fae385b0 100644 --- a/src/librustc_attr/builtin.rs +++ b/src/librustc_attr/builtin.rs @@ -20,6 +20,7 @@ enum AttrError { MultipleItem(String), UnknownMetaItem(String, &'static [&'static str]), MissingSince, + NonIdentFeature, MissingFeature, MultipleStabilityLevels, UnsupportedLiteral(&'static str, /* is_bytestr */ bool), @@ -40,6 +41,9 @@ fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) { AttrError::MissingSince => { struct_span_err!(diag, span, E0542, "missing 'since'").emit(); } + AttrError::NonIdentFeature => { + struct_span_err!(diag, span, E0546, "'feature' is not an identifier").emit(); + } AttrError::MissingFeature => { struct_span_err!(diag, span, E0546, "missing 'feature'").emit(); } @@ -344,6 +348,14 @@ where match (feature, reason, issue) { (Some(feature), reason, Some(_)) => { + if !rustc_lexer::is_ident(&feature.as_str()) { + handle_errors( + &sess.parse_sess, + attr.span, + AttrError::NonIdentFeature, + ); + continue; + } let level = Unstable { reason, issue: issue_num, is_soft }; if sym::unstable == meta_name { stab = Some(Stability { level, feature }); diff --git a/src/librustc_expand/proc_macro_server.rs b/src/librustc_expand/proc_macro_server.rs index dc7ba2d0424fc..83a650443bcba 100644 --- a/src/librustc_expand/proc_macro_server.rs +++ b/src/librustc_expand/proc_macro_server.rs @@ -319,18 +319,10 @@ pub struct Ident { } impl Ident { - fn is_valid(string: &str) -> bool { - let mut chars = string.chars(); - if let Some(start) = chars.next() { - rustc_lexer::is_id_start(start) && chars.all(rustc_lexer::is_id_continue) - } else { - false - } - } fn new(sess: &ParseSess, sym: Symbol, is_raw: bool, span: Span) -> Ident { let sym = nfc_normalize(&sym.as_str()); let string = sym.as_str(); - if !Self::is_valid(&string) { + if !rustc_lexer::is_ident(&string) { panic!("`{:?}` is not a valid identifier", string) } if is_raw && !sym.can_be_raw() { diff --git a/src/librustc_lexer/src/lib.rs b/src/librustc_lexer/src/lib.rs index 862ffd50d38f6..7949a232b9b35 100644 --- a/src/librustc_lexer/src/lib.rs +++ b/src/librustc_lexer/src/lib.rs @@ -274,6 +274,16 @@ pub fn is_id_continue(c: char) -> bool { || (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_continue(c)) } +/// The passed string is lexically an identifier. +pub fn is_ident(string: &str) -> bool { + let mut chars = string.chars(); + if let Some(start) = chars.next() { + is_id_start(start) && chars.all(is_id_continue) + } else { + false + } +} + impl Cursor<'_> { /// Parses a token from the input string. fn advance_token(&mut self) -> Token { diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 15a9affbff7e9..1f17c7dcba43f 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -219,7 +219,7 @@ pub fn new_lint_store(no_interleave_lints: bool, internal_lints: bool) -> LintSt /// Tell the `LintStore` about all the built-in lints (the ones /// defined in this crate and the ones defined in -/// `rustc::lint::builtin`). +/// `rustc_session::lint::builtin`). fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { macro_rules! add_lint_group { ($name:expr, $($lint:ident),*) => ( diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 3afd3671d6ba6..801d06e610169 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2358,7 +2358,7 @@ impl Clean for attr::Stability { fn clean(&self, _: &DocContext<'_>) -> Stability { Stability { level: stability::StabilityLevel::from_attr_level(&self.level), - feature: Some(self.feature.to_string()).filter(|f| !f.is_empty()), + feature: self.feature.to_string(), since: match self.level { attr::Stable { ref since } => since.to_string(), _ => String::new(), diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 50eca75d7cab2..627f88df45c9f 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1525,7 +1525,7 @@ pub struct ProcMacro { #[derive(Clone, Debug)] pub struct Stability { pub level: stability::StabilityLevel, - pub feature: Option, + pub feature: String, pub since: String, pub unstable_reason: Option, pub issue: Option, diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 3635753969286..bd919205dd176 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2144,7 +2144,7 @@ fn stability_tags(item: &clean::Item) -> String { if item .stability .as_ref() - .map(|s| s.level == stability::Unstable && s.feature.as_deref() != Some("rustc_private")) + .map(|s| s.level == stability::Unstable && s.feature != "rustc_private") == Some(true) { tags += &tag_html("unstable", "Experimental"); @@ -2195,25 +2195,25 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { // Render unstable items. But don't render "rustc_private" crates (internal compiler crates). // Those crates are permanently unstable so it makes no sense to render "unstable" everywhere. - if let Some(stab) = item.stability.as_ref().filter(|stab| { - stab.level == stability::Unstable && stab.feature.as_deref() != Some("rustc_private") - }) { + if let Some(stab) = item + .stability + .as_ref() + .filter(|stab| stab.level == stability::Unstable && stab.feature != "rustc_private") + { let mut message = "🔬 This is a nightly-only experimental API.".to_owned(); - if let Some(feature) = stab.feature.as_deref() { - let mut feature = format!("{}", Escape(&feature)); - if let (Some(url), Some(issue)) = (&cx.shared.issue_tracker_base_url, stab.issue) { - feature.push_str(&format!( - " #{issue}", - url = url, - issue = issue - )); - } - - message.push_str(&format!(" ({})", feature)); + let mut feature = format!("{}", Escape(&stab.feature)); + if let (Some(url), Some(issue)) = (&cx.shared.issue_tracker_base_url, stab.issue) { + feature.push_str(&format!( + " #{issue}", + url = url, + issue = issue + )); } + message.push_str(&format!(" ({})", feature)); + if let Some(unstable_reason) = &stab.unstable_reason { let mut ids = cx.id_map.borrow_mut(); message = format!( diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 63853e7394b4d..462a696dee6ef 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -408,9 +408,7 @@ function defocusSearchBar() { break; case "?": - if (ev.shiftKey) { - displayHelp(true, ev); - } + displayHelp(true, ev); break; } }