mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-14 21:16:50 +00:00
Auto merge of #76231 - tmandry:rollup-ilvs9fq, r=tmandry
Rollup of 14 pull requests Successful merges: - #74880 (Add trailing comma support to matches macro) - #76074 (Add new `-Z dump-mir-spanview` option) - #76088 (Add more examples to lexicographic cmp on Iterators.) - #76099 (Add info about `!` and `impl Trait`) - #76126 (Use "Fira Sans" for crate list font) - #76132 (Factor out StmtKind::MacCall fields into `MacCallStmt` struct) - #76143 (Give a better error message for duplicate built-in macros) - #76158 (Stabilise link-self-contained option) - #76201 (Move to intra-doc links for library/core/src/panic.rs) - #76206 (Make all methods of `std::net::Ipv6Addr` const) - #76207 (# Move to intra-doc links for library/core/src/clone.rs) - #76212 (Document lint missing_doc_code_examples is nightly-only) - #76218 (lexer: Tiny improvement to shebang detection) - #76221 (Clean up header in `iter` docs for `for` loops) Failed merges: r? @ghost
This commit is contained in:
commit
e36e4bd0f7
@ -922,9 +922,13 @@ impl Stmt {
|
||||
pub fn add_trailing_semicolon(mut self) -> Self {
|
||||
self.kind = match self.kind {
|
||||
StmtKind::Expr(expr) => StmtKind::Semi(expr),
|
||||
StmtKind::MacCall(mac) => StmtKind::MacCall(
|
||||
mac.map(|(mac, _style, attrs)| (mac, MacStmtStyle::Semicolon, attrs)),
|
||||
),
|
||||
StmtKind::MacCall(mac) => {
|
||||
StmtKind::MacCall(mac.map(|MacCallStmt { mac, style: _, attrs }| MacCallStmt {
|
||||
mac,
|
||||
style: MacStmtStyle::Semicolon,
|
||||
attrs,
|
||||
}))
|
||||
}
|
||||
kind => kind,
|
||||
};
|
||||
self
|
||||
@ -958,7 +962,14 @@ pub enum StmtKind {
|
||||
/// Just a trailing semi-colon.
|
||||
Empty,
|
||||
/// Macro.
|
||||
MacCall(P<(MacCall, MacStmtStyle, AttrVec)>),
|
||||
MacCall(P<MacCallStmt>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub struct MacCallStmt {
|
||||
pub mac: MacCall,
|
||||
pub style: MacStmtStyle,
|
||||
pub attrs: AttrVec,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug)]
|
||||
|
@ -16,7 +16,6 @@ use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
||||
use std::iter;
|
||||
use std::ops::DerefMut;
|
||||
|
||||
pub struct MarkedAttrs(GrowableBitSet<AttrId>);
|
||||
|
||||
@ -634,10 +633,7 @@ impl HasAttrs for StmtKind {
|
||||
StmtKind::Local(ref local) => local.attrs(),
|
||||
StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.attrs(),
|
||||
StmtKind::Empty | StmtKind::Item(..) => &[],
|
||||
StmtKind::MacCall(ref mac) => {
|
||||
let (_, _, ref attrs) = **mac;
|
||||
attrs.attrs()
|
||||
}
|
||||
StmtKind::MacCall(ref mac) => mac.attrs.attrs(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -647,8 +643,7 @@ impl HasAttrs for StmtKind {
|
||||
StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.visit_attrs(f),
|
||||
StmtKind::Empty | StmtKind::Item(..) => {}
|
||||
StmtKind::MacCall(mac) => {
|
||||
let (_mac, _style, attrs) = mac.deref_mut();
|
||||
attrs.visit_attrs(f);
|
||||
mac.attrs.visit_attrs(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1305,7 +1305,7 @@ pub fn noop_flat_map_stmt_kind<T: MutVisitor>(
|
||||
StmtKind::Semi(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Semi).collect(),
|
||||
StmtKind::Empty => smallvec![StmtKind::Empty],
|
||||
StmtKind::MacCall(mut mac) => {
|
||||
let (mac_, _semi, attrs) = mac.deref_mut();
|
||||
let MacCallStmt { mac: mac_, style: _, attrs } = mac.deref_mut();
|
||||
vis.visit_mac(mac_);
|
||||
visit_thin_attrs(attrs, vis);
|
||||
smallvec![StmtKind::MacCall(mac)]
|
||||
|
@ -692,7 +692,7 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) {
|
||||
StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => visitor.visit_expr(expr),
|
||||
StmtKind::Empty => {}
|
||||
StmtKind::MacCall(ref mac) => {
|
||||
let (ref mac, _, ref attrs) = **mac;
|
||||
let MacCallStmt { ref mac, style: _, ref attrs } = **mac;
|
||||
visitor.visit_mac(mac);
|
||||
for attr in attrs.iter() {
|
||||
visitor.visit_attribute(attr);
|
||||
|
@ -1507,11 +1507,10 @@ impl<'a> State<'a> {
|
||||
self.s.word(";");
|
||||
}
|
||||
ast::StmtKind::MacCall(ref mac) => {
|
||||
let (ref mac, style, ref attrs) = **mac;
|
||||
self.space_if_not_bol();
|
||||
self.print_outer_attributes(attrs);
|
||||
self.print_mac(mac);
|
||||
if style == ast::MacStmtStyle::Semicolon {
|
||||
self.print_outer_attributes(&mac.attrs);
|
||||
self.print_mac(&mac.mac);
|
||||
if mac.style == ast::MacStmtStyle::Semicolon {
|
||||
self.s.word(";");
|
||||
}
|
||||
}
|
||||
|
@ -1084,7 +1084,7 @@ fn get_crt_libs_path(sess: &Session) -> Option<PathBuf> {
|
||||
|
||||
fn get_object_file_path(sess: &Session, name: &str, self_contained: bool) -> PathBuf {
|
||||
// prefer system {,dll}crt2.o libs, see get_crt_libs_path comment for more details
|
||||
if sess.opts.debugging_opts.link_self_contained.is_none()
|
||||
if sess.opts.cg.link_self_contained.is_none()
|
||||
&& sess.target.target.llvm_target.contains("windows-gnu")
|
||||
{
|
||||
if let Some(compiler_libs_path) = get_crt_libs_path(sess) {
|
||||
@ -1289,7 +1289,7 @@ fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind {
|
||||
/// Whether we link to our own CRT objects instead of relying on gcc to pull them.
|
||||
/// We only provide such support for a very limited number of targets.
|
||||
fn crt_objects_fallback(sess: &Session, crate_type: CrateType) -> bool {
|
||||
if let Some(self_contained) = sess.opts.debugging_opts.link_self_contained {
|
||||
if let Some(self_contained) = sess.opts.cg.link_self_contained {
|
||||
return self_contained;
|
||||
}
|
||||
|
||||
@ -1499,7 +1499,7 @@ fn link_local_crate_native_libs_and_dependent_crate_libs<'a, B: ArchiveBuilder<'
|
||||
/// Add sysroot and other globally set directories to the directory search list.
|
||||
fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session, self_contained: bool) {
|
||||
// Prefer system mingw-w64 libs, see get_crt_libs_path comment for more details.
|
||||
if sess.opts.debugging_opts.link_self_contained.is_none()
|
||||
if sess.opts.cg.link_self_contained.is_none()
|
||||
&& cfg!(windows)
|
||||
&& sess.target.target.llvm_target.contains("windows-gnu")
|
||||
{
|
||||
|
@ -454,6 +454,7 @@ E0768: include_str!("./error_codes/E0768.md"),
|
||||
E0769: include_str!("./error_codes/E0769.md"),
|
||||
E0770: include_str!("./error_codes/E0770.md"),
|
||||
E0771: include_str!("./error_codes/E0771.md"),
|
||||
E0773: include_str!("./error_codes/E0773.md"),
|
||||
;
|
||||
// E0006, // merged with E0005
|
||||
// E0008, // cannot bind by-move into a pattern guard
|
||||
|
38
compiler/rustc_error_codes/src/error_codes/E0773.md
Normal file
38
compiler/rustc_error_codes/src/error_codes/E0773.md
Normal file
@ -0,0 +1,38 @@
|
||||
A builtin-macro was defined more than once.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0773
|
||||
#![feature(decl_macro)]
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#[rustc_builtin_macro]
|
||||
pub macro test($item:item) {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
mod inner {
|
||||
#[rustc_builtin_macro]
|
||||
pub macro test($item:item) {
|
||||
/* compiler built-in */
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To fix the issue, remove the duplicate declaration:
|
||||
|
||||
```
|
||||
#![feature(decl_macro)]
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#[rustc_builtin_macro]
|
||||
pub macro test($item:item) {
|
||||
/* compiler built-in */
|
||||
}
|
||||
```
|
||||
|
||||
In very rare edge cases, this may happen when loading `core` or `std` twice,
|
||||
once with `check` metadata and once with `build` metadata.
|
||||
For more information, see [#75176].
|
||||
|
||||
[#75176]: https://github.com/rust-lang/rust/pull/75176#issuecomment-683234468
|
@ -13,7 +13,7 @@ use rustc_ast::token;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::visit::{self, AssocCtxt, Visitor};
|
||||
use rustc_ast::{self as ast, AttrItem, Block, LitKind, NodeId, PatKind, Path};
|
||||
use rustc_ast::{ItemKind, MacArgs, MacStmtStyle, StmtKind};
|
||||
use rustc_ast::{ItemKind, MacArgs, MacCallStmt, MacStmtStyle, StmtKind};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
|
||||
use rustc_data_structures::map_in_place::MapInPlace;
|
||||
@ -1363,7 +1363,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
||||
}
|
||||
|
||||
if let StmtKind::MacCall(mac) = stmt.kind {
|
||||
let (mac, style, attrs) = mac.into_inner();
|
||||
let MacCallStmt { mac, style, attrs } = mac.into_inner();
|
||||
self.check_attributes(&attrs);
|
||||
let mut placeholder =
|
||||
self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts).make_stmts();
|
||||
|
@ -92,7 +92,11 @@ pub fn placeholder(
|
||||
AstFragment::Ty(P(ast::Ty { id, span, kind: ast::TyKind::MacCall(mac_placeholder()) }))
|
||||
}
|
||||
AstFragmentKind::Stmts => AstFragment::Stmts(smallvec![{
|
||||
let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ast::AttrVec::new()));
|
||||
let mac = P(ast::MacCallStmt {
|
||||
mac: mac_placeholder(),
|
||||
style: ast::MacStmtStyle::Braces,
|
||||
attrs: ast::AttrVec::new(),
|
||||
});
|
||||
ast::Stmt { id, span, kind: ast::StmtKind::MacCall(mac) }
|
||||
}]),
|
||||
AstFragmentKind::Arms => AstFragment::Arms(smallvec![ast::Arm {
|
||||
@ -293,7 +297,7 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
|
||||
|
||||
fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
|
||||
let (style, mut stmts) = match stmt.kind {
|
||||
ast::StmtKind::MacCall(mac) => (mac.1, self.remove(stmt.id).make_stmts()),
|
||||
ast::StmtKind::MacCall(mac) => (mac.style, self.remove(stmt.id).make_stmts()),
|
||||
_ => return noop_flat_map_stmt(stmt, self),
|
||||
};
|
||||
|
||||
|
@ -402,6 +402,7 @@ fn test_codegen_options_tracking_hash() {
|
||||
// `link_arg` is omitted because it just forwards to `link_args`.
|
||||
untracked!(link_args, vec![String::from("abc"), String::from("def")]);
|
||||
untracked!(link_dead_code, Some(true));
|
||||
untracked!(link_self_contained, Some(true));
|
||||
untracked!(linker, Some(PathBuf::from("linker")));
|
||||
untracked!(linker_flavor, Some(LinkerFlavor::Gcc));
|
||||
untracked!(no_stack_check, true);
|
||||
|
@ -191,12 +191,16 @@ pub fn strip_shebang(input: &str) -> Option<usize> {
|
||||
// For simplicity we consider any line starting with `#!` a shebang,
|
||||
// regardless of restrictions put on shebangs by specific platforms.
|
||||
if let Some(input_tail) = input.strip_prefix("#!") {
|
||||
// Ok, this is a shebang but if the next non-whitespace token is `[` or maybe
|
||||
// a doc comment (due to `TokenKind::(Line,Block)Comment` ambiguity at lexer level),
|
||||
// Ok, this is a shebang but if the next non-whitespace token is `[`,
|
||||
// then it may be valid Rust code, so consider it Rust code.
|
||||
let next_non_whitespace_token = tokenize(input_tail).map(|tok| tok.kind).find(|tok|
|
||||
!matches!(tok, TokenKind::Whitespace | TokenKind::LineComment { .. } | TokenKind::BlockComment { .. })
|
||||
);
|
||||
let next_non_whitespace_token = tokenize(input_tail).map(|tok| tok.kind).find(|tok| {
|
||||
!matches!(
|
||||
tok,
|
||||
TokenKind::Whitespace
|
||||
| TokenKind::LineComment { doc_style: None }
|
||||
| TokenKind::BlockComment { doc_style: None, .. }
|
||||
)
|
||||
});
|
||||
if next_non_whitespace_token != Some(TokenKind::OpenBracket) {
|
||||
// No other choice than to consider this a shebang.
|
||||
return Some(2 + input_tail.lines().next().unwrap_or_default().len());
|
||||
|
@ -9,6 +9,7 @@ mod alignment;
|
||||
pub mod collect_writes;
|
||||
mod graphviz;
|
||||
pub(crate) mod pretty;
|
||||
pub(crate) mod spanview;
|
||||
|
||||
pub use self::aggregate::expand_aggregate;
|
||||
pub use self::alignment::is_disaligned;
|
||||
|
@ -6,6 +6,7 @@ use std::io::{self, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use super::graphviz::write_mir_fn_graphviz;
|
||||
use super::spanview::write_mir_fn_spanview;
|
||||
use crate::transform::MirSource;
|
||||
use either::Either;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
@ -147,6 +148,16 @@ fn dump_matched_mir_node<'tcx, F>(
|
||||
write_mir_fn_graphviz(tcx, source.def_id(), body, false, &mut file)?;
|
||||
};
|
||||
}
|
||||
|
||||
if let Some(spanview) = tcx.sess.opts.debugging_opts.dump_mir_spanview {
|
||||
let _: io::Result<()> = try {
|
||||
let mut file =
|
||||
create_dump_file(tcx, "html", pass_num, pass_name, disambiguator, source)?;
|
||||
if source.def_id().is_local() {
|
||||
write_mir_fn_spanview(tcx, source.def_id(), body, spanview, &mut file)?;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the path to the filename where we should dump a given MIR.
|
||||
|
461
compiler/rustc_mir/src/util/spanview.rs
Normal file
461
compiler/rustc_mir/src/util/spanview.rs
Normal file
@ -0,0 +1,461 @@
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::hir;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::MirSpanview;
|
||||
use rustc_span::{BytePos, Pos, Span};
|
||||
|
||||
use std::io::{self, Write};
|
||||
use std::iter::Peekable;
|
||||
|
||||
pub const TOOLTIP_INDENT: &str = " ";
|
||||
|
||||
const NEW_LINE_SPAN: &str = "</span>\n<span class=\"line\">";
|
||||
const HEADER: &str = r#"<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>coverage_of_if_else - Code Regions</title>
|
||||
<style>
|
||||
.line {
|
||||
counter-increment: line;
|
||||
}
|
||||
.line:before {
|
||||
content: counter(line) ": ";
|
||||
font-family: Menlo, Monaco, monospace;
|
||||
font-style: italic;
|
||||
width: 3.8em;
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
filter: opacity(50%);
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
.code {
|
||||
color: #dddddd;
|
||||
background-color: #222222;
|
||||
font-family: Menlo, Monaco, monospace;
|
||||
line-height: 1.4em;
|
||||
border-bottom: 2px solid #222222;
|
||||
white-space: pre;
|
||||
display: inline-block;
|
||||
}
|
||||
.odd {
|
||||
background-color: #55bbff;
|
||||
color: #223311;
|
||||
}
|
||||
.even {
|
||||
background-color: #ee7756;
|
||||
color: #551133;
|
||||
}
|
||||
.code {
|
||||
--index: calc(var(--layer) - 1);
|
||||
padding-top: calc(var(--index) * 0.15em);
|
||||
filter:
|
||||
hue-rotate(calc(var(--index) * 25deg))
|
||||
saturate(calc(100% - (var(--index) * 2%)))
|
||||
brightness(calc(100% - (var(--index) * 1.5%)));
|
||||
}
|
||||
.annotation {
|
||||
color: #4444ff;
|
||||
font-family: monospace;
|
||||
font-style: italic;
|
||||
display: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
body:active .annotation {
|
||||
/* requires holding mouse down anywhere on the page */
|
||||
display: inline-block;
|
||||
}
|
||||
span:hover .annotation {
|
||||
/* requires hover over a span ONLY on its first line */
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>"#;
|
||||
|
||||
const FOOTER: &str = r#"
|
||||
</body>
|
||||
</html>"#;
|
||||
|
||||
/// Metadata to highlight the span of a MIR BasicBlock, Statement, or Terminator.
|
||||
pub struct SpanViewable {
|
||||
pub span: Span,
|
||||
pub title: String,
|
||||
pub tooltip: String,
|
||||
}
|
||||
|
||||
/// Write a spanview HTML+CSS file to analyze MIR element spans.
|
||||
pub fn write_mir_fn_spanview<'tcx, W>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
body: &Body<'tcx>,
|
||||
spanview: MirSpanview,
|
||||
w: &mut W,
|
||||
) -> io::Result<()>
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
let body_span = hir_body(tcx, def_id).value.span;
|
||||
let mut span_viewables = Vec::new();
|
||||
for (bb, data) in body.basic_blocks().iter_enumerated() {
|
||||
match spanview {
|
||||
MirSpanview::Statement => {
|
||||
for (i, statement) in data.statements.iter().enumerate() {
|
||||
if let Some(span_viewable) =
|
||||
statement_span_viewable(tcx, body_span, bb, i, statement)
|
||||
{
|
||||
span_viewables.push(span_viewable);
|
||||
}
|
||||
}
|
||||
if let Some(span_viewable) = terminator_span_viewable(tcx, body_span, bb, data) {
|
||||
span_viewables.push(span_viewable);
|
||||
}
|
||||
}
|
||||
MirSpanview::Terminator => {
|
||||
if let Some(span_viewable) = terminator_span_viewable(tcx, body_span, bb, data) {
|
||||
span_viewables.push(span_viewable);
|
||||
}
|
||||
}
|
||||
MirSpanview::Block => {
|
||||
if let Some(span_viewable) = block_span_viewable(tcx, body_span, bb, data) {
|
||||
span_viewables.push(span_viewable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
write_spanview_document(tcx, def_id, span_viewables, w)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Generate a spanview HTML+CSS document for the given local function `def_id`, and a pre-generated
|
||||
/// list `SpanViewable`s.
|
||||
pub fn write_spanview_document<'tcx, W>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
mut span_viewables: Vec<SpanViewable>,
|
||||
w: &mut W,
|
||||
) -> io::Result<()>
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
let fn_span = fn_span(tcx, def_id);
|
||||
writeln!(w, "{}", HEADER)?;
|
||||
let mut next_pos = fn_span.lo();
|
||||
let end_pos = fn_span.hi();
|
||||
let source_map = tcx.sess.source_map();
|
||||
let start = source_map.lookup_char_pos(next_pos);
|
||||
write!(
|
||||
w,
|
||||
r#"<div class="code" style="counter-reset: line {}"><span class="line">{}"#,
|
||||
start.line - 1,
|
||||
" ".repeat(start.col.to_usize())
|
||||
)?;
|
||||
span_viewables.sort_unstable_by(|a, b| {
|
||||
let a = a.span;
|
||||
let b = b.span;
|
||||
if a.lo() == b.lo() {
|
||||
// Sort hi() in reverse order so shorter spans are attempted after longer spans.
|
||||
// This should give shorter spans a higher "layer", so they are not covered by
|
||||
// the longer spans.
|
||||
b.hi().partial_cmp(&a.hi())
|
||||
} else {
|
||||
a.lo().partial_cmp(&b.lo())
|
||||
}
|
||||
.unwrap()
|
||||
});
|
||||
let mut ordered_span_viewables = span_viewables.iter().peekable();
|
||||
let mut alt = false;
|
||||
while ordered_span_viewables.peek().is_some() {
|
||||
next_pos = write_span_viewables(tcx, next_pos, &mut ordered_span_viewables, false, 1, w)?;
|
||||
alt = !alt;
|
||||
}
|
||||
if next_pos < end_pos {
|
||||
write_coverage_gap(tcx, next_pos, end_pos, w)?;
|
||||
}
|
||||
write!(w, r#"</span></div>"#)?;
|
||||
writeln!(w, "{}", FOOTER)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Format a string showing the start line and column, and end line and column within a file.
|
||||
pub fn source_range_no_file<'tcx>(tcx: TyCtxt<'tcx>, span: &Span) -> String {
|
||||
let source_map = tcx.sess.source_map();
|
||||
let start = source_map.lookup_char_pos(span.lo());
|
||||
let end = source_map.lookup_char_pos(span.hi());
|
||||
format!("{}:{}-{}:{}", start.line, start.col.to_usize() + 1, end.line, end.col.to_usize() + 1)
|
||||
}
|
||||
|
||||
pub fn statement_kind_name(statement: &Statement<'_>) -> &'static str {
|
||||
use StatementKind::*;
|
||||
match statement.kind {
|
||||
Assign(..) => "Assign",
|
||||
FakeRead(..) => "FakeRead",
|
||||
SetDiscriminant { .. } => "SetDiscriminant",
|
||||
StorageLive(..) => "StorageLive",
|
||||
StorageDead(..) => "StorageDead",
|
||||
LlvmInlineAsm(..) => "LlvmInlineAsm",
|
||||
Retag(..) => "Retag",
|
||||
AscribeUserType(..) => "AscribeUserType",
|
||||
Coverage(..) => "Coverage",
|
||||
Nop => "Nop",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn terminator_kind_name(term: &Terminator<'_>) -> &'static str {
|
||||
use TerminatorKind::*;
|
||||
match term.kind {
|
||||
Goto { .. } => "Goto",
|
||||
SwitchInt { .. } => "SwitchInt",
|
||||
Resume => "Resume",
|
||||
Abort => "Abort",
|
||||
Return => "Return",
|
||||
Unreachable => "Unreachable",
|
||||
Drop { .. } => "Drop",
|
||||
DropAndReplace { .. } => "DropAndReplace",
|
||||
Call { .. } => "Call",
|
||||
Assert { .. } => "Assert",
|
||||
Yield { .. } => "Yield",
|
||||
GeneratorDrop => "GeneratorDrop",
|
||||
FalseEdge { .. } => "FalseEdge",
|
||||
FalseUnwind { .. } => "FalseUnwind",
|
||||
InlineAsm { .. } => "InlineAsm",
|
||||
}
|
||||
}
|
||||
|
||||
fn statement_span_viewable<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body_span: Span,
|
||||
bb: BasicBlock,
|
||||
i: usize,
|
||||
statement: &Statement<'tcx>,
|
||||
) -> Option<SpanViewable> {
|
||||
let span = statement.source_info.span;
|
||||
if !body_span.contains(span) {
|
||||
return None;
|
||||
}
|
||||
let title = format!("bb{}[{}]", bb.index(), i);
|
||||
let tooltip = tooltip(tcx, &title, span, vec![statement.clone()], &None);
|
||||
Some(SpanViewable { span, title, tooltip })
|
||||
}
|
||||
|
||||
fn terminator_span_viewable<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body_span: Span,
|
||||
bb: BasicBlock,
|
||||
data: &BasicBlockData<'tcx>,
|
||||
) -> Option<SpanViewable> {
|
||||
let term = data.terminator();
|
||||
let span = term.source_info.span;
|
||||
if !body_span.contains(span) {
|
||||
return None;
|
||||
}
|
||||
let title = format!("bb{}`{}`", bb.index(), terminator_kind_name(term));
|
||||
let tooltip = tooltip(tcx, &title, span, vec![], &data.terminator);
|
||||
Some(SpanViewable { span, title, tooltip })
|
||||
}
|
||||
|
||||
fn block_span_viewable<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body_span: Span,
|
||||
bb: BasicBlock,
|
||||
data: &BasicBlockData<'tcx>,
|
||||
) -> Option<SpanViewable> {
|
||||
let span = compute_block_span(data, body_span);
|
||||
if !body_span.contains(span) {
|
||||
return None;
|
||||
}
|
||||
let title = format!("bb{}", bb.index());
|
||||
let tooltip = tooltip(tcx, &title, span, data.statements.clone(), &data.terminator);
|
||||
Some(SpanViewable { span, title, tooltip })
|
||||
}
|
||||
|
||||
fn compute_block_span<'tcx>(data: &BasicBlockData<'tcx>, body_span: Span) -> Span {
|
||||
let mut span = data.terminator().source_info.span;
|
||||
for statement_span in data.statements.iter().map(|statement| statement.source_info.span) {
|
||||
// Only combine Spans from the function's body_span.
|
||||
if body_span.contains(statement_span) {
|
||||
span = span.to(statement_span);
|
||||
}
|
||||
}
|
||||
span
|
||||
}
|
||||
|
||||
/// Recursively process each ordered span. Spans that overlap will have progressively varying
|
||||
/// styles, such as increased padding for each overlap. Non-overlapping adjacent spans will
|
||||
/// have alternating style choices, to help distinguish between them if, visually adjacent.
|
||||
/// The `layer` is incremented for each overlap, and the `alt` bool alternates between true
|
||||
/// and false, for each adjacent non-overlapping span. Source code between the spans (code
|
||||
/// that is not in any coverage region) has neutral styling.
|
||||
fn write_span_viewables<'tcx, 'b, W>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
next_pos: BytePos,
|
||||
ordered_span_viewables: &mut Peekable<impl Iterator<Item = &'b SpanViewable>>,
|
||||
alt: bool,
|
||||
layer: usize,
|
||||
w: &mut W,
|
||||
) -> io::Result<BytePos>
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
let span_viewable =
|
||||
ordered_span_viewables.next().expect("ordered_span_viewables should have some");
|
||||
if next_pos < span_viewable.span.lo() {
|
||||
write_coverage_gap(tcx, next_pos, span_viewable.span.lo(), w)?;
|
||||
}
|
||||
let mut remaining_span = span_viewable.span;
|
||||
let mut subalt = false;
|
||||
loop {
|
||||
let next_span_viewable = match ordered_span_viewables.peek() {
|
||||
None => break,
|
||||
Some(span_viewable) => *span_viewable,
|
||||
};
|
||||
if !next_span_viewable.span.overlaps(remaining_span) {
|
||||
break;
|
||||
}
|
||||
write_span(
|
||||
tcx,
|
||||
remaining_span.until(next_span_viewable.span),
|
||||
Some(span_viewable),
|
||||
alt,
|
||||
layer,
|
||||
w,
|
||||
)?;
|
||||
let next_pos = write_span_viewables(
|
||||
tcx,
|
||||
next_span_viewable.span.lo(),
|
||||
ordered_span_viewables,
|
||||
subalt,
|
||||
layer + 1,
|
||||
w,
|
||||
)?;
|
||||
subalt = !subalt;
|
||||
if next_pos < remaining_span.hi() {
|
||||
remaining_span = remaining_span.with_lo(next_pos);
|
||||
} else {
|
||||
return Ok(next_pos);
|
||||
}
|
||||
}
|
||||
write_span(tcx, remaining_span, Some(span_viewable), alt, layer, w)
|
||||
}
|
||||
|
||||
fn write_coverage_gap<'tcx, W>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
lo: BytePos,
|
||||
hi: BytePos,
|
||||
w: &mut W,
|
||||
) -> io::Result<BytePos>
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
write_span(tcx, Span::with_root_ctxt(lo, hi), None, false, 0, w)
|
||||
}
|
||||
|
||||
fn write_span<'tcx, W>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
span: Span,
|
||||
span_viewable: Option<&SpanViewable>,
|
||||
alt: bool,
|
||||
layer: usize,
|
||||
w: &mut W,
|
||||
) -> io::Result<BytePos>
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
let source_map = tcx.sess.source_map();
|
||||
let snippet = source_map
|
||||
.span_to_snippet(span)
|
||||
.unwrap_or_else(|err| bug!("span_to_snippet error for span {:?}: {:?}", span, err));
|
||||
let labeled_snippet = if let Some(SpanViewable { title, .. }) = span_viewable {
|
||||
if span.is_empty() {
|
||||
format!(r#"<span class="annotation">@{}</span>"#, title)
|
||||
} else {
|
||||
format!(r#"<span class="annotation">@{}:</span> {}"#, title, escape_html(&snippet))
|
||||
}
|
||||
} else {
|
||||
snippet
|
||||
};
|
||||
let maybe_alt = if layer > 0 {
|
||||
if alt { " odd" } else { " even" }
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let maybe_tooltip = if let Some(SpanViewable { tooltip, .. }) = span_viewable {
|
||||
format!(" title=\"{}\"", escape_attr(tooltip))
|
||||
} else {
|
||||
"".to_owned()
|
||||
};
|
||||
if layer == 1 {
|
||||
write!(w, "<span>")?;
|
||||
}
|
||||
for (i, line) in labeled_snippet.lines().enumerate() {
|
||||
if i > 0 {
|
||||
write!(w, "{}", NEW_LINE_SPAN)?;
|
||||
}
|
||||
write!(
|
||||
w,
|
||||
r#"<span class="code{}" style="--layer: {}"{}>{}</span>"#,
|
||||
maybe_alt, layer, maybe_tooltip, line
|
||||
)?;
|
||||
}
|
||||
if layer == 1 {
|
||||
write!(w, "</span>")?;
|
||||
}
|
||||
Ok(span.hi())
|
||||
}
|
||||
|
||||
fn tooltip<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
title: &str,
|
||||
span: Span,
|
||||
statements: Vec<Statement<'tcx>>,
|
||||
terminator: &Option<Terminator<'tcx>>,
|
||||
) -> String {
|
||||
let source_map = tcx.sess.source_map();
|
||||
let mut text = Vec::new();
|
||||
text.push(format!("{}: {}:", title, &source_map.span_to_string(span)));
|
||||
for statement in statements {
|
||||
let source_range = source_range_no_file(tcx, &statement.source_info.span);
|
||||
text.push(format!(
|
||||
"\n{}{}: {}: {}",
|
||||
TOOLTIP_INDENT,
|
||||
source_range,
|
||||
statement_kind_name(&statement),
|
||||
format!("{:?}", statement)
|
||||
));
|
||||
}
|
||||
if let Some(term) = terminator {
|
||||
let source_range = source_range_no_file(tcx, &term.source_info.span);
|
||||
text.push(format!(
|
||||
"\n{}{}: {}: {:?}",
|
||||
TOOLTIP_INDENT,
|
||||
source_range,
|
||||
terminator_kind_name(term),
|
||||
term.kind
|
||||
));
|
||||
}
|
||||
text.join("")
|
||||
}
|
||||
|
||||
fn fn_span<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Span {
|
||||
let hir_id =
|
||||
tcx.hir().local_def_id_to_hir_id(def_id.as_local().expect("expected DefId is local"));
|
||||
tcx.hir().span(hir_id)
|
||||
}
|
||||
|
||||
fn hir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx rustc_hir::Body<'tcx> {
|
||||
let hir_node = tcx.hir().get_if_local(def_id).expect("expected DefId is local");
|
||||
let fn_body_id = hir::map::associated_body(hir_node).expect("HIR node is a function with body");
|
||||
tcx.hir().body(fn_body_id)
|
||||
}
|
||||
|
||||
fn escape_html(s: &str) -> String {
|
||||
s.replace("&", "&").replace("<", "<").replace(">", ">")
|
||||
}
|
||||
|
||||
fn escape_attr(s: &str) -> String {
|
||||
s.replace("&", "&")
|
||||
.replace("\"", """)
|
||||
.replace("'", "'")
|
||||
.replace("<", "<")
|
||||
.replace(">", ">")
|
||||
}
|
@ -10,7 +10,7 @@ use rustc_ast as ast;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{self, TokenKind};
|
||||
use rustc_ast::util::classify;
|
||||
use rustc_ast::{AttrStyle, AttrVec, Attribute, MacCall, MacStmtStyle};
|
||||
use rustc_ast::{AttrStyle, AttrVec, Attribute, MacCall, MacCallStmt, MacStmtStyle};
|
||||
use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKind, DUMMY_NODE_ID};
|
||||
use rustc_errors::{Applicability, PResult};
|
||||
use rustc_span::source_map::{BytePos, Span};
|
||||
@ -107,7 +107,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
let kind = if delim == token::Brace || self.token == token::Semi || self.token == token::Eof
|
||||
{
|
||||
StmtKind::MacCall(P((mac, style, attrs)))
|
||||
StmtKind::MacCall(P(MacCallStmt { mac, style, attrs }))
|
||||
} else {
|
||||
// Since none of the above applied, this is an expression statement macro.
|
||||
let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac), AttrVec::new());
|
||||
|
@ -867,6 +867,12 @@ pub struct ExternPreludeEntry<'a> {
|
||||
pub introduced_by_item: bool,
|
||||
}
|
||||
|
||||
/// Used for better errors for E0773
|
||||
enum BuiltinMacroState {
|
||||
NotYetSeen(SyntaxExtension),
|
||||
AlreadySeen(Span),
|
||||
}
|
||||
|
||||
/// The main resolver class.
|
||||
///
|
||||
/// This is the visitor that walks the whole crate.
|
||||
@ -960,7 +966,7 @@ pub struct Resolver<'a> {
|
||||
|
||||
crate_loader: CrateLoader<'a>,
|
||||
macro_names: FxHashSet<Ident>,
|
||||
builtin_macros: FxHashMap<Symbol, SyntaxExtension>,
|
||||
builtin_macros: FxHashMap<Symbol, BuiltinMacroState>,
|
||||
registered_attrs: FxHashSet<Ident>,
|
||||
registered_tools: FxHashSet<Ident>,
|
||||
macro_use_prelude: FxHashMap<Symbol, &'a NameBinding<'a>>,
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
use crate::imports::ImportResolver;
|
||||
use crate::Namespace::*;
|
||||
use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy};
|
||||
use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BuiltinMacroState, Determinacy};
|
||||
use crate::{CrateLint, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Weak};
|
||||
use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding};
|
||||
use rustc_ast::{self as ast, NodeId};
|
||||
@ -11,6 +11,7 @@ use rustc_ast_lowering::ResolverAstLowering;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_attr::StabilityLevel;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_expand::base::{Indeterminate, InvocationRes, ResolverExpand, SyntaxExtension};
|
||||
use rustc_expand::compile_declarative_macro;
|
||||
use rustc_expand::expand::{AstFragment, AstFragmentKind, Invocation, InvocationKind};
|
||||
@ -166,7 +167,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
|
||||
}
|
||||
|
||||
fn register_builtin_macro(&mut self, ident: Ident, ext: SyntaxExtension) {
|
||||
if self.builtin_macros.insert(ident.name, ext).is_some() {
|
||||
if self.builtin_macros.insert(ident.name, BuiltinMacroState::NotYetSeen(ext)).is_some() {
|
||||
self.session
|
||||
.span_err(ident.span, &format!("built-in macro `{}` was already defined", ident));
|
||||
}
|
||||
@ -1076,10 +1077,23 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
if result.is_builtin {
|
||||
// The macro was marked with `#[rustc_builtin_macro]`.
|
||||
if let Some(ext) = self.builtin_macros.remove(&item.ident.name) {
|
||||
if let Some(builtin_macro) = self.builtin_macros.get_mut(&item.ident.name) {
|
||||
// The macro is a built-in, replace its expander function
|
||||
// while still taking everything else from the source code.
|
||||
result.kind = ext.kind;
|
||||
// If we already loaded this builtin macro, give a better error message than 'no such builtin macro'.
|
||||
match mem::replace(builtin_macro, BuiltinMacroState::AlreadySeen(item.span)) {
|
||||
BuiltinMacroState::NotYetSeen(ext) => result.kind = ext.kind,
|
||||
BuiltinMacroState::AlreadySeen(span) => {
|
||||
struct_span_err!(
|
||||
self.session,
|
||||
item.span,
|
||||
E0773,
|
||||
"attempted to define built-in macro more than once"
|
||||
)
|
||||
.span_note(span, "previously defined here")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let msg = format!("cannot find a built-in macro with name `{}`", item.ident);
|
||||
self.session.span_err(item.span, &msg);
|
||||
|
@ -163,6 +163,21 @@ pub enum LtoCli {
|
||||
Unspecified,
|
||||
}
|
||||
|
||||
/// The different settings that the `-Z dump_mir_spanview` flag can have. `Statement` generates a
|
||||
/// document highlighting each span of every statement (including terminators). `Terminator` and
|
||||
/// `Block` highlight a single span per `BasicBlock`: the span of the block's `Terminator`, or a
|
||||
/// computed span for the block, representing the entire range, covering the block's terminator and
|
||||
/// all of its statements.
|
||||
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
|
||||
pub enum MirSpanview {
|
||||
/// Default `-Z dump_mir_spanview` or `-Z dump_mir_spanview=statement`
|
||||
Statement,
|
||||
/// `-Z dump_mir_spanview=terminator`
|
||||
Terminator,
|
||||
/// `-Z dump_mir_spanview=block`
|
||||
Block,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Hash)]
|
||||
pub enum LinkerPluginLto {
|
||||
LinkerPlugin(PathBuf),
|
||||
|
@ -255,6 +255,7 @@ macro_rules! options {
|
||||
pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`";
|
||||
pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavor::one_of();
|
||||
pub const parse_optimization_fuel: &str = "crate=integer";
|
||||
pub const parse_mir_spanview: &str = "`statement` (default), `terminator`, or `block`";
|
||||
pub const parse_unpretty: &str = "`string` or `string=string`";
|
||||
pub const parse_treat_err_as_bug: &str = "either no value or a number bigger than 0";
|
||||
pub const parse_lto: &str =
|
||||
@ -551,6 +552,36 @@ macro_rules! options {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_mir_spanview(slot: &mut Option<MirSpanview>, v: Option<&str>) -> bool {
|
||||
if v.is_some() {
|
||||
let mut bool_arg = None;
|
||||
if parse_opt_bool(&mut bool_arg, v) {
|
||||
*slot = if bool_arg.unwrap() {
|
||||
Some(MirSpanview::Statement)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
let v = match v {
|
||||
None => {
|
||||
*slot = Some(MirSpanview::Statement);
|
||||
return true;
|
||||
}
|
||||
Some(v) => v,
|
||||
};
|
||||
|
||||
*slot = Some(match v.trim_end_matches("s") {
|
||||
"statement" | "stmt" => MirSpanview::Statement,
|
||||
"terminator" | "term" => MirSpanview::Terminator,
|
||||
"block" | "basicblock" => MirSpanview::Block,
|
||||
_ => return false,
|
||||
});
|
||||
true
|
||||
}
|
||||
|
||||
fn parse_treat_err_as_bug(slot: &mut Option<usize>, v: Option<&str>) -> bool {
|
||||
match v {
|
||||
Some(s) => { *slot = s.parse().ok().filter(|&x| x != 0); slot.unwrap_or(0) != 0 }
|
||||
@ -719,6 +750,9 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
|
||||
"extra arguments to append to the linker invocation (space separated)"),
|
||||
link_dead_code: Option<bool> = (None, parse_opt_bool, [UNTRACKED],
|
||||
"keep dead code at link time (useful for code coverage) (default: no)"),
|
||||
link_self_contained: Option<bool> = (None, parse_opt_bool, [UNTRACKED],
|
||||
"control whether to link Rust provided C objects/libraries or rely
|
||||
on C toolchain installed in the system"),
|
||||
linker: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
|
||||
"system linker to link outputs with"),
|
||||
linker_flavor: Option<LinkerFlavor> = (None, parse_linker_flavor, [UNTRACKED],
|
||||
@ -849,6 +883,11 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||
"exclude the pass number when dumping MIR (used in tests) (default: no)"),
|
||||
dump_mir_graphviz: bool = (false, parse_bool, [UNTRACKED],
|
||||
"in addition to `.mir` files, create graphviz `.dot` files (default: no)"),
|
||||
dump_mir_spanview: Option<MirSpanview> = (None, parse_mir_spanview, [UNTRACKED],
|
||||
"in addition to `.mir` files, create `.html` files to view spans for \
|
||||
all `statement`s (including terminators), only `terminator` spans, or \
|
||||
computed `block` spans (one span encompassing a block's terminator and \
|
||||
all statements)."),
|
||||
emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED],
|
||||
"emit a section containing stack size metadata (default: no)"),
|
||||
fewer_names: bool = (false, parse_bool, [TRACKED],
|
||||
@ -894,9 +933,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||
"keep hygiene data after analysis (default: no)"),
|
||||
link_native_libraries: bool = (true, parse_bool, [UNTRACKED],
|
||||
"link native libraries in the linker invocation (default: yes)"),
|
||||
link_self_contained: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||
"control whether to link Rust provided C objects/libraries or rely
|
||||
on C toolchain installed in the system"),
|
||||
link_only: bool = (false, parse_bool, [TRACKED],
|
||||
"link the `.rlink` file generated by `-Z no-link` (default: no)"),
|
||||
llvm_time_trace: bool = (false, parse_bool, [UNTRACKED],
|
||||
|
@ -7,11 +7,9 @@
|
||||
//! contain owned boxes or implement [`Drop`]), so the compiler considers
|
||||
//! them cheap and safe to copy. For other types copies must be made
|
||||
//! explicitly, by convention implementing the [`Clone`] trait and calling
|
||||
//! the [`clone`][clone] method.
|
||||
//! the [`clone`] method.
|
||||
//!
|
||||
//! [`Clone`]: trait.Clone.html
|
||||
//! [clone]: trait.Clone.html#tymethod.clone
|
||||
//! [`Drop`]: ../../std/ops/trait.Drop.html
|
||||
//! [`clone`]: Clone::clone
|
||||
//!
|
||||
//! Basic usage example:
|
||||
//!
|
||||
@ -51,7 +49,9 @@
|
||||
/// ## Derivable
|
||||
///
|
||||
/// This trait can be used with `#[derive]` if all fields are `Clone`. The `derive`d
|
||||
/// implementation of [`clone`] calls [`clone`] on each field.
|
||||
/// implementation of [`Clone`] calls [`clone`] on each field.
|
||||
///
|
||||
/// [`clone`]: Clone::clone
|
||||
///
|
||||
/// For a generic struct, `#[derive]` implements `Clone` conditionally by adding bound `Clone` on
|
||||
/// generic parameters.
|
||||
@ -74,9 +74,6 @@
|
||||
/// An example is a generic struct holding a function pointer. In this case, the
|
||||
/// implementation of `Clone` cannot be `derive`d, but can be implemented as:
|
||||
///
|
||||
/// [`Copy`]: ../../std/marker/trait.Copy.html
|
||||
/// [`clone`]: trait.Clone.html#tymethod.clone
|
||||
///
|
||||
/// ```
|
||||
/// struct Generate<T>(fn() -> T);
|
||||
///
|
||||
|
@ -135,7 +135,7 @@
|
||||
//! methods like `nth` and `fold` if an iterator can compute them more efficiently without calling
|
||||
//! `next`.
|
||||
//!
|
||||
//! # for Loops and IntoIterator
|
||||
//! # `for` loops and `IntoIterator`
|
||||
//!
|
||||
//! Rust's `for` loop syntax is actually sugar for iterators. Here's a basic
|
||||
//! example of `for`:
|
||||
|
@ -3078,6 +3078,7 @@ pub trait Iterator {
|
||||
/// assert_eq!([1].iter().lt([1].iter()), false);
|
||||
/// assert_eq!([1].iter().lt([1, 2].iter()), true);
|
||||
/// assert_eq!([1, 2].iter().lt([1].iter()), false);
|
||||
/// assert_eq!([1, 2].iter().lt([1, 2].iter()), false);
|
||||
/// ```
|
||||
#[stable(feature = "iter_order", since = "1.5.0")]
|
||||
fn lt<I>(self, other: I) -> bool
|
||||
@ -3098,6 +3099,7 @@ pub trait Iterator {
|
||||
/// assert_eq!([1].iter().le([1].iter()), true);
|
||||
/// assert_eq!([1].iter().le([1, 2].iter()), true);
|
||||
/// assert_eq!([1, 2].iter().le([1].iter()), false);
|
||||
/// assert_eq!([1, 2].iter().le([1, 2].iter()), true);
|
||||
/// ```
|
||||
#[stable(feature = "iter_order", since = "1.5.0")]
|
||||
fn le<I>(self, other: I) -> bool
|
||||
@ -3118,6 +3120,7 @@ pub trait Iterator {
|
||||
/// assert_eq!([1].iter().gt([1].iter()), false);
|
||||
/// assert_eq!([1].iter().gt([1, 2].iter()), false);
|
||||
/// assert_eq!([1, 2].iter().gt([1].iter()), true);
|
||||
/// assert_eq!([1, 2].iter().gt([1, 2].iter()), false);
|
||||
/// ```
|
||||
#[stable(feature = "iter_order", since = "1.5.0")]
|
||||
fn gt<I>(self, other: I) -> bool
|
||||
@ -3138,6 +3141,7 @@ pub trait Iterator {
|
||||
/// assert_eq!([1].iter().ge([1].iter()), true);
|
||||
/// assert_eq!([1].iter().ge([1, 2].iter()), false);
|
||||
/// assert_eq!([1, 2].iter().ge([1].iter()), true);
|
||||
/// assert_eq!([1, 2].iter().ge([1, 2].iter()), true);
|
||||
/// ```
|
||||
#[stable(feature = "iter_order", since = "1.5.0")]
|
||||
fn ge<I>(self, other: I) -> bool
|
||||
|
@ -242,7 +242,7 @@ macro_rules! debug_assert_ne {
|
||||
#[macro_export]
|
||||
#[stable(feature = "matches_macro", since = "1.42.0")]
|
||||
macro_rules! matches {
|
||||
($expression:expr, $( $pattern:pat )|+ $( if $guard: expr )?) => {
|
||||
($expression:expr, $( $pattern:pat )|+ $( if $guard: expr )? $(,)?) => {
|
||||
match $expression {
|
||||
$( $pattern )|+ $( if $guard )? => true,
|
||||
_ => false
|
||||
|
@ -92,8 +92,6 @@ impl<'a> PanicInfo<'a> {
|
||||
/// If the `panic!` macro from the `core` crate (not from `std`)
|
||||
/// was used with a formatting string and some additional arguments,
|
||||
/// returns that message ready to be used for example with [`fmt::write`]
|
||||
///
|
||||
/// [`fmt::write`]: ../fmt/fn.write.html
|
||||
#[unstable(feature = "panic_info_message", issue = "66745")]
|
||||
pub fn message(&self) -> Option<&fmt::Arguments<'_>> {
|
||||
self.message
|
||||
@ -105,8 +103,6 @@ impl<'a> PanicInfo<'a> {
|
||||
/// This method will currently always return [`Some`], but this may change
|
||||
/// in future versions.
|
||||
///
|
||||
/// [`Some`]: ../../std/option/enum.Option.html#variant.Some
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```should_panic
|
||||
@ -153,10 +149,7 @@ impl fmt::Display for PanicInfo<'_> {
|
||||
|
||||
/// A struct containing information about the location of a panic.
|
||||
///
|
||||
/// This structure is created by the [`location`] method of [`PanicInfo`].
|
||||
///
|
||||
/// [`location`]: ../../std/panic/struct.PanicInfo.html#method.location
|
||||
/// [`PanicInfo`]: ../../std/panic/struct.PanicInfo.html
|
||||
/// This structure is created by [`PanicInfo::location()`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -238,6 +238,7 @@
|
||||
#![feature(concat_idents)]
|
||||
#![feature(const_cstr_unchecked)]
|
||||
#![feature(const_fn_transmute)]
|
||||
#![feature(const_ipv6)]
|
||||
#![feature(const_raw_ptr_deref)]
|
||||
#![feature(container_error_extra)]
|
||||
#![feature(core_intrinsics)]
|
||||
|
@ -1102,8 +1102,9 @@ impl Ipv6Addr {
|
||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(),
|
||||
/// [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]);
|
||||
/// ```
|
||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn segments(&self) -> [u16; 8] {
|
||||
pub const fn segments(&self) -> [u16; 8] {
|
||||
// All elements in `s6_addr` must be big endian.
|
||||
// SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`.
|
||||
let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.inner.s6_addr) };
|
||||
@ -1135,9 +1136,10 @@ impl Ipv6Addr {
|
||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false);
|
||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true);
|
||||
/// ```
|
||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
||||
#[stable(since = "1.7.0", feature = "ip_17")]
|
||||
pub fn is_unspecified(&self) -> bool {
|
||||
self.segments() == [0, 0, 0, 0, 0, 0, 0, 0]
|
||||
pub const fn is_unspecified(&self) -> bool {
|
||||
u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets())
|
||||
}
|
||||
|
||||
/// Returns [`true`] if this is a loopback address (::1).
|
||||
@ -1155,9 +1157,10 @@ impl Ipv6Addr {
|
||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false);
|
||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true);
|
||||
/// ```
|
||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
||||
#[stable(since = "1.7.0", feature = "ip_17")]
|
||||
pub fn is_loopback(&self) -> bool {
|
||||
self.segments() == [0, 0, 0, 0, 0, 0, 0, 1]
|
||||
pub const fn is_loopback(&self) -> bool {
|
||||
u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
|
||||
}
|
||||
|
||||
/// Returns [`true`] if the address appears to be globally routable.
|
||||
@ -1182,7 +1185,8 @@ impl Ipv6Addr {
|
||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_global(), false);
|
||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true);
|
||||
/// ```
|
||||
pub fn is_global(&self) -> bool {
|
||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
||||
pub const fn is_global(&self) -> bool {
|
||||
match self.multicast_scope() {
|
||||
Some(Ipv6MulticastScope::Global) => true,
|
||||
None => self.is_unicast_global(),
|
||||
@ -1208,7 +1212,8 @@ impl Ipv6Addr {
|
||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false);
|
||||
/// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true);
|
||||
/// ```
|
||||
pub fn is_unique_local(&self) -> bool {
|
||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
||||
pub const fn is_unique_local(&self) -> bool {
|
||||
(self.segments()[0] & 0xfe00) == 0xfc00
|
||||
}
|
||||
|
||||
@ -1263,7 +1268,8 @@ impl Ipv6Addr {
|
||||
/// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
|
||||
/// [IETF RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6
|
||||
/// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
|
||||
pub fn is_unicast_link_local_strict(&self) -> bool {
|
||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
||||
pub const fn is_unicast_link_local_strict(&self) -> bool {
|
||||
(self.segments()[0] & 0xffff) == 0xfe80
|
||||
&& (self.segments()[1] & 0xffff) == 0
|
||||
&& (self.segments()[2] & 0xffff) == 0
|
||||
@ -1320,7 +1326,8 @@ impl Ipv6Addr {
|
||||
///
|
||||
/// [IETF RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4
|
||||
/// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
|
||||
pub fn is_unicast_link_local(&self) -> bool {
|
||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
||||
pub const fn is_unicast_link_local(&self) -> bool {
|
||||
(self.segments()[0] & 0xffc0) == 0xfe80
|
||||
}
|
||||
|
||||
@ -1359,7 +1366,8 @@ impl Ipv6Addr {
|
||||
/// addresses.
|
||||
///
|
||||
/// [RFC 3879]: https://tools.ietf.org/html/rfc3879
|
||||
pub fn is_unicast_site_local(&self) -> bool {
|
||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
||||
pub const fn is_unicast_site_local(&self) -> bool {
|
||||
(self.segments()[0] & 0xffc0) == 0xfec0
|
||||
}
|
||||
|
||||
@ -1381,7 +1389,8 @@ impl Ipv6Addr {
|
||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false);
|
||||
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
|
||||
/// ```
|
||||
pub fn is_documentation(&self) -> bool {
|
||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
||||
pub const fn is_documentation(&self) -> bool {
|
||||
(self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
|
||||
}
|
||||
|
||||
@ -1416,7 +1425,8 @@ impl Ipv6Addr {
|
||||
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false);
|
||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true);
|
||||
/// ```
|
||||
pub fn is_unicast_global(&self) -> bool {
|
||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
||||
pub const fn is_unicast_global(&self) -> bool {
|
||||
!self.is_multicast()
|
||||
&& !self.is_loopback()
|
||||
&& !self.is_unicast_link_local()
|
||||
@ -1440,7 +1450,8 @@ impl Ipv6Addr {
|
||||
/// );
|
||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None);
|
||||
/// ```
|
||||
pub fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
|
||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
||||
pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
|
||||
if self.is_multicast() {
|
||||
match self.segments()[0] & 0x000f {
|
||||
1 => Some(Ipv6MulticastScope::InterfaceLocal),
|
||||
@ -1472,8 +1483,9 @@ impl Ipv6Addr {
|
||||
/// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true);
|
||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false);
|
||||
/// ```
|
||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
||||
#[stable(since = "1.7.0", feature = "ip_17")]
|
||||
pub fn is_multicast(&self) -> bool {
|
||||
pub const fn is_multicast(&self) -> bool {
|
||||
(self.segments()[0] & 0xff00) == 0xff00
|
||||
}
|
||||
|
||||
@ -1498,7 +1510,8 @@ impl Ipv6Addr {
|
||||
/// Some(Ipv4Addr::new(192, 10, 2, 255)));
|
||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None);
|
||||
/// ```
|
||||
pub fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
|
||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
||||
pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
|
||||
match self.octets() {
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
|
||||
Some(Ipv4Addr::new(a, b, c, d))
|
||||
@ -1525,8 +1538,9 @@ impl Ipv6Addr {
|
||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(),
|
||||
/// Some(Ipv4Addr::new(0, 0, 0, 1)));
|
||||
/// ```
|
||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn to_ipv4(&self) -> Option<Ipv4Addr> {
|
||||
pub const fn to_ipv4(&self) -> Option<Ipv4Addr> {
|
||||
if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
|
||||
let [a, b] = ab.to_be_bytes();
|
||||
let [c, d] = cd.to_be_bytes();
|
||||
|
@ -1,7 +1,6 @@
|
||||
#[doc(primitive = "bool")]
|
||||
#[doc(alias = "true")]
|
||||
#[doc(alias = "false")]
|
||||
//
|
||||
/// The boolean type.
|
||||
///
|
||||
/// The `bool` represents a value, which could only be either `true` or `false`. If you cast
|
||||
@ -12,8 +11,8 @@
|
||||
/// `bool` implements various traits, such as [`BitAnd`], [`BitOr`], [`Not`], etc.,
|
||||
/// which allow us to perform boolean operations using `&`, `|` and `!`.
|
||||
///
|
||||
/// `if` always demands a `bool` value. [`assert!`], being an important macro in testing,
|
||||
/// checks whether an expression returns `true`.
|
||||
/// `if` always demands a `bool` value. [`assert!`], which is an important macro in testing,
|
||||
/// checks whether an expression returns `true` and panics if it isn't.
|
||||
///
|
||||
/// ```
|
||||
/// let bool_val = true & false | false;
|
||||
@ -194,14 +193,48 @@ mod prim_bool {}
|
||||
/// # `!` and traits
|
||||
///
|
||||
/// When writing your own traits, `!` should have an `impl` whenever there is an obvious `impl`
|
||||
/// which doesn't `panic!`. As it turns out, most traits can have an `impl` for `!`. Take [`Debug`]
|
||||
/// which doesn't `panic!`. The reason is that functions returning an `impl Trait` where `!`
|
||||
/// does not have an `impl` of `Trait` cannot diverge as their only possible code path. In other
|
||||
/// words, they can't return `!` from every code path. As an example, this code doesn't compile:
|
||||
///
|
||||
/// ```compile_fail
|
||||
/// use core::ops::Add;
|
||||
///
|
||||
/// fn foo() -> impl Add<u32> {
|
||||
/// unimplemented!()
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// But this code does:
|
||||
///
|
||||
/// ```
|
||||
/// use core::ops::Add;
|
||||
///
|
||||
/// fn foo() -> impl Add<u32> {
|
||||
/// if true {
|
||||
/// unimplemented!()
|
||||
/// } else {
|
||||
/// 0
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The reason is that, in the first example, there are many possible types that `!` could coerce
|
||||
/// to, because many types implement `Add<u32>`. However, in the second example,
|
||||
/// the `else` branch returns a `0`, which the compiler infers from the return type to be of type
|
||||
/// `u32`. Since `u32` is a concrete type, `!` can and will be coerced to it. See issue [#36375]
|
||||
/// for more information on this quirk of `!`.
|
||||
///
|
||||
/// [#36375]: https://github.com/rust-lang/rust/issues/36375
|
||||
///
|
||||
/// As it turns out, though, most traits can have an `impl` for `!`. Take [`Debug`]
|
||||
/// for example:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(never_type)]
|
||||
/// # use std::fmt;
|
||||
/// # trait Debug {
|
||||
/// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result;
|
||||
/// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result;
|
||||
/// # }
|
||||
/// impl Debug for ! {
|
||||
/// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
@ -44,13 +44,13 @@ incremental builds the default is 256 which allows caching to be more granular.
|
||||
|
||||
## control-flow-guard
|
||||
|
||||
This flag controls whether LLVM enables the Windows [Control Flow
|
||||
Guard](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard)
|
||||
platform security feature. This flag is currently ignored for non-Windows targets.
|
||||
This flag controls whether LLVM enables the Windows [Control Flow
|
||||
Guard](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard)
|
||||
platform security feature. This flag is currently ignored for non-Windows targets.
|
||||
It takes one of the following values:
|
||||
|
||||
* `y`, `yes`, `on`, `checks`, or no value: enable Control Flow Guard.
|
||||
* `nochecks`: emit Control Flow Guard metadata without runtime enforcement checks (this
|
||||
* `nochecks`: emit Control Flow Guard metadata without runtime enforcement checks (this
|
||||
should only be used for testing purposes as it does not provide security enforcement).
|
||||
* `n`, `no`, `off`: do not enable Control Flow Guard (the default).
|
||||
|
||||
@ -200,6 +200,18 @@ the following values:
|
||||
An example of when this flag might be useful is when trying to construct code coverage
|
||||
metrics.
|
||||
|
||||
## link-self-contained
|
||||
|
||||
On targets that support it this flag controls whether the linker will use libraries and objects
|
||||
shipped with Rust instead or those in the system.
|
||||
It takes one of the following values:
|
||||
|
||||
* no value: rustc will use heuristic to disable self-contained mode if system has necessary tools.
|
||||
* `y`, `yes`, `on`: use only libraries/objects shipped with Rust.
|
||||
* `n`, `no`, or `off`: rely on the user or the linker to provide non-Rust libraries/objects.
|
||||
|
||||
This allows overriding cases when detection fails or user wants to use shipped libraries.
|
||||
|
||||
## linker
|
||||
|
||||
This flag controls which linker `rustc` invokes to link your code. It takes a
|
||||
|
@ -51,7 +51,7 @@ warning: missing documentation for a function
|
||||
|
||||
## missing_doc_code_examples
|
||||
|
||||
This lint is **allowed by default**. It detects when a documentation block
|
||||
This lint is **allowed by default** and is **nightly-only**. It detects when a documentation block
|
||||
is missing a code example. For example:
|
||||
|
||||
```rust
|
||||
|
@ -1062,12 +1062,13 @@ themePicker.onblur = handleThemeButtonsBlur;
|
||||
let content = format!(
|
||||
"<h1 class='fqn'>\
|
||||
<span class='in-band'>List of all crates</span>\
|
||||
</h1><ul class='mod'>{}</ul>",
|
||||
</h1>\
|
||||
<ul class='crate mod'>{}</ul>",
|
||||
krates
|
||||
.iter()
|
||||
.map(|s| {
|
||||
format!(
|
||||
"<li><a class=\"mod\" href=\"{}index.html\">{}</a></li>",
|
||||
"<li><a class=\"crate mod\" href=\"{}index.html\">{}</a></li>",
|
||||
ensure_trailing_slash(s),
|
||||
s
|
||||
)
|
||||
|
@ -178,6 +178,9 @@ pre {
|
||||
.content span.externcrate, .content span.mod, .content a.mod {
|
||||
color: #acccf9;
|
||||
}
|
||||
.content ul.crate a.crate {
|
||||
font: 16px/1.6 "Fira Sans";
|
||||
}
|
||||
.content span.struct, .content a.struct {
|
||||
color: #ffa0a5;
|
||||
}
|
||||
|
5
src/test/mir-opt/spanview-block.rs
Normal file
5
src/test/mir-opt/spanview-block.rs
Normal file
@ -0,0 +1,5 @@
|
||||
// Test spanview block output
|
||||
// compile-flags: -Z dump-mir-spanview=block
|
||||
|
||||
// EMIT_MIR spanview_block.main.mir_map.0.html
|
||||
fn main() {}
|
5
src/test/mir-opt/spanview-statement.rs
Normal file
5
src/test/mir-opt/spanview-statement.rs
Normal file
@ -0,0 +1,5 @@
|
||||
// Test spanview output (the default value for `-Z dump-mir-spanview` is "statement")
|
||||
// compile-flags: -Z dump-mir-spanview
|
||||
|
||||
// EMIT_MIR spanview_statement.main.mir_map.0.html
|
||||
fn main() {}
|
5
src/test/mir-opt/spanview-terminator.rs
Normal file
5
src/test/mir-opt/spanview-terminator.rs
Normal file
@ -0,0 +1,5 @@
|
||||
// Test spanview terminator output
|
||||
// compile-flags: -Z dump-mir-spanview=terminator
|
||||
|
||||
// EMIT_MIR spanview_terminator.main.mir_map.0.html
|
||||
fn main() {}
|
67
src/test/mir-opt/spanview_block.main.mir_map.0.html
Normal file
67
src/test/mir-opt/spanview_block.main.mir_map.0.html
Normal file
@ -0,0 +1,67 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>coverage_of_if_else - Code Regions</title>
|
||||
<style>
|
||||
.line {
|
||||
counter-increment: line;
|
||||
}
|
||||
.line:before {
|
||||
content: counter(line) ": ";
|
||||
font-family: Menlo, Monaco, monospace;
|
||||
font-style: italic;
|
||||
width: 3.8em;
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
filter: opacity(50%);
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
.code {
|
||||
color: #dddddd;
|
||||
background-color: #222222;
|
||||
font-family: Menlo, Monaco, monospace;
|
||||
line-height: 1.4em;
|
||||
border-bottom: 2px solid #222222;
|
||||
white-space: pre;
|
||||
display: inline-block;
|
||||
}
|
||||
.odd {
|
||||
background-color: #55bbff;
|
||||
color: #223311;
|
||||
}
|
||||
.even {
|
||||
background-color: #ee7756;
|
||||
color: #551133;
|
||||
}
|
||||
.code {
|
||||
--index: calc(var(--layer) - 1);
|
||||
padding-top: calc(var(--index) * 0.15em);
|
||||
filter:
|
||||
hue-rotate(calc(var(--index) * 25deg))
|
||||
saturate(calc(100% - (var(--index) * 2%)))
|
||||
brightness(calc(100% - (var(--index) * 1.5%)));
|
||||
}
|
||||
.annotation {
|
||||
color: #4444ff;
|
||||
font-family: monospace;
|
||||
font-style: italic;
|
||||
display: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
body:active .annotation {
|
||||
/* requires holding mouse down anywhere on the page */
|
||||
display: inline-block;
|
||||
}
|
||||
span:hover .annotation {
|
||||
/* requires hover over a span ONLY on its first line */
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="code" style="counter-reset: line 4"><span class="line"><span class="code" style="--layer: 0">fn main() </span><span><span class="code even" style="--layer: 1" title="bb0: $DIR/spanview-block.rs:5:11: 5:13:
|
||||
5:11-5:13: Assign: _0 = const ()
|
||||
5:13-5:13: Goto: goto -> bb2"><span class="annotation">@bb0:</span> {}</span></span><span><span class="code even" style="--layer: 1" title="bb2: $DIR/spanview-block.rs:5:13: 5:13:
|
||||
5:13-5:13: Return: return"><span class="annotation">@bb2</span></span></span></span></div>
|
||||
</body>
|
||||
</html>
|
67
src/test/mir-opt/spanview_statement.main.mir_map.0.html
Normal file
67
src/test/mir-opt/spanview_statement.main.mir_map.0.html
Normal file
@ -0,0 +1,67 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>coverage_of_if_else - Code Regions</title>
|
||||
<style>
|
||||
.line {
|
||||
counter-increment: line;
|
||||
}
|
||||
.line:before {
|
||||
content: counter(line) ": ";
|
||||
font-family: Menlo, Monaco, monospace;
|
||||
font-style: italic;
|
||||
width: 3.8em;
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
filter: opacity(50%);
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
.code {
|
||||
color: #dddddd;
|
||||
background-color: #222222;
|
||||
font-family: Menlo, Monaco, monospace;
|
||||
line-height: 1.4em;
|
||||
border-bottom: 2px solid #222222;
|
||||
white-space: pre;
|
||||
display: inline-block;
|
||||
}
|
||||
.odd {
|
||||
background-color: #55bbff;
|
||||
color: #223311;
|
||||
}
|
||||
.even {
|
||||
background-color: #ee7756;
|
||||
color: #551133;
|
||||
}
|
||||
.code {
|
||||
--index: calc(var(--layer) - 1);
|
||||
padding-top: calc(var(--index) * 0.15em);
|
||||
filter:
|
||||
hue-rotate(calc(var(--index) * 25deg))
|
||||
saturate(calc(100% - (var(--index) * 2%)))
|
||||
brightness(calc(100% - (var(--index) * 1.5%)));
|
||||
}
|
||||
.annotation {
|
||||
color: #4444ff;
|
||||
font-family: monospace;
|
||||
font-style: italic;
|
||||
display: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
body:active .annotation {
|
||||
/* requires holding mouse down anywhere on the page */
|
||||
display: inline-block;
|
||||
}
|
||||
span:hover .annotation {
|
||||
/* requires hover over a span ONLY on its first line */
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="code" style="counter-reset: line 4"><span class="line"><span class="code" style="--layer: 0">fn main() </span><span><span class="code even" style="--layer: 1" title="bb0[0]: $DIR/spanview-statement.rs:5:11: 5:13:
|
||||
5:11-5:13: Assign: _0 = const ()"><span class="annotation">@bb0[0]:</span> {}</span></span><span><span class="code even" style="--layer: 1" title="bb0`Goto`: $DIR/spanview-statement.rs:5:13: 5:13:
|
||||
5:13-5:13: Goto: goto -> bb2"><span class="annotation">@bb0`Goto`</span></span></span><span><span class="code even" style="--layer: 1" title="bb2`Return`: $DIR/spanview-statement.rs:5:13: 5:13:
|
||||
5:13-5:13: Return: return"><span class="annotation">@bb2`Return`</span></span></span></span></div>
|
||||
</body>
|
||||
</html>
|
66
src/test/mir-opt/spanview_terminator.main.mir_map.0.html
Normal file
66
src/test/mir-opt/spanview_terminator.main.mir_map.0.html
Normal file
@ -0,0 +1,66 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>coverage_of_if_else - Code Regions</title>
|
||||
<style>
|
||||
.line {
|
||||
counter-increment: line;
|
||||
}
|
||||
.line:before {
|
||||
content: counter(line) ": ";
|
||||
font-family: Menlo, Monaco, monospace;
|
||||
font-style: italic;
|
||||
width: 3.8em;
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
filter: opacity(50%);
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
.code {
|
||||
color: #dddddd;
|
||||
background-color: #222222;
|
||||
font-family: Menlo, Monaco, monospace;
|
||||
line-height: 1.4em;
|
||||
border-bottom: 2px solid #222222;
|
||||
white-space: pre;
|
||||
display: inline-block;
|
||||
}
|
||||
.odd {
|
||||
background-color: #55bbff;
|
||||
color: #223311;
|
||||
}
|
||||
.even {
|
||||
background-color: #ee7756;
|
||||
color: #551133;
|
||||
}
|
||||
.code {
|
||||
--index: calc(var(--layer) - 1);
|
||||
padding-top: calc(var(--index) * 0.15em);
|
||||
filter:
|
||||
hue-rotate(calc(var(--index) * 25deg))
|
||||
saturate(calc(100% - (var(--index) * 2%)))
|
||||
brightness(calc(100% - (var(--index) * 1.5%)));
|
||||
}
|
||||
.annotation {
|
||||
color: #4444ff;
|
||||
font-family: monospace;
|
||||
font-style: italic;
|
||||
display: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
body:active .annotation {
|
||||
/* requires holding mouse down anywhere on the page */
|
||||
display: inline-block;
|
||||
}
|
||||
span:hover .annotation {
|
||||
/* requires hover over a span ONLY on its first line */
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="code" style="counter-reset: line 4"><span class="line"><span class="code" style="--layer: 0">fn main() {}</span><span><span class="code even" style="--layer: 1" title="bb0`Goto`: $DIR/spanview-terminator.rs:5:13: 5:13:
|
||||
5:13-5:13: Goto: goto -> bb2"><span class="annotation">@bb0`Goto`</span></span></span><span><span class="code even" style="--layer: 1" title="bb2`Return`: $DIR/spanview-terminator.rs:5:13: 5:13:
|
||||
5:13-5:13: Return: return"><span class="annotation">@bb2`Return`</span></span></span></span></div>
|
||||
</body>
|
||||
</html>
|
@ -6,6 +6,6 @@
|
||||
|
||||
// @has foo/../index.html
|
||||
// @has - '//span[@class="in-band"]' 'List of all crates'
|
||||
// @has - '//ul[@class="mod"]//a[@href="foo/index.html"]' 'foo'
|
||||
// @has - '//ul[@class="mod"]//a[@href="all_item_types/index.html"]' 'all_item_types'
|
||||
// @has - '//ul[@class="crate mod"]//a[@href="foo/index.html"]' 'foo'
|
||||
// @has - '//ul[@class="crate mod"]//a[@href="all_item_types/index.html"]' 'all_item_types'
|
||||
pub struct Foo;
|
||||
|
53
src/test/ui/consts/std/net/ipv6.rs
Normal file
53
src/test/ui/consts/std/net/ipv6.rs
Normal file
@ -0,0 +1,53 @@
|
||||
// run-pass
|
||||
|
||||
#![feature(ip)]
|
||||
#![feature(const_ipv6)]
|
||||
|
||||
use std::net::{Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
|
||||
|
||||
fn main() {
|
||||
const IP_ADDRESS : Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
|
||||
assert_eq!(IP_ADDRESS, Ipv6Addr::LOCALHOST);
|
||||
|
||||
const SEGMENTS : [u16; 8] = IP_ADDRESS.segments();
|
||||
assert_eq!(SEGMENTS, [0 ,0 ,0 ,0 ,0 ,0 ,0, 1]);
|
||||
|
||||
const OCTETS : [u8; 16] = IP_ADDRESS.octets();
|
||||
assert_eq!(OCTETS, [0 ,0 ,0 ,0 ,0 ,0 ,0, 0 ,0 ,0 ,0 ,0 ,0 ,0, 0, 1]);
|
||||
|
||||
const IS_UNSPECIFIED : bool = IP_ADDRESS.is_unspecified();
|
||||
assert!(!IS_UNSPECIFIED);
|
||||
|
||||
const IS_LOOPBACK : bool = IP_ADDRESS.is_loopback();
|
||||
assert!(IS_LOOPBACK);
|
||||
|
||||
const IS_GLOBAL : bool = IP_ADDRESS.is_global();
|
||||
assert!(!IS_GLOBAL);
|
||||
|
||||
const IS_UNIQUE_LOCAL : bool = IP_ADDRESS.is_unique_local();
|
||||
assert!(!IS_UNIQUE_LOCAL);
|
||||
|
||||
const IS_UNICAST_LINK_LOCAL_STRICT : bool = IP_ADDRESS.is_unicast_link_local_strict();
|
||||
assert!(!IS_UNICAST_LINK_LOCAL_STRICT);
|
||||
|
||||
const IS_UNICAST_LINK_LOCAL : bool = IP_ADDRESS.is_unicast_link_local();
|
||||
assert!(!IS_UNICAST_LINK_LOCAL);
|
||||
|
||||
const IS_UNICAST_SITE_LOCAL : bool = IP_ADDRESS.is_unicast_site_local();
|
||||
assert!(!IS_UNICAST_SITE_LOCAL);
|
||||
|
||||
const IS_DOCUMENTATION : bool = IP_ADDRESS.is_documentation();
|
||||
assert!(!IS_DOCUMENTATION);
|
||||
|
||||
const IS_UNICAST_GLOBAL : bool = IP_ADDRESS.is_unicast_global();
|
||||
assert!(!IS_UNICAST_GLOBAL);
|
||||
|
||||
const MULTICAST_SCOPE : Option<Ipv6MulticastScope> = IP_ADDRESS.multicast_scope();
|
||||
assert_eq!(MULTICAST_SCOPE, None);
|
||||
|
||||
const IS_MULTICAST : bool = IP_ADDRESS.is_multicast();
|
||||
assert!(!IS_MULTICAST);
|
||||
|
||||
const IP_V4 : Option<Ipv4Addr> = IP_ADDRESS.to_ipv4();
|
||||
assert_eq!(IP_V4.unwrap(), Ipv4Addr::new(0, 0, 0, 1));
|
||||
}
|
17
src/test/ui/macros/duplicate-builtin.rs
Normal file
17
src/test/ui/macros/duplicate-builtin.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// compile-flags:--crate-type lib
|
||||
#![feature(decl_macro)]
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#[rustc_builtin_macro]
|
||||
pub macro test($item:item) {
|
||||
//~^ NOTE previously defined
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
mod inner {
|
||||
#[rustc_builtin_macro]
|
||||
pub macro test($item:item) {
|
||||
//~^ ERROR attempted to define built-in macro more than once [E0773]
|
||||
/* compiler built-in */
|
||||
}
|
||||
}
|
21
src/test/ui/macros/duplicate-builtin.stderr
Normal file
21
src/test/ui/macros/duplicate-builtin.stderr
Normal file
@ -0,0 +1,21 @@
|
||||
error[E0773]: attempted to define built-in macro more than once
|
||||
--> $DIR/duplicate-builtin.rs:13:5
|
||||
|
|
||||
LL | / pub macro test($item:item) {
|
||||
LL | |
|
||||
LL | | /* compiler built-in */
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
note: previously defined here
|
||||
--> $DIR/duplicate-builtin.rs:6:1
|
||||
|
|
||||
LL | / pub macro test($item:item) {
|
||||
LL | |
|
||||
LL | | /* compiler built-in */
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0773`.
|
@ -1,4 +1,4 @@
|
||||
// error-pattern: cannot find a built-in macro with name `line`
|
||||
// error-pattern: attempted to define built-in macro more than once
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
macro_rules! unknown { () => () } //~ ERROR cannot find a built-in macro with name `unknown`
|
||||
|
||||
#[rustc_builtin_macro]
|
||||
macro_rules! line { () => () }
|
||||
macro_rules! line { () => () } //~ NOTE previously defined here
|
||||
|
||||
fn main() {
|
||||
line!();
|
||||
|
@ -4,7 +4,7 @@ error: cannot find a built-in macro with name `unknown`
|
||||
LL | macro_rules! unknown { () => () }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: cannot find a built-in macro with name `line`
|
||||
error[E0773]: attempted to define built-in macro more than once
|
||||
--> $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||
|
|
||||
LL | / macro_rules! line {
|
||||
@ -13,6 +13,13 @@ LL | | /* compiler built-in */
|
||||
LL | | };
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
note: previously defined here
|
||||
--> $DIR/unknown-builtin.rs:9:1
|
||||
|
|
||||
LL | macro_rules! line { () => () }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0773`.
|
||||
|
@ -1,6 +1,3 @@
|
||||
#!///bin/bash
|
||||
[allow(unused_variables)]
|
||||
//~^^ ERROR expected `[`, found doc comment
|
||||
|
||||
// Doc comment is misinterpreted as a whitespace (regular comment) during shebang detection.
|
||||
// Even if it wasn't, it would still result in an error, just a different one.
|
||||
//~^ ERROR expected item, found `[`
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: expected `[`, found doc comment `///bin/bash`
|
||||
--> $DIR/shebang-doc-comment.rs:1:3
|
||||
error: expected item, found `[`
|
||||
--> $DIR/shebang-doc-comment.rs:2:1
|
||||
|
|
||||
LL | #!///bin/bash
|
||||
| ^^^^^^^^^^^ expected `[`
|
||||
LL | [allow(unused_variables)]
|
||||
| ^ expected item
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -191,7 +191,7 @@ pub fn eq_stmt(l: &Stmt, r: &Stmt) -> bool {
|
||||
(Item(l), Item(r)) => eq_item(l, r, eq_item_kind),
|
||||
(Expr(l), Expr(r)) | (Semi(l), Semi(r)) => eq_expr(l, r),
|
||||
(Empty, Empty) => true,
|
||||
(MacCall(l), MacCall(r)) => l.1 == r.1 && eq_mac_call(&l.0, &r.0) && over(&l.2, &r.2, |l, r| eq_attr(l, r)),
|
||||
(MacCall(l), MacCall(r)) => l.style == r.style && eq_mac_call(&l.mac, &r.mac) && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r)),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user