From e9c78db0861f6495f903a41e087c9628d777b87b Mon Sep 17 00:00:00 2001 From: Juan Aguilar Santillana Date: Fri, 8 May 2020 22:48:26 +0200 Subject: [PATCH 01/18] Update annotate-snippets-rs to 0.8.0 --- Cargo.lock | 12 +- src/librustc_errors/Cargo.toml | 2 +- .../annotate_snippet_emitter_writer.rs | 204 +++++++----------- .../ui/annotate-snippet/missing-type.stderr | 2 +- 4 files changed, 92 insertions(+), 128 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 375e567222965..7e0448a152f4d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -48,6 +48,12 @@ dependencies = [ "ansi_term", ] +[[package]] +name = "annotate-snippets" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d78ea013094e5ea606b1c05fe35f1dd7ea1eb1ea259908d040b25bd5ec677ee5" + [[package]] name = "ansi_term" version = "0.11.0" @@ -3277,7 +3283,7 @@ version = "654.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "908e1ea187c6bb368af4ba6db980001e920515e67371ddc4086e749baabe6080" dependencies = [ - "annotate-snippets", + "annotate-snippets 0.6.1", "atty", "log", "rustc-ap-rustc_data_structures", @@ -3761,7 +3767,7 @@ version = "0.0.0" name = "rustc_errors" version = "0.0.0" dependencies = [ - "annotate-snippets", + "annotate-snippets 0.8.0", "atty", "log", "rustc_data_structures", @@ -4408,7 +4414,7 @@ dependencies = [ name = "rustfmt-nightly" version = "1.4.14" dependencies = [ - "annotate-snippets", + "annotate-snippets 0.6.1", "bytecount", "cargo_metadata 0.8.0", "derive-new", diff --git a/src/librustc_errors/Cargo.toml b/src/librustc_errors/Cargo.toml index b8340b1a1df6a..5882a6855b673 100644 --- a/src/librustc_errors/Cargo.toml +++ b/src/librustc_errors/Cargo.toml @@ -17,7 +17,7 @@ rustc_data_structures = { path = "../librustc_data_structures" } unicode-width = "0.1.4" atty = "0.2" termcolor = "1.0" -annotate-snippets = "0.6.1" +annotate-snippets = "0.8.0" termize = "0.1.1" [target.'cfg(windows)'.dependencies] diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs index d83175694f407..df5e43626aab9 100644 --- a/src/librustc_errors/annotate_snippet_emitter_writer.rs +++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs @@ -8,12 +8,11 @@ use crate::emitter::FileWithAnnotatedLines; use crate::snippet::Line; use crate::{CodeSuggestion, Diagnostic, DiagnosticId, Emitter, Level, SubDiagnostic}; -use annotate_snippets::display_list::DisplayList; -use annotate_snippets::formatter::DisplayListFormatter; +use annotate_snippets::display_list::{DisplayList, FormatOptions}; use annotate_snippets::snippet::*; use rustc_data_structures::sync::Lrc; use rustc_span::source_map::SourceMap; -use rustc_span::{Loc, MultiSpan, SourceFile}; +use rustc_span::{MultiSpan, SourceFile}; /// Generates diagnostics using annotate-snippet pub struct AnnotateSnippetEmitterWriter { @@ -59,112 +58,20 @@ impl Emitter for AnnotateSnippetEmitterWriter { } } -/// Collects all the data needed to generate the data structures needed for the -/// `annotate-snippets` library. -struct DiagnosticConverter<'a> { - source_map: Option>, - level: Level, - message: String, - code: Option, - msp: MultiSpan, - #[allow(dead_code)] - children: &'a [SubDiagnostic], - #[allow(dead_code)] - suggestions: &'a [CodeSuggestion], +/// Provides the source string for the given `line` of `file` +fn source_string(file: Lrc, line: &Line) -> String { + file.get_line(line.line_index - 1).map(|a| a.to_string()).unwrap_or_default() } -impl<'a> DiagnosticConverter<'a> { - /// Turns rustc Diagnostic information into a `annotate_snippets::snippet::Snippet`. - fn to_annotation_snippet(&self) -> Option { - if let Some(source_map) = &self.source_map { - // Make sure our primary file comes first - let primary_lo = if let Some(ref primary_span) = self.msp.primary_span().as_ref() { - source_map.lookup_char_pos(primary_span.lo()) - } else { - // FIXME(#59346): Not sure when this is the case and what - // should be done if it happens - return None; - }; - let annotated_files = - FileWithAnnotatedLines::collect_annotations(&self.msp, &self.source_map); - let slices = self.slices_for_files(annotated_files, primary_lo); - - Some(Snippet { - title: Some(Annotation { - label: Some(self.message.to_string()), - id: self.code.clone().map(|c| match c { - DiagnosticId::Error(val) | DiagnosticId::Lint(val) => val, - }), - annotation_type: Self::annotation_type_for_level(self.level), - }), - footer: vec![], - slices, - }) - } else { - // FIXME(#59346): Is it ok to return None if there's no source_map? - None - } - } - - fn slices_for_files( - &self, - annotated_files: Vec, - primary_lo: Loc, - ) -> Vec { - // FIXME(#64205): Provide a test case where `annotated_files` is > 1 - annotated_files - .iter() - .flat_map(|annotated_file| { - annotated_file - .lines - .iter() - .map(|line| { - let line_source = Self::source_string(annotated_file.file.clone(), &line); - Slice { - source: line_source, - line_start: line.line_index, - origin: Some(primary_lo.file.name.to_string()), - // FIXME(#59346): Not really sure when `fold` should be true or false - fold: false, - annotations: line - .annotations - .iter() - .map(|a| self.annotation_to_source_annotation(a.clone())) - .collect(), - } - }) - .collect::>() - }) - .collect::>() - } - - /// Turns a `crate::snippet::Annotation` into a `SourceAnnotation` - fn annotation_to_source_annotation( - &self, - annotation: crate::snippet::Annotation, - ) -> SourceAnnotation { - SourceAnnotation { - range: (annotation.start_col, annotation.end_col), - label: annotation.label.unwrap_or("".to_string()), - annotation_type: Self::annotation_type_for_level(self.level), - } - } - - /// Provides the source string for the given `line` of `file` - fn source_string(file: Lrc, line: &Line) -> String { - file.get_line(line.line_index - 1).map(|a| a.to_string()).unwrap_or(String::new()) - } - - /// Maps `Diagnostic::Level` to `snippet::AnnotationType` - fn annotation_type_for_level(level: Level) -> AnnotationType { - match level { - Level::Bug | Level::Fatal | Level::Error => AnnotationType::Error, - Level::Warning => AnnotationType::Warning, - Level::Note => AnnotationType::Note, - Level::Help => AnnotationType::Help, - // FIXME(#59346): Not sure how to map these two levels - Level::Cancelled | Level::FailureNote => AnnotationType::Error, - } +/// Maps `Diagnostic::Level` to `snippet::AnnotationType` +fn annotation_type_for_level(level: Level) -> AnnotationType { + match level { + Level::Bug | Level::Fatal | Level::Error => AnnotationType::Error, + Level::Warning => AnnotationType::Warning, + Level::Note => AnnotationType::Note, + Level::Help => AnnotationType::Help, + // FIXME(#59346): Not sure how to map these two levels + Level::Cancelled | Level::FailureNote => AnnotationType::Error, } } @@ -191,25 +98,76 @@ impl AnnotateSnippetEmitterWriter { message: String, code: &Option, msp: &MultiSpan, - children: &[SubDiagnostic], - suggestions: &[CodeSuggestion], + _children: &[SubDiagnostic], + _suggestions: &[CodeSuggestion], ) { - let converter = DiagnosticConverter { - source_map: self.source_map.clone(), - level: *level, - message, - code: code.clone(), - msp: msp.clone(), - children, - suggestions, - }; - if let Some(snippet) = converter.to_annotation_snippet() { - let dl = DisplayList::from(snippet); - let dlf = DisplayListFormatter::new(true, self.ui_testing); + if let Some(source_map) = &self.source_map { + // Make sure our primary file comes first + let primary_lo = if let Some(ref primary_span) = msp.primary_span().as_ref() { + source_map.lookup_char_pos(primary_span.lo()) + } else { + // FIXME(#59346): Not sure when this is the case and what + // should be done if it happens + return; + }; + let annotated_files = + FileWithAnnotatedLines::collect_annotations(msp, &self.source_map); + // owned: line source, line index, annotations + type Owned = (String, usize, Vec); + let origin = primary_lo.file.name.to_string(); + let annotated_files: Vec = annotated_files + .into_iter() + .flat_map(|annotated_file| { + let file = annotated_file.file; + annotated_file + .lines + .into_iter() + .map(|line| { + (source_string(file.clone(), &line), line.line_index, line.annotations) + }) + .collect::>() + }) + .collect(); + let snippet = Snippet { + title: Some(Annotation { + label: Some(&message), + id: code.as_ref().map(|c| match c { + DiagnosticId::Error(val) | DiagnosticId::Lint(val) => val.as_str(), + }), + annotation_type: annotation_type_for_level(*level), + }), + footer: vec![], + opt: FormatOptions { color: true, anonymized_line_numbers: self.ui_testing }, + slices: annotated_files + .iter() + .map(|(source, line_index, annotations)| { + Slice { + source, + line_start: *line_index, + origin: Some(&origin), + // FIXME(#59346): Not really sure when `fold` should be true or false + fold: false, + annotations: annotations + .into_iter() + .map(|annotation| SourceAnnotation { + range: (annotation.start_col, annotation.end_col), + label: annotation + .label + .as_ref() + .map(|s| s.as_str()) + .unwrap_or_default(), + annotation_type: annotation_type_for_level(*level), + }) + .collect(), + } + }) + .collect(), + }; // FIXME(#59346): Figure out if we can _always_ print to stderr or not. // `emitter.rs` has the `Destination` enum that lists various possible output // destinations. - eprintln!("{}", dlf.format(&dl)); - }; + eprintln!("{}", DisplayList::from(snippet)) + } + // FIXME(#59346): Is it ok to return None if there's no source_map? } } diff --git a/src/test/ui/annotate-snippet/missing-type.stderr b/src/test/ui/annotate-snippet/missing-type.stderr index 806acf0bed5d1..c16f022a77fa3 100644 --- a/src/test/ui/annotate-snippet/missing-type.stderr +++ b/src/test/ui/annotate-snippet/missing-type.stderr @@ -1,5 +1,5 @@ error[E0412]: cannot find type `Iter` in this scope - --> $DIR/missing-type.rs:4:11 + --> $DIR/missing-type.rs:4:12 | LL | let x: Iter; | ^^^^ not found in this scope From f16060f386c3ceee257b2c38ce5072b2d0943b6a Mon Sep 17 00:00:00 2001 From: Juan Aguilar Santillana Date: Sun, 10 May 2020 01:25:30 +0200 Subject: [PATCH 02/18] Add UI test where `annotated_files` count is > 1 #64205 --- .../annotate-snippet/auxiliary/multispan.rs | 37 ++++++++++++++++ src/test/ui/annotate-snippet/multispan.rs | 28 +++++++++++++ src/test/ui/annotate-snippet/multispan.stderr | 42 +++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 src/test/ui/annotate-snippet/auxiliary/multispan.rs create mode 100644 src/test/ui/annotate-snippet/multispan.rs create mode 100644 src/test/ui/annotate-snippet/multispan.stderr diff --git a/src/test/ui/annotate-snippet/auxiliary/multispan.rs b/src/test/ui/annotate-snippet/auxiliary/multispan.rs new file mode 100644 index 0000000000000..c05d15643dbb1 --- /dev/null +++ b/src/test/ui/annotate-snippet/auxiliary/multispan.rs @@ -0,0 +1,37 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Span, Diagnostic}; + +fn parse(input: TokenStream) -> Result<(), Diagnostic> { + let mut hi_spans = vec![]; + for tree in input { + if let TokenTree::Ident(ref ident) = tree { + if ident.to_string() == "hi" { + hi_spans.push(ident.span()); + } + } + } + + if !hi_spans.is_empty() { + return Err(Span::def_site() + .error("hello to you, too!") + .span_note(hi_spans, "found these 'hi's")); + } + + Ok(()) +} + +#[proc_macro] +pub fn hello(input: TokenStream) -> TokenStream { + if let Err(diag) = parse(input) { + diag.emit(); + } + + TokenStream::new() +} diff --git a/src/test/ui/annotate-snippet/multispan.rs b/src/test/ui/annotate-snippet/multispan.rs new file mode 100644 index 0000000000000..325252d7716f6 --- /dev/null +++ b/src/test/ui/annotate-snippet/multispan.rs @@ -0,0 +1,28 @@ +// aux-build:multispan.rs +// compile-flags: --error-format human-annotate-rs + +#![feature(proc_macro_hygiene)] + +extern crate multispan; + +use multispan::hello; + +fn main() { + // This one emits no error. + hello!(); + + // Exactly one 'hi'. + hello!(hi); //~ ERROR hello to you, too! + + // Now two, back to back. + hello!(hi hi); //~ ERROR hello to you, too! + + // Now three, back to back. + hello!(hi hi hi); //~ ERROR hello to you, too! + + // Now several, with spacing. + hello!(hi hey hi yo hi beep beep hi hi); //~ ERROR hello to you, too! + hello!(hi there, hi how are you? hi... hi.); //~ ERROR hello to you, too! + hello!(whoah. hi di hi di ho); //~ ERROR hello to you, too! + hello!(hi good hi and good bye); //~ ERROR hello to you, too! +} diff --git a/src/test/ui/annotate-snippet/multispan.stderr b/src/test/ui/annotate-snippet/multispan.stderr new file mode 100644 index 0000000000000..4ac31e32ba7cf --- /dev/null +++ b/src/test/ui/annotate-snippet/multispan.stderr @@ -0,0 +1,42 @@ +error: hello to you, too! + --> $DIR/multispan.rs:15:5 + | +LL | hello!(hi); + | ^^^^^^^^^^^ + | +error: hello to you, too! + --> $DIR/multispan.rs:18:5 + | +LL | hello!(hi hi); + | ^^^^^^^^^^^^^^ + | +error: hello to you, too! + --> $DIR/multispan.rs:21:5 + | +LL | hello!(hi hi hi); + | ^^^^^^^^^^^^^^^^^ + | +error: hello to you, too! + --> $DIR/multispan.rs:24:5 + | +LL | hello!(hi hey hi yo hi beep beep hi hi); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +error: hello to you, too! + --> $DIR/multispan.rs:25:5 + | +LL | hello!(hi there, hi how are you? hi... hi.); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +error: hello to you, too! + --> $DIR/multispan.rs:26:5 + | +LL | hello!(whoah. hi di hi di ho); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +error: hello to you, too! + --> $DIR/multispan.rs:27:5 + | +LL | hello!(hi good hi and good bye); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | From 8fc62029114a917969a55a50f05c1688599a5c33 Mon Sep 17 00:00:00 2001 From: Juan Aguilar Santillana Date: Sat, 16 May 2020 04:57:40 +0200 Subject: [PATCH 03/18] Fix make sure out primary file comes first --- .../annotate_snippet_emitter_writer.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs index df5e43626aab9..5b47364e714e9 100644 --- a/src/librustc_errors/annotate_snippet_emitter_writer.rs +++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs @@ -104,14 +104,25 @@ impl AnnotateSnippetEmitterWriter { if let Some(source_map) = &self.source_map { // Make sure our primary file comes first let primary_lo = if let Some(ref primary_span) = msp.primary_span().as_ref() { - source_map.lookup_char_pos(primary_span.lo()) + if primary_span.is_dummy() { + // FIXME(#59346): Not sure when this is the case and what + // should be done if it happens + return; + } else { + source_map.lookup_char_pos(primary_span.lo()) + } } else { // FIXME(#59346): Not sure when this is the case and what // should be done if it happens return; }; - let annotated_files = + let mut annotated_files = FileWithAnnotatedLines::collect_annotations(msp, &self.source_map); + if let Ok(pos) = + annotated_files.binary_search_by(|x| x.file.name.cmp(&primary_lo.file.name)) + { + annotated_files.swap(0, pos); + } // owned: line source, line index, annotations type Owned = (String, usize, Vec); let origin = primary_lo.file.name.to_string(); From 91f52a51a23f8c5e8c82c49bbf3ab1bb781d3b02 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Mon, 25 May 2020 15:16:31 -0400 Subject: [PATCH 04/18] impl AsRef<[T]> for vec::IntoIter --- src/liballoc/vec.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index d26cd77aae4b7..9e887cf446e70 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2603,6 +2603,13 @@ impl IntoIter { } } +#[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")] +impl AsRef<[T]> for IntoIter { + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Send for IntoIter {} #[stable(feature = "rust1", since = "1.0.0")] From 2b26b8b32bb2246caa0a82b6ea16f11da3686d0e Mon Sep 17 00:00:00 2001 From: Jonathan Schwender Date: Tue, 26 May 2020 15:16:57 +0200 Subject: [PATCH 05/18] Fix documentation example for gcov profiling Incremental compilation needs to be turned off. Also added the other RUSTFLAGS that should/need to be turned on. --- src/doc/unstable-book/src/compiler-flags/profile.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/doc/unstable-book/src/compiler-flags/profile.md b/src/doc/unstable-book/src/compiler-flags/profile.md index 452aca51532c9..b3b3e4eb4058f 100644 --- a/src/doc/unstable-book/src/compiler-flags/profile.md +++ b/src/doc/unstable-book/src/compiler-flags/profile.md @@ -12,10 +12,15 @@ For example: ```Bash cargo new testgcov --bin cd testgcov -export RUSTFLAGS="-Zprofile" +export RUSTFLAGS="-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort" +export CARGO_INCREMENTAL=0 cargo build cargo run ``` Once you've built and run your program, files with the `gcno` (after build) and `gcda` (after execution) extensions will be created. You can parse them with [llvm-cov gcov](https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-gcov) or [grcov](https://github.com/mozilla/grcov). + +Please note that `RUSTFLAGS` apply to everything that cargo builds and runs during a build, including build scripts! +To avoid this, pass a `RUSTC_WRAPPER` program to cargo that only adds the profiling flags to rustc for the specific +crates you want to profile. From d1e3898bd5d830c29602067ffdb87639f99f0862 Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Fri, 29 May 2020 23:41:46 +0200 Subject: [PATCH 06/18] Added the documentation for the 'use' keyword --- src/libstd/keyword_docs.rs | 58 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 6fbb0139b0eca..f74ee6a3e9b00 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -1213,9 +1213,63 @@ mod unsafe_keyword {} // /// Import or rename items from other crates or modules. /// -/// The documentation for this keyword is [not yet complete]. Pull requests welcome! +/// Usually a `use` keyword is used to shorten the path required to refer to a module item. +/// The keyword may appear in modules, blocks and even functions, usually at the top. +/// +/// The most basic usage of the keyword is `use path::to::item;`, +/// though a number of convenient shortcuts are supported: +/// +/// * Simultaneously binding a list of paths with a common prefix, +/// using the glob-like brace syntax use `a::b::{c, d, e::f, g::h::i};` +/// * Simultaneously binding a list of paths with a common prefix and their common parent module, +/// using the [`self`] keyword, such as `use a::b::{self, c, d::e};` +/// * Rebinding the target name as a new local name, using the syntax `use p::q::r as x;`. +/// This can also be used with the last two features: `use a::b::{self as ab, c as abc}`. +/// * Binding all paths matching a given prefix, +/// using the asterisk wildcard syntax `use a::b::*;`. +/// * Nesting groups of the previous features multiple times, +/// such as `use a::b::{self as ab, c, d::{*, e::f}};` +/// * Reexporting with visibility modifiers such as `pub use a::b;` +/// * Importing with `_` to only import the methods of the item without binding it to a name +/// (to avoid conflict for example): `use ::std::io::Read as _;`. +/// +/// Using path qualifiers like [`crate`], [`super`] or [`self`] is supported: `use crate::a::b;`. +/// +/// Note that when the wildcard `*` is used on a type, it does not import its methods (though +/// for `enum`s it imports the variants, as shown in the example below). +/// +/// ```compile_fail +/// # fn main() { +/// enum ExampleEnum { +/// VariantA, +/// VariantB, +/// } /// -/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 +/// impl ExampleEnum { +/// fn new() -> Self { +/// Self::VariantA +/// } +/// } +/// +/// use ExampleEnum::*; +/// +/// // Compiles. +/// let _ = VariantA; +/// +/// // Does not compile ! +/// let n = new(); +/// # } +/// ``` +/// +/// For more information on `use` and paths in general, see the [Reference]. +/// +/// The differences about paths and the `use` keyword between the 2015 and 2018 editions +/// can also be found in the [Reference]. +/// +/// [`crate`]: keyword.crate.html +/// [`self`]: keyword.self.html +/// [`super`]: keyword.super.html +/// [Reference]: ../reference/items/use-declarations.html mod use_keyword {} #[doc(keyword = "where")] From b0e524d444ea1a060b248b7ffedd48693f14285b Mon Sep 17 00:00:00 2001 From: Poliorcetics Date: Sat, 30 May 2020 18:58:54 +0200 Subject: [PATCH 07/18] Apply suggestions from code review Fix suggestions from review. Co-authored-by: Bastian Kauschke --- src/libstd/keyword_docs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index f74ee6a3e9b00..a957bcf215f27 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -1220,7 +1220,7 @@ mod unsafe_keyword {} /// though a number of convenient shortcuts are supported: /// /// * Simultaneously binding a list of paths with a common prefix, -/// using the glob-like brace syntax use `a::b::{c, d, e::f, g::h::i};` +/// using the glob-like brace syntax `use a::b::{c, d, e::f, g::h::i};` /// * Simultaneously binding a list of paths with a common prefix and their common parent module, /// using the [`self`] keyword, such as `use a::b::{self, c, d::e};` /// * Rebinding the target name as a new local name, using the syntax `use p::q::r as x;`. @@ -1230,7 +1230,7 @@ mod unsafe_keyword {} /// * Nesting groups of the previous features multiple times, /// such as `use a::b::{self as ab, c, d::{*, e::f}};` /// * Reexporting with visibility modifiers such as `pub use a::b;` -/// * Importing with `_` to only import the methods of the item without binding it to a name +/// * Importing with `_` to only import the methods of a trait without binding it to a name /// (to avoid conflict for example): `use ::std::io::Read as _;`. /// /// Using path qualifiers like [`crate`], [`super`] or [`self`] is supported: `use crate::a::b;`. From 4bae9e59373e2ef405ea2601822137bd72122ef6 Mon Sep 17 00:00:00 2001 From: Poliorcetics Date: Sat, 30 May 2020 19:18:05 +0200 Subject: [PATCH 08/18] Remove the fn main() in code example --- src/libstd/keyword_docs.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index a957bcf215f27..a4996d9eee810 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -1238,8 +1238,7 @@ mod unsafe_keyword {} /// Note that when the wildcard `*` is used on a type, it does not import its methods (though /// for `enum`s it imports the variants, as shown in the example below). /// -/// ```compile_fail -/// # fn main() { +/// ```compile_fail,edition2018 /// enum ExampleEnum { /// VariantA, /// VariantB, @@ -1258,7 +1257,6 @@ mod unsafe_keyword {} /// /// // Does not compile ! /// let n = new(); -/// # } /// ``` /// /// For more information on `use` and paths in general, see the [Reference]. From 79449986b707c18df92622a53d83eddd6872d8ee Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sun, 31 May 2020 17:16:47 +0800 Subject: [PATCH 09/18] Rearrange impl blocks with Deref as first The other blocks depends on Deref to make it easier for readers when reimplementing or reading the implementations. --- src/liballoc/vec.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 42fb1f8c737b3..6409c66b08140 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1900,6 +1900,22 @@ unsafe impl IsZero for Option> { // Common trait implementations for Vec //////////////////////////////////////////////////////////////////////////////// +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::Deref for Vec { + type Target = [T]; + + fn deref(&self) -> &[T] { + unsafe { slice::from_raw_parts(self.as_ptr(), self.len) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::DerefMut for Vec { + fn deref_mut(&mut self) -> &mut [T] { + unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Vec { #[cfg(not(test))] @@ -1955,22 +1971,6 @@ impl> IndexMut for Vec { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::Deref for Vec { - type Target = [T]; - - fn deref(&self) -> &[T] { - unsafe { slice::from_raw_parts(self.as_ptr(), self.len) } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::DerefMut for Vec { - fn deref_mut(&mut self) -> &mut [T] { - unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) } - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for Vec { #[inline] From 71404633e843e0e5a533c677a764c8cb7f2a55fb Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sun, 31 May 2020 17:19:06 +0800 Subject: [PATCH 10/18] Merge raw_vec into_box with previous impl There are two separate `impl` which no special reason, it would be better to merge both of them. --- src/liballoc/raw_vec.rs | 50 ++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 56e284a12fa83..5b365f0387a9b 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -118,6 +118,30 @@ impl RawVec { RawVec::from_raw_parts(slice.as_mut_ptr(), slice.len()) } } + + /// Converts the entire buffer into `Box<[MaybeUninit]>` with the specified `len`. + /// + /// Note that this will correctly reconstitute any `cap` changes + /// that may have been performed. (See description of type for details.) + /// + /// # Safety + /// + /// * `len` must be greater than or equal to the most recently requested capacity, and + /// * `len` must be less than or equal to `self.capacity()`. + /// + /// Note, that the requested capacity and `self.capacity()` could differ, as + /// an allocator could overallocate and return a greater memory block than requested. + pub unsafe fn into_box(self, len: usize) -> Box<[MaybeUninit]> { + // Sanity-check one half of the safety requirement (we cannot check the other half). + debug_assert!( + len <= self.capacity(), + "`len` must be smaller than or equal to `self.capacity()`" + ); + + let me = ManuallyDrop::new(self); + let slice = slice::from_raw_parts_mut(me.ptr() as *mut MaybeUninit, len); + Box::from_raw(slice) + } } impl RawVec { @@ -520,32 +544,6 @@ where Ok(memory) } -impl RawVec { - /// Converts the entire buffer into `Box<[MaybeUninit]>` with the specified `len`. - /// - /// Note that this will correctly reconstitute any `cap` changes - /// that may have been performed. (See description of type for details.) - /// - /// # Safety - /// - /// * `len` must be greater than or equal to the most recently requested capacity, and - /// * `len` must be less than or equal to `self.capacity()`. - /// - /// Note, that the requested capacity and `self.capacity()` could differ, as - /// an allocator could overallocate and return a greater memory block than requested. - pub unsafe fn into_box(self, len: usize) -> Box<[MaybeUninit]> { - // Sanity-check one half of the safety requirement (we cannot check the other half). - debug_assert!( - len <= self.capacity(), - "`len` must be smaller than or equal to `self.capacity()`" - ); - - let me = ManuallyDrop::new(self); - let slice = slice::from_raw_parts_mut(me.ptr() as *mut MaybeUninit, len); - Box::from_raw(slice) - } -} - unsafe impl<#[may_dangle] T, A: AllocRef> Drop for RawVec { /// Frees the memory owned by the `RawVec` *without* trying to drop its contents. fn drop(&mut self) { From 7bf026eed6924f7175e9df8c7c81ac2e2697daef Mon Sep 17 00:00:00 2001 From: Jonathan Schwender Date: Wed, 3 Jun 2020 11:05:56 +0200 Subject: [PATCH 11/18] Doc: unstable book - profile.md: improve wording - mention `--target` flag excludes RUSTFLAGS passing to build scripts and proc macros --- src/doc/unstable-book/src/compiler-flags/profile.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/doc/unstable-book/src/compiler-flags/profile.md b/src/doc/unstable-book/src/compiler-flags/profile.md index b3b3e4eb4058f..7973b3e4f2f32 100644 --- a/src/doc/unstable-book/src/compiler-flags/profile.md +++ b/src/doc/unstable-book/src/compiler-flags/profile.md @@ -21,6 +21,7 @@ cargo run Once you've built and run your program, files with the `gcno` (after build) and `gcda` (after execution) extensions will be created. You can parse them with [llvm-cov gcov](https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-gcov) or [grcov](https://github.com/mozilla/grcov). -Please note that `RUSTFLAGS` apply to everything that cargo builds and runs during a build, including build scripts! -To avoid this, pass a `RUSTC_WRAPPER` program to cargo that only adds the profiling flags to rustc for the specific -crates you want to profile. +Please note that `RUSTFLAGS` by default applies to everything that cargo builds and runs during a build! +When the `--target` flag is explicitly passed to cargo, the `RUSTFLAGS` no longer apply to build scripts and procedural macros. +For more fine-grained control consider passing a `RUSTC_WRAPPER` program to cargo that only adds the profiling flags to +rustc for the specific crates you want to profile. From 00a7b56bab317d9f1aaa5255145ce3414081cbfe Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Wed, 3 Jun 2020 23:32:26 +0200 Subject: [PATCH 12/18] Added the documentation about length to CString::from_raw --- src/libstd/ffi/c_str.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 4bac9a4917d8f..3d7ac724fbd5a 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -395,6 +395,12 @@ impl CString { /// ownership of a string that was allocated by foreign code) is likely to lead /// to undefined behavior or allocator corruption. /// + /// It should be noted that the length isn't just "recomputed," but that + /// the recomputed length must match the original length from the + /// [`into_raw`] call. This means the [`into_raw`]/`from_raw` methods + /// should not be used when passing the string to C functions that can + /// modify the string's length. + /// /// > **Note:** If you need to borrow a string that was allocated by /// > foreign code, use [`CStr`]. If you need to take ownership of /// > a string that was allocated by foreign code, you will need to From 87abe174c46bf10246369e63a36eccd6748b7dbe Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Wed, 3 Jun 2020 23:55:41 +0200 Subject: [PATCH 13/18] Added a warning to CString::into_raw too --- src/libstd/ffi/c_str.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 3d7ac724fbd5a..b324b1618966b 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -446,6 +446,11 @@ impl CString { /// /// Failure to call [`from_raw`] will lead to a memory leak. /// + /// The C side must **not** modify the length of the string (by writing a + /// `NULL` somewhere inside the string or removing the final one) before + /// it makes it back into Rust using [`from_raw`]. See the safety section + /// in [`from_raw`]. + /// /// [`from_raw`]: #method.from_raw /// /// # Examples From b541d3da5d9f89407c7072f4a6d65872cf30a577 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sun, 31 May 2020 16:20:50 -0400 Subject: [PATCH 14/18] Add `-Z span-debug` to allow for easier debugging of proc macros Currently, the `Debug` impl for `proc_macro::Span` just prints out the byte range. This can make debugging proc macros (either as a crate author or as a compiler developer) very frustrating, since neither the actual filename nor the `SyntaxContext` is displayed. This commit adds a perma-unstable flag `-Z span-debug`. When enabled, the `Debug` impl for `proc_macro::Span` simply forwards directly to `rustc_span::Span`. Once #72618 is merged, this will start displaying actual line numbers. While `Debug` impls are not subject to Rust's normal stability guarnatees, we probably shouldn't expose any additional information on stable until `#![feature(proc_macro_span)]` is stabilized. Otherwise, we would be providing a 'backdoor' way to access information that's supposed be behind unstable APIs. --- src/librustc_expand/expand.rs | 2 + src/librustc_expand/proc_macro_server.rs | 8 +- src/librustc_interface/passes.rs | 1 + src/librustc_interface/tests.rs | 1 + src/librustc_session/options.rs | 2 + .../proc-macro/debug/dump-debug-span-debug.rs | 41 +++++ .../debug/dump-debug-span-debug.stderr | 166 ++++++++++++++++++ 7 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/proc-macro/debug/dump-debug-span-debug.rs create mode 100644 src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 5214ca0dc7fff..4e41bd4bbfa08 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -1789,6 +1789,7 @@ pub struct ExpansionConfig<'feat> { pub trace_mac: bool, pub should_test: bool, // If false, strip `#[test]` nodes pub keep_macs: bool, + pub span_debug: bool, // If true, use verbose debugging for `proc_macro::Span` } impl<'feat> ExpansionConfig<'feat> { @@ -1800,6 +1801,7 @@ impl<'feat> ExpansionConfig<'feat> { trace_mac: false, should_test: false, keep_macs: false, + span_debug: false, } } diff --git a/src/librustc_expand/proc_macro_server.rs b/src/librustc_expand/proc_macro_server.rs index 36af83711f7e4..79fa091ba1808 100644 --- a/src/librustc_expand/proc_macro_server.rs +++ b/src/librustc_expand/proc_macro_server.rs @@ -352,6 +352,7 @@ pub(crate) struct Rustc<'a> { def_site: Span, call_site: Span, mixed_site: Span, + span_debug: bool, } impl<'a> Rustc<'a> { @@ -362,6 +363,7 @@ impl<'a> Rustc<'a> { def_site: cx.with_def_site_ctxt(expn_data.def_site), call_site: cx.with_call_site_ctxt(expn_data.call_site), mixed_site: cx.with_mixed_site_ctxt(expn_data.call_site), + span_debug: cx.ecfg.span_debug, } } @@ -646,7 +648,11 @@ impl server::Diagnostic for Rustc<'_> { impl server::Span for Rustc<'_> { fn debug(&mut self, span: Self::Span) -> String { - format!("{:?} bytes({}..{})", span.ctxt(), span.lo().0, span.hi().0) + if self.span_debug { + format!("{:?}", span) + } else { + format!("{:?} bytes({}..{})", span.ctxt(), span.lo().0, span.hi().0) + } } fn def_site(&mut self) -> Self::Span { self.def_site diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index a01170db807f2..9a60e74d94d01 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -291,6 +291,7 @@ fn configure_and_expand_inner<'a>( recursion_limit: sess.recursion_limit(), trace_mac: sess.opts.debugging_opts.trace_macros, should_test: sess.opts.test, + span_debug: sess.opts.debugging_opts.span_debug, ..rustc_expand::expand::ExpansionConfig::default(crate_name.to_string()) }; diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs index 18cbea858d47a..87647f3b0b017 100644 --- a/src/librustc_interface/tests.rs +++ b/src/librustc_interface/tests.rs @@ -506,6 +506,7 @@ fn test_debugging_options_tracking_hash() { untracked!(save_analysis, true); untracked!(self_profile, SwitchWithOptPath::Enabled(None)); untracked!(self_profile_events, Some(vec![String::new()])); + untracked!(span_debug, true); untracked!(span_free_formats, true); untracked!(strip, Strip::None); untracked!(terminal_width, Some(80)); diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index a38e7f063d79a..d22c6ec9d7d01 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -996,6 +996,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "make the current crate share its generic instantiations"), show_span: Option = (None, parse_opt_string, [TRACKED], "show spans for compiler debugging (expr|pat|ty)"), + span_debug: bool = (false, parse_bool, [UNTRACKED], + "forward proc_macro::Span's `Debug` impl to `Span`"), // o/w tests have closure@path span_free_formats: bool = (false, parse_bool, [UNTRACKED], "exclude spans when debug-printing compiler state (default: no)"), diff --git a/src/test/ui/proc-macro/debug/dump-debug-span-debug.rs b/src/test/ui/proc-macro/debug/dump-debug-span-debug.rs new file mode 100644 index 0000000000000..fd34eb974c094 --- /dev/null +++ b/src/test/ui/proc-macro/debug/dump-debug-span-debug.rs @@ -0,0 +1,41 @@ +// run-pass +// aux-build:macro-dump-debug.rs +// compile-flags: -Z span-debug + +extern crate macro_dump_debug; +use macro_dump_debug::dump_debug; + +dump_debug! { + ident // ident + r#ident // raw ident + , // alone punct + ==> // joint punct + () // empty group + [_] // nonempty group + + // unsuffixed literals + 0 + 1.0 + "S" + b"B" + r"R" + r##"R"## + br"BR" + br##"BR"## + 'C' + b'B' + + // suffixed literals + 0q + 1.0q + "S"q + b"B"q + r"R"q + r##"R"##q + br"BR"q + br##"BR"##q + 'C'q + b'B'q +} + +fn main() {} diff --git a/src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr b/src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr new file mode 100644 index 0000000000000..163a2c9f44cad --- /dev/null +++ b/src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr @@ -0,0 +1,166 @@ +TokenStream [Ident { ident: "ident", span: $DIR/dump-debug-span-debug.rs:9:5: 9:10 }, Ident { ident: "r#ident", span: $DIR/dump-debug-span-debug.rs:10:5: 10:12 }, Punct { ch: ',', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:11:5: 11:6 }, Punct { ch: '=', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 }, Punct { ch: '=', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 }, Punct { ch: '>', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:12:7: 12:8 }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/dump-debug-span-debug.rs:13:5: 13:7 }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: $DIR/dump-debug-span-debug.rs:14:6: 14:7 }], span: $DIR/dump-debug-span-debug.rs:14:5: 14:8 }, Literal { kind: Integer, symbol: "0", suffix: None, span: $DIR/dump-debug-span-debug.rs:17:5: 17:6 }, Literal { kind: Float, symbol: "1.0", suffix: None, span: $DIR/dump-debug-span-debug.rs:18:5: 18:8 }, Literal { kind: Str, symbol: "S", suffix: None, span: $DIR/dump-debug-span-debug.rs:19:5: 19:8 }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: $DIR/dump-debug-span-debug.rs:20:5: 20:9 }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: $DIR/dump-debug-span-debug.rs:21:5: 21:9 }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: $DIR/dump-debug-span-debug.rs:22:5: 22:13 }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: $DIR/dump-debug-span-debug.rs:23:5: 23:11 }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: $DIR/dump-debug-span-debug.rs:24:5: 24:15 }, Literal { kind: Char, symbol: "C", suffix: None, span: $DIR/dump-debug-span-debug.rs:25:5: 25:8 }, Literal { kind: Byte, symbol: "B", suffix: None, span: $DIR/dump-debug-span-debug.rs:26:5: 26:9 }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:29:5: 29:7 }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:30:5: 30:9 }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:31:5: 31:9 }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:32:5: 32:10 }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:33:5: 33:10 }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:34:5: 34:14 }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:35:5: 35:12 }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:36:5: 36:16 }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:37:5: 37:9 }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:38:5: 38:10 }] +TokenStream [ + Ident { + ident: "ident", + span: $DIR/dump-debug-span-debug.rs:9:5: 9:10, + }, + Ident { + ident: "r#ident", + span: $DIR/dump-debug-span-debug.rs:10:5: 10:12, + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/dump-debug-span-debug.rs:11:5: 11:6, + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/dump-debug-span-debug.rs:12:5: 12:7, + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/dump-debug-span-debug.rs:12:5: 12:7, + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/dump-debug-span-debug.rs:12:7: 12:8, + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/dump-debug-span-debug.rs:13:5: 13:7, + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "_", + span: $DIR/dump-debug-span-debug.rs:14:6: 14:7, + }, + ], + span: $DIR/dump-debug-span-debug.rs:14:5: 14:8, + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:17:5: 17:6, + }, + Literal { + kind: Float, + symbol: "1.0", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:18:5: 18:8, + }, + Literal { + kind: Str, + symbol: "S", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:19:5: 19:8, + }, + Literal { + kind: ByteStr, + symbol: "B", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:20:5: 20:9, + }, + Literal { + kind: StrRaw(0), + symbol: "R", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:21:5: 21:9, + }, + Literal { + kind: StrRaw(2), + symbol: "R", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:22:5: 22:13, + }, + Literal { + kind: ByteStrRaw(0), + symbol: "BR", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:23:5: 23:11, + }, + Literal { + kind: ByteStrRaw(2), + symbol: "BR", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:24:5: 24:15, + }, + Literal { + kind: Char, + symbol: "C", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:25:5: 25:8, + }, + Literal { + kind: Byte, + symbol: "B", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:26:5: 26:9, + }, + Literal { + kind: Integer, + symbol: "0", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:29:5: 29:7, + }, + Literal { + kind: Float, + symbol: "1.0", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:30:5: 30:9, + }, + Literal { + kind: Str, + symbol: "S", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:31:5: 31:9, + }, + Literal { + kind: ByteStr, + symbol: "B", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:32:5: 32:10, + }, + Literal { + kind: StrRaw(0), + symbol: "R", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:33:5: 33:10, + }, + Literal { + kind: StrRaw(2), + symbol: "R", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:34:5: 34:14, + }, + Literal { + kind: ByteStrRaw(0), + symbol: "BR", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:35:5: 35:12, + }, + Literal { + kind: ByteStrRaw(2), + symbol: "BR", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:36:5: 36:16, + }, + Literal { + kind: Char, + symbol: "C", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:37:5: 37:9, + }, + Literal { + kind: Byte, + symbol: "B", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:38:5: 38:10, + }, +] From ff327c87e380ed34f6304531a8b46ad0a0124082 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 6 Jun 2020 17:09:31 -0400 Subject: [PATCH 15/18] Add comments to `Resolve::get_module` --- src/librustc_resolve/build_reduced_graph.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 9ee3d989bf3f1..2ae063660e38d 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -95,24 +95,30 @@ impl<'a> Resolver<'a> { } crate fn get_module(&mut self, def_id: DefId) -> Module<'a> { + // If this is a local module, it will be in `module_map`, no need to recalculate it. if let Some(def_id) = def_id.as_local() { return self.module_map[&def_id]; } + // Cache module resolution if let Some(&module) = self.extern_module_map.get(&def_id) { return module; } let (name, parent) = if def_id.index == CRATE_DEF_INDEX { + // This is the crate root (self.cstore().crate_name_untracked(def_id.krate), None) } else { let def_key = self.cstore().def_key(def_id); ( + // This unwrap is safe: crates must always have a name def_key.disambiguated_data.data.get_opt_name().unwrap(), + // This unwrap is safe since we know this isn't the root Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id })), ) }; + // Allocate and return a new module with the information we found let kind = ModuleKind::Def(DefKind::Mod, def_id, name); let module = self.arenas.alloc_module(ModuleData::new( parent, From 8f4dfa88399320eba07e9717f60a5c32d73299a3 Mon Sep 17 00:00:00 2001 From: Ilya Bobyr Date: Wed, 3 Jun 2020 20:36:53 -0700 Subject: [PATCH 16/18] Free `default()` forwarding to `Default::default()` When creating default values a trait method needs to be called with an explicit trait name. `Default::default()` seems redundant. A free function on the other hand, when imported directly, seems to be a better API, as it is just `default()`. When implementing the trait, a method is still required. --- src/libcore/default.rs | 44 +++++++++++++++++++++++++++ src/test/ui/resolve/issue-2356.stderr | 11 ++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 06402a05d2687..9a8d65cd4e06b 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -115,6 +115,50 @@ pub trait Default: Sized { fn default() -> Self; } +/// Return the default value of a type according to the `Default` trait. +/// +/// The type to return is inferred from context; this is equivalent to +/// `Default::default()` but shorter to type. +/// +/// For example: +/// ``` +/// #![feature(default_free_fn)] +/// +/// use std::default::default; +/// +/// #[derive(Default)] +/// struct AppConfig { +/// foo: FooConfig, +/// bar: BarConfig, +/// } +/// +/// #[derive(Default)] +/// struct FooConfig { +/// foo: i32, +/// } +/// +/// #[derive(Default)] +/// struct BarConfig { +/// bar: f32, +/// baz: u8, +/// } +/// +/// fn main() { +/// let options = AppConfig { +/// foo: default(), +/// bar: BarConfig { +/// bar: 10.1, +/// ..default() +/// }, +/// }; +/// } +/// ``` +#[unstable(feature = "default_free_fn", issue = "73014")] +#[inline] +pub fn default() -> T { + Default::default() +} + /// Derive macro generating an impl of the trait `Default`. #[rustc_builtin_macro] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr index 329543114a610..b687f0b0af0ad 100644 --- a/src/test/ui/resolve/issue-2356.stderr +++ b/src/test/ui/resolve/issue-2356.stderr @@ -14,7 +14,16 @@ error[E0425]: cannot find function `default` in this scope --> $DIR/issue-2356.rs:31:5 | LL | default(); - | ^^^^^^^ help: try: `Self::default` + | ^^^^^^^ + | +help: try + | +LL | Self::default(); + | ^^^^^^^^^^^^^ +help: consider importing this function + | +LL | use std::default::default; + | error[E0425]: cannot find value `whiskers` in this scope --> $DIR/issue-2356.rs:39:5 From ebb8722ea7b184ade7015fd1094475a18e1198f7 Mon Sep 17 00:00:00 2001 From: Ilya Bobyr Date: Thu, 4 Jun 2020 23:15:35 -0700 Subject: [PATCH 17/18] unstable book: default_free_fn --- .../src/library-features/default-free-fn.md | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/doc/unstable-book/src/library-features/default-free-fn.md diff --git a/src/doc/unstable-book/src/library-features/default-free-fn.md b/src/doc/unstable-book/src/library-features/default-free-fn.md new file mode 100644 index 0000000000000..5dff73a94dd87 --- /dev/null +++ b/src/doc/unstable-book/src/library-features/default-free-fn.md @@ -0,0 +1,45 @@ +# `default_free_fn` + +The tracking issue for this feature is: [#73014] + +[#73014]: https://github.com/rust-lang/rust/issues/73014 + +------------------------ + +Adds a free `default()` function to the `std::default` module. This function +just forwards to [`Default::default()`], but may remove repetition of the word +"default" from the call site. + +Here is an example: + +```rust +#![feature(default_free_fn)] +use std::default::default; + +#[derive(Default)] +struct AppConfig { + foo: FooConfig, + bar: BarConfig, +} + +#[derive(Default)] +struct FooConfig { + foo: i32, +} + +#[derive(Default)] +struct BarConfig { + bar: f32, + baz: u8, +} + +fn main() { + let options = AppConfig { + foo: default(), + bar: BarConfig { + bar: 10.1, + ..default() + }, + }; +} +``` From af68249a8d5b106c454edb044dac9fa5dbeaf0b3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 7 Jun 2020 15:22:15 +0200 Subject: [PATCH 18/18] Clean up E0646 --- src/librustc_error_codes/error_codes/E0646.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_error_codes/error_codes/E0646.md b/src/librustc_error_codes/error_codes/E0646.md index e01dbae8b9060..1e9ec7d4380ad 100644 --- a/src/librustc_error_codes/error_codes/E0646.md +++ b/src/librustc_error_codes/error_codes/E0646.md @@ -1,4 +1,5 @@ It is not possible to define `main` with a where clause. + Erroneous code example: ```compile_fail,E0646