From 52ed89ae8c264d8885bfda4f79033289db459c02 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 28 May 2020 10:31:38 +0200 Subject: [PATCH 01/10] from_u32_unchecked: check validity when debug assertions are enabled --- src/libcore/char/convert.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/char/convert.rs b/src/libcore/char/convert.rs index 315020bac5850..87c56c4b0a105 100644 --- a/src/libcore/char/convert.rs +++ b/src/libcore/char/convert.rs @@ -99,7 +99,7 @@ pub fn from_u32(i: u32) -> Option { #[inline] #[stable(feature = "char_from_unchecked", since = "1.5.0")] pub unsafe fn from_u32_unchecked(i: u32) -> char { - transmute(i) + if cfg!(debug_assertions) { char::from_u32(i).unwrap() } else { transmute(i) } } #[stable(feature = "char_convert", since = "1.13.0")] @@ -218,7 +218,7 @@ impl TryFrom for char { Err(CharTryFromError(())) } else { // SAFETY: checked that it's a legal unicode value - Ok(unsafe { from_u32_unchecked(i) }) + Ok(unsafe { transmute(i) }) } } } From 04243710a0077ad140b8259c21bc1aac02057a48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 28 May 2020 16:31:48 -0700 Subject: [PATCH 02/10] Account for trailing comma when suggesting `where` clauses Fix #72693. --- src/librustc_middle/ty/diagnostics.rs | 21 ++++++++----------- .../traits/error_reporting/suggestions.rs | 11 +++++++++- src/test/ui/bound-suggestions.rs | 2 +- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/librustc_middle/ty/diagnostics.rs b/src/librustc_middle/ty/diagnostics.rs index 613d66d59c55b..96c36d989e928 100644 --- a/src/librustc_middle/ty/diagnostics.rs +++ b/src/librustc_middle/ty/diagnostics.rs @@ -7,7 +7,6 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate}; -use rustc_span::{BytePos, Span}; impl<'tcx> TyS<'tcx> { /// Similar to `TyS::is_primitive`, but also considers inferred numeric values to be primitive. @@ -221,18 +220,16 @@ pub fn suggest_constraining_type_param( } } - let where_clause_span = generics.where_clause.span_for_predicates_or_empty_place(); // Account for `fn foo(t: T) where T: Foo,` so we don't suggest two trailing commas. - let mut trailing_comma = false; - if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(where_clause_span) { - trailing_comma = snippet.ends_with(','); - } - let where_clause_span = if trailing_comma { - let hi = where_clause_span.hi(); - Span::new(hi - BytePos(1), hi, where_clause_span.ctxt()) - } else { - where_clause_span.shrink_to_hi() - }; + let end = generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(); + let where_clause_span = generics + .where_clause + .predicates + .last() + .map(|p| p.span()) + .unwrap_or(end) + .shrink_to_hi() + .to(end); match ¶m_spans[..] { &[¶m_span] => suggest_restrict(param_span.shrink_to_hi()), diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 5c85855535e38..eb281b270ff2a 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -169,8 +169,17 @@ pub trait InferCtxtExt<'tcx> { } fn predicate_constraint(generics: &hir::Generics<'_>, pred: String) -> (Span, String) { + let end = generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(); ( - generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(), + // Account for `where T: Foo,` so we don't suggest two trailing commas. + generics + .where_clause + .predicates + .last() + .map(|p| p.span()) + .unwrap_or(end) + .shrink_to_hi() + .to(end), format!( "{} {}", if !generics.where_clause.predicates.is_empty() { "," } else { " where" }, diff --git a/src/test/ui/bound-suggestions.rs b/src/test/ui/bound-suggestions.rs index 605a6df838658..562dec9f080de 100644 --- a/src/test/ui/bound-suggestions.rs +++ b/src/test/ui/bound-suggestions.rs @@ -19,7 +19,7 @@ fn test_one_bound(t: T) { } #[allow(dead_code)] -fn test_no_bounds_where(x: X, y: Y) where X: std::fmt::Debug { +fn test_no_bounds_where(x: X, y: Y) where X: std::fmt::Debug, { println!("{:?} {:?}", x, y); //~^ ERROR doesn't implement } From 0d18136b776cd7cda2c4932f447e6484377f42b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 29 May 2020 09:44:41 -0700 Subject: [PATCH 03/10] Move common code to `WhereClause` --- src/librustc_hir/hir.rs | 7 +++++++ src/librustc_middle/ty/diagnostics.rs | 13 +------------ .../traits/error_reporting/suggestions.rs | 11 +---------- 3 files changed, 9 insertions(+), 22 deletions(-) diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index ef398ab25d3fb..a46871ac80798 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -525,6 +525,13 @@ impl WhereClause<'_> { pub fn span_for_predicates_or_empty_place(&self) -> Span { self.span } + + /// `Span` where further predicates would be suggested, accounting for trailing commas, like + /// in `fn foo(t: T) where T: Foo,` so we don't suggest two trailing commas. + pub fn tail_span_for_suggestion(&self) -> Span { + let end = self.span_for_predicates_or_empty_place().shrink_to_hi(); + self.predicates.last().map(|p| p.span()).unwrap_or(end).shrink_to_hi().to(end) + } } /// A single predicate in a where-clause. diff --git a/src/librustc_middle/ty/diagnostics.rs b/src/librustc_middle/ty/diagnostics.rs index 96c36d989e928..ba3cc0a7af2c6 100644 --- a/src/librustc_middle/ty/diagnostics.rs +++ b/src/librustc_middle/ty/diagnostics.rs @@ -220,22 +220,11 @@ pub fn suggest_constraining_type_param( } } - // Account for `fn foo(t: T) where T: Foo,` so we don't suggest two trailing commas. - let end = generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(); - let where_clause_span = generics - .where_clause - .predicates - .last() - .map(|p| p.span()) - .unwrap_or(end) - .shrink_to_hi() - .to(end); - match ¶m_spans[..] { &[¶m_span] => suggest_restrict(param_span.shrink_to_hi()), _ => { err.span_suggestion_verbose( - where_clause_span, + generics.where_clause.tail_span_for_suggestion(), &msg_restrict_type_further, format!(", {}: {}", param_name, constraint), Applicability::MachineApplicable, diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index eb281b270ff2a..a8d4de873f958 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -169,17 +169,8 @@ pub trait InferCtxtExt<'tcx> { } fn predicate_constraint(generics: &hir::Generics<'_>, pred: String) -> (Span, String) { - let end = generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(); ( - // Account for `where T: Foo,` so we don't suggest two trailing commas. - generics - .where_clause - .predicates - .last() - .map(|p| p.span()) - .unwrap_or(end) - .shrink_to_hi() - .to(end), + generics.where_clause.tail_span_for_suggestion(), format!( "{} {}", if !generics.where_clause.predicates.is_empty() { "," } else { " where" }, From 15955772276e5574414a6ff630495a9898a99efb Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Fri, 29 May 2020 19:48:47 +0200 Subject: [PATCH 04/10] Borrow<[T]> for Interned<'tcx, List> --- src/librustc_middle/ty/context.rs | 50 ++----------------------------- 1 file changed, 2 insertions(+), 48 deletions(-) diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index 7a20014484190..a2e8771e05895 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -1924,32 +1924,8 @@ impl<'tcx, T: Hash> Hash for Interned<'tcx, List> { } } -impl<'tcx> Borrow<[Ty<'tcx>]> for Interned<'tcx, List>> { - fn borrow<'a>(&'a self) -> &'a [Ty<'tcx>] { - &self.0[..] - } -} - -impl<'tcx> Borrow<[CanonicalVarInfo]> for Interned<'tcx, List> { - fn borrow(&self) -> &[CanonicalVarInfo] { - &self.0[..] - } -} - -impl<'tcx> Borrow<[GenericArg<'tcx>]> for Interned<'tcx, InternalSubsts<'tcx>> { - fn borrow<'a>(&'a self) -> &'a [GenericArg<'tcx>] { - &self.0[..] - } -} - -impl<'tcx> Borrow<[ProjectionKind]> for Interned<'tcx, List> { - fn borrow(&self) -> &[ProjectionKind] { - &self.0[..] - } -} - -impl<'tcx> Borrow<[PlaceElem<'tcx>]> for Interned<'tcx, List>> { - fn borrow(&self) -> &[PlaceElem<'tcx>] { +impl<'tcx, T> Borrow<[T]> for Interned<'tcx, List> { + fn borrow<'a>(&'a self) -> &'a [T] { &self.0[..] } } @@ -1960,34 +1936,12 @@ impl<'tcx> Borrow for Interned<'tcx, RegionKind> { } } -impl<'tcx> Borrow<[ExistentialPredicate<'tcx>]> - for Interned<'tcx, List>> -{ - fn borrow<'a>(&'a self) -> &'a [ExistentialPredicate<'tcx>] { - &self.0[..] - } -} - -impl<'tcx> Borrow<[Predicate<'tcx>]> for Interned<'tcx, List>> { - fn borrow<'a>(&'a self) -> &'a [Predicate<'tcx>] { - &self.0[..] - } -} - impl<'tcx> Borrow> for Interned<'tcx, Const<'tcx>> { fn borrow<'a>(&'a self) -> &'a Const<'tcx> { &self.0 } } -impl<'tcx> Borrow<[traits::ChalkEnvironmentClause<'tcx>]> - for Interned<'tcx, List>> -{ - fn borrow<'a>(&'a self) -> &'a [traits::ChalkEnvironmentClause<'tcx>] { - &self.0[..] - } -} - impl<'tcx> Borrow> for Interned<'tcx, PredicateKind<'tcx>> { fn borrow<'a>(&'a self) -> &'a PredicateKind<'tcx> { &self.0 From 72d85db6eea29004a467842923c07169bc304217 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 30 May 2020 11:49:31 +0200 Subject: [PATCH 05/10] expose char::encode_utf8_raw for libstd --- src/libcore/char/methods.rs | 99 ++++++++++++++++++++++--------------- src/libcore/char/mod.rs | 4 ++ 2 files changed, 63 insertions(+), 40 deletions(-) diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs index 5c5bc9adb5df2..112e7e38e414b 100644 --- a/src/libcore/char/methods.rs +++ b/src/libcore/char/methods.rs @@ -593,16 +593,7 @@ impl char { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn len_utf8(self) -> usize { - let code = self as u32; - if code < MAX_ONE_B { - 1 - } else if code < MAX_TWO_B { - 2 - } else if code < MAX_THREE_B { - 3 - } else { - 4 - } + len_utf8(self as u32) } /// Returns the number of 16-bit code units this `char` would need if @@ -670,36 +661,7 @@ impl char { #[stable(feature = "unicode_encode_char", since = "1.15.0")] #[inline] pub fn encode_utf8(self, dst: &mut [u8]) -> &mut str { - let code = self as u32; - let len = self.len_utf8(); - match (len, &mut dst[..]) { - (1, [a, ..]) => { - *a = code as u8; - } - (2, [a, b, ..]) => { - *a = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; - *b = (code & 0x3F) as u8 | TAG_CONT; - } - (3, [a, b, c, ..]) => { - *a = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; - *b = (code >> 6 & 0x3F) as u8 | TAG_CONT; - *c = (code & 0x3F) as u8 | TAG_CONT; - } - (4, [a, b, c, d, ..]) => { - *a = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; - *b = (code >> 12 & 0x3F) as u8 | TAG_CONT; - *c = (code >> 6 & 0x3F) as u8 | TAG_CONT; - *d = (code & 0x3F) as u8 | TAG_CONT; - } - _ => panic!( - "encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}", - len, - code, - dst.len(), - ), - }; - // SAFETY: We just wrote UTF-8 content in, so converting to str is fine. - unsafe { from_utf8_unchecked_mut(&mut dst[..len]) } + encode_utf8_raw(self as u32, dst) } /// Encodes this character as UTF-16 into the provided `u16` buffer, @@ -1673,3 +1635,60 @@ impl char { } } } + +#[inline] +fn len_utf8(code: u32) -> usize { + if code < MAX_ONE_B { + 1 + } else if code < MAX_TWO_B { + 2 + } else if code < MAX_THREE_B { + 3 + } else { + 4 + } +} + +/// Encodes a raw u32 value as UTF-8 into the provided byte buffer, +/// and then returns the subslice of the buffer that contains the encoded character. +/// +/// Unlike `char::encode_utf8`, this method can be called on codepoints in the surrogate range. +/// +/// # Panics +/// +/// Panics if the buffer is not large enough. +/// A buffer of length four is large enough to encode any `char`. +#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] +#[doc(hidden)] +#[inline] +pub fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut str { + let len = len_utf8(code); + match (len, &mut dst[..]) { + (1, [a, ..]) => { + *a = code as u8; + } + (2, [a, b, ..]) => { + *a = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; + *b = (code & 0x3F) as u8 | TAG_CONT; + } + (3, [a, b, c, ..]) => { + *a = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; + *b = (code >> 6 & 0x3F) as u8 | TAG_CONT; + *c = (code & 0x3F) as u8 | TAG_CONT; + } + (4, [a, b, c, d, ..]) => { + *a = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; + *b = (code >> 12 & 0x3F) as u8 | TAG_CONT; + *c = (code >> 6 & 0x3F) as u8 | TAG_CONT; + *d = (code & 0x3F) as u8 | TAG_CONT; + } + _ => panic!( + "encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}", + len, + code, + dst.len(), + ), + }; + // SAFETY: We just wrote UTF-8 content in, so converting to str is fine. + unsafe { from_utf8_unchecked_mut(&mut dst[..len]) } +} diff --git a/src/libcore/char/mod.rs b/src/libcore/char/mod.rs index bf65c31e13597..40b429b749668 100644 --- a/src/libcore/char/mod.rs +++ b/src/libcore/char/mod.rs @@ -37,6 +37,10 @@ pub use self::decode::{decode_utf16, DecodeUtf16, DecodeUtf16Error}; #[stable(feature = "unicode_version", since = "1.45.0")] pub use crate::unicode::UNICODE_VERSION; +// perma-unstable re-exports +#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] +pub use self::methods::encode_utf8_raw; + use crate::fmt::{self, Write}; use crate::iter::FusedIterator; From 3182cdf9baf8ed9e8ae24f4742ee5d3d01c2b54a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 30 May 2020 11:53:50 +0200 Subject: [PATCH 06/10] wtf8: use encode_utf8_raw --- src/libstd/lib.rs | 1 + src/libstd/sys_common/wtf8.rs | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index cc3e613fa3d60..3e3c1fd9026bc 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -247,6 +247,7 @@ #![feature(cfg_target_has_atomic)] #![feature(cfg_target_thread_local)] #![feature(char_error_internals)] +#![feature(char_internals)] #![feature(clamp)] #![feature(concat_idents)] #![feature(const_cstr_unchecked)] diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index a98407da44850..90bbf4afd1a32 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -201,9 +201,8 @@ impl Wtf8Buf { /// Copied from String::push /// This does **not** include the WTF-8 concatenation check. fn push_code_point_unchecked(&mut self, code_point: CodePoint) { - let c = unsafe { char::from_u32_unchecked(code_point.value) }; let mut bytes = [0; 4]; - let bytes = c.encode_utf8(&mut bytes).as_bytes(); + let bytes = char::encode_utf8_raw(code_point.value, &mut bytes).as_bytes(); self.bytes.extend_from_slice(bytes) } From 9c627c33dde998cfe42bcde07e1c5692370daf63 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 30 May 2020 12:08:55 +0200 Subject: [PATCH 07/10] also expose and use encode_utf16_raw for wtf8 --- src/libcore/char/methods.rs | 59 ++++++++++++++++++++++------------- src/libcore/char/mod.rs | 2 ++ src/libstd/sys_common/wtf8.rs | 3 +- 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs index 112e7e38e414b..b1b3c70efb1c7 100644 --- a/src/libcore/char/methods.rs +++ b/src/libcore/char/methods.rs @@ -701,28 +701,7 @@ impl char { #[stable(feature = "unicode_encode_char", since = "1.15.0")] #[inline] pub fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16] { - let mut code = self as u32; - // SAFETY: each arm checks whether there are enough bits to write into - unsafe { - if (code & 0xFFFF) == code && !dst.is_empty() { - // The BMP falls through (assuming non-surrogate, as it should) - *dst.get_unchecked_mut(0) = code as u16; - slice::from_raw_parts_mut(dst.as_mut_ptr(), 1) - } else if dst.len() >= 2 { - // Supplementary planes break into surrogates. - code -= 0x1_0000; - *dst.get_unchecked_mut(0) = 0xD800 | ((code >> 10) as u16); - *dst.get_unchecked_mut(1) = 0xDC00 | ((code as u16) & 0x3FF); - slice::from_raw_parts_mut(dst.as_mut_ptr(), 2) - } else { - panic!( - "encode_utf16: need {} units to encode U+{:X}, but the buffer has {}", - from_u32_unchecked(code).len_utf16(), - code, - dst.len(), - ) - } - } + encode_utf16_raw(self as u32, dst) } /// Returns `true` if this `char` has the `Alphabetic` property. @@ -1692,3 +1671,39 @@ pub fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut str { // SAFETY: We just wrote UTF-8 content in, so converting to str is fine. unsafe { from_utf8_unchecked_mut(&mut dst[..len]) } } + +/// Encodes a raw u32 value as UTF-16 into the provided `u16` buffer, +/// and then returns the subslice of the buffer that contains the encoded character. +/// +/// Unlike `char::encode_utf16`, this method can be called on codepoints in the surrogate range. +/// +/// # Panics +/// +/// Panics if the buffer is not large enough. +/// A buffer of length 2 is large enough to encode any `char`. +#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] +#[doc(hidden)] +#[inline] +pub fn encode_utf16_raw(mut code: u32, dst: &mut [u16]) -> &mut [u16] { + // SAFETY: each arm checks whether there are enough bits to write into + unsafe { + if (code & 0xFFFF) == code && !dst.is_empty() { + // The BMP falls through (assuming non-surrogate, as it should) + *dst.get_unchecked_mut(0) = code as u16; + slice::from_raw_parts_mut(dst.as_mut_ptr(), 1) + } else if dst.len() >= 2 { + // Supplementary planes break into surrogates. + code -= 0x1_0000; + *dst.get_unchecked_mut(0) = 0xD800 | ((code >> 10) as u16); + *dst.get_unchecked_mut(1) = 0xDC00 | ((code as u16) & 0x3FF); + slice::from_raw_parts_mut(dst.as_mut_ptr(), 2) + } else { + panic!( + "encode_utf16: need {} units to encode U+{:X}, but the buffer has {}", + from_u32_unchecked(code).len_utf16(), + code, + dst.len(), + ) + } + } +} diff --git a/src/libcore/char/mod.rs b/src/libcore/char/mod.rs index 40b429b749668..1b4e906e4e475 100644 --- a/src/libcore/char/mod.rs +++ b/src/libcore/char/mod.rs @@ -39,6 +39,8 @@ pub use crate::unicode::UNICODE_VERSION; // perma-unstable re-exports #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] +pub use self::methods::encode_utf16_raw; +#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] pub use self::methods::encode_utf8_raw; use crate::fmt::{self, Write}; diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 90bbf4afd1a32..9f589c93ae59c 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -828,8 +828,7 @@ impl<'a> Iterator for EncodeWide<'a> { let mut buf = [0; 2]; self.code_points.next().map(|code_point| { - let c = unsafe { char::from_u32_unchecked(code_point.value) }; - let n = c.encode_utf16(&mut buf).len(); + let n = char::encode_utf16_raw(code_point.value, &mut buf).len(); if n == 2 { self.extra = buf[1]; } From 372ba2a03d7180c3a58631ecbd93e8912e697bab Mon Sep 17 00:00:00 2001 From: marmeladema Date: Sat, 30 May 2020 14:38:46 +0100 Subject: [PATCH 08/10] Use `LocalDefId` instead of `NodeId` in `resolve_str_path_error` --- src/librustc_resolve/lib.rs | 7 ++----- src/librustdoc/core.rs | 10 +++++++--- src/librustdoc/passes/collect_intra_doc_links.rs | 6 +++--- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b50f9fe8e907d..e5fc23e14d2ab 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2902,7 +2902,7 @@ impl<'a> Resolver<'a> { span: Span, path_str: &str, ns: Namespace, - module_id: NodeId, + module_id: LocalDefId, ) -> Result<(ast::Path, Res), ()> { let path = if path_str.starts_with("::") { ast::Path { @@ -2922,10 +2922,7 @@ impl<'a> Resolver<'a> { .collect(), } }; - let module = self.block_map.get(&module_id).copied().unwrap_or_else(|| { - let def_id = self.definitions.local_def_id(module_id); - self.module_map.get(&def_id).copied().unwrap_or(self.graph_root) - }); + let module = self.module_map.get(&module_id).copied().unwrap_or(self.graph_root); let parent_scope = &ParentScope::module(module); let res = self.resolve_ast_path(&path, ns, parent_scope).map_err(|_| ())?; Ok((path, res)) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 99ca7084c30dd..06293a987124e 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -1,4 +1,3 @@ -use rustc_ast::ast::CRATE_NODE_ID; use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{self, Lrc}; @@ -7,7 +6,7 @@ use rustc_errors::emitter::{Emitter, EmitterWriter}; use rustc_errors::json::JsonEmitter; use rustc_feature::UnstableFeatures; use rustc_hir::def::Namespace::TypeNS; -use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::HirId; use rustc_interface::interface; use rustc_middle::middle::cstore::CrateStore; @@ -390,7 +389,12 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt resolver.borrow_mut().access(|resolver| { for extern_name in &extern_names { resolver - .resolve_str_path_error(DUMMY_SP, extern_name, TypeNS, CRATE_NODE_ID) + .resolve_str_path_error( + DUMMY_SP, + extern_name, + TypeNS, + LocalDefId { local_def_index: CRATE_DEF_INDEX }, + ) .unwrap_or_else(|()| { panic!("Unable to resolve external crate {}", extern_name) }); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index adb7fc3eb9cff..149480ec80f29 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -8,7 +8,7 @@ use rustc_hir::def::{ Namespace::{self, *}, PerNS, Res, }; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty; use rustc_resolve::ParentScope; use rustc_session::lint; @@ -61,7 +61,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { &self, path_str: &str, current_item: &Option, - module_id: rustc_ast::ast::NodeId, + module_id: LocalDefId, ) -> Result<(Res, Option), ErrorKind> { let cx = self.cx; @@ -137,7 +137,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { // In case we're in a module, try to resolve the relative path. if let Some(module_id) = parent_id.or(self.mod_ids.last().cloned()) { - let module_id = cx.tcx.hir().hir_id_to_node_id(module_id); + let module_id = cx.tcx.hir().local_def_id(module_id); let result = cx.enter_resolver(|resolver| { resolver.resolve_str_path_error(DUMMY_SP, &path_str, ns, module_id) }); From 0fb6e63c0438ace4ad9d496376af955c0baacf04 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 30 May 2020 17:13:07 +0200 Subject: [PATCH 09/10] encode_utf8_raw is not always valid UTF-8; clarify comments --- src/libcore/char/methods.rs | 19 ++++++++++++------- src/libstd/sys_common/wtf8.rs | 2 +- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs index b1b3c70efb1c7..bf09b28ff693e 100644 --- a/src/libcore/char/methods.rs +++ b/src/libcore/char/methods.rs @@ -661,7 +661,8 @@ impl char { #[stable(feature = "unicode_encode_char", since = "1.15.0")] #[inline] pub fn encode_utf8(self, dst: &mut [u8]) -> &mut str { - encode_utf8_raw(self as u32, dst) + // SAFETY: `char` is not a surrogate, so this is valid UTF-8. + unsafe { from_utf8_unchecked_mut(encode_utf8_raw(self as u32, dst)) } } /// Encodes this character as UTF-16 into the provided `u16` buffer, @@ -1631,7 +1632,11 @@ fn len_utf8(code: u32) -> usize { /// Encodes a raw u32 value as UTF-8 into the provided byte buffer, /// and then returns the subslice of the buffer that contains the encoded character. /// -/// Unlike `char::encode_utf8`, this method can be called on codepoints in the surrogate range. +/// Unlike `char::encode_utf8`, this method also handles codepoints in the surrogate range. +/// (Creating a `char` in the surrogate range is UB.) +/// The result is valid [generalized UTF-8] but not valid UTF-8. +/// +/// [generalized UTF-8]: https://simonsapin.github.io/wtf-8/#generalized-utf8 /// /// # Panics /// @@ -1640,7 +1645,7 @@ fn len_utf8(code: u32) -> usize { #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] #[doc(hidden)] #[inline] -pub fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut str { +pub fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] { let len = len_utf8(code); match (len, &mut dst[..]) { (1, [a, ..]) => { @@ -1668,14 +1673,14 @@ pub fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut str { dst.len(), ), }; - // SAFETY: We just wrote UTF-8 content in, so converting to str is fine. - unsafe { from_utf8_unchecked_mut(&mut dst[..len]) } + &mut dst[..len] } /// Encodes a raw u32 value as UTF-16 into the provided `u16` buffer, /// and then returns the subslice of the buffer that contains the encoded character. /// -/// Unlike `char::encode_utf16`, this method can be called on codepoints in the surrogate range. +/// Unlike `char::encode_utf16`, this method also handles codepoints in the surrogate range. +/// (Creating a `char` in the surrogate range is UB.) /// /// # Panics /// @@ -1688,7 +1693,7 @@ pub fn encode_utf16_raw(mut code: u32, dst: &mut [u16]) -> &mut [u16] { // SAFETY: each arm checks whether there are enough bits to write into unsafe { if (code & 0xFFFF) == code && !dst.is_empty() { - // The BMP falls through (assuming non-surrogate, as it should) + // The BMP falls through *dst.get_unchecked_mut(0) = code as u16; slice::from_raw_parts_mut(dst.as_mut_ptr(), 1) } else if dst.len() >= 2 { diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 9f589c93ae59c..ccb54b7e68d18 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -202,7 +202,7 @@ impl Wtf8Buf { /// This does **not** include the WTF-8 concatenation check. fn push_code_point_unchecked(&mut self, code_point: CodePoint) { let mut bytes = [0; 4]; - let bytes = char::encode_utf8_raw(code_point.value, &mut bytes).as_bytes(); + let bytes = char::encode_utf8_raw(code_point.value, &mut bytes); self.bytes.extend_from_slice(bytes) } From 15201af7edbf93732756510527977327563b44e8 Mon Sep 17 00:00:00 2001 From: Mahmut Bulut Date: Fri, 29 May 2020 20:28:18 +0200 Subject: [PATCH 10/10] Update stdarch submodule to latest head --- src/stdarch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stdarch b/src/stdarch index ec6fccd34c300..45340c0e2fdad 160000 --- a/src/stdarch +++ b/src/stdarch @@ -1 +1 @@ -Subproject commit ec6fccd34c30003a7ebf4e7a9dfe4e31f5b76e1b +Subproject commit 45340c0e2fdadf2f131ef43cb683b5cafab0ff15