提交 bc10b68e 编写于 作者: B bors

Auto merge of #73115 - RalfJung:rollup-jecowhz, r=RalfJung

Rollup of 10 pull requests

Successful merges:

 - #72026 (Update annotate-snippets-rs to 0.8.0)
 - #72583 (impl AsRef<[T]> for vec::IntoIter<T>)
 - #72615 (Fix documentation example for gcov profiling)
 - #72761 (Added the documentation for the 'use' keyword)
 - #72799 (Add `-Z span-debug` to allow for easier debugging of proc macros)
 - #72811 (Liballoc impl)
 - #72963 (Cstring `from_raw` and `into_raw` safety precisions)
 - #73001 (Free `default()` forwarding to `Default::default()`)
 - #73075 (Add comments to `Resolve::get_module`)
 - #73092 (Clean up E0646)

Failed merges:

r? @ghost
......@@ -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"
......@@ -3316,7 +3322,7 @@ version = "659.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c374e89b3c9714869ef86076942155383804ba6778c26be2169d324563c31f9"
dependencies = [
"annotate-snippets",
"annotate-snippets 0.6.1",
"atty",
"log",
"rustc-ap-rustc_data_structures",
......@@ -3810,7 +3816,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",
......@@ -4477,7 +4483,7 @@ dependencies = [
name = "rustfmt-nightly"
version = "1.4.15"
dependencies = [
"annotate-snippets",
"annotate-snippets 0.6.1",
"bytecount",
"cargo_metadata 0.8.0",
"derive-new",
......
......@@ -12,10 +12,16 @@ 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` 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.
# `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()
},
};
}
```
......@@ -118,6 +118,30 @@ pub fn from_box(slice: Box<[T]>) -> Self {
RawVec::from_raw_parts(slice.as_mut_ptr(), slice.len())
}
}
/// Converts the entire buffer into `Box<[MaybeUninit<T>]>` 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<T>]> {
// 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<T>, len);
Box::from_raw(slice)
}
}
impl<T, A: AllocRef> RawVec<T, A> {
......@@ -520,32 +544,6 @@ fn finish_grow<A>(
Ok(memory)
}
impl<T> RawVec<T, Global> {
/// Converts the entire buffer into `Box<[MaybeUninit<T>]>` 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<T>]> {
// 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<T>, len);
Box::from_raw(slice)
}
}
unsafe impl<#[may_dangle] T, A: AllocRef> Drop for RawVec<T, A> {
/// Frees the memory owned by the `RawVec` *without* trying to drop its contents.
fn drop(&mut self) {
......
......@@ -1905,6 +1905,22 @@ fn is_zero(&self) -> bool {
// Common trait implementations for Vec
////////////////////////////////////////////////////////////////////////////////
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ops::Deref for Vec<T> {
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<T> ops::DerefMut for Vec<T> {
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<T: Clone> Clone for Vec<T> {
#[cfg(not(test))]
......@@ -1960,22 +1976,6 @@ fn index_mut(&mut self, index: I) -> &mut Self::Output {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ops::Deref for Vec<T> {
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<T> ops::DerefMut for Vec<T> {
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<T> FromIterator<T> for Vec<T> {
#[inline]
......@@ -2628,6 +2628,13 @@ fn as_raw_mut_slice(&mut self) -> *mut [T] {
}
}
#[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")]
impl<T> AsRef<[T]> for IntoIter<T> {
fn as_ref(&self) -> &[T] {
self.as_slice()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<T: Send> Send for IntoIter<T> {}
#[stable(feature = "rust1", since = "1.0.0")]
......
......@@ -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>() -> T {
Default::default()
}
/// Derive macro generating an impl of the trait `Default`.
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
......
It is not possible to define `main` with a where clause.
Erroneous code example:
```compile_fail,E0646
......
......@@ -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]
......
......@@ -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 @@ fn should_show_explain(&self) -> bool {
}
}
/// Collects all the data needed to generate the data structures needed for the
/// `annotate-snippets` library.
struct DiagnosticConverter<'a> {
source_map: Option<Lrc<SourceMap>>,
level: Level,
message: String,
code: Option<DiagnosticId>,
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<SourceFile>, 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<Snippet> {
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<FileWithAnnotatedLines>,
primary_lo: Loc,
) -> Vec<Slice> {
// 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::<Vec<Slice>>()
})
.collect::<Vec<Slice>>()
}
/// 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<SourceFile>, 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,87 @@ fn emit_messages_default(
message: String,
code: &Option<DiagnosticId>,
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() {
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 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<crate::snippet::Annotation>);
let origin = primary_lo.file.name.to_string();
let annotated_files: Vec<Owned> = 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::<Vec<Owned>>()
})
.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?
}
}
......@@ -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 @@ pub fn default(crate_name: String) -> ExpansionConfig<'static> {
trace_mac: false,
should_test: false,
keep_macs: false,
span_debug: false,
}
}
......
......@@ -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 @@ pub fn new(cx: &'a ExtCtxt<'_>) -> Self {
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 @@ fn emit(&mut self, diag: Self::Diagnostic) {
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
......
......@@ -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())
};
......
......@@ -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));
......
......@@ -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,
......
......@@ -996,6 +996,8 @@ fn parse_target_feature(slot: &mut String, v: Option<&str>) -> bool {
"make the current crate share its generic instantiations"),
show_span: Option<String> = (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)"),
......
......@@ -395,6 +395,12 @@ pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> 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
......@@ -440,6 +446,11 @@ pub unsafe fn from_raw(ptr: *mut c_char) -> 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
......
......@@ -1213,9 +1213,61 @@ 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 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;`.
///
/// 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,edition2018
/// 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")]
......
// 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()
}
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
......
// 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!
}
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);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
// 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() {}
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,
},
]
......@@ -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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册