From 0d8245b5b1f587ed2e52b6c97732299bdf7368df Mon Sep 17 00:00:00 2001 From: Fabian Wolff Date: Thu, 9 Sep 2021 23:25:43 +0200 Subject: [PATCH 01/14] Improve diagnostics if a character literal contains combining marks --- .../src/lexer/unescape_error_reporting.rs | 61 ++++++++++++++----- .../ui/parser/unicode-character-literal.fixed | 21 +++++++ .../ui/parser/unicode-character-literal.rs | 21 +++++++ .../parser/unicode-character-literal.stderr | 48 +++++++++++++++ 4 files changed, 137 insertions(+), 14 deletions(-) create mode 100644 src/test/ui/parser/unicode-character-literal.fixed create mode 100644 src/test/ui/parser/unicode-character-literal.rs create mode 100644 src/test/ui/parser/unicode-character-literal.stderr diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index aa6b424ce2b57..cef5b3a226bff 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -3,7 +3,7 @@ use std::iter::once; use std::ops::Range; -use rustc_errors::{Applicability, Handler}; +use rustc_errors::{pluralize, Applicability, Handler}; use rustc_lexer::unescape::{EscapeError, Mode}; use rustc_span::{BytePos, Span}; @@ -49,24 +49,57 @@ pub(crate) fn emit_unescape_error( .emit(); } EscapeError::MoreThanOneChar => { - let (prefix, msg) = if mode.is_bytes() { - ("b", "if you meant to write a byte string literal, use double quotes") - } else { - ("", "if you meant to write a `str` literal, use double quotes") - }; + use unicode_normalization::{char::is_combining_mark, UnicodeNormalization}; - handler - .struct_span_err( - span_with_quotes, - "character literal may only contain one codepoint", - ) - .span_suggestion( + let mut has_help = false; + let mut handler = handler.struct_span_err( + span_with_quotes, + "character literal may only contain one codepoint", + ); + + if lit.chars().skip(1).all(|c| is_combining_mark(c)) { + let escaped_marks = + lit.chars().skip(1).map(|c| c.escape_default().to_string()).collect::>(); + handler.span_note( + span, + &format!( + "this `{}` is followed by the combining mark{} `{}`", + lit.chars().next().unwrap(), + pluralize!(escaped_marks.len()), + escaped_marks.join(""), + ), + ); + let normalized = lit.nfc().to_string(); + if normalized.chars().count() == 1 { + has_help = true; + handler.span_suggestion( + span, + &format!( + "consider using the normalized form `{}` of this character", + normalized.chars().next().unwrap().escape_default() + ), + normalized, + Applicability::MachineApplicable, + ); + } + } + + if !has_help { + let (prefix, msg) = if mode.is_bytes() { + ("b", "if you meant to write a byte string literal, use double quotes") + } else { + ("", "if you meant to write a `str` literal, use double quotes") + }; + + handler.span_suggestion( span_with_quotes, msg, format!("{}\"{}\"", prefix, lit), Applicability::MachineApplicable, - ) - .emit(); + ); + } + + handler.emit(); } EscapeError::EscapeOnlyChar => { let (c, char_span) = last_char(); diff --git a/src/test/ui/parser/unicode-character-literal.fixed b/src/test/ui/parser/unicode-character-literal.fixed new file mode 100644 index 0000000000000..26ef5ffa11a80 --- /dev/null +++ b/src/test/ui/parser/unicode-character-literal.fixed @@ -0,0 +1,21 @@ +// Regression test for #88684: Improve diagnostics for combining marks +// in character literals. + +// run-rustfix + +fn main() { + let _spade = "♠️"; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: this `♠` is followed by the combining mark `\u{fe0f}` + //~| HELP: if you meant to write a `str` literal, use double quotes + + let _s = "ṩ̂̊"; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}` + //~| HELP: if you meant to write a `str` literal, use double quotes + + let _a = 'Å'; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: this `A` is followed by the combining mark `\u{30a}` + //~| HELP: consider using the normalized form `\u{c5}` of this character +} diff --git a/src/test/ui/parser/unicode-character-literal.rs b/src/test/ui/parser/unicode-character-literal.rs new file mode 100644 index 0000000000000..d331522c04cbb --- /dev/null +++ b/src/test/ui/parser/unicode-character-literal.rs @@ -0,0 +1,21 @@ +// Regression test for #88684: Improve diagnostics for combining marks +// in character literals. + +// run-rustfix + +fn main() { + let _spade = '♠️'; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: this `♠` is followed by the combining mark `\u{fe0f}` + //~| HELP: if you meant to write a `str` literal, use double quotes + + let _s = 'ṩ̂̊'; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}` + //~| HELP: if you meant to write a `str` literal, use double quotes + + let _a = 'Å'; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: this `A` is followed by the combining mark `\u{30a}` + //~| HELP: consider using the normalized form `\u{c5}` of this character +} diff --git a/src/test/ui/parser/unicode-character-literal.stderr b/src/test/ui/parser/unicode-character-literal.stderr new file mode 100644 index 0000000000000..5cd3bd0fe69d7 --- /dev/null +++ b/src/test/ui/parser/unicode-character-literal.stderr @@ -0,0 +1,48 @@ +error: character literal may only contain one codepoint + --> $DIR/unicode-character-literal.rs:7:18 + | +LL | let _spade = '♠️'; + | ^^^ + | +note: this `♠` is followed by the combining mark `\u{fe0f}` + --> $DIR/unicode-character-literal.rs:7:19 + | +LL | let _spade = '♠️'; + | ^ +help: if you meant to write a `str` literal, use double quotes + | +LL | let _spade = "♠️"; + | ~~~ + +error: character literal may only contain one codepoint + --> $DIR/unicode-character-literal.rs:12:14 + | +LL | let _s = 'ṩ̂̊'; + | ^^^ + | +note: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}` + --> $DIR/unicode-character-literal.rs:12:15 + | +LL | let _s = 'ṩ̂̊'; + | ^ +help: if you meant to write a `str` literal, use double quotes + | +LL | let _s = "ṩ̂̊"; + | ~~~ + +error: character literal may only contain one codepoint + --> $DIR/unicode-character-literal.rs:17:14 + | +LL | let _a = 'Å'; + | ^-^ + | | + | help: consider using the normalized form `\u{c5}` of this character: `Å` + | +note: this `A` is followed by the combining mark `\u{30a}` + --> $DIR/unicode-character-literal.rs:17:15 + | +LL | let _a = 'Å'; + | ^ + +error: aborting due to 3 previous errors + From 71e2eacc7bedeba7ca851164d0485c7e635a6697 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 17 Sep 2021 19:42:46 +0300 Subject: [PATCH 02/14] Stabilize `Iterator::map_while` --- compiler/rustc_data_structures/src/lib.rs | 1 - library/alloc/tests/lib.rs | 1 - library/core/src/iter/adapters/map_while.rs | 6 +++--- library/core/src/iter/adapters/mod.rs | 2 +- library/core/src/iter/mod.rs | 2 +- library/core/src/iter/traits/iterator.rs | 5 +---- library/core/tests/lib.rs | 1 - 7 files changed, 6 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index dd6a17b92aef3..b1f04bfbf0a84 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -18,7 +18,6 @@ #![feature(extend_one)] #![feature(hash_raw_entry)] #![feature(in_band_lifetimes)] -#![feature(iter_map_while)] #![feature(maybe_uninit_uninit_array)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 5767108d423c6..cae4dae708e59 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -18,7 +18,6 @@ #![feature(binary_heap_retain)] #![feature(binary_heap_as_slice)] #![feature(inplace_iteration)] -#![feature(iter_map_while)] #![feature(slice_group_by)] #![feature(slice_partition_dedup)] #![feature(vec_spare_capacity)] diff --git a/library/core/src/iter/adapters/map_while.rs b/library/core/src/iter/adapters/map_while.rs index 8f89e1588048f..793b05fcf9529 100644 --- a/library/core/src/iter/adapters/map_while.rs +++ b/library/core/src/iter/adapters/map_while.rs @@ -10,7 +10,7 @@ use crate::ops::{ControlFlow, Try}; /// [`map_while`]: Iterator::map_while /// [`Iterator`]: trait.Iterator.html #[must_use = "iterators are lazy and do nothing unless consumed"] -#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] +#[stable(feature = "iter_map_while", since = "1.57.0")] #[derive(Clone)] pub struct MapWhile { iter: I, @@ -23,14 +23,14 @@ impl MapWhile { } } -#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] +#[stable(feature = "iter_map_while", since = "1.57.0")] impl fmt::Debug for MapWhile { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("MapWhile").field("iter", &self.iter).finish() } } -#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] +#[stable(feature = "iter_map_while", since = "1.57.0")] impl Iterator for MapWhile where P: FnMut(I::Item) -> Option, diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index f02d278aff5e4..48e7dcfa7d9a3 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -45,7 +45,7 @@ pub use self::copied::Copied; #[stable(feature = "iter_intersperse", since = "1.56.0")] pub use self::intersperse::{Intersperse, IntersperseWith}; -#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] +#[stable(feature = "iter_map_while", since = "1.57.0")] pub use self::map_while::MapWhile; #[unstable(feature = "trusted_random_access", issue = "none")] diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index cd8a26025ffb6..d6f9edaa046c6 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -399,7 +399,7 @@ pub use self::adapters::Cloned; pub use self::adapters::Copied; #[stable(feature = "iterator_flatten", since = "1.29.0")] pub use self::adapters::Flatten; -#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] +#[stable(feature = "iter_map_while", since = "1.57.0")] pub use self::adapters::MapWhile; #[unstable(feature = "inplace_iteration", issue = "none")] pub use self::adapters::SourceIter; diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index b0a9d9f5ef5c9..f884340f4e0bd 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1116,7 +1116,6 @@ pub trait Iterator { /// Basic usage: /// /// ``` - /// #![feature(iter_map_while)] /// let a = [-1i32, 4, 0, 1]; /// /// let mut iter = a.iter().map_while(|x| 16i32.checked_div(*x)); @@ -1147,7 +1146,6 @@ pub trait Iterator { /// Stopping after an initial [`None`]: /// /// ``` - /// #![feature(iter_map_while)] /// use std::convert::TryFrom; /// /// let a = [0, 1, 2, -3, 4, 5, -6]; @@ -1165,7 +1163,6 @@ pub trait Iterator { /// removed: /// /// ``` - /// #![feature(iter_map_while)] /// use std::convert::TryFrom; /// /// let a = [1, 2, -3, 4]; @@ -1191,7 +1188,7 @@ pub trait Iterator { /// /// [`fuse`]: Iterator::fuse #[inline] - #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] + #[stable(feature = "iter_map_while", since = "1.57.0")] fn map_while(self, predicate: P) -> MapWhile where Self: Sized, diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 19bcc45108dfd..cd3aed4cd28f8 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -50,7 +50,6 @@ #![feature(iter_partition_in_place)] #![feature(iter_is_partitioned)] #![feature(iter_order_by)] -#![feature(iter_map_while)] #![feature(const_mut_refs)] #![feature(const_pin)] #![feature(const_slice_from_raw_parts)] From cccd6e0e830fcaaa5891102f48b10786c24a2fe5 Mon Sep 17 00:00:00 2001 From: klensy Date: Thu, 16 Sep 2021 18:10:04 +0300 Subject: [PATCH 03/14] EscapeDefault: change `range` field to `Range`, reducing struct size 24 -> 6 bytes --- library/core/src/ascii.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs index 4780d8dc7883f..0a456ee1eb2d5 100644 --- a/library/core/src/ascii.rs +++ b/library/core/src/ascii.rs @@ -21,7 +21,7 @@ use crate::str::from_utf8_unchecked; #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] pub struct EscapeDefault { - range: Range, + range: Range, data: [u8; 4], } @@ -114,7 +114,7 @@ pub fn escape_default(c: u8) -> EscapeDefault { impl Iterator for EscapeDefault { type Item = u8; fn next(&mut self) -> Option { - self.range.next().map(|i| self.data[i]) + self.range.next().map(|i| self.data[i as usize]) } fn size_hint(&self) -> (usize, Option) { self.range.size_hint() @@ -126,7 +126,7 @@ impl Iterator for EscapeDefault { #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for EscapeDefault { fn next_back(&mut self) -> Option { - self.range.next_back().map(|i| self.data[i]) + self.range.next_back().map(|i| self.data[i as usize]) } } #[stable(feature = "rust1", since = "1.0.0")] @@ -138,7 +138,9 @@ impl FusedIterator for EscapeDefault {} impl fmt::Display for EscapeDefault { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // SAFETY: ok because `escape_default` created only valid utf-8 data - f.write_str(unsafe { from_utf8_unchecked(&self.data[self.range.clone()]) }) + f.write_str(unsafe { + from_utf8_unchecked(&self.data[(self.range.start as usize)..(self.range.end as usize)]) + }) } } From 7c8f4f7eabe876057d855a2f5c008bedb6f477a4 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Sat, 18 Sep 2021 15:48:07 -0500 Subject: [PATCH 04/14] Remove needless hir Map ref --- compiler/rustc_middle/src/hir/map/mod.rs | 16 ++++++++-------- compiler/rustc_resolve/src/late/lifetimes.rs | 3 +-- src/tools/clippy/clippy_utils/src/higher.rs | 3 +-- src/tools/clippy/clippy_utils/src/lib.rs | 15 +++++---------- 4 files changed, 15 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 10714a4b706f6..23c002ce18cc2 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -82,12 +82,12 @@ pub struct Map<'hir> { /// An iterator that walks up the ancestor tree of a given `HirId`. /// Constructed using `tcx.hir().parent_iter(hir_id)`. -pub struct ParentHirIterator<'map, 'hir> { +pub struct ParentHirIterator<'hir> { current_id: HirId, - map: &'map Map<'hir>, + map: Map<'hir>, } -impl<'hir> Iterator for ParentHirIterator<'_, 'hir> { +impl<'hir> Iterator for ParentHirIterator<'hir> { type Item = (HirId, Node<'hir>); fn next(&mut self) -> Option { @@ -114,12 +114,12 @@ impl<'hir> Iterator for ParentHirIterator<'_, 'hir> { /// An iterator that walks up the ancestor tree of a given `HirId`. /// Constructed using `tcx.hir().parent_owner_iter(hir_id)`. -pub struct ParentOwnerIterator<'map, 'hir> { +pub struct ParentOwnerIterator<'hir> { current_id: HirId, - map: &'map Map<'hir>, + map: Map<'hir>, } -impl<'hir> Iterator for ParentOwnerIterator<'_, 'hir> { +impl<'hir> Iterator for ParentOwnerIterator<'hir> { type Item = (HirId, OwnerNode<'hir>); fn next(&mut self) -> Option { @@ -560,13 +560,13 @@ impl<'hir> Map<'hir> { /// Returns an iterator for the nodes in the ancestor tree of the `current_id` /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`. - pub fn parent_iter(&self, current_id: HirId) -> ParentHirIterator<'_, 'hir> { + pub fn parent_iter(self, current_id: HirId) -> ParentHirIterator<'hir> { ParentHirIterator { current_id, map: self } } /// Returns an iterator for the nodes in the ancestor tree of the `current_id` /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`. - pub fn parent_owner_iter(&self, current_id: HirId) -> ParentOwnerIterator<'_, 'hir> { + pub fn parent_owner_iter(self, current_id: HirId) -> ParentOwnerIterator<'hir> { ParentOwnerIterator { current_id, map: self } } diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index a5dbbffeaa86b..c7cd435312f32 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -522,8 +522,7 @@ fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId { _ => {} } let item = { - let hir = tcx.hir(); - let mut parent_iter = hir.parent_iter(hir_id); + let mut parent_iter = tcx.hir().parent_iter(hir_id); loop { let node = parent_iter.next().map(|n| n.1); match node { diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs index 05a4a01431950..94b3cd371bd08 100644 --- a/src/tools/clippy/clippy_utils/src/higher.rs +++ b/src/tools/clippy/clippy_utils/src/higher.rs @@ -105,8 +105,7 @@ impl<'hir> IfLet<'hir> { if_else, ) = expr.kind { - let hir = cx.tcx.hir(); - let mut iter = hir.parent_iter(expr.hir_id); + let mut iter = cx.tcx.hir().parent_iter(expr.hir_id); if let Some((_, Node::Block(Block { stmts: [], .. }))) = iter.next() { if let Some(( _, diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 3a94f47298390..7f5a1bf9c0741 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -833,12 +833,11 @@ pub fn capture_local_usage(cx: &LateContext<'tcx>, e: &Expr<'_>) -> CaptureKind ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(_), .. })) )); - let map = cx.tcx.hir(); let mut child_id = e.hir_id; let mut capture = CaptureKind::Value; let mut capture_expr_ty = e; - for (parent_id, parent) in map.parent_iter(e.hir_id) { + for (parent_id, parent) in cx.tcx.hir().parent_iter(e.hir_id) { if let [Adjustment { kind: Adjust::Deref(_) | Adjust::Borrow(AutoBorrow::Ref(..)), target, @@ -1224,8 +1223,7 @@ pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio /// Gets the loop or closure enclosing the given expression, if any. pub fn get_enclosing_loop_or_closure(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> { - let map = tcx.hir(); - for (_, node) in map.parent_iter(expr.hir_id) { + for (_, node) in tcx.hir().parent_iter(expr.hir_id) { match node { Node::Expr( e @@ -1244,8 +1242,7 @@ pub fn get_enclosing_loop_or_closure(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Opti /// Gets the parent node if it's an impl block. pub fn get_parent_as_impl(tcx: TyCtxt<'_>, id: HirId) -> Option<&Impl<'_>> { - let map = tcx.hir(); - match map.parent_iter(id).next() { + match tcx.hir().parent_iter(id).next() { Some(( _, Node::Item(Item { @@ -1259,8 +1256,7 @@ pub fn get_parent_as_impl(tcx: TyCtxt<'_>, id: HirId) -> Option<&Impl<'_>> { /// Checks if the given expression is the else clause of either an `if` or `if let` expression. pub fn is_else_clause(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { - let map = tcx.hir(); - let mut iter = map.parent_iter(expr.hir_id); + let mut iter = tcx.hir().parent_iter(expr.hir_id); match iter.next() { Some(( _, @@ -1794,9 +1790,8 @@ pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool /// Gets the node where an expression is either used, or it's type is unified with another branch. pub fn get_expr_use_or_unification_node(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option> { - let map = tcx.hir(); let mut child_id = expr.hir_id; - let mut iter = map.parent_iter(child_id); + let mut iter = tcx.hir().parent_iter(child_id); loop { match iter.next() { None => break None, From a627b4f2bfb3012bd69650ee7defc9ef2ef2ec1e Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Sun, 19 Sep 2021 14:27:49 +0100 Subject: [PATCH 05/14] [bootstrap] Improve the error message when `ninja` is not found to link to installation instructions. Signed-off-by: Daira Hopwood --- src/bootstrap/lib.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index a4735d54be038..9302217297b02 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -1494,8 +1494,12 @@ impl Build { { eprintln!( " -Couldn't find required command: ninja -You should install ninja, or set `ninja=false` in config.toml in the `[llvm]` section. +Couldn't find required command: ninja (or ninja-build) + +You should install ninja as described at +, +or set `download-ci-llvm = true` in the `[llvm]` section of `config.toml` +to download LLVM rather than building it. " ); std::process::exit(1); From 23d643712807bdbc49e82c5b3170c1b33d3be8ee Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Sun, 19 Sep 2021 19:50:08 +0100 Subject: [PATCH 06/14] Restore the suggestion to set `ninja = false`. --- src/bootstrap/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 9302217297b02..2d4e152789724 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -1498,7 +1498,8 @@ Couldn't find required command: ninja (or ninja-build) You should install ninja as described at , -or set `download-ci-llvm = true` in the `[llvm]` section of `config.toml` +or set `ninja = false` in the `[llvm]` section of `config.toml`. +Alternatively, set `download-ci-llvm = true` in that `[llvm]` section to download LLVM rather than building it. " ); From 23c608f3a1b0cf09344f0e356610e59d8ee581ac Mon Sep 17 00:00:00 2001 From: Nadja Reitzenstein Date: Mon, 20 Sep 2021 08:19:13 +0200 Subject: [PATCH 07/14] Fix a technicality regarding the size of C's `char` type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Specifically, ISO/IEC 9899:2018 — better known as "C18" — (and at least C11, C99 and C89) do not specify the size of `byte` in bits. Section 3.6 defines "byte" as "addressable unit of data storage" while section 6.2.5 ("Types") only defines "char" as "large enough to store any member of the basic execution set" giving it a lower bound of 7 bit (since there are 96 characters in the basic execution set). With section 6.5.3.4 paragraph 4 "When sizeof is applied to an operant that has type char […] the result is 1" you could read this as the size of `char` in bits being defined as exactly the same as the number of bits in a byte but it's also valid to read that as an exception. In general implementations take `char` as the smallest unit of addressable memory, which for modern byte-addressed architectures is overwhelmingly 8 bits to the point of this convention being completely cemented into just about all of our software. So is any of this actually relevant at all? I hope not. I sincerely hope that this never, ever comes up. But if for some reason a poor rustacean is having to interface with C code running on a Cray X1 that in 2003 is still doing word-addressed memory with 64-bit words and they trust the docs here blindly it will blow up in her face. And I'll be truly sorry for her to have to deal with … all of that. --- library/std/src/os/raw/char.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/os/raw/char.md b/library/std/src/os/raw/char.md index 8256b725acfa3..375d070516eb4 100644 --- a/library/std/src/os/raw/char.md +++ b/library/std/src/os/raw/char.md @@ -1,6 +1,6 @@ Equivalent to C's `char` type. -[C's `char` type] is completely unlike [Rust's `char` type]; while Rust's type represents a unicode scalar value, C's `char` type is just an ordinary integer. This type will always be either [`i8`] or [`u8`], as the type is defined as being one byte long. +[C's `char` type] is completely unlike [Rust's `char` type]; while Rust's type represents a unicode scalar value, C's `char` type is just an ordinary integer. On modern architectures this type will always be either [`i8`] or [`u8`], as they use byte-addresses memory with 8-bit bytes. C chars are most commonly used to make C strings. Unlike Rust, where the length of a string is included alongside the string, C strings mark the end of a string with the character `'\0'`. See [`CStr`] for more information. From 5fdb9e4cf43899eaab1121a77e19b20fac1835cb Mon Sep 17 00:00:00 2001 From: Ellen Date: Mon, 20 Sep 2021 09:30:23 +0100 Subject: [PATCH 08/14] no ensure --- compiler/rustc_mir_build/src/build/mod.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 0ee740a646359..4108ad50470b7 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -44,15 +44,18 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ let body_owner_kind = tcx.hir().body_owner_kind(id); let typeck_results = tcx.typeck_opt_const_arg(def); - // Ensure unsafeck is ran before we steal the THIR. + // Ensure unsafeck and abstract const building is ran before we steal the THIR. + // We can't use `ensure()` for `thir_abstract_const` as it doesn't compute the query + // if inputs are green. This can cause ICEs when calling `thir_abstract_const` after + // THIR has been stolen if we haven't computed this query yet. match def { ty::WithOptConstParam { did, const_param_did: Some(const_param_did) } => { tcx.ensure().thir_check_unsafety_for_const_arg((did, const_param_did)); - tcx.ensure().thir_abstract_const_of_const_arg((did, const_param_did)); + drop(tcx.thir_abstract_const_of_const_arg((did, const_param_did))); } ty::WithOptConstParam { did, const_param_did: None } => { tcx.ensure().thir_check_unsafety(did); - tcx.ensure().thir_abstract_const(did); + drop(tcx.thir_abstract_const(did)); } } From 514b8ba0baa171eedd8e4d442fd4337c4500fe34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 20 Sep 2021 15:45:46 +0300 Subject: [PATCH 09/14] :arrow_up: rust-analyzer --- src/tools/rust-analyzer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index b73b321478d3b..f1d7f98ed07b9 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit b73b321478d3b2a98d380eb79de717e01620c4e9 +Subproject commit f1d7f98ed07b9934286b9c4809dd4d7a47537879 From 402ebc72b32529398220467e09227e2749200345 Mon Sep 17 00:00:00 2001 From: Fabian Wolff Date: Mon, 20 Sep 2021 21:06:09 +0200 Subject: [PATCH 10/14] Fix ICE when `indirect_structural_match` is allowed --- .../src/thir/pattern/const_to_pat.rs | 14 +++++++----- src/test/ui/consts/issue-89088.rs | 22 +++++++++++++++++++ 2 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/consts/issue-89088.rs diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index bbb5de34d1860..847b89f0464f6 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -322,16 +322,18 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { && !self.saw_const_match_lint.get() { self.saw_const_match_lint.set(true); - let msg = format!( - "to use a constant of type `{}` in a pattern, \ - `{}` must be annotated with `#[derive(PartialEq, Eq)]`", - cv.ty, cv.ty, - ); tcx.struct_span_lint_hir( lint::builtin::INDIRECT_STRUCTURAL_MATCH, id, span, - |lint| lint.build(&msg).emit(), + |lint| { + let msg = format!( + "to use a constant of type `{}` in a pattern, \ + `{}` must be annotated with `#[derive(PartialEq, Eq)]`", + cv.ty, cv.ty, + ); + lint.build(&msg).emit() + }, ); } // Since we are behind a reference, we can just bubble the error up so we get a diff --git a/src/test/ui/consts/issue-89088.rs b/src/test/ui/consts/issue-89088.rs new file mode 100644 index 0000000000000..40cc665fb612b --- /dev/null +++ b/src/test/ui/consts/issue-89088.rs @@ -0,0 +1,22 @@ +// Regression test for the ICE described in #89088. + +// check-pass + +#![allow(indirect_structural_match)] +use std::borrow::Cow; + +const FOO: &A = &A::Field(Cow::Borrowed("foo")); + +#[derive(PartialEq, Eq)] +enum A { + Field(Cow<'static, str>) +} + +fn main() { + let var = A::Field(Cow::Borrowed("bar")); + + match &var { + FOO => todo!(), + _ => todo!() + } +} From 33766ae3723ca09618180ee6efa5dd20c1cc3995 Mon Sep 17 00:00:00 2001 From: mbartlett21 <29034492+mbartlett21@users.noreply.github.com> Date: Tue, 21 Sep 2021 18:02:18 +1000 Subject: [PATCH 11/14] Impl `Error` for `FromSecsError` without foreign type Using it through the crate-local path in `std` means that it shouldn't make an "Implementations on Foreign Types" section in the `std::error::Error` docs. --- library/std/src/error.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/std/src/error.rs b/library/std/src/error.rs index 8164ec5698579..cc4ea27e57e8d 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -31,6 +31,7 @@ use crate::num; use crate::str; use crate::string; use crate::sync::Arc; +use crate::time; /// `Error` is a trait representing the basic expectations for error values, /// i.e., values of type `E` in [`Result`]. @@ -598,7 +599,7 @@ impl Error for char::ParseCharError { impl Error for alloc::collections::TryReserveError {} #[unstable(feature = "duration_checked_float", issue = "83400")] -impl Error for core::time::FromSecsError {} +impl Error for time::FromSecsError {} // Copied from `any.rs`. impl dyn Error + 'static { From d4ee6982e459c7a39051b15920a07cda2810a8f2 Mon Sep 17 00:00:00 2001 From: Ankit Chandawala Date: Tue, 21 Sep 2021 09:31:59 +0100 Subject: [PATCH 12/14] Fix match for placeholder region --- compiler/rustc_middle/src/ich/impls_ty.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ich/impls_ty.rs b/compiler/rustc_middle/src/ich/impls_ty.rs index 8e53e4ba94805..3b0640eb98d93 100644 --- a/compiler/rustc_middle/src/ich/impls_ty.rs +++ b/compiler/rustc_middle/src/ich/impls_ty.rs @@ -90,7 +90,10 @@ impl<'a> HashStable> for ty::RegionKind { ty::ReFree(ref free_region) => { free_region.hash_stable(hcx, hasher); } - ty::ReVar(..) | ty::RePlaceholder(..) => { + ty::RePlaceholder(p) => { + p.hash_stable(hcx, hasher); + } + ty::ReVar(..) => { bug!("StableHasher: unexpected region {:?}", *self) } } From e4faf17437ae3aa7609a415d061817e40d3f9ab3 Mon Sep 17 00:00:00 2001 From: mbartlett21 <29034492+mbartlett21@users.noreply.github.com> Date: Tue, 21 Sep 2021 21:18:57 +1000 Subject: [PATCH 13/14] Re-export FromSecsError from `std` --- library/std/src/time.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/std/src/time.rs b/library/std/src/time.rs index e9207ee36171b..bf3eb5b30c77d 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -44,6 +44,9 @@ use crate::sys_common::FromInner; #[stable(feature = "time", since = "1.3.0")] pub use core::time::Duration; +#[unstable(feature = "duration_checked_float", issue = "83400")] +pub use core::time::FromSecsError; + /// A measurement of a monotonically nondecreasing clock. /// Opaque and useful only with [`Duration`]. /// From 999888c086446c4c43bd5e99d8a0d2a1a7ee0404 Mon Sep 17 00:00:00 2001 From: b-naber Date: Tue, 21 Sep 2021 15:07:28 +0200 Subject: [PATCH 14/14] add case for checking const refs in check_const_value_eq --- compiler/rustc_middle/src/ty/relate.rs | 9 +++++++ .../consts/refs_check_const_eq-issue-88384.rs | 25 +++++++++++++++++++ .../refs_check_const_eq-issue-88384.stderr | 11 ++++++++ .../refs_check_const_value_eq-issue-88876.rs | 12 +++++++++ 4 files changed, 57 insertions(+) create mode 100644 src/test/ui/consts/refs_check_const_eq-issue-88384.rs create mode 100644 src/test/ui/consts/refs_check_const_eq-issue-88384.stderr create mode 100644 src/test/ui/consts/refs_check_const_value_eq-issue-88876.rs diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 9d1be212f5b8c..2c786538014ff 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -639,6 +639,15 @@ fn check_const_value_eq>( get_slice_bytes(&tcx, a_val) == get_slice_bytes(&tcx, b_val) } + (ConstValue::ByRef { alloc: alloc_a, .. }, ConstValue::ByRef { alloc: alloc_b, .. }) + if a.ty.is_ref() || b.ty.is_ref() => + { + if a.ty.is_ref() && b.ty.is_ref() { + alloc_a == alloc_b + } else { + false + } + } (ConstValue::ByRef { .. }, ConstValue::ByRef { .. }) => { let a_destructured = tcx.destructure_const(relation.param_env().and(a)); let b_destructured = tcx.destructure_const(relation.param_env().and(b)); diff --git a/src/test/ui/consts/refs_check_const_eq-issue-88384.rs b/src/test/ui/consts/refs_check_const_eq-issue-88384.rs new file mode 100644 index 0000000000000..204d18ea25de4 --- /dev/null +++ b/src/test/ui/consts/refs_check_const_eq-issue-88384.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(fn_traits)] +#![feature(adt_const_params)] +//~^ WARNING the feature `adt_const_params` is incomplete + +#[derive(PartialEq, Eq)] +struct CompileTimeSettings{ + hooks: &'static[fn()], +} + +struct Foo; + +impl Foo { + fn call_hooks(){ + } +} + +fn main(){ + const SETTINGS: CompileTimeSettings = CompileTimeSettings{ + hooks: &[], + }; + + Foo::::call_hooks(); +} diff --git a/src/test/ui/consts/refs_check_const_eq-issue-88384.stderr b/src/test/ui/consts/refs_check_const_eq-issue-88384.stderr new file mode 100644 index 0000000000000..55928b495b24c --- /dev/null +++ b/src/test/ui/consts/refs_check_const_eq-issue-88384.stderr @@ -0,0 +1,11 @@ +warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/refs_check_const_eq-issue-88384.rs:4:12 + | +LL | #![feature(adt_const_params)] + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/consts/refs_check_const_value_eq-issue-88876.rs b/src/test/ui/consts/refs_check_const_value_eq-issue-88876.rs new file mode 100644 index 0000000000000..6ce9da4366800 --- /dev/null +++ b/src/test/ui/consts/refs_check_const_value_eq-issue-88876.rs @@ -0,0 +1,12 @@ +// check-pass + +#![allow(incomplete_features)] +#![feature(adt_const_params)] + +struct FooConst {} + +const FOO_ARR: &[&'static str; 2] = &["Hello", "Friend"]; + +fn main() { + let _ = FooConst:: {}; +}