--- /dev/null
+---
+name: Internal Compiler Error
+about: Create a report for an internal compiler error in rustc.
+labels: C-bug, I-ICE, T-compiler
+---
+<!--
+Thank you for finding an Internal Compiler Error! 🧊 If possible, try to provide
+a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for
+how to create smaller examples.
+http://blog.pnkfx.org/blog/2019/11/18/rust-bug-minimization-patterns/
+-->
+
+### Code
+
+```Rust
+<code>
+```
+
+
+### Meta
+<!--
+If you're using the stable version of the compiler, you should also check if the
+bug also exists in the beta or nightly versions.
+-->
+
+`rustc --version --verbose`:
+```
+<version>
+```
+
+### Error output
+
+```
+<output>
+```
+
+<!--
+Include a backtrace in the code block by setting `RUST_BACKTRACE=1` in your
+environment. E.g. `RUST_BACKTRACE=1 cargo build`.
+-->
+<details><summary><strong>Backtrace</strong></summary>
+<p>
+
+```
+<backtrace>
+```
+
+</p>
+</details>
-name: Internal Compiler Error
-description: Create a report for an internal compiler error in `rustc`
+name: Internal Compiler Error (Structured form)
+description: For now, you'll want to use the other ICE template, as GitHub forms have strict limits on the size of fields so backtraces cannot be pasted directly.
labels: ["C-bug", "I-ICE", "T-compiler"]
title: "[ICE]: "
body:
label: Anything else?
description: If you have more details you want to give us to reproduce this issue, please add it here
validations:
- required: false
\ No newline at end of file
+ required: false
name: PR
env:
CI_JOB_NAME: "${{ matrix.name }}"
+ CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
SCCACHE_BUCKET: rust-lang-ci-sccache2
TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
CACHE_DOMAIN: ci-caches.rust-lang.org
name: auto
env:
CI_JOB_NAME: "${{ matrix.name }}"
+ CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
SCCACHE_BUCKET: rust-lang-ci-sccache2
DEPLOY_BUCKET: rust-lang-ci2
TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
NO_DEBUG_ASSERTIONS: 1
NO_OVERFLOW_CHECKS: 1
DIST_REQUIRE_ALL_TOOLS: 1
- os: macos-12-xl
+ os: macos-latest
- name: dist-apple-various
env:
SCRIPT: "./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim"
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
NO_OVERFLOW_CHECKS: 1
- os: macos-12-xl
+ os: macos-latest
- name: dist-x86_64-apple-alt
env:
SCRIPT: "./x.py dist bootstrap --include-default-paths"
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
NO_OVERFLOW_CHECKS: 1
- os: macos-12-xl
+ os: macos-latest
- name: x86_64-apple-1
env:
SCRIPT: "./x.py --stage 2 test --exclude tests/ui --exclude tests/rustdoc --exclude tests/run-make-fulldeps"
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
NO_OVERFLOW_CHECKS: 1
- os: macos-12-xl
+ os: macos-latest
- name: x86_64-apple-2
env:
SCRIPT: "./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps"
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
NO_OVERFLOW_CHECKS: 1
- os: macos-12-xl
+ os: macos-latest
- name: dist-aarch64-apple
env:
SCRIPT: "./x.py dist bootstrap --include-default-paths --stage 2"
NO_OVERFLOW_CHECKS: 1
DIST_REQUIRE_ALL_TOOLS: 1
JEMALLOC_SYS_WITH_LG_PAGE: 14
- os: macos-12-xl
+ os: macos-latest
- name: x86_64-msvc-1
env:
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler"
name: try
env:
CI_JOB_NAME: "${{ matrix.name }}"
+ CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
SCCACHE_BUCKET: rust-lang-ci-sccache2
DEPLOY_BUCKET: rust-lang-ci2
TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
Eduardo Bautista <me@eduardobautista.com> <=>
Eduardo Bautista <me@eduardobautista.com> <mail@eduardobautista.com>
Eduardo Broto <ebroto@tutanota.com>
+Edward Shen <code@eddie.sh> <xes@meta.com>
Elliott Slaughter <elliottslaughter@gmail.com> <eslaughter@mozilla.com>
Elly Fong-Jones <elly@leptoquark.net>
Eric Holk <eric.holk@gmail.com> <eholk@cs.indiana.edu>
[[package]]
name = "cargo"
-version = "0.69.0"
+version = "0.70.0"
dependencies = [
"anyhow",
"base64",
"jemalloc-sys",
"rustc_codegen_ssa",
"rustc_driver",
+ "rustc_driver_impl",
"rustc_smir",
]
name = "rustc_ast_lowering"
version = "0.0.0"
dependencies = [
- "rustc_arena",
"rustc_ast",
"rustc_ast_pretty",
"rustc_data_structures",
"rustc_index",
"rustc_macros",
"rustc_middle",
- "rustc_query_system",
"rustc_session",
"rustc_span",
"rustc_target",
version = "0.0.0"
dependencies = [
"rustc_ast",
- "rustc_parse_format",
"rustc_span",
]
"rustc_metadata",
"rustc_middle",
"rustc_query_system",
- "rustc_serialize",
"rustc_session",
"rustc_span",
"rustc_symbol_mangling",
"rustc_arena",
"rustc_ast",
"rustc_attr",
- "rustc_const_eval",
"rustc_data_structures",
"rustc_errors",
"rustc_fs_util",
"rustc_macros",
"rustc_middle",
"rustc_mir_dataflow",
- "rustc_query_system",
"rustc_session",
"rustc_span",
"rustc_target",
[[package]]
name = "rustc_driver"
version = "0.0.0"
+dependencies = [
+ "rustc_driver_impl",
+]
+
+[[package]]
+name = "rustc_driver_impl"
+version = "0.0.0"
dependencies = [
"libc",
"rustc_ast",
"rustc_data_structures",
"rustc_errors",
"rustc_feature",
- "rustc_graphviz",
"rustc_hir",
- "rustc_hir_pretty",
"rustc_index",
"rustc_infer",
"rustc_lint",
"rustc_macros",
"rustc_middle",
- "rustc_serialize",
"rustc_session",
"rustc_span",
"rustc_target",
"rustc_macros",
"rustc_middle",
"rustc_serialize",
- "rustc_session",
"rustc_span",
"rustc_target",
"smallvec",
"rustc_privacy",
"rustc_query_impl",
"rustc_resolve",
- "rustc_serialize",
"rustc_session",
"rustc_span",
"rustc_symbol_mangling",
"rustc_apfloat",
"rustc_arena",
"rustc_ast",
- "rustc_attr",
"rustc_data_structures",
"rustc_errors",
"rustc_hir",
"rustc_macros",
"rustc_middle",
"rustc_serialize",
- "rustc_session",
"rustc_span",
"rustc_target",
"smallvec",
"rustc_middle",
"rustc_session",
"rustc_span",
- "rustc_trait_selection",
"tracing",
]
"rustc_serialize",
"rustc_session",
"rustc_span",
- "rustc_target",
"thin-vec",
"tracing",
]
"rustc_hir",
"rustc_index",
"rustc_infer",
- "rustc_lint_defs",
"rustc_macros",
"rustc_middle",
"rustc_parse_format",
"chalk-ir",
"chalk-solve",
"rustc_ast",
- "rustc_attr",
"rustc_data_structures",
"rustc_hir",
"rustc_index",
[dependencies]
rustc_driver = { path = "../rustc_driver" }
+rustc_driver_impl = { path = "../rustc_driver_impl" }
# Make sure rustc_codegen_ssa ends up in the sysroot, because this
# crate is intended to be used by codegen backends, which may not be in-tree.
[features]
jemalloc = ['jemalloc-sys']
-llvm = ['rustc_driver/llvm']
-max_level_info = ['rustc_driver/max_level_info']
-rustc_use_parallel_compiler = ['rustc_driver/rustc_use_parallel_compiler']
+llvm = ['rustc_driver_impl/llvm']
+max_level_info = ['rustc_driver_impl/max_level_info']
+rustc_use_parallel_compiler = ['rustc_driver_impl/rustc_use_parallel_compiler']
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum PointerKind {
- /// Most general case, we know no restrictions to tell LLVM.
- SharedMutable,
-
- /// `&T` where `T` contains no `UnsafeCell`, is `dereferenceable`, `noalias` and `readonly`.
- Frozen,
-
- /// `&mut T` which is `dereferenceable` and `noalias` but not `readonly`.
- UniqueBorrowed,
-
- /// `&mut !Unpin`, which is `dereferenceable` but neither `noalias` nor `readonly`.
- UniqueBorrowedPinned,
-
- /// `Box<T>`, which is `noalias` (even on return types, unlike the above) but neither `readonly`
- /// nor `dereferenceable`.
- UniqueOwned,
+ /// Shared reference. `frozen` indicates the absence of any `UnsafeCell`.
+ SharedRef { frozen: bool },
+ /// Mutable reference. `unpin` indicates the absence of any pinned data.
+ MutableRef { unpin: bool },
+ /// Box. `unpin` indicates the absence of any pinned data.
+ Box { unpin: bool },
}
+/// Note that this information is advisory only, and backends are free to ignore it.
+/// It can only be used to encode potential optimizations, but no critical information.
#[derive(Copy, Clone, Debug)]
pub struct PointeeInfo {
pub size: Size,
}
impl LitKind {
+ pub fn str(&self) -> Option<Symbol> {
+ match *self {
+ LitKind::Str(s, _) => Some(s),
+ _ => None,
+ }
+ }
+
/// Returns `true` if this literal is a string.
pub fn is_str(&self) -> bool {
matches!(self, LitKind::Str(..))
pub fn value_str(&self) -> Option<Symbol> {
match &self.kind {
- AttrKind::Normal(normal) => normal.item.meta_kind().and_then(|kind| kind.value_str()),
+ AttrKind::Normal(normal) => normal.item.value_str(),
AttrKind::DocComment(..) => None,
}
}
pub fn meta_item_list(&self) -> Option<Vec<NestedMetaItem>> {
match &self.kind {
- AttrKind::Normal(normal) => match normal.item.meta_kind() {
- Some(MetaItemKind::List(list)) => Some(list),
- _ => None,
- },
+ AttrKind::Normal(normal) => normal.item.meta_item_list(),
AttrKind::DocComment(..) => None,
}
}
}
}
+impl AttrArgsEq {
+ fn value_str(&self) -> Option<Symbol> {
+ match self {
+ AttrArgsEq::Ast(expr) => match expr.kind {
+ ExprKind::Lit(token_lit) => {
+ LitKind::from_token_lit(token_lit).ok().and_then(|lit| lit.str())
+ }
+ _ => None,
+ },
+ AttrArgsEq::Hir(lit) => lit.kind.str(),
+ }
+ }
+}
+
impl AttrItem {
pub fn span(&self) -> Span {
self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span))
pub fn meta_kind(&self) -> Option<MetaItemKind> {
MetaItemKind::from_attr_args(&self.args)
}
+
+ fn meta_item_list(&self) -> Option<Vec<NestedMetaItem>> {
+ match &self.args {
+ AttrArgs::Delimited(args) if args.delim == MacDelimiter::Parenthesis => {
+ MetaItemKind::list_from_tokens(args.tokens.clone())
+ }
+ AttrArgs::Delimited(_) | AttrArgs::Eq(..) | AttrArgs::Empty => None,
+ }
+ }
+
+ fn value_str(&self) -> Option<Symbol> {
+ match &self.args {
+ AttrArgs::Eq(_, args) => args.value_str(),
+ AttrArgs::Delimited(_) | AttrArgs::Empty => None,
+ }
+ }
}
impl Attribute {
/// * `#[doc = "doc"]` returns `Some(("doc", CommentKind::Line))`.
/// * `#[doc(...)]` returns `None`.
pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
- match self.kind {
- AttrKind::DocComment(kind, data) => Some((data, kind)),
- AttrKind::Normal(ref normal) if normal.item.path == sym::doc => normal
- .item
- .meta_kind()
- .and_then(|kind| kind.value_str())
- .map(|data| (data, CommentKind::Line)),
+ match &self.kind {
+ AttrKind::DocComment(kind, data) => Some((*data, *kind)),
+ AttrKind::Normal(normal) if normal.item.path == sym::doc => {
+ normal.item.value_str().map(|s| (s, CommentKind::Line))
+ }
_ => None,
}
}
pub fn doc_str(&self) -> Option<Symbol> {
match &self.kind {
AttrKind::DocComment(.., data) => Some(*data),
- AttrKind::Normal(normal) if normal.item.path == sym::doc => {
- normal.item.meta_kind().and_then(|kind| kind.value_str())
- }
+ AttrKind::Normal(normal) if normal.item.path == sym::doc => normal.item.value_str(),
_ => None,
}
}
impl MetaItemKind {
pub fn value_str(&self) -> Option<Symbol> {
match self {
- MetaItemKind::NameValue(v) => match v.kind {
- LitKind::Str(s, _) => Some(s),
- _ => None,
- },
+ MetaItemKind::NameValue(v) => v.kind.str(),
_ => None,
}
}
- fn list_from_tokens(tokens: TokenStream) -> Option<MetaItemKind> {
+ fn list_from_tokens(tokens: TokenStream) -> Option<Vec<NestedMetaItem>> {
let mut tokens = tokens.into_trees().peekable();
let mut result = Vec::new();
while tokens.peek().is_some() {
_ => return None,
}
}
- Some(MetaItemKind::List(result))
+ Some(result)
}
fn name_value_from_tokens(
dspan: _,
delim: MacDelimiter::Parenthesis,
tokens,
- }) => MetaItemKind::list_from_tokens(tokens.clone()),
+ }) => MetaItemKind::list_from_tokens(tokens.clone()).map(MetaItemKind::List),
AttrArgs::Delimited(..) => None,
AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => match expr.kind {
ExprKind::Lit(token_lit) => {
Some(TokenTree::Delimited(_, Delimiter::Parenthesis, inner_tokens)) => {
let inner_tokens = inner_tokens.clone();
tokens.next();
- MetaItemKind::list_from_tokens(inner_tokens)
+ MetaItemKind::list_from_tokens(inner_tokens).map(MetaItemKind::List)
}
Some(TokenTree::Delimited(..)) => None,
Some(TokenTree::Token(Token { kind: token::Eq, .. }, _)) => {
/// Nothing special happens to misnamed or misplaced `SubstNt`s.
#[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
pub enum TokenTree {
- /// A single token.
+ /// A single token. Should never be `OpenDelim` or `CloseDelim`, because
+ /// delimiters are implicitly represented by `Delimited`.
Token(Token, Spacing),
/// A delimited sequence of token trees.
Delimited(DelimSpan, Delimiter, TokenStream),
self.0.len()
}
- pub fn trees(&self) -> CursorRef<'_> {
- CursorRef::new(self)
+ pub fn trees(&self) -> RefTokenTreeCursor<'_> {
+ RefTokenTreeCursor::new(self)
}
- pub fn into_trees(self) -> Cursor {
- Cursor::new(self)
+ pub fn into_trees(self) -> TokenTreeCursor {
+ TokenTreeCursor::new(self)
}
/// Compares two `TokenStream`s, checking equality without regarding span information.
}
}
-/// By-reference iterator over a [`TokenStream`].
+/// By-reference iterator over a [`TokenStream`], that produces `&TokenTree`
+/// items.
#[derive(Clone)]
-pub struct CursorRef<'t> {
+pub struct RefTokenTreeCursor<'t> {
stream: &'t TokenStream,
index: usize,
}
-impl<'t> CursorRef<'t> {
+impl<'t> RefTokenTreeCursor<'t> {
fn new(stream: &'t TokenStream) -> Self {
- CursorRef { stream, index: 0 }
+ RefTokenTreeCursor { stream, index: 0 }
}
pub fn look_ahead(&self, n: usize) -> Option<&TokenTree> {
}
}
-impl<'t> Iterator for CursorRef<'t> {
+impl<'t> Iterator for RefTokenTreeCursor<'t> {
type Item = &'t TokenTree;
fn next(&mut self) -> Option<&'t TokenTree> {
}
}
-/// Owning by-value iterator over a [`TokenStream`].
+/// Owning by-value iterator over a [`TokenStream`], that produces `TokenTree`
+/// items.
// FIXME: Many uses of this can be replaced with by-reference iterator to avoid clones.
#[derive(Clone)]
-pub struct Cursor {
+pub struct TokenTreeCursor {
pub stream: TokenStream,
index: usize,
}
-impl Iterator for Cursor {
+impl Iterator for TokenTreeCursor {
type Item = TokenTree;
fn next(&mut self) -> Option<TokenTree> {
}
}
-impl Cursor {
+impl TokenTreeCursor {
fn new(stream: TokenStream) -> Self {
- Cursor { stream, index: 0 }
+ TokenTreeCursor { stream, index: 0 }
}
#[inline]
pub fn look_ahead(&self, n: usize) -> Option<&TokenTree> {
self.stream.0.get(self.index + n)
}
+
+ // Replace the previously obtained token tree with `tts`, and rewind to
+ // just before them.
+ pub fn replace_prev_and_rewind(&mut self, tts: Vec<TokenTree>) {
+ assert!(self.index > 0);
+ self.index -= 1;
+ let stream = Lrc::make_mut(&mut self.stream.0);
+ stream.splice(self.index..self.index + 1, tts);
+ }
}
#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
// In case we have doc comments like `/**` or `/*!`, we want to remove stars if they are
// present. However, we first need to strip the empty lines so they don't get in the middle
// when we try to compute the "horizontal trim".
- let lines = if kind == CommentKind::Block {
- // Whatever happens, we skip the first line.
- let mut i = lines
- .get(0)
- .map(|l| if l.trim_start().starts_with('*') { 0 } else { 1 })
- .unwrap_or(0);
- let mut j = lines.len();
-
- while i < j && lines[i].trim().is_empty() {
- i += 1;
- }
- while j > i && lines[j - 1].trim().is_empty() {
- j -= 1;
+ let lines = match kind {
+ CommentKind::Block => {
+ // Whatever happens, we skip the first line.
+ let mut i = lines
+ .get(0)
+ .map(|l| if l.trim_start().starts_with('*') { 0 } else { 1 })
+ .unwrap_or(0);
+ let mut j = lines.len();
+
+ while i < j && lines[i].trim().is_empty() {
+ i += 1;
+ }
+ while j > i && lines[j - 1].trim().is_empty() {
+ j -= 1;
+ }
+ &lines[i..j]
}
- &lines[i..j]
- } else {
- lines
+ CommentKind::Line => lines,
};
for line in lines {
walk_list!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Ref);
visitor.visit_ty(&mutable_type.ty)
}
- TyKind::Tup(tys) => {
- walk_list!(visitor, visit_ty, tys);
+ TyKind::Tup(tuple_element_types) => {
+ walk_list!(visitor, visit_ty, tuple_element_types);
}
TyKind::BareFn(function_declaration) => {
walk_list!(visitor, visit_generic_param, &function_declaration.generic_params);
doctest = false
[dependencies]
-rustc_arena = { path = "../rustc_arena" }
rustc_ast = { path = "../rustc_ast" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_index = { path = "../rustc_index" }
rustc_middle = { path = "../rustc_middle" }
rustc_macros = { path = "../rustc_macros" }
-rustc_query_system = { path = "../rustc_query_system" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
[dependencies]
rustc_ast = { path = "../rustc_ast" }
-rustc_parse_format = { path = "../rustc_parse_format" }
rustc_span = { path = "../rustc_span" }
// Currently, in Rust 2018 we don't have `extern crate std;` at the crate
// root, so this is not needed, and actually breaks things.
- if edition == Edition::Edition2015 {
+ if edition.is_rust_2015() {
// `#![no_std]`
let fake_attr = attr::mk_attr_word(g, ast::AttrStyle::Inner, sym::no_std, DUMMY_SP);
s.print_attribute(&fake_attr);
operands,
) = rvalue
{
+ let def_id = def_id.expect_local();
for operand in operands {
let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand else {
continue;
// into a place then we should annotate the closure in
// case it ends up being assigned into the return place.
annotated_closure =
- self.annotate_fn_sig(*def_id, substs.as_closure().sig());
+ self.annotate_fn_sig(def_id, substs.as_closure().sig());
debug!(
"annotate_argument_and_return_for_borrow: \
annotated_closure={:?} assigned_from_local={:?} \
&& let AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) = **kind
{
debug!("move_spans: def_id={:?} places={:?}", def_id, places);
+ let def_id = def_id.expect_local();
if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
self.closure_span(def_id, moved_place, places)
{
box AggregateKind::Generator(def_id, _, _) => (def_id, true),
_ => continue,
};
+ let def_id = def_id.expect_local();
debug!(
"borrow_spans: def_id={:?} is_generator={:?} places={:?}",
} else {
err.span_help(source_info.span, "try removing `&mut` here");
}
- } else if decl.mutability == Mutability::Not {
+ } else if decl.mutability.is_not() {
if matches!(
decl.local_info,
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(
}
}
Some((false, err_label_span, message)) => {
- err.span_label(
- err_label_span,
- &format!(
- "consider changing this binding's type to be: `{message}`"
- ),
- );
+ struct BindingFinder {
+ span: Span,
+ hir_id: Option<hir::HirId>,
+ }
+
+ impl<'tcx> Visitor<'tcx> for BindingFinder {
+ fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) {
+ if let hir::StmtKind::Local(local) = s.kind {
+ if local.pat.span == self.span {
+ self.hir_id = Some(local.hir_id);
+ }
+ }
+ hir::intravisit::walk_stmt(self, s);
+ }
+ }
+ let hir_map = self.infcx.tcx.hir();
+ let def_id = self.body.source.def_id();
+ let hir_id = hir_map.local_def_id_to_hir_id(def_id.expect_local());
+ let node = hir_map.find(hir_id);
+ let hir_id = if let Some(hir::Node::Item(item)) = node
+ && let hir::ItemKind::Fn(.., body_id) = item.kind
+ {
+ let body = hir_map.body(body_id);
+ let mut v = BindingFinder {
+ span: err_label_span,
+ hir_id: None,
+ };
+ v.visit_body(body);
+ v.hir_id
+ } else {
+ None
+ };
+ if let Some(hir_id) = hir_id
+ && let Some(hir::Node::Local(local)) = hir_map.find(hir_id)
+ {
+ let (changing, span, sugg) = match local.ty {
+ Some(ty) => ("changing", ty.span, message),
+ None => (
+ "specifying",
+ local.pat.span.shrink_to_hi(),
+ format!(": {message}"),
+ ),
+ };
+ err.span_suggestion_verbose(
+ span,
+ &format!("consider {changing} this binding's type"),
+ sugg,
+ Applicability::HasPlaceholders,
+ );
+ } else {
+ err.span_label(
+ err_label_span,
+ &format!(
+ "consider changing this binding's type to be: `{message}`"
+ ),
+ );
+ }
}
None => {}
}
let err = FnMutError {
span: *span,
ty_err: match output_ty.kind() {
- ty::Closure(_, _) => FnMutReturnTypeErr::ReturnClosure { span: *span },
ty::Generator(def, ..) if self.infcx.tcx.generator_is_async(*def) => {
FnMutReturnTypeErr::ReturnAsyncBlock { span: *span }
}
+ _ if output_ty.contains_closure() => {
+ FnMutReturnTypeErr::ReturnClosure { span: *span }
+ }
_ => FnMutReturnTypeErr::ReturnRef { span: *span },
},
};
fn suggest_move_on_borrowing_closure(&self, diag: &mut Diagnostic) {
let map = self.infcx.tcx.hir();
let body_id = map.body_owned_by(self.mir_def_id());
- let expr = &map.body(body_id).value;
+ let expr = &map.body(body_id).value.peel_blocks();
let mut closure_span = None::<rustc_span::Span>;
match expr.kind {
hir::ExprKind::MethodCall(.., args, _) => {
}
}
}
- hir::ExprKind::Block(blk, _) => {
- if let Some(expr) = blk.expr {
- // only when the block is a closure
- if let hir::ExprKind::Closure(hir::Closure {
- capture_clause: hir::CaptureBy::Ref,
- body,
- ..
- }) = expr.kind
- {
- let body = map.body(*body);
- if !matches!(body.generator_kind, Some(hir::GeneratorKind::Async(..))) {
- closure_span = Some(expr.span.shrink_to_lo());
- }
- }
+ hir::ExprKind::Closure(hir::Closure {
+ capture_clause: hir::CaptureBy::Ref,
+ body,
+ ..
+ }) => {
+ let body = map.body(*body);
+ if !matches!(body.generator_kind, Some(hir::GeneratorKind::Async(..))) {
+ closure_span = Some(expr.span.shrink_to_lo());
}
}
_ => {}
}
}
+impl rustc_errors::IntoDiagnosticArg for RegionName {
+ fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+ self.to_string().into_diagnostic_arg()
+ }
+}
+
impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
pub(crate) fn mir_def_id(&self) -> hir::def_id::LocalDefId {
self.body.source.def_id().expect_local()
// in order to populate our used_mut set.
match **aggregate_kind {
AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) => {
+ let def_id = def_id.expect_local();
let BorrowCheckResult { used_mut_upvars, .. } =
self.infcx.tcx.mir_borrowck(def_id);
debug!("{:?} used_mut_upvars={:?}", def_id, used_mut_upvars);
};
}
+#[allow(rustc::diagnostic_outside_of_impl)]
+#[allow(rustc::untranslatable_diagnostic)]
pub(super) fn dump_annotation<'tcx>(
infcx: &InferCtxt<'tcx>,
body: &Body<'tcx>,
-use rustc_errors::{IntoDiagnosticArg, MultiSpan};
+use rustc_errors::MultiSpan;
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::{GenericArg, Ty};
use rustc_span::Span;
},
}
-impl IntoDiagnosticArg for &RegionName {
- fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
- format!("{}", self).into_diagnostic_arg()
- }
-}
-
-impl IntoDiagnosticArg for RegionName {
- fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
- format!("{}", self).into_diagnostic_arg()
- }
-}
-
#[derive(Subdiagnostic)]
pub(crate) enum RequireStaticErr {
#[note(borrowck_used_impl_require_static)]
user_ty: ty::UserType<'tcx>,
span: Span,
) {
- // FIXME: Ideally MIR types are normalized, but this is not always true.
- let mir_ty = self.normalize(mir_ty, Locations::All(span));
-
self.fully_perform_op(
Locations::All(span),
ConstraintCategory::Boring,
return;
}
+ // FIXME: Ideally MIR types are normalized, but this is not always true.
let mir_ty = self.normalize(mir_ty, Locations::All(span));
+
let cause = ObligationCause::dummy_with_span(span);
let param_env = self.param_env;
let op = |infcx: &'_ _| {
}
}
None => {
- if !sig.output().is_privately_uninhabited(self.tcx(), self.param_env) {
+ // The signature in this call can reference region variables,
+ // so erase them before calling a query.
+ let output_ty = self.tcx().erase_regions(sig.output());
+ if !output_ty.is_privately_uninhabited(self.tcx(), self.param_env) {
span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
}
}
}
};
- if ty_to_mut == Mutability::Mut && ty_mut == Mutability::Not {
+ if ty_to_mut.is_mut() && ty_mut.is_not() {
span_mirbug!(
self,
rvalue,
// clauses on the struct.
AggregateKind::Closure(def_id, substs)
| AggregateKind::Generator(def_id, substs, _) => {
- (def_id.to_def_id(), self.prove_closure_bounds(tcx, def_id, substs, location))
+ (def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), substs, location))
}
AggregateKind::Array(_) | AggregateKind::Tuple => {
cx.span_bug(field.span, "not exactly 2 arguments in `derive(PartialEq)`");
};
- // We received `&T` arguments. Convert them to `T` by
- // stripping `&` or adding `*`. This isn't necessary for
- // type checking, but it results in much better error
- // messages if something goes wrong.
+ // We received arguments of type `&T`. Convert them to type `T` by stripping
+ // any leading `&` or adding `*`. This isn't necessary for type checking, but
+ // it results in better error messages if something goes wrong.
+ //
+ // Note: for arguments that look like `&{ x }`, which occur with packed
+ // structs, this would cause expressions like `{ self.x } == { other.x }`,
+ // which isn't valid Rust syntax. This wouldn't break compilation because these
+ // AST nodes are constructed within the compiler. But it would mean that code
+ // printed by `-Zunpretty=expanded` (or `cargo expand`) would have invalid
+ // syntax, which would be suboptimal. So we wrap these in parens, giving
+ // `({ self.x }) == ({ other.x })`, which is valid syntax.
let convert = |expr: &P<Expr>| {
if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) =
&expr.kind
{
- inner.clone()
+ if let ExprKind::Block(..) = &inner.kind {
+ // `&{ x }` form: remove the `&`, add parens.
+ cx.expr_paren(field.span, inner.clone())
+ } else {
+ // `&x` form: remove the `&`.
+ inner.clone()
+ }
} else {
+ // No leading `&`: add a leading `*`.
cx.expr_deref(field.span, expr.clone())
}
};
// The number of fields that can be handled without an array.
const CUTOFF: usize = 5;
+ fn expr_for_field(
+ cx: &ExtCtxt<'_>,
+ field: &FieldInfo,
+ index: usize,
+ len: usize,
+ ) -> ast::ptr::P<ast::Expr> {
+ if index < len - 1 {
+ field.self_expr.clone()
+ } else {
+ // Unsized types need an extra indirection, but only the last field
+ // may be unsized.
+ cx.expr_addr_of(field.span, field.self_expr.clone())
+ }
+ }
+
if fields.is_empty() {
// Special case for no fields.
let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]);
let name = cx.expr_str(field.span, field.name.unwrap().name);
args.push(name);
}
- // Use an extra indirection to make sure this works for unsized types.
- let field = cx.expr_addr_of(field.span, field.self_expr.clone());
+
+ let field = expr_for_field(cx, field, i, fields.len());
args.push(field);
}
let expr = cx.expr_call_global(span, fn_path_debug, args);
let mut name_exprs = Vec::with_capacity(fields.len());
let mut value_exprs = Vec::with_capacity(fields.len());
- for field in fields {
+ for i in 0..fields.len() {
+ let field = &fields[i];
if is_struct {
name_exprs.push(cx.expr_str(field.span, field.name.unwrap().name));
}
- // Use an extra indirection to make sure this works for unsized types.
- let field = cx.expr_addr_of(field.span, field.self_expr.clone());
+ let field = expr_for_field(cx, field, i, fields.len());
value_exprs.push(field);
}
impl WriteBackendMethods for GccCodegenBackend {
type Module = GccContext;
type TargetMachine = ();
+ type TargetMachineError = ();
type ModuleBuffer = ModuleBuffer;
type ThinData = ();
type ThinBuffer = ThinBuffer;
rustc_metadata = { path = "../rustc_metadata" }
rustc_query_system = { path = "../rustc_query_system" }
rustc_session = { path = "../rustc_session" }
-rustc_serialize = { path = "../rustc_serialize" }
rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
rustc_target = { path = "../rustc_target" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
use crate::back::write::{self, save_temp_bitcode, DiagnosticHandlers};
-use crate::errors::DynamicLinkingWithLTO;
+use crate::errors::{
+ DynamicLinkingWithLTO, LlvmError, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib,
+};
use crate::llvm::{self, build_string};
use crate::{LlvmCodegenBackend, ModuleLlvm};
use object::read::archive::ArchiveFile;
// Make sure we actually can run LTO
for crate_type in cgcx.crate_types.iter() {
if !crate_type_allows_lto(*crate_type) {
- let e = diag_handler.fatal(
- "lto can only be run for executables, cdylibs and \
- static library outputs",
- );
- return Err(e);
+ diag_handler.emit_err(LtoDisallowed);
+ return Err(FatalError);
} else if *crate_type == CrateType::Dylib {
if !cgcx.opts.unstable_opts.dylib_lto {
- return Err(diag_handler
- .fatal("lto cannot be used for `dylib` crate type without `-Zdylib-lto`"));
+ diag_handler.emit_err(LtoDylib);
+ return Err(FatalError);
}
}
}
let module = SerializedModule::FromRlib(data.to_vec());
upstream_modules.push((module, CString::new(name).unwrap()));
}
- Err(msg) => return Err(diag_handler.fatal(&msg)),
+ Err(e) => {
+ diag_handler.emit_err(e);
+ return Err(FatalError);
+ }
}
}
}
Ok((symbols_below_threshold, upstream_modules))
}
-fn get_bitcode_slice_from_object_data(obj: &[u8]) -> Result<&[u8], String> {
+fn get_bitcode_slice_from_object_data(obj: &[u8]) -> Result<&[u8], LtoBitcodeFromRlib> {
let mut len = 0;
let data =
unsafe { llvm::LLVMRustGetBitcodeSliceFromObjectData(obj.as_ptr(), obj.len(), &mut len) };
Ok(bc)
} else {
assert!(len == 0);
- let msg = llvm::last_error().unwrap_or_else(|| "unknown LLVM error".to_string());
- Err(format!("failed to get bitcode from object file for LTO ({})", msg))
+ Err(LtoBitcodeFromRlib {
+ llvm_err: llvm::last_error().unwrap_or_else(|| "unknown LLVM error".to_string()),
+ })
}
}
});
info!("linking {:?}", name);
let data = bc_decoded.data();
- linker.add(data).map_err(|()| {
- let msg = format!("failed to load bitcode of module {:?}", name);
- write::llvm_err(diag_handler, &msg)
- })?;
+ linker
+ .add(data)
+ .map_err(|()| write::llvm_err(diag_handler, LlvmError::LoadBitcode { name }))?;
serialized_bitcode.push(bc_decoded);
}
drop(linker);
symbols_below_threshold.as_ptr(),
symbols_below_threshold.len() as u32,
)
- .ok_or_else(|| write::llvm_err(diag_handler, "failed to prepare thin LTO context"))?;
+ .ok_or_else(|| write::llvm_err(diag_handler, LlvmError::PrepareThinLtoContext))?;
let data = ThinData(data);
// session, overwriting the previous serialized data (if any).
if let Some(path) = key_map_path {
if let Err(err) = curr_key_map.save_to_file(&path) {
- let msg = format!("Error while writing ThinLTO key data: {}", err);
- return Err(write::llvm_err(diag_handler, &msg));
+ return Err(write::llvm_err(diag_handler, LlvmError::WriteThinLtoKey { err }));
}
}
let module_name = &thin_module.shared.module_names[thin_module.idx];
let tm_factory_config = TargetMachineFactoryConfig::new(cgcx, module_name.to_str().unwrap());
- let tm =
- (cgcx.tm_factory)(tm_factory_config).map_err(|e| write::llvm_err(&diag_handler, &e))?;
+ let tm = (cgcx.tm_factory)(tm_factory_config).map_err(|e| write::llvm_err(&diag_handler, e))?;
// Right now the implementation we've got only works over serialized
// modules, so we create a fresh new LLVM context and parse the module
let mut cu2 = ptr::null_mut();
llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2);
if !cu2.is_null() {
- let msg = "multiple source DICompileUnits found";
- return Err(write::llvm_err(&diag_handler, msg));
+ return Err(write::llvm_err(&diag_handler, LlvmError::MultipleSourceDiCompileUnit));
}
// Up next comes the per-module local analyses that we do for Thin LTO.
let _timer =
cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_rename", thin_module.name());
if !llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod, target) {
- let msg = "failed to prepare thin LTO module";
- return Err(write::llvm_err(&diag_handler, msg));
+ return Err(write::llvm_err(&diag_handler, LlvmError::PrepareThinLtoModule));
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-rename");
}
.prof
.generic_activity_with_arg("LLVM_thin_lto_resolve_weak", thin_module.name());
if !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) {
- let msg = "failed to prepare thin LTO module";
- return Err(write::llvm_err(&diag_handler, msg));
+ return Err(write::llvm_err(&diag_handler, LlvmError::PrepareThinLtoModule));
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-resolve");
}
.prof
.generic_activity_with_arg("LLVM_thin_lto_internalize", thin_module.name());
if !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) {
- let msg = "failed to prepare thin LTO module";
- return Err(write::llvm_err(&diag_handler, msg));
+ return Err(write::llvm_err(&diag_handler, LlvmError::PrepareThinLtoModule));
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-internalize");
}
let _timer =
cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_import", thin_module.name());
if !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod, target) {
- let msg = "failed to prepare thin LTO module";
- return Err(write::llvm_err(&diag_handler, msg));
+ return Err(write::llvm_err(&diag_handler, LlvmError::PrepareThinLtoModule));
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-import");
}
diag_handler: &Handler,
) -> Result<&'a llvm::Module, FatalError> {
unsafe {
- llvm::LLVMRustParseBitcodeForLTO(cx, data.as_ptr(), data.len(), name.as_ptr()).ok_or_else(
- || {
- let msg = "failed to parse bitcode for LTO module";
- write::llvm_err(diag_handler, msg)
- },
- )
+ llvm::LLVMRustParseBitcodeForLTO(cx, data.as_ptr(), data.len(), name.as_ptr())
+ .ok_or_else(|| write::llvm_err(diag_handler, LlvmError::ParseBitcode))
}
}
use crate::base;
use crate::common;
use crate::consts;
+use crate::errors::{
+ CopyBitcode, FromLlvmDiag, FromLlvmOptimizationDiag, LlvmError, WithLlvmError, WriteBytecode,
+};
use crate::llvm::{self, DiagnosticInfo, PassManager};
use crate::llvm_util;
use crate::type_::Type;
use std::str;
use std::sync::Arc;
-pub fn llvm_err(handler: &rustc_errors::Handler, msg: &str) -> FatalError {
+pub fn llvm_err<'a>(handler: &rustc_errors::Handler, err: LlvmError<'a>) -> FatalError {
match llvm::last_error() {
- Some(err) => handler.fatal(&format!("{}: {}", msg, err)),
- None => handler.fatal(msg),
+ Some(llvm_err) => handler.emit_almost_fatal(WithLlvmError(err, llvm_err)),
+ None => handler.emit_almost_fatal(err),
}
}
}
}
- result.into_result().map_err(|()| {
- let msg = format!("could not write output to {}", output.display());
- llvm_err(handler, &msg)
- })
+ result
+ .into_result()
+ .map_err(|()| llvm_err(handler, LlvmError::WriteOutput { path: output }))
}
}
// system/tcx is set up.
let features = llvm_util::global_llvm_features(sess, false);
target_machine_factory(sess, config::OptLevel::No, &features)(config)
- .unwrap_or_else(|err| llvm_err(sess.diagnostic(), &err).raise())
+ .unwrap_or_else(|err| llvm_err(sess.diagnostic(), err).raise())
}
pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> &'static mut llvm::TargetMachine {
tcx.backend_optimization_level(()),
tcx.global_backend_features(()),
)(config)
- .unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), &err).raise())
+ .unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), err).raise())
}
pub fn to_llvm_opt_settings(
)
};
- tm.ok_or_else(|| {
- format!("Could not create LLVM TargetMachine for triple: {}", triple.to_str().unwrap())
- })
+ tm.ok_or_else(|| LlvmError::CreateTargetMachine { triple: triple.clone() })
})
}
};
if enabled {
- diag_handler.note_without_error(&format!(
- "{}:{}:{}: {}: {}",
- opt.filename, opt.line, opt.column, opt.pass_name, opt.message,
- ));
+ diag_handler.emit_note(FromLlvmOptimizationDiag {
+ filename: &opt.filename,
+ line: opt.line,
+ column: opt.column,
+ pass_name: &opt.pass_name,
+ message: &opt.message,
+ });
}
}
llvm::diagnostic::PGO(diagnostic_ref) | llvm::diagnostic::Linker(diagnostic_ref) => {
- let msg = llvm::build_string(|s| {
+ let message = llvm::build_string(|s| {
llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s)
})
.expect("non-UTF8 diagnostic");
- diag_handler.warn(&msg);
+ diag_handler.emit_warning(FromLlvmDiag { message });
}
llvm::diagnostic::Unsupported(diagnostic_ref) => {
- let msg = llvm::build_string(|s| {
+ let message = llvm::build_string(|s| {
llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s)
})
.expect("non-UTF8 diagnostic");
- diag_handler.err(&msg);
+ diag_handler.emit_err(FromLlvmDiag { message });
}
llvm::diagnostic::UnknownDiagnostic(..) => {}
}
llvm_plugins.as_ptr().cast(),
llvm_plugins.len(),
);
- result.into_result().map_err(|()| llvm_err(diag_handler, "failed to run LLVM passes"))
+ result.into_result().map_err(|()| llvm_err(diag_handler, LlvmError::RunLlvmPasses))
}
// Unsafe due to LLVM calls.
let _timer = cgcx.prof.generic_activity_with_arg("LLVM_link_module", &*module.name);
let buffer = ModuleBuffer::new(module.module_llvm.llmod());
linker.add(buffer.data()).map_err(|()| {
- let msg = format!("failed to serialize module {:?}", module.name);
- llvm_err(diag_handler, &msg)
+ llvm_err(diag_handler, LlvmError::SerializeModule { name: &module.name })
})?;
}
drop(linker);
let _timer = cgcx
.prof
.generic_activity_with_arg("LLVM_module_codegen_emit_bitcode", &*module.name);
- if let Err(e) = fs::write(&bc_out, data) {
- let msg = format!("failed to write bytecode to {}: {}", bc_out.display(), e);
- diag_handler.err(&msg);
+ if let Err(err) = fs::write(&bc_out, data) {
+ diag_handler.emit_err(WriteBytecode { path: &bc_out, err });
}
}
record_artifact_size(&cgcx.prof, "llvm_ir", &out);
}
- result.into_result().map_err(|()| {
- let msg = format!("failed to write LLVM IR to {}", out.display());
- llvm_err(diag_handler, &msg)
- })?;
+ result
+ .into_result()
+ .map_err(|()| llvm_err(diag_handler, LlvmError::WriteIr { path: &out }))?;
}
if config.emit_asm {
EmitObj::Bitcode => {
debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
- if let Err(e) = link_or_copy(&bc_out, &obj_out) {
- diag_handler.err(&format!("failed to copy bitcode to object file: {}", e));
+ if let Err(err) = link_or_copy(&bc_out, &obj_out) {
+ diag_handler.emit_err(CopyBitcode { err });
}
if !config.emit_bc {
target_data_layout =
"e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:32-n8:16:32-a:0:32-S32"
.to_string();
- }
- if sess.target.arch == "wasm32" {
+ } else if sess.target.arch == "wasm32" {
target_data_layout = target_data_layout.replace("-p10:8:8-p20:8:8", "");
}
}
if llvm_version < (16, 0, 0) {
if sess.target.arch == "s390x" {
target_data_layout = target_data_layout.replace("-v128:64", "");
- }
-
- if sess.target.arch == "riscv64" {
+ } else if sess.target.arch == "riscv64" {
target_data_layout = target_data_layout.replace("-n32:64-", "-n64-");
}
}
use std::borrow::Cow;
+use std::ffi::CString;
+use std::path::Path;
-use rustc_errors::fluent;
-use rustc_errors::DiagnosticBuilder;
-use rustc_errors::ErrorGuaranteed;
-use rustc_errors::Handler;
-use rustc_errors::IntoDiagnostic;
+use rustc_data_structures::small_c_str::SmallCStr;
+use rustc_errors::{
+ fluent, DiagnosticBuilder, EmissionGuarantee, ErrorGuaranteed, Handler, IntoDiagnostic,
+};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::Span;
#[note]
pub(crate) struct DynamicLinkingWithLTO;
-#[derive(Diagnostic)]
-#[diag(codegen_llvm_fail_parsing_target_machine_config_to_target_machine)]
-pub(crate) struct FailParsingTargetMachineConfigToTargetMachine {
- pub error: String,
+pub(crate) struct ParseTargetMachineConfig<'a>(pub LlvmError<'a>);
+
+impl<EM: EmissionGuarantee> IntoDiagnostic<'_, EM> for ParseTargetMachineConfig<'_> {
+ fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, EM> {
+ let diag: DiagnosticBuilder<'_, EM> = self.0.into_diagnostic(sess);
+ let (message, _) = diag.styled_message().first().expect("`LlvmError` with no message");
+ let message = sess.eagerly_translate_to_string(message.clone(), diag.args());
+
+ let mut diag = sess.struct_diagnostic(fluent::codegen_llvm_parse_target_machine_config);
+ diag.set_arg("error", message);
+ diag
+ }
}
pub(crate) struct TargetFeatureDisableOrEnable<'a> {
diag
}
}
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_lto_disallowed)]
+pub(crate) struct LtoDisallowed;
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_lto_dylib)]
+pub(crate) struct LtoDylib;
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_lto_bitcode_from_rlib)]
+pub(crate) struct LtoBitcodeFromRlib {
+ pub llvm_err: String,
+}
+
+#[derive(Diagnostic)]
+pub enum LlvmError<'a> {
+ #[diag(codegen_llvm_write_output)]
+ WriteOutput { path: &'a Path },
+ #[diag(codegen_llvm_target_machine)]
+ CreateTargetMachine { triple: SmallCStr },
+ #[diag(codegen_llvm_run_passes)]
+ RunLlvmPasses,
+ #[diag(codegen_llvm_serialize_module)]
+ SerializeModule { name: &'a str },
+ #[diag(codegen_llvm_write_ir)]
+ WriteIr { path: &'a Path },
+ #[diag(codegen_llvm_prepare_thin_lto_context)]
+ PrepareThinLtoContext,
+ #[diag(codegen_llvm_load_bitcode)]
+ LoadBitcode { name: CString },
+ #[diag(codegen_llvm_write_thinlto_key)]
+ WriteThinLtoKey { err: std::io::Error },
+ #[diag(codegen_llvm_multiple_source_dicompileunit)]
+ MultipleSourceDiCompileUnit,
+ #[diag(codegen_llvm_prepare_thin_lto_module)]
+ PrepareThinLtoModule,
+ #[diag(codegen_llvm_parse_bitcode)]
+ ParseBitcode,
+}
+
+pub(crate) struct WithLlvmError<'a>(pub LlvmError<'a>, pub String);
+
+impl<EM: EmissionGuarantee> IntoDiagnostic<'_, EM> for WithLlvmError<'_> {
+ fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, EM> {
+ use LlvmError::*;
+ let msg_with_llvm_err = match &self.0 {
+ WriteOutput { .. } => fluent::codegen_llvm_write_output_with_llvm_err,
+ CreateTargetMachine { .. } => fluent::codegen_llvm_target_machine_with_llvm_err,
+ RunLlvmPasses => fluent::codegen_llvm_run_passes_with_llvm_err,
+ SerializeModule { .. } => fluent::codegen_llvm_serialize_module_with_llvm_err,
+ WriteIr { .. } => fluent::codegen_llvm_write_ir_with_llvm_err,
+ PrepareThinLtoContext => fluent::codegen_llvm_prepare_thin_lto_context_with_llvm_err,
+ LoadBitcode { .. } => fluent::codegen_llvm_load_bitcode_with_llvm_err,
+ WriteThinLtoKey { .. } => fluent::codegen_llvm_write_thinlto_key_with_llvm_err,
+ MultipleSourceDiCompileUnit => {
+ fluent::codegen_llvm_multiple_source_dicompileunit_with_llvm_err
+ }
+ PrepareThinLtoModule => fluent::codegen_llvm_prepare_thin_lto_module_with_llvm_err,
+ ParseBitcode => fluent::codegen_llvm_parse_bitcode_with_llvm_err,
+ };
+ let mut diag = self.0.into_diagnostic(sess);
+ diag.set_primary_message(msg_with_llvm_err);
+ diag.set_arg("llvm_err", self.1);
+ diag
+ }
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_from_llvm_optimization_diag)]
+pub(crate) struct FromLlvmOptimizationDiag<'a> {
+ pub filename: &'a str,
+ pub line: std::ffi::c_uint,
+ pub column: std::ffi::c_uint,
+ pub pass_name: &'a str,
+ pub message: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_from_llvm_diag)]
+pub(crate) struct FromLlvmDiag {
+ pub message: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_write_bytecode)]
+pub(crate) struct WriteBytecode<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_copy_bitcode)]
+pub(crate) struct CopyBitcode {
+ pub err: std::io::Error,
+}
//! This API is completely unstable and subject to change.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(extern_types)]
#![feature(hash_raw_entry)]
+#![feature(iter_intersperse)]
#![feature(let_chains)]
-#![feature(extern_types)]
+#![feature(never_type)]
#![feature(once_cell)]
-#![feature(iter_intersperse)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
#![deny(rustc::untranslatable_diagnostic)]
use back::write::{create_informational_target_machine, create_target_machine};
-use errors::FailParsingTargetMachineConfigToTargetMachine;
+use errors::ParseTargetMachineConfig;
pub use llvm_util::target_features;
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
type Module = ModuleLlvm;
type ModuleBuffer = back::lto::ModuleBuffer;
type TargetMachine = &'static mut llvm::TargetMachine;
+ type TargetMachineError = crate::errors::LlvmError<'static>;
type ThinData = back::lto::ThinData;
type ThinBuffer = back::lto::ThinBuffer;
fn print_pass_timings(&self) {
let tm = match (cgcx.tm_factory)(tm_factory_config) {
Ok(m) => m,
Err(e) => {
- handler.emit_err(FailParsingTargetMachineConfigToTargetMachine { error: e });
- return Err(FatalError);
+ return Err(handler.emit_almost_fatal(ParseTargetMachineConfig(e)));
}
};
rustc_query_system = { path = "../rustc_query_system" }
rustc_target = { path = "../rustc_target" }
rustc_session = { path = "../rustc_session" }
-rustc_const_eval = { path = "../rustc_const_eval" }
[dependencies.object]
version = "0.30.1"
}
pub type TargetMachineFactoryFn<B> = Arc<
- dyn Fn(TargetMachineFactoryConfig) -> Result<<B as WriteBackendMethods>::TargetMachine, String>
- + Send
+ dyn Fn(
+ TargetMachineFactoryConfig,
+ ) -> Result<
+ <B as WriteBackendMethods>::TargetMachine,
+ <B as WriteBackendMethods>::TargetMachineError,
+ > + Send
+ Sync,
>;
} else if attr.has_name(sym::rustc_allocator) {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
} else if attr.has_name(sym::ffi_returns_twice) {
- if tcx.is_foreign_item(did) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
- } else {
- // `#[ffi_returns_twice]` is only allowed `extern fn`s.
- struct_span_err!(
- tcx.sess,
- attr.span,
- E0724,
- "`#[ffi_returns_twice]` may only be used on foreign functions"
- )
- .emit();
- }
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
} else if attr.has_name(sym::ffi_pure) {
- if tcx.is_foreign_item(did) {
- if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
- // `#[ffi_const]` functions cannot be `#[ffi_pure]`
- struct_span_err!(
- tcx.sess,
- attr.span,
- E0757,
- "`#[ffi_const]` function cannot be `#[ffi_pure]`"
- )
- .emit();
- } else {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
- }
- } else {
- // `#[ffi_pure]` is only allowed on foreign functions
- struct_span_err!(
- tcx.sess,
- attr.span,
- E0755,
- "`#[ffi_pure]` may only be used on foreign functions"
- )
- .emit();
- }
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
} else if attr.has_name(sym::ffi_const) {
- if tcx.is_foreign_item(did) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
- } else {
- // `#[ffi_const]` is only allowed on foreign functions
- struct_span_err!(
- tcx.sess,
- attr.span,
- E0756,
- "`#[ffi_const]` may only be used on foreign functions"
- )
- .emit();
- }
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
} else if attr.has_name(sym::rustc_nounwind) {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
} else if attr.has_name(sym::rustc_reallocator) {
}
}
} else if attr.has_name(sym::instruction_set) {
- codegen_fn_attrs.instruction_set = match attr.meta_kind() {
- Some(MetaItemKind::List(ref items)) => match items.as_slice() {
- [NestedMetaItem::MetaItem(set)] => {
- let segments =
- set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
- match segments.as_slice() {
- [sym::arm, sym::a32] | [sym::arm, sym::t32] => {
- if !tcx.sess.target.has_thumb_interworking {
- struct_span_err!(
- tcx.sess.diagnostic(),
- attr.span,
- E0779,
- "target does not support `#[instruction_set]`"
- )
- .emit();
- None
- } else if segments[1] == sym::a32 {
- Some(InstructionSetAttr::ArmA32)
- } else if segments[1] == sym::t32 {
- Some(InstructionSetAttr::ArmT32)
- } else {
- unreachable!()
- }
- }
- _ => {
+ codegen_fn_attrs.instruction_set = attr.meta_item_list().and_then(|l| match &l[..] {
+ [NestedMetaItem::MetaItem(set)] => {
+ let segments =
+ set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
+ match segments.as_slice() {
+ [sym::arm, sym::a32] | [sym::arm, sym::t32] => {
+ if !tcx.sess.target.has_thumb_interworking {
struct_span_err!(
tcx.sess.diagnostic(),
attr.span,
E0779,
- "invalid instruction set specified",
+ "target does not support `#[instruction_set]`"
)
.emit();
None
+ } else if segments[1] == sym::a32 {
+ Some(InstructionSetAttr::ArmA32)
+ } else if segments[1] == sym::t32 {
+ Some(InstructionSetAttr::ArmT32)
+ } else {
+ unreachable!()
}
}
+ _ => {
+ struct_span_err!(
+ tcx.sess.diagnostic(),
+ attr.span,
+ E0779,
+ "invalid instruction set specified",
+ )
+ .emit();
+ None
+ }
}
- [] => {
- struct_span_err!(
- tcx.sess.diagnostic(),
- attr.span,
- E0778,
- "`#[instruction_set]` requires an argument"
- )
- .emit();
- None
- }
- _ => {
- struct_span_err!(
- tcx.sess.diagnostic(),
- attr.span,
- E0779,
- "cannot specify more than one instruction set"
- )
- .emit();
- None
- }
- },
- _ => {
+ }
+ [] => {
struct_span_err!(
tcx.sess.diagnostic(),
attr.span,
E0778,
- "must specify an instruction set"
+ "`#[instruction_set]` requires an argument"
)
.emit();
None
}
- };
+ _ => {
+ struct_span_err!(
+ tcx.sess.diagnostic(),
+ attr.span,
+ E0779,
+ "cannot specify more than one instruction set"
+ )
+ .emit();
+ None
+ }
+ })
} else if attr.has_name(sym::repr) {
codegen_fn_attrs.alignment = match attr.meta_item_list() {
Some(items) => match items.as_slice() {
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt};
use rustc_span::source_map::{Span, DUMMY_SP};
+use rustc_target::abi::VariantIdx;
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
#[instrument(level = "trace", skip(self, bx))]
}
mir::Rvalue::Aggregate(ref kind, ref operands) => {
- let (dest, active_field_index) = match **kind {
- mir::AggregateKind::Adt(adt_did, variant_index, _, _, active_field_index) => {
- dest.codegen_set_discr(bx, variant_index);
- if bx.tcx().adt_def(adt_did).is_enum() {
- (dest.project_downcast(bx, variant_index), active_field_index)
- } else {
- (dest, active_field_index)
- }
+ let (variant_index, variant_dest, active_field_index) = match **kind {
+ mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => {
+ let variant_dest = dest.project_downcast(bx, variant_index);
+ (variant_index, variant_dest, active_field_index)
}
- _ => (dest, None),
+ _ => (VariantIdx::from_u32(0), dest, None),
};
+ if active_field_index.is_some() {
+ assert_eq!(operands.len(), 1);
+ }
for (i, operand) in operands.iter().enumerate() {
let op = self.codegen_operand(bx, operand);
// Do not generate stores and GEPis for zero-sized fields.
let field_index = active_field_index.unwrap_or(i);
let field = if let mir::AggregateKind::Array(_) = **kind {
let llindex = bx.cx().const_usize(field_index as u64);
- dest.project_index(bx, llindex)
+ variant_dest.project_index(bx, llindex)
} else {
- dest.project_field(bx, field_index)
+ variant_dest.project_field(bx, field_index)
};
op.val.store(bx, field);
}
}
+ dest.codegen_set_discr(bx, variant_index);
}
_ => {
pub trait WriteBackendMethods: 'static + Sized + Clone {
type Module: Send + Sync;
type TargetMachine;
+ type TargetMachineError;
type ModuleBuffer: ModuleBufferMethods;
type ThinData: Send + Sync;
type ThinBuffer: ThinBufferMethods;
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_mir_dataflow = { path = "../rustc_mir_dataflow" }
-rustc_query_system = { path = "../rustc_query_system" }
rustc_session = { path = "../rustc_session" }
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
let alloc = alloc.inner();
if is_write {
// Write access. These are never allowed, but we give a targeted error message.
- if alloc.mutability == Mutability::Not {
- Err(err_ub!(WriteToReadOnly(alloc_id)).into())
- } else {
- Err(ConstEvalErrKind::ModifiedGlobal.into())
+ match alloc.mutability {
+ Mutability::Not => Err(err_ub!(WriteToReadOnly(alloc_id)).into()),
+ Mutability::Mut => Err(ConstEvalErrKind::ModifiedGlobal.into()),
}
} else {
// Read access. These are usually allowed, with some exceptions.
--- /dev/null
+//! Functions for reading and writing discriminants of multi-variant layouts (enums and generators).
+
+use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt};
+use rustc_middle::{mir, ty};
+use rustc_target::abi::{self, TagEncoding};
+use rustc_target::abi::{VariantIdx, Variants};
+
+use super::{ImmTy, InterpCx, InterpResult, Machine, OpTy, PlaceTy, Scalar};
+
+impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
+ /// Writes the discriminant of the given variant.
+ #[instrument(skip(self), level = "trace")]
+ pub fn write_discriminant(
+ &mut self,
+ variant_index: VariantIdx,
+ dest: &PlaceTy<'tcx, M::Provenance>,
+ ) -> InterpResult<'tcx> {
+ // Layout computation excludes uninhabited variants from consideration
+ // therefore there's no way to represent those variants in the given layout.
+ // Essentially, uninhabited variants do not have a tag that corresponds to their
+ // discriminant, so we cannot do anything here.
+ // When evaluating we will always error before even getting here, but ConstProp 'executes'
+ // dead code, so we cannot ICE here.
+ if dest.layout.for_variant(self, variant_index).abi.is_uninhabited() {
+ throw_ub!(UninhabitedEnumVariantWritten)
+ }
+
+ match dest.layout.variants {
+ abi::Variants::Single { index } => {
+ assert_eq!(index, variant_index);
+ }
+ abi::Variants::Multiple {
+ tag_encoding: TagEncoding::Direct,
+ tag: tag_layout,
+ tag_field,
+ ..
+ } => {
+ // No need to validate that the discriminant here because the
+ // `TyAndLayout::for_variant()` call earlier already checks the variant is valid.
+
+ let discr_val =
+ dest.layout.ty.discriminant_for_variant(*self.tcx, variant_index).unwrap().val;
+
+ // raw discriminants for enums are isize or bigger during
+ // their computation, but the in-memory tag is the smallest possible
+ // representation
+ let size = tag_layout.size(self);
+ let tag_val = size.truncate(discr_val);
+
+ let tag_dest = self.place_field(dest, tag_field)?;
+ self.write_scalar(Scalar::from_uint(tag_val, size), &tag_dest)?;
+ }
+ abi::Variants::Multiple {
+ tag_encoding:
+ TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start },
+ tag: tag_layout,
+ tag_field,
+ ..
+ } => {
+ // No need to validate that the discriminant here because the
+ // `TyAndLayout::for_variant()` call earlier already checks the variant is valid.
+
+ if variant_index != untagged_variant {
+ let variants_start = niche_variants.start().as_u32();
+ let variant_index_relative = variant_index
+ .as_u32()
+ .checked_sub(variants_start)
+ .expect("overflow computing relative variant idx");
+ // We need to use machine arithmetic when taking into account `niche_start`:
+ // tag_val = variant_index_relative + niche_start_val
+ let tag_layout = self.layout_of(tag_layout.primitive().to_int_ty(*self.tcx))?;
+ let niche_start_val = ImmTy::from_uint(niche_start, tag_layout);
+ let variant_index_relative_val =
+ ImmTy::from_uint(variant_index_relative, tag_layout);
+ let tag_val = self.binary_op(
+ mir::BinOp::Add,
+ &variant_index_relative_val,
+ &niche_start_val,
+ )?;
+ // Write result.
+ let niche_dest = self.place_field(dest, tag_field)?;
+ self.write_immediate(*tag_val, &niche_dest)?;
+ }
+ }
+ }
+
+ Ok(())
+ }
+
+ /// Read discriminant, return the runtime value as well as the variant index.
+ /// Can also legally be called on non-enums (e.g. through the discriminant_value intrinsic)!
+ #[instrument(skip(self), level = "trace")]
+ pub fn read_discriminant(
+ &self,
+ op: &OpTy<'tcx, M::Provenance>,
+ ) -> InterpResult<'tcx, (Scalar<M::Provenance>, VariantIdx)> {
+ trace!("read_discriminant_value {:#?}", op.layout);
+ // Get type and layout of the discriminant.
+ let discr_layout = self.layout_of(op.layout.ty.discriminant_ty(*self.tcx))?;
+ trace!("discriminant type: {:?}", discr_layout.ty);
+
+ // We use "discriminant" to refer to the value associated with a particular enum variant.
+ // This is not to be confused with its "variant index", which is just determining its position in the
+ // declared list of variants -- they can differ with explicitly assigned discriminants.
+ // We use "tag" to refer to how the discriminant is encoded in memory, which can be either
+ // straight-forward (`TagEncoding::Direct`) or with a niche (`TagEncoding::Niche`).
+ let (tag_scalar_layout, tag_encoding, tag_field) = match op.layout.variants {
+ Variants::Single { index } => {
+ let discr = match op.layout.ty.discriminant_for_variant(*self.tcx, index) {
+ Some(discr) => {
+ // This type actually has discriminants.
+ assert_eq!(discr.ty, discr_layout.ty);
+ Scalar::from_uint(discr.val, discr_layout.size)
+ }
+ None => {
+ // On a type without actual discriminants, variant is 0.
+ assert_eq!(index.as_u32(), 0);
+ Scalar::from_uint(index.as_u32(), discr_layout.size)
+ }
+ };
+ return Ok((discr, index));
+ }
+ Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => {
+ (tag, tag_encoding, tag_field)
+ }
+ };
+
+ // There are *three* layouts that come into play here:
+ // - The discriminant has a type for typechecking. This is `discr_layout`, and is used for
+ // the `Scalar` we return.
+ // - The tag (encoded discriminant) has layout `tag_layout`. This is always an integer type,
+ // and used to interpret the value we read from the tag field.
+ // For the return value, a cast to `discr_layout` is performed.
+ // - The field storing the tag has a layout, which is very similar to `tag_layout` but
+ // may be a pointer. This is `tag_val.layout`; we just use it for sanity checks.
+
+ // Get layout for tag.
+ let tag_layout = self.layout_of(tag_scalar_layout.primitive().to_int_ty(*self.tcx))?;
+
+ // Read tag and sanity-check `tag_layout`.
+ let tag_val = self.read_immediate(&self.operand_field(op, tag_field)?)?;
+ assert_eq!(tag_layout.size, tag_val.layout.size);
+ assert_eq!(tag_layout.abi.is_signed(), tag_val.layout.abi.is_signed());
+ trace!("tag value: {}", tag_val);
+
+ // Figure out which discriminant and variant this corresponds to.
+ Ok(match *tag_encoding {
+ TagEncoding::Direct => {
+ let scalar = tag_val.to_scalar();
+ // Generate a specific error if `tag_val` is not an integer.
+ // (`tag_bits` itself is only used for error messages below.)
+ let tag_bits = scalar
+ .try_to_int()
+ .map_err(|dbg_val| err_ub!(InvalidTag(dbg_val)))?
+ .assert_bits(tag_layout.size);
+ // Cast bits from tag layout to discriminant layout.
+ // After the checks we did above, this cannot fail, as
+ // discriminants are int-like.
+ let discr_val =
+ self.cast_from_int_like(scalar, tag_val.layout, discr_layout.ty).unwrap();
+ let discr_bits = discr_val.assert_bits(discr_layout.size);
+ // Convert discriminant to variant index, and catch invalid discriminants.
+ let index = match *op.layout.ty.kind() {
+ ty::Adt(adt, _) => {
+ adt.discriminants(*self.tcx).find(|(_, var)| var.val == discr_bits)
+ }
+ ty::Generator(def_id, substs, _) => {
+ let substs = substs.as_generator();
+ substs
+ .discriminants(def_id, *self.tcx)
+ .find(|(_, var)| var.val == discr_bits)
+ }
+ _ => span_bug!(self.cur_span(), "tagged layout for non-adt non-generator"),
+ }
+ .ok_or_else(|| err_ub!(InvalidTag(Scalar::from_uint(tag_bits, tag_layout.size))))?;
+ // Return the cast value, and the index.
+ (discr_val, index.0)
+ }
+ TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => {
+ let tag_val = tag_val.to_scalar();
+ // Compute the variant this niche value/"tag" corresponds to. With niche layout,
+ // discriminant (encoded in niche/tag) and variant index are the same.
+ let variants_start = niche_variants.start().as_u32();
+ let variants_end = niche_variants.end().as_u32();
+ let variant = match tag_val.try_to_int() {
+ Err(dbg_val) => {
+ // So this is a pointer then, and casting to an int failed.
+ // Can only happen during CTFE.
+ // The niche must be just 0, and the ptr not null, then we know this is
+ // okay. Everything else, we conservatively reject.
+ let ptr_valid = niche_start == 0
+ && variants_start == variants_end
+ && !self.scalar_may_be_null(tag_val)?;
+ if !ptr_valid {
+ throw_ub!(InvalidTag(dbg_val))
+ }
+ untagged_variant
+ }
+ Ok(tag_bits) => {
+ let tag_bits = tag_bits.assert_bits(tag_layout.size);
+ // We need to use machine arithmetic to get the relative variant idx:
+ // variant_index_relative = tag_val - niche_start_val
+ let tag_val = ImmTy::from_uint(tag_bits, tag_layout);
+ let niche_start_val = ImmTy::from_uint(niche_start, tag_layout);
+ let variant_index_relative_val =
+ self.binary_op(mir::BinOp::Sub, &tag_val, &niche_start_val)?;
+ let variant_index_relative =
+ variant_index_relative_val.to_scalar().assert_bits(tag_val.layout.size);
+ // Check if this is in the range that indicates an actual discriminant.
+ if variant_index_relative <= u128::from(variants_end - variants_start) {
+ let variant_index_relative = u32::try_from(variant_index_relative)
+ .expect("we checked that this fits into a u32");
+ // Then computing the absolute variant idx should not overflow any more.
+ let variant_index = variants_start
+ .checked_add(variant_index_relative)
+ .expect("overflow computing absolute variant idx");
+ let variants_len = op
+ .layout
+ .ty
+ .ty_adt_def()
+ .expect("tagged layout for non adt")
+ .variants()
+ .len();
+ assert!(usize::try_from(variant_index).unwrap() < variants_len);
+ VariantIdx::from_u32(variant_index)
+ } else {
+ untagged_variant
+ }
+ }
+ };
+ // Compute the size of the scalar we need to return.
+ // No need to cast, because the variant index directly serves as discriminant and is
+ // encoded in the tag.
+ (Scalar::from_uint(variant.as_u32(), discr_layout.size), variant)
+ }
+ })
+ }
+}
use crate::const_eval;
pub trait CompileTimeMachine<'mir, 'tcx, T> = Machine<
- 'mir,
- 'tcx,
- MemoryKind = T,
- Provenance = AllocId,
- ExtraFnVal = !,
- FrameExtra = (),
- AllocExtra = (),
- MemoryMap = FxIndexMap<AllocId, (MemoryKind<T>, Allocation)>,
->;
+ 'mir,
+ 'tcx,
+ MemoryKind = T,
+ Provenance = AllocId,
+ ExtraFnVal = !,
+ FrameExtra = (),
+ AllocExtra = (),
+ MemoryMap = FxIndexMap<AllocId, (MemoryKind<T>, Allocation)>,
+ >;
struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>> {
/// The ectx from which we intern.
.into());
};
- if alloc.mutability == Mutability::Not {
+ if alloc.mutability.is_not() {
throw_ub_format!("deallocating immutable allocation {alloc_id:?}");
}
if alloc_kind != kind {
}
let (_kind, alloc) = self.memory.alloc_map.get_mut(id).unwrap();
- if alloc.mutability == Mutability::Not {
+ if alloc.mutability.is_not() {
throw_ub!(WriteToReadOnly(id))
}
Ok((alloc, &mut self.machine))
//! An interpreter for MIR used in CTFE and by miri
mod cast;
+mod discriminant;
mod eval_context;
mod intern;
mod intrinsics;
use either::{Either, Left, Right};
use rustc_hir::def::Namespace;
-use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
+use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter};
use rustc_middle::ty::{ConstInt, Ty, ValTree};
use rustc_middle::{mir, ty};
use rustc_span::Span;
-use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size, TagEncoding};
-use rustc_target::abi::{VariantIdx, Variants};
+use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size};
use super::{
alloc_range, from_known_layout, mir_assign_valid_types, AllocId, ConstValue, Frame, GlobalId,
};
Ok(OpTy { op, layout, align: Some(layout.align.abi) })
}
-
- /// Read discriminant, return the runtime value as well as the variant index.
- /// Can also legally be called on non-enums (e.g. through the discriminant_value intrinsic)!
- pub fn read_discriminant(
- &self,
- op: &OpTy<'tcx, M::Provenance>,
- ) -> InterpResult<'tcx, (Scalar<M::Provenance>, VariantIdx)> {
- trace!("read_discriminant_value {:#?}", op.layout);
- // Get type and layout of the discriminant.
- let discr_layout = self.layout_of(op.layout.ty.discriminant_ty(*self.tcx))?;
- trace!("discriminant type: {:?}", discr_layout.ty);
-
- // We use "discriminant" to refer to the value associated with a particular enum variant.
- // This is not to be confused with its "variant index", which is just determining its position in the
- // declared list of variants -- they can differ with explicitly assigned discriminants.
- // We use "tag" to refer to how the discriminant is encoded in memory, which can be either
- // straight-forward (`TagEncoding::Direct`) or with a niche (`TagEncoding::Niche`).
- let (tag_scalar_layout, tag_encoding, tag_field) = match op.layout.variants {
- Variants::Single { index } => {
- let discr = match op.layout.ty.discriminant_for_variant(*self.tcx, index) {
- Some(discr) => {
- // This type actually has discriminants.
- assert_eq!(discr.ty, discr_layout.ty);
- Scalar::from_uint(discr.val, discr_layout.size)
- }
- None => {
- // On a type without actual discriminants, variant is 0.
- assert_eq!(index.as_u32(), 0);
- Scalar::from_uint(index.as_u32(), discr_layout.size)
- }
- };
- return Ok((discr, index));
- }
- Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => {
- (tag, tag_encoding, tag_field)
- }
- };
-
- // There are *three* layouts that come into play here:
- // - The discriminant has a type for typechecking. This is `discr_layout`, and is used for
- // the `Scalar` we return.
- // - The tag (encoded discriminant) has layout `tag_layout`. This is always an integer type,
- // and used to interpret the value we read from the tag field.
- // For the return value, a cast to `discr_layout` is performed.
- // - The field storing the tag has a layout, which is very similar to `tag_layout` but
- // may be a pointer. This is `tag_val.layout`; we just use it for sanity checks.
-
- // Get layout for tag.
- let tag_layout = self.layout_of(tag_scalar_layout.primitive().to_int_ty(*self.tcx))?;
-
- // Read tag and sanity-check `tag_layout`.
- let tag_val = self.read_immediate(&self.operand_field(op, tag_field)?)?;
- assert_eq!(tag_layout.size, tag_val.layout.size);
- assert_eq!(tag_layout.abi.is_signed(), tag_val.layout.abi.is_signed());
- trace!("tag value: {}", tag_val);
-
- // Figure out which discriminant and variant this corresponds to.
- Ok(match *tag_encoding {
- TagEncoding::Direct => {
- let scalar = tag_val.to_scalar();
- // Generate a specific error if `tag_val` is not an integer.
- // (`tag_bits` itself is only used for error messages below.)
- let tag_bits = scalar
- .try_to_int()
- .map_err(|dbg_val| err_ub!(InvalidTag(dbg_val)))?
- .assert_bits(tag_layout.size);
- // Cast bits from tag layout to discriminant layout.
- // After the checks we did above, this cannot fail, as
- // discriminants are int-like.
- let discr_val =
- self.cast_from_int_like(scalar, tag_val.layout, discr_layout.ty).unwrap();
- let discr_bits = discr_val.assert_bits(discr_layout.size);
- // Convert discriminant to variant index, and catch invalid discriminants.
- let index = match *op.layout.ty.kind() {
- ty::Adt(adt, _) => {
- adt.discriminants(*self.tcx).find(|(_, var)| var.val == discr_bits)
- }
- ty::Generator(def_id, substs, _) => {
- let substs = substs.as_generator();
- substs
- .discriminants(def_id, *self.tcx)
- .find(|(_, var)| var.val == discr_bits)
- }
- _ => span_bug!(self.cur_span(), "tagged layout for non-adt non-generator"),
- }
- .ok_or_else(|| err_ub!(InvalidTag(Scalar::from_uint(tag_bits, tag_layout.size))))?;
- // Return the cast value, and the index.
- (discr_val, index.0)
- }
- TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => {
- let tag_val = tag_val.to_scalar();
- // Compute the variant this niche value/"tag" corresponds to. With niche layout,
- // discriminant (encoded in niche/tag) and variant index are the same.
- let variants_start = niche_variants.start().as_u32();
- let variants_end = niche_variants.end().as_u32();
- let variant = match tag_val.try_to_int() {
- Err(dbg_val) => {
- // So this is a pointer then, and casting to an int failed.
- // Can only happen during CTFE.
- // The niche must be just 0, and the ptr not null, then we know this is
- // okay. Everything else, we conservatively reject.
- let ptr_valid = niche_start == 0
- && variants_start == variants_end
- && !self.scalar_may_be_null(tag_val)?;
- if !ptr_valid {
- throw_ub!(InvalidTag(dbg_val))
- }
- untagged_variant
- }
- Ok(tag_bits) => {
- let tag_bits = tag_bits.assert_bits(tag_layout.size);
- // We need to use machine arithmetic to get the relative variant idx:
- // variant_index_relative = tag_val - niche_start_val
- let tag_val = ImmTy::from_uint(tag_bits, tag_layout);
- let niche_start_val = ImmTy::from_uint(niche_start, tag_layout);
- let variant_index_relative_val =
- self.binary_op(mir::BinOp::Sub, &tag_val, &niche_start_val)?;
- let variant_index_relative =
- variant_index_relative_val.to_scalar().assert_bits(tag_val.layout.size);
- // Check if this is in the range that indicates an actual discriminant.
- if variant_index_relative <= u128::from(variants_end - variants_start) {
- let variant_index_relative = u32::try_from(variant_index_relative)
- .expect("we checked that this fits into a u32");
- // Then computing the absolute variant idx should not overflow any more.
- let variant_index = variants_start
- .checked_add(variant_index_relative)
- .expect("overflow computing absolute variant idx");
- let variants_len = op
- .layout
- .ty
- .ty_adt_def()
- .expect("tagged layout for non adt")
- .variants()
- .len();
- assert!(usize::try_from(variant_index).unwrap() < variants_len);
- VariantIdx::from_u32(variant_index)
- } else {
- untagged_variant
- }
- }
- };
- // Compute the size of the scalar we need to return.
- // No need to cast, because the variant index directly serves as discriminant and is
- // encoded in the tag.
- (Scalar::from_uint(variant.as_u32(), discr_layout.size), variant)
- }
- })
- }
}
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
use rustc_ast::Mutability;
use rustc_middle::mir;
use rustc_middle::ty;
-use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
-use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size, TagEncoding, VariantIdx};
+use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
+use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size, VariantIdx};
use super::{
alloc_range, mir_assign_valid_types, AllocId, AllocRef, AllocRefMut, CheckInAllocMsg,
MPlaceTy { mplace, layout, align: layout.align.abi }
}
- /// Writes the discriminant of the given variant.
- #[instrument(skip(self), level = "debug")]
- pub fn write_discriminant(
+ /// Writes the aggregate to the destination.
+ #[instrument(skip(self), level = "trace")]
+ pub fn write_aggregate(
&mut self,
- variant_index: VariantIdx,
+ kind: &mir::AggregateKind<'tcx>,
+ operands: &[mir::Operand<'tcx>],
dest: &PlaceTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx> {
- // This must be an enum or generator.
- match dest.layout.ty.kind() {
- ty::Adt(adt, _) => assert!(adt.is_enum()),
- ty::Generator(..) => {}
- _ => span_bug!(
- self.cur_span(),
- "write_discriminant called on non-variant-type (neither enum nor generator)"
- ),
- }
- // Layout computation excludes uninhabited variants from consideration
- // therefore there's no way to represent those variants in the given layout.
- // Essentially, uninhabited variants do not have a tag that corresponds to their
- // discriminant, so we cannot do anything here.
- // When evaluating we will always error before even getting here, but ConstProp 'executes'
- // dead code, so we cannot ICE here.
- if dest.layout.for_variant(self, variant_index).abi.is_uninhabited() {
- throw_ub!(UninhabitedEnumVariantWritten)
- }
-
- match dest.layout.variants {
- abi::Variants::Single { index } => {
- assert_eq!(index, variant_index);
- }
- abi::Variants::Multiple {
- tag_encoding: TagEncoding::Direct,
- tag: tag_layout,
- tag_field,
- ..
- } => {
- // No need to validate that the discriminant here because the
- // `TyAndLayout::for_variant()` call earlier already checks the variant is valid.
-
- let discr_val =
- dest.layout.ty.discriminant_for_variant(*self.tcx, variant_index).unwrap().val;
-
- // raw discriminants for enums are isize or bigger during
- // their computation, but the in-memory tag is the smallest possible
- // representation
- let size = tag_layout.size(self);
- let tag_val = size.truncate(discr_val);
-
- let tag_dest = self.place_field(dest, tag_field)?;
- self.write_scalar(Scalar::from_uint(tag_val, size), &tag_dest)?;
- }
- abi::Variants::Multiple {
- tag_encoding:
- TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start },
- tag: tag_layout,
- tag_field,
- ..
- } => {
- // No need to validate that the discriminant here because the
- // `TyAndLayout::for_variant()` call earlier already checks the variant is valid.
-
- if variant_index != untagged_variant {
- let variants_start = niche_variants.start().as_u32();
- let variant_index_relative = variant_index
- .as_u32()
- .checked_sub(variants_start)
- .expect("overflow computing relative variant idx");
- // We need to use machine arithmetic when taking into account `niche_start`:
- // tag_val = variant_index_relative + niche_start_val
- let tag_layout = self.layout_of(tag_layout.primitive().to_int_ty(*self.tcx))?;
- let niche_start_val = ImmTy::from_uint(niche_start, tag_layout);
- let variant_index_relative_val =
- ImmTy::from_uint(variant_index_relative, tag_layout);
- let tag_val = self.binary_op(
- mir::BinOp::Add,
- &variant_index_relative_val,
- &niche_start_val,
- )?;
- // Write result.
- let niche_dest = self.place_field(dest, tag_field)?;
- self.write_immediate(*tag_val, &niche_dest)?;
- }
+ self.write_uninit(&dest)?;
+ let (variant_index, variant_dest, active_field_index) = match *kind {
+ mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => {
+ let variant_dest = self.place_downcast(&dest, variant_index)?;
+ (variant_index, variant_dest, active_field_index)
}
+ _ => (VariantIdx::from_u32(0), dest.clone(), None),
+ };
+ if active_field_index.is_some() {
+ assert_eq!(operands.len(), 1);
}
-
- Ok(())
+ for (field_index, operand) in operands.iter().enumerate() {
+ let field_index = active_field_index.unwrap_or(field_index);
+ let field_dest = self.place_field(&variant_dest, field_index)?;
+ let op = self.eval_operand(operand, Some(field_dest.layout))?;
+ self.copy_op(&op, &field_dest, /*allow_transmute*/ false)?;
+ }
+ self.write_discriminant(variant_index, &dest)
}
pub fn raw_const_to_mplace(
}
Aggregate(box ref kind, ref operands) => {
- assert!(matches!(kind, mir::AggregateKind::Array(..)));
-
- for (field_index, operand) in operands.iter().enumerate() {
- let op = self.eval_operand(operand, None)?;
- let field_dest = self.place_field(&dest, field_index)?;
- self.copy_op(&op, &field_dest, /*allow_transmute*/ false)?;
- }
+ self.write_aggregate(kind, operands, &dest)?;
}
Repeat(ref operand, _) => {
Rvalue::Aggregate(kind, ..) => {
if let AggregateKind::Generator(def_id, ..) = kind.as_ref()
- && let Some(generator_kind @ hir::GeneratorKind::Async(..)) = self.tcx.generator_kind(def_id.to_def_id())
+ && let Some(generator_kind @ hir::GeneratorKind::Async(..)) = self.tcx.generator_kind(def_id)
{
self.check_op(ops::Generator(generator_kind));
}
use rustc_trait_selection::traits::SelectionContext;
use super::ConstCx;
-use crate::errors::{
- InteriorMutabilityBorrow, InteriorMutableDataRefer, MutDerefErr, NonConstFmtMacroCall,
- NonConstFnCall, NonConstOpErr, PanicNonStrErr, RawPtrToIntErr, StaticAccessErr,
- TransientMutBorrowErr, TransientMutBorrowErrRaw, UnallowedFnPointerCall,
- UnallowedHeapAllocations, UnallowedInlineAsm, UnallowedMutableRefs, UnallowedMutableRefsRaw,
- UnallowedOpInConstContext, UnstableConstFn,
-};
+use crate::errors;
use crate::util::{call_kind, CallDesugaringKind, CallKind};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(UnallowedFnPointerCall { span, kind: ccx.const_kind() })
+ ccx.tcx.sess.create_err(errors::UnallowedFnPointerCall { span, kind: ccx.const_kind() })
}
}
diag_trait(&mut err, self_ty, tcx.require_lang_item(LangItem::Deref, Some(span)));
err
}
- _ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentV1Methods) => {
- ccx.tcx.sess.create_err(NonConstFmtMacroCall { span, kind: ccx.const_kind() })
- }
- _ => ccx.tcx.sess.create_err(NonConstFnCall {
+ _ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentV1Methods) => ccx
+ .tcx
+ .sess
+ .create_err(errors::NonConstFmtMacroCall { span, kind: ccx.const_kind() }),
+ _ => ccx.tcx.sess.create_err(errors::NonConstFnCall {
span,
def_path_str: ccx.tcx.def_path_str_with_substs(callee, substs),
kind: ccx.const_kind(),
let mut err = ccx
.tcx
.sess
- .create_err(UnstableConstFn { span, def_path: ccx.tcx.def_path_str(def_id) });
+ .create_err(errors::UnstableConstFn { span, def_path: ccx.tcx.def_path_str(def_id) });
if ccx.is_const_stable_const_fn() {
err.help("const-stable functions can only call other const-stable functions");
let msg = format!("{}s are not allowed in {}s", self.0.descr(), ccx.const_kind());
if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 {
ccx.tcx.sess.create_feature_err(
- UnallowedOpInConstContext { span, msg },
+ errors::UnallowedOpInConstContext { span, msg },
sym::const_async_blocks,
)
} else {
- ccx.tcx.sess.create_err(UnallowedOpInConstContext { span, msg })
+ ccx.tcx.sess.create_err(errors::UnallowedOpInConstContext { span, msg })
}
}
}
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(UnallowedHeapAllocations {
+ ccx.tcx.sess.create_err(errors::UnallowedHeapAllocations {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0010)).then_some(()),
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(UnallowedInlineAsm { span, kind: ccx.const_kind() })
+ ccx.tcx.sess.create_err(errors::UnallowedInlineAsm { span, kind: ccx.const_kind() })
}
}
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_feature_err(InteriorMutabilityBorrow { span }, sym::const_refs_to_cell)
+ ccx.tcx
+ .sess
+ .create_feature_err(errors::InteriorMutabilityBorrow { span }, sym::const_refs_to_cell)
}
}
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
// FIXME: Maybe a more elegant solution to this if else case
if let hir::ConstContext::Static(_) = ccx.const_kind() {
- ccx.tcx.sess.create_err(InteriorMutableDataRefer {
+ ccx.tcx.sess.create_err(errors::InteriorMutableDataRefer {
span,
opt_help: Some(()),
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0492)).then_some(()),
})
} else {
- ccx.tcx.sess.create_err(InteriorMutableDataRefer {
+ ccx.tcx.sess.create_err(errors::InteriorMutableDataRefer {
span,
opt_help: None,
kind: ccx.const_kind(),
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
match self.0 {
- hir::BorrowKind::Raw => ccx.tcx.sess.create_err(UnallowedMutableRefsRaw {
+ hir::BorrowKind::Raw => ccx.tcx.sess.create_err(errors::UnallowedMutableRefsRaw {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()),
}),
- hir::BorrowKind::Ref => ccx.tcx.sess.create_err(UnallowedMutableRefs {
+ hir::BorrowKind::Ref => ccx.tcx.sess.create_err(errors::UnallowedMutableRefs {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()),
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let kind = ccx.const_kind();
match self.0 {
- hir::BorrowKind::Raw => ccx
- .tcx
- .sess
- .create_feature_err(TransientMutBorrowErrRaw { span, kind }, sym::const_mut_refs),
- hir::BorrowKind::Ref => ccx
- .tcx
- .sess
- .create_feature_err(TransientMutBorrowErr { span, kind }, sym::const_mut_refs),
+ hir::BorrowKind::Raw => ccx.tcx.sess.create_feature_err(
+ errors::TransientMutBorrowErrRaw { span, kind },
+ sym::const_mut_refs,
+ ),
+ hir::BorrowKind::Ref => ccx.tcx.sess.create_feature_err(
+ errors::TransientMutBorrowErr { span, kind },
+ sym::const_mut_refs,
+ ),
}
}
}
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx
- .sess
- .create_feature_err(MutDerefErr { span, kind: ccx.const_kind() }, sym::const_mut_refs)
+ ccx.tcx.sess.create_feature_err(
+ errors::MutDerefErr { span, kind: ccx.const_kind() },
+ sym::const_mut_refs,
+ )
}
}
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(PanicNonStrErr { span })
+ ccx.tcx.sess.create_err(errors::PanicNonStrErr { span })
}
}
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(RawPtrToIntErr { span })
+ ccx.tcx.sess.create_err(errors::RawPtrToIntErr { span })
}
}
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(StaticAccessErr {
+ ccx.tcx.sess.create_err(errors::StaticAccessErr {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0013)).then_some(()),
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(NonConstOpErr { span })
+ ccx.tcx.sess.create_err(errors::NonConstOpErr { span })
}
}
use rustc_middle::mir::visit::NonUseContext::VarDebugInfo;
use rustc_middle::mir::visit::{PlaceContext, Visitor};
use rustc_middle::mir::{
- traversal, AggregateKind, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping,
- Local, Location, MirPass, MirPhase, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef,
- ProjectionElem, RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind,
- Terminator, TerminatorKind, UnOp, START_BLOCK,
+ traversal, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, Local, Location,
+ MirPass, MirPhase, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, ProjectionElem,
+ RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, Terminator,
+ TerminatorKind, UnOp, START_BLOCK,
};
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt};
use rustc_mir_dataflow::impls::MaybeStorageLive;
};
}
match rvalue {
- Rvalue::Use(_) | Rvalue::CopyForDeref(_) => {}
- Rvalue::Aggregate(agg_kind, _) => {
- let disallowed = match **agg_kind {
- AggregateKind::Array(..) => false,
- _ => self.mir_phase >= MirPhase::Runtime(RuntimePhase::PostCleanup),
- };
- if disallowed {
- self.fail(
- location,
- format!("{:?} have been lowered to field assignments", rvalue),
- )
- }
- }
+ Rvalue::Use(_) | Rvalue::CopyForDeref(_) | Rvalue::Aggregate(..) => {}
Rvalue::Ref(_, BorrowKind::Shallow, _) => {
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(
// FIXME(JakobDegen) The validator should check that `self.mir_phase <
// DropsLowered`. However, this causes ICEs with generation of drop shims, which
// seem to fail to set their `MirPhase` correctly.
- if *kind == RetagKind::Raw || *kind == RetagKind::TwoPhase {
+ if matches!(kind, RetagKind::Raw | RetagKind::TwoPhase) {
self.fail(location, format!("explicit `{:?}` is forbidden", kind));
}
}
+++ /dev/null
-use rustc_index::vec::Idx;
-use rustc_middle::mir::*;
-use rustc_middle::ty::{Ty, TyCtxt};
-use rustc_target::abi::VariantIdx;
-
-use std::iter::TrustedLen;
-
-/// Expand `lhs = Rvalue::Aggregate(kind, operands)` into assignments to the fields.
-///
-/// Produces something like
-/// ```ignore (ilustrative)
-/// (lhs as Variant).field0 = arg0; // We only have a downcast if this is an enum
-/// (lhs as Variant).field1 = arg1;
-/// discriminant(lhs) = variant_index; // If lhs is an enum or generator.
-/// ```
-pub fn expand_aggregate<'tcx>(
- orig_lhs: Place<'tcx>,
- operands: impl Iterator<Item = (Operand<'tcx>, Ty<'tcx>)> + TrustedLen,
- kind: AggregateKind<'tcx>,
- source_info: SourceInfo,
- tcx: TyCtxt<'tcx>,
-) -> impl Iterator<Item = Statement<'tcx>> + TrustedLen {
- let mut lhs = orig_lhs;
- let mut set_discriminant = None;
- let active_field_index = match kind {
- AggregateKind::Adt(adt_did, variant_index, _, _, active_field_index) => {
- let adt_def = tcx.adt_def(adt_did);
- if adt_def.is_enum() {
- set_discriminant = Some(Statement {
- kind: StatementKind::SetDiscriminant {
- place: Box::new(orig_lhs),
- variant_index,
- },
- source_info,
- });
- lhs = tcx.mk_place_downcast(orig_lhs, adt_def, variant_index);
- }
- active_field_index
- }
- AggregateKind::Generator(..) => {
- // Right now we only support initializing generators to
- // variant 0 (Unresumed).
- let variant_index = VariantIdx::new(0);
- set_discriminant = Some(Statement {
- kind: StatementKind::SetDiscriminant { place: Box::new(orig_lhs), variant_index },
- source_info,
- });
-
- // Operands are upvars stored on the base place, so no
- // downcast is necessary.
-
- None
- }
- _ => None,
- };
-
- let operands = operands.enumerate().map(move |(i, (op, ty))| {
- let lhs_field = if let AggregateKind::Array(_) = kind {
- let offset = u64::try_from(i).unwrap();
- tcx.mk_place_elem(
- lhs,
- ProjectionElem::ConstantIndex { offset, min_length: offset + 1, from_end: false },
- )
- } else {
- let field = Field::new(active_field_index.unwrap_or(i));
- tcx.mk_place_field(lhs, field, ty)
- };
- Statement {
- source_info,
- kind: StatementKind::Assign(Box::new((lhs_field, Rvalue::Use(op)))),
- }
- });
- [Statement { source_info, kind: StatementKind::Deinit(Box::new(orig_lhs)) }]
- .into_iter()
- .chain(operands)
- .chain(set_discriminant)
-}
-pub mod aggregate;
mod alignment;
mod call_kind;
pub mod collect_writes;
mod might_permit_raw_init;
mod type_name;
-pub use self::aggregate::expand_aggregate;
pub use self::alignment::is_disaligned;
pub use self::call_kind::{call_kind, CallDesugaringKind, CallKind};
pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype};
pub trait ObligationProcessor {
type Obligation: ForestObligation;
type Error: Debug;
- type OUT: OutcomeTrait<
- Obligation = Self::Obligation,
- Error = Error<Self::Obligation, Self::Error>,
- >;
+ type OUT: OutcomeTrait<Obligation = Self::Obligation, Error = Error<Self::Obligation, Self::Error>>;
fn needs_process_obligation(&self, obligation: &Self::Obligation) -> bool;
pub auto trait Send {}
pub auto trait Sync {}
- impl<T: ?Sized> Send for T {}
- impl<T: ?Sized> Sync for T {}
+ impl<T> Send for T {}
+ impl<T> Sync for T {}
#[macro_export]
macro_rules! rustc_erase_owner {
crate-type = ["dylib"]
[dependencies]
-tracing = { version = "0.1.35" }
-serde_json = "1.0.59"
-rustc_log = { path = "../rustc_log" }
-rustc_middle = { path = "../rustc_middle" }
-rustc_ast_pretty = { path = "../rustc_ast_pretty" }
-rustc_target = { path = "../rustc_target" }
-rustc_lint = { path = "../rustc_lint" }
-rustc_data_structures = { path = "../rustc_data_structures" }
-rustc_errors = { path = "../rustc_errors" }
-rustc_feature = { path = "../rustc_feature" }
-rustc_hir = { path = "../rustc_hir" }
-rustc_hir_pretty = { path = "../rustc_hir_pretty" }
-rustc_macros = { path = "../rustc_macros" }
-rustc_metadata = { path = "../rustc_metadata" }
-rustc_parse = { path = "../rustc_parse" }
-rustc_plugin_impl = { path = "../rustc_plugin_impl" }
-rustc_save_analysis = { path = "../rustc_save_analysis" }
-rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
-rustc_session = { path = "../rustc_session" }
-rustc_error_codes = { path = "../rustc_error_codes" }
-rustc_interface = { path = "../rustc_interface" }
-rustc_ast = { path = "../rustc_ast" }
-rustc_span = { path = "../rustc_span" }
-rustc_hir_analysis = { path = "../rustc_hir_analysis" }
-
-[target.'cfg(unix)'.dependencies]
-libc = "0.2"
-
-[target.'cfg(windows)'.dependencies]
-winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"] }
-
-[features]
-llvm = ['rustc_interface/llvm']
-max_level_info = ['rustc_log/max_level_info']
-rustc_use_parallel_compiler = ['rustc_data_structures/rustc_use_parallel_compiler', 'rustc_interface/rustc_use_parallel_compiler',
- 'rustc_middle/rustc_use_parallel_compiler']
+rustc_driver_impl = { path = "../rustc_driver_impl" }
+++ /dev/null
-The `driver` crate is effectively the "main" function for the rust
-compiler. It orchestrates the compilation process and "knits together"
-the code from the other crates within rustc. This crate itself does
-not contain any of the "main logic" of the compiler (though it does
-have some code related to pretty printing or other minor compiler
-options).
-
-For more information about how the driver works, see the [rustc dev guide].
-
-[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/rustc-driver.html
+++ /dev/null
-use std::error;
-use std::fmt;
-use std::fs;
-use std::io;
-
-fn arg_expand(arg: String) -> Result<Vec<String>, Error> {
- if let Some(path) = arg.strip_prefix('@') {
- let file = match fs::read_to_string(path) {
- Ok(file) => file,
- Err(ref err) if err.kind() == io::ErrorKind::InvalidData => {
- return Err(Error::Utf8Error(Some(path.to_string())));
- }
- Err(err) => return Err(Error::IOError(path.to_string(), err)),
- };
- Ok(file.lines().map(ToString::to_string).collect())
- } else {
- Ok(vec![arg])
- }
-}
-
-pub fn arg_expand_all(at_args: &[String]) -> Vec<String> {
- let mut args = Vec::new();
- for arg in at_args {
- match arg_expand(arg.clone()) {
- Ok(arg) => args.extend(arg),
- Err(err) => rustc_session::early_error(
- rustc_session::config::ErrorOutputType::default(),
- &format!("Failed to load argument file: {err}"),
- ),
- }
- }
- args
-}
-
-#[derive(Debug)]
-pub enum Error {
- Utf8Error(Option<String>),
- IOError(String, io::Error),
-}
-
-impl fmt::Display for Error {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Error::Utf8Error(None) => write!(fmt, "Utf8 error"),
- Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {path}"),
- Error::IOError(path, err) => write!(fmt, "IO Error: {path}: {err}"),
- }
- }
-}
-
-impl error::Error for Error {}
-//! The Rust compiler.
-//!
-//! # Note
-//!
-//! This API is completely unstable and subject to change.
+// This crate is intentionally empty and a rexport of `rustc_driver_impl` to allow the code in
+// `rustc_driver_impl` to be compiled in parallel with other crates.
-#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![feature(is_terminal)]
-#![feature(once_cell)]
-#![feature(decl_macro)]
-#![recursion_limit = "256"]
-#![allow(rustc::potential_query_instability)]
-#![deny(rustc::untranslatable_diagnostic)]
-#![deny(rustc::diagnostic_outside_of_impl)]
-
-#[macro_use]
-extern crate tracing;
-
-pub extern crate rustc_plugin_impl as plugin;
-
-use rustc_ast as ast;
-use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults};
-use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
-use rustc_data_structures::sync::SeqCst;
-use rustc_errors::registry::{InvalidErrorCode, Registry};
-use rustc_errors::{ErrorGuaranteed, PResult};
-use rustc_feature::find_gated_cfg;
-use rustc_hir::def_id::LOCAL_CRATE;
-use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
-use rustc_interface::{interface, Queries};
-use rustc_lint::LintStore;
-use rustc_metadata::locator;
-use rustc_save_analysis as save;
-use rustc_save_analysis::DumpHandler;
-use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS};
-use rustc_session::config::{ErrorOutputType, Input, OutputType, PrintRequest, TrimmedDefPaths};
-use rustc_session::cstore::MetadataLoader;
-use rustc_session::getopts;
-use rustc_session::lint::{Lint, LintId};
-use rustc_session::{config, Session};
-use rustc_session::{early_error, early_error_no_abort, early_warn};
-use rustc_span::source_map::{FileLoader, FileName};
-use rustc_span::symbol::sym;
-use rustc_target::json::ToJson;
-
-use std::borrow::Cow;
-use std::cmp::max;
-use std::env;
-use std::ffi::OsString;
-use std::fs;
-use std::io::{self, IsTerminal, Read, Write};
-use std::panic::{self, catch_unwind};
-use std::path::PathBuf;
-use std::process::{self, Command, Stdio};
-use std::str;
-use std::sync::LazyLock;
-use std::time::Instant;
-
-pub mod args;
-pub mod pretty;
-mod session_diagnostics;
-
-use crate::session_diagnostics::{
- RLinkEmptyVersionNumber, RLinkEncodingVersionMismatch, RLinkRustcVersionMismatch,
- RLinkWrongFileType, RlinkNotAFile, RlinkUnableToRead,
-};
-
-/// Exit status code used for successful compilation and help output.
-pub const EXIT_SUCCESS: i32 = 0;
-
-/// Exit status code used for compilation failures and invalid flags.
-pub const EXIT_FAILURE: i32 = 1;
-
-const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust/issues/new\
- ?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md";
-
-const ICE_REPORT_COMPILER_FLAGS: &[&str] = &["-Z", "-C", "--crate-type"];
-
-const ICE_REPORT_COMPILER_FLAGS_EXCLUDE: &[&str] = &["metadata", "extra-filename"];
-
-const ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE: &[&str] = &["incremental"];
-
-pub fn abort_on_err<T>(result: Result<T, ErrorGuaranteed>, sess: &Session) -> T {
- match result {
- Err(..) => {
- sess.abort_if_errors();
- panic!("error reported but abort_if_errors didn't abort???");
- }
- Ok(x) => x,
- }
-}
-
-pub trait Callbacks {
- /// Called before creating the compiler instance
- fn config(&mut self, _config: &mut interface::Config) {}
- /// Called after parsing. Return value instructs the compiler whether to
- /// continue the compilation afterwards (defaults to `Compilation::Continue`)
- fn after_parsing<'tcx>(
- &mut self,
- _compiler: &interface::Compiler,
- _queries: &'tcx Queries<'tcx>,
- ) -> Compilation {
- Compilation::Continue
- }
- /// Called after expansion. Return value instructs the compiler whether to
- /// continue the compilation afterwards (defaults to `Compilation::Continue`)
- fn after_expansion<'tcx>(
- &mut self,
- _compiler: &interface::Compiler,
- _queries: &'tcx Queries<'tcx>,
- ) -> Compilation {
- Compilation::Continue
- }
- /// Called after analysis. Return value instructs the compiler whether to
- /// continue the compilation afterwards (defaults to `Compilation::Continue`)
- fn after_analysis<'tcx>(
- &mut self,
- _compiler: &interface::Compiler,
- _queries: &'tcx Queries<'tcx>,
- ) -> Compilation {
- Compilation::Continue
- }
-}
-
-#[derive(Default)]
-pub struct TimePassesCallbacks {
- time_passes: bool,
-}
-
-impl Callbacks for TimePassesCallbacks {
- // JUSTIFICATION: the session doesn't exist at this point.
- #[allow(rustc::bad_opt_access)]
- fn config(&mut self, config: &mut interface::Config) {
- // If a --print=... option has been given, we don't print the "total"
- // time because it will mess up the --print output. See #64339.
- //
- self.time_passes = config.opts.prints.is_empty() && config.opts.unstable_opts.time_passes;
- config.opts.trimmed_def_paths = TrimmedDefPaths::GoodPath;
- }
-}
-
-pub fn diagnostics_registry() -> Registry {
- Registry::new(rustc_error_codes::DIAGNOSTICS)
-}
-
-/// This is the primary entry point for rustc.
-pub struct RunCompiler<'a, 'b> {
- at_args: &'a [String],
- callbacks: &'b mut (dyn Callbacks + Send),
- file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
- make_codegen_backend:
- Option<Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>>,
-}
-
-impl<'a, 'b> RunCompiler<'a, 'b> {
- pub fn new(at_args: &'a [String], callbacks: &'b mut (dyn Callbacks + Send)) -> Self {
- Self { at_args, callbacks, file_loader: None, make_codegen_backend: None }
- }
-
- /// Set a custom codegen backend.
- ///
- /// Has no uses within this repository, but is used by bjorn3 for "the
- /// hotswapping branch of cg_clif" for "setting the codegen backend from a
- /// custom driver where the custom codegen backend has arbitrary data."
- /// (See #102759.)
- pub fn set_make_codegen_backend(
- &mut self,
- make_codegen_backend: Option<
- Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
- >,
- ) -> &mut Self {
- self.make_codegen_backend = make_codegen_backend;
- self
- }
-
- /// Load files from sources other than the file system.
- ///
- /// Has no uses within this repository, but may be used in the future by
- /// bjorn3 for "hooking rust-analyzer's VFS into rustc at some point for
- /// running rustc without having to save". (See #102759.)
- pub fn set_file_loader(
- &mut self,
- file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
- ) -> &mut Self {
- self.file_loader = file_loader;
- self
- }
-
- /// Parse args and run the compiler.
- pub fn run(self) -> interface::Result<()> {
- run_compiler(self.at_args, self.callbacks, self.file_loader, self.make_codegen_backend)
- }
-}
-
-fn run_compiler(
- at_args: &[String],
- callbacks: &mut (dyn Callbacks + Send),
- file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
- make_codegen_backend: Option<
- Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
- >,
-) -> interface::Result<()> {
- let args = args::arg_expand_all(at_args);
-
- let Some(matches) = handle_options(&args) else { return Ok(()) };
-
- let sopts = config::build_session_options(&matches);
-
- if let Some(ref code) = matches.opt_str("explain") {
- handle_explain(diagnostics_registry(), code, sopts.error_format);
- return Ok(());
- }
-
- let cfg = interface::parse_cfgspecs(matches.opt_strs("cfg"));
- let check_cfg = interface::parse_check_cfg(matches.opt_strs("check-cfg"));
- let (odir, ofile) = make_output(&matches);
- let mut config = interface::Config {
- opts: sopts,
- crate_cfg: cfg,
- crate_check_cfg: check_cfg,
- input: Input::File(PathBuf::new()),
- output_file: ofile,
- output_dir: odir,
- file_loader,
- lint_caps: Default::default(),
- parse_sess_created: None,
- register_lints: None,
- override_queries: None,
- make_codegen_backend,
- registry: diagnostics_registry(),
- };
-
- if !tracing::dispatcher::has_been_set() {
- init_rustc_env_logger_with_backtrace_option(&config.opts.unstable_opts.log_backtrace);
- }
-
- match make_input(config.opts.error_format, &matches.free) {
- Err(reported) => return Err(reported),
- Ok(Some(input)) => {
- config.input = input;
-
- callbacks.config(&mut config);
- }
- Ok(None) => match matches.free.len() {
- 0 => {
- callbacks.config(&mut config);
- interface::run_compiler(config, |compiler| {
- let sopts = &compiler.session().opts;
- if sopts.describe_lints {
- let mut lint_store =
- rustc_lint::new_lint_store(compiler.session().enable_internal_lints());
- let registered_lints =
- if let Some(register_lints) = compiler.register_lints() {
- register_lints(compiler.session(), &mut lint_store);
- true
- } else {
- false
- };
- describe_lints(compiler.session(), &lint_store, registered_lints);
- return;
- }
- let should_stop =
- print_crate_info(&***compiler.codegen_backend(), compiler.session(), false);
-
- if should_stop == Compilation::Stop {
- return;
- }
- early_error(sopts.error_format, "no input filename given")
- });
- return Ok(());
- }
- 1 => panic!("make_input should have provided valid inputs"),
- _ => early_error(
- config.opts.error_format,
- &format!(
- "multiple input filenames provided (first two filenames are `{}` and `{}`)",
- matches.free[0], matches.free[1],
- ),
- ),
- },
- };
-
- interface::run_compiler(config, |compiler| {
- let sess = compiler.session();
- let should_stop = print_crate_info(&***compiler.codegen_backend(), sess, true)
- .and_then(|| list_metadata(sess, &*compiler.codegen_backend().metadata_loader()))
- .and_then(|| try_process_rlink(sess, compiler));
-
- if should_stop == Compilation::Stop {
- return sess.compile_status();
- }
-
- let linker = compiler.enter(|queries| {
- let early_exit = || sess.compile_status().map(|_| None);
- queries.parse()?;
-
- if let Some(ppm) = &sess.opts.pretty {
- if ppm.needs_ast_map() {
- queries.global_ctxt()?.enter(|tcx| {
- pretty::print_after_hir_lowering(tcx, *ppm);
- Ok(())
- })?;
- } else {
- let krate = queries.parse()?.steal();
- pretty::print_after_parsing(sess, &krate, *ppm);
- }
- trace!("finished pretty-printing");
- return early_exit();
- }
-
- if callbacks.after_parsing(compiler, queries) == Compilation::Stop {
- return early_exit();
- }
-
- if sess.opts.unstable_opts.parse_only || sess.opts.unstable_opts.show_span.is_some() {
- return early_exit();
- }
-
- {
- let plugins = queries.register_plugins()?;
- let (_, lint_store) = &*plugins.borrow();
-
- // Lint plugins are registered; now we can process command line flags.
- if sess.opts.describe_lints {
- describe_lints(sess, lint_store, true);
- return early_exit();
- }
- }
-
- let mut gctxt = queries.global_ctxt()?;
- if callbacks.after_expansion(compiler, queries) == Compilation::Stop {
- return early_exit();
- }
-
- // Make sure the `output_filenames` query is run for its side
- // effects of writing the dep-info and reporting errors.
- gctxt.enter(|tcx| tcx.output_filenames(()));
-
- if sess.opts.output_types.contains_key(&OutputType::DepInfo)
- && sess.opts.output_types.len() == 1
- {
- return early_exit();
- }
-
- if sess.opts.unstable_opts.no_analysis {
- return early_exit();
- }
-
- gctxt.enter(|tcx| {
- let result = tcx.analysis(());
- if sess.opts.unstable_opts.save_analysis {
- let crate_name = tcx.crate_name(LOCAL_CRATE);
- sess.time("save_analysis", || {
- save::process_crate(
- tcx,
- crate_name,
- &sess.io.input,
- None,
- DumpHandler::new(sess.io.output_dir.as_deref(), crate_name),
- )
- });
- }
- result
- })?;
-
- drop(gctxt);
-
- if callbacks.after_analysis(compiler, queries) == Compilation::Stop {
- return early_exit();
- }
-
- queries.ongoing_codegen()?;
-
- if sess.opts.unstable_opts.print_type_sizes {
- sess.code_stats.print_type_sizes();
- }
-
- let linker = queries.linker()?;
- Ok(Some(linker))
- })?;
-
- if let Some(linker) = linker {
- let _timer = sess.timer("link");
- linker.link()?
- }
-
- if sess.opts.unstable_opts.perf_stats {
- sess.print_perf_stats();
- }
-
- if sess.opts.unstable_opts.print_fuel.is_some() {
- eprintln!(
- "Fuel used by {}: {}",
- sess.opts.unstable_opts.print_fuel.as_ref().unwrap(),
- sess.print_fuel.load(SeqCst)
- );
- }
-
- Ok(())
- })
-}
-
-// Extract output directory and file from matches.
-fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<PathBuf>) {
- let odir = matches.opt_str("out-dir").map(|o| PathBuf::from(&o));
- let ofile = matches.opt_str("o").map(|o| PathBuf::from(&o));
- (odir, ofile)
-}
-
-// Extract input (string or file and optional path) from matches.
-fn make_input(
- error_format: ErrorOutputType,
- free_matches: &[String],
-) -> Result<Option<Input>, ErrorGuaranteed> {
- if free_matches.len() == 1 {
- let ifile = &free_matches[0];
- if ifile == "-" {
- let mut src = String::new();
- if io::stdin().read_to_string(&mut src).is_err() {
- // Immediately stop compilation if there was an issue reading
- // the input (for example if the input stream is not UTF-8).
- let reported = early_error_no_abort(
- error_format,
- "couldn't read from stdin, as it did not contain valid UTF-8",
- );
- return Err(reported);
- }
- if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") {
- let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect(
- "when UNSTABLE_RUSTDOC_TEST_PATH is set \
- UNSTABLE_RUSTDOC_TEST_LINE also needs to be set",
- );
- let line = isize::from_str_radix(&line, 10)
- .expect("UNSTABLE_RUSTDOC_TEST_LINE needs to be an number");
- let file_name = FileName::doc_test_source_code(PathBuf::from(path), line);
- Ok(Some(Input::Str { name: file_name, input: src }))
- } else {
- Ok(Some(Input::Str { name: FileName::anon_source_code(&src), input: src }))
- }
- } else {
- Ok(Some(Input::File(PathBuf::from(ifile))))
- }
- } else {
- Ok(None)
- }
-}
-
-/// Whether to stop or continue compilation.
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-pub enum Compilation {
- Stop,
- Continue,
-}
-
-impl Compilation {
- pub fn and_then<F: FnOnce() -> Compilation>(self, next: F) -> Compilation {
- match self {
- Compilation::Stop => Compilation::Stop,
- Compilation::Continue => next(),
- }
- }
-}
-
-fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
- let upper_cased_code = code.to_ascii_uppercase();
- let normalised =
- if upper_cased_code.starts_with('E') { upper_cased_code } else { format!("E{code:0>4}") };
- match registry.try_find_description(&normalised) {
- Ok(Some(description)) => {
- let mut is_in_code_block = false;
- let mut text = String::new();
- // Slice off the leading newline and print.
- for line in description.lines() {
- let indent_level =
- line.find(|c: char| !c.is_whitespace()).unwrap_or_else(|| line.len());
- let dedented_line = &line[indent_level..];
- if dedented_line.starts_with("```") {
- is_in_code_block = !is_in_code_block;
- text.push_str(&line[..(indent_level + 3)]);
- } else if is_in_code_block && dedented_line.starts_with("# ") {
- continue;
- } else {
- text.push_str(line);
- }
- text.push('\n');
- }
- if io::stdout().is_terminal() {
- show_content_with_pager(&text);
- } else {
- print!("{text}");
- }
- }
- Ok(None) => {
- early_error(output, &format!("no extended information for {code}"));
- }
- Err(InvalidErrorCode) => {
- early_error(output, &format!("{code} is not a valid error code"));
- }
- }
-}
-
-fn show_content_with_pager(content: &str) {
- let pager_name = env::var_os("PAGER").unwrap_or_else(|| {
- if cfg!(windows) { OsString::from("more.com") } else { OsString::from("less") }
- });
-
- let mut fallback_to_println = false;
-
- match Command::new(pager_name).stdin(Stdio::piped()).spawn() {
- Ok(mut pager) => {
- if let Some(pipe) = pager.stdin.as_mut() {
- if pipe.write_all(content.as_bytes()).is_err() {
- fallback_to_println = true;
- }
- }
-
- if pager.wait().is_err() {
- fallback_to_println = true;
- }
- }
- Err(_) => {
- fallback_to_println = true;
- }
- }
-
- // If pager fails for whatever reason, we should still print the content
- // to standard output
- if fallback_to_println {
- print!("{content}");
- }
-}
-
-pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Compilation {
- if sess.opts.unstable_opts.link_only {
- if let Input::File(file) = &sess.io.input {
- // FIXME: #![crate_type] and #![crate_name] support not implemented yet
- sess.init_crate_types(collect_crate_types(sess, &[]));
- let outputs = compiler.build_output_filenames(sess, &[]);
- let rlink_data = fs::read(file).unwrap_or_else(|err| {
- sess.emit_fatal(RlinkUnableToRead { err });
- });
- let codegen_results = match CodegenResults::deserialize_rlink(rlink_data) {
- Ok(codegen) => codegen,
- Err(err) => {
- match err {
- CodegenErrors::WrongFileType => sess.emit_fatal(RLinkWrongFileType),
- CodegenErrors::EmptyVersionNumber => {
- sess.emit_fatal(RLinkEmptyVersionNumber)
- }
- CodegenErrors::EncodingVersionMismatch { version_array, rlink_version } => {
- sess.emit_fatal(RLinkEncodingVersionMismatch {
- version_array,
- rlink_version,
- })
- }
- CodegenErrors::RustcVersionMismatch { rustc_version, current_version } => {
- sess.emit_fatal(RLinkRustcVersionMismatch {
- rustc_version,
- current_version,
- })
- }
- };
- }
- };
- let result = compiler.codegen_backend().link(sess, codegen_results, &outputs);
- abort_on_err(result, sess);
- } else {
- sess.emit_fatal(RlinkNotAFile {})
- }
- Compilation::Stop
- } else {
- Compilation::Continue
- }
-}
-
-pub fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) -> Compilation {
- if sess.opts.unstable_opts.ls {
- match sess.io.input {
- Input::File(ref ifile) => {
- let path = &(*ifile);
- let mut v = Vec::new();
- locator::list_file_metadata(&sess.target, path, metadata_loader, &mut v).unwrap();
- println!("{}", String::from_utf8(v).unwrap());
- }
- Input::Str { .. } => {
- early_error(ErrorOutputType::default(), "cannot list metadata for stdin");
- }
- }
- return Compilation::Stop;
- }
-
- Compilation::Continue
-}
-
-fn print_crate_info(
- codegen_backend: &dyn CodegenBackend,
- sess: &Session,
- parse_attrs: bool,
-) -> Compilation {
- use rustc_session::config::PrintRequest::*;
- // NativeStaticLibs and LinkArgs are special - printed during linking
- // (empty iterator returns true)
- if sess.opts.prints.iter().all(|&p| p == NativeStaticLibs || p == LinkArgs) {
- return Compilation::Continue;
- }
-
- let attrs = if parse_attrs {
- let result = parse_crate_attrs(sess);
- match result {
- Ok(attrs) => Some(attrs),
- Err(mut parse_error) => {
- parse_error.emit();
- return Compilation::Stop;
- }
- }
- } else {
- None
- };
- for req in &sess.opts.prints {
- match *req {
- TargetList => {
- let mut targets = rustc_target::spec::TARGETS.to_vec();
- targets.sort_unstable();
- println!("{}", targets.join("\n"));
- }
- Sysroot => println!("{}", sess.sysroot.display()),
- TargetLibdir => println!("{}", sess.target_tlib_path.dir.display()),
- TargetSpec => {
- println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap());
- }
- FileNames | CrateName => {
- let attrs = attrs.as_ref().unwrap();
- let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess);
- let id = rustc_session::output::find_crate_name(sess, attrs);
- if *req == PrintRequest::CrateName {
- println!("{id}");
- continue;
- }
- let crate_types = collect_crate_types(sess, attrs);
- for &style in &crate_types {
- let fname =
- rustc_session::output::filename_for_input(sess, style, id, &t_outputs);
- println!("{}", fname.file_name().unwrap().to_string_lossy());
- }
- }
- Cfg => {
- let mut cfgs = sess
- .parse_sess
- .config
- .iter()
- .filter_map(|&(name, value)| {
- // Note that crt-static is a specially recognized cfg
- // directive that's printed out here as part of
- // rust-lang/rust#37406, but in general the
- // `target_feature` cfg is gated under
- // rust-lang/rust#29717. For now this is just
- // specifically allowing the crt-static cfg and that's
- // it, this is intended to get into Cargo and then go
- // through to build scripts.
- if (name != sym::target_feature || value != Some(sym::crt_dash_static))
- && !sess.is_nightly_build()
- && find_gated_cfg(|cfg_sym| cfg_sym == name).is_some()
- {
- return None;
- }
-
- if let Some(value) = value {
- Some(format!("{name}=\"{value}\""))
- } else {
- Some(name.to_string())
- }
- })
- .collect::<Vec<String>>();
-
- cfgs.sort();
- for cfg in cfgs {
- println!("{cfg}");
- }
- }
- CallingConventions => {
- let mut calling_conventions = rustc_target::spec::abi::all_names();
- calling_conventions.sort_unstable();
- println!("{}", calling_conventions.join("\n"));
- }
- RelocationModels
- | CodeModels
- | TlsModels
- | TargetCPUs
- | StackProtectorStrategies
- | TargetFeatures => {
- codegen_backend.print(*req, sess);
- }
- // Any output here interferes with Cargo's parsing of other printed output
- NativeStaticLibs => {}
- LinkArgs => {}
- SplitDebuginfo => {
- use rustc_target::spec::SplitDebuginfo::{Off, Packed, Unpacked};
-
- for split in &[Off, Packed, Unpacked] {
- let stable = sess.target.options.supported_split_debuginfo.contains(split);
- let unstable_ok = sess.unstable_options();
- if stable || unstable_ok {
- println!("{split}");
- }
- }
- }
- }
- }
- Compilation::Stop
-}
-
-/// Prints version information
-///
-/// NOTE: this is a macro to support drivers built at a different time than the main `rustc_driver` crate.
-pub macro version($binary: literal, $matches: expr) {
- fn unw(x: Option<&str>) -> &str {
- x.unwrap_or("unknown")
- }
- $crate::version_at_macro_invocation(
- $binary,
- $matches,
- unw(option_env!("CFG_VERSION")),
- unw(option_env!("CFG_VER_HASH")),
- unw(option_env!("CFG_VER_DATE")),
- unw(option_env!("CFG_RELEASE")),
- )
-}
-
-#[doc(hidden)] // use the macro instead
-pub fn version_at_macro_invocation(
- binary: &str,
- matches: &getopts::Matches,
- version: &str,
- commit_hash: &str,
- commit_date: &str,
- release: &str,
-) {
- let verbose = matches.opt_present("verbose");
-
- println!("{binary} {version}");
-
- if verbose {
- println!("binary: {binary}");
- println!("commit-hash: {commit_hash}");
- println!("commit-date: {commit_date}");
- println!("host: {}", config::host_triple());
- println!("release: {release}");
-
- let debug_flags = matches.opt_strs("Z");
- let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
- get_codegen_backend(&None, backend_name).print_version();
- }
-}
-
-fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) {
- let groups = if verbose { config::rustc_optgroups() } else { config::rustc_short_optgroups() };
- let mut options = getopts::Options::new();
- for option in groups.iter().filter(|x| include_unstable_options || x.is_stable()) {
- (option.apply)(&mut options);
- }
- let message = "Usage: rustc [OPTIONS] INPUT";
- let nightly_help = if nightly_build {
- "\n -Z help Print unstable compiler options"
- } else {
- ""
- };
- let verbose_help = if verbose {
- ""
- } else {
- "\n --help -v Print the full set of options rustc accepts"
- };
- let at_path = if verbose {
- " @path Read newline separated options from `path`\n"
- } else {
- ""
- };
- println!(
- "{options}{at_path}\nAdditional help:
- -C help Print codegen options
- -W help \
- Print 'lint' options and default settings{nightly}{verbose}\n",
- options = options.usage(message),
- at_path = at_path,
- nightly = nightly_help,
- verbose = verbose_help
- );
-}
-
-fn print_wall_help() {
- println!(
- "
-The flag `-Wall` does not exist in `rustc`. Most useful lints are enabled by
-default. Use `rustc -W help` to see all available lints. It's more common to put
-warning settings in the crate root using `#![warn(LINT_NAME)]` instead of using
-the command line flag directly.
-"
- );
-}
-
-/// Write to stdout lint command options, together with a list of all available lints
-pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) {
- println!(
- "
-Available lint options:
- -W <foo> Warn about <foo>
- -A <foo> \
- Allow <foo>
- -D <foo> Deny <foo>
- -F <foo> Forbid <foo> \
- (deny <foo> and all attempts to override)
-
-"
- );
-
- fn sort_lints(sess: &Session, mut lints: Vec<&'static Lint>) -> Vec<&'static Lint> {
- // The sort doesn't case-fold but it's doubtful we care.
- lints.sort_by_cached_key(|x: &&Lint| (x.default_level(sess.edition()), x.name));
- lints
- }
-
- fn sort_lint_groups(
- lints: Vec<(&'static str, Vec<LintId>, bool)>,
- ) -> Vec<(&'static str, Vec<LintId>)> {
- let mut lints: Vec<_> = lints.into_iter().map(|(x, y, _)| (x, y)).collect();
- lints.sort_by_key(|l| l.0);
- lints
- }
-
- let (plugin, builtin): (Vec<_>, _) =
- lint_store.get_lints().iter().cloned().partition(|&lint| lint.is_plugin);
- let plugin = sort_lints(sess, plugin);
- let builtin = sort_lints(sess, builtin);
-
- let (plugin_groups, builtin_groups): (Vec<_>, _) =
- lint_store.get_lint_groups().partition(|&(.., p)| p);
- let plugin_groups = sort_lint_groups(plugin_groups);
- let builtin_groups = sort_lint_groups(builtin_groups);
-
- let max_name_len =
- plugin.iter().chain(&builtin).map(|&s| s.name.chars().count()).max().unwrap_or(0);
- let padded = |x: &str| {
- let mut s = " ".repeat(max_name_len - x.chars().count());
- s.push_str(x);
- s
- };
-
- println!("Lint checks provided by rustc:\n");
-
- let print_lints = |lints: Vec<&Lint>| {
- println!(" {} {:7.7} {}", padded("name"), "default", "meaning");
- println!(" {} {:7.7} {}", padded("----"), "-------", "-------");
- for lint in lints {
- let name = lint.name_lower().replace('_', "-");
- println!(
- " {} {:7.7} {}",
- padded(&name),
- lint.default_level(sess.edition()).as_str(),
- lint.desc
- );
- }
- println!("\n");
- };
-
- print_lints(builtin);
-
- let max_name_len = max(
- "warnings".len(),
- plugin_groups
- .iter()
- .chain(&builtin_groups)
- .map(|&(s, _)| s.chars().count())
- .max()
- .unwrap_or(0),
- );
-
- let padded = |x: &str| {
- let mut s = " ".repeat(max_name_len - x.chars().count());
- s.push_str(x);
- s
- };
-
- println!("Lint groups provided by rustc:\n");
-
- let print_lint_groups = |lints: Vec<(&'static str, Vec<LintId>)>, all_warnings| {
- println!(" {} sub-lints", padded("name"));
- println!(" {} ---------", padded("----"));
-
- if all_warnings {
- println!(" {} all lints that are set to issue warnings", padded("warnings"));
- }
-
- for (name, to) in lints {
- let name = name.to_lowercase().replace('_', "-");
- let desc = to
- .into_iter()
- .map(|x| x.to_string().replace('_', "-"))
- .collect::<Vec<String>>()
- .join(", ");
- println!(" {} {}", padded(&name), desc);
- }
- println!("\n");
- };
-
- print_lint_groups(builtin_groups, true);
-
- match (loaded_plugins, plugin.len(), plugin_groups.len()) {
- (false, 0, _) | (false, _, 0) => {
- println!("Lint tools like Clippy can provide additional lints and lint groups.");
- }
- (false, ..) => panic!("didn't load lint plugins but got them anyway!"),
- (true, 0, 0) => println!("This crate does not load any lint plugins or lint groups."),
- (true, l, g) => {
- if l > 0 {
- println!("Lint checks provided by plugins loaded by this crate:\n");
- print_lints(plugin);
- }
- if g > 0 {
- println!("Lint groups provided by plugins loaded by this crate:\n");
- print_lint_groups(plugin_groups, false);
- }
- }
- }
-}
-
-fn describe_debug_flags() {
- println!("\nAvailable options:\n");
- print_flag_list("-Z", config::Z_OPTIONS);
-}
-
-fn describe_codegen_flags() {
- println!("\nAvailable codegen options:\n");
- print_flag_list("-C", config::CG_OPTIONS);
-}
-
-pub fn print_flag_list<T>(
- cmdline_opt: &str,
- flag_list: &[(&'static str, T, &'static str, &'static str)],
-) {
- let max_len = flag_list.iter().map(|&(name, _, _, _)| name.chars().count()).max().unwrap_or(0);
-
- for &(name, _, _, desc) in flag_list {
- println!(
- " {} {:>width$}=val -- {}",
- cmdline_opt,
- name.replace('_', "-"),
- desc,
- width = max_len
- );
- }
-}
-
-/// Process command line options. Emits messages as appropriate. If compilation
-/// should continue, returns a getopts::Matches object parsed from args,
-/// otherwise returns `None`.
-///
-/// The compiler's handling of options is a little complicated as it ties into
-/// our stability story. The current intention of each compiler option is to
-/// have one of two modes:
-///
-/// 1. An option is stable and can be used everywhere.
-/// 2. An option is unstable, and can only be used on nightly.
-///
-/// Like unstable library and language features, however, unstable options have
-/// always required a form of "opt in" to indicate that you're using them. This
-/// provides the easy ability to scan a code base to check to see if anything
-/// unstable is being used. Currently, this "opt in" is the `-Z` "zed" flag.
-///
-/// All options behind `-Z` are considered unstable by default. Other top-level
-/// options can also be considered unstable, and they were unlocked through the
-/// `-Z unstable-options` flag. Note that `-Z` remains to be the root of
-/// instability in both cases, though.
-///
-/// So with all that in mind, the comments below have some more detail about the
-/// contortions done here to get things to work out correctly.
-pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
- // Throw away the first argument, the name of the binary
- let args = &args[1..];
-
- if args.is_empty() {
- // user did not write `-v` nor `-Z unstable-options`, so do not
- // include that extra information.
- let nightly_build =
- rustc_feature::UnstableFeatures::from_environment(None).is_nightly_build();
- usage(false, false, nightly_build);
- return None;
- }
-
- // Parse with *all* options defined in the compiler, we don't worry about
- // option stability here we just want to parse as much as possible.
- let mut options = getopts::Options::new();
- for option in config::rustc_optgroups() {
- (option.apply)(&mut options);
- }
- let matches = options.parse(args).unwrap_or_else(|e| {
- let msg = match e {
- getopts::Fail::UnrecognizedOption(ref opt) => CG_OPTIONS
- .iter()
- .map(|&(name, ..)| ('C', name))
- .chain(Z_OPTIONS.iter().map(|&(name, ..)| ('Z', name)))
- .find(|&(_, name)| *opt == name.replace('_', "-"))
- .map(|(flag, _)| format!("{e}. Did you mean `-{flag} {opt}`?")),
- _ => None,
- };
- early_error(ErrorOutputType::default(), &msg.unwrap_or_else(|| e.to_string()));
- });
-
- // For all options we just parsed, we check a few aspects:
- //
- // * If the option is stable, we're all good
- // * If the option wasn't passed, we're all good
- // * If `-Z unstable-options` wasn't passed (and we're not a -Z option
- // ourselves), then we require the `-Z unstable-options` flag to unlock
- // this option that was passed.
- // * If we're a nightly compiler, then unstable options are now unlocked, so
- // we're good to go.
- // * Otherwise, if we're an unstable option then we generate an error
- // (unstable option being used on stable)
- nightly_options::check_nightly_options(&matches, &config::rustc_optgroups());
-
- if matches.opt_present("h") || matches.opt_present("help") {
- // Only show unstable options in --help if we accept unstable options.
- let unstable_enabled = nightly_options::is_unstable_enabled(&matches);
- let nightly_build = nightly_options::match_is_nightly_build(&matches);
- usage(matches.opt_present("verbose"), unstable_enabled, nightly_build);
- return None;
- }
-
- // Handle the special case of -Wall.
- let wall = matches.opt_strs("W");
- if wall.iter().any(|x| *x == "all") {
- print_wall_help();
- rustc_errors::FatalError.raise();
- }
-
- // Don't handle -W help here, because we might first load plugins.
- let debug_flags = matches.opt_strs("Z");
- if debug_flags.iter().any(|x| *x == "help") {
- describe_debug_flags();
- return None;
- }
-
- let cg_flags = matches.opt_strs("C");
-
- if cg_flags.iter().any(|x| *x == "help") {
- describe_codegen_flags();
- return None;
- }
-
- if cg_flags.iter().any(|x| *x == "no-stack-check") {
- early_warn(
- ErrorOutputType::default(),
- "the --no-stack-check flag is deprecated and does nothing",
- );
- }
-
- if cg_flags.iter().any(|x| *x == "passes=list") {
- let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
- get_codegen_backend(&None, backend_name).print_passes();
- return None;
- }
-
- if matches.opt_present("version") {
- version!("rustc", &matches);
- return None;
- }
-
- Some(matches)
-}
-
-fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> {
- match &sess.io.input {
- Input::File(ifile) => rustc_parse::parse_crate_attrs_from_file(ifile, &sess.parse_sess),
- Input::Str { name, input } => rustc_parse::parse_crate_attrs_from_source_str(
- name.clone(),
- input.clone(),
- &sess.parse_sess,
- ),
- }
-}
-
-/// Gets a list of extra command-line flags provided by the user, as strings.
-///
-/// This function is used during ICEs to show more information useful for
-/// debugging, since some ICEs only happens with non-default compiler flags
-/// (and the users don't always report them).
-fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
- let mut args = env::args_os().map(|arg| arg.to_string_lossy().to_string()).peekable();
-
- let mut result = Vec::new();
- let mut excluded_cargo_defaults = false;
- while let Some(arg) = args.next() {
- if let Some(a) = ICE_REPORT_COMPILER_FLAGS.iter().find(|a| arg.starts_with(*a)) {
- let content = if arg.len() == a.len() {
- // A space-separated option, like `-C incremental=foo` or `--crate-type rlib`
- match args.next() {
- Some(arg) => arg.to_string(),
- None => continue,
- }
- } else if arg.get(a.len()..a.len() + 1) == Some("=") {
- // An equals option, like `--crate-type=rlib`
- arg[a.len() + 1..].to_string()
- } else {
- // A non-space option, like `-Cincremental=foo`
- arg[a.len()..].to_string()
- };
- let option = content.split_once('=').map(|s| s.0).unwrap_or(&content);
- if ICE_REPORT_COMPILER_FLAGS_EXCLUDE.iter().any(|exc| option == *exc) {
- excluded_cargo_defaults = true;
- } else {
- result.push(a.to_string());
- match ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.iter().find(|s| option == **s) {
- Some(s) => result.push(format!("{s}=[REDACTED]")),
- None => result.push(content),
- }
- }
- }
- }
-
- if !result.is_empty() { Some((result, excluded_cargo_defaults)) } else { None }
-}
-
-/// Runs a closure and catches unwinds triggered by fatal errors.
-///
-/// The compiler currently unwinds with a special sentinel value to abort
-/// compilation on fatal errors. This function catches that sentinel and turns
-/// the panic into a `Result` instead.
-pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorGuaranteed> {
- catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| {
- if value.is::<rustc_errors::FatalErrorMarker>() {
- ErrorGuaranteed::unchecked_claim_error_was_emitted()
- } else {
- panic::resume_unwind(value);
- }
- })
-}
-
-/// Variant of `catch_fatal_errors` for the `interface::Result` return type
-/// that also computes the exit code.
-pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 {
- let result = catch_fatal_errors(f).and_then(|result| result);
- match result {
- Ok(()) => EXIT_SUCCESS,
- Err(_) => EXIT_FAILURE,
- }
-}
-
-static DEFAULT_HOOK: LazyLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
- LazyLock::new(|| {
- let hook = panic::take_hook();
- panic::set_hook(Box::new(|info| {
- // If the error was caused by a broken pipe then this is not a bug.
- // Write the error and return immediately. See #98700.
- #[cfg(windows)]
- if let Some(msg) = info.payload().downcast_ref::<String>() {
- if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)")
- {
- early_error_no_abort(ErrorOutputType::default(), &msg);
- return;
- }
- };
-
- // Invoke the default handler, which prints the actual panic message and optionally a backtrace
- // Don't do this for delayed bugs, which already emit their own more useful backtrace.
- if !info.payload().is::<rustc_errors::DelayedBugPanic>() {
- (*DEFAULT_HOOK)(info);
-
- // Separate the output with an empty line
- eprintln!();
- }
-
- // Print the ICE message
- report_ice(info, BUG_REPORT_URL);
- }));
- hook
- });
-
-/// Prints the ICE message, including query stack, but without backtrace.
-///
-/// The message will point the user at `bug_report_url` to report the ICE.
-///
-/// When `install_ice_hook` is called, this function will be called as the panic
-/// hook.
-pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
- let fallback_bundle =
- rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
- let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
- rustc_errors::ColorConfig::Auto,
- None,
- None,
- fallback_bundle,
- false,
- false,
- None,
- false,
- false,
- ));
- let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
-
- // a .span_bug or .bug call has already printed what
- // it wants to print.
- if !info.payload().is::<rustc_errors::ExplicitBug>()
- && !info.payload().is::<rustc_errors::DelayedBugPanic>()
- {
- let mut d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic");
- handler.emit_diagnostic(&mut d);
- }
-
- let mut xs: Vec<Cow<'static, str>> = vec![
- "the compiler unexpectedly panicked. this is a bug.".into(),
- format!("we would appreciate a bug report: {bug_report_url}").into(),
- format!(
- "rustc {} running on {}",
- util::version_str!().unwrap_or("unknown_version"),
- config::host_triple()
- )
- .into(),
- ];
-
- if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() {
- xs.push(format!("compiler flags: {}", flags.join(" ")).into());
-
- if excluded_cargo_defaults {
- xs.push("some of the compiler flags provided by cargo are hidden".into());
- }
- }
-
- for note in &xs {
- handler.note_without_error(note.as_ref());
- }
-
- // If backtraces are enabled, also print the query stack
- let backtrace = env::var_os("RUST_BACKTRACE").map_or(false, |x| &x != "0");
-
- let num_frames = if backtrace { None } else { Some(2) };
-
- interface::try_print_query_stack(&handler, num_frames);
-
- #[cfg(windows)]
- unsafe {
- if env::var("RUSTC_BREAK_ON_ICE").is_ok() {
- // Trigger a debugger if we crashed during bootstrap
- winapi::um::debugapi::DebugBreak();
- }
- }
-}
-
-/// Installs a panic hook that will print the ICE message on unexpected panics.
-///
-/// A custom rustc driver can skip calling this to set up a custom ICE hook.
-pub fn install_ice_hook() {
- // If the user has not explicitly overridden "RUST_BACKTRACE", then produce
- // full backtraces. When a compiler ICE happens, we want to gather
- // as much information as possible to present in the issue opened
- // by the user. Compiler developers and other rustc users can
- // opt in to less-verbose backtraces by manually setting "RUST_BACKTRACE"
- // (e.g. `RUST_BACKTRACE=1`)
- if std::env::var("RUST_BACKTRACE").is_err() {
- std::env::set_var("RUST_BACKTRACE", "full");
- }
- LazyLock::force(&DEFAULT_HOOK);
-}
-
-/// This allows tools to enable rust logging without having to magically match rustc's
-/// tracing crate version.
-pub fn init_rustc_env_logger() {
- init_rustc_env_logger_with_backtrace_option(&None);
-}
-
-/// This allows tools to enable rust logging without having to magically match rustc's
-/// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to
-/// choose a target module you wish to show backtraces along with its logging.
-pub fn init_rustc_env_logger_with_backtrace_option(backtrace_target: &Option<String>) {
- if let Err(error) = rustc_log::init_rustc_env_logger_with_backtrace_option(backtrace_target) {
- early_error(ErrorOutputType::default(), &error.to_string());
- }
-}
-
-/// This allows tools to enable rust logging without having to magically match rustc's
-/// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to choose an env var
-/// other than `RUSTC_LOG`.
-pub fn init_env_logger(env: &str) {
- if let Err(error) = rustc_log::init_env_logger(env) {
- early_error(ErrorOutputType::default(), &error.to_string());
- }
-}
-
-#[cfg(all(unix, any(target_env = "gnu", target_os = "macos")))]
-mod signal_handler {
- extern "C" {
- fn backtrace_symbols_fd(
- buffer: *const *mut libc::c_void,
- size: libc::c_int,
- fd: libc::c_int,
- );
- }
-
- extern "C" fn print_stack_trace(_: libc::c_int) {
- const MAX_FRAMES: usize = 256;
- static mut STACK_TRACE: [*mut libc::c_void; MAX_FRAMES] =
- [std::ptr::null_mut(); MAX_FRAMES];
- unsafe {
- let depth = libc::backtrace(STACK_TRACE.as_mut_ptr(), MAX_FRAMES as i32);
- if depth == 0 {
- return;
- }
- backtrace_symbols_fd(STACK_TRACE.as_ptr(), depth, 2);
- }
- }
-
- /// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the
- /// process, print a stack trace and then exit.
- pub(super) fn install() {
- unsafe {
- const ALT_STACK_SIZE: usize = libc::MINSIGSTKSZ + 64 * 1024;
- let mut alt_stack: libc::stack_t = std::mem::zeroed();
- alt_stack.ss_sp =
- std::alloc::alloc(std::alloc::Layout::from_size_align(ALT_STACK_SIZE, 1).unwrap())
- as *mut libc::c_void;
- alt_stack.ss_size = ALT_STACK_SIZE;
- libc::sigaltstack(&alt_stack, std::ptr::null_mut());
-
- let mut sa: libc::sigaction = std::mem::zeroed();
- sa.sa_sigaction = print_stack_trace as libc::sighandler_t;
- sa.sa_flags = libc::SA_NODEFER | libc::SA_RESETHAND | libc::SA_ONSTACK;
- libc::sigemptyset(&mut sa.sa_mask);
- libc::sigaction(libc::SIGSEGV, &sa, std::ptr::null_mut());
- }
- }
-}
-
-#[cfg(not(all(unix, any(target_env = "gnu", target_os = "macos"))))]
-mod signal_handler {
- pub(super) fn install() {}
-}
-
-pub fn main() -> ! {
- let start_time = Instant::now();
- let start_rss = get_resident_set_size();
- signal_handler::install();
- let mut callbacks = TimePassesCallbacks::default();
- install_ice_hook();
- let exit_code = catch_with_exit_code(|| {
- let args = env::args_os()
- .enumerate()
- .map(|(i, arg)| {
- arg.into_string().unwrap_or_else(|arg| {
- early_error(
- ErrorOutputType::default(),
- &format!("argument {i} is not valid Unicode: {arg:?}"),
- )
- })
- })
- .collect::<Vec<_>>();
- RunCompiler::new(&args, &mut callbacks).run()
- });
-
- if callbacks.time_passes {
- let end_rss = get_resident_set_size();
- print_time_passes_entry("total", start_time.elapsed(), start_rss, end_rss);
- }
-
- process::exit(exit_code)
-}
+pub use rustc_driver_impl::*;
+++ /dev/null
-//! The various pretty-printing routines.
-
-use crate::session_diagnostics::UnprettyDumpFail;
-use rustc_ast as ast;
-use rustc_ast_pretty::pprust;
-use rustc_errors::ErrorGuaranteed;
-use rustc_hir as hir;
-use rustc_hir_pretty as pprust_hir;
-use rustc_middle::hir::map as hir_map;
-use rustc_middle::mir::{write_mir_graphviz, write_mir_pretty};
-use rustc_middle::ty::{self, TyCtxt};
-use rustc_session::config::{PpAstTreeMode, PpHirMode, PpMode, PpSourceMode};
-use rustc_session::Session;
-use rustc_span::symbol::Ident;
-use rustc_span::FileName;
-
-use std::cell::Cell;
-use std::fmt::Write;
-
-pub use self::PpMode::*;
-pub use self::PpSourceMode::*;
-use crate::abort_on_err;
-
-// This slightly awkward construction is to allow for each PpMode to
-// choose whether it needs to do analyses (which can consume the
-// Session) and then pass through the session (now attached to the
-// analysis results) on to the chosen pretty-printer, along with the
-// `&PpAnn` object.
-//
-// Note that since the `&PrinterSupport` is freshly constructed on each
-// call, it would not make sense to try to attach the lifetime of `self`
-// to the lifetime of the `&PrinterObject`.
-
-/// Constructs a `PrinterSupport` object and passes it to `f`.
-fn call_with_pp_support<'tcx, A, F>(
- ppmode: &PpSourceMode,
- sess: &'tcx Session,
- tcx: Option<TyCtxt<'tcx>>,
- f: F,
-) -> A
-where
- F: FnOnce(&dyn PrinterSupport) -> A,
-{
- match *ppmode {
- Normal | Expanded => {
- let annotation = NoAnn { sess, tcx };
- f(&annotation)
- }
-
- Identified | ExpandedIdentified => {
- let annotation = IdentifiedAnnotation { sess, tcx };
- f(&annotation)
- }
- ExpandedHygiene => {
- let annotation = HygieneAnnotation { sess };
- f(&annotation)
- }
- }
-}
-fn call_with_pp_support_hir<A, F>(ppmode: &PpHirMode, tcx: TyCtxt<'_>, f: F) -> A
-where
- F: FnOnce(&dyn HirPrinterSupport<'_>, hir_map::Map<'_>) -> A,
-{
- match *ppmode {
- PpHirMode::Normal => {
- let annotation = NoAnn { sess: tcx.sess, tcx: Some(tcx) };
- f(&annotation, tcx.hir())
- }
-
- PpHirMode::Identified => {
- let annotation = IdentifiedAnnotation { sess: tcx.sess, tcx: Some(tcx) };
- f(&annotation, tcx.hir())
- }
- PpHirMode::Typed => {
- abort_on_err(tcx.analysis(()), tcx.sess);
-
- let annotation = TypedAnnotation { tcx, maybe_typeck_results: Cell::new(None) };
- tcx.dep_graph.with_ignore(|| f(&annotation, tcx.hir()))
- }
- }
-}
-
-trait PrinterSupport: pprust::PpAnn {
- /// Provides a uniform interface for re-extracting a reference to a
- /// `Session` from a value that now owns it.
- fn sess(&self) -> &Session;
-
- /// Produces the pretty-print annotation object.
- ///
- /// (Rust does not yet support upcasting from a trait object to
- /// an object for one of its supertraits.)
- fn pp_ann(&self) -> &dyn pprust::PpAnn;
-}
-
-trait HirPrinterSupport<'hir>: pprust_hir::PpAnn {
- /// Provides a uniform interface for re-extracting a reference to a
- /// `Session` from a value that now owns it.
- fn sess(&self) -> &Session;
-
- /// Provides a uniform interface for re-extracting a reference to an
- /// `hir_map::Map` from a value that now owns it.
- fn hir_map(&self) -> Option<hir_map::Map<'hir>>;
-
- /// Produces the pretty-print annotation object.
- ///
- /// (Rust does not yet support upcasting from a trait object to
- /// an object for one of its supertraits.)
- fn pp_ann(&self) -> &dyn pprust_hir::PpAnn;
-}
-
-struct NoAnn<'hir> {
- sess: &'hir Session,
- tcx: Option<TyCtxt<'hir>>,
-}
-
-impl<'hir> PrinterSupport for NoAnn<'hir> {
- fn sess(&self) -> &Session {
- self.sess
- }
-
- fn pp_ann(&self) -> &dyn pprust::PpAnn {
- self
- }
-}
-
-impl<'hir> HirPrinterSupport<'hir> for NoAnn<'hir> {
- fn sess(&self) -> &Session {
- self.sess
- }
-
- fn hir_map(&self) -> Option<hir_map::Map<'hir>> {
- self.tcx.map(|tcx| tcx.hir())
- }
-
- fn pp_ann(&self) -> &dyn pprust_hir::PpAnn {
- self
- }
-}
-
-impl<'hir> pprust::PpAnn for NoAnn<'hir> {}
-impl<'hir> pprust_hir::PpAnn for NoAnn<'hir> {
- fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
- if let Some(tcx) = self.tcx {
- pprust_hir::PpAnn::nested(&(&tcx.hir() as &dyn hir::intravisit::Map<'_>), state, nested)
- }
- }
-}
-
-struct IdentifiedAnnotation<'hir> {
- sess: &'hir Session,
- tcx: Option<TyCtxt<'hir>>,
-}
-
-impl<'hir> PrinterSupport for IdentifiedAnnotation<'hir> {
- fn sess(&self) -> &Session {
- self.sess
- }
-
- fn pp_ann(&self) -> &dyn pprust::PpAnn {
- self
- }
-}
-
-impl<'hir> pprust::PpAnn for IdentifiedAnnotation<'hir> {
- fn pre(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
- if let pprust::AnnNode::Expr(_) = node {
- s.popen();
- }
- }
- fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
- match node {
- pprust::AnnNode::Crate(_) | pprust::AnnNode::Ident(_) | pprust::AnnNode::Name(_) => {}
-
- pprust::AnnNode::Item(item) => {
- s.s.space();
- s.synth_comment(item.id.to_string())
- }
- pprust::AnnNode::SubItem(id) => {
- s.s.space();
- s.synth_comment(id.to_string())
- }
- pprust::AnnNode::Block(blk) => {
- s.s.space();
- s.synth_comment(format!("block {}", blk.id))
- }
- pprust::AnnNode::Expr(expr) => {
- s.s.space();
- s.synth_comment(expr.id.to_string());
- s.pclose()
- }
- pprust::AnnNode::Pat(pat) => {
- s.s.space();
- s.synth_comment(format!("pat {}", pat.id));
- }
- }
- }
-}
-
-impl<'hir> HirPrinterSupport<'hir> for IdentifiedAnnotation<'hir> {
- fn sess(&self) -> &Session {
- self.sess
- }
-
- fn hir_map(&self) -> Option<hir_map::Map<'hir>> {
- self.tcx.map(|tcx| tcx.hir())
- }
-
- fn pp_ann(&self) -> &dyn pprust_hir::PpAnn {
- self
- }
-}
-
-impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> {
- fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
- if let Some(ref tcx) = self.tcx {
- pprust_hir::PpAnn::nested(&(&tcx.hir() as &dyn hir::intravisit::Map<'_>), state, nested)
- }
- }
- fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
- if let pprust_hir::AnnNode::Expr(_) = node {
- s.popen();
- }
- }
- fn post(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
- match node {
- pprust_hir::AnnNode::Name(_) => {}
- pprust_hir::AnnNode::Item(item) => {
- s.s.space();
- s.synth_comment(format!("hir_id: {}", item.hir_id()));
- }
- pprust_hir::AnnNode::SubItem(id) => {
- s.s.space();
- s.synth_comment(id.to_string());
- }
- pprust_hir::AnnNode::Block(blk) => {
- s.s.space();
- s.synth_comment(format!("block hir_id: {}", blk.hir_id));
- }
- pprust_hir::AnnNode::Expr(expr) => {
- s.s.space();
- s.synth_comment(format!("expr hir_id: {}", expr.hir_id));
- s.pclose();
- }
- pprust_hir::AnnNode::Pat(pat) => {
- s.s.space();
- s.synth_comment(format!("pat hir_id: {}", pat.hir_id));
- }
- pprust_hir::AnnNode::Arm(arm) => {
- s.s.space();
- s.synth_comment(format!("arm hir_id: {}", arm.hir_id));
- }
- }
- }
-}
-
-struct HygieneAnnotation<'a> {
- sess: &'a Session,
-}
-
-impl<'a> PrinterSupport for HygieneAnnotation<'a> {
- fn sess(&self) -> &Session {
- self.sess
- }
-
- fn pp_ann(&self) -> &dyn pprust::PpAnn {
- self
- }
-}
-
-impl<'a> pprust::PpAnn for HygieneAnnotation<'a> {
- fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
- match node {
- pprust::AnnNode::Ident(&Ident { name, span }) => {
- s.s.space();
- s.synth_comment(format!("{}{:?}", name.as_u32(), span.ctxt()))
- }
- pprust::AnnNode::Name(&name) => {
- s.s.space();
- s.synth_comment(name.as_u32().to_string())
- }
- pprust::AnnNode::Crate(_) => {
- s.s.hardbreak();
- let verbose = self.sess.verbose();
- s.synth_comment(rustc_span::hygiene::debug_hygiene_data(verbose));
- s.s.hardbreak_if_not_bol();
- }
- _ => {}
- }
- }
-}
-
-struct TypedAnnotation<'tcx> {
- tcx: TyCtxt<'tcx>,
- maybe_typeck_results: Cell<Option<&'tcx ty::TypeckResults<'tcx>>>,
-}
-
-impl<'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'tcx> {
- fn sess(&self) -> &Session {
- self.tcx.sess
- }
-
- fn hir_map(&self) -> Option<hir_map::Map<'tcx>> {
- Some(self.tcx.hir())
- }
-
- fn pp_ann(&self) -> &dyn pprust_hir::PpAnn {
- self
- }
-}
-
-impl<'tcx> pprust_hir::PpAnn for TypedAnnotation<'tcx> {
- fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
- let old_maybe_typeck_results = self.maybe_typeck_results.get();
- if let pprust_hir::Nested::Body(id) = nested {
- self.maybe_typeck_results.set(Some(self.tcx.typeck_body(id)));
- }
- let pp_ann = &(&self.tcx.hir() as &dyn hir::intravisit::Map<'_>);
- pprust_hir::PpAnn::nested(pp_ann, state, nested);
- self.maybe_typeck_results.set(old_maybe_typeck_results);
- }
- fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
- if let pprust_hir::AnnNode::Expr(_) = node {
- s.popen();
- }
- }
- fn post(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
- if let pprust_hir::AnnNode::Expr(expr) = node {
- let typeck_results = self.maybe_typeck_results.get().or_else(|| {
- self.tcx
- .hir()
- .maybe_body_owned_by(expr.hir_id.owner.def_id)
- .map(|body_id| self.tcx.typeck_body(body_id))
- });
-
- if let Some(typeck_results) = typeck_results {
- s.s.space();
- s.s.word("as");
- s.s.space();
- s.s.word(typeck_results.expr_ty(expr).to_string());
- }
-
- s.pclose();
- }
- }
-}
-
-fn get_source(sess: &Session) -> (String, FileName) {
- let src_name = sess.io.input.source_name();
- let src = String::clone(
- sess.source_map()
- .get_source_file(&src_name)
- .expect("get_source_file")
- .src
- .as_ref()
- .expect("src"),
- );
- (src, src_name)
-}
-
-fn write_or_print(out: &str, sess: &Session) {
- match &sess.io.output_file {
- None => print!("{out}"),
- Some(p) => {
- if let Err(e) = std::fs::write(p, out) {
- sess.emit_fatal(UnprettyDumpFail {
- path: p.display().to_string(),
- err: e.to_string(),
- });
- }
- }
- }
-}
-
-pub fn print_after_parsing(sess: &Session, krate: &ast::Crate, ppm: PpMode) {
- let (src, src_name) = get_source(sess);
-
- let out = match ppm {
- Source(s) => {
- // Silently ignores an identified node.
- call_with_pp_support(&s, sess, None, move |annotation| {
- debug!("pretty printing source code {:?}", s);
- let sess = annotation.sess();
- let parse = &sess.parse_sess;
- pprust::print_crate(
- sess.source_map(),
- krate,
- src_name,
- src,
- annotation.pp_ann(),
- false,
- parse.edition,
- &sess.parse_sess.attr_id_generator,
- )
- })
- }
- AstTree(PpAstTreeMode::Normal) => {
- debug!("pretty printing AST tree");
- format!("{krate:#?}")
- }
- _ => unreachable!(),
- };
-
- write_or_print(&out, sess);
-}
-
-pub fn print_after_hir_lowering<'tcx>(tcx: TyCtxt<'tcx>, ppm: PpMode) {
- if ppm.needs_analysis() {
- abort_on_err(print_with_analysis(tcx, ppm), tcx.sess);
- return;
- }
-
- let (src, src_name) = get_source(tcx.sess);
-
- let out = match ppm {
- Source(s) => {
- // Silently ignores an identified node.
- call_with_pp_support(&s, tcx.sess, Some(tcx), move |annotation| {
- debug!("pretty printing source code {:?}", s);
- let sess = annotation.sess();
- let parse = &sess.parse_sess;
- pprust::print_crate(
- sess.source_map(),
- &tcx.resolver_for_lowering(()).borrow().1,
- src_name,
- src,
- annotation.pp_ann(),
- true,
- parse.edition,
- &sess.parse_sess.attr_id_generator,
- )
- })
- }
-
- AstTree(PpAstTreeMode::Expanded) => {
- debug!("pretty-printing expanded AST");
- format!("{:#?}", tcx.resolver_for_lowering(()).borrow().1)
- }
-
- Hir(s) => call_with_pp_support_hir(&s, tcx, move |annotation, hir_map| {
- debug!("pretty printing HIR {:?}", s);
- let sess = annotation.sess();
- let sm = sess.source_map();
- let attrs = |id| hir_map.attrs(id);
- pprust_hir::print_crate(
- sm,
- hir_map.root_module(),
- src_name,
- src,
- &attrs,
- annotation.pp_ann(),
- )
- }),
-
- HirTree => {
- call_with_pp_support_hir(&PpHirMode::Normal, tcx, move |_annotation, hir_map| {
- debug!("pretty printing HIR tree");
- format!("{:#?}", hir_map.krate())
- })
- }
-
- _ => unreachable!(),
- };
-
- write_or_print(&out, tcx.sess);
-}
-
-// In an ideal world, this would be a public function called by the driver after
-// analysis is performed. However, we want to call `phase_3_run_analysis_passes`
-// with a different callback than the standard driver, so that isn't easy.
-// Instead, we call that function ourselves.
-fn print_with_analysis(tcx: TyCtxt<'_>, ppm: PpMode) -> Result<(), ErrorGuaranteed> {
- tcx.analysis(())?;
- let out = match ppm {
- Mir => {
- let mut out = Vec::new();
- write_mir_pretty(tcx, None, &mut out).unwrap();
- String::from_utf8(out).unwrap()
- }
-
- MirCFG => {
- let mut out = Vec::new();
- write_mir_graphviz(tcx, None, &mut out).unwrap();
- String::from_utf8(out).unwrap()
- }
-
- ThirTree => {
- let mut out = String::new();
- abort_on_err(rustc_hir_analysis::check_crate(tcx), tcx.sess);
- debug!("pretty printing THIR tree");
- for did in tcx.hir().body_owners() {
- let _ = writeln!(
- out,
- "{:?}:\n{}\n",
- did,
- tcx.thir_tree(ty::WithOptConstParam::unknown(did))
- );
- }
- out
- }
-
- ThirFlat => {
- let mut out = String::new();
- abort_on_err(rustc_hir_analysis::check_crate(tcx), tcx.sess);
- debug!("pretty printing THIR flat");
- for did in tcx.hir().body_owners() {
- let _ = writeln!(
- out,
- "{:?}:\n{}\n",
- did,
- tcx.thir_flat(ty::WithOptConstParam::unknown(did))
- );
- }
- out
- }
-
- _ => unreachable!(),
- };
-
- write_or_print(&out, tcx.sess);
-
- Ok(())
-}
+++ /dev/null
-use rustc_macros::Diagnostic;
-
-#[derive(Diagnostic)]
-#[diag(driver_rlink_unable_to_read)]
-pub(crate) struct RlinkUnableToRead {
- pub err: std::io::Error,
-}
-
-#[derive(Diagnostic)]
-#[diag(driver_rlink_wrong_file_type)]
-pub(crate) struct RLinkWrongFileType;
-
-#[derive(Diagnostic)]
-#[diag(driver_rlink_empty_version_number)]
-pub(crate) struct RLinkEmptyVersionNumber;
-
-#[derive(Diagnostic)]
-#[diag(driver_rlink_encoding_version_mismatch)]
-pub(crate) struct RLinkEncodingVersionMismatch {
- pub version_array: String,
- pub rlink_version: u32,
-}
-
-#[derive(Diagnostic)]
-#[diag(driver_rlink_rustc_version_mismatch)]
-pub(crate) struct RLinkRustcVersionMismatch<'a> {
- pub rustc_version: String,
- pub current_version: &'a str,
-}
-
-#[derive(Diagnostic)]
-#[diag(driver_rlink_no_a_file)]
-pub(crate) struct RlinkNotAFile;
-
-#[derive(Diagnostic)]
-#[diag(driver_unpretty_dump_fail)]
-pub(crate) struct UnprettyDumpFail {
- pub path: String,
- pub err: String,
-}
--- /dev/null
+[package]
+name = "rustc_driver_impl"
+version = "0.0.0"
+edition = "2021"
+
+[lib]
+
+[dependencies]
+tracing = { version = "0.1.35" }
+serde_json = "1.0.59"
+rustc_log = { path = "../rustc_log" }
+rustc_middle = { path = "../rustc_middle" }
+rustc_ast_pretty = { path = "../rustc_ast_pretty" }
+rustc_target = { path = "../rustc_target" }
+rustc_lint = { path = "../rustc_lint" }
+rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_errors = { path = "../rustc_errors" }
+rustc_feature = { path = "../rustc_feature" }
+rustc_hir = { path = "../rustc_hir" }
+rustc_hir_pretty = { path = "../rustc_hir_pretty" }
+rustc_macros = { path = "../rustc_macros" }
+rustc_metadata = { path = "../rustc_metadata" }
+rustc_parse = { path = "../rustc_parse" }
+rustc_plugin_impl = { path = "../rustc_plugin_impl" }
+rustc_save_analysis = { path = "../rustc_save_analysis" }
+rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
+rustc_session = { path = "../rustc_session" }
+rustc_error_codes = { path = "../rustc_error_codes" }
+rustc_interface = { path = "../rustc_interface" }
+rustc_ast = { path = "../rustc_ast" }
+rustc_span = { path = "../rustc_span" }
+rustc_hir_analysis = { path = "../rustc_hir_analysis" }
+
+[target.'cfg(unix)'.dependencies]
+libc = "0.2"
+
+[target.'cfg(windows)'.dependencies]
+winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"] }
+
+[features]
+llvm = ['rustc_interface/llvm']
+max_level_info = ['rustc_log/max_level_info']
+rustc_use_parallel_compiler = ['rustc_data_structures/rustc_use_parallel_compiler', 'rustc_interface/rustc_use_parallel_compiler',
+ 'rustc_middle/rustc_use_parallel_compiler']
--- /dev/null
+The `driver` crate is effectively the "main" function for the rust
+compiler. It orchestrates the compilation process and "knits together"
+the code from the other crates within rustc. This crate itself does
+not contain any of the "main logic" of the compiler (though it does
+have some code related to pretty printing or other minor compiler
+options).
+
+For more information about how the driver works, see the [rustc dev guide].
+
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/rustc-driver.html
--- /dev/null
+use std::error;
+use std::fmt;
+use std::fs;
+use std::io;
+
+fn arg_expand(arg: String) -> Result<Vec<String>, Error> {
+ if let Some(path) = arg.strip_prefix('@') {
+ let file = match fs::read_to_string(path) {
+ Ok(file) => file,
+ Err(ref err) if err.kind() == io::ErrorKind::InvalidData => {
+ return Err(Error::Utf8Error(Some(path.to_string())));
+ }
+ Err(err) => return Err(Error::IOError(path.to_string(), err)),
+ };
+ Ok(file.lines().map(ToString::to_string).collect())
+ } else {
+ Ok(vec![arg])
+ }
+}
+
+pub fn arg_expand_all(at_args: &[String]) -> Vec<String> {
+ let mut args = Vec::new();
+ for arg in at_args {
+ match arg_expand(arg.clone()) {
+ Ok(arg) => args.extend(arg),
+ Err(err) => rustc_session::early_error(
+ rustc_session::config::ErrorOutputType::default(),
+ &format!("Failed to load argument file: {err}"),
+ ),
+ }
+ }
+ args
+}
+
+#[derive(Debug)]
+pub enum Error {
+ Utf8Error(Option<String>),
+ IOError(String, io::Error),
+}
+
+impl fmt::Display for Error {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Error::Utf8Error(None) => write!(fmt, "Utf8 error"),
+ Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {path}"),
+ Error::IOError(path, err) => write!(fmt, "IO Error: {path}: {err}"),
+ }
+ }
+}
+
+impl error::Error for Error {}
--- /dev/null
+//! The Rust compiler.
+//!
+//! # Note
+//!
+//! This API is completely unstable and subject to change.
+
+#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(is_terminal)]
+#![feature(once_cell)]
+#![feature(decl_macro)]
+#![recursion_limit = "256"]
+#![allow(rustc::potential_query_instability)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
+
+#[macro_use]
+extern crate tracing;
+
+pub extern crate rustc_plugin_impl as plugin;
+
+use rustc_ast as ast;
+use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults};
+use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
+use rustc_data_structures::sync::SeqCst;
+use rustc_errors::registry::{InvalidErrorCode, Registry};
+use rustc_errors::{ErrorGuaranteed, PResult};
+use rustc_feature::find_gated_cfg;
+use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
+use rustc_interface::{interface, Queries};
+use rustc_lint::LintStore;
+use rustc_metadata::locator;
+use rustc_save_analysis as save;
+use rustc_save_analysis::DumpHandler;
+use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS};
+use rustc_session::config::{ErrorOutputType, Input, OutputType, PrintRequest, TrimmedDefPaths};
+use rustc_session::cstore::MetadataLoader;
+use rustc_session::getopts;
+use rustc_session::lint::{Lint, LintId};
+use rustc_session::{config, Session};
+use rustc_session::{early_error, early_error_no_abort, early_warn};
+use rustc_span::source_map::{FileLoader, FileName};
+use rustc_span::symbol::sym;
+use rustc_target::json::ToJson;
+
+use std::cmp::max;
+use std::env;
+use std::ffi::OsString;
+use std::fs;
+use std::io::{self, IsTerminal, Read, Write};
+use std::panic::{self, catch_unwind};
+use std::path::PathBuf;
+use std::process::{self, Command, Stdio};
+use std::str;
+use std::sync::LazyLock;
+use std::time::Instant;
+
+pub mod args;
+pub mod pretty;
+mod session_diagnostics;
+
+use crate::session_diagnostics::{
+ RLinkEmptyVersionNumber, RLinkEncodingVersionMismatch, RLinkRustcVersionMismatch,
+ RLinkWrongFileType, RlinkNotAFile, RlinkUnableToRead,
+};
+
+/// Exit status code used for successful compilation and help output.
+pub const EXIT_SUCCESS: i32 = 0;
+
+/// Exit status code used for compilation failures and invalid flags.
+pub const EXIT_FAILURE: i32 = 1;
+
+const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust/issues/new\
+ ?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md";
+
+const ICE_REPORT_COMPILER_FLAGS: &[&str] = &["-Z", "-C", "--crate-type"];
+
+const ICE_REPORT_COMPILER_FLAGS_EXCLUDE: &[&str] = &["metadata", "extra-filename"];
+
+const ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE: &[&str] = &["incremental"];
+
+pub fn abort_on_err<T>(result: Result<T, ErrorGuaranteed>, sess: &Session) -> T {
+ match result {
+ Err(..) => {
+ sess.abort_if_errors();
+ panic!("error reported but abort_if_errors didn't abort???");
+ }
+ Ok(x) => x,
+ }
+}
+
+pub trait Callbacks {
+ /// Called before creating the compiler instance
+ fn config(&mut self, _config: &mut interface::Config) {}
+ /// Called after parsing. Return value instructs the compiler whether to
+ /// continue the compilation afterwards (defaults to `Compilation::Continue`)
+ fn after_parsing<'tcx>(
+ &mut self,
+ _compiler: &interface::Compiler,
+ _queries: &'tcx Queries<'tcx>,
+ ) -> Compilation {
+ Compilation::Continue
+ }
+ /// Called after expansion. Return value instructs the compiler whether to
+ /// continue the compilation afterwards (defaults to `Compilation::Continue`)
+ fn after_expansion<'tcx>(
+ &mut self,
+ _compiler: &interface::Compiler,
+ _queries: &'tcx Queries<'tcx>,
+ ) -> Compilation {
+ Compilation::Continue
+ }
+ /// Called after analysis. Return value instructs the compiler whether to
+ /// continue the compilation afterwards (defaults to `Compilation::Continue`)
+ fn after_analysis<'tcx>(
+ &mut self,
+ _compiler: &interface::Compiler,
+ _queries: &'tcx Queries<'tcx>,
+ ) -> Compilation {
+ Compilation::Continue
+ }
+}
+
+#[derive(Default)]
+pub struct TimePassesCallbacks {
+ time_passes: bool,
+}
+
+impl Callbacks for TimePassesCallbacks {
+ // JUSTIFICATION: the session doesn't exist at this point.
+ #[allow(rustc::bad_opt_access)]
+ fn config(&mut self, config: &mut interface::Config) {
+ // If a --print=... option has been given, we don't print the "total"
+ // time because it will mess up the --print output. See #64339.
+ //
+ self.time_passes = config.opts.prints.is_empty() && config.opts.unstable_opts.time_passes;
+ config.opts.trimmed_def_paths = TrimmedDefPaths::GoodPath;
+ }
+}
+
+pub fn diagnostics_registry() -> Registry {
+ Registry::new(rustc_error_codes::DIAGNOSTICS)
+}
+
+/// This is the primary entry point for rustc.
+pub struct RunCompiler<'a, 'b> {
+ at_args: &'a [String],
+ callbacks: &'b mut (dyn Callbacks + Send),
+ file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
+ make_codegen_backend:
+ Option<Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>>,
+}
+
+impl<'a, 'b> RunCompiler<'a, 'b> {
+ pub fn new(at_args: &'a [String], callbacks: &'b mut (dyn Callbacks + Send)) -> Self {
+ Self { at_args, callbacks, file_loader: None, make_codegen_backend: None }
+ }
+
+ /// Set a custom codegen backend.
+ ///
+ /// Has no uses within this repository, but is used by bjorn3 for "the
+ /// hotswapping branch of cg_clif" for "setting the codegen backend from a
+ /// custom driver where the custom codegen backend has arbitrary data."
+ /// (See #102759.)
+ pub fn set_make_codegen_backend(
+ &mut self,
+ make_codegen_backend: Option<
+ Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
+ >,
+ ) -> &mut Self {
+ self.make_codegen_backend = make_codegen_backend;
+ self
+ }
+
+ /// Load files from sources other than the file system.
+ ///
+ /// Has no uses within this repository, but may be used in the future by
+ /// bjorn3 for "hooking rust-analyzer's VFS into rustc at some point for
+ /// running rustc without having to save". (See #102759.)
+ pub fn set_file_loader(
+ &mut self,
+ file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
+ ) -> &mut Self {
+ self.file_loader = file_loader;
+ self
+ }
+
+ /// Parse args and run the compiler.
+ pub fn run(self) -> interface::Result<()> {
+ run_compiler(self.at_args, self.callbacks, self.file_loader, self.make_codegen_backend)
+ }
+}
+
+fn run_compiler(
+ at_args: &[String],
+ callbacks: &mut (dyn Callbacks + Send),
+ file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
+ make_codegen_backend: Option<
+ Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
+ >,
+) -> interface::Result<()> {
+ let args = args::arg_expand_all(at_args);
+
+ let Some(matches) = handle_options(&args) else { return Ok(()) };
+
+ let sopts = config::build_session_options(&matches);
+
+ if let Some(ref code) = matches.opt_str("explain") {
+ handle_explain(diagnostics_registry(), code, sopts.error_format);
+ return Ok(());
+ }
+
+ let cfg = interface::parse_cfgspecs(matches.opt_strs("cfg"));
+ let check_cfg = interface::parse_check_cfg(matches.opt_strs("check-cfg"));
+ let (odir, ofile) = make_output(&matches);
+ let mut config = interface::Config {
+ opts: sopts,
+ crate_cfg: cfg,
+ crate_check_cfg: check_cfg,
+ input: Input::File(PathBuf::new()),
+ output_file: ofile,
+ output_dir: odir,
+ file_loader,
+ lint_caps: Default::default(),
+ parse_sess_created: None,
+ register_lints: None,
+ override_queries: None,
+ make_codegen_backend,
+ registry: diagnostics_registry(),
+ };
+
+ if !tracing::dispatcher::has_been_set() {
+ init_rustc_env_logger_with_backtrace_option(&config.opts.unstable_opts.log_backtrace);
+ }
+
+ match make_input(config.opts.error_format, &matches.free) {
+ Err(reported) => return Err(reported),
+ Ok(Some(input)) => {
+ config.input = input;
+
+ callbacks.config(&mut config);
+ }
+ Ok(None) => match matches.free.len() {
+ 0 => {
+ callbacks.config(&mut config);
+ interface::run_compiler(config, |compiler| {
+ let sopts = &compiler.session().opts;
+ if sopts.describe_lints {
+ let mut lint_store =
+ rustc_lint::new_lint_store(compiler.session().enable_internal_lints());
+ let registered_lints =
+ if let Some(register_lints) = compiler.register_lints() {
+ register_lints(compiler.session(), &mut lint_store);
+ true
+ } else {
+ false
+ };
+ describe_lints(compiler.session(), &lint_store, registered_lints);
+ return;
+ }
+ let should_stop =
+ print_crate_info(&***compiler.codegen_backend(), compiler.session(), false);
+
+ if should_stop == Compilation::Stop {
+ return;
+ }
+ early_error(sopts.error_format, "no input filename given")
+ });
+ return Ok(());
+ }
+ 1 => panic!("make_input should have provided valid inputs"),
+ _ => early_error(
+ config.opts.error_format,
+ &format!(
+ "multiple input filenames provided (first two filenames are `{}` and `{}`)",
+ matches.free[0], matches.free[1],
+ ),
+ ),
+ },
+ };
+
+ interface::run_compiler(config, |compiler| {
+ let sess = compiler.session();
+ let should_stop = print_crate_info(&***compiler.codegen_backend(), sess, true)
+ .and_then(|| list_metadata(sess, &*compiler.codegen_backend().metadata_loader()))
+ .and_then(|| try_process_rlink(sess, compiler));
+
+ if should_stop == Compilation::Stop {
+ return sess.compile_status();
+ }
+
+ let linker = compiler.enter(|queries| {
+ let early_exit = || sess.compile_status().map(|_| None);
+ queries.parse()?;
+
+ if let Some(ppm) = &sess.opts.pretty {
+ if ppm.needs_ast_map() {
+ queries.global_ctxt()?.enter(|tcx| {
+ pretty::print_after_hir_lowering(tcx, *ppm);
+ Ok(())
+ })?;
+ } else {
+ let krate = queries.parse()?.steal();
+ pretty::print_after_parsing(sess, &krate, *ppm);
+ }
+ trace!("finished pretty-printing");
+ return early_exit();
+ }
+
+ if callbacks.after_parsing(compiler, queries) == Compilation::Stop {
+ return early_exit();
+ }
+
+ if sess.opts.unstable_opts.parse_only || sess.opts.unstable_opts.show_span.is_some() {
+ return early_exit();
+ }
+
+ {
+ let plugins = queries.register_plugins()?;
+ let (_, lint_store) = &*plugins.borrow();
+
+ // Lint plugins are registered; now we can process command line flags.
+ if sess.opts.describe_lints {
+ describe_lints(sess, lint_store, true);
+ return early_exit();
+ }
+ }
+
+ let mut gctxt = queries.global_ctxt()?;
+ if callbacks.after_expansion(compiler, queries) == Compilation::Stop {
+ return early_exit();
+ }
+
+ // Make sure the `output_filenames` query is run for its side
+ // effects of writing the dep-info and reporting errors.
+ gctxt.enter(|tcx| tcx.output_filenames(()));
+
+ if sess.opts.output_types.contains_key(&OutputType::DepInfo)
+ && sess.opts.output_types.len() == 1
+ {
+ return early_exit();
+ }
+
+ if sess.opts.unstable_opts.no_analysis {
+ return early_exit();
+ }
+
+ gctxt.enter(|tcx| {
+ let result = tcx.analysis(());
+ if sess.opts.unstable_opts.save_analysis {
+ let crate_name = tcx.crate_name(LOCAL_CRATE);
+ sess.time("save_analysis", || {
+ save::process_crate(
+ tcx,
+ crate_name,
+ &sess.io.input,
+ None,
+ DumpHandler::new(sess.io.output_dir.as_deref(), crate_name),
+ )
+ });
+ }
+ result
+ })?;
+
+ drop(gctxt);
+
+ if callbacks.after_analysis(compiler, queries) == Compilation::Stop {
+ return early_exit();
+ }
+
+ queries.ongoing_codegen()?;
+
+ if sess.opts.unstable_opts.print_type_sizes {
+ sess.code_stats.print_type_sizes();
+ }
+
+ let linker = queries.linker()?;
+ Ok(Some(linker))
+ })?;
+
+ if let Some(linker) = linker {
+ let _timer = sess.timer("link");
+ linker.link()?
+ }
+
+ if sess.opts.unstable_opts.perf_stats {
+ sess.print_perf_stats();
+ }
+
+ if sess.opts.unstable_opts.print_fuel.is_some() {
+ eprintln!(
+ "Fuel used by {}: {}",
+ sess.opts.unstable_opts.print_fuel.as_ref().unwrap(),
+ sess.print_fuel.load(SeqCst)
+ );
+ }
+
+ Ok(())
+ })
+}
+
+// Extract output directory and file from matches.
+fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<PathBuf>) {
+ let odir = matches.opt_str("out-dir").map(|o| PathBuf::from(&o));
+ let ofile = matches.opt_str("o").map(|o| PathBuf::from(&o));
+ (odir, ofile)
+}
+
+// Extract input (string or file and optional path) from matches.
+fn make_input(
+ error_format: ErrorOutputType,
+ free_matches: &[String],
+) -> Result<Option<Input>, ErrorGuaranteed> {
+ if free_matches.len() == 1 {
+ let ifile = &free_matches[0];
+ if ifile == "-" {
+ let mut src = String::new();
+ if io::stdin().read_to_string(&mut src).is_err() {
+ // Immediately stop compilation if there was an issue reading
+ // the input (for example if the input stream is not UTF-8).
+ let reported = early_error_no_abort(
+ error_format,
+ "couldn't read from stdin, as it did not contain valid UTF-8",
+ );
+ return Err(reported);
+ }
+ if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") {
+ let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect(
+ "when UNSTABLE_RUSTDOC_TEST_PATH is set \
+ UNSTABLE_RUSTDOC_TEST_LINE also needs to be set",
+ );
+ let line = isize::from_str_radix(&line, 10)
+ .expect("UNSTABLE_RUSTDOC_TEST_LINE needs to be an number");
+ let file_name = FileName::doc_test_source_code(PathBuf::from(path), line);
+ Ok(Some(Input::Str { name: file_name, input: src }))
+ } else {
+ Ok(Some(Input::Str { name: FileName::anon_source_code(&src), input: src }))
+ }
+ } else {
+ Ok(Some(Input::File(PathBuf::from(ifile))))
+ }
+ } else {
+ Ok(None)
+ }
+}
+
+/// Whether to stop or continue compilation.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum Compilation {
+ Stop,
+ Continue,
+}
+
+impl Compilation {
+ pub fn and_then<F: FnOnce() -> Compilation>(self, next: F) -> Compilation {
+ match self {
+ Compilation::Stop => Compilation::Stop,
+ Compilation::Continue => next(),
+ }
+ }
+}
+
+fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
+ let upper_cased_code = code.to_ascii_uppercase();
+ let normalised =
+ if upper_cased_code.starts_with('E') { upper_cased_code } else { format!("E{code:0>4}") };
+ match registry.try_find_description(&normalised) {
+ Ok(Some(description)) => {
+ let mut is_in_code_block = false;
+ let mut text = String::new();
+ // Slice off the leading newline and print.
+ for line in description.lines() {
+ let indent_level =
+ line.find(|c: char| !c.is_whitespace()).unwrap_or_else(|| line.len());
+ let dedented_line = &line[indent_level..];
+ if dedented_line.starts_with("```") {
+ is_in_code_block = !is_in_code_block;
+ text.push_str(&line[..(indent_level + 3)]);
+ } else if is_in_code_block && dedented_line.starts_with("# ") {
+ continue;
+ } else {
+ text.push_str(line);
+ }
+ text.push('\n');
+ }
+ if io::stdout().is_terminal() {
+ show_content_with_pager(&text);
+ } else {
+ print!("{text}");
+ }
+ }
+ Ok(None) => {
+ early_error(output, &format!("no extended information for {code}"));
+ }
+ Err(InvalidErrorCode) => {
+ early_error(output, &format!("{code} is not a valid error code"));
+ }
+ }
+}
+
+fn show_content_with_pager(content: &str) {
+ let pager_name = env::var_os("PAGER").unwrap_or_else(|| {
+ if cfg!(windows) { OsString::from("more.com") } else { OsString::from("less") }
+ });
+
+ let mut fallback_to_println = false;
+
+ match Command::new(pager_name).stdin(Stdio::piped()).spawn() {
+ Ok(mut pager) => {
+ if let Some(pipe) = pager.stdin.as_mut() {
+ if pipe.write_all(content.as_bytes()).is_err() {
+ fallback_to_println = true;
+ }
+ }
+
+ if pager.wait().is_err() {
+ fallback_to_println = true;
+ }
+ }
+ Err(_) => {
+ fallback_to_println = true;
+ }
+ }
+
+ // If pager fails for whatever reason, we should still print the content
+ // to standard output
+ if fallback_to_println {
+ print!("{content}");
+ }
+}
+
+pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Compilation {
+ if sess.opts.unstable_opts.link_only {
+ if let Input::File(file) = &sess.io.input {
+ // FIXME: #![crate_type] and #![crate_name] support not implemented yet
+ sess.init_crate_types(collect_crate_types(sess, &[]));
+ let outputs = compiler.build_output_filenames(sess, &[]);
+ let rlink_data = fs::read(file).unwrap_or_else(|err| {
+ sess.emit_fatal(RlinkUnableToRead { err });
+ });
+ let codegen_results = match CodegenResults::deserialize_rlink(rlink_data) {
+ Ok(codegen) => codegen,
+ Err(err) => {
+ match err {
+ CodegenErrors::WrongFileType => sess.emit_fatal(RLinkWrongFileType),
+ CodegenErrors::EmptyVersionNumber => {
+ sess.emit_fatal(RLinkEmptyVersionNumber)
+ }
+ CodegenErrors::EncodingVersionMismatch { version_array, rlink_version } => {
+ sess.emit_fatal(RLinkEncodingVersionMismatch {
+ version_array,
+ rlink_version,
+ })
+ }
+ CodegenErrors::RustcVersionMismatch { rustc_version, current_version } => {
+ sess.emit_fatal(RLinkRustcVersionMismatch {
+ rustc_version,
+ current_version,
+ })
+ }
+ };
+ }
+ };
+ let result = compiler.codegen_backend().link(sess, codegen_results, &outputs);
+ abort_on_err(result, sess);
+ } else {
+ sess.emit_fatal(RlinkNotAFile {})
+ }
+ Compilation::Stop
+ } else {
+ Compilation::Continue
+ }
+}
+
+pub fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) -> Compilation {
+ if sess.opts.unstable_opts.ls {
+ match sess.io.input {
+ Input::File(ref ifile) => {
+ let path = &(*ifile);
+ let mut v = Vec::new();
+ locator::list_file_metadata(&sess.target, path, metadata_loader, &mut v).unwrap();
+ println!("{}", String::from_utf8(v).unwrap());
+ }
+ Input::Str { .. } => {
+ early_error(ErrorOutputType::default(), "cannot list metadata for stdin");
+ }
+ }
+ return Compilation::Stop;
+ }
+
+ Compilation::Continue
+}
+
+fn print_crate_info(
+ codegen_backend: &dyn CodegenBackend,
+ sess: &Session,
+ parse_attrs: bool,
+) -> Compilation {
+ use rustc_session::config::PrintRequest::*;
+ // NativeStaticLibs and LinkArgs are special - printed during linking
+ // (empty iterator returns true)
+ if sess.opts.prints.iter().all(|&p| p == NativeStaticLibs || p == LinkArgs) {
+ return Compilation::Continue;
+ }
+
+ let attrs = if parse_attrs {
+ let result = parse_crate_attrs(sess);
+ match result {
+ Ok(attrs) => Some(attrs),
+ Err(mut parse_error) => {
+ parse_error.emit();
+ return Compilation::Stop;
+ }
+ }
+ } else {
+ None
+ };
+ for req in &sess.opts.prints {
+ match *req {
+ TargetList => {
+ let mut targets = rustc_target::spec::TARGETS.to_vec();
+ targets.sort_unstable();
+ println!("{}", targets.join("\n"));
+ }
+ Sysroot => println!("{}", sess.sysroot.display()),
+ TargetLibdir => println!("{}", sess.target_tlib_path.dir.display()),
+ TargetSpec => {
+ println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap());
+ }
+ FileNames | CrateName => {
+ let attrs = attrs.as_ref().unwrap();
+ let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess);
+ let id = rustc_session::output::find_crate_name(sess, attrs);
+ if *req == PrintRequest::CrateName {
+ println!("{id}");
+ continue;
+ }
+ let crate_types = collect_crate_types(sess, attrs);
+ for &style in &crate_types {
+ let fname =
+ rustc_session::output::filename_for_input(sess, style, id, &t_outputs);
+ println!("{}", fname.file_name().unwrap().to_string_lossy());
+ }
+ }
+ Cfg => {
+ let mut cfgs = sess
+ .parse_sess
+ .config
+ .iter()
+ .filter_map(|&(name, value)| {
+ // Note that crt-static is a specially recognized cfg
+ // directive that's printed out here as part of
+ // rust-lang/rust#37406, but in general the
+ // `target_feature` cfg is gated under
+ // rust-lang/rust#29717. For now this is just
+ // specifically allowing the crt-static cfg and that's
+ // it, this is intended to get into Cargo and then go
+ // through to build scripts.
+ if (name != sym::target_feature || value != Some(sym::crt_dash_static))
+ && !sess.is_nightly_build()
+ && find_gated_cfg(|cfg_sym| cfg_sym == name).is_some()
+ {
+ return None;
+ }
+
+ if let Some(value) = value {
+ Some(format!("{name}=\"{value}\""))
+ } else {
+ Some(name.to_string())
+ }
+ })
+ .collect::<Vec<String>>();
+
+ cfgs.sort();
+ for cfg in cfgs {
+ println!("{cfg}");
+ }
+ }
+ CallingConventions => {
+ let mut calling_conventions = rustc_target::spec::abi::all_names();
+ calling_conventions.sort_unstable();
+ println!("{}", calling_conventions.join("\n"));
+ }
+ RelocationModels
+ | CodeModels
+ | TlsModels
+ | TargetCPUs
+ | StackProtectorStrategies
+ | TargetFeatures => {
+ codegen_backend.print(*req, sess);
+ }
+ // Any output here interferes with Cargo's parsing of other printed output
+ NativeStaticLibs => {}
+ LinkArgs => {}
+ SplitDebuginfo => {
+ use rustc_target::spec::SplitDebuginfo::{Off, Packed, Unpacked};
+
+ for split in &[Off, Packed, Unpacked] {
+ let stable = sess.target.options.supported_split_debuginfo.contains(split);
+ let unstable_ok = sess.unstable_options();
+ if stable || unstable_ok {
+ println!("{split}");
+ }
+ }
+ }
+ }
+ }
+ Compilation::Stop
+}
+
+/// Prints version information
+///
+/// NOTE: this is a macro to support drivers built at a different time than the main `rustc_driver` crate.
+pub macro version($binary: literal, $matches: expr) {
+ fn unw(x: Option<&str>) -> &str {
+ x.unwrap_or("unknown")
+ }
+ $crate::version_at_macro_invocation(
+ $binary,
+ $matches,
+ unw(option_env!("CFG_VERSION")),
+ unw(option_env!("CFG_VER_HASH")),
+ unw(option_env!("CFG_VER_DATE")),
+ unw(option_env!("CFG_RELEASE")),
+ )
+}
+
+#[doc(hidden)] // use the macro instead
+pub fn version_at_macro_invocation(
+ binary: &str,
+ matches: &getopts::Matches,
+ version: &str,
+ commit_hash: &str,
+ commit_date: &str,
+ release: &str,
+) {
+ let verbose = matches.opt_present("verbose");
+
+ println!("{binary} {version}");
+
+ if verbose {
+ println!("binary: {binary}");
+ println!("commit-hash: {commit_hash}");
+ println!("commit-date: {commit_date}");
+ println!("host: {}", config::host_triple());
+ println!("release: {release}");
+
+ let debug_flags = matches.opt_strs("Z");
+ let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
+ get_codegen_backend(&None, backend_name).print_version();
+ }
+}
+
+fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) {
+ let groups = if verbose { config::rustc_optgroups() } else { config::rustc_short_optgroups() };
+ let mut options = getopts::Options::new();
+ for option in groups.iter().filter(|x| include_unstable_options || x.is_stable()) {
+ (option.apply)(&mut options);
+ }
+ let message = "Usage: rustc [OPTIONS] INPUT";
+ let nightly_help = if nightly_build {
+ "\n -Z help Print unstable compiler options"
+ } else {
+ ""
+ };
+ let verbose_help = if verbose {
+ ""
+ } else {
+ "\n --help -v Print the full set of options rustc accepts"
+ };
+ let at_path = if verbose {
+ " @path Read newline separated options from `path`\n"
+ } else {
+ ""
+ };
+ println!(
+ "{options}{at_path}\nAdditional help:
+ -C help Print codegen options
+ -W help \
+ Print 'lint' options and default settings{nightly}{verbose}\n",
+ options = options.usage(message),
+ at_path = at_path,
+ nightly = nightly_help,
+ verbose = verbose_help
+ );
+}
+
+fn print_wall_help() {
+ println!(
+ "
+The flag `-Wall` does not exist in `rustc`. Most useful lints are enabled by
+default. Use `rustc -W help` to see all available lints. It's more common to put
+warning settings in the crate root using `#![warn(LINT_NAME)]` instead of using
+the command line flag directly.
+"
+ );
+}
+
+/// Write to stdout lint command options, together with a list of all available lints
+pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) {
+ println!(
+ "
+Available lint options:
+ -W <foo> Warn about <foo>
+ -A <foo> \
+ Allow <foo>
+ -D <foo> Deny <foo>
+ -F <foo> Forbid <foo> \
+ (deny <foo> and all attempts to override)
+
+"
+ );
+
+ fn sort_lints(sess: &Session, mut lints: Vec<&'static Lint>) -> Vec<&'static Lint> {
+ // The sort doesn't case-fold but it's doubtful we care.
+ lints.sort_by_cached_key(|x: &&Lint| (x.default_level(sess.edition()), x.name));
+ lints
+ }
+
+ fn sort_lint_groups(
+ lints: Vec<(&'static str, Vec<LintId>, bool)>,
+ ) -> Vec<(&'static str, Vec<LintId>)> {
+ let mut lints: Vec<_> = lints.into_iter().map(|(x, y, _)| (x, y)).collect();
+ lints.sort_by_key(|l| l.0);
+ lints
+ }
+
+ let (plugin, builtin): (Vec<_>, _) =
+ lint_store.get_lints().iter().cloned().partition(|&lint| lint.is_plugin);
+ let plugin = sort_lints(sess, plugin);
+ let builtin = sort_lints(sess, builtin);
+
+ let (plugin_groups, builtin_groups): (Vec<_>, _) =
+ lint_store.get_lint_groups().partition(|&(.., p)| p);
+ let plugin_groups = sort_lint_groups(plugin_groups);
+ let builtin_groups = sort_lint_groups(builtin_groups);
+
+ let max_name_len =
+ plugin.iter().chain(&builtin).map(|&s| s.name.chars().count()).max().unwrap_or(0);
+ let padded = |x: &str| {
+ let mut s = " ".repeat(max_name_len - x.chars().count());
+ s.push_str(x);
+ s
+ };
+
+ println!("Lint checks provided by rustc:\n");
+
+ let print_lints = |lints: Vec<&Lint>| {
+ println!(" {} {:7.7} {}", padded("name"), "default", "meaning");
+ println!(" {} {:7.7} {}", padded("----"), "-------", "-------");
+ for lint in lints {
+ let name = lint.name_lower().replace('_', "-");
+ println!(
+ " {} {:7.7} {}",
+ padded(&name),
+ lint.default_level(sess.edition()).as_str(),
+ lint.desc
+ );
+ }
+ println!("\n");
+ };
+
+ print_lints(builtin);
+
+ let max_name_len = max(
+ "warnings".len(),
+ plugin_groups
+ .iter()
+ .chain(&builtin_groups)
+ .map(|&(s, _)| s.chars().count())
+ .max()
+ .unwrap_or(0),
+ );
+
+ let padded = |x: &str| {
+ let mut s = " ".repeat(max_name_len - x.chars().count());
+ s.push_str(x);
+ s
+ };
+
+ println!("Lint groups provided by rustc:\n");
+
+ let print_lint_groups = |lints: Vec<(&'static str, Vec<LintId>)>, all_warnings| {
+ println!(" {} sub-lints", padded("name"));
+ println!(" {} ---------", padded("----"));
+
+ if all_warnings {
+ println!(" {} all lints that are set to issue warnings", padded("warnings"));
+ }
+
+ for (name, to) in lints {
+ let name = name.to_lowercase().replace('_', "-");
+ let desc = to
+ .into_iter()
+ .map(|x| x.to_string().replace('_', "-"))
+ .collect::<Vec<String>>()
+ .join(", ");
+ println!(" {} {}", padded(&name), desc);
+ }
+ println!("\n");
+ };
+
+ print_lint_groups(builtin_groups, true);
+
+ match (loaded_plugins, plugin.len(), plugin_groups.len()) {
+ (false, 0, _) | (false, _, 0) => {
+ println!("Lint tools like Clippy can provide additional lints and lint groups.");
+ }
+ (false, ..) => panic!("didn't load lint plugins but got them anyway!"),
+ (true, 0, 0) => println!("This crate does not load any lint plugins or lint groups."),
+ (true, l, g) => {
+ if l > 0 {
+ println!("Lint checks provided by plugins loaded by this crate:\n");
+ print_lints(plugin);
+ }
+ if g > 0 {
+ println!("Lint groups provided by plugins loaded by this crate:\n");
+ print_lint_groups(plugin_groups, false);
+ }
+ }
+ }
+}
+
+fn describe_debug_flags() {
+ println!("\nAvailable options:\n");
+ print_flag_list("-Z", config::Z_OPTIONS);
+}
+
+fn describe_codegen_flags() {
+ println!("\nAvailable codegen options:\n");
+ print_flag_list("-C", config::CG_OPTIONS);
+}
+
+pub fn print_flag_list<T>(
+ cmdline_opt: &str,
+ flag_list: &[(&'static str, T, &'static str, &'static str)],
+) {
+ let max_len = flag_list.iter().map(|&(name, _, _, _)| name.chars().count()).max().unwrap_or(0);
+
+ for &(name, _, _, desc) in flag_list {
+ println!(
+ " {} {:>width$}=val -- {}",
+ cmdline_opt,
+ name.replace('_', "-"),
+ desc,
+ width = max_len
+ );
+ }
+}
+
+/// Process command line options. Emits messages as appropriate. If compilation
+/// should continue, returns a getopts::Matches object parsed from args,
+/// otherwise returns `None`.
+///
+/// The compiler's handling of options is a little complicated as it ties into
+/// our stability story. The current intention of each compiler option is to
+/// have one of two modes:
+///
+/// 1. An option is stable and can be used everywhere.
+/// 2. An option is unstable, and can only be used on nightly.
+///
+/// Like unstable library and language features, however, unstable options have
+/// always required a form of "opt in" to indicate that you're using them. This
+/// provides the easy ability to scan a code base to check to see if anything
+/// unstable is being used. Currently, this "opt in" is the `-Z` "zed" flag.
+///
+/// All options behind `-Z` are considered unstable by default. Other top-level
+/// options can also be considered unstable, and they were unlocked through the
+/// `-Z unstable-options` flag. Note that `-Z` remains to be the root of
+/// instability in both cases, though.
+///
+/// So with all that in mind, the comments below have some more detail about the
+/// contortions done here to get things to work out correctly.
+pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
+ // Throw away the first argument, the name of the binary
+ let args = &args[1..];
+
+ if args.is_empty() {
+ // user did not write `-v` nor `-Z unstable-options`, so do not
+ // include that extra information.
+ let nightly_build =
+ rustc_feature::UnstableFeatures::from_environment(None).is_nightly_build();
+ usage(false, false, nightly_build);
+ return None;
+ }
+
+ // Parse with *all* options defined in the compiler, we don't worry about
+ // option stability here we just want to parse as much as possible.
+ let mut options = getopts::Options::new();
+ for option in config::rustc_optgroups() {
+ (option.apply)(&mut options);
+ }
+ let matches = options.parse(args).unwrap_or_else(|e| {
+ let msg = match e {
+ getopts::Fail::UnrecognizedOption(ref opt) => CG_OPTIONS
+ .iter()
+ .map(|&(name, ..)| ('C', name))
+ .chain(Z_OPTIONS.iter().map(|&(name, ..)| ('Z', name)))
+ .find(|&(_, name)| *opt == name.replace('_', "-"))
+ .map(|(flag, _)| format!("{e}. Did you mean `-{flag} {opt}`?")),
+ _ => None,
+ };
+ early_error(ErrorOutputType::default(), &msg.unwrap_or_else(|| e.to_string()));
+ });
+
+ // For all options we just parsed, we check a few aspects:
+ //
+ // * If the option is stable, we're all good
+ // * If the option wasn't passed, we're all good
+ // * If `-Z unstable-options` wasn't passed (and we're not a -Z option
+ // ourselves), then we require the `-Z unstable-options` flag to unlock
+ // this option that was passed.
+ // * If we're a nightly compiler, then unstable options are now unlocked, so
+ // we're good to go.
+ // * Otherwise, if we're an unstable option then we generate an error
+ // (unstable option being used on stable)
+ nightly_options::check_nightly_options(&matches, &config::rustc_optgroups());
+
+ if matches.opt_present("h") || matches.opt_present("help") {
+ // Only show unstable options in --help if we accept unstable options.
+ let unstable_enabled = nightly_options::is_unstable_enabled(&matches);
+ let nightly_build = nightly_options::match_is_nightly_build(&matches);
+ usage(matches.opt_present("verbose"), unstable_enabled, nightly_build);
+ return None;
+ }
+
+ // Handle the special case of -Wall.
+ let wall = matches.opt_strs("W");
+ if wall.iter().any(|x| *x == "all") {
+ print_wall_help();
+ rustc_errors::FatalError.raise();
+ }
+
+ // Don't handle -W help here, because we might first load plugins.
+ let debug_flags = matches.opt_strs("Z");
+ if debug_flags.iter().any(|x| *x == "help") {
+ describe_debug_flags();
+ return None;
+ }
+
+ let cg_flags = matches.opt_strs("C");
+
+ if cg_flags.iter().any(|x| *x == "help") {
+ describe_codegen_flags();
+ return None;
+ }
+
+ if cg_flags.iter().any(|x| *x == "no-stack-check") {
+ early_warn(
+ ErrorOutputType::default(),
+ "the --no-stack-check flag is deprecated and does nothing",
+ );
+ }
+
+ if cg_flags.iter().any(|x| *x == "passes=list") {
+ let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
+ get_codegen_backend(&None, backend_name).print_passes();
+ return None;
+ }
+
+ if matches.opt_present("version") {
+ version!("rustc", &matches);
+ return None;
+ }
+
+ Some(matches)
+}
+
+fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> {
+ match &sess.io.input {
+ Input::File(ifile) => rustc_parse::parse_crate_attrs_from_file(ifile, &sess.parse_sess),
+ Input::Str { name, input } => rustc_parse::parse_crate_attrs_from_source_str(
+ name.clone(),
+ input.clone(),
+ &sess.parse_sess,
+ ),
+ }
+}
+
+/// Gets a list of extra command-line flags provided by the user, as strings.
+///
+/// This function is used during ICEs to show more information useful for
+/// debugging, since some ICEs only happens with non-default compiler flags
+/// (and the users don't always report them).
+fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
+ let mut args = env::args_os().map(|arg| arg.to_string_lossy().to_string()).peekable();
+
+ let mut result = Vec::new();
+ let mut excluded_cargo_defaults = false;
+ while let Some(arg) = args.next() {
+ if let Some(a) = ICE_REPORT_COMPILER_FLAGS.iter().find(|a| arg.starts_with(*a)) {
+ let content = if arg.len() == a.len() {
+ // A space-separated option, like `-C incremental=foo` or `--crate-type rlib`
+ match args.next() {
+ Some(arg) => arg.to_string(),
+ None => continue,
+ }
+ } else if arg.get(a.len()..a.len() + 1) == Some("=") {
+ // An equals option, like `--crate-type=rlib`
+ arg[a.len() + 1..].to_string()
+ } else {
+ // A non-space option, like `-Cincremental=foo`
+ arg[a.len()..].to_string()
+ };
+ let option = content.split_once('=').map(|s| s.0).unwrap_or(&content);
+ if ICE_REPORT_COMPILER_FLAGS_EXCLUDE.iter().any(|exc| option == *exc) {
+ excluded_cargo_defaults = true;
+ } else {
+ result.push(a.to_string());
+ match ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.iter().find(|s| option == **s) {
+ Some(s) => result.push(format!("{s}=[REDACTED]")),
+ None => result.push(content),
+ }
+ }
+ }
+ }
+
+ if !result.is_empty() { Some((result, excluded_cargo_defaults)) } else { None }
+}
+
+/// Runs a closure and catches unwinds triggered by fatal errors.
+///
+/// The compiler currently unwinds with a special sentinel value to abort
+/// compilation on fatal errors. This function catches that sentinel and turns
+/// the panic into a `Result` instead.
+pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorGuaranteed> {
+ catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| {
+ if value.is::<rustc_errors::FatalErrorMarker>() {
+ ErrorGuaranteed::unchecked_claim_error_was_emitted()
+ } else {
+ panic::resume_unwind(value);
+ }
+ })
+}
+
+/// Variant of `catch_fatal_errors` for the `interface::Result` return type
+/// that also computes the exit code.
+pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 {
+ let result = catch_fatal_errors(f).and_then(|result| result);
+ match result {
+ Ok(()) => EXIT_SUCCESS,
+ Err(_) => EXIT_FAILURE,
+ }
+}
+
+static DEFAULT_HOOK: LazyLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
+ LazyLock::new(|| {
+ let hook = panic::take_hook();
+ panic::set_hook(Box::new(|info| {
+ // If the error was caused by a broken pipe then this is not a bug.
+ // Write the error and return immediately. See #98700.
+ #[cfg(windows)]
+ if let Some(msg) = info.payload().downcast_ref::<String>() {
+ if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)")
+ {
+ early_error_no_abort(ErrorOutputType::default(), &msg);
+ return;
+ }
+ };
+
+ // Invoke the default handler, which prints the actual panic message and optionally a backtrace
+ // Don't do this for delayed bugs, which already emit their own more useful backtrace.
+ if !info.payload().is::<rustc_errors::DelayedBugPanic>() {
+ (*DEFAULT_HOOK)(info);
+
+ // Separate the output with an empty line
+ eprintln!();
+ }
+
+ // Print the ICE message
+ report_ice(info, BUG_REPORT_URL);
+ }));
+ hook
+ });
+
+/// Prints the ICE message, including query stack, but without backtrace.
+///
+/// The message will point the user at `bug_report_url` to report the ICE.
+///
+/// When `install_ice_hook` is called, this function will be called as the panic
+/// hook.
+pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
+ let fallback_bundle =
+ rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+ let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
+ rustc_errors::ColorConfig::Auto,
+ None,
+ None,
+ fallback_bundle,
+ false,
+ false,
+ None,
+ false,
+ false,
+ ));
+ let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
+
+ // a .span_bug or .bug call has already printed what
+ // it wants to print.
+ if !info.payload().is::<rustc_errors::ExplicitBug>()
+ && !info.payload().is::<rustc_errors::DelayedBugPanic>()
+ {
+ let mut d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic");
+ handler.emit_diagnostic(&mut d);
+ }
+
+ handler.emit_note(session_diagnostics::Ice);
+ handler.emit_note(session_diagnostics::IceBugReport { bug_report_url });
+ handler.emit_note(session_diagnostics::IceVersion {
+ version: util::version_str!().unwrap_or("unknown_version"),
+ triple: config::host_triple(),
+ });
+
+ if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() {
+ handler.emit_note(session_diagnostics::IceFlags { flags: flags.join(" ") });
+ if excluded_cargo_defaults {
+ handler.emit_note(session_diagnostics::IceExcludeCargoDefaults);
+ }
+ }
+
+ // If backtraces are enabled, also print the query stack
+ let backtrace = env::var_os("RUST_BACKTRACE").map_or(false, |x| &x != "0");
+
+ let num_frames = if backtrace { None } else { Some(2) };
+
+ interface::try_print_query_stack(&handler, num_frames);
+
+ #[cfg(windows)]
+ unsafe {
+ if env::var("RUSTC_BREAK_ON_ICE").is_ok() {
+ // Trigger a debugger if we crashed during bootstrap
+ winapi::um::debugapi::DebugBreak();
+ }
+ }
+}
+
+/// Installs a panic hook that will print the ICE message on unexpected panics.
+///
+/// A custom rustc driver can skip calling this to set up a custom ICE hook.
+pub fn install_ice_hook() {
+ // If the user has not explicitly overridden "RUST_BACKTRACE", then produce
+ // full backtraces. When a compiler ICE happens, we want to gather
+ // as much information as possible to present in the issue opened
+ // by the user. Compiler developers and other rustc users can
+ // opt in to less-verbose backtraces by manually setting "RUST_BACKTRACE"
+ // (e.g. `RUST_BACKTRACE=1`)
+ if std::env::var("RUST_BACKTRACE").is_err() {
+ std::env::set_var("RUST_BACKTRACE", "full");
+ }
+ LazyLock::force(&DEFAULT_HOOK);
+}
+
+/// This allows tools to enable rust logging without having to magically match rustc's
+/// tracing crate version.
+pub fn init_rustc_env_logger() {
+ init_rustc_env_logger_with_backtrace_option(&None);
+}
+
+/// This allows tools to enable rust logging without having to magically match rustc's
+/// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to
+/// choose a target module you wish to show backtraces along with its logging.
+pub fn init_rustc_env_logger_with_backtrace_option(backtrace_target: &Option<String>) {
+ if let Err(error) = rustc_log::init_rustc_env_logger_with_backtrace_option(backtrace_target) {
+ early_error(ErrorOutputType::default(), &error.to_string());
+ }
+}
+
+/// This allows tools to enable rust logging without having to magically match rustc's
+/// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to choose an env var
+/// other than `RUSTC_LOG`.
+pub fn init_env_logger(env: &str) {
+ if let Err(error) = rustc_log::init_env_logger(env) {
+ early_error(ErrorOutputType::default(), &error.to_string());
+ }
+}
+
+#[cfg(all(unix, any(target_env = "gnu", target_os = "macos")))]
+mod signal_handler {
+ extern "C" {
+ fn backtrace_symbols_fd(
+ buffer: *const *mut libc::c_void,
+ size: libc::c_int,
+ fd: libc::c_int,
+ );
+ }
+
+ extern "C" fn print_stack_trace(_: libc::c_int) {
+ const MAX_FRAMES: usize = 256;
+ static mut STACK_TRACE: [*mut libc::c_void; MAX_FRAMES] =
+ [std::ptr::null_mut(); MAX_FRAMES];
+ unsafe {
+ let depth = libc::backtrace(STACK_TRACE.as_mut_ptr(), MAX_FRAMES as i32);
+ if depth == 0 {
+ return;
+ }
+ backtrace_symbols_fd(STACK_TRACE.as_ptr(), depth, 2);
+ }
+ }
+
+ /// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the
+ /// process, print a stack trace and then exit.
+ pub(super) fn install() {
+ unsafe {
+ const ALT_STACK_SIZE: usize = libc::MINSIGSTKSZ + 64 * 1024;
+ let mut alt_stack: libc::stack_t = std::mem::zeroed();
+ alt_stack.ss_sp =
+ std::alloc::alloc(std::alloc::Layout::from_size_align(ALT_STACK_SIZE, 1).unwrap())
+ as *mut libc::c_void;
+ alt_stack.ss_size = ALT_STACK_SIZE;
+ libc::sigaltstack(&alt_stack, std::ptr::null_mut());
+
+ let mut sa: libc::sigaction = std::mem::zeroed();
+ sa.sa_sigaction = print_stack_trace as libc::sighandler_t;
+ sa.sa_flags = libc::SA_NODEFER | libc::SA_RESETHAND | libc::SA_ONSTACK;
+ libc::sigemptyset(&mut sa.sa_mask);
+ libc::sigaction(libc::SIGSEGV, &sa, std::ptr::null_mut());
+ }
+ }
+}
+
+#[cfg(not(all(unix, any(target_env = "gnu", target_os = "macos"))))]
+mod signal_handler {
+ pub(super) fn install() {}
+}
+
+pub fn main() -> ! {
+ let start_time = Instant::now();
+ let start_rss = get_resident_set_size();
+ signal_handler::install();
+ let mut callbacks = TimePassesCallbacks::default();
+ install_ice_hook();
+ let exit_code = catch_with_exit_code(|| {
+ let args = env::args_os()
+ .enumerate()
+ .map(|(i, arg)| {
+ arg.into_string().unwrap_or_else(|arg| {
+ early_error(
+ ErrorOutputType::default(),
+ &format!("argument {i} is not valid Unicode: {arg:?}"),
+ )
+ })
+ })
+ .collect::<Vec<_>>();
+ RunCompiler::new(&args, &mut callbacks).run()
+ });
+
+ if callbacks.time_passes {
+ let end_rss = get_resident_set_size();
+ print_time_passes_entry("total", start_time.elapsed(), start_rss, end_rss);
+ }
+
+ process::exit(exit_code)
+}
--- /dev/null
+//! The various pretty-printing routines.
+
+use crate::session_diagnostics::UnprettyDumpFail;
+use rustc_ast as ast;
+use rustc_ast_pretty::pprust;
+use rustc_errors::ErrorGuaranteed;
+use rustc_hir as hir;
+use rustc_hir_pretty as pprust_hir;
+use rustc_middle::hir::map as hir_map;
+use rustc_middle::mir::{write_mir_graphviz, write_mir_pretty};
+use rustc_middle::ty::{self, TyCtxt};
+use rustc_session::config::{PpAstTreeMode, PpHirMode, PpMode, PpSourceMode};
+use rustc_session::Session;
+use rustc_span::symbol::Ident;
+use rustc_span::FileName;
+
+use std::cell::Cell;
+use std::fmt::Write;
+
+pub use self::PpMode::*;
+pub use self::PpSourceMode::*;
+use crate::abort_on_err;
+
+// This slightly awkward construction is to allow for each PpMode to
+// choose whether it needs to do analyses (which can consume the
+// Session) and then pass through the session (now attached to the
+// analysis results) on to the chosen pretty-printer, along with the
+// `&PpAnn` object.
+//
+// Note that since the `&PrinterSupport` is freshly constructed on each
+// call, it would not make sense to try to attach the lifetime of `self`
+// to the lifetime of the `&PrinterObject`.
+
+/// Constructs a `PrinterSupport` object and passes it to `f`.
+fn call_with_pp_support<'tcx, A, F>(
+ ppmode: &PpSourceMode,
+ sess: &'tcx Session,
+ tcx: Option<TyCtxt<'tcx>>,
+ f: F,
+) -> A
+where
+ F: FnOnce(&dyn PrinterSupport) -> A,
+{
+ match *ppmode {
+ Normal | Expanded => {
+ let annotation = NoAnn { sess, tcx };
+ f(&annotation)
+ }
+
+ Identified | ExpandedIdentified => {
+ let annotation = IdentifiedAnnotation { sess, tcx };
+ f(&annotation)
+ }
+ ExpandedHygiene => {
+ let annotation = HygieneAnnotation { sess };
+ f(&annotation)
+ }
+ }
+}
+fn call_with_pp_support_hir<A, F>(ppmode: &PpHirMode, tcx: TyCtxt<'_>, f: F) -> A
+where
+ F: FnOnce(&dyn HirPrinterSupport<'_>, hir_map::Map<'_>) -> A,
+{
+ match *ppmode {
+ PpHirMode::Normal => {
+ let annotation = NoAnn { sess: tcx.sess, tcx: Some(tcx) };
+ f(&annotation, tcx.hir())
+ }
+
+ PpHirMode::Identified => {
+ let annotation = IdentifiedAnnotation { sess: tcx.sess, tcx: Some(tcx) };
+ f(&annotation, tcx.hir())
+ }
+ PpHirMode::Typed => {
+ abort_on_err(tcx.analysis(()), tcx.sess);
+
+ let annotation = TypedAnnotation { tcx, maybe_typeck_results: Cell::new(None) };
+ tcx.dep_graph.with_ignore(|| f(&annotation, tcx.hir()))
+ }
+ }
+}
+
+trait PrinterSupport: pprust::PpAnn {
+ /// Provides a uniform interface for re-extracting a reference to a
+ /// `Session` from a value that now owns it.
+ fn sess(&self) -> &Session;
+
+ /// Produces the pretty-print annotation object.
+ ///
+ /// (Rust does not yet support upcasting from a trait object to
+ /// an object for one of its supertraits.)
+ fn pp_ann(&self) -> &dyn pprust::PpAnn;
+}
+
+trait HirPrinterSupport<'hir>: pprust_hir::PpAnn {
+ /// Provides a uniform interface for re-extracting a reference to a
+ /// `Session` from a value that now owns it.
+ fn sess(&self) -> &Session;
+
+ /// Provides a uniform interface for re-extracting a reference to an
+ /// `hir_map::Map` from a value that now owns it.
+ fn hir_map(&self) -> Option<hir_map::Map<'hir>>;
+
+ /// Produces the pretty-print annotation object.
+ ///
+ /// (Rust does not yet support upcasting from a trait object to
+ /// an object for one of its supertraits.)
+ fn pp_ann(&self) -> &dyn pprust_hir::PpAnn;
+}
+
+struct NoAnn<'hir> {
+ sess: &'hir Session,
+ tcx: Option<TyCtxt<'hir>>,
+}
+
+impl<'hir> PrinterSupport for NoAnn<'hir> {
+ fn sess(&self) -> &Session {
+ self.sess
+ }
+
+ fn pp_ann(&self) -> &dyn pprust::PpAnn {
+ self
+ }
+}
+
+impl<'hir> HirPrinterSupport<'hir> for NoAnn<'hir> {
+ fn sess(&self) -> &Session {
+ self.sess
+ }
+
+ fn hir_map(&self) -> Option<hir_map::Map<'hir>> {
+ self.tcx.map(|tcx| tcx.hir())
+ }
+
+ fn pp_ann(&self) -> &dyn pprust_hir::PpAnn {
+ self
+ }
+}
+
+impl<'hir> pprust::PpAnn for NoAnn<'hir> {}
+impl<'hir> pprust_hir::PpAnn for NoAnn<'hir> {
+ fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
+ if let Some(tcx) = self.tcx {
+ pprust_hir::PpAnn::nested(&(&tcx.hir() as &dyn hir::intravisit::Map<'_>), state, nested)
+ }
+ }
+}
+
+struct IdentifiedAnnotation<'hir> {
+ sess: &'hir Session,
+ tcx: Option<TyCtxt<'hir>>,
+}
+
+impl<'hir> PrinterSupport for IdentifiedAnnotation<'hir> {
+ fn sess(&self) -> &Session {
+ self.sess
+ }
+
+ fn pp_ann(&self) -> &dyn pprust::PpAnn {
+ self
+ }
+}
+
+impl<'hir> pprust::PpAnn for IdentifiedAnnotation<'hir> {
+ fn pre(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
+ if let pprust::AnnNode::Expr(_) = node {
+ s.popen();
+ }
+ }
+ fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
+ match node {
+ pprust::AnnNode::Crate(_) | pprust::AnnNode::Ident(_) | pprust::AnnNode::Name(_) => {}
+
+ pprust::AnnNode::Item(item) => {
+ s.s.space();
+ s.synth_comment(item.id.to_string())
+ }
+ pprust::AnnNode::SubItem(id) => {
+ s.s.space();
+ s.synth_comment(id.to_string())
+ }
+ pprust::AnnNode::Block(blk) => {
+ s.s.space();
+ s.synth_comment(format!("block {}", blk.id))
+ }
+ pprust::AnnNode::Expr(expr) => {
+ s.s.space();
+ s.synth_comment(expr.id.to_string());
+ s.pclose()
+ }
+ pprust::AnnNode::Pat(pat) => {
+ s.s.space();
+ s.synth_comment(format!("pat {}", pat.id));
+ }
+ }
+ }
+}
+
+impl<'hir> HirPrinterSupport<'hir> for IdentifiedAnnotation<'hir> {
+ fn sess(&self) -> &Session {
+ self.sess
+ }
+
+ fn hir_map(&self) -> Option<hir_map::Map<'hir>> {
+ self.tcx.map(|tcx| tcx.hir())
+ }
+
+ fn pp_ann(&self) -> &dyn pprust_hir::PpAnn {
+ self
+ }
+}
+
+impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> {
+ fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
+ if let Some(ref tcx) = self.tcx {
+ pprust_hir::PpAnn::nested(&(&tcx.hir() as &dyn hir::intravisit::Map<'_>), state, nested)
+ }
+ }
+ fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
+ if let pprust_hir::AnnNode::Expr(_) = node {
+ s.popen();
+ }
+ }
+ fn post(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
+ match node {
+ pprust_hir::AnnNode::Name(_) => {}
+ pprust_hir::AnnNode::Item(item) => {
+ s.s.space();
+ s.synth_comment(format!("hir_id: {}", item.hir_id()));
+ }
+ pprust_hir::AnnNode::SubItem(id) => {
+ s.s.space();
+ s.synth_comment(id.to_string());
+ }
+ pprust_hir::AnnNode::Block(blk) => {
+ s.s.space();
+ s.synth_comment(format!("block hir_id: {}", blk.hir_id));
+ }
+ pprust_hir::AnnNode::Expr(expr) => {
+ s.s.space();
+ s.synth_comment(format!("expr hir_id: {}", expr.hir_id));
+ s.pclose();
+ }
+ pprust_hir::AnnNode::Pat(pat) => {
+ s.s.space();
+ s.synth_comment(format!("pat hir_id: {}", pat.hir_id));
+ }
+ pprust_hir::AnnNode::Arm(arm) => {
+ s.s.space();
+ s.synth_comment(format!("arm hir_id: {}", arm.hir_id));
+ }
+ }
+ }
+}
+
+struct HygieneAnnotation<'a> {
+ sess: &'a Session,
+}
+
+impl<'a> PrinterSupport for HygieneAnnotation<'a> {
+ fn sess(&self) -> &Session {
+ self.sess
+ }
+
+ fn pp_ann(&self) -> &dyn pprust::PpAnn {
+ self
+ }
+}
+
+impl<'a> pprust::PpAnn for HygieneAnnotation<'a> {
+ fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
+ match node {
+ pprust::AnnNode::Ident(&Ident { name, span }) => {
+ s.s.space();
+ s.synth_comment(format!("{}{:?}", name.as_u32(), span.ctxt()))
+ }
+ pprust::AnnNode::Name(&name) => {
+ s.s.space();
+ s.synth_comment(name.as_u32().to_string())
+ }
+ pprust::AnnNode::Crate(_) => {
+ s.s.hardbreak();
+ let verbose = self.sess.verbose();
+ s.synth_comment(rustc_span::hygiene::debug_hygiene_data(verbose));
+ s.s.hardbreak_if_not_bol();
+ }
+ _ => {}
+ }
+ }
+}
+
+struct TypedAnnotation<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ maybe_typeck_results: Cell<Option<&'tcx ty::TypeckResults<'tcx>>>,
+}
+
+impl<'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'tcx> {
+ fn sess(&self) -> &Session {
+ self.tcx.sess
+ }
+
+ fn hir_map(&self) -> Option<hir_map::Map<'tcx>> {
+ Some(self.tcx.hir())
+ }
+
+ fn pp_ann(&self) -> &dyn pprust_hir::PpAnn {
+ self
+ }
+}
+
+impl<'tcx> pprust_hir::PpAnn for TypedAnnotation<'tcx> {
+ fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
+ let old_maybe_typeck_results = self.maybe_typeck_results.get();
+ if let pprust_hir::Nested::Body(id) = nested {
+ self.maybe_typeck_results.set(Some(self.tcx.typeck_body(id)));
+ }
+ let pp_ann = &(&self.tcx.hir() as &dyn hir::intravisit::Map<'_>);
+ pprust_hir::PpAnn::nested(pp_ann, state, nested);
+ self.maybe_typeck_results.set(old_maybe_typeck_results);
+ }
+ fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
+ if let pprust_hir::AnnNode::Expr(_) = node {
+ s.popen();
+ }
+ }
+ fn post(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
+ if let pprust_hir::AnnNode::Expr(expr) = node {
+ let typeck_results = self.maybe_typeck_results.get().or_else(|| {
+ self.tcx
+ .hir()
+ .maybe_body_owned_by(expr.hir_id.owner.def_id)
+ .map(|body_id| self.tcx.typeck_body(body_id))
+ });
+
+ if let Some(typeck_results) = typeck_results {
+ s.s.space();
+ s.s.word("as");
+ s.s.space();
+ s.s.word(typeck_results.expr_ty(expr).to_string());
+ }
+
+ s.pclose();
+ }
+ }
+}
+
+fn get_source(sess: &Session) -> (String, FileName) {
+ let src_name = sess.io.input.source_name();
+ let src = String::clone(
+ sess.source_map()
+ .get_source_file(&src_name)
+ .expect("get_source_file")
+ .src
+ .as_ref()
+ .expect("src"),
+ );
+ (src, src_name)
+}
+
+fn write_or_print(out: &str, sess: &Session) {
+ match &sess.io.output_file {
+ None => print!("{out}"),
+ Some(p) => {
+ if let Err(e) = std::fs::write(p, out) {
+ sess.emit_fatal(UnprettyDumpFail {
+ path: p.display().to_string(),
+ err: e.to_string(),
+ });
+ }
+ }
+ }
+}
+
+pub fn print_after_parsing(sess: &Session, krate: &ast::Crate, ppm: PpMode) {
+ let (src, src_name) = get_source(sess);
+
+ let out = match ppm {
+ Source(s) => {
+ // Silently ignores an identified node.
+ call_with_pp_support(&s, sess, None, move |annotation| {
+ debug!("pretty printing source code {:?}", s);
+ let sess = annotation.sess();
+ let parse = &sess.parse_sess;
+ pprust::print_crate(
+ sess.source_map(),
+ krate,
+ src_name,
+ src,
+ annotation.pp_ann(),
+ false,
+ parse.edition,
+ &sess.parse_sess.attr_id_generator,
+ )
+ })
+ }
+ AstTree(PpAstTreeMode::Normal) => {
+ debug!("pretty printing AST tree");
+ format!("{krate:#?}")
+ }
+ _ => unreachable!(),
+ };
+
+ write_or_print(&out, sess);
+}
+
+pub fn print_after_hir_lowering<'tcx>(tcx: TyCtxt<'tcx>, ppm: PpMode) {
+ if ppm.needs_analysis() {
+ abort_on_err(print_with_analysis(tcx, ppm), tcx.sess);
+ return;
+ }
+
+ let (src, src_name) = get_source(tcx.sess);
+
+ let out = match ppm {
+ Source(s) => {
+ // Silently ignores an identified node.
+ call_with_pp_support(&s, tcx.sess, Some(tcx), move |annotation| {
+ debug!("pretty printing source code {:?}", s);
+ let sess = annotation.sess();
+ let parse = &sess.parse_sess;
+ pprust::print_crate(
+ sess.source_map(),
+ &tcx.resolver_for_lowering(()).borrow().1,
+ src_name,
+ src,
+ annotation.pp_ann(),
+ true,
+ parse.edition,
+ &sess.parse_sess.attr_id_generator,
+ )
+ })
+ }
+
+ AstTree(PpAstTreeMode::Expanded) => {
+ debug!("pretty-printing expanded AST");
+ format!("{:#?}", tcx.resolver_for_lowering(()).borrow().1)
+ }
+
+ Hir(s) => call_with_pp_support_hir(&s, tcx, move |annotation, hir_map| {
+ debug!("pretty printing HIR {:?}", s);
+ let sess = annotation.sess();
+ let sm = sess.source_map();
+ let attrs = |id| hir_map.attrs(id);
+ pprust_hir::print_crate(
+ sm,
+ hir_map.root_module(),
+ src_name,
+ src,
+ &attrs,
+ annotation.pp_ann(),
+ )
+ }),
+
+ HirTree => {
+ call_with_pp_support_hir(&PpHirMode::Normal, tcx, move |_annotation, hir_map| {
+ debug!("pretty printing HIR tree");
+ format!("{:#?}", hir_map.krate())
+ })
+ }
+
+ _ => unreachable!(),
+ };
+
+ write_or_print(&out, tcx.sess);
+}
+
+// In an ideal world, this would be a public function called by the driver after
+// analysis is performed. However, we want to call `phase_3_run_analysis_passes`
+// with a different callback than the standard driver, so that isn't easy.
+// Instead, we call that function ourselves.
+fn print_with_analysis(tcx: TyCtxt<'_>, ppm: PpMode) -> Result<(), ErrorGuaranteed> {
+ tcx.analysis(())?;
+ let out = match ppm {
+ Mir => {
+ let mut out = Vec::new();
+ write_mir_pretty(tcx, None, &mut out).unwrap();
+ String::from_utf8(out).unwrap()
+ }
+
+ MirCFG => {
+ let mut out = Vec::new();
+ write_mir_graphviz(tcx, None, &mut out).unwrap();
+ String::from_utf8(out).unwrap()
+ }
+
+ ThirTree => {
+ let mut out = String::new();
+ abort_on_err(rustc_hir_analysis::check_crate(tcx), tcx.sess);
+ debug!("pretty printing THIR tree");
+ for did in tcx.hir().body_owners() {
+ let _ = writeln!(
+ out,
+ "{:?}:\n{}\n",
+ did,
+ tcx.thir_tree(ty::WithOptConstParam::unknown(did))
+ );
+ }
+ out
+ }
+
+ ThirFlat => {
+ let mut out = String::new();
+ abort_on_err(rustc_hir_analysis::check_crate(tcx), tcx.sess);
+ debug!("pretty printing THIR flat");
+ for did in tcx.hir().body_owners() {
+ let _ = writeln!(
+ out,
+ "{:?}:\n{}\n",
+ did,
+ tcx.thir_flat(ty::WithOptConstParam::unknown(did))
+ );
+ }
+ out
+ }
+
+ _ => unreachable!(),
+ };
+
+ write_or_print(&out, tcx.sess);
+
+ Ok(())
+}
--- /dev/null
+use rustc_macros::Diagnostic;
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_rlink_unable_to_read)]
+pub(crate) struct RlinkUnableToRead {
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_rlink_wrong_file_type)]
+pub(crate) struct RLinkWrongFileType;
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_rlink_empty_version_number)]
+pub(crate) struct RLinkEmptyVersionNumber;
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_rlink_encoding_version_mismatch)]
+pub(crate) struct RLinkEncodingVersionMismatch {
+ pub version_array: String,
+ pub rlink_version: u32,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_rlink_rustc_version_mismatch)]
+pub(crate) struct RLinkRustcVersionMismatch<'a> {
+ pub rustc_version: String,
+ pub current_version: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_rlink_no_a_file)]
+pub(crate) struct RlinkNotAFile;
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_unpretty_dump_fail)]
+pub(crate) struct UnprettyDumpFail {
+ pub path: String,
+ pub err: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_ice)]
+pub(crate) struct Ice;
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_ice_bug_report)]
+pub(crate) struct IceBugReport<'a> {
+ pub bug_report_url: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_ice_version)]
+pub(crate) struct IceVersion<'a> {
+ pub version: &'a str,
+ pub triple: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_ice_flags)]
+pub(crate) struct IceFlags {
+ pub flags: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_ice_exclude_cargo_defaults)]
+pub(crate) struct IceExcludeCargoDefaults;
// /!\ IMPORTANT /!\
//
// Error messages' format must follow the RFC 1567 available here:
-// https://github.com/rust-lang/rfcs/pull/1567
+// https://rust-lang.github.io/rfcs/1567-long-error-codes-explanation-normalization.html
register_diagnostics! {
E0001: include_str!("./error_codes/E0001.md"),
E0520: include_str!("./error_codes/E0520.md"),
E0521: include_str!("./error_codes/E0521.md"),
E0522: include_str!("./error_codes/E0522.md"),
+E0523: include_str!("./error_codes/E0523.md"),
E0524: include_str!("./error_codes/E0524.md"),
E0525: include_str!("./error_codes/E0525.md"),
E0527: include_str!("./error_codes/E0527.md"),
E0790: include_str!("./error_codes/E0790.md"),
E0791: include_str!("./error_codes/E0791.md"),
E0792: include_str!("./error_codes/E0792.md"),
+E0793: include_str!("./error_codes/E0793.md"),
;
// E0006, // merged with E0005
// E0008, // cannot bind by-move into a pattern guard
// E0488, // lifetime of variable does not enclose its declaration
// E0489, // type/lifetime parameter not in scope here
// E0490, // removed: unreachable
- E0523, // two dependencies have same (crate-name, disambiguator) but different SVH
// E0526, // shuffle indices are not constant
// E0540, // multiple rustc_deprecated attributes
// E0548, // replaced with a generic attribute input check
The compiler found multiple library files with the requested crate name.
+```compile_fail
+// aux-build:crateresolve-1.rs
+// aux-build:crateresolve-2.rs
+// aux-build:crateresolve-3.rs
+
+extern crate crateresolve;
+//~^ ERROR multiple candidates for `rlib` dependency `crateresolve` found
+
+fn main() {}
+```
+
This error can occur in several different cases -- for example, when using
`extern crate` or passing `--extern` options without crate paths. It can also be
caused by caching issues with the build directory, in which case `cargo clean`
may help.
+
+In the above example, there are three different library files, all of which
+define the same crate name. Without providing a full path, there is no way for
+the compiler to know which crate it should use.
--- /dev/null
+#### Note: this error code is no longer emitted by the compiler.
+
+The compiler found multiple library files with the requested crate name.
+
+```compile_fail
+// aux-build:crateresolve-1.rs
+// aux-build:crateresolve-2.rs
+// aux-build:crateresolve-3.rs
+
+extern crate crateresolve;
+//~^ ERROR multiple candidates for `rlib` dependency `crateresolve` found
+
+fn main() {}
+```
+
+This error can occur in several different cases -- for example, when using
+`extern crate` or passing `--extern` options without crate paths. It can also be
+caused by caching issues with the build directory, in which case `cargo clean`
+may help.
+
+In the above example, there are three different library files, all of which
+define the same crate name. Without providing a full path, there is no way for
+the compiler to know which crate it should use.
+
+*Note that E0523 has been merged into E0464.*
--- /dev/null
+An unaligned references to a field of a [packed] struct got created.
+
+Erroneous code example:
+
+```compile_fail,E0793
+#[repr(packed)]
+pub struct Foo {
+ field1: u64,
+ field2: u8,
+}
+
+unsafe {
+ let foo = Foo { field1: 0, field2: 0 };
+ // Accessing the field directly is fine.
+ let val = foo.field1;
+ // A reference to a packed field causes a error.
+ let val = &foo.field1; // ERROR
+ // An implicit `&` is added in format strings, causing the same error.
+ println!("{}", foo.field1); // ERROR
+}
+```
+
+Creating a reference to an insufficiently aligned packed field is
+[undefined behavior] and therefore disallowed. Using an `unsafe` block does not
+change anything about this. Instead, the code should do a copy of the data in
+the packed field or use raw pointers and unaligned accesses.
+
+```
+#[repr(packed)]
+pub struct Foo {
+ field1: u64,
+ field2: u8,
+}
+
+unsafe {
+ let foo = Foo { field1: 0, field2: 0 };
+
+ // Instead of a reference, we can create a raw pointer...
+ let ptr = std::ptr::addr_of!(foo.field1);
+ // ... and then (crucially!) access it in an explicitly unaligned way.
+ let val = unsafe { ptr.read_unaligned() };
+ // This would *NOT* be correct:
+ // let val = unsafe { *ptr }; // Undefined Behavior due to unaligned load!
+
+ // For formatting, we can create a copy to avoid the direct reference.
+ let copy = foo.field1;
+ println!("{}", copy);
+ // Creating a copy can be written in a single line with curly braces.
+ // (This is equivalent to the two lines above.)
+ println!("{}", { foo.field1 });
+}
+```
+
+### Additional information
+
+Note that this error is specifically about *references* to packed fields.
+Direct by-value access of those fields is fine, since then the compiler has
+enough information to generate the correct kind of access.
+
+See [issue #82523] for more information.
+
+[packed]: https://doc.rust-lang.org/reference/type-layout.html#the-alignment-modifiers
+[undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+[issue #82523]: https://github.com/rust-lang/rust/issues/82523
borrowck_var_here_captured = variable captured here
-borrowck_closure_inferred_mut = inferred to be a `FnMut` closure
+borrowck_closure_inferred_mut = inferred to be a `FnMut` closure
borrowck_returned_closure_escaped =
returns a closure that contains a reference to a captured variable, which then escapes the closure body
cannot prefer dynamic linking when performing LTO
.note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
-codegen_llvm_fail_parsing_target_machine_config_to_target_machine =
+codegen_llvm_parse_target_machine_config =
failed to parse target machine config to target machine: {$error}
+
+codegen_llvm_lto_disallowed = lto can only be run for executables, cdylibs and static library outputs
+
+codegen_llvm_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto`
+
+codegen_llvm_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$llvm_err})
+
+codegen_llvm_write_output = could not write output to {$path}
+codegen_llvm_write_output_with_llvm_err = could not write output to {$path}: {$llvm_err}
+
+codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$triple}
+codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err}
+
+codegen_llvm_run_passes = failed to run LLVM passes
+codegen_llvm_run_passes_with_llvm_err = failed to run LLVM passes: {$llvm_err}
+
+codegen_llvm_serialize_module = failed to serialize module {$name}
+codegen_llvm_serialize_module_with_llvm_err = failed to serialize module {$name}: {$llvm_err}
+
+codegen_llvm_write_ir = failed to write LLVM IR to {$path}
+codegen_llvm_write_ir_with_llvm_err = failed to write LLVM IR to {$path}: {$llvm_err}
+
+codegen_llvm_prepare_thin_lto_context = failed to prepare thin LTO context
+codegen_llvm_prepare_thin_lto_context_with_llvm_err = failed to prepare thin LTO context: {$llvm_err}
+
+codegen_llvm_load_bitcode = failed to load bitcode of module "{$name}"
+codegen_llvm_load_bitcode_with_llvm_err = failed to load bitcode of module "{$name}": {$llvm_err}
+
+codegen_llvm_write_thinlto_key = error while writing ThinLTO key data: {$err}
+codegen_llvm_write_thinlto_key_with_llvm_err = error while writing ThinLTO key data: {$err}: {$llvm_err}
+
+codegen_llvm_multiple_source_dicompileunit = multiple source DICompileUnits found
+codegen_llvm_multiple_source_dicompileunit_with_llvm_err = multiple source DICompileUnits found: {$llvm_err}
+
+codegen_llvm_prepare_thin_lto_module = failed to prepare thin LTO module
+codegen_llvm_prepare_thin_lto_module_with_llvm_err = failed to prepare thin LTO module: {$llvm_err}
+
+codegen_llvm_parse_bitcode = failed to parse bitcode for LTO module
+codegen_llvm_parse_bitcode_with_llvm_err = failed to parse bitcode for LTO module: {$llvm_err}
+
+codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name}: {$message}
+codegen_llvm_from_llvm_diag = {$message}
+
+codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err}
+
+codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err}
-driver_rlink_unable_to_read = failed to read rlink file: `{$err}`
+driver_impl_rlink_unable_to_read = failed to read rlink file: `{$err}`
-driver_rlink_wrong_file_type = The input does not look like a .rlink file
+driver_impl_rlink_wrong_file_type = The input does not look like a .rlink file
-driver_rlink_empty_version_number = The input does not contain version number
+driver_impl_rlink_empty_version_number = The input does not contain version number
-driver_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}`
+driver_impl_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}`
-driver_rlink_rustc_version_mismatch = .rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}`
+driver_impl_rlink_rustc_version_mismatch = .rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}`
-driver_rlink_no_a_file = rlink must be a file
+driver_impl_rlink_no_a_file = rlink must be a file
-driver_unpretty_dump_fail = pretty-print failed to write `{$path}` due to error `{$err}`
+driver_impl_unpretty_dump_fail = pretty-print failed to write `{$path}` due to error `{$err}`
+
+driver_impl_ice = the compiler unexpectedly panicked. this is a bug.
+driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
+driver_impl_ice_version = rustc {$version} running on {$triple}
+driver_impl_ice_flags = compiler flags: {$flags}
+driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
expand_module_multiple_candidates =
file for module `{$name}` found at both "{$default_path}" and "{$secondary_path}"
.help = delete or rename one of them to remove the ambiguity
+
+expand_trace_macro = trace_macro
hir_typeck_lang_start_incorrect_ret_ty = the return type of the `start` lang item is incorrect
.suggestion = change the type from `{$found_ty}` to `{$expected_ty}`
+
+hir_typeck_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
+hir_typeck_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
+hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
+
+hir_typeck_convert_to_str = try converting the passed type into a `&str`
--- /dev/null
+incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name}
+
+incremental_missing_depnode = missing `DepNode` variant
+
+incremental_missing_if_this_changed = no `#[rustc_if_this_changed]` annotation detected
+
+incremental_no_path = no path from `{$source}` to `{$target}`
+
+incremental_ok = OK
+
+incremental_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified
+
+incremental_missing_query_depgraph =
+ found CGU-reuse attribute but `-Zquery-dep-graph` was not specified
+
+incremental_malformed_cgu_name =
+ found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case).
+
+incremental_no_module_named =
+ no module named `{$user_path}` (mangled: {$cgu_name}). available modules: {$cgu_names}
+
+incremental_field_associated_value_expected = associated value expected for `{$name}`
+
+incremental_no_field = no field `{$name}`
+
+incremental_assertion_auto =
+ `except` specified DepNodes that can not be affected for \"{$name}\": \"{$e}\"
+
+incremental_undefined_clean_dirty_assertions_item =
+ clean/dirty auto-assertions not yet defined for Node::Item.node={$kind}
+
+incremental_undefined_clean_dirty_assertions =
+ clean/dirty auto-assertions not yet defined for {$kind}
+
+incremental_repeated_depnode_label = dep-node label `{$label}` is repeated
+
+incremental_unrecognized_depnode_label = dep-node label `{$label}` not recognized
+
+incremental_not_dirty = `{$dep_node_str}` should be dirty but is not
+
+incremental_not_clean = `{$dep_node_str}` should be clean but is not
+
+incremental_not_loaded = `{$dep_node_str}` should have been loaded from disk but it was not
+
+incremental_unknown_item = unknown item `{$name}`
+
+incremental_no_cfg = no cfg attribute
+
+incremental_associated_value_expected_for = associated value expected for `{$ident}`
+
+incremental_associated_value_expected = expected an associated value
+
+incremental_unchecked_clean = found unchecked `#[rustc_clean]` attribute
+
+incremental_delete_old = unable to delete old {$name} at `{$path}`: {$err}
+
+incremental_create_new = failed to create {$name} at `{$path}`: {$err}
+
+incremental_write_new = failed to write {$name} to `{$path}`: {$err}
+
+incremental_canonicalize_path = incremental compilation: error canonicalizing path `{$path}`: {$err}
+
+incremental_create_incr_comp_dir =
+ could not create incremental compilation {$tag} directory `{$path}`: {$err}
+
+incremental_create_lock =
+ incremental compilation: could not create session directory lock file: {$lock_err}
+incremental_lock_unsupported =
+ the filesystem for the incremental path at {$session_dir} does not appear to support locking, consider changing the incremental path to a filesystem that supports locking or disable incremental compilation
+incremental_cargo_help_1 =
+ incremental compilation can be disabled by setting the environment variable CARGO_INCREMENTAL=0 (see https://doc.rust-lang.org/cargo/reference/profiles.html#incremental)
+incremental_cargo_help_2 =
+ the entire build directory can be changed to a different filesystem by setting the environment variable CARGO_TARGET_DIR to a different path (see https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir)
+
+incremental_delete_lock =
+ error deleting lock file for incremental compilation session directory `{$path}`: {$err}
+
+incremental_hard_link_failed =
+ hard linking files in the incremental compilation cache failed. copying files instead. consider moving the cache directory to a file system which supports hard linking in session dir `{$path}`
+
+incremental_delete_partial = failed to delete partly initialized session dir `{$path}`: {$err}
+
+incremental_delete_full = error deleting incremental compilation session directory `{$path}`: {$err}
+
+incremental_finalize = error finalizing incremental compilation session directory `{$path}`: {$err}
+
+incremental_invalid_gc_failed =
+ failed to garbage collect invalid incremental compilation session directory `{$path}`: {$err}
+
+incremental_finalized_gc_failed =
+ failed to garbage collect finalized incremental compilation session directory `{$path}`: {$err}
+
+incremental_session_gc_failed =
+ failed to garbage collect incremental compilation session directory `{$path}`: {$err}
+
+incremental_assert_not_loaded =
+ we asserted that the incremental cache should not be loaded, but it was loaded
+
+incremental_assert_loaded =
+ we asserted that an existing incremental cache directory should be successfully loaded, but it was not
+
+incremental_delete_incompatible =
+ failed to delete invalidated or incompatible incremental compilation session directory contents `{$path}`: {$err}
+
+incremental_load_dep_graph = could not load dep-graph from `{$path}`: {$err}
+
+incremental_decode_incr_cache = could not decode incremental cache: {$err}
+
+incremental_write_dep_graph = failed to write dependency graph to `{$path}`: {$err}
+
+incremental_move_dep_graph = failed to move dependency graph from `{$from}` to `{$to}`: {$err}
+
+incremental_create_dep_graph = failed to create dependency graph at `{$path}`: {$err}
+
+incremental_copy_workproduct_to_cache =
+ error copying object file `{$from}` to incremental directory as `{$to}`: {$err}
+
+incremental_delete_workproduct = file-system error deleting outdated file `{$path}`: {$err}
interface_proc_macro_crate_panic_abort =
building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic
+
+interface_unsupported_crate_type_for_target =
+ dropping unsupported crate type `{$crate_type}` for target `{$target_triple}`
+
+interface_multiple_output_types_adaption =
+ due to multiple output types requested, the explicitly specified output file name will be adapted for each output type
+
+interface_ignoring_extra_filename = ignoring -C extra-filename flag due to -o flag
+
+interface_ignoring_out_dir = ignoring --out-dir flag due to -o flag
.note = generators are lazy and do nothing unless resumed
lint_unused_def = unused {$pre}`{$def}`{$post} that must be used
+ .suggestion = use `let _ = ...` to ignore the resulting value
lint_path_statement_drop = path statement drops value
.suggestion = use `drop` to clarify the intent
monomorphize_couldnt_dump_mono_stats =
unexpected error occurred while dumping monomorphization stats: {$error}
+
+monomorphize_encountered_error_while_instantiating =
+ the above error was encountered while instantiating `{$formatted_item}`
+
+monomorphize_unknown_cgu_collection_mode =
+ unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode
.use_in_not_of = try using `in` here instead
.add_in = try adding `in` here
+parse_missing_expression_in_for_loop = missing expression to iterate on in `for` loop
+ .suggestion = try adding an expression to the `for` loop
+
parse_missing_comma_after_match_arm = expected `,` following `match` arm
.suggestion = missing a comma here to end this `match` arm
.suggestion_remove_eq = use `..=` instead
.note = inclusive ranges end with a single equals sign (`..=`)
-parse_inclusive_range_match_arrow = unexpected `=>` after open range
- .suggestion_add_space = add a space between the pattern and `=>`
+parse_inclusive_range_match_arrow = unexpected `>` after inclusive range
+ .label = this is parsed as an inclusive range `..=`
+ .suggestion = add a space between the pattern and `=>`
parse_inclusive_range_no_end = inclusive range with no end
.suggestion_open_range = use `..` instead
.name_label = while parsing this tuple struct
.body_label = the struct body
.suggestion = move the body before the where clause
+
+parse_async_fn_in_2015 = `async fn` is not permitted in Rust 2015
+ .label = to use `async fn`, switch to Rust 2018 or later
+
+parse_async_block_in_2015 = `async` blocks are only allowed in Rust 2018 or later
+
+parse_self_argument_pointer = cannot pass `self` by raw pointer
+ .label = cannot pass `self` by raw pointer
+
+parse_visibility_not_followed_by_item = visibility `{$vis}` is not followed by an item
+ .label = the visibility
+ .help = you likely meant to define an item, e.g., `{$vis} fn foo() {"{}"}`
+
+parse_default_not_followed_by_item = `default` is not followed by an item
+ .label = the `default` qualifier
+ .note = only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
+
+parse_missing_struct_for_struct_definition = missing `struct` for struct definition
+ .suggestion = add `struct` here to parse `{$ident}` as a public struct
+
+parse_missing_fn_for_function_definition = missing `fn` for function definition
+ .suggestion = add `fn` here to parse `{$ident}` as a public function
+
+parse_missing_fn_for_method_definition = missing `fn` for method definition
+ .suggestion = add `fn` here to parse `{$ident}` as a public method
+
+parse_ambiguous_missing_keyword_for_item_definition = missing `fn` or `struct` for function or struct definition
+ .suggestion = if you meant to call a macro, try
+ .help = if you meant to call a macro, remove the `pub` and add a trailing `!` after the identifier
+
+parse_missing_trait_in_trait_impl = missing trait in a trait impl
+ .suggestion_add_trait = add a trait here
+ .suggestion_remove_for = for an inherent impl, drop this `for`
+
+parse_missing_for_in_trait_impl = missing `for` in a trait impl
+ .suggestion = add `for` here
+
+parse_expected_trait_in_trait_impl_found_type = expected a trait, found type
+
+parse_non_item_in_item_list = non-item in item list
+ .suggestion_use_const_not_let = consider using `const` instead of `let` for associated const
+ .label_list_start = item list starts here
+ .label_non_item = non-item starts here
+ .label_list_end = item list ends here
+ .suggestion_remove_semicolon = consider removing this semicolon
+
+parse_bounds_not_allowed_on_trait_aliases = bounds are not allowed on trait aliases
+
+parse_trait_alias_cannot_be_auto = trait aliases cannot be `auto`
+parse_trait_alias_cannot_be_unsafe = trait aliases cannot be `unsafe`
+
+parse_associated_static_item_not_allowed = associated `static` items are not allowed
+
+parse_extern_crate_name_with_dashes = crate name using dashes are not valid in `extern crate` statements
+ .label = dash-separated idents are not valid
+ .suggestion = if the original crate name uses dashes you need to use underscores in the code
+
+parse_extern_item_cannot_be_const = extern items cannot be `const`
+ .suggestion = try using a static value
+ .note = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+
+parse_const_global_cannot_be_mutable = const globals cannot be mutable
+ .label = cannot be mutable
+ .suggestion = you might want to declare a static instead
+
+parse_missing_const_type = missing type for `{$kind}` item
+ .suggestion = provide a type for the item
+
+parse_enum_struct_mutually_exclusive = `enum` and `struct` are mutually exclusive
+ .suggestion = replace `enum struct` with
+
+parse_unexpected_token_after_struct_name = expected `where`, `{"{"}`, `(`, or `;` after struct name
+parse_unexpected_token_after_struct_name_found_reserved_identifier = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved identifier `{$token}`
+parse_unexpected_token_after_struct_name_found_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found keyword `{$token}`
+parse_unexpected_token_after_struct_name_found_reserved_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved keyword `{$token}`
+parse_unexpected_token_after_struct_name_found_doc_comment = expected `where`, `{"{"}`, `(`, or `;` after struct name, found doc comment `{$token}`
+parse_unexpected_token_after_struct_name_found_other = expected `where`, `{"{"}`, `(`, or `;` after struct name, found `{$token}`
+
+parse_unexpected_self_in_generic_parameters = unexpected keyword `Self` in generic parameters
+ .note = you cannot use `Self` as a generic parameter because it is reserved for associated items
+
+parse_unexpected_default_value_for_lifetime_in_generic_parameters = unexpected default lifetime parameter
+ .label = lifetime parameters cannot have default values
+
+parse_multiple_where_clauses = cannot define duplicate `where` clauses on an item
+ .label = previous `where` clause starts here
+ .suggestion = consider joining the two `where` clauses into one
+
+parse_nonterminal_expected_item_keyword = expected an item keyword
+parse_nonterminal_expected_statement = expected a statement
+parse_nonterminal_expected_ident = expected ident, found `{$token}`
+parse_nonterminal_expected_lifetime = expected a lifetime, found `{$token}`
+
+parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings
+parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters
+parse_sugg_remove_leading_vert_in_pattern = remove the `|`
+parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses
+
+parse_note_pattern_alternatives_use_single_vert = alternatives in or-patterns are separated with `|`, not `||`
+
+parse_unexpected_vert_vert_before_function_parameter = unexpected `||` before function parameter
+ .suggestion = remove the `||`
+
+parse_label_while_parsing_or_pattern_here = while parsing this or-pattern starting here
+
+parse_unexpected_vert_vert_in_pattern = unexpected token `||` in pattern
+ .suggestion = use a single `|` to separate multiple alternative patterns
+
+parse_trailing_vert_not_allowed = a trailing `|` is not allowed in an or-pattern
+ .suggestion = remove the `{$token}`
+
+parse_dotdotdot_rest_pattern = unexpected `...`
+ .label = not a valid pattern
+ .suggestion = for a rest pattern, use `..` instead of `...`
+
+parse_pattern_on_wrong_side_of_at = pattern on wrong side of `@`
+ .label_pattern = pattern on the left, should be on the right
+ .label_binding = binding on the right, should be on the left
+ .suggestion = switch the order
+
+parse_expected_binding_left_of_at = left-hand side of `@` must be a binding
+ .label_lhs = interpreted as a pattern, not a binding
+ .label_rhs = also a pattern
+ .note = bindings are `x`, `mut x`, `ref x`, and `ref mut x`
+
+parse_ambiguous_range_pattern = the range pattern here has ambiguous interpretation
+ .suggestion = add parentheses to clarify the precedence
+
+parse_unexpected_lifetime_in_pattern = unexpected lifetime `{$symbol}` in pattern
+ .suggestion = remove the lifetime
+
+parse_ref_mut_order_incorrect = the order of `mut` and `ref` is incorrect
+ .suggestion = try switching the order
+
+parse_mut_on_nested_ident_pattern = `mut` must be attached to each individual binding
+ .suggestion = add `mut` to each binding
+parse_mut_on_non_ident_pattern = `mut` must be followed by a named binding
+ .suggestion = remove the `mut` prefix
+parse_note_mut_pattern_usage = `mut` may be followed by `variable` and `variable @ pattern`
+
+parse_repeated_mut_in_pattern = `mut` on a binding may not be repeated
+ .suggestion = remove the additional `mut`s
+
+parse_dot_dot_dot_range_to_pattern_not_allowed = range-to patterns with `...` are not allowed
+ .suggestion = use `..=` instead
+
+parse_enum_pattern_instead_of_identifier = expected identifier, found enum pattern
+
+parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `{$token_str}`
+ .suggestion = to omit remaining fields, use `..`
+
+parse_expected_comma_after_pattern_field = expected `,`
+
+parse_return_types_use_thin_arrow = return types are denoted using `->`
+ .suggestion = use `->` instead
+
+parse_need_plus_after_trait_object_lifetime = lifetime in trait object type must be followed by `+`
+
+parse_expected_mut_or_const_in_raw_pointer_type = expected `mut` or `const` keyword in raw pointer type
+ .suggestion = add `mut` or `const` here
+
+parse_lifetime_after_mut = lifetime must precede `mut`
+ .suggestion = place the lifetime before `mut`
+
+parse_dyn_after_mut = `mut` must precede `dyn`
+ .suggestion = place `mut` before `dyn`
+
+parse_fn_pointer_cannot_be_const = an `fn` pointer type cannot be `const`
+ .label = `const` because of this
+ .suggestion = remove the `const` qualifier
+
+parse_fn_pointer_cannot_be_async = an `fn` pointer type cannot be `async`
+ .label = `async` because of this
+ .suggestion = remove the `async` qualifier
+
+parse_nested_c_variadic_type = C-variadic type `...` may not be nested inside another type
+
+parse_invalid_dyn_keyword = invalid `dyn` keyword
+ .help = `dyn` is only needed at the start of a trait `+`-separated list
+ .suggestion = remove this keyword
+
+parse_negative_bounds_not_supported = negative bounds are not supported
+ .label = negative bounds are not supported
+ .suggestion = {$num_bounds ->
+ [one] remove the bound
+ *[other] remove the bounds
+ }
+
+parse_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
+parse_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
+parse_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
`rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits.
.label = only adts, extern types and traits are supported
+passes_both_ffi_const_and_pure =
+ `#[ffi_const]` function cannot be `#[ffi_pure]`
+
+passes_ffi_pure_invalid_target =
+ `#[ffi_pure]` may only be used on foreign functions
+
+passes_ffi_const_invalid_target =
+ `#[ffi_const]` may only be used on foreign functions
+
+passes_ffi_returns_twice_invalid_target =
+ `#[ffi_returns_twice]` may only be used on foreign functions
+
passes_must_use_async =
`must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within
.label = this attribute does nothing, the `Future`s returned by async functions are already `must_use`
passes_proc_macro_invalid_abi = proc macro functions may not be `extern "{$abi}"`
passes_proc_macro_unsafe = proc macro functions may not be `unsafe`
+
+passes_skipping_const_checks = skipping const checks
session_invalid_int_literal_width = invalid width `{$width}` for integer literal
.help = valid widths are 8, 16, 32, 64 and 128
+
+session_optimization_fuel_exhausted = optimization-fuel-exhausted: {$msg}
expand => "../locales/en-US/expand.ftl",
hir_analysis => "../locales/en-US/hir_analysis.ftl",
hir_typeck => "../locales/en-US/hir_typeck.ftl",
+ incremental => "../locales/en-US/incremental.ftl",
infer => "../locales/en-US/infer.ftl",
interface => "../locales/en-US/interface.ftl",
lint => "../locales/en-US/lint.ftl",
use rustc_error_messages::fluent_value_from_str_list_sep_by_and;
use rustc_error_messages::FluentValue;
use rustc_lint_defs::{Applicability, LintExpectationId};
-use rustc_span::edition::LATEST_STABLE_EDITION;
use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
use std::borrow::Cow;
self
}
- /// Help the user upgrade to the latest edition.
- /// This is factored out to make sure it does the right thing with `Cargo.toml`.
- pub fn help_use_latest_edition(&mut self) -> &mut Self {
- if std::env::var_os("CARGO").is_some() {
- self.help(&format!("set `edition = \"{}\"` in `Cargo.toml`", LATEST_STABLE_EDITION));
- } else {
- self.help(&format!("pass `--edition {}` to `rustc`", LATEST_STABLE_EDITION));
- }
- self.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
- self
- }
-
/// Disallow attaching suggestions this diagnostic.
/// Any suggestions attached e.g. with the `span_suggestion_*` methods
/// (before and after the call to `disable_suggestions`) will be ignored.
) -> (
&Level,
&[(DiagnosticMessage, Style)],
+ Vec<(&Cow<'static, str>, &DiagnosticArgValue<'static>)>,
&Option<DiagnosticId>,
&MultiSpan,
&Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
(
&self.level,
&self.message,
+ self.args().collect(),
&self.code,
&self.span,
&self.suggestions,
}
}
+impl<'a> DiagnosticBuilder<'a, rustc_span::fatal_error::FatalError> {
+ /// Convenience function for internal use, clients should use one of the
+ /// `struct_*` methods on [`Handler`].
+ #[track_caller]
+ pub(crate) fn new_almost_fatal(
+ handler: &'a Handler,
+ message: impl Into<DiagnosticMessage>,
+ ) -> Self {
+ let diagnostic = Diagnostic::new_with_code(Level::Fatal, None, message);
+ Self::new_diagnostic_almost_fatal(handler, diagnostic)
+ }
+
+ /// Creates a new `DiagnosticBuilder` with an already constructed
+ /// diagnostic.
+ pub(crate) fn new_diagnostic_almost_fatal(
+ handler: &'a Handler,
+ diagnostic: Diagnostic,
+ ) -> Self {
+ debug!("Created new diagnostic");
+ Self {
+ inner: DiagnosticBuilderInner {
+ state: DiagnosticBuilderState::Emittable(handler),
+ diagnostic: Box::new(diagnostic),
+ },
+ _marker: PhantomData,
+ }
+ }
+}
+
+impl EmissionGuarantee for rustc_span::fatal_error::FatalError {
+ fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
+ match db.inner.state {
+ // First `.emit()` call, the `&Handler` is still available.
+ DiagnosticBuilderState::Emittable(handler) => {
+ db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
+
+ handler.emit_diagnostic(&mut db.inner.diagnostic);
+ }
+ // `.emit()` was previously called, disallowed from repeating it.
+ DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
+ }
+ // Then fatally error..
+ rustc_span::fatal_error::FatalError
+ }
+
+ fn make_diagnostic_builder(
+ handler: &Handler,
+ msg: impl Into<DiagnosticMessage>,
+ ) -> DiagnosticBuilder<'_, Self> {
+ DiagnosticBuilder::new_almost_fatal(handler, msg)
+ }
+}
+
/// In general, the `DiagnosticBuilder` uses deref to allow access to
/// the fields and methods of the embedded `diagnostic` in a
/// transparent way. *However,* many of the methods are intended to
sp: impl Into<MultiSpan>,
msg: impl Into<SubdiagnosticMessage>,
) -> &mut Self);
- forward!(pub fn help_use_latest_edition(&mut self,) -> &mut Self);
forward!(pub fn set_is_lint(&mut self,) -> &mut Self);
forward!(pub fn disable_suggestions(&mut self,) -> &mut Self);
}
}
+impl<'a, T: Clone + IntoDiagnosticArg> IntoDiagnosticArg for &'a T {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ self.clone().into_diagnostic_arg()
+ }
+}
+
macro_rules! into_diagnostic_arg_using_display {
($( $ty:ty ),+ $(,)?) => {
$(
}
}
-impl IntoDiagnosticArg for &ast::Path {
- fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
- DiagnosticArgValue::Str(Cow::Owned(pprust::path_to_string(self)))
- }
-}
-
impl IntoDiagnosticArg for ast::token::Token {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
DiagnosticArgValue::Str(pprust::token_to_string(&self))
}
}
+impl IntoDiagnosticArg for std::ffi::CString {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned()))
+ }
+}
+
+impl IntoDiagnosticArg for rustc_data_structures::small_c_str::SmallCStr {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned()))
+ }
+}
+
+impl IntoDiagnosticArg for ast::Visibility {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ let s = pprust::vis_to_string(&self);
+ let s = s.trim_end().to_string();
+ DiagnosticArgValue::Str(Cow::Owned(s))
+ }
+}
+
impl IntoDiagnosticArg for Level {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
DiagnosticArgValue::Str(Cow::Borrowed(self.to_cmd_flag()))
}
}
for sugg in suggestions {
- if sugg.style == SuggestionStyle::CompletelyHidden {
- // do not display this suggestion, it is meant only for tools
- } else if sugg.style == SuggestionStyle::HideCodeAlways {
- if let Err(e) = self.emit_message_default(
- &MultiSpan::new(),
- &[(sugg.msg.to_owned(), Style::HeaderMsg)],
- args,
- &None,
- &Level::Help,
- max_line_num_len,
- true,
- None,
- ) {
- panic!("failed to emit error: {}", e);
+ match sugg.style {
+ SuggestionStyle::CompletelyHidden => {
+ // do not display this suggestion, it is meant only for tools
}
- } else if let Err(e) = self.emit_suggestion_default(
- span,
- sugg,
- args,
- &Level::Help,
- max_line_num_len,
- ) {
- panic!("failed to emit error: {}", e);
- };
+ SuggestionStyle::HideCodeAlways => {
+ if let Err(e) = self.emit_message_default(
+ &MultiSpan::new(),
+ &[(sugg.msg.to_owned(), Style::HeaderMsg)],
+ args,
+ &None,
+ &Level::Help,
+ max_line_num_len,
+ true,
+ None,
+ ) {
+ panic!("failed to emit error: {}", e);
+ }
+ }
+ SuggestionStyle::HideCodeInline
+ | SuggestionStyle::ShowCode
+ | SuggestionStyle::ShowAlways => {
+ if let Err(e) = self.emit_suggestion_default(
+ span,
+ sugg,
+ args,
+ &Level::Help,
+ max_line_num_len,
+ ) {
+ panic!("failed to emit error: {}", e);
+ }
+ }
+ }
}
}
}
}
}
- /// Translate `message` eagerly with `args`.
+ /// Translate `message` eagerly with `args` to `SubdiagnosticMessage::Eager`.
pub fn eagerly_translate<'a>(
&self,
message: DiagnosticMessage,
args: impl Iterator<Item = DiagnosticArg<'a, 'static>>,
) -> SubdiagnosticMessage {
+ SubdiagnosticMessage::Eager(self.eagerly_translate_to_string(message, args))
+ }
+
+ /// Translate `message` eagerly with `args` to `String`.
+ pub fn eagerly_translate_to_string<'a>(
+ &self,
+ message: DiagnosticMessage,
+ args: impl Iterator<Item = DiagnosticArg<'a, 'static>>,
+ ) -> String {
let inner = self.inner.borrow();
let args = crate::translation::to_fluent_args(args);
- SubdiagnosticMessage::Eager(
- inner
- .emitter
- .translate_message(&message, &args)
- .map_err(Report::new)
- .unwrap()
- .to_string(),
- )
+ inner.emitter.translate_message(&message, &args).map_err(Report::new).unwrap().to_string()
}
// This is here to not allow mutation of flags;
}
#[track_caller]
+ #[rustc_lint_diagnostics]
pub fn span_note_without_error(
&self,
span: impl Into<MultiSpan>,
}
#[track_caller]
+ #[rustc_lint_diagnostics]
pub fn span_note_diag(
&self,
span: Span,
}
// NOTE: intentionally doesn't raise an error so rustc_codegen_ssa only reports fatal errors in the main thread
+ #[rustc_lint_diagnostics]
pub fn fatal(&self, msg: impl Into<DiagnosticMessage>) -> FatalError {
self.inner.borrow_mut().fatal(msg)
}
+ #[rustc_lint_diagnostics]
pub fn err(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
self.inner.borrow_mut().err(msg)
}
+ #[rustc_lint_diagnostics]
pub fn warn(&self, msg: impl Into<DiagnosticMessage>) {
let mut db = DiagnosticBuilder::new(self, Warning(None), msg);
db.emit();
}
+ #[rustc_lint_diagnostics]
pub fn note_without_error(&self, msg: impl Into<DiagnosticMessage>) {
DiagnosticBuilder::new(self, Note, msg).emit();
}
pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
if self.inner.borrow().has_errors() { Some(ErrorGuaranteed(())) } else { None }
}
+
pub fn has_errors_or_lint_errors(&self) -> Option<ErrorGuaranteed> {
if self.inner.borrow().has_errors_or_lint_errors() {
Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
self.create_warning(warning).emit()
}
+ pub fn create_almost_fatal<'a>(
+ &'a self,
+ fatal: impl IntoDiagnostic<'a, FatalError>,
+ ) -> DiagnosticBuilder<'a, FatalError> {
+ fatal.into_diagnostic(self)
+ }
+
+ pub fn emit_almost_fatal<'a>(
+ &'a self,
+ fatal: impl IntoDiagnostic<'a, FatalError>,
+ ) -> FatalError {
+ self.create_almost_fatal(fatal).emit()
+ }
+
pub fn create_fatal<'a>(
&'a self,
fatal: impl IntoDiagnostic<'a, !>,
self.create_bug(bug).emit()
}
+ pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted {
+ self.create_note(note).emit()
+ }
+
+ pub fn create_note<'a>(
+ &'a self,
+ note: impl IntoDiagnostic<'a, Noted>,
+ ) -> DiagnosticBuilder<'a, Noted> {
+ note.into_diagnostic(self)
+ }
+
fn emit_diag_at_span(
&self,
mut diag: Diagnostic,
pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) {
if let Some(ref mut line) = self.lines.get_mut(line) {
if let Some(StyledChar { style: s, .. }) = line.get_mut(col) {
- if overwrite || *s == Style::NoStyle || *s == Style::Quotation {
+ if overwrite || matches!(s, Style::NoStyle | Style::Quotation) {
*s = style;
}
}
#![deny(rustc::untranslatable_diagnostic)]
-use crate::errors::{
- ArgumentNotAttributes, AttrNoArguments, AttributeMetaItem, AttributeSingleWord,
- AttributesWrongForm, CannotBeNameOfMacro, ExpectedCommaInList, HelperAttributeNameInvalid,
- MacroBodyStability, MacroConstStability, NotAMetaItem, OnlyOneArgument, OnlyOneWord,
- ResolveRelativePath, TakesNoArguments,
-};
+use crate::errors;
use crate::expand::{self, AstFragment, Invocation};
use crate::module::DirOwnership;
.unwrap_or_else(|| (None, helper_attrs));
let (stability, const_stability, body_stability) = attr::find_stability(&sess, attrs, span);
if let Some((_, sp)) = const_stability {
- sess.emit_err(MacroConstStability {
+ sess.emit_err(errors::MacroConstStability {
span: sp,
head_span: sess.source_map().guess_head_span(span),
});
}
if let Some((_, sp)) = body_stability {
- sess.emit_err(MacroBodyStability {
+ sess.emit_err(errors::MacroBodyStability {
span: sp,
head_span: sess.source_map().guess_head_span(span),
});
self.sess.parse_sess.span_diagnostic.span_bug(sp, msg);
}
pub fn trace_macros_diag(&mut self) {
- for (sp, notes) in self.expansions.iter() {
- let mut db = self.sess.parse_sess.span_diagnostic.span_note_diag(*sp, "trace_macro");
+ for (span, notes) in self.expansions.iter() {
+ let mut db = self.sess.parse_sess.create_note(errors::TraceMacro { span: *span });
for note in notes {
db.note(note);
}
.expect("attempting to resolve a file path in an external file"),
FileName::DocTest(path, _) => path,
other => {
- return Err(ResolveRelativePath {
+ return Err(errors::ResolveRelativePath {
span,
path: parse_sess.source_map().filename_for_diagnostics(&other).to_string(),
}
/// done as rarely as possible).
pub fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, name: &str) {
if !tts.is_empty() {
- cx.emit_err(TakesNoArguments { span, name });
+ cx.emit_err(errors::TakesNoArguments { span, name });
}
}
) -> Option<Symbol> {
let mut p = cx.new_parser_from_tts(tts);
if p.token == token::Eof {
- cx.emit_err(OnlyOneArgument { span, name });
+ cx.emit_err(errors::OnlyOneArgument { span, name });
return None;
}
let ret = parse_expr(&mut p)?;
let _ = p.eat(&token::Comma);
if p.token != token::Eof {
- cx.emit_err(OnlyOneArgument { span, name });
+ cx.emit_err(errors::OnlyOneArgument { span, name });
}
expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s)
}
continue;
}
if p.token != token::Eof {
- cx.emit_err(ExpectedCommaInList { span: p.token.span });
+ cx.emit_err(errors::ExpectedCommaInList { span: p.token.span });
return None;
}
}
// `#[proc_macro_derive(Foo, attributes(A, ..))]`
let list = attr.meta_item_list()?;
if list.len() != 1 && list.len() != 2 {
- diag.emit_err(AttrNoArguments { span: attr.span });
+ diag.emit_err(errors::AttrNoArguments { span: attr.span });
return None;
}
let Some(trait_attr) = list[0].meta_item() else {
- diag.emit_err(NotAMetaItem {span: list[0].span()});
+ diag.emit_err(errors::NotAMetaItem {span: list[0].span()});
return None;
};
let trait_ident = match trait_attr.ident() {
Some(trait_ident) if trait_attr.is_word() => trait_ident,
_ => {
- diag.emit_err(OnlyOneWord { span: trait_attr.span });
+ diag.emit_err(errors::OnlyOneWord { span: trait_attr.span });
return None;
}
};
if !trait_ident.name.can_be_raw() {
- diag.emit_err(CannotBeNameOfMacro { span: trait_attr.span, trait_ident, macro_type });
+ diag.emit_err(errors::CannotBeNameOfMacro {
+ span: trait_attr.span,
+ trait_ident,
+ macro_type,
+ });
}
let attributes_attr = list.get(1);
let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
if !attr.has_name(sym::attributes) {
- diag.emit_err(ArgumentNotAttributes { span: attr.span() });
+ diag.emit_err(errors::ArgumentNotAttributes { span: attr.span() });
}
attr.meta_item_list()
.unwrap_or_else(|| {
- diag.emit_err(AttributesWrongForm { span: attr.span() });
+ diag.emit_err(errors::AttributesWrongForm { span: attr.span() });
&[]
})
.iter()
.filter_map(|attr| {
let Some(attr) = attr.meta_item() else {
- diag.emit_err(AttributeMetaItem { span: attr.span() });
+ diag.emit_err(errors::AttributeMetaItem { span: attr.span() });
return None;
};
let ident = match attr.ident() {
Some(ident) if attr.is_word() => ident,
_ => {
- diag.emit_err(AttributeSingleWord { span: attr.span });
+ diag.emit_err(errors::AttributeSingleWord { span: attr.span });
return None;
}
};
if !ident.name.can_be_raw() {
- diag.emit_err(HelperAttributeNameInvalid { span: attr.span, name: ident });
+ diag.emit_err(errors::HelperAttributeNameInvalid {
+ span: attr.span,
+ name: ident,
+ });
}
Some(ident.name)
self.expr(sp, ast::ExprKind::AddrOf(ast::BorrowKind::Ref, ast::Mutability::Not, e))
}
+ pub fn expr_paren(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
+ self.expr(sp, ast::ExprKind::Paren(e))
+ }
+
pub fn expr_call(
&self,
span: Span,
pub default_path: String,
pub secondary_path: String,
}
+
+#[derive(Diagnostic)]
+#[diag(expand_trace_macro)]
+pub struct TraceMacro {
+ #[primary_span]
+ pub span: Span,
+}
mp.push_match(metavar_idx, seq_depth, MatchedSeq(vec![]));
}
- if op == KleeneOp::ZeroOrMore || op == KleeneOp::ZeroOrOne {
+ if matches!(op, KleeneOp::ZeroOrMore | KleeneOp::ZeroOrOne) {
// Try zero matches of this sequence, by skipping over it.
self.cur_mps.push(MatcherPos {
idx: idx_first_after,
use rustc_ast::token::{self, Delimiter};
-use rustc_ast::tokenstream::{CursorRef, TokenStream, TokenTree};
+use rustc_ast::tokenstream::{RefTokenTreeCursor, TokenStream, TokenTree};
use rustc_ast::{LitIntType, LitKind};
use rustc_ast_pretty::pprust;
use rustc_errors::{Applicability, PResult};
// Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}`
fn check_trailing_token<'sess>(
- iter: &mut CursorRef<'_>,
+ iter: &mut RefTokenTreeCursor<'_>,
sess: &'sess ParseSess,
) -> PResult<'sess, ()> {
if let Some(tt) = iter.next() {
/// Parse a meta-variable `count` expression: `count(ident[, depth])`
fn parse_count<'sess>(
- iter: &mut CursorRef<'_>,
+ iter: &mut RefTokenTreeCursor<'_>,
sess: &'sess ParseSess,
span: Span,
) -> PResult<'sess, MetaVarExpr> {
/// Parses the depth used by index(depth) and length(depth).
fn parse_depth<'sess>(
- iter: &mut CursorRef<'_>,
+ iter: &mut RefTokenTreeCursor<'_>,
sess: &'sess ParseSess,
span: Span,
) -> PResult<'sess, usize> {
/// Parses an generic ident
fn parse_ident<'sess>(
- iter: &mut CursorRef<'_>,
+ iter: &mut RefTokenTreeCursor<'_>,
sess: &'sess ParseSess,
span: Span,
) -> PResult<'sess, Ident> {
/// Tries to move the iterator forward returning `true` if there is a comma. If not, then the
/// iterator is not modified and the result is `false`.
-fn try_eat_comma(iter: &mut CursorRef<'_>) -> bool {
+fn try_eat_comma(iter: &mut RefTokenTreeCursor<'_>) -> bool {
if let Some(TokenTree::Token(token::Token { kind: token::Comma, .. }, _)) = iter.look_ahead(0) {
let _ = iter.next();
return true;
/// Allows `#[target_feature(...)]` on aarch64 platforms
(accepted, aarch64_target_feature, "1.61.0", Some(44839), None),
/// Allows using the `efiapi` ABI.
- (accepted, abi_efiapi, "CURRENT_RUSTC_VERSION", Some(65815), None),
+ (accepted, abi_efiapi, "1.68.0", Some(65815), None),
/// Allows the sysV64 ABI to be specified on all platforms
/// instead of just the platforms on which it is the C ABI.
(accepted, abi_sysv64, "1.24.0", Some(36167), None),
/// Allows `crate` in paths.
(accepted, crate_in_paths, "1.30.0", Some(45477), None),
/// Allows rustc to inject a default alloc_error_handler
- (accepted, default_alloc_error_handler, "CURRENT_RUSTC_VERSION", Some(66741), None),
+ (accepted, default_alloc_error_handler, "1.68.0", Some(66741), None),
/// Allows using assigning a default type to type parameters in algebraic data type definitions.
(accepted, default_type_params, "1.0.0", None, None),
/// Allows `#[deprecated]` attribute.
/// Allows access to crate names passed via `--extern` through prelude.
(accepted, extern_prelude, "1.30.0", Some(44660), None),
/// Allows using F16C intrinsics from `core::arch::{x86, x86_64}`.
- (accepted, f16c_target_feature, "CURRENT_RUSTC_VERSION", Some(44839), None),
+ (accepted, f16c_target_feature, "1.68.0", Some(44839), None),
/// Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
(accepted, field_init_shorthand, "1.17.0", Some(37340), None),
/// Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940).
/// Allows `async {}` expressions in const contexts.
(active, const_async_blocks, "1.53.0", Some(85368), None),
/// Allows `const || {}` closures in const contexts.
- (incomplete, const_closures, "CURRENT_RUSTC_VERSION", Some(106003), None),
+ (incomplete, const_closures, "1.68.0", Some(106003), None),
/// Allows limiting the evaluation steps of const expressions
(active, const_eval_limit, "1.43.0", Some(67217), None),
/// Allows the definition of `const extern fn` and `const unsafe extern fn`.
pub defaultness: Defaultness,
}
-impl TraitItem<'_> {
+impl<'hir> TraitItem<'hir> {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
pub fn trait_item_id(&self) -> TraitItemId {
TraitItemId { owner_id: self.owner_id }
}
+
+ /// Expect an [`TraitItemKind::Const`] or panic.
+ #[track_caller]
+ pub fn expect_const(&self) -> (&'hir Ty<'hir>, Option<BodyId>) {
+ let TraitItemKind::Const(ty, body) = self.kind else { self.expect_failed("a constant") };
+ (ty, body)
+ }
+
+ /// Expect an [`TraitItemKind::Fn`] or panic.
+ #[track_caller]
+ pub fn expect_fn(&self) -> (&FnSig<'hir>, &TraitFn<'hir>) {
+ let TraitItemKind::Fn(ty, trfn) = &self.kind else { self.expect_failed("a function") };
+ (ty, trfn)
+ }
+
+ /// Expect an [`TraitItemKind::Type`] or panic.
+ #[track_caller]
+ pub fn expect_type(&self) -> (GenericBounds<'hir>, Option<&'hir Ty<'hir>>) {
+ let TraitItemKind::Type(bounds, ty) = self.kind else { self.expect_failed("a type") };
+ (bounds, ty)
+ }
+
+ #[track_caller]
+ fn expect_failed(&self, expected: &'static str) -> ! {
+ panic!("expected {expected} item, found {self:?}")
+ }
}
/// Represents a trait method's body (or just argument names).
pub vis_span: Span,
}
-impl ImplItem<'_> {
+impl<'hir> ImplItem<'hir> {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
pub fn impl_item_id(&self) -> ImplItemId {
ImplItemId { owner_id: self.owner_id }
}
+
+ /// Expect an [`ImplItemKind::Const`] or panic.
+ #[track_caller]
+ pub fn expect_const(&self) -> (&'hir Ty<'hir>, BodyId) {
+ let ImplItemKind::Const(ty, body) = self.kind else { self.expect_failed("a constant") };
+ (ty, body)
+ }
+
+ /// Expect an [`ImplItemKind::Fn`] or panic.
+ #[track_caller]
+ pub fn expect_fn(&self) -> (&FnSig<'hir>, BodyId) {
+ let ImplItemKind::Fn(ty, body) = &self.kind else { self.expect_failed("a function") };
+ (ty, *body)
+ }
+
+ /// Expect an [`ImplItemKind::Type`] or panic.
+ #[track_caller]
+ pub fn expect_type(&self) -> &'hir Ty<'hir> {
+ let ImplItemKind::Type(ty) = self.kind else { self.expect_failed("a type") };
+ ty
+ }
+
+ #[track_caller]
+ fn expect_failed(&self, expected: &'static str) -> ! {
+ panic!("expected {expected} item, found {self:?}")
+ }
}
/// Represents various kinds of content within an `impl`.
pub vis_span: Span,
}
-impl Item<'_> {
+impl<'hir> Item<'hir> {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
pub fn item_id(&self) -> ItemId {
ItemId { owner_id: self.owner_id }
}
+
+ /// Expect an [`ItemKind::ExternCrate`] or panic.
+ #[track_caller]
+ pub fn expect_extern_crate(&self) -> Option<Symbol> {
+ let ItemKind::ExternCrate(s) = self.kind else { self.expect_failed("an extern crate") };
+ s
+ }
+
+ /// Expect an [`ItemKind::Use`] or panic.
+ #[track_caller]
+ pub fn expect_use(&self) -> (&'hir UsePath<'hir>, UseKind) {
+ let ItemKind::Use(p, uk) = self.kind else { self.expect_failed("a use") };
+ (p, uk)
+ }
+
+ /// Expect an [`ItemKind::Static`] or panic.
+ #[track_caller]
+ pub fn expect_static(&self) -> (&'hir Ty<'hir>, Mutability, BodyId) {
+ let ItemKind::Static(ty, mutbl, body) = self.kind else { self.expect_failed("a static") };
+ (ty, mutbl, body)
+ }
+ /// Expect an [`ItemKind::Const`] or panic.
+ #[track_caller]
+ pub fn expect_const(&self) -> (&'hir Ty<'hir>, BodyId) {
+ let ItemKind::Const(ty, body) = self.kind else { self.expect_failed("a constant") };
+ (ty, body)
+ }
+ /// Expect an [`ItemKind::Fn`] or panic.
+ #[track_caller]
+ pub fn expect_fn(&self) -> (&FnSig<'hir>, &'hir Generics<'hir>, BodyId) {
+ let ItemKind::Fn(sig, gen, body) = &self.kind else { self.expect_failed("a function") };
+ (sig, gen, *body)
+ }
+
+ /// Expect an [`ItemKind::Macro`] or panic.
+ #[track_caller]
+ pub fn expect_macro(&self) -> (&ast::MacroDef, MacroKind) {
+ let ItemKind::Macro(def, mk) = &self.kind else { self.expect_failed("a macro") };
+ (def, *mk)
+ }
+
+ /// Expect an [`ItemKind::Mod`] or panic.
+ #[track_caller]
+ pub fn expect_mod(&self) -> &'hir Mod<'hir> {
+ let ItemKind::Mod(m) = self.kind else { self.expect_failed("a module") };
+ m
+ }
+
+ /// Expect an [`ItemKind::ForeignMod`] or panic.
+ #[track_caller]
+ pub fn expect_foreign_mod(&self) -> (Abi, &'hir [ForeignItemRef]) {
+ let ItemKind::ForeignMod { abi, items } = self.kind else { self.expect_failed("a foreign module") };
+ (abi, items)
+ }
+
+ /// Expect an [`ItemKind::GlobalAsm`] or panic.
+ #[track_caller]
+ pub fn expect_global_asm(&self) -> &'hir InlineAsm<'hir> {
+ let ItemKind::GlobalAsm(asm) = self.kind else { self.expect_failed("a global asm") };
+ asm
+ }
+
+ /// Expect an [`ItemKind::TyAlias`] or panic.
+ #[track_caller]
+ pub fn expect_ty_alias(&self) -> (&'hir Ty<'hir>, &'hir Generics<'hir>) {
+ let ItemKind::TyAlias(ty, gen) = self.kind else { self.expect_failed("a type alias") };
+ (ty, gen)
+ }
+
+ /// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`.
+ /// Expect an [`ItemKind::OpaqueTy`] or panic.
+ #[track_caller]
+ pub fn expect_opaque_ty(&self) -> &OpaqueTy<'hir> {
+ let ItemKind::OpaqueTy(ty) = &self.kind else { self.expect_failed("an opaque type") };
+ ty
+ }
+
+ /// Expect an [`ItemKind::Enum`] or panic.
+ #[track_caller]
+ pub fn expect_enum(&self) -> (&EnumDef<'hir>, &'hir Generics<'hir>) {
+ let ItemKind::Enum(def, gen) = &self.kind else { self.expect_failed("an enum") };
+ (def, gen)
+ }
+
+ /// Expect an [`ItemKind::Struct`] or panic.
+ #[track_caller]
+ pub fn expect_struct(&self) -> (&VariantData<'hir>, &'hir Generics<'hir>) {
+ let ItemKind::Struct(data, gen) = &self.kind else { self.expect_failed("a struct") };
+ (data, gen)
+ }
+
+ /// A union definition, e.g., `union Foo<A, B> {x: A, y: B}`.
+ /// Expect an [`ItemKind::Union`] or panic.
+ #[track_caller]
+ pub fn expect_union(&self) -> (&VariantData<'hir>, &'hir Generics<'hir>) {
+ let ItemKind::Union(data, gen) = &self.kind else { self.expect_failed("a union") };
+ (data, gen)
+ }
+
+ /// Expect an [`ItemKind::Trait`] or panic.
+ #[track_caller]
+ pub fn expect_trait(
+ self,
+ ) -> (IsAuto, Unsafety, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]) {
+ let ItemKind::Trait(is_auto, unsafety, gen, bounds, items) = self.kind else { self.expect_failed("a trait") };
+ (is_auto, unsafety, gen, bounds, items)
+ }
+
+ /// Expect an [`ItemKind::TraitAlias`] or panic.
+ #[track_caller]
+ pub fn expect_trait_alias(&self) -> (&'hir Generics<'hir>, GenericBounds<'hir>) {
+ let ItemKind::TraitAlias(gen, bounds) = self.kind else { self.expect_failed("a trait alias") };
+ (gen, bounds)
+ }
+
+ /// Expect an [`ItemKind::Impl`] or panic.
+ #[track_caller]
+ pub fn expect_impl(&self) -> &'hir Impl<'hir> {
+ let ItemKind::Impl(imp) = self.kind else { self.expect_failed("an impl") };
+ imp
+ }
+
+ #[track_caller]
+ fn expect_failed(&self, expected: &'static str) -> ! {
+ panic!("expected {expected} item, found {self:?}")
+ }
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub fn tuple_fields(&self) -> Option<&'hir [FieldDef<'hir>]> {
if let Node::Ctor(&VariantData::Tuple(fields, _, _)) = self { Some(fields) } else { None }
}
+
+ /// Expect a [`Node::Param`] or panic.
+ #[track_caller]
+ pub fn expect_param(self) -> &'hir Param<'hir> {
+ let Node::Param(this) = self else { self.expect_failed("a parameter") };
+ this
+ }
+
+ /// Expect a [`Node::Item`] or panic.
+ #[track_caller]
+ pub fn expect_item(self) -> &'hir Item<'hir> {
+ let Node::Item(this) = self else { self.expect_failed("a item") };
+ this
+ }
+
+ /// Expect a [`Node::ForeignItem`] or panic.
+ #[track_caller]
+ pub fn expect_foreign_item(self) -> &'hir ForeignItem<'hir> {
+ let Node::ForeignItem(this) = self else { self.expect_failed("a foreign item") };
+ this
+ }
+
+ /// Expect a [`Node::TraitItem`] or panic.
+ #[track_caller]
+ pub fn expect_trait_item(self) -> &'hir TraitItem<'hir> {
+ let Node::TraitItem(this) = self else { self.expect_failed("a trait item") };
+ this
+ }
+
+ /// Expect a [`Node::ImplItem`] or panic.
+ #[track_caller]
+ pub fn expect_impl_item(self) -> &'hir ImplItem<'hir> {
+ let Node::ImplItem(this) = self else { self.expect_failed("an implementation item") };
+ this
+ }
+
+ /// Expect a [`Node::Variant`] or panic.
+ #[track_caller]
+ pub fn expect_variant(self) -> &'hir Variant<'hir> {
+ let Node::Variant(this) = self else { self.expect_failed("a variant") };
+ this
+ }
+
+ /// Expect a [`Node::Field`] or panic.
+ #[track_caller]
+ pub fn expect_field(self) -> &'hir FieldDef<'hir> {
+ let Node::Field(this) = self else { self.expect_failed("a field definition") };
+ this
+ }
+
+ /// Expect a [`Node::AnonConst`] or panic.
+ #[track_caller]
+ pub fn expect_anon_const(self) -> &'hir AnonConst {
+ let Node::AnonConst(this) = self else { self.expect_failed("an anonymous constant") };
+ this
+ }
+
+ /// Expect a [`Node::Expr`] or panic.
+ #[track_caller]
+ pub fn expect_expr(self) -> &'hir Expr<'hir> {
+ let Node::Expr(this) = self else { self.expect_failed("an expression") };
+ this
+ }
+ /// Expect a [`Node::ExprField`] or panic.
+ #[track_caller]
+ pub fn expect_expr_field(self) -> &'hir ExprField<'hir> {
+ let Node::ExprField(this) = self else { self.expect_failed("an expression field") };
+ this
+ }
+
+ /// Expect a [`Node::Stmt`] or panic.
+ #[track_caller]
+ pub fn expect_stmt(self) -> &'hir Stmt<'hir> {
+ let Node::Stmt(this) = self else { self.expect_failed("a statement") };
+ this
+ }
+
+ /// Expect a [`Node::PathSegment`] or panic.
+ #[track_caller]
+ pub fn expect_path_segment(self) -> &'hir PathSegment<'hir> {
+ let Node::PathSegment(this) = self else { self.expect_failed("a path segment") };
+ this
+ }
+
+ /// Expect a [`Node::Ty`] or panic.
+ #[track_caller]
+ pub fn expect_ty(self) -> &'hir Ty<'hir> {
+ let Node::Ty(this) = self else { self.expect_failed("a type") };
+ this
+ }
+
+ /// Expect a [`Node::TypeBinding`] or panic.
+ #[track_caller]
+ pub fn expect_type_binding(self) -> &'hir TypeBinding<'hir> {
+ let Node::TypeBinding(this) = self else { self.expect_failed("a type binding") };
+ this
+ }
+
+ /// Expect a [`Node::TraitRef`] or panic.
+ #[track_caller]
+ pub fn expect_trait_ref(self) -> &'hir TraitRef<'hir> {
+ let Node::TraitRef(this) = self else { self.expect_failed("a trait reference") };
+ this
+ }
+
+ /// Expect a [`Node::Pat`] or panic.
+ #[track_caller]
+ pub fn expect_pat(self) -> &'hir Pat<'hir> {
+ let Node::Pat(this) = self else { self.expect_failed("a pattern") };
+ this
+ }
+
+ /// Expect a [`Node::PatField`] or panic.
+ #[track_caller]
+ pub fn expect_pat_field(self) -> &'hir PatField<'hir> {
+ let Node::PatField(this) = self else { self.expect_failed("a pattern field") };
+ this
+ }
+
+ /// Expect a [`Node::Arm`] or panic.
+ #[track_caller]
+ pub fn expect_arm(self) -> &'hir Arm<'hir> {
+ let Node::Arm(this) = self else { self.expect_failed("an arm") };
+ this
+ }
+
+ /// Expect a [`Node::Block`] or panic.
+ #[track_caller]
+ pub fn expect_block(self) -> &'hir Block<'hir> {
+ let Node::Block(this) = self else { self.expect_failed("a block") };
+ this
+ }
+
+ /// Expect a [`Node::Local`] or panic.
+ #[track_caller]
+ pub fn expect_local(self) -> &'hir Local<'hir> {
+ let Node::Local(this) = self else { self.expect_failed("a local") };
+ this
+ }
+
+ /// Expect a [`Node::Ctor`] or panic.
+ #[track_caller]
+ pub fn expect_ctor(self) -> &'hir VariantData<'hir> {
+ let Node::Ctor(this) = self else { self.expect_failed("a constructor") };
+ this
+ }
+
+ /// Expect a [`Node::Lifetime`] or panic.
+ #[track_caller]
+ pub fn expect_lifetime(self) -> &'hir Lifetime {
+ let Node::Lifetime(this) = self else { self.expect_failed("a lifetime") };
+ this
+ }
+
+ /// Expect a [`Node::GenericParam`] or panic.
+ #[track_caller]
+ pub fn expect_generic_param(self) -> &'hir GenericParam<'hir> {
+ let Node::GenericParam(this) = self else { self.expect_failed("a generic parameter") };
+ this
+ }
+
+ /// Expect a [`Node::Crate`] or panic.
+ #[track_caller]
+ pub fn expect_crate(self) -> &'hir Mod<'hir> {
+ let Node::Crate(this) = self else { self.expect_failed("a crate") };
+ this
+ }
+
+ /// Expect a [`Node::Infer`] or panic.
+ #[track_caller]
+ pub fn expect_infer(self) -> &'hir InferArg {
+ let Node::Infer(this) = self else { self.expect_failed("an infer") };
+ this
+ }
+
+ #[track_caller]
+ fn expect_failed(&self, expected: &'static str) -> ! {
+ panic!("expected {expected} node, found {self:?}")
+ }
}
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
-rustc_graphviz = { path = "../rustc_graphviz" }
rustc_hir = { path = "../rustc_hir" }
-rustc_hir_pretty = { path = "../rustc_hir_pretty" }
rustc_target = { path = "../rustc_target" }
rustc_session = { path = "../rustc_session" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
rustc_infer = { path = "../rustc_infer" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
rustc_lint = { path = "../rustc_lint" }
-rustc_serialize = { path = "../rustc_serialize" }
rustc_type_ir = { path = "../rustc_type_ir" }
rustc_feature = { path = "../rustc_feature" }
) -> GenericArgCountResult {
let empty_args = hir::GenericArgs::none();
let gen_args = seg.args.unwrap_or(&empty_args);
- let gen_pos = if is_method_call == IsMethodCall::Yes {
- GenericArgPosition::MethodCall
- } else {
- GenericArgPosition::Value
+ let gen_pos = match is_method_call {
+ IsMethodCall::Yes => GenericArgPosition::MethodCall,
+ IsMethodCall::No => GenericArgPosition::Value,
};
let has_self = generics.parent.is_none() && generics.has_self;
if r.is_erased() { tcx.lifetimes.re_static } else { r }
});
let span = ast_ty.span;
- tcx.sess.emit_err(TypeofReservedKeywordUsed {
- span,
- ty,
- opt_sugg: Some((span, Applicability::MachineApplicable))
- .filter(|_| ty.is_suggestable(tcx, false)),
- });
+ let (ty, opt_sugg) = if let Some(ty) = ty.make_suggestable(tcx, false) {
+ (ty, Some((span, Applicability::MachineApplicable)))
+ } else {
+ (ty, None)
+ };
+ tcx.sess.emit_err(TypeofReservedKeywordUsed { span, ty, opt_sugg });
ty
}
let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), ident, .. }) =
hir.get(fn_hir_id) else { return None };
- let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(i), .. }) =
- hir.get_parent(fn_hir_id) else { bug!("ImplItem should have Impl parent") };
+ let i = hir.get_parent(fn_hir_id).expect_item().expect_impl();
let trait_ref = self.instantiate_mono_trait_ref(
i.of_trait.as_ref()?,
match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) {
Ok(()) => {}
Err(ty_err) => {
+ let ty_err = ty_err.to_string(tcx);
tcx.sess.delay_span_bug(
span,
&format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"),
};
check_abi(tcx, it.hir_id(), it.span, abi);
- if abi == Abi::RustIntrinsic {
- for item in items {
- let item = tcx.hir().foreign_item(item.id);
- intrinsic::check_intrinsic_type(tcx, item);
- }
- } else if abi == Abi::PlatformIntrinsic {
- for item in items {
- let item = tcx.hir().foreign_item(item.id);
- intrinsic::check_platform_intrinsic_type(tcx, item);
+ match abi {
+ Abi::RustIntrinsic => {
+ for item in items {
+ let item = tcx.hir().foreign_item(item.id);
+ intrinsic::check_intrinsic_type(tcx, item);
+ }
}
- } else {
- for item in items {
- let def_id = item.id.owner_id.def_id;
- let generics = tcx.generics_of(def_id);
- let own_counts = generics.own_counts();
- if generics.params.len() - own_counts.lifetimes != 0 {
- let (kinds, kinds_pl, egs) = match (own_counts.types, own_counts.consts) {
- (_, 0) => ("type", "types", Some("u32")),
- // We don't specify an example value, because we can't generate
- // a valid value for any type.
- (0, _) => ("const", "consts", None),
- _ => ("type or const", "types or consts", None),
- };
- struct_span_err!(
- tcx.sess,
- item.span,
- E0044,
- "foreign items may not have {kinds} parameters",
- )
- .span_label(item.span, &format!("can't have {kinds} parameters"))
- .help(
- // FIXME: once we start storing spans for type arguments, turn this
- // into a suggestion.
- &format!(
- "replace the {} parameters with concrete {}{}",
- kinds,
- kinds_pl,
- egs.map(|egs| format!(" like `{}`", egs)).unwrap_or_default(),
- ),
- )
- .emit();
+
+ Abi::PlatformIntrinsic => {
+ for item in items {
+ let item = tcx.hir().foreign_item(item.id);
+ intrinsic::check_platform_intrinsic_type(tcx, item);
}
+ }
- let item = tcx.hir().foreign_item(item.id);
- match &item.kind {
- hir::ForeignItemKind::Fn(fn_decl, _, _) => {
- require_c_abi_if_c_variadic(tcx, fn_decl, abi, item.span);
+ _ => {
+ for item in items {
+ let def_id = item.id.owner_id.def_id;
+ let generics = tcx.generics_of(def_id);
+ let own_counts = generics.own_counts();
+ if generics.params.len() - own_counts.lifetimes != 0 {
+ let (kinds, kinds_pl, egs) = match (own_counts.types, own_counts.consts)
+ {
+ (_, 0) => ("type", "types", Some("u32")),
+ // We don't specify an example value, because we can't generate
+ // a valid value for any type.
+ (0, _) => ("const", "consts", None),
+ _ => ("type or const", "types or consts", None),
+ };
+ struct_span_err!(
+ tcx.sess,
+ item.span,
+ E0044,
+ "foreign items may not have {kinds} parameters",
+ )
+ .span_label(item.span, &format!("can't have {kinds} parameters"))
+ .help(
+ // FIXME: once we start storing spans for type arguments, turn this
+ // into a suggestion.
+ &format!(
+ "replace the {} parameters with concrete {}{}",
+ kinds,
+ kinds_pl,
+ egs.map(|egs| format!(" like `{}`", egs)).unwrap_or_default(),
+ ),
+ )
+ .emit();
}
- hir::ForeignItemKind::Static(..) => {
- check_static_inhabited(tcx, def_id);
- check_static_linkage(tcx, def_id);
+
+ let item = tcx.hir().foreign_item(item.id);
+ match &item.kind {
+ hir::ForeignItemKind::Fn(fn_decl, _, _) => {
+ require_c_abi_if_c_variadic(tcx, fn_decl, abi, item.span);
+ }
+ hir::ForeignItemKind::Static(..) => {
+ check_static_inhabited(tcx, def_id);
+ check_static_linkage(tcx, def_id);
+ }
+ _ => {}
}
- _ => {}
}
}
}
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit;
-use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
+use rustc_hir::{GenericParamKind, ImplItemKind};
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
// When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the
// span points only at the type `Box<Self`>, but we want to cover the whole
// argument pattern and type.
- let ImplItemKind::Fn(ref sig, body) = tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind else { bug!("{impl_m:?} is not a method") };
+ let (sig, body) = tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
let span = tcx
.hir()
.body_param_names(body)
) -> (Span, Option<Span>) {
let tcx = infcx.tcx;
let mut impl_args = {
- let ImplItemKind::Fn(sig, _) = &tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind else { bug!("{:?} is not a method", impl_m) };
+ let (sig, _) = tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
};
let trait_args = trait_m.def_id.as_local().map(|def_id| {
- let TraitItemKind::Fn(sig, _) = &tcx.hir().expect_trait_item(def_id).kind else { bug!("{:?} is not a TraitItemKind::Fn", trait_m) };
+ let (sig, _) = tcx.hir().expect_trait_item(def_id).expect_fn();
sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
});
.def_id
.as_local()
.and_then(|def_id| {
- let TraitItemKind::Fn(trait_m_sig, _) = &tcx.hir().expect_trait_item(def_id).kind else { bug!("{:?} is not a method", impl_m) };
+ let (trait_m_sig, _) = &tcx.hir().expect_trait_item(def_id).expect_fn();
let pos = trait_number_args.saturating_sub(1);
trait_m_sig.decl.inputs.get(pos).map(|arg| {
if pos == 0 {
})
.or(trait_item_span);
- let ImplItemKind::Fn(impl_m_sig, _) = &tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind else { bug!("{:?} is not a method", impl_m) };
+ let (impl_m_sig, _) = &tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
let pos = impl_number_args.saturating_sub(1);
let impl_span = impl_m_sig
.decl
let _: Option<_> = try {
let impl_m = impl_m.def_id.as_local()?;
let impl_m = tcx.hir().expect_impl_item(impl_m);
- let hir::ImplItemKind::Fn(sig, _) = &impl_m.kind else { unreachable!() };
+ let (sig, _) = impl_m.expect_fn();
let input_tys = sig.decl.inputs;
struct Visitor(Option<Span>, hir::def_id::LocalDefId);
);
// Locate the Span containing just the type of the offending impl
- let ImplItemKind::Const(ty, _) = tcx.hir().expect_impl_item(impl_const_item_def).kind else { bug!("{impl_const_item:?} is not a impl const") };
+ let (ty, _) = tcx.hir().expect_impl_item(impl_const_item_def).expect_const();
cause.span = ty.span;
let mut diag = struct_span_err!(
let trait_c_span = trait_const_item_def.as_local().map(|trait_c_def_id| {
// Add a label to the Span containing just the type of the const
- let TraitItemKind::Const(ty, _) = tcx.hir().expect_trait_item(trait_c_def_id).kind else { bug!("{trait_const_item:?} is not a trait const") };
+ let (ty, _) = tcx.hir().expect_trait_item(trait_c_def_id).expect_const();
ty.span
});
smallvec::SmallVec::with_capacity(defs.count());
InternalSubsts::fill_single(&mut substs, defs, &mut |param, _| match param.kind {
GenericParamDefKind::Type { .. } => {
- let kind = ty::BoundTyKind::Param(param.name);
+ let kind = ty::BoundTyKind::Param(param.def_id, param.name);
let bound_var = ty::BoundVariableKind::Ty(kind);
bound_vars.push(bound_var);
tcx.mk_ty(ty::Bound(
// All field types must be well-formed.
for field in &variant.fields {
let field_id = field.did.expect_local();
- let hir::Node::Field(hir::FieldDef { ty: hir_ty, .. }) = tcx.hir().get_by_def_id(field_id)
- else { bug!() };
+ let hir::FieldDef { ty: hir_ty, .. } =
+ tcx.hir().get_by_def_id(field_id).expect_field();
let ty = wfcx.normalize(hir_ty.span, None, tcx.type_of(field.did));
wfcx.register_wf_obligation(
hir_ty.span,
{
let last = idx == variant.fields.len() - 1;
let field_id = field.did.expect_local();
- let hir::Node::Field(hir::FieldDef { ty: hir_ty, .. }) = tcx.hir().get_by_def_id(field_id)
- else { bug!() };
+ let hir::FieldDef { ty: hir_ty, .. } =
+ tcx.hir().get_by_def_id(field_id).expect_field();
let ty = wfcx.normalize(hir_ty.span, None, tcx.type_of(field.did));
wfcx.register_bound(
traits::ObligationCause::new(
if item.span.is_dummy() {
continue;
}
- let hir::ItemKind::Use(path, _) = item.kind else { unreachable!() };
+ let (path, _) = item.expect_use();
let msg = if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(path.span) {
format!("unused import: `{}`", snippet)
} else {
_ => {}
}
- let ItemKind::Impl(impl_) = tcx.hir().expect_item(impl_did).kind else { bug!("expected Drop impl item") };
+ let impl_ = tcx.hir().expect_item(impl_did).expect_impl();
tcx.sess.emit_err(DropImplOnWrongItem { span: impl_.self_ty.span });
}
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::IgnoreRegions;
use rustc_middle::ty::{
- self, ImplPolarity, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
+ self, AliasKind, ImplPolarity, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
use rustc_session::lint;
use rustc_span::def_id::{DefId, LocalDefId};
// struct B { }
// impl Foo for A { }
// impl Foo for B { }
- // impl !Send for (A, B) { }
+ // impl !Foo for (A, B) { }
// ```
//
// This final impl is legal according to the orphan
tcx.trait_is_auto(trait_def_id)
);
- if tcx.trait_is_auto(trait_def_id) && !trait_def_id.is_local() {
+ if tcx.trait_is_auto(trait_def_id) {
let self_ty = trait_ref.self_ty();
- let opt_self_def_id = match *self_ty.kind() {
- ty::Adt(self_def, _) => Some(self_def.did()),
- ty::Foreign(did) => Some(did),
- _ => None,
- };
- let msg = match opt_self_def_id {
- // We only want to permit nominal types, but not *all* nominal types.
- // They must be local to the current crate, so that people
- // can't do `unsafe impl Send for Rc<SomethingLocal>` or
- // `impl !Send for Box<SomethingLocalAndSend>`.
- Some(self_def_id) => {
- if self_def_id.is_local() {
- None
+ // If the impl is in the same crate as the auto-trait, almost anything
+ // goes.
+ //
+ // impl MyAuto for Rc<Something> {} // okay
+ // impl<T> !MyAuto for *const T {} // okay
+ // impl<T> MyAuto for T {} // okay
+ //
+ // But there is one important exception: implementing for a trait object
+ // is not allowed.
+ //
+ // impl MyAuto for dyn Trait {} // NOT OKAY
+ // impl<T: ?Sized> MyAuto for T {} // NOT OKAY
+ //
+ // With this restriction, it's guaranteed that an auto-trait is
+ // implemented for a trait object if and only if the auto-trait is one
+ // of the trait object's trait bounds (or a supertrait of a bound). In
+ // other words `dyn Trait + AutoTrait` always implements AutoTrait,
+ // while `dyn Trait` never implements AutoTrait.
+ //
+ // This is necessary in order for autotrait bounds on methods of trait
+ // objects to be sound.
+ //
+ // auto trait AutoTrait {}
+ //
+ // trait ObjectSafeTrait {
+ // fn f(&self) where Self: AutoTrait;
+ // }
+ //
+ // We can allow f to be called on `dyn ObjectSafeTrait + AutoTrait`.
+ //
+ // If we didn't deny `impl AutoTrait for dyn Trait`, it would be unsound
+ // for the ObjectSafeTrait shown above to be object safe because someone
+ // could take some type implementing ObjectSafeTrait but not AutoTrait,
+ // unsize it to `dyn ObjectSafeTrait`, and call .f() which has no
+ // concrete implementation (issue #50781).
+ enum LocalImpl {
+ Allow,
+ Disallow { problematic_kind: &'static str },
+ }
+
+ // If the auto-trait is from a dependency, it must only be getting
+ // implemented for a nominal type, and specifically one local to the
+ // current crate.
+ //
+ // impl<T> Sync for MyStruct<T> {} // okay
+ //
+ // impl Sync for Rc<MyStruct> {} // NOT OKAY
+ enum NonlocalImpl {
+ Allow,
+ DisallowBecauseNonlocal,
+ DisallowOther,
+ }
+
+ // Exhaustive match considering that this logic is essential for
+ // soundness.
+ let (local_impl, nonlocal_impl) = match self_ty.kind() {
+ // struct Struct<T>;
+ // impl AutoTrait for Struct<Foo> {}
+ ty::Adt(self_def, _) => (
+ LocalImpl::Allow,
+ if self_def.did().is_local() {
+ NonlocalImpl::Allow
+ } else {
+ NonlocalImpl::DisallowBecauseNonlocal
+ },
+ ),
+
+ // extern { type OpaqueType; }
+ // impl AutoTrait for OpaqueType {}
+ ty::Foreign(did) => (
+ LocalImpl::Allow,
+ if did.is_local() {
+ NonlocalImpl::Allow
} else {
- Some((
- format!(
- "cross-crate traits with a default impl, like `{}`, \
- can only be implemented for a struct/enum type \
- defined in the current crate",
- tcx.def_path_str(trait_def_id)
- ),
- "can't implement cross-crate trait for type in another crate",
- ))
+ NonlocalImpl::DisallowBecauseNonlocal
+ },
+ ),
+
+ // impl AutoTrait for dyn Trait {}
+ ty::Dynamic(..) => (
+ LocalImpl::Disallow { problematic_kind: "trait object" },
+ NonlocalImpl::DisallowOther,
+ ),
+
+ // impl<T> AutoTrait for T {}
+ // impl<T: ?Sized> AutoTrait for T {}
+ ty::Param(..) => (
+ if self_ty.is_sized(tcx, tcx.param_env(def_id)) {
+ LocalImpl::Allow
+ } else {
+ LocalImpl::Disallow { problematic_kind: "generic type" }
+ },
+ NonlocalImpl::DisallowOther,
+ ),
+
+ // trait Id { type This: ?Sized; }
+ // impl<T: ?Sized> Id for T {
+ // type This = T;
+ // }
+ // impl<T: ?Sized> AutoTrait for <T as Id>::This {}
+ ty::Alias(AliasKind::Projection, _) => (
+ LocalImpl::Disallow { problematic_kind: "associated type" },
+ NonlocalImpl::DisallowOther,
+ ),
+
+ // type Opaque = impl Trait;
+ // impl AutoTrait for Opaque {}
+ ty::Alias(AliasKind::Opaque, _) => (
+ LocalImpl::Disallow { problematic_kind: "opaque type" },
+ NonlocalImpl::DisallowOther,
+ ),
+
+ ty::Bool
+ | ty::Char
+ | ty::Int(..)
+ | ty::Uint(..)
+ | ty::Float(..)
+ | ty::Str
+ | ty::Array(..)
+ | ty::Slice(..)
+ | ty::RawPtr(..)
+ | ty::Ref(..)
+ | ty::FnDef(..)
+ | ty::FnPtr(..)
+ | ty::Never
+ | ty::Tuple(..) => (LocalImpl::Allow, NonlocalImpl::DisallowOther),
+
+ ty::Closure(..)
+ | ty::Generator(..)
+ | ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
+ | ty::Bound(..)
+ | ty::Placeholder(..)
+ | ty::Infer(..) => span_bug!(sp, "weird self type for autotrait impl"),
+
+ ty::Error(..) => (LocalImpl::Allow, NonlocalImpl::Allow),
+ };
+
+ if trait_def_id.is_local() {
+ match local_impl {
+ LocalImpl::Allow => {}
+ LocalImpl::Disallow { problematic_kind } => {
+ let msg = format!(
+ "traits with a default impl, like `{trait}`, \
+ cannot be implemented for {problematic_kind} `{self_ty}`",
+ trait = tcx.def_path_str(trait_def_id),
+ );
+ let label = format!(
+ "a trait object implements `{trait}` if and only if `{trait}` \
+ is one of the trait object's trait bounds",
+ trait = tcx.def_path_str(trait_def_id),
+ );
+ let reported =
+ struct_span_err!(tcx.sess, sp, E0321, "{}", msg).note(label).emit();
+ return Err(reported);
}
}
- _ => Some((
- format!(
- "cross-crate traits with a default impl, like `{}`, can \
+ } else {
+ if let Some((msg, label)) = match nonlocal_impl {
+ NonlocalImpl::Allow => None,
+ NonlocalImpl::DisallowBecauseNonlocal => Some((
+ format!(
+ "cross-crate traits with a default impl, like `{}`, \
+ can only be implemented for a struct/enum type \
+ defined in the current crate",
+ tcx.def_path_str(trait_def_id)
+ ),
+ "can't implement cross-crate trait for type in another crate",
+ )),
+ NonlocalImpl::DisallowOther => Some((
+ format!(
+ "cross-crate traits with a default impl, like `{}`, can \
only be implemented for a struct/enum type, not `{}`",
- tcx.def_path_str(trait_def_id),
- self_ty
- ),
- "can't implement cross-crate trait with a default impl for \
- non-struct/enum type",
- )),
- };
-
- if let Some((msg, label)) = msg {
- let reported =
- struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit();
- return Err(reported);
+ tcx.def_path_str(trait_def_id),
+ self_ty
+ ),
+ "can't implement cross-crate trait with a default impl for \
+ non-struct/enum type",
+ )),
+ } {
+ let reported =
+ struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit();
+ return Err(reported);
+ }
}
}
use rustc_errors::struct_span_err;
use rustc_hir as hir;
-use rustc_hir::def::DefKind;
use rustc_hir::Unsafety;
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::LocalDefId;
pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
- debug_assert!(matches!(tcx.def_kind(def_id), DefKind::Impl));
let item = tcx.hir().expect_item(def_id);
- let hir::ItemKind::Impl(impl_) = item.kind else { bug!() };
+ let impl_ = item.expect_impl();
if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) {
let trait_ref = trait_ref.subst_identity();
visitor.visit_ty(ty);
let mut diag = bad_placeholder(tcx, visitor.0, "return type");
let ret_ty = fn_sig.output();
- if ret_ty.is_suggestable(tcx, false) {
+ if let Some(ret_ty) = ret_ty.make_suggestable(tcx, false) {
diag.span_suggestion(
ty.span,
"replace with the correct return type",
ret_ty,
Applicability::MachineApplicable,
);
- } else if matches!(ret_ty.kind(), ty::FnDef(..)) {
- let fn_sig = ret_ty.fn_sig(tcx);
- if fn_sig
- .skip_binder()
- .inputs_and_output
- .iter()
- .all(|t| t.is_suggestable(tcx, false))
- {
- diag.span_suggestion(
- ty.span,
- "replace with the correct return type",
- fn_sig,
- Applicability::MachineApplicable,
- );
- }
+ } else if matches!(ret_ty.kind(), ty::FnDef(..))
+ && let Some(fn_sig) = ret_ty.fn_sig(tcx).make_suggestable(tcx, false)
+ {
+ diag.span_suggestion(
+ ty.span,
+ "replace with the correct return type",
+ fn_sig,
+ Applicability::MachineApplicable,
+ );
} else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, hir_id, def_id) {
diag.span_suggestion(
ty.span,
let trait_name = tcx.item_name(trait_def_id);
let args_tuple = substs.type_at(1);
let ty::Tuple(types) = *args_tuple.kind() else { return None; };
- if !types.is_suggestable(tcx, false) {
- return None;
- }
+ let types = types.make_suggestable(tcx, false)?;
let maybe_ret =
if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") };
Some(format!(
// FIXME(compiler-errors): We may benefit from resolving regions here.
if ocx.select_where_possible().is_empty()
&& let item_ty = infcx.resolve_vars_if_possible(item_ty)
- && item_ty.is_suggestable(tcx, false)
+ && let Some(item_ty) = item_ty.make_suggestable(tcx, false)
&& let Some(sugg) = formatter(tcx, infcx.resolve_vars_if_possible(substs), trait_def_id, assoc_item_def_id, item_ty)
{
return Some(sugg);
fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::EarlyBinder<ty::TraitRef<'_>>> {
let icx = ItemCtxt::new(tcx, def_id);
- let item = tcx.hir().expect_item(def_id.expect_local());
- let hir::ItemKind::Impl(impl_) = item.kind else { bug!() };
+ let impl_ = tcx.hir().expect_item(def_id.expect_local()).expect_impl();
impl_
.of_trait
.as_ref()
use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::IntTypeExt;
-use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable};
+use rustc_middle::ty::{
+ self, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable,
+};
use rustc_span::symbol::Ident;
use rustc_span::{Span, DUMMY_SP};
) -> Ty<'a> {
// Attempts to make the type nameable by turning FnDefs into FnPtrs.
struct MakeNameable<'tcx> {
- success: bool,
tcx: TyCtxt<'tcx>,
}
- impl<'tcx> MakeNameable<'tcx> {
- fn new(tcx: TyCtxt<'tcx>) -> Self {
- MakeNameable { success: true, tcx }
- }
- }
-
impl<'tcx> TypeFolder<'tcx> for MakeNameable<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
- if !self.success {
- return ty;
- }
-
- match ty.kind() {
+ let ty = match *ty.kind() {
ty::FnDef(def_id, substs) => {
- self.tcx.mk_fn_ptr(self.tcx.fn_sig(*def_id).subst(self.tcx, substs))
+ self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs))
}
- // FIXME: non-capturing closures should also suggest a function pointer
- ty::Closure(..) | ty::Generator(..) => {
- self.success = false;
- ty
- }
- _ => ty.super_fold_with(self),
- }
+ _ => ty,
+ };
+
+ ty.super_fold_with(self)
}
}
suggestions.clear();
}
- // Suggesting unnameable types won't help.
- let mut mk_nameable = MakeNameable::new(tcx);
- let ty = mk_nameable.fold_ty(ty);
- let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
- if let Some(sugg_ty) = sugg_ty {
+ if let Some(ty) = ty.make_suggestable(tcx, false) {
err.span_suggestion(
span,
&format!("provide a type for the {item}", item = kind),
- format!("{colon} {sugg_ty}"),
+ format!("{colon} {ty}"),
Applicability::MachineApplicable,
);
} else {
let mut diag = bad_placeholder(tcx, vec![span], kind);
if !ty.references_error() {
- let mut mk_nameable = MakeNameable::new(tcx);
- let ty = mk_nameable.fold_ty(ty);
- let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
- if let Some(sugg_ty) = sugg_ty {
+ if let Some(ty) = ty.make_suggestable(tcx, false) {
diag.span_suggestion(
span,
"replace with the correct type",
- sugg_ty,
- Applicability::MaybeIncorrect,
+ ty,
+ Applicability::MachineApplicable,
);
} else {
with_forced_trimmed_paths!(diag.span_note(
use rustc_ast_pretty::pprust::{Comments, PrintState};
use rustc_hir as hir;
use rustc_hir::LifetimeParamKind;
-use rustc_hir::{
- BindingAnnotation, ByRef, GenericArg, GenericParam, GenericParamKind, Mutability, Node, Term,
-};
+use rustc_hir::{BindingAnnotation, ByRef, GenericArg, GenericParam, GenericParamKind, Node, Term};
use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier};
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, Ident, IdentPrinter, Symbol};
if by_ref == ByRef::Yes {
self.word_nbsp("ref");
}
- if mutbl == Mutability::Mut {
+ if mutbl.is_mut() {
self.word_nbsp("mut");
}
self.print_ident(ident);
use rustc_middle::ty::{self, Ty, TypeSuperVisitable, TypeVisitor};
use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Span;
+use rustc_span::sym;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::error_reporting::ArgKind;
let trait_def_id = projection.trait_def_id(tcx);
let is_fn = tcx.is_fn_trait(trait_def_id);
- let gen_trait = tcx.require_lang_item(LangItem::Generator, cause_span);
- let is_gen = gen_trait == trait_def_id;
+
+ let gen_trait = tcx.lang_items().gen_trait();
+ let is_gen = gen_trait == Some(trait_def_id);
+
if !is_fn && !is_gen {
debug!("not fn or generator");
return None;
}
- if is_gen {
- // Check that we deduce the signature from the `<_ as std::ops::Generator>::Return`
- // associated item and not yield.
- let return_assoc_item = self.tcx.associated_item_def_ids(gen_trait)[1];
- if return_assoc_item != projection.projection_def_id() {
- debug!("not return assoc item of generator");
- return None;
- }
+ // Check that we deduce the signature from the `<_ as std::ops::Generator>::Return`
+ // associated item and not yield.
+ if is_gen && self.tcx.associated_item(projection.projection_def_id()).name != sym::Return {
+ debug!("not `Return` assoc item of `Generator`");
+ return None;
}
let input_tys = if is_fn {
|| self.suggest_clone_for_ref(err, expr, expr_ty, expected)
|| self.suggest_into(err, expr, expr_ty, expected)
|| self.suggest_floating_point_literal(err, expr, expected)
+ || self.suggest_null_ptr_for_literal_zero_given_to_ptr_arg(err, expr, expected)
|| self.note_result_coercion(err, expr, expected, expr_ty);
if !suggested {
self.point_at_expr_source_of_inferred_type(err, expr, expr_ty, expected, expr.span);
use rustc_errors::{AddToDiagnostic, Applicability, Diagnostic, MultiSpan, SubdiagnosticMessage};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_middle::ty::Ty;
-use rustc_span::{symbol::Ident, Span};
+use rustc_span::{
+ edition::{Edition, LATEST_STABLE_EDITION},
+ symbol::Ident,
+ Span,
+};
#[derive(Diagnostic)]
#[diag(hir_typeck_field_multiply_specified_in_initializer, code = "E0062")]
pub expected_ty: Ty<'tcx>,
pub found_ty: Ty<'tcx>,
}
+
+#[derive(Subdiagnostic)]
+pub enum HelpUseLatestEdition {
+ #[help(hir_typeck_help_set_edition_cargo)]
+ #[note(hir_typeck_note_edition_guide)]
+ Cargo { edition: Edition },
+ #[help(hir_typeck_help_set_edition_standalone)]
+ #[note(hir_typeck_note_edition_guide)]
+ Standalone { edition: Edition },
+}
+
+impl HelpUseLatestEdition {
+ pub fn new() -> Self {
+ let edition = LATEST_STABLE_EDITION;
+ if std::env::var_os("CARGO").is_some() {
+ Self::Cargo { edition }
+ } else {
+ Self::Standalone { edition }
+ }
+ }
+}
use crate::errors::TypeMismatchFruTypo;
use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive};
use crate::errors::{
- FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct,
+ FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct, HelpUseLatestEdition,
YieldExprOutsideOfGenerator,
};
use crate::fatally_break_rust;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{
- pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId,
- ErrorGuaranteed, StashKey,
+ pluralize, struct_span_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder,
+ DiagnosticId, ErrorGuaranteed, StashKey,
};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
// We know by construction that `<expr>.await` is either on Rust 2015
// or results in `ExprKind::Await`. Suggest switching the edition to 2018.
err.note("to `.await` a `Future`, switch to Rust 2018 or later");
- err.help_use_latest_edition();
+ HelpUseLatestEdition::new().add_to_diagnostic(&mut err);
}
err.emit();
None if let Some(e) = self.tainted_by_errors() => self.tcx.ty_error_with_guaranteed(e),
None => {
bug!(
- "no type for node {}: {} in fcx {}",
- id,
+ "no type for node {} in fcx {}",
self.tcx.hir().node_to_string(id),
self.tag()
);
kind: hir::ImplItemKind::Fn(ref sig, ..),
..
}) => Some((&sig.decl, ident, false)),
+ Node::Expr(&hir::Expr {
+ hir_id,
+ kind: hir::ExprKind::Closure(..),
+ ..
+ }) if let Some(Node::Expr(&hir::Expr {
+ hir_id,
+ kind: hir::ExprKind::Call(..),
+ ..
+ })) = self.tcx.hir().find_parent(hir_id) &&
+ let Some(Node::Item(&hir::Item {
+ ident,
+ kind: hir::ItemKind::Fn(ref sig, ..),
+ ..
+ })) = self.tcx.hir().find_parent(hir_id) => {
+ Some((&sig.decl, ident, ident.name != sym::main))
+ },
_ => None,
}
}
--- /dev/null
+use crate::FnCtxt;
+use rustc_hir as hir;
+use rustc_hir::def::Res;
+use rustc_middle::ty::{self, DefIdTree, Ty};
+use rustc_trait_selection::traits;
+
+impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+ /**
+ * Recursively searches for the most-specific blamable expression.
+ * For example, if you have a chain of constraints like:
+ * - want `Vec<i32>: Copy`
+ * - because `Option<Vec<i32>>: Copy` needs `Vec<i32>: Copy` because `impl <T: Copy> Copy for Option<T>`
+ * - because `(Option<Vec<i32>, bool)` needs `Option<Vec<i32>>: Copy` because `impl <A: Copy, B: Copy> Copy for (A, B)`
+ * then if you pass in `(Some(vec![1, 2, 3]), false)`, this helper `point_at_specific_expr_if_possible`
+ * will find the expression `vec![1, 2, 3]` as the "most blameable" reason for this missing constraint.
+ *
+ * This function only updates the error span.
+ */
+ pub fn blame_specific_expr_if_possible(
+ &self,
+ error: &mut traits::FulfillmentError<'tcx>,
+ expr: &'tcx hir::Expr<'tcx>,
+ ) {
+ // Whether it succeeded or failed, it likely made some amount of progress.
+ // In the very worst case, it's just the same `expr` we originally passed in.
+ let expr = match self.blame_specific_expr_if_possible_for_obligation_cause_code(
+ &error.obligation.cause.code(),
+ expr,
+ ) {
+ Ok(expr) => expr,
+ Err(expr) => expr,
+ };
+
+ // Either way, use this expression to update the error span.
+ // If it doesn't overlap the existing span at all, use the original span.
+ // FIXME: It would possibly be better to do this more continuously, at each level...
+ error.obligation.cause.span = expr
+ .span
+ .find_ancestor_in_same_ctxt(error.obligation.cause.span)
+ .unwrap_or(error.obligation.cause.span);
+ }
+
+ fn blame_specific_expr_if_possible_for_obligation_cause_code(
+ &self,
+ obligation_cause_code: &traits::ObligationCauseCode<'tcx>,
+ expr: &'tcx hir::Expr<'tcx>,
+ ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
+ match obligation_cause_code {
+ traits::ObligationCauseCode::ExprBindingObligation(_, _, _, _) => {
+ // This is the "root"; we assume that the `expr` is already pointing here.
+ // Therefore, we return `Ok` so that this `expr` can be refined further.
+ Ok(expr)
+ }
+ traits::ObligationCauseCode::ImplDerivedObligation(impl_derived) => self
+ .blame_specific_expr_if_possible_for_derived_predicate_obligation(
+ impl_derived,
+ expr,
+ ),
+ _ => {
+ // We don't recognize this kind of constraint, so we cannot refine the expression
+ // any further.
+ Err(expr)
+ }
+ }
+ }
+
+ /// We want to achieve the error span in the following example:
+ ///
+ /// ```ignore (just for demonstration)
+ /// struct Burrito<Filling> {
+ /// filling: Filling,
+ /// }
+ /// impl <Filling: Delicious> Delicious for Burrito<Filling> {}
+ /// fn eat_delicious_food<Food: Delicious>(_food: Food) {}
+ ///
+ /// fn will_type_error() {
+ /// eat_delicious_food(Burrito { filling: Kale });
+ /// } // ^--- The trait bound `Kale: Delicious`
+ /// // is not satisfied
+ /// ```
+ ///
+ /// Without calling this function, the error span will cover the entire argument expression.
+ ///
+ /// Before we do any of this logic, we recursively call `point_at_specific_expr_if_possible` on the parent
+ /// obligation. Hence we refine the `expr` "outwards-in" and bail at the first kind of expression/impl we don't recognize.
+ ///
+ /// This function returns a `Result<&Expr, &Expr>` - either way, it returns the `Expr` whose span should be
+ /// reported as an error. If it is `Ok`, then it means it refined successfull. If it is `Err`, then it may be
+ /// only a partial success - but it cannot be refined even further.
+ fn blame_specific_expr_if_possible_for_derived_predicate_obligation(
+ &self,
+ obligation: &traits::ImplDerivedObligationCause<'tcx>,
+ expr: &'tcx hir::Expr<'tcx>,
+ ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
+ // First, we attempt to refine the `expr` for our span using the parent obligation.
+ // If this cannot be done, then we are already stuck, so we stop early (hence the use
+ // of the `?` try operator here).
+ let expr = self.blame_specific_expr_if_possible_for_obligation_cause_code(
+ &*obligation.derived.parent_code,
+ expr,
+ )?;
+
+ // This is the "trait" (meaning, the predicate "proved" by this `impl`) which provides the `Self` type we care about.
+ // For the purposes of this function, we hope that it is a `struct` type, and that our current `expr` is a literal of
+ // that struct type.
+ let impl_trait_self_ref: Option<ty::TraitRef<'tcx>> =
+ self.tcx.impl_trait_ref(obligation.impl_def_id).map(|impl_def| impl_def.skip_binder());
+
+ let Some(impl_trait_self_ref) = impl_trait_self_ref else {
+ // It is possible that this is absent. In this case, we make no progress.
+ return Err(expr);
+ };
+
+ // We only really care about the `Self` type itself, which we extract from the ref.
+ let impl_self_ty: Ty<'tcx> = impl_trait_self_ref.self_ty();
+
+ let impl_predicates: ty::GenericPredicates<'tcx> =
+ self.tcx.predicates_of(obligation.impl_def_id);
+ let Some(impl_predicate_index) = obligation.impl_def_predicate_index else {
+ // We don't have the index, so we can only guess.
+ return Err(expr);
+ };
+
+ if impl_predicate_index >= impl_predicates.predicates.len() {
+ // This shouldn't happen, but since this is only a diagnostic improvement, avoid breaking things.
+ return Err(expr);
+ }
+ let relevant_broken_predicate: ty::PredicateKind<'tcx> =
+ impl_predicates.predicates[impl_predicate_index].0.kind().skip_binder();
+
+ match relevant_broken_predicate {
+ ty::PredicateKind::Clause(ty::Clause::Trait(broken_trait)) => {
+ // ...
+ self.blame_specific_part_of_expr_corresponding_to_generic_param(
+ broken_trait.trait_ref.self_ty().into(),
+ expr,
+ impl_self_ty.into(),
+ )
+ }
+ _ => Err(expr),
+ }
+ }
+
+ /// Drills into `expr` to arrive at the equivalent location of `find_generic_param` in `in_ty`.
+ /// For example, given
+ /// - expr: `(Some(vec![1, 2, 3]), false)`
+ /// - param: `T`
+ /// - in_ty: `(Option<Vec<T>, bool)`
+ /// we would drill until we arrive at `vec![1, 2, 3]`.
+ ///
+ /// If successful, we return `Ok(refined_expr)`. If unsuccesful, we return `Err(partially_refined_expr`),
+ /// which will go as far as possible. For example, given `(foo(), false)` instead, we would drill to
+ /// `foo()` and then return `Err("foo()")`.
+ ///
+ /// This means that you can (and should) use the `?` try operator to chain multiple calls to this
+ /// function with different types, since you can only continue drilling the second time if you
+ /// succeeded the first time.
+ fn blame_specific_part_of_expr_corresponding_to_generic_param(
+ &self,
+ param: ty::GenericArg<'tcx>,
+ expr: &'tcx hir::Expr<'tcx>,
+ in_ty: ty::GenericArg<'tcx>,
+ ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
+ if param == in_ty {
+ // The types match exactly, so we have drilled as far as we can.
+ return Ok(expr);
+ }
+
+ let ty::GenericArgKind::Type(in_ty) = in_ty.unpack() else {
+ return Err(expr);
+ };
+
+ if let (hir::ExprKind::Tup(expr_elements), ty::Tuple(in_ty_elements)) =
+ (&expr.kind, in_ty.kind())
+ {
+ if in_ty_elements.len() != expr_elements.len() {
+ return Err(expr);
+ }
+ // Find out which of `in_ty_elements` refer to `param`.
+ // FIXME: It may be better to take the first if there are multiple,
+ // just so that the error points to a smaller expression.
+ let Some((drill_expr, drill_ty)) = Self::is_iterator_singleton(expr_elements.iter().zip( in_ty_elements.iter()).filter(|(_expr_elem, in_ty_elem)| {
+ Self::find_param_in_ty((*in_ty_elem).into(), param)
+ })) else {
+ // The param is not mentioned, or it is mentioned in multiple indexes.
+ return Err(expr);
+ };
+
+ return self.blame_specific_part_of_expr_corresponding_to_generic_param(
+ param,
+ drill_expr,
+ drill_ty.into(),
+ );
+ }
+
+ if let (
+ hir::ExprKind::Struct(expr_struct_path, expr_struct_fields, _expr_struct_rest),
+ ty::Adt(in_ty_adt, in_ty_adt_generic_args),
+ ) = (&expr.kind, in_ty.kind())
+ {
+ // First, confirm that this struct is the same one as in the types, and if so,
+ // find the right variant.
+ let Res::Def(expr_struct_def_kind, expr_struct_def_id) = self.typeck_results.borrow().qpath_res(expr_struct_path, expr.hir_id) else {
+ return Err(expr);
+ };
+
+ let variant_def_id = match expr_struct_def_kind {
+ hir::def::DefKind::Struct => {
+ if in_ty_adt.did() != expr_struct_def_id {
+ // FIXME: Deal with type aliases?
+ return Err(expr);
+ }
+ expr_struct_def_id
+ }
+ hir::def::DefKind::Variant => {
+ // If this is a variant, its parent is the type definition.
+ if in_ty_adt.did() != self.tcx.parent(expr_struct_def_id) {
+ // FIXME: Deal with type aliases?
+ return Err(expr);
+ }
+ expr_struct_def_id
+ }
+ _ => {
+ return Err(expr);
+ }
+ };
+
+ // We need to know which of the generic parameters mentions our target param.
+ // We expect that at least one of them does, since it is expected to be mentioned.
+ let Some((drill_generic_index, generic_argument_type)) =
+ Self::is_iterator_singleton(
+ in_ty_adt_generic_args.iter().enumerate().filter(
+ |(_index, in_ty_generic)| {
+ Self::find_param_in_ty(*in_ty_generic, param)
+ },
+ ),
+ ) else {
+ return Err(expr);
+ };
+
+ let struct_generic_parameters: &ty::Generics = self.tcx.generics_of(in_ty_adt.did());
+ if drill_generic_index >= struct_generic_parameters.params.len() {
+ return Err(expr);
+ }
+
+ let param_to_point_at_in_struct = self.tcx.mk_param_from_def(
+ struct_generic_parameters.param_at(drill_generic_index, self.tcx),
+ );
+
+ // We make 3 steps:
+ // Suppose we have a type like
+ // ```ignore (just for demonstration)
+ // struct ExampleStruct<T> {
+ // enabled: bool,
+ // item: Option<(usize, T, bool)>,
+ // }
+ //
+ // f(ExampleStruct {
+ // enabled: false,
+ // item: Some((0, Box::new(String::new()), 1) }, true)),
+ // });
+ // ```
+ // Here, `f` is passed a `ExampleStruct<Box<String>>`, but it wants
+ // for `String: Copy`, which isn't true here.
+ //
+ // (1) First, we drill into `.item` and highlight that expression
+ // (2) Then we use the template type `Option<(usize, T, bool)>` to
+ // drill into the `T`, arriving at a `Box<String>` expression.
+ // (3) Then we keep going, drilling into this expression using our
+ // outer contextual information.
+
+ // (1) Find the (unique) field which mentions the type in our constraint:
+ let (field_expr, field_type) = self
+ .point_at_field_if_possible(
+ in_ty_adt.did(),
+ param_to_point_at_in_struct,
+ variant_def_id,
+ expr_struct_fields,
+ )
+ .ok_or(expr)?;
+
+ // (2) Continue drilling into the struct, ignoring the struct's
+ // generic argument types.
+ let expr = self.blame_specific_part_of_expr_corresponding_to_generic_param(
+ param_to_point_at_in_struct,
+ field_expr,
+ field_type.into(),
+ )?;
+
+ // (3) Continue drilling into the expression, having "passed
+ // through" the struct entirely.
+ return self.blame_specific_part_of_expr_corresponding_to_generic_param(
+ param,
+ expr,
+ generic_argument_type,
+ );
+ }
+
+ if let (
+ hir::ExprKind::Call(expr_callee, expr_args),
+ ty::Adt(in_ty_adt, in_ty_adt_generic_args),
+ ) = (&expr.kind, in_ty.kind())
+ {
+ let hir::ExprKind::Path(expr_callee_path) = &expr_callee.kind else {
+ // FIXME: This case overlaps with another one worth handling,
+ // which should happen above since it applies to non-ADTs:
+ // we can drill down into regular generic functions.
+ return Err(expr);
+ };
+ // This is (possibly) a constructor call, like `Some(...)` or `MyStruct(a, b, c)`.
+
+ let Res::Def(expr_struct_def_kind, expr_ctor_def_id) = self.typeck_results.borrow().qpath_res(expr_callee_path, expr_callee.hir_id) else {
+ return Err(expr);
+ };
+
+ let variant_def_id = match expr_struct_def_kind {
+ hir::def::DefKind::Ctor(hir::def::CtorOf::Struct, hir::def::CtorKind::Fn) => {
+ if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) {
+ // FIXME: Deal with type aliases?
+ return Err(expr);
+ }
+ self.tcx.parent(expr_ctor_def_id)
+ }
+ hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => {
+ // If this is a variant, its parent is the type definition.
+ if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) {
+ // FIXME: Deal with type aliases?
+ return Err(expr);
+ }
+ expr_ctor_def_id
+ }
+ _ => {
+ return Err(expr);
+ }
+ };
+
+ // We need to know which of the generic parameters mentions our target param.
+ // We expect that at least one of them does, since it is expected to be mentioned.
+ let Some((drill_generic_index, generic_argument_type)) =
+ Self::is_iterator_singleton(
+ in_ty_adt_generic_args.iter().enumerate().filter(
+ |(_index, in_ty_generic)| {
+ Self::find_param_in_ty(*in_ty_generic, param)
+ },
+ ),
+ ) else {
+ return Err(expr);
+ };
+
+ let struct_generic_parameters: &ty::Generics = self.tcx.generics_of(in_ty_adt.did());
+ if drill_generic_index >= struct_generic_parameters.params.len() {
+ return Err(expr);
+ }
+
+ let param_to_point_at_in_struct = self.tcx.mk_param_from_def(
+ struct_generic_parameters.param_at(drill_generic_index, self.tcx),
+ );
+
+ // We make 3 steps:
+ // Suppose we have a type like
+ // ```ignore (just for demonstration)
+ // struct ExampleStruct<T> {
+ // enabled: bool,
+ // item: Option<(usize, T, bool)>,
+ // }
+ //
+ // f(ExampleStruct {
+ // enabled: false,
+ // item: Some((0, Box::new(String::new()), 1) }, true)),
+ // });
+ // ```
+ // Here, `f` is passed a `ExampleStruct<Box<String>>`, but it wants
+ // for `String: Copy`, which isn't true here.
+ //
+ // (1) First, we drill into `.item` and highlight that expression
+ // (2) Then we use the template type `Option<(usize, T, bool)>` to
+ // drill into the `T`, arriving at a `Box<String>` expression.
+ // (3) Then we keep going, drilling into this expression using our
+ // outer contextual information.
+
+ // (1) Find the (unique) field index which mentions the type in our constraint:
+ let Some((field_index, field_type)) = Self::is_iterator_singleton(
+ in_ty_adt
+ .variant_with_id(variant_def_id)
+ .fields
+ .iter()
+ .map(|field| field.ty(self.tcx, *in_ty_adt_generic_args))
+ .enumerate()
+ .filter(|(_index, field_type)| Self::find_param_in_ty((*field_type).into(), param))
+ ) else {
+ return Err(expr);
+ };
+
+ if field_index >= expr_args.len() {
+ return Err(expr);
+ }
+
+ // (2) Continue drilling into the struct, ignoring the struct's
+ // generic argument types.
+ let expr = self.blame_specific_part_of_expr_corresponding_to_generic_param(
+ param_to_point_at_in_struct,
+ &expr_args[field_index],
+ field_type.into(),
+ )?;
+
+ // (3) Continue drilling into the expression, having "passed
+ // through" the struct entirely.
+ return self.blame_specific_part_of_expr_corresponding_to_generic_param(
+ param,
+ expr,
+ generic_argument_type,
+ );
+ }
+
+ // At this point, none of the basic patterns matched.
+ // One major possibility which remains is that we have a function call.
+ // In this case, it's often possible to dive deeper into the call to find something to blame,
+ // but this is not always possible.
+
+ Err(expr)
+ }
+
+ // FIXME: This can be made into a private, non-impl function later.
+ /// Traverses the given ty (either a `ty::Ty` or a `ty::GenericArg`) and searches for references
+ /// to the given `param_to_point_at`. Returns `true` if it finds any use of the param.
+ pub fn find_param_in_ty(
+ ty: ty::GenericArg<'tcx>,
+ param_to_point_at: ty::GenericArg<'tcx>,
+ ) -> bool {
+ let mut walk = ty.walk();
+ while let Some(arg) = walk.next() {
+ if arg == param_to_point_at {
+ return true;
+ } else if let ty::GenericArgKind::Type(ty) = arg.unpack()
+ && let ty::Alias(ty::Projection, ..) = ty.kind()
+ {
+ // This logic may seem a bit strange, but typically when
+ // we have a projection type in a function signature, the
+ // argument that's being passed into that signature is
+ // not actually constraining that projection's substs in
+ // a meaningful way. So we skip it, and see improvements
+ // in some UI tests.
+ walk.skip_current_subtree();
+ }
+ }
+ false
+ }
+
+ // FIXME: This can be made into a private, non-impl function later.
+ /// Returns `Some(iterator.next())` if it has exactly one item, and `None` otherwise.
+ pub fn is_iterator_singleton<T>(mut iterator: impl Iterator<Item = T>) -> Option<T> {
+ match (iterator.next(), iterator.next()) {
+ (_, Some(_)) => None,
+ (first, _) => first,
+ }
+ }
+}
use std::iter;
use std::mem;
-use std::ops::ControlFlow;
use std::slice;
+use std::ops::ControlFlow;
+
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(in super::super) fn check_casts(&mut self) {
// don't hold the borrow to deferred_cast_checks while checking to avoid borrow checker errors
.into_iter()
.flatten()
{
- if self.point_at_arg_if_possible(
+ if self.blame_specific_arg_if_possible(
error,
def_id,
param,
.into_iter()
.flatten()
{
- if self.point_at_arg_if_possible(
+ if self.blame_specific_arg_if_possible(
error,
def_id,
param,
for param in
[param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
{
- if let Some(param) = param
- && self.point_at_field_if_possible(
- error,
+ if let Some(param) = param {
+ let refined_expr = self.point_at_field_if_possible(
def_id,
param,
variant_def_id,
fields,
- )
- {
- return true;
+ );
+
+ match refined_expr {
+ None => {}
+ Some((refined_expr, _)) => {
+ error.obligation.cause.span = refined_expr
+ .span
+ .find_ancestor_in_same_ctxt(error.obligation.cause.span)
+ .unwrap_or(refined_expr.span);
+ return true;
+ }
+ }
}
}
}
}
}
- fn point_at_arg_if_possible(
+ /// - `blame_specific_*` means that the function will recursively traverse the expression,
+ /// looking for the most-specific-possible span to blame.
+ ///
+ /// - `point_at_*` means that the function will only go "one level", pointing at the specific
+ /// expression mentioned.
+ ///
+ /// `blame_specific_arg_if_possible` will find the most-specific expression anywhere inside
+ /// the provided function call expression, and mark it as responsible for the fullfillment
+ /// error.
+ fn blame_specific_arg_if_possible(
&self,
error: &mut traits::FulfillmentError<'tcx>,
def_id: DefId,
.inputs()
.iter()
.enumerate()
- .filter(|(_, ty)| find_param_in_ty(**ty, param_to_point_at))
+ .filter(|(_, ty)| Self::find_param_in_ty((**ty).into(), param_to_point_at))
.collect();
// If there's one field that references the given generic, great!
if let [(idx, _)] = args_referencing_param.as_slice()
&& let Some(arg) = receiver
.map_or(args.get(*idx), |rcvr| if *idx == 0 { Some(rcvr) } else { args.get(*idx - 1) }) {
+
error.obligation.cause.span = arg.span.find_ancestor_in_same_ctxt(error.obligation.cause.span).unwrap_or(arg.span);
+
+ if let hir::Node::Expr(arg_expr) = self.tcx.hir().get(arg.hir_id) {
+ // This is more specific than pointing at the entire argument.
+ self.blame_specific_expr_if_possible(error, arg_expr)
+ }
+
error.obligation.cause.map_code(|parent_code| {
ObligationCauseCode::FunctionArgumentObligation {
arg_hir_id: arg.hir_id,
false
}
- fn point_at_field_if_possible(
+ // FIXME: Make this private and move to mod adjust_fulfillment_errors
+ pub fn point_at_field_if_possible(
&self,
- error: &mut traits::FulfillmentError<'tcx>,
def_id: DefId,
param_to_point_at: ty::GenericArg<'tcx>,
variant_def_id: DefId,
expr_fields: &[hir::ExprField<'tcx>],
- ) -> bool {
+ ) -> Option<(&'tcx hir::Expr<'tcx>, Ty<'tcx>)> {
let def = self.tcx.adt_def(def_id);
let identity_substs = ty::InternalSubsts::identity_for_item(self.tcx, def_id);
.iter()
.filter(|field| {
let field_ty = field.ty(self.tcx, identity_substs);
- find_param_in_ty(field_ty, param_to_point_at)
+ Self::find_param_in_ty(field_ty.into(), param_to_point_at)
})
.collect();
// same rules that check_expr_struct uses for macro hygiene.
if self.tcx.adjust_ident(expr_field.ident, variant_def_id) == field.ident(self.tcx)
{
- error.obligation.cause.span = expr_field
- .expr
- .span
- .find_ancestor_in_same_ctxt(error.obligation.cause.span)
- .unwrap_or(expr_field.span);
- return true;
+ return Some((expr_field.expr, self.tcx.type_of(field.did)));
}
}
}
- false
+ None
}
fn point_at_path_if_possible(
}
}
}
-
-fn find_param_in_ty<'tcx>(ty: Ty<'tcx>, param_to_point_at: ty::GenericArg<'tcx>) -> bool {
- let mut walk = ty.walk();
- while let Some(arg) = walk.next() {
- if arg == param_to_point_at {
- return true;
- } else if let ty::GenericArgKind::Type(ty) = arg.unpack()
- && let ty::Alias(ty::Projection, ..) = ty.kind()
- {
- // This logic may seem a bit strange, but typically when
- // we have a projection type in a function signature, the
- // argument that's being passed into that signature is
- // not actually constraining that projection's substs in
- // a meaningful way. So we skip it, and see improvements
- // in some UI tests.
- walk.skip_current_subtree();
- }
- }
- false
-}
mod _impl;
+mod adjust_fulfillment_errors;
mod arg_matrix;
mod checks;
mod suggestions;
use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel};
use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
-use rustc_errors::{Applicability, Diagnostic, MultiSpan};
+use rustc_errors::{fluent, Applicability, Diagnostic, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, CtorOf, DefKind};
use rustc_hir::lang_items::LangItem;
use rustc_hir_analysis::astconv::AstConv;
use rustc_infer::traits::{self, StatementAsExpression};
use rustc_middle::lint::in_external_macro;
+use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{
self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty,
TypeVisitable,
if let ty::Adt(adt, _) = peeled.kind()
&& Some(adt.did()) == self.tcx.lang_items().string()
{
+ let sugg = if ref_cnt == 0 {
+ ".as_deref()"
+ } else {
+ ".map(|x| x.as_str())"
+ };
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
- "try converting the passed type into a `&str`",
- format!(".map(|x| &*{}x)", "*".repeat(ref_cnt)),
- Applicability::MaybeIncorrect,
+ fluent::hir_typeck_convert_to_str,
+ sugg,
+ Applicability::MachineApplicable,
);
return true;
}
return true;
}
&hir::FnRetTy::DefaultReturn(span) if expected.is_unit() => {
- if found.is_suggestable(self.tcx, false) {
+ if let Some(found) = found.make_suggestable(self.tcx, false) {
err.subdiagnostic(AddReturnTypeSuggestion::Add { span, found: found.to_string() });
return true;
} else if let ty::Closure(_, substs) = found.kind()
}
}
hir::FnRetTy::Return(ty) => {
+ let span = ty.span;
+
+ if let hir::TyKind::OpaqueDef(item_id, ..) = ty.kind
+ && let hir::Node::Item(hir::Item {
+ kind: hir::ItemKind::OpaqueTy(op_ty),
+ ..
+ }) = self.tcx.hir().get(item_id.hir_id())
+ && let hir::OpaqueTy {
+ bounds: [bound], ..
+ } = op_ty
+ && let hir::GenericBound::LangItemTrait(
+ hir::LangItem::Future, _, _, generic_args) = bound
+ && let hir::GenericArgs { bindings: [ty_binding], .. } = generic_args
+ && let hir::TypeBinding { kind, .. } = ty_binding
+ && let hir::TypeBindingKind::Equality { term } = kind
+ && let hir::Term::Ty(term_ty) = term {
+ // Check if async function's return type was omitted.
+ // Don't emit suggestions if the found type is `impl Future<...>`.
+ debug!("suggest_missing_return_type: found = {:?}", found);
+ if found.is_suggestable(self.tcx, false) {
+ if term_ty.span.is_empty() {
+ err.subdiagnostic(AddReturnTypeSuggestion::Add { span, found: found.to_string() });
+ return true;
+ } else {
+ err.subdiagnostic(ExpectedReturnTypeLabel::Other { span, expected });
+ }
+ }
+ }
+
// Only point to return type if the expected type is the return type, as if they
// are not, the expectation must have been caused by something else.
debug!("suggest_missing_return_type: return type {:?} node {:?}", ty, ty.kind);
- let span = ty.span;
let ty = self.astconv().ast_ty_to_ty(ty);
debug!("suggest_missing_return_type: return type {:?}", ty);
debug!("suggest_missing_return_type: expected type {:?}", ty);
}
}
+ /// Suggest providing `std::ptr::null()` or `std::ptr::null_mut()` if they
+ /// pass in a literal 0 to an raw pointer.
+ #[instrument(skip(self, err))]
+ pub(crate) fn suggest_null_ptr_for_literal_zero_given_to_ptr_arg(
+ &self,
+ err: &mut Diagnostic,
+ expr: &hir::Expr<'_>,
+ expected_ty: Ty<'tcx>,
+ ) -> bool {
+ // Expected type needs to be a raw pointer.
+ let ty::RawPtr(ty::TypeAndMut { mutbl, .. }) = expected_ty.kind() else {
+ return false;
+ };
+
+ // Provided expression needs to be a literal `0`.
+ let ExprKind::Lit(Spanned {
+ node: rustc_ast::LitKind::Int(0, _),
+ span,
+ }) = expr.kind else {
+ return false;
+ };
+
+ // We need to find a null pointer symbol to suggest
+ let null_sym = match mutbl {
+ hir::Mutability::Not => sym::ptr_null,
+ hir::Mutability::Mut => sym::ptr_null_mut,
+ };
+ let Some(null_did) = self.tcx.get_diagnostic_item(null_sym) else {
+ return false;
+ };
+ let null_path_str = with_no_trimmed_paths!(self.tcx.def_path_str(null_did));
+
+ // We have satisfied all requirements to provide a suggestion. Emit it.
+ err.span_suggestion(
+ span,
+ format!("if you meant to create a null pointer, use `{null_path_str}()`"),
+ null_path_str + "()",
+ Applicability::MachineApplicable,
+ );
+
+ true
+ }
+
pub(crate) fn suggest_associated_const(
&self,
err: &mut Diagnostic,
None if self.is_tainted_by_errors() => Err(()),
None => {
bug!(
- "no type for node {}: {} in mem_categorization",
- id,
+ "no type for node {} in mem_categorization",
self.tcx().hir().node_to_string(id)
);
}
return Some(Err(MethodError::Ambiguity(sources)));
}
- applicable_candidates.pop().map(|(probe, status)| {
- if status == ProbeResult::Match {
+ applicable_candidates.pop().map(|(probe, status)| match status {
+ ProbeResult::Match => {
Ok(probe
.to_unadjusted_pick(self_ty, unstable_candidates.cloned().unwrap_or_default()))
- } else {
- Err(MethodError::BadReturnType)
}
+ ProbeResult::NoMatch | ProbeResult::BadReturnType => Err(MethodError::BadReturnType),
})
}
}
traits::ImplDerivedObligationCause {
derived,
impl_def_id,
+ impl_def_predicate_index: None,
span,
},
))
let mode = no_match_data.mode;
let tcx = self.tcx;
let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
- let ty_str = with_forced_trimmed_paths!(self.ty_to_string(rcvr_ty));
+ let (ty_str, ty_file) = tcx.short_ty_string(rcvr_ty);
+ let short_ty_str = with_forced_trimmed_paths!(rcvr_ty.to_string());
let is_method = mode == Mode::MethodCall;
let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;
let similar_candidate = no_match_data.similar_candidate;
}
};
- if self.suggest_wrapping_range_with_parens(tcx, rcvr_ty, source, span, item_name, &ty_str)
- || self.suggest_constraining_numerical_ty(
- tcx, rcvr_ty, source, span, item_kind, item_name, &ty_str,
- )
- {
+ // We could pass the file for long types into these two, but it isn't strictly necessary
+ // given how targetted they are.
+ if self.suggest_wrapping_range_with_parens(
+ tcx,
+ rcvr_ty,
+ source,
+ span,
+ item_name,
+ &short_ty_str,
+ ) || self.suggest_constraining_numerical_ty(
+ tcx,
+ rcvr_ty,
+ source,
+ span,
+ item_kind,
+ item_name,
+ &short_ty_str,
+ ) {
return None;
}
span = item_name.span;
rcvr_ty.prefix_string(self.tcx),
ty_str_reported,
);
+ let ty_str = if short_ty_str.len() < ty_str.len() && ty_str.len() > 10 {
+ short_ty_str
+ } else {
+ ty_str
+ };
+ if let Some(file) = ty_file {
+ err.note(&format!("the full type name has been written to '{}'", file.display(),));
+ }
if rcvr_ty.references_error() {
err.downgrade_to_delayed_bug();
}
let primary_message = primary_message.unwrap_or_else(|| {
format!(
"the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \
- but its trait bounds were not satisfied"
+ but its trait bounds were not satisfied"
)
});
err.set_primary_message(&primary_message);
format!("cannot divide `{lhs_ty}` by `{rhs_ty}`")
}
hir::BinOpKind::Rem => {
- format!("cannot mod `{lhs_ty}` by `{rhs_ty}`")
+ format!(
+ "cannot calculate the remainder of `{lhs_ty}` divided by `{rhs_ty}`"
+ )
}
hir::BinOpKind::BitAnd => {
format!("no implementation for `{lhs_ty} & {rhs_ty}`")
if let Some(output_def_id) = output_def_id
&& let Some(trait_def_id) = trait_def_id
&& self.tcx.parent(output_def_id) == trait_def_id
- && output_ty.is_suggestable(self.tcx, false)
+ && let Some(output_ty) = output_ty.make_suggestable(self.tcx, false)
{
- Some(("Output", *output_ty))
+ Some(("Output", output_ty))
} else {
None
}
//! fn baz() { foo(); }
//! ```
+use crate::errors;
use rustc_ast as ast;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::graph::implementation::{Direction, NodeIndex, INCOMING, OUTGOING};
Some(n) => {
match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) {
Ok(n) => n,
- Err(()) => {
- self.tcx.sess.span_fatal(
- attr.span,
- &format!("unrecognized DepNode variant {:?}", n),
- );
- }
+ Err(()) => self.tcx.sess.emit_fatal(errors::UnrecognizedDepNode {
+ span: attr.span,
+ name: n,
+ }),
}
}
};
Some(n) => {
match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) {
Ok(n) => n,
- Err(()) => {
- self.tcx.sess.span_fatal(
- attr.span,
- &format!("unrecognized DepNode variant {:?}", n),
- );
- }
+ Err(()) => self.tcx.sess.emit_fatal(errors::UnrecognizedDepNode {
+ span: attr.span,
+ name: n,
+ }),
}
}
None => {
- self.tcx.sess.span_fatal(attr.span, "missing DepNode variant");
+ self.tcx.sess.emit_fatal(errors::MissingDepNode { span: attr.span });
}
};
self.then_this_would_need.push((
// Return early here so as not to construct the query, which is not cheap.
if if_this_changed.is_empty() {
for &(target_span, _, _, _) in then_this_would_need {
- tcx.sess.span_err(target_span, "no `#[rustc_if_this_changed]` annotation detected");
+ tcx.sess.emit_err(errors::MissingIfThisChanged { span: target_span });
}
return;
}
let dependents = query.transitive_predecessors(source_dep_node);
for &(target_span, ref target_pass, _, ref target_dep_node) in then_this_would_need {
if !dependents.contains(&target_dep_node) {
- tcx.sess.span_err(
- target_span,
- &format!(
- "no path from `{}` to `{}`",
- tcx.def_path_str(source_def_id),
- target_pass
- ),
- );
+ tcx.sess.emit_err(errors::NoPath {
+ span: target_span,
+ source: tcx.def_path_str(source_def_id),
+ target: *target_pass,
+ });
} else {
- tcx.sess.span_err(target_span, "OK");
+ tcx.sess.emit_err(errors::Ok { span: target_span });
}
}
}
//! allows for doing a more fine-grained check to see if pre- or post-lto data
//! was re-used.
+use crate::errors;
use rustc_ast as ast;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::LOCAL_CRATE;
sym::post_dash_lto => (CguReuse::PostLto, ComparisonKind::Exact),
sym::any => (CguReuse::PreLto, ComparisonKind::AtLeast),
other => {
- self.tcx.sess.span_fatal(
- attr.span,
- &format!("unknown cgu-reuse-kind `{}` specified", other),
- );
+ self.tcx
+ .sess
+ .emit_fatal(errors::UnknownReuseKind { span: attr.span, kind: other });
}
}
} else {
};
if !self.tcx.sess.opts.unstable_opts.query_dep_graph {
- self.tcx.sess.span_fatal(
- attr.span,
- "found CGU-reuse attribute but `-Zquery-dep-graph` was not specified",
- );
+ self.tcx.sess.emit_fatal(errors::MissingQueryDepGraph { span: attr.span });
}
if !self.check_config(attr) {
let crate_name = self.tcx.crate_name(LOCAL_CRATE).to_string();
if !user_path.starts_with(&crate_name) {
- let msg = format!(
- "Found malformed codegen unit name `{}`. \
- Codegen units names must always start with the name of the \
- crate (`{}` in this case).",
- user_path, crate_name
- );
- self.tcx.sess.span_fatal(attr.span, &msg);
+ self.tcx.sess.emit_fatal(errors::MalformedCguName {
+ span: attr.span,
+ user_path,
+ crate_name,
+ });
}
// Split of the "special suffix" if there is one.
let mut cgu_names: Vec<&str> =
self.available_cgus.iter().map(|cgu| cgu.as_str()).collect();
cgu_names.sort();
- self.tcx.sess.span_err(
- attr.span,
- &format!(
- "no module named `{}` (mangled: {}). Available modules: {}",
- user_path,
- cgu_name,
- cgu_names.join(", ")
- ),
- );
+ self.tcx.sess.emit_err(errors::NoModuleNamed {
+ span: attr.span,
+ user_path,
+ cgu_name,
+ cgu_names: cgu_names.join(", "),
+ });
}
self.tcx.sess.cgu_reuse_tracker.set_expectation(
if let Some(value) = item.value_str() {
return value;
} else {
- self.tcx.sess.span_fatal(
- item.span(),
- &format!("associated value expected for `{}`", name),
- );
+ self.tcx.sess.emit_fatal(errors::FieldAssociatedValueExpected {
+ span: item.span(),
+ name,
+ });
}
}
}
- self.tcx.sess.span_fatal(attr.span, &format!("no field `{}`", name));
+ self.tcx.sess.emit_fatal(errors::NoField { span: attr.span, name });
}
/// Scan for a `cfg="foo"` attribute and check whether we have a
--- /dev/null
+use rustc_macros::Diagnostic;
+use rustc_span::{symbol::Ident, Span, Symbol};
+use std::path::{Path, PathBuf};
+
+#[derive(Diagnostic)]
+#[diag(incremental_unrecognized_depnode)]
+pub struct UnrecognizedDepNode {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_missing_depnode)]
+pub struct MissingDepNode {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_missing_if_this_changed)]
+pub struct MissingIfThisChanged {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_ok)]
+pub struct Ok {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_no_path)]
+pub struct NoPath {
+ #[primary_span]
+ pub span: Span,
+ pub target: Symbol,
+ pub source: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_unknown_reuse_kind)]
+pub struct UnknownReuseKind {
+ #[primary_span]
+ pub span: Span,
+ pub kind: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_missing_query_depgraph)]
+pub struct MissingQueryDepGraph {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_malformed_cgu_name)]
+pub struct MalformedCguName {
+ #[primary_span]
+ pub span: Span,
+ pub user_path: String,
+ pub crate_name: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_no_module_named)]
+pub struct NoModuleNamed<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub user_path: &'a str,
+ pub cgu_name: Symbol,
+ pub cgu_names: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_field_associated_value_expected)]
+pub struct FieldAssociatedValueExpected {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_no_field)]
+pub struct NoField {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_assertion_auto)]
+pub struct AssertionAuto<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: &'a str,
+ pub e: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_undefined_clean_dirty_assertions_item)]
+pub struct UndefinedCleanDirtyItem {
+ #[primary_span]
+ pub span: Span,
+ pub kind: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_undefined_clean_dirty_assertions)]
+pub struct UndefinedCleanDirty {
+ #[primary_span]
+ pub span: Span,
+ pub kind: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_repeated_depnode_label)]
+pub struct RepeatedDepNodeLabel<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub label: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_unrecognized_depnode_label)]
+pub struct UnrecognizedDepNodeLabel<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub label: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_not_dirty)]
+pub struct NotDirty<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub dep_node_str: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_not_clean)]
+pub struct NotClean<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub dep_node_str: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_not_loaded)]
+pub struct NotLoaded<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub dep_node_str: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_unknown_item)]
+pub struct UnknownItem {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_no_cfg)]
+pub struct NoCfg {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_associated_value_expected_for)]
+pub struct AssociatedValueExpectedFor {
+ #[primary_span]
+ pub span: Span,
+ pub ident: Ident,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_associated_value_expected)]
+pub struct AssociatedValueExpected {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_unchecked_clean)]
+pub struct UncheckedClean {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_delete_old)]
+pub struct DeleteOld<'a> {
+ pub name: &'a str,
+ pub path: PathBuf,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_create_new)]
+pub struct CreateNew<'a> {
+ pub name: &'a str,
+ pub path: PathBuf,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_write_new)]
+pub struct WriteNew<'a> {
+ pub name: &'a str,
+ pub path: PathBuf,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_canonicalize_path)]
+pub struct CanonicalizePath {
+ pub path: PathBuf,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_create_incr_comp_dir)]
+pub struct CreateIncrCompDir<'a> {
+ pub tag: &'a str,
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_create_lock)]
+pub struct CreateLock<'a> {
+ pub lock_err: std::io::Error,
+ pub session_dir: &'a Path,
+ #[note(incremental_lock_unsupported)]
+ pub is_unsupported_lock: Option<()>,
+ #[help(incremental_cargo_help_1)]
+ #[help(incremental_cargo_help_2)]
+ pub is_cargo: Option<()>,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_delete_lock)]
+pub struct DeleteLock<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_hard_link_failed)]
+pub struct HardLinkFailed<'a> {
+ pub path: &'a Path,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_delete_partial)]
+pub struct DeletePartial<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_delete_full)]
+pub struct DeleteFull<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_finalize)]
+pub struct Finalize<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_invalid_gc_failed)]
+pub struct InvalidGcFailed<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_finalized_gc_failed)]
+pub struct FinalizedGcFailed<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_session_gc_failed)]
+pub struct SessionGcFailed<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_assert_not_loaded)]
+pub struct AssertNotLoaded;
+
+#[derive(Diagnostic)]
+#[diag(incremental_assert_loaded)]
+pub struct AssertLoaded;
+
+#[derive(Diagnostic)]
+#[diag(incremental_delete_incompatible)]
+pub struct DeleteIncompatible {
+ pub path: PathBuf,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_load_dep_graph)]
+pub struct LoadDepGraph {
+ pub path: PathBuf,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_decode_incr_cache)]
+pub struct DecodeIncrCache {
+ pub err: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_write_dep_graph)]
+pub struct WriteDepGraph<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_move_dep_graph)]
+pub struct MoveDepGraph<'a> {
+ pub from: &'a Path,
+ pub to: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_create_dep_graph)]
+pub struct CreateDepGraph<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_copy_workproduct_to_cache)]
+pub struct CopyWorkProductToCache<'a> {
+ pub from: &'a Path,
+ pub to: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_delete_workproduct)]
+pub struct DeleteWorkProduct<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
#![deny(missing_docs)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(never_type)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
#[macro_use]
extern crate rustc_middle;
mod assert_dep_graph;
pub mod assert_module_sources;
+mod errors;
mod persist;
use assert_dep_graph::assert_dep_graph;
//! Errors are reported if we are in the suitable configuration but
//! the required condition is not met.
+use crate::errors;
use rustc_ast::{self as ast, Attribute, NestedMetaItem};
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::LocalDefId;
let loaded_from_disk = self.loaded_from_disk(attr);
for e in except.iter() {
if !auto.remove(e) {
- let msg = format!(
- "`except` specified DepNodes that can not be affected for \"{}\": \"{}\"",
- name, e
- );
- self.tcx.sess.span_fatal(attr.span, &msg);
+ self.tcx.sess.emit_fatal(errors::AssertionAuto { span: attr.span, name, e });
}
}
Assertion { clean: auto, dirty: except, loaded_from_disk }
// An implementation, eg `impl<A> Trait for Foo { .. }`
HirItem::Impl { .. } => ("ItemKind::Impl", LABELS_IMPL),
- _ => self.tcx.sess.span_fatal(
- attr.span,
- &format!(
- "clean/dirty auto-assertions not yet defined \
- for Node::Item.node={:?}",
- item.kind
- ),
- ),
+ _ => self.tcx.sess.emit_fatal(errors::UndefinedCleanDirtyItem {
+ span: attr.span,
+ kind: format!("{:?}", item.kind),
+ }),
}
}
HirNode::TraitItem(item) => match item.kind {
ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_IN_IMPL),
ImplItemKind::Type(..) => ("NodeImplType", LABELS_CONST_IN_IMPL),
},
- _ => self.tcx.sess.span_fatal(
- attr.span,
- &format!("clean/dirty auto-assertions not yet defined for {:?}", node),
- ),
+ _ => self.tcx.sess.emit_fatal(errors::UndefinedCleanDirty {
+ span: attr.span,
+ kind: format!("{:?}", node),
+ }),
};
let labels =
Labels::from_iter(labels.iter().flat_map(|s| s.iter().map(|l| (*l).to_string())));
let label = label.trim();
if DepNode::has_label_string(label) {
if out.contains(label) {
- self.tcx.sess.span_fatal(
- item.span(),
- &format!("dep-node label `{}` is repeated", label),
- );
+ self.tcx
+ .sess
+ .emit_fatal(errors::RepeatedDepNodeLabel { span: item.span(), label });
}
out.insert(label.to_string());
} else {
self.tcx
.sess
- .span_fatal(item.span(), &format!("dep-node label `{}` not recognized", label));
+ .emit_fatal(errors::UnrecognizedDepNodeLabel { span: item.span(), label });
}
}
out
let dep_node_str = self.dep_node_str(&dep_node);
self.tcx
.sess
- .span_err(item_span, &format!("`{}` should be dirty but is not", dep_node_str));
+ .emit_err(errors::NotDirty { span: item_span, dep_node_str: &dep_node_str });
}
}
let dep_node_str = self.dep_node_str(&dep_node);
self.tcx
.sess
- .span_err(item_span, &format!("`{}` should be clean but is not", dep_node_str));
+ .emit_err(errors::NotClean { span: item_span, dep_node_str: &dep_node_str });
}
}
if !self.tcx.dep_graph.debug_was_loaded_from_disk(dep_node) {
let dep_node_str = self.dep_node_str(&dep_node);
- self.tcx.sess.span_err(
- item_span,
- &format!("`{}` should have been loaded from disk but it was not", dep_node_str),
- );
+ self.tcx
+ .sess
+ .emit_err(errors::NotLoaded { span: item_span, dep_node_str: &dep_node_str });
}
}
debug!("check_config: searching for cfg {:?}", value);
cfg = Some(config.contains(&(value, None)));
} else if !(item.has_name(EXCEPT) || item.has_name(LOADED_FROM_DISK)) {
- tcx.sess.span_err(attr.span, &format!("unknown item `{}`", item.name_or_empty()));
+ tcx.sess.emit_err(errors::UnknownItem { span: attr.span, name: item.name_or_empty() });
}
}
match cfg {
- None => tcx.sess.span_fatal(attr.span, "no cfg attribute"),
+ None => tcx.sess.emit_fatal(errors::NoCfg { span: attr.span }),
Some(c) => c,
}
}
if let Some(value) = item.value_str() {
value
} else {
- let msg = if let Some(ident) = item.ident() {
- format!("associated value expected for `{}`", ident)
+ if let Some(ident) = item.ident() {
+ tcx.sess.emit_fatal(errors::AssociatedValueExpectedFor { span: item.span(), ident });
} else {
- "expected an associated value".to_string()
- };
-
- tcx.sess.span_fatal(item.span(), &msg);
+ tcx.sess.emit_fatal(errors::AssociatedValueExpected { span: item.span() });
+ }
}
}
fn report_unchecked_attrs(&self, mut checked_attrs: FxHashSet<ast::AttrId>) {
for attr in &self.found_attrs {
if !checked_attrs.contains(&attr.id) {
- self.tcx.sess.span_err(attr.span, "found unchecked `#[rustc_clean]` attribute");
+ self.tcx.sess.emit_err(errors::UncheckedClean { span: attr.span });
checked_attrs.insert(attr.id);
}
}
//! compiler versions don't change frequently for the typical user, being
//! conservative here practically has no downside.
-use std::env;
-use std::fs;
-use std::io::{self, Read};
-use std::path::{Path, PathBuf};
-
+use crate::errors;
use rustc_data_structures::memmap::Mmap;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use rustc_serialize::Encoder;
use rustc_session::Session;
+use std::env;
+use std::fs;
+use std::io::{self, Read};
+use std::path::{Path, PathBuf};
/// The first few bytes of files generated by incremental compilation.
const FILE_MAGIC: &[u8] = b"RSIC";
}
Err(err) if err.kind() == io::ErrorKind::NotFound => (),
Err(err) => {
- sess.err(&format!(
- "unable to delete old {} at `{}`: {}",
- name,
- path_buf.display(),
- err
- ));
+ sess.emit_err(errors::DeleteOld { name, path: path_buf, err });
return;
}
}
let mut encoder = match FileEncoder::new(&path_buf) {
Ok(encoder) => encoder,
Err(err) => {
- sess.err(&format!("failed to create {} at `{}`: {}", name, path_buf.display(), err));
+ sess.emit_err(errors::CreateNew { name, path: path_buf, err });
return;
}
};
debug!("save: data written to disk successfully");
}
Err(err) => {
- sess.err(&format!("failed to write {} to `{}`: {}", name, path_buf.display(), err));
+ sess.emit_err(errors::WriteNew { name, path: path_buf, err });
}
}
}
//! unsupported file system and emit a warning in that case. This is not yet
//! implemented.
+use crate::errors;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::svh::Svh;
use rustc_data_structures::{base_n, flock};
let crate_dir = match crate_dir.canonicalize() {
Ok(v) => v,
Err(err) => {
- let reported = sess.err(&format!(
- "incremental compilation: error canonicalizing path `{}`: {}",
- crate_dir.display(),
- err
- ));
- return Err(reported);
+ return Err(sess.emit_err(errors::CanonicalizePath { path: crate_dir, err }));
}
};
debug!("successfully copied data from: {}", source_directory.display());
if !allows_links {
- sess.warn(&format!(
- "Hard linking files in the incremental \
- compilation cache failed. Copying files \
- instead. Consider moving the cache \
- directory to a file system which supports \
- hard linking in session dir `{}`",
- session_dir.display()
- ));
+ sess.emit_warning(errors::HardLinkFailed { path: &session_dir });
}
sess.init_incr_comp_session(session_dir, directory_lock, true);
// Try to remove the session directory we just allocated. We don't
// know if there's any garbage in it from the failed copy action.
if let Err(err) = safe_remove_dir_all(&session_dir) {
- sess.warn(&format!(
- "Failed to delete partly initialized \
- session dir `{}`: {}",
- session_dir.display(),
- err
- ));
+ sess.emit_warning(errors::DeletePartial { path: &session_dir, err });
}
delete_session_dir_lock_file(sess, &lock_file_path);
);
if let Err(err) = safe_remove_dir_all(&*incr_comp_session_dir) {
- sess.warn(&format!(
- "Error deleting incremental compilation \
- session directory `{}`: {}",
- incr_comp_session_dir.display(),
- err
- ));
+ sess.emit_warning(errors::DeleteFull { path: &incr_comp_session_dir, err });
}
let lock_file_path = lock_file_path(&*incr_comp_session_dir);
}
Err(e) => {
// Warn about the error. However, no need to abort compilation now.
- sess.warn(&format!(
- "Error finalizing incremental compilation \
- session directory `{}`: {}",
- incr_comp_session_dir.display(),
- e
- ));
+ sess.emit_warning(errors::Finalize { path: &incr_comp_session_dir, err: e });
debug!("finalize_session_directory() - error, marking as invalid");
// Drop the file lock, so we can garage collect
debug!("{} directory created successfully", dir_tag);
Ok(())
}
- Err(err) => {
- let reported = sess.err(&format!(
- "Could not create incremental compilation {} \
- directory `{}`: {}",
- dir_tag,
- path.display(),
- err
- ));
- Err(reported)
- }
+ Err(err) => Err(sess.emit_err(errors::CreateIncrCompDir { tag: dir_tag, path, err })),
}
}
// the lock should be exclusive
Ok(lock) => Ok((lock, lock_file_path)),
Err(lock_err) => {
- let mut err = sess.struct_err(&format!(
- "incremental compilation: could not create \
- session directory lock file: {}",
- lock_err
- ));
- if flock::Lock::error_unsupported(&lock_err) {
- err.note(&format!(
- "the filesystem for the incremental path at {} \
- does not appear to support locking, consider changing the \
- incremental path to a filesystem that supports locking \
- or disable incremental compilation",
- session_dir.display()
- ));
- if std::env::var_os("CARGO").is_some() {
- err.help(
- "incremental compilation can be disabled by setting the \
- environment variable CARGO_INCREMENTAL=0 (see \
- https://doc.rust-lang.org/cargo/reference/profiles.html#incremental)",
- );
- err.help(
- "the entire build directory can be changed to a different \
- filesystem by setting the environment variable CARGO_TARGET_DIR \
- to a different path (see \
- https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir)",
- );
- }
- }
- Err(err.emit())
+ let is_unsupported_lock = flock::Lock::error_unsupported(&lock_err).then_some(());
+ Err(sess.emit_err(errors::CreateLock {
+ lock_err,
+ session_dir,
+ is_unsupported_lock,
+ is_cargo: std::env::var_os("CARGO").map(|_| ()),
+ }))
}
}
}
fn delete_session_dir_lock_file(sess: &Session, lock_file_path: &Path) {
if let Err(err) = safe_remove_file(&lock_file_path) {
- sess.warn(&format!(
- "Error deleting lock file for incremental \
- compilation session directory `{}`: {}",
- lock_file_path.display(),
- err
- ));
+ sess.emit_warning(errors::DeleteLock { path: lock_file_path, err });
}
}
if !lock_file_to_session_dir.values().any(|dir| *dir == directory_name) {
let path = crate_directory.join(directory_name);
if let Err(err) = safe_remove_dir_all(&path) {
- sess.warn(&format!(
- "Failed to garbage collect invalid incremental \
- compilation session directory `{}`: {}",
- path.display(),
- err
- ));
+ sess.emit_warning(errors::InvalidGcFailed { path: &path, err });
}
}
}
debug!("garbage_collect_session_directories() - deleting `{}`", path.display());
if let Err(err) = safe_remove_dir_all(&path) {
- sess.warn(&format!(
- "Failed to garbage collect finalized incremental \
- compilation session directory `{}`: {}",
- path.display(),
- err
- ));
+ sess.emit_warning(errors::FinalizedGcFailed { path: &path, err });
} else {
delete_session_dir_lock_file(sess, &lock_file_path(&path));
}
debug!("garbage_collect_session_directories() - deleting `{}`", path.display());
if let Err(err) = safe_remove_dir_all(&path) {
- sess.warn(&format!(
- "Failed to garbage collect incremental compilation session directory `{}`: {}",
- path.display(),
- err
- ));
+ sess.emit_warning(errors::SessionGcFailed { path: &path, err });
} else {
delete_session_dir_lock_file(sess, &lock_file_path(&path));
}
//! Code to save/load the dep-graph from files.
+use crate::errors;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::memmap::Mmap;
use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId};
use rustc_serialize::Decodable;
use rustc_session::config::IncrementalStateAssertion;
use rustc_session::Session;
-use std::path::Path;
+use std::path::{Path, PathBuf};
use super::data::*;
use super::file_format;
},
/// The file either didn't exist or was produced by an incompatible compiler version.
DataOutOfDate,
- /// An error occurred.
- Error {
- #[allow(missing_docs)]
- message: String,
- },
+ /// Loading the dep graph failed.
+ LoadDepGraph(PathBuf, std::io::Error),
+ /// Decoding loaded incremental cache failed.
+ DecodeIncrCache(Box<dyn std::any::Any + Send>),
}
impl<T: Default> LoadResult<T> {
// Check for errors when using `-Zassert-incremental-state`
match (sess.opts.assert_incr_state, &self) {
(Some(IncrementalStateAssertion::NotLoaded), LoadResult::Ok { .. }) => {
- sess.fatal(
- "We asserted that the incremental cache should not be loaded, \
- but it was loaded.",
- );
+ sess.emit_fatal(errors::AssertNotLoaded);
}
(
Some(IncrementalStateAssertion::Loaded),
- LoadResult::Error { .. } | LoadResult::DataOutOfDate,
+ LoadResult::LoadDepGraph(..)
+ | LoadResult::DecodeIncrCache(..)
+ | LoadResult::DataOutOfDate,
) => {
- sess.fatal(
- "We asserted that an existing incremental cache directory should \
- be successfully loaded, but it was not.",
- );
+ sess.emit_fatal(errors::AssertLoaded);
}
_ => {}
};
match self {
- LoadResult::Error { message } => {
- sess.warn(&message);
+ LoadResult::LoadDepGraph(path, err) => {
+ sess.emit_warning(errors::LoadDepGraph { path, err });
+ Default::default()
+ }
+ LoadResult::DecodeIncrCache(err) => {
+ sess.emit_warning(errors::DecodeIncrCache { err: format!("{err:?}") });
Default::default()
}
LoadResult::DataOutOfDate => {
if let Err(err) = delete_all_session_dir_contents(sess) {
- sess.err(&format!(
- "Failed to delete invalidated or incompatible \
- incremental compilation session directory contents `{}`: {}.",
- dep_graph_path(sess).display(),
- err
- ));
+ sess.emit_err(errors::DeleteIncompatible { path: dep_graph_path(sess), err });
}
Default::default()
}
// compiler version. Neither is an error.
LoadResult::DataOutOfDate
}
- Err(err) => LoadResult::Error {
- message: format!("could not load dep-graph from `{}`: {}", path.display(), err),
- },
+ Err(err) => LoadResult::LoadDepGraph(path.to_path_buf(), err),
}
}
pub fn open(self) -> LoadResult<T> {
match self {
MaybeAsync::Sync(result) => result,
- MaybeAsync::Async(handle) => handle.join().unwrap_or_else(|e| LoadResult::Error {
- message: format!("could not decode incremental cache: {:?}", e),
- }),
+ MaybeAsync::Async(handle) => {
+ handle.join().unwrap_or_else(|e| LoadResult::DecodeIncrCache(e))
+ }
}
}
}
match load_data(report_incremental_info, &path, nightly_build) {
LoadResult::DataOutOfDate => LoadResult::DataOutOfDate,
- LoadResult::Error { message } => LoadResult::Error { message },
+ LoadResult::LoadDepGraph(path, err) => LoadResult::LoadDepGraph(path, err),
+ LoadResult::DecodeIncrCache(err) => LoadResult::DecodeIncrCache(err),
LoadResult::Ok { data: (bytes, start_pos) } => {
let mut decoder = MemDecoder::new(&bytes, start_pos);
let prev_commandline_args_hash = u64::decode(&mut decoder);
+use crate::errors;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::join;
use rustc_middle::dep_graph::{DepGraph, SerializedDepGraph, WorkProduct, WorkProductId};
move || {
sess.time("incr_comp_persist_dep_graph", || {
if let Err(err) = tcx.dep_graph.encode(&tcx.sess.prof) {
- sess.err(&format!(
- "failed to write dependency graph to `{}`: {}",
- staging_dep_graph_path.display(),
- err
- ));
+ sess.emit_err(errors::WriteDepGraph { path: &staging_dep_graph_path, err });
}
if let Err(err) = fs::rename(&staging_dep_graph_path, &dep_graph_path) {
- sess.err(&format!(
- "failed to move dependency graph from `{}` to `{}`: {}",
- staging_dep_graph_path.display(),
- dep_graph_path.display(),
- err
- ));
+ sess.emit_err(errors::MoveDepGraph {
+ from: &staging_dep_graph_path,
+ to: &dep_graph_path,
+ err,
+ });
}
});
},
let mut encoder = match FileEncoder::new(&path_buf) {
Ok(encoder) => encoder,
Err(err) => {
- sess.err(&format!(
- "failed to create dependency graph at `{}`: {}",
- path_buf.display(),
- err
- ));
+ sess.emit_err(errors::CreateDepGraph { path: &path_buf, err });
return None;
}
};
//!
//! [work products]: WorkProduct
+use crate::errors;
use crate::persist::fs::*;
use rustc_data_structures::fx::FxHashMap;
use rustc_fs_util::link_or_copy;
let _ = saved_files.insert(ext.to_string(), file_name);
}
Err(err) => {
- sess.warn(&format!(
- "error copying object file `{}` to incremental directory as `{}`: {}",
- path.display(),
- path_in_incr_dir.display(),
- err
- ));
+ sess.emit_warning(errors::CopyWorkProductToCache {
+ from: &path,
+ to: &path_in_incr_dir,
+ err,
+ });
}
}
}
for (_, path) in &work_product.saved_files {
let path = in_incr_comp_dir_sess(sess, path);
if let Err(err) = std_fs::remove_file(&path) {
- sess.warn(&format!(
- "file-system error deleting outdated file `{}`: {}",
- path.display(),
- err
- ));
+ sess.emit_warning(errors::DeleteWorkProduct { path: &path, err });
}
}
}
rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_serialize = { path = "../rustc_serialize" }
-rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnosticArg};
-use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan};
+use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem;
use rustc_hir::Node;
use rustc_middle::dep_graph::DepContext;
+use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
use rustc_middle::ty::{
self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
for (key, values) in types.iter() {
let count = values.len();
let kind = key.descr();
- let mut returned_async_output_error = false;
for &sp in values {
- if sp.is_desugaring(DesugaringKind::Async) && !returned_async_output_error {
- if [sp] != err.span.primary_spans() {
- let mut span: MultiSpan = sp.into();
- span.push_span_label(
- sp,
- format!(
- "checked the `Output` of this `async fn`, {}{} {}{}",
- if count > 1 { "one of the " } else { "" },
- target,
- kind,
- pluralize!(count),
- ),
- );
- err.span_note(
- span,
- "while checking the return type of the `async fn`",
- );
- } else {
- err.span_label(
- sp,
- format!(
- "checked the `Output` of this `async fn`, {}{} {}{}",
- if count > 1 { "one of the " } else { "" },
- target,
- kind,
- pluralize!(count),
- ),
- );
- err.note("while checking the return type of the `async fn`");
- }
- returned_async_output_error = true;
- } else {
- err.span_label(
- sp,
- format!(
- "{}{} {}{}",
- if count == 1 { "the " } else { "one of the " },
- target,
- kind,
- pluralize!(count),
- ),
- );
- }
+ err.span_label(
+ sp,
+ format!(
+ "{}{} {}{}",
+ if count == 1 { "the " } else { "one of the " },
+ target,
+ kind,
+ pluralize!(count),
+ ),
+ );
}
}
}
// |
// = note: expected unit type `()`
// found closure `[closure@$DIR/issue-20862.rs:2:5: 2:14 x:_]`
- if !self.ignore_span.overlaps(span) {
+ //
+ // Also ignore opaque `Future`s that come from async fns.
+ if !self.ignore_span.overlaps(span)
+ && !span.is_desugaring(DesugaringKind::Async)
+ {
self.types.entry(kind).or_default().insert(span);
}
}
{
format!("expected this to be `{}`", expected)
} else {
- terr.to_string()
+ terr.to_string(self.tcx).to_string()
};
label_or_note(sp, &terr);
label_or_note(span, &msg);
} else {
- label_or_note(span, &terr.to_string());
+ label_or_note(span, &terr.to_string(self.tcx));
label_or_note(sp, &msg);
}
} else {
- label_or_note(span, &terr.to_string());
+ if let Some(values) = values
+ && let Some((e, f)) = values.ty()
+ && let TypeError::ArgumentSorts(..) | TypeError::Sorts(_) = terr
+ {
+ let e = self.tcx.erase_regions(e);
+ let f = self.tcx.erase_regions(f);
+ let expected = with_forced_trimmed_paths!(e.sort_string(self.tcx));
+ let found = with_forced_trimmed_paths!(f.sort_string(self.tcx));
+ if expected == found {
+ label_or_note(span, &terr.to_string(self.tcx));
+ } else {
+ label_or_note(span, &format!("expected {expected}, found {found}"));
+ }
+ } else {
+ label_or_note(span, &terr.to_string(self.tcx));
+ }
}
if let Some((expected, found, exp_p, found_p)) = expected_found {
self.check_and_note_conflicting_crates(diag, terr);
self.note_and_explain_type_err(diag, terr, cause, span, cause.body_id.to_def_id());
+ if let Some(exp_found) = exp_found
+ && let exp_found = TypeError::Sorts(exp_found)
+ && exp_found != terr
+ {
+ self.note_and_explain_type_err(
+ diag,
+ exp_found,
+ cause,
+ span,
+ cause.body_id.to_def_id(),
+ );
+ }
if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values
&& let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind()
diag.help(
"given a type parameter `T` and a method `foo`:
```
-trait Trait<T> { fn foo(&tcx) -> T; }
+trait Trait<T> { fn foo(&self) -> T; }
```
the only ways to implement method `foo` are:
- constrain `T` with an explicit type:
```
impl Trait<String> for X {
- fn foo(&tcx) -> String { String::new() }
+ fn foo(&self) -> String { String::new() }
}
```
- add a trait bound to `T` and call a method on that trait that returns `Self`:
```
impl<T: std::default::Default> Trait<T> for X {
- fn foo(&tcx) -> T { <T as std::default::Default>::default() }
+ fn foo(&self) -> T { <T as std::default::Default>::default() }
}
```
- change `foo` to return an argument of type `T`:
```
impl<T> Trait<T> for X {
- fn foo(&tcx, x: T) -> T { x }
+ fn foo(&self, x: T) -> T { x }
}
```",
);
);
}
}
+ (ty::FnPtr(_), ty::FnDef(def, _))
+ if let hir::def::DefKind::Fn = tcx.def_kind(def) => {
+ diag.note(
+ "when the arguments and return types match, functions can be coerced \
+ to function pointers",
+ );
+ }
_ => {}
}
debug!(
```
trait Trait {
type T;
-fn foo(&tcx) -> Self::T;
+fn foo(&self) -> Self::T;
}
```
the only way of implementing method `foo` is to constrain `T` with an explicit associated type:
```
impl Trait for X {
type T = String;
-fn foo(&tcx) -> Self::T { String::new() }
+fn foo(&self) -> Self::T { String::new() }
}
```",
);
(msg, sug)
}
};
- diag.span_suggestion(span, msg, sug, Applicability::MaybeIncorrect);
+ diag.span_suggestion_verbose(span, msg, sug, Applicability::MaybeIncorrect);
}
(ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
let expected_sig =
}
}
+ #[inline]
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if !t.needs_infer() && !t.has_erasable_regions() {
- return t;
- }
-
- let tcx = self.infcx.tcx;
-
- match *t.kind() {
- ty::Infer(ty::TyVar(v)) => {
- let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
- self.freshen_ty(opt_ty, ty::TyVar(v), ty::FreshTy)
- }
+ t
+ } else {
+ match *t.kind() {
+ ty::Infer(v) => self.fold_infer_ty(v).unwrap_or(t),
- ty::Infer(ty::IntVar(v)) => self.freshen_ty(
- self.infcx
- .inner
- .borrow_mut()
- .int_unification_table()
- .probe_value(v)
- .map(|v| v.to_type(tcx)),
- ty::IntVar(v),
- ty::FreshIntTy,
- ),
+ // This code is hot enough that a non-debug assertion here makes a noticeable
+ // difference on benchmarks like `wg-grammar`.
+ #[cfg(debug_assertions)]
+ ty::Placeholder(..) | ty::Bound(..) => bug!("unexpected type {:?}", t),
- ty::Infer(ty::FloatVar(v)) => self.freshen_ty(
- self.infcx
- .inner
- .borrow_mut()
- .float_unification_table()
- .probe_value(v)
- .map(|v| v.to_type(tcx)),
- ty::FloatVar(v),
- ty::FreshFloatTy,
- ),
-
- ty::Infer(ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct)) => {
- if ct >= self.ty_freshen_count {
- bug!(
- "Encountered a freshend type with id {} \
- but our counter is only at {}",
- ct,
- self.ty_freshen_count
- );
- }
- t
+ _ => t.super_fold_with(self),
}
-
- ty::Generator(..)
- | ty::Bool
- | ty::Char
- | ty::Int(..)
- | ty::Uint(..)
- | ty::Float(..)
- | ty::Adt(..)
- | ty::Str
- | ty::Error(_)
- | ty::Array(..)
- | ty::Slice(..)
- | ty::RawPtr(..)
- | ty::Ref(..)
- | ty::FnDef(..)
- | ty::FnPtr(_)
- | ty::Dynamic(..)
- | ty::Never
- | ty::Tuple(..)
- | ty::Alias(..)
- | ty::Foreign(..)
- | ty::Param(..)
- | ty::Closure(..)
- | ty::GeneratorWitnessMIR(..)
- | ty::GeneratorWitness(..) => t.super_fold_with(self),
-
- ty::Placeholder(..) | ty::Bound(..) => bug!("unexpected type {:?}", t),
}
}
}
}
}
+
+impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
+ // This is separate from `fold_ty` to keep that method small and inlinable.
+ #[inline(never)]
+ fn fold_infer_ty(&mut self, v: ty::InferTy) -> Option<Ty<'tcx>> {
+ match v {
+ ty::TyVar(v) => {
+ let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
+ Some(self.freshen_ty(opt_ty, ty::TyVar(v), ty::FreshTy))
+ }
+
+ ty::IntVar(v) => Some(
+ self.freshen_ty(
+ self.infcx
+ .inner
+ .borrow_mut()
+ .int_unification_table()
+ .probe_value(v)
+ .map(|v| v.to_type(self.infcx.tcx)),
+ ty::IntVar(v),
+ ty::FreshIntTy,
+ ),
+ ),
+
+ ty::FloatVar(v) => Some(
+ self.freshen_ty(
+ self.infcx
+ .inner
+ .borrow_mut()
+ .float_unification_table()
+ .probe_value(v)
+ .map(|v| v.to_type(self.infcx.tcx)),
+ ty::FloatVar(v),
+ ty::FreshFloatTy,
+ ),
+ ),
+
+ ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct) => {
+ if ct >= self.ty_freshen_count {
+ bug!(
+ "Encountered a freshend type with id {} \
+ but our counter is only at {}",
+ ct,
+ self.ty_freshen_count
+ );
+ }
+ None
+ }
+ }
+ }
+}
types: &mut |bound_ty: ty::BoundTy| {
self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
universe: next_universe,
- name: bound_ty.var,
+ name: bound_ty.kind,
}))
},
consts: &mut |bound_var: ty::BoundVar, ty| {
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
use rustc_middle::ty::visit::TypeVisitable;
pub use rustc_middle::ty::IntVarValue;
-use rustc_middle::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt};
+use rustc_middle::ty::{self, GenericParamDefKind, InferConst, InferTy, Ty, TyCtxt};
use rustc_middle::ty::{ConstVid, FloatVid, IntVid, TyVid};
use rustc_span::symbol::Symbol;
use rustc_span::Span;
where
T: TypeFoldable<'tcx>,
{
- if !value.needs_infer() {
- return value; // Avoid duplicated subst-folding.
+ if !value.has_non_region_infer() {
+ return value;
}
let mut r = resolve::OpportunisticVarResolver::new(self);
value.fold_with(&mut r)
/// If `ty` is a type variable of some kind, resolve it one level
/// (but do not resolve types found in the result). If `typ` is
/// not a type variable, just return it unmodified.
+ #[inline]
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
- match *ty.kind() {
- ty::Infer(ty::TyVar(v)) => {
+ if let ty::Infer(v) = ty.kind() { self.fold_infer_ty(*v).unwrap_or(ty) } else { ty }
+ }
+
+ fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
+ if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() {
+ self.infcx
+ .inner
+ .borrow_mut()
+ .const_unification_table()
+ .probe_value(vid)
+ .val
+ .known()
+ .unwrap_or(ct)
+ } else {
+ ct
+ }
+ }
+}
+
+impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
+ // This is separate from `fold_ty` to keep that method small and inlinable.
+ #[inline(never)]
+ fn fold_infer_ty(&mut self, v: InferTy) -> Option<Ty<'tcx>> {
+ match v {
+ ty::TyVar(v) => {
// Not entirely obvious: if `typ` is a type variable,
// it can be resolved to an int/float variable, which
// can then be recursively resolved, hence the
// Note: if these two lines are combined into one we get
// dynamic borrow errors on `self.inner`.
let known = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
- known.map_or(ty, |t| self.fold_ty(t))
+ known.map(|t| self.fold_ty(t))
}
- ty::Infer(ty::IntVar(v)) => self
+ ty::IntVar(v) => self
.infcx
.inner
.borrow_mut()
.int_unification_table()
.probe_value(v)
- .map_or(ty, |v| v.to_type(self.infcx.tcx)),
+ .map(|v| v.to_type(self.infcx.tcx)),
- ty::Infer(ty::FloatVar(v)) => self
+ ty::FloatVar(v) => self
.infcx
.inner
.borrow_mut()
.float_unification_table()
.probe_value(v)
- .map_or(ty, |v| v.to_type(self.infcx.tcx)),
+ .map(|v| v.to_type(self.infcx.tcx)),
- _ => ty,
- }
- }
-
- fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
- if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() {
- self.infcx
- .inner
- .borrow_mut()
- .const_unification_table()
- .probe_value(vid)
- .val
- .known()
- .unwrap_or(ct)
- } else {
- ct
+ ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => None,
}
}
}
) -> SubstsRef<'tcx> {
struct ReplaceParamAndInferWithPlaceholder<'tcx> {
tcx: TyCtxt<'tcx>,
- idx: usize,
+ idx: u32,
}
impl<'tcx> TypeFolder<'tcx> for ReplaceParamAndInferWithPlaceholder<'tcx> {
if let ty::Infer(_) = t.kind() {
self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
universe: ty::UniverseIndex::ROOT,
- name: ty::BoundVar::from_usize({
+ name: ty::BoundTyKind::Anon({
let idx = self.idx;
self.idx += 1;
idx
self.tcx.mk_const(
ty::PlaceholderConst {
universe: ty::UniverseIndex::ROOT,
- name: ty::BoundVar::from_usize({
+ name: ty::BoundVar::from_u32({
let idx = self.idx;
self.idx += 1;
idx
where
D: TypeRelatingDelegate<'tcx>,
{
- fn const_equate_obligation(&mut self, _a: ty::Const<'tcx>, _b: ty::Const<'tcx>) {
- // We don't have to worry about the equality of consts during borrow checking
- // as consts always have a static lifetime.
- // FIXME(oli-obk): is this really true? We can at least have HKL and with
- // inline consts we may have further lifetimes that may be unsound to treat as
- // 'static.
+ fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
+ self.delegate.register_obligations(vec![Obligation::new(
+ self.tcx(),
+ ObligationCause::dummy(),
+ self.param_env(),
+ ty::Binder::dummy(ty::PredicateKind::ConstEquate(a, b)),
+ )]);
}
}
/// useful for printing messages etc but also required at various
/// points for correctness.
pub struct OpportunisticVarResolver<'a, 'tcx> {
- infcx: &'a InferCtxt<'tcx>,
+ // The shallow resolver is used to resolve inference variables at every
+ // level of the type.
+ shallow_resolver: crate::infer::ShallowResolver<'a, 'tcx>,
}
impl<'a, 'tcx> OpportunisticVarResolver<'a, 'tcx> {
#[inline]
pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
- OpportunisticVarResolver { infcx }
+ OpportunisticVarResolver { shallow_resolver: crate::infer::ShallowResolver { infcx } }
}
}
impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> {
fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
- self.infcx.tcx
+ TypeFolder::tcx(&self.shallow_resolver)
}
+ #[inline]
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if !t.has_non_region_infer() {
t // micro-optimize -- if there is nothing in this type that this fold affects...
} else {
- let t = self.infcx.shallow_resolve(t);
+ let t = self.shallow_resolver.fold_ty(t);
t.super_fold_with(self)
}
}
if !ct.has_non_region_infer() {
ct // micro-optimize -- if there is nothing in this const that this fold affects...
} else {
- let ct = self.infcx.shallow_resolve(ct);
+ let ct = self.shallow_resolver.fold_const(ct);
ct.super_fold_with(self)
}
}
// Get predicates declared on the trait.
let predicates = tcx.super_predicates_of(data.def_id());
- let obligations = predicates.predicates.iter().map(|&(mut pred, span)| {
- // when parent predicate is non-const, elaborate it to non-const predicates.
- if data.constness == ty::BoundConstness::NotConst {
- pred = pred.without_const(tcx);
- }
-
- let cause = obligation.cause.clone().derived_cause(
- bound_predicate.rebind(data),
- |derived| {
- traits::ImplDerivedObligation(Box::new(
- traits::ImplDerivedObligationCause {
- derived,
- impl_def_id: data.def_id(),
- span,
- },
- ))
- },
- );
- predicate_obligation(
- pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)),
- obligation.param_env,
- cause,
- )
- });
+ let obligations =
+ predicates.predicates.iter().enumerate().map(|(index, &(mut pred, span))| {
+ // when parent predicate is non-const, elaborate it to non-const predicates.
+ if data.constness == ty::BoundConstness::NotConst {
+ pred = pred.without_const(tcx);
+ }
+
+ let cause = obligation.cause.clone().derived_cause(
+ bound_predicate.rebind(data),
+ |derived| {
+ traits::ImplDerivedObligation(Box::new(
+ traits::ImplDerivedObligationCause {
+ derived,
+ impl_def_id: data.def_id(),
+ impl_def_predicate_index: Some(index),
+ span,
+ },
+ ))
+ },
+ );
+ predicate_obligation(
+ pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)),
+ obligation.param_env,
+ cause,
+ )
+ });
debug!(?data, ?obligations, "super_predicates");
// Only keep those bounds that we haven't already seen.
rustc_parse = { path = "../rustc_parse" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
-rustc_serialize = { path = "../rustc_serialize" }
rustc_middle = { path = "../rustc_middle" }
rustc_ast_lowering = { path = "../rustc_ast_lowering" }
rustc_ast_passes = { path = "../rustc_ast_passes" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
rustc_ty_utils = { path = "../rustc_ty_utils" }
-[dev-dependencies]
-rustc_target = { path = "../rustc_target" }
-
[features]
llvm = ['rustc_codegen_llvm']
rustc_use_parallel_compiler = ['rayon', 'rustc-rayon-core', 'rustc_query_impl/rustc_use_parallel_compiler', 'rustc_errors/rustc_use_parallel_compiler']
use rustc_macros::Diagnostic;
+use rustc_session::config::CrateType;
use rustc_span::{Span, Symbol};
+use rustc_target::spec::TargetTriple;
use std::io;
use std::path::Path;
#[derive(Diagnostic)]
#[diag(interface_proc_macro_crate_panic_abort)]
pub struct ProcMacroCratePanicAbort;
+
+#[derive(Diagnostic)]
+#[diag(interface_unsupported_crate_type_for_target)]
+pub struct UnsupportedCrateTypeForTarget<'a> {
+ pub crate_type: CrateType,
+ pub target_triple: &'a TargetTriple,
+}
+
+#[derive(Diagnostic)]
+#[diag(interface_multiple_output_types_adaption)]
+pub struct MultipleOutputTypesAdaption;
+
+#[derive(Diagnostic)]
+#[diag(interface_ignoring_extra_filename)]
+pub struct IgnoringExtraFilename;
+
+#[derive(Diagnostic)]
+#[diag(interface_ignoring_out_dir)]
+pub struct IgnoringOutDir;
-use crate::errors::{
- CantEmitMIR, EmojiIdentifier, ErrorWritingDependencies, FerrisIdentifier,
- GeneratedFileConflictsWithDirectory, InputFileWouldBeOverWritten, MixedBinCrate,
- MixedProcMacroCrate, OutDirError, ProcMacroCratePanicAbort, ProcMacroDocWithoutArg,
- TempsDirError,
-};
+use crate::errors;
use crate::interface::{Compiler, Result};
use crate::proc_macro_decls;
use crate::util;
if crate_types.len() > 1 {
if is_executable_crate {
- sess.emit_err(MixedBinCrate);
+ sess.emit_err(errors::MixedBinCrate);
}
if is_proc_macro_crate {
- sess.emit_err(MixedProcMacroCrate);
+ sess.emit_err(errors::MixedProcMacroCrate);
}
}
if is_proc_macro_crate && sess.panic_strategy() == PanicStrategy::Abort {
- sess.emit_warning(ProcMacroCratePanicAbort);
+ sess.emit_warning(errors::ProcMacroCratePanicAbort);
}
// For backwards compatibility, we don't try to run proc macro injection
// However, we do emit a warning, to let such users know that they should
// start passing '--crate-type proc-macro'
if has_proc_macro_decls && sess.opts.actually_rustdoc && !is_proc_macro_crate {
- sess.emit_warning(ProcMacroDocWithoutArg);
+ sess.emit_warning(errors::ProcMacroDocWithoutArg);
} else {
krate = sess.time("maybe_create_a_macro_crate", || {
let is_test_crate = sess.opts.test;
spans.sort();
if ident == sym::ferris {
let first_span = spans[0];
- sess.emit_err(FerrisIdentifier { spans, first_span });
+ sess.emit_err(errors::FerrisIdentifier { spans, first_span });
} else {
- sess.emit_err(EmojiIdentifier { spans, ident });
+ sess.emit_err(errors::EmojiIdentifier { spans, ident });
}
}
});
}
}
Err(error) => {
- sess.emit_fatal(ErrorWritingDependencies { path: &deps_filename, error });
+ sess.emit_fatal(errors::ErrorWritingDependencies { path: &deps_filename, error });
}
}
}
if let Some(ref input_path) = sess.io.input.opt_path() {
if sess.opts.will_create_output_file() {
if output_contains_path(&output_paths, input_path) {
- sess.emit_fatal(InputFileWouldBeOverWritten { path: input_path });
+ sess.emit_fatal(errors::InputFileWouldBeOverWritten { path: input_path });
}
if let Some(ref dir_path) = output_conflicts_with_dir(&output_paths) {
- sess.emit_fatal(GeneratedFileConflictsWithDirectory { input_path, dir_path });
+ sess.emit_fatal(errors::GeneratedFileConflictsWithDirectory {
+ input_path,
+ dir_path,
+ });
}
}
}
if let Some(ref dir) = sess.io.temps_dir {
if fs::create_dir_all(dir).is_err() {
- sess.emit_fatal(TempsDirError);
+ sess.emit_fatal(errors::TempsDirError);
}
}
if !only_dep_info {
if let Some(ref dir) = sess.io.output_dir {
if fs::create_dir_all(dir).is_err() {
- sess.emit_fatal(OutDirError);
+ sess.emit_fatal(errors::OutDirError);
}
}
}
if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) {
if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx) {
- tcx.sess.emit_err(CantEmitMIR { error });
+ tcx.sess.emit_err(errors::CantEmitMIR { error });
tcx.sess.abort_if_errors();
}
}
+use crate::errors;
use info;
use libloading::Library;
use rustc_ast as ast;
}
base.retain(|crate_type| {
- let res = !output::invalid_output_for_target(session, *crate_type);
-
- if !res {
- session.warn(&format!(
- "dropping unsupported crate type `{}` for target `{}`",
- *crate_type, session.opts.target_triple
- ));
+ if output::invalid_output_for_target(session, *crate_type) {
+ session.emit_warning(errors::UnsupportedCrateTypeForTarget {
+ crate_type: *crate_type,
+ target_triple: &session.opts.target_triple,
+ });
+ false
+ } else {
+ true
}
-
- res
});
base
let unnamed_output_types =
sess.opts.output_types.values().filter(|a| a.is_none()).count();
let ofile = if unnamed_output_types > 1 {
- sess.warn(
- "due to multiple output types requested, the explicitly specified \
- output file name will be adapted for each output type",
- );
+ sess.emit_warning(errors::MultipleOutputTypesAdaption);
None
} else {
if !sess.opts.cg.extra_filename.is_empty() {
- sess.warn("ignoring -C extra-filename flag due to -o flag");
+ sess.emit_warning(errors::IgnoringExtraFilename);
}
Some(out_file.clone())
};
if sess.io.output_dir != None {
- sess.warn("ignoring --out-dir flag due to -o flag");
+ sess.emit_warning(errors::IgnoringOutDir);
}
OutputFilenames::new(
}
fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
- // If the method is an impl for a trait, don't doc.
let context = method_context(cx, impl_item.owner_id.def_id);
- if context == MethodLateContext::TraitImpl {
- return;
- }
- // If the method is an impl for an item with docs_hidden, don't doc.
- if context == MethodLateContext::PlainImpl {
- let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
- let impl_ty = cx.tcx.type_of(parent);
- let outerdef = match impl_ty.kind() {
- ty::Adt(def, _) => Some(def.did()),
- ty::Foreign(def_id) => Some(*def_id),
- _ => None,
- };
- let is_hidden = match outerdef {
- Some(id) => cx.tcx.is_doc_hidden(id),
- None => false,
- };
- if is_hidden {
- return;
+ match context {
+ // If the method is an impl for a trait, don't doc.
+ MethodLateContext::TraitImpl => return,
+ MethodLateContext::TraitAutoImpl => {}
+ // If the method is an impl for an item with docs_hidden, don't doc.
+ MethodLateContext::PlainImpl => {
+ let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
+ let impl_ty = cx.tcx.type_of(parent);
+ let outerdef = match impl_ty.kind() {
+ ty::Adt(def, _) => Some(def.did()),
+ ty::Foreign(def_id) => Some(*def_id),
+ _ => None,
+ };
+ let is_hidden = match outerdef {
+ Some(id) => cx.tcx.is_doc_hidden(id),
+ None => false,
+ };
+ if is_hidden {
+ return;
+ }
}
}
store.register_renamed("exceeding_bitshifts", "arithmetic_overflow");
store.register_renamed("redundant_semicolon", "redundant_semicolons");
store.register_renamed("overlapping_patterns", "overlapping_range_endpoints");
- store.register_renamed("safe_packed_borrows", "unaligned_references");
store.register_renamed("disjoint_capture_migration", "rust_2021_incompatible_closure_captures");
store.register_renamed("or_patterns_back_compat", "rust_2021_incompatible_or_patterns");
store.register_renamed("non_fmt_panic", "non_fmt_panics");
"converted into hard error, see issue #71800 \
<https://github.com/rust-lang/rust/issues/71800> for more information",
);
+ store.register_removed(
+ "safe_packed_borrows",
+ "converted into hard error, see issue #82523 \
+ <https://github.com/rust-lang/rust/issues/82523> for more information",
+ );
+ store.register_removed(
+ "unaligned_references",
+ "converted into hard error, see issue #82523 \
+ <https://github.com/rust-lang/rust/issues/82523> for more information",
+ );
}
fn register_internals(store: &mut LintStore) {
pub cx: &'a LateContext<'b>,
pub def_id: DefId,
pub note: Option<Symbol>,
+ pub suggestion: Option<UnusedDefSuggestion>,
+}
+
+#[derive(Subdiagnostic)]
+pub enum UnusedDefSuggestion {
+ #[suggestion(
+ suggestion,
+ style = "verbose",
+ code = "let _ = ",
+ applicability = "machine-applicable"
+ )]
+ Default {
+ #[primary_span]
+ span: Span,
+ },
}
// Needed because of def_path_str
if let Some(note) = self.note {
diag.note(note.as_str());
}
+ if let Some(sugg) = self.suggestion {
+ diag.subdiagnostic(sugg);
+ }
diag
}
use crate::lints::{
PathStatementDrop, PathStatementDropSub, PathStatementNoEffect, UnusedAllocationDiag,
- UnusedAllocationMutDiag, UnusedClosure, UnusedDef, UnusedDelim, UnusedDelimSuggestion,
- UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedResult,
+ UnusedAllocationMutDiag, UnusedClosure, UnusedDef, UnusedDefSuggestion, UnusedDelim,
+ UnusedDelimSuggestion, UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedResult,
};
use crate::Lint;
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
);
}
MustUsePath::Def(span, def_id, reason) => {
+ let suggestion = if matches!(
+ cx.tcx.get_diagnostic_name(*def_id),
+ Some(sym::add)
+ | Some(sym::sub)
+ | Some(sym::mul)
+ | Some(sym::div)
+ | Some(sym::rem)
+ | Some(sym::neg),
+ ) {
+ Some(UnusedDefSuggestion::Default { span: span.shrink_to_lo() })
+ } else {
+ None
+ };
cx.emit_spanned_lint(
UNUSED_MUST_USE,
*span,
cx,
def_id: *def_id,
note: *reason,
+ suggestion,
},
);
}
ArrayLenExpr,
AnonConst,
MatchArmExpr,
+ IndexExpr,
}
impl From<UnusedDelimsCtx> for &'static str {
UnusedDelimsCtx::LetScrutineeExpr => "`let` scrutinee expression",
UnusedDelimsCtx::ArrayLenExpr | UnusedDelimsCtx::AnonConst => "const expression",
UnusedDelimsCtx::MatchArmExpr => "match arm expression",
+ UnusedDelimsCtx::IndexExpr => "index expression",
}
}
}
keep_space: (bool, bool),
) {
let primary_span = if let Some((lo, hi)) = spans {
+ if hi.is_empty() {
+ // do not point at delims that do not exist
+ return;
+ }
MultiSpan::from(vec![lo, hi])
} else {
MultiSpan::from(value_span)
(value, UnusedDelimsCtx::ReturnValue, false, Some(left), None)
}
+ Index(_, ref value) => (value, UnusedDelimsCtx::IndexExpr, false, None, None),
+
Assign(_, ref value, _) | AssignOp(.., ref value) => {
(value, UnusedDelimsCtx::AssignedValue, false, None, None)
}
"lints that have been renamed or removed"
}
-declare_lint! {
- /// The `unaligned_references` lint detects unaligned references to fields
- /// of [packed] structs.
- ///
- /// [packed]: https://doc.rust-lang.org/reference/type-layout.html#the-alignment-modifiers
- ///
- /// ### Example
- ///
- /// ```rust,compile_fail
- /// #[repr(packed)]
- /// pub struct Foo {
- /// field1: u64,
- /// field2: u8,
- /// }
- ///
- /// fn main() {
- /// unsafe {
- /// let foo = Foo { field1: 0, field2: 0 };
- /// let _ = &foo.field1;
- /// println!("{}", foo.field1); // An implicit `&` is added here, triggering the lint.
- /// }
- /// }
- /// ```
- ///
- /// {{produces}}
- ///
- /// ### Explanation
- ///
- /// Creating a reference to an insufficiently aligned packed field is [undefined behavior] and
- /// should be disallowed. Using an `unsafe` block does not change anything about this. Instead,
- /// the code should do a copy of the data in the packed field or use raw pointers and unaligned
- /// accesses. See [issue #82523] for more information.
- ///
- /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
- /// [issue #82523]: https://github.com/rust-lang/rust/issues/82523
- pub UNALIGNED_REFERENCES,
- Deny,
- "detects unaligned references to fields of packed structs",
- @future_incompatible = FutureIncompatibleInfo {
- reference: "issue #82523 <https://github.com/rust-lang/rust/issues/82523>",
- reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
- };
- report_in_external_macro
-}
-
declare_lint! {
/// The `const_item_mutation` lint detects attempts to mutate a `const`
/// item.
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
INVALID_TYPE_PARAM_DEFAULT,
RENAMED_AND_REMOVED_LINTS,
- UNALIGNED_REFERENCES,
CONST_ITEM_MUTATION,
PATTERNS_IN_FNS_WITHOUT_BODY,
MISSING_FRAGMENT_SPECIFIER,
#include "llvm/Passes/StandardInstrumentations.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/FileSystem.h"
+#if LLVM_VERSION_GE(17, 0)
+#include "llvm/Support/VirtualFileSystem.h"
+#endif
#include "llvm/Support/Host.h"
#if LLVM_VERSION_LT(14, 0)
#include "llvm/Support/TargetRegistry.h"
Optional<PGOOptions> PGOOpt;
#else
std::optional<PGOOptions> PGOOpt;
+#endif
+#if LLVM_VERSION_GE(17, 0)
+ auto FS = vfs::getRealFileSystem();
#endif
if (PGOGenPath) {
assert(!PGOUsePath && !PGOSampleUsePath);
- PGOOpt = PGOOptions(PGOGenPath, "", "", PGOOptions::IRInstr,
- PGOOptions::NoCSAction, DebugInfoForProfiling);
+ PGOOpt = PGOOptions(PGOGenPath, "", "",
+#if LLVM_VERSION_GE(17, 0)
+ FS,
+#endif
+ PGOOptions::IRInstr, PGOOptions::NoCSAction,
+ DebugInfoForProfiling);
} else if (PGOUsePath) {
assert(!PGOSampleUsePath);
- PGOOpt = PGOOptions(PGOUsePath, "", "", PGOOptions::IRUse,
- PGOOptions::NoCSAction, DebugInfoForProfiling);
+ PGOOpt = PGOOptions(PGOUsePath, "", "",
+#if LLVM_VERSION_GE(17, 0)
+ FS,
+#endif
+ PGOOptions::IRUse, PGOOptions::NoCSAction,
+ DebugInfoForProfiling);
} else if (PGOSampleUsePath) {
- PGOOpt = PGOOptions(PGOSampleUsePath, "", "", PGOOptions::SampleUse,
- PGOOptions::NoCSAction, DebugInfoForProfiling);
+ PGOOpt = PGOOptions(PGOSampleUsePath, "", "",
+#if LLVM_VERSION_GE(17, 0)
+ FS,
+#endif
+ PGOOptions::SampleUse, PGOOptions::NoCSAction,
+ DebugInfoForProfiling);
} else if (DebugInfoForProfiling) {
- PGOOpt = PGOOptions("", "", "", PGOOptions::NoAction,
- PGOOptions::NoCSAction, DebugInfoForProfiling);
+ PGOOpt = PGOOptions("", "", "",
+#if LLVM_VERSION_GE(17, 0)
+ FS,
+#endif
+ PGOOptions::NoAction, PGOOptions::NoCSAction,
+ DebugInfoForProfiling);
}
PassBuilder PB(TM, PTO, PGOOpt, &PIC);
let generated_code = self
.generate_inner_field_code(
attr,
- FieldInfo {
- binding: binding_info,
- ty: inner_ty.inner_type().unwrap_or(&field.ty),
- span: &field.span(),
- },
+ FieldInfo { binding: binding_info, ty: inner_ty, span: &field.span() },
binding,
)
.unwrap_or_else(|v| v.to_compile_error());
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug))
}
SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => {
- if type_matches_path(info.ty, &["rustc_span", "Span"]) {
+ if type_matches_path(info.ty.inner_type(), &["rustc_span", "Span"]) {
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug))
- } else if type_is_unit(info.ty) {
+ } else if type_is_unit(info.ty.inner_type()) {
Ok(self.add_subdiagnostic(&fn_ident, slug))
} else {
report_type_error(attr, "`Span` or `()`")?
code_field,
code_init,
} => {
+ if let FieldInnerTy::Vec(_) = info.ty {
+ throw_invalid_attr!(attr, &meta, |diag| {
+ diag
+ .note("`#[suggestion(...)]` applied to `Vec` field is ambiguous")
+ .help("to show a suggestion consisting of multiple parts, use a `Subdiagnostic` annotated with `#[multipart_suggestion(...)]`")
+ .help("to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]`")
+ });
+ }
+
let (span_field, mut applicability) = self.span_and_applicability_of_ty(info)?;
if let Some((static_applicability, span)) = static_applicability {
&self,
info: FieldInfo<'_>,
) -> Result<(TokenStream, SpannedOption<TokenStream>), DiagnosticDeriveError> {
- match &info.ty {
+ match &info.ty.inner_type() {
// If `ty` is `Span` w/out applicability, then use `Applicability::Unspecified`.
ty @ Type::Path(..) if type_matches_path(ty, &["rustc_span", "Span"]) => {
let binding = &info.binding.binding;
return quote! {};
}
- let info = FieldInfo {
- binding,
- ty: inner_ty.inner_type().unwrap_or(&ast.ty),
- span: &ast.span(),
- };
+ let info = FieldInfo { binding, ty: inner_ty, span: &ast.span() };
let generated = self
.generate_field_code_inner(kind_stats, attr, info, inner_ty.will_iterate())
let binding = info.binding.binding.clone();
// FIXME(#100717): support `Option<Span>` on `primary_span` like in the
// diagnostic derive
+ if !matches!(info.ty, FieldInnerTy::Plain(_)) {
+ throw_invalid_attr!(attr, &Meta::Path(path), |diag| {
+ let diag = diag.note("there must be exactly one primary span");
+
+ if kind_stats.has_normal_suggestion {
+ diag.help(
+ "to create a suggestion with multiple spans, \
+ use `#[multipart_suggestion]` instead",
+ )
+ } else {
+ diag
+ }
+ });
+ }
+
self.span_field.set_once(binding, span);
}
path: &[&str],
ty_name: &str,
) -> Result<(), DiagnosticDeriveError> {
- if !type_matches_path(info.ty, path) {
+ if !type_matches_path(info.ty.inner_type(), path) {
report_type_error(attr, ty_name)?;
}
attr: &Attribute,
info: &FieldInfo<'_>,
) -> Result<(), DiagnosticDeriveError> {
- if !type_matches_path(info.ty, &["rustc_span", "Span"])
- && !type_matches_path(info.ty, &["rustc_errors", "MultiSpan"])
+ if !type_matches_path(info.ty.inner_type(), &["rustc_span", "Span"])
+ && !type_matches_path(info.ty.inner_type(), &["rustc_errors", "MultiSpan"])
{
report_type_error(attr, "`Span` or `MultiSpan`")?;
}
}
/// Inner type of a field and type of wrapper.
+#[derive(Copy, Clone)]
pub(crate) enum FieldInnerTy<'ty> {
/// Field is wrapped in a `Option<$inner>`.
Option(&'ty Type),
/// Field is wrapped in a `Vec<$inner>`.
Vec(&'ty Type),
/// Field isn't wrapped in an outer type.
- None,
+ Plain(&'ty Type),
}
impl<'ty> FieldInnerTy<'ty> {
/// Returns inner type for a field, if there is one.
///
- /// - If `ty` is an `Option`, returns `FieldInnerTy::Option { inner: (inner type) }`.
- /// - If `ty` is a `Vec`, returns `FieldInnerTy::Vec { inner: (inner type) }`.
- /// - Otherwise returns `None`.
+ /// - If `ty` is an `Option<Inner>`, returns `FieldInnerTy::Option(Inner)`.
+ /// - If `ty` is a `Vec<Inner>`, returns `FieldInnerTy::Vec(Inner)`.
+ /// - Otherwise returns `FieldInnerTy::Plain(ty)`.
pub(crate) fn from_type(ty: &'ty Type) -> Self {
- let variant: &dyn Fn(&'ty Type) -> FieldInnerTy<'ty> =
- if type_matches_path(ty, &["std", "option", "Option"]) {
- &FieldInnerTy::Option
- } else if type_matches_path(ty, &["std", "vec", "Vec"]) {
- &FieldInnerTy::Vec
- } else {
- return FieldInnerTy::None;
+ fn single_generic_type(ty: &Type) -> &Type {
+ let Type::Path(ty_path) = ty else {
+ panic!("expected path type");
};
- if let Type::Path(ty_path) = ty {
let path = &ty_path.path;
let ty = path.segments.iter().last().unwrap();
- if let syn::PathArguments::AngleBracketed(bracketed) = &ty.arguments {
- if bracketed.args.len() == 1 {
- if let syn::GenericArgument::Type(ty) = &bracketed.args[0] {
- return variant(ty);
- }
- }
- }
+ let syn::PathArguments::AngleBracketed(bracketed) = &ty.arguments else {
+ panic!("expected bracketed generic arguments");
+ };
+
+ assert_eq!(bracketed.args.len(), 1);
+
+ let syn::GenericArgument::Type(ty) = &bracketed.args[0] else {
+ panic!("expected generic parameter to be a type generic");
+ };
+
+ ty
}
- unreachable!();
+ if type_matches_path(ty, &["std", "option", "Option"]) {
+ FieldInnerTy::Option(single_generic_type(ty))
+ } else if type_matches_path(ty, &["std", "vec", "Vec"]) {
+ FieldInnerTy::Vec(single_generic_type(ty))
+ } else {
+ FieldInnerTy::Plain(ty)
+ }
}
/// Returns `true` if `FieldInnerTy::with` will result in iteration for this inner type (i.e.
pub(crate) fn will_iterate(&self) -> bool {
match self {
FieldInnerTy::Vec(..) => true,
- FieldInnerTy::Option(..) | FieldInnerTy::None => false,
+ FieldInnerTy::Option(..) | FieldInnerTy::Plain(_) => false,
}
}
- /// Returns `Option` containing inner type if there is one.
- pub(crate) fn inner_type(&self) -> Option<&'ty Type> {
+ /// Returns the inner type.
+ pub(crate) fn inner_type(&self) -> &'ty Type {
match self {
- FieldInnerTy::Option(inner) | FieldInnerTy::Vec(inner) => Some(inner),
- FieldInnerTy::None => None,
+ FieldInnerTy::Option(inner) | FieldInnerTy::Vec(inner) | FieldInnerTy::Plain(inner) => {
+ inner
+ }
}
}
#inner
}
},
- FieldInnerTy::None => quote! { #inner },
+ FieldInnerTy::Plain(..) => quote! { #inner },
}
}
}
/// `generate_*` methods from walking the attributes themselves.
pub(crate) struct FieldInfo<'a> {
pub(crate) binding: &'a BindingInfo<'a>,
- pub(crate) ty: &'a Type,
+ pub(crate) ty: FieldInnerTy<'a>,
pub(crate) span: &'a proc_macro2::Span,
}
//! Validates all used crates and extern libraries and loads their metadata
-use crate::errors::{
- ConflictingAllocErrorHandler, ConflictingGlobalAlloc, CrateNotPanicRuntime,
- GlobalAllocRequired, NoMultipleAllocErrorHandler, NoMultipleGlobalAlloc, NoPanicStrategy,
- NoTransitiveNeedsDep, NotProfilerRuntime, ProfilerBuiltinsNeedsCore,
-};
+use crate::errors;
use crate::locator::{CrateError, CrateLocator, CratePaths};
use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
use proc_macro::bridge::client::ProcMacro;
use std::ops::Fn;
use std::path::Path;
+use std::time::Duration;
use std::{cmp, env};
#[derive(Clone)]
for (_, other) in self.cstore.iter_crate_data() {
// Same stable crate id but different SVH
if other.stable_crate_id() == root.stable_crate_id() && other.hash() != root.hash() {
- return Err(CrateError::SymbolConflictsOthers(root.name()));
+ bug!(
+ "Previously returned E0523 here. \
+ See https://github.com/rust-lang/rust/pull/100599 for additional discussion.\
+ root.name() = {}.",
+ root.name()
+ );
}
}
) -> Result<&'static [ProcMacro], CrateError> {
// Make sure the path contains a / or the linker will search for it.
let path = env::current_dir().unwrap().join(path);
- let lib = unsafe { libloading::Library::new(path) }
- .map_err(|err| CrateError::DlOpen(err.to_string()))?;
+ let lib = load_dylib(&path, 5).map_err(|err| CrateError::DlOpen(err))?;
let sym_name = self.sess.generate_proc_macro_decls_symbol(stable_crate_id);
let sym = unsafe { lib.get::<*const &[ProcMacro]>(sym_name.as_bytes()) }
// Sanity check the loaded crate to ensure it is indeed a panic runtime
// and the panic strategy is indeed what we thought it was.
if !data.is_panic_runtime() {
- self.sess.emit_err(CrateNotPanicRuntime { crate_name: name });
+ self.sess.emit_err(errors::CrateNotPanicRuntime { crate_name: name });
}
if data.required_panic_strategy() != Some(desired_strategy) {
- self.sess.emit_err(NoPanicStrategy { crate_name: name, strategy: desired_strategy });
+ self.sess
+ .emit_err(errors::NoPanicStrategy { crate_name: name, strategy: desired_strategy });
}
self.cstore.injected_panic_runtime = Some(cnum);
let name = Symbol::intern(&self.sess.opts.unstable_opts.profiler_runtime);
if name == sym::profiler_builtins && self.sess.contains_name(&krate.attrs, sym::no_core) {
- self.sess.emit_err(ProfilerBuiltinsNeedsCore);
+ self.sess.emit_err(errors::ProfilerBuiltinsNeedsCore);
}
let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; };
// Sanity check the loaded crate to ensure it is indeed a profiler runtime
if !data.is_profiler_runtime() {
- self.sess.emit_err(NotProfilerRuntime { crate_name: name });
+ self.sess.emit_err(errors::NotProfilerRuntime { crate_name: name });
}
}
fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
self.cstore.has_global_allocator = match &*global_allocator_spans(&self.sess, krate) {
[span1, span2, ..] => {
- self.sess.emit_err(NoMultipleGlobalAlloc { span2: *span2, span1: *span1 });
+ self.sess.emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 });
true
}
spans => !spans.is_empty(),
};
self.cstore.has_alloc_error_handler = match &*alloc_error_handler_spans(&self.sess, krate) {
[span1, span2, ..] => {
- self.sess.emit_err(NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 });
+ self.sess
+ .emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 });
true
}
spans => !spans.is_empty(),
if data.has_global_allocator() {
match global_allocator {
Some(other_crate) => {
- self.sess.emit_err(ConflictingGlobalAlloc {
+ self.sess.emit_err(errors::ConflictingGlobalAlloc {
crate_name: data.name(),
other_crate_name: other_crate,
});
if data.has_alloc_error_handler() {
match alloc_error_handler {
Some(other_crate) => {
- self.sess.emit_err(ConflictingAllocErrorHandler {
+ self.sess.emit_err(errors::ConflictingAllocErrorHandler {
crate_name: data.name(),
other_crate_name: other_crate,
});
if !self.sess.contains_name(&krate.attrs, sym::default_lib_allocator)
&& !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator())
{
- self.sess.emit_err(GlobalAllocRequired);
+ self.sess.emit_err(errors::GlobalAllocRequired);
}
self.cstore.allocator_kind = Some(AllocatorKind::Default);
}
for dep in self.cstore.crate_dependencies_in_reverse_postorder(krate) {
let data = self.cstore.get_crate_data(dep);
if needs_dep(&data) {
- self.sess.emit_err(NoTransitiveNeedsDep {
+ self.sess.emit_err(errors::NoTransitiveNeedsDep {
crate_name: self.cstore.get_crate_data(krate).name(),
needs_crate_name: what,
deps_crate_name: data.name(),
visit::walk_crate(&mut f, krate);
f.spans
}
+
+// On Windows the compiler would sometimes intermittently fail to open the
+// proc-macro DLL with `Error::LoadLibraryExW`. It is suspected that something in the
+// system still holds a lock on the file, so we retry a few times before calling it
+// an error.
+fn load_dylib(path: &Path, max_attempts: usize) -> Result<libloading::Library, String> {
+ assert!(max_attempts > 0);
+
+ let mut last_error = None;
+
+ for attempt in 0..max_attempts {
+ match unsafe { libloading::Library::new(&path) } {
+ Ok(lib) => {
+ if attempt > 0 {
+ debug!(
+ "Loaded proc-macro `{}` after {} attempts.",
+ path.display(),
+ attempt + 1
+ );
+ }
+ return Ok(lib);
+ }
+ Err(err) => {
+ // Only try to recover from this specific error.
+ if !matches!(err, libloading::Error::LoadLibraryExW { .. }) {
+ return Err(err.to_string());
+ }
+
+ last_error = Some(err);
+ std::thread::sleep(Duration::from_millis(100));
+ debug!("Failed to load proc-macro `{}`. Retrying.", path.display());
+ }
+ }
+ }
+
+ debug!("Failed to load proc-macro `{}` even after {} attempts.", path.display(), max_attempts);
+ Err(format!("{} (retried {} times)", last_error.unwrap(), max_attempts))
+}
CrateType::Staticlib => Linkage::Static,
};
- if preferred_linkage == Linkage::NotLinked {
+ match preferred_linkage {
// If the crate is not linked, there are no link-time dependencies.
- return Vec::new();
- }
-
- if preferred_linkage == Linkage::Static {
- // Attempt static linkage first. For dylibs and executables, we may be
- // able to retry below with dynamic linkage.
- if let Some(v) = attempt_static(tcx) {
- return v;
- }
+ Linkage::NotLinked => return Vec::new(),
+ Linkage::Static => {
+ // Attempt static linkage first. For dylibs and executables, we may be
+ // able to retry below with dynamic linkage.
+ if let Some(v) = attempt_static(tcx) {
+ return v;
+ }
- // Staticlibs and static executables must have all static dependencies.
- // If any are not found, generate some nice pretty errors.
- if ty == CrateType::Staticlib
- || (ty == CrateType::Executable
- && sess.crt_static(Some(ty))
- && !sess.target.crt_static_allows_dylibs)
- {
- for &cnum in tcx.crates(()).iter() {
- if tcx.dep_kind(cnum).macros_only() {
- continue;
+ // Staticlibs and static executables must have all static dependencies.
+ // If any are not found, generate some nice pretty errors.
+ if ty == CrateType::Staticlib
+ || (ty == CrateType::Executable
+ && sess.crt_static(Some(ty))
+ && !sess.target.crt_static_allows_dylibs)
+ {
+ for &cnum in tcx.crates(()).iter() {
+ if tcx.dep_kind(cnum).macros_only() {
+ continue;
+ }
+ let src = tcx.used_crate_source(cnum);
+ if src.rlib.is_some() {
+ continue;
+ }
+ sess.emit_err(RlibRequired { crate_name: tcx.crate_name(cnum) });
}
- let src = tcx.used_crate_source(cnum);
- if src.rlib.is_some() {
- continue;
- }
- sess.emit_err(RlibRequired { crate_name: tcx.crate_name(cnum) });
+ return Vec::new();
}
- return Vec::new();
}
+ Linkage::Dynamic | Linkage::IncludedFromDylib => {}
}
let mut formats = FxHashMap::default();
let mut ret = tcx
.crates(())
.iter()
- .map(|&cnum| {
- if tcx.dep_kind(cnum) == CrateDepKind::Explicit {
- Linkage::Static
- } else {
- Linkage::NotLinked
- }
+ .map(|&cnum| match tcx.dep_kind(cnum) {
+ CrateDepKind::Explicit => Linkage::Static,
+ CrateDepKind::MacrosOnly | CrateDepKind::Implicit => Linkage::NotLinked,
})
.collect::<Vec<_>>();
pub crate_name: Symbol,
}
-#[derive(Diagnostic)]
-#[diag(metadata_symbol_conflicts_others, code = "E0523")]
-pub struct SymbolConflictsOthers {
- #[primary_span]
- pub span: Span,
- pub crate_name: Symbol,
-}
-
#[derive(Diagnostic)]
#[diag(metadata_stable_crate_id_collision)]
pub struct StableCrateIdCollision {
//! metadata::locator or metadata::creader for all the juicy details!
use crate::creader::Library;
-use crate::errors::{
- CannotFindCrate, CrateLocationUnknownType, DlError, ExternLocationNotExist,
- ExternLocationNotFile, FoundStaticlib, IncompatibleRustc, InvalidMetadataFiles,
- LibFilenameForm, MultipleCandidates, NewerCrateVersion, NoCrateWithTriple, NoDylibPlugin,
- NonAsciiName, StableCrateIdCollision, SymbolConflictsCurrent, SymbolConflictsOthers,
-};
+use crate::errors;
use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
ExternLocationNotFile(Symbol, PathBuf),
MultipleCandidates(Symbol, CrateFlavor, Vec<PathBuf>),
SymbolConflictsCurrent(Symbol),
- SymbolConflictsOthers(Symbol),
StableCrateIdCollision(Symbol, Symbol),
DlOpen(String),
DlSym(String),
pub(crate) fn report(self, sess: &Session, span: Span, missing_core: bool) {
match self {
CrateError::NonAsciiName(crate_name) => {
- sess.emit_err(NonAsciiName { span, crate_name });
+ sess.emit_err(errors::NonAsciiName { span, crate_name });
}
CrateError::ExternLocationNotExist(crate_name, loc) => {
- sess.emit_err(ExternLocationNotExist { span, crate_name, location: &loc });
+ sess.emit_err(errors::ExternLocationNotExist { span, crate_name, location: &loc });
}
CrateError::ExternLocationNotFile(crate_name, loc) => {
- sess.emit_err(ExternLocationNotFile { span, crate_name, location: &loc });
+ sess.emit_err(errors::ExternLocationNotFile { span, crate_name, location: &loc });
}
CrateError::MultipleCandidates(crate_name, flavor, candidates) => {
- sess.emit_err(MultipleCandidates { span, crate_name, flavor, candidates });
+ sess.emit_err(errors::MultipleCandidates { span, crate_name, flavor, candidates });
}
CrateError::SymbolConflictsCurrent(root_name) => {
- sess.emit_err(SymbolConflictsCurrent { span, crate_name: root_name });
- }
- CrateError::SymbolConflictsOthers(root_name) => {
- sess.emit_err(SymbolConflictsOthers { span, crate_name: root_name });
+ sess.emit_err(errors::SymbolConflictsCurrent { span, crate_name: root_name });
}
CrateError::StableCrateIdCollision(crate_name0, crate_name1) => {
- sess.emit_err(StableCrateIdCollision { span, crate_name0, crate_name1 });
+ sess.emit_err(errors::StableCrateIdCollision { span, crate_name0, crate_name1 });
}
CrateError::DlOpen(s) | CrateError::DlSym(s) => {
- sess.emit_err(DlError { span, err: s });
+ sess.emit_err(errors::DlError { span, err: s });
}
CrateError::LocatorCombined(locator) => {
let crate_name = locator.crate_name;
if !locator.crate_rejections.via_filename.is_empty() {
let mismatches = locator.crate_rejections.via_filename.iter();
for CrateMismatch { path, .. } in mismatches {
- sess.emit_err(CrateLocationUnknownType { span, path: &path, crate_name });
- sess.emit_err(LibFilenameForm {
+ sess.emit_err(errors::CrateLocationUnknownType {
+ span,
+ path: &path,
+ crate_name,
+ });
+ sess.emit_err(errors::LibFilenameForm {
span,
dll_prefix: &locator.dll_prefix,
dll_suffix: &locator.dll_suffix,
));
}
}
- sess.emit_err(NewerCrateVersion {
+ sess.emit_err(errors::NewerCrateVersion {
span,
crate_name: crate_name,
add_info,
path.display(),
));
}
- sess.emit_err(NoCrateWithTriple {
+ sess.emit_err(errors::NoCrateWithTriple {
span,
crate_name,
locator_triple: locator.triple.triple(),
path.display()
));
}
- sess.emit_err(FoundStaticlib { span, crate_name, add_info, found_crates });
+ sess.emit_err(errors::FoundStaticlib {
+ span,
+ crate_name,
+ add_info,
+ found_crates,
+ });
} else if !locator.crate_rejections.via_version.is_empty() {
let mismatches = locator.crate_rejections.via_version.iter();
for CrateMismatch { path, got } in mismatches {
path.display(),
));
}
- sess.emit_err(IncompatibleRustc {
+ sess.emit_err(errors::IncompatibleRustc {
span,
crate_name,
add_info,
for CrateMismatch { path: _, got } in locator.crate_rejections.via_invalid {
crate_rejections.push(got);
}
- sess.emit_err(InvalidMetadataFiles {
+ sess.emit_err(errors::InvalidMetadataFiles {
span,
crate_name,
add_info,
crate_rejections,
});
} else {
- sess.emit_err(CannotFindCrate {
+ sess.emit_err(errors::CannotFindCrate {
span,
crate_name,
add_info,
}
}
CrateError::NonDylibPlugin(crate_name) => {
- sess.emit_err(NoDylibPlugin { span, crate_name });
+ sess.emit_err(errors::NoDylibPlugin { span, crate_name });
}
}
}
use rustc_span::symbol::{sym, Symbol};
use rustc_target::spec::abi::Abi;
-use crate::errors::{
- AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, EmptyRenamingTarget,
- FrameworkOnlyWindows, ImportNameTypeForm, ImportNameTypeRaw, ImportNameTypeX86,
- IncompatibleWasmLink, InvalidLinkModifier, LibFrameworkApple, LinkCfgForm,
- LinkCfgSinglePredicate, LinkFrameworkApple, LinkKindForm, LinkModifiersForm, LinkNameForm,
- LinkOrdinalRawDylib, LinkRequiresName, MissingNativeLibrary, MultipleCfgs,
- MultipleImportNameType, MultipleKindsInLink, MultipleLinkModifiers, MultipleModifiers,
- MultipleNamesInLink, MultipleRenamings, MultipleWasmImport, NoLinkModOverride, RawDylibNoNul,
- RenamingNoLink, UnexpectedLinkArg, UnknownImportNameType, UnknownLinkKind, UnknownLinkModifier,
- UnsupportedAbi, UnsupportedAbiI686, WasmImportForm, WholeArchiveNeedsStatic,
-};
+use crate::errors;
use std::path::PathBuf;
}
}
- sess.emit_fatal(MissingNativeLibrary::new(name, verbatim));
+ sess.emit_fatal(errors::MissingNativeLibrary::new(name, verbatim));
}
fn find_bundled_library(
return;
};
- if abi == Abi::Rust || abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
+ if matches!(abi, Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic) {
return;
}
match item.name_or_empty() {
sym::name => {
if name.is_some() {
- sess.emit_err(MultipleNamesInLink { span: item.span() });
+ sess.emit_err(errors::MultipleNamesInLink { span: item.span() });
continue;
}
let Some(link_name) = item.value_str() else {
- sess.emit_err(LinkNameForm { span: item.span() });
+ sess.emit_err(errors::LinkNameForm { span: item.span() });
continue;
};
let span = item.name_value_literal_span().unwrap();
if link_name.is_empty() {
- sess.emit_err(EmptyLinkName { span });
+ sess.emit_err(errors::EmptyLinkName { span });
}
name = Some((link_name, span));
}
sym::kind => {
if kind.is_some() {
- sess.emit_err(MultipleKindsInLink { span: item.span() });
+ sess.emit_err(errors::MultipleKindsInLink { span: item.span() });
continue;
}
let Some(link_kind) = item.value_str() else {
- sess.emit_err(LinkKindForm { span: item.span() });
+ sess.emit_err(errors::LinkKindForm { span: item.span() });
continue;
};
"dylib" => NativeLibKind::Dylib { as_needed: None },
"framework" => {
if !sess.target.is_like_osx {
- sess.emit_err(LinkFrameworkApple { span });
+ sess.emit_err(errors::LinkFrameworkApple { span });
}
NativeLibKind::Framework { as_needed: None }
}
"raw-dylib" => {
if !sess.target.is_like_windows {
- sess.emit_err(FrameworkOnlyWindows { span });
+ sess.emit_err(errors::FrameworkOnlyWindows { span });
} else if !features.raw_dylib && sess.target.arch == "x86" {
feature_err(
&sess.parse_sess,
NativeLibKind::RawDylib
}
kind => {
- sess.emit_err(UnknownLinkKind { span, kind });
+ sess.emit_err(errors::UnknownLinkKind { span, kind });
continue;
}
};
}
sym::modifiers => {
if modifiers.is_some() {
- sess.emit_err(MultipleLinkModifiers { span: item.span() });
+ sess.emit_err(errors::MultipleLinkModifiers { span: item.span() });
continue;
}
let Some(link_modifiers) = item.value_str() else {
- sess.emit_err(LinkModifiersForm { span: item.span() });
+ sess.emit_err(errors::LinkModifiersForm { span: item.span() });
continue;
};
modifiers = Some((link_modifiers, item.name_value_literal_span().unwrap()));
}
sym::cfg => {
if cfg.is_some() {
- sess.emit_err(MultipleCfgs { span: item.span() });
+ sess.emit_err(errors::MultipleCfgs { span: item.span() });
continue;
}
let Some(link_cfg) = item.meta_item_list() else {
- sess.emit_err(LinkCfgForm { span: item.span() });
+ sess.emit_err(errors::LinkCfgForm { span: item.span() });
continue;
};
let [NestedMetaItem::MetaItem(link_cfg)] = link_cfg else {
- sess.emit_err(LinkCfgSinglePredicate { span: item.span() });
+ sess.emit_err(errors::LinkCfgSinglePredicate { span: item.span() });
continue;
};
if !features.link_cfg {
}
sym::wasm_import_module => {
if wasm_import_module.is_some() {
- sess.emit_err(MultipleWasmImport { span: item.span() });
+ sess.emit_err(errors::MultipleWasmImport { span: item.span() });
continue;
}
let Some(link_wasm_import_module) = item.value_str() else {
- sess.emit_err(WasmImportForm { span: item.span() });
+ sess.emit_err(errors::WasmImportForm { span: item.span() });
continue;
};
wasm_import_module = Some((link_wasm_import_module, item.span()));
}
sym::import_name_type => {
if import_name_type.is_some() {
- sess.emit_err(MultipleImportNameType { span: item.span() });
+ sess.emit_err(errors::MultipleImportNameType { span: item.span() });
continue;
}
let Some(link_import_name_type) = item.value_str() else {
- sess.emit_err(ImportNameTypeForm { span: item.span() });
+ sess.emit_err(errors::ImportNameTypeForm { span: item.span() });
continue;
};
if self.tcx.sess.target.arch != "x86" {
- sess.emit_err(ImportNameTypeX86 { span: item.span() });
+ sess.emit_err(errors::ImportNameTypeX86 { span: item.span() });
continue;
}
"noprefix" => PeImportNameType::NoPrefix,
"undecorated" => PeImportNameType::Undecorated,
import_name_type => {
- sess.emit_err(UnknownImportNameType {
+ sess.emit_err(errors::UnknownImportNameType {
span: item.span(),
import_name_type,
});
import_name_type = Some((link_import_name_type, item.span()));
}
_ => {
- sess.emit_err(UnexpectedLinkArg { span: item.span() });
+ sess.emit_err(errors::UnexpectedLinkArg { span: item.span() });
}
}
}
let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
Some(m) => (m, modifier.starts_with('+')),
None => {
- sess.emit_err(InvalidLinkModifier { span });
+ sess.emit_err(errors::InvalidLinkModifier { span });
continue;
}
};
}
let assign_modifier = |dst: &mut Option<bool>| {
if dst.is_some() {
- sess.emit_err(MultipleModifiers { span, modifier });
+ sess.emit_err(errors::MultipleModifiers { span, modifier });
} else {
*dst = Some(value);
}
assign_modifier(bundle)
}
("bundle", _) => {
- sess.emit_err(BundleNeedsStatic { span });
+ sess.emit_err(errors::BundleNeedsStatic { span });
}
("verbatim", _) => assign_modifier(&mut verbatim),
assign_modifier(whole_archive)
}
("whole-archive", _) => {
- sess.emit_err(WholeArchiveNeedsStatic { span });
+ sess.emit_err(errors::WholeArchiveNeedsStatic { span });
}
("as-needed", Some(NativeLibKind::Dylib { as_needed }))
assign_modifier(as_needed)
}
("as-needed", _) => {
- sess.emit_err(AsNeededCompatibility { span });
+ sess.emit_err(errors::AsNeededCompatibility { span });
}
_ => {
- sess.emit_err(UnknownLinkModifier { span, modifier });
+ sess.emit_err(errors::UnknownLinkModifier { span, modifier });
}
}
}
if let Some((_, span)) = wasm_import_module {
if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() {
- sess.emit_err(IncompatibleWasmLink { span });
+ sess.emit_err(errors::IncompatibleWasmLink { span });
}
} else if name.is_none() {
- sess.emit_err(LinkRequiresName { span: m.span });
+ sess.emit_err(errors::LinkRequiresName { span: m.span });
}
// Do this outside of the loop so that `import_name_type` can be specified before `kind`.
if let Some((_, span)) = import_name_type {
if kind != Some(NativeLibKind::RawDylib) {
- sess.emit_err(ImportNameTypeRaw { span });
+ sess.emit_err(errors::ImportNameTypeRaw { span });
}
}
let dll_imports = match kind {
Some(NativeLibKind::RawDylib) => {
if let Some((name, span)) = name && name.as_str().contains('\0') {
- sess.emit_err(RawDylibNoNul { span });
+ sess.emit_err(errors::RawDylibNoNul { span });
}
foreign_mod_items
.iter()
.iter()
.find(|a| a.has_name(sym::link_ordinal))
.unwrap();
- sess.emit_err(LinkOrdinalRawDylib { span: link_ordinal_attr.span });
+ sess.emit_err(errors::LinkOrdinalRawDylib {
+ span: link_ordinal_attr.span,
+ });
}
}
for lib in &self.tcx.sess.opts.libs {
if let NativeLibKind::Framework { .. } = lib.kind && !self.tcx.sess.target.is_like_osx {
// Cannot check this when parsing options because the target is not yet available.
- self.tcx.sess.emit_err(LibFrameworkApple);
+ self.tcx.sess.emit_err(errors::LibFrameworkApple);
}
if let Some(ref new_name) = lib.new_name {
let any_duplicate = self
.filter_map(|lib| lib.name.as_ref())
.any(|n| n.as_str() == lib.name);
if new_name.is_empty() {
- self.tcx.sess.emit_err(EmptyRenamingTarget { lib_name: &lib.name });
+ self.tcx.sess.emit_err(errors::EmptyRenamingTarget { lib_name: &lib.name });
} else if !any_duplicate {
- self.tcx.sess.emit_err(RenamingNoLink { lib_name: &lib.name });
+ self.tcx.sess.emit_err(errors::RenamingNoLink { lib_name: &lib.name });
} else if !renames.insert(&lib.name) {
- self.tcx.sess.emit_err(MultipleRenamings { lib_name: &lib.name });
+ self.tcx.sess.emit_err(errors::MultipleRenamings { lib_name: &lib.name });
}
}
}
// explicit `:rename` in particular.
if lib.has_modifiers() || passed_lib.has_modifiers() {
match lib.foreign_module {
- Some(def_id) => self.tcx.sess.emit_err(NoLinkModOverride {
- span: Some(self.tcx.def_span(def_id)),
- }),
- None => {
- self.tcx.sess.emit_err(NoLinkModOverride { span: None })
+ Some(def_id) => {
+ self.tcx.sess.emit_err(errors::NoLinkModOverride {
+ span: Some(self.tcx.def_span(def_id)),
+ })
}
+ None => self
+ .tcx
+ .sess
+ .emit_err(errors::NoLinkModOverride { span: None }),
};
}
if passed_lib.kind != NativeLibKind::Unspecified {
DllCallingConvention::Vectorcall(self.i686_arg_list_size(item))
}
_ => {
- self.tcx.sess.emit_fatal(UnsupportedAbiI686 { span: item.span });
+ self.tcx.sess.emit_fatal(errors::UnsupportedAbiI686 { span: item.span });
}
}
} else {
match abi {
Abi::C { .. } | Abi::Win64 { .. } | Abi::System { .. } => DllCallingConvention::C,
_ => {
- self.tcx.sess.emit_fatal(UnsupportedAbi { span: item.span });
+ self.tcx.sess.emit_fatal(errors::UnsupportedAbi { span: item.span });
}
}
};
impl<'a, 'tcx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyArray<T> {
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self {
let len = decoder.read_usize();
- if len == 0 { LazyArray::empty() } else { decoder.read_lazy_array(len) }
+ if len == 0 { LazyArray::default() } else { decoder.read_lazy_array(len) }
}
}
.tables
.children
.get(self, index)
- .unwrap_or_else(LazyArray::empty)
+ .expect("fields are not encoded for a variant")
.decode(self)
.map(|index| ty::FieldDef {
did: self.local_def_id(index),
.tables
.children
.get(self, item_id)
- .unwrap_or_else(LazyArray::empty)
+ .expect("variants are not encoded for an enum")
.decode(self)
.filter_map(|index| {
let kind = self.def_kind(index);
.tables
.fn_arg_names
.get(self, id)
- .unwrap_or_else(LazyArray::empty)
+ .expect("argument names not encoded for a function")
.decode((self, sess))
.nth(0)
.map_or(false, |ident| ident.name == kw::SelfLower)
.tables
.children
.get(self, id)
- .unwrap_or_else(LazyArray::empty)
+ .expect("associated items not encoded for an item")
.decode((self, sess))
.map(move |child_index| self.local_def_id(child_index))
}
fn get_associated_item(self, id: DefIndex, sess: &'a Session) -> ty::AssocItem {
let name = self.item_name(id);
- let kind = match self.def_kind(id) {
- DefKind::AssocConst => ty::AssocKind::Const,
- DefKind::AssocFn => ty::AssocKind::Fn,
- DefKind::AssocTy => ty::AssocKind::Type,
+ let (kind, has_self) = match self.def_kind(id) {
+ DefKind::AssocConst => (ty::AssocKind::Const, false),
+ DefKind::AssocFn => (ty::AssocKind::Fn, self.get_fn_has_self_parameter(id, sess)),
+ DefKind::AssocTy => (ty::AssocKind::Type, false),
_ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)),
};
- let has_self = self.get_fn_has_self_parameter(id, sess);
let container = self.root.tables.assoc_container.get(self, id).unwrap();
ty::AssocItem {
.tables
.children
.get(self, id)
- .unwrap_or_else(LazyArray::empty)
+ .expect("fields not encoded for a struct")
.decode(self)
.map(move |index| respan(self.get_span(index, sess), self.item_name(index)))
}
.tables
.children
.get(self, id)
- .unwrap_or_else(LazyArray::empty)
+ .expect("fields not encoded for a struct")
.decode(self)
.map(move |field_index| self.get_visibility(field_index))
}
.tables
.inherent_impls
.get(self, id)
- .unwrap_or_else(LazyArray::empty)
.decode(self)
.map(|index| self.local_def_id(index)),
)
.tables
.inherent_impls
.get(self, ty_index)
- .unwrap_or_else(LazyArray::empty)
.decode(self)
.map(move |impl_index| (ty_def_id, self.local_def_id(impl_index)))
})
) -> DefPathHash {
*def_path_hashes
.entry(index)
- .or_insert_with(|| self.root.tables.def_path_hashes.get(self, index).unwrap())
+ .or_insert_with(|| self.root.tables.def_path_hashes.get(self, index))
}
#[inline]
use crate::creader::{CStore, LoadedMacro};
use crate::foreign_modules;
use crate::native_libs;
+use crate::rmeta::table::IsDefault;
use crate::rmeta::AttrFlags;
use rustc_ast as ast;
}
}
};
+ ($tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => { table_defaulted_array }) => {
+ provide_one! {
+ $tcx, $def_id, $other, $cdata, $name => {
+ let lazy = $cdata.root.tables.$name.get($cdata, $def_id.index);
+ if lazy.is_default() { &[] } else { $tcx.arena.alloc_from_iter(lazy.decode(($cdata, $tcx))) }
+ }
+ }
+ };
($tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => { table_direct }) => {
provide_one! {
$tcx, $def_id, $other, $cdata, $name => {
}
provide! { tcx, def_id, other, cdata,
- explicit_item_bounds => { table }
+ explicit_item_bounds => { table_defaulted_array }
explicit_predicates_of => { table }
generics_of => { table }
- inferred_outlives_of => { table }
+ inferred_outlives_of => { table_defaulted_array }
super_predicates_of => { table }
type_of => { table }
variances_of => { table }
symbol_table: FxHashMap<Symbol, usize>,
}
-/// If the current crate is a proc-macro, returns early with `LazyArray::empty()`.
+/// If the current crate is a proc-macro, returns early with `LazyArray::default()`.
/// This is useful for skipping the encoding of things that aren't needed
/// for proc-macro crates.
macro_rules! empty_proc_macro {
($self:ident) => {
if $self.is_proc_macro {
- return LazyArray::empty();
+ return LazyArray::default();
}
};
}
}
}
-// Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy_value($value))`, which would
+// Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_value($value))`, which would
// normally need extra variables to avoid errors about multiple mutable borrows.
macro_rules! record {
($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{
{
let value = $value;
let lazy = $self.lazy(value);
- $self.$tables.$table.set($def_id.index, lazy);
+ $self.$tables.$table.set_some($def_id.index, lazy);
}
}};
}
-// Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy_value($value))`, which would
+// Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_value($value))`, which would
// normally need extra variables to avoid errors about multiple mutable borrows.
macro_rules! record_array {
+ ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{
+ {
+ let value = $value;
+ let lazy = $self.lazy_array(value);
+ $self.$tables.$table.set_some($def_id.index, lazy);
+ }
+ }};
+}
+
+macro_rules! record_defaulted_array {
($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{
{
let value = $value;
{
let def_key = self.lazy(table.def_key(def_index));
let def_path_hash = table.def_path_hash(def_index);
- self.tables.def_keys.set(def_index, def_key);
+ self.tables.def_keys.set_some(def_index, def_key);
self.tables.def_path_hashes.set(def_index, def_path_hash);
}
} else {
for (def_index, def_key, def_path_hash) in table.enumerated_keys_and_path_hashes() {
let def_key = self.lazy(def_key);
- self.tables.def_keys.set(def_index, def_key);
+ self.tables.def_keys.set_some(def_index, def_key);
self.tables.def_path_hashes.set(def_index, *def_path_hash);
}
}
let on_disk_index: u32 =
on_disk_index.try_into().expect("cannot export more than U32_MAX files");
- adapted.set(on_disk_index, self.lazy(source_file));
+ adapted.set_some(on_disk_index, self.lazy(source_file));
}
adapted.encode(&mut self.opaque)
if state.is_doc_hidden {
attr_flags |= AttrFlags::IS_DOC_HIDDEN;
}
- if !attr_flags.is_empty() {
- self.tables.attr_flags.set_nullable(def_id.local_def_index, attr_flags);
- }
+ self.tables.attr_flags.set(def_id.local_def_index, attr_flags);
}
fn encode_def_ids(&mut self) {
let def_id = local_id.to_def_id();
let def_kind = tcx.opt_def_kind(local_id);
let Some(def_kind) = def_kind else { continue };
- self.tables.opt_def_kind.set(def_id.index, def_kind);
+ self.tables.opt_def_kind.set_some(def_id.index, def_kind);
let def_span = tcx.def_span(local_id);
record!(self.tables.def_span[def_id] <- def_span);
self.encode_attrs(local_id);
record!(self.tables.generics_of[def_id] <- g);
record!(self.tables.explicit_predicates_of[def_id] <- self.tcx.explicit_predicates_of(def_id));
let inferred_outlives = self.tcx.inferred_outlives_of(def_id);
- if !inferred_outlives.is_empty() {
- record_array!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives);
- }
+ record_defaulted_array!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives);
}
if should_encode_type(tcx, local_id, def_kind) {
record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id));
record!(self.tables.trait_impl_trait_tys[def_id] <- table);
}
}
+
let inherent_impls = tcx.with_stable_hashing_context(|hcx| {
tcx.crate_inherent_impls(()).inherent_impls.to_sorted(&hcx, true)
});
-
- for (def_id, implementations) in inherent_impls {
- if implementations.is_empty() {
- continue;
- }
- record_array!(self.tables.inherent_impls[def_id.to_def_id()] <- implementations.iter().map(|&def_id| {
+ for (def_id, impls) in inherent_impls {
+ record_defaulted_array!(self.tables.inherent_impls[def_id.to_def_id()] <- impls.iter().map(|def_id| {
assert!(def_id.is_local());
def_id.index
}));
};
record!(self.tables.variant_data[variant.def_id] <- data);
- self.tables.constness.set(variant.def_id.index, hir::Constness::Const);
+ self.tables.constness.set_some(variant.def_id.index, hir::Constness::Const);
record_array!(self.tables.children[variant.def_id] <- variant.fields.iter().map(|f| {
assert!(f.did.is_local());
f.did.index
}));
if let Some((CtorKind::Fn, ctor_def_id)) = variant.ctor {
- self.tables.constness.set(ctor_def_id.index, hir::Constness::Const);
+ self.tables.constness.set_some(ctor_def_id.index, hir::Constness::Const);
let fn_sig = tcx.fn_sig(ctor_def_id);
record!(self.tables.fn_sig[ctor_def_id] <- fn_sig);
// FIXME only encode signature for ctor_def_id
fn encode_explicit_item_bounds(&mut self, def_id: DefId) {
debug!("EncodeContext::encode_explicit_item_bounds({:?})", def_id);
let bounds = self.tcx.explicit_item_bounds(def_id);
- if !bounds.is_empty() {
- record_array!(self.tables.explicit_item_bounds[def_id] <- bounds);
- }
+ record_defaulted_array!(self.tables.explicit_item_bounds[def_id] <- bounds);
}
fn encode_info_for_trait_item(&mut self, def_id: DefId) {
let tcx = self.tcx;
let impl_defaultness = tcx.impl_defaultness(def_id.expect_local());
- self.tables.impl_defaultness.set(def_id.index, impl_defaultness);
+ self.tables.impl_defaultness.set_some(def_id.index, impl_defaultness);
let trait_item = tcx.associated_item(def_id);
- self.tables.assoc_container.set(def_id.index, trait_item.container);
+ self.tables.assoc_container.set_some(def_id.index, trait_item.container);
match trait_item.kind {
ty::AssocKind::Const => {}
ty::AssocKind::Fn => {
record_array!(self.tables.fn_arg_names[def_id] <- tcx.fn_arg_names(def_id));
- self.tables.asyncness.set(def_id.index, tcx.asyncness(def_id));
- self.tables.constness.set(def_id.index, hir::Constness::NotConst);
+ self.tables.asyncness.set_some(def_id.index, tcx.asyncness(def_id));
+ self.tables.constness.set_some(def_id.index, hir::Constness::NotConst);
}
ty::AssocKind::Type => {
self.encode_explicit_item_bounds(def_id);
let tcx = self.tcx;
let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local());
- self.tables.impl_defaultness.set(def_id.index, ast_item.defaultness);
+ self.tables.impl_defaultness.set_some(def_id.index, ast_item.defaultness);
let impl_item = self.tcx.associated_item(def_id);
- self.tables.assoc_container.set(def_id.index, impl_item.container);
+ self.tables.assoc_container.set_some(def_id.index, impl_item.container);
match impl_item.kind {
ty::AssocKind::Fn => {
let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind else { bug!() };
- self.tables.asyncness.set(def_id.index, sig.header.asyncness);
+ self.tables.asyncness.set_some(def_id.index, sig.header.asyncness);
record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body));
// Can be inside `impl const Trait`, so using sig.header.constness is not reliable
let constness = if self.tcx.is_const_fn_raw(def_id) {
} else {
hir::Constness::NotConst
};
- self.tables.constness.set(def_id.index, constness);
+ self.tables.constness.set_some(def_id.index, constness);
}
ty::AssocKind::Const | ty::AssocKind::Type => {}
}
if let Some(trait_item_def_id) = impl_item.trait_item_def_id {
- self.tables.trait_item_def_id.set(def_id.index, trait_item_def_id.into());
+ self.tables.trait_item_def_id.set_some(def_id.index, trait_item_def_id.into());
}
if impl_item.kind == ty::AssocKind::Fn {
record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
- if tcx.is_intrinsic(def_id) {
- self.tables.is_intrinsic.set_nullable(def_id.index, true);
- }
+ self.tables.is_intrinsic.set(def_id.index, tcx.is_intrinsic(def_id));
}
}
if encode_opt {
record!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id));
- if let DefKind::Generator = self.tcx.def_kind(def_id) && tcx.sess.opts.unstable_opts.drop_tracking_mir {
+ if tcx.sess.opts.unstable_opts.drop_tracking_mir && let DefKind::Generator = self.tcx.def_kind(def_id) {
record!(self.tables.mir_generator_witnesses[def_id.to_def_id()] <- tcx.mir_generator_witnesses(def_id));
}
}
match item.kind {
hir::ItemKind::Fn(ref sig, .., body) => {
- self.tables.asyncness.set(def_id.index, sig.header.asyncness);
+ self.tables.asyncness.set_some(def_id.index, sig.header.asyncness);
record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body));
- self.tables.constness.set(def_id.index, sig.header.constness);
+ self.tables.constness.set_some(def_id.index, sig.header.constness);
}
hir::ItemKind::Macro(ref macro_def, _) => {
- if macro_def.macro_rules {
- self.tables.is_macro_rules.set_nullable(def_id.index, true);
- }
+ self.tables.is_macro_rules.set(def_id.index, macro_def.macro_rules);
record!(self.tables.macro_definition[def_id] <- &*macro_def.body);
}
hir::ItemKind::Mod(ref m) => {
}
hir::ItemKind::OpaqueTy(ref opaque) => {
self.encode_explicit_item_bounds(def_id);
- if matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias) {
- self.tables.is_type_alias_impl_trait.set_nullable(def_id.index, true);
- }
+ self.tables
+ .is_type_alias_impl_trait
+ .set(def_id.index, matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias));
}
hir::ItemKind::Impl(hir::Impl { defaultness, constness, .. }) => {
- self.tables.impl_defaultness.set(def_id.index, *defaultness);
- self.tables.constness.set(def_id.index, *constness);
+ self.tables.impl_defaultness.set_some(def_id.index, *defaultness);
+ self.tables.constness.set_some(def_id.index, *constness);
let trait_ref = self.tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::skip_binder);
if let Some(trait_ref) = trait_ref {
let trait_def = self.tcx.trait_def(trait_ref.def_id);
if let Ok(mut an) = trait_def.ancestors(self.tcx, def_id) {
if let Some(specialization_graph::Node::Impl(parent)) = an.nth(1) {
- self.tables.impl_parent.set(def_id.index, parent.into());
+ self.tables.impl_parent.set_some(def_id.index, parent.into());
}
}
}
let polarity = self.tcx.impl_polarity(def_id);
- self.tables.impl_polarity.set(def_id.index, polarity);
+ self.tables.impl_polarity.set_some(def_id.index, polarity);
}
hir::ItemKind::Trait(..) => {
let trait_def = self.tcx.trait_def(def_id);
}
if let hir::ItemKind::Fn(..) = item.kind {
record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
- if tcx.is_intrinsic(def_id) {
- self.tables.is_intrinsic.set_nullable(def_id.index, true);
- }
+ self.tables.is_intrinsic.set(def_id.index, tcx.is_intrinsic(def_id));
}
if let hir::ItemKind::Impl { .. } = item.kind {
if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) {
ty::Closure(_, substs) => {
let constness = self.tcx.constness(def_id.to_def_id());
- self.tables.constness.set(def_id.to_def_id().index, constness);
+ self.tables.constness.set_some(def_id.to_def_id().index, constness);
record!(self.tables.fn_sig[def_id.to_def_id()] <- ty::EarlyBinder(substs.as_closure().sig()));
}
self.hygiene_ctxt.encode(
&mut (&mut *self, &mut syntax_contexts, &mut expn_data_table, &mut expn_hash_table),
|(this, syntax_contexts, _, _), index, ctxt_data| {
- syntax_contexts.set(index, this.lazy(ctxt_data));
+ syntax_contexts.set_some(index, this.lazy(ctxt_data));
},
|(this, _, expn_data_table, expn_hash_table), index, expn_data, hash| {
if let Some(index) = index.as_local() {
- expn_data_table.set(index.as_raw(), this.lazy(expn_data));
- expn_hash_table.set(index.as_raw(), this.lazy(hash));
+ expn_data_table.set_some(index.as_raw(), this.lazy(expn_data));
+ expn_hash_table.set_some(index.as_raw(), this.lazy(hash));
}
},
);
let spans = self.tcx.sess.parse_sess.proc_macro_quoted_spans();
for (i, span) in spans.into_iter().enumerate() {
let span = self.lazy(span);
- self.tables.proc_macro_quoted_spans.set(i, span);
+ self.tables.proc_macro_quoted_spans.set_some(i, span);
}
- self.tables.opt_def_kind.set(LOCAL_CRATE.as_def_id().index, DefKind::Mod);
+ self.tables.opt_def_kind.set_some(LOCAL_CRATE.as_def_id().index, DefKind::Mod);
record!(self.tables.def_span[LOCAL_CRATE.as_def_id()] <- tcx.def_span(LOCAL_CRATE.as_def_id()));
self.encode_attrs(LOCAL_CRATE.as_def_id().expect_local());
let vis = tcx.local_visibility(CRATE_DEF_ID).map_id(|def_id| def_id.local_def_index);
def_key.disambiguated_data.data = DefPathData::MacroNs(name);
let def_id = id.to_def_id();
- self.tables.opt_def_kind.set(def_id.index, DefKind::Macro(macro_kind));
- self.tables.proc_macro.set(def_id.index, macro_kind);
+ self.tables.opt_def_kind.set_some(def_id.index, DefKind::Macro(macro_kind));
+ self.tables.proc_macro.set_some(def_id.index, macro_kind);
self.encode_attrs(id);
record!(self.tables.def_keys[def_id] <- def_key);
record!(self.tables.def_ident_span[def_id] <- span);
Linkage::Static => Some(LinkagePreference::RequireStatic),
}));
}
- LazyArray::empty()
+ LazyArray::default()
}
fn encode_info_for_foreign_item(&mut self, def_id: DefId, nitem: &hir::ForeignItem<'_>) {
match nitem.kind {
hir::ForeignItemKind::Fn(_, ref names, _) => {
- self.tables.asyncness.set(def_id.index, hir::IsAsync::NotAsync);
+ self.tables.asyncness.set_some(def_id.index, hir::IsAsync::NotAsync);
record_array!(self.tables.fn_arg_names[def_id] <- *names);
let constness = if self.tcx.is_const_fn_raw(def_id) {
hir::Constness::Const
} else {
hir::Constness::NotConst
};
- self.tables.constness.set(def_id.index, constness);
+ self.tables.constness.set_some(def_id.index, constness);
record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
}
hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => {}
}
if let hir::ForeignItemKind::Fn(..) = nitem.kind {
- if tcx.is_intrinsic(def_id) {
- self.tables.is_intrinsic.set_nullable(def_id.index, true);
- }
+ self.tables.is_intrinsic.set(def_id.index, tcx.is_intrinsic(def_id));
}
}
}
type Value<'tcx> = LazyArray<T::Value<'tcx>>;
}
+impl<T> Default for LazyArray<T> {
+ fn default() -> LazyArray<T> {
+ LazyArray::from_position_and_num_elems(NonZeroUsize::new(1).unwrap(), 0)
+ }
+}
+
impl<T> LazyArray<T> {
fn from_position_and_num_elems(position: NonZeroUsize, num_elems: usize) -> LazyArray<T> {
LazyArray { position, num_elems, _marker: PhantomData }
}
-
- fn empty() -> LazyArray<T> {
- LazyArray::from_position_and_num_elems(NonZeroUsize::new(1).unwrap(), 0)
- }
}
/// A list of lazily-decoded values, with the added capability of random access.
/// Define `LazyTables` and `TableBuilders` at the same time.
macro_rules! define_tables {
(
- - nullable: $($name1:ident: Table<$IDX1:ty, $T1:ty>,)+
+ - defaulted: $($name1:ident: Table<$IDX1:ty, $T1:ty>,)+
- optional: $($name2:ident: Table<$IDX2:ty, $T2:ty>,)+
) => {
#[derive(MetadataEncodable, MetadataDecodable)]
}
define_tables! {
-- nullable:
+- defaulted:
is_intrinsic: Table<DefIndex, bool>,
is_macro_rules: Table<DefIndex, bool>,
is_type_alias_impl_trait: Table<DefIndex, bool>,
attr_flags: Table<DefIndex, AttrFlags>,
+ def_path_hashes: Table<DefIndex, DefPathHash>,
+ explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Predicate<'static>, Span)>>,
+ inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
+ inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
- optional:
attributes: Table<DefIndex, LazyArray<ast::Attribute>>,
lookup_const_stability: Table<DefIndex, LazyValue<attr::ConstStability>>,
lookup_default_body_stability: Table<DefIndex, LazyValue<attr::DefaultBodyStability>>,
lookup_deprecation_entry: Table<DefIndex, LazyValue<attr::Deprecation>>,
- // As an optimization, a missing entry indicates an empty `&[]`.
- explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Predicate<'static>, Span)>>,
explicit_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
generics_of: Table<DefIndex, LazyValue<ty::Generics>>,
- // As an optimization, a missing entry indicates an empty `&[]`.
- inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
super_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
type_of: Table<DefIndex, LazyValue<Ty<'static>>>,
variances_of: Table<DefIndex, LazyArray<ty::Variance>>,
generator_kind: Table<DefIndex, LazyValue<hir::GeneratorKind>>,
trait_def: Table<DefIndex, LazyValue<ty::TraitDef>>,
trait_item_def_id: Table<DefIndex, RawDefId>,
- inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
expn_that_defined: Table<DefIndex, LazyValue<ExpnId>>,
unused_generic_params: Table<DefIndex, LazyValue<UnusedGenericParams>>,
params_in_repr: Table<DefIndex, LazyValue<BitSet<u32>>>,
// `DefPathTable` up front, since we may only ever use a few
// definitions from any given crate.
def_keys: Table<DefIndex, LazyValue<DefKey>>,
- def_path_hashes: Table<DefIndex, DefPathHash>,
proc_macro_quoted_spans: Table<usize, LazyValue<Span>>,
generator_diagnostic_data: Table<DefIndex, LazyValue<GeneratorDiagnosticData<'static>>>,
variant_data: Table<DefIndex, LazyValue<VariantData>>,
use std::marker::PhantomData;
use std::num::NonZeroUsize;
+pub(super) trait IsDefault: Default {
+ fn is_default(&self) -> bool;
+}
+
+impl<T> IsDefault for Option<T> {
+ fn is_default(&self) -> bool {
+ self.is_none()
+ }
+}
+
+impl IsDefault for AttrFlags {
+ fn is_default(&self) -> bool {
+ self.is_empty()
+ }
+}
+
+impl IsDefault for bool {
+ fn is_default(&self) -> bool {
+ !self
+ }
+}
+
+impl IsDefault for u32 {
+ fn is_default(&self) -> bool {
+ *self == 0
+ }
+}
+
+impl<T> IsDefault for LazyArray<T> {
+ fn is_default(&self) -> bool {
+ self.num_elems == 0
+ }
+}
+
+impl IsDefault for DefPathHash {
+ fn is_default(&self) -> bool {
+ self.0 == Fingerprint::ZERO
+ }
+}
+
/// Helper trait, for encoding to, and decoding from, a fixed number of bytes.
/// Used mainly for Lazy positions and lengths.
/// Unchecked invariant: `Self::default()` should encode as `[0; BYTE_LEN]`,
/// but this has no impact on safety.
-pub(super) trait FixedSizeEncoding: Default {
+pub(super) trait FixedSizeEncoding: IsDefault {
/// This should be `[u8; BYTE_LEN]`;
/// Cannot use an associated `const BYTE_LEN: usize` instead due to const eval limitations.
type ByteArray;
fn write_to_bytes(self, b: &mut Self::ByteArray);
}
+/// This implementation is not used generically, but for reading/writing
+/// concrete `u32` fields in `Lazy*` structures, which may be zero.
impl FixedSizeEncoding for u32 {
type ByteArray = [u8; 4];
fn write_to_bytes(self, b: &mut [u8;1]) {
use $ty::*;
b[0] = match self {
- None => 0,
+ None => unreachable!(),
$(Some($($pat)*) => 1 + ${index()},)*
}
}
}
// We directly encode `DefPathHash` because a `LazyValue` would incur a 25% cost.
-impl FixedSizeEncoding for Option<DefPathHash> {
+impl FixedSizeEncoding for DefPathHash {
type ByteArray = [u8; 16];
#[inline]
fn from_bytes(b: &[u8; 16]) -> Self {
- Some(DefPathHash(Fingerprint::from_le_bytes(*b)))
+ DefPathHash(Fingerprint::from_le_bytes(*b))
}
#[inline]
fn write_to_bytes(self, b: &mut [u8; 16]) {
- let Some(DefPathHash(fingerprint)) = self else {
- panic!("Trying to encode absent DefPathHash.")
- };
- *b = fingerprint.to_le_bytes();
+ debug_assert!(!self.is_default());
+ *b = self.0.to_le_bytes();
}
}
#[inline]
fn from_bytes(b: &[u8; 8]) -> Self {
let krate = u32::from_le_bytes(b[0..4].try_into().unwrap());
- let index = u32::from_le_bytes(b[4..8].try_into().unwrap());
if krate == 0 {
return None;
}
+ let index = u32::from_le_bytes(b[4..8].try_into().unwrap());
Some(RawDefId { krate: krate - 1, index })
}
#[inline]
fn write_to_bytes(self, b: &mut [u8; 8]) {
match self {
- None => *b = [0; 8],
+ None => unreachable!(),
Some(RawDefId { krate, index }) => {
// CrateNum is less than `CrateNum::MAX_AS_U32`.
debug_assert!(krate < u32::MAX);
#[inline]
fn write_to_bytes(self, b: &mut [u8; 1]) {
+ debug_assert!(!self.is_default());
b[0] = self.bits();
}
}
#[inline]
fn write_to_bytes(self, b: &mut [u8; 1]) {
+ debug_assert!(!self.is_default());
b[0] = self as u8
}
}
#[inline]
fn write_to_bytes(self, b: &mut [u8; 4]) {
- let position = self.map_or(0, |lazy| lazy.position.get());
+ match self {
+ None => unreachable!(),
+ Some(lazy) => {
+ let position = lazy.position.get();
+ let position: u32 = position.try_into().unwrap();
+ position.write_to_bytes(b)
+ }
+ }
+ }
+}
+
+impl<T> LazyArray<T> {
+ #[inline]
+ fn write_to_bytes_impl(self, b: &mut [u8; 8]) {
+ let ([position_bytes, meta_bytes],[])= b.as_chunks_mut::<4>() else { panic!() };
+
+ let position = self.position.get();
let position: u32 = position.try_into().unwrap();
- position.write_to_bytes(b)
+ position.write_to_bytes(position_bytes);
+
+ let len = self.num_elems;
+ let len: u32 = len.try_into().unwrap();
+ len.write_to_bytes(meta_bytes);
+ }
+
+ fn from_bytes_impl(position_bytes: &[u8; 4], meta_bytes: &[u8; 4]) -> Option<LazyArray<T>> {
+ let position = NonZeroUsize::new(u32::from_bytes(position_bytes) as usize)?;
+ let len = u32::from_bytes(meta_bytes) as usize;
+ Some(LazyArray::from_position_and_num_elems(position, len))
}
}
-impl<T> FixedSizeEncoding for Option<LazyArray<T>> {
+impl<T> FixedSizeEncoding for LazyArray<T> {
type ByteArray = [u8; 8];
#[inline]
fn from_bytes(b: &[u8; 8]) -> Self {
- let ([ref position_bytes, ref meta_bytes],[])= b.as_chunks::<4>() else { panic!() };
- let position = NonZeroUsize::new(u32::from_bytes(position_bytes) as usize)?;
- let len = u32::from_bytes(meta_bytes) as usize;
- Some(LazyArray::from_position_and_num_elems(position, len))
+ let ([position_bytes, meta_bytes],[])= b.as_chunks::<4>() else { panic!() };
+ if *meta_bytes == [0; 4] {
+ return Default::default();
+ }
+ LazyArray::from_bytes_impl(position_bytes, meta_bytes).unwrap()
}
#[inline]
fn write_to_bytes(self, b: &mut [u8; 8]) {
- let ([ref mut position_bytes, ref mut meta_bytes],[])= b.as_chunks_mut::<4>() else { panic!() };
+ assert!(!self.is_default());
+ self.write_to_bytes_impl(b)
+ }
+}
- let position = self.map_or(0, |lazy| lazy.position.get());
- let position: u32 = position.try_into().unwrap();
- position.write_to_bytes(position_bytes);
+impl<T> FixedSizeEncoding for Option<LazyArray<T>> {
+ type ByteArray = [u8; 8];
- let len = self.map_or(0, |lazy| lazy.num_elems);
- let len: u32 = len.try_into().unwrap();
- len.write_to_bytes(meta_bytes);
+ #[inline]
+ fn from_bytes(b: &[u8; 8]) -> Self {
+ let ([position_bytes, meta_bytes],[])= b.as_chunks::<4>() else { panic!() };
+ LazyArray::from_bytes_impl(position_bytes, meta_bytes)
+ }
+
+ #[inline]
+ fn write_to_bytes(self, b: &mut [u8; 8]) {
+ match self {
+ None => unreachable!(),
+ Some(lazy) => lazy.write_to_bytes_impl(b),
+ }
}
}
where
Option<T>: FixedSizeEncoding<ByteArray = [u8; N]>,
{
- pub(crate) fn set(&mut self, i: I, value: T) {
- self.set_nullable(i, Some(value))
+ pub(crate) fn set_some(&mut self, i: I, value: T) {
+ self.set(i, Some(value))
}
}
impl<I: Idx, const N: usize, T: FixedSizeEncoding<ByteArray = [u8; N]>> TableBuilder<I, T> {
- pub(crate) fn set_nullable(&mut self, i: I, value: T) {
- // FIXME(eddyb) investigate more compact encodings for sparse tables.
- // On the PR @michaelwoerister mentioned:
- // > Space requirements could perhaps be optimized by using the HAMT `popcnt`
- // > trick (i.e. divide things into buckets of 32 or 64 items and then
- // > store bit-masks of which item in each bucket is actually serialized).
- self.blocks.ensure_contains_elem(i, || [0; N]);
- value.write_to_bytes(&mut self.blocks[i]);
+ /// Sets the table value if it is not default.
+ /// ATTENTION: For optimization default values are simply ignored by this function, because
+ /// right now metadata tables never need to reset non-default values to default. If such need
+ /// arises in the future then a new method (e.g. `clear` or `reset`) will need to be introduced
+ /// for doing that explicitly.
+ pub(crate) fn set(&mut self, i: I, value: T) {
+ if !value.is_default() {
+ // FIXME(eddyb) investigate more compact encodings for sparse tables.
+ // On the PR @michaelwoerister mentioned:
+ // > Space requirements could perhaps be optimized by using the HAMT `popcnt`
+ // > trick (i.e. divide things into buckets of 32 or 64 items and then
+ // > store bit-masks of which item in each bucket is actually serialized).
+ self.blocks.ensure_contains_elem(i, || [0; N]);
+ value.write_to_bytes(&mut self.blocks[i]);
+ }
}
pub(crate) fn encode(&self, buf: &mut FileEncoder) -> LazyTable<I, T> {
let start = self.position.get();
let bytes = &metadata.blob()[start..start + self.encoded_size];
let (bytes, []) = bytes.as_chunks::<N>() else { panic!() };
- match bytes.get(i.index()) {
- Some(bytes) => FixedSizeEncoding::from_bytes(bytes),
- None => FixedSizeEncoding::from_bytes(&[0; N]),
- }
+ bytes.get(i.index()).map_or_else(Default::default, FixedSizeEncoding::from_bytes)
}
/// Size of the table in entries, including possible gaps.
[decode] trait_impl_trait_tys: rustc_data_structures::fx::FxHashMap<rustc_hir::def_id::DefId, rustc_middle::ty::Ty<'tcx>>,
[] bit_set_u32: rustc_index::bit_set::BitSet<u32>,
+ [] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>,
]);
)
}
#[track_caller]
pub fn parent_id(self, hir_id: HirId) -> HirId {
self.opt_parent_id(hir_id)
- .unwrap_or_else(|| bug!("No parent for node {:?}", self.node_to_string(hir_id)))
+ .unwrap_or_else(|| bug!("No parent for node {}", self.node_to_string(hir_id)))
}
pub fn get_parent(self, hir_id: HirId) -> Node<'hir> {
}
fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
- let id_str = format!(" (hir_id={})", id);
-
let path_str = |def_id: LocalDefId| map.tcx.def_path_str(def_id.to_def_id());
let span_str = || map.tcx.sess.source_map().span_to_snippet(map.span(id)).unwrap_or_default();
- let node_str = |prefix| format!("{} {}{}", prefix, span_str(), id_str);
+ let node_str = |prefix| format!("{id} ({prefix} `{}`)", span_str());
match map.find(id) {
Some(Node::Item(item)) => {
ItemKind::TraitAlias(..) => "trait alias",
ItemKind::Impl { .. } => "impl",
};
- format!("{} {}{}", item_str, path_str(item.owner_id.def_id), id_str)
+ format!("{id} ({item_str} {})", path_str(item.owner_id.def_id))
}
Some(Node::ForeignItem(item)) => {
- format!("foreign item {}{}", path_str(item.owner_id.def_id), id_str)
+ format!("{id} (foreign item {})", path_str(item.owner_id.def_id))
}
Some(Node::ImplItem(ii)) => {
let kind = match ii.kind {
ImplItemKind::Fn(..) => "method",
ImplItemKind::Type(_) => "assoc type",
};
- format!("{} {} in {}{}", kind, ii.ident, path_str(ii.owner_id.def_id), id_str)
+ format!("{id} ({kind} `{}` in {})", ii.ident, path_str(ii.owner_id.def_id))
}
Some(Node::TraitItem(ti)) => {
let kind = match ti.kind {
TraitItemKind::Type(..) => "assoc type",
};
- format!("{} {} in {}{}", kind, ti.ident, path_str(ti.owner_id.def_id), id_str)
+ format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id))
}
Some(Node::Variant(ref variant)) => {
- format!("variant {} in {}{}", variant.ident, path_str(variant.def_id), id_str)
+ format!("{id} (variant `{}` in {})", variant.ident, path_str(variant.def_id))
}
Some(Node::Field(ref field)) => {
- format!("field {} in {}{}", field.ident, path_str(field.def_id), id_str)
+ format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id))
}
Some(Node::AnonConst(_)) => node_str("const"),
Some(Node::Expr(_)) => node_str("expr"),
Some(Node::Infer(_)) => node_str("infer"),
Some(Node::Local(_)) => node_str("local"),
Some(Node::Ctor(ctor)) => format!(
- "ctor {}{}",
+ "{id} (ctor {})",
ctor.ctor_def_id().map_or("<missing path>".into(), |def_id| path_str(def_id)),
- id_str
),
Some(Node::Lifetime(_)) => node_str("lifetime"),
Some(Node::GenericParam(ref param)) => {
- format!("generic_param {}{}", path_str(param.def_id), id_str)
+ format!("{id} (generic_param {})", path_str(param.def_id))
}
- Some(Node::Crate(..)) => String::from("root_crate"),
- None => format!("unknown node{}", id_str),
+ Some(Node::Crate(..)) => String::from("(root_crate)"),
+ None => format!("{id} (unknown node)"),
}
}
"Expression({:?}) = {} {} {}",
id.index(),
lhs.index(),
- if *op == Op::Add { "+" } else { "-" },
+ match op {
+ Op::Add => "+",
+ Op::Subtract => "-",
+ },
rhs.index(),
),
Unreachable => write!(fmt, "Unreachable"),
let decl = &body.local_decls[local];
write!(w, "let ")?;
- if decl.mutability == Mutability::Mut {
+ if decl.mutability.is_mut() {
write!(w, "mut ")?;
}
(self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
let local = Local::new(index);
let decl = &self.local_decls[local];
- if decl.is_user_variable() && decl.mutability == Mutability::Mut {
- Some(local)
- } else {
- None
- }
+ (decl.is_user_variable() && decl.mutability.is_mut()).then(|| local)
})
}
AggregateKind::Closure(def_id, substs) => ty::tls::with(|tcx| {
let name = if tcx.sess.opts.unstable_opts.span_free_formats {
let substs = tcx.lift(substs).unwrap();
- format!(
- "[closure@{}]",
- tcx.def_path_str_with_substs(def_id.to_def_id(), substs),
- )
+ format!("[closure@{}]", tcx.def_path_str_with_substs(def_id, substs),)
} else {
let span = tcx.def_span(def_id);
format!(
let mut struct_fmt = fmt.debug_struct(&name);
// FIXME(project-rfc-2229#48): This should be a list of capture names/places
- if let Some(upvars) = tcx.upvars_mentioned(def_id) {
+ if let Some(def_id) = def_id.as_local()
+ && let Some(upvars) = tcx.upvars_mentioned(def_id)
+ {
for (&var_id, place) in iter::zip(upvars.keys(), places) {
let var_name = tcx.hir().name(var_id);
struct_fmt.field(var_name.as_str(), place);
}
+ } else {
+ for (index, place) in places.iter().enumerate() {
+ struct_fmt.field(&format!("{index}"), place);
+ }
}
struct_fmt.finish()
let mut struct_fmt = fmt.debug_struct(&name);
// FIXME(project-rfc-2229#48): This should be a list of capture names/places
- if let Some(upvars) = tcx.upvars_mentioned(def_id) {
+ if let Some(def_id) = def_id.as_local()
+ && let Some(upvars) = tcx.upvars_mentioned(def_id)
+ {
for (&var_id, place) in iter::zip(upvars.keys(), places) {
let var_name = tcx.hir().name(var_id);
struct_fmt.field(var_name.as_str(), place);
}
+ } else {
+ for (index, place) in places.iter().enumerate() {
+ struct_fmt.field(&format!("{index}"), place);
+ }
}
struct_fmt.finish()
base_n::encode(hash, base_n::CASE_INSENSITIVE)
}
- pub fn estimate_size(&mut self, tcx: TyCtxt<'tcx>) {
+ pub fn create_size_estimate(&mut self, tcx: TyCtxt<'tcx>) {
// Estimate the size of a codegen unit as (approximately) the number of MIR
// statements it corresponds to.
self.size_estimate = Some(self.items.keys().map(|mi| mi.size_estimate(tcx)).sum());
}
#[inline]
+ /// Should only be called if [`create_size_estimate`] has previously been called.
+ ///
+ /// [`create_size_estimate`]: Self::create_size_estimate
pub fn size_estimate(&self) -> usize {
- // Should only be called if `estimate_size` has previously been called.
- self.size_estimate.expect("estimate_size must be called before getting a size_estimate")
+ self.size_estimate
+ .expect("create_size_estimate must be called before getting a size_estimate")
}
pub fn modify_size_estimate(&mut self, delta: usize) {
continue;
}
- let mut_str = if local_decl.mutability == Mutability::Mut { "mut " } else { "" };
+ let mut_str = local_decl.mutability.prefix_str();
let mut indented_decl =
format!("{0:1$}let {2}{3:?}: {4:?}", INDENT, indent, mut_str, local, local_decl.ty);
/// active field index would identity the field `c`
Adt(DefId, VariantIdx, SubstsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<usize>),
- // Note: We can use LocalDefId since closures and generators a deaggregated
- // before codegen.
- Closure(LocalDefId, SubstsRef<'tcx>),
- Generator(LocalDefId, SubstsRef<'tcx>, hir::Movability),
+ Closure(DefId, SubstsRef<'tcx>),
+ Generator(DefId, SubstsRef<'tcx>, hir::Movability),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
AggregateKind::Adt(did, _, substs, _, _) => {
tcx.bound_type_of(did).subst(tcx, substs)
}
- AggregateKind::Closure(did, substs) => tcx.mk_closure(did.to_def_id(), substs),
+ AggregateKind::Closure(did, substs) => tcx.mk_closure(did, substs),
AggregateKind::Generator(did, substs, movability) => {
- tcx.mk_generator(did.to_def_id(), substs, movability)
+ tcx.mk_generator(did, substs, movability)
}
},
Rvalue::ShallowInitBox(_, ty) => tcx.mk_box(ty),
mod chalk;
pub mod query;
pub mod select;
+pub mod solve;
pub mod specialization_graph;
mod structural_impls;
pub mod util;
pub struct ImplDerivedObligationCause<'tcx> {
pub derived: DerivedObligationCause<'tcx>,
pub impl_def_id: DefId,
+ /// The index of the derived predicate in the parent impl's predicates.
+ pub impl_def_predicate_index: Option<usize>,
pub span: Span,
}
--- /dev/null
+use std::ops::ControlFlow;
+
+use rustc_data_structures::intern::Interned;
+
+use crate::ty::{FallibleTypeFolder, Ty, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor};
+
+#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
+pub struct ExternalConstraints<'tcx>(pub(crate) Interned<'tcx, ExternalConstraintsData<'tcx>>);
+
+impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> {
+ type Target = ExternalConstraintsData<'tcx>;
+
+ fn deref(&self) -> &Self::Target {
+ &*self.0
+ }
+}
+
+/// Additional constraints returned on success.
+#[derive(Debug, PartialEq, Eq, Clone, Hash, Default)]
+pub struct ExternalConstraintsData<'tcx> {
+ // FIXME: implement this.
+ pub regions: (),
+ pub opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>,
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ExternalConstraints<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+ Ok(FallibleTypeFolder::tcx(folder).intern_external_constraints(ExternalConstraintsData {
+ regions: (),
+ opaque_types: self
+ .opaque_types
+ .iter()
+ .map(|opaque| opaque.try_fold_with(folder))
+ .collect::<Result<_, F::Error>>()?,
+ }))
+ }
+
+ fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+ TypeFolder::tcx(folder).intern_external_constraints(ExternalConstraintsData {
+ regions: (),
+ opaque_types: self.opaque_types.iter().map(|opaque| opaque.fold_with(folder)).collect(),
+ })
+ }
+}
+
+impl<'tcx> TypeVisitable<'tcx> for ExternalConstraints<'tcx> {
+ fn visit_with<V: TypeVisitor<'tcx>>(
+ &self,
+ visitor: &mut V,
+ ) -> std::ops::ControlFlow<V::BreakTy> {
+ self.regions.visit_with(visitor)?;
+ self.opaque_types.visit_with(visitor)?;
+ ControlFlow::Continue(())
+ }
+}
};
use crate::thir::Thir;
use crate::traits;
+use crate::traits::solve::{ExternalConstraints, ExternalConstraintsData};
use crate::ty::query::{self, TyCtxtAt};
use crate::ty::{
self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, DefIdTree, FloatTy, FloatVar,
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
layout: InternedSet<'tcx, LayoutS<VariantIdx>>,
adt_def: InternedSet<'tcx, AdtDefData>,
+ external_constraints: InternedSet<'tcx, ExternalConstraintsData<'tcx>>,
}
impl<'tcx> CtxtInterners<'tcx> {
bound_variable_kinds: Default::default(),
layout: Default::default(),
adt_def: Default::default(),
+ external_constraints: Default::default(),
}
}
const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
layout: intern_layout(LayoutS<VariantIdx>): Layout -> Layout<'tcx>,
adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>,
+ external_constraints: intern_external_constraints(ExternalConstraintsData<'tcx>): ExternalConstraints -> ExternalConstraints<'tcx>,
}
macro_rules! slice_interners {
self.late_bound_vars_map(id.owner)
.and_then(|map| map.get(&id.local_id).cloned())
.unwrap_or_else(|| {
- bug!("No bound vars found for {:?} ({:?})", self.hir().node_to_string(id), id)
+ bug!("No bound vars found for {}", self.hir().node_to_string(id))
})
.iter(),
)
use std::ops::ControlFlow;
use crate::ty::{
- visit::TypeVisitable, AliasTy, Const, ConstKind, DefIdTree, InferConst, InferTy, Opaque,
- PolyTraitPredicate, Projection, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor,
+ visit::TypeVisitable, AliasTy, Const, ConstKind, DefIdTree, FallibleTypeFolder, InferConst,
+ InferTy, Opaque, PolyTraitPredicate, Projection, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
+ TypeSuperVisitable, TypeVisitor,
};
use rustc_data_structures::fx::FxHashMap;
}
}
-pub trait IsSuggestable<'tcx> {
+pub trait IsSuggestable<'tcx>: Sized {
/// Whether this makes sense to suggest in a diagnostic.
///
/// We filter out certain types and constants since they don't provide
/// Only if `infer_suggestable` is true, we consider type and const
/// inference variables to be suggestable.
fn is_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> bool;
+
+ fn make_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> Option<Self>;
}
impl<'tcx, T> IsSuggestable<'tcx> for T
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<'tcx> + TypeFoldable<'tcx>,
{
fn is_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> bool {
self.visit_with(&mut IsSuggestableVisitor { tcx, infer_suggestable }).is_continue()
}
+
+ fn make_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> Option<T> {
+ self.try_fold_with(&mut MakeSuggestableFolder { tcx, infer_suggestable }).ok()
+ }
}
pub fn suggest_arbitrary_trait_bound<'tcx>(
c.super_visit_with(self)
}
}
+
+pub struct MakeSuggestableFolder<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ infer_suggestable: bool,
+}
+
+impl<'tcx> FallibleTypeFolder<'tcx> for MakeSuggestableFolder<'tcx> {
+ type Error = ();
+
+ fn tcx(&self) -> TyCtxt<'tcx> {
+ self.tcx
+ }
+
+ fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+ let t = match *t.kind() {
+ Infer(InferTy::TyVar(_)) if self.infer_suggestable => t,
+
+ FnDef(def_id, substs) => {
+ self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs))
+ }
+
+ // FIXME(compiler-errors): We could replace these with infer, I guess.
+ Closure(..)
+ | Infer(..)
+ | Generator(..)
+ | GeneratorWitness(..)
+ | Bound(_, _)
+ | Placeholder(_)
+ | Error(_) => {
+ return Err(());
+ }
+
+ Alias(Opaque, AliasTy { def_id, .. }) => {
+ let parent = self.tcx.parent(def_id);
+ if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent)
+ && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *self.tcx.type_of(parent).kind()
+ && parent_opaque_def_id == def_id
+ {
+ t
+ } else {
+ return Err(());
+ }
+ }
+
+ Param(param) => {
+ // FIXME: It would be nice to make this not use string manipulation,
+ // but it's pretty hard to do this, since `ty::ParamTy` is missing
+ // sufficient info to determine if it is synthetic, and we don't
+ // always have a convenient way of getting `ty::Generics` at the call
+ // sites we invoke `IsSuggestable::is_suggestable`.
+ if param.name.as_str().starts_with("impl ") {
+ return Err(());
+ }
+
+ t
+ }
+
+ _ => t,
+ };
+
+ t.try_super_fold_with(self)
+ }
+
+ fn try_fold_const(&mut self, c: Const<'tcx>) -> Result<Const<'tcx>, ()> {
+ let c = match c.kind() {
+ ConstKind::Infer(InferConst::Var(_)) if self.infer_suggestable => c,
+
+ ConstKind::Infer(..)
+ | ConstKind::Bound(..)
+ | ConstKind::Placeholder(..)
+ | ConstKind::Error(..) => {
+ return Err(());
+ }
+
+ _ => c,
+ };
+
+ c.try_super_fold_with(self)
+ }
+}
use rustc_target::spec::abi;
use std::borrow::Cow;
use std::collections::hash_map::DefaultHasher;
-use std::fmt;
-use std::hash::Hash;
-use std::hash::Hasher;
+use std::hash::{Hash, Hasher};
use std::path::PathBuf;
#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable, Lift)]
}
// Data structures used in type unification
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift, PartialEq, Eq)]
#[rustc_pass_by_value]
pub enum TypeError<'tcx> {
Mismatch,
/// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
/// afterwards to present additional details, particularly when it comes to lifetime-related
/// errors.
-impl<'tcx> fmt::Display for TypeError<'tcx> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+impl<'tcx> TypeError<'tcx> {
+ pub fn to_string(self, tcx: TyCtxt<'tcx>) -> Cow<'static, str> {
use self::TypeError::*;
- fn report_maybe_different(
- f: &mut fmt::Formatter<'_>,
- expected: &str,
- found: &str,
- ) -> fmt::Result {
+ fn report_maybe_different(expected: &str, found: &str) -> String {
// A naive approach to making sure that we're not reporting silly errors such as:
// (expected closure, found closure).
if expected == found {
- write!(f, "expected {}, found a different {}", expected, found)
+ format!("expected {}, found a different {}", expected, found)
} else {
- write!(f, "expected {}, found {}", expected, found)
+ format!("expected {}, found {}", expected, found)
}
}
_ => String::new(),
};
- match *self {
- CyclicTy(_) => write!(f, "cyclic type of infinite size"),
- CyclicConst(_) => write!(f, "encountered a self-referencing constant"),
- Mismatch => write!(f, "types differ"),
+ match self {
+ CyclicTy(_) => "cyclic type of infinite size".into(),
+ CyclicConst(_) => "encountered a self-referencing constant".into(),
+ Mismatch => "types differ".into(),
ConstnessMismatch(values) => {
- write!(f, "expected {} bound, found {} bound", values.expected, values.found)
+ format!("expected {} bound, found {} bound", values.expected, values.found).into()
}
PolarityMismatch(values) => {
- write!(f, "expected {} polarity, found {} polarity", values.expected, values.found)
+ format!("expected {} polarity, found {} polarity", values.expected, values.found)
+ .into()
}
UnsafetyMismatch(values) => {
- write!(f, "expected {} fn, found {} fn", values.expected, values.found)
+ format!("expected {} fn, found {} fn", values.expected, values.found).into()
}
AbiMismatch(values) => {
- write!(f, "expected {} fn, found {} fn", values.expected, values.found)
+ format!("expected {} fn, found {} fn", values.expected, values.found).into()
}
- ArgumentMutability(_) | Mutability => write!(f, "types differ in mutability"),
- TupleSize(values) => write!(
- f,
+ ArgumentMutability(_) | Mutability => "types differ in mutability".into(),
+ TupleSize(values) => format!(
"expected a tuple with {} element{}, found one with {} element{}",
values.expected,
pluralize!(values.expected),
values.found,
pluralize!(values.found)
- ),
- FixedArraySize(values) => write!(
- f,
+ )
+ .into(),
+ FixedArraySize(values) => format!(
"expected an array with a fixed size of {} element{}, found one with {} element{}",
values.expected,
pluralize!(values.expected),
values.found,
pluralize!(values.found)
- ),
- ArgCount => write!(f, "incorrect number of function parameters"),
- FieldMisMatch(adt, field) => write!(f, "field type mismatch: {}.{}", adt, field),
- RegionsDoesNotOutlive(..) => write!(f, "lifetime mismatch"),
+ )
+ .into(),
+ ArgCount => "incorrect number of function parameters".into(),
+ FieldMisMatch(adt, field) => format!("field type mismatch: {}.{}", adt, field).into(),
+ RegionsDoesNotOutlive(..) => "lifetime mismatch".into(),
// Actually naming the region here is a bit confusing because context is lacking
RegionsInsufficientlyPolymorphic(..) => {
- write!(f, "one type is more general than the other")
+ "one type is more general than the other".into()
}
- RegionsOverlyPolymorphic(br, _) => write!(
- f,
+ RegionsOverlyPolymorphic(br, _) => format!(
"expected concrete lifetime, found bound lifetime parameter{}",
br_string(br)
- ),
- RegionsPlaceholderMismatch => write!(f, "one type is more general than the other"),
- ArgumentSorts(values, _) | Sorts(values) => ty::tls::with(|tcx| {
- let (mut expected, mut found) = with_forced_trimmed_paths!((
- values.expected.sort_string(tcx),
- values.found.sort_string(tcx),
- ));
+ )
+ .into(),
+ RegionsPlaceholderMismatch => "one type is more general than the other".into(),
+ ArgumentSorts(values, _) | Sorts(values) => {
+ let mut expected = values.expected.sort_string(tcx);
+ let mut found = values.found.sort_string(tcx);
if expected == found {
expected = values.expected.sort_string(tcx);
found = values.found.sort_string(tcx);
}
- report_maybe_different(f, &expected, &found)
- }),
- Traits(values) => ty::tls::with(|tcx| {
+ report_maybe_different(&expected, &found).into()
+ }
+ Traits(values) => {
let (mut expected, mut found) = with_forced_trimmed_paths!((
tcx.def_path_str(values.expected),
tcx.def_path_str(values.found),
expected = tcx.def_path_str(values.expected);
found = tcx.def_path_str(values.found);
}
- report_maybe_different(
- f,
- &format!("trait `{expected}`"),
- &format!("trait `{found}`"),
- )
- }),
+ report_maybe_different(&format!("trait `{expected}`"), &format!("trait `{found}`"))
+ .into()
+ }
IntMismatch(ref values) => {
let expected = match values.expected {
ty::IntVarValue::IntType(ty) => ty.name_str(),
ty::IntVarValue::IntType(ty) => ty.name_str(),
ty::IntVarValue::UintType(ty) => ty.name_str(),
};
- write!(f, "expected `{}`, found `{}`", expected, found)
- }
- FloatMismatch(ref values) => {
- write!(
- f,
- "expected `{}`, found `{}`",
- values.expected.name_str(),
- values.found.name_str()
- )
+ format!("expected `{}`, found `{}`", expected, found).into()
}
- VariadicMismatch(ref values) => write!(
- f,
+ FloatMismatch(ref values) => format!(
+ "expected `{}`, found `{}`",
+ values.expected.name_str(),
+ values.found.name_str()
+ )
+ .into(),
+ VariadicMismatch(ref values) => format!(
"expected {} fn, found {} function",
if values.expected { "variadic" } else { "non-variadic" },
if values.found { "variadic" } else { "non-variadic" }
- ),
- ProjectionMismatched(ref values) => ty::tls::with(|tcx| {
- write!(
- f,
- "expected {}, found {}",
- tcx.def_path_str(values.expected),
- tcx.def_path_str(values.found)
- )
- }),
+ )
+ .into(),
+ ProjectionMismatched(ref values) => format!(
+ "expected `{}`, found `{}`",
+ tcx.def_path_str(values.expected),
+ tcx.def_path_str(values.found)
+ )
+ .into(),
ExistentialMismatch(ref values) => report_maybe_different(
- f,
&format!("trait `{}`", values.expected),
&format!("trait `{}`", values.found),
- ),
+ )
+ .into(),
ConstMismatch(ref values) => {
- write!(f, "expected `{}`, found `{}`", values.expected, values.found)
+ format!("expected `{}`, found `{}`", values.expected, values.found).into()
+ }
+ IntrinsicCast => "cannot coerce intrinsics to function pointers".into(),
+ TargetFeatureCast(_) => {
+ "cannot coerce functions with `#[target_feature]` to safe function pointers".into()
}
- IntrinsicCast => write!(f, "cannot coerce intrinsics to function pointers"),
- TargetFeatureCast(_) => write!(
- f,
- "cannot coerce functions with `#[target_feature]` to safe function pointers"
- ),
}
}
}
}
impl<'tcx> Ty<'tcx> {
- pub fn sort_string(self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
+ pub fn sort_string(self, tcx: TyCtxt<'tcx>) -> Cow<'static, str> {
match *self.kind() {
- ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => {
- format!("`{}`", self).into()
- }
- ty::Tuple(ref tys) if tys.is_empty() => format!("`{}`", self).into(),
-
- ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did())).into(),
ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(),
- ty::Array(t, n) => {
- if t.is_simple_ty() {
- return format!("array `{}`", self).into();
- }
-
- let n = tcx.lift(n).unwrap();
- if let ty::ConstKind::Value(v) = n.kind() {
- if let Some(n) = v.try_to_machine_usize(tcx) {
- return format!("array of {} element{}", n, pluralize!(n)).into();
- }
- }
- "array".into()
- }
- ty::Slice(ty) if ty.is_simple_ty() => format!("slice `{}`", self).into(),
- ty::Slice(_) => "slice".into(),
- ty::RawPtr(tymut) => {
- let tymut_string = match tymut.mutbl {
- hir::Mutability::Mut => tymut.to_string(),
- hir::Mutability::Not => format!("const {}", tymut.ty),
- };
-
- if tymut_string != "_" && (tymut.ty.is_simple_text() || tymut_string.len() < "const raw pointer".len()) {
- format!("`*{}`", tymut_string).into()
- } else {
- // Unknown type name, it's long or has type arguments
- "raw pointer".into()
- }
- },
- ty::Ref(_, ty, mutbl) => {
- let tymut = ty::TypeAndMut { ty, mutbl };
- let tymut_string = tymut.to_string();
-
- if tymut_string != "_"
- && (ty.is_simple_text() || tymut_string.len() < "mutable reference".len())
- {
- format!("`&{}`", tymut_string).into()
- } else {
- // Unknown type name, it's long or has type arguments
- match mutbl {
- hir::Mutability::Mut => "mutable reference",
- _ => "reference",
- }
- .into()
- }
- }
ty::FnDef(def_id, ..) => match tcx.def_kind(def_id) {
DefKind::Ctor(CtorOf::Struct, _) => "struct constructor".into(),
DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(),
},
ty::FnPtr(_) => "fn pointer".into(),
ty::Dynamic(ref inner, ..) if let Some(principal) = inner.principal() => {
- format!("trait object `dyn {}`", tcx.def_path_str(principal.def_id())).into()
+ format!("`dyn {}`", tcx.def_path_str(principal.def_id())).into()
}
ty::Dynamic(..) => "trait object".into(),
ty::Closure(..) => "closure".into(),
ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(),
ty::GeneratorWitness(..) |
ty::GeneratorWitnessMIR(..) => "generator witness".into(),
- ty::Tuple(..) => "tuple".into(),
ty::Infer(ty::TyVar(_)) => "inferred type".into(),
ty::Infer(ty::IntVar(_)) => "integer".into(),
ty::Infer(ty::FloatVar(_)) => "floating-point number".into(),
ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
ty::Alias(ty::Projection, _) => "associated type".into(),
- ty::Param(p) => format!("type parameter `{}`", p).into(),
+ ty::Param(p) => format!("type parameter `{p}`").into(),
ty::Alias(ty::Opaque, ..) => "opaque type".into(),
ty::Error(_) => "type error".into(),
+ _ => {
+ let width = tcx.sess.diagnostic_width();
+ let length_limit = std::cmp::max(width / 4, 15);
+ format!("`{}`", tcx.ty_string_with_limit(self, length_limit)).into()
+ }
}
}
}
impl<'tcx> TyCtxt<'tcx> {
- pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
- let width = self.sess.diagnostic_width();
- let length_limit = width.saturating_sub(30);
+ pub fn ty_string_with_limit(self, ty: Ty<'tcx>, length_limit: usize) -> String {
let mut type_limit = 50;
let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS)
.pretty_print_type(ty)
.expect("could not write to `String`")
.into_buffer();
- if regular.len() <= width {
- return (regular, None);
+ if regular.len() <= length_limit {
+ return regular;
}
let mut short;
loop {
}
type_limit -= 1;
}
+ short
+ }
+
+ pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
+ let width = self.sess.diagnostic_width();
+ let length_limit = width.saturating_sub(30);
+ let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS)
+ .pretty_print_type(ty)
+ .expect("could not write to `String`")
+ .into_buffer();
+ if regular.len() <= width {
+ return (regular, None);
+ }
+ let short = self.ty_string_with_limit(ty, length_limit);
if regular == short {
return (regular, None);
}
/// the infallible methods of this trait to ensure that the two APIs
/// are coherent.
pub trait TypeFolder<'tcx>: FallibleTypeFolder<'tcx, Error = !> {
- fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
+ fn tcx(&self) -> TyCtxt<'tcx>;
fn fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T>
where
let index = entry.index();
let var = ty::BoundVar::from_usize(index);
let kind = entry
- .or_insert_with(|| ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon))
+ .or_insert_with(|| {
+ ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon(index as u32))
+ })
.expect_ty();
self.tcx.mk_ty(ty::Bound(ty::INNERMOST, BoundTy { var, kind }))
}
let tcx = cx.tcx();
let param_env = cx.param_env();
- let pointee_info =
- match *this.ty.kind() {
- ty::RawPtr(mt) if offset.bytes() == 0 => {
- tcx.layout_of(param_env.and(mt.ty)).ok().map(|layout| PointeeInfo {
- size: layout.size,
- align: layout.align.abi,
- safe: None,
- })
- }
- ty::FnPtr(fn_sig) if offset.bytes() == 0 => {
- tcx.layout_of(param_env.and(tcx.mk_fn_ptr(fn_sig))).ok().map(|layout| {
- PointeeInfo { size: layout.size, align: layout.align.abi, safe: None }
- })
- }
- ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
- let kind = if tcx.sess.opts.optimize == OptLevel::No {
- // Use conservative pointer kind if not optimizing. This saves us the
- // Freeze/Unpin queries, and can save time in the codegen backend (noalias
- // attributes in LLVM have compile-time cost even in unoptimized builds).
- PointerKind::SharedMutable
- } else {
- match mt {
- hir::Mutability::Not => {
- if ty.is_freeze(tcx, cx.param_env()) {
- PointerKind::Frozen
- } else {
- PointerKind::SharedMutable
- }
- }
- hir::Mutability::Mut => {
- // References to self-referential structures should not be considered
- // noalias, as another pointer to the structure can be obtained, that
- // is not based-on the original reference. We consider all !Unpin
- // types to be potentially self-referential here.
- if ty.is_unpin(tcx, cx.param_env()) {
- PointerKind::UniqueBorrowed
- } else {
- PointerKind::UniqueBorrowedPinned
- }
- }
- }
- };
+ let pointee_info = match *this.ty.kind() {
+ ty::RawPtr(mt) if offset.bytes() == 0 => {
+ tcx.layout_of(param_env.and(mt.ty)).ok().map(|layout| PointeeInfo {
+ size: layout.size,
+ align: layout.align.abi,
+ safe: None,
+ })
+ }
+ ty::FnPtr(fn_sig) if offset.bytes() == 0 => {
+ tcx.layout_of(param_env.and(tcx.mk_fn_ptr(fn_sig))).ok().map(|layout| PointeeInfo {
+ size: layout.size,
+ align: layout.align.abi,
+ safe: None,
+ })
+ }
+ ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
+ // Use conservative pointer kind if not optimizing. This saves us the
+ // Freeze/Unpin queries, and can save time in the codegen backend (noalias
+ // attributes in LLVM have compile-time cost even in unoptimized builds).
+ let optimize = tcx.sess.opts.optimize != OptLevel::No;
+ let kind = match mt {
+ hir::Mutability::Not => PointerKind::SharedRef {
+ frozen: optimize && ty.is_freeze(tcx, cx.param_env()),
+ },
+ hir::Mutability::Mut => PointerKind::MutableRef {
+ unpin: optimize && ty.is_unpin(tcx, cx.param_env()),
+ },
+ };
- tcx.layout_of(param_env.and(ty)).ok().map(|layout| PointeeInfo {
- size: layout.size,
- align: layout.align.abi,
- safe: Some(kind),
- })
- }
+ tcx.layout_of(param_env.and(ty)).ok().map(|layout| PointeeInfo {
+ size: layout.size,
+ align: layout.align.abi,
+ safe: Some(kind),
+ })
+ }
- _ => {
- let mut data_variant = match this.variants {
- // Within the discriminant field, only the niche itself is
- // always initialized, so we only check for a pointer at its
- // offset.
- //
- // If the niche is a pointer, it's either valid (according
- // to its type), or null (which the niche field's scalar
- // validity range encodes). This allows using
- // `dereferenceable_or_null` for e.g., `Option<&T>`, and
- // this will continue to work as long as we don't start
- // using more niches than just null (e.g., the first page of
- // the address space, or unaligned pointers).
- Variants::Multiple {
- tag_encoding: TagEncoding::Niche { untagged_variant, .. },
- tag_field,
- ..
- } if this.fields.offset(tag_field) == offset => {
- Some(this.for_variant(cx, untagged_variant))
- }
- _ => Some(this),
- };
+ _ => {
+ let mut data_variant = match this.variants {
+ // Within the discriminant field, only the niche itself is
+ // always initialized, so we only check for a pointer at its
+ // offset.
+ //
+ // If the niche is a pointer, it's either valid (according
+ // to its type), or null (which the niche field's scalar
+ // validity range encodes). This allows using
+ // `dereferenceable_or_null` for e.g., `Option<&T>`, and
+ // this will continue to work as long as we don't start
+ // using more niches than just null (e.g., the first page of
+ // the address space, or unaligned pointers).
+ Variants::Multiple {
+ tag_encoding: TagEncoding::Niche { untagged_variant, .. },
+ tag_field,
+ ..
+ } if this.fields.offset(tag_field) == offset => {
+ Some(this.for_variant(cx, untagged_variant))
+ }
+ _ => Some(this),
+ };
- if let Some(variant) = data_variant {
- // We're not interested in any unions.
- if let FieldsShape::Union(_) = variant.fields {
- data_variant = None;
- }
+ if let Some(variant) = data_variant {
+ // We're not interested in any unions.
+ if let FieldsShape::Union(_) = variant.fields {
+ data_variant = None;
}
+ }
- let mut result = None;
-
- if let Some(variant) = data_variant {
- // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
- // (requires passing in the expected address space from the caller)
- let ptr_end = offset + Pointer(AddressSpace::DATA).size(cx);
- for i in 0..variant.fields.count() {
- let field_start = variant.fields.offset(i);
- if field_start <= offset {
- let field = variant.field(cx, i);
- result = field.to_result().ok().and_then(|field| {
- if ptr_end <= field_start + field.size {
- // We found the right field, look inside it.
- let field_info =
- field.pointee_info_at(cx, offset - field_start);
- field_info
- } else {
- None
- }
- });
- if result.is_some() {
- break;
+ let mut result = None;
+
+ if let Some(variant) = data_variant {
+ // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
+ // (requires passing in the expected address space from the caller)
+ let ptr_end = offset + Pointer(AddressSpace::DATA).size(cx);
+ for i in 0..variant.fields.count() {
+ let field_start = variant.fields.offset(i);
+ if field_start <= offset {
+ let field = variant.field(cx, i);
+ result = field.to_result().ok().and_then(|field| {
+ if ptr_end <= field_start + field.size {
+ // We found the right field, look inside it.
+ let field_info =
+ field.pointee_info_at(cx, offset - field_start);
+ field_info
+ } else {
+ None
}
+ });
+ if result.is_some() {
+ break;
}
}
}
+ }
- // FIXME(eddyb) This should be for `ptr::Unique<T>`, not `Box<T>`.
- if let Some(ref mut pointee) = result {
- if let ty::Adt(def, _) = this.ty.kind() {
- if def.is_box() && offset.bytes() == 0 {
- pointee.safe = Some(PointerKind::UniqueOwned);
- }
+ // FIXME(eddyb) This should be for `ptr::Unique<T>`, not `Box<T>`.
+ if let Some(ref mut pointee) = result {
+ if let ty::Adt(def, _) = this.ty.kind() {
+ if def.is_box() && offset.bytes() == 0 {
+ let optimize = tcx.sess.opts.optimize != OptLevel::No;
+ pointee.safe = Some(PointerKind::Box {
+ unpin: optimize && this.ty.boxed_ty().is_unpin(tcx, cx.param_env()),
+ });
}
}
-
- result
}
- };
+
+ result
+ }
+ };
debug!(
"pointee_info_at (offset={:?}, type kind: {:?}) => {:?}",
pub type PlaceholderRegion = Placeholder<BoundRegionKind>;
-pub type PlaceholderType = Placeholder<BoundVar>;
+pub type PlaceholderType = Placeholder<BoundTyKind>;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
#[derive(TyEncodable, TyDecodable, PartialOrd, Ord)]
p!(")")
}
ty::FnDef(def_id, substs) => {
- let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs);
- p!(print(sig), " {{", print_value_path(def_id, substs), "}}");
+ if NO_QUERIES.with(|q| q.get()) {
+ p!(print_def_path(def_id, substs));
+ } else {
+ let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs);
+ p!(print(sig), " {{", print_value_path(def_id, substs), "}}");
+ }
}
ty::FnPtr(ref bare_fn) => p!(print(bare_fn)),
ty::Infer(infer_ty) => {
ty::Error(_) => p!("[type error]"),
ty::Param(ref param_ty) => p!(print(param_ty)),
ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
- ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?,
- ty::BoundTyKind::Param(p) => p!(write("{}", p)),
+ ty::BoundTyKind::Anon(bv) => {
+ self.pretty_print_bound_var(debruijn, ty::BoundVar::from_u32(bv))?
+ }
+ ty::BoundTyKind::Param(_, s) => p!(write("{}", s)),
},
ty::Adt(def, substs) => {
p!(print_def_path(def.did(), substs));
}
ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
- // FIXME(eddyb) print this with `print_def_path`.
// We use verbose printing in 'NO_QUERIES' mode, to
// avoid needing to call `predicates_of`. This should
// only affect certain debug messages (e.g. messages printed
// from `rustc_middle::ty` during the computation of `tcx.predicates_of`),
// and should have no effect on any compiler output.
- if self.should_print_verbose() || NO_QUERIES.with(|q| q.get()) {
+ if self.should_print_verbose() {
+ // FIXME(eddyb) print this with `print_def_path`.
p!(write("Opaque({:?}, {:?})", def_id, substs));
return Ok(self);
}
let parent = self.tcx().parent(def_id);
match self.tcx().def_kind(parent) {
DefKind::TyAlias | DefKind::AssocTy => {
+ // NOTE: I know we should check for NO_QUERIES here, but it's alright.
+ // `type_of` on a type alias or assoc type should never cause a cycle.
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: d, .. }) =
*self.tcx().type_of(parent).kind()
{
p!(print_def_path(def_id, substs));
return Ok(self);
}
- _ => return self.pretty_print_opaque_impl_type(def_id, substs),
+ _ => {
+ if NO_QUERIES.with(|q| q.get()) {
+ p!(print_def_path(def_id, &[]));
+ return Ok(self);
+ } else {
+ return self.pretty_print_opaque_impl_type(def_id, substs);
+ }
+ }
}
}
ty::Str => p!("str"),
write!(self, "Sized")?;
}
- for re in lifetimes {
- write!(self, " + ")?;
- self = self.print_region(re)?;
+ if !FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+ for re in lifetimes {
+ write!(self, " + ")?;
+ self = self.print_region(re)?;
+ }
}
Ok(self)
return true;
}
+ if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+ return false;
+ }
+
let identify_regions = self.tcx.sess.opts.unstable_opts.identify_regions;
match *region {
} else {
let tcx = self.tcx;
+ let trim_path = FORCE_TRIMMED_PATH.with(|flag| flag.get());
// Closure used in `RegionFolder` to create names for anonymous late-bound
// regions. We use two `DebruijnIndex`es (one for the currently folded
// late-bound region and the other for the binder level) to determine
}
};
- start_or_continue(&mut self, "for<", ", ");
- do_continue(&mut self, name);
+ if !trim_path {
+ start_or_continue(&mut self, "for<", ", ");
+ do_continue(&mut self, name);
+ }
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind }))
};
let mut folder = RegionFolder {
};
let new_value = value.clone().skip_binder().fold_with(&mut folder);
let region_map = folder.region_map;
- start_or_continue(&mut self, "", "> ");
+ if !trim_path {
+ start_or_continue(&mut self, "", "> ");
+ }
(new_value, region_map)
};
}
}
-/// Helper for `TyCtxtEnsure` to avoid a closure.
-#[inline(always)]
-fn noop<T>(_: &T) {}
-
-/// Helper to ensure that queries only return `Copy` types.
-#[inline(always)]
-fn copy<T: Copy>(x: &T) -> T {
- *x
-}
-
macro_rules! query_helper_param_ty {
(DefId) => { impl IntoQueryParam<DefId> };
(LocalDefId) => { impl IntoQueryParam<LocalDefId> };
let key = key.into_query_param();
opt_remap_env_constness!([$($modifiers)*][key]);
- let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, noop);
-
- match cached {
- Ok(()) => return,
- Err(()) => (),
- }
-
- self.tcx.queries.$name(self.tcx, DUMMY_SP, key, QueryMode::Ensure);
+ match try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key) {
+ Some(_) => return,
+ None => self.tcx.queries.$name(self.tcx, DUMMY_SP, key, QueryMode::Ensure),
+ };
})*
}
let key = key.into_query_param();
opt_remap_env_constness!([$($modifiers)*][key]);
- let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, copy);
-
- match cached {
- Ok(value) => return value,
- Err(()) => (),
+ match try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key) {
+ Some(value) => value,
+ None => self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap(),
}
-
- self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap()
})*
}
let tcx = self.tcx;
let cache = &tcx.query_caches.$name;
- let cached = try_get_cached(tcx, cache, &key, copy);
-
- match cached {
- Ok(old) => {
+ match try_get_cached(tcx, cache, &key) {
+ Some(old) => {
bug!(
"Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
stringify!($name),
+ )
+ }
+ None => {
+ let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key);
+ let dep_node_index = tcx.dep_graph.with_feed_task(
+ dep_node,
+ tcx,
+ key,
+ &value,
+ hash_result!([$($modifiers)*]),
);
+ cache.complete(key, value, dep_node_index)
}
- Err(()) => (),
}
-
- let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key);
- let dep_node_index = tcx.dep_graph.with_feed_task(
- dep_node,
- tcx,
- key,
- &value,
- hash_result!([$($modifiers)*]),
- );
- cache.complete(key, value, dep_node_index)
}
})*
}
b = tcx.expand_abstract_consts(b);
}
+ debug!("{}.super_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b);
+
// Currently, the values that can be unified are primitive types,
// and those that derive both `PartialEq` and `Eq`, corresponding
// to structural-match types.
// FIXME(generic_const_exprs): is it possible to relate two consts which are not identical
// exprs? Should we care about that?
+ // FIXME(generic_const_exprs): relating the `ty()`s is a little weird since it is supposed to
+ // ICE If they mismatch. Unfortunately `ConstKind::Expr` is a little special and can be thought
+ // of as being generic over the argument types, however this is implicit so these types don't get
+ // related when we relate the substs of the item this const arg is for.
let expr = match (ae, be) {
- (Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br))
- if a_op == b_op && al.ty() == bl.ty() && ar.ty() == br.ty() =>
- {
+ (Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br)) if a_op == b_op => {
+ r.relate(al.ty(), bl.ty())?;
+ r.relate(ar.ty(), br.ty())?;
Expr::Binop(a_op, r.consts(al, bl)?, r.consts(ar, br)?)
}
- (Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv))
- if a_op == b_op && av.ty() == bv.ty() =>
- {
+ (Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv)) if a_op == b_op => {
+ r.relate(av.ty(), bv.ty())?;
Expr::UnOp(a_op, r.consts(av, bv)?)
}
- (Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt))
- if ak == bk && av.ty() == bv.ty() =>
- {
+ (Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt)) if ak == bk => {
+ r.relate(av.ty(), bv.ty())?;
Expr::Cast(ak, r.consts(av, bv)?, r.tys(at, bt)?)
}
(Expr::FunctionCall(af, aa), Expr::FunctionCall(bf, ba))
- if aa.len() == ba.len()
- && af.ty() == bf.ty()
- && aa
- .iter()
- .zip(ba.iter())
- .all(|(a_arg, b_arg)| a_arg.ty() == b_arg.ty()) =>
+ if aa.len() == ba.len() =>
{
+ r.relate(af.ty(), bf.ty())?;
let func = r.consts(af, bf)?;
let mut related_args = Vec::with_capacity(aa.len());
for (a_arg, b_arg) in aa.iter().zip(ba.iter()) {
crate::ty::AssocKind,
crate::ty::AliasKind,
crate::ty::Placeholder<crate::ty::BoundRegionKind>,
+ crate::ty::Placeholder<crate::ty::BoundTyKind>,
crate::ty::ClosureKind,
crate::ty::FreeRegion,
crate::ty::InferTy,
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub enum BoundTyKind {
- Anon,
- Param(Symbol),
+ Anon(u32),
+ Param(DefId, Symbol),
+}
+
+impl BoundTyKind {
+ pub fn expect_anon(self) -> u32 {
+ match self {
+ BoundTyKind::Anon(i) => i,
+ _ => bug!(),
+ }
+ }
}
impl From<BoundVar> for BoundTy {
fn from(var: BoundVar) -> Self {
- BoundTy { var, kind: BoundTyKind::Anon }
+ BoundTy { var, kind: BoundTyKind::Anon(var.as_u32()) }
}
}
cf.is_break()
}
+ /// Checks whether a type recursively contains any closure
+ ///
+ /// Example: `Option<[closure@file.rs:4:20]>` returns true
+ pub fn contains_closure(self) -> bool {
+ struct ContainsClosureVisitor;
+
+ impl<'tcx> TypeVisitor<'tcx> for ContainsClosureVisitor {
+ type BreakTy = ();
+
+ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+ if let ty::Closure(_, _) = t.kind() {
+ ControlFlow::Break(())
+ } else {
+ t.super_visit_with(self)
+ }
+ }
+ }
+
+ let cf = self.visit_with(&mut ContainsClosureVisitor);
+ cf.is_break()
+ }
+
/// Returns the type and mutability of `*ty`.
///
/// The parameter `explicit` indicates if this is an *explicit* dereference.
pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
self.node_type_opt(id).unwrap_or_else(|| {
- bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id)))
+ bug!("node_type: no type for node {}", tls::with(|tcx| tcx.hir().node_to_string(id)))
})
}
fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
ty::tls::with(|tcx| {
bug!(
- "node {} with HirId::owner {:?} cannot be placed in TypeckResults with hir_owner {:?}",
+ "node {} cannot be placed in TypeckResults with hir_owner {:?}",
tcx.hir().node_to_string(hir_id),
- hir_id.owner,
hir_owner
)
});
either = "1"
rustc_middle = { path = "../rustc_middle" }
rustc_apfloat = { path = "../rustc_apfloat" }
-rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_index = { path = "../rustc_index" }
rustc_errors = { path = "../rustc_errors" }
// We implicitly set the discriminant to 0. See
// librustc_mir/transform/deaggregator.rs for details.
let movability = movability.unwrap();
- Box::new(AggregateKind::Generator(closure_id, substs, movability))
+ Box::new(AggregateKind::Generator(
+ closure_id.to_def_id(),
+ substs,
+ movability,
+ ))
}
UpvarSubsts::Closure(substs) => {
- Box::new(AggregateKind::Closure(closure_id, substs))
+ Box::new(AggregateKind::Closure(closure_id.to_def_id(), substs))
}
};
block.and(Rvalue::Aggregate(result, operands))
let expr_ty = expr.ty;
let temp = {
let mut local_decl = LocalDecl::new(expr_ty, expr_span);
- if mutability == Mutability::Not {
+ if mutability.is_not() {
local_decl = local_decl.immutable();
}
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_serialize = { path = "../rustc_serialize" }
-rustc_session = { path = "../rustc_session" }
rustc_target = { path = "../rustc_target" }
rustc_span = { path = "../rustc_span" }
}
/// Invokes `f` on all direct fields of `ty`.
-fn iter_fields<'tcx>(
+pub fn iter_fields<'tcx>(
ty: Ty<'tcx>,
tcx: TyCtxt<'tcx>,
mut f: impl FnMut(Option<VariantIdx>, Field, Ty<'tcx>),
}
/// Returns all locals with projections that have their reference or address taken.
-fn excluded_locals(body: &Body<'_>) -> IndexVec<Local, bool> {
+pub fn excluded_locals(body: &Body<'_>) -> IndexVec<Local, bool> {
struct Collector {
result: IndexVec<Local, bool>,
}
+use rustc_errors::struct_span_err;
use rustc_middle::mir::visit::{PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::{self, TyCtxt};
-use rustc_session::lint::builtin::UNALIGNED_REFERENCES;
use crate::util;
use crate::MirLint;
// shouldn't do.
unreachable!();
} else {
- let source_info = self.source_info;
- let lint_root = self.body.source_scopes[source_info.scope]
- .local_data
- .as_ref()
- .assert_crate_local()
- .lint_root;
- self.tcx.struct_span_lint_hir(
- UNALIGNED_REFERENCES,
- lint_root,
- source_info.span,
- "reference to packed field is unaligned",
- |lint| {
- lint
- .note(
- "fields of packed structs are not properly aligned, and creating \
- a misaligned reference is undefined behavior (even if that \
- reference is never dereferenced)",
- )
- .help(
- "copy the field contents to a local variable, or replace the \
- reference with a raw pointer and use `read_unaligned`/`write_unaligned` \
- (loads and stores via `*p` must be properly aligned even when using raw pointers)"
- )
- },
- );
+ struct_span_err!(
+ self.tcx.sess,
+ self.source_info.span,
+ E0793,
+ "reference to packed field is unaligned"
+ )
+ .note(
+ "fields of packed structs are not properly aligned, and creating \
+ a misaligned reference is undefined behavior (even if that \
+ reference is never dereferenced)",
+ ).help(
+ "copy the field contents to a local variable, or replace the \
+ reference with a raw pointer and use `read_unaligned`/`write_unaligned` \
+ (loads and stores via `*p` must be properly aligned even when using raw pointers)"
+ )
+ .emit();
}
}
}
}
}
&AggregateKind::Closure(def_id, _) | &AggregateKind::Generator(def_id, _, _) => {
+ let def_id = def_id.expect_local();
let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } =
self.tcx.unsafety_check_result(def_id);
self.register_violations(violations, used_unsafe_blocks.iter().copied());
use either::Right;
-use rustc_ast::Mutability;
use rustc_const_eval::const_eval::CheckAlignment;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::DefKind;
}
// If the static allocation is mutable, then we can't const prop it as its content
// might be different at runtime.
- if alloc.inner().mutability == Mutability::Mut {
+ if alloc.inner().mutability.is_mut() {
throw_machine_stop_str!("can't access mutable globals in ConstProp");
}
let r = self.use_ecx(|this| this.ecx.read_immediate(&this.ecx.eval_operand(right, None)?));
let l = self.use_ecx(|this| this.ecx.read_immediate(&this.ecx.eval_operand(left, None)?));
// Check for exceeding shifts *even if* we cannot evaluate the LHS.
- if op == BinOp::Shr || op == BinOp::Shl {
+ if matches!(op, BinOp::Shr | BinOp::Shl) {
let r = r.clone()?;
// We need the type of the LHS. We cannot use `place_layout` as that is the type
// of the result, which for checked binops is not the same!
this.ecx.read_immediate(&this.ecx.eval_operand(left, None)?)
});
// Check for exceeding shifts *even if* we cannot evaluate the LHS.
- if op == BinOp::Shr || op == BinOp::Shl {
+ if matches!(op, BinOp::Shr | BinOp::Shl) {
let r = r.clone()?;
// We need the type of the LHS. We cannot use `place_layout` as that is the type
// of the result, which for checked binops is not the same!
}
fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, loc: Location) {
- if let StatementKind::StorageDead(l) = stmt.kind
- && self.storage_to_remove.contains(l)
- {
- stmt.make_nop();
- } else if let StatementKind::Assign(box (ref place, ref mut rvalue)) = stmt.kind
- && place.as_local().is_some()
- {
- // Do not replace assignments.
- self.visit_rvalue(rvalue, loc)
- } else {
- self.super_statement(stmt, loc);
+ match stmt.kind {
+ // When removing storage statements, we need to remove both (#107511).
+ StatementKind::StorageLive(l) | StatementKind::StorageDead(l)
+ if self.storage_to_remove.contains(l) =>
+ {
+ stmt.make_nop()
+ }
+ StatementKind::Assign(box (ref place, ref mut rvalue))
+ if place.as_local().is_some() =>
+ {
+ // Do not replace assignments.
+ self.visit_rvalue(rvalue, loc)
+ }
+ _ => self.super_statement(stmt, loc),
}
}
}
String::new()
},
self.format_operand(lhs),
- if op == Op::Add { "+" } else { "-" },
+ match op {
+ Op::Add => "+",
+ Op::Subtract => "-",
+ },
self.format_operand(rhs),
);
}
use rustc_const_eval::const_eval::CheckAlignment;
use rustc_const_eval::interpret::{ConstValue, ImmTy, Immediate, InterpCx, Scalar};
use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def::DefKind;
use rustc_middle::mir::visit::{MutVisitor, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty, TyCtxt};
state: &mut State<Self::Value>,
) {
match rvalue {
+ Rvalue::Aggregate(kind, operands) => {
+ let target = self.map().find(target.as_ref());
+ if let Some(target) = target {
+ state.flood_idx_with(target, self.map(), FlatSet::Bottom);
+ let field_based = match **kind {
+ AggregateKind::Tuple | AggregateKind::Closure(..) => true,
+ AggregateKind::Adt(def_id, ..) => {
+ matches!(self.tcx.def_kind(def_id), DefKind::Struct)
+ }
+ _ => false,
+ };
+ if field_based {
+ for (field_index, operand) in operands.iter().enumerate() {
+ if let Some(field) = self
+ .map()
+ .apply(target, TrackElem::Field(Field::from_usize(field_index)))
+ {
+ let result = self.handle_operand(operand, state);
+ state.assign_idx(field, result, self.map());
+ }
+ }
+ }
+ }
+ }
Rvalue::CheckedBinaryOp(op, box (left, right)) => {
let target = self.map().find(target.as_ref());
if let Some(target) = target {
+++ /dev/null
-use crate::util::expand_aggregate;
-use crate::MirPass;
-use rustc_middle::mir::*;
-use rustc_middle::ty::TyCtxt;
-
-pub struct Deaggregator;
-
-impl<'tcx> MirPass<'tcx> for Deaggregator {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
- let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
- for bb in basic_blocks {
- bb.expand_statements(|stmt| {
- // FIXME(eddyb) don't match twice on `stmt.kind` (post-NLL).
- match stmt.kind {
- // FIXME(#48193) Deaggregate arrays when it's cheaper to do so.
- StatementKind::Assign(box (
- _,
- Rvalue::Aggregate(box AggregateKind::Array(_), _),
- )) => {
- return None;
- }
- StatementKind::Assign(box (_, Rvalue::Aggregate(_, _))) => {}
- _ => return None,
- }
-
- let stmt = stmt.replace_nop();
- let source_info = stmt.source_info;
- let StatementKind::Assign(box (lhs, Rvalue::Aggregate(kind, operands))) = stmt.kind else {
- bug!();
- };
-
- Some(expand_aggregate(
- lhs,
- operands.into_iter().map(|op| {
- let ty = op.ty(&body.local_decls, tcx);
- (op, ty)
- }),
- *kind,
- source_info,
- tcx,
- ))
- });
- }
- }
-}
use crate::deref_separator::deref_finder;
use crate::simplify;
-use crate::util::expand_aggregate;
use crate::MirPass;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::pluralize;
assert_eq!(self.state_adt_ref.variant(idx).fields.len(), 0);
// FIXME(swatinem): assert that `val` is indeed unit?
- statements.extend(expand_aggregate(
- Place::return_place(),
- std::iter::empty(),
- kind,
+ statements.push(Statement {
+ kind: StatementKind::Assign(Box::new((
+ Place::return_place(),
+ Rvalue::Aggregate(Box::new(kind), vec![]),
+ ))),
source_info,
- self.tcx,
- ));
+ });
return;
}
// else: `Poll::Ready(x)`, `GeneratorState::Yielded(x)` or `GeneratorState::Complete(x)`
assert_eq!(self.state_adt_ref.variant(idx).fields.len(), 1);
- let ty = self
- .tcx
- .bound_type_of(self.state_adt_ref.variant(idx).fields[0].did)
- .subst(self.tcx, self.state_substs);
-
- statements.extend(expand_aggregate(
- Place::return_place(),
- std::iter::once((val, ty)),
- kind,
+ statements.push(Statement {
+ kind: StatementKind::Assign(Box::new((
+ Place::return_place(),
+ Rvalue::Aggregate(Box::new(kind), vec![val]),
+ ))),
source_info,
- self.tcx,
- ));
+ });
}
// Create a Place referencing a generator struct field
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::steal::Steal;
use rustc_hir as hir;
+use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_index::vec::IndexVec;
mod ctfe_limit;
mod dataflow_const_prop;
mod dead_store_elimination;
-mod deaggregator;
mod deduce_param_attrs;
mod deduplicate_blocks;
mod deref_separator;
return tcx.mir_drops_elaborated_and_const_checked(def);
}
- if tcx.generator_kind(def.did).is_some() && tcx.sess.opts.unstable_opts.drop_tracking_mir {
+ if tcx.sess.opts.unstable_opts.drop_tracking_mir
+ && let DefKind::Generator = tcx.def_kind(def.did)
+ {
tcx.ensure().mir_generator_witnesses(def.did);
}
let mir_borrowck = tcx.mir_borrowck_opt_const_arg(def);
&elaborate_box_derefs::ElaborateBoxDerefs,
&generator::StateTransform,
&add_retag::AddRetag,
- // Deaggregator is necessary for const prop. We may want to consider implementing
- // CTFE support for aggregates.
- &deaggregator::Deaggregator,
&Lint(const_prop_lint::ConstProp),
];
pm::run_passes_no_validate(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::Initial)));
&[
&reveal_all::RevealAll, // has to be done before inlining, since inlined code is in RevealAll mode.
&lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first
- &normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering
&unreachable_prop::UnreachablePropagation,
&uninhabited_enum_branching::UninhabitedEnumBranching,
&o1(simplify::SimplifyCfg::new("after-uninhabited-enum-branching")),
&inline::Inline,
&remove_storage_markers::RemoveStorageMarkers,
&remove_zsts::RemoveZsts,
+ &normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering
&const_goto::ConstGoto,
&remove_unneeded_drops::RemoveUnneededDrops,
&sroa::ScalarReplacementOfAggregates,
//! This pass eliminates casting of arrays into slices when their length
//! is taken using `.len()` method. Handy to preserve information in MIR for const prop
+use crate::ssa::SsaLocals;
use crate::MirPass;
-use rustc_data_structures::fx::FxIndexMap;
-use rustc_data_structures::intern::Interned;
-use rustc_index::bit_set::BitSet;
use rustc_index::vec::IndexVec;
+use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
-use rustc_middle::ty::{self, ReErased, Region, TyCtxt};
-
-const MAX_NUM_BLOCKS: usize = 800;
-const MAX_NUM_LOCALS: usize = 3000;
+use rustc_middle::ty::{self, TyCtxt};
+use rustc_mir_dataflow::impls::borrowed_locals;
pub struct NormalizeArrayLen;
impl<'tcx> MirPass<'tcx> for NormalizeArrayLen {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
- // See #105929
- sess.mir_opt_level() >= 4 && sess.opts.unstable_opts.unsound_mir_opts
+ sess.mir_opt_level() >= 3
}
+ #[instrument(level = "trace", skip(self, tcx, body))]
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
- // early returns for edge cases of highly unrolled functions
- if body.basic_blocks.len() > MAX_NUM_BLOCKS {
- return;
- }
- if body.local_decls.len() > MAX_NUM_LOCALS {
- return;
- }
+ debug!(def_id = ?body.source.def_id());
normalize_array_len_calls(tcx, body)
}
}
-pub fn normalize_array_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
- // We don't ever touch terminators, so no need to invalidate the CFG cache
- let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
- let local_decls = &mut body.local_decls;
+fn normalize_array_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+ let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+ let borrowed_locals = borrowed_locals(body);
+ let ssa = SsaLocals::new(tcx, param_env, body, &borrowed_locals);
- // do a preliminary analysis to see if we ever have locals of type `[T;N]` or `&[T;N]`
- let mut interesting_locals = BitSet::new_empty(local_decls.len());
- for (local, decl) in local_decls.iter_enumerated() {
- match decl.ty.kind() {
- ty::Array(..) => {
- interesting_locals.insert(local);
- }
- ty::Ref(.., ty, Mutability::Not) => match ty.kind() {
- ty::Array(..) => {
- interesting_locals.insert(local);
- }
- _ => {}
- },
- _ => {}
- }
- }
- if interesting_locals.is_empty() {
- // we have found nothing to analyze
- return;
- }
- let num_intesting_locals = interesting_locals.count();
- let mut state = FxIndexMap::with_capacity_and_hasher(num_intesting_locals, Default::default());
- let mut patches_scratchpad =
- FxIndexMap::with_capacity_and_hasher(num_intesting_locals, Default::default());
- let mut replacements_scratchpad =
- FxIndexMap::with_capacity_and_hasher(num_intesting_locals, Default::default());
- for block in basic_blocks {
- // make length calls for arrays [T; N] not to decay into length calls for &[T]
- // that forbids constant propagation
- normalize_array_len_call(
- tcx,
- block,
- local_decls,
- &interesting_locals,
- &mut state,
- &mut patches_scratchpad,
- &mut replacements_scratchpad,
- );
- state.clear();
- patches_scratchpad.clear();
- replacements_scratchpad.clear();
- }
-}
+ let slice_lengths = compute_slice_length(tcx, &ssa, body);
+ debug!(?slice_lengths);
-struct Patcher<'a, 'tcx> {
- tcx: TyCtxt<'tcx>,
- patches_scratchpad: &'a FxIndexMap<usize, usize>,
- replacements_scratchpad: &'a mut FxIndexMap<usize, Local>,
- local_decls: &'a mut IndexVec<Local, LocalDecl<'tcx>>,
- statement_idx: usize,
+ Replacer { tcx, slice_lengths }.visit_body_preserves_cfg(body);
}
-impl<'tcx> Patcher<'_, 'tcx> {
- fn patch_expand_statement(
- &mut self,
- statement: &mut Statement<'tcx>,
- ) -> Option<std::vec::IntoIter<Statement<'tcx>>> {
- let idx = self.statement_idx;
- if let Some(len_statemnt_idx) = self.patches_scratchpad.get(&idx).copied() {
- let mut statements = Vec::with_capacity(2);
-
- // we are at statement that performs a cast. The only sound way is
- // to create another local that performs a similar copy without a cast and then
- // use this copy in the Len operation
-
- match &statement.kind {
- StatementKind::Assign(box (
- ..,
- Rvalue::Cast(
- CastKind::Pointer(ty::adjustment::PointerCast::Unsize),
- operand,
- _,
- ),
- )) => {
- match operand {
- Operand::Copy(place) | Operand::Move(place) => {
- // create new local
- let ty = operand.ty(self.local_decls, self.tcx);
- let local_decl = LocalDecl::with_source_info(ty, statement.source_info);
- let local = self.local_decls.push(local_decl);
- // make it live
- let mut make_live_statement = statement.clone();
- make_live_statement.kind = StatementKind::StorageLive(local);
- statements.push(make_live_statement);
- // copy into it
-
- let operand = Operand::Copy(*place);
- let mut make_copy_statement = statement.clone();
- let assign_to = Place::from(local);
- let rvalue = Rvalue::Use(operand);
- make_copy_statement.kind =
- StatementKind::Assign(Box::new((assign_to, rvalue)));
- statements.push(make_copy_statement);
-
- // to reorder we have to copy and make NOP
- statements.push(statement.clone());
- statement.make_nop();
-
- self.replacements_scratchpad.insert(len_statemnt_idx, local);
- }
- _ => {
- unreachable!("it's a bug in the implementation")
- }
- }
- }
- _ => {
- unreachable!("it's a bug in the implementation")
+fn compute_slice_length<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ ssa: &SsaLocals,
+ body: &Body<'tcx>,
+) -> IndexVec<Local, Option<ty::Const<'tcx>>> {
+ let mut slice_lengths = IndexVec::from_elem(None, &body.local_decls);
+
+ for (local, rvalue) in ssa.assignments(body) {
+ match rvalue {
+ Rvalue::Cast(
+ CastKind::Pointer(ty::adjustment::PointerCast::Unsize),
+ operand,
+ cast_ty,
+ ) => {
+ let operand_ty = operand.ty(body, tcx);
+ debug!(?operand_ty);
+ if let Some(operand_ty) = operand_ty.builtin_deref(true)
+ && let ty::Array(_, len) = operand_ty.ty.kind()
+ && let Some(cast_ty) = cast_ty.builtin_deref(true)
+ && let ty::Slice(..) = cast_ty.ty.kind()
+ {
+ slice_lengths[local] = Some(*len);
}
}
-
- self.statement_idx += 1;
-
- Some(statements.into_iter())
- } else if let Some(local) = self.replacements_scratchpad.get(&idx).copied() {
- let mut statements = Vec::with_capacity(2);
-
- match &statement.kind {
- StatementKind::Assign(box (into, Rvalue::Len(place))) => {
- let add_deref = if let Some(..) = place.as_local() {
- false
- } else if let Some(..) = place.local_or_deref_local() {
- true
- } else {
- unreachable!("it's a bug in the implementation")
- };
- // replace len statement
- let mut len_statement = statement.clone();
- let mut place = Place::from(local);
- if add_deref {
- place = self.tcx.mk_place_deref(place);
- }
- len_statement.kind =
- StatementKind::Assign(Box::new((*into, Rvalue::Len(place))));
- statements.push(len_statement);
-
- // make temporary dead
- let mut make_dead_statement = statement.clone();
- make_dead_statement.kind = StatementKind::StorageDead(local);
- statements.push(make_dead_statement);
-
- // make original statement NOP
- statement.make_nop();
+ // The length information is stored in the fat pointer, so we treat `operand` as a value.
+ Rvalue::Use(operand) => {
+ if let Some(rhs) = operand.place() && let Some(rhs) = rhs.as_local() {
+ slice_lengths[local] = slice_lengths[rhs];
}
- _ => {
- unreachable!("it's a bug in the implementation")
+ }
+ // The length information is stored in the fat pointer.
+ // Reborrowing copies length information from one pointer to the other.
+ Rvalue::Ref(_, _, rhs) | Rvalue::AddressOf(_, rhs) => {
+ if let [PlaceElem::Deref] = rhs.projection[..] {
+ slice_lengths[local] = slice_lengths[rhs.local];
}
}
-
- self.statement_idx += 1;
-
- Some(statements.into_iter())
- } else {
- self.statement_idx += 1;
- None
+ _ => {}
}
}
+
+ slice_lengths
}
-fn normalize_array_len_call<'tcx>(
+struct Replacer<'tcx> {
tcx: TyCtxt<'tcx>,
- block: &mut BasicBlockData<'tcx>,
- local_decls: &mut IndexVec<Local, LocalDecl<'tcx>>,
- interesting_locals: &BitSet<Local>,
- state: &mut FxIndexMap<Local, usize>,
- patches_scratchpad: &mut FxIndexMap<usize, usize>,
- replacements_scratchpad: &mut FxIndexMap<usize, Local>,
-) {
- for (statement_idx, statement) in block.statements.iter_mut().enumerate() {
- match &mut statement.kind {
- StatementKind::Assign(box (place, rvalue)) => {
- match rvalue {
- Rvalue::Cast(
- CastKind::Pointer(ty::adjustment::PointerCast::Unsize),
- operand,
- cast_ty,
- ) => {
- let Some(local) = place.as_local() else { return };
- match operand {
- Operand::Copy(place) | Operand::Move(place) => {
- let Some(operand_local) = place.local_or_deref_local() else { return; };
- if !interesting_locals.contains(operand_local) {
- return;
- }
- let operand_ty = local_decls[operand_local].ty;
- match (operand_ty.kind(), cast_ty.kind()) {
- (ty::Array(of_ty_src, ..), ty::Slice(of_ty_dst)) => {
- if of_ty_src == of_ty_dst {
- // this is a cast from [T; N] into [T], so we are good
- state.insert(local, statement_idx);
- }
- }
- // current way of patching doesn't allow to work with `mut`
- (
- ty::Ref(
- Region(Interned(ReErased, _)),
- operand_ty,
- Mutability::Not,
- ),
- ty::Ref(
- Region(Interned(ReErased, _)),
- cast_ty,
- Mutability::Not,
- ),
- ) => {
- match (operand_ty.kind(), cast_ty.kind()) {
- // current way of patching doesn't allow to work with `mut`
- (ty::Array(of_ty_src, ..), ty::Slice(of_ty_dst)) => {
- if of_ty_src == of_ty_dst {
- // this is a cast from [T; N] into [T], so we are good
- state.insert(local, statement_idx);
- }
- }
- _ => {}
- }
- }
- _ => {}
- }
- }
- _ => {}
- }
- }
- Rvalue::Len(place) => {
- let Some(local) = place.local_or_deref_local() else {
- return;
- };
- if let Some(cast_statement_idx) = state.get(&local).copied() {
- patches_scratchpad.insert(cast_statement_idx, statement_idx);
- }
- }
- _ => {
- // invalidate
- state.remove(&place.local);
- }
- }
- }
- _ => {}
- }
- }
+ slice_lengths: IndexVec<Local, Option<ty::Const<'tcx>>>,
+}
- let mut patcher = Patcher {
- tcx,
- patches_scratchpad: &*patches_scratchpad,
- replacements_scratchpad,
- local_decls,
- statement_idx: 0,
- };
+impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
+ fn tcx(&self) -> TyCtxt<'tcx> {
+ self.tcx
+ }
- block.expand_statements(|st| patcher.patch_expand_statement(st));
+ fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, loc: Location) {
+ if let Rvalue::Len(place) = rvalue
+ && let [PlaceElem::Deref] = &place.projection[..]
+ && let Some(len) = self.slice_lengths[place.local]
+ {
+ *rvalue = Rvalue::Use(Operand::Constant(Box::new(Constant {
+ span: rustc_span::DUMMY_SP,
+ user_ty: None,
+ literal: ConstantKind::from_const(len, self.tcx),
+ })));
+ }
+ self.super_rvalue(rvalue, loc);
+ }
}
use std::fmt;
use std::iter;
-use crate::util::expand_aggregate;
use crate::{
abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, deref_separator,
pass_manager as pm, remove_noop_landing_pads, simplify,
fn make_place(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Place<'tcx> {
let span = self.span;
let mut local = LocalDecl::new(ty, span);
- if mutability == Mutability::Not {
+ if mutability.is_not() {
local = local.immutable();
}
Place::from(self.local_decls.push(local))
// return;
debug!("build_ctor: variant_index={:?}", variant_index);
- let statements = expand_aggregate(
- Place::return_place(),
- adt_def.variant(variant_index).fields.iter().enumerate().map(|(idx, field_def)| {
- (Operand::Move(Place::from(Local::new(idx + 1))), field_def.ty(tcx, substs))
- }),
- AggregateKind::Adt(adt_def.did(), variant_index, substs, None, None),
+ let kind = AggregateKind::Adt(adt_def.did(), variant_index, substs, None, None);
+ let variant = adt_def.variant(variant_index);
+ let statement = Statement {
+ kind: StatementKind::Assign(Box::new((
+ Place::return_place(),
+ Rvalue::Aggregate(
+ Box::new(kind),
+ (0..variant.fields.len())
+ .map(|idx| Operand::Move(Place::from(Local::new(idx + 1))))
+ .collect(),
+ ),
+ ))),
source_info,
- tcx,
- )
- .collect();
+ };
let start_block = BasicBlockData {
- statements,
+ statements: vec![statement],
terminator: Some(Terminator { source_info, kind: TerminatorKind::Return }),
is_cleanup: false,
};
use crate::MirPass;
-use rustc_data_structures::fx::{FxIndexMap, IndexEntry};
use rustc_index::bit_set::BitSet;
use rustc_index::vec::IndexVec;
+use rustc_middle::mir::patch::MirPatch;
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{Ty, TyCtxt};
+use rustc_mir_dataflow::value_analysis::{excluded_locals, iter_fields};
pub struct ScalarReplacementOfAggregates;
sess.mir_opt_level() >= 3
}
+ #[instrument(level = "debug", skip(self, tcx, body))]
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
- let escaping = escaping_locals(&*body);
- debug!(?escaping);
- let replacements = compute_flattening(tcx, body, escaping);
- debug!(?replacements);
- replace_flattened_locals(tcx, body, replacements);
+ debug!(def_id = ?body.source.def_id());
+ let mut excluded = excluded_locals(body);
+ loop {
+ debug!(?excluded);
+ let escaping = escaping_locals(&excluded, body);
+ debug!(?escaping);
+ let replacements = compute_flattening(tcx, body, escaping);
+ debug!(?replacements);
+ let all_dead_locals = replace_flattened_locals(tcx, body, replacements);
+ if !all_dead_locals.is_empty() {
+ for local in excluded.indices() {
+ excluded[local] |= all_dead_locals.contains(local);
+ }
+ excluded.raw.resize(body.local_decls.len(), false);
+ } else {
+ break;
+ }
+ }
}
}
/// Identify all locals that are not eligible for SROA.
///
/// There are 3 cases:
-/// - the aggegated local is used or passed to other code (function parameters and arguments);
+/// - the aggregated local is used or passed to other code (function parameters and arguments);
/// - the locals is a union or an enum;
/// - the local's address is taken, and thus the relative addresses of the fields are observable to
/// client code.
-fn escaping_locals(body: &Body<'_>) -> BitSet<Local> {
+fn escaping_locals(excluded: &IndexVec<Local, bool>, body: &Body<'_>) -> BitSet<Local> {
let mut set = BitSet::new_empty(body.local_decls.len());
set.insert_range(RETURN_PLACE..=Local::from_usize(body.arg_count));
for (local, decl) in body.local_decls().iter_enumerated() {
- if decl.ty.is_union() || decl.ty.is_enum() {
+ if decl.ty.is_union() || decl.ty.is_enum() || excluded[local] {
set.insert(local);
}
}
self.super_place(place, context, location);
}
- fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
- if let Rvalue::AddressOf(.., place) | Rvalue::Ref(.., place) = rvalue {
- if !place.is_indirect() {
- // Raw pointers may be used to access anything inside the enclosing place.
- self.set.insert(place.local);
- return;
+ fn visit_assign(
+ &mut self,
+ lvalue: &Place<'tcx>,
+ rvalue: &Rvalue<'tcx>,
+ location: Location,
+ ) {
+ if lvalue.as_local().is_some() {
+ match rvalue {
+ // Aggregate assignments are expanded in run_pass.
+ Rvalue::Aggregate(..) | Rvalue::Use(..) => {
+ self.visit_rvalue(rvalue, location);
+ return;
+ }
+ _ => {}
}
}
- self.super_rvalue(rvalue, location)
+ self.super_assign(lvalue, rvalue, location)
}
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
- if let StatementKind::StorageLive(..)
- | StatementKind::StorageDead(..)
- | StatementKind::Deinit(..) = statement.kind
- {
+ match statement.kind {
// Storage statements are expanded in run_pass.
- return;
+ StatementKind::StorageLive(..)
+ | StatementKind::StorageDead(..)
+ | StatementKind::Deinit(..) => return,
+ _ => self.super_statement(statement, location),
}
- self.super_statement(statement, location)
- }
-
- fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
- // Drop implicitly calls `drop_in_place`, which takes a `&mut`.
- // This implies that `Drop` implicitly takes the address of the place.
- if let TerminatorKind::Drop { place, .. }
- | TerminatorKind::DropAndReplace { place, .. } = terminator.kind
- {
- if !place.is_indirect() {
- // Raw pointers may be used to access anything inside the enclosing place.
- self.set.insert(place.local);
- return;
- }
- }
- self.super_terminator(terminator, location);
}
// We ignore anything that happens in debuginfo, since we expand it using
#[derive(Default, Debug)]
struct ReplacementMap<'tcx> {
- fields: FxIndexMap<PlaceRef<'tcx>, Local>,
+ /// Pre-computed list of all "new" locals for each "old" local. This is used to expand storage
+ /// and deinit statement and debuginfo.
+ fragments: IndexVec<Local, Option<IndexVec<Field, Option<(Ty<'tcx>, Local)>>>>,
+}
+
+impl<'tcx> ReplacementMap<'tcx> {
+ fn replace_place(&self, tcx: TyCtxt<'tcx>, place: PlaceRef<'tcx>) -> Option<Place<'tcx>> {
+ let &[PlaceElem::Field(f, _), ref rest @ ..] = place.projection else { return None; };
+ let fields = self.fragments[place.local].as_ref()?;
+ let (_, new_local) = fields[f]?;
+ Some(Place { local: new_local, projection: tcx.intern_place_elems(&rest) })
+ }
+
+ fn place_fragments(
+ &self,
+ place: Place<'tcx>,
+ ) -> Option<impl Iterator<Item = (Field, Ty<'tcx>, Local)> + '_> {
+ let local = place.as_local()?;
+ let fields = self.fragments[local].as_ref()?;
+ Some(fields.iter_enumerated().filter_map(|(field, &opt_ty_local)| {
+ let (ty, local) = opt_ty_local?;
+ Some((field, ty, local))
+ }))
+ }
}
/// Compute the replacement of flattened places into locals.
body: &mut Body<'tcx>,
escaping: BitSet<Local>,
) -> ReplacementMap<'tcx> {
- let mut visitor = PreFlattenVisitor {
- tcx,
- escaping,
- local_decls: &mut body.local_decls,
- map: Default::default(),
- };
- for (block, bbdata) in body.basic_blocks.iter_enumerated() {
- visitor.visit_basic_block_data(block, bbdata);
- }
- return visitor.map;
-
- struct PreFlattenVisitor<'tcx, 'll> {
- tcx: TyCtxt<'tcx>,
- local_decls: &'ll mut LocalDecls<'tcx>,
- escaping: BitSet<Local>,
- map: ReplacementMap<'tcx>,
- }
-
- impl<'tcx, 'll> PreFlattenVisitor<'tcx, 'll> {
- fn create_place(&mut self, place: PlaceRef<'tcx>) {
- if self.escaping.contains(place.local) {
- return;
- }
+ let mut fragments = IndexVec::from_elem(None, &body.local_decls);
- match self.map.fields.entry(place) {
- IndexEntry::Occupied(_) => {}
- IndexEntry::Vacant(v) => {
- let ty = place.ty(&*self.local_decls, self.tcx).ty;
- let local = self.local_decls.push(LocalDecl {
- ty,
- user_ty: None,
- ..self.local_decls[place.local].clone()
- });
- v.insert(local);
- }
- }
- }
- }
-
- impl<'tcx, 'll> Visitor<'tcx> for PreFlattenVisitor<'tcx, 'll> {
- fn visit_place(&mut self, place: &Place<'tcx>, _: PlaceContext, _: Location) {
- if let &[PlaceElem::Field(..), ..] = &place.projection[..] {
- let pr = PlaceRef { local: place.local, projection: &place.projection[..1] };
- self.create_place(pr)
- }
+ for local in body.local_decls.indices() {
+ if escaping.contains(local) {
+ continue;
}
+ let decl = body.local_decls[local].clone();
+ let ty = decl.ty;
+ iter_fields(ty, tcx, |variant, field, field_ty| {
+ if variant.is_some() {
+ // Downcasts are currently not supported.
+ return;
+ };
+ let new_local =
+ body.local_decls.push(LocalDecl { ty: field_ty, user_ty: None, ..decl.clone() });
+ fragments.get_or_insert_with(local, IndexVec::new).insert(field, (field_ty, new_local));
+ });
}
+ ReplacementMap { fragments }
}
/// Perform the replacement computed by `compute_flattening`.
tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>,
replacements: ReplacementMap<'tcx>,
-) {
+) -> BitSet<Local> {
let mut all_dead_locals = BitSet::new_empty(body.local_decls.len());
- for p in replacements.fields.keys() {
- all_dead_locals.insert(p.local);
+ for (local, replacements) in replacements.fragments.iter_enumerated() {
+ if replacements.is_some() {
+ all_dead_locals.insert(local);
+ }
}
debug!(?all_dead_locals);
if all_dead_locals.is_empty() {
- return;
+ return all_dead_locals;
}
- let mut fragments = IndexVec::new();
- for (k, v) in &replacements.fields {
- fragments.ensure_contains_elem(k.local, || Vec::new());
- fragments[k.local].push((k.projection, *v));
- }
- debug!(?fragments);
-
let mut visitor = ReplacementVisitor {
tcx,
local_decls: &body.local_decls,
- replacements,
+ replacements: &replacements,
all_dead_locals,
- fragments,
+ patch: MirPatch::new(body),
};
for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
visitor.visit_basic_block_data(bb, data);
for var_debug_info in &mut body.var_debug_info {
visitor.visit_var_debug_info(var_debug_info);
}
+ let ReplacementVisitor { patch, all_dead_locals, .. } = visitor;
+ patch.apply(body);
+ all_dead_locals
}
struct ReplacementVisitor<'tcx, 'll> {
/// This is only used to compute the type for `VarDebugInfoContents::Composite`.
local_decls: &'ll LocalDecls<'tcx>,
/// Work to do.
- replacements: ReplacementMap<'tcx>,
+ replacements: &'ll ReplacementMap<'tcx>,
/// This is used to check that we are not leaving references to replaced locals behind.
all_dead_locals: BitSet<Local>,
- /// Pre-computed list of all "new" locals for each "old" local. This is used to expand storage
- /// and deinit statement and debuginfo.
- fragments: IndexVec<Local, Vec<(&'tcx [PlaceElem<'tcx>], Local)>>,
+ patch: MirPatch<'tcx>,
}
-impl<'tcx, 'll> ReplacementVisitor<'tcx, 'll> {
- fn gather_debug_info_fragments(
- &self,
- place: PlaceRef<'tcx>,
- ) -> Vec<VarDebugInfoFragment<'tcx>> {
+impl<'tcx> ReplacementVisitor<'tcx, '_> {
+ fn gather_debug_info_fragments(&self, local: Local) -> Option<Vec<VarDebugInfoFragment<'tcx>>> {
let mut fragments = Vec::new();
- let parts = &self.fragments[place.local];
- for (proj, replacement_local) in parts {
- if proj.starts_with(place.projection) {
- fragments.push(VarDebugInfoFragment {
- projection: proj[place.projection.len()..].to_vec(),
- contents: Place::from(*replacement_local),
- });
- }
- }
- fragments
- }
-
- fn replace_place(&self, place: PlaceRef<'tcx>) -> Option<Place<'tcx>> {
- if let &[PlaceElem::Field(..), ref rest @ ..] = place.projection {
- let pr = PlaceRef { local: place.local, projection: &place.projection[..1] };
- let local = self.replacements.fields.get(&pr)?;
- Some(Place { local: *local, projection: self.tcx.intern_place_elems(&rest) })
- } else {
- None
+ let parts = self.replacements.place_fragments(local.into())?;
+ for (field, ty, replacement_local) in parts {
+ fragments.push(VarDebugInfoFragment {
+ projection: vec![PlaceElem::Field(field, ty)],
+ contents: Place::from(replacement_local),
+ });
}
+ Some(fragments)
}
}
self.tcx
}
- fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) {
- if let StatementKind::StorageLive(..)
- | StatementKind::StorageDead(..)
- | StatementKind::Deinit(..) = statement.kind
- {
- // Storage statements are expanded in run_pass.
- return;
- }
- self.super_statement(statement, location)
- }
-
fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
- if let Some(repl) = self.replace_place(place.as_ref()) {
+ if let Some(repl) = self.replacements.replace_place(self.tcx, place.as_ref()) {
*place = repl
} else {
self.super_place(place, context, location)
}
}
+ #[instrument(level = "trace", skip(self))]
+ fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) {
+ match statement.kind {
+ // Duplicate storage and deinit statements, as they pretty much apply to all fields.
+ StatementKind::StorageLive(l) => {
+ if let Some(final_locals) = self.replacements.place_fragments(l.into()) {
+ for (_, _, fl) in final_locals {
+ self.patch.add_statement(location, StatementKind::StorageLive(fl));
+ }
+ statement.make_nop();
+ }
+ return;
+ }
+ StatementKind::StorageDead(l) => {
+ if let Some(final_locals) = self.replacements.place_fragments(l.into()) {
+ for (_, _, fl) in final_locals {
+ self.patch.add_statement(location, StatementKind::StorageDead(fl));
+ }
+ statement.make_nop();
+ }
+ return;
+ }
+ StatementKind::Deinit(box place) => {
+ if let Some(final_locals) = self.replacements.place_fragments(place) {
+ for (_, _, fl) in final_locals {
+ self.patch
+ .add_statement(location, StatementKind::Deinit(Box::new(fl.into())));
+ }
+ statement.make_nop();
+ return;
+ }
+ }
+
+ // We have `a = Struct { 0: x, 1: y, .. }`.
+ // We replace it by
+ // ```
+ // a_0 = x
+ // a_1 = y
+ // ...
+ // ```
+ StatementKind::Assign(box (place, Rvalue::Aggregate(_, ref mut operands))) => {
+ if let Some(local) = place.as_local()
+ && let Some(final_locals) = &self.replacements.fragments[local]
+ {
+ // This is ok as we delete the statement later.
+ let operands = std::mem::take(operands);
+ for (&opt_ty_local, mut operand) in final_locals.iter().zip(operands) {
+ if let Some((_, new_local)) = opt_ty_local {
+ // Replace mentions of SROA'd locals that appear in the operand.
+ self.visit_operand(&mut operand, location);
+
+ let rvalue = Rvalue::Use(operand);
+ self.patch.add_statement(
+ location,
+ StatementKind::Assign(Box::new((new_local.into(), rvalue))),
+ );
+ }
+ }
+ statement.make_nop();
+ return;
+ }
+ }
+
+ // We have `a = some constant`
+ // We add the projections.
+ // ```
+ // a_0 = a.0
+ // a_1 = a.1
+ // ...
+ // ```
+ // ConstProp will pick up the pieces and replace them by actual constants.
+ StatementKind::Assign(box (place, Rvalue::Use(Operand::Constant(_)))) => {
+ if let Some(final_locals) = self.replacements.place_fragments(place) {
+ for (field, ty, new_local) in final_locals {
+ let rplace = self.tcx.mk_place_field(place, field, ty);
+ let rvalue = Rvalue::Use(Operand::Move(rplace));
+ self.patch.add_statement(
+ location,
+ StatementKind::Assign(Box::new((new_local.into(), rvalue))),
+ );
+ }
+ // We still need `place.local` to exist, so don't make it nop.
+ return;
+ }
+ }
+
+ // We have `a = move? place`
+ // We replace it by
+ // ```
+ // a_0 = move? place.0
+ // a_1 = move? place.1
+ // ...
+ // ```
+ StatementKind::Assign(box (lhs, Rvalue::Use(ref op))) => {
+ let (rplace, copy) = match *op {
+ Operand::Copy(rplace) => (rplace, true),
+ Operand::Move(rplace) => (rplace, false),
+ Operand::Constant(_) => bug!(),
+ };
+ if let Some(final_locals) = self.replacements.place_fragments(lhs) {
+ for (field, ty, new_local) in final_locals {
+ let rplace = self.tcx.mk_place_field(rplace, field, ty);
+ debug!(?rplace);
+ let rplace = self
+ .replacements
+ .replace_place(self.tcx, rplace.as_ref())
+ .unwrap_or(rplace);
+ debug!(?rplace);
+ let rvalue = if copy {
+ Rvalue::Use(Operand::Copy(rplace))
+ } else {
+ Rvalue::Use(Operand::Move(rplace))
+ };
+ self.patch.add_statement(
+ location,
+ StatementKind::Assign(Box::new((new_local.into(), rvalue))),
+ );
+ }
+ statement.make_nop();
+ return;
+ }
+ }
+
+ _ => {}
+ }
+ self.super_statement(statement, location)
+ }
+
+ #[instrument(level = "trace", skip(self))]
fn visit_var_debug_info(&mut self, var_debug_info: &mut VarDebugInfo<'tcx>) {
match &mut var_debug_info.value {
VarDebugInfoContents::Place(ref mut place) => {
- if let Some(repl) = self.replace_place(place.as_ref()) {
+ if let Some(repl) = self.replacements.replace_place(self.tcx, place.as_ref()) {
*place = repl;
- } else if self.all_dead_locals.contains(place.local) {
+ } else if let Some(local) = place.as_local()
+ && let Some(fragments) = self.gather_debug_info_fragments(local)
+ {
let ty = place.ty(self.local_decls, self.tcx).ty;
- let fragments = self.gather_debug_info_fragments(place.as_ref());
var_debug_info.value = VarDebugInfoContents::Composite { ty, fragments };
}
}
VarDebugInfoContents::Composite { ty: _, ref mut fragments } => {
let mut new_fragments = Vec::new();
+ debug!(?fragments);
fragments
.drain_filter(|fragment| {
- if let Some(repl) = self.replace_place(fragment.contents.as_ref()) {
+ if let Some(repl) =
+ self.replacements.replace_place(self.tcx, fragment.contents.as_ref())
+ {
fragment.contents = repl;
- true
- } else if self.all_dead_locals.contains(fragment.contents.local) {
- let frg = self.gather_debug_info_fragments(fragment.contents.as_ref());
+ false
+ } else if let Some(local) = fragment.contents.as_local()
+ && let Some(frg) = self.gather_debug_info_fragments(local)
+ {
new_fragments.extend(frg.into_iter().map(|mut f| {
f.projection.splice(0..0, fragment.projection.iter().copied());
f
}));
- false
- } else {
true
+ } else {
+ false
}
})
.for_each(drop);
+ debug!(?fragments);
+ debug!(?new_fragments);
fragments.extend(new_fragments);
}
VarDebugInfoContents::Const(_) => {}
}
}
- fn visit_basic_block_data(&mut self, bb: BasicBlock, bbdata: &mut BasicBlockData<'tcx>) {
- self.super_basic_block_data(bb, bbdata);
-
- #[derive(Debug)]
- enum Stmt {
- StorageLive,
- StorageDead,
- Deinit,
- }
-
- bbdata.expand_statements(|stmt| {
- let source_info = stmt.source_info;
- let (stmt, origin_local) = match &stmt.kind {
- StatementKind::StorageLive(l) => (Stmt::StorageLive, *l),
- StatementKind::StorageDead(l) => (Stmt::StorageDead, *l),
- StatementKind::Deinit(p) if let Some(l) = p.as_local() => (Stmt::Deinit, l),
- _ => return None,
- };
- if !self.all_dead_locals.contains(origin_local) {
- return None;
- }
- let final_locals = self.fragments.get(origin_local)?;
- Some(final_locals.iter().map(move |&(_, l)| {
- let kind = match stmt {
- Stmt::StorageLive => StatementKind::StorageLive(l),
- Stmt::StorageDead => StatementKind::StorageDead(l),
- Stmt::Deinit => StatementKind::Deinit(Box::new(l.into())),
- };
- Statement { source_info, kind }
- }))
- });
- }
-
fn visit_local(&mut self, local: &mut Local, _: PlaceContext, _: Location) {
assert!(!self.all_dead_locals.contains(*local));
}
use std::ops::Range;
use std::path::PathBuf;
-use crate::errors::{LargeAssignmentsLint, RecursionLimit, TypeLengthLimit};
+use crate::errors::{
+ EncounteredErrorWhileInstantiating, LargeAssignmentsLint, RecursionLimit, TypeLengthLimit,
+};
#[derive(PartialEq)]
pub enum MonoItemCollectionMode {
&& starting_point.node.is_user_defined()
{
let formatted_item = with_no_trimmed_paths!(starting_point.node.to_string());
- tcx.sess.span_note_without_error(
- starting_point.span,
- &format!("the above error was encountered while instantiating `{formatted_item}`"),
- );
+ tcx.sess.emit_note(EncounteredErrorWhileInstantiating {
+ span: starting_point.span,
+ formatted_item,
+ });
}
inlining_map.lock_mut().record_accesses(starting_point.node, &neighbors.items);
pub struct CouldntDumpMonoStats {
pub error: String,
}
+
+#[derive(Diagnostic)]
+#[diag(monomorphize_encountered_error_while_instantiating)]
+pub struct EncounteredErrorWhileInstantiating {
+ #[primary_span]
+ pub span: Span,
+ pub formatted_item: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(monomorphize_unknown_cgu_collection_mode)]
+pub struct UnknownCguCollectionMode<'a> {
+ pub mode: &'a str,
+}
use crate::collector::InliningMap;
use crate::collector::{self, MonoItemCollectionMode};
-use crate::errors::{CouldntDumpMonoStats, SymbolAlreadyDefined, UnknownPartitionStrategy};
+use crate::errors::{
+ CouldntDumpMonoStats, SymbolAlreadyDefined, UnknownCguCollectionMode, UnknownPartitionStrategy,
+};
pub struct PartitioningCx<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
partitioner.place_root_mono_items(cx, mono_items)
};
- initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx));
+ initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.create_size_estimate(tcx));
debug_dump(tcx, "INITIAL PARTITIONING:", initial_partitioning.codegen_units.iter());
partitioner.place_inlined_mono_items(cx, initial_partitioning)
};
- post_inlining.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx));
+ post_inlining.codegen_units.iter_mut().for_each(|cgu| cgu.create_size_estimate(tcx));
debug_dump(tcx, "POST INLINING:", post_inlining.codegen_units.iter());
fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[CodegenUnit<'_>]) {
let collection_mode = match tcx.sess.opts.unstable_opts.print_mono_items {
Some(ref s) => {
- let mode_string = s.to_lowercase();
- let mode_string = mode_string.trim();
- if mode_string == "eager" {
+ let mode = s.to_lowercase();
+ let mode = mode.trim();
+ if mode == "eager" {
MonoItemCollectionMode::Eager
} else {
- if mode_string != "lazy" {
- let message = format!(
- "Unknown codegen-item collection mode '{mode_string}'. \
- Falling back to 'lazy' mode."
- );
- tcx.sess.warn(&message);
+ if mode != "lazy" {
+ tcx.sess.emit_warning(UnknownCguCollectionMode { mode });
}
MonoItemCollectionMode::Lazy
+use std::borrow::Cow;
+
use rustc_ast::token::Token;
-use rustc_ast::Path;
+use rustc_ast::{Path, Visibility};
use rustc_errors::{fluent, AddToDiagnostic, Applicability, EmissionGuarantee, IntoDiagnostic};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_session::errors::ExprParenthesesNeeded;
+use rustc_span::edition::{Edition, LATEST_STABLE_EDITION};
use rustc_span::symbol::Ident;
use rustc_span::{Span, Symbol};
}
#[derive(Subdiagnostic)]
-#[help(parse_extra_if_in_let_else)]
+#[suggestion(parse_extra_if_in_let_else, applicability = "maybe-incorrect", code = "")]
pub(crate) struct IfExpressionLetSomeSub {
#[primary_span]
pub if_span: Span,
AddIn(#[primary_span] Span),
}
+#[derive(Diagnostic)]
+#[diag(parse_missing_expression_in_for_loop)]
+pub(crate) struct MissingExpressionInForLoop {
+ #[primary_span]
+ #[suggestion(
+ code = "/* expression */ ",
+ applicability = "has-placeholders",
+ style = "verbose"
+ )]
+ pub span: Span,
+}
+
#[derive(Diagnostic)]
#[diag(parse_missing_comma_after_match_arm)]
pub(crate) struct MissingCommaAfterMatchArm {
#[diag(parse_inclusive_range_match_arrow)]
pub(crate) struct InclusiveRangeMatchArrow {
#[primary_span]
+ pub arrow: Span,
+ #[label]
pub span: Span,
- #[suggestion(
- suggestion_add_space,
- style = "verbose",
- code = " ",
- applicability = "machine-applicable"
- )]
+ #[suggestion(style = "verbose", code = " ", applicability = "machine-applicable")]
pub after_pat: Span,
}
#[suggestion_part(code = "")]
pub right: Span,
}
+
+#[derive(Diagnostic)]
+#[diag(parse_async_fn_in_2015, code = "E0670")]
+pub(crate) struct AsyncFnIn2015 {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[subdiagnostic]
+ pub help: HelpUseLatestEdition,
+}
+
+#[derive(Subdiagnostic)]
+#[label(parse_async_block_in_2015)]
+pub(crate) struct AsyncBlockIn2015 {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_self_argument_pointer)]
+pub(crate) struct SelfArgumentPointer {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_visibility_not_followed_by_item)]
+#[help]
+pub(crate) struct VisibilityNotFollowedByItem {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub vis: Visibility,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_default_not_followed_by_item)]
+#[note]
+pub(crate) struct DefaultNotFollowedByItem {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+pub(crate) enum MissingKeywordForItemDefinition {
+ #[diag(parse_missing_struct_for_struct_definition)]
+ Struct {
+ #[primary_span]
+ #[suggestion(style = "short", applicability = "maybe-incorrect", code = " struct ")]
+ span: Span,
+ ident: Ident,
+ },
+ #[diag(parse_missing_fn_for_function_definition)]
+ Function {
+ #[primary_span]
+ #[suggestion(style = "short", applicability = "maybe-incorrect", code = " fn ")]
+ span: Span,
+ ident: Ident,
+ },
+ #[diag(parse_missing_fn_for_method_definition)]
+ Method {
+ #[primary_span]
+ #[suggestion(style = "short", applicability = "maybe-incorrect", code = " fn ")]
+ span: Span,
+ ident: Ident,
+ },
+ #[diag(parse_ambiguous_missing_keyword_for_item_definition)]
+ Ambiguous {
+ #[primary_span]
+ span: Span,
+ #[subdiagnostic]
+ subdiag: Option<AmbiguousMissingKwForItemSub>,
+ },
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum AmbiguousMissingKwForItemSub {
+ #[suggestion(suggestion, applicability = "maybe-incorrect", code = "{snippet}!")]
+ SuggestMacro {
+ #[primary_span]
+ span: Span,
+ snippet: String,
+ },
+ #[help(help)]
+ HelpMacro,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_missing_trait_in_trait_impl)]
+pub(crate) struct MissingTraitInTraitImpl {
+ #[primary_span]
+ #[suggestion(suggestion_add_trait, code = " Trait ", applicability = "has-placeholders")]
+ pub span: Span,
+ #[suggestion(suggestion_remove_for, code = "", applicability = "maybe-incorrect")]
+ pub for_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_missing_for_in_trait_impl)]
+pub(crate) struct MissingForInTraitImpl {
+ #[primary_span]
+ #[suggestion(style = "short", code = " for ", applicability = "machine-applicable")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_expected_trait_in_trait_impl_found_type)]
+pub(crate) struct ExpectedTraitInTraitImplFoundType {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_bounds_not_allowed_on_trait_aliases)]
+pub(crate) struct BoundsNotAllowedOnTraitAliases {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_trait_alias_cannot_be_auto)]
+pub(crate) struct TraitAliasCannotBeAuto {
+ #[primary_span]
+ #[label(parse_trait_alias_cannot_be_auto)]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_trait_alias_cannot_be_unsafe)]
+pub(crate) struct TraitAliasCannotBeUnsafe {
+ #[primary_span]
+ #[label(parse_trait_alias_cannot_be_unsafe)]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_associated_static_item_not_allowed)]
+pub(crate) struct AssociatedStaticItemNotAllowed {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_extern_crate_name_with_dashes)]
+pub(crate) struct ExternCrateNameWithDashes {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[subdiagnostic]
+ pub sugg: ExternCrateNameWithDashesSugg,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+pub(crate) struct ExternCrateNameWithDashesSugg {
+ #[suggestion_part(code = "_")]
+ pub dashes: Vec<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_extern_item_cannot_be_const)]
+#[note]
+pub(crate) struct ExternItemCannotBeConst {
+ #[primary_span]
+ pub ident_span: Span,
+ #[suggestion(code = "static ", applicability = "machine-applicable")]
+ pub const_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_const_global_cannot_be_mutable)]
+pub(crate) struct ConstGlobalCannotBeMutable {
+ #[primary_span]
+ #[label]
+ pub ident_span: Span,
+ #[suggestion(code = "static", applicability = "maybe-incorrect")]
+ pub const_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_missing_const_type)]
+pub(crate) struct MissingConstType {
+ #[primary_span]
+ #[suggestion(code = "{colon} <type>", applicability = "has-placeholders")]
+ pub span: Span,
+
+ pub kind: &'static str,
+ pub colon: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_enum_struct_mutually_exclusive)]
+pub(crate) struct EnumStructMutuallyExclusive {
+ #[primary_span]
+ #[suggestion(code = "enum", applicability = "machine-applicable")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+pub(crate) enum UnexpectedTokenAfterStructName {
+ #[diag(parse_unexpected_token_after_struct_name_found_reserved_identifier)]
+ ReservedIdentifier {
+ #[primary_span]
+ #[label(parse_unexpected_token_after_struct_name)]
+ span: Span,
+ token: Token,
+ },
+ #[diag(parse_unexpected_token_after_struct_name_found_keyword)]
+ Keyword {
+ #[primary_span]
+ #[label(parse_unexpected_token_after_struct_name)]
+ span: Span,
+ token: Token,
+ },
+ #[diag(parse_unexpected_token_after_struct_name_found_reserved_keyword)]
+ ReservedKeyword {
+ #[primary_span]
+ #[label(parse_unexpected_token_after_struct_name)]
+ span: Span,
+ token: Token,
+ },
+ #[diag(parse_unexpected_token_after_struct_name_found_doc_comment)]
+ DocComment {
+ #[primary_span]
+ #[label(parse_unexpected_token_after_struct_name)]
+ span: Span,
+ token: Token,
+ },
+ #[diag(parse_unexpected_token_after_struct_name_found_other)]
+ Other {
+ #[primary_span]
+ #[label(parse_unexpected_token_after_struct_name)]
+ span: Span,
+ token: Token,
+ },
+}
+
+impl UnexpectedTokenAfterStructName {
+ pub fn new(span: Span, token: Token) -> Self {
+ match TokenDescription::from_token(&token) {
+ Some(TokenDescription::ReservedIdentifier) => Self::ReservedIdentifier { span, token },
+ Some(TokenDescription::Keyword) => Self::Keyword { span, token },
+ Some(TokenDescription::ReservedKeyword) => Self::ReservedKeyword { span, token },
+ Some(TokenDescription::DocComment) => Self::DocComment { span, token },
+ None => Self::Other { span, token },
+ }
+ }
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_unexpected_self_in_generic_parameters)]
+#[note]
+pub(crate) struct UnexpectedSelfInGenericParameters {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_unexpected_default_value_for_lifetime_in_generic_parameters)]
+pub(crate) struct UnexpectedDefaultValueForLifetimeInGenericParameters {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_multiple_where_clauses)]
+pub(crate) struct MultipleWhereClauses {
+ #[primary_span]
+ pub span: Span,
+ #[label]
+ pub previous: Span,
+ #[suggestion(style = "verbose", code = ",", applicability = "maybe-incorrect")]
+ pub between: Span,
+}
+
+#[derive(Diagnostic)]
+pub(crate) enum UnexpectedNonterminal {
+ #[diag(parse_nonterminal_expected_item_keyword)]
+ Item(#[primary_span] Span),
+ #[diag(parse_nonterminal_expected_statement)]
+ Statement(#[primary_span] Span),
+ #[diag(parse_nonterminal_expected_ident)]
+ Ident {
+ #[primary_span]
+ span: Span,
+ token: Token,
+ },
+ #[diag(parse_nonterminal_expected_lifetime)]
+ Lifetime {
+ #[primary_span]
+ span: Span,
+ token: Token,
+ },
+}
+
+#[derive(Diagnostic)]
+pub(crate) enum TopLevelOrPatternNotAllowed {
+ #[diag(parse_or_pattern_not_allowed_in_let_binding)]
+ LetBinding {
+ #[primary_span]
+ span: Span,
+ #[subdiagnostic]
+ sub: Option<TopLevelOrPatternNotAllowedSugg>,
+ },
+ #[diag(parse_or_pattern_not_allowed_in_fn_parameters)]
+ FunctionParameter {
+ #[primary_span]
+ span: Span,
+ #[subdiagnostic]
+ sub: Option<TopLevelOrPatternNotAllowedSugg>,
+ },
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum TopLevelOrPatternNotAllowedSugg {
+ #[suggestion(
+ parse_sugg_remove_leading_vert_in_pattern,
+ code = "{pat}",
+ applicability = "machine-applicable"
+ )]
+ RemoveLeadingVert {
+ #[primary_span]
+ span: Span,
+ pat: String,
+ },
+ #[suggestion(
+ parse_sugg_wrap_pattern_in_parens,
+ code = "({pat})",
+ applicability = "machine-applicable"
+ )]
+ WrapInParens {
+ #[primary_span]
+ span: Span,
+ pat: String,
+ },
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_unexpected_vert_vert_before_function_parameter)]
+#[note(parse_note_pattern_alternatives_use_single_vert)]
+pub(crate) struct UnexpectedVertVertBeforeFunctionParam {
+ #[primary_span]
+ #[suggestion(code = "", applicability = "machine-applicable")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_unexpected_vert_vert_in_pattern)]
+pub(crate) struct UnexpectedVertVertInPattern {
+ #[primary_span]
+ #[suggestion(code = "|", applicability = "machine-applicable")]
+ pub span: Span,
+ #[label(parse_label_while_parsing_or_pattern_here)]
+ pub start: Option<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_trailing_vert_not_allowed)]
+pub(crate) struct TrailingVertNotAllowed {
+ #[primary_span]
+ #[suggestion(code = "", applicability = "machine-applicable")]
+ pub span: Span,
+ #[label(parse_label_while_parsing_or_pattern_here)]
+ pub start: Option<Span>,
+ pub token: Token,
+ #[note(parse_note_pattern_alternatives_use_single_vert)]
+ pub note_double_vert: Option<()>,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_dotdotdot_rest_pattern)]
+pub(crate) struct DotDotDotRestPattern {
+ #[primary_span]
+ #[suggestion(style = "short", code = "..", applicability = "machine-applicable")]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_pattern_on_wrong_side_of_at)]
+pub(crate) struct PatternOnWrongSideOfAt {
+ #[primary_span]
+ #[suggestion(code = "{whole_pat}", applicability = "machine-applicable")]
+ pub whole_span: Span,
+ pub whole_pat: String,
+ #[label(label_pattern)]
+ pub pattern: Span,
+ #[label(label_binding)]
+ pub binding: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_expected_binding_left_of_at)]
+#[note]
+pub(crate) struct ExpectedBindingLeftOfAt {
+ #[primary_span]
+ pub whole_span: Span,
+ #[label(label_lhs)]
+ pub lhs: Span,
+ #[label(label_rhs)]
+ pub rhs: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_ambiguous_range_pattern)]
+pub(crate) struct AmbiguousRangePattern {
+ #[primary_span]
+ #[suggestion(code = "({pat})", applicability = "maybe-incorrect")]
+ pub span: Span,
+ pub pat: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_unexpected_lifetime_in_pattern)]
+pub(crate) struct UnexpectedLifetimeInPattern {
+ #[primary_span]
+ #[suggestion(code = "", applicability = "machine-applicable")]
+ pub span: Span,
+ pub symbol: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_ref_mut_order_incorrect)]
+pub(crate) struct RefMutOrderIncorrect {
+ #[primary_span]
+ #[suggestion(code = "ref mut", applicability = "machine-applicable")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+pub(crate) enum InvalidMutInPattern {
+ #[diag(parse_mut_on_nested_ident_pattern)]
+ #[note(parse_note_mut_pattern_usage)]
+ NestedIdent {
+ #[primary_span]
+ #[suggestion(code = "{pat}", applicability = "machine-applicable")]
+ span: Span,
+ pat: String,
+ },
+ #[diag(parse_mut_on_non_ident_pattern)]
+ #[note(parse_note_mut_pattern_usage)]
+ NonIdent {
+ #[primary_span]
+ #[suggestion(code = "{pat}", applicability = "machine-applicable")]
+ span: Span,
+ pat: String,
+ },
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_repeated_mut_in_pattern)]
+pub(crate) struct RepeatedMutInPattern {
+ #[primary_span]
+ #[suggestion(code = "", applicability = "machine-applicable")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_dot_dot_dot_range_to_pattern_not_allowed)]
+pub(crate) struct DotDotDotRangeToPatternNotAllowed {
+ #[primary_span]
+ #[suggestion(style = "short", code = "..=", applicability = "machine-applicable")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_enum_pattern_instead_of_identifier)]
+pub(crate) struct EnumPatternInsteadOfIdentifier {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_dot_dot_dot_for_remaining_fields)]
+pub(crate) struct DotDotDotForRemainingFields {
+ #[primary_span]
+ #[suggestion(code = "..", style = "verbose", applicability = "machine-applicable")]
+ pub span: Span,
+ pub token_str: Cow<'static, str>,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_expected_comma_after_pattern_field)]
+pub(crate) struct ExpectedCommaAfterPatternField {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_return_types_use_thin_arrow)]
+pub(crate) struct ReturnTypesUseThinArrow {
+ #[primary_span]
+ #[suggestion(style = "short", code = "->", applicability = "machine-applicable")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_need_plus_after_trait_object_lifetime)]
+pub(crate) struct NeedPlusAfterTraitObjectLifetime {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_expected_mut_or_const_in_raw_pointer_type)]
+pub(crate) struct ExpectedMutOrConstInRawPointerType {
+ #[primary_span]
+ pub span: Span,
+ #[suggestion(code("mut ", "const "), applicability = "has-placeholders")]
+ pub after_asterisk: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_lifetime_after_mut)]
+pub(crate) struct LifetimeAfterMut {
+ #[primary_span]
+ pub span: Span,
+ #[suggestion(code = "&{snippet} mut", applicability = "maybe-incorrect")]
+ pub suggest_lifetime: Option<Span>,
+ pub snippet: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_dyn_after_mut)]
+pub(crate) struct DynAfterMut {
+ #[primary_span]
+ #[suggestion(code = "&mut dyn", applicability = "machine-applicable")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_fn_pointer_cannot_be_const)]
+pub(crate) struct FnPointerCannotBeConst {
+ #[primary_span]
+ pub span: Span,
+ #[suggestion(code = "", applicability = "maybe-incorrect")]
+ #[label]
+ pub qualifier: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_fn_pointer_cannot_be_async)]
+pub(crate) struct FnPointerCannotBeAsync {
+ #[primary_span]
+ pub span: Span,
+ #[suggestion(code = "", applicability = "maybe-incorrect")]
+ #[label]
+ pub qualifier: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_nested_c_variadic_type, code = "E0743")]
+pub(crate) struct NestedCVariadicType {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_invalid_dyn_keyword)]
+#[help]
+pub(crate) struct InvalidDynKeyword {
+ #[primary_span]
+ #[suggestion(code = "", applicability = "machine-applicable")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_negative_bounds_not_supported)]
+pub(crate) struct NegativeBoundsNotSupported {
+ #[primary_span]
+ pub negative_bounds: Vec<Span>,
+ #[label]
+ pub last_span: Span,
+ #[subdiagnostic]
+ pub sub: Option<NegativeBoundsNotSupportedSugg>,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+ suggestion,
+ style = "tool-only",
+ code = "{fixed}",
+ applicability = "machine-applicable"
+)]
+pub(crate) struct NegativeBoundsNotSupportedSugg {
+ #[primary_span]
+ pub bound_list: Span,
+ pub num_bounds: usize,
+ pub fixed: String,
+}
+
+#[derive(Subdiagnostic)]
+pub enum HelpUseLatestEdition {
+ #[help(parse_help_set_edition_cargo)]
+ #[note(parse_note_edition_guide)]
+ Cargo { edition: Edition },
+ #[help(parse_help_set_edition_standalone)]
+ #[note(parse_note_edition_guide)]
+ Standalone { edition: Edition },
+}
+
+impl HelpUseLatestEdition {
+ pub fn new() -> Self {
+ let edition = LATEST_STABLE_EDITION;
+ if std::env::var_os("CARGO").is_some() {
+ Self::Cargo { edition }
+ } else {
+ Self::Standalone { edition }
+ }
+ }
+}
use rustc_data_structures::static_assert_size;
// tidy-alphabetical-start
static_assert_size!(AttrWrapper, 16);
- static_assert_size!(LazyAttrTokenStreamImpl, 144);
+ static_assert_size!(LazyAttrTokenStreamImpl, 120);
// tidy-alphabetical-end
}
}
pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (P<ast::Pat>, P<ast::Ty>)> {
- let pat = self.parse_pat_no_top_alt(Some("argument name"))?;
+ let pat = self.parse_pat_no_top_alt(Some(Expected::ArgumentName))?;
self.expect(&token::Colon)?;
let ty = self.parse_ty()?;
/// Some special error handling for the "top-level" patterns in a match arm,
/// `for` loop, `let`, &c. (in contrast to subpatterns within such).
- pub(crate) fn maybe_recover_colon_colon_in_pat_typo_or_anon_enum(
+ pub(crate) fn maybe_recover_colon_colon_in_pat_typo(
&mut self,
mut first_pat: P<Pat>,
- expected: Expected,
+ expected: Option<Expected>,
) -> P<Pat> {
if token::Colon != self.token.kind {
return first_pat;
// Create error for "unexpected `:`".
match self.expected_one_of_not_found(&[], &[]) {
Err(mut err) => {
- snapshot_pat.bump(); // Skip the `:`.
- snapshot_type.bump(); // Skip the `:`.
+ // Skip the `:`.
+ snapshot_pat.bump();
+ snapshot_type.bump();
match snapshot_pat.parse_pat_no_top_alt(expected) {
Err(inner_err) => {
inner_err.cancel();
use super::diagnostics::SnapshotParser;
-use super::pat::{CommaRecoveryMode, RecoverColon, RecoverComma, PARAM_EXPECTED};
+use super::pat::{CommaRecoveryMode, Expected, RecoverColon, RecoverComma};
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{
AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions,
SemiColonMode, SeqSep, TokenExpectType, TokenType, TrailingToken,
};
-use crate::errors::{
- ArrayBracketsInsteadOfSpaces, ArrayBracketsInsteadOfSpacesSugg, AsyncMoveOrderIncorrect,
- BracesForStructLiteral, CatchAfterTry, CommaAfterBaseStruct, ComparisonInterpretedAsGeneric,
- ComparisonOrShiftInterpretedAsGenericSugg, DoCatchSyntaxRemoved, DotDotDot, EqFieldInit,
- ExpectedElseBlock, ExpectedEqForLetExpr, ExpectedExpressionFoundLet,
- FieldExpressionWithGeneric, FloatLiteralRequiresIntegerPart, FoundExprWouldBeStmt,
- IfExpressionLetSomeSub, IfExpressionMissingCondition, IfExpressionMissingThenBlock,
- IfExpressionMissingThenBlockSub, InvalidBlockMacroSegment, InvalidComparisonOperator,
- InvalidComparisonOperatorSub, InvalidInterpolatedExpression, InvalidLiteralSuffixOnTupleIndex,
- InvalidLogicalOperator, InvalidLogicalOperatorSub, LabeledLoopInBreak, LeadingPlusNotSupported,
- LeftArrowOperator, LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath,
- MalformedLoopLabel, MatchArmBodyWithoutBraces, MatchArmBodyWithoutBracesSugg,
- MissingCommaAfterMatchArm, MissingDotDot, MissingInInForLoop, MissingInInForLoopSub,
- MissingSemicolonBeforeArray, NoFieldsForFnCall, NotAsNegationOperator,
- NotAsNegationOperatorSub, OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields,
- RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, StructLiteralNotAllowedHere,
- StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, UnexpectedIfWithIf,
- UnexpectedTokenAfterLabel, UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses,
-};
+use crate::errors;
use crate::maybe_recover_from_interpolated_ty_qpath;
use core::mem;
use rustc_ast::ptr::P;
use rustc_ast::{ClosureBinder, MetaItemLit, StmtKind};
use rustc_ast_pretty::pprust;
use rustc_errors::{
- Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult,
- StashKey,
+ AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic,
+ PResult, StashKey,
};
use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded};
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
}
.into();
let invalid = format!("{}=", &sugg);
- self.sess.emit_err(InvalidComparisonOperator {
+ self.sess.emit_err(errors::InvalidComparisonOperator {
span: sp,
invalid: invalid.clone(),
- sub: InvalidComparisonOperatorSub::Correctable {
+ sub: errors::InvalidComparisonOperatorSub::Correctable {
span: sp,
invalid,
correct: sugg,
&& self.prev_token.span.hi() == self.token.span.lo()
{
let sp = op.span.to(self.token.span);
- self.sess.emit_err(InvalidComparisonOperator {
+ self.sess.emit_err(errors::InvalidComparisonOperator {
span: sp,
invalid: "<>".into(),
- sub: InvalidComparisonOperatorSub::Correctable {
+ sub: errors::InvalidComparisonOperatorSub::Correctable {
span: sp,
invalid: "<>".into(),
correct: "!=".into(),
&& self.prev_token.span.hi() == self.token.span.lo()
{
let sp = op.span.to(self.token.span);
- self.sess.emit_err(InvalidComparisonOperator {
+ self.sess.emit_err(errors::InvalidComparisonOperator {
span: sp,
invalid: "<=>".into(),
- sub: InvalidComparisonOperatorSub::Spaceship(sp),
+ sub: errors::InvalidComparisonOperatorSub::Spaceship(sp),
});
self.bump();
}
/// but the next token implies this should be parsed as an expression.
/// For example: `if let Some(x) = x { x } else { 0 } / 2`.
fn error_found_expr_would_be_stmt(&self, lhs: &Expr) {
- self.sess.emit_err(FoundExprWouldBeStmt {
+ self.sess.emit_err(errors::FoundExprWouldBeStmt {
span: self.token.span,
token: self.token.clone(),
suggestion: ExprParenthesesNeeded::surrounding(lhs.span),
}
(Some(op), _) => (op, self.token.span),
(None, Some((Ident { name: sym::and, span }, false))) if self.may_recover() => {
- self.sess.emit_err(InvalidLogicalOperator {
+ self.sess.emit_err(errors::InvalidLogicalOperator {
span: self.token.span,
incorrect: "and".into(),
- sub: InvalidLogicalOperatorSub::Conjunction(self.token.span),
+ sub: errors::InvalidLogicalOperatorSub::Conjunction(self.token.span),
});
(AssocOp::LAnd, span)
}
(None, Some((Ident { name: sym::or, span }, false))) if self.may_recover() => {
- self.sess.emit_err(InvalidLogicalOperator {
+ self.sess.emit_err(errors::InvalidLogicalOperator {
span: self.token.span,
incorrect: "or".into(),
- sub: InvalidLogicalOperatorSub::Disjunction(self.token.span),
+ sub: errors::InvalidLogicalOperatorSub::Disjunction(self.token.span),
});
(AssocOp::LOr, span)
}
}
// `+lit`
token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => {
- let mut err =
- LeadingPlusNotSupported { span: lo, remove_plus: None, add_parentheses: None };
+ let mut err = errors::LeadingPlusNotSupported {
+ span: lo,
+ remove_plus: None,
+ add_parentheses: None,
+ };
// a block on the LHS might have been intended to be an expression instead
if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) {
/// Recover on `~expr` in favor of `!expr`.
fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
- self.sess.emit_err(TildeAsUnaryOperator(lo));
+ self.sess.emit_err(errors::TildeAsUnaryOperator(lo));
self.parse_unary_expr(lo, UnOp::Not)
}
let negated_token = self.look_ahead(1, |t| t.clone());
let sub_diag = if negated_token.is_numeric_lit() {
- NotAsNegationOperatorSub::SuggestNotBitwise
+ errors::NotAsNegationOperatorSub::SuggestNotBitwise
} else if negated_token.is_bool_lit() {
- NotAsNegationOperatorSub::SuggestNotLogical
+ errors::NotAsNegationOperatorSub::SuggestNotLogical
} else {
- NotAsNegationOperatorSub::SuggestNotDefault
+ errors::NotAsNegationOperatorSub::SuggestNotDefault
};
- self.sess.emit_err(NotAsNegationOperator {
+ self.sess.emit_err(errors::NotAsNegationOperator {
negated: negated_token.span,
negated_desc: super::token_descr(&negated_token),
// Span the `not` plus trailing whitespace to avoid
match self.parse_labeled_expr(label, false) {
Ok(expr) => {
type_err.cancel();
- self.sess.emit_err(MalformedLoopLabel {
+ self.sess.emit_err(errors::MalformedLoopLabel {
span: label.ident.span,
correct_label: label.ident,
});
);
let args_span = self.look_ahead(1, |t| t.span).to(span_after_type);
- let suggestion = ComparisonOrShiftInterpretedAsGenericSugg {
+ let suggestion = errors::ComparisonOrShiftInterpretedAsGenericSugg {
left: expr.span.shrink_to_lo(),
right: expr.span.shrink_to_hi(),
};
match self.token.kind {
- token::Lt => self.sess.emit_err(ComparisonInterpretedAsGeneric {
- comparison: self.token.span,
- r#type: path,
- args: args_span,
- suggestion,
- }),
+ token::Lt => {
+ self.sess.emit_err(errors::ComparisonInterpretedAsGeneric {
+ comparison: self.token.span,
+ r#type: path,
+ args: args_span,
+ suggestion,
+ })
+ }
token::BinOp(token::Shl) => {
- self.sess.emit_err(ShiftInterpretedAsGeneric {
+ self.sess.emit_err(errors::ShiftInterpretedAsGeneric {
shift: self.token.span,
r#type: path,
args: args_span,
}
fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) {
- self.sess.emit_err(LifetimeInBorrowExpression { span, lifetime_span: lt_span });
+ self.sess.emit_err(errors::LifetimeInBorrowExpression { span, lifetime_span: lt_span });
}
/// Parse `mut?` or `raw [ const | mut ]`.
let close_paren = self.prev_token.span;
let span = lo.to(self.prev_token.span);
if !fields.is_empty() {
- let mut replacement_err = ParenthesesWithStructFields {
+ let mut replacement_err = errors::ParenthesesWithStructFields {
span,
r#type: path,
- braces_for_struct: BracesForStructLiteral {
+ braces_for_struct: errors::BracesForStructLiteral {
first: open_paren,
second: close_paren,
},
- no_fields_for_fn: NoFieldsForFnCall {
+ no_fields_for_fn: errors::NoFieldsForFnCall {
fields: fields
.into_iter()
.map(|field| field.span.until(field.expr.span))
} else {
// Field access `expr.f`
if let Some(args) = seg.args {
- self.sess.emit_err(FieldExpressionWithGeneric(args.span()));
+ self.sess.emit_err(errors::FieldExpressionWithGeneric(args.span()));
}
let span = lo.to(self.prev_token.span);
let (span, kind) = if self.eat(&token::Not) {
// MACRO INVOCATION expression
if qself.is_some() {
- self.sess.emit_err(MacroInvocationWithQualifiedPath(path.span));
+ self.sess.emit_err(errors::MacroInvocationWithQualifiedPath(path.span));
}
let lo = path.span;
let mac = P(MacCall {
{
let (lit, _) =
self.recover_unclosed_char(label_.ident, Parser::mk_token_lit_char, |self_| {
- self_.sess.create_err(UnexpectedTokenAfterLabel {
+ self_.sess.create_err(errors::UnexpectedTokenAfterLabel {
span: self_.token.span,
remove_label: None,
enclose_in_block: None,
&& (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
{
// We're probably inside of a `Path<'a>` that needs a turbofish
- self.sess.emit_err(UnexpectedTokenAfterLabel {
+ self.sess.emit_err(errors::UnexpectedTokenAfterLabel {
span: self.token.span,
remove_label: None,
enclose_in_block: None,
consume_colon = false;
Ok(self.mk_expr_err(lo))
} else {
- let mut err = UnexpectedTokenAfterLabel {
+ let mut err = errors::UnexpectedTokenAfterLabel {
span: self.token.span,
remove_label: None,
enclose_in_block: None,
return expr;
}
- err.enclose_in_block = Some(UnexpectedTokenAfterLabelSugg {
+ err.enclose_in_block = Some(errors::UnexpectedTokenAfterLabelSugg {
left: span.shrink_to_lo(),
right: span.shrink_to_hi(),
});
}?;
if !ate_colon && consume_colon {
- self.sess.emit_err(RequireColonAfterLabeledExpression {
+ self.sess.emit_err(errors::RequireColonAfterLabeledExpression {
span: expr.span,
label: lo,
label_end: lo.shrink_to_hi(),
self.bump(); // `catch`
let span = lo.to(self.prev_token.span);
- self.sess.emit_err(DoCatchSyntaxRemoved { span });
+ self.sess.emit_err(errors::DoCatchSyntaxRemoved { span });
self.parse_try_block(lo)
}
// The value expression can be a labeled loop, see issue #86948, e.g.:
// `loop { break 'label: loop { break 'label 42; }; }`
let lexpr = self.parse_labeled_expr(label, true)?;
- self.sess.emit_err(LabeledLoopInBreak {
+ self.sess.emit_err(errors::LabeledLoopInBreak {
span: lexpr.span,
- sub: WrapExpressionInParentheses {
+ sub: errors::WrapExpressionInParentheses {
left: lexpr.span.shrink_to_lo(),
right: lexpr.span.shrink_to_hi(),
},
};
if let Some(expr) = expr {
if matches!(expr.kind, ExprKind::Err) {
- let mut err = InvalidInterpolatedExpression { span: self.token.span }
+ let mut err = errors::InvalidInterpolatedExpression { span: self.token.span }
.into_diagnostic(&self.sess.span_diagnostic);
err.downgrade_to_delayed_bug();
return Err(err);
if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) =
next_token.kind
{
- if self.token.span.hi() == next_token.span.lo() {
+ // If this integer looks like a float, then recover as such.
+ //
+ // We will never encounter the exponent part of a floating
+ // point literal here, since there's no use of the exponent
+ // syntax that also constitutes a valid integer, so we need
+ // not check for that.
+ if suffix.map_or(true, |s| s == sym::f32 || s == sym::f64)
+ && symbol.as_str().chars().all(|c| c.is_numeric() || c == '_')
+ && self.token.span.hi() == next_token.span.lo()
+ {
let s = String::from("0.") + symbol.as_str();
let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix);
return Some(Token::new(kind, self.token.span.to(next_token.span)));
});
if let Some(token) = &recovered {
self.bump();
- self.sess.emit_err(FloatLiteralRequiresIntegerPart {
+ self.sess.emit_err(errors::FloatLiteralRequiresIntegerPart {
span: token.span,
correct: pprust::token_to_string(token).into_owned(),
});
if [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suffix) {
// #59553: warn instead of reject out of hand to allow the fix to percolate
// through the ecosystem when people fix their macros
- self.sess.emit_warning(InvalidLiteralSuffixOnTupleIndex {
+ self.sess.emit_warning(errors::InvalidLiteralSuffixOnTupleIndex {
span,
suffix,
exception: Some(()),
});
} else {
- self.sess.emit_err(InvalidLiteralSuffixOnTupleIndex { span, suffix, exception: None });
+ self.sess.emit_err(errors::InvalidLiteralSuffixOnTupleIndex {
+ span,
+ suffix,
+ exception: None,
+ });
}
}
let mut snapshot = self.create_snapshot_for_diagnostic();
match snapshot.parse_array_or_repeat_expr(Delimiter::Brace) {
Ok(arr) => {
- self.sess.emit_err(ArrayBracketsInsteadOfSpaces {
+ self.sess.emit_err(errors::ArrayBracketsInsteadOfSpaces {
span: arr.span,
- sub: ArrayBracketsInsteadOfSpacesSugg {
+ sub: errors::ArrayBracketsInsteadOfSpacesSugg {
left: lo,
right: snapshot.prev_token.span,
},
.span_to_snippet(snapshot.token.span)
.map_or(false, |snippet| snippet == "]") =>
{
- return Err(MissingSemicolonBeforeArray {
+ return Err(errors::MissingSemicolonBeforeArray {
open_delim: open_delim_span,
semicolon: prev_span.shrink_to_hi(),
}.into_diagnostic(&self.sess.span_diagnostic));
}
if self.token.is_whole_block() {
- self.sess.emit_err(InvalidBlockMacroSegment {
+ self.sess.emit_err(errors::InvalidBlockMacroSegment {
span: self.token.span,
context: lo.to(self.token.span),
});
ClosureBinder::NotPresent
};
- let constness = self.parse_constness(Case::Sensitive);
+ let constness = self.parse_closure_constness(Case::Sensitive);
let movability =
if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable };
}
if self.token.kind == TokenKind::Semi
- && matches!(self.token_cursor.frame.delim_sp, Some((Delimiter::Parenthesis, _)))
+ && matches!(self.token_cursor.stack.last(), Some((_, Delimiter::Parenthesis, _)))
&& self.may_recover()
{
// It is likely that the closure body is a block but where the
// Check for `move async` and recover
if self.check_keyword(kw::Async) {
let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo);
- Err(AsyncMoveOrderIncorrect { span: move_async_span }
+ Err(errors::AsyncMoveOrderIncorrect { span: move_async_span }
.into_diagnostic(&self.sess.span_diagnostic))
} else {
Ok(CaptureBy::Value)
let lo = self.token.span;
let attrs = self.parse_outer_attributes()?;
self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
- let pat = this.parse_pat_no_top_alt(PARAM_EXPECTED)?;
+ let pat = this.parse_pat_no_top_alt(Some(Expected::ParameterName))?;
let ty = if this.eat(&token::Colon) {
this.parse_ty()?
} else {
let block = match &mut cond.kind {
ExprKind::Binary(Spanned { span: binop_span, .. }, _, right)
if let ExprKind::Block(_, None) = right.kind => {
- self.sess.emit_err(IfExpressionMissingThenBlock {
+ self.sess.emit_err(errors::IfExpressionMissingThenBlock {
if_span: lo,
missing_then_block_sub:
- IfExpressionMissingThenBlockSub::UnfinishedCondition(cond_span.shrink_to_lo().to(*binop_span)),
+ errors::IfExpressionMissingThenBlockSub::UnfinishedCondition(cond_span.shrink_to_lo().to(*binop_span)),
let_else_sub: None,
});
std::mem::replace(right, this.mk_expr_err(binop_span.shrink_to_hi()))
},
ExprKind::Block(_, None) => {
- self.sess.emit_err(IfExpressionMissingCondition {
+ self.sess.emit_err(errors::IfExpressionMissingCondition {
if_span: lo.shrink_to_hi(),
block_span: self.sess.source_map().start_point(cond_span),
});
block
} else {
let let_else_sub = matches!(cond.kind, ExprKind::Let(..))
- .then(|| IfExpressionLetSomeSub { if_span: lo });
+ .then(|| errors::IfExpressionLetSomeSub { if_span: lo.until(cond_span) });
- self.sess.emit_err(IfExpressionMissingThenBlock {
+ self.sess.emit_err(errors::IfExpressionMissingThenBlock {
if_span: lo,
- missing_then_block_sub: IfExpressionMissingThenBlockSub::AddThenBlock(
+ missing_then_block_sub: errors::IfExpressionMissingThenBlockSub::AddThenBlock(
cond_span.shrink_to_hi(),
),
let_else_sub,
TokenKind::AndAnd | TokenKind::Ident(kw::If, _) | TokenKind::Ident(kw::While, _)
);
if !self.restrictions.contains(Restrictions::ALLOW_LET) || not_in_chain {
- self.sess.emit_err(ExpectedExpressionFoundLet { span: self.token.span });
+ self.sess.emit_err(errors::ExpectedExpressionFoundLet { span: self.token.span });
}
self.bump(); // Eat `let` token
CommaRecoveryMode::LikelyTuple,
)?;
if self.token == token::EqEq {
- self.sess.emit_err(ExpectedEqForLetExpr {
+ self.sess.emit_err(errors::ExpectedEqForLetExpr {
span: self.token.span,
sugg_span: self.token.span,
});
if self.check(&TokenKind::OpenDelim(Delimiter::Brace))
&& classify::expr_requires_semi_to_be_stmt(&cond) =>
{
- self.sess.emit_err(ExpectedElseBlock {
+ self.sess.emit_err(errors::ExpectedElseBlock {
first_tok_span,
first_tok,
else_span,
[x0 @ xn] | [x0, .., xn] => (x0.span.to(xn.span), xn.span),
};
let ctx = if is_ctx_else { "else" } else { "if" };
- self.sess.emit_err(OuterAttributeNotAllowedOnIfElse {
+ self.sess.emit_err(errors::OuterAttributeNotAllowedOnIfElse {
last,
branch_span,
ctx_span,
if let ExprKind::Binary(Spanned { span: binop_span, node: binop}, _, right) = &cond.kind &&
let BinOpKind::And = binop &&
let ExprKind::If(cond, ..) = &right.kind {
- Err(self.sess.create_err(UnexpectedIfWithIf(binop_span.shrink_to_hi().to(cond.span.shrink_to_lo()))))
+ Err(self.sess.create_err(errors::UnexpectedIfWithIf(binop_span.shrink_to_hi().to(cond.span.shrink_to_lo()))))
} else {
Ok(())
}
let pat = self.recover_parens_around_for_head(pat, begin_paren);
+ // Recover from missing expression in `for` loop
+ if matches!(expr.kind, ExprKind::Block(..))
+ && !matches!(self.token.kind, token::OpenDelim(token::Delimiter::Brace))
+ && self.may_recover()
+ {
+ self.sess
+ .emit_err(errors::MissingExpressionInForLoop { span: expr.span.shrink_to_lo() });
+ let err_expr = self.mk_expr(expr.span, ExprKind::Err);
+ let block = self.mk_block(vec![], BlockCheckMode::Default, self.prev_token.span);
+ return Ok(self.mk_expr(
+ lo.to(self.prev_token.span),
+ ExprKind::ForLoop(pat, err_expr, block, opt_label),
+ ));
+ }
+
let (attrs, loop_block) = self.parse_inner_attrs_and_block()?;
let kind = ExprKind::ForLoop(pat, expr, loop_block, opt_label);
// Possibly using JS syntax (#75311).
let span = self.token.span;
self.bump();
- (span, MissingInInForLoopSub::InNotOf)
+ (span, errors::MissingInInForLoopSub::InNotOf)
} else {
- (self.prev_token.span.between(self.token.span), MissingInInForLoopSub::AddIn)
+ (self.prev_token.span.between(self.token.span), errors::MissingInInForLoopSub::AddIn)
};
- self.sess.emit_err(MissingInInForLoop { span, sub: sub(span) });
+ self.sess.emit_err(errors::MissingInInForLoop { span, sub: sub(span) });
}
/// Parses a `while` or `while let` expression (`while` token already eaten).
let err = |this: &Parser<'_>, stmts: Vec<ast::Stmt>| {
let span = stmts[0].span.to(stmts[stmts.len() - 1].span);
- this.sess.emit_err(MatchArmBodyWithoutBraces {
+ this.sess.emit_err(errors::MatchArmBodyWithoutBraces {
statements: span,
arrow: arrow_span,
num_statements: stmts.len(),
sub: if stmts.len() > 1 {
- MatchArmBodyWithoutBracesSugg::AddBraces {
+ errors::MatchArmBodyWithoutBracesSugg::AddBraces {
left: span.shrink_to_lo(),
right: span.shrink_to_hi(),
}
} else {
- MatchArmBodyWithoutBracesSugg::UseComma { semicolon: semi_sp }
+ errors::MatchArmBodyWithoutBracesSugg::UseComma { semicolon: semi_sp }
},
});
this.mk_expr_err(span)
);
err.emit();
this.bump();
+ } else if matches!(
+ (&this.prev_token.kind, &this.token.kind),
+ (token::DotDotEq, token::Gt)
+ ) {
+ // `error_inclusive_range_match_arrow` handles cases like `0..=> {}`,
+ // so we supress the error here
+ err.delay_as_bug();
+ this.bump();
} else {
return Err(err);
}
.is_ok();
if pattern_follows && snapshot.check(&TokenKind::FatArrow) {
err.cancel();
- this.sess.emit_err(MissingCommaAfterMatchArm {
+ this.sess.emit_err(errors::MissingCommaAfterMatchArm {
span: hi.shrink_to_hi(),
});
return Ok(true);
fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P<Expr>> {
let (attrs, body) = self.parse_inner_attrs_and_block()?;
if self.eat_keyword(kw::Catch) {
- Err(CatchAfterTry { span: self.prev_token.span }
+ Err(errors::CatchAfterTry { span: self.prev_token.span }
.into_diagnostic(&self.sess.span_diagnostic))
} else {
let span = span_lo.to(body.span);
let expr = self.parse_struct_expr(qself.clone(), path.clone(), true);
if let (Ok(expr), false) = (&expr, struct_allowed) {
// This is a struct literal, but we don't can't accept them here.
- self.sess.emit_err(StructLiteralNotAllowedHere {
+ self.sess.emit_err(errors::StructLiteralNotAllowedHere {
span: expr.span,
- sub: StructLiteralNotAllowedHereSugg {
+ sub: errors::StructLiteralNotAllowedHereSugg {
left: path.span.shrink_to_lo(),
right: expr.span.shrink_to_hi(),
},
let mut async_block_err = |e: &mut Diagnostic, span: Span| {
recover_async = true;
- e.span_label(span, "`async` blocks are only allowed in Rust 2018 or later");
- e.help_use_latest_edition();
+ errors::AsyncBlockIn2015 { span }.add_to_diagnostic(e);
+ errors::HelpUseLatestEdition::new().add_to_diagnostic(e);
};
while self.token != token::CloseDelim(close_delim) {
if self.token != token::Comma {
return;
}
- self.sess.emit_err(CommaAfterBaseStruct {
+ self.sess.emit_err(errors::CommaAfterBaseStruct {
span: span.to(self.prev_token.span),
comma: self.token.span,
});
{
// recover from typo of `...`, suggest `..`
let span = self.prev_token.span;
- self.sess.emit_err(MissingDotDot { token_span: span, sugg_span: span });
+ self.sess.emit_err(errors::MissingDotDot { token_span: span, sugg_span: span });
return true;
}
false
return;
}
- self.sess.emit_err(EqFieldInit {
+ self.sess.emit_err(errors::EqFieldInit {
span: self.token.span,
eq: field_name.span.shrink_to_hi().to(self.token.span),
});
}
fn err_dotdotdot_syntax(&self, span: Span) {
- self.sess.emit_err(DotDotDot { span });
+ self.sess.emit_err(errors::DotDotDot { span });
}
fn err_larrow_operator(&self, span: Span) {
- self.sess.emit_err(LeftArrowOperator { span });
+ self.sess.emit_err(errors::LeftArrowOperator { span });
}
fn mk_assign_op(&self, binop: BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind {
-use crate::errors::{WhereClauseBeforeTupleStructBody, WhereClauseBeforeTupleStructBodySugg};
+use crate::errors::{
+ MultipleWhereClauses, UnexpectedDefaultValueForLifetimeInGenericParameters,
+ UnexpectedSelfInGenericParameters, WhereClauseBeforeTupleStructBody,
+ WhereClauseBeforeTupleStructBodySugg,
+};
use super::{ForceCollect, Parser, TrailingToken};
if this.eat_keyword_noexpect(kw::SelfUpper) {
// `Self` as a generic param is invalid. Here we emit the diagnostic and continue parsing
// as if `Self` never existed.
- this.struct_span_err(
- this.prev_token.span,
- "unexpected keyword `Self` in generic parameters",
- )
- .note("you cannot use `Self` as a generic parameter because it is reserved for associated items")
- .emit();
+ this.sess.emit_err(UnexpectedSelfInGenericParameters {
+ span: this.prev_token.span,
+ });
this.eat(&token::Comma);
}
} else {
(None, Vec::new())
};
+
+ if this.check_noexpect(&token::Eq)
+ && this.look_ahead(1, |t| t.is_lifetime())
+ {
+ let lo = this.token.span;
+ // Parse `= 'lifetime`.
+ this.bump(); // `=`
+ this.bump(); // `'lifetime`
+ let span = lo.to(this.prev_token.span);
+ this.sess.emit_err(
+ UnexpectedDefaultValueForLifetimeInGenericParameters { span },
+ );
+ }
+
Some(ast::GenericParam {
ident: lifetime.ident,
id: lifetime.id,
let ate_comma = self.eat(&token::Comma);
if self.eat_keyword_noexpect(kw::Where) {
- let msg = "cannot define duplicate `where` clauses on an item";
- let mut err = self.struct_span_err(self.token.span, msg);
- err.span_label(pred_lo, "previous `where` clause starts here");
- err.span_suggestion_verbose(
- prev_token.shrink_to_hi().to(self.prev_token.span),
- "consider joining the two `where` clauses into one",
- ",",
- Applicability::MaybeIncorrect,
- );
- err.emit();
+ self.sess.emit_err(MultipleWhereClauses {
+ span: self.token.span,
+ previous: pred_lo,
+ between: prev_token.shrink_to_hi().to(self.prev_token.span),
+ });
} else if !ate_comma {
break;
}
-use crate::errors::{DocCommentDoesNotDocumentAnything, UseEmptyBlockNotSemi};
+use crate::errors::{
+ AmbiguousMissingKwForItemSub, AssociatedStaticItemNotAllowed, AsyncFnIn2015,
+ BoundsNotAllowedOnTraitAliases, ConstGlobalCannotBeMutable, ConstLetMutuallyExclusive,
+ DefaultNotFollowedByItem, DocCommentDoesNotDocumentAnything, EnumStructMutuallyExclusive,
+ ExpectedTraitInTraitImplFoundType, ExternCrateNameWithDashes, ExternCrateNameWithDashesSugg,
+ ExternItemCannotBeConst, HelpUseLatestEdition, MissingConstType, MissingForInTraitImpl,
+ MissingKeywordForItemDefinition, MissingTraitInTraitImpl, SelfArgumentPointer,
+ TraitAliasCannotBeAuto, TraitAliasCannotBeUnsafe, UnexpectedTokenAfterStructName,
+ UseEmptyBlockNotSemi, VisibilityNotFollowedByItem,
+};
use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use rustc_ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind};
use rustc_ast::{MacCall, MacDelimiter};
use rustc_ast_pretty::pprust;
-use rustc_errors::{struct_span_err, Applicability, IntoDiagnostic, PResult, StashKey};
+use rustc_errors::{
+ struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult,
+ StashKey,
+};
use rustc_span::edition::Edition;
use rustc_span::lev_distance::lev_distance;
use rustc_span::source_map::{self, Span};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::DUMMY_SP;
+use std::fmt::Write;
use std::mem;
use thin_vec::ThinVec;
}
// At this point, we have failed to parse an item.
- self.error_on_unmatched_vis(&vis);
- self.error_on_unmatched_defaultness(def);
- if !attrs_allowed {
- self.recover_attrs_no_item(&attrs)?;
+ if !matches!(vis.kind, VisibilityKind::Inherited) {
+ self.sess.emit_err(VisibilityNotFollowedByItem { span: vis.span, vis });
}
- Ok(None)
- }
- /// Error in-case a non-inherited visibility was parsed but no item followed.
- fn error_on_unmatched_vis(&self, vis: &Visibility) {
- if let VisibilityKind::Inherited = vis.kind {
- return;
+ if let Defaultness::Default(span) = def {
+ self.sess.emit_err(DefaultNotFollowedByItem { span });
}
- let vs = pprust::vis_to_string(&vis);
- let vs = vs.trim_end();
- self.struct_span_err(vis.span, &format!("visibility `{vs}` is not followed by an item"))
- .span_label(vis.span, "the visibility")
- .help(&format!("you likely meant to define an item, e.g., `{vs} fn foo() {{}}`"))
- .emit();
- }
- /// Error in-case a `default` was parsed but no item followed.
- fn error_on_unmatched_defaultness(&self, def: Defaultness) {
- if let Defaultness::Default(sp) = def {
- self.struct_span_err(sp, "`default` is not followed by an item")
- .span_label(sp, "the `default` qualifier")
- .note("only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`")
- .emit();
+ if !attrs_allowed {
+ self.recover_attrs_no_item(&attrs)?;
}
+ Ok(None)
}
/// Error in-case `default` was parsed in an in-appropriate context.
let sp = self.prev_token.span.between(self.token.span);
let full_sp = self.prev_token.span.to(self.token.span);
let ident_sp = self.token.span;
- if self.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace)) {
+
+ let ident = if self.look_ahead(1, |t| {
+ [
+ token::Lt,
+ token::OpenDelim(Delimiter::Brace),
+ token::OpenDelim(Delimiter::Parenthesis),
+ ]
+ .contains(&t.kind)
+ }) {
+ self.parse_ident().unwrap()
+ } else {
+ return Ok(());
+ };
+
+ let mut found_generics = false;
+ if self.check(&token::Lt) {
+ found_generics = true;
+ self.eat_to_tokens(&[&token::Gt]);
+ self.bump(); // `>`
+ }
+
+ let err = if self.check(&token::OpenDelim(Delimiter::Brace)) {
// possible public struct definition where `struct` was forgotten
- let ident = self.parse_ident().unwrap();
- let msg = format!("add `struct` here to parse `{ident}` as a public struct");
- let mut err = self.struct_span_err(sp, "missing `struct` for struct definition");
- err.span_suggestion_short(
- sp,
- &msg,
- " struct ",
- Applicability::MaybeIncorrect, // speculative
- );
- Err(err)
- } else if self.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Parenthesis)) {
- let ident = self.parse_ident().unwrap();
+ Some(MissingKeywordForItemDefinition::Struct { span: sp, ident })
+ } else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
+ // possible public function or tuple struct definition where `fn`/`struct` was
+ // forgotten
self.bump(); // `(`
- let kw_name = self.recover_first_param();
+ let is_method = self.recover_self_param();
+
self.consume_block(Delimiter::Parenthesis, ConsumeClosingDelim::Yes);
- let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) {
+
+ let err = if self.check(&token::RArrow)
+ || self.check(&token::OpenDelim(Delimiter::Brace))
+ {
self.eat_to_tokens(&[&token::OpenDelim(Delimiter::Brace)]);
self.bump(); // `{`
- ("fn", kw_name, false)
- } else if self.check(&token::OpenDelim(Delimiter::Brace)) {
- self.bump(); // `{`
- ("fn", kw_name, false)
- } else if self.check(&token::Colon) {
- let kw = "struct";
- (kw, kw, false)
- } else {
- ("fn` or `struct", "function or struct", true)
- };
-
- let msg = format!("missing `{kw}` for {kw_name} definition");
- let mut err = self.struct_span_err(sp, &msg);
- if !ambiguous {
self.consume_block(Delimiter::Brace, ConsumeClosingDelim::Yes);
- let suggestion =
- format!("add `{kw}` here to parse `{ident}` as a public {kw_name}");
- err.span_suggestion_short(
- sp,
- &suggestion,
- format!(" {kw} "),
- Applicability::MachineApplicable,
- );
- } else if let Ok(snippet) = self.span_to_snippet(ident_sp) {
- err.span_suggestion(
- full_sp,
- "if you meant to call a macro, try",
- format!("{}!", snippet),
- // this is the `ambiguous` conditional branch
- Applicability::MaybeIncorrect,
- );
- } else {
- err.help(
- "if you meant to call a macro, remove the `pub` \
- and add a trailing `!` after the identifier",
- );
- }
- Err(err)
- } else if self.look_ahead(1, |t| *t == token::Lt) {
- let ident = self.parse_ident().unwrap();
- self.eat_to_tokens(&[&token::Gt]);
- self.bump(); // `>`
- let (kw, kw_name, ambiguous) = if self.eat(&token::OpenDelim(Delimiter::Parenthesis)) {
- ("fn", self.recover_first_param(), false)
- } else if self.check(&token::OpenDelim(Delimiter::Brace)) {
- ("struct", "struct", false)
+ if is_method {
+ MissingKeywordForItemDefinition::Method { span: sp, ident }
+ } else {
+ MissingKeywordForItemDefinition::Function { span: sp, ident }
+ }
+ } else if self.check(&token::Semi) {
+ MissingKeywordForItemDefinition::Struct { span: sp, ident }
} else {
- ("fn` or `struct", "function or struct", true)
+ MissingKeywordForItemDefinition::Ambiguous {
+ span: sp,
+ subdiag: if found_generics {
+ None
+ } else if let Ok(snippet) = self.span_to_snippet(ident_sp) {
+ Some(AmbiguousMissingKwForItemSub::SuggestMacro { span: full_sp, snippet })
+ } else {
+ Some(AmbiguousMissingKwForItemSub::HelpMacro)
+ },
+ }
};
- let msg = format!("missing `{kw}` for {kw_name} definition");
- let mut err = self.struct_span_err(sp, &msg);
- if !ambiguous {
- err.span_suggestion_short(
- sp,
- &format!("add `{kw}` here to parse `{ident}` as a public {kw_name}"),
- format!(" {} ", kw),
- Applicability::MachineApplicable,
- );
- }
- Err(err)
+ Some(err)
+ } else if found_generics {
+ Some(MissingKeywordForItemDefinition::Ambiguous { span: sp, subdiag: None })
+ } else {
+ None
+ };
+
+ if let Some(err) = err {
+ Err(err.into_diagnostic(&self.sess.span_diagnostic))
} else {
Ok(())
}
let mut err = self.struct_span_err(end.span, msg);
if end.is_doc_comment() {
err.span_label(end.span, "this doc comment doesn't document anything");
- }
- if end.meta_kind().is_some() {
- if self.token.kind == TokenKind::Semi {
- err.span_suggestion_verbose(
- self.token.span,
- "consider removing this semicolon",
- "",
- Applicability::MaybeIncorrect,
- );
- }
+ } else if self.token.kind == TokenKind::Semi {
+ err.span_suggestion_verbose(
+ self.token.span,
+ "consider removing this semicolon",
+ "",
+ Applicability::MaybeIncorrect,
+ );
}
if let [.., penultimate, _] = attrs {
err.span_label(start.span.to(penultimate.span), "other attributes here");
let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt)
{
let span = self.prev_token.span.between(self.token.span);
- self.struct_span_err(span, "missing trait in a trait impl")
- .span_suggestion(
- span,
- "add a trait here",
- " Trait ",
- Applicability::HasPlaceholders,
- )
- .span_suggestion(
- span.to(self.token.span),
- "for an inherent impl, drop this `for`",
- "",
- Applicability::MaybeIncorrect,
- )
- .emit();
+ self.sess
+ .emit_err(MissingTraitInTraitImpl { span, for_span: span.to(self.token.span) });
+
P(Ty {
kind: TyKind::Path(None, err_path(span)),
span,
Some(ty_second) => {
// impl Trait for Type
if !has_for {
- self.struct_span_err(missing_for_span, "missing `for` in a trait impl")
- .span_suggestion_short(
- missing_for_span,
- "add `for` here",
- " for ",
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(MissingForInTraitImpl { span: missing_for_span });
}
let ty_first = ty_first.into_inner();
// This notably includes paths passed through `ty` macro fragments (#46438).
TyKind::Path(None, path) => path,
_ => {
- self.struct_span_err(ty_first.span, "expected a trait, found type").emit();
+ self.sess
+ .emit_err(ExpectedTraitInTraitImplFoundType { span: ty_first.span });
err_path(ty_first.span)
}
};
fn recover_doc_comment_before_brace(&mut self) -> bool {
if let token::DocComment(..) = self.token.kind {
if self.look_ahead(1, |tok| tok == &token::CloseDelim(Delimiter::Brace)) {
+ // FIXME: merge with `DocCommentDoesNotDocumentAnything` (E0585)
struct_span_err!(
self.diagnostic(),
self.token.span,
// It's a trait alias.
if had_colon {
let span = span_at_colon.to(span_before_eq);
- self.struct_span_err(span, "bounds are not allowed on trait aliases").emit();
+ self.sess.emit_err(BoundsNotAllowedOnTraitAliases { span });
}
let bounds = self.parse_generic_bounds(None)?;
let whole_span = lo.to(self.prev_token.span);
if is_auto == IsAuto::Yes {
- let msg = "trait aliases cannot be `auto`";
- self.struct_span_err(whole_span, msg).span_label(whole_span, msg).emit();
+ self.sess.emit_err(TraitAliasCannotBeAuto { span: whole_span });
}
if let Unsafe::Yes(_) = unsafety {
- let msg = "trait aliases cannot be `unsafe`";
- self.struct_span_err(whole_span, msg).span_label(whole_span, msg).emit();
+ self.sess.emit_err(TraitAliasCannotBeUnsafe { span: whole_span });
}
self.sess.gated_spans.gate(sym::trait_alias, whole_span);
Ok(kind) => kind,
Err(kind) => match kind {
ItemKind::Static(a, _, b) => {
- self.struct_span_err(span, "associated `static` items are not allowed")
- .emit();
+ self.sess.emit_err(AssociatedStaticItemNotAllowed { span });
AssocItemKind::Const(Defaultness::Final, a, b)
}
_ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
}
fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> {
- let error_msg = "crate name using dashes are not valid in `extern crate` statements";
- let suggestion_msg = "if the original crate name uses dashes you need to use underscores \
- in the code";
- let mut ident = if self.token.is_keyword(kw::SelfLower) {
+ let ident = if self.token.is_keyword(kw::SelfLower) {
self.parse_path_segment_ident()
} else {
self.parse_ident()
}?;
- let mut idents = vec![];
- let mut replacement = vec![];
- let mut fixed_crate_name = false;
- // Accept `extern crate name-like-this` for better diagnostics.
+
let dash = token::BinOp(token::BinOpToken::Minus);
- if self.token == dash {
- // Do not include `-` as part of the expected tokens list.
- while self.eat(&dash) {
- fixed_crate_name = true;
- replacement.push((self.prev_token.span, "_".to_string()));
- idents.push(self.parse_ident()?);
- }
+ if self.token != dash {
+ return Ok(ident);
}
- if fixed_crate_name {
- let fixed_name_sp = ident.span.to(idents.last().unwrap().span);
- let mut fixed_name = ident.name.to_string();
- for part in idents {
- fixed_name.push_str(&format!("_{}", part.name));
- }
- ident = Ident::from_str_and_span(&fixed_name, fixed_name_sp);
- self.struct_span_err(fixed_name_sp, error_msg)
- .span_label(fixed_name_sp, "dash-separated idents are not valid")
- .multipart_suggestion(suggestion_msg, replacement, Applicability::MachineApplicable)
- .emit();
+ // Accept `extern crate name-like-this` for better diagnostics.
+ let mut dashes = vec![];
+ let mut idents = vec![];
+ while self.eat(&dash) {
+ dashes.push(self.prev_token.span);
+ idents.push(self.parse_ident()?);
}
- Ok(ident)
+
+ let fixed_name_sp = ident.span.to(idents.last().unwrap().span);
+ let mut fixed_name = ident.name.to_string();
+ for part in idents {
+ write!(fixed_name, "_{}", part.name).unwrap();
+ }
+
+ self.sess.emit_err(ExternCrateNameWithDashes {
+ span: fixed_name_sp,
+ sugg: ExternCrateNameWithDashesSugg { dashes },
+ });
+
+ Ok(Ident::from_str_and_span(&fixed_name, fixed_name_sp))
}
/// Parses `extern` for foreign ABIs modules.
Ok(kind) => kind,
Err(kind) => match kind {
ItemKind::Const(_, a, b) => {
- self.error_on_foreign_const(span, ident);
+ self.sess.emit_err(ExternItemCannotBeConst {
+ ident_span: ident.span,
+ const_span: span.with_hi(ident.span.lo()),
+ });
ForeignItemKind::Static(a, Mutability::Not, b)
}
_ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
}
fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &str) -> Option<T> {
+ // FIXME(#100717): needs variant for each `ItemKind` (instead of using `ItemKind::descr()`)
let span = self.sess.source_map().guess_head_span(span);
let descr = kind.descr();
self.struct_span_err(span, &format!("{descr} is not supported in {ctx}"))
None
}
- fn error_on_foreign_const(&self, span: Span, ident: Ident) {
- self.struct_span_err(ident.span, "extern items cannot be `const`")
- .span_suggestion(
- span.with_hi(ident.span.lo()),
- "try using a static value",
- "static ",
- Applicability::MachineApplicable,
- )
- .note("for more information, visit https://doc.rust-lang.org/std/keyword.extern.html")
- .emit();
- }
-
fn is_unsafe_foreign_mod(&self) -> bool {
self.token.is_keyword(kw::Unsafe)
&& self.is_keyword_ahead(1, &[kw::Extern])
fn recover_const_mut(&mut self, const_span: Span) {
if self.eat_keyword(kw::Mut) {
let span = self.prev_token.span;
- self.struct_span_err(span, "const globals cannot be mutable")
- .span_label(span, "cannot be mutable")
- .span_suggestion(
- const_span,
- "you might want to declare a static instead",
- "static",
- Applicability::MaybeIncorrect,
- )
- .emit();
+ self.sess.emit_err(ConstGlobalCannotBeMutable { ident_span: span, const_span });
} else if self.eat_keyword(kw::Let) {
let span = self.prev_token.span;
- self.struct_span_err(const_span.to(span), "`const` and `let` are mutually exclusive")
- .span_suggestion(
- const_span.to(span),
- "remove `let`",
- "const",
- Applicability::MaybeIncorrect,
- )
- .emit();
+ self.sess.emit_err(ConstLetMutuallyExclusive { span: const_span.to(span) });
}
}
};
let span = self.prev_token.span.shrink_to_hi();
- let mut err = self.struct_span_err(span, &format!("missing type for `{kind}` item"));
- err.span_suggestion(
- span,
- "provide a type for the item",
- format!("{colon} <type>"),
- Applicability::HasPlaceholders,
- );
+ let err: DiagnosticBuilder<'_, ErrorGuaranteed> =
+ MissingConstType { span, colon, kind }.into_diagnostic(&self.sess.span_diagnostic);
err.stash(span, StashKey::ItemNoType);
// The user intended that the type be inferred,
fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> {
if self.token.is_keyword(kw::Struct) {
let span = self.prev_token.span.to(self.token.span);
- let mut err = self.struct_span_err(span, "`enum` and `struct` are mutually exclusive");
- err.span_suggestion(
- span,
- "replace `enum struct` with",
- "enum",
- Applicability::MachineApplicable,
- );
+ let err = EnumStructMutuallyExclusive { span };
if self.look_ahead(1, |t| t.is_ident()) {
self.bump();
- err.emit();
+ self.sess.emit_err(err);
} else {
- return Err(err);
+ return Err(err.into_diagnostic(&self.sess.span_diagnostic));
}
}
self.expect_semi()?;
body
} else {
- let token_str = super::token_descr(&self.token);
- let msg = &format!(
- "expected `where`, `{{`, `(`, or `;` after struct name, found {token_str}"
- );
- let mut err = self.struct_span_err(self.token.span, msg);
- err.span_label(self.token.span, "expected `where`, `{`, `(`, or `;` after struct name");
- return Err(err);
+ let err = UnexpectedTokenAfterStructName::new(self.token.span, self.token.clone());
+ return Err(err.into_diagnostic(&self.sess.span_diagnostic));
};
Ok((class_name, ItemKind::Struct(vdata, generics)))
let ext = self.parse_extern(case);
if let Async::Yes { span, .. } = asyncness {
- self.ban_async_in_2015(span);
+ if span.is_rust_2015() {
+ self.sess.emit_err(AsyncFnIn2015 { span, help: HelpUseLatestEdition::new() });
+ }
}
if !self.eat_keyword_case(kw::Fn, case) {
Ok(FnHeader { constness, unsafety, asyncness, ext })
}
- /// We are parsing `async fn`. If we are on Rust 2015, emit an error.
- fn ban_async_in_2015(&self, span: Span) {
- if span.rust_2015() {
- let diag = self.diagnostic();
- struct_span_err!(diag, span, E0670, "`async fn` is not permitted in Rust 2015")
- .span_label(span, "to use `async fn`, switch to Rust 2018 or later")
- .help_use_latest_edition()
- .emit();
- }
- }
-
/// Parses the parameter list and result type of a function declaration.
pub(super) fn parse_fn_decl(
&mut self,
};
// Recover for the grammar `*self`, `*const self`, and `*mut self`.
let recover_self_ptr = |this: &mut Self| {
- let msg = "cannot pass `self` by raw pointer";
- let span = this.token.span;
- this.struct_span_err(span, msg).span_label(span, msg).emit();
+ self.sess.emit_err(SelfArgumentPointer { span: this.token.span });
Ok((SelfKind::Value(Mutability::Not), expect_self_ident(this), this.prev_token.span))
};
&& self.look_ahead(offset + 1, |t| t == &token::Colon)
}
- fn recover_first_param(&mut self) -> &'static str {
+ fn recover_self_param(&mut self) -> bool {
match self
.parse_outer_attributes()
.and_then(|_| self.parse_self_param())
.map_err(|e| e.cancel())
{
- Ok(Some(_)) => "method",
- _ => "function",
+ Ok(Some(_)) => true,
+ _ => false,
}
}
}
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, Nonterminal, Token, TokenKind};
-use rustc_ast::tokenstream::AttributesData;
-use rustc_ast::tokenstream::{self, DelimSpan, Spacing};
-use rustc_ast::tokenstream::{TokenStream, TokenTree};
+use rustc_ast::tokenstream::{AttributesData, DelimSpan, Spacing};
+use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
use rustc_ast::util::case::Case;
use rustc_ast::AttrId;
use rustc_ast::DUMMY_NODE_ID;
// This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. Make sure
// it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Parser<'_>, 336);
+rustc_data_structures::static_assert_size!(Parser<'_>, 312);
/// Stores span information about a closure.
#[derive(Clone)]
}
}
+/// Iterator over a `TokenStream` that produces `Token`s. It's a bit odd that
+/// we (a) lex tokens into a nice tree structure (`TokenStream`), and then (b)
+/// use this type to emit them as a linear sequence. But a linear sequence is
+/// what the parser expects, for the most part.
#[derive(Clone)]
struct TokenCursor {
- // The current (innermost) frame. `frame` and `stack` could be combined,
- // but it's faster to have them separately to access `frame` directly
- // rather than via something like `stack.last().unwrap()` or
- // `stack[stack.len() - 1]`.
- frame: TokenCursorFrame,
- // Additional frames that enclose `frame`.
- stack: Vec<TokenCursorFrame>,
+ // Cursor for the current (innermost) token stream. The delimiters for this
+ // token stream are found in `self.stack.last()`; when that is `None` then
+ // we are in the outermost token stream which never has delimiters.
+ tree_cursor: TokenTreeCursor,
+
+ // Token streams surrounding the current one. The delimiters for stack[n]'s
+ // tokens are in `stack[n-1]`. `stack[0]` (when present) has no delimiters
+ // because it's the outermost token stream which never has delimiters.
+ stack: Vec<(TokenTreeCursor, Delimiter, DelimSpan)>,
+
desugar_doc_comments: bool,
+
// Counts the number of calls to `{,inlined_}next`.
num_next_calls: usize,
+
// During parsing, we may sometimes need to 'unglue' a
// glued token into two component tokens
// (e.g. '>>' into '>' and '>), so that the parser
break_last_token: bool,
}
-#[derive(Clone)]
-struct TokenCursorFrame {
- delim_sp: Option<(Delimiter, DelimSpan)>,
- tree_cursor: tokenstream::Cursor,
-}
-
-impl TokenCursorFrame {
- fn new(delim_sp: Option<(Delimiter, DelimSpan)>, tts: TokenStream) -> Self {
- TokenCursorFrame { delim_sp, tree_cursor: tts.into_trees() }
- }
-}
-
impl TokenCursor {
fn next(&mut self, desugar_doc_comments: bool) -> (Token, Spacing) {
self.inlined_next(desugar_doc_comments)
// FIXME: we currently don't return `Delimiter` open/close delims. To fix #67062 we will
// need to, whereupon the `delim != Delimiter::Invisible` conditions below can be
// removed.
- if let Some(tree) = self.frame.tree_cursor.next_ref() {
+ if let Some(tree) = self.tree_cursor.next_ref() {
match tree {
&TokenTree::Token(ref token, spacing) => match (desugar_doc_comments, token) {
(true, &Token { kind: token::DocComment(_, attr_style, data), span }) => {
- return self.desugar(attr_style, data, span);
+ let desugared = self.desugar(attr_style, data, span);
+ self.tree_cursor.replace_prev_and_rewind(desugared);
+ // Continue to get the first token of the desugared doc comment.
+ }
+ _ => {
+ debug_assert!(!matches!(
+ token.kind,
+ token::OpenDelim(_) | token::CloseDelim(_)
+ ));
+ return (token.clone(), spacing);
}
- _ => return (token.clone(), spacing),
},
&TokenTree::Delimited(sp, delim, ref tts) => {
- // Set `open_delim` to true here because we deal with it immediately.
- let frame = TokenCursorFrame::new(Some((delim, sp)), tts.clone());
- self.stack.push(mem::replace(&mut self.frame, frame));
+ let trees = tts.clone().into_trees();
+ self.stack.push((mem::replace(&mut self.tree_cursor, trees), delim, sp));
if delim != Delimiter::Invisible {
return (Token::new(token::OpenDelim(delim), sp.open), Spacing::Alone);
}
// No open delimiter to return; continue on to the next iteration.
}
};
- } else if let Some(frame) = self.stack.pop() {
- if let Some((delim, span)) = self.frame.delim_sp && delim != Delimiter::Invisible {
- self.frame = frame;
+ } else if let Some((tree_cursor, delim, span)) = self.stack.pop() {
+ // We have exhausted this token stream. Move back to its parent token stream.
+ self.tree_cursor = tree_cursor;
+ if delim != Delimiter::Invisible {
return (Token::new(token::CloseDelim(delim), span.close), Spacing::Alone);
}
- self.frame = frame;
// No close delimiter to return; continue on to the next iteration.
} else {
+ // We have exhausted the outermost token stream.
return (Token::new(token::Eof, DUMMY_SP), Spacing::Alone);
}
}
}
- fn desugar(&mut self, attr_style: AttrStyle, data: Symbol, span: Span) -> (Token, Spacing) {
+ // Desugar a doc comment into something like `#[doc = r"foo"]`.
+ fn desugar(&mut self, attr_style: AttrStyle, data: Symbol, span: Span) -> Vec<TokenTree> {
// Searches for the occurrences of `"#*` and returns the minimum number of `#`s
// required to wrap the text. E.g.
// - `abc d` is wrapped as `r"abc d"` (num_of_hashes = 0)
.collect::<TokenStream>(),
);
- self.stack.push(mem::replace(
- &mut self.frame,
- TokenCursorFrame::new(
- None,
- if attr_style == AttrStyle::Inner {
- [
- TokenTree::token_alone(token::Pound, span),
- TokenTree::token_alone(token::Not, span),
- body,
- ]
- .into_iter()
- .collect::<TokenStream>()
- } else {
- [TokenTree::token_alone(token::Pound, span), body]
- .into_iter()
- .collect::<TokenStream>()
- },
- ),
- ));
-
- self.next(/* desugar_doc_comments */ false)
+ if attr_style == AttrStyle::Inner {
+ vec![
+ TokenTree::token_alone(token::Pound, span),
+ TokenTree::token_alone(token::Not, span),
+ body,
+ ]
+ } else {
+ vec![TokenTree::token_alone(token::Pound, span), body]
+ }
}
}
restrictions: Restrictions::empty(),
expected_tokens: Vec::new(),
token_cursor: TokenCursor {
- frame: TokenCursorFrame::new(None, tokens),
+ tree_cursor: tokens.into_trees(),
stack: Vec::new(),
num_next_calls: 0,
desugar_doc_comments,
fn check_const_closure(&self) -> bool {
self.is_keyword_ahead(0, &[kw::Const])
&& self.look_ahead(1, |t| match &t.kind {
- token::Ident(kw::Move | kw::Static | kw::Async, _)
- | token::OrOr
- | token::BinOp(token::Or) => true,
+ // async closures do not work with const closures, so we do not parse that here.
+ token::Ident(kw::Move | kw::Static, _) | token::OrOr | token::BinOp(token::Or) => {
+ true
+ }
_ => false,
})
}
return looker(&self.token);
}
- let frame = &self.token_cursor.frame;
- if let Some((delim, span)) = frame.delim_sp && delim != Delimiter::Invisible {
+ let tree_cursor = &self.token_cursor.tree_cursor;
+ if let Some(&(_, delim, span)) = self.token_cursor.stack.last()
+ && delim != Delimiter::Invisible
+ {
let all_normal = (0..dist).all(|i| {
- let token = frame.tree_cursor.look_ahead(i);
+ let token = tree_cursor.look_ahead(i);
!matches!(token, Some(TokenTree::Delimited(_, Delimiter::Invisible, _)))
});
if all_normal {
- return match frame.tree_cursor.look_ahead(dist - 1) {
+ return match tree_cursor.look_ahead(dist - 1) {
Some(tree) => match tree {
TokenTree::Token(token, _) => looker(token),
TokenTree::Delimited(dspan, delim, _) => {
/// Parses constness: `const` or nothing.
fn parse_constness(&mut self, case: Case) -> Const {
- // Avoid const blocks to be parsed as const items
- if self.look_ahead(1, |t| t != &token::OpenDelim(Delimiter::Brace))
+ self.parse_constness_(case, false)
+ }
+
+ /// Parses constness for closures
+ fn parse_closure_constness(&mut self, case: Case) -> Const {
+ self.parse_constness_(case, true)
+ }
+
+ fn parse_constness_(&mut self, case: Case, is_closure: bool) -> Const {
+ // Avoid const blocks and const closures to be parsed as const items
+ if (self.check_const_closure() == is_closure)
+ && self.look_ahead(1, |t| t != &token::OpenDelim(Delimiter::Brace))
&& self.eat_keyword_case(kw::Const, case)
{
Const::Yes(self.prev_token.uninterpolated_span())
pub(crate) fn parse_token_tree(&mut self) -> TokenTree {
match self.token.kind {
token::OpenDelim(..) => {
- // Grab the tokens from this frame.
- let frame = &self.token_cursor.frame;
- let stream = frame.tree_cursor.stream.clone();
- let (delim, span) = frame.delim_sp.unwrap();
+ // Grab the tokens within the delimiters.
+ let tree_cursor = &self.token_cursor.tree_cursor;
+ let stream = tree_cursor.stream.clone();
+ let (_, delim, span) = *self.token_cursor.stack.last().unwrap();
// Advance the token cursor through the entire delimited
// sequence. After getting the `OpenDelim` we are *within* the
use rustc_ast::token::{self, Delimiter, NonterminalKind, Token};
use rustc_ast::HasTokens;
use rustc_ast_pretty::pprust;
+use rustc_errors::IntoDiagnostic;
use rustc_errors::PResult;
use rustc_span::symbol::{kw, Ident};
+use crate::errors::UnexpectedNonterminal;
use crate::parser::pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
use crate::parser::{FollowedByType, ForceCollect, NtOrTt, Parser, PathStyle};
NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? {
Some(item) => token::NtItem(item),
None => {
- return Err(self.struct_span_err(self.token.span, "expected an item keyword"));
+ return Err(UnexpectedNonterminal::Item(self.token.span)
+ .into_diagnostic(&self.sess.span_diagnostic));
}
},
NonterminalKind::Block => {
NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? {
Some(s) => token::NtStmt(P(s)),
None => {
- return Err(self.struct_span_err(self.token.span, "expected a statement"));
+ return Err(UnexpectedNonterminal::Statement(self.token.span)
+ .into_diagnostic(&self.sess.span_diagnostic));
}
},
NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => {
token::NtIdent(ident, is_raw)
}
NonterminalKind::Ident => {
- let token_str = pprust::token_to_string(&self.token);
- let msg = &format!("expected ident, found {}", &token_str);
- return Err(self.struct_span_err(self.token.span, msg));
+ return Err(UnexpectedNonterminal::Ident {
+ span: self.token.span,
+ token: self.token.clone(),
+ }.into_diagnostic(&self.sess.span_diagnostic));
}
NonterminalKind::Path => token::NtPath(
P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?),
if self.check_lifetime() {
token::NtLifetime(self.expect_lifetime().ident)
} else {
- let token_str = pprust::token_to_string(&self.token);
- let msg = &format!("expected a lifetime, found `{}`", &token_str);
- return Err(self.struct_span_err(self.token.span, msg));
+ return Err(UnexpectedNonterminal::Lifetime {
+ span: self.token.span,
+ token: self.token.clone(),
+ }.into_diagnostic(&self.sess.span_diagnostic));
}
}
};
use super::{ForceCollect, Parser, PathStyle, TrailingToken};
use crate::errors::{
- InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, RemoveLet,
+ AmbiguousRangePattern, DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed,
+ DotDotDotRestPattern, EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt,
+ ExpectedCommaAfterPatternField, InclusiveRangeExtraEquals, InclusiveRangeMatchArrow,
+ InclusiveRangeNoEnd, InvalidMutInPattern, PatternOnWrongSideOfAt, RefMutOrderIncorrect,
+ RemoveLet, RepeatedMutInPattern, TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg,
+ TrailingVertNotAllowed, UnexpectedLifetimeInPattern, UnexpectedVertVertBeforeFunctionParam,
+ UnexpectedVertVertInPattern,
};
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor};
PatField, PatKind, Path, QSelf, RangeEnd, RangeSyntax,
};
use rustc_ast_pretty::pprust;
-use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
+use rustc_errors::{
+ fluent, Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult,
+};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::source_map::{respan, Span, Spanned};
use rustc_span::symbol::{kw, sym, Ident};
-pub(super) type Expected = Option<&'static str>;
+#[derive(PartialEq, Copy, Clone)]
+pub enum Expected {
+ ParameterName,
+ ArgumentName,
+ Identifier,
+ BindingPattern,
+}
-/// `Expected` for function and lambda parameter patterns.
-pub(super) const PARAM_EXPECTED: Expected = Some("parameter name");
+impl Expected {
+ // FIXME(#100717): migrate users of this to proper localization
+ fn to_string_or_fallback(expected: Option<Expected>) -> &'static str {
+ match expected {
+ Some(Expected::ParameterName) => "parameter name",
+ Some(Expected::ArgumentName) => "argument name",
+ Some(Expected::Identifier) => "identifier",
+ Some(Expected::BindingPattern) => "binding pattern",
+ None => "pattern",
+ }
+ }
+}
const WHILE_PARSING_OR_MSG: &str = "while parsing this or-pattern starting here";
None,
}
+/// The syntax location of a given pattern. Used for diagnostics.
+pub(super) enum PatternLocation {
+ LetBinding,
+ FunctionParameter,
+}
+
impl<'a> Parser<'a> {
/// Parses a pattern.
///
/// Corresponds to `pat<no_top_alt>` in RFC 2535 and does not admit or-patterns
/// at the top level. Used when parsing the parameters of lambda expressions,
/// functions, function pointers, and `pat` macro fragments.
- pub fn parse_pat_no_top_alt(&mut self, expected: Expected) -> PResult<'a, P<Pat>> {
+ pub fn parse_pat_no_top_alt(&mut self, expected: Option<Expected>) -> PResult<'a, P<Pat>> {
self.parse_pat_with_range_pat(true, expected)
}
/// simplify the grammar somewhat.
pub fn parse_pat_allow_top_alt(
&mut self,
- expected: Expected,
+ expected: Option<Expected>,
rc: RecoverComma,
ra: RecoverColon,
rt: CommaRecoveryMode,
/// recovered).
fn parse_pat_allow_top_alt_inner(
&mut self,
- expected: Expected,
+ expected: Option<Expected>,
rc: RecoverComma,
ra: RecoverColon,
rt: CommaRecoveryMode,
// Check if the user wrote `foo:bar` instead of `foo::bar`.
if ra == RecoverColon::Yes {
- first_pat =
- self.maybe_recover_colon_colon_in_pat_typo_or_anon_enum(first_pat, expected);
+ first_pat = self.maybe_recover_colon_colon_in_pat_typo(first_pat, expected);
}
if let Some(leading_vert_span) = leading_vert_span {
/// otherwise).
pub(super) fn parse_pat_before_ty(
&mut self,
- expected: Expected,
+ expected: Option<Expected>,
rc: RecoverComma,
- syntax_loc: &str,
+ syntax_loc: PatternLocation,
) -> PResult<'a, (P<Pat>, bool)> {
// We use `parse_pat_allow_top_alt` regardless of whether we actually want top-level
// or-patterns so that we can detect when a user tries to use it. This allows us to print a
let colon = self.eat(&token::Colon);
if let PatKind::Or(pats) = &pat.kind {
- let msg = format!("top-level or-patterns are not allowed in {}", syntax_loc);
- let (help, fix) = if pats.len() == 1 {
- // If all we have is a leading vert, then print a special message. This is the case
- // if `parse_pat_allow_top_alt` returns an or-pattern with one variant.
- let msg = "remove the `|`";
- let fix = pprust::pat_to_string(&pat);
- (msg, fix)
- } else {
- let msg = "wrap the pattern in parentheses";
- let fix = format!("({})", pprust::pat_to_string(&pat));
- (msg, fix)
- };
+ let span = pat.span;
if trailing_vert {
// We already emitted an error and suggestion to remove the trailing vert. Don't
// emit again.
- self.sess.span_diagnostic.delay_span_bug(pat.span, &msg);
+
+ // FIXME(#100717): pass `TopLevelOrPatternNotAllowed::* { sub: None }` to
+ // `delay_span_bug()` instead of fluent message
+ self.sess.span_diagnostic.delay_span_bug(
+ span,
+ match syntax_loc {
+ PatternLocation::LetBinding => {
+ fluent::parse_or_pattern_not_allowed_in_let_binding
+ }
+ PatternLocation::FunctionParameter => {
+ fluent::parse_or_pattern_not_allowed_in_fn_parameters
+ }
+ },
+ );
} else {
- self.struct_span_err(pat.span, &msg)
- .span_suggestion(pat.span, help, fix, Applicability::MachineApplicable)
- .emit();
+ let pat = pprust::pat_to_string(&pat);
+ let sub = if pats.len() == 1 {
+ Some(TopLevelOrPatternNotAllowedSugg::RemoveLeadingVert { span, pat })
+ } else {
+ Some(TopLevelOrPatternNotAllowedSugg::WrapInParens { span, pat })
+ };
+
+ self.sess.emit_err(match syntax_loc {
+ PatternLocation::LetBinding => {
+ TopLevelOrPatternNotAllowed::LetBinding { span, sub }
+ }
+ PatternLocation::FunctionParameter => {
+ TopLevelOrPatternNotAllowed::FunctionParameter { span, sub }
+ }
+ });
}
}
// a leading `||` probably doesn't indicate an or-pattern attempt, so we handle that
// separately.
if let token::OrOr = self.token.kind {
- let span = self.token.span;
- let mut err = self.struct_span_err(span, "unexpected `||` before function parameter");
- err.span_suggestion(span, "remove the `||`", "", Applicability::MachineApplicable);
- err.note("alternatives in or-patterns are separated with `|`, not `||`");
- err.emit();
+ self.sess.emit_err(UnexpectedVertVertBeforeFunctionParam { span: self.token.span });
self.bump();
}
- self.parse_pat_before_ty(PARAM_EXPECTED, RecoverComma::No, "function parameters")
+ self.parse_pat_before_ty(
+ Some(Expected::ParameterName),
+ RecoverComma::No,
+ PatternLocation::FunctionParameter,
+ )
}
/// Eat the or-pattern `|` separator.
EatOrResult::TrailingVert
} else if matches!(self.token.kind, token::OrOr) {
// Found `||`; Recover and pretend we parsed `|`.
- self.ban_unexpected_or_or(lo);
+ self.sess.emit_err(UnexpectedVertVertInPattern { span: self.token.span, start: lo });
self.bump();
EatOrResult::AteOr
} else if self.eat(&token::BinOp(token::Or)) {
});
match (is_end_ahead, &self.token.kind) {
(true, token::BinOp(token::Or) | token::OrOr) => {
- self.ban_illegal_vert(lo, "trailing", "not allowed in an or-pattern");
+ // A `|` or possibly `||` token shouldn't be here. Ban it.
+ self.sess.emit_err(TrailingVertNotAllowed {
+ span: self.token.span,
+ start: lo,
+ token: self.token.clone(),
+ note_double_vert: matches!(self.token.kind, token::OrOr).then_some(()),
+ });
self.bump();
true
}
}
}
- /// We have parsed `||` instead of `|`. Error and suggest `|` instead.
- fn ban_unexpected_or_or(&mut self, lo: Option<Span>) {
- let mut err = self.struct_span_err(self.token.span, "unexpected token `||` in pattern");
- err.span_suggestion(
- self.token.span,
- "use a single `|` to separate multiple alternative patterns",
- "|",
- Applicability::MachineApplicable,
- );
- if let Some(lo) = lo {
- err.span_label(lo, WHILE_PARSING_OR_MSG);
- }
- err.emit();
- }
-
- /// A `|` or possibly `||` token shouldn't be here. Ban it.
- fn ban_illegal_vert(&mut self, lo: Option<Span>, pos: &str, ctx: &str) {
- let span = self.token.span;
- let mut err = self.struct_span_err(span, &format!("a {} `|` is {}", pos, ctx));
- err.span_suggestion(
- span,
- &format!("remove the `{}`", pprust::token_to_string(&self.token)),
- "",
- Applicability::MachineApplicable,
- );
- if let Some(lo) = lo {
- err.span_label(lo, WHILE_PARSING_OR_MSG);
- }
- if let token::OrOr = self.token.kind {
- err.note("alternatives in or-patterns are separated with `|`, not `||`");
- }
- err.emit();
- }
-
/// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are
/// allowed).
fn parse_pat_with_range_pat(
&mut self,
allow_range_pat: bool,
- expected: Expected,
+ expected: Option<Expected>,
) -> PResult<'a, P<Pat>> {
maybe_recover_from_interpolated_ty_qpath!(self, true);
maybe_whole!(self, NtPat, |x| x);
let lt = self.expect_lifetime();
let (lit, _) =
self.recover_unclosed_char(lt.ident, Parser::mk_token_lit_char, |self_| {
- let expected = expected.unwrap_or("pattern");
+ let expected = Expected::to_string_or_fallback(expected);
let msg = format!(
"expected {}, found {}",
expected,
self.bump(); // `...`
// The user probably mistook `...` for a rest pattern `..`.
- self.struct_span_err(lo, "unexpected `...`")
- .span_label(lo, "not a valid pattern")
- .span_suggestion_short(
- lo,
- "for a rest pattern, use `..` instead of `...`",
- "..",
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(DotDotDotRestPattern { span: lo });
PatKind::Rest
}
// At this point we attempt to parse `@ $pat_rhs` and emit an error.
self.bump(); // `@`
let mut rhs = self.parse_pat_no_top_alt(None)?;
- let sp = lhs.span.to(rhs.span);
+ let whole_span = lhs.span.to(rhs.span);
if let PatKind::Ident(_, _, sub @ None) = &mut rhs.kind {
// The user inverted the order, so help them fix that.
// The RHS is now the full pattern.
*sub = Some(lhs);
- self.struct_span_err(sp, "pattern on wrong side of `@`")
- .span_label(lhs_span, "pattern on the left, should be on the right")
- .span_label(rhs.span, "binding on the right, should be on the left")
- .span_suggestion(
- sp,
- "switch the order",
- pprust::pat_to_string(&rhs),
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(PatternOnWrongSideOfAt {
+ whole_span,
+ whole_pat: pprust::pat_to_string(&rhs),
+ pattern: lhs_span,
+ binding: rhs.span,
+ });
} else {
// The special case above doesn't apply so we may have e.g. `A(x) @ B(y)`.
rhs.kind = PatKind::Wild;
- self.struct_span_err(sp, "left-hand side of `@` must be a binding")
- .span_label(lhs.span, "interpreted as a pattern, not a binding")
- .span_label(rhs.span, "also a pattern")
- .note("bindings are `x`, `mut x`, `ref x`, and `ref mut x`")
- .emit();
+ self.sess.emit_err(ExpectedBindingLeftOfAt {
+ whole_span,
+ lhs: lhs.span,
+ rhs: rhs.span,
+ });
}
- rhs.span = sp;
+ rhs.span = whole_span;
Ok(rhs)
}
_ => return,
}
- self.struct_span_err(pat.span, "the range pattern here has ambiguous interpretation")
- .span_suggestion(
- pat.span,
- "add parentheses to clarify the precedence",
- format!("({})", pprust::pat_to_string(&pat)),
- // "ambiguous interpretation" implies that we have to be guessing
- Applicability::MaybeIncorrect,
- )
- .emit();
+ self.sess
+ .emit_err(AmbiguousRangePattern { span: pat.span, pat: pprust::pat_to_string(&pat) });
}
/// Parse `&pat` / `&mut pat`.
- fn parse_pat_deref(&mut self, expected: Expected) -> PResult<'a, PatKind> {
+ fn parse_pat_deref(&mut self, expected: Option<Expected>) -> PResult<'a, PatKind> {
self.expect_and()?;
- self.recover_lifetime_in_deref_pat();
- let mutbl = self.parse_mutability();
- let subpat = self.parse_pat_with_range_pat(false, expected)?;
- Ok(PatKind::Ref(subpat, mutbl))
- }
-
- fn recover_lifetime_in_deref_pat(&mut self) {
if let token::Lifetime(name) = self.token.kind {
self.bump(); // `'a`
- let span = self.prev_token.span;
- self.struct_span_err(span, &format!("unexpected lifetime `{}` in pattern", name))
- .span_suggestion(span, "remove the lifetime", "", Applicability::MachineApplicable)
- .emit();
+ self.sess
+ .emit_err(UnexpectedLifetimeInPattern { span: self.prev_token.span, symbol: name });
}
+
+ let mutbl = self.parse_mutability();
+ let subpat = self.parse_pat_with_range_pat(false, expected)?;
+ Ok(PatKind::Ref(subpat, mutbl))
}
/// Parse a tuple or parenthesis pattern.
let mut_span = self.prev_token.span;
if self.eat_keyword(kw::Ref) {
- return self.recover_mut_ref_ident(mut_span);
+ self.sess.emit_err(RefMutOrderIncorrect { span: mut_span.to(self.prev_token.span) });
+ return self.parse_pat_ident(BindingAnnotation::REF_MUT);
}
self.recover_additional_muts();
}
// Parse the pattern we hope to be an identifier.
- let mut pat = self.parse_pat_no_top_alt(Some("identifier"))?;
+ let mut pat = self.parse_pat_no_top_alt(Some(Expected::Identifier))?;
// If we don't have `mut $ident (@ pat)?`, error.
if let PatKind::Ident(BindingAnnotation(ByRef::No, m @ Mutability::Not), ..) = &mut pat.kind
Ok(pat.into_inner().kind)
}
- /// Recover on `mut ref? ident @ pat` and suggest
- /// that the order of `mut` and `ref` is incorrect.
- fn recover_mut_ref_ident(&mut self, lo: Span) -> PResult<'a, PatKind> {
- let mutref_span = lo.to(self.prev_token.span);
- self.struct_span_err(mutref_span, "the order of `mut` and `ref` is incorrect")
- .span_suggestion(
- mutref_span,
- "try switching the order",
- "ref mut",
- Applicability::MachineApplicable,
- )
- .emit();
-
- self.parse_pat_ident(BindingAnnotation::REF_MUT)
- }
-
/// Turn all by-value immutable bindings in a pattern into mutable bindings.
/// Returns `true` if any change was made.
fn make_all_value_bindings_mutable(pat: &mut P<Pat>) -> bool {
/// Error on `mut $pat` where `$pat` is not an ident.
fn ban_mut_general_pat(&self, lo: Span, pat: &Pat, changed_any_binding: bool) {
let span = lo.to(pat.span);
- let fix = pprust::pat_to_string(&pat);
- let (problem, suggestion) = if changed_any_binding {
- ("`mut` must be attached to each individual binding", "add `mut` to each binding")
+ let pat = pprust::pat_to_string(&pat);
+
+ self.sess.emit_err(if changed_any_binding {
+ InvalidMutInPattern::NestedIdent { span, pat }
} else {
- ("`mut` must be followed by a named binding", "remove the `mut` prefix")
- };
- self.struct_span_err(span, problem)
- .span_suggestion(span, suggestion, fix, Applicability::MachineApplicable)
- .note("`mut` may be followed by `variable` and `variable @ pattern`")
- .emit();
+ InvalidMutInPattern::NonIdent { span, pat }
+ });
}
/// Eat any extraneous `mut`s and error + recover if we ate any.
return;
}
- let span = lo.to(self.prev_token.span);
- self.struct_span_err(span, "`mut` on a binding may not be repeated")
- .span_suggestion(
- span,
- "remove the additional `mut`s",
- "",
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(RepeatedMutInPattern { span: lo.to(self.prev_token.span) });
}
/// Parse macro invocation
fn fatal_unexpected_non_pat(
&mut self,
err: DiagnosticBuilder<'a, ErrorGuaranteed>,
- expected: Expected,
+ expected: Option<Expected>,
) -> PResult<'a, P<Pat>> {
err.cancel();
- let expected = expected.unwrap_or("pattern");
+ let expected = Expected::to_string_or_fallback(expected);
let msg = format!("expected {}, found {}", expected, super::token_descr(&self.token));
let mut err = self.struct_span_err(self.token.span, &msg);
let _ = self.parse_pat_range_end().map_err(|e| e.cancel());
}
- self.error_inclusive_range_with_extra_equals(span_with_eq);
+ self.sess.emit_err(InclusiveRangeExtraEquals { span: span_with_eq });
}
token::Gt if no_space => {
- self.error_inclusive_range_match_arrow(span);
+ let after_pat = span.with_hi(span.hi() - rustc_span::BytePos(1)).shrink_to_hi();
+ self.sess.emit_err(InclusiveRangeMatchArrow { span, arrow: tok.span, after_pat });
+ }
+ _ => {
+ self.sess.emit_err(InclusiveRangeNoEnd { span });
}
- _ => self.error_inclusive_range_with_no_end(span),
}
}
- fn error_inclusive_range_with_extra_equals(&self, span: Span) {
- self.sess.emit_err(InclusiveRangeExtraEquals { span });
- }
-
- fn error_inclusive_range_match_arrow(&self, span: Span) {
- let after_pat = span.with_hi(span.hi() - rustc_span::BytePos(1)).shrink_to_hi();
- self.sess.emit_err(InclusiveRangeMatchArrow { span, after_pat });
- }
-
- fn error_inclusive_range_with_no_end(&self, span: Span) {
- self.sess.emit_err(InclusiveRangeNoEnd { span });
- }
-
/// Parse a range-to pattern, `..X` or `..=X` where `X` remains to be parsed.
///
/// The form `...X` is prohibited to reduce confusion with the potential
let end = self.parse_pat_range_end()?;
if let RangeEnd::Included(syn @ RangeSyntax::DotDotDot) = &mut re.node {
*syn = RangeSyntax::DotDotEq;
- self.struct_span_err(re.span, "range-to patterns with `...` are not allowed")
- .span_suggestion_short(
- re.span,
- "use `..=` instead",
- "..=",
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(DotDotDotRangeToPatternNotAllowed { span: re.span });
}
Ok(PatKind::Range(None, Some(end), re))
}
fn parse_pat_ident(&mut self, binding_annotation: BindingAnnotation) -> PResult<'a, PatKind> {
let ident = self.parse_ident()?;
let sub = if self.eat(&token::At) {
- Some(self.parse_pat_no_top_alt(Some("binding pattern"))?)
+ Some(self.parse_pat_no_top_alt(Some(Expected::BindingPattern))?)
} else {
None
};
// binding mode then we do not end up here, because the lookahead
// will direct us over to `parse_enum_variant()`.
if self.token == token::OpenDelim(Delimiter::Parenthesis) {
- return Err(self
- .struct_span_err(self.prev_token.span, "expected identifier, found enum pattern"));
+ return Err(EnumPatternInsteadOfIdentifier { span: self.prev_token.span }
+ .into_diagnostic(&self.sess.span_diagnostic));
}
Ok(PatKind::Ident(binding_annotation, ident, sub))
// We cannot use `parse_pat_ident()` since it will complain `box`
// is not an identifier.
let sub = if self.eat(&token::At) {
- Some(self.parse_pat_no_top_alt(Some("binding pattern"))?)
+ Some(self.parse_pat_no_top_alt(Some(Expected::BindingPattern))?)
} else {
None
};
// check that a comma comes after every field
if !ate_comma {
- let err = self.struct_span_err(self.token.span, "expected `,`");
+ let err = ExpectedCommaAfterPatternField { span: self.token.span }
+ .into_diagnostic(&self.sess.span_diagnostic);
if let Some(mut delayed) = delayed_err {
delayed.emit();
}
}
ate_comma = false;
- if self.check(&token::DotDot) || self.token == token::DotDotDot {
+ if self.check(&token::DotDot)
+ || self.check_noexpect(&token::DotDotDot)
+ || self.check_keyword(kw::Underscore)
+ {
etc = true;
let mut etc_sp = self.token.span;
- self.recover_one_fewer_dotdot();
- self.bump(); // `..` || `...`
+ self.recover_bad_dot_dot();
+ self.bump(); // `..` || `...` || `_`
if self.token == token::CloseDelim(Delimiter::Brace) {
etc_span = Some(etc_sp);
Ok((fields, etc))
}
- /// Recover on `...` as if it were `..` to avoid further errors.
+ /// Recover on `...` or `_` as if it were `..` to avoid further errors.
/// See issue #46718.
- fn recover_one_fewer_dotdot(&self) {
- if self.token != token::DotDotDot {
+ fn recover_bad_dot_dot(&self) {
+ if self.token == token::DotDot {
return;
}
- self.struct_span_err(self.token.span, "expected field pattern, found `...`")
- .span_suggestion(
- self.token.span,
- "to omit remaining fields, use one fewer `.`",
- "..",
- Applicability::MachineApplicable,
- )
- .emit();
+ let token_str = pprust::token_to_string(&self.token);
+ self.sess.emit_err(DotDotDotForRemainingFields { span: self.token.span, token_str });
}
fn parse_pat_field(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, PatField> {
use super::attr::InnerAttrForbiddenReason;
use super::diagnostics::AttemptLocalParseRecovery;
use super::expr::LhsExpr;
-use super::pat::RecoverComma;
+use super::pat::{PatternLocation, RecoverComma};
use super::path::PathStyle;
use super::TrailingToken;
use super::{
AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode,
};
-use crate::errors::{
- AssignmentElseNotAllowed, CompoundAssignmentExpressionInLet, ConstLetMutuallyExclusive,
- DocCommentDoesNotDocumentAnything, ExpectedStatementAfterOuterAttr, InvalidCurlyInLetElse,
- InvalidExpressionInLetElse, InvalidIdentiferStartsWithNumber, InvalidVariableDeclaration,
- InvalidVariableDeclarationSub, WrapExpressionInParentheses,
-};
+use crate::errors;
use crate::maybe_whole;
use rustc_ast as ast;
if self.token.is_keyword(kw::Mut) && self.is_keyword_ahead(1, &[kw::Let]) {
self.bump();
let mut_let_span = lo.to(self.token.span);
- self.sess.emit_err(InvalidVariableDeclaration {
+ self.sess.emit_err(errors::InvalidVariableDeclaration {
span: mut_let_span,
- sub: InvalidVariableDeclarationSub::SwitchMutLetOrder(mut_let_span),
+ sub: errors::InvalidVariableDeclarationSub::SwitchMutLetOrder(mut_let_span),
});
}
Ok(Some(if self.token.is_keyword(kw::Let) {
self.parse_local_mk(lo, attrs, capture_semi, force_collect)?
} else if self.is_kw_followed_by_ident(kw::Mut) && self.may_recover() {
- self.recover_stmt_local_after_let(lo, attrs, InvalidVariableDeclarationSub::MissingLet)?
+ self.recover_stmt_local_after_let(
+ lo,
+ attrs,
+ errors::InvalidVariableDeclarationSub::MissingLet,
+ )?
} else if self.is_kw_followed_by_ident(kw::Auto) && self.may_recover() {
self.bump(); // `auto`
self.recover_stmt_local_after_let(
lo,
attrs,
- InvalidVariableDeclarationSub::UseLetNotAuto,
+ errors::InvalidVariableDeclarationSub::UseLetNotAuto,
)?
} else if self.is_kw_followed_by_ident(sym::var) && self.may_recover() {
self.bump(); // `var`
self.recover_stmt_local_after_let(
lo,
attrs,
- InvalidVariableDeclarationSub::UseLetNotVar,
+ errors::InvalidVariableDeclarationSub::UseLetNotVar,
)?
} else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() {
// We have avoided contextual keywords like `union`, items with `crate` visibility,
// or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something
// that starts like a path (1 token), but it fact not a path.
// Also, we avoid stealing syntax from `parse_item_`.
- if force_collect == ForceCollect::Yes {
- self.collect_tokens_no_attrs(|this| this.parse_stmt_path_start(lo, attrs))
- } else {
- self.parse_stmt_path_start(lo, attrs)
- }?
+ match force_collect {
+ ForceCollect::Yes => {
+ self.collect_tokens_no_attrs(|this| this.parse_stmt_path_start(lo, attrs))?
+ }
+ ForceCollect::No => self.parse_stmt_path_start(lo, attrs)?,
+ }
} else if let Some(item) = self.parse_item_common(
attrs.clone(),
false,
self.mk_stmt(lo, StmtKind::Empty)
} else if self.token != token::CloseDelim(Delimiter::Brace) {
// Remainder are line-expr stmts.
- let e = if force_collect == ForceCollect::Yes {
- self.collect_tokens_no_attrs(|this| {
+ let e = match force_collect {
+ ForceCollect::Yes => self.collect_tokens_no_attrs(|this| {
this.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs))
- })
- } else {
- self.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs))
- }?;
+ })?,
+ ForceCollect::No => self.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs))?,
+ };
if matches!(e.kind, ExprKind::Assign(..)) && self.eat_keyword(kw::Else) {
let bl = self.parse_block()?;
// Destructuring assignment ... else.
// This is not allowed, but point it out in a nice way.
- self.sess.emit_err(AssignmentElseNotAllowed { span: e.span.to(bl.span) });
+ self.sess.emit_err(errors::AssignmentElseNotAllowed { span: e.span.to(bl.span) });
}
self.mk_stmt(lo.to(e.span), StmtKind::Expr(e))
} else {
&& let attrs = attrs.take_for_recovery(self.sess)
&& let attrs @ [.., last] = &*attrs {
if last.is_doc_comment() {
- self.sess.emit_err(DocCommentDoesNotDocumentAnything {
+ self.sess.emit_err(errors::DocCommentDoesNotDocumentAnything {
span: last.span,
missing_comma: None,
});
} else if attrs.iter().any(|a| a.style == AttrStyle::Outer) {
- self.sess.emit_err(ExpectedStatementAfterOuterAttr { span: last.span });
+ self.sess.emit_err(errors::ExpectedStatementAfterOuterAttr { span: last.span });
}
}
}
&mut self,
lo: Span,
attrs: AttrWrapper,
- subdiagnostic: fn(Span) -> InvalidVariableDeclarationSub,
+ subdiagnostic: fn(Span) -> errors::InvalidVariableDeclarationSub,
) -> PResult<'a, Stmt> {
let stmt =
self.collect_tokens_trailing_token(attrs, ForceCollect::Yes, |this, attrs| {
TrailingToken::None,
))
})?;
- self.sess.emit_err(InvalidVariableDeclaration { span: lo, sub: subdiagnostic(lo) });
+ self.sess.emit_err(errors::InvalidVariableDeclaration { span: lo, sub: subdiagnostic(lo) });
Ok(stmt)
}
let lo = self.prev_token.span;
if self.token.is_keyword(kw::Const) && self.look_ahead(1, |t| t.is_ident()) {
- self.sess.emit_err(ConstLetMutuallyExclusive { span: lo.to(self.token.span) });
+ self.sess.emit_err(errors::ConstLetMutuallyExclusive { span: lo.to(self.token.span) });
self.bump();
}
self.report_invalid_identifier_error()?;
- let (pat, colon) = self.parse_pat_before_ty(None, RecoverComma::Yes, "`let` bindings")?;
+ let (pat, colon) =
+ self.parse_pat_before_ty(None, RecoverComma::Yes, PatternLocation::LetBinding)?;
let (err, ty) = if colon {
// Save the state of the parser before parsing type normally, in case there is a `:`
rustc_ast::MetaItemLit::from_token(&self.token).is_none() &&
(lit.kind == token::LitKind::Integer || lit.kind == token::LitKind::Float) &&
self.look_ahead(1, |t| matches!(t.kind, token::Eq) || matches!(t.kind, token::Colon ) ) {
- return Err(self.sess.create_err(InvalidIdentiferStartsWithNumber { span: self.token.span }));
+ return Err(self.sess.create_err(errors::InvalidIdentiferStartsWithNumber { span: self.token.span }));
}
Ok(())
}
fn check_let_else_init_bool_expr(&self, init: &ast::Expr) {
if let ast::ExprKind::Binary(op, ..) = init.kind {
if op.node.lazy() {
- self.sess.emit_err(InvalidExpressionInLetElse {
+ self.sess.emit_err(errors::InvalidExpressionInLetElse {
span: init.span,
operator: op.node.to_string(),
- sugg: WrapExpressionInParentheses {
+ sugg: errors::WrapExpressionInParentheses {
left: init.span.shrink_to_lo(),
right: init.span.shrink_to_hi(),
},
fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) {
if let Some(trailing) = classify::expr_trailing_brace(init) {
- self.sess.emit_err(InvalidCurlyInLetElse {
+ self.sess.emit_err(errors::InvalidCurlyInLetElse {
span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)),
- sugg: WrapExpressionInParentheses {
+ sugg: errors::WrapExpressionInParentheses {
left: trailing.span.shrink_to_lo(),
right: trailing.span.shrink_to_hi(),
},
let eq_consumed = match self.token.kind {
token::BinOpEq(..) => {
// Recover `let x <op>= 1` as `let x = 1`
- self.sess.emit_err(CompoundAssignmentExpressionInLet { span: self.token.span });
+ self.sess
+ .emit_err(errors::CompoundAssignmentExpressionInLet { span: self.token.span });
self.bump();
true
}
use super::{Parser, PathStyle, TokenType};
-use crate::errors::{ExpectedFnPathFoundFnKeyword, FnPtrWithGenerics, FnPtrWithGenericsSugg};
+use crate::errors::{
+ DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
+ FnPointerCannotBeAsync, FnPointerCannotBeConst, FnPtrWithGenerics, FnPtrWithGenericsSugg,
+ InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
+ NegativeBoundsNotSupported, NegativeBoundsNotSupportedSugg, NestedCVariadicType,
+ ReturnTypesUseThinArrow,
+};
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
use ast::DUMMY_NODE_ID;
self as ast, BareFnTy, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime,
MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, Ty, TyKind,
};
-use rustc_ast_pretty::pprust;
-use rustc_errors::{pluralize, struct_span_err, Applicability, PResult};
+use rustc_errors::{Applicability, PResult};
use rustc_span::source_map::Span;
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Symbol;
No,
}
-#[derive(PartialEq, Clone, Copy)]
+#[derive(PartialEq)]
pub(super) enum RecoverQPath {
Yes,
No,
}
-#[derive(PartialEq, Clone, Copy)]
pub(super) enum RecoverQuestionMark {
Yes,
No,
}
-#[derive(PartialEq, Clone, Copy)]
-pub(super) enum RecoverAnonEnum {
- Yes,
- No,
-}
-
/// Signals whether parsing a type should recover `->`.
///
/// More specifically, when parsing a function like:
}
// Is `...` (`CVarArgs`) legal at this level of type parsing?
-#[derive(PartialEq, Clone, Copy)]
+#[derive(PartialEq)]
enum AllowCVariadic {
Yes,
No,
RecoverReturnSign::Yes,
None,
RecoverQuestionMark::Yes,
- RecoverAnonEnum::No,
)
}
RecoverReturnSign::Yes,
Some(ty_params),
RecoverQuestionMark::Yes,
- RecoverAnonEnum::No,
)
}
RecoverReturnSign::Yes,
None,
RecoverQuestionMark::Yes,
- RecoverAnonEnum::Yes,
)
}
RecoverReturnSign::Yes,
None,
RecoverQuestionMark::Yes,
- RecoverAnonEnum::No,
)
}
RecoverReturnSign::Yes,
None,
RecoverQuestionMark::No,
- RecoverAnonEnum::No,
)
}
RecoverReturnSign::Yes,
None,
RecoverQuestionMark::No,
- RecoverAnonEnum::No,
)
}
RecoverReturnSign::OnlyFatArrow,
None,
RecoverQuestionMark::Yes,
- RecoverAnonEnum::No,
)
}
recover_return_sign,
None,
RecoverQuestionMark::Yes,
- RecoverAnonEnum::Yes,
)?;
FnRetTy::Ty(ty)
} else if recover_return_sign.can_recover(&self.token.kind) {
// Don't `eat` to prevent `=>` from being added as an expected token which isn't
// actually expected and could only confuse users
self.bump();
- self.struct_span_err(self.prev_token.span, "return types are denoted using `->`")
- .span_suggestion_short(
- self.prev_token.span,
- "use `->` instead",
- "->",
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(ReturnTypesUseThinArrow { span: self.prev_token.span });
let ty = self.parse_ty_common(
allow_plus,
AllowCVariadic::No,
recover_return_sign,
None,
RecoverQuestionMark::Yes,
- RecoverAnonEnum::Yes,
)?;
FnRetTy::Ty(ty)
} else {
recover_return_sign: RecoverReturnSign,
ty_generics: Option<&Generics>,
recover_question_mark: RecoverQuestionMark,
- recover_anon_enum: RecoverAnonEnum,
) -> PResult<'a, P<Ty>> {
let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
} else if self.can_begin_bound() {
self.parse_bare_trait_object(lo, allow_plus)?
} else if self.eat(&token::DotDotDot) {
- if allow_c_variadic == AllowCVariadic::Yes {
- TyKind::CVarArgs
- } else {
- // FIXME(Centril): Should we just allow `...` syntactically
- // anywhere in a type and use semantic restrictions instead?
- self.error_illegal_c_varadic_ty(lo);
- TyKind::Err
+ match allow_c_variadic {
+ AllowCVariadic::Yes => TyKind::CVarArgs,
+ AllowCVariadic::No => {
+ // FIXME(Centril): Should we just allow `...` syntactically
+ // anywhere in a type and use semantic restrictions instead?
+ self.sess.emit_err(NestedCVariadicType { span: lo.to(self.prev_token.span) });
+ TyKind::Err
+ }
}
} else {
let msg = format!("expected type, found {}", super::token_descr(&self.token));
let mut ty = self.mk_ty(span, kind);
// Try to recover from use of `+` with incorrect priority.
- if allow_plus == AllowPlus::Yes {
- self.maybe_recover_from_bad_type_plus(&ty)?;
- } else {
- self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty);
+ match allow_plus {
+ AllowPlus::Yes => self.maybe_recover_from_bad_type_plus(&ty)?,
+ AllowPlus::No => self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty),
}
- if RecoverQuestionMark::Yes == recover_question_mark {
+ if let RecoverQuestionMark::Yes = recover_question_mark {
ty = self.maybe_recover_from_question_mark(ty);
}
- if recover_anon_enum == RecoverAnonEnum::Yes
- && self.check_noexpect(&token::BinOp(token::Or))
- && self.look_ahead(1, |t| t.can_begin_type())
- {
- let mut pipes = vec![self.token.span];
- let mut types = vec![ty];
- loop {
- if !self.eat(&token::BinOp(token::Or)) {
- break;
- }
- pipes.push(self.prev_token.span);
- types.push(self.parse_ty_common(
- allow_plus,
- allow_c_variadic,
- recover_qpath,
- recover_return_sign,
- ty_generics,
- recover_question_mark,
- RecoverAnonEnum::No,
- )?);
- }
- let mut err = self.struct_span_err(pipes, "anonymous enums are not supported");
- for ty in &types {
- err.span_label(ty.span, "");
- }
- err.help(&format!(
- "create a named `enum` and use it here instead:\nenum Name {{\n{}\n}}",
- types
- .iter()
- .enumerate()
- .map(|(i, t)| format!(
- " Variant{}({}),",
- i + 1, // Lets not confuse people with zero-indexing :)
- pprust::to_string(|s| s.print_type(&t)),
- ))
- .collect::<Vec<_>>()
- .join("\n"),
- ));
- err.emit();
- return Ok(self.mk_ty(lo.to(self.prev_token.span), TyKind::Err));
- }
if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }
}
let lt_no_plus = self.check_lifetime() && !self.look_ahead(1, |t| t.is_like_plus());
let bounds = self.parse_generic_bounds_common(allow_plus, None)?;
if lt_no_plus {
- self.struct_span_err(lo, "lifetime in trait object type must be followed by `+`")
- .emit();
+ self.sess.emit_err(NeedPlusAfterTraitObjectLifetime { span: lo });
}
Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
}
fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
let span = self.prev_token.span;
- self.struct_span_err(span, "expected `mut` or `const` keyword in raw pointer type")
- .span_suggestions(
- span.shrink_to_hi(),
- "add `mut` or `const` here",
- ["mut ".to_string(), "const ".to_string()],
- Applicability::HasPlaceholders,
- )
- .emit();
+ self.sess.emit_err(ExpectedMutOrConstInRawPointerType {
+ span,
+ after_asterisk: span.shrink_to_hi(),
+ });
Mutability::Not
});
let ty = self.parse_ty_no_plus()?;
let lifetime_span = self.token.span;
let span = and_span.to(lifetime_span);
- let mut err = self.struct_span_err(span, "lifetime must precede `mut`");
- if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
- err.span_suggestion(
- span,
- "place the lifetime before `mut`",
- format!("&{} mut", lifetime_src),
- Applicability::MaybeIncorrect,
- );
- }
- err.emit();
+ let (suggest_lifetime, snippet) =
+ if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
+ (Some(span), lifetime_src)
+ } else {
+ (None, String::new())
+ };
+ self.sess.emit_err(LifetimeAfterMut { span, suggest_lifetime, snippet });
opt_lifetime = Some(self.expect_lifetime());
}
{
// We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`.
let span = and_span.to(self.look_ahead(1, |t| t.span));
- let mut err = self.struct_span_err(span, "`mut` must precede `dyn`");
- err.span_suggestion(
- span,
- "place `mut` before `dyn`",
- "&mut dyn",
- Applicability::MachineApplicable,
- );
- err.emit();
+ self.sess.emit_err(DynAfterMut { span });
// Recovery
mutbl = Mutability::Mut;
// If we ever start to allow `const fn()`, then update
// feature gating for `#![feature(const_extern_fn)]` to
// cover it.
- self.error_fn_ptr_bad_qualifier(whole_span, span, "const");
+ self.sess.emit_err(FnPointerCannotBeConst { span: whole_span, qualifier: span });
}
if let ast::Async::Yes { span, .. } = asyncness {
- self.error_fn_ptr_bad_qualifier(whole_span, span, "async");
+ self.sess.emit_err(FnPointerCannotBeAsync { span: whole_span, qualifier: span });
}
let decl_span = span_start.to(self.token.span);
Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params: params, decl, decl_span })))
Ok(())
}
- /// Emit an error for the given bad function pointer qualifier.
- fn error_fn_ptr_bad_qualifier(&self, span: Span, qual_span: Span, qual: &str) {
- self.struct_span_err(span, &format!("an `fn` pointer type cannot be `{}`", qual))
- .span_label(qual_span, format!("`{}` because of this", qual))
- .span_suggestion_short(
- qual_span,
- &format!("remove the `{}` qualifier", qual),
- "",
- Applicability::MaybeIncorrect,
- )
- .emit();
- }
-
/// Parses an `impl B0 + ... + Bn` type.
fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
// Always parse bounds greedily for better error recovery.
/// Is a `dyn B0 + ... + Bn` type allowed here?
fn is_explicit_dyn_type(&mut self) -> bool {
self.check_keyword(kw::Dyn)
- && (!self.token.uninterpolated_span().rust_2015()
+ && (self.token.uninterpolated_span().rust_2018()
|| self.look_ahead(1, |t| {
(t.can_begin_bound() || t.kind == TokenKind::BinOp(token::Star))
&& !can_continue_type_after_non_fn_ident(t)
}
}
- fn error_illegal_c_varadic_ty(&self, lo: Span) {
- struct_span_err!(
- self.sess.span_diagnostic,
- lo.to(self.prev_token.span),
- E0743,
- "C-variadic type `...` may not be nested inside another type",
- )
- .emit();
- }
-
pub(super) fn parse_generic_bounds(
&mut self,
colon_span: Option<Span>,
{
if self.token.is_keyword(kw::Dyn) {
// Account for `&dyn Trait + dyn Other`.
- self.struct_span_err(self.token.span, "invalid `dyn` keyword")
- .help("`dyn` is only needed at the start of a trait `+`-separated list")
- .span_suggestion(
- self.token.span,
- "remove this keyword",
- "",
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(InvalidDynKeyword { span: self.token.span });
self.bump();
}
match self.parse_generic_bound()? {
bounds: &[GenericBound],
negative_bounds: Vec<Span>,
) {
- let negative_bounds_len = negative_bounds.len();
- let last_span = *negative_bounds.last().expect("no negative bounds, but still error?");
- let mut err = self.struct_span_err(negative_bounds, "negative bounds are not supported");
- err.span_label(last_span, "negative bounds are not supported");
- if let Some(bound_list) = colon_span {
+ let sub = if let Some(bound_list) = colon_span {
let bound_list = bound_list.to(self.prev_token.span);
let mut new_bound_list = String::new();
if !bounds.is_empty() {
}
new_bound_list = new_bound_list.replacen(" +", ":", 1);
}
- err.tool_only_span_suggestion(
+
+ Some(NegativeBoundsNotSupportedSugg {
bound_list,
- &format!("remove the bound{}", pluralize!(negative_bounds_len)),
- new_bound_list,
- Applicability::MachineApplicable,
- );
- }
- err.emit();
+ num_bounds: negative_bounds.len(),
+ fixed: new_bound_list,
+ })
+ } else {
+ None
+ };
+
+ let last_span = *negative_bounds.last().expect("no negative bounds, but still error?");
+ self.sess.emit_err(NegativeBoundsNotSupported { negative_bounds, last_span, sub });
}
/// Parses a bound according to the grammar:
);
}
} else {
- self.suggest_positional_arg_instead_of_captured_arg(arg);
+ if let Some(&(_, maybe)) = self.cur.peek() {
+ if maybe == '?' {
+ self.suggest_format();
+ } else {
+ self.suggest_positional_arg_instead_of_captured_arg(arg);
+ }
+ }
}
Some(NextArgument(Box::new(arg)))
}
if found { Some(cur) } else { None }
}
+ fn suggest_format(&mut self) {
+ if let (Some(pos), Some(_)) = (self.consume_pos('?'), self.consume_pos(':')) {
+ let word = self.word();
+ let _end = self.current_pos();
+ let pos = self.to_span_index(pos);
+ self.errors.insert(
+ 0,
+ ParseError {
+ description: "expected format parameter to occur after `:`".to_owned(),
+ note: Some(
+ format!("`?` comes after `:`, try `{}:{}` instead", word, "?").to_owned(),
+ ),
+ label: "expected `?` to occur after `:`".to_owned(),
+ span: pos.to(pos),
+ secondary_label: None,
+ should_be_replaced_with_positional_argument: false,
+ },
+ );
+ }
+ }
+
fn suggest_positional_arg_instead_of_captured_arg(&mut self, arg: Argument<'a>) {
if let Some(end) = self.consume_pos('.') {
let byte_pos = self.to_span_index(end);
//! conflicts between multiple such attributes attached to the same
//! item.
-use crate::errors::{
- self, AttrApplication, DebugVisualizerUnreadable, InvalidAttrAtCrateLevel, ObjectLifetimeErr,
- OnlyHasEffectOn, ProcMacroDiffArguments, ProcMacroInvalidAbi, ProcMacroMissingArguments,
- ProcMacroTypeError, ProcMacroUnsafe, TransparentIncompatible, UnrecognizedReprHint,
-};
+use crate::errors;
use rustc_ast::{ast, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{fluent, Applicability, IntoDiagnosticArg, MultiSpan};
sym::rustc_has_incoherent_inherent_impls => {
self.check_has_incoherent_inherent_impls(&attr, span, target)
}
+ sym::ffi_pure => self.check_ffi_pure(attr.span, attrs, target),
+ sym::ffi_const => self.check_ffi_const(attr.span, target),
+ sym::ffi_returns_twice => self.check_ffi_returns_twice(attr.span, target),
sym::rustc_const_unstable
| sym::rustc_const_stable
| sym::unstable
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
- OnlyHasEffectOn {
+ errors::OnlyHasEffectOn {
attr_name: attr.name_or_empty(),
target_name: allowed_target.name().replace(' ', "_"),
},
ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(),
ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(),
};
- tcx.sess.emit_err(ObjectLifetimeErr { span: p.span, repr });
+ tcx.sess.emit_err(errors::ObjectLifetimeErr { span: p.span, repr });
}
}
}
target: Target,
specified_inline: &mut Option<(bool, Span)>,
) -> bool {
- if target == Target::Use || target == Target::ExternCrate {
- let do_inline = meta.name_or_empty() == sym::inline;
- if let Some((prev_inline, prev_span)) = *specified_inline {
- if do_inline != prev_inline {
- let mut spans = MultiSpan::from_spans(vec![prev_span, meta.span()]);
- spans.push_span_label(prev_span, fluent::passes_doc_inline_conflict_first);
- spans.push_span_label(meta.span(), fluent::passes_doc_inline_conflict_second);
- self.tcx.sess.emit_err(errors::DocKeywordConflict { spans });
- return false;
+ match target {
+ Target::Use | Target::ExternCrate => {
+ let do_inline = meta.name_or_empty() == sym::inline;
+ if let Some((prev_inline, prev_span)) = *specified_inline {
+ if do_inline != prev_inline {
+ let mut spans = MultiSpan::from_spans(vec![prev_span, meta.span()]);
+ spans.push_span_label(prev_span, fluent::passes_doc_inline_conflict_first);
+ spans.push_span_label(
+ meta.span(),
+ fluent::passes_doc_inline_conflict_second,
+ );
+ self.tcx.sess.emit_err(errors::DocKeywordConflict { spans });
+ return false;
+ }
+ true
+ } else {
+ *specified_inline = Some((do_inline, meta.span()));
+ true
}
- true
- } else {
- *specified_inline = Some((do_inline, meta.span()));
- true
}
- } else {
- self.tcx.emit_spanned_lint(
- INVALID_DOC_ATTRIBUTES,
- hir_id,
- meta.span(),
- errors::DocInlineOnlyUse {
- attr_span: meta.span(),
- item_span: (attr.style == AttrStyle::Outer)
- .then(|| self.tcx.hir().span(hir_id)),
- },
- );
- false
+ _ => {
+ self.tcx.emit_spanned_lint(
+ INVALID_DOC_ATTRIBUTES,
+ hir_id,
+ meta.span(),
+ errors::DocInlineOnlyUse {
+ attr_span: meta.span(),
+ item_span: (attr.style == AttrStyle::Outer)
+ .then(|| self.tcx.hir().span(hir_id)),
+ },
+ );
+ false
+ }
}
}
errors::DocTestUnknownInclude {
path,
value: value.to_string(),
- inner: if attr.style == AttrStyle::Inner { "!" } else { "" },
+ inner: match attr.style { AttrStyle::Inner=> "!" , AttrStyle::Outer => "" },
sugg: (attr.meta().unwrap().span, applicability),
}
);
}
}
+ fn check_ffi_pure(&self, attr_span: Span, attrs: &[Attribute], target: Target) -> bool {
+ if target != Target::ForeignFn {
+ self.tcx.sess.emit_err(errors::FfiPureInvalidTarget { attr_span });
+ return false;
+ }
+ if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
+ // `#[ffi_const]` functions cannot be `#[ffi_pure]`
+ self.tcx.sess.emit_err(errors::BothFfiConstAndPure { attr_span });
+ false
+ } else {
+ true
+ }
+ }
+
+ fn check_ffi_const(&self, attr_span: Span, target: Target) -> bool {
+ if target == Target::ForeignFn {
+ true
+ } else {
+ self.tcx.sess.emit_err(errors::FfiConstInvalidTarget { attr_span });
+ false
+ }
+ }
+
+ fn check_ffi_returns_twice(&self, attr_span: Span, target: Target) -> bool {
+ if target == Target::ForeignFn {
+ true
+ } else {
+ self.tcx.sess.emit_err(errors::FfiReturnsTwiceInvalidTarget { attr_span });
+ false
+ }
+ }
+
/// Warns against some misuses of `#[must_use]`
fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) -> bool {
if !matches!(
match target {
Target::Struct | Target::Union | Target::Enum => continue,
_ => {
- self.tcx.sess.emit_err(AttrApplication::StructEnumUnion {
+ self.tcx.sess.emit_err(errors::AttrApplication::StructEnumUnion {
hint_span: hint.span(),
span,
});
match target {
Target::Struct | Target::Union | Target::Enum | Target::Fn => continue,
_ => {
- self.tcx.sess.emit_err(AttrApplication::StructEnumFunctionUnion {
- hint_span: hint.span(),
- span,
- });
+ self.tcx.sess.emit_err(
+ errors::AttrApplication::StructEnumFunctionUnion {
+ hint_span: hint.span(),
+ span,
+ },
+ );
}
}
}
sym::packed => {
if target != Target::Struct && target != Target::Union {
- self.tcx.sess.emit_err(AttrApplication::StructUnion {
+ self.tcx.sess.emit_err(errors::AttrApplication::StructUnion {
hint_span: hint.span(),
span,
});
sym::simd => {
is_simd = true;
if target != Target::Struct {
- self.tcx
- .sess
- .emit_err(AttrApplication::Struct { hint_span: hint.span(), span });
+ self.tcx.sess.emit_err(errors::AttrApplication::Struct {
+ hint_span: hint.span(),
+ span,
+ });
} else {
continue;
}
match target {
Target::Struct | Target::Union | Target::Enum => continue,
_ => {
- self.tcx.sess.emit_err(AttrApplication::StructEnumUnion {
+ self.tcx.sess.emit_err(errors::AttrApplication::StructEnumUnion {
hint_span: hint.span(),
span,
});
| sym::usize => {
int_reprs += 1;
if target != Target::Enum {
- self.tcx
- .sess
- .emit_err(AttrApplication::Enum { hint_span: hint.span(), span });
+ self.tcx.sess.emit_err(errors::AttrApplication::Enum {
+ hint_span: hint.span(),
+ span,
+ });
} else {
continue;
}
}
_ => {
- self.tcx.sess.emit_err(UnrecognizedReprHint { span: hint.span() });
+ self.tcx.sess.emit_err(errors::UnrecognizedReprHint { span: hint.span() });
continue;
}
};
// Error on repr(transparent, <anything else>).
if is_transparent && hints.len() > 1 {
let hint_spans: Vec<_> = hint_spans.clone().collect();
- self.tcx
- .sess
- .emit_err(TransparentIncompatible { hint_spans, target: target.to_string() });
+ self.tcx.sess.emit_err(errors::TransparentIncompatible {
+ hint_spans,
+ target: target.to_string(),
+ });
}
// Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
if (int_reprs > 1)
match std::fs::File::open(&file) {
Ok(_) => true,
Err(error) => {
- self.tcx.sess.emit_err(DebugVisualizerUnreadable {
+ self.tcx.sess.emit_err(errors::DebugVisualizerUnreadable {
span: meta_item.span,
file: &file,
error,
let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer };
if sig.abi != Abi::Rust {
- tcx.sess.emit_err(ProcMacroInvalidAbi { span: hir_sig.span, abi: sig.abi.name() });
+ tcx.sess.emit_err(errors::ProcMacroInvalidAbi {
+ span: hir_sig.span,
+ abi: sig.abi.name(),
+ });
self.abort.set(true);
}
if sig.unsafety == Unsafety::Unsafe {
- tcx.sess.emit_err(ProcMacroUnsafe { span: hir_sig.span });
+ tcx.sess.emit_err(errors::ProcMacroUnsafe { span: hir_sig.span });
self.abort.set(true);
}
// Typecheck the output
if !drcx.types_may_unify(output, tokenstream) {
- tcx.sess.emit_err(ProcMacroTypeError {
+ tcx.sess.emit_err(errors::ProcMacroTypeError {
span: hir_sig.decl.output.span(),
found: output,
kind,
}
if sig.inputs().len() < expected_input_count {
- tcx.sess.emit_err(ProcMacroMissingArguments {
+ tcx.sess.emit_err(errors::ProcMacroMissingArguments {
expected_input_count,
span: hir_sig.span,
kind,
sig.inputs().iter().zip(hir_sig.decl.inputs).take(expected_input_count)
{
if !drcx.types_may_unify(*arg, tokenstream) {
- tcx.sess.emit_err(ProcMacroTypeError {
+ tcx.sess.emit_err(errors::ProcMacroTypeError {
span: input.span,
found: *arg,
kind,
let body_id = tcx.hir().body_owned_by(id.def_id);
let excess = tcx.hir().body(body_id).params.get(expected_input_count..);
if let Some(excess @ [begin @ end] | excess @ [begin, .., end]) = excess {
- tcx.sess.emit_err(ProcMacroDiffArguments {
+ tcx.sess.emit_err(errors::ProcMacroDiffArguments {
span: begin.span.to(end.span),
count: excess.len(),
kind,
if attr.style == AttrStyle::Inner {
for attr_to_check in ATTRS_TO_CHECK {
if attr.has_name(*attr_to_check) {
- tcx.sess.emit_err(InvalidAttrAtCrateLevel {
+ tcx.sess.emit_err(errors::InvalidAttrAtCrateLevel {
span: attr.span,
snippet: tcx.sess.source_map().span_to_snippet(attr.span).ok(),
name: *attr_to_check,
use rustc_session::parse::feature_err;
use rustc_span::{sym, Span, Symbol};
-use crate::errors::ExprNotAllowedInContext;
+use crate::errors::{ExprNotAllowedInContext, SkippingConstChecks};
/// An expression that is not *always* legal in a const context.
#[derive(Clone, Copy)]
// corresponding feature gate. This encourages nightly users to use feature gates when
// possible.
None if tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you => {
- tcx.sess.span_warn(span, "skipping const checks");
+ tcx.sess.emit_warning(SkippingConstChecks { span });
return;
}
}
fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
- if tcx.has_attr(def_id.to_def_id(), sym::lang) {
- return true;
+ fn has_lang_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
+ tcx.has_attr(def_id.to_def_id(), sym::lang)
+ // Stable attribute for #[lang = "panic_impl"]
+ || tcx.has_attr(def_id.to_def_id(), sym::panic_handler)
}
- // Stable attribute for #[lang = "panic_impl"]
- if tcx.has_attr(def_id.to_def_id(), sym::panic_handler) {
- return true;
+ fn has_allow_dead_code(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+ tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0 == lint::Allow
}
- if tcx.def_kind(def_id).has_codegen_attrs() {
- let cg_attrs = tcx.codegen_fn_attrs(def_id);
+ fn has_used_like_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
+ tcx.def_kind(def_id).has_codegen_attrs() && {
+ let cg_attrs = tcx.codegen_fn_attrs(def_id);
- // #[used], #[no_mangle], #[export_name], etc also keeps the item alive
- // forcefully, e.g., for placing it in a specific section.
- if cg_attrs.contains_extern_indicator()
- || cg_attrs.flags.contains(CodegenFnAttrFlags::USED)
- || cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
- {
- return true;
+ // #[used], #[no_mangle], #[export_name], etc also keeps the item alive
+ // forcefully, e.g., for placing it in a specific section.
+ cg_attrs.contains_extern_indicator()
+ || cg_attrs.flags.contains(CodegenFnAttrFlags::USED)
+ || cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
}
}
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0 == lint::Allow
+ has_allow_dead_code(tcx, def_id)
+ || has_used_like_attr(tcx, def_id)
+ || has_lang_attr(tcx, def_id)
}
// These check_* functions seeds items that
pub span: Span,
}
+#[derive(Diagnostic)]
+#[diag(passes_both_ffi_const_and_pure, code = "E0757")]
+pub struct BothFfiConstAndPure {
+ #[primary_span]
+ pub attr_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_ffi_pure_invalid_target, code = "E0755")]
+pub struct FfiPureInvalidTarget {
+ #[primary_span]
+ pub attr_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_ffi_const_invalid_target, code = "E0756")]
+pub struct FfiConstInvalidTarget {
+ #[primary_span]
+ pub attr_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_ffi_returns_twice_invalid_target, code = "E0724")]
+pub struct FfiReturnsTwiceInvalidTarget {
+ #[primary_span]
+ pub attr_span: Span,
+}
+
#[derive(LintDiagnostic)]
#[diag(passes_must_use_async)]
pub struct MustUseAsync {
#[primary_span]
pub span: Span,
}
+
+#[derive(Diagnostic)]
+#[diag(passes_skipping_const_checks)]
+pub struct SkippingConstChecks {
+ #[primary_span]
+ pub span: Span,
+}
.expect("owning item has no entry");
if max != self.hir_ids_seen.len() - 1 {
- // Collect the missing ItemLocalIds
- let missing: Vec<_> = (0..=max as u32)
- .filter(|&i| !self.hir_ids_seen.contains(ItemLocalId::from_u32(i)))
- .collect();
-
- // Try to map those to something more useful
- let mut missing_items = Vec::with_capacity(missing.len());
+ let hir = self.tcx.hir();
+ let pretty_owner = hir.def_path(owner.def_id).to_string_no_crate_verbose();
- for local_id in missing {
- let hir_id = HirId { owner, local_id: ItemLocalId::from_u32(local_id) };
+ let missing_items: Vec<_> = (0..=max as u32)
+ .map(|i| ItemLocalId::from_u32(i))
+ .filter(|&local_id| !self.hir_ids_seen.contains(local_id))
+ .map(|local_id| hir.node_to_string(HirId { owner, local_id }))
+ .collect();
- trace!("missing hir id {:#?}", hir_id);
+ let seen_items: Vec<_> = self
+ .hir_ids_seen
+ .iter()
+ .map(|local_id| hir.node_to_string(HirId { owner, local_id }))
+ .collect();
- missing_items.push(format!(
- "[local_id: {}, owner: {}]",
- local_id,
- self.tcx.hir().def_path(owner.def_id).to_string_no_crate_verbose()
- ));
- }
self.error(|| {
format!(
"ItemLocalIds not assigned densely in {}. \
- Max ItemLocalId = {}, missing IDs = {:#?}; seens IDs = {:#?}",
- self.tcx.hir().def_path(owner.def_id).to_string_no_crate_verbose(),
- max,
- missing_items,
- self.hir_ids_seen
- .iter()
- .map(|local_id| HirId { owner, local_id })
- .map(|h| format!("({:?} {})", h, self.tcx.hir().node_to_string(h)))
- .collect::<Vec<_>>()
+ Max ItemLocalId = {}, missing IDs = {:#?}; seen IDs = {:#?}",
+ pretty_owner, max, missing_items, seen_items
)
});
}
//! but are not declared in one single location (unlike lang features), which means we need to
//! collect them instead.
-use rustc_ast::{Attribute, MetaItemKind};
+use rustc_ast::Attribute;
use rustc_attr::{rust_version_symbol, VERSION_PLACEHOLDER};
use rustc_hir::intravisit::Visitor;
use rustc_middle::hir::nested_filter;
// Find a stability attribute: one of #[stable(…)], #[unstable(…)],
// #[rustc_const_stable(…)], #[rustc_const_unstable(…)] or #[rustc_default_body_unstable].
if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| attr.has_name(**stab_attr)) {
- let meta_kind = attr.meta_kind();
- if let Some(MetaItemKind::List(ref metas)) = meta_kind {
+ if let Some(metas) = attr.meta_item_list() {
let mut feature = None;
let mut since = None;
for meta in metas {
//! A pass that annotates every item and method with its stability level,
//! propagating default levels lexically from parent to children ast nodes.
-use crate::errors::{
- self, CannotStabilizeDeprecated, DeprecatedAttribute, DuplicateFeatureErr,
- FeatureOnlyOnNightly, ImpliedFeatureNotExist, InvalidDeprecationVersion, InvalidStability,
- MissingConstErr, MissingConstStabAttr, MissingStabilityAttr, TraitImplConstStable,
- UnknownFeature, UselessStability,
-};
+use crate::errors;
use rustc_attr::{
self as attr, rust_version_symbol, ConstStability, Stability, StabilityLevel, Unstable,
UnstableReason, VERSION_PLACEHOLDER,
if let Some((depr, span)) = &depr {
is_deprecated = true;
- if kind == AnnotationKind::Prohibited || kind == AnnotationKind::DeprecationProhibited {
+ if matches!(kind, AnnotationKind::Prohibited | AnnotationKind::DeprecationProhibited) {
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
self.tcx.emit_spanned_lint(
USELESS_DEPRECATED,
{
self.tcx
.sess
- .emit_err(MissingConstErr { fn_sig_span: fn_sig.span, const_span });
+ .emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span, const_span });
}
}
}
if let Some((rustc_attr::Deprecation { is_since_rustc_version: true, .. }, span)) = &depr {
if stab.is_none() {
- self.tcx.sess.emit_err(DeprecatedAttribute { span: *span });
+ self.tcx.sess.emit_err(errors::DeprecatedAttribute { span: *span });
}
}
if kind == AnnotationKind::Prohibited
|| (kind == AnnotationKind::Container && stab.level.is_stable() && is_deprecated)
{
- self.tcx.sess.emit_err(UselessStability { span, item_sp });
+ self.tcx.sess.emit_err(errors::UselessStability { span, item_sp });
}
debug!("annotate: found {:?}", stab);
{
match stab_v.parse::<u64>() {
Err(_) => {
- self.tcx.sess.emit_err(InvalidStability { span, item_sp });
+ self.tcx.sess.emit_err(errors::InvalidStability { span, item_sp });
break;
}
Ok(stab_vp) => match dep_v.parse::<u64>() {
Ok(dep_vp) => match dep_vp.cmp(&stab_vp) {
Ordering::Less => {
- self.tcx
- .sess
- .emit_err(CannotStabilizeDeprecated { span, item_sp });
+ self.tcx.sess.emit_err(errors::CannotStabilizeDeprecated {
+ span,
+ item_sp,
+ });
break;
}
Ordering::Equal => continue,
},
Err(_) => {
if dep_v != "TBD" {
- self.tcx
- .sess
- .emit_err(InvalidDeprecationVersion { span, item_sp });
+ self.tcx.sess.emit_err(errors::InvalidDeprecationVersion {
+ span,
+ item_sp,
+ });
}
break;
}
&& self.effective_visibilities.is_reachable(def_id)
{
let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id());
- self.tcx.sess.emit_err(MissingStabilityAttr { span, descr });
+ self.tcx.sess.emit_err(errors::MissingStabilityAttr { span, descr });
}
}
if is_const && is_stable && missing_const_stability_attribute && is_reachable {
let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id());
- self.tcx.sess.emit_err(MissingConstStabAttr { span, descr });
+ self.tcx.sess.emit_err(errors::MissingConstStabAttr { span, descr });
}
}
}
&& *constness == hir::Constness::Const
&& const_stab.map_or(false, |(stab, _)| stab.is_const_stable())
{
- self.tcx.sess.emit_err(TraitImplConstStable { span: item.span });
+ self.tcx.sess.emit_err(errors::TraitImplConstStable { span: item.span });
}
}
}
if !lang_features.insert(feature) {
// Warn if the user enables a lang feature multiple times.
- tcx.sess.emit_err(DuplicateFeatureErr { span, feature });
+ tcx.sess.emit_err(errors::DuplicateFeatureErr { span, feature });
}
}
let mut remaining_lib_features = FxIndexMap::default();
for (feature, span) in declared_lib_features {
if !tcx.sess.opts.unstable_features.is_nightly_build() {
- tcx.sess.emit_err(FeatureOnlyOnNightly {
+ tcx.sess.emit_err(errors::FeatureOnlyOnNightly {
span: *span,
release_channel: env!("CFG_RELEASE_CHANNEL"),
});
}
if remaining_lib_features.contains_key(&feature) {
// Warn if the user enables a lib feature multiple times.
- tcx.sess.emit_err(DuplicateFeatureErr { span: *span, feature: *feature });
+ tcx.sess.emit_err(errors::DuplicateFeatureErr { span: *span, feature: *feature });
}
remaining_lib_features.insert(feature, *span);
}
}
for (feature, span) in remaining_lib_features {
- tcx.sess.emit_err(UnknownFeature { span, feature: *feature });
+ tcx.sess.emit_err(errors::UnknownFeature { span, feature: *feature });
}
for (implied_by, feature) in remaining_implications {
.map(|(_, span)| span)
.or_else(|| local_defined_features.unstable.get(&feature))
.expect("feature that implied another does not exist");
- tcx.sess.emit_err(ImpliedFeatureNotExist { span, feature, implied_by });
+ tcx.sess.emit_err(errors::ImpliedFeatureNotExist { span, feature, implied_by });
}
// FIXME(#44232): the `used_features` table no longer exists, so we
rustc_middle = { path = "../rustc_middle" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
-rustc_trait_selection = { path = "../rustc_trait_selection" }
rustc_hir_analysis = { path = "../rustc_hir_analysis" }
tracing = "0.1"
rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
-rustc_target = { path = "../rustc_target" }
thin-vec = "0.2.9"
tracing = "0.1"
kind: DepKind,
name: &'static str,
) -> QueryStackFrame<DepKind> {
- // Disable visible paths printing for performance reasons.
- // Showing visible path instead of any path is not that important in production.
- let description = ty::print::with_no_visible_paths!(
- // Force filename-line mode to avoid invoking `type_of` query.
- ty::print::with_forced_impl_filename_line!(do_describe(tcx.tcx, key))
+ // Avoid calling queries while formatting the description
+ let description = ty::print::with_no_queries!(
+ // Disable visible paths printing for performance reasons.
+ // Showing visible path instead of any path is not that important in production.
+ ty::print::with_no_visible_paths!(
+ // Force filename-line mode to avoid invoking `type_of` query.
+ ty::print::with_forced_impl_filename_line!(do_describe(tcx.tcx, key))
+ )
);
let description =
if tcx.sess.verbose() { format!("{description} [{name:?}]") } else { description };
pub trait CacheSelector<'tcx, V> {
type Cache
where
- V: Clone;
+ V: Copy;
type ArenaCache;
}
pub trait QueryStorage {
type Value: Debug;
- type Stored: Clone;
+ type Stored: Copy;
/// Store a value without putting it in the cache.
/// This is meant to be used with cycle errors.
/// It returns the shard index and a lock guard to the shard,
/// which will be used if the query is not in the cache and we need
/// to compute it.
- fn lookup<R, OnHit>(
- &self,
- key: &Self::Key,
- // `on_hit` can be called while holding a lock to the query state shard.
- on_hit: OnHit,
- ) -> Result<R, ()>
- where
- OnHit: FnOnce(&Self::Stored, DepNodeIndex) -> R;
+ fn lookup(&self, key: &Self::Key) -> Option<(Self::Stored, DepNodeIndex)>;
fn complete(&self, key: Self::Key, value: Self::Value, index: DepNodeIndex) -> Self::Stored;
impl<'tcx, K: Eq + Hash, V: 'tcx> CacheSelector<'tcx, V> for DefaultCacheSelector<K> {
type Cache = DefaultCache<K, V>
where
- V: Clone;
+ V: Copy;
type ArenaCache = ArenaCache<'tcx, K, V>;
}
}
}
-impl<K: Eq + Hash, V: Clone + Debug> QueryStorage for DefaultCache<K, V> {
+impl<K: Eq + Hash, V: Copy + Debug> QueryStorage for DefaultCache<K, V> {
type Value = V;
type Stored = V;
impl<K, V> QueryCache for DefaultCache<K, V>
where
K: Eq + Hash + Clone + Debug,
- V: Clone + Debug,
+ V: Copy + Debug,
{
type Key = K;
#[inline(always)]
- fn lookup<R, OnHit>(&self, key: &K, on_hit: OnHit) -> Result<R, ()>
- where
- OnHit: FnOnce(&V, DepNodeIndex) -> R,
- {
+ fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
let key_hash = sharded::make_hash(key);
#[cfg(parallel_compiler)]
let lock = self.cache.get_shard_by_hash(key_hash).lock();
let lock = self.cache.lock();
let result = lock.raw_entry().from_key_hashed_nocheck(key_hash, key);
- if let Some((_, value)) = result {
- let hit_result = on_hit(&value.0, value.1);
- Ok(hit_result)
- } else {
- Err(())
- }
+ if let Some((_, value)) = result { Some(*value) } else { None }
}
#[inline]
type Key = K;
#[inline(always)]
- fn lookup<R, OnHit>(&self, key: &K, on_hit: OnHit) -> Result<R, ()>
- where
- OnHit: FnOnce(&&'tcx V, DepNodeIndex) -> R,
- {
+ fn lookup(&self, key: &K) -> Option<(&'tcx V, DepNodeIndex)> {
let key_hash = sharded::make_hash(key);
#[cfg(parallel_compiler)]
let lock = self.cache.get_shard_by_hash(key_hash).lock();
let lock = self.cache.lock();
let result = lock.raw_entry().from_key_hashed_nocheck(key_hash, key);
- if let Some((_, value)) = result {
- let hit_result = on_hit(&&value.0, value.1);
- Ok(hit_result)
- } else {
- Err(())
- }
+ if let Some((_, value)) = result { Some((&value.0, value.1)) } else { None }
}
#[inline]
impl<'tcx, K: Idx, V: 'tcx> CacheSelector<'tcx, V> for VecCacheSelector<K> {
type Cache = VecCache<K, V>
where
- V: Clone;
+ V: Copy;
type ArenaCache = VecArenaCache<'tcx, K, V>;
}
}
}
-impl<K: Eq + Idx, V: Clone + Debug> QueryStorage for VecCache<K, V> {
+impl<K: Eq + Idx, V: Copy + Debug> QueryStorage for VecCache<K, V> {
type Value = V;
type Stored = V;
impl<K, V> QueryCache for VecCache<K, V>
where
K: Eq + Idx + Clone + Debug,
- V: Clone + Debug,
+ V: Copy + Debug,
{
type Key = K;
#[inline(always)]
- fn lookup<R, OnHit>(&self, key: &K, on_hit: OnHit) -> Result<R, ()>
- where
- OnHit: FnOnce(&V, DepNodeIndex) -> R,
- {
+ fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
#[cfg(parallel_compiler)]
let lock = self.cache.get_shard_by_hash(key.index() as u64).lock();
#[cfg(not(parallel_compiler))]
let lock = self.cache.lock();
- if let Some(Some(value)) = lock.get(*key) {
- let hit_result = on_hit(&value.0, value.1);
- Ok(hit_result)
- } else {
- Err(())
- }
+ if let Some(Some(value)) = lock.get(*key) { Some(*value) } else { None }
}
#[inline]
type Key = K;
#[inline(always)]
- fn lookup<R, OnHit>(&self, key: &K, on_hit: OnHit) -> Result<R, ()>
- where
- OnHit: FnOnce(&&'tcx V, DepNodeIndex) -> R,
- {
+ fn lookup(&self, key: &K) -> Option<(&'tcx V, DepNodeIndex)> {
#[cfg(parallel_compiler)]
let lock = self.cache.get_shard_by_hash(key.index() as u64).lock();
#[cfg(not(parallel_compiler))]
let lock = self.cache.lock();
- if let Some(Some(value)) = lock.get(*key) {
- let hit_result = on_hit(&&value.0, value.1);
- Ok(hit_result)
- } else {
- Err(())
- }
+ if let Some(Some(value)) = lock.get(*key) { Some((&value.0, value.1)) } else { None }
}
#[inline]
type Key: DepNodeParams<Qcx::DepContext> + Eq + Hash + Clone + Debug;
type Value: Debug;
- type Stored: Debug + Clone + std::borrow::Borrow<Self::Value>;
+ type Stored: Debug + Copy + std::borrow::Borrow<Self::Value>;
type Cache: QueryCache<Key = Self::Key, Stored = Self::Stored, Value = Self::Value>;
where
Qcx: QueryContext + crate::query::HasDepContext<DepKind = D>,
V: std::fmt::Debug + Value<Qcx::DepContext, Qcx::DepKind>,
- R: Clone,
+ R: Copy,
{
let error = report_cycle(qcx.dep_context().sess(), &cycle_error);
let value = handle_cycle_error(*qcx.dep_context(), &cycle_error, error, handler);
/// which will be used if the query is not in the cache and we need
/// to compute it.
#[inline]
-pub fn try_get_cached<Tcx, C, R, OnHit>(
- tcx: Tcx,
- cache: &C,
- key: &C::Key,
- // `on_hit` can be called while holding a lock to the query cache
- on_hit: OnHit,
-) -> Result<R, ()>
+pub fn try_get_cached<Tcx, C>(tcx: Tcx, cache: &C, key: &C::Key) -> Option<C::Stored>
where
C: QueryCache,
Tcx: DepContext,
- OnHit: FnOnce(&C::Stored) -> R,
{
- cache.lookup(&key, |value, index| {
- if std::intrinsics::unlikely(tcx.profiler().enabled()) {
- tcx.profiler().query_cache_hit(index.into());
+ match cache.lookup(&key) {
+ Some((value, index)) => {
+ if std::intrinsics::unlikely(tcx.profiler().enabled()) {
+ tcx.profiler().query_cache_hit(index.into());
+ }
+ tcx.dep_graph().read_index(index);
+ Some(value)
}
- tcx.dep_graph().read_index(index);
- on_hit(value)
- })
+ None => None,
+ }
}
fn try_execute_query<Q, Qcx>(
if Q::FEEDABLE {
// We may have put a value inside the cache from inside the execution.
// Verify that it has the same hash as what we have now, to ensure consistency.
- let _ = cache.lookup(&key, |cached_result, _| {
+ if let Some((cached_result, _)) = cache.lookup(&key) {
let hasher = Q::HASH_RESULT.expect("feedable forbids no_hash");
- let old_hash = qcx.dep_context().with_stable_hashing_context(|mut hcx| hasher(&mut hcx, cached_result.borrow()));
- let new_hash = qcx.dep_context().with_stable_hashing_context(|mut hcx| hasher(&mut hcx, &result));
+ let old_hash = qcx.dep_context().with_stable_hashing_context(|mut hcx| {
+ hasher(&mut hcx, cached_result.borrow())
+ });
+ let new_hash = qcx
+ .dep_context()
+ .with_stable_hashing_context(|mut hcx| hasher(&mut hcx, &result));
debug_assert_eq!(
- old_hash, new_hash,
+ old_hash,
+ new_hash,
"Computed query value for {:?}({:?}) is inconsistent with fed value,\ncomputed={:#?}\nfed={:#?}",
- Q::DEP_KIND, key, result, cached_result,
+ Q::DEP_KIND,
+ key,
+ result,
+ cached_result,
);
- });
+ }
}
let result = job.complete(cache, result, dep_node_index);
(result, Some(dep_node_index))
}
#[cfg(parallel_compiler)]
TryGetJob::JobCompleted(query_blocked_prof_timer) => {
- let (v, index) = cache
- .lookup(&key, |value, index| (value.clone(), index))
- .unwrap_or_else(|_| panic!("value must be in cache after waiting"));
+ let Some((v, index)) = cache.lookup(&key) else {
+ panic!("value must be in cache after waiting")
+ };
if std::intrinsics::unlikely(qcx.dep_context().profiler().enabled()) {
qcx.dep_context().profiler().query_cache_hit(index.into());
// We may be concurrently trying both execute and force a query.
// Ensure that only one of them runs the query.
let cache = Q::query_cache(qcx);
- let cached = cache.lookup(&key, |_, index| {
+ if let Some((_, index)) = cache.lookup(&key) {
if std::intrinsics::unlikely(qcx.dep_context().profiler().enabled()) {
qcx.dep_context().profiler().query_cache_hit(index.into());
}
- });
-
- match cached {
- Ok(()) => return,
- Err(()) => {}
+ return;
}
let state = Q::query_state(qcx);
let ident = path.segments.get(0).expect("empty path in visibility").ident;
let crate_root = if ident.is_path_segment_keyword() {
None
- } else if ident.span.rust_2015() {
+ } else if ident.span.is_rust_2015() {
Some(Segment::from_ident(Ident::new(
kw::PathRoot,
path.span.shrink_to_lo().with_ctxt(ident.span.ctxt()),
self.r.record_partial_res(id, PartialRes::new(res));
}
if module.is_normal() {
- if res == Res::Err {
- Ok(ty::Visibility::Public)
- } else {
- let vis = ty::Visibility::Restricted(res.def_id());
- if self.r.is_accessible_from(vis, parent_scope.module) {
- Ok(vis.expect_local())
- } else {
- Err(VisResolutionError::AncestorOnly(path.span))
+ match res {
+ Res::Err => Ok(ty::Visibility::Public),
+ _ => {
+ let vis = ty::Visibility::Restricted(res.def_id());
+ if self.r.is_accessible_from(vis, parent_scope.module) {
+ Ok(vis.expect_local())
+ } else {
+ Err(VisResolutionError::AncestorOnly(path.span))
+ }
}
}
} else {
// appears, so imports in braced groups can have roots prepended independently.
let is_glob = matches!(use_tree.kind, ast::UseTreeKind::Glob);
let crate_root = match prefix_iter.peek() {
- Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.rust_2015() => {
+ Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.is_rust_2015() => {
Some(seg.ident.span.ctxt())
}
- None if is_glob && use_tree.span.rust_2015() => Some(use_tree.span.ctxt()),
+ None if is_glob && use_tree.span.is_rust_2015() => Some(use_tree.span.ctxt()),
_ => None,
}
.map(|ctxt| {
let first_name = match path.get(0) {
// In the 2018 edition this lint is a hard error, so nothing to do
- Some(seg) if seg.ident.span.rust_2015() && self.session.rust_2015() => seg.ident.name,
+ Some(seg) if seg.ident.span.is_rust_2015() && self.session.is_rust_2015() => {
+ seg.ident.name
+ }
_ => return,
};
if b.is_extern_crate() && ident.span.rust_2018() {
help_msgs.push(format!("use `::{ident}` to refer to this {thing} unambiguously"))
}
- if misc == AmbiguityErrorMisc::SuggestCrate {
- help_msgs
- .push(format!("use `crate::{ident}` to refer to this {thing} unambiguously"))
- } else if misc == AmbiguityErrorMisc::SuggestSelf {
- help_msgs
- .push(format!("use `self::{ident}` to refer to this {thing} unambiguously"))
+ match misc {
+ AmbiguityErrorMisc::SuggestCrate => help_msgs
+ .push(format!("use `crate::{ident}` to refer to this {thing} unambiguously")),
+ AmbiguityErrorMisc::SuggestSelf => help_msgs
+ .push(format!("use `self::{ident}` to refer to this {thing} unambiguously")),
+ AmbiguityErrorMisc::FromPrelude | AmbiguityErrorMisc::None => {}
}
err.span_note(b.span, ¬e_msg);
Applicability::MaybeIncorrect,
)),
)
- } else if self.session.edition() == Edition::Edition2015 {
+ } else if self.session.is_rust_2015() {
(
format!("maybe a missing crate `{ident}`?"),
Some((
mut path: Vec<Segment>,
parent_scope: &ParentScope<'b>,
) -> Option<(Vec<Segment>, Option<String>)> {
- if path[1].ident.span.rust_2015() {
+ if path[1].ident.span.is_rust_2015() {
return None;
}
use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK;
use rustc_session::lint::BuiltinLintDiagnostics;
use rustc_span::def_id::LocalDefId;
-use rustc_span::edition::Edition;
use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext};
use rustc_span::symbol::{kw, Ident};
use rustc_span::{Span, DUMMY_SP};
// 4c. Standard library prelude (de-facto closed, controlled).
// 6. Language prelude: builtin attributes (closed, controlled).
- let rust_2015 = ctxt.edition() == Edition::Edition2015;
+ let rust_2015 = ctxt.edition().is_rust_2015();
let (ns, macro_kind, is_absolute_path) = match scope_set {
ScopeSet::All(ns, _) => (ns, None, false),
ScopeSet::AbsolutePath(ns) => (ns, None, true),
module = Some(ModuleOrUniformRoot::ExternPrelude);
continue;
}
- if name == kw::PathRoot && ident.span.rust_2015() && self.session.rust_2018() {
+ if name == kw::PathRoot && ident.span.is_rust_2015() && self.session.rust_2018()
+ {
// `::a::b` from 2015 macro on 2018 global edition
module = Some(ModuleOrUniformRoot::CrateRootAndExternPrelude);
continue;
let segments = &use_tree.prefix.segments;
if !segments.is_empty() {
let ident = segments[0].ident;
- if ident.is_path_segment_keyword() || ident.span.rust_2015() {
+ if ident.is_path_segment_keyword() || ident.span.is_rust_2015() {
return;
}
"!",
Applicability::MaybeIncorrect,
);
- if path_str == "try" && span.rust_2015() {
+ if path_str == "try" && span.is_rust_2015() {
err.note("if you want the `try` keyword, you need Rust 2018 or later");
}
}
use rls_data::{SigElement, Signature};
-use rustc_ast::Mutability;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir_pretty::id_to_string;
}
hir::ForeignItemKind::Static(ref ty, m) => {
let mut text = "static ".to_owned();
- if m == Mutability::Mut {
- text.push_str("mut ");
- }
+ text.push_str(m.prefix_str());
+
let name = self.ident.to_string();
let defs = vec![SigElement {
id: id_from_def_id(self.owner_id.to_def_id()),
Min,
}
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub enum FieldKind {
+ AdtField,
+ Upvar,
+ GeneratorLocal,
+}
+
+impl std::fmt::Display for FieldKind {
+ fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ FieldKind::AdtField => write!(w, "field"),
+ FieldKind::Upvar => write!(w, "upvar"),
+ FieldKind::GeneratorLocal => write!(w, "local"),
+ }
+ }
+}
+
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct FieldInfo {
+ pub kind: FieldKind,
pub name: Symbol,
pub offset: u64,
pub size: u64,
// Sort variants so the largest ones are shown first. A stable sort is
// used here so that source code order is preserved for all variants
// that have the same size.
- variants.sort_by(|info1, info2| info2.size.cmp(&info1.size));
+ // Except for Generators, whose variants are already sorted according to
+ // their yield points in `variant_info_for_generator`.
+ if kind != DataTypeKind::Generator {
+ variants.sort_by(|info1, info2| info2.size.cmp(&info1.size));
+ }
let info = TypeSizeInfo {
kind,
type_description: type_desc.to_string(),
fields.sort_by_key(|f| (f.offset, f.size));
for field in fields {
- let FieldInfo { ref name, offset, size, align } = field;
+ let FieldInfo { kind, ref name, offset, size, align } = field;
if offset > min_offset {
let pad = offset - min_offset;
if offset < min_offset {
// If this happens it's probably a union.
println!(
- "print-type-size {indent}field `.{name}`: {size} bytes, \
+ "print-type-size {indent}{kind} `.{name}`: {size} bytes, \
offset: {offset} bytes, \
alignment: {align} bytes"
);
} else if info.packed || offset == min_offset {
- println!("print-type-size {indent}field `.{name}`: {size} bytes");
+ println!("print-type-size {indent}{kind} `.{name}`: {size} bytes");
} else {
// Include field alignment in output only if it caused padding injection
println!(
- "print-type-size {indent}field `.{name}`: {size} bytes, \
+ "print-type-size {indent}{kind} `.{name}`: {size} bytes, \
alignment: {align} bytes"
);
}
use rustc_span::SourceFileHashAlgorithm;
use rustc_errors::emitter::HumanReadableErrorType;
-use rustc_errors::{ColorConfig, HandlerFlags};
+use rustc_errors::{ColorConfig, DiagnosticArgValue, HandlerFlags, IntoDiagnosticArg};
use std::collections::btree_map::{
Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter,
}
}
+impl IntoDiagnosticArg for CrateType {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ self.to_string().into_diagnostic_arg()
+ }
+}
+
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum PpSourceMode {
/// `-Zunpretty=normal`
}
}
}
+
+#[derive(Diagnostic)]
+#[diag(session_optimization_fuel_exhausted)]
+pub struct OptimisationFuelExhausted {
+ pub msg: String,
+}
use crate::cgu_reuse_tracker::CguReuseTracker;
use crate::code_stats::CodeStats;
-pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
+pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
use crate::config::Input;
use crate::config::{self, CrateType, InstrumentCoverage, OptLevel, OutputType, SwitchWithOptPath};
-use crate::errors::{
- BranchProtectionRequiresAArch64, CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers,
- LinkerPluginToWindowsNotSupported, NotCircumventFeature, ProfileSampleUseFileDoesNotExist,
- ProfileUseFileDoesNotExist, SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported,
- SkippingConstChecks, SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget,
- TargetRequiresUnwindTables, UnleashedFeatureHelp, UnstableVirtualFunctionElimination,
- UnsupportedDwarfVersion,
-};
+use crate::errors;
use crate::parse::{add_feature_diagnostics, ParseSess};
use crate::search_paths::{PathKind, SearchPath};
use crate::{filesearch, lint};
if !unleashed_features.is_empty() {
let mut must_err = false;
// Create a diagnostic pointing at where things got unleashed.
- self.emit_warning(SkippingConstChecks {
+ self.emit_warning(errors::SkippingConstChecks {
unleashed_features: unleashed_features
.iter()
.map(|(span, gate)| {
gate.map(|gate| {
must_err = true;
- UnleashedFeatureHelp::Named { span: *span, gate }
+ errors::UnleashedFeatureHelp::Named { span: *span, gate }
})
- .unwrap_or(UnleashedFeatureHelp::Unnamed { span: *span })
+ .unwrap_or(errors::UnleashedFeatureHelp::Unnamed { span: *span })
})
.collect(),
});
// If we should err, make sure we did.
if must_err && self.has_errors().is_none() {
// We have skipped a feature gate, and not run into other errors... reject.
- self.emit_err(NotCircumventFeature);
+ self.emit_err(errors::NotCircumventFeature);
}
}
}
self.diagnostic().span_err_with_code(sp, msg, code)
}
#[rustc_lint_diagnostics]
+ #[allow(rustc::untranslatable_diagnostic)]
+ #[allow(rustc::diagnostic_outside_of_impl)]
pub fn err(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
self.diagnostic().err(msg)
}
))
}
}
+
+ #[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
#[track_caller]
pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) {
self.diagnostic().span_warn(sp, msg)
}
+
+ #[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn span_warn_with_code<S: Into<MultiSpan>>(
) {
self.diagnostic().span_warn_with_code(sp, msg, code)
}
+
+ #[rustc_lint_diagnostics]
+ #[allow(rustc::untranslatable_diagnostic)]
+ #[allow(rustc::diagnostic_outside_of_impl)]
pub fn warn(&self, msg: impl Into<DiagnosticMessage>) {
self.diagnostic().warn(msg)
}
self.diagnostic().delay_good_path_bug(msg)
}
+ #[rustc_lint_diagnostics]
+ #[allow(rustc::untranslatable_diagnostic)]
+ #[allow(rustc::diagnostic_outside_of_impl)]
pub fn note_without_error(&self, msg: impl Into<DiagnosticMessage>) {
self.diagnostic().note_without_error(msg)
}
#[track_caller]
+ #[rustc_lint_diagnostics]
+ #[allow(rustc::untranslatable_diagnostic)]
+ #[allow(rustc::diagnostic_outside_of_impl)]
pub fn span_note_without_error<S: Into<MultiSpan>>(
&self,
sp: S,
) {
self.diagnostic().span_note_without_error(sp, msg)
}
+
+ #[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_note_without_error(
// We only call `msg` in case we can actually emit warnings.
// Otherwise, this could cause a `delay_good_path_bug` to
// trigger (issue #79546).
- self.warn(&format!("optimization-fuel-exhausted: {}", msg()));
+ self.emit_warning(errors::OptimisationFuelExhausted { msg: msg() });
}
fuel.out_of_fuel = true;
} else if fuel.remaining > 0 {
ret
}
- pub fn rust_2015(&self) -> bool {
- self.edition() == Edition::Edition2015
+ /// Is this edition 2015?
+ pub fn is_rust_2015(&self) -> bool {
+ self.edition().is_rust_2015()
}
/// Are we allowed to use features from the Rust 2018 edition?
pub fn rust_2018(&self) -> bool {
- self.edition() >= Edition::Edition2018
+ self.edition().rust_2018()
}
/// Are we allowed to use features from the Rust 2021 edition?
pub fn rust_2021(&self) -> bool {
- self.edition() >= Edition::Edition2021
+ self.edition().rust_2021()
}
/// Are we allowed to use features from the Rust 2024 edition?
pub fn rust_2024(&self) -> bool {
- self.edition() >= Edition::Edition2024
+ self.edition().rust_2024()
}
/// Returns `true` if we cannot skip the PLT for shared library calls.
&& sess.opts.cg.prefer_dynamic
&& sess.target.is_like_windows
{
- sess.emit_err(LinkerPluginToWindowsNotSupported);
+ sess.emit_err(errors::LinkerPluginToWindowsNotSupported);
}
// Make sure that any given profiling data actually exists so LLVM can't
// decide to silently skip PGO.
if let Some(ref path) = sess.opts.cg.profile_use {
if !path.exists() {
- sess.emit_err(ProfileUseFileDoesNotExist { path });
+ sess.emit_err(errors::ProfileUseFileDoesNotExist { path });
}
}
// Do the same for sample profile data.
if let Some(ref path) = sess.opts.unstable_opts.profile_sample_use {
if !path.exists() {
- sess.emit_err(ProfileSampleUseFileDoesNotExist { path });
+ sess.emit_err(errors::ProfileSampleUseFileDoesNotExist { path });
}
}
// Unwind tables cannot be disabled if the target requires them.
if let Some(include_uwtables) = sess.opts.cg.force_unwind_tables {
if sess.target.requires_uwtable && !include_uwtables {
- sess.emit_err(TargetRequiresUnwindTables);
+ sess.emit_err(errors::TargetRequiresUnwindTables);
}
}
match unsupported_sanitizers.into_iter().count() {
0 => {}
1 => {
- sess.emit_err(SanitizerNotSupported { us: unsupported_sanitizers.to_string() });
+ sess.emit_err(errors::SanitizerNotSupported { us: unsupported_sanitizers.to_string() });
}
_ => {
- sess.emit_err(SanitizersNotSupported { us: unsupported_sanitizers.to_string() });
+ sess.emit_err(errors::SanitizersNotSupported {
+ us: unsupported_sanitizers.to_string(),
+ });
}
}
// Cannot mix and match sanitizers.
let mut sanitizer_iter = sess.opts.unstable_opts.sanitizer.into_iter();
if let (Some(first), Some(second)) = (sanitizer_iter.next(), sanitizer_iter.next()) {
- sess.emit_err(CannotMixAndMatchSanitizers {
+ sess.emit_err(errors::CannotMixAndMatchSanitizers {
first: first.to_string(),
second: second.to_string(),
});
// Cannot enable crt-static with sanitizers on Linux
if sess.crt_static(None) && !sess.opts.unstable_opts.sanitizer.is_empty() {
- sess.emit_err(CannotEnableCrtStaticLinux);
+ sess.emit_err(errors::CannotEnableCrtStaticLinux);
}
// LLVM CFI and VFE both require LTO.
if sess.lto() != config::Lto::Fat {
if sess.is_sanitizer_cfi_enabled() {
- sess.emit_err(SanitizerCfiEnabled);
+ sess.emit_err(errors::SanitizerCfiEnabled);
}
if sess.opts.unstable_opts.virtual_function_elimination {
- sess.emit_err(UnstableVirtualFunctionElimination);
+ sess.emit_err(errors::UnstableVirtualFunctionElimination);
}
}
// LLVM CFI and KCFI are mutually exclusive
if sess.is_sanitizer_cfi_enabled() && sess.is_sanitizer_kcfi_enabled() {
- sess.emit_err(CannotMixAndMatchSanitizers {
+ sess.emit_err(errors::CannotMixAndMatchSanitizers {
first: "cfi".to_string(),
second: "kcfi".to_string(),
});
if sess.opts.unstable_opts.stack_protector != StackProtector::None {
if !sess.target.options.supports_stack_protector {
- sess.emit_warning(StackProtectorNotSupportedForTarget {
+ sess.emit_warning(errors::StackProtectorNotSupportedForTarget {
stack_protector: sess.opts.unstable_opts.stack_protector,
target_triple: &sess.opts.target_triple,
});
}
if sess.opts.unstable_opts.branch_protection.is_some() && sess.target.arch != "aarch64" {
- sess.emit_err(BranchProtectionRequiresAArch64);
+ sess.emit_err(errors::BranchProtectionRequiresAArch64);
}
if let Some(dwarf_version) = sess.opts.unstable_opts.dwarf_version {
if dwarf_version > 5 {
- sess.emit_err(UnsupportedDwarfVersion { dwarf_version });
+ sess.emit_err(errors::UnsupportedDwarfVersion { dwarf_version });
}
}
if !sess.target.options.supported_split_debuginfo.contains(&sess.split_debuginfo())
&& !sess.opts.unstable_opts.unstable_options
{
- sess.emit_err(SplitDebugInfoUnstablePlatform { debuginfo: sess.split_debuginfo() });
+ sess.emit_err(errors::SplitDebugInfoUnstablePlatform { debuginfo: sess.split_debuginfo() });
}
}
}
}
+impl Default for DefPathHash {
+ fn default() -> Self {
+ DefPathHash(Fingerprint::ZERO)
+ }
+}
+
impl Borrow<Fingerprint> for DefPathHash {
#[inline]
fn borrow(&self) -> &Fingerprint {
}
impl Edition {
- pub fn lint_name(&self) -> &'static str {
- match *self {
+ pub fn lint_name(self) -> &'static str {
+ match self {
Edition::Edition2015 => "rust_2015_compatibility",
Edition::Edition2018 => "rust_2018_compatibility",
Edition::Edition2021 => "rust_2021_compatibility",
}
}
- pub fn feature_name(&self) -> Symbol {
- match *self {
+ pub fn feature_name(self) -> Symbol {
+ match self {
Edition::Edition2015 => sym::rust_2015_preview,
Edition::Edition2018 => sym::rust_2018_preview,
Edition::Edition2021 => sym::rust_2021_preview,
}
}
- pub fn is_stable(&self) -> bool {
- match *self {
+ pub fn is_stable(self) -> bool {
+ match self {
Edition::Edition2015 => true,
Edition::Edition2018 => true,
Edition::Edition2021 => true,
}
}
- pub fn rust_2015(&self) -> bool {
- *self == Edition::Edition2015
+ /// Is this edition 2015?
+ pub fn is_rust_2015(self) -> bool {
+ self == Edition::Edition2015
}
/// Are we allowed to use features from the Rust 2018 edition?
- pub fn rust_2018(&self) -> bool {
- *self >= Edition::Edition2018
+ pub fn rust_2018(self) -> bool {
+ self >= Edition::Edition2018
}
/// Are we allowed to use features from the Rust 2021 edition?
- pub fn rust_2021(&self) -> bool {
- *self >= Edition::Edition2021
+ pub fn rust_2021(self) -> bool {
+ self >= Edition::Edition2021
}
/// Are we allowed to use features from the Rust 2024 edition?
- pub fn rust_2024(&self) -> bool {
- *self >= Edition::Edition2024
+ pub fn rust_2024(self) -> bool {
+ self >= Edition::Edition2024
}
}
}
#[inline]
- pub fn rust_2015(self) -> bool {
- self.edition() == edition::Edition::Edition2015
+ pub fn is_rust_2015(self) -> bool {
+ self.edition().is_rust_2015()
}
#[inline]
pub fn rust_2018(self) -> bool {
- self.edition() >= edition::Edition::Edition2018
+ self.edition().rust_2018()
}
#[inline]
pub fn rust_2021(self) -> bool {
- self.edition() >= edition::Edition::Edition2021
+ self.edition().rust_2021()
}
#[inline]
pub fn rust_2024(self) -> bool {
- self.edition() >= edition::Edition::Edition2024
+ self.edition().rust_2024()
}
/// Returns the source callee.
use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions};
pub fn target() -> Target {
- let llvm_target = "arm64-apple-ios14.0-macabi";
+ let llvm_target = "arm64-apple-ios-macabi";
let arch = Arch::Arm64_macabi;
let mut base = opts("ios", arch);
// These arguments are not actually invoked - they just have
// to look right to pass App Store validation.
bitcode_llvm_cmdline: "-triple\0\
- arm64-apple-ios14.0-macabi\0\
+ arm64-apple-ios-macabi\0\
-emit-obj\0\
-disable-llvm-passes\0\
-Os\0"
use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
- let llvm_target = "x86_64-apple-ios13.0-macabi";
+ let llvm_target = "x86_64-apple-ios-macabi";
let arch = Arch::X86_64_macabi;
let mut base = opts("ios", arch);
rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
rustc_infer = { path = "../rustc_infer" }
-rustc_lint_defs = { path = "../rustc_lint_defs" }
rustc_macros = { path = "../rustc_macros" }
rustc_query_system = { path = "../rustc_query_system" }
rustc_serialize = { path = "../rustc_serialize" }
AliasBound,
}
+/// Methods used to assemble candidates for either trait or projection goals.
pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy + Eq {
fn self_ty(self) -> Ty<'tcx>;
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;
+
+ // The most common forms of unsizing are array to slice, and concrete (Sized)
+ // type into a `dyn Trait`. ADTs and Tuples can also have their final field
+ // unsized if it's generic.
+ fn consider_builtin_unsize_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx>;
+
+ // `dyn Trait1` can be unsized to `dyn Trait2` if they are the same trait, or
+ // if `Trait2` is a (transitive) supertrait of `Trait2`.
+ fn consider_builtin_dyn_upcast_candidates(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> Vec<CanonicalResponse<'tcx>>;
+
+ fn consider_builtin_discriminant_kind_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx>;
}
impl<'tcx> EvalCtxt<'_, 'tcx> {
G::consider_builtin_future_candidate(self, goal)
} else if lang_items.gen_trait() == Some(trait_def_id) {
G::consider_builtin_generator_candidate(self, goal)
+ } else if lang_items.unsize_trait() == Some(trait_def_id) {
+ G::consider_builtin_unsize_candidate(self, goal)
+ } else if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
+ G::consider_builtin_discriminant_kind_candidate(self, goal)
} else {
Err(NoSolution)
};
}
Err(NoSolution) => (),
}
+
+ // There may be multiple unsize candidates for a trait with several supertraits:
+ // `trait Foo: Bar<A> + Bar<B>` and `dyn Foo: Unsize<dyn Bar<_>>`
+ if lang_items.unsize_trait() == Some(trait_def_id) {
+ for result in G::consider_builtin_dyn_upcast_candidates(self, goal) {
+ candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result });
+ }
+ }
}
fn assemble_param_env_candidates<G: GoalKind<'tcx>>(
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::Obligation;
use rustc_middle::infer::canonical::Certainty as OldCertainty;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData};
+use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::ty::{
CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TypeOutlivesPredicate,
};
Goal { param_env: obligation.param_env, predicate: obligation.predicate }
}
}
-
-#[derive(Debug, PartialEq, Eq, Clone, Hash, TypeFoldable, TypeVisitable)]
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
pub struct Response<'tcx> {
pub var_values: CanonicalVarValues<'tcx>,
/// Additional constraints returned by this query.
Overflow,
}
-/// Additional constraints returned on success.
-#[derive(Debug, PartialEq, Eq, Clone, Hash, TypeFoldable, TypeVisitable, Default)]
-pub struct ExternalConstraints<'tcx> {
- // FIXME: implement this.
- regions: (),
- opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>,
-}
-
type CanonicalGoal<'tcx, T = ty::Predicate<'tcx>> = Canonical<'tcx, Goal<'tcx, T>>;
type CanonicalResponse<'tcx> = Canonical<'tcx, Response<'tcx>>;
/// The result of evaluating a canonical query.
search_graph: &mut search_graph,
infcx: self,
var_values: CanonicalVarValues::dummy(),
+ in_projection_eq_hack: false,
}
.evaluate_goal(goal);
var_values: CanonicalVarValues<'tcx>,
search_graph: &'a mut search_graph::SearchGraph<'tcx>,
+
+ /// This field is used by a debug assertion in [`EvalCtxt::evaluate_goal`],
+ /// see the comment in that method for more details.
+ in_projection_eq_hack: bool,
}
impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
loop {
let (ref infcx, goal, var_values) =
tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical_goal);
- let mut ecx = EvalCtxt { infcx, var_values, search_graph };
+ let mut ecx =
+ EvalCtxt { infcx, var_values, search_graph, in_projection_eq_hack: false };
let result = ecx.compute_goal(goal);
- // FIXME: `Response` should be `Copy`
- if search_graph.try_finalize_goal(tcx, canonical_goal, result.clone()) {
+ if search_graph.try_finalize_goal(tcx, canonical_goal, result) {
return result;
}
}
}
fn make_canonical_response(&self, certainty: Certainty) -> QueryResult<'tcx> {
- let external_constraints = take_external_constraints(self.infcx)?;
+ let external_constraints = compute_external_query_constraints(self.infcx)?;
Ok(self.infcx.canonicalize_response(Response {
var_values: self.var_values,
let canonical_goal = self.infcx.canonicalize_query(goal, &mut orig_values);
let canonical_response =
EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?;
- Ok((
- !canonical_response.value.var_values.is_identity(),
- instantiate_canonical_query_response(self.infcx, &orig_values, canonical_response),
- ))
+
+ let has_changed = !canonical_response.value.var_values.is_identity();
+ let certainty =
+ instantiate_canonical_query_response(self.infcx, &orig_values, canonical_response);
+
+ // Check that rerunning this query with its inference constraints applied
+ // doesn't result in new inference constraints and has the same result.
+ //
+ // If we have projection goals like `<T as Trait>::Assoc == u32` we recursively
+ // call `exists<U> <T as Trait>::Assoc == U` to enable better caching. This goal
+ // could constrain `U` to `u32` which would cause this check to result in a
+ // solver cycle.
+ if cfg!(debug_assertions) && has_changed && !self.in_projection_eq_hack {
+ let mut orig_values = OriginalQueryValues::default();
+ let canonical_goal = self.infcx.canonicalize_query(goal, &mut orig_values);
+ let canonical_response =
+ EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?;
+ assert!(canonical_response.value.var_values.is_identity());
+ assert_eq!(certainty, canonical_response.value.certainty);
+ }
+
+ Ok((has_changed, certainty))
}
fn compute_goal(&mut self, goal: Goal<'tcx, ty::Predicate<'tcx>>) -> QueryResult<'tcx> {
}
#[instrument(level = "debug", skip(infcx), ret)]
-fn take_external_constraints<'tcx>(
+fn compute_external_query_constraints<'tcx>(
infcx: &InferCtxt<'tcx>,
) -> Result<ExternalConstraints<'tcx>, NoSolution> {
let region_obligations = infcx.take_registered_region_obligations();
let opaque_types = infcx.take_opaque_types_for_query_response();
- Ok(ExternalConstraints {
+ Ok(infcx.tcx.intern_external_constraints(ExternalConstraintsData {
// FIXME: Now that's definitely wrong :)
//
// Should also do the leak check here I think
regions: drop(region_obligations),
opaque_types,
- })
+ }))
}
fn instantiate_canonical_query_response<'tcx>(
Certainty::Yes => OldCertainty::Proven,
Certainty::Maybe(_) => OldCertainty::Ambiguous,
},
- opaque_types: resp.external_constraints.opaque_types,
+ // FIXME: This to_owned makes me sad, but we should eventually impl
+ // `instantiate_query_response_and_region_obligations` separately
+ // instead of piggybacking off of the old implementation.
+ opaque_types: resp.external_constraints.opaque_types.to_owned(),
value: resp.certainty,
}),
) else { bug!(); };
variables: goal.variables,
value: Response {
var_values: CanonicalVarValues::make_identity(tcx, goal.variables),
- external_constraints: Default::default(),
+ // FIXME: maybe we should store the "no response" version in tcx, like
+ // we do for tcx.types and stuff.
+ external_constraints: tcx
+ .intern_external_constraints(ExternalConstraintsData::default()),
certainty,
},
})
projection_ty: goal.predicate.projection_ty,
term: unconstrained_rhs,
});
- let (_has_changed, normalize_certainty) =
- self.evaluate_goal(goal.with(self.tcx(), unconstrained_predicate))?;
+ let (_has_changed, normalize_certainty) = self.in_projection_eq_hack(|this| {
+ this.evaluate_goal(goal.with(this.tcx(), unconstrained_predicate))
+ })?;
let nested_eq_goals =
self.infcx.eq(goal.param_env, unconstrained_rhs, predicate.term)?;
}
}
+ /// This sets a flag used by a debug assert in [`EvalCtxt::evaluate_goal`],
+ /// see the comment in that method for more details.
+ fn in_projection_eq_hack<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
+ self.in_projection_eq_hack = true;
+ let result = f(self);
+ self.in_projection_eq_hack = false;
+ result
+ }
+
/// Is the projection predicate is of the form `exists<T> <Ty as Trait>::Assoc = T`.
///
/// This is the case if the `term` is an inference variable in the innermost universe
&& goal.param_env.visit_with(&mut visitor).is_continue()
}
+ /// After normalizing the projection to `normalized_alias` with the given
+ /// `normalization_certainty`, constrain the inference variable `term` to it
+ /// and return a query response.
+ fn eq_term_and_make_canonical_response(
+ &mut self,
+ goal: Goal<'tcx, ProjectionPredicate<'tcx>>,
+ normalization_certainty: Certainty,
+ normalized_alias: impl Into<ty::Term<'tcx>>,
+ ) -> QueryResult<'tcx> {
+ // The term of our goal should be fully unconstrained, so this should never fail.
+ //
+ // It can however be ambiguous when the `normalized_alias` contains a projection.
+ let nested_goals = self
+ .infcx
+ .eq(goal.param_env, goal.predicate.term, normalized_alias.into())
+ .expect("failed to unify with unconstrained term");
+ let rhs_certainty =
+ self.evaluate_all(nested_goals).expect("failed to unify with unconstrained term");
+
+ self.make_canonical_response(normalization_certainty.unify_and(rhs_certainty))
+ }
+
fn merge_project_candidates(
&mut self,
mut candidates: Vec<Candidate<'tcx>>,
.map(|pred| goal.with(tcx, pred));
nested_goals.extend(where_clause_bounds);
- let trait_ref_certainty = ecx.evaluate_all(nested_goals)?;
+ let match_impl_certainty = ecx.evaluate_all(nested_goals)?;
// In case the associated item is hidden due to specialization, we have to
// return ambiguity this would otherwise be incomplete, resulting in
goal.predicate.def_id(),
impl_def_id
)? else {
- return ecx.make_canonical_response(trait_ref_certainty.unify_and(Certainty::AMBIGUOUS));
+ return ecx.make_canonical_response(match_impl_certainty.unify_and(Certainty::AMBIGUOUS));
};
if !assoc_def.item.defaultness(tcx).has_value() {
ty.map_bound(|ty| ty.into())
};
- // The term of our goal should be fully unconstrained, so this should never fail.
- //
- // It can however be ambiguous when the resolved type is a projection.
- let nested_goals = ecx
- .infcx
- .eq(goal.param_env, goal.predicate.term, term.subst(tcx, substs))
- .expect("failed to unify with unconstrained term");
- let rhs_certainty =
- ecx.evaluate_all(nested_goals).expect("failed to unify with unconstrained term");
-
- ecx.make_canonical_response(trait_ref_certainty.unify_and(rhs_certainty))
+ ecx.eq_term_and_make_canonical_response(goal, match_impl_certainty, term.subst(tcx, substs))
})
}
)?;
let subst_certainty = ecx.evaluate_all(nested_goals)?;
- // The term of our goal should be fully unconstrained, so this should never fail.
- //
- // It can however be ambiguous when the resolved type is a projection.
- let nested_goals = ecx
- .infcx
- .eq(goal.param_env, goal.predicate.term, assumption_projection_pred.term)
- .expect("failed to unify with unconstrained term");
- let rhs_certainty = ecx
- .evaluate_all(nested_goals)
- .expect("failed to unify with unconstrained term");
-
- ecx.make_canonical_response(subst_certainty.unify_and(rhs_certainty))
+ ecx.eq_term_and_make_canonical_response(
+ goal,
+ subst_certainty,
+ assumption_projection_pred.term,
+ )
})
} else {
Err(NoSolution)
[ty::GenericArg::from(goal.predicate.self_ty())],
));
- let mut nested_goals = ecx.infcx.eq(
- goal.param_env,
- goal.predicate.term.ty().unwrap(),
+ let is_sized_certainty = ecx.evaluate_goal(goal.with(tcx, sized_predicate))?.1;
+ return ecx.eq_term_and_make_canonical_response(
+ goal,
+ is_sized_certainty,
tcx.types.unit,
- )?;
- nested_goals.push(goal.with(tcx, sized_predicate));
-
- return ecx.evaluate_all_and_make_canonical_response(nested_goals);
+ );
}
ty::Adt(def, substs) if def.is_struct() => {
tcx,
ty::Binder::dummy(goal.predicate.with_self_ty(tcx, self_ty)),
);
- return ecx.evaluate_all_and_make_canonical_response(vec![new_goal]);
+ let (_, certainty) = ecx.evaluate_goal(new_goal)?;
+ return ecx.make_canonical_response(certainty);
}
}
}
tcx,
ty::Binder::dummy(goal.predicate.with_self_ty(tcx, self_ty)),
);
- return ecx.evaluate_all_and_make_canonical_response(vec![new_goal]);
+ let (_, certainty) = ecx.evaluate_goal(new_goal)?;
+ return ecx.make_canonical_response(certainty);
}
},
),
};
- let nested_goals =
- ecx.infcx.eq(goal.param_env, goal.predicate.term.ty().unwrap(), metadata_ty)?;
- ecx.evaluate_all_and_make_canonical_response(nested_goals)
+ ecx.eq_term_and_make_canonical_response(goal, Certainty::Yes, metadata_ty)
})
}
.to_predicate(tcx),
)
}
+
+ fn consider_builtin_unsize_candidate(
+ _ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx> {
+ bug!("`Unsize` does not have an associated type: {:?}", goal);
+ }
+
+ fn consider_builtin_dyn_upcast_candidates(
+ _ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> Vec<super::CanonicalResponse<'tcx>> {
+ bug!("`Unsize` does not have an associated type: {:?}", goal);
+ }
+
+ fn consider_builtin_discriminant_kind_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx> {
+ let discriminant = goal.predicate.self_ty().discriminant_ty(ecx.tcx());
+ ecx.infcx
+ .probe(|_| ecx.eq_term_and_make_canonical_response(goal, Certainty::Yes, discriminant))
+ }
}
/// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code.
}
pub(super) fn provisional_result(&self, entry_index: EntryIndex) -> QueryResult<'tcx> {
- // FIXME: Responses should probably be `Copy` as well
- self.entries[entry_index].response.clone()
+ self.entries[entry_index].response
}
}
/// Tries putting the new goal on the stack, returning an error if it is already cached.
///
/// This correctly updates the provisional cache if there is a cycle.
+ #[instrument(level = "debug", skip(self, tcx), ret)]
pub(super) fn try_push_stack(
&mut self,
tcx: TyCtxt<'tcx>,
Entry::Occupied(entry_index) => {
let entry_index = *entry_index.get();
- cache.add_dependency_of_leaf_on(entry_index);
let stack_depth = cache.depth(entry_index);
+ debug!("encountered cycle with depth {stack_depth:?}");
+
+ cache.add_dependency_of_leaf_on(entry_index);
self.stack[stack_depth].has_been_used = true;
// NOTE: The goals on the stack aren't the only goals involved in this cycle.
/// updated the provisional cache and we have to recompute the current goal.
///
/// FIXME: Refer to the rustc-dev-guide entry once it exists.
+ #[instrument(level = "debug", skip(self, tcx, actual_goal), ret)]
pub(super) fn try_finalize_goal(
&mut self,
tcx: TyCtxt<'tcx>,
use super::assembly::{self, Candidate, CandidateSource};
use super::infcx_ext::InferCtxtExt;
-use super::{Certainty, EvalCtxt, Goal, QueryResult};
+use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, QueryResult};
use rustc_hir::def_id::DefId;
use rustc_infer::infer::InferCtxt;
use rustc_infer::traits::query::NoSolution;
+use rustc_infer::traits::util::supertraits;
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
use rustc_middle::ty::{TraitPredicate, TypeVisitable};
.to_predicate(tcx),
)
}
+
+ fn consider_builtin_unsize_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx> {
+ let tcx = ecx.tcx();
+ let a_ty = goal.predicate.self_ty();
+ let b_ty = goal.predicate.trait_ref.substs.type_at(1);
+ if b_ty.is_ty_var() {
+ return ecx.make_canonical_response(Certainty::AMBIGUOUS);
+ }
+ ecx.infcx.probe(|_| {
+ match (a_ty.kind(), b_ty.kind()) {
+ // Trait upcasting, or `dyn Trait + Auto + 'a` -> `dyn Trait + 'b`
+ (&ty::Dynamic(_, _, ty::Dyn), &ty::Dynamic(_, _, ty::Dyn)) => {
+ // Dyn upcasting is handled separately, since due to upcasting,
+ // when there are two supertraits that differ by substs, we
+ // may return more than one query response.
+ return Err(NoSolution);
+ }
+ // `T` -> `dyn Trait` unsizing
+ (_, &ty::Dynamic(data, region, ty::Dyn)) => {
+ // Can only unsize to an object-safe type
+ if data
+ .principal_def_id()
+ .map_or(false, |def_id| !tcx.check_is_object_safe(def_id))
+ {
+ return Err(NoSolution);
+ }
+
+ let Some(sized_def_id) = tcx.lang_items().sized_trait() else {
+ return Err(NoSolution);
+ };
+ let nested_goals: Vec<_> = data
+ .iter()
+ // Check that the type implements all of the predicates of the def-id.
+ // (i.e. the principal, all of the associated types match, and any auto traits)
+ .map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty)))
+ .chain([
+ // The type must be Sized to be unsized.
+ goal.with(
+ tcx,
+ ty::Binder::dummy(tcx.mk_trait_ref(sized_def_id, [a_ty])),
+ ),
+ // The type must outlive the lifetime of the `dyn` we're unsizing into.
+ goal.with(tcx, ty::Binder::dummy(ty::OutlivesPredicate(a_ty, region))),
+ ])
+ .collect();
+
+ ecx.evaluate_all_and_make_canonical_response(nested_goals)
+ }
+ // `[T; n]` -> `[T]` unsizing
+ (&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => {
+ // We just require that the element type stays the same
+ let nested_goals = ecx.infcx.eq(goal.param_env, a_elem_ty, b_elem_ty)?;
+ ecx.evaluate_all_and_make_canonical_response(nested_goals)
+ }
+ // Struct unsizing `Struct<T>` -> `Struct<U>` where `T: Unsize<U>`
+ (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs))
+ if a_def.is_struct() && a_def.did() == b_def.did() =>
+ {
+ let unsizing_params = tcx.unsizing_params_for_adt(a_def.did());
+ // We must be unsizing some type parameters. This also implies
+ // that the struct has a tail field.
+ if unsizing_params.is_empty() {
+ return Err(NoSolution);
+ }
+
+ let tail_field = a_def
+ .non_enum_variant()
+ .fields
+ .last()
+ .expect("expected unsized ADT to have a tail field");
+ let tail_field_ty = tcx.bound_type_of(tail_field.did);
+
+ let a_tail_ty = tail_field_ty.subst(tcx, a_substs);
+ let b_tail_ty = tail_field_ty.subst(tcx, b_substs);
+
+ // Substitute just the unsizing params from B into A. The type after
+ // this substitution must be equal to B. This is so we don't unsize
+ // unrelated type parameters.
+ let new_a_substs = tcx.mk_substs(a_substs.iter().enumerate().map(|(i, a)| {
+ if unsizing_params.contains(i as u32) { b_substs[i] } else { a }
+ }));
+ let unsized_a_ty = tcx.mk_adt(a_def, new_a_substs);
+
+ // Finally, we require that `TailA: Unsize<TailB>` for the tail field
+ // types.
+ let mut nested_goals = ecx.infcx.eq(goal.param_env, unsized_a_ty, b_ty)?;
+ nested_goals.push(goal.with(
+ tcx,
+ ty::Binder::dummy(
+ tcx.mk_trait_ref(goal.predicate.def_id(), [a_tail_ty, b_tail_ty]),
+ ),
+ ));
+
+ ecx.evaluate_all_and_make_canonical_response(nested_goals)
+ }
+ // Tuple unsizing `(.., T)` -> `(.., U)` where `T: Unsize<U>`
+ (&ty::Tuple(a_tys), &ty::Tuple(b_tys))
+ if a_tys.len() == b_tys.len() && !a_tys.is_empty() =>
+ {
+ let (a_last_ty, a_rest_tys) = a_tys.split_last().unwrap();
+ let b_last_ty = b_tys.last().unwrap();
+
+ // Substitute just the tail field of B., and require that they're equal.
+ let unsized_a_ty = tcx.mk_tup(a_rest_tys.iter().chain([b_last_ty]));
+ let mut nested_goals = ecx.infcx.eq(goal.param_env, unsized_a_ty, b_ty)?;
+
+ // Similar to ADTs, require that the rest of the fields are equal.
+ nested_goals.push(goal.with(
+ tcx,
+ ty::Binder::dummy(
+ tcx.mk_trait_ref(goal.predicate.def_id(), [*a_last_ty, *b_last_ty]),
+ ),
+ ));
+
+ ecx.evaluate_all_and_make_canonical_response(nested_goals)
+ }
+ _ => Err(NoSolution),
+ }
+ })
+ }
+
+ fn consider_builtin_dyn_upcast_candidates(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> Vec<CanonicalResponse<'tcx>> {
+ let tcx = ecx.tcx();
+
+ let a_ty = goal.predicate.self_ty();
+ let b_ty = goal.predicate.trait_ref.substs.type_at(1);
+ let ty::Dynamic(a_data, a_region, ty::Dyn) = *a_ty.kind() else {
+ return vec![];
+ };
+ let ty::Dynamic(b_data, b_region, ty::Dyn) = *b_ty.kind() else {
+ return vec![];
+ };
+
+ // All of a's auto traits need to be in b's auto traits.
+ let auto_traits_compatible =
+ b_data.auto_traits().all(|b| a_data.auto_traits().any(|a| a == b));
+ if !auto_traits_compatible {
+ return vec![];
+ }
+
+ let mut unsize_dyn_to_principal = |principal: Option<ty::PolyExistentialTraitRef<'tcx>>| {
+ ecx.infcx.probe(|_| -> Result<_, NoSolution> {
+ // Require that all of the trait predicates from A match B, except for
+ // the auto traits. We do this by constructing a new A type with B's
+ // auto traits, and equating these types.
+ let new_a_data = principal
+ .into_iter()
+ .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait))
+ .chain(a_data.iter().filter(|a| {
+ matches!(a.skip_binder(), ty::ExistentialPredicate::Projection(_))
+ }))
+ .chain(
+ b_data
+ .auto_traits()
+ .map(ty::ExistentialPredicate::AutoTrait)
+ .map(ty::Binder::dummy),
+ );
+ let new_a_data = tcx.mk_poly_existential_predicates(new_a_data);
+ let new_a_ty = tcx.mk_dynamic(new_a_data, b_region, ty::Dyn);
+
+ // We also require that A's lifetime outlives B's lifetime.
+ let mut nested_obligations = ecx.infcx.eq(goal.param_env, new_a_ty, b_ty)?;
+ nested_obligations.push(
+ goal.with(tcx, ty::Binder::dummy(ty::OutlivesPredicate(a_region, b_region))),
+ );
+
+ ecx.evaluate_all_and_make_canonical_response(nested_obligations)
+ })
+ };
+
+ let mut responses = vec![];
+ // If the principal def ids match (or are both none), then we're not doing
+ // trait upcasting. We're just removing auto traits (or shortening the lifetime).
+ if a_data.principal_def_id() == b_data.principal_def_id() {
+ if let Ok(response) = unsize_dyn_to_principal(a_data.principal()) {
+ responses.push(response);
+ }
+ } else if let Some(a_principal) = a_data.principal()
+ && let Some(b_principal) = b_data.principal()
+ {
+ for super_trait_ref in supertraits(tcx, a_principal.with_self_ty(tcx, a_ty)) {
+ if super_trait_ref.def_id() != b_principal.def_id() {
+ continue;
+ }
+ let erased_trait_ref = super_trait_ref
+ .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
+ if let Ok(response) = unsize_dyn_to_principal(Some(erased_trait_ref)) {
+ responses.push(response);
+ }
+ }
+ }
+
+ responses
+ }
+
+ fn consider_builtin_discriminant_kind_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ _goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx> {
+ // `DiscriminantKind` is automatically implemented for every type.
+ ecx.make_canonical_response(Certainty::Yes)
+ }
}
impl<'tcx> EvalCtxt<'_, 'tcx> {
}
if let Some(Ok(c)) = single_match {
- let ocx = ObligationCtxt::new(infcx);
+ let ocx = ObligationCtxt::new_in_snapshot(infcx);
assert!(ocx.eq(&ObligationCause::dummy(), param_env, c.ty(), ct.ty()).is_ok());
assert!(ocx.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok());
assert!(ocx.select_all_or_error().is_empty());
}
ty::PredicateKind::WellFormed(ty) => {
- if self.tcx.sess.opts.unstable_opts.trait_solver == TraitSolver::Classic {
- // WF predicates cannot themselves make
- // errors. They can only block due to
- // ambiguity; otherwise, they always
- // degenerate into other obligations
- // (which may fail).
- span_bug!(span, "WF predicate not satisfied for {:?}", ty);
- } else {
- // FIXME: we'll need a better message which takes into account
- // which bounds actually failed to hold.
- self.tcx.sess.struct_span_err(
- span,
- &format!("the type `{}` is not well-formed", ty),
- )
+ match self.tcx.sess.opts.unstable_opts.trait_solver {
+ TraitSolver::Classic => {
+ // WF predicates cannot themselves make
+ // errors. They can only block due to
+ // ambiguity; otherwise, they always
+ // degenerate into other obligations
+ // (which may fail).
+ span_bug!(span, "WF predicate not satisfied for {:?}", ty);
+ }
+ TraitSolver::Chalk | TraitSolver::Next => {
+ // FIXME: we'll need a better message which takes into account
+ // which bounds actually failed to hold.
+ self.tcx.sess.struct_span_err(
+ span,
+ &format!("the type `{}` is not well-formed", ty),
+ )
+ }
}
}
with_forced_trimmed_paths! {
if Some(pred.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() {
+ let fn_kind = self_ty.prefix_string(self.tcx);
+ let item = match self_ty.kind() {
+ ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(),
+ _ => self_ty.to_string(),
+ };
Some(format!(
- "expected `{self_ty}` to be a {fn_kind} that returns `{expected_ty}`, but it \
+ "expected `{item}` to be a {fn_kind} that returns `{expected_ty}`, but it \
returns `{normalized_ty}`",
- fn_kind = self_ty.prefix_string(self.tcx)
))
} else if Some(trait_def_id) == self.tcx.lang_items().future_trait() {
Some(format!(
.cloned()
.unwrap_or_else(|| {
bug!(
- "node_type: no type for node `{}`",
+ "node_type: no type for node {}",
ty::tls::with(|tcx| tcx
.hir()
.node_to_string(await_expr.hir_id))
// NOTE: This check happens last, because it results in a lint, and not a
// hard error.
- if tcx
- .predicates_of(method.def_id)
- .predicates
- .iter()
- // A trait object can't claim to live more than the concrete type,
- // so outlives predicates will always hold.
- .cloned()
- .filter(|(p, _)| p.to_opt_type_outlives().is_none())
- .any(|pred| contains_illegal_self_type_reference(tcx, trait_def_id, pred))
- {
+ if tcx.predicates_of(method.def_id).predicates.iter().any(|&(pred, span)| {
+ // dyn Trait is okay:
+ //
+ // trait Trait {
+ // fn f(&self) where Self: 'static;
+ // }
+ //
+ // because a trait object can't claim to live longer than the concrete
+ // type. If the lifetime bound holds on dyn Trait then it's guaranteed
+ // to hold as well on the concrete type.
+ if pred.to_opt_type_outlives().is_some() {
+ return false;
+ }
+
+ // dyn Trait is okay:
+ //
+ // auto trait AutoTrait {}
+ //
+ // trait Trait {
+ // fn f(&self) where Self: AutoTrait;
+ // }
+ //
+ // because `impl AutoTrait for dyn Trait` is disallowed by coherence.
+ // Traits with a default impl are implemented for a trait object if and
+ // only if the autotrait is one of the trait object's trait bounds, like
+ // in `dyn Trait + AutoTrait`. This guarantees that trait objects only
+ // implement auto traits if the underlying type does as well.
+ if let ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
+ trait_ref: pred_trait_ref,
+ constness: ty::BoundConstness::NotConst,
+ polarity: ty::ImplPolarity::Positive,
+ })) = pred.kind().skip_binder()
+ && pred_trait_ref.self_ty() == tcx.types.self_param
+ && tcx.trait_is_auto(pred_trait_ref.def_id)
+ {
+ // Consider bounds like `Self: Bound<Self>`. Auto traits are not
+ // allowed to have generic parameters so `auto trait Bound<T> {}`
+ // would already have reported an error at the definition of the
+ // auto trait.
+ if pred_trait_ref.substs.len() != 1 {
+ tcx.sess.diagnostic().delay_span_bug(
+ span,
+ "auto traits cannot have generic parameters",
+ );
+ }
+ return false;
+ }
+
+ contains_illegal_self_type_reference(tcx, trait_def_id, pred.clone())
+ }) {
return Some(MethodViolationCode::WhereClauseReferencesSelf);
}
}
ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
let universe = self.universe_for(debruijn);
- let p = ty::PlaceholderType { universe, name: bound_ty.var };
+ let p = ty::PlaceholderType { universe, name: bound_ty.kind };
self.mapped_types.insert(p, bound_ty);
self.infcx.tcx.mk_ty(ty::Placeholder(p))
}
.kind
{
GenericParamDefKind::Type { .. } => {
- let kind = ty::BoundTyKind::Param(param.name);
+ let kind = ty::BoundTyKind::Param(param.def_id, param.name);
let bound_var = ty::BoundVariableKind::Ty(kind);
bound_vars.push(bound_var);
tcx.mk_ty(ty::Bound(
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
derived,
impl_def_id,
+ impl_def_predicate_index: None,
span: obligation.cause.span,
}))
});
.at(&cause, obligation.param_env)
.define_opaque_types(false)
.eq(placeholder_obligation_trait_ref, impl_trait_ref)
- .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{e}`"))?;
+ .map_err(|e| {
+ debug!("match_impl: failed eq_trait_refs due to `{}`", e.to_string(self.tcx()))
+ })?;
nested_obligations.extend(obligations);
if !self.is_intercrate()
assert_eq!(predicates.parent, None);
let predicates = predicates.instantiate_own(tcx, substs);
let mut obligations = Vec::with_capacity(predicates.len());
- for (predicate, span) in predicates {
+ for (index, (predicate, span)) in predicates.into_iter().enumerate() {
let cause = cause.clone().derived_cause(parent_trait_pred, |derived| {
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
derived,
impl_def_id: def_id,
+ impl_def_predicate_index: Some(index),
span,
}))
});
[dependencies]
tracing = "0.1"
-rustc_attr = { path = "../rustc_attr" }
rustc_middle = { path = "../rustc_middle" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_hir = { path = "../rustc_hir" }
ty::INNERMOST,
ty::BoundTy {
var: ty::BoundVar::from(param.index),
- kind: ty::BoundTyKind::Param(param.name),
+ kind: ty::BoundTyKind::Param(param.def_id, param.name),
},
))
.into(),
ty::Placeholder(_placeholder) => {
chalk_ir::TyKind::Placeholder(chalk_ir::PlaceholderIndex {
ui: chalk_ir::UniverseIndex { counter: _placeholder.universe.as_usize() },
- idx: _placeholder.name.as_usize(),
+ idx: _placeholder.name.expect_anon() as usize,
})
}
ty::Infer(_infer) => unimplemented!(),
),
TyKind::Foreign(def_id) => ty::Foreign(def_id.0),
TyKind::Error => return interner.tcx.ty_error(),
- TyKind::Placeholder(placeholder) => ty::Placeholder(ty::Placeholder {
- universe: ty::UniverseIndex::from_usize(placeholder.ui.counter),
- name: ty::BoundVar::from_usize(placeholder.idx),
- }),
TyKind::Alias(alias_ty) => match alias_ty {
chalk_ir::AliasTy::Projection(projection) => ty::Alias(
ty::Projection,
),
},
TyKind::Function(_quantified_ty) => unimplemented!(),
- TyKind::BoundVar(_bound) => ty::Bound(
- ty::DebruijnIndex::from_usize(_bound.debruijn.depth() as usize),
+ TyKind::BoundVar(bound) => ty::Bound(
+ ty::DebruijnIndex::from_usize(bound.debruijn.depth() as usize),
ty::BoundTy {
- var: ty::BoundVar::from_usize(_bound.index),
- kind: ty::BoundTyKind::Anon,
+ var: ty::BoundVar::from_usize(bound.index),
+ kind: ty::BoundTyKind::Anon(bound.index as u32),
},
),
+ TyKind::Placeholder(placeholder) => ty::Placeholder(ty::Placeholder {
+ universe: ty::UniverseIndex::from_usize(placeholder.ui.counter),
+ name: ty::BoundTyKind::Anon(placeholder.idx as u32),
+ }),
TyKind::InferenceVar(_, _) => unimplemented!(),
TyKind::Dyn(_) => unimplemented!(),
};
ty::RePlaceholder(placeholder_region) => {
chalk_ir::LifetimeData::Placeholder(chalk_ir::PlaceholderIndex {
ui: chalk_ir::UniverseIndex { counter: placeholder_region.universe.index() },
- idx: 0,
+ idx: 0, // FIXME: This `idx: 0` is sus.
})
.intern(interner)
}
let self_ty = interner.tcx.mk_ty(ty::Bound(
// This is going to be wrapped in a binder
ty::DebruijnIndex::from_usize(1),
- ty::BoundTy { var: ty::BoundVar::from_usize(0), kind: ty::BoundTyKind::Anon },
+ ty::BoundTy { var: ty::BoundVar::from_usize(0), kind: ty::BoundTyKind::Anon(0) },
));
let where_clauses = predicates.into_iter().map(|predicate| {
let (predicate, binders, _named_regions) =
binder_index: ty::DebruijnIndex,
list: Vec<rustc_middle::ty::ParamTy>,
next_ty_placeholder: usize,
- pub(crate) params: rustc_data_structures::fx::FxHashMap<usize, rustc_middle::ty::ParamTy>,
+ pub(crate) params: rustc_data_structures::fx::FxHashMap<u32, rustc_middle::ty::ParamTy>,
pub(crate) named_regions: BTreeMap<DefId, u32>,
}
ty::Param(param) => match self.list.iter().position(|r| r == ¶m) {
Some(idx) => self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
universe: ty::UniverseIndex::from_usize(0),
- name: ty::BoundVar::from_usize(idx),
+ name: ty::BoundTyKind::Anon(idx as u32),
})),
None => {
self.list.push(param);
let idx = self.list.len() - 1 + self.next_ty_placeholder;
- self.params.insert(idx, param);
+ self.params.insert(idx as u32, param);
self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
universe: ty::UniverseIndex::from_usize(0),
- name: ty::BoundVar::from_usize(idx),
+ name: ty::BoundTyKind::Anon(idx as u32),
}))
}
},
pub(crate) struct ReverseParamsSubstitutor<'tcx> {
tcx: TyCtxt<'tcx>,
- params: rustc_data_structures::fx::FxHashMap<usize, rustc_middle::ty::ParamTy>,
+ params: rustc_data_structures::fx::FxHashMap<u32, rustc_middle::ty::ParamTy>,
}
impl<'tcx> ReverseParamsSubstitutor<'tcx> {
pub(crate) fn new(
tcx: TyCtxt<'tcx>,
- params: rustc_data_structures::fx::FxHashMap<usize, rustc_middle::ty::ParamTy>,
+ params: rustc_data_structures::fx::FxHashMap<u32, rustc_middle::ty::ParamTy>,
) -> Self {
Self { tcx, params }
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
match *t.kind() {
ty::Placeholder(ty::PlaceholderType { universe: ty::UniverseIndex::ROOT, name }) => {
- match self.params.get(&name.as_usize()) {
+ match self.params.get(&name.expect_anon()) {
Some(param) => self.tcx.mk_ty(ty::Param(*param)),
None => t,
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() {
ty::Placeholder(p) if p.universe == self.universe_index => {
- self.next_ty_placeholder = self.next_ty_placeholder.max(p.name.as_usize() + 1);
+ self.next_ty_placeholder =
+ self.next_ty_placeholder.max(p.name.expect_anon() as usize + 1);
}
_ => (),
if let ty::BoundRegionKind::BrAnon(anon, _) = p.name {
self.next_anon_region_placeholder = self.next_anon_region_placeholder.max(anon);
}
+ // FIXME: This doesn't seem to handle BrNamed at all?
}
_ => (),
pub(crate) mod db;
pub(crate) mod lowering;
-use rustc_data_structures::fx::FxHashMap;
-
use rustc_middle::infer::canonical::{CanonicalTyVarKind, CanonicalVarKind};
use rustc_middle::traits::ChalkRustInterner;
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, ParamTy, TyCtxt, TypeFoldable, TypeVisitable};
+use rustc_middle::ty::{self, TyCtxt, TypeFoldable, TypeVisitable};
use rustc_infer::infer::canonical::{
Canonical, CanonicalVarValues, Certainty, QueryRegionConstraints, QueryResponse,
let mut params_substitutor =
ParamsSubstitutor::new(tcx, placeholders_collector.next_ty_placeholder);
let obligation = obligation.fold_with(&mut params_substitutor);
- let params: FxHashMap<usize, ParamTy> = params_substitutor.params;
+ let params = params_substitutor.params;
let max_universe = obligation.max_universe.index();
if let Some(kind) = pointee.safe {
attrs.pointee_align = Some(pointee.align);
- // `Box` (`UniqueBorrowed`) are not necessarily dereferenceable
- // for the entire duration of the function as they can be deallocated
- // at any time. Same for shared mutable references. If LLVM had a
- // way to say "dereferenceable on entry" we could use it here.
+ // `Box` are not necessarily dereferenceable for the entire duration of the function as
+ // they can be deallocated at any time. Same for non-frozen shared references (see
+ // <https://github.com/rust-lang/rust/pull/98017>), and for mutable references to
+ // potentially self-referential types (see
+ // <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>). If LLVM had a way
+ // to say "dereferenceable on entry" we could use it here.
attrs.pointee_size = match kind {
- PointerKind::UniqueBorrowed
- | PointerKind::UniqueBorrowedPinned
- | PointerKind::Frozen => pointee.size,
- PointerKind::SharedMutable | PointerKind::UniqueOwned => Size::ZERO,
+ PointerKind::Box { .. }
+ | PointerKind::SharedRef { frozen: false }
+ | PointerKind::MutableRef { unpin: false } => Size::ZERO,
+ PointerKind::SharedRef { frozen: true }
+ | PointerKind::MutableRef { unpin: true } => pointee.size,
};
// The aliasing rules for `Box<T>` are still not decided, but currently we emit
// versions at all anymore. We still support turning it off using -Zmutable-noalias.
let noalias_mut_ref = cx.tcx.sess.opts.unstable_opts.mutable_noalias;
- // `&mut` pointer parameters never alias other parameters,
- // or mutable global data
+ // `&T` where `T` contains no `UnsafeCell<U>` is immutable, and can be marked as both
+ // `readonly` and `noalias`, as LLVM's definition of `noalias` is based solely on memory
+ // dependencies rather than pointer equality. However this only applies to arguments,
+ // not return values.
//
- // `&T` where `T` contains no `UnsafeCell<U>` is immutable,
- // and can be marked as both `readonly` and `noalias`, as
- // LLVM's definition of `noalias` is based solely on memory
- // dependencies rather than pointer equality
+ // `&mut T` and `Box<T>` where `T: Unpin` are unique and hence `noalias`.
let no_alias = match kind {
- PointerKind::SharedMutable | PointerKind::UniqueBorrowedPinned => false,
- PointerKind::UniqueBorrowed => noalias_mut_ref,
- PointerKind::UniqueOwned => noalias_for_box,
- PointerKind::Frozen => true,
+ PointerKind::SharedRef { frozen } => frozen,
+ PointerKind::MutableRef { unpin } => unpin && noalias_mut_ref,
+ PointerKind::Box { unpin } => unpin && noalias_for_box,
};
// We can never add `noalias` in return position; that LLVM attribute has some very surprising semantics
// (see <https://github.com/rust-lang/unsafe-code-guidelines/issues/385#issuecomment-1368055745>).
attrs.set(ArgAttribute::NoAlias);
}
- if kind == PointerKind::Frozen && !is_return {
+ if matches!(kind, PointerKind::SharedRef { frozen: true }) && !is_return {
attrs.set(ArgAttribute::ReadOnly);
}
}
hir::ItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter(
impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()),
),
- hir::ItemKind::TraitAlias(..) => &[],
_ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
}
}
fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems<'_> {
- let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did));
- ty::AssocItems::new(items)
+ if tcx.is_trait_alias(def_id) {
+ ty::AssocItems::new(Vec::new())
+ } else {
+ let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did));
+ ty::AssocItems::new(items)
+ }
}
fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> FxHashMap<DefId, DefId> {
use rustc_middle::ty::{
self, subst::SubstsRef, AdtDef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitable,
};
-use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
+use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
use rustc_span::symbol::Symbol;
use rustc_span::DUMMY_SP;
use rustc_target::abi::*;
let offset = layout.fields.offset(i);
min_size = min_size.max(offset + field_layout.size);
FieldInfo {
+ kind: FieldKind::AdtField,
name,
offset: offset.bytes(),
size: field_layout.size.bytes(),
let offset = layout.fields.offset(field_idx);
upvars_size = upvars_size.max(offset + field_layout.size);
FieldInfo {
+ kind: FieldKind::Upvar,
name: Symbol::intern(&name),
offset: offset.bytes(),
size: field_layout.size.bytes(),
})
.collect();
- let variant_infos: Vec<_> = generator
+ let mut variant_infos: Vec<_> = generator
.variant_fields
.iter_enumerated()
.map(|(variant_idx, variant_def)| {
// The struct is as large as the last field's end
variant_size = variant_size.max(offset + field_layout.size);
FieldInfo {
+ kind: FieldKind::GeneratorLocal,
name: state_specific_names.get(*local).copied().flatten().unwrap_or(
Symbol::intern(&format!(".generator_field{}", local.as_usize())),
),
}
})
.collect();
+
+ // The first three variants are hardcoded to be `UNRESUMED`, `RETURNED` and `POISONED`.
+ // We will move the `RETURNED` and `POISONED` elements to the end so we
+ // are left with a sorting order according to the generators yield points:
+ // First `Unresumed`, then the `SuspendN` followed by `Returned` and `Panicked` (POISONED).
+ let end_states = variant_infos.drain(1..=2);
+ let end_states: Vec<_> = end_states.collect();
+ variant_infos.extend(end_states);
+
(
variant_infos,
match tag_encoding {
},
};
- // FIXME(eddyb) cache this (including computing `unsizing_params`)
- // by putting it in a query; it would only need the `DefId` as it
- // looks at declared field types, not anything substituted.
-
// The last field of the structure has to exist and contain type/const parameters.
let Some((tail_field, prefix_fields)) =
def.non_enum_variant().fields.split_last() else
# Select LTO mode that will be used for compiling rustc. By default, thin local LTO
# (LTO within a single crate) is used (like for any Rust crate). You can also select
-# "thin" or "fat" to apply Thin/Fat LTO to the `rustc_driver` dylib.
+# "thin" or "fat" to apply Thin/Fat LTO to the `rustc_driver` dylib, or "off" to disable
+# LTO entirely.
#lto = "thin-local"
# =============================================================================
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_stable(feature = "const_vec_deque_new", since = "CURRENT_RUSTC_VERSION")]
+ #[rustc_const_stable(feature = "const_vec_deque_new", since = "1.68.0")]
#[must_use]
pub const fn new() -> VecDeque<T> {
// FIXME: This should just be `VecDeque::new_in(Global)` once that hits stable.
}
}
+// Specializable trait for implementing ToOwned::clone_into. This is
+// public in the crate and has the Allocator parameter so that
+// vec::clone_from use it too.
+#[cfg(not(no_global_oom_handling))]
+pub(crate) trait SpecCloneIntoVec<T, A: Allocator> {
+ fn clone_into(&self, target: &mut Vec<T, A>);
+}
+
+#[cfg(not(no_global_oom_handling))]
+impl<T: Clone, A: Allocator> SpecCloneIntoVec<T, A> for [T] {
+ default fn clone_into(&self, target: &mut Vec<T, A>) {
+ // drop anything in target that will not be overwritten
+ target.truncate(self.len());
+
+ // target.len <= self.len due to the truncate above, so the
+ // slices here are always in-bounds.
+ let (init, tail) = self.split_at(target.len());
+
+ // reuse the contained values' allocations/resources.
+ target.clone_from_slice(init);
+ target.extend_from_slice(tail);
+ }
+}
+
+#[cfg(not(no_global_oom_handling))]
+impl<T: Copy, A: Allocator> SpecCloneIntoVec<T, A> for [T] {
+ fn clone_into(&self, target: &mut Vec<T, A>) {
+ target.clear();
+ target.extend_from_slice(self);
+ }
+}
+
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone> ToOwned for [T] {
}
fn clone_into(&self, target: &mut Vec<T>) {
- // drop anything in target that will not be overwritten
- target.truncate(self.len());
-
- // target.len <= self.len due to the truncate above, so the
- // slices here are always in-bounds.
- let (init, tail) = self.split_at(target.len());
-
- // reuse the contained values' allocations/resources.
- target.clone_from_slice(init);
- target.extend_from_slice(tail);
+ SpecCloneIntoVec::clone_into(self, target);
}
}
}
#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "bool_to_string_specialization", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "bool_to_string_specialization", since = "1.68.0")]
impl ToString for bool {
#[inline]
fn to_string(&self) -> String {
}
}
-#[cfg(not(no_global_oom_handling))]
-trait SpecCloneFrom {
- fn clone_from(this: &mut Self, other: &Self);
-}
-
-#[cfg(not(no_global_oom_handling))]
-impl<T: Clone, A: Allocator> SpecCloneFrom for Vec<T, A> {
- default fn clone_from(this: &mut Self, other: &Self) {
- // drop anything that will not be overwritten
- this.truncate(other.len());
-
- // self.len <= other.len due to the truncate above, so the
- // slices here are always in-bounds.
- let (init, tail) = other.split_at(this.len());
-
- // reuse the contained values' allocations/resources.
- this.clone_from_slice(init);
- this.extend_from_slice(tail);
- }
-}
-
-#[cfg(not(no_global_oom_handling))]
-impl<T: Copy, A: Allocator> SpecCloneFrom for Vec<T, A> {
- fn clone_from(this: &mut Self, other: &Self) {
- this.clear();
- this.extend_from_slice(other);
- }
-}
-
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
}
fn clone_from(&mut self, other: &Self) {
- SpecCloneFrom::clone_from(self, other)
+ crate::slice::SpecCloneIntoVec::clone_into(other.as_slice(), self);
}
}
-use test::Bencher;
+use test::{black_box, Bencher};
const CHARS: [char; 9] = ['0', 'x', '2', '5', 'A', 'f', '7', '8', '9'];
const RADIX: [u32; 5] = [2, 8, 10, 16, 32];
#[bench]
fn bench_to_digit_radix_2(b: &mut Bencher) {
- b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(2)).min())
+ b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(2)).min())
}
#[bench]
fn bench_to_digit_radix_10(b: &mut Bencher) {
- b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(10)).min())
+ b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(10)).min())
}
#[bench]
fn bench_to_digit_radix_16(b: &mut Bencher) {
- b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(16)).min())
+ b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(16)).min())
}
#[bench]
fn bench_to_digit_radix_36(b: &mut Bencher) {
- b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(36)).min())
+ b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(36)).min())
}
#[bench]
.cycle()
.zip(RADIX.iter().cycle())
.take(10_000)
- .map(|(c, radix)| c.to_digit(*radix))
+ .map(|(c, radix)| black_box(c).to_digit(*radix))
.min()
})
}
#[bench]
fn bench_to_ascii_uppercase(b: &mut Bencher) {
- b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_ascii_uppercase()).min())
+ b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_ascii_uppercase()).min())
}
#[bench]
fn bench_to_ascii_lowercase(b: &mut Bencher) {
- b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_ascii_lowercase()).min())
+ b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_ascii_lowercase()).min())
}
#[bench]
fn bench_ascii_mix_to_uppercase(b: &mut Bencher) {
- b.iter(|| (0..=255).cycle().take(10_000).map(|b| char::from(b).to_uppercase()).count())
+ b.iter(|| {
+ (0..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count()
+ })
}
#[bench]
fn bench_ascii_mix_to_lowercase(b: &mut Bencher) {
- b.iter(|| (0..=255).cycle().take(10_000).map(|b| char::from(b).to_lowercase()).count())
+ b.iter(|| {
+ (0..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count()
+ })
}
#[bench]
fn bench_ascii_char_to_uppercase(b: &mut Bencher) {
- b.iter(|| (0..=127).cycle().take(10_000).map(|b| char::from(b).to_uppercase()).count())
+ b.iter(|| {
+ (0..=127).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count()
+ })
}
#[bench]
fn bench_ascii_char_to_lowercase(b: &mut Bencher) {
- b.iter(|| (0..=127).cycle().take(10_000).map(|b| char::from(b).to_lowercase()).count())
+ b.iter(|| {
+ (0..=127).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count()
+ })
}
#[bench]
fn bench_non_ascii_char_to_uppercase(b: &mut Bencher) {
- b.iter(|| (128..=255).cycle().take(10_000).map(|b| char::from(b).to_uppercase()).count())
+ b.iter(|| {
+ (128..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count()
+ })
}
#[bench]
fn bench_non_ascii_char_to_lowercase(b: &mut Bencher) {
- b.iter(|| (128..=255).cycle().take(10_000).map(|b| char::from(b).to_lowercase()).count())
+ b.iter(|| {
+ (128..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count()
+ })
}
use super::super::*;
use core::num::flt2dec::strategy::dragon::*;
use std::mem::MaybeUninit;
-use test::Bencher;
+use test::{black_box, Bencher};
#[bench]
fn bench_small_shortest(b: &mut Bencher) {
let decoded = decode_finite(3.141592f64);
let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS];
b.iter(|| {
- format_shortest(&decoded, &mut buf);
+ format_shortest(black_box(&decoded), &mut buf);
});
}
let decoded = decode_finite(f64::MAX);
let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS];
b.iter(|| {
- format_shortest(&decoded, &mut buf);
+ format_shortest(black_box(&decoded), &mut buf);
});
}
let decoded = decode_finite(3.141592f64);
let mut buf = [MaybeUninit::new(0); 3];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
let decoded = decode_finite(f64::MAX);
let mut buf = [MaybeUninit::new(0); 3];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
let decoded = decode_finite(3.141592f64);
let mut buf = [MaybeUninit::new(0); 12];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
let decoded = decode_finite(f64::MAX);
let mut buf = [MaybeUninit::new(0); 12];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
let decoded = decode_finite(3.141592f64);
let mut buf = [MaybeUninit::new(0); 1024];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
let decoded = decode_finite(f64::MAX);
let mut buf = [MaybeUninit::new(0); 1024];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
use super::super::*;
use core::num::flt2dec::strategy::grisu::*;
use std::mem::MaybeUninit;
-use test::Bencher;
+use test::{black_box, Bencher};
pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
match decode(v).1 {
let decoded = decode_finite(3.141592f64);
let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS];
b.iter(|| {
- format_shortest(&decoded, &mut buf);
+ format_shortest(black_box(&decoded), &mut buf);
});
}
let decoded = decode_finite(f64::MAX);
let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS];
b.iter(|| {
- format_shortest(&decoded, &mut buf);
+ format_shortest(black_box(&decoded), &mut buf);
});
}
let decoded = decode_finite(3.141592f64);
let mut buf = [MaybeUninit::new(0); 3];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
let decoded = decode_finite(f64::MAX);
let mut buf = [MaybeUninit::new(0); 3];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
let decoded = decode_finite(3.141592f64);
let mut buf = [MaybeUninit::new(0); 12];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
let decoded = decode_finite(f64::MAX);
let mut buf = [MaybeUninit::new(0); 12];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
let decoded = decode_finite(3.141592f64);
let mut buf = [MaybeUninit::new(0); 1024];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
let decoded = decode_finite(f64::MAX);
let mut buf = [MaybeUninit::new(0); 1024];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
#![stable(feature = "rust1", since = "1.0.0")]
-use crate::const_closure::ConstFnMutClosure;
use crate::marker::Destruct;
use self::Ordering::*;
Self: Sized,
Self: ~const Destruct,
{
- #[cfg(not(bootstrap))]
- {
- max_by(self, other, Ord::cmp)
- }
-
- #[cfg(bootstrap)]
- match self.cmp(&other) {
- Ordering::Less | Ordering::Equal => other,
- Ordering::Greater => self,
- }
+ max_by(self, other, Ord::cmp)
}
/// Compares and returns the minimum of two values.
Self: Sized,
Self: ~const Destruct,
{
- #[cfg(not(bootstrap))]
- {
- min_by(self, other, Ord::cmp)
- }
-
- #[cfg(bootstrap)]
- match self.cmp(&other) {
- Ordering::Less | Ordering::Equal => self,
- Ordering::Greater => other,
- }
+ min_by(self, other, Ord::cmp)
}
/// Restrict a value to a certain interval.
F: ~const Destruct,
K: ~const Destruct,
{
- cfg_if! {
- if #[cfg(bootstrap)] {
- const fn imp<T, F: ~const FnMut(&T) -> K, K: ~const Ord>(
- f: &mut F,
- (v1, v2): (&T, &T),
- ) -> Ordering
- where
- T: ~const Destruct,
- K: ~const Destruct,
- {
- f(v1).cmp(&f(v2))
- }
- min_by(v1, v2, ConstFnMutClosure::new(&mut f, imp))
- } else {
- min_by(v1, v2, const |v1, v2| f(v1).cmp(&f(v2)))
- }
- }
+ min_by(v1, v2, const |v1, v2| f(v1).cmp(&f(v2)))
}
/// Compares and returns the maximum of two values.
F: ~const Destruct,
K: ~const Destruct,
{
- const fn imp<T, F: ~const FnMut(&T) -> K, K: ~const Ord>(
- f: &mut F,
- (v1, v2): (&T, &T),
- ) -> Ordering
- where
- T: ~const Destruct,
- K: ~const Destruct,
- {
- f(v1).cmp(&f(v2))
- }
- max_by(v1, v2, ConstFnMutClosure::new(&mut f, imp))
+ max_by(v1, v2, const |v1, v2| f(v1).cmp(&f(v2)))
}
// Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types
+++ /dev/null
-use crate::marker::Destruct;
-use crate::marker::Tuple;
-
-/// Struct representing a closure with mutably borrowed data.
-///
-/// Example:
-/// ```no_build
-/// #![feature(const_mut_refs)]
-/// use crate::const_closure::ConstFnMutClosure;
-/// const fn imp(state: &mut i32, (arg,): (i32,)) -> i32 {
-/// *state += arg;
-/// *state
-/// }
-/// let mut i = 5;
-/// let mut cl = ConstFnMutClosure::new(&mut i, imp);
-///
-/// assert!(7 == cl(2));
-/// assert!(8 == cl(1));
-/// ```
-pub(crate) struct ConstFnMutClosure<CapturedData, Function> {
- /// The Data captured by the Closure.
- /// Must be either a (mutable) reference or a tuple of (mutable) references.
- pub data: CapturedData,
- /// The Function of the Closure, must be: Fn(CapturedData, ClosureArgs) -> ClosureReturn
- pub func: Function,
-}
-impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<&'a mut CapturedData, Function> {
- /// Function for creating a new closure.
- ///
- /// `data` is the a mutable borrow of data that is captured from the environment.
- /// If you want Data to be a tuple of mutable Borrows, the struct must be constructed manually.
- ///
- /// `func` is the function of the closure, it gets the data and a tuple of the arguments closure
- /// and return the return value of the closure.
- pub(crate) const fn new<ClosureArguments, ClosureReturnValue>(
- data: &'a mut CapturedData,
- func: Function,
- ) -> Self
- where
- Function: ~const Fn(&mut CapturedData, ClosureArguments) -> ClosureReturnValue,
- {
- Self { data, func }
- }
-}
-
-macro_rules! impl_fn_mut_tuple {
- ($($var:ident)*) => {
- #[allow(unused_parens)]
- impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const
- FnOnce<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
- where
- Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue+ ~const Destruct,
- {
- type Output = ClosureReturnValue;
-
- extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output {
- self.call_mut(args)
- }
- }
- #[allow(unused_parens)]
- impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const
- FnMut<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
- where
- Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue,
- {
- extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output {
- #[allow(non_snake_case)]
- let ($($var),*) = &mut self.data;
- (self.func)(($($var),*), args)
- }
- }
- };
-}
-impl_fn_mut_tuple!(A);
-impl_fn_mut_tuple!(A B);
-impl_fn_mut_tuple!(A B C);
-impl_fn_mut_tuple!(A B C D);
-impl_fn_mut_tuple!(A B C D E);
impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
// bool -> Float
-#[stable(feature = "float_from_bool", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "float_from_bool", since = "1.68.0")]
#[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")]
impl const From<bool> for f32 {
/// Converts `bool` to `f32` losslessly.
small as u8 as Self
}
}
-#[stable(feature = "float_from_bool", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "float_from_bool", since = "1.68.0")]
#[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")]
impl const From<bool> for f64 {
/// Converts `bool` to `f64` losslessly.
#[unstable(feature = "gen_future", issue = "50547")]
unsafe impl Sync for ResumeTy {}
-/// Wrap a generator in a future.
-///
-/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
-/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
-// This is `const` to avoid extra errors after we recover from `const async fn`
-#[doc(hidden)]
-#[unstable(feature = "gen_future", issue = "50547")]
-#[rustc_const_unstable(feature = "gen_future", issue = "50547")]
-#[inline]
-pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
-where
- T: crate::ops::Generator<ResumeTy, Yield = ()>,
-{
- use crate::{
- ops::{Generator, GeneratorState},
- pin::Pin,
- task::Poll,
- };
-
- #[rustc_diagnostic_item = "gen_future"]
- struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T);
-
- // We rely on the fact that async/await futures are immovable in order to create
- // self-referential borrows in the underlying generator.
- impl<T: Generator<ResumeTy, Yield = ()>> !Unpin for GenFuture<T> {}
-
- impl<T: Generator<ResumeTy, Yield = ()>> Future for GenFuture<T> {
- type Output = T::Return;
- #[track_caller]
- fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
- // SAFETY: Safe because we're !Unpin + !Drop, and this is just a field projection.
- let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
-
- // Resume the generator, turning the `&mut Context` into a `NonNull` raw pointer. The
- // `.await` lowering will safely cast that back to a `&mut Context`.
- match gen.resume(ResumeTy(NonNull::from(cx).cast::<Context<'static>>())) {
- GeneratorState::Yielded(()) => Poll::Pending,
- GeneratorState::Complete(x) => Poll::Ready(x),
- }
- }
- }
-
- GenFuture(gen)
-}
-
#[lang = "get_context"]
#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
use crate::marker::Tuple;
use crate::mem;
-#[cfg(not(bootstrap))]
pub mod mir;
// These imports are used for simplifying intra-doc links
/// This intrinsic does not have a stable counterpart.
#[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
#[rustc_safe_intrinsic]
- #[cfg(not(bootstrap))]
pub fn assert_mem_uninitialized_valid<T>();
/// Gets a reference to a static `Location` indicating where it was called.
//!
//! # Examples
//!
-#![cfg_attr(bootstrap, doc = "```rust,compile_fail")]
-#![cfg_attr(not(bootstrap), doc = "```rust")]
+//! ```rust
//! #![feature(core_intrinsics, custom_mir)]
//!
//! extern crate core;
///
/// # Examples
///
- #[cfg_attr(bootstrap, doc = "```rust,compile_fail")]
- #[cfg_attr(not(bootstrap), doc = "```rust")]
+ /// ```rust
/// #![feature(custom_mir, core_intrinsics)]
///
/// extern crate core;
use crate::array;
-use crate::const_closure::ConstFnMutClosure;
use crate::iter::{ByRefSized, FusedIterator, Iterator, TrustedRandomAccessNoCoerce};
use crate::mem::{self, MaybeUninit};
use crate::ops::{ControlFlow, NeverShortCircuit, Try};
I: Iterator,
{
#[inline]
- default fn fold<B, F>(mut self, init: B, mut f: F) -> B
+ default fn fold<B, F>(mut self, init: B, f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
- let fold = ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp);
- self.try_fold(init, fold).0
+ self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0
}
}
-use crate::{
- const_closure::ConstFnMutClosure,
- ops::{NeverShortCircuit, Try},
-};
+use crate::ops::{NeverShortCircuit, Try};
/// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics.
///
}
#[inline]
- fn fold<B, F>(self, init: B, mut f: F) -> B
+ fn fold<B, F>(self, init: B, f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
// `fold` needs ownership, so this can't forward directly.
- I::try_fold(self.0, init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp))
- .0
+ I::try_fold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0
}
#[inline]
}
#[inline]
- fn rfold<B, F>(self, init: B, mut f: F) -> B
+ fn rfold<B, F>(self, init: B, f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
// `rfold` needs ownership, so this can't forward directly.
- I::try_rfold(
- self.0,
- init,
- ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp),
- )
- .0
+ I::try_rfold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0
}
#[inline]
};
(@internal $fold:ident -> $try_fold:ident) => {
#[inline]
- fn $fold<AAA, FFF>(mut self, init: AAA, mut fold: FFF) -> AAA
+ fn $fold<AAA, FFF>(mut self, init: AAA, fold: FFF) -> AAA
where
FFF: FnMut(AAA, Self::Item) -> AAA,
{
- use crate::const_closure::ConstFnMutClosure;
use crate::ops::NeverShortCircuit;
- let fold = ConstFnMutClosure::new(&mut fold, NeverShortCircuit::wrap_mut_2_imp);
- self.$try_fold(init, fold).0
+ self.$try_fold(init, NeverShortCircuit::wrap_mut_2(fold)).0
}
};
}
gen: Option<F>,
}
-#[stable(feature = "iter_once_with_debug", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_once_with_debug", since = "1.68.0")]
impl<F> fmt::Debug for OnceWith<F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.gen.is_some() {
repeater: F,
}
-#[stable(feature = "iterator_repeat_with_debug", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iterator_repeat_with_debug", since = "1.68.0")]
impl<F> fmt::Debug for RepeatWith<F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RepeatWith").finish_non_exhaustive()
#![feature(cfg_sanitize)]
#![feature(cfg_target_has_atomic)]
#![feature(cfg_target_has_atomic_equal_alignment)]
-#![cfg_attr(not(bootstrap), feature(const_closures))]
+#![feature(const_closures)]
#![feature(const_fn_floating_point_arithmetic)]
#![feature(const_mut_refs)]
#![feature(const_precise_live_drops)]
#![feature(sse4a_target_feature)]
#![feature(tbm_target_feature)]
#![feature(wasm_target_feature)]
-#![cfg_attr(bootstrap, feature(f16c_target_feature))]
// allow using `core::` in intra-doc links
#[allow(unused_extern_crates)]
mod tuple;
mod unit;
-mod const_closure;
-
#[stable(feature = "core_primitive", since = "1.43.0")]
pub mod primitive;
pub unsafe fn uninitialized<T>() -> T {
// SAFETY: the caller must guarantee that an uninitialized value is valid for `T`.
unsafe {
- #[cfg(not(bootstrap))] // If the compiler hits this itself then it deserves the UB.
intrinsics::assert_mem_uninitialized_valid::<T>();
let mut val = MaybeUninit::<T>::uninit();
pub const MIN: Self = 0;
/// The largest value that can be represented by this integer type
- #[doc = concat!("(2<sup>", $BITS, "</sup> − 1", $bound_condition, ")")]
+ #[doc = concat!("(2<sup>", $BITS, "</sup> − 1", $bound_condition, ").")]
///
/// # Examples
///
/// ```
/// assert_eq!(12 + 1, 13);
/// ```
- #[must_use]
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[rustc_diagnostic_item = "add"]
#[stable(feature = "rust1", since = "1.0.0")]
fn add(self, rhs: Rhs) -> Self::Output;
}
/// ```
/// assert_eq!(12 - 1, 11);
/// ```
- #[must_use]
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[rustc_diagnostic_item = "sub"]
#[stable(feature = "rust1", since = "1.0.0")]
fn sub(self, rhs: Rhs) -> Self::Output;
}
/// ```
/// assert_eq!(12 * 2, 24);
/// ```
- #[must_use]
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[rustc_diagnostic_item = "mul"]
#[stable(feature = "rust1", since = "1.0.0")]
fn mul(self, rhs: Rhs) -> Self::Output;
}
/// ```
/// assert_eq!(12 / 2, 6);
/// ```
- #[must_use]
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[rustc_diagnostic_item = "div"]
#[stable(feature = "rust1", since = "1.0.0")]
fn div(self, rhs: Rhs) -> Self::Output;
}
#[lang = "rem"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(
- message = "cannot mod `{Self}` by `{Rhs}`",
+ message = "cannot calculate the remainder of `{Self}` divided by `{Rhs}`",
label = "no implementation for `{Self} % {Rhs}`"
)]
#[doc(alias = "%")]
/// ```
/// assert_eq!(12 % 10, 2);
/// ```
- #[must_use]
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[rustc_diagnostic_item = "rem"]
#[stable(feature = "rust1", since = "1.0.0")]
fn rem(self, rhs: Rhs) -> Self::Output;
}
/// let x: i32 = 12;
/// assert_eq!(-x, -12);
/// ```
- #[must_use]
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[rustc_diagnostic_item = "neg"]
#[stable(feature = "rust1", since = "1.0.0")]
fn neg(self) -> Self::Output;
}
#[lang = "rem_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented(
- message = "cannot mod-assign `{Self}` by `{Rhs}``",
+ message = "cannot calculate and assign the remainder of `{Self}` divided by `{Rhs}`",
label = "no implementation for `{Self} %= {Rhs}`"
)]
#[doc(alias = "%")]
pub(crate) struct NeverShortCircuit<T>(pub T);
impl<T> NeverShortCircuit<T> {
- /// Implementation for building `ConstFnMutClosure` for wrapping the output of a ~const FnMut in a `NeverShortCircuit`.
#[inline]
- pub const fn wrap_mut_2_imp<A, B, F: ~const FnMut(A, B) -> T>(
- f: &mut F,
- (a, b): (A, B),
- ) -> NeverShortCircuit<T> {
- NeverShortCircuit(f(a, b))
+ pub fn wrap_mut_2<A, B>(
+ mut f: impl ~const FnMut(A, B) -> T,
+ ) -> impl ~const FnMut(A, B) -> Self {
+ cfg_if! {
+ if #[cfg(bootstrap)] {
+ #[allow(unused_parens)]
+ (const move |a, b| NeverShortCircuit(f(a, b)))
+ } else {
+ const move |a, b| NeverShortCircuit(f(a, b))
+ }
+ }
}
}
// Transforming contained values
/////////////////////////////////////////////////////////////////////////
- /// Maps an `Option<T>` to `Option<U>` by applying a function to a contained value.
+ /// Maps an `Option<T>` to `Option<U>` by applying a function to a contained value (if `Some`) or returns `None` (if `None`).
///
/// # Examples
///
/// let maybe_some_string = Some(String::from("Hello, World!"));
/// // `Option::map` takes self *by value*, consuming `maybe_some_string`
/// let maybe_some_len = maybe_some_string.map(|s| s.len());
- ///
/// assert_eq!(maybe_some_len, Some(13));
+ ///
+ /// let x: Option<&str> = None;
+ /// assert_eq!(x.map(|s| s.len()), None);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
/// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize.
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
-#[cfg_attr(not(bootstrap), lang = "panic_nounwind")] // needed by codegen for non-unwinding panics
+#[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics
#[rustc_nounwind]
pub fn panic_nounwind(expr: &'static str) -> ! {
panic_nounwind_fmt(fmt::Arguments::new_v1(&[expr], &[]));
/// any extra arguments (including those synthesized by track_caller).
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
-#[cfg_attr(bootstrap, lang = "panic_no_unwind")] // needed by codegen for panic in nounwind function
-#[cfg_attr(not(bootstrap), lang = "panic_cannot_unwind")] // needed by codegen for panic in nounwind function
+#[lang = "panic_cannot_unwind"] // needed by codegen for panic in nounwind function
#[rustc_nounwind]
fn panic_cannot_unwind() -> ! {
panic_nounwind("panic in a function that cannot unwind")
/// constructor.
///
/// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin
-#[stable(feature = "pin_macro", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "pin_macro", since = "1.68.0")]
#[rustc_macro_transparency = "semitransparent"]
#[allow_internal_unstable(unsafe_pin_internals)]
pub macro pin($value:expr $(,)?) {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
+ #[track_caller]
pub fn windows(&self, size: usize) -> Windows<'_, T> {
- let size = NonZeroUsize::new(size).expect("size is zero");
+ let size = NonZeroUsize::new(size).expect("window size must be non-zero");
Windows::new(self, size)
}
/// [`rchunks`]: slice::rchunks
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
+ #[track_caller]
pub fn chunks(&self, chunk_size: usize) -> Chunks<'_, T> {
- assert_ne!(chunk_size, 0, "chunks cannot have a size of zero");
+ assert!(chunk_size != 0, "chunk size must be non-zero");
Chunks::new(self, chunk_size)
}
/// [`rchunks_mut`]: slice::rchunks_mut
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
+ #[track_caller]
pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<'_, T> {
- assert_ne!(chunk_size, 0, "chunks cannot have a size of zero");
+ assert!(chunk_size != 0, "chunk size must be non-zero");
ChunksMut::new(self, chunk_size)
}
/// [`rchunks_exact`]: slice::rchunks_exact
#[stable(feature = "chunks_exact", since = "1.31.0")]
#[inline]
+ #[track_caller]
pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> {
- assert_ne!(chunk_size, 0, "chunks cannot have a size of zero");
+ assert!(chunk_size != 0, "chunk size must be non-zero");
ChunksExact::new(self, chunk_size)
}
/// [`rchunks_exact_mut`]: slice::rchunks_exact_mut
#[stable(feature = "chunks_exact", since = "1.31.0")]
#[inline]
+ #[track_caller]
pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_, T> {
- assert_ne!(chunk_size, 0, "chunks cannot have a size of zero");
+ assert!(chunk_size != 0, "chunk size must be non-zero");
ChunksExactMut::new(self, chunk_size)
}
/// ```
#[unstable(feature = "slice_as_chunks", issue = "74985")]
#[inline]
+ #[track_caller]
#[must_use]
pub fn as_chunks<const N: usize>(&self) -> (&[[T; N]], &[T]) {
- assert_ne!(N, 0, "chunks cannot have a size of zero");
+ assert!(N != 0, "chunk size must be non-zero");
let len = self.len() / N;
let (multiple_of_n, remainder) = self.split_at(len * N);
// SAFETY: We already panicked for zero, and ensured by construction
/// ```
#[unstable(feature = "slice_as_chunks", issue = "74985")]
#[inline]
+ #[track_caller]
#[must_use]
pub fn as_rchunks<const N: usize>(&self) -> (&[T], &[[T; N]]) {
- assert_ne!(N, 0, "chunks cannot have a size of zero");
+ assert!(N != 0, "chunk size must be non-zero");
let len = self.len() / N;
let (remainder, multiple_of_n) = self.split_at(self.len() - len * N);
// SAFETY: We already panicked for zero, and ensured by construction
/// [`chunks_exact`]: slice::chunks_exact
#[unstable(feature = "array_chunks", issue = "74985")]
#[inline]
+ #[track_caller]
pub fn array_chunks<const N: usize>(&self) -> ArrayChunks<'_, T, N> {
- assert_ne!(N, 0, "chunks cannot have a size of zero");
+ assert!(N != 0, "chunk size must be non-zero");
ArrayChunks::new(self)
}
/// ```
#[unstable(feature = "slice_as_chunks", issue = "74985")]
#[inline]
+ #[track_caller]
#[must_use]
pub fn as_chunks_mut<const N: usize>(&mut self) -> (&mut [[T; N]], &mut [T]) {
- assert_ne!(N, 0, "chunks cannot have a size of zero");
+ assert!(N != 0, "chunk size must be non-zero");
let len = self.len() / N;
let (multiple_of_n, remainder) = self.split_at_mut(len * N);
// SAFETY: We already panicked for zero, and ensured by construction
/// ```
#[unstable(feature = "slice_as_chunks", issue = "74985")]
#[inline]
+ #[track_caller]
#[must_use]
pub fn as_rchunks_mut<const N: usize>(&mut self) -> (&mut [T], &mut [[T; N]]) {
- assert_ne!(N, 0, "chunks cannot have a size of zero");
+ assert!(N != 0, "chunk size must be non-zero");
let len = self.len() / N;
let (remainder, multiple_of_n) = self.split_at_mut(self.len() - len * N);
// SAFETY: We already panicked for zero, and ensured by construction
/// [`chunks_exact_mut`]: slice::chunks_exact_mut
#[unstable(feature = "array_chunks", issue = "74985")]
#[inline]
+ #[track_caller]
pub fn array_chunks_mut<const N: usize>(&mut self) -> ArrayChunksMut<'_, T, N> {
- assert_ne!(N, 0, "chunks cannot have a size of zero");
+ assert!(N != 0, "chunk size must be non-zero");
ArrayChunksMut::new(self)
}
/// [`windows`]: slice::windows
#[unstable(feature = "array_windows", issue = "75027")]
#[inline]
+ #[track_caller]
pub fn array_windows<const N: usize>(&self) -> ArrayWindows<'_, T, N> {
- assert_ne!(N, 0, "windows cannot have a size of zero");
+ assert!(N != 0, "window size must be non-zero");
ArrayWindows::new(self)
}
/// [`chunks`]: slice::chunks
#[stable(feature = "rchunks", since = "1.31.0")]
#[inline]
+ #[track_caller]
pub fn rchunks(&self, chunk_size: usize) -> RChunks<'_, T> {
- assert!(chunk_size != 0);
+ assert!(chunk_size != 0, "chunk size must be non-zero");
RChunks::new(self, chunk_size)
}
/// [`chunks_mut`]: slice::chunks_mut
#[stable(feature = "rchunks", since = "1.31.0")]
#[inline]
+ #[track_caller]
pub fn rchunks_mut(&mut self, chunk_size: usize) -> RChunksMut<'_, T> {
- assert!(chunk_size != 0);
+ assert!(chunk_size != 0, "chunk size must be non-zero");
RChunksMut::new(self, chunk_size)
}
/// [`chunks_exact`]: slice::chunks_exact
#[stable(feature = "rchunks", since = "1.31.0")]
#[inline]
+ #[track_caller]
pub fn rchunks_exact(&self, chunk_size: usize) -> RChunksExact<'_, T> {
- assert!(chunk_size != 0);
+ assert!(chunk_size != 0, "chunk size must be non-zero");
RChunksExact::new(self, chunk_size)
}
/// [`chunks_exact_mut`]: slice::chunks_exact_mut
#[stable(feature = "rchunks", since = "1.31.0")]
#[inline]
+ #[track_caller]
pub fn rchunks_exact_mut(&mut self, chunk_size: usize) -> RChunksExactMut<'_, T> {
- assert!(chunk_size != 0);
+ assert!(chunk_size != 0, "chunk size must be non-zero");
RChunksExactMut::new(self, chunk_size)
}
/// Currently, `Context` only serves to provide access to a [`&Waker`](Waker)
/// which can be used to wake the current task.
#[stable(feature = "futures_api", since = "1.36.0")]
-#[cfg_attr(not(bootstrap), lang = "Context")]
+#[lang = "Context"]
pub struct Context<'a> {
waker: &'a Waker,
// Ensure we future-proof against variance changes by forcing
///
/// The hash map will be able to hold at least `capacity` elements without
/// reallocating. This method is allowed to allocate for more elements than
- /// `capacity`. If `capacity` is 0, the hash set will not allocate.
+ /// `capacity`. If `capacity` is 0, the hash map will not allocate.
///
/// # Examples
///
unsafe { intrinsics::ceilf32(self) }
}
- /// Returns the nearest integer to `self`. Round half-way cases away from
- /// `0.0`.
+ /// Returns the nearest integer to `self`. If a value is half-way between two
+ /// integers, round away from `0.0`.
///
/// # Examples
///
unsafe { intrinsics::ceilf64(self) }
}
- /// Returns the nearest integer to `self`. Round half-way cases away from
- /// `0.0`.
+ /// Returns the nearest integer to `self`. If a value is half-way between two
+ /// integers, round away from `0.0`.
///
/// # Examples
///
// doesn't accidentally get printed.
#[cfg_attr(test, derive(Debug))]
enum ErrorData<C> {
- Os(i32),
+ Os(RawOsError),
Simple(ErrorKind),
SimpleMessage(&'static SimpleMessage),
Custom(C),
}
+/// The type of raw OS error codes returned by [`Error::raw_os_error`].
+///
+/// This is an [`i32`] on all currently supported platforms, but platforms
+/// added in the future (such as UEFI) may use a different primitive type like
+/// [`usize`]. Use `as`or [`into`] conversions where applicable to ensure maximum
+/// portability.
+///
+/// [`into`]: Into::into
+#[unstable(feature = "raw_os_error_ty", issue = "none")]
+pub type RawOsError = i32;
+
// `#[repr(align(4))]` is probably redundant, it should have that value or
// higher already. We include it just because repr_bitpacked.rs's encoding
// requires an alignment >= 4 (note that `#[repr(align)]` will not reduce the
#[must_use]
#[inline]
pub fn last_os_error() -> Error {
- Error::from_raw_os_error(sys::os::errno() as i32)
+ Error::from_raw_os_error(sys::os::errno())
}
/// Creates a new instance of an [`Error`] from a particular OS error code.
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
#[inline]
- pub fn from_raw_os_error(code: i32) -> Error {
+ pub fn from_raw_os_error(code: RawOsError) -> Error {
Error { repr: Repr::new_os(code) }
}
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
#[inline]
- pub fn raw_os_error(&self) -> Option<i32> {
+ pub fn raw_os_error(&self) -> Option<RawOsError> {
match self.repr.data() {
ErrorData::Os(i) => Some(i),
ErrorData::Custom(..) => None,
//! to use a pointer type to store something that may hold an integer, some of
//! the time.
-use super::{Custom, ErrorData, ErrorKind, SimpleMessage};
+use super::{Custom, ErrorData, ErrorKind, RawOsError, SimpleMessage};
use alloc::boxed::Box;
use core::marker::PhantomData;
use core::mem::{align_of, size_of};
}
#[inline]
- pub(super) fn new_os(code: i32) -> Self {
+ pub(super) fn new_os(code: RawOsError) -> Self {
let utagged = ((code as usize) << 32) | TAG_OS;
// Safety: `TAG_OS` is not zero, so the result of the `|` is not 0.
let res = Self(unsafe { NonNull::new_unchecked(ptr::invalid_mut(utagged)) }, PhantomData);
let bits = ptr.as_ptr().addr();
match bits & TAG_MASK {
TAG_OS => {
- let code = ((bits as i64) >> 32) as i32;
+ let code = ((bits as i64) >> 32) as RawOsError;
ErrorData::Os(code)
}
TAG_SIMPLE => {
static_assert!(align_of::<SimpleMessage>() >= TAG_MASK + 1);
static_assert!(align_of::<Custom>() >= TAG_MASK + 1);
+// `RawOsError` must be an alias for `i32`.
+const _: fn(RawOsError) -> i32 = |os| os;
+
static_assert!(@usize_eq: TAG_MASK & TAG_SIMPLE_MESSAGE, TAG_SIMPLE_MESSAGE);
static_assert!(@usize_eq: TAG_MASK & TAG_CUSTOM, TAG_CUSTOM);
static_assert!(@usize_eq: TAG_MASK & TAG_OS, TAG_OS);
//! non-64bit targets, where the packed 64 bit representation wouldn't work, and
//! would have no benefit.
-use super::{Custom, ErrorData, ErrorKind, SimpleMessage};
+use super::{Custom, ErrorData, ErrorKind, RawOsError, SimpleMessage};
use alloc::boxed::Box;
type Inner = ErrorData<Box<Custom>>;
Self(Inner::Custom(b))
}
#[inline]
- pub(super) fn new_os(code: i32) -> Self {
+ pub(super) fn new_os(code: RawOsError) -> Self {
Self(Inner::Os(code))
}
#[inline]
#[test]
fn test_os_packing() {
- for code in -20i32..20i32 {
+ for code in -20..20 {
let e = Error::from_raw_os_error(code);
assert_eq!(e.raw_os_error(), Some(code));
assert_matches!(
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
pub use self::buffered::WriterPanicked;
+#[unstable(feature = "raw_os_error_ty", issue = "none")]
+pub use self::error::RawOsError;
pub(crate) use self::stdio::attempt_print_to_stderr;
#[unstable(feature = "internal_output_capture", issue = "none")]
#[doc(no_inline, hidden)]
/// }
///
/// fn main() -> std::io::Result<()> {
- /// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
+ /// let listener = TcpListener::bind("127.0.0.1:80")?;
///
/// for stream in listener.incoming() {
/// match stream {
#[stable(feature = "raw_ext", since = "1.1.0")]
pub use self::arch::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t};
-#[cfg(any(
- target_arch = "x86",
- target_arch = "le32",
- target_arch = "powerpc",
- target_arch = "arm"
-))]
+#[cfg(any(target_arch = "x86", target_arch = "powerpc", target_arch = "arm"))]
mod arch {
use crate::os::raw::{c_long, c_short, c_uint};
#[cfg(any(
target_arch = "x86",
- target_arch = "le32",
target_arch = "m68k",
target_arch = "powerpc",
target_arch = "sparc",
#[cfg(any(
target_arch = "x86",
- target_arch = "le32",
target_arch = "m68k",
target_arch = "powerpc",
target_arch = "sparc",
/// The primary separator of path components for the current platform.
///
/// For example, `/` on Unix and `\` on Windows.
-#[stable(feature = "main_separator_str", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "main_separator_str", since = "1.68.0")]
pub const MAIN_SEPARATOR_STR: &str = crate::sys::path::MAIN_SEP_STR;
////////////////////////////////////////////////////////////////////////////////
}
}
-#[stable(feature = "path_buf_deref_mut", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "path_buf_deref_mut", since = "1.68.0")]
impl ops::DerefMut for PathBuf {
#[inline]
fn deref_mut(&mut self) -> &mut Path {
/// escapes the path please use [`Debug`] instead.
///
/// [`Display`]: fmt::Display
+ /// [`Debug`]: fmt::Debug
///
/// # Examples
///
is bootstrapped and in general, some of the technical details of the build
system.
-## Using rustbuild
+Note that this README only covers internal information, not how to use the tool.
+Please check [bootstrapping dev guide][bootstrapping-dev-guide] for further information.
-The rustbuild build system has a primary entry point, a top level `x.py` script:
+[bootstrapping-dev-guide]: https://rustc-dev-guide.rust-lang.org/building/bootstrapping.html
-```sh
-$ python ./x.py build
-```
-
-Note that if you're on Unix, you should be able to execute the script directly:
-
-```sh
-$ ./x.py build
-```
-
-The script accepts commands, flags, and arguments to determine what to do:
-
-* `build` - a general purpose command for compiling code. Alone, `build` will
- bootstrap the entire compiler, and otherwise, arguments passed indicate what to
- build. For example:
-
- ```
- # build the whole compiler
- ./x.py build --stage 2
-
- # build the stage1 compiler
- ./x.py build
-
- # build stage0 libstd
- ./x.py build --stage 0 library/std
-
- # build a particular crate in stage0
- ./x.py build --stage 0 library/test
- ```
-
- If files that would normally be rebuilt from stage 0 are dirty, the rebuild can be
- overridden using `--keep-stage 0`. Using `--keep-stage n` will skip all steps
- that belong to stage n or earlier:
-
- ```
- # build stage 1, keeping old build products for stage 0
- ./x.py build --keep-stage 0
- ```
-
-* `test` - a command for executing unit tests. Like the `build` command, this
- will execute the entire test suite by default, and otherwise, it can be used to
- select which test suite is run:
-
- ```
- # run all unit tests
- ./x.py test
-
- # execute tool tests
- ./x.py test tidy
-
- # execute the UI test suite
- ./x.py test tests/ui
-
- # execute only some tests in the UI test suite
- ./x.py test tests/ui --test-args substring-of-test-name
-
- # execute tests in the standard library in stage0
- ./x.py test --stage 0 library/std
-
- # execute tests in the core and standard library in stage0,
- # without running doc tests (thus avoid depending on building the compiler)
- ./x.py test --stage 0 --no-doc library/core library/std
+## Introduction
- # execute all doc tests
- ./x.py test src/doc
- ```
+The build system defers most of the complicated logic managing invocations
+of rustc and rustdoc to Cargo itself. However, moving through various stages
+and copying artifacts is still necessary for it to do. Each time rustbuild
+is invoked, it will iterate through the list of predefined steps and execute
+each serially in turn if it matches the paths passed or is a default rule.
+For each step rustbuild relies on the step internally being incremental and
+parallel. Note, though, that the `-j` parameter to rustbuild gets forwarded
+to appropriate test harnesses and such.
-* `doc` - a command for building documentation. Like above, can take arguments
- for what to document.
-
-## Configuring rustbuild
-
-rustbuild offers a TOML-based configuration system with a `config.toml`
-file. An example of this configuration can be found at `config.toml.example`,
-and the configuration file can also be passed as `--config path/to/config.toml`
-if the build system is being invoked manually (via the python script).
-
-You can generate a config.toml using `./configure` options if you want to automate creating the file without having to edit it.
-
-Finally, rustbuild makes use of the [cc-rs crate] which has [its own
-method][env-vars] of configuring C compilers and C flags via environment
-variables.
-
-[cc-rs crate]: https://github.com/alexcrichton/cc-rs
-[env-vars]: https://github.com/alexcrichton/cc-rs#external-configuration-via-environment-variables
-
-## Build stages
+## Build phases
The rustbuild build system goes through a few phases to actually build the
compiler. What actually happens when you invoke rustbuild is:
-1. The entry point script, `x.py` is run. This script is
- responsible for downloading the stage0 compiler/Cargo binaries, and it then
- compiles the build system itself (this folder). Finally, it then invokes the
- actual `bootstrap` binary build system.
+1. The entry point script(`x` for unix like systems, `x.ps1` for windows systems,
+ `x.py` cross-platform) is run. This script is responsible for downloading the stage0
+ compiler/Cargo binaries, and it then compiles the build system itself (this folder).
+ Finally, it then invokes the actual `bootstrap` binary build system.
2. In Rust, `bootstrap` will slurp up all configuration, perform a number of
sanity checks (whether compilers exist, for example), and then start building the
stage0 artifacts.
The goal of each stage is to (a) leverage Cargo as much as possible and failing
that (b) leverage Rust as much as possible!
-## Incremental builds
-
-You can configure rustbuild to use incremental compilation with the
-`--incremental` flag:
-
-```sh
-$ ./x.py build --incremental
-```
-
-The `--incremental` flag will store incremental compilation artifacts
-in `build/<host>/stage0-incremental`. Note that we only use incremental
-compilation for the stage0 -> stage1 compilation -- this is because
-the stage1 compiler is changing, and we don't try to cache and reuse
-incremental artifacts across different versions of the compiler.
-
-You can always drop the `--incremental` to build as normal (but you
-will still be using the local nightly as your bootstrap).
-
## Directory Layout
This build system houses all output under the `build` directory, which looks
# system will link (using hard links) output from stageN-{std,rustc} into
# each of these directories.
#
- # In theory, there is no extra build output in these directories.
+ # In theory these are working rustc sysroot directories, meaning there is
+ # no extra build output in these directories.
stage1/
stage2/
stage3/
```
-## Cargo projects
-
-The current build is unfortunately not quite as simple as `cargo build` in a
-directory, but rather the compiler is split into three different Cargo projects:
-
-* `library/std` - the standard library
-* `library/test` - testing support, depends on libstd
-* `compiler/rustc` - the actual compiler itself
-
-Each "project" has a corresponding Cargo.lock file with all dependencies, and
-this means that building the compiler involves running Cargo three times. The
-structure here serves two goals:
-
-1. Facilitating dependencies coming from crates.io. These dependencies don't
- depend on `std`, so libstd is a separate project compiled ahead of time
- before the actual compiler builds.
-2. Splitting "host artifacts" from "target artifacts". That is, when building
- code for an arbitrary target, you don't need the entire compiler, but you'll
- end up needing libraries like libtest that depend on std but also want to use
- crates.io dependencies. Hence, libtest is split out as its own project that
- is sequenced after `std` but before `rustc`. This project is built for all
- targets.
-
-There is some loss in build parallelism here because libtest can be compiled in
-parallel with a number of rustc artifacts, but in theory, the loss isn't too bad!
-
-## Build tools
-
-We've actually got quite a few tools that we use in the compiler's build system
-and for testing. To organize these, each tool is a project in `src/tools` with a
-corresponding `Cargo.toml`. All tools are compiled with Cargo (currently having
-independent `Cargo.lock` files) and do not currently explicitly depend on the
-compiler or standard library. Compiling each tool is sequenced after the
-appropriate libstd/libtest/librustc compile above.
-
## Extending rustbuild
-So, you'd like to add a feature to the rustbuild build system or just fix a bug.
-Great! One of the major motivational factors for moving away from `make` is that
-Rust is in theory much easier to read, modify, and write. If you find anything
-excessively confusing, please open an issue on this, and we'll try to get it
-documented or simplified, pronto.
+When you use the bootstrap system, you'll call it through the entry point script
+(`x`, `x.ps1`, or `x.py`). However, most of the code lives in `src/bootstrap`.
+`bootstrap` has a difficult problem: it is written in Rust, but yet it is run
+before the Rust compiler is built! To work around this, there are two components
+of bootstrap: the main one written in rust, and `bootstrap.py`. `bootstrap.py`
+is what gets run by entry point script. It takes care of downloading the `stage0`
+compiler, which will then build the bootstrap binary written in Rust.
-First up, you'll probably want to read over the documentation above, as that'll
-give you a high level overview of what rustbuild is doing. You also probably
-want to play around a bit yourself by just getting it up and running before you
-dive too much into the actual build system itself.
+Because there are two separate codebases behind `x.py`, they need to
+be kept in sync. In particular, both `bootstrap.py` and the bootstrap binary
+parse `config.toml` and read the same command line arguments. `bootstrap.py`
+keeps these in sync by setting various environment variables, and the
+programs sometimes have to add arguments that are explicitly ignored, to be
+read by the other.
-After that, each module in rustbuild should have enough documentation to keep
-you up and running. Some general areas that you may be interested in modifying
-are:
+Some general areas that you may be interested in modifying are:
* Adding a new build tool? Take a look at `bootstrap/tool.rs` for examples of
other tools.
Changes that do not affect contributors to the compiler or users
building rustc from source don't need an update to `VERSION`.
-If you have any questions, feel free to reach out on the `#t-infra` channel in
-the [Rust Zulip server][rust-zulip] or ask on internals.rust-lang.org. When
-you encounter bugs, please file issues on the rust-lang/rust issue tracker.
+If you have any questions, feel free to reach out on the `#t-infra/bootstrap` channel
+at [Rust Bootstrap Zulip server][rust-bootstrap-zulip]. When you encounter bugs,
+please file issues on the [Rust issue tracker][rust-issue-tracker].
-[rust-zulip]: https://rust-lang.zulipchat.com/#narrow/stream/242791-t-infra
+[rust-bootstrap-zulip]: https://rust-lang.zulipchat.com/#narrow/stream/t-infra.2Fbootstrap
+[rust-issue-tracker]: https://github.com/rust-lang/rust/issues
import argparse
import contextlib
import datetime
-import distutils.version
import hashlib
import json
import os
import tarfile
import tempfile
-from time import time, sleep
+from time import time
-def support_xz():
- try:
- with tempfile.NamedTemporaryFile(delete=False) as temp_file:
- temp_path = temp_file.name
- with tarfile.open(temp_path, "w:xz"):
- pass
- return True
- except tarfile.CompressionError:
- return False
+try:
+ import lzma
+except ImportError:
+ lzma = None
+
+if sys.platform == 'win32':
+ EXE_SUFFIX = ".exe"
+else:
+ EXE_SUFFIX = ""
def get(base, url, path, checksums, verbose=False):
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
def download(path, url, probably_big, verbose):
- for _ in range(0, 4):
+ for _ in range(4):
try:
_download(path, url, probably_big, verbose, True)
return
def __init__(self):
self.checksums_sha256 = {}
self.stage0_compiler = None
- self._download_url = ''
+ self.download_url = ''
self.build = ''
self.build_dir = ''
self.clean = False
self.config_toml = ''
self.rust_root = ''
- self.use_locked_deps = ''
- self.use_vendored_sources = ''
+ self.use_locked_deps = False
+ self.use_vendored_sources = False
self.verbose = False
self.git_version = None
self.nix_deps_dir = None
+ self._should_fix_bins_and_dylibs = None
def download_toolchain(self):
"""Fetch the build system for Rust, written in Rust
self.program_out_of_date(self.rustc_stamp(), key)):
if os.path.exists(bin_root):
shutil.rmtree(bin_root)
- tarball_suffix = '.tar.xz' if support_xz() else '.tar.gz'
+ tarball_suffix = '.tar.gz' if lzma is None else '.tar.xz'
filename = "rust-std-{}-{}{}".format(
rustc_channel, self.build, tarball_suffix)
pattern = "rust-std-{}".format(self.build)
filename = "cargo-{}-{}{}".format(rustc_channel, self.build,
tarball_suffix)
self._download_component_helper(filename, "cargo", tarball_suffix)
- self.fix_bin_or_dylib("{}/bin/cargo".format(bin_root))
-
- self.fix_bin_or_dylib("{}/bin/rustc".format(bin_root))
- self.fix_bin_or_dylib("{}/bin/rustdoc".format(bin_root))
- self.fix_bin_or_dylib("{}/libexec/rust-analyzer-proc-macro-srv".format(bin_root))
- lib_dir = "{}/lib".format(bin_root)
- for lib in os.listdir(lib_dir):
- if lib.endswith(".so"):
- self.fix_bin_or_dylib(os.path.join(lib_dir, lib))
+ if self.should_fix_bins_and_dylibs():
+ self.fix_bin_or_dylib("{}/bin/cargo".format(bin_root))
+
+ self.fix_bin_or_dylib("{}/bin/rustc".format(bin_root))
+ self.fix_bin_or_dylib("{}/bin/rustdoc".format(bin_root))
+ self.fix_bin_or_dylib("{}/libexec/rust-analyzer-proc-macro-srv".format(bin_root))
+ lib_dir = "{}/lib".format(bin_root)
+ for lib in os.listdir(lib_dir):
+ if lib.endswith(".so"):
+ self.fix_bin_or_dylib(os.path.join(lib_dir, lib))
+
with output(self.rustc_stamp()) as rust_stamp:
rust_stamp.write(key)
if not os.path.exists(rustc_cache):
os.makedirs(rustc_cache)
- base = self._download_url
- url = "dist/{}".format(key)
tarball = os.path.join(rustc_cache, filename)
if not os.path.exists(tarball):
get(
- base,
- "{}/{}".format(url, filename),
+ self.download_url,
+ "dist/{}/{}".format(key, filename),
tarball,
self.checksums_sha256,
verbose=self.verbose,
)
unpack(tarball, tarball_suffix, self.bin_root(), match=pattern, verbose=self.verbose)
- def fix_bin_or_dylib(self, fname):
- """Modifies the interpreter section of 'fname' to fix the dynamic linker,
- or the RPATH section, to fix the dynamic library search path
-
- This method is only required on NixOS and uses the PatchELF utility to
- change the interpreter/RPATH of ELF executables.
-
- Please see https://nixos.org/patchelf.html for more information
+ def should_fix_bins_and_dylibs(self):
+ """Whether or not `fix_bin_or_dylib` needs to be run; can only be True
+ on NixOS.
"""
- default_encoding = sys.getdefaultencoding()
- try:
- ostype = subprocess.check_output(
- ['uname', '-s']).strip().decode(default_encoding)
- except subprocess.CalledProcessError:
- return
- except OSError as reason:
- if getattr(reason, 'winerror', None) is not None:
- return
- raise reason
+ if self._should_fix_bins_and_dylibs is not None:
+ return self._should_fix_bins_and_dylibs
- if ostype != "Linux":
- return
+ def get_answer():
+ default_encoding = sys.getdefaultencoding()
+ try:
+ ostype = subprocess.check_output(
+ ['uname', '-s']).strip().decode(default_encoding)
+ except subprocess.CalledProcessError:
+ return False
+ except OSError as reason:
+ if getattr(reason, 'winerror', None) is not None:
+ return False
+ raise reason
+
+ if ostype != "Linux":
+ return False
+
+ # If the user has asked binaries to be patched for Nix, then
+ # don't check for NixOS or `/lib`.
+ if self.get_toml("patch-binaries-for-nix", "build") == "true":
+ return True
- # If the user has asked binaries to be patched for Nix, then
- # don't check for NixOS or `/lib`, just continue to the patching.
- if self.get_toml('patch-binaries-for-nix', 'build') != 'true':
# Use `/etc/os-release` instead of `/etc/NIXOS`.
# The latter one does not exist on NixOS when using tmpfs as root.
try:
with open("/etc/os-release", "r") as f:
- if not any(l.strip() in ["ID=nixos", "ID='nixos'", 'ID="nixos"'] for l in f):
- return
+ if not any(l.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"') for l in f):
+ return False
except FileNotFoundError:
- return
+ return False
if os.path.exists("/lib"):
- return
+ return False
+
+ return True
+
+ answer = self._should_fix_bins_and_dylibs = get_answer()
+ if answer:
+ print("info: You seem to be using Nix.")
+ return answer
+
+ def fix_bin_or_dylib(self, fname):
+ """Modifies the interpreter section of 'fname' to fix the dynamic linker,
+ or the RPATH section, to fix the dynamic library search path
- # At this point we're pretty sure the user is running NixOS or
- # using Nix
- nix_os_msg = "info: you seem to be using Nix. Attempting to patch"
- print(nix_os_msg, fname)
+ This method is only required on NixOS and uses the PatchELF utility to
+ change the interpreter/RPATH of ELF executables.
+
+ Please see https://nixos.org/patchelf.html for more information
+ """
+ assert self._should_fix_bins_and_dylibs is True
+ print("attempting to patch", fname)
# Only build `.nix-deps` once.
nix_deps_dir = self.nix_deps_dir
config = self.get_toml(program)
if config:
return os.path.expanduser(config)
- return os.path.join(self.bin_root(), "bin", "{}{}".format(
- program, self.exe_suffix()))
+ return os.path.join(self.bin_root(), "bin", "{}{}".format(program, EXE_SUFFIX))
@staticmethod
def get_string(line):
return line[start + 1:end]
return None
- @staticmethod
- def exe_suffix():
- """Return a suffix for executables"""
- if sys.platform == 'win32':
- return '.exe'
- return ''
-
def bootstrap_binary(self):
"""Return the path of the bootstrap binary
"""
return os.path.join(self.build_dir, "bootstrap", "debug", "bootstrap")
- def build_bootstrap(self, color):
+ def build_bootstrap(self, color, verbose_count):
"""Build bootstrap"""
print("Building bootstrap")
build_dir = os.path.join(self.build_dir, "bootstrap")
if target_linker is not None:
env["RUSTFLAGS"] += " -C linker=" + target_linker
env["RUSTFLAGS"] += " -Wrust_2018_idioms -Wunused_lifetimes"
- env["RUSTFLAGS"] += " -Wsemicolon_in_expressions_from_macros"
if self.get_toml("deny-warnings", "rust") != "false":
env["RUSTFLAGS"] += " -Dwarnings"
self.cargo()))
args = [self.cargo(), "build", "--manifest-path",
os.path.join(self.rust_root, "src/bootstrap/Cargo.toml")]
- for _ in range(0, self.verbose):
- args.append("--verbose")
+ args.extend("--verbose" for _ in range(verbose_count))
if self.use_locked_deps:
args.append("--locked")
if self.use_vendored_sources:
so use `self.build` where possible.
"""
config = self.get_toml('build')
- if config:
- return config
- return default_build_triple(self.verbose)
-
- def set_dist_environment(self, url):
- """Set download URL for normal environment"""
- if 'RUSTUP_DIST_SERVER' in os.environ:
- self._download_url = os.environ['RUSTUP_DIST_SERVER']
- else:
- self._download_url = url
+ return config or default_build_triple(self.verbose)
def check_vendored_status(self):
"""Check that vendoring is configured properly"""
if os.path.exists(cargo_dir):
shutil.rmtree(cargo_dir)
-def bootstrap(help_triggered):
- """Configure, fetch, build and run the initial bootstrap"""
-
- # If the user is asking for help, let them know that the whole download-and-build
- # process has to happen before anything is printed out.
- if help_triggered:
- print("info: Downloading and building bootstrap before processing --help")
- print(" command. See src/bootstrap/README.md for help with common")
- print(" commands.")
-
- parser = argparse.ArgumentParser(description='Build rust')
+def parse_args():
+ """Parse the command line arguments that the python script needs."""
+ parser = argparse.ArgumentParser(add_help=False)
+ parser.add_argument('-h', '--help', action='store_true')
parser.add_argument('--config')
parser.add_argument('--build-dir')
parser.add_argument('--build')
parser.add_argument('--clean', action='store_true')
parser.add_argument('-v', '--verbose', action='count', default=0)
- args = [a for a in sys.argv if a != '-h' and a != '--help']
- args, _ = parser.parse_known_args(args)
+ return parser.parse_known_args(sys.argv)[0]
+def bootstrap(args):
+ """Configure, fetch, build and run the initial bootstrap"""
# Configure initial bootstrap
build = RustBuild()
build.rust_root = os.path.abspath(os.path.join(__file__, '../../..'))
- build.verbose = args.verbose
+ build.verbose = args.verbose != 0
build.clean = args.clean
# Read from `--config`, then `RUST_BOOTSTRAP_CONFIG`, then `./config.toml`,
with open(include_path) as included_toml:
build.config_toml += os.linesep + included_toml.read()
- config_verbose = build.get_toml('verbose', 'build')
- if config_verbose is not None:
- build.verbose = max(build.verbose, int(config_verbose))
+ verbose_count = args.verbose
+ config_verbose_count = build.get_toml('verbose', 'build')
+ if config_verbose_count is not None:
+ verbose_count = max(args.verbose, int(config_verbose_count))
build.use_vendored_sources = build.get_toml('vendor', 'build') == 'true'
-
build.use_locked_deps = build.get_toml('locked-deps', 'build') == 'true'
build.check_vendored_status()
data = json.load(f)
build.checksums_sha256 = data["checksums_sha256"]
build.stage0_compiler = Stage0Toolchain(data["compiler"])
-
- build.set_dist_environment(data["config"]["dist_server"])
+ build.download_url = os.getenv("RUSTUP_DIST_SERVER") or data["config"]["dist_server"]
build.build = args.build or build.build_triple()
# Fetch/build the bootstrap
build.download_toolchain()
sys.stdout.flush()
- build.build_bootstrap(args.color)
+ build.build_bootstrap(args.color, verbose_count)
sys.stdout.flush()
# Run the bootstrap
# x.py help <cmd> ...
if len(sys.argv) > 1 and sys.argv[1] == 'help':
- sys.argv = [sys.argv[0], '-h'] + sys.argv[2:]
+ sys.argv[1] = '-h'
+
+ args = parse_args()
+ help_triggered = args.help or len(sys.argv) == 1
- help_triggered = (
- '-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1)
+ # If the user is asking for help, let them know that the whole download-and-build
+ # process has to happen before anything is printed out.
+ if help_triggered:
+ print(
+ "info: Downloading and building bootstrap before processing --help command.\n"
+ " See src/bootstrap/README.md for help with common commands."
+ )
+
+ exit_code = 0
try:
- bootstrap(help_triggered)
- if not help_triggered:
- print("Build completed successfully in {}".format(
- format_build_time(time() - start_time)))
+ bootstrap(args)
except (SystemExit, KeyboardInterrupt) as error:
if hasattr(error, 'code') and isinstance(error.code, int):
exit_code = error.code
else:
exit_code = 1
print(error)
- if not help_triggered:
- print("Build completed unsuccessfully in {}".format(
- format_build_time(time() - start_time)))
- sys.exit(exit_code)
+
+ if not help_triggered:
+ print("Build completed successfully in", format_build_time(time() - start_time))
+ sys.exit(exit_code)
if __name__ == '__main__':
if stage >= 1 {
cargo.rustflag("-Cembed-bitcode=yes");
}
+ if builder.config.rust_lto == RustcLto::Off {
+ cargo.rustflag("-Clto=off");
+ }
// By default, rustc does not include unwind tables unless they are required
// for a particular target. They are not required by RISC-V targets, but
cargo.rustflag("-Cembed-bitcode=yes");
}
RustcLto::ThinLocal => { /* Do nothing, this is the default */ }
+ RustcLto::Off => {
+ cargo.rustflag("-Clto=off");
+ }
+ }
+ } else {
+ if builder.config.rust_lto == RustcLto::Off {
+ cargo.rustflag("-Clto=off");
}
}
}
/// LTO mode used for compiling rustc itself.
-#[derive(Default, Clone)]
+#[derive(Default, Clone, PartialEq)]
pub enum RustcLto {
+ Off,
#[default]
ThinLocal,
Thin,
"thin-local" => Ok(RustcLto::ThinLocal),
"thin" => Ok(RustcLto::Thin),
"fat" => Ok(RustcLto::Fat),
+ "off" => Ok(RustcLto::Off),
_ => Err(format!("Invalid value for rustc LTO: {}", s)),
}
}
incremental = true
# Print backtrace on internal compiler errors during bootstrap
backtrace-on-ice = true
+# Make the compiler and standard library faster to build, at the expense of a ~20% runtime slowdown.
+lto = "off"
[llvm]
# Will download LLVM from CI if available on your platform.
[rust]
# This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower.
incremental = true
+# Make the compiler and standard library faster to build, at the expense of a ~20% runtime slowdown.
+lto = "off"
[llvm]
# Will download LLVM from CI if available on your platform.
Config,
};
+static SHOULD_FIX_BINS_AND_DYLIBS: OnceCell<bool> = OnceCell::new();
+
/// Generic helpers that are useful anywhere in bootstrap.
impl Config {
pub fn is_verbose(&self) -> bool {
check_run(cmd, self.is_verbose())
}
- /// Modifies the interpreter section of 'fname' to fix the dynamic linker,
- /// or the RPATH section, to fix the dynamic library search path
- ///
- /// This is only required on NixOS and uses the PatchELF utility to
- /// change the interpreter/RPATH of ELF executables.
- ///
- /// Please see https://nixos.org/patchelf.html for more information
- fn fix_bin_or_dylib(&self, fname: &Path) {
- // FIXME: cache NixOS detection?
- match Command::new("uname").arg("-s").stderr(Stdio::inherit()).output() {
- Err(_) => return,
- Ok(output) if !output.status.success() => return,
- Ok(output) => {
- let mut s = output.stdout;
- if s.last() == Some(&b'\n') {
- s.pop();
- }
- if s != b"Linux" {
- return;
+ /// Whether or not `fix_bin_or_dylib` needs to be run; can only be true
+ /// on NixOS
+ fn should_fix_bins_and_dylibs(&self) -> bool {
+ let val = *SHOULD_FIX_BINS_AND_DYLIBS.get_or_init(|| {
+ match Command::new("uname").arg("-s").stderr(Stdio::inherit()).output() {
+ Err(_) => return false,
+ Ok(output) if !output.status.success() => return false,
+ Ok(output) => {
+ let mut os_name = output.stdout;
+ if os_name.last() == Some(&b'\n') {
+ os_name.pop();
+ }
+ if os_name != b"Linux" {
+ return false;
+ }
}
}
- }
- // If the user has asked binaries to be patched for Nix, then
- // don't check for NixOS or `/lib`, just continue to the patching.
- // NOTE: this intentionally comes after the Linux check:
- // - patchelf only works with ELF files, so no need to run it on Mac or Windows
- // - On other Unix systems, there is no stable syscall interface, so Nix doesn't manage the global libc.
- if !self.patch_binaries_for_nix {
+ // If the user has asked binaries to be patched for Nix, then
+ // don't check for NixOS or `/lib`.
+ // NOTE: this intentionally comes after the Linux check:
+ // - patchelf only works with ELF files, so no need to run it on Mac or Windows
+ // - On other Unix systems, there is no stable syscall interface, so Nix doesn't manage the global libc.
+ if self.patch_binaries_for_nix {
+ return true;
+ }
+
// Use `/etc/os-release` instead of `/etc/NIXOS`.
// The latter one does not exist on NixOS when using tmpfs as root.
- const NIX_IDS: &[&str] = &["ID=nixos", "ID='nixos'", "ID=\"nixos\""];
- let os_release = match File::open("/etc/os-release") {
- Err(e) if e.kind() == ErrorKind::NotFound => return,
+ let is_nixos = match File::open("/etc/os-release") {
+ Err(e) if e.kind() == ErrorKind::NotFound => false,
Err(e) => panic!("failed to access /etc/os-release: {}", e),
- Ok(f) => f,
+ Ok(os_release) => BufReader::new(os_release).lines().any(|l| {
+ let l = l.expect("reading /etc/os-release");
+ matches!(l.trim(), "ID=nixos" | "ID='nixos'" | "ID=\"nixos\"")
+ }),
};
- if !BufReader::new(os_release).lines().any(|l| NIX_IDS.contains(&t!(l).trim())) {
- return;
- }
- if Path::new("/lib").exists() {
- return;
- }
+ is_nixos && !Path::new("/lib").exists()
+ });
+ if val {
+ println!("info: You seem to be using Nix.");
}
+ val
+ }
- // At this point we're pretty sure the user is running NixOS or using Nix
- println!("info: you seem to be using Nix. Attempting to patch {}", fname.display());
+ /// Modifies the interpreter section of 'fname' to fix the dynamic linker,
+ /// or the RPATH section, to fix the dynamic library search path
+ ///
+ /// This is only required on NixOS and uses the PatchELF utility to
+ /// change the interpreter/RPATH of ELF executables.
+ ///
+ /// Please see https://nixos.org/patchelf.html for more information
+ fn fix_bin_or_dylib(&self, fname: &Path) {
+ assert_eq!(SHOULD_FIX_BINS_AND_DYLIBS.get(), Some(&true));
+ println!("attempting to patch {}", fname.display());
// Only build `.nix-deps` once.
static NIX_DEPS_DIR: OnceCell<PathBuf> = OnceCell::new();
let channel = format!("{version}-{date}");
let host = self.build;
- let rustfmt_path = self.initial_rustc.with_file_name(exe("rustfmt", host));
- let bin_root = self.out.join(host.triple).join("stage0");
+ let bin_root = self.out.join(host.triple).join("rustfmt");
+ let rustfmt_path = bin_root.join("bin").join(exe("rustfmt", host));
let rustfmt_stamp = bin_root.join(".rustfmt-stamp");
if rustfmt_path.exists() && !program_out_of_date(&rustfmt_stamp, &channel) {
return Some(rustfmt_path);
}
- let filename = format!("rustfmt-{version}-{build}.tar.xz", build = host.triple);
- self.download_component(DownloadSource::Dist, filename, "rustfmt-preview", &date, "stage0");
-
- self.fix_bin_or_dylib(&bin_root.join("bin").join("rustfmt"));
- self.fix_bin_or_dylib(&bin_root.join("bin").join("cargo-fmt"));
+ self.download_component(
+ DownloadSource::Dist,
+ format!("rustfmt-{version}-{build}.tar.xz", build = host.triple),
+ "rustfmt-preview",
+ &date,
+ "rustfmt",
+ );
+ self.download_component(
+ DownloadSource::Dist,
+ format!("rustc-{version}-{build}.tar.xz", build = host.triple),
+ "rustc",
+ &date,
+ "rustfmt",
+ );
+
+ if self.should_fix_bins_and_dylibs() {
+ self.fix_bin_or_dylib(&bin_root.join("bin").join("rustfmt"));
+ self.fix_bin_or_dylib(&bin_root.join("bin").join("cargo-fmt"));
+ }
self.create(&rustfmt_stamp, &channel);
Some(rustfmt_path)
let filename = format!("rust-src-{version}.tar.xz");
self.download_ci_component(filename, "rust-src", commit);
- self.fix_bin_or_dylib(&bin_root.join("bin").join("rustc"));
- self.fix_bin_or_dylib(&bin_root.join("bin").join("rustdoc"));
- self.fix_bin_or_dylib(&bin_root.join("libexec").join("rust-analyzer-proc-macro-srv"));
- let lib_dir = bin_root.join("lib");
- for lib in t!(fs::read_dir(&lib_dir), lib_dir.display().to_string()) {
- let lib = t!(lib);
- if lib.path().extension() == Some(OsStr::new("so")) {
- self.fix_bin_or_dylib(&lib.path());
+ if self.should_fix_bins_and_dylibs() {
+ self.fix_bin_or_dylib(&bin_root.join("bin").join("rustc"));
+ self.fix_bin_or_dylib(&bin_root.join("bin").join("rustdoc"));
+ self.fix_bin_or_dylib(
+ &bin_root.join("libexec").join("rust-analyzer-proc-macro-srv"),
+ );
+ let lib_dir = bin_root.join("lib");
+ for lib in t!(fs::read_dir(&lib_dir), lib_dir.display().to_string()) {
+ let lib = t!(lib);
+ if lib.path().extension() == Some(OsStr::new("so")) {
+ self.fix_bin_or_dylib(&lib.path());
+ }
}
}
+
t!(fs::write(rustc_stamp, commit));
}
}
let key = format!("{}{}", llvm_sha, self.llvm_assertions);
if program_out_of_date(&llvm_stamp, &key) && !self.dry_run() {
self.download_ci_llvm(&llvm_sha);
- for entry in t!(fs::read_dir(llvm_root.join("bin"))) {
- self.fix_bin_or_dylib(&t!(entry).path());
+ if self.should_fix_bins_and_dylibs() {
+ for entry in t!(fs::read_dir(llvm_root.join("bin"))) {
+ self.fix_bin_or_dylib(&t!(entry).path());
+ }
}
// Update the timestamp of llvm-config to force rustc_llvm to be
let llvm_config = llvm_root.join("bin").join(exe("llvm-config", self.build));
t!(filetime::set_file_times(&llvm_config, now, now));
- let llvm_lib = llvm_root.join("lib");
- for entry in t!(fs::read_dir(&llvm_lib)) {
- let lib = t!(entry).path();
- if lib.extension().map_or(false, |ext| ext == "so") {
- self.fix_bin_or_dylib(&lib);
+ if self.should_fix_bins_and_dylibs() {
+ let llvm_lib = llvm_root.join("lib");
+ for entry in t!(fs::read_dir(&llvm_lib)) {
+ let lib = t!(entry).path();
+ if lib.extension().map_or(false, |ext| ext == "so") {
+ self.fix_bin_or_dylib(&lib);
+ }
}
}
+
t!(fs::write(llvm_stamp, key));
}
}
//! crates.io and Cargo.
//! * A standard interface to build across all platforms, including MSVC
//!
-//! ## Architecture
-//!
-//! The build system defers most of the complicated logic managing invocations
-//! of rustc and rustdoc to Cargo itself. However, moving through various stages
-//! and copying artifacts is still necessary for it to do. Each time rustbuild
-//! is invoked, it will iterate through the list of predefined steps and execute
-//! each serially in turn if it matches the paths passed or is a default rule.
-//! For each step rustbuild relies on the step internally being incremental and
-//! parallel. Note, though, that the `-j` parameter to rustbuild gets forwarded
-//! to appropriate test harnesses and such.
-//!
-//! Most of the "meaty" steps that matter are backed by Cargo, which does indeed
-//! have its own parallelism and incremental management. Later steps, like
-//! tests, aren't incremental and simply run the entire suite currently.
-//! However, compiletest itself tries to avoid running tests when the artifacts
-//! that are involved (mainly the compiler) haven't changed.
-//!
-//! When you execute `x.py build`, the steps executed are:
-//!
-//! * First, the python script is run. This will automatically download the
-//! stage0 rustc and cargo according to `src/stage0.json`, or use the cached
-//! versions if they're available. These are then used to compile rustbuild
-//! itself (using Cargo). Finally, control is then transferred to rustbuild.
-//!
-//! * Rustbuild takes over, performs sanity checks, probes the environment,
-//! reads configuration, and starts executing steps as it reads the command
-//! line arguments (paths) or going through the default rules.
-//!
-//! The build output will be something like the following:
-//!
-//! Building stage0 std artifacts
-//! Copying stage0 std
-//! Building stage0 test artifacts
-//! Copying stage0 test
-//! Building stage0 compiler artifacts
-//! Copying stage0 rustc
-//! Assembling stage1 compiler
-//! Building stage1 std artifacts
-//! Copying stage1 std
-//! Building stage1 test artifacts
-//! Copying stage1 test
-//! Building stage1 compiler artifacts
-//! Copying stage1 rustc
-//! Assembling stage2 compiler
-//! Uplifting stage1 std
-//! Uplifting stage1 test
-//! Uplifting stage1 rustc
-//!
-//! Let's disect that a little:
-//!
-//! ## Building stage0 {std,test,compiler} artifacts
-//!
-//! These steps use the provided (downloaded, usually) compiler to compile the
-//! local Rust source into libraries we can use.
-//!
-//! ## Copying stage0 {std,test,rustc}
-//!
-//! This copies the build output from Cargo into
-//! `build/$HOST/stage0-sysroot/lib/rustlib/$ARCH/lib`. FIXME: this step's
-//! documentation should be expanded -- the information already here may be
-//! incorrect.
-//!
-//! ## Assembling stage1 compiler
-//!
-//! This copies the libraries we built in "building stage0 ... artifacts" into
-//! the stage1 compiler's lib directory. These are the host libraries that the
-//! compiler itself uses to run. These aren't actually used by artifacts the new
-//! compiler generates. This step also copies the rustc and rustdoc binaries we
-//! generated into build/$HOST/stage/bin.
-//!
-//! The stage1/bin/rustc is a fully functional compiler, but it doesn't yet have
-//! any libraries to link built binaries or libraries to. The next 3 steps will
-//! provide those libraries for it; they are mostly equivalent to constructing
-//! the stage1/bin compiler so we don't go through them individually.
-//!
-//! ## Uplifting stage1 {std,test,rustc}
-//!
-//! This step copies the libraries from the stage1 compiler sysroot into the
-//! stage2 compiler. This is done to avoid rebuilding the compiler; libraries
-//! we'd build in this step should be identical (in function, if not necessarily
-//! identical on disk) so there's no need to recompile the compiler again. Note
-//! that if you want to, you can enable the full-bootstrap option to change this
-//! behavior.
-//!
-//! Each step is driven by a separate Cargo project and rustbuild orchestrates
-//! copying files between steps and otherwise preparing for Cargo to run.
-//!
//! ## Further information
//!
//! More documentation can be found in each respective module below, and you can
(None, "bootstrap", None),
(Some(Mode::Rustc), "parallel_compiler", None),
(Some(Mode::ToolRustc), "parallel_compiler", None),
- (Some(Mode::ToolRustc), "emulate_second_only_system", None),
(Some(Mode::Codegen), "parallel_compiler", None),
(Some(Mode::Std), "stdarch_intel_sde", None),
(Some(Mode::Std), "no_fp_fmt_parse", None),
(Some(Mode::Std), "backtrace_in_libstd", None),
/* Extra values not defined in the built-in targets yet, but used in std */
(Some(Mode::Std), "target_env", Some(&["libnx"])),
- (Some(Mode::Std), "target_os", Some(&["watchos"])),
- (
- Some(Mode::Std),
- "target_arch",
- Some(&["asmjs", "spirv", "nvptx", "nvptx64", "le32", "xtensa"]),
- ),
+ // (Some(Mode::Std), "target_os", Some(&[])),
+ (Some(Mode::Std), "target_arch", Some(&["asmjs", "spirv", "nvptx", "xtensa"])),
/* Extra names used by dependencies */
- // FIXME: Used by rustfmt is their test but is invalid (neither cargo nor bootstrap ever set
- // this config) should probably by removed or use a allow attribute.
- (Some(Mode::ToolRustc), "release", None),
- // FIXME: Used by stdarch in their test, should use a allow attribute instead.
- (Some(Mode::Std), "dont_compile_me", None),
// FIXME: Used by serde_json, but we should not be triggering on external dependencies.
(Some(Mode::Rustc), "no_btreemap_remove_entry", None),
(Some(Mode::ToolRustc), "no_btreemap_remove_entry", None),
// FIXME: Used by proc-macro2, but we should not be triggering on external dependencies.
(Some(Mode::Rustc), "span_locations", None),
(Some(Mode::ToolRustc), "span_locations", None),
- // Can be passed in RUSTFLAGS to prevent direct syscalls in rustix.
- (None, "rustix_use_libc", None),
+ // FIXME: Used by rustix, but we should not be triggering on external dependencies.
+ (Some(Mode::Rustc), "rustix_use_libc", None),
+ (Some(Mode::ToolRustc), "rustix_use_libc", None),
+ // FIXME: Used by filetime, but we should not be triggering on external dependencies.
+ (Some(Mode::Rustc), "emulate_second_only_system", None),
+ (Some(Mode::ToolRustc), "emulate_second_only_system", None),
];
/// A structure representing a Rust compiler.
cmd.arg("--bless");
}
- builder.info("tidy check");
- try_run(builder, &mut cmd);
-
if builder.config.channel == "dev" || builder.config.channel == "nightly" {
builder.info("fmt check");
if builder.initial_rustfmt().is_none() {
}
crate::format::format(&builder, !builder.config.cmd.bless(), &[]);
}
+
+ builder.info("tidy check");
+ try_run(builder, &mut cmd);
+
+ builder.ensure(ExpandYamlAnchors {});
}
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
import signal
import subprocess
import sys
-from typing import ClassVar, List
+from typing import ClassVar, List, Optional
@dataclass
class TestEnvironment:
rust_dir: str
sdk_dir: str
- target_arch: str
- package_server_pid: int = None
- emu_addr: str = None
- libstd_name: str = None
- libtest_name: str = None
+ target: str
+ package_server_pid: Optional[int] = None
+ emu_addr: Optional[str] = None
+ libstd_name: Optional[str] = None
+ libtest_name: Optional[str] = None
verbose: bool = False
@staticmethod
return os.path.abspath(tmp_dir)
return os.path.join(os.path.dirname(__file__), "tmp~")
+ @staticmethod
+ def triple_to_arch(triple):
+ if "x86_64" in triple:
+ return "x64"
+ elif "aarch64" in triple:
+ return "arm64"
+ else:
+ raise Exception(f"Unrecognized target triple {triple}")
+
@classmethod
def env_file_path(cls):
return os.path.join(cls.tmp_dir(), "test_env.json")
return cls(
os.path.abspath(args.rust),
os.path.abspath(args.sdk),
- args.target_arch,
+ args.target,
verbose=args.verbose,
)
return cls(
test_env["rust_dir"],
test_env["sdk_dir"],
- test_env["target_arch"],
+ test_env["target"],
libstd_name=test_env["libstd_name"],
libtest_name=test_env["libtest_name"],
emu_addr=test_env["emu_addr"],
verbose=test_env["verbose"],
)
- def image_name(self):
- if self.target_arch == "x64":
- return "qemu-x64"
- if self.target_arch == "arm64":
- return "qemu-arm64"
- raise Exception(f"Unrecognized target architecture {self.target_arch}")
-
def write_to_file(self):
with open(self.env_file_path(), "w", encoding="utf-8") as f:
f.write(json.dumps(self.__dict__))
def repo_dir(self):
return os.path.join(self.tmp_dir(), self.TEST_REPO_NAME)
- def rustlib_dir(self):
- if self.target_arch == "x64":
- return "x86_64-unknown-fuchsia"
- if self.target_arch == "arm64":
- return "aarch64-unknown-fuchsia"
- raise Exception(f"Unrecognized target architecture {self.target_arch}")
-
def libs_dir(self):
return os.path.join(
self.rust_dir,
return os.path.join(
self.libs_dir(),
"rustlib",
- self.rustlib_dir(),
+ self.target,
"lib",
)
"--emulator-log",
self.emulator_log_path(),
"--image-name",
- self.image_name(),
+ "qemu-" + self.triple_to_arch(self.target),
],
stdout=self.subprocess_output(),
stderr=self.subprocess_output(),
package_dir=package_dir,
package_name=package_name,
rust_dir=self.rust_dir,
- rustlib_dir=self.rustlib_dir(),
+ rustlib_dir=self.target,
sdk_dir=self.sdk_dir,
libstd_name=self.libstd_name,
libtest_name=self.libtest_name,
- target_arch=self.target_arch,
+ target_arch=self.triple_to_arch(self.target),
)
)
for shared_lib in shared_libs:
action="store_true",
)
start_parser.add_argument(
- "--target-arch",
- help="the architecture of the image to test",
+ "--target",
+ help="the target platform to test",
required=True,
)
start_parser.set_defaults(func=start)
- &shared-ci-variables
CI_JOB_NAME: ${{ matrix.name }}
+ CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
- &public-variables
SCCACHE_BUCKET: rust-lang-ci-sccache2
<<: *base-job
- &job-macos-xl
- os: macos-12-xl
+ os: macos-latest # We don't have an XL builder for this
<<: *base-job
- &job-windows-xl
ci_dir=`cd $(dirname $0) && pwd`
source "$ci_dir/shared.sh"
+export CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse
+
if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try || isCiBranch try-perf; then
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests"
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.metrics"
import time
import traceback
import urllib.request
-from collections import OrderedDict
from io import StringIO
from pathlib import Path
-from typing import Callable, Dict, Iterable, List, Optional, Union
+from typing import Callable, Dict, Iterable, Iterator, List, Optional, Tuple, Union
PGO_HOST = os.environ["PGO_HOST"]
return False
+def get_timestamp() -> float:
+ return time.time()
+
+
+Duration = float
+TimerSection = Union[Duration, "Timer"]
+
+
+def iterate_sections(section: TimerSection, name: str, level: int = 0) -> Iterator[Tuple[int, str, Duration]]:
+ """
+ Hierarchically iterate the sections of a timer, in a depth-first order.
+ """
+ if isinstance(section, Duration):
+ yield (level, name, section)
+ elif isinstance(section, Timer):
+ yield (level, name, section.total_duration())
+ for (child_name, child_section) in section.sections:
+ yield from iterate_sections(child_section, child_name, level=level + 1)
+ else:
+ assert False
+
+
class Timer:
- def __init__(self):
- # We want this dictionary to be ordered by insertion.
- # We use `OrderedDict` for compatibility with older Python versions.
- self.stages = OrderedDict()
+ def __init__(self, parent_names: Tuple[str, ...] = ()):
+ self.sections: List[Tuple[str, TimerSection]] = []
+ self.section_active = False
+ self.parent_names = parent_names
@contextlib.contextmanager
- def stage(self, name: str):
- assert name not in self.stages
+ def section(self, name: str) -> "Timer":
+ assert not self.section_active
+ self.section_active = True
- start = time.time()
+ start = get_timestamp()
exc = None
+
+ child_timer = Timer(parent_names=self.parent_names + (name, ))
+ full_name = " > ".join(child_timer.parent_names)
try:
- LOGGER.info(f"Stage `{name}` starts")
- yield
+ LOGGER.info(f"Section `{full_name}` starts")
+ yield child_timer
except BaseException as exception:
exc = exception
raise
finally:
- end = time.time()
+ end = get_timestamp()
duration = end - start
- self.stages[name] = duration
+
+ if child_timer.has_children():
+ self.sections.append((name, child_timer))
+ else:
+ self.sections.append((name, duration))
if exc is None:
- LOGGER.info(f"Stage `{name}` ended: OK ({duration:.2f}s)")
+ LOGGER.info(f"Section `{full_name}` ended: OK ({duration:.2f}s)")
+ else:
+ LOGGER.info(f"Section `{full_name}` ended: FAIL ({duration:.2f}s)")
+ self.section_active = False
+
+ def total_duration(self) -> Duration:
+ duration = 0
+ for (_, section) in self.sections:
+ if isinstance(section, Duration):
+ duration += section
else:
- LOGGER.info(f"Stage `{name}` ended: FAIL ({duration:.2f}s)")
+ duration += section.total_duration()
+ return duration
+
+ def has_children(self) -> bool:
+ return len(self.sections) > 0
def print_stats(self):
- total_duration = sum(self.stages.values())
+ rows = []
+ for (child_name, child_section) in self.sections:
+ for (level, name, duration) in iterate_sections(child_section, child_name, level=0):
+ label = f"{' ' * level}{name}:"
+ rows.append((label, duration))
- # 57 is the width of the whole table
- divider = "-" * 57
+ # Empty row
+ rows.append(("", ""))
+
+ total_duration_label = "Total duration:"
+ total_duration = self.total_duration()
+ rows.append((total_duration_label, humantime(total_duration)))
+
+ space_after_label = 2
+ max_label_length = max(16, max(len(label) for (label, _) in rows)) + space_after_label
+
+ table_width = max_label_length + 23
+ divider = "-" * table_width
with StringIO() as output:
print(divider, file=output)
- for (name, duration) in self.stages.items():
- pct = (duration / total_duration) * 100
- name_str = f"{name}:"
- print(f"{name_str:<34} {duration:>12.2f}s ({pct:>5.2f}%)", file=output)
-
- total_duration_label = "Total duration:"
- print(f"{total_duration_label:<34} {total_duration:>12.2f}s", file=output)
+ for (label, duration) in rows:
+ if isinstance(duration, Duration):
+ pct = (duration / total_duration) * 100
+ value = f"{duration:>12.2f}s ({pct:>5.2f}%)"
+ else:
+ value = f"{duration:>{len(total_duration_label) + 7}}"
+ print(f"{label:<{max_label_length}} {value}", file=output)
print(divider, file=output, end="")
LOGGER.info(f"Timer results\n{output.getvalue()}")
os.chdir(cwd)
+def humantime(time_s: float) -> str:
+ hours = time_s // 3600
+ time_s = time_s % 3600
+ minutes = time_s // 60
+ seconds = time_s % 60
+
+ result = ""
+ if hours > 0:
+ result += f"{int(hours)}h "
+ if minutes > 0:
+ result += f"{int(minutes)}m "
+ result += f"{round(seconds)}s"
+ return result
+
+
def move_path(src: Path, dst: Path):
LOGGER.info(f"Moving `{src}` to `{dst}`")
shutil.move(src, dst)
pipeline.build_rustc_perf()
# Stage 1: Build rustc + PGO instrumented LLVM
- with timer.stage("Build rustc (LLVM PGO)"):
- build_rustc(pipeline, args=[
- "--llvm-profile-generate"
- ], env=dict(
- LLVM_PROFILE_DIR=str(pipeline.llvm_profile_dir_root() / "prof-%p")
- ))
+ with timer.section("Stage 1 (LLVM PGO)") as stage1:
+ with stage1.section("Build rustc and LLVM"):
+ build_rustc(pipeline, args=[
+ "--llvm-profile-generate"
+ ], env=dict(
+ LLVM_PROFILE_DIR=str(pipeline.llvm_profile_dir_root() / "prof-%p")
+ ))
- with timer.stage("Gather profiles (LLVM PGO)"):
- gather_llvm_profiles(pipeline)
+ with stage1.section("Gather profiles"):
+ gather_llvm_profiles(pipeline)
clear_llvm_files(pipeline)
final_build_args += [
]
# Stage 2: Build PGO instrumented rustc + LLVM
- with timer.stage("Build rustc (rustc PGO)"):
- build_rustc(pipeline, args=[
- "--rust-profile-generate",
- pipeline.rustc_profile_dir_root()
- ])
+ with timer.section("Stage 2 (rustc PGO)") as stage2:
+ with stage2.section("Build rustc and LLVM"):
+ build_rustc(pipeline, args=[
+ "--rust-profile-generate",
+ pipeline.rustc_profile_dir_root()
+ ])
- with timer.stage("Gather profiles (rustc PGO)"):
- gather_rustc_profiles(pipeline)
+ with stage2.section("Gather profiles"):
+ gather_rustc_profiles(pipeline)
clear_llvm_files(pipeline)
final_build_args += [
# Stage 3: Build rustc + BOLT instrumented LLVM
if pipeline.supports_bolt():
- with timer.stage("Build rustc (LLVM BOLT)"):
- build_rustc(pipeline, args=[
- "--llvm-profile-use",
- pipeline.llvm_profile_merged_file(),
- "--llvm-bolt-profile-generate",
- ])
- with timer.stage("Gather profiles (LLVM BOLT)"):
- gather_llvm_bolt_profiles(pipeline)
+ with timer.section("Stage 3 (LLVM BOLT)") as stage3:
+ with stage3.section("Build rustc and LLVM"):
+ build_rustc(pipeline, args=[
+ "--llvm-profile-use",
+ pipeline.llvm_profile_merged_file(),
+ "--llvm-bolt-profile-generate",
+ ])
+ with stage3.section("Gather profiles"):
+ gather_llvm_bolt_profiles(pipeline)
clear_llvm_files(pipeline)
final_build_args += [
]
# Stage 4: Build PGO optimized rustc + PGO/BOLT optimized LLVM
- with timer.stage("Final build"):
+ with timer.section("Stage 4 (final build)"):
cmd(final_build_args)
-Subproject commit 2cd1b5593d26dc6a03c20f8619187ad4b2485552
+Subproject commit f2a78f64b668f63f581203c6bac509903f7c00ee
-Subproject commit 19f798d448835a4888e3b3eae7fe69f1d61d8681
+Subproject commit f1a4614aa41cc544b91b79760a709e113f3451d7
-Subproject commit 960d610e7f33889a2577f5f17c26f0d5c82b30df
+Subproject commit bd1829d235296952bf72ca55635e360584b8805e
-Subproject commit 2cb0ed9ba56360949f492f9866afe8c293f9f9da
+Subproject commit 22882fb3f7b4d69fdc0d1731e8b9cfcb6910537d
-Subproject commit a9fb7d13eadfcc5f457962731f105b97f9a7474a
+Subproject commit 134376872e8c387ef369507e0ee9b5a0e3272718
-Subproject commit 7352353ae91c48b136d2ca7d03822e1448165e1e
+Subproject commit e359ee27fc3da3356d71a732128c0a1abe02e53a
src/ci/docker/scripts/fuchsia-test-runner.py start
--rust ${RUST_SRC_PATH}/install
--sdk ${SDK_PATH}
- --target-arch {x64,arm64}
+ --target-triple {x86_64-unknown-fuchsia|aarch64-unknown-fuchsia}
```
Where `${RUST_SRC_PATH}/install` is the `prefix` set in `config.toml` and
);
```
+#### else blocks (let-else statements)
+
+If a let statement contains an `else` component, also known as a let-else statement,
+then the `else` component should be formatted according to the same rules as the `else` block
+in [control flow expressions (i.e. if-else, and if-let-else expressions)](./expressions.md#control-flow-expressions).
+Apply the same formatting rules to the components preceding
+the `else` block (i.e. the `let pattern: Type = initializer_expr ...` portion)
+as described [above](#let-statements)
+
+Similarly to if-else expressions, if the initializer
+expression is multi-lined, then the `else` keyword and opening brace of the block (i.e. `else {`)
+should be put on the same line as the end of the initializer
+expression with a preceding space if all the following are true:
+
+* The initializer expression ends with one or more closing
+ parentheses, square brackets, and/or braces
+* There is nothing else on that line
+* That line is not indented beyond the indent of the first line containing the `let` keyword
+
+For example:
+
+```rust
+let Some(x) = y.foo(
+ "abc",
+ fairly_long_identifier,
+ "def",
+ "123456",
+ "string",
+ "cheese",
+) else {
+ bar()
+}
+```
+
+Otherwise, the `else` keyword and opening brace should be placed on the next line after the end of the initializer expression, and should not be indented (the `else` keyword should be aligned with the `let` keyword).
+
+For example:
+
+```rust
+let Some(x) = abcdef()
+ .foo(
+ "abc",
+ some_really_really_really_long_ident,
+ "ident",
+ "123456",
+ )
+ .bar()
+ .baz()
+ .qux("fffffffffffffffff")
+else {
+ foo_bar()
+}
+```
+
+##### Single line let-else statements
+
+The entire let-else statement may be formatted on a single line if all the following are true:
+
+* the entire statement is *short*
+* the `else` block contains a single-line expression and no statements
+* the `else` block contains no comments
+* the let statement components preceding the `else` block can be formatted on a single line
+
+```rust
+let Some(1) = opt else { return };
+
+let Some(1) = opt else {
+ return;
+};
+
+let Some(1) = opt else {
+ // nope
+ return
+};
+```
+
+Formatters may allow users to configure the value of the threshold
+used to determine whether a let-else statement is *short*.
### Macros in statement position
get_all_import_attributes(use_node, cx.tcx, item.owner_id.def_id, &mut extra_attrs);
}
- if !extra_attrs.is_empty() {
+ let mut item = if !extra_attrs.is_empty() {
extra_attrs.extend_from_slice(inline::load_attrs(cx, def_id));
let attrs = Attributes::from_ast(&extra_attrs);
let cfg = extra_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg);
- vec![Item::from_def_id_and_attrs_and_parts(
- def_id,
- Some(name),
- kind,
- Box::new(attrs),
- cfg,
- )]
+ Item::from_def_id_and_attrs_and_parts(def_id, Some(name), kind, Box::new(attrs), cfg)
} else {
- vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)]
- }
+ Item::from_def_id_and_parts(def_id, Some(name), kind, cx)
+ };
+ item.inline_stmt_id = import_id.map(|def_id| def_id.to_def_id());
+ vec![item]
})
}
// these values up both in `dataset` and in the storage API, so it needs to be able
// to convert the names back and forth. Despite doing this kebab-case to
// StudlyCaps transformation automatically, the JS DOM API does not provide a
- // mechanism for doing the just transformation on a string. So we want to avoid
+ // mechanism for doing just the transformation on a string. So we want to avoid
// the StudlyCaps representation in the `dataset` property.
//
// We solve this by replacing all the `-`s with `_`s. We do that here, when we
if f.alternate() {
write!(f, ": {:#}", print_generic_bounds(bounds, cx))?;
} else {
- write!(f, ": {}", print_generic_bounds(bounds, cx))?;
+ write!(f, ": {}", print_generic_bounds(bounds, cx))?;
}
}
if f.alternate() {
write!(f, " = {:#}", ty.print(cx))?;
} else {
- write!(f, " = {}", ty.print(cx))?;
+ write!(f, " = {}", ty.print(cx))?;
}
}
if f.alternate() {
write!(f, "const {}: {:#}", self.name, ty.print(cx))?;
} else {
- write!(f, "const {}: {}", self.name, ty.print(cx))?;
+ write!(f, "const {}: {}", self.name, ty.print(cx))?;
}
if let Some(default) = default {
if f.alternate() {
write!(f, " = {:#}", default)?;
} else {
- write!(f, " = {}", default)?;
+ write!(f, " = {}", default)?;
}
}
} else {
let mut br_with_padding = String::with_capacity(6 * indent + 28);
br_with_padding.push_str("<br>");
- for _ in 0..indent + 4 {
- br_with_padding.push_str(" ");
+
+ let padding_amout =
+ if ending == Ending::Newline { indent + 4 } else { indent + "fn where ".len() };
+
+ for _ in 0..padding_amout {
+ br_with_padding.push_str(" ");
}
let where_preds = where_preds.to_string().replace("<br>", &br_with_padding);
if ending == Ending::Newline {
- let mut clause = " ".repeat(indent.saturating_sub(1));
+ let mut clause = " ".repeat(indent.saturating_sub(1));
write!(clause, "<span class=\"where fmt-newline\">where{where_preds},</span>")?;
clause
} else {
if indent == 0 {
format!("<br><span class=\"where\">where{where_preds}</span>")
} else {
+ // put the first one on the same line as the 'where' keyword
+ let where_preds = where_preds.replacen(&br_with_padding, " ", 1);
+
let mut clause = br_with_padding;
- clause.truncate(clause.len() - 4 * " ".len());
+ clause.truncate(clause.len() - "where ".len());
+
write!(clause, "<span class=\"where\">where{where_preds}</span>")?;
clause
}
let declaration_len = header_len + args_plain.len() + arrow_plain.len();
let output = if declaration_len > 80 {
- let full_pad = format!("<br>{}", " ".repeat(indent + 4));
- let close_pad = format!("<br>{}", " ".repeat(indent));
+ let full_pad = format!("<br>{}", " ".repeat(indent + 4));
+ let close_pad = format!("<br>{}", " ".repeat(indent));
format!(
"({pad}{args}{close}){arrow}",
pad = if self.inputs.values.is_empty() { "" } else { &full_pad },
if f.alternate() {
write!(f, ": {:#}", print_generic_bounds(bounds, cx))?;
} else {
- write!(f, ": {}", print_generic_bounds(bounds, cx))?;
+ write!(f, ": {}", print_generic_bounds(bounds, cx))?;
}
}
}
write_footer(out, playground_button);
}
-/// Highlights `src` as a macro, returning the HTML output.
-pub(crate) fn render_macro_with_highlighting(src: &str, out: &mut Buffer) {
- write_header(out, "macro", None, Tooltip::None);
+/// Highlights `src` as an item-decl, returning the HTML output.
+pub(crate) fn render_item_decl_with_highlighting(src: &str, out: &mut Buffer) {
+ write!(out, "<pre class=\"rust item-decl\">");
write_code(out, src, None, None);
- write_footer(out, None);
+ write!(out, "</pre>");
}
/// Highlights `src` as a source code page, returning the HTML output.
pub(crate) root_path: &'a str,
pub(crate) static_root_path: Option<&'a str>,
pub(crate) description: &'a str,
- pub(crate) keywords: &'a str,
pub(crate) resource_suffix: &'a str,
}
/// E.g. if `heading_offset: HeadingOffset::H2`, then `# something` renders an `<h2>`.
pub heading_offset: HeadingOffset,
}
-/// A tuple struct like `Markdown` that renders the markdown with a table of contents.
-pub(crate) struct MarkdownWithToc<'a>(
- pub(crate) &'a str,
- pub(crate) &'a mut IdMap,
- pub(crate) ErrorCodes,
- pub(crate) Edition,
- pub(crate) &'a Option<Playground>,
-);
+/// A struct like `Markdown` that renders the markdown with a table of contents.
+pub(crate) struct MarkdownWithToc<'a> {
+ pub(crate) content: &'a str,
+ pub(crate) ids: &'a mut IdMap,
+ pub(crate) error_codes: ErrorCodes,
+ pub(crate) edition: Edition,
+ pub(crate) playground: &'a Option<Playground>,
+}
/// A tuple struct like `Markdown` that renders the markdown escaping HTML tags
/// and includes no paragraph tags.
pub(crate) struct MarkdownItemInfo<'a>(pub(crate) &'a str, pub(crate) &'a mut IdMap);
impl MarkdownWithToc<'_> {
pub(crate) fn into_string(self) -> String {
- let MarkdownWithToc(md, ids, codes, edition, playground) = self;
+ let MarkdownWithToc { content: md, ids, error_codes: codes, edition, playground } = self;
let p = Parser::new_ext(md, main_body_opts()).into_offset_iter();
use super::write_shared::write_shared;
use super::{
collect_spans_and_sources, print_sidebar, scrape_examples_help, sidebar_module_like, AllTypes,
- LinkFromSrc, NameDoc, StylePath, BASIC_KEYWORDS,
+ LinkFromSrc, NameDoc, StylePath,
};
use crate::clean::{self, types::ExternalLocation, ExternalCrate};
self.shared.layout.krate
)
};
- let keywords = make_item_keywords(it);
let name;
let tyname_s = if it.is_crate() {
name = format!("{} crate", tyname);
static_root_path: clone_shared.static_root_path.as_deref(),
title: &title,
description: &desc,
- keywords: &keywords,
resource_suffix: &clone_shared.resource_suffix,
};
let mut page_buffer = Buffer::html();
root_path: "../",
static_root_path: shared.static_root_path.as_deref(),
description: "List of all items in this crate",
- keywords: BASIC_KEYWORDS,
resource_suffix: &shared.resource_suffix,
};
let all = shared.all.replace(AllTypes::new());
&self.shared.cache
}
}
-
-fn make_item_keywords(it: &clean::Item) -> String {
- format!("{}, {}", BASIC_KEYWORDS, it.name.as_ref().unwrap())
-}
}
}
-pub(crate) const BASIC_KEYWORDS: &str = "rust, rustlang, rust-lang";
-
/// Returns a list of all paths used in the type.
/// This is used to help deduplicate imported impls
/// for reexported types. If any of the contained
}
clean::ImportItem(ref import) => {
- let (stab, stab_tags) = if let Some(import_def_id) = import.source.did {
+ let stab_tags = if let Some(import_def_id) = import.source.did {
let ast_attrs = cx.tcx().get_attrs_unchecked(import_def_id);
let import_attrs = Box::new(clean::Attributes::from_ast(ast_attrs));
..myitem.clone()
};
- let stab = import_item.stability_class(cx.tcx());
let stab_tags = Some(extra_info_tags(&import_item, item, cx.tcx()));
- (stab, stab_tags)
+ stab_tags
} else {
- (None, None)
+ None
};
- let add = if stab.is_some() { " " } else { "" };
-
w.write_str(ITEM_TABLE_ROW_OPEN);
let id = match import.kind {
clean::ImportKind::Simple(s) => {
};
write!(
w,
- "<div class=\"item-left{add}{stab}\"{id}>\
+ "<div class=\"item-left\"{id}>\
<code>{vis}{imp}</code>\
</div>\
{stab_tags_before}{stab_tags}{stab_tags_after}",
- stab = stab.unwrap_or_default(),
vis = visibility_print_with_space(myitem.visibility(tcx), myitem.item_id, cx),
imp = import.print(cx),
);
_ => "",
};
- let stab = myitem.stability_class(cx.tcx());
- let add = if stab.is_some() { " " } else { "" };
-
let visibility_emoji = match myitem.visibility(tcx) {
Some(ty::Visibility::Restricted(_)) => {
"<span title=\"Restricted Visibility\"> 🔒</span> "
};
write!(
w,
- "<div class=\"item-left{add}{stab}\">\
+ "<div class=\"item-left\">\
<a class=\"{class}\" href=\"{href}\" title=\"{title}\">{name}</a>\
{visibility_emoji}\
{unsafety_flag}\
visibility_emoji = visibility_emoji,
stab_tags = extra_info_tags(myitem, item, cx.tcx()),
class = myitem.type_(),
- add = add,
- stab = stab.unwrap_or_default(),
unsafety_flag = unsafety_flag,
href = item_path(myitem.type_(), myitem.name.unwrap().as_str()),
title = [myitem.type_().to_string(), full_path(cx, myitem)]
let notable_traits =
f.decl.output.as_return().and_then(|output| notable_traits_button(output, cx));
- wrap_into_item_decl(w, |w| {
- wrap_item(w, |w| {
- render_attributes_in_pre(w, it, "");
- w.reserve(header_len);
- write!(
- w,
- "{vis}{constness}{asyncness}{unsafety}{abi}fn \
- {name}{generics}{decl}{notable_traits}{where_clause}",
- vis = visibility,
- constness = constness,
- asyncness = asyncness,
- unsafety = unsafety,
- abi = abi,
- name = name,
- generics = f.generics.print(cx),
- where_clause = print_where_clause(&f.generics, cx, 0, Ending::Newline),
- decl = f.decl.full_print(header_len, 0, cx),
- notable_traits = notable_traits.unwrap_or_default(),
- );
- });
+ wrap_item(w, |w| {
+ render_attributes_in_pre(w, it, "");
+ w.reserve(header_len);
+ write!(
+ w,
+ "{vis}{constness}{asyncness}{unsafety}{abi}fn \
+ {name}{generics}{decl}{notable_traits}{where_clause}",
+ vis = visibility,
+ constness = constness,
+ asyncness = asyncness,
+ unsafety = unsafety,
+ abi = abi,
+ name = name,
+ generics = f.generics.print(cx),
+ where_clause = print_where_clause(&f.generics, cx, 0, Ending::Newline),
+ decl = f.decl.full_print(header_len, 0, cx),
+ notable_traits = notable_traits.unwrap_or_default(),
+ );
});
document(w, cx, it, None, HeadingOffset::H2);
}
let must_implement_one_of_functions = tcx.trait_def(t.def_id).must_implement_one_of.clone();
// Output the trait definition
- wrap_into_item_decl(w, |w| {
- wrap_item(w, |w| {
- render_attributes_in_pre(w, it, "");
- write!(
- w,
- "{}{}{}trait {}{}{}",
- visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
- t.unsafety(tcx).print_with_space(),
- if t.is_auto(tcx) { "auto " } else { "" },
- it.name.unwrap(),
- t.generics.print(cx),
- bounds
- );
+ wrap_item(w, |w| {
+ render_attributes_in_pre(w, it, "");
+ write!(
+ w,
+ "{}{}{}trait {}{}{}",
+ visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
+ t.unsafety(tcx).print_with_space(),
+ if t.is_auto(tcx) { "auto " } else { "" },
+ it.name.unwrap(),
+ t.generics.print(cx),
+ bounds
+ );
- if !t.generics.where_predicates.is_empty() {
- write!(w, "{}", print_where_clause(&t.generics, cx, 0, Ending::Newline));
- } else {
- w.write_str(" ");
- }
+ if !t.generics.where_predicates.is_empty() {
+ write!(w, "{}", print_where_clause(&t.generics, cx, 0, Ending::Newline));
+ } else {
+ w.write_str(" ");
+ }
- if t.items.is_empty() {
- w.write_str("{ }");
- } else {
- // FIXME: we should be using a derived_id for the Anchors here
- w.write_str("{\n");
- let mut toggle = false;
-
- // If there are too many associated types, hide _everything_
- if should_hide_fields(count_types) {
- toggle = true;
- toggle_open(
- w,
- format_args!(
- "{} associated items",
- count_types + count_consts + count_methods
- ),
- );
- }
- for types in [&required_types, &provided_types] {
- for t in types {
- render_assoc_item(
- w,
- t,
- AssocItemLink::Anchor(None),
- ItemType::Trait,
- cx,
- RenderMode::Normal,
- );
- w.write_str(";\n");
- }
- }
- // If there are too many associated constants, hide everything after them
- // We also do this if the types + consts is large because otherwise we could
- // render a bunch of types and _then_ a bunch of consts just because both were
- // _just_ under the limit
- if !toggle && should_hide_fields(count_types + count_consts) {
- toggle = true;
- toggle_open(
- w,
- format_args!(
- "{} associated constant{} and {} method{}",
- count_consts,
- pluralize(count_consts),
- count_methods,
- pluralize(count_methods),
- ),
- );
- }
- if count_types != 0 && (count_consts != 0 || count_methods != 0) {
- w.write_str("\n");
- }
- for consts in [&required_consts, &provided_consts] {
- for c in consts {
- render_assoc_item(
- w,
- c,
- AssocItemLink::Anchor(None),
- ItemType::Trait,
- cx,
- RenderMode::Normal,
- );
- w.write_str(";\n");
- }
- }
- if !toggle && should_hide_fields(count_methods) {
- toggle = true;
- toggle_open(w, format_args!("{} methods", count_methods));
- }
- if count_consts != 0 && count_methods != 0 {
- w.write_str("\n");
- }
- for (pos, m) in required_methods.iter().enumerate() {
+ if t.items.is_empty() {
+ w.write_str("{ }");
+ } else {
+ // FIXME: we should be using a derived_id for the Anchors here
+ w.write_str("{\n");
+ let mut toggle = false;
+
+ // If there are too many associated types, hide _everything_
+ if should_hide_fields(count_types) {
+ toggle = true;
+ toggle_open(
+ w,
+ format_args!("{} associated items", count_types + count_consts + count_methods),
+ );
+ }
+ for types in [&required_types, &provided_types] {
+ for t in types {
render_assoc_item(
w,
- m,
+ t,
AssocItemLink::Anchor(None),
ItemType::Trait,
cx,
RenderMode::Normal,
);
w.write_str(";\n");
-
- if pos < required_methods.len() - 1 {
- w.write_str("<span class=\"item-spacer\"></span>");
- }
}
- if !required_methods.is_empty() && !provided_methods.is_empty() {
- w.write_str("\n");
- }
- for (pos, m) in provided_methods.iter().enumerate() {
+ }
+ // If there are too many associated constants, hide everything after them
+ // We also do this if the types + consts is large because otherwise we could
+ // render a bunch of types and _then_ a bunch of consts just because both were
+ // _just_ under the limit
+ if !toggle && should_hide_fields(count_types + count_consts) {
+ toggle = true;
+ toggle_open(
+ w,
+ format_args!(
+ "{} associated constant{} and {} method{}",
+ count_consts,
+ pluralize(count_consts),
+ count_methods,
+ pluralize(count_methods),
+ ),
+ );
+ }
+ if count_types != 0 && (count_consts != 0 || count_methods != 0) {
+ w.write_str("\n");
+ }
+ for consts in [&required_consts, &provided_consts] {
+ for c in consts {
render_assoc_item(
w,
- m,
+ c,
AssocItemLink::Anchor(None),
ItemType::Trait,
cx,
RenderMode::Normal,
);
- match *m.kind {
- clean::MethodItem(ref inner, _)
- if !inner.generics.where_predicates.is_empty() =>
- {
- w.write_str(",\n { ... }\n");
- }
- _ => {
- w.write_str(" { ... }\n");
- }
- }
+ w.write_str(";\n");
+ }
+ }
+ if !toggle && should_hide_fields(count_methods) {
+ toggle = true;
+ toggle_open(w, format_args!("{} methods", count_methods));
+ }
+ if count_consts != 0 && count_methods != 0 {
+ w.write_str("\n");
+ }
- if pos < provided_methods.len() - 1 {
- w.write_str("<span class=\"item-spacer\"></span>");
- }
+ if !required_methods.is_empty() {
+ write!(w, " // Required method{}\n", pluralize(required_methods.len()));
+ }
+ for (pos, m) in required_methods.iter().enumerate() {
+ render_assoc_item(
+ w,
+ m,
+ AssocItemLink::Anchor(None),
+ ItemType::Trait,
+ cx,
+ RenderMode::Normal,
+ );
+ w.write_str(";\n");
+
+ if pos < required_methods.len() - 1 {
+ w.write_str("<span class=\"item-spacer\"></span>");
}
- if toggle {
- toggle_close(w);
+ }
+ if !required_methods.is_empty() && !provided_methods.is_empty() {
+ w.write_str("\n");
+ }
+
+ if !provided_methods.is_empty() {
+ write!(w, " // Provided method{}\n", pluralize(provided_methods.len()));
+ }
+ for (pos, m) in provided_methods.iter().enumerate() {
+ render_assoc_item(
+ w,
+ m,
+ AssocItemLink::Anchor(None),
+ ItemType::Trait,
+ cx,
+ RenderMode::Normal,
+ );
+
+ w.write_str(" { ... }\n");
+
+ if pos < provided_methods.len() - 1 {
+ w.write_str("<span class=\"item-spacer\"></span>");
}
- w.write_str("}");
}
- });
+ if toggle {
+ toggle_close(w);
+ }
+ w.write_str("}");
+ }
});
// Trait documentation
}
fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TraitAlias) {
- wrap_into_item_decl(w, |w| {
- wrap_item(w, |w| {
- render_attributes_in_pre(w, it, "");
- write!(
- w,
- "trait {}{}{} = {};",
- it.name.unwrap(),
- t.generics.print(cx),
- print_where_clause(&t.generics, cx, 0, Ending::Newline),
- bounds(&t.bounds, true, cx)
- );
- });
+ wrap_item(w, |w| {
+ render_attributes_in_pre(w, it, "");
+ write!(
+ w,
+ "trait {}{}{} = {};",
+ it.name.unwrap(),
+ t.generics.print(cx),
+ print_where_clause(&t.generics, cx, 0, Ending::Newline),
+ bounds(&t.bounds, true, cx)
+ );
});
document(w, cx, it, None, HeadingOffset::H2);
}
fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) {
- wrap_into_item_decl(w, |w| {
- wrap_item(w, |w| {
- render_attributes_in_pre(w, it, "");
- write!(
- w,
- "type {}{}{where_clause} = impl {bounds};",
- it.name.unwrap(),
- t.generics.print(cx),
- where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline),
- bounds = bounds(&t.bounds, false, cx),
- );
- });
+ wrap_item(w, |w| {
+ render_attributes_in_pre(w, it, "");
+ write!(
+ w,
+ "type {}{}{where_clause} = impl {bounds};",
+ it.name.unwrap(),
+ t.generics.print(cx),
+ where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline),
+ bounds = bounds(&t.bounds, false, cx),
+ );
});
document(w, cx, it, None, HeadingOffset::H2);
});
}
- wrap_into_item_decl(w, |w| write_content(w, cx, it, t));
+ write_content(w, cx, it, t);
document(w, cx, it, None, HeadingOffset::H2);
}
fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Union) {
- wrap_into_item_decl(w, |w| {
- wrap_item(w, |w| {
- render_attributes_in_pre(w, it, "");
- render_union(w, it, Some(&s.generics), &s.fields, "", cx);
- });
+ wrap_item(w, |w| {
+ render_attributes_in_pre(w, it, "");
+ render_union(w, it, Some(&s.generics), &s.fields, "", cx);
});
document(w, cx, it, None, HeadingOffset::H2);
fn print_tuple_struct_fields(w: &mut Buffer, cx: &Context<'_>, s: &[clean::Item]) {
for (i, ty) in s.iter().enumerate() {
if i > 0 {
- w.write_str(", ");
+ w.write_str(", ");
}
match *ty.kind {
clean::StrippedItem(box clean::StructFieldItem(_)) => w.write_str("_"),
fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::Enum) {
let tcx = cx.tcx();
let count_variants = e.variants().count();
- wrap_into_item_decl(w, |w| {
- wrap_item(w, |w| {
- render_attributes_in_pre(w, it, "");
- write!(
- w,
- "{}enum {}{}",
- visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
- it.name.unwrap(),
- e.generics.print(cx),
- );
- if !print_where_clause_and_check(w, &e.generics, cx) {
- // If there wasn't a `where` clause, we add a whitespace.
- w.write_str(" ");
- }
+ wrap_item(w, |w| {
+ render_attributes_in_pre(w, it, "");
+ write!(
+ w,
+ "{}enum {}{}",
+ visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
+ it.name.unwrap(),
+ e.generics.print(cx),
+ );
+ if !print_where_clause_and_check(w, &e.generics, cx) {
+ // If there wasn't a `where` clause, we add a whitespace.
+ w.write_str(" ");
+ }
- let variants_stripped = e.has_stripped_entries();
- if count_variants == 0 && !variants_stripped {
- w.write_str("{}");
- } else {
- w.write_str("{\n");
- let toggle = should_hide_fields(count_variants);
- if toggle {
- toggle_open(w, format_args!("{} variants", count_variants));
- }
- for v in e.variants() {
- w.write_str(" ");
- let name = v.name.unwrap();
- match *v.kind {
- // FIXME(#101337): Show discriminant
- clean::VariantItem(ref var) => match var.kind {
- clean::VariantKind::CLike => write!(w, "{}", name),
- clean::VariantKind::Tuple(ref s) => {
- write!(w, "{}(", name);
- print_tuple_struct_fields(w, cx, s);
- w.write_str(")");
- }
- clean::VariantKind::Struct(ref s) => {
- render_struct(w, v, None, None, &s.fields, " ", false, cx);
- }
- },
- _ => unreachable!(),
- }
- w.write_str(",\n");
+ let variants_stripped = e.has_stripped_entries();
+ if count_variants == 0 && !variants_stripped {
+ w.write_str("{}");
+ } else {
+ w.write_str("{\n");
+ let toggle = should_hide_fields(count_variants);
+ if toggle {
+ toggle_open(w, format_args!("{} variants", count_variants));
+ }
+ for v in e.variants() {
+ w.write_str(" ");
+ let name = v.name.unwrap();
+ match *v.kind {
+ // FIXME(#101337): Show discriminant
+ clean::VariantItem(ref var) => match var.kind {
+ clean::VariantKind::CLike => write!(w, "{}", name),
+ clean::VariantKind::Tuple(ref s) => {
+ write!(w, "{}(", name);
+ print_tuple_struct_fields(w, cx, s);
+ w.write_str(")");
+ }
+ clean::VariantKind::Struct(ref s) => {
+ render_struct(w, v, None, None, &s.fields, " ", false, cx);
+ }
+ },
+ _ => unreachable!(),
}
+ w.write_str(",\n");
+ }
- if variants_stripped {
- w.write_str(" // some variants omitted\n");
- }
- if toggle {
- toggle_close(w);
- }
- w.write_str("}");
+ if variants_stripped {
+ w.write_str(" // some variants omitted\n");
}
- });
+ if toggle {
+ toggle_close(w);
+ }
+ w.write_str("}");
+ }
});
document(w, cx, it, None, HeadingOffset::H2);
"<div class=\"sub-variant-field\">\
<span id=\"{id}\" class=\"small-section-header\">\
<a href=\"#{id}\" class=\"anchor field\">§</a>\
- <code>{f}: {t}</code>\
+ <code>{f}: {t}</code>\
</span>",
id = id,
f = field.name.unwrap(),
}
fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) {
- wrap_into_item_decl(w, |w| {
- highlight::render_macro_with_highlighting(&t.source, w);
- });
+ highlight::render_item_decl_with_highlighting(&t.source, w);
document(w, cx, it, None, HeadingOffset::H2)
}
fn item_proc_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, m: &clean::ProcMacro) {
- wrap_into_item_decl(w, |w| {
+ wrap_item(w, |w| {
let name = it.name.expect("proc-macros always have names");
match m.kind {
MacroKind::Bang => {
- wrap_item(w, |w| {
- write!(w, "{}!() {{ /* proc-macro */ }}", name);
- });
+ write!(w, "{}!() {{ /* proc-macro */ }}", name);
}
MacroKind::Attr => {
- wrap_item(w, |w| {
- write!(w, "#[{}]", name);
- });
+ write!(w, "#[{}]", name);
}
MacroKind::Derive => {
- wrap_item(w, |w| {
- write!(w, "#[derive({})]", name);
- if !m.helpers.is_empty() {
- w.push_str("\n{\n");
- w.push_str(" // Attributes available to this derive:\n");
- for attr in &m.helpers {
- writeln!(w, " #[{}]", attr);
- }
- w.push_str("}\n");
+ write!(w, "#[derive({})]", name);
+ if !m.helpers.is_empty() {
+ w.push_str("\n{\n");
+ w.push_str(" // Attributes available to this derive:\n");
+ for attr in &m.helpers {
+ writeln!(w, " #[{}]", attr);
}
- });
+ w.push_str("}\n");
+ }
}
}
});
}
fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &clean::Constant) {
- wrap_into_item_decl(w, |w| {
- wrap_item(w, |w| {
- let tcx = cx.tcx();
- render_attributes_in_code(w, it);
+ wrap_item(w, |w| {
+ let tcx = cx.tcx();
+ render_attributes_in_code(w, it);
- write!(
- w,
- "{vis}const {name}: {typ}",
- vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
- name = it.name.unwrap(),
- typ = c.type_.print(cx),
- );
+ write!(
+ w,
+ "{vis}const {name}: {typ}",
+ vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
+ name = it.name.unwrap(),
+ typ = c.type_.print(cx),
+ );
- // FIXME: The code below now prints
- // ` = _; // 100i32`
- // if the expression is
- // `50 + 50`
- // which looks just wrong.
- // Should we print
- // ` = 100i32;`
- // instead?
-
- let value = c.value(tcx);
- let is_literal = c.is_literal(tcx);
- let expr = c.expr(tcx);
- if value.is_some() || is_literal {
- write!(w, " = {expr};", expr = Escape(&expr));
- } else {
- w.write_str(";");
- }
+ // FIXME: The code below now prints
+ // ` = _; // 100i32`
+ // if the expression is
+ // `50 + 50`
+ // which looks just wrong.
+ // Should we print
+ // ` = 100i32;`
+ // instead?
+
+ let value = c.value(tcx);
+ let is_literal = c.is_literal(tcx);
+ let expr = c.expr(tcx);
+ if value.is_some() || is_literal {
+ write!(w, " = {expr};", expr = Escape(&expr));
+ } else {
+ w.write_str(";");
+ }
- if !is_literal {
- if let Some(value) = &value {
- let value_lowercase = value.to_lowercase();
- let expr_lowercase = expr.to_lowercase();
+ if !is_literal {
+ if let Some(value) = &value {
+ let value_lowercase = value.to_lowercase();
+ let expr_lowercase = expr.to_lowercase();
- if value_lowercase != expr_lowercase
- && value_lowercase.trim_end_matches("i32") != expr_lowercase
- {
- write!(w, " // {value}", value = Escape(value));
- }
+ if value_lowercase != expr_lowercase
+ && value_lowercase.trim_end_matches("i32") != expr_lowercase
+ {
+ write!(w, " // {value}", value = Escape(value));
}
}
- });
+ }
});
document(w, cx, it, None, HeadingOffset::H2)
}
fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) {
- wrap_into_item_decl(w, |w| {
- wrap_item(w, |w| {
- render_attributes_in_code(w, it);
- render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx);
- });
+ wrap_item(w, |w| {
+ render_attributes_in_code(w, it);
+ render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx);
});
document(w, cx, it, None, HeadingOffset::H2);
}
fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) {
- wrap_into_item_decl(w, |w| {
- wrap_item(w, |w| {
- render_attributes_in_code(w, it);
- write!(
- w,
- "{vis}static {mutability}{name}: {typ}",
- vis = visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
- mutability = s.mutability.print_with_space(),
- name = it.name.unwrap(),
- typ = s.type_.print(cx)
- );
- });
+ wrap_item(w, |w| {
+ render_attributes_in_code(w, it);
+ write!(
+ w,
+ "{vis}static {mutability}{name}: {typ}",
+ vis = visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
+ mutability = s.mutability.print_with_space(),
+ name = it.name.unwrap(),
+ typ = s.type_.print(cx)
+ );
});
document(w, cx, it, None, HeadingOffset::H2)
}
fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
- wrap_into_item_decl(w, |w| {
- wrap_item(w, |w| {
- w.write_str("extern {\n");
- render_attributes_in_code(w, it);
- write!(
- w,
- " {}type {};\n}}",
- visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
- it.name.unwrap(),
- );
- });
+ wrap_item(w, |w| {
+ w.write_str("extern {\n");
+ render_attributes_in_code(w, it);
+ write!(
+ w,
+ " {}type {};\n}}",
+ visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
+ it.name.unwrap(),
+ );
});
document(w, cx, it, None, HeadingOffset::H2);
bounds
}
-fn wrap_into_item_decl<F>(w: &mut Buffer, f: F)
-where
- F: FnOnce(&mut Buffer),
-{
- w.write_str("<div class=\"item-decl\">");
- f(w);
- w.write_str("</div>")
-}
-
fn wrap_item<F>(w: &mut Buffer, f: F)
where
F: FnOnce(&mut Buffer),
{
- w.write_str(r#"<pre class="rust"><code>"#);
+ w.write_str(r#"<pre class="rust item-decl"><code>"#);
f(w);
w.write_str("</code></pre>");
}
use serde::ser::SerializeSeq;
use serde::{Serialize, Serializer};
-use super::{collect_paths_for_type, ensure_trailing_slash, Context, BASIC_KEYWORDS};
+use super::{collect_paths_for_type, ensure_trailing_slash, Context};
use crate::clean::Crate;
use crate::config::{EmitType, RenderOptions};
use crate::docfs::PathError;
Ok((ret, krates))
}
- /// Read a file and return all lines that match the <code>"{crate}":{data},\</code> format,
+ /// Read a file and return all lines that match the <code>"{crate}":{data},\ </code> format,
/// and return a tuple `(Vec<DataString>, Vec<CrateNameString>)`.
///
/// This forms the payload of files that look like this:
root_path: "./",
static_root_path: shared.static_root_path.as_deref(),
description: "List of crates",
- keywords: BASIC_KEYWORDS,
resource_suffix: &shared.resource_suffix,
};
use crate::html::format::Buffer;
use crate::html::highlight;
use crate::html::layout;
-use crate::html::render::{Context, BASIC_KEYWORDS};
+use crate::html::render::Context;
use crate::visit::DocVisitor;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
root_path: &root_path,
static_root_path: shared.static_root_path.as_deref(),
description: &desc,
- keywords: BASIC_KEYWORDS,
resource_suffix: &shared.resource_suffix,
};
let v = layout::render(
+/* When static files are updated, their suffixes need to be updated.
+ 1. In the top directory run:
+ ./x.py doc --stage 1 library/core
+ 2. Find the directory containing files named with updated suffixes:
+ find build -path '*'/stage1-std/'*'/static.files
+ 3. Copy the filenames with updated suffixes from the directory.
+*/
+
/* See FiraSans-LICENSE.txt for the Fira Sans license. */
@font-face {
font-family: 'Fira Sans';
font-style: normal;
font-weight: 400;
src: local('Source Serif 4'),
- url("SourceSerif4-Regular-1f7d512b176f0f72.ttf.woff2") format("woff2");
+ url("SourceSerif4-Regular-46f98efaafac5295.ttf.woff2") format("woff2");
font-display: swap;
}
@font-face {
font-style: italic;
font-weight: 400;
src: local('Source Serif 4 Italic'),
- url("SourceSerif4-It-d034fe4ef9d0fa00.ttf.woff2") format("woff2");
+ url("SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2") format("woff2");
font-display: swap;
}
@font-face {
font-style: normal;
font-weight: 700;
src: local('Source Serif 4 Bold'),
- url("SourceSerif4-Bold-124a1ca42af929b6.ttf.woff2") format("woff2");
+ url("SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2") format("woff2");
font-display: swap;
}
font-weight: 600;
margin: 0;
padding: 0;
+ white-space: pre-wrap;
}
#crate-search,
padding: 14px;
line-height: 1.5; /* https://github.com/rust-lang/rust/issues/105906 */
}
-.item-decl pre {
+pre.item-decl {
overflow-x: auto;
}
/* This rule allows to have scrolling on the X axis. */
.fn .where,
.where.fmt-newline {
display: block;
+ white-space: pre-wrap;
font-size: 0.875rem;
}
background-repeat: no-repeat;
background-size: 20px;
background-position: calc(100% - 2px) 56%;
- /* image is black color */
- background-image: url("down-arrow-927217e04c7463ac.svg");
+ /* down arrow (image is black color) */
+ background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" \
+ width="128" height="128" viewBox="-30 -20 176 176"><path d="M111,40.5L64,87.499L17,40.5" \
+ fill="none" stroke="black" strike-linecap="square" stroke-miterlimit="10" stroke-width="12"/> \
+ </svg>');
/* changes the arrow image color */
filter: var(--crate-search-div-filter);
}
0 -1px 0 black;
}
-.item-left.unstable {
- opacity: 0.65;
-}
-
.since {
font-weight: normal;
font-size: initial;
.item-spacer {
width: 100%;
height: 12px;
+ display: block;
}
.out-of-band > span.since {
line-height: 1.5;
color: inherit;
}
+#search-tabs button:not(.selected) {
+ background-color: var(--search-tab-button-not-selected-background);
+ border-top-color: var(--search-tab-button-not-selected-border-top-color);
+}
+#search-tabs button:hover, #search-tabs button.selected {
+ background-color: var(--search-tab-button-selected-background);
+ border-top-color: var(--search-tab-button-selected-border-top-color);
+}
#search-tabs .count {
font-size: 1rem;
}
details.toggle > summary::before {
- background: url("toggle-plus-1092eb4930d581b0.svg") no-repeat top left;
+ /* toggle plus */
+ background: url('data:image/svg+xml,<svg width="17" height="17" \
+shape-rendering="crispEdges" stroke="black" fill="none" xmlns="http://www.w3.org/2000/svg"><path \
+d="M5 2.5H2.5v12H5m7-12h2.5v12H12M5 8.5h7M8.5 12V8.625v0V5"/></svg>') no-repeat top left;
content: "";
cursor: pointer;
width: 16px;
}
details.toggle[open] > summary::before {
- background: url("toggle-minus-31bbd6e4c77f5c96.svg") no-repeat top left;
+ /* toggle minus */
+ background: url('data:image/svg+xml,<svg width="17" height="17" \
+shape-rendering="crispEdges" stroke="black" fill="none" xmlns="http://www.w3.org/2000/svg"><path \
+d="M5 2.5H2.5v12H5m7-12h2.5v12H12M5 8.5h7"/></svg>') no-repeat top left;
}
details.toggle[open] > summary::after {
}
.setting-check {
- position: relative;
- width: 100%;
margin-right: 20px;
display: flex;
align-items: center;
--search-results-alias-color: #c5c5c5;
--search-results-grey-color: #999;
--search-tab-title-count-color: #888;
+ --search-tab-button-not-selected-border-top-color: none;
+ --search-tab-button-not-selected-background: transparent !important;
+ --search-tab-button-selected-border-top-color: none;
+ --search-tab-button-selected-background: #141920 !important;
--stab-background-color: #314559;
--stab-code-color: #e6e1cf;
--code-highlight-kw-color: #ff7733;
--scrape-example-code-wrapper-background-end: rgba(15, 20, 25, 0);
}
-h1, h2, h3, h4 {
- color: white;
-}
-h1 a {
+h1, h2, h3, h4,
+h1 a, .sidebar h2 a, .sidebar h3 a,
+#source-sidebar > .title {
color: #fff;
}
h4 {
.docblock code {
color: #ffb454;
}
-.code-header {
- color: #e6e1cf;
-}
-.docblock pre > code, pre > code {
- color: #e6e1cf;
-}
-.item-info code {
- color: #e6e1cf;
-}
.docblock a > code {
color: #39AFD7 !important;
}
-pre, .rustdoc.source .example-wrap {
+.code-header,
+.docblock pre > code,
+pre, pre > code,
+.item-info code,
+.rustdoc.source .example-wrap {
color: #e6e1cf;
}
.sidebar .current,
-.sidebar a:hover {
+.sidebar a:hover,
+#source-sidebar div.files > a:hover, details.dir-entry summary:hover,
+#source-sidebar div.files > a:focus, details.dir-entry summary:focus,
+#source-sidebar div.files > a.selected {
color: #ffb44c;
}
border-right: 1px solid #ffb44c;
}
-.search-results a:hover {
- color: #fff !important;
- background-color: #3c3c3c;
-}
-
+.search-results a:hover,
.search-results a:focus {
color: #fff !important;
background-color: #3c3c3c;
}
+
.search-results a {
color: #0096cf;
}
color: #c5c5c5;
}
-.sidebar h2 a,
-.sidebar h3 a {
- color: white;
-}
-
.result-name .primitive > i, .result-name .keyword > i {
color: #788797;
}
#search-tabs > button.selected {
- background-color: #141920 !important;
border-bottom: 1px solid #ffb44c !important;
border-top: none;
}
-
#search-tabs > button:not(.selected) {
- background-color: transparent !important;
border: none;
+ background-color: transparent !important;
}
-
#search-tabs > button:hover {
border-bottom: 1px solid rgba(242, 151, 24, 0.3);
}
-/* rules that this theme does not need to set, here to satisfy the rule checker */
-/* note that a lot of these are partially set in some way (meaning they are set
-individually rather than as a group) */
-/* FIXME: these rules should be at the bottom of the file but currently must be
-above the `@media (max-width: 700px)` rules due to a bug in the css checker */
-/* see https://github.com/rust-lang/rust/pull/71237#issuecomment-618170143 */
-#search-tabs > button:hover, #search-tabs > button.selected {}
-
#settings-menu > a img {
filter: invert(100);
}
-
-#source-sidebar > .title {
- color: #fff;
-}
-#source-sidebar div.files > a:hover, details.dir-entry summary:hover,
-#source-sidebar div.files > a:focus, details.dir-entry summary:focus,
-#source-sidebar div.files > a.selected {
- color: #ffb44c;
-}
--search-results-alias-color: #fff;
--search-results-grey-color: #ccc;
--search-tab-title-count-color: #888;
+ --search-tab-button-not-selected-border-top-color: #252525;
+ --search-tab-button-not-selected-background: #252525;
+ --search-tab-button-selected-border-top-color: #0089ff;
+ --search-tab-button-selected-background: #353535;
--stab-background-color: #314559;
--stab-code-color: #e6e1cf;
--code-highlight-kw-color: #ab8ac1;
--scrape-example-code-wrapper-background-start: rgba(53, 53, 53, 1);
--scrape-example-code-wrapper-background-end: rgba(53, 53, 53, 0);
}
-
-#search-tabs > button:not(.selected) {
- background-color: #252525;
- border-top-color: #252525;
-}
-
-#search-tabs > button:hover, #search-tabs > button.selected {
- border-top-color: #0089ff;
- background-color: #353535;
-}
--search-results-alias-color: #000;
--search-results-grey-color: #999;
--search-tab-title-count-color: #888;
+ --search-tab-button-not-selected-border-top-color: #e6e6e6;
+ --search-tab-button-not-selected-background: #e6e6e6;
+ --search-tab-button-selected-border-top-color: #0089ff;
+ --search-tab-button-selected-background: #ffffff;
--stab-background-color: #fff5d6;
--stab-code-color: #000;
--code-highlight-kw-color: #8959a8;
--scrape-example-code-wrapper-background-start: rgba(255, 255, 255, 1);
--scrape-example-code-wrapper-background-end: rgba(255, 255, 255, 0);
}
-
-#search-tabs > button:not(.selected) {
- background-color: #e6e6e6;
- border-top-color: #e6e6e6;
-}
-
-#search-tabs > button:hover, #search-tabs > button.selected {
- background-color: #ffffff;
- border-top-color: #0089ff;
-}
-Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries.
+Copyright 2014 - 2023 Adobe (http://www.adobe.com/), with Reserved Font Name ‘Source’. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
+++ /dev/null
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Layer_1" width="128" height="128" enable-background="new 0 0 128 128" version="1.1" viewBox="-30 -20 176 176" xml:space="preserve"><g><line x1="111" x2="64" y1="40.5" y2="87.499" fill="none" stroke="#000000" stroke-linecap="square" stroke-miterlimit="10" stroke-width="12"/><line x1="64" x2="17" y1="87.499" y2="40.5" fill="none" stroke="#000000" stroke-linecap="square" stroke-miterlimit="10" stroke-width="12"/></g></svg>
\ No newline at end of file
+++ /dev/null
-<svg width="17" height="17" shape-rendering="crispEdges" stroke="#000" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5 2.5H2.5v12H5m7-12h2.5v12H12M5 8.5h7"/></svg>
\ No newline at end of file
+++ /dev/null
-<svg width="17" height="17" shape-rendering="crispEdges" stroke="#000" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5 2.5H2.5v12H5m7-12h2.5v12H12M5 8.5h7M8.5 12V8.625v0V5"/></svg>
\ No newline at end of file
return window.history && typeof window.history.pushState === "function";
}
-// eslint-disable-next-line no-unused-vars
function loadCss(cssUrl) {
const link = document.createElement("link");
link.href = cssUrl;
}
function initSearch(rawSearchIndex) {
- const MAX_LEV_DISTANCE = 3;
const MAX_RESULTS = 200;
const NO_TYPE_FILTER = -1;
/**
* @param {QueryElement} elem - The element from the parsed query.
* @param {integer} defaultLev - This is the value to return in case there are no generics.
*
- * @return {integer} - Returns the best match (if any) or `MAX_LEV_DISTANCE + 1`.
+ * @return {integer} - Returns the best match (if any) or `maxLevDistance + 1`.
*/
- function checkGenerics(row, elem, defaultLev) {
+ function checkGenerics(row, elem, defaultLev, maxLevDistance) {
if (row.generics.length === 0) {
- return elem.generics.length === 0 ? defaultLev : MAX_LEV_DISTANCE + 1;
+ return elem.generics.length === 0 ? defaultLev : maxLevDistance + 1;
} else if (row.generics.length > 0 && row.generics[0].name === null) {
- return checkGenerics(row.generics[0], elem, defaultLev);
+ return checkGenerics(row.generics[0], elem, defaultLev, maxLevDistance);
}
// The names match, but we need to be sure that all generics kinda
// match as well.
elem_name = entry.name;
if (elem_name === "") {
// Pure generic, needs to check into it.
- if (checkGenerics(entry, elem, MAX_LEV_DISTANCE + 1) !== 0) {
- return MAX_LEV_DISTANCE + 1;
+ if (checkGenerics(entry, elem, maxLevDistance + 1, maxLevDistance) !== 0) {
+ return maxLevDistance + 1;
}
continue;
}
}
}
if (match === null) {
- return MAX_LEV_DISTANCE + 1;
+ return maxLevDistance + 1;
}
elems[match] -= 1;
if (elems[match] === 0) {
}
return 0;
}
- return MAX_LEV_DISTANCE + 1;
+ return maxLevDistance + 1;
}
/**
*
* @return {integer} - Returns a Levenshtein distance to the best match.
*/
- function checkIfInGenerics(row, elem) {
- let lev = MAX_LEV_DISTANCE + 1;
+ function checkIfInGenerics(row, elem, maxLevDistance) {
+ let lev = maxLevDistance + 1;
for (const entry of row.generics) {
- lev = Math.min(checkType(entry, elem, true), lev);
+ lev = Math.min(checkType(entry, elem, true, maxLevDistance), lev);
if (lev === 0) {
break;
}
* @param {boolean} literalSearch
*
* @return {integer} - Returns a Levenshtein distance to the best match. If there is
- * no match, returns `MAX_LEV_DISTANCE + 1`.
+ * no match, returns `maxLevDistance + 1`.
*/
- function checkType(row, elem, literalSearch) {
+ function checkType(row, elem, literalSearch, maxLevDistance) {
if (row.name === null) {
// This is a pure "generic" search, no need to run other checks.
if (row.generics.length > 0) {
- return checkIfInGenerics(row, elem);
+ return checkIfInGenerics(row, elem, maxLevDistance);
}
- return MAX_LEV_DISTANCE + 1;
+ return maxLevDistance + 1;
}
let lev = levenshtein(row.name, elem.name);
return 0;
}
}
- return MAX_LEV_DISTANCE + 1;
+ return maxLevDistance + 1;
} else if (elem.generics.length > 0) {
- return checkGenerics(row, elem, MAX_LEV_DISTANCE + 1);
+ return checkGenerics(row, elem, maxLevDistance + 1, maxLevDistance);
}
return 0;
} else if (row.generics.length > 0) {
}
// The name didn't match so we now check if the type we're looking for is inside
// the generics!
- lev = checkIfInGenerics(row, elem);
- // Now whatever happens, the returned distance is "less good" so we should mark
- // it as such, and so we add 0.5 to the distance to make it "less good".
- return lev + 0.5;
- } else if (lev > MAX_LEV_DISTANCE) {
+ lev = Math.min(lev, checkIfInGenerics(row, elem, maxLevDistance));
+ return lev;
+ } else if (lev > maxLevDistance) {
// So our item's name doesn't match at all and has generics.
//
// Maybe it's present in a sub generic? For example "f<A<B<C>>>()", if we're
// looking for "B<C>", we'll need to go down.
- return checkIfInGenerics(row, elem);
+ return checkIfInGenerics(row, elem, maxLevDistance);
} else {
// At this point, the name kinda match and we have generics to check, so
// let's go!
- const tmp_lev = checkGenerics(row, elem, lev);
- if (tmp_lev > MAX_LEV_DISTANCE) {
- return MAX_LEV_DISTANCE + 1;
+ const tmp_lev = checkGenerics(row, elem, lev, maxLevDistance);
+ if (tmp_lev > maxLevDistance) {
+ return maxLevDistance + 1;
}
// We compute the median value of both checks and return it.
return (tmp_lev + lev) / 2;
} else if (elem.generics.length > 0) {
// In this case, we were expecting generics but there isn't so we simply reject this
// one.
- return MAX_LEV_DISTANCE + 1;
+ return maxLevDistance + 1;
}
// No generics on our query or on the target type so we can return without doing
// anything else.
* @param {integer} typeFilter
*
* @return {integer} - Returns a Levenshtein distance to the best match. If there is no
- * match, returns `MAX_LEV_DISTANCE + 1`.
+ * match, returns `maxLevDistance + 1`.
*/
- function findArg(row, elem, typeFilter) {
- let lev = MAX_LEV_DISTANCE + 1;
+ function findArg(row, elem, typeFilter, maxLevDistance) {
+ let lev = maxLevDistance + 1;
if (row && row.type && row.type.inputs && row.type.inputs.length > 0) {
for (const input of row.type.inputs) {
if (!typePassesFilter(typeFilter, input.ty)) {
continue;
}
- lev = Math.min(lev, checkType(input, elem, parsedQuery.literalSearch));
+ lev = Math.min(
+ lev,
+ checkType(input, elem, parsedQuery.literalSearch, maxLevDistance)
+ );
if (lev === 0) {
return 0;
}
}
}
- return parsedQuery.literalSearch ? MAX_LEV_DISTANCE + 1 : lev;
+ return parsedQuery.literalSearch ? maxLevDistance + 1 : lev;
}
/**
* @param {integer} typeFilter
*
* @return {integer} - Returns a Levenshtein distance to the best match. If there is no
- * match, returns `MAX_LEV_DISTANCE + 1`.
+ * match, returns `maxLevDistance + 1`.
*/
- function checkReturned(row, elem, typeFilter) {
- let lev = MAX_LEV_DISTANCE + 1;
+ function checkReturned(row, elem, typeFilter, maxLevDistance) {
+ let lev = maxLevDistance + 1;
if (row && row.type && row.type.output.length > 0) {
const ret = row.type.output;
if (!typePassesFilter(typeFilter, ret_ty.ty)) {
continue;
}
- lev = Math.min(lev, checkType(ret_ty, elem, parsedQuery.literalSearch));
+ lev = Math.min(
+ lev,
+ checkType(ret_ty, elem, parsedQuery.literalSearch, maxLevDistance)
+ );
if (lev === 0) {
return 0;
}
}
}
- return parsedQuery.literalSearch ? MAX_LEV_DISTANCE + 1 : lev;
+ return parsedQuery.literalSearch ? maxLevDistance + 1 : lev;
}
- function checkPath(contains, ty) {
+ function checkPath(contains, ty, maxLevDistance) {
if (contains.length === 0) {
return 0;
}
- let ret_lev = MAX_LEV_DISTANCE + 1;
+ let ret_lev = maxLevDistance + 1;
const path = ty.path.split("::");
if (ty.parent && ty.parent.name) {
const length = path.length;
const clength = contains.length;
if (clength > length) {
- return MAX_LEV_DISTANCE + 1;
+ return maxLevDistance + 1;
}
for (let i = 0; i < length; ++i) {
if (i + clength > length) {
let aborted = false;
for (let x = 0; x < clength; ++x) {
const lev = levenshtein(path[i + x], contains[x]);
- if (lev > MAX_LEV_DISTANCE) {
+ if (lev > maxLevDistance) {
aborted = true;
break;
}
* following condition:
*
* * If it is a "literal search" (`parsedQuery.literalSearch`), then `lev` must be 0.
- * * If it is not a "literal search", `lev` must be <= `MAX_LEV_DISTANCE`.
+ * * If it is not a "literal search", `lev` must be <= `maxLevDistance`.
*
* The `results` map contains information which will be used to sort the search results:
*
* @param {integer} lev
* @param {integer} path_lev
*/
- function addIntoResults(results, fullId, id, index, lev, path_lev) {
- const inBounds = lev <= MAX_LEV_DISTANCE || index !== -1;
+ function addIntoResults(results, fullId, id, index, lev, path_lev, maxLevDistance) {
+ const inBounds = lev <= maxLevDistance || index !== -1;
if (lev === 0 || (!parsedQuery.literalSearch && inBounds)) {
if (results[fullId] !== undefined) {
const result = results[fullId];
elem,
results_others,
results_in_args,
- results_returned
+ results_returned,
+ maxLevDistance
) {
if (!row || (filterCrates !== null && row.crate !== filterCrates)) {
return;
const fullId = row.id;
const searchWord = searchWords[pos];
- const in_args = findArg(row, elem, parsedQuery.typeFilter);
- const returned = checkReturned(row, elem, parsedQuery.typeFilter);
+ const in_args = findArg(row, elem, parsedQuery.typeFilter, maxLevDistance);
+ const returned = checkReturned(row, elem, parsedQuery.typeFilter, maxLevDistance);
// path_lev is 0 because no parent path information is currently stored
// in the search index
- addIntoResults(results_in_args, fullId, pos, -1, in_args, 0);
- addIntoResults(results_returned, fullId, pos, -1, returned, 0);
+ addIntoResults(results_in_args, fullId, pos, -1, in_args, 0, maxLevDistance);
+ addIntoResults(results_returned, fullId, pos, -1, returned, 0, maxLevDistance);
if (!typePassesFilter(parsedQuery.typeFilter, row.ty)) {
return;
// No need to check anything else if it's a "pure" generics search.
if (elem.name.length === 0) {
if (row.type !== null) {
- lev = checkGenerics(row.type, elem, MAX_LEV_DISTANCE + 1);
+ lev = checkGenerics(row.type, elem, maxLevDistance + 1, maxLevDistance);
// path_lev is 0 because we know it's empty
- addIntoResults(results_others, fullId, pos, index, lev, 0);
+ addIntoResults(results_others, fullId, pos, index, lev, 0, maxLevDistance);
}
return;
}
if (elem.fullPath.length > 1) {
- path_lev = checkPath(elem.pathWithoutLast, row);
- if (path_lev > MAX_LEV_DISTANCE) {
+ path_lev = checkPath(elem.pathWithoutLast, row, maxLevDistance);
+ if (path_lev > maxLevDistance) {
return;
}
}
lev = levenshtein(searchWord, elem.pathLast);
- if (index === -1 && lev + path_lev > MAX_LEV_DISTANCE) {
+ if (index === -1 && lev + path_lev > maxLevDistance) {
return;
}
- addIntoResults(results_others, fullId, pos, index, lev, path_lev);
+ addIntoResults(results_others, fullId, pos, index, lev, path_lev, maxLevDistance);
}
/**
* @param {integer} pos - Position in the `searchIndex`.
* @param {Object} results
*/
- function handleArgs(row, pos, results) {
+ function handleArgs(row, pos, results, maxLevDistance) {
if (!row || (filterCrates !== null && row.crate !== filterCrates)) {
return;
}
function checkArgs(elems, callback) {
for (const elem of elems) {
// There is more than one parameter to the query so all checks should be "exact"
- const lev = callback(row, elem, NO_TYPE_FILTER);
+ const lev = callback(row, elem, NO_TYPE_FILTER, maxLevDistance);
if (lev <= 1) {
nbLev += 1;
totalLev += lev;
return;
}
const lev = Math.round(totalLev / nbLev);
- addIntoResults(results, row.id, pos, 0, lev, 0);
+ addIntoResults(results, row.id, pos, 0, lev, 0, maxLevDistance);
}
function innerRunQuery() {
let elem, i, nSearchWords, in_returned, row;
+ let queryLen = 0;
+ for (const elem of parsedQuery.elems) {
+ queryLen += elem.name.length;
+ }
+ for (const elem of parsedQuery.returned) {
+ queryLen += elem.name.length;
+ }
+ const maxLevDistance = Math.floor(queryLen / 3);
+
if (parsedQuery.foundElems === 1) {
if (parsedQuery.elems.length === 1) {
elem = parsedQuery.elems[0];
elem,
results_others,
results_in_args,
- results_returned
+ results_returned,
+ maxLevDistance
);
}
} else if (parsedQuery.returned.length === 1) {
elem = parsedQuery.returned[0];
for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
row = searchIndex[i];
- in_returned = checkReturned(row, elem, parsedQuery.typeFilter);
- addIntoResults(results_others, row.id, i, -1, in_returned);
+ in_returned = checkReturned(
+ row,
+ elem,
+ parsedQuery.typeFilter,
+ maxLevDistance
+ );
+ addIntoResults(results_others, row.id, i, -1, in_returned, maxLevDistance);
}
}
} else if (parsedQuery.foundElems > 0) {
for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
- handleArgs(searchIndex[i], i, results_others);
+ handleArgs(searchIndex[i], i, results_others, maxLevDistance);
}
}
}
*
* @return {boolean} - Whether the result is valid or not
*/
- function validateResult(name, path, keys, parent) {
+ function validateResult(name, path, keys, parent, maxLevDistance) {
if (!keys || !keys.length) {
return true;
}
(parent !== undefined && parent.name !== undefined &&
parent.name.toLowerCase().indexOf(key) > -1) ||
// lastly check to see if the name was a levenshtein match
- levenshtein(name, key) <= MAX_LEV_DISTANCE)) {
+ levenshtein(name, key) <= maxLevDistance)) {
return false;
}
}
// Local js definitions:
-/* global getSettingValue, getVirtualKey, updateLocalStorage, updateSystemTheme */
+/* global getSettingValue, getVirtualKey, updateLocalStorage, updateTheme */
/* global addClass, removeClass, onEach, onEachLazy, blurHandler, elemIsInParent */
/* global MAIN_ID, getVar, getSettingsButton */
case "theme":
case "preferred-dark-theme":
case "preferred-light-theme":
- updateSystemTheme();
+ updateTheme();
updateLightAndDark();
break;
case "line-numbers":
return elem && elem.classList && elem.classList.contains(className);
}
-// eslint-disable-next-line no-unused-vars
function addClass(elem, className) {
if (!elem || !elem.classList) {
return;
}
}
-// This function is called from "main.js".
-// eslint-disable-next-line no-unused-vars
-function useSystemTheme(value) {
- if (value === undefined) {
- value = true;
- }
-
- updateLocalStorage("use-system-theme", value);
-
- // update the toggle if we're on the settings page
- const toggle = document.getElementById("use-system-theme");
- if (toggle && toggle instanceof HTMLInputElement) {
- toggle.checked = value;
- }
-}
-
-const updateSystemTheme = (function() {
- if (!window.matchMedia) {
- // fallback to the CSS computed value
- return () => {
- const cssTheme = getComputedStyle(document.documentElement)
- .getPropertyValue("content");
-
- switchTheme(
- window.currentTheme,
- window.mainTheme,
- JSON.parse(cssTheme) || "light",
- true
- );
+const updateTheme = (function() {
+ /**
+ * Update the current theme to match whatever the current combination of
+ * * the preference for using the system theme
+ * (if this is the case, the value of preferred-light-theme, if the
+ * system theme is light, otherwise if dark, the value of
+ * preferred-dark-theme.)
+ * * the preferred theme
+ * … dictates that it should be.
+ */
+ function updateTheme() {
+ const use = (theme, saveTheme) => {
+ switchTheme(window.currentTheme, window.mainTheme, theme, saveTheme);
};
- }
-
- // only listen to (prefers-color-scheme: dark) because light is the default
- const mql = window.matchMedia("(prefers-color-scheme: dark)");
- function handlePreferenceChange(mql) {
- const use = theme => {
- switchTheme(window.currentTheme, window.mainTheme, theme, true);
- };
// maybe the user has disabled the setting in the meantime!
if (getSettingValue("use-system-theme") !== "false") {
const lightTheme = getSettingValue("preferred-light-theme") || "light";
const darkTheme = getSettingValue("preferred-dark-theme") || "dark";
- if (mql.matches) {
- use(darkTheme);
+ if (isDarkMode()) {
+ use(darkTheme, true);
} else {
// prefers a light theme, or has no preference
- use(lightTheme);
+ use(lightTheme, true);
}
// note: we save the theme so that it doesn't suddenly change when
// the user disables "use-system-theme" and reloads the page or
// navigates to another page
} else {
- use(getSettingValue("theme"));
+ use(getSettingValue("theme"), false);
}
}
- mql.addListener(handlePreferenceChange);
+ // This is always updated below to a function () => bool.
+ let isDarkMode;
- return () => {
- handlePreferenceChange(mql);
- };
-})();
+ // Determine the function for isDarkMode, and if we have
+ // `window.matchMedia`, set up an event listener on the preferred color
+ // scheme.
+ //
+ // Otherwise, fall back to the prefers-color-scheme value CSS captured in
+ // the "content" property.
+ if (window.matchMedia) {
+ // only listen to (prefers-color-scheme: dark) because light is the default
+ const mql = window.matchMedia("(prefers-color-scheme: dark)");
-function switchToSavedTheme() {
- switchTheme(
- window.currentTheme,
- window.mainTheme,
- getSettingValue("theme") || "light",
- false
- );
-}
+ isDarkMode = () => mql.matches;
+
+ if (mql.addEventListener) {
+ mql.addEventListener("change", updateTheme);
+ } else {
+ // This is deprecated, see:
+ // https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList/addListener
+ mql.addListener(updateTheme);
+ }
+ } else {
+ // fallback to the CSS computed value
+ const cssContent = getComputedStyle(document.documentElement)
+ .getPropertyValue("content");
+ // (Note: the double-quotes come from that this is a CSS value, which
+ // might be a length, string, etc.)
+ const cssColorScheme = cssContent || "\"light\"";
+ isDarkMode = () => (cssColorScheme === "\"dark\"");
+ }
+
+ return updateTheme;
+})();
if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) {
// update the preferred dark theme if the user is already using a dark theme
&& darkThemes.indexOf(localStoredTheme) >= 0) {
updateLocalStorage("preferred-dark-theme", localStoredTheme);
}
-
- // call the function to initialize the theme at least once!
- updateSystemTheme();
-} else {
- switchToSavedTheme();
}
+updateTheme();
+
if (getSettingValue("source-sidebar-show") === "true") {
// At this point in page load, `document.body` is not available yet.
// Set a class on the `<html>` element instead.
// specifically when talking to a remote website with no caching.
window.addEventListener("pageshow", ev => {
if (ev.persisted) {
- setTimeout(switchToSavedTheme, 0);
+ setTimeout(updateTheme, 0);
}
});
scrape_examples_js => "static/js/scrape-examples.js",
wheel_svg => "static/images/wheel.svg",
clipboard_svg => "static/images/clipboard.svg",
- down_arrow_svg => "static/images/down-arrow.svg",
- toggle_minus_png => "static/images/toggle-minus.svg",
- toggle_plus_png => "static/images/toggle-plus.svg",
copyright => "static/COPYRIGHT.txt",
license_apache => "static/LICENSE-APACHE.txt",
license_mit => "static/LICENSE-MIT.txt",
<meta name="viewport" content="width=device-width, initial-scale=1.0"> {#- -#}
<meta name="generator" content="rustdoc"> {#- -#}
<meta name="description" content="{{page.description}}"> {#- -#}
- <meta name="keywords" content="{{page.keywords}}"> {#- -#}
<title>{{page.title}}</title> {#- -#}
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_serif_4_regular}}"> {#- -#}
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.fira_sans_regular}}"> {#- -#}
let mut ids = IdMap::new();
let error_codes = ErrorCodes::from(options.unstable_features.is_nightly_build());
let text = if !options.markdown_no_toc {
- MarkdownWithToc(text, &mut ids, error_codes, edition, &playground).into_string()
+ MarkdownWithToc {
+ content: text,
+ ids: &mut ids,
+ error_codes,
+ edition,
+ playground: &playground,
+ }
+ .into_string()
} else {
Markdown {
content: text,
//! Strip all doc(hidden) items from the output.
+
+use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::sym;
use std::mem;
use crate::core::DocContext;
use crate::fold::{strip_item, DocFolder};
use crate::passes::{ImplStripper, Pass};
+use crate::visit_ast::inherits_doc_hidden;
pub(crate) const STRIP_HIDDEN: Pass = Pass {
name: "strip-hidden",
// strip all #[doc(hidden)] items
let krate = {
- let mut stripper = Stripper { retained: &mut retained, update_retained: true };
+ let mut stripper = Stripper {
+ retained: &mut retained,
+ update_retained: true,
+ tcx: cx.tcx,
+ is_in_hidden_item: false,
+ };
stripper.fold_crate(krate)
};
stripper.fold_crate(krate)
}
-struct Stripper<'a> {
+struct Stripper<'a, 'tcx> {
retained: &'a mut ItemIdSet,
update_retained: bool,
+ tcx: TyCtxt<'tcx>,
+ is_in_hidden_item: bool,
+}
+
+impl<'a, 'tcx> Stripper<'a, 'tcx> {
+ fn set_is_in_hidden_item_and_fold(&mut self, is_in_hidden_item: bool, i: Item) -> Item {
+ let prev = self.is_in_hidden_item;
+ self.is_in_hidden_item |= is_in_hidden_item;
+ let ret = self.fold_item_recur(i);
+ self.is_in_hidden_item = prev;
+ ret
+ }
+
+ /// In case `i` is a non-hidden impl block, then we special-case it by changing the value
+ /// of `is_in_hidden_item` to `true` because the impl children inherit its visibility.
+ fn recurse_in_impl(&mut self, i: Item) -> Item {
+ let prev = mem::replace(&mut self.is_in_hidden_item, false);
+ let ret = self.fold_item_recur(i);
+ self.is_in_hidden_item = prev;
+ ret
+ }
}
-impl<'a> DocFolder for Stripper<'a> {
+impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
fn fold_item(&mut self, i: Item) -> Option<Item> {
- if i.attrs.lists(sym::doc).has_word(sym::hidden) {
- debug!("strip_hidden: stripping {:?} {:?}", i.type_(), i.name);
- // Use a dedicated hidden item for fields, variants, and modules.
- // We need to keep private fields and variants, so that the docs
- // can show a placeholder "// some variants omitted". We need to keep
- // private modules, because they can contain impl blocks, and impl
- // block privacy is inherited from the type and trait, not from the
- // module it's defined in. Both of these are marked "stripped," and
- // not included in the final docs, but since they still have an effect
- // on the final doc, cannot be completely removed from the Clean IR.
- match *i.kind {
- clean::StructFieldItem(..) | clean::ModuleItem(..) | clean::VariantItem(..) => {
- // We need to recurse into stripped modules to
- // strip things like impl methods but when doing so
- // we must not add any items to the `retained` set.
- let old = mem::replace(&mut self.update_retained, false);
- let ret = strip_item(self.fold_item_recur(i));
- self.update_retained = old;
- return Some(ret);
- }
- _ => return None,
+ let has_doc_hidden = i.attrs.lists(sym::doc).has_word(sym::hidden);
+ let is_impl = matches!(*i.kind, clean::ImplItem(..));
+ let mut is_hidden = has_doc_hidden;
+ if !is_impl {
+ is_hidden = self.is_in_hidden_item || has_doc_hidden;
+ if !is_hidden && i.inline_stmt_id.is_none() {
+ // We don't need to check if it's coming from a reexport since the reexport itself was
+ // already checked.
+ is_hidden = i
+ .item_id
+ .as_def_id()
+ .and_then(|def_id| def_id.as_local())
+ .map(|def_id| inherits_doc_hidden(self.tcx, def_id))
+ .unwrap_or(false);
}
- } else {
+ }
+ if !is_hidden {
if self.update_retained {
self.retained.insert(i.item_id);
}
+ return Some(if is_impl {
+ self.recurse_in_impl(i)
+ } else {
+ self.set_is_in_hidden_item_and_fold(false, i)
+ });
+ }
+ debug!("strip_hidden: stripping {:?} {:?}", i.type_(), i.name);
+ // Use a dedicated hidden item for fields, variants, and modules.
+ // We need to keep private fields and variants, so that the docs
+ // can show a placeholder "// some variants omitted". We need to keep
+ // private modules, because they can contain impl blocks, and impl
+ // block privacy is inherited from the type and trait, not from the
+ // module it's defined in. Both of these are marked "stripped," and
+ // not included in the final docs, but since they still have an effect
+ // on the final doc, cannot be completely removed from the Clean IR.
+ match *i.kind {
+ clean::StructFieldItem(..) | clean::ModuleItem(..) | clean::VariantItem(..) => {
+ // We need to recurse into stripped modules to
+ // strip things like impl methods but when doing so
+ // we must not add any items to the `retained` set.
+ let old = mem::replace(&mut self.update_retained, false);
+ let ret = strip_item(self.set_is_in_hidden_item_and_fold(true, i));
+ self.update_retained = old;
+ Some(ret)
+ }
+ _ => {
+ let ret = self.set_is_in_hidden_item_and_fold(true, i);
+ if has_doc_hidden {
+ // If the item itself has `#[doc(hidden)]`, then we simply remove it.
+ None
+ } else {
+ // However if it's a "descendant" of a `#[doc(hidden)]` item, then we strip it.
+ Some(strip_item(ret))
+ }
+ }
}
- Some(self.fold_item_recur(i))
}
}
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LocalDefIdSet};
+use rustc_hir::intravisit::{walk_item, Visitor};
use rustc_hir::{Node, CRATE_HIR_ID};
+use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{DefIdTree, TyCtxt};
use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
use rustc_span::symbol::{kw, sym, Symbol};
std::iter::once(crate_name).chain(relative).collect()
}
-pub(crate) fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut node: LocalDefId) -> bool {
- while let Some(id) = tcx.opt_local_parent(node) {
- node = id;
- if tcx.is_doc_hidden(node.to_def_id()) {
+pub(crate) fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut def_id: LocalDefId) -> bool {
+ let hir = tcx.hir();
+ while let Some(id) = tcx.opt_local_parent(def_id) {
+ def_id = id;
+ if tcx.is_doc_hidden(def_id.to_def_id()) {
return true;
+ } else if let Some(node) = hir.find_by_def_id(def_id) &&
+ matches!(
+ node,
+ hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }),
+ )
+ {
+ // `impl` blocks stand a bit on their own: unless they have `#[doc(hidden)]` directly
+ // on them, they don't inherit it from the parent context.
+ return false;
}
}
false
}
-// Also, is there some reason that this doesn't use the 'visit'
-// framework from syntax?.
-
pub(crate) struct RustdocVisitor<'a, 'tcx> {
cx: &'a mut core::DocContext<'tcx>,
view_item_stack: LocalDefIdSet,
/// Are the current module and all of its parents public?
inside_public_path: bool,
exact_paths: DefIdMap<Vec<Symbol>>,
+ modules: Vec<Module<'tcx>>,
}
impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
// If the root is re-exported, terminate all recursion.
let mut stack = LocalDefIdSet::default();
stack.insert(CRATE_DEF_ID);
+ let om = Module::new(
+ cx.tcx.crate_name(LOCAL_CRATE),
+ CRATE_DEF_ID,
+ cx.tcx.hir().root_module().spans.inner_span,
+ );
+
RustdocVisitor {
cx,
view_item_stack: stack,
inlining: false,
inside_public_path: true,
exact_paths: Default::default(),
+ modules: vec![om],
}
}
}
pub(crate) fn visit(mut self) -> Module<'tcx> {
- let mut top_level_module = self.visit_mod_contents(
- CRATE_DEF_ID,
- self.cx.tcx.hir().root_module(),
- self.cx.tcx.crate_name(LOCAL_CRATE),
- None,
- );
+ let root_module = self.cx.tcx.hir().root_module();
+ self.visit_mod_contents(CRATE_DEF_ID, root_module);
+
+ let mut top_level_module = self.modules.pop().unwrap();
// `#[macro_export] macro_rules!` items are reexported at the top level of the
// crate, regardless of where they're defined. We want to document the
// macro in the same module.
let mut inserted = FxHashSet::default();
for export in self.cx.tcx.module_reexports(CRATE_DEF_ID).unwrap_or(&[]) {
- if let Res::Def(DefKind::Macro(_), def_id) = export.res {
- if let Some(local_def_id) = def_id.as_local() {
- if self.cx.tcx.has_attr(def_id, sym::macro_export) {
- if inserted.insert(def_id) {
- let item = self.cx.tcx.hir().expect_item(local_def_id);
- top_level_module.items.push((item, None, None));
- }
- }
- }
+ if let Res::Def(DefKind::Macro(_), def_id) = export.res &&
+ let Some(local_def_id) = def_id.as_local() &&
+ self.cx.tcx.has_attr(def_id, sym::macro_export) &&
+ inserted.insert(def_id)
+ {
+ let item = self.cx.tcx.hir().expect_item(local_def_id);
+ top_level_module.items.push((item, None, None));
}
}
top_level_module
}
- fn visit_mod_contents(
- &mut self,
- def_id: LocalDefId,
- m: &'tcx hir::Mod<'tcx>,
- name: Symbol,
- parent_id: Option<LocalDefId>,
- ) -> Module<'tcx> {
- let mut om = Module::new(name, def_id, m.spans.inner_span);
+ /// This method will go through the given module items in two passes:
+ /// 1. The items which are not glob imports/reexports.
+ /// 2. The glob imports/reexports.
+ fn visit_mod_contents(&mut self, def_id: LocalDefId, m: &'tcx hir::Mod<'tcx>) {
+ debug!("Going through module {:?}", m);
// Keep track of if there were any private modules in the path.
let orig_inside_public_path = self.inside_public_path;
self.inside_public_path &= self.cx.tcx.local_visibility(def_id).is_public();
+
+ // Reimplementation of `walk_mod` because we need to do it in two passes (explanations in
+ // the second loop):
for &i in m.item_ids {
let item = self.cx.tcx.hir().item(i);
- if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
- continue;
+ if !matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
+ self.visit_item(item);
}
- self.visit_item(item, None, &mut om, parent_id);
}
for &i in m.item_ids {
let item = self.cx.tcx.hir().item(i);
// Later passes in rustdoc will de-duplicate by name and kind, so if glob-
// imported items appear last, then they'll be the ones that get discarded.
if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
- self.visit_item(item, None, &mut om, parent_id);
+ self.visit_item(item);
}
}
self.inside_public_path = orig_inside_public_path;
- om
+ debug!("Leaving module {:?}", m);
}
/// Tries to resolve the target of a `pub use` statement and inlines the
res: Res,
renamed: Option<Symbol>,
glob: bool,
- om: &mut Module<'tcx>,
please_inline: bool,
) -> bool {
debug!("maybe_inline_local res: {:?}", res);
}
let tcx = self.cx.tcx;
- let Some(res_did) = res.opt_def_id() else {
+ let Some(ori_res_did) = res.opt_def_id() else {
return false;
};
let use_attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(def_id));
// Don't inline `doc(hidden)` imports so they can be stripped at a later stage.
let is_no_inline = use_attrs.lists(sym::doc).has_word(sym::no_inline)
- || tcx.is_doc_hidden(def_id.to_def_id());
+ || use_attrs.lists(sym::doc).has_word(sym::hidden);
// For cross-crate impl inlining we need to know whether items are
// reachable in documentation -- a previously unreachable item can be
// made reachable by cross-crate inlining which we're checking here.
// (this is done here because we need to know this upfront).
- if !res_did.is_local() && !is_no_inline {
- crate::visit_lib::lib_embargo_visit_item(self.cx, res_did);
+ if !ori_res_did.is_local() && !is_no_inline {
+ crate::visit_lib::lib_embargo_visit_item(self.cx, ori_res_did);
return false;
}
- let Some(res_did) = res_did.as_local() else {
+ let Some(res_did) = ori_res_did.as_local() else {
return false;
};
- let is_private = !self
- .cx
- .cache
- .effective_visibilities
- .is_directly_public(self.cx.tcx, res_did.to_def_id());
+ let is_private =
+ !self.cx.cache.effective_visibilities.is_directly_public(self.cx.tcx, ori_res_did);
let is_hidden = inherits_doc_hidden(self.cx.tcx, res_did);
// Only inline if requested or if the item would otherwise be stripped.
let prev = mem::replace(&mut self.inlining, true);
for &i in m.item_ids {
let i = self.cx.tcx.hir().item(i);
- self.visit_item(i, None, om, Some(def_id));
+ self.visit_item_inner(i, None, Some(def_id));
}
self.inlining = prev;
true
}
Node::Item(it) if !glob => {
let prev = mem::replace(&mut self.inlining, true);
- self.visit_item(it, renamed, om, Some(def_id));
+ self.visit_item_inner(it, renamed, Some(def_id));
self.inlining = prev;
true
}
Node::ForeignItem(it) if !glob => {
let prev = mem::replace(&mut self.inlining, true);
- self.visit_foreign_item(it, renamed, om);
+ self.visit_foreign_item_inner(it, renamed);
self.inlining = prev;
true
}
ret
}
- fn visit_item(
+ #[inline]
+ fn add_to_current_mod(
&mut self,
item: &'tcx hir::Item<'_>,
renamed: Option<Symbol>,
- om: &mut Module<'tcx>,
parent_id: Option<LocalDefId>,
) {
+ self.modules.last_mut().unwrap().items.push((item, renamed, parent_id))
+ }
+
+ fn visit_item_inner(
+ &mut self,
+ item: &'tcx hir::Item<'_>,
+ renamed: Option<Symbol>,
+ import_id: Option<LocalDefId>,
+ ) -> bool {
debug!("visiting item {:?}", item);
let name = renamed.unwrap_or(item.ident.name);
+ let tcx = self.cx.tcx;
let def_id = item.owner_id.to_def_id();
- let is_pub = self.cx.tcx.visibility(def_id).is_public();
+ let is_pub = tcx.visibility(def_id).is_public();
if is_pub {
self.store_path(item.owner_id.to_def_id());
match item.kind {
hir::ItemKind::ForeignMod { items, .. } => {
for item in items {
- let item = self.cx.tcx.hir().foreign_item(item.id);
- self.visit_foreign_item(item, None, om);
+ let item = tcx.hir().foreign_item(item.id);
+ self.visit_foreign_item_inner(item, None);
}
}
// If we're inlining, skip private items or item reexported as "_".
continue;
}
- let attrs = self.cx.tcx.hir().attrs(item.hir_id());
+ let attrs =
+ tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(item.owner_id.def_id));
// If there was a private module in the current path then don't bother inlining
// anything as it will probably be stripped anyway.
res,
ident,
is_glob,
- om,
please_inline,
) {
continue;
}
}
- om.items.push((item, renamed, parent_id))
+ self.add_to_current_mod(item, renamed, import_id);
}
}
hir::ItemKind::Macro(ref macro_def, _) => {
let def_id = item.owner_id.to_def_id();
let is_macro_2_0 = !macro_def.macro_rules;
- let nonexported = !self.cx.tcx.has_attr(def_id, sym::macro_export);
+ let nonexported = !tcx.has_attr(def_id, sym::macro_export);
if is_macro_2_0 || nonexported || self.inlining {
- om.items.push((item, renamed, None));
+ self.add_to_current_mod(item, renamed, None);
}
}
hir::ItemKind::Mod(ref m) => {
- om.mods.push(self.visit_mod_contents(item.owner_id.def_id, m, name, parent_id));
+ self.enter_mod(item.owner_id.def_id, m, name);
}
hir::ItemKind::Fn(..)
| hir::ItemKind::ExternCrate(..)
| hir::ItemKind::OpaqueTy(..)
| hir::ItemKind::Static(..)
| hir::ItemKind::Trait(..)
- | hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed, parent_id)),
+ | hir::ItemKind::TraitAlias(..) => {
+ self.add_to_current_mod(item, renamed, import_id);
+ }
hir::ItemKind::Const(..) => {
// Underscore constants do not correspond to a nameable item and
// so are never useful in documentation.
if name != kw::Underscore {
- om.items.push((item, renamed, parent_id));
+ self.add_to_current_mod(item, renamed, import_id);
}
}
hir::ItemKind::Impl(impl_) => {
// Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
// them up regardless of where they're located.
if !self.inlining && impl_.of_trait.is_none() {
- om.items.push((item, None, None));
+ self.add_to_current_mod(item, None, None);
}
}
}
+ true
}
- fn visit_foreign_item(
+ fn visit_foreign_item_inner(
&mut self,
item: &'tcx hir::ForeignItem<'_>,
renamed: Option<Symbol>,
- om: &mut Module<'tcx>,
) {
// If inlining we only want to include public functions.
if !self.inlining || self.cx.tcx.visibility(item.owner_id).is_public() {
- om.foreigns.push((item, renamed));
+ self.modules.last_mut().unwrap().foreigns.push((item, renamed));
+ }
+ }
+
+ /// This method will create a new module and push it onto the "modules stack" then call
+ /// `visit_mod_contents`. Once done, it'll remove it from the "modules stack" and instead
+ /// add into the list of modules of the current module.
+ fn enter_mod(&mut self, id: LocalDefId, m: &'tcx hir::Mod<'tcx>, name: Symbol) {
+ self.modules.push(Module::new(name, id, m.spans.inner_span));
+
+ self.visit_mod_contents(id, m);
+
+ let last = self.modules.pop().unwrap();
+ self.modules.last_mut().unwrap().mods.push(last);
+ }
+}
+
+// We need to implement this visitor so it'll go everywhere and retrieve items we're interested in
+// such as impl blocks in const blocks.
+impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
+ type NestedFilter = nested_filter::All;
+
+ fn nested_visit_map(&mut self) -> Self::Map {
+ self.cx.tcx.hir()
+ }
+
+ fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
+ if self.visit_item_inner(i, None, None) {
+ walk_item(self, i);
}
}
+
+ fn visit_mod(&mut self, _: &hir::Mod<'tcx>, _: Span, _: hir::HirId) {
+ // Handled in `visit_item_inner`
+ }
+
+ fn visit_use(&mut self, _: &hir::UsePath<'tcx>, _: hir::HirId) {
+ // Handled in `visit_item_inner`
+ }
+
+ fn visit_path(&mut self, _: &hir::Path<'tcx>, _: hir::HirId) {
+ // Handled in `visit_item_inner`
+ }
+
+ fn visit_label(&mut self, _: &rustc_ast::Label) {
+ // Unneeded.
+ }
+
+ fn visit_infer(&mut self, _: &hir::InferArg) {
+ // Unneeded.
+ }
+
+ fn visit_lifetime(&mut self, _: &hir::Lifetime) {
+ // Unneeded.
+ }
}
"tool is executed."
],
"compiler": {
- "date": "2022-12-27",
+ "date": "2023-01-25",
"version": "beta"
},
"rustfmt": {
- "date": "2022-12-27",
+ "date": "2023-01-30",
"version": "nightly"
},
"checksums_sha256": {
- "dist/2022-12-27/cargo-beta-aarch64-apple-darwin.tar.gz": "00b7df89de07931d150940536a1e6c980897ed0e9880bb6f24d5ebbad896c8f2",
- "dist/2022-12-27/cargo-beta-aarch64-apple-darwin.tar.xz": "17e1e9cf2c4dad4fec7f420f43cea21923d76ba2d6f87ad67c90ea9c8e4a04f6",
- "dist/2022-12-27/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "783b7e2569490dffc953d4b24e659fec384739ceb8bad37e3a97df374945a91d",
- "dist/2022-12-27/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "a9402480620b03c010cb18dacca9a95c82e7b6078d2c1163543bc4292d7dd300",
- "dist/2022-12-27/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "7fa9aa92c2b1268420f60af2826dffa50b61c9926a2a1cd1c8273fe5861cde11",
- "dist/2022-12-27/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "97d583ed82db1fd5a03ce44a660f1163d0812b6f352adc6d78e61d7ae4fbfe23",
- "dist/2022-12-27/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "69236898b091d6ef31445eb1223acfc01adf21fb1aa277a7d441eaa300c0c9ad",
- "dist/2022-12-27/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "4a92788cdba1705b79ce9999d45a62d4631dbc59cc980437e1635dc908458b66",
- "dist/2022-12-27/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "b35b72b16c59b38e38acddf2c06c2c819ca78f146bbf4f3ce9d7ff982b86655e",
- "dist/2022-12-27/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "81d7fbe3f50cbad04c2ad0e118001976a880d23ad2a894ee49c6f6c10583d10d",
- "dist/2022-12-27/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "942f6860e2cf9da7c5399d308acad43f862750bf7d383444c2dd636b86553e14",
- "dist/2022-12-27/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "5f2f3c7186a2cb28f96bba8db7d404b0f3338bbe57edd631bb16fe4d2c8d493a",
- "dist/2022-12-27/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "f15932518f114587c3639ed270cab3e4ef4eb28e0abb6b59b5f63138fa43e829",
- "dist/2022-12-27/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "41116748ab087e0c7a5354508fb95e1a966212ef5cac40da59e363108077c3a9",
- "dist/2022-12-27/cargo-beta-i686-pc-windows-gnu.tar.gz": "37bbf0a9dcc1b3fbc11a5f72de922fb0f5dc80a632d803fa0a892d72bdd457c1",
- "dist/2022-12-27/cargo-beta-i686-pc-windows-gnu.tar.xz": "7a8afd8a69e1e25e47122096920217bbe765e82e831583420487702831241d5c",
- "dist/2022-12-27/cargo-beta-i686-pc-windows-msvc.tar.gz": "c40ec16780156f6568bf8f1353a3bb367d4bec09dc6e98b03de44bd2ed301ae8",
- "dist/2022-12-27/cargo-beta-i686-pc-windows-msvc.tar.xz": "94320949f071236d828fb1252159f0f2b1f18030303af1ae0b7ca06cd9567de0",
- "dist/2022-12-27/cargo-beta-i686-unknown-linux-gnu.tar.gz": "1fb3fc33289ae716f950feca832196bb32cde0556e41e501d05c84116836d916",
- "dist/2022-12-27/cargo-beta-i686-unknown-linux-gnu.tar.xz": "4f112ea5a91abbf63db484368090fdf8fbc6b7abc1a5d7c8353df15e7908c2e3",
- "dist/2022-12-27/cargo-beta-mips-unknown-linux-gnu.tar.gz": "b90f3c17c73f4dd7b36e0ff56b17be8e1c90f82b33c9be28b7b813fc5c788e05",
- "dist/2022-12-27/cargo-beta-mips-unknown-linux-gnu.tar.xz": "8754bb3f116b09a8b38ac0684014532a19ccb57e4e94d1097a8484e8d67e31ce",
- "dist/2022-12-27/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "549733dbbc3ec23976d6975e78ec8b8a30396eb45e4a8f5eef6d4c846cf04da1",
- "dist/2022-12-27/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "f5997ebe7c67969b7d14a2233897b6014ebd9b38010eee101d9e484d42b220c9",
- "dist/2022-12-27/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "3450c71c082bf84115fb035239453e39230afa0575dca0fc52586222b474a0c2",
- "dist/2022-12-27/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "a16c397c5e980a926e0122cff5f8d30c4b54c2dba7f48ef00b587c5cda8f500d",
- "dist/2022-12-27/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "62e025463eca2dac0547275c7827e6ecd109d1b84d056526e647abd220b3e1fc",
- "dist/2022-12-27/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "99c5f5511b23d93707df394c2ab90ddd98e7876c9ee74c861dc919cdd498399b",
- "dist/2022-12-27/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "eee574420f365d02d52f5f4754563bc1fe4f0b07d02a554f6aa886bccbe4c092",
- "dist/2022-12-27/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "64e53a591e2d4dee9935fca4a2df18fbbed1b00b74dd6631473ba2d5b257891b",
- "dist/2022-12-27/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "37d2a5f1c496c8ad8d2b5af5e89a4a325ddcef32ebd7087ef3cc9e653e5a8f4a",
- "dist/2022-12-27/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "8753d9bfdda6decdcc4f58d2391956609e0aeb75ce4368c7ed52c23ed3f28943",
- "dist/2022-12-27/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "303c63a294f2112fceb70cee063f35cbee3296b93ca91e43300e72b064d80da7",
- "dist/2022-12-27/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "96b752dd307d2709dbf2b91c687a55992f4e0e5a143223a8c2a267883b4a2832",
- "dist/2022-12-27/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "e5c279922e9adb47e6ecaee191ad291bfc627aa05e4c026628664bc47e5ce254",
- "dist/2022-12-27/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "7e0145fe22bfca7070dcace196e3229a86f9f5b31ab1cfc4fd7ff158db5b1388",
- "dist/2022-12-27/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "49df0b5774471ced53703942c6551c045ed56c92a3a224615f583511bc845a61",
- "dist/2022-12-27/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "955e67ac19fc7a2a882f759339343c466da9658b2cd95799dd78328c13d6527e",
- "dist/2022-12-27/cargo-beta-x86_64-apple-darwin.tar.gz": "a0e01a9ded551ea1f411da70d4481627579e870c2ff7592efde1d8be83ca46d5",
- "dist/2022-12-27/cargo-beta-x86_64-apple-darwin.tar.xz": "a9205d81dff07cbf2468fa6f6999fd0f1266ad4faf84f5688e3e5cb330bdce0f",
- "dist/2022-12-27/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "d6406b59361cdc97df606901beeafe6660a4cf557b9de4a313d4659c83f10255",
- "dist/2022-12-27/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "ae15fd38cfcd149de306280a48785fe269ea36b1a958de6815adc7a80792d798",
- "dist/2022-12-27/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "d75a793188af608b8bbd92907ff69294bc66b85b7ffe03882abcb661fd8c27f9",
- "dist/2022-12-27/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "26f4ed51fc227dccc67d4c68fcac78374fb1441093d3524ec157b1b6b6e90012",
- "dist/2022-12-27/cargo-beta-x86_64-unknown-freebsd.tar.gz": "6503b65a5258b5517c5213f0fb858aeff7e00c453a3633749d1a72f7f645050b",
- "dist/2022-12-27/cargo-beta-x86_64-unknown-freebsd.tar.xz": "75ba61fe1670d0e4cf9f9f35460c663701c75ceca95917ed25e98f20cc2f0ef5",
- "dist/2022-12-27/cargo-beta-x86_64-unknown-illumos.tar.gz": "e003c3a1ed8b57546e6ecdcbbcb58a97896a8e511b6a8fdc31100c24b8dd5a17",
- "dist/2022-12-27/cargo-beta-x86_64-unknown-illumos.tar.xz": "b377d76b8fae7ebc607f33400cc0b37974fbf02a4d29187b1f0f6f668c12ff01",
- "dist/2022-12-27/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "0dcfb9c65b5ad5c6af905c78d6914f5d7f8a62def817e64192b29c957b848783",
- "dist/2022-12-27/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "1ca64be7777194c3191350723e8a909cce93d8ac28ceafb5df641f3066c6a8b9",
- "dist/2022-12-27/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "9c24ff865929e88db27285fcb4a10adf97289a388f93ff5fa421211f35267047",
- "dist/2022-12-27/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "b794e0397ca0ec274e307468ed56b8116438c0b8a444f593eb56350d687e8137",
- "dist/2022-12-27/cargo-beta-x86_64-unknown-netbsd.tar.gz": "0fc5f8716933c46509cc05492e5bf75f6d06575dd6f803882397929b95394e12",
- "dist/2022-12-27/cargo-beta-x86_64-unknown-netbsd.tar.xz": "0cfe7415cb4c0a96019eefe0363c1d61934d76f3b5fb72a113b9de1401ecfad9",
- "dist/2022-12-27/rust-std-beta-aarch64-apple-darwin.tar.gz": "777b016bebe68ea79bfb336eedb595174466bfd54321523b9913f5c2741d0135",
- "dist/2022-12-27/rust-std-beta-aarch64-apple-darwin.tar.xz": "c4ab94494052bf3fb37a226e1313886546bde1ec4d7188049cb95dbf2963e1fa",
- "dist/2022-12-27/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "884004f47fea38414ed805abda4afce3adf5a83fcd072ddececfa888e55bdef4",
- "dist/2022-12-27/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "db0858bd63fa8609ceb6ee42cbddc31f31b2a0ce0c02e1fe1c2d32f0c8d607c6",
- "dist/2022-12-27/rust-std-beta-aarch64-apple-ios.tar.gz": "996c8612a39bddb3047ce0f23f761deeca61d15b36f2ea270f5a220d14c1ed27",
- "dist/2022-12-27/rust-std-beta-aarch64-apple-ios.tar.xz": "c06360094800d069261d363b709ca552d3899d50c12d39c23eb58d75015c980a",
- "dist/2022-12-27/rust-std-beta-aarch64-fuchsia.tar.gz": "891f1909fcc78019f77d704c3b3b1031c605dee01a116f04e7f4f402d6b9b2af",
- "dist/2022-12-27/rust-std-beta-aarch64-fuchsia.tar.xz": "3033d409735b299b6754852c28c1dac378a94ad892144ed76199d542a265c8a7",
- "dist/2022-12-27/rust-std-beta-aarch64-linux-android.tar.gz": "080c97ad158327dfdd24a3c17477614de1dfe27f1236c73ed43b1e7e881f6b06",
- "dist/2022-12-27/rust-std-beta-aarch64-linux-android.tar.xz": "80b89416148f4ed917978686ba337ebdbb3d4a50903a792831fa3b83032c43cb",
- "dist/2022-12-27/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "854badcf35650c196b2051be46254d2f4e86b4522dbfa9f1d1a64148cae7bf1e",
- "dist/2022-12-27/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "e4ccf358da4cb13b281c999318816fc99948a3531e9ecd6d0abad9b819c117be",
- "dist/2022-12-27/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "9473f12fc35106ab9144b38bddc3c35d56b0413bec06c2d1d5f43d4fde614331",
- "dist/2022-12-27/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "5cb44be7d8adc0589afca90ef0669c42f03a61a622d856fb057d450554d24c01",
- "dist/2022-12-27/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "25ebf045fc59488abc07ed24aa3364fb64cc186f6c852b12cb5c094f81d5fd69",
- "dist/2022-12-27/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "d43bca65f55159d6eafb7e342ec5d4598d63bc8fad0c9fc15b6bd88743321d4e",
- "dist/2022-12-27/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "91198741990d9300024da5113843cbeff02ed9ea344d9feb57736e9334136d27",
- "dist/2022-12-27/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "0aee6204d34246480be1d0f6efd6a66eb10d83a9dd1c215433e840949687c598",
- "dist/2022-12-27/rust-std-beta-aarch64-unknown-none.tar.gz": "97f3193bfde82b997346b49231a0f24a6960da88773bf27c73f57f40ec4f84e6",
- "dist/2022-12-27/rust-std-beta-aarch64-unknown-none.tar.xz": "1d2122442cc0a6595c901831e8cbaaeafd2043fbc8c4b028265310d2086673cb",
- "dist/2022-12-27/rust-std-beta-aarch64-unknown-uefi.tar.gz": "6d351f35cb9252c2825311eb22049283534cc2877cfd673fc1b5b3c94c6ef864",
- "dist/2022-12-27/rust-std-beta-aarch64-unknown-uefi.tar.xz": "054bb5a98df25830201ab04e81f63630dc329f48daa0d715a3443f95d2c0f442",
- "dist/2022-12-27/rust-std-beta-arm-linux-androideabi.tar.gz": "93b70e7c6b686ed5695bcf2f0b2da14e89a50e54304d445ebfc35107f689c442",
- "dist/2022-12-27/rust-std-beta-arm-linux-androideabi.tar.xz": "9b8983be6089216428007e968844f57bd88e2371dd592b1ca06aed2aa6479d8c",
- "dist/2022-12-27/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "753ef462dd47349fee5f45adadc073363250fbcbf566ff337250466d0ce73343",
- "dist/2022-12-27/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "c19389db997fd0e158e5a5e847f566f6b03f06b3161ce5644ca0178fae25d0f5",
- "dist/2022-12-27/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "c819d6a3de743f54e28eab0f2c7744dd5a5be7c6677bb712bfd3f93938435194",
- "dist/2022-12-27/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "4ca09f9df5476449c3510c82e284026329411253e2a02c90e6239f30a9a6074a",
- "dist/2022-12-27/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "f7994d565baee0fbdb010211fcd30398f7f90bd97770ce72e5ba34bf1f06a466",
- "dist/2022-12-27/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "f54e1efdb9a088a13371e5fd7e1599a7bcadc5db4247e8811ab9d374c17fac8a",
- "dist/2022-12-27/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "add3333e892ccfc31b8fa506e79d5633261daf13e7902549ac5ecfe8f3655bbd",
- "dist/2022-12-27/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "bfa9a7cb0de16ecef093d593677e32164e4e68042806f543824c16f2a12b55ae",
- "dist/2022-12-27/rust-std-beta-armebv7r-none-eabi.tar.gz": "81c958b4ba5933c02cb2872efc4d5de86a2bc1a1d326bf563256ec74e256fd8f",
- "dist/2022-12-27/rust-std-beta-armebv7r-none-eabi.tar.xz": "634d2e35b2314826198eb2a7fd6f253cac5c2bbe7a5a7c7cdecc09949db23b3a",
- "dist/2022-12-27/rust-std-beta-armebv7r-none-eabihf.tar.gz": "62dd020647cfa88c6719b4b9a803d07f3ccae7c2f94c924e1529def264db1be8",
- "dist/2022-12-27/rust-std-beta-armebv7r-none-eabihf.tar.xz": "53a03694b610146cb80e0ef0033600ea4dd6f8b7d413c3ac675cb57c9b4c5cde",
- "dist/2022-12-27/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "ac7c396d35406501eda50191b92abab74e19148ec6caa2d5171bba35f2d3ec96",
- "dist/2022-12-27/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "058c514636a2063193d278e16fc683dbe9c1dadcbca45707152d150dba71065a",
- "dist/2022-12-27/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "bc5400e734bc4747b3ea44bb5c3cf9af5f11d5b5f2e970bd4626a25a276f15f7",
- "dist/2022-12-27/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "0079d1cb3d1fd5be99bed480e6ec0b451dd9e2a2299e3347cbee33344cd8c718",
- "dist/2022-12-27/rust-std-beta-armv7-linux-androideabi.tar.gz": "9dbc9e97f9990f03efe67c817c9dda7fcdc931c7605742182f4d128859c1a53f",
- "dist/2022-12-27/rust-std-beta-armv7-linux-androideabi.tar.xz": "d0119bed6cb41629aa65d83f7c1021e05e2f90bd21a28e6f0d3b6f0ea9127dd4",
- "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "09cab74e4a6e38d07622fd80e97d424d7437d554c05ce1896acaaddad0e3b637",
- "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "4602ca768e8ba85cfc5a4d4a2964cccd048ad82f349b7453f077e38de918cb0d",
- "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "b983a7699fce4c6f9c7f16ea3fd2905a8ddf21623bae71a9e7515b5cd5b288ec",
- "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "ca2d6d4c09326559a1528cf32c7a899f985c7e3b7751cec8911d0facac149e51",
- "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "dfa375f608f297f4dd0fc39921609ecebb31101850d73a8bb8b67ce98e319f3d",
- "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "3159afaebb2b17f6b12128e2829944f9406e26cc7019eb33839fda311ea0b809",
- "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "5a2c2361c944d85455b7a037bc820fbfe824180106f5a6d6fbf4066ef78236a3",
- "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "0bd7ac1cada0a3a3894d404ad5871ef3abc4963eeb5a1f05f59e6264b1e6cc3c",
- "dist/2022-12-27/rust-std-beta-armv7a-none-eabi.tar.gz": "1f9daa0af4695c51e4cda38235497923b9adfefd1a6eb4be086d720cffab7594",
- "dist/2022-12-27/rust-std-beta-armv7a-none-eabi.tar.xz": "b9e5b75720d71bc9e0e16b73b7cf04cd3e5a57da7a6b842926ffcf273308543b",
- "dist/2022-12-27/rust-std-beta-armv7r-none-eabi.tar.gz": "4837b13f144f12e9edb5b49ddf5169d1cd13cff0a3ec3e54160714d45138448e",
- "dist/2022-12-27/rust-std-beta-armv7r-none-eabi.tar.xz": "32a56e92757a9ee82ff71962c7c8144e4240133d44de77d5955510640a31061b",
- "dist/2022-12-27/rust-std-beta-armv7r-none-eabihf.tar.gz": "d31ed0250a195a8043e71c8ae3b2e86111ec07b00892ae05c3783761b20774ee",
- "dist/2022-12-27/rust-std-beta-armv7r-none-eabihf.tar.xz": "06b70c26d9161b17c2e4ca9255ae1a73f7bbeadb24d733c320875e3dbbc77caf",
- "dist/2022-12-27/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "6271afcf4b05fb4de2ed08ba441b3ee0b476e2e33dbda8a5efa3d7540475bca5",
- "dist/2022-12-27/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "131c51bb571df676dbafd84d5015888c4bc15130bd7300d4c53c1667907f7f51",
- "dist/2022-12-27/rust-std-beta-i586-pc-windows-msvc.tar.gz": "d6bca2e8ba737a4704dc01dd6fca58a7c8dc8a065107f9fa98588c5fbdfe39a3",
- "dist/2022-12-27/rust-std-beta-i586-pc-windows-msvc.tar.xz": "d64aa029d4209256e18d7bed6e0e28156a965b1d50cb3eb8d70abab57be55a97",
- "dist/2022-12-27/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "f48248f5fedc961ea4050254cf9bdbbe70420ebdaf712847a5374a3c97e21df3",
- "dist/2022-12-27/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "c9287bc9be332f084a2779803964ae374930d3bec787155ac3c8d1d6be6a587d",
- "dist/2022-12-27/rust-std-beta-i586-unknown-linux-musl.tar.gz": "1914ba0edb77b0bc7cd83dd93d8a6ca53b29800844cdec9a976342982aad8b27",
- "dist/2022-12-27/rust-std-beta-i586-unknown-linux-musl.tar.xz": "30d5d1bf54eb6758e0bd3a3f48f186a957fdb1310ba8b3625b5f33994c8a58fb",
- "dist/2022-12-27/rust-std-beta-i686-linux-android.tar.gz": "6c05a59ff653bcde6a71dfcbd38718ca3cfeb89b7ec09d1cd380fdb589941d27",
- "dist/2022-12-27/rust-std-beta-i686-linux-android.tar.xz": "80b6b57ff73a9483046380c0d4cfc8c090fca5fc4174d5c47f71fffccb7178a6",
- "dist/2022-12-27/rust-std-beta-i686-pc-windows-gnu.tar.gz": "941bb6f5107630a0b26b8749be29c6df920ccb467df367a5f55491b062352f4a",
- "dist/2022-12-27/rust-std-beta-i686-pc-windows-gnu.tar.xz": "f3f2ece3bb0080980e099c176a8a1366171741450fa8b8e515362572b519e19f",
- "dist/2022-12-27/rust-std-beta-i686-pc-windows-msvc.tar.gz": "a94fcee79bd5941e718a112d855163563f6e5377b59a9c1405ac8804131b0383",
- "dist/2022-12-27/rust-std-beta-i686-pc-windows-msvc.tar.xz": "4bea862e2d998e976526cb741b7d674a7d620fc7e4838955ef4c53d000cf24aa",
- "dist/2022-12-27/rust-std-beta-i686-unknown-freebsd.tar.gz": "e5cc60f1c00d966809cd76fd452bbb03452c5cc94a487ef4ad14af12608ae5fa",
- "dist/2022-12-27/rust-std-beta-i686-unknown-freebsd.tar.xz": "df8df7d1750cf9e92b3e4b57b83b195c1eea6ca62f38ad317882a69e2e813ba9",
- "dist/2022-12-27/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "4ff8fc04b63f7a80587d4f75376c74ade7721369ad1508faf5c0f83930e1cf7a",
- "dist/2022-12-27/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "4716141a8be8017adb8540c05f88e6463b2add95439320b0084ffb290bc0d943",
- "dist/2022-12-27/rust-std-beta-i686-unknown-linux-musl.tar.gz": "d7cff128c80db94aaaa2bb708bafa3f857fe8b819ff21a85f7c6c7c5170576be",
- "dist/2022-12-27/rust-std-beta-i686-unknown-linux-musl.tar.xz": "bc83b17627e87ee4b555e9cc5912dbfbba74586f46719994be6832e22f70424b",
- "dist/2022-12-27/rust-std-beta-i686-unknown-uefi.tar.gz": "ec6723c138565c4d9ca87bcda199aceb7b3a42ddf979658cf9e8433a4dae9c70",
- "dist/2022-12-27/rust-std-beta-i686-unknown-uefi.tar.xz": "0e67f10a29f2826399604839a4dcbd173f8de39a755283a0c245c54b8a658210",
- "dist/2022-12-27/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "a78f899f6fae1671e41aa7d76b37d9041cc32dfa6e9315dabff3afe21f93700b",
- "dist/2022-12-27/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "4c74cece45b9271c77c4b328d1b3d876b50429077074580d771fc2b03f0d4738",
- "dist/2022-12-27/rust-std-beta-mips-unknown-linux-musl.tar.gz": "a854fbab503a0541d593cf9496a4e4cf8b9edb49422406b3a7f34e3fa21905f6",
- "dist/2022-12-27/rust-std-beta-mips-unknown-linux-musl.tar.xz": "f42a81564e7366d5d630632af3113b99c5de6d147d7eb9e31da762bb9d35d4ea",
- "dist/2022-12-27/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "de070d1ae3fb8a825092a9a78c26db553839c6d862e451a497d5f94230414bc5",
- "dist/2022-12-27/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "0a7092c99c587ef69801af713ef834bae809e4868dfcff43babd44bec532717e",
- "dist/2022-12-27/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "7077c20142082b0e2b8d6299ffcd8739c8295d315b917563cffe6d42e129cd08",
- "dist/2022-12-27/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "86f0988f3baf0b5bbed81483e7d68004651f227ab22d1d36b34c73f132191dfb",
- "dist/2022-12-27/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "536fe3059a8095bcc1c44391c27b7d9832d6a057388b4de089915810cbe1baae",
- "dist/2022-12-27/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "6b4e397a3a175f4cbbddabb750df14d668c1f4c8520577d35fbcb9dfa8613097",
- "dist/2022-12-27/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "30f42499ab4f21caf21551e0e92bb5db9a2e0f42fd0b3e59ee9789dd40d10391",
- "dist/2022-12-27/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "1190cfa1023a8d35d202979a1070863bb713495c2c9b720d0371b6d70d23bd7c",
- "dist/2022-12-27/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "4ac79a395ba5d70e1a09d0e1ce232b9405b9995f7c459d176be52eade40bbab7",
- "dist/2022-12-27/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "42f3666885680cbb2d15ec85cfbc9103e5b170346a9b8cff63a2d15f78472c67",
- "dist/2022-12-27/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "0b1c979205f8476ad6f0e35c05acb1976cb4c44006c25931e73c35025939f1ff",
- "dist/2022-12-27/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "7b6c76ae46ca56746b0bdea404125256636f05c1354e5dcf32c2a487d25e0ee1",
- "dist/2022-12-27/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "ad9cb2ec325e2a2f14ac4db6a5df53a7c06adfe8c4c58f0f2c83748a34d0c550",
- "dist/2022-12-27/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "1d507bb0cd8c80ee4e9155a0740c2319027ee5280552c1056ee7921a82bb9aa7",
- "dist/2022-12-27/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "e8d3b7bb483d7b3b737840ddf7a27a28c216d9d0b3ffc7ccded547f76bc932c5",
- "dist/2022-12-27/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "130edffa27b82def2876fb5562fc7a3971d33855e3ce023e18507b3e1bd47d10",
- "dist/2022-12-27/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "b5659dcc18fb0e5849acb13df7153518c8df5ca9566852cabaeee33583321d1f",
- "dist/2022-12-27/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "6bdfae3e9cf07608c862f4c042c47ed318c388bfcfb4cabfa233580b90c7a459",
- "dist/2022-12-27/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "f28795f8c2823bd817df63486d8a11b6b7cfb9538110e87d8d008ed979a81a3c",
- "dist/2022-12-27/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "695f6acb6ddb4c4a87515646157b88d2f58e2114b100f22bedcd4e2fa8de00b8",
- "dist/2022-12-27/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "5f004e4b265efae872e8b0d8fda81f4e65cc50452d558ef90b9bef7639f6ba6d",
- "dist/2022-12-27/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "c93c1cb534e83d43c40c62ed6623559e3e380f177c4bd151a0d1389a80a58139",
- "dist/2022-12-27/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "79988bb7bfa27dcacae0c459143be6a34f328ec6bcb73c2267d41a6f022fc045",
- "dist/2022-12-27/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "11235a96e7e8e14a173db0be71cd1ce7955c79f5a7d20b7436238256a06342fd",
- "dist/2022-12-27/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "a315accc791f1247e92a6362eb7bd6ab899c4688db7decb36b8d892c200186b1",
- "dist/2022-12-27/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "a4f6ac1d21ecda00c9d3e34d900771a4c5a50e3e5071d2eba837c9e4738edc80",
- "dist/2022-12-27/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "06dd8941f63c3031fa0383dd34981c655b26fd10d5510cd06bdcabb4a592a435",
- "dist/2022-12-27/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "882e464b44acb7e286f49d45a4f5a41fbf570ee0d78f1915fd6f94ac392fa928",
- "dist/2022-12-27/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "734d6f54d143ddddc2141da72ee02a32d4d505e20eaf0041c86c89f8ad8730ea",
- "dist/2022-12-27/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "be32ca1ddb2d48877c70c9a128dba02bfdca7a00e93c114c3c99127e7be04adf",
- "dist/2022-12-27/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "a6c70d3715b7e50ff15f5473348d8e1c5a061036055a85784b5e84a99e4008ee",
- "dist/2022-12-27/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "0dbbf637d310f7ef44cb1bc08122c172606c8ff1c886195eebbd52cad5789597",
- "dist/2022-12-27/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "3e2f7751028f9123d94ff72b08f8ce0b40da36eada77e1414d4178756b46313a",
- "dist/2022-12-27/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "382a35c79a03f7abebb9c5788f9dd19bd0973cb89e9b07a971eaafc611c3645a",
- "dist/2022-12-27/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "3eb49f766b206966433eecc7cdbbf709e75991644eae6f44596e5ec893fb3e8b",
- "dist/2022-12-27/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "9162e50f2ddb12fefecdc7c4c2d60e76874e78fd89b45d7fd81a6c95a856ee28",
- "dist/2022-12-27/rust-std-beta-sparcv9-sun-solaris.tar.gz": "dbf20b8fd52e1b6a553369a1690344574e6c660996ddd5121d4a05bfb71c87aa",
- "dist/2022-12-27/rust-std-beta-sparcv9-sun-solaris.tar.xz": "a40d8d444e57eabeecf8acf0b59f24b5d4e2c97ee538bfe38904a1f81a48fb14",
- "dist/2022-12-27/rust-std-beta-thumbv6m-none-eabi.tar.gz": "1e63244aa865e6a115e603f238b64410606453fb38802b1684fa6397660a1501",
- "dist/2022-12-27/rust-std-beta-thumbv6m-none-eabi.tar.xz": "ecd94de3f4a3aff8f9f920ff68383e342dc293ad2fb2584c9d9e48bf60eb82d5",
- "dist/2022-12-27/rust-std-beta-thumbv7em-none-eabi.tar.gz": "ad21ab2584999c7c528dcde2e435d0ee73686b9b94c4f31dfeb3abf3cf9b9821",
- "dist/2022-12-27/rust-std-beta-thumbv7em-none-eabi.tar.xz": "9394854e14bc3e671060630c01b6977ab5afcf9022790986c492fe58f0509191",
- "dist/2022-12-27/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "1cbabb457c0546da725a548a88b3268bb0feca4269af2b9cd0b98455c2e0c468",
- "dist/2022-12-27/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "1bb23d8d2783554e2043ed71cf982d9750bafa3ccac6e387b25d279137042867",
- "dist/2022-12-27/rust-std-beta-thumbv7m-none-eabi.tar.gz": "076a918e524cc33a02ab2c94e3a607dd293d5d6d63e0797b16f2246057d1082c",
- "dist/2022-12-27/rust-std-beta-thumbv7m-none-eabi.tar.xz": "de8f3e8907fde91bfcbff0c353eb3d1cb9d06dec31142479ef1ad2c6c368d5c6",
- "dist/2022-12-27/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "658d66031594324821649058e16e3e0b06542e8c9dd17c5fe705c487b5915ffe",
- "dist/2022-12-27/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "56a9a0235c0aacf561cfc9e7981c57a4d174dbedf5ed943d266302662246b10e",
- "dist/2022-12-27/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "3318c23ea42624e26cf2a25dd5fae206ccb96137d6833f28d7bfebe3ba7e327c",
- "dist/2022-12-27/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "b91396e82a9c30711608c3650d637a3ad56ea90d682460c791210f8bfb5a6854",
- "dist/2022-12-27/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "55b45e9863e197262bd97a9bcb80991c9c34385acaa228b062546b690621b530",
- "dist/2022-12-27/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "dc0b7ed56a142475759164713bcdd7c64958c7e7febcafa5371414082ae495b2",
- "dist/2022-12-27/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "b2bed92d03b295035e4bc4e0fd63b44ee1cc634edb394cfbd7afdc00353a73e9",
- "dist/2022-12-27/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "bcce53fd7c0c494ea1c45227190a959e992f07851dd064b2a9c599fafb07077c",
- "dist/2022-12-27/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "d6df9026c218b906671e89e433b165552a9486e41399a8f01a12d10495afc8dc",
- "dist/2022-12-27/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "f5f2411e3ff94f6e524a14ee46e6e6bc2e9ec91e395b0382f7a40bc6e970d623",
- "dist/2022-12-27/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "c766ec36907ce0a7e76ba9a227fdd57eae7a744bc5679b67a6ce1d6ab41ea19f",
- "dist/2022-12-27/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "de5f398bc34fb22489e9f6f2a9847954d8231ff5732f2595e8be93eaf7849986",
- "dist/2022-12-27/rust-std-beta-wasm32-unknown-unknown.tar.gz": "e3ed4bc39da4731443b3bbd584106444aceaf91720546ac66e98712fe65dfa93",
- "dist/2022-12-27/rust-std-beta-wasm32-unknown-unknown.tar.xz": "704a65e4f3e1afea9d1bd6a60c4d3e5fd57e3e14ba0dd2e2b94305c3e1c92cb8",
- "dist/2022-12-27/rust-std-beta-wasm32-wasi.tar.gz": "03e2ca41c758fb4f9a2ea562ac4ed7186e27607458bdd7b575d786368336ea11",
- "dist/2022-12-27/rust-std-beta-wasm32-wasi.tar.xz": "1ebc2ac44181d6d26928cbd550c64c5b496008e97356c68497f15f8cc8351f37",
- "dist/2022-12-27/rust-std-beta-x86_64-apple-darwin.tar.gz": "0f0520f7163ef3d659e5761b2f0c7a9f2de00b2f769eeec8d1e7e9b3b08daf6d",
- "dist/2022-12-27/rust-std-beta-x86_64-apple-darwin.tar.xz": "25795f1876330666b7fd6dd724661b364643448d0688d479f492c02faf2f7a4a",
- "dist/2022-12-27/rust-std-beta-x86_64-apple-ios.tar.gz": "014a022bbb524d8c550d5dc7d678b9764adcc9962538980e9596ebced9c5614d",
- "dist/2022-12-27/rust-std-beta-x86_64-apple-ios.tar.xz": "9b38e214e203c959eba0e8d651410f6cafc9e4b5725228c2bb4ac8f562e6cfa7",
- "dist/2022-12-27/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "afd9236304892945334183b31072b9b9f9b4faef8b7cdc4ad1f45a9b3e080a58",
- "dist/2022-12-27/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "33a7e5fd18f2166fb2b6cbe7630d80915533d59afc0080f1370bcfad1114eaa1",
- "dist/2022-12-27/rust-std-beta-x86_64-fuchsia.tar.gz": "7e91e1298da3676c4c051d7f34eec21f2fffa0a34af212c785b79c2d1048fe92",
- "dist/2022-12-27/rust-std-beta-x86_64-fuchsia.tar.xz": "fff70ed752d0760990f7a90bc3c50ac6586e8b012e61a15b6dfb325dd081b9a9",
- "dist/2022-12-27/rust-std-beta-x86_64-linux-android.tar.gz": "f9183794392422fbe8cfd61ea7bae0dadd8731e82b1d15a59f4e93acccd2048f",
- "dist/2022-12-27/rust-std-beta-x86_64-linux-android.tar.xz": "4fce2ab0dacac153de7d9805786b17d517863b0ff04a8224540daee86eff4056",
- "dist/2022-12-27/rust-std-beta-x86_64-pc-solaris.tar.gz": "d5b64111b3763063c38ae63915ca366a4fdb63f0dcf8121588a8953f01ebc669",
- "dist/2022-12-27/rust-std-beta-x86_64-pc-solaris.tar.xz": "c396b086773dc06db2e59bcdaff8ffbb7069efee5841b9e3cdd4dfb05fd95ce4",
- "dist/2022-12-27/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "e851812f69bcb2fe606bfbda125fa6b3f55752fd1a2330878c48ca99eedbb8b6",
- "dist/2022-12-27/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "689738a0952a0eab27ba3d3f9bc9b531ec29f338ea373bfa783a83786d5c2885",
- "dist/2022-12-27/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "b51f78199bfc1417f020e2d0dd16044f63f6b6675b2b6856f669f8604e44a6bf",
- "dist/2022-12-27/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "7713269f3c51717f6231cf4100043eca2330512b602c2962da81af561e90193b",
- "dist/2022-12-27/rust-std-beta-x86_64-sun-solaris.tar.gz": "9f0a129f4c2ea324e2dc94fad3f7acbc7bf2b988f66d9c42dd8abbc60c569acf",
- "dist/2022-12-27/rust-std-beta-x86_64-sun-solaris.tar.xz": "6ca71851fd0a7879aa750a63deb4ee587f82c28b27486f716e4fae5ebe599086",
- "dist/2022-12-27/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "6cfbf0f85757854fba1551c3312baac820e398b573d50b005cc3958723db7c82",
- "dist/2022-12-27/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "2e2dfb82fa7e23f888ae9541a30d15ba978cb29bbdfec6afb00590a39c16df5d",
- "dist/2022-12-27/rust-std-beta-x86_64-unknown-illumos.tar.gz": "92650856a7e74c8b912d5c84cd1002a490f9c8e3fa4506733fcbedb3cd42792b",
- "dist/2022-12-27/rust-std-beta-x86_64-unknown-illumos.tar.xz": "3dd302996bd3fb9f8b077e6d5fe3dc6f7dd9590d5fc3eb3bab2cffaada4e99d3",
- "dist/2022-12-27/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "3a1faf905ffc7263e725ce7571cb84dd8698adbc45b6902da86350299b2e3ccb",
- "dist/2022-12-27/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "daef635cdf88c8d9c924c0d66e2b26db1f56bda9b48ca0c21e089060b07dc997",
- "dist/2022-12-27/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "567bb99f67737cca721d1dc6975daefd3dad29b13d531d3b939405ef4e7aee84",
- "dist/2022-12-27/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "aa218c4547e77f33ba4bc45bba0b6fcf3cce9355c2cf11d74a3a4c5e49f9b3cd",
- "dist/2022-12-27/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "de43b04cccb3c2bdcd2a7993c391299a4bde5041102ce0eb5e32b6cfae86cd79",
- "dist/2022-12-27/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "f99963704b4c3189361925ec8b53daa2ca15ae4af9215cbd87cfec23e044cefa",
- "dist/2022-12-27/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "3d4949e63f137552e3b74e50b366f95d7a153e7c61cf5587634be51516fdc610",
- "dist/2022-12-27/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "5b48095a35f862190536e64eff726327e25c23981c0bc1224c8c44bfccbb705d",
- "dist/2022-12-27/rust-std-beta-x86_64-unknown-none.tar.gz": "12b5c69138260daf976e963ba503c66ec4432f11cf7506bc9ba691ac2c1df4a1",
- "dist/2022-12-27/rust-std-beta-x86_64-unknown-none.tar.xz": "5c334a67f6586dc406b6e55c7f9d64b7701e1c7879bf5860b378069301c57854",
- "dist/2022-12-27/rust-std-beta-x86_64-unknown-redox.tar.gz": "58c15f9119e5f78d7c70b24e67af57ce10bb2d2cb1347b9b4631478665c624de",
- "dist/2022-12-27/rust-std-beta-x86_64-unknown-redox.tar.xz": "a2f8b635254d53ec5b902dbeb8ac63c6c3982f94dfbcaec3d093f17f0f5fa896",
- "dist/2022-12-27/rust-std-beta-x86_64-unknown-uefi.tar.gz": "1ce5c25480e97699b12c180ed6198766a0c12a3543dd317ba6f4a52538027b0d",
- "dist/2022-12-27/rust-std-beta-x86_64-unknown-uefi.tar.xz": "e4d9ffe34ba40e5ccf87007085dc4daa20a8a52944f092e2a075527702b55072",
- "dist/2022-12-27/rustc-beta-aarch64-apple-darwin.tar.gz": "f5c8dadb8eb0335a50326a94f858625e4f01e3159e933d58f9d24338d47943be",
- "dist/2022-12-27/rustc-beta-aarch64-apple-darwin.tar.xz": "0a6eeb32e4d85b628044c3e075e5f1414a42bb582905b199d360addae466d3ae",
- "dist/2022-12-27/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "0f7ce917f14a1d42637fbbbc343473596becceb22634cb7c7cdee6beaa2b9ca1",
- "dist/2022-12-27/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "49667bd902fb5fb2855e843ca5c1dcd453171f164a3dee2dcd9e09b0d9e1e57e",
- "dist/2022-12-27/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "d5a03695685afff4debff8e09f2d91db02d2ac29981a9ec230619c3e388ce1c9",
- "dist/2022-12-27/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "db1aeb772a08f111d8f024164b570322f45ecab0f6db4e931b91971b2b982323",
- "dist/2022-12-27/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "0e51f97b677b5c813862bba3e5a3b0884f0ecdf9b7c3676089625431a3d0cb2c",
- "dist/2022-12-27/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "f88c6c33ac3682f340ed60b4f62ee8ed61eb21069a1f0a912024d19e41c0d5c7",
- "dist/2022-12-27/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "25abe3158ec3ab7c064341247d78ea265ad7e0dc2063837fb5cf0a3bea9d011e",
- "dist/2022-12-27/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "1d430b8e35ebd63a79b34917edacebb76b2fa8f1cea4772ba2c4ef0340485fb3",
- "dist/2022-12-27/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "1858d5ed21a3132af4b56c841cbabc9fb834d501946956a0e9aeeddfa095344f",
- "dist/2022-12-27/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "17cc52dbd6ccbed4677ad52fa666ea10295c11209528e78ac190f01b5d509f87",
- "dist/2022-12-27/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "3440edd99025f24f2640528d2d1c10047c834b93cb09a935c65ecfb72012e7d0",
- "dist/2022-12-27/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "7e1ff0a950db0ecbadef3a9ee55a593891f11a42c6c0ff59637074c8b5c4da74",
- "dist/2022-12-27/rustc-beta-i686-pc-windows-gnu.tar.gz": "90487ff490c4e71ae62e28492cf49600f8f92e0f35f5d76a50eafcf4bbcf4bcb",
- "dist/2022-12-27/rustc-beta-i686-pc-windows-gnu.tar.xz": "8b44fb934aba0eef296098bfc5a9f2994cdd595420ce10f4f310c5ee9d481071",
- "dist/2022-12-27/rustc-beta-i686-pc-windows-msvc.tar.gz": "0fefda6b62234a43976ebf18d7cd62057cad5b494c750f2d9730f5df64cadb00",
- "dist/2022-12-27/rustc-beta-i686-pc-windows-msvc.tar.xz": "c9eecbc06e7456bf5e383557a8e5720d00d09de640b8c46139121faadc354d74",
- "dist/2022-12-27/rustc-beta-i686-unknown-linux-gnu.tar.gz": "8b17d032192aa17e52a3f08a074079561ad7ad6c439f9274aef228af93adacc3",
- "dist/2022-12-27/rustc-beta-i686-unknown-linux-gnu.tar.xz": "c70638cad594097450a469837411b110e979c303727341623427e3c9e4e4f507",
- "dist/2022-12-27/rustc-beta-mips-unknown-linux-gnu.tar.gz": "3669ff9024092ab467a1b95aec2cb1692810ee716739f31e3aee7d89e6bd6d7f",
- "dist/2022-12-27/rustc-beta-mips-unknown-linux-gnu.tar.xz": "165859e42492e33bff634c80b6c96b13fd2252981b4be2821b96a6593933e22a",
- "dist/2022-12-27/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "2ac418c0cdeb2382aea7296169d747f65349d7e6d5aebbdde7b377e985de354e",
- "dist/2022-12-27/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "21ae51357508398527b6edd2e5fbb1745fda1c8db2683c40847216c0ce251d47",
- "dist/2022-12-27/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "3eb68935676424aa8c68bc32b06c010c5c1302fa6f77e9b33e5543565562d176",
- "dist/2022-12-27/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "0eeb58035b510a166b8506168f67850993e278888986773c779bee24d7a6ec11",
- "dist/2022-12-27/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "f41d878b2e49beb9ee3a1bb8863ce1b81fae7100a786a78d9922bf8a4fd0dfc8",
- "dist/2022-12-27/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "e0cd18973c7651cd2e1e041f92900375a045bef62754d432df539000aa5946c4",
- "dist/2022-12-27/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "7206be82ba39971c6a734f4a89f7f750d581768d82253e31cd985fecd1d17c3e",
- "dist/2022-12-27/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "f9ec2a3e98a3b94b170237386256c763d62925b430d0e12a289982c7c79d2bfc",
- "dist/2022-12-27/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "32be7fe5f359cb2312c9bd966eb43b143b336b4acbdf118bf09221574f157b16",
- "dist/2022-12-27/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "a8163a5b527b1ee932e06589d690c17d8848dbfa8504de6984a718579698abb2",
- "dist/2022-12-27/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "3e875cb943dd0ffff907f6a582a64f923cb84a07ddd8b5e6f1ec2e1d4228342f",
- "dist/2022-12-27/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "22537364de01be77a2a5d79486b1090dbee7b3273fc634073031f82576a61a14",
- "dist/2022-12-27/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "230041ec7d0d4debc841abafe2f3314de51793d281a1077835d9190286a558f7",
- "dist/2022-12-27/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "2dafdb1a97469737123149608476c248a77ccebeb22834b6a2166fc30551a7ce",
- "dist/2022-12-27/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "0bd96121550321138dad9f74f331eaefd77ab388843e5561c5c0cb32e9d80072",
- "dist/2022-12-27/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "ecb02c8535c1518e589eefb10be17830010c40be61f3184576abe93e098d793d",
- "dist/2022-12-27/rustc-beta-x86_64-apple-darwin.tar.gz": "600b83ea5c832dc6ad9746d74b7dbc8ea566adb9208c4260b183ef05078d2bff",
- "dist/2022-12-27/rustc-beta-x86_64-apple-darwin.tar.xz": "175930f3062b433fc0a2b959917933bf3347d3f3e0900684785493d0ee9dc6f3",
- "dist/2022-12-27/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "d1701678ee1d2f2e91f3c1f898f852593ec1b109e430c53c13bc2898b08bca3f",
- "dist/2022-12-27/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "3400e923af537d28139b9d5d780caa039828e06677cbf499322614006552778c",
- "dist/2022-12-27/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "d462ca50803b13e136fbfd49ac4a6e186e416041f3cdaa8b4fe72e628cc10555",
- "dist/2022-12-27/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "81ca0992ec8306ff67b00f5f85f31c6617f78b7350116dd56df082c477c9069d",
- "dist/2022-12-27/rustc-beta-x86_64-unknown-freebsd.tar.gz": "65fe64154264ab76bb94aa7f107efa9b58cb801c9aaabcc7e6ffa0ce14319ef9",
- "dist/2022-12-27/rustc-beta-x86_64-unknown-freebsd.tar.xz": "cd6e9bfb6e8c08a46dce7bc623cfdc5a04e55c8377eaa3a75fae0bfe8e00b43e",
- "dist/2022-12-27/rustc-beta-x86_64-unknown-illumos.tar.gz": "a66bb4b0d9dd9a21b54857c4fa7eb48a88789f0414fec4a1e36c798546c4b71f",
- "dist/2022-12-27/rustc-beta-x86_64-unknown-illumos.tar.xz": "b63e6299e961b75d9c9bcb46e1dbc22b8fec89292ee6c8758edd43f4b89cb12e",
- "dist/2022-12-27/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "c768beca1350bdcbcc31c7d3f30c3ccec0ab2bea0c28bc4c89cdd32d9780cd00",
- "dist/2022-12-27/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "62a675d74274ddb4d8a9146c20942cb91b86e0c94a902169c2cf77f4d471d645",
- "dist/2022-12-27/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "8f2b81b37bc34291f3d90bb6aec621da0ac760c39727bfd24449c288cc8cb3c3",
- "dist/2022-12-27/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "053c313c9a751bf0102448866fad2a80ca67b9f79afce82ce03805430e2e695b",
- "dist/2022-12-27/rustc-beta-x86_64-unknown-netbsd.tar.gz": "a9f42eb0ffdc4bef87669d8fb5163e81a5d82ff6baf631f159b7bccafe9df453",
- "dist/2022-12-27/rustc-beta-x86_64-unknown-netbsd.tar.xz": "d1ea529e56d57132de1782396a767f8f00f30e2b5f7c9a5fa96c3289b43e3515",
- "dist/2022-12-27/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "411b96fddfbcc90b4522e3f4e2d6e174f3440960e89193c97fcd5ca8afd62809",
- "dist/2022-12-27/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "29db6fb11b411dc8351a8a8d1b148e81d9c87f9fb234b3a18722ee470b4d36c0",
- "dist/2022-12-27/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "32ab437117791eb7113ac522ee4119e2e43722528141302772adf9cda7306b24",
- "dist/2022-12-27/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "4d892f3c65ef8e32670ab3c3e8fb39a2ae623c59d1ff555ec94644254e954474",
- "dist/2022-12-27/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "8bff3a1591d25d3e1acb70600e6cd54d712772247376ac5eb90a4b2aafd21a6a",
- "dist/2022-12-27/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "b81b094d128a37b178da1eda7c72399a9da4bd614e697c53e9c4d78589f859f5",
- "dist/2022-12-27/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "b3a685d1abe4ac639a0a3ea187b83ec660cd838e7c5c010ed60f8620d17df906",
- "dist/2022-12-27/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "10b7563202520708fd27cc221ee8db34b368563eb1586be1395955ebf4313d6e",
- "dist/2022-12-27/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "34e5ca3d51b51ccd97ded5e0c31c999a84f9d5ca5ee3d010e15212a97ab40567",
- "dist/2022-12-27/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "16638ba8478861276c10847b989fd23de942cb82a9d4da9d92858c6800a39a9e",
- "dist/2022-12-27/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "13fa3bf29e9d20291703bf2c03bc97cd8e2081d1c747b6835eb0a06f94dd5d19",
- "dist/2022-12-27/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "98dd01d90657e43ab3a2b91673137cd6ae4c171633db1f1e4b68b2e90bcb9bab",
- "dist/2022-12-27/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "1370e4c8ad5bab425c02fc924d5ac079ac1387368a3ea5d22c1cdc2edc9c6ba0",
- "dist/2022-12-27/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "8c312da4ccd992c303fa3f181dc46f9b01022f72061ef43b2fd5848736547870",
- "dist/2022-12-27/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "0d7a87816f50452349bd26cefdd9f53f2d93a53243290ac59bd5de414407aa1e",
- "dist/2022-12-27/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "982fc6783ad07235d375c4c8964104fdc64a009ea359cca532cc268a8249e88c",
- "dist/2022-12-27/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "a5b76840e49a912a819809a2b4c73a0e750422fad4876d11b409a8ed49a77911",
- "dist/2022-12-27/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "9566b6417a0bdb4c73272d167cc743b297db62f625449343a6f1ab60c52d5327",
- "dist/2022-12-27/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "bf6cb5e886ce02a3f9b4b00a3696da0ee277af8f690f5a31119c5fce5779cd4d",
- "dist/2022-12-27/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "7afa5129bc43346614869721e7094f65eba6681bb9b8ca8a3559925f29433f10",
- "dist/2022-12-27/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "f9805697506a0c730299492fe04c53433c8c4deb70ca245ff1c2cf5151fe306e",
- "dist/2022-12-27/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "f5d7d5a841a7e7a5d749e52cdb118d2f2cec09de68835a42748db4b3a0a79979",
- "dist/2022-12-27/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "dc903c64c969a3c21664263c2a30e9cb0dc42069a95f755545ce9648240a376e",
- "dist/2022-12-27/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "de6591cc73244d99b3469d88439ad442f00037a1cdcaf5fdc5a694b52e47b2fb",
- "dist/2022-12-27/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "f4e8dba56a1b90d5871bf8722a5ecd2027a4f101299880a8689f5cf46df2606a",
- "dist/2022-12-27/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "496c19042848726db446cd3df4c52f3e8a5527002ca5492e2d6ef72528d6887a",
- "dist/2022-12-27/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "58742a5c8230e8749b01058acea639d92d45090bcec6fb7eb1d8f356b0f08631",
- "dist/2022-12-27/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "bbbdaa32d8d29c407133b0ef2851970da884032effeb85c271d57e58b7d38a44",
- "dist/2022-12-27/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "1a8a59193dc15d331c3243a2cfaf5c81c023464becc4da63201583d2d2cdc27d",
- "dist/2022-12-27/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "ee86ae7621804a7b57ccab06dc73b7d87453b53814d482ea43dc26dd01dae1c5",
- "dist/2022-12-27/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "21a79a050e4461305e280ed7de7c0ade2774ad5230f671c76667be7bdbdc47af",
- "dist/2022-12-27/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "033afa47c24a4887d40d62391f9f66b76dffdc1bd8f1ad622bfb14db91d7df03",
- "dist/2022-12-27/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "01cea51850a7f676803f5f8f9a556a71bfb8e7a7e04cc5fc0e7d1b706473338b",
- "dist/2022-12-27/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "720bf138fb2c541d8d8d0c60d6584cff692c932c6f383901f999e7b3d4078770",
- "dist/2022-12-27/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "8c3f3fd601bc7d8670f6acfcda29206fd5590fb3a2a6cbb3794ba29cf749144d",
- "dist/2022-12-27/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "8f1b43479a724197c7ac051c6a6d2a10bd87c6b24fed1d38c9e93f503c87e5b6",
- "dist/2022-12-27/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "b38b6dc1e65cc0f5031d2045a90404f3b2ce2648884db1f658641e76168d0109",
- "dist/2022-12-27/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "ed635e2388fcd3bbe94f497404b6787edd5e7471d6c6471345386a43444f46d1",
- "dist/2022-12-27/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "457995f055ef35a2491326f95caf31376b21e3cc4c0316cf4536cb7604e472d3",
- "dist/2022-12-27/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "d80b01e8c007da58250f7affea8d034a536437efd766eeb8de6d5b7feba9b0d5",
- "dist/2022-12-27/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "ee2ab7683e75fa68ad482c81e546cd71b9209497f16a0590507e5de884f1e627",
- "dist/2022-12-27/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "d08326f42bf7f38855e37c624a38923d09cbf162b666e8058891aff06ec017c8",
- "dist/2022-12-27/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "e42ee4dfdd0aa342dd8192204fd6cfb503eaa0069f70776adbbca352d7e7b661",
- "dist/2022-12-27/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "76ec230ae507729fb4ced016a45b0020775a9eef068c2b2e5ae6e3fcb451d32d",
- "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "55f5c89950a81b00efc542c19b42cbfeb9c969af63280106fc78e8893df3d568",
- "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "5a4cf3589d06e562ebed70bf0015af3e80f83de1c4d311c810ebf09feac640bf",
- "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "fb44bc69be6c89c7245b914324e23284dbd9887ac0c1c4a65379344ce78cfb28",
- "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "8d34915b54cd8ea6abf0bff01546f31f74342e1d21128b1e14c32cdfd3505afd",
- "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "d15403f81b36c0a2829ad2dee5c1edf39a993a13ccc57f01bb45c77898e3b9ec",
- "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "4c0c61f404ec6bb87ab044c0850d116c577a2ff3cfda9ac1598a7858b4fe1a7d",
- "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "8bc1fe0e2496769f52a576ccd13f706b26f706f060bebb2618e2c64c3831e2d3",
- "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "bcb527bb736bea88bbbb6974ba388b11fe20596c2c178314bbfdad5e2db65fcc",
- "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "8bffdf816b12c53d5443e2523c0960a37ab67c93590b0bb753fd5a026e67d368",
- "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "bb5c947ab6dfa28fa7c3d7050e9c14c02eaedf2a4e06d290bee554f569be2c30"
+ "dist/2023-01-25/cargo-beta-aarch64-apple-darwin.tar.gz": "323f3c4c41892765b24201aae83a54fcaef08e47b9b2912a2680528c6ed4f8f8",
+ "dist/2023-01-25/cargo-beta-aarch64-apple-darwin.tar.xz": "2039157d9100ccadf4d3596f5d7b052e10ff997b59ac7619999969794fc51eae",
+ "dist/2023-01-25/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "ac3c88c99aed8d4547f8b0f857ec3538456f10223411580278eed10f6e2be30b",
+ "dist/2023-01-25/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "27b11ea3c67f202e61b5e7394d36bedc7f1b054ca53d68e53ccd7bacf77b4af3",
+ "dist/2023-01-25/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "4d6d1d47d34e8042aa978fe5a6b5b8984d6626d38731081db2d5b413d5b844f4",
+ "dist/2023-01-25/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "a50e473aa6b6bffd84a719aec602d4bc19f03ccb0ee5f26340eb466501cb2970",
+ "dist/2023-01-25/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "a043def73a5c72d515c3d7dabe09022c353b047e7a4e4e13e9b17da9b30f8828",
+ "dist/2023-01-25/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "a63a8915409df4ae5d76d530b46cb7e83b6e6ca79790fa095d899e33773124a0",
+ "dist/2023-01-25/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "9c0c413187f1f1e0f1b6f1b66af0bd1b264d94f73439f6df24f476ee1c6c04fe",
+ "dist/2023-01-25/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "cb79e76beb989a3e4ffd1461817ad2dd0602aca3bce1a2e54cccc1bbb518a303",
+ "dist/2023-01-25/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "d57c5806a13b498768b53a053c7eb17e8becb19ea5fc9561a2a600dafea32056",
+ "dist/2023-01-25/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "33f35d8c2f5fcd5fa7928f2186a8b2417040e01462152430bae978d8d5a661cd",
+ "dist/2023-01-25/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "80ba79da61f82dc760a9dd7bfdfde29fefcab4ae94917cbf5d908332f93061d3",
+ "dist/2023-01-25/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "a8e48c6345b0e195ea58d6237a247b0d20c8d128af1b12813430806b9a340d5b",
+ "dist/2023-01-25/cargo-beta-i686-pc-windows-gnu.tar.gz": "052e2c0ff954d66e40101dc075bdd19fdb0befcbfdbc26dd94093bc4147c65cc",
+ "dist/2023-01-25/cargo-beta-i686-pc-windows-gnu.tar.xz": "94681fbbeb12de4b97b0a5a0206204c41b16c3de1c7c3262e1488f00b22aeb51",
+ "dist/2023-01-25/cargo-beta-i686-pc-windows-msvc.tar.gz": "3c0c2205e97136ac5e13b3c89d745af24afc60e6b5adc24abf22755d8d0007a1",
+ "dist/2023-01-25/cargo-beta-i686-pc-windows-msvc.tar.xz": "9ccf1a81d524fbac3f859c0185421936b97ae565164c12ed32e6a39052eac695",
+ "dist/2023-01-25/cargo-beta-i686-unknown-linux-gnu.tar.gz": "68749447a45ada6bb6e06488e3d58ecca7939d3c77dc40c22f22d7257eae247c",
+ "dist/2023-01-25/cargo-beta-i686-unknown-linux-gnu.tar.xz": "6b8942c01d1b8fd1f1f399b7f63db409a30df240b5aca5cf34e3166adafb5053",
+ "dist/2023-01-25/cargo-beta-mips-unknown-linux-gnu.tar.gz": "7f8fcf5d25353dac5d2cd6ad04b20da19b2dbccd25a977e8122d85724a632392",
+ "dist/2023-01-25/cargo-beta-mips-unknown-linux-gnu.tar.xz": "91d0ec836e2941287ac28a753650e1b7b57364af58fdfedebe1fafea8612f1ac",
+ "dist/2023-01-25/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "171f40046f777d84fe5a4349d3565ad3485fdf075d8fbe194ca31ba2be9eeb1a",
+ "dist/2023-01-25/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "0521be760b2a1e6cc134bbe3473dea01a6d0fbf68b05995f41a75875d489eb60",
+ "dist/2023-01-25/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "ee7c39af31d09a42c5ce1151da6dc1147b5c1aceb0ea94cb3059bac49e72ba2a",
+ "dist/2023-01-25/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "dc8ddfc8bd305c3f1f4d7965b8bbd8b24235ef758c38a32b3d64b5879fab25d2",
+ "dist/2023-01-25/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "4757229750f44b3d523ef7a9c778d923113a8eb8b93ad97ef5e4f23a6f1e6a21",
+ "dist/2023-01-25/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "36911ebbdde86d90bca90b61b1b31f6ab054ff65907ac73a22d5ae09d061c444",
+ "dist/2023-01-25/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "8e4ce0a0743d301d056a1bafb4216ae96fd6cb06ca083216eaf7f3a21514e064",
+ "dist/2023-01-25/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "47e28a41670bbcc7a3787c68dcf72ffe42bfbc3e9f14418871ca814538f88180",
+ "dist/2023-01-25/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "7bcab6e25cd8208eb220839f6adb202dcd382e4bc32fa63b83c40fba330246b9",
+ "dist/2023-01-25/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "650bb4d6b51ef5293164642101395fbf6d9eedcaccccc8ff3e2be032d9e60316",
+ "dist/2023-01-25/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "fc779f539835c1f3e1e7d9c1eed932568a5e731888f766202279e9240dd20e36",
+ "dist/2023-01-25/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "b39ab17c34560266df7dc60b6cf5626758f8b28f7142b916f1f3399342e6e0ec",
+ "dist/2023-01-25/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "7b677b4a2cc59b3baebc1265f8a364879b2195905de1eb20f62b66e2fbfdbb08",
+ "dist/2023-01-25/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "bceab89d3ae1ffd25fc155a7b3514c69e3962ce8f7727cc7e7c4b40f0c6eb3eb",
+ "dist/2023-01-25/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "d0522064a1994aa338d12f5ef68635f8804a2cb9151dd67771ae132e65560790",
+ "dist/2023-01-25/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "478fdff509a609e5310c54fa1e0eecbb3870a0636132dbcc71291e150c805828",
+ "dist/2023-01-25/cargo-beta-x86_64-apple-darwin.tar.gz": "cfb5bc9dcf4c85915e5c7e4a29e7f45c4e5de4a3535c75ce7c192c08511e0350",
+ "dist/2023-01-25/cargo-beta-x86_64-apple-darwin.tar.xz": "6b1f48ceebc916f9829f599fc815de2b8724873ce8a22ba058a2a1ac1df46295",
+ "dist/2023-01-25/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "60d119c084899f0a1d7661188756833118bc538d7e7298c72d1452b06e27ef62",
+ "dist/2023-01-25/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "801d03dfab7e8007a97d95c551b3a069e56371fe33fa4682e20fa50a8123bc20",
+ "dist/2023-01-25/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "269bdb128749d234e12b5795b90acc1a91bc0c338ed3be70ab2e62d476fcd055",
+ "dist/2023-01-25/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "88737cc19187a0752e45345eb286a5e9d500f9c71e03bb26737888fe42b350b5",
+ "dist/2023-01-25/cargo-beta-x86_64-unknown-freebsd.tar.gz": "146d1af37cce4b6eff9f99bb74ad33f2d91383a2b69dfdbd59ad54fc2dd44c49",
+ "dist/2023-01-25/cargo-beta-x86_64-unknown-freebsd.tar.xz": "9466a4417a1ea6a9ab03ea7d05f747a731ed0bf5545148a1c782c797dcff50a9",
+ "dist/2023-01-25/cargo-beta-x86_64-unknown-illumos.tar.gz": "f32fcd8a18047646865afc67f92d6edda54fbe3f4e9963aba2095e23295e6ce0",
+ "dist/2023-01-25/cargo-beta-x86_64-unknown-illumos.tar.xz": "25431bfe87d8c944225122d21ca4823cefe72b304b10933c628d5d2df13d5f5c",
+ "dist/2023-01-25/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "cd67e483efd3a9cca57523cee428cd9a5555ff93b057f7fef4178a3e2fd49309",
+ "dist/2023-01-25/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "45d578c09399495b67ac38358e4251e3d7a20e988428a1a5a1e39387d2664da8",
+ "dist/2023-01-25/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "f66eb2cf2c637b4822e2c326b4a57d63eb3c0b517ddb69ff57a45001bc0a110f",
+ "dist/2023-01-25/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "7a0817ef29d6511d4fd9dbbdf3e9a92635f076d9b0633cb55b325cebeee4efb9",
+ "dist/2023-01-25/cargo-beta-x86_64-unknown-netbsd.tar.gz": "1330a1b4f975b1d96692bdc4a6392ca87e8e99982768acefc2815e386b6f4e77",
+ "dist/2023-01-25/cargo-beta-x86_64-unknown-netbsd.tar.xz": "919e25bd54133f4a8cbbf09218415ca7a5041298b32181fa566c5d4a8bfd8b90",
+ "dist/2023-01-25/rust-std-beta-aarch64-apple-darwin.tar.gz": "3dcf5c58141e44d1c84f33f58ca4dd99edd277ef15a69fc6b94fbe7c67a27483",
+ "dist/2023-01-25/rust-std-beta-aarch64-apple-darwin.tar.xz": "a651af6487e2f3246075b984fffb4072338a559ff8e6c373289a6242c0ca3ea7",
+ "dist/2023-01-25/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "5e3d5aa50784ee63c6df03b07ac92649f76c40ac6fb49c24d97896814002697c",
+ "dist/2023-01-25/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "0ae7440c74cee87c25757159a5749014eecf77b2bcee7e1e71eb9249f917d725",
+ "dist/2023-01-25/rust-std-beta-aarch64-apple-ios.tar.gz": "a47acbecb37786773c5d80da5990298c5facad11151c9991796eedf80472b1d5",
+ "dist/2023-01-25/rust-std-beta-aarch64-apple-ios.tar.xz": "9168f9b1cea16a213249a1c452a59719234c145045ddc6ae1752ce4bdf02be41",
+ "dist/2023-01-25/rust-std-beta-aarch64-linux-android.tar.gz": "54fad0afeead88e1f33eaada03b14710052c6fa0b7130dd87463d3670f1d9fb3",
+ "dist/2023-01-25/rust-std-beta-aarch64-linux-android.tar.xz": "5fdd761ca88de80754cf3e1221db141204f79e6c2aa57c72c0879af3b87dd0f4",
+ "dist/2023-01-25/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "27196acc8f1ab9d6843b673835927c16d6730a8daf96b1f05959884ac53232fe",
+ "dist/2023-01-25/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "0ea12b5fade681173aa4795399710cf5ff21d58f5f2fe54eb8d2c7516ef387b8",
+ "dist/2023-01-25/rust-std-beta-aarch64-unknown-fuchsia.tar.gz": "7bd0d57ba438868635726bad30fea7a52a5c429e77329bf2977805872deb1be2",
+ "dist/2023-01-25/rust-std-beta-aarch64-unknown-fuchsia.tar.xz": "8520674b4e10a6948b25dc0c58369e921a68c48a7b961bae510ac36e5c29cfe8",
+ "dist/2023-01-25/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "67c5668ce3427245821e53ea976201ebc23d1cb3c1a35a0d725d935de303e8a6",
+ "dist/2023-01-25/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "38236c5e562995e1aadd25151513580a2a7c7828df3baec0e0cccc0f6a856c2a",
+ "dist/2023-01-25/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "a5453d21e3620701a957208c573d718872c3909c2c4f9e83be33e14d36677cda",
+ "dist/2023-01-25/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "751928d0f640e3b77e2fde9cda623c3e9b3bca7de742100fc1f48388e4d22d8d",
+ "dist/2023-01-25/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "5a036c4d9cbda730e6f2af8c4912506659d1e3065b4d72050cc5b18e442105ea",
+ "dist/2023-01-25/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "2adfb04a0700dd3503527a80eb5ee71733b0fa2dbe974650d450d4bc3b5c8b0e",
+ "dist/2023-01-25/rust-std-beta-aarch64-unknown-none.tar.gz": "a92fa3278a98de5ab93d1f487863453dbe60bb31158d027aaaef85adf1f62924",
+ "dist/2023-01-25/rust-std-beta-aarch64-unknown-none.tar.xz": "1c0e523505aa9dbc07ec867ff8527dde29a706868bb55694d62e31924429e235",
+ "dist/2023-01-25/rust-std-beta-aarch64-unknown-uefi.tar.gz": "4adaac4b13c8d8170b59913230ac9e313ae48400b314d2ce10c138631626728e",
+ "dist/2023-01-25/rust-std-beta-aarch64-unknown-uefi.tar.xz": "2a2178e4e55f35ea5147f66d36450f9694416c0fbae9b776f39f405a1ab31cbb",
+ "dist/2023-01-25/rust-std-beta-arm-linux-androideabi.tar.gz": "17e4384d3a229bc452897e26400016c70912feb7e6ac2991a256829c5b391148",
+ "dist/2023-01-25/rust-std-beta-arm-linux-androideabi.tar.xz": "e57afb560be9a93faf5f0f852eac5cf5b16e2c05383d995a4e6a249367ee4567",
+ "dist/2023-01-25/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "d5a7c8f2fd9c3a1baa573b805334e5446605d2aa4589262f67e321c0590ef19e",
+ "dist/2023-01-25/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "1e62c48781111afd20fb1e015a4f611c3a3301762fd9e64e49beeb6f2bd14c8d",
+ "dist/2023-01-25/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "9e62d990466900818533af63479758f01f6e914d6ccb7910639c6fbbd49ae803",
+ "dist/2023-01-25/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "e685b0f2acf33c2eb58ac1e1a526787ee9df2f0bd1a1850581cc681c41a3ef0e",
+ "dist/2023-01-25/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "7a02618c26f17076add562a9f8792d170fe60190d1868703936e37df3af882e4",
+ "dist/2023-01-25/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "d8988dd528dcc19742b703d44dff4ebcef71cec66eaae39768434d77e53557eb",
+ "dist/2023-01-25/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "882e8f09cf68f135a29e64d0eb50727e4ac56939c4cfbcc3d369b928be442099",
+ "dist/2023-01-25/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "7d9b1ebaf89cad6024f07543519dde11da15eab0e2de3df88543156e4a44c48f",
+ "dist/2023-01-25/rust-std-beta-armebv7r-none-eabi.tar.gz": "a7e73661652b1feb9b1f50d271ebeba2938c169c8add96add8a26ded3d8468f5",
+ "dist/2023-01-25/rust-std-beta-armebv7r-none-eabi.tar.xz": "2a80ab44cb2f2b9769f52b6ddc5ffa4c8994092b18a7fb3125cdfaecb4e1a578",
+ "dist/2023-01-25/rust-std-beta-armebv7r-none-eabihf.tar.gz": "f70b0f86c783cc771700dc1f59c43e53b0de2d57775fef5854cd97fde4406b11",
+ "dist/2023-01-25/rust-std-beta-armebv7r-none-eabihf.tar.xz": "07214e7295be853fc7859481fcf94a4b20cc3bc2c022bf1783ddea56e30f92de",
+ "dist/2023-01-25/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "72be8b0740b14edda6656d2b5cffc69dea01f9bad7fcc9202586a901376116b2",
+ "dist/2023-01-25/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "42fb2607f1c7402f4d32be981cb5c0755be2e36fd0296b3b2753eecae98e5cc3",
+ "dist/2023-01-25/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "ae9ec6f3c3444e5b14103db8c04b95597705fe44c68c253c75383b47da4094de",
+ "dist/2023-01-25/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "1e0f7f1ccf9e4f6cc010a096d01f3e6056f1d4b0d319f5699dc67cad2f889d4a",
+ "dist/2023-01-25/rust-std-beta-armv7-linux-androideabi.tar.gz": "6e8b70d2606902b369dfc263ee25343fa3c71c4081f03066822e9a2a260ac573",
+ "dist/2023-01-25/rust-std-beta-armv7-linux-androideabi.tar.xz": "e3f9052bc831ca0a9b38a3da3be846113c6ab2c4f320ecdba489f0eddfc7e47c",
+ "dist/2023-01-25/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "e858e836806f3641c2f1074e63ce88771cdf135bca36d7c0d3dec0d1a4c98f8e",
+ "dist/2023-01-25/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "becfe9addbca5bf2123d12e70007c16c036c79fb299de2ce8da067d0f21b0f74",
+ "dist/2023-01-25/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "eef38b595752add74cf3bd29326116e33a0945115d08ced77e603c5bb46e72c0",
+ "dist/2023-01-25/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "77e5cf7b344e590b9a15b2c160473f7c212304f624ed9aea8c7a8fd5e0fd787c",
+ "dist/2023-01-25/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "2a70ffd7f8f3289e005c0f72e2c127a44f8f014628df7ac01b4b0ae2fc61a9c9",
+ "dist/2023-01-25/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "97e2ae0072d5ae01644eda9a0c3438e78da27bb2f78d843fd626d3db36a6090b",
+ "dist/2023-01-25/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "7a30075e86bbd33241120dcf078b31ca9ec1877788db2c5700f4752cd447b587",
+ "dist/2023-01-25/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "2c1dfbc1361f030a3a116936f3e43e2c3adae2529feffc98a76e78fdad3572d9",
+ "dist/2023-01-25/rust-std-beta-armv7a-none-eabi.tar.gz": "aafe7ae2fc49e2c4ae9e1e008700f399f397dfca05d624dac4999f6c733ae2cb",
+ "dist/2023-01-25/rust-std-beta-armv7a-none-eabi.tar.xz": "d4bde0e0db35cb07134f6a94eee24e4359478dec9054e8a3802440eed68f60b7",
+ "dist/2023-01-25/rust-std-beta-armv7r-none-eabi.tar.gz": "fe83fe1f0b051838767589ecc9c17915441a44cd77226c9be26e9a63951bce2c",
+ "dist/2023-01-25/rust-std-beta-armv7r-none-eabi.tar.xz": "94eee8d1125537ebe1002c424c686c50996c03ed31d0a1275d49fd7ef0420ae1",
+ "dist/2023-01-25/rust-std-beta-armv7r-none-eabihf.tar.gz": "6ea9fca06fdb82026505c85a7bf7ad8be01926096be63c6cf20c5625c42df7dd",
+ "dist/2023-01-25/rust-std-beta-armv7r-none-eabihf.tar.xz": "70459483493bbb4cb2cc4b2af0cb012c01c47afc214643a588cf894a028a0ceb",
+ "dist/2023-01-25/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "27d86df76c05de73d0ff9542d6904f03ecbd2cedd3a9d6a9cb654dcb78363514",
+ "dist/2023-01-25/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "24b5a81721fe20849bdf075d39a99c0e80a21178327f9fa96b21649c99486213",
+ "dist/2023-01-25/rust-std-beta-i586-pc-windows-msvc.tar.gz": "3740517ab4573f77d5812c9b9c04fe63eacd29e56ea7ba5c5f335ad66026bd30",
+ "dist/2023-01-25/rust-std-beta-i586-pc-windows-msvc.tar.xz": "6c4e780249dcf8b306f8fab3fddd232724248b2670113dfc14c7823781d669f5",
+ "dist/2023-01-25/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "15fc95314219ac5b38f44a4ec3568fbb4ce66d7ff7b63cdf1fb7a8b058f2933c",
+ "dist/2023-01-25/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "b1a5ffd05afd400760002da124a8e5c86d091db574bf1ccf255d86b2515789e8",
+ "dist/2023-01-25/rust-std-beta-i586-unknown-linux-musl.tar.gz": "ef3551edc72cb79e776c7792346352eb858f3e3f7ee1c261b47ef974e52d9a2f",
+ "dist/2023-01-25/rust-std-beta-i586-unknown-linux-musl.tar.xz": "0e1a8e0ababab458af0a329e14398274fa55bf0e6ce2b2a0a515e5f6d12d6f34",
+ "dist/2023-01-25/rust-std-beta-i686-linux-android.tar.gz": "74a26b7fee3e0b95f4f0e065bcac58b865abd5f9abe14e42b2263bb0b87aee69",
+ "dist/2023-01-25/rust-std-beta-i686-linux-android.tar.xz": "c7df97d2322f5f331d349e35091ab5a61fae8dfc16781f1a74849c7c1e150293",
+ "dist/2023-01-25/rust-std-beta-i686-pc-windows-gnu.tar.gz": "396ca6747252adc4e6d41764df00418de22c22ee77823836c4fa3f1bd7cae869",
+ "dist/2023-01-25/rust-std-beta-i686-pc-windows-gnu.tar.xz": "4536de17560a21d543f81f6bdb25581a3b145b792531590a6ba35464e95c6389",
+ "dist/2023-01-25/rust-std-beta-i686-pc-windows-msvc.tar.gz": "da11b2338bacffa3940497b20fbb2544c0846696925d59cf9d7cf4514dedbb81",
+ "dist/2023-01-25/rust-std-beta-i686-pc-windows-msvc.tar.xz": "5bd5cd665f9e3d92f26998694c12b1f0e53df8ca9ef305c4cc48dd81bbe181f8",
+ "dist/2023-01-25/rust-std-beta-i686-unknown-freebsd.tar.gz": "b1553f92e0d0891717635136ad698a017c6aaab07a58183284752ff5480b37bf",
+ "dist/2023-01-25/rust-std-beta-i686-unknown-freebsd.tar.xz": "d6d2a550d36028e5adf62b875fccbae2f78546828de880e5bea33effca22edbd",
+ "dist/2023-01-25/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "3d9f9c3108d45f95ebd12c284147111155cd3714caa555548111fb6791c7ef1b",
+ "dist/2023-01-25/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "a4d9ee2238037d3ca5d4a9dd51c04737ecc2a12dc0be1e2996bbe46d7c1cebb9",
+ "dist/2023-01-25/rust-std-beta-i686-unknown-linux-musl.tar.gz": "9380bbf6ac2d745d1b7c3207c2cdacdd7bef0ff225e3ee5f22e46d826835b17a",
+ "dist/2023-01-25/rust-std-beta-i686-unknown-linux-musl.tar.xz": "517232f4e831f5305e836cc0666adef721c1b68fae80617a57bfb56405e343b9",
+ "dist/2023-01-25/rust-std-beta-i686-unknown-uefi.tar.gz": "1e6bfe0d160e3650a1a453de57f51673a6e04f9348f361fe08d2e96fa89d058c",
+ "dist/2023-01-25/rust-std-beta-i686-unknown-uefi.tar.xz": "f19c1458ef1386540cffca6cf7485ad22c38f0e9ee8a62e26a4e10eeeddb2a36",
+ "dist/2023-01-25/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "6169b653843ce79f799a99fc7f147bf8315688214dc47a64aed792f5ca274ffa",
+ "dist/2023-01-25/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "7f5e0f0e02c51dd88b9b819d1ae370e922eacf2523dd0ae664cbd8d79b7cdffe",
+ "dist/2023-01-25/rust-std-beta-mips-unknown-linux-musl.tar.gz": "124c50ad3ca4da2c97a5e96599762d7fad6701d0193b4a1ba3249c3a67d349ab",
+ "dist/2023-01-25/rust-std-beta-mips-unknown-linux-musl.tar.xz": "0a07005e369def1cbc8d49cd2904a1fd60c23771eca700e9b4abc49d2edf74a6",
+ "dist/2023-01-25/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "5278c6eab22d49d033595f8b98cccfcb89fa8827ef3a8ce487e78c9f74452d2b",
+ "dist/2023-01-25/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "206a55c0e4fb54ccfe2f372888bf42212352d56a7f1b3ba6628aec130b325573",
+ "dist/2023-01-25/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "f64069192d200f852e82735e239cb678fae027a7120e9d79c136aa4a3887bdb1",
+ "dist/2023-01-25/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "b31af554724c4582494548efda53dbef35db5cd3609104550ab2eee1bcb3f327",
+ "dist/2023-01-25/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "8445183d07e397b5bcd0f45fbb1b58ff22dc0901d0a1a3637761929f6b0e0364",
+ "dist/2023-01-25/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "5919f229d0ca138205def6752109056c989493c3a2a241cbd891bfdd84f8c7f0",
+ "dist/2023-01-25/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "c72e51c7b1a5720dd74a923fc2ce1caaff1da484c063b50f96bcf84db529326f",
+ "dist/2023-01-25/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "9a11cb1d587e2389531edff732c205a653e43bc62132cf697cb9fd04842558df",
+ "dist/2023-01-25/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "682fe8fe1e3dad08190e8c42fb2df8fc734a42df081c59d0b30f4cc9f5fcef8d",
+ "dist/2023-01-25/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "7eee1fff997cd847aac8d6c61cad4bc572d3069dbe59ce2a06c39d6b63346d34",
+ "dist/2023-01-25/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "0b5c68bb95668394dda1c910cf99835007271b5598d4652c7c6b974c6c0b2acd",
+ "dist/2023-01-25/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "411c8552901b80720a3bca0707eef475a7ad1650d34cda0b29fedfa9fc9b1852",
+ "dist/2023-01-25/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "187fef84302125e38937cf390bdf26d40ef98c6d06fd5893db8adceab3e75f04",
+ "dist/2023-01-25/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "83ce613db91a23549e4a1e1d5e4c24ad3ca7ddfb586b45d25e2bd85e67a19390",
+ "dist/2023-01-25/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "785bdd67b22af15637696a03b6a4a917f8195049a4bda14a88dc48e6c3101a5e",
+ "dist/2023-01-25/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "df034c1d2baea51f6756e1efef58db81cda5e795691c3a7175cb3b61edd8f33a",
+ "dist/2023-01-25/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "24d020c96db72a49c39dca1546a683d4d2134718dafbd74fb846dc77b30cf78e",
+ "dist/2023-01-25/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "a798a58bf5723f86b08a11c92f901cee246c5a0af06c4f7e08b303c7fd6c0354",
+ "dist/2023-01-25/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "0c383e01f53b5bf85301c46978493e94aef2eba98a966ea283771de7829ea492",
+ "dist/2023-01-25/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "61040426e2eb9950a3487109977ebfe66c134f5394c95847df222ff24c61563b",
+ "dist/2023-01-25/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "ef44851d420b5ee0cc3351084c9bc645e4caba447c8dd737840315687547657d",
+ "dist/2023-01-25/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "5cb083baabc7f33c515f2dbdaafd49465c85888d97af68dbd2bcd08a3e70e016",
+ "dist/2023-01-25/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "96bd2d16b470e6377c9c2894b24e77d9f7b51dd54d5369dc361791153a9d1519",
+ "dist/2023-01-25/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "93af94b167327c431158be466ff47b3aab8a77319bf7bed8bdbdedb4633a8e67",
+ "dist/2023-01-25/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "57071d1f70a444a1b4b26b2a579e6c6324522893de60be9e97fe281e8878f276",
+ "dist/2023-01-25/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "a75b8cbf062d1c6fcd8b2089c83f82b75247ced44793272ec56849c4448389f9",
+ "dist/2023-01-25/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "195fe88c1b4b77cb12f566e27a9d3ff25ed2edf5f26be9b3b3dd0a88ac6f5e3c",
+ "dist/2023-01-25/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "76884a90032874b98b0f4f873818dd90befc91d2ed96945120a1ce5a6a80c4e6",
+ "dist/2023-01-25/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "017a6896b2b0e534c1c80f13eca4a3a570560800a117ea2d6b4ae0e6d665a969",
+ "dist/2023-01-25/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "ac712a5b5cf3cd2eb2ae3825e75a5d84c5a899f86a104195b200711da15e9e53",
+ "dist/2023-01-25/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "405fd311dec82db95adea38b3ec0e53454aca72bafd58f7960f8be25b50f9bc6",
+ "dist/2023-01-25/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "0a3c8988561da39a817a3dba8115237f1c4ab6642f1925f52b7398102184ec7a",
+ "dist/2023-01-25/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "65b8a84d7355f889de036b1ce760068c2b81d73b43e5f7da29f9706ae1806a89",
+ "dist/2023-01-25/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "1c8843868742c36a5e9f6839275b4ad2b8a45f587f18f798448a674e0b0841cd",
+ "dist/2023-01-25/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "b225da38b37554abb5a7f098be013b2e5971f9f34c634661d3244dad3ef1315f",
+ "dist/2023-01-25/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "78018c4b996f7fd8bcaaf6073c84a3180250840263b54cc68ff6d195855b0727",
+ "dist/2023-01-25/rust-std-beta-sparcv9-sun-solaris.tar.gz": "468853e0d54a486aa0a25dd9fd2ab47c08e48c6aa47838c350c108738d7ca812",
+ "dist/2023-01-25/rust-std-beta-sparcv9-sun-solaris.tar.xz": "c59fec4162cbd9204d73f7aada19aa459e23f3ed73584203d83d52439a982382",
+ "dist/2023-01-25/rust-std-beta-thumbv6m-none-eabi.tar.gz": "326a3fe4191366ad170f44bfe726d80954024b1a3c7560d75da77bd16b44cafb",
+ "dist/2023-01-25/rust-std-beta-thumbv6m-none-eabi.tar.xz": "9c59dca2473fc377b65ce74cda0a3a064cf9fe07b1fb1eca0a4641b6de397d0a",
+ "dist/2023-01-25/rust-std-beta-thumbv7em-none-eabi.tar.gz": "ba2a8bd5d55ee9eefb6f5a5bae987822bf763783ac0374b97c823cfbcced622f",
+ "dist/2023-01-25/rust-std-beta-thumbv7em-none-eabi.tar.xz": "e8b7df90ffd190d0122d20d4c070f42273bab2da67745f831934fbc09730f34f",
+ "dist/2023-01-25/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "183f0945d1df7a68c45bed842991486ffee21a03313e60e89746ac4122ca348e",
+ "dist/2023-01-25/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "039816d5dc555e28fe45183a09a77a6357ce571111041740d0f95e89489b7cf6",
+ "dist/2023-01-25/rust-std-beta-thumbv7m-none-eabi.tar.gz": "22c48ee80a14149c2635eb344f74ec5765bcc5b7eb0fa1c7ad55b25c016c0934",
+ "dist/2023-01-25/rust-std-beta-thumbv7m-none-eabi.tar.xz": "a690f9227a3587f5dc143ab86a1ea7c83777a36b1ff18e877801c73745ff80cf",
+ "dist/2023-01-25/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "16978fed1307ce642c4c9b0acfb09d9dc532b64a72d25e2d1f3ab3afbcb673b9",
+ "dist/2023-01-25/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "c1cb59f61a45cb2a842d235762d244a4f4b2f078bc9cd1fe6ef5c632c665573d",
+ "dist/2023-01-25/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "7d005cc7f199344bf7ecbcb5d3a4acc8ef42cb61d18fa091fe001872a69ab4bf",
+ "dist/2023-01-25/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "cb567b761f1d78188538e1a5cf4f01aadd641dfec3e8c1a3e2ff2d5e7b930070",
+ "dist/2023-01-25/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "c7c83022f3772e1f7af9e8883a1082695f17956ad4b2d4b8fafeb2a8b9ec6ee7",
+ "dist/2023-01-25/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "392e9bdc0d84e9b9ab83f7118abd07ca39df9fb5a8482f6c9a1bb8969db2c1b5",
+ "dist/2023-01-25/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "97f59b364d4a3491f612217f455b1e7285691e12e73e42d4e7a074c301a973f6",
+ "dist/2023-01-25/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "4935afc5e64589ca8f06d3b8bda2ccb89901a60334b50c45be0b760d6f9f58a8",
+ "dist/2023-01-25/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "eb165b5f5924a077c563d7e8e2eef96eff9398432748070b87f4baf0d04388a3",
+ "dist/2023-01-25/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "9c2bf943142fb554fe2332cd7d12ebd568b8b59e06df73e45ad35da27400757e",
+ "dist/2023-01-25/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "bbd4bb99dbf9b8a178ae767962877bbe8dbd73175e68db654d7eb208c0f10cff",
+ "dist/2023-01-25/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "265ef776729a591e3867947eb23384aeaf02887a2f03f893bb21489bac1aff88",
+ "dist/2023-01-25/rust-std-beta-wasm32-unknown-unknown.tar.gz": "177edb18d11154664c510f27fc02b566c40320b5604587975b0897a70647be3d",
+ "dist/2023-01-25/rust-std-beta-wasm32-unknown-unknown.tar.xz": "7105e29d9a6540ec629a8844407b84624efed5e2a2642a5fc18fa8d73ad5356e",
+ "dist/2023-01-25/rust-std-beta-wasm32-wasi.tar.gz": "d13a3c25523c269b2515d254558af46bb35fe24d796bdd00aafcc84c63f3ac69",
+ "dist/2023-01-25/rust-std-beta-wasm32-wasi.tar.xz": "97ee2ec6214ffc91e46e4e590acc8dc4e69a7a935a64a0e2af31940d745e2ac1",
+ "dist/2023-01-25/rust-std-beta-x86_64-apple-darwin.tar.gz": "d184abb149484d78b713cd1d0f94db958dc4ac182eed453178f669c44856c823",
+ "dist/2023-01-25/rust-std-beta-x86_64-apple-darwin.tar.xz": "e3c448e63d87842f42f99390d7d0ed18c13e03a226967e8f2e9ef8c764d10318",
+ "dist/2023-01-25/rust-std-beta-x86_64-apple-ios.tar.gz": "04c884f5f4c4a6d1dfb0941b62e16ec5516d42e6ecdb7b3b86f23994b8c7b295",
+ "dist/2023-01-25/rust-std-beta-x86_64-apple-ios.tar.xz": "6a3c0e72376a2f1654e7ac08dc5e38794a91b432450c7bf978be97ed10f1fa61",
+ "dist/2023-01-25/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "fc41a378f93c5bf1280c52d21f495924c2e76925f609356b8d27e43d0650d2ab",
+ "dist/2023-01-25/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "ab6bd497938262cae110bf9f39cc94f5ef1ba831db19e63b4d60c8fef7f8dc90",
+ "dist/2023-01-25/rust-std-beta-x86_64-linux-android.tar.gz": "d990e089f838d0158fa2ba3ea08153edb48f4346e682f0fdcdfed1b37a186b2d",
+ "dist/2023-01-25/rust-std-beta-x86_64-linux-android.tar.xz": "0b6e71cdcef8c32e649dc209dbe9bc30a0864aba4fc85d0d615ff5c405204f6b",
+ "dist/2023-01-25/rust-std-beta-x86_64-pc-solaris.tar.gz": "3cc30012778b45a27dc6c92f5cb0955461dbd1aba130c191c20a510d29bf2c00",
+ "dist/2023-01-25/rust-std-beta-x86_64-pc-solaris.tar.xz": "0e3f033b01d1223d9f55c86497c9625c4de36953b6c269ca622c96b2fce09afe",
+ "dist/2023-01-25/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "18a61cd3593bc67eeb93b615c4585e18495128cd4f50933776705c6ff5cf1616",
+ "dist/2023-01-25/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "8bf3998dfd69a17354dd79dea20220f405a2a116842d3813fe033cfa5a6aafdb",
+ "dist/2023-01-25/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "76137f8246ad53adaf26d739c91dd3bc5820697a0c1d2af0937328bb5e6536b9",
+ "dist/2023-01-25/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "2febd8119b376da8f2b1baf3ca63b97d11a17e1a766986ff1d6dffc522cb0081",
+ "dist/2023-01-25/rust-std-beta-x86_64-sun-solaris.tar.gz": "b5769729f089ea5cd5fb5ba1995a0e18dcef21425b69b7e952d42c5bdf0253c2",
+ "dist/2023-01-25/rust-std-beta-x86_64-sun-solaris.tar.xz": "a8593120f87887738390e0ec9ff1d72a743a77dc17a33276e7bec7b04f45442e",
+ "dist/2023-01-25/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "269fec46599b8839f3a81c6cc85fbca7a7e86cb661e5cbcbffb853ba674ae1cb",
+ "dist/2023-01-25/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "20c2d1d3e64f56f00c237ae261d5880a7fd7c6f1e2360dc7fa0039b3ea932c66",
+ "dist/2023-01-25/rust-std-beta-x86_64-unknown-fuchsia.tar.gz": "d64735ce43c75d7c741f9cb7754812f09e21706be8bd0931d72b09916d312844",
+ "dist/2023-01-25/rust-std-beta-x86_64-unknown-fuchsia.tar.xz": "f501f199bfe1120901e919a14684e57f0723b59ffb5cad79f501834a63df5570",
+ "dist/2023-01-25/rust-std-beta-x86_64-unknown-illumos.tar.gz": "a80058880e7441e2cd6bb77a7a284902d15dc21d8f0b37f2af3b3da31f07f9f4",
+ "dist/2023-01-25/rust-std-beta-x86_64-unknown-illumos.tar.xz": "17d07564595b2dbc9eecc8271d3332bef81c7a57138559740c606d2181777f89",
+ "dist/2023-01-25/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "0e4c01e6438fc005ba7177d33cc0dba8646eb51a47da06b079ef9fc2e264f052",
+ "dist/2023-01-25/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "1f95934a853b0ce1f4bc50ac86b1ae74a34acbae8a64903faf6f7ba63e49051b",
+ "dist/2023-01-25/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "431fa66d45ff345f1fb2e279eb52ab24757ed3971f049f9a04a63b228a417f59",
+ "dist/2023-01-25/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "6901b028b8df3d09e994387a810d3a74b873d2ff5fcf93c1d49bf7c3521a506b",
+ "dist/2023-01-25/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "a22d8f960e3d15886f893dd4e137becf9c84b1bb2ce500d574e5cc85f43b2b64",
+ "dist/2023-01-25/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "1fa467a1334a1cea4af8b27f7fc186eabf3a8f26091ae29b501bec6b2564b98e",
+ "dist/2023-01-25/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "50f2c04d4ee499959f52546af600c40b16a5627bb9adddeab819519231cf1efe",
+ "dist/2023-01-25/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "69084f5bf6e22d6ba232d2040bfee15b00418ab20980c716602a19134ee54bcd",
+ "dist/2023-01-25/rust-std-beta-x86_64-unknown-none.tar.gz": "5a8b98fce343e17fdfd2f3f9b4f810097cdf12430e02d65b3d1042e273f1ddae",
+ "dist/2023-01-25/rust-std-beta-x86_64-unknown-none.tar.xz": "d5db956978faa532d822609d475599c12507e5b67ac73b9a9194afb7449b9b7d",
+ "dist/2023-01-25/rust-std-beta-x86_64-unknown-redox.tar.gz": "3c4f69556a6ed2c64fd6274bfa17ff489b5e0c9f1f8d6884fe31c28c39e15d89",
+ "dist/2023-01-25/rust-std-beta-x86_64-unknown-redox.tar.xz": "feb6456b55a38b83755b281e039941d97659947b289ac2750fd3b3588cf43fd3",
+ "dist/2023-01-25/rust-std-beta-x86_64-unknown-uefi.tar.gz": "81e795c668369a3947d4d69aeb4f823c8446b09ae18c6fdc800d54aae514f27e",
+ "dist/2023-01-25/rust-std-beta-x86_64-unknown-uefi.tar.xz": "5c51b99639e5f67e01fe37a868dae17da4ff11d755434b189cc4ae81453826ac",
+ "dist/2023-01-25/rustc-beta-aarch64-apple-darwin.tar.gz": "9d6277d58b9a679d47eb80d1132d590102f632d5fdb85ba54ef653b2e602c6d3",
+ "dist/2023-01-25/rustc-beta-aarch64-apple-darwin.tar.xz": "6a49fa544dd3bc4d657ae064863b760935977674e6c837f6a7f84dc1c9dbe95a",
+ "dist/2023-01-25/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "0536b525d92007041a4d5f4b57601bcc17e1257f44eddd1e4630fbda8b5ea2e8",
+ "dist/2023-01-25/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "35621c50a8e1ce5591dfdf95b4f5e17e60478309348e67f6e3bf767b57c494ba",
+ "dist/2023-01-25/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "feb0c0534f2f78500a25906fb6f0bd5772574fbfbd23b6abea807f074905905a",
+ "dist/2023-01-25/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "fb269a472ef44aad092259352bb55b24dafc56459eacb7300fd7db0bbc5a96c1",
+ "dist/2023-01-25/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "98514e08e1a21f94028df39496e802f5b6379414dad4e7069253cd8b3f961c43",
+ "dist/2023-01-25/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "b01b5ef23232834174ea31bbf402fd4652769a7fac5b522ac28e53c469389b60",
+ "dist/2023-01-25/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "d638873a2fe3bb666174b4270a44da25a9f7f05f0a2544598556485661b51d66",
+ "dist/2023-01-25/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "7bd32b738a280b6d42fb925b5c7cd8b4ca660285ae77cf27b0ed6eafb0b0237c",
+ "dist/2023-01-25/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "8ed861c6ccc085030bb0947119746df3c83b9971e7b7c0ca43a8133700f985bc",
+ "dist/2023-01-25/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "f4ffb8ec45475b96815eccb657d9a5f443e8067a2f7b50a18eaf80c8a9cd1944",
+ "dist/2023-01-25/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "e6a809e4e255e265aa54ac730655569e93b0227037e5eebe2995e6ed13c4a2fd",
+ "dist/2023-01-25/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "0849a22e9d82c3cacfb39c5067106767bc40380e231842e968770b7d79dc9376",
+ "dist/2023-01-25/rustc-beta-i686-pc-windows-gnu.tar.gz": "348a94bb0048a2de0764ea5ebc83a6578d1f63f4edf8d6627cd346345cb3beda",
+ "dist/2023-01-25/rustc-beta-i686-pc-windows-gnu.tar.xz": "02885355eefef4a901522a441c376a59521ff91889dd6e2438cfe5869360ad7f",
+ "dist/2023-01-25/rustc-beta-i686-pc-windows-msvc.tar.gz": "56d6b9b2d0e8eb13a568b60f2b5284cbdb3efcbc921d6c318408c58d12c6ee11",
+ "dist/2023-01-25/rustc-beta-i686-pc-windows-msvc.tar.xz": "bcf405c76b2aebb76ca70595ddbe5de1faf8c34320b08cd4839db7f46dc9dc7c",
+ "dist/2023-01-25/rustc-beta-i686-unknown-linux-gnu.tar.gz": "6b5c11f41bdb8a7b596ac92bfe18e7a2410a7fc77fe7ca7036e72c563b9e41c0",
+ "dist/2023-01-25/rustc-beta-i686-unknown-linux-gnu.tar.xz": "7291ffdbce495b5d0ca017730495300a72d3341170d099b3c8abda5cb9ed190c",
+ "dist/2023-01-25/rustc-beta-mips-unknown-linux-gnu.tar.gz": "6005076b8cd38020a02cd2720e8c67491d31f50465d62d9f5148d93feb4eb198",
+ "dist/2023-01-25/rustc-beta-mips-unknown-linux-gnu.tar.xz": "1b421c2addb488faefec78cdcbbaf03a9c45640f4ba6740bbb1afbece3e30ba0",
+ "dist/2023-01-25/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "2d1f7463d3922238c189c5f669b8f4e80f85f389f5edca000b63ebf041fb4222",
+ "dist/2023-01-25/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "29dcad8e598e6b79730a53146d3d8ceb5acd0029a83216060ece931d149e9a97",
+ "dist/2023-01-25/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "c3e1527a463155bc9ed2c3eb65217c72fd067bbd316432a16a2777a444e7eb9a",
+ "dist/2023-01-25/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "8a031c5830bb8168c1e20426082c0783fa52310b22a28c5fbb5b1214adcf3bd5",
+ "dist/2023-01-25/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "5c1af72641cb7bf514f936def835ebccfa908434f9e26e6d3cf65756d68fe24d",
+ "dist/2023-01-25/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "40a95925bb98eadd7b49be71dd9fa76abf09fc16bd2d6707e3206cf7e7f9b9ce",
+ "dist/2023-01-25/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "2dfea875b3b5f3405f9df83fd5a5144b8fc93a90ba17a3ffcb437c934a9772e8",
+ "dist/2023-01-25/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "2c23590890472f2ed15df449a33188bbc7d3dc8755e8929861ccdfeb24ee0909",
+ "dist/2023-01-25/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "0b31cad32717c5c7a75069bfaa32fab82d0eb75190b0d34d2e09c221def5f7a5",
+ "dist/2023-01-25/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "939feb641d84aa98e46934c3896adee94169d8e5d8d2d97065e904aa1eac16ad",
+ "dist/2023-01-25/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "d031874dccc1fc029196bc49f7713805226be2ac03a17fc38dc2f40c7f807093",
+ "dist/2023-01-25/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "8b6f367822b14dfd341d711c4736e00ac1fcc914a3c5214209742f2543bba880",
+ "dist/2023-01-25/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "6fb98f6c504ff7278af6f840e39d1236b7209a35a3f5dc78d281c59a2264b525",
+ "dist/2023-01-25/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "1e5a16e7c67bad200e3f051aa959cd9123ad26e15443128ee9ce28151b28e7ba",
+ "dist/2023-01-25/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "c8bbed9a7319e601e9e53461665201f89aceca9bc72dcdd1e3206110d535c6c4",
+ "dist/2023-01-25/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "05af8b1637b522af7ac981d133eaf88c157a7d4ed414ce53c13bbca0667510dd",
+ "dist/2023-01-25/rustc-beta-x86_64-apple-darwin.tar.gz": "ead6472d2644ffeb7f27252e0445aa27b9cb028dc982da011069975767711249",
+ "dist/2023-01-25/rustc-beta-x86_64-apple-darwin.tar.xz": "3777d00c129c51b8980afc2ba1b1605f58490ec4d5203609d260e05ae5801182",
+ "dist/2023-01-25/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "5871e7fa9b9af9af9ccc405866774db110dc5ba8b66649c87f546139c383cea1",
+ "dist/2023-01-25/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "9804f9a57acfa97db3a33fa7f77f5a8ced7d6b9e5013e61aa76287dfe45d9223",
+ "dist/2023-01-25/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "3a7387c88e4a17e331d8f8800e6be0cf113242edb2b760fcff0dcd2ff97c1ca8",
+ "dist/2023-01-25/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "12becb176b75b9274a44ccb22a4859fb8cb52df2cf954011c7294d22dc2e8721",
+ "dist/2023-01-25/rustc-beta-x86_64-unknown-freebsd.tar.gz": "262df9ec15e8b14d1a2959f9d386717147af17612ae92762916e9e195ac83c7f",
+ "dist/2023-01-25/rustc-beta-x86_64-unknown-freebsd.tar.xz": "2647f9420cc4b2a2a94b32ef6c7d88285bb50c3b04bbd29bdc11f6e5fb8f9c4f",
+ "dist/2023-01-25/rustc-beta-x86_64-unknown-illumos.tar.gz": "82875b6f60bbdea438f0da1a162c30d236fdd32124296a83510954f89dfbb20d",
+ "dist/2023-01-25/rustc-beta-x86_64-unknown-illumos.tar.xz": "19bd296d5c116bdb620e50b6fba3c7d5a5e978f26a8f1be1afec1c6854408d2c",
+ "dist/2023-01-25/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "45b8d74f203b66d25a15e59db755918d0954a3338f08236664007de2478e2438",
+ "dist/2023-01-25/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "c047becdba71a802c1d06b31e5c3dce8efb11a9daa299e1cd03a0f9f6b48cbf9",
+ "dist/2023-01-25/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "a649445f1676acafc59b4808211aa669c9fb8093cabb7007432d0ae2f6e21239",
+ "dist/2023-01-25/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "b6ed06a8df0de6b64099fba4d1ca9478e0802dfc086308f425692ee40faa8d2a",
+ "dist/2023-01-25/rustc-beta-x86_64-unknown-netbsd.tar.gz": "d939bd071f42aa7657297110be68dd9d2aad840272bf881a1fdc82053914f970",
+ "dist/2023-01-25/rustc-beta-x86_64-unknown-netbsd.tar.xz": "5671084575291d8c4ef2ed0930b22815d6810e2378fb98ca5a0738faa76b525b",
+ "dist/2023-01-30/rustc-nightly-aarch64-apple-darwin.tar.gz": "f634a282a8388aff57d988616f17f2c511253a02d45193b03fa87167448a8cd9",
+ "dist/2023-01-30/rustc-nightly-aarch64-apple-darwin.tar.xz": "4fd6a4ec8665ba71ccf3ac7d08f9010b4e130ce496bc62548d36170786f213ab",
+ "dist/2023-01-30/rustc-nightly-aarch64-pc-windows-msvc.tar.gz": "5b7fc325745b2f1e22b1a58ead8163314c3ec06f4a30483bf7ddfb57f811a2d4",
+ "dist/2023-01-30/rustc-nightly-aarch64-pc-windows-msvc.tar.xz": "4aa8d587ebd53bbd11c33f263991328576977d801d5b6eccf56147301ea0f52e",
+ "dist/2023-01-30/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz": "7838bf7da92539b0329be0b9b80f0738df3617e982f539326a6a99892eb905f1",
+ "dist/2023-01-30/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz": "636af094f94de9baa3edd5f9e1b7655e0bb7f6f23d24d6f389a3abeab7360e00",
+ "dist/2023-01-30/rustc-nightly-aarch64-unknown-linux-musl.tar.gz": "51b8a8a06244ee37d2c37e84154ff87132b4f90a1e62a8c9454ed5ea5c296c1f",
+ "dist/2023-01-30/rustc-nightly-aarch64-unknown-linux-musl.tar.xz": "cc18ce5f4f461a830c725ca8ddccda17bd726374198c487810eab8d36a8f7c98",
+ "dist/2023-01-30/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz": "e2d7b96bf5e2feb47019c63067dbb1627bf26ac4e730774d29ea9f6967edae3a",
+ "dist/2023-01-30/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz": "0483f07f1a53949c2f04e2766f53fe9138ce126059f650ac61215e6a84c5fd57",
+ "dist/2023-01-30/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz": "d3ad417041c432438f1ed56a2324ab412dca7631a74da03e0bc72cd28e69f197",
+ "dist/2023-01-30/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz": "f029fafa0635efec9065d76780f003e2c4220c7b6ea4b426ebcb57d943403998",
+ "dist/2023-01-30/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "dd2ee13ccea00c23ca2f90872c7c31a3a1ef008962db9cf8066acc130bca778f",
+ "dist/2023-01-30/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "dc23fa4c0268a7227e0f9e4941376ffc4c64c0614622f442da10dbb75e014dd4",
+ "dist/2023-01-30/rustc-nightly-i686-pc-windows-gnu.tar.gz": "d4b02e59373fe60ba06e979f784bf1b8c94ca4a5ee471ed83814623db9e14af6",
+ "dist/2023-01-30/rustc-nightly-i686-pc-windows-gnu.tar.xz": "5355e1bfdddd2a56dd0c882fc492e4d571e5b29636d381e848102e996ca9b680",
+ "dist/2023-01-30/rustc-nightly-i686-pc-windows-msvc.tar.gz": "02a43fb72394837461770c1b472afb534ac03bac9cf23bfdbba8227cf879dabe",
+ "dist/2023-01-30/rustc-nightly-i686-pc-windows-msvc.tar.xz": "78cbe74bd0f7029b01e3aeb451ea6bbc1656db1fb4a80caac4cc27b6e0144b79",
+ "dist/2023-01-30/rustc-nightly-i686-unknown-linux-gnu.tar.gz": "7fa9a3e3d70a6c15bfd00a0b5a83d73f4e952862b8ef1d6837d3598c4cee8752",
+ "dist/2023-01-30/rustc-nightly-i686-unknown-linux-gnu.tar.xz": "76b3abe5c532785ab80804461204280e6d853773c62956f283f5dc88130e310c",
+ "dist/2023-01-30/rustc-nightly-mips-unknown-linux-gnu.tar.gz": "2aa78ea99fceb90e568f6c46881623f5088afeaf47ba204abf2ef755397e84eb",
+ "dist/2023-01-30/rustc-nightly-mips-unknown-linux-gnu.tar.xz": "6abe1f28662aca904b1fd91e46e0441ba7b4f66f1e7757cab93a0d73012b36fc",
+ "dist/2023-01-30/rustc-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "3afadbbe1b073ee2a81609c87c3d88a5d7344765b970b8c48dcdfe539c5ba540",
+ "dist/2023-01-30/rustc-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "f1eb22696c376dfea266090320e7a941986f8de2176b6ceb6dc0f0452994ae4a",
+ "dist/2023-01-30/rustc-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "c7f548350e118d4281a8a6ac8044c19eb1583683490b0ea6fb9f5f27f5e3873a",
+ "dist/2023-01-30/rustc-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "aad40926a20ac8bda9e534d63e180adfa355e9df22a1068310cf9ae667ffd0ad",
+ "dist/2023-01-30/rustc-nightly-mipsel-unknown-linux-gnu.tar.gz": "4778f49dceea661baaf641531946dda47d8ddb7f801cc63afbec37a86d45a0f4",
+ "dist/2023-01-30/rustc-nightly-mipsel-unknown-linux-gnu.tar.xz": "1ba09bcefaf5ed5a3029230ebc3e9cad33626b38553451b952ef215c68a98e34",
+ "dist/2023-01-30/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz": "6efe1f619ad49c94b3e6fef2a51893cec88ecacf31d963576e6343e8a050d20d",
+ "dist/2023-01-30/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz": "971fdc824861c98bf223fb2c733e780cf87c90f3a5646561f4e35fa8cd068c7c",
+ "dist/2023-01-30/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz": "10741ef62e00541a85747db16f830c71ffa1dce036a95bc43df433e450f96602",
+ "dist/2023-01-30/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz": "b8bc80ee97c54e428c51f56e30cdd610fb07f41bead0409b089fe56237bb0421",
+ "dist/2023-01-30/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "f8f52abf57943895d34ffe2157f863bbdabaf804969baa2624e38a13648d43de",
+ "dist/2023-01-30/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "7dfb9af100df05b558c873b5440c532d28de44fbf8c7d933c29481eef6693539",
+ "dist/2023-01-30/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "9454d78432ce8ad61f8cfbe448654d8acddda9c596c36c7863631c638aba949f",
+ "dist/2023-01-30/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "c69f1b0062aaf566d6610e6b19335ed002a281aa65b34c1be001a875b85f76d2",
+ "dist/2023-01-30/rustc-nightly-s390x-unknown-linux-gnu.tar.gz": "92184254f00348bfaa7f40f8a07b585eeb6dabc02e4dff3351cb395b354a930a",
+ "dist/2023-01-30/rustc-nightly-s390x-unknown-linux-gnu.tar.xz": "b41eff99cf9b9851ffbf496ba6dc892d5dfd124da68c91db66d6fb77b19370d4",
+ "dist/2023-01-30/rustc-nightly-x86_64-apple-darwin.tar.gz": "8d901d7c2ed293a9e2d2fb8849edee50e6f6e3c5a049fa91cfb13f8f16571b7e",
+ "dist/2023-01-30/rustc-nightly-x86_64-apple-darwin.tar.xz": "d472dc97f3242d243f584efe113f23e62ac1f53677fb3b3cd1749adb65a6635c",
+ "dist/2023-01-30/rustc-nightly-x86_64-pc-windows-gnu.tar.gz": "9259adfb75f90cd43c99f253aaf4b242afe941c4075eabc6bce824c3337b4d2e",
+ "dist/2023-01-30/rustc-nightly-x86_64-pc-windows-gnu.tar.xz": "e42b3e9a462004296e53ed3e71403caff98b3718ff15508d913e0a25ad02ea3d",
+ "dist/2023-01-30/rustc-nightly-x86_64-pc-windows-msvc.tar.gz": "82f615142be1fed6ffd5c9a6f2d1d3fb73ebf32801348cf6279991c0a76b771c",
+ "dist/2023-01-30/rustc-nightly-x86_64-pc-windows-msvc.tar.xz": "2a4e2aad343062379334ee1a73b657656e0c03f0490c901806c864ea8a38ebe1",
+ "dist/2023-01-30/rustc-nightly-x86_64-unknown-freebsd.tar.gz": "2a8fa3a6a104bd35de9a83d98786e7acb7614e0b830336adda30e8d1f1cade69",
+ "dist/2023-01-30/rustc-nightly-x86_64-unknown-freebsd.tar.xz": "37327a8b756918c25cb799f2e5742a07145e4c1e424442a5d975e99aff1f303d",
+ "dist/2023-01-30/rustc-nightly-x86_64-unknown-illumos.tar.gz": "8be0295e8b89b6e8f465b0825b0625232c7624cb897efe3e0bf4da222799349c",
+ "dist/2023-01-30/rustc-nightly-x86_64-unknown-illumos.tar.xz": "8e515082490a64d83771131f4fa5fba8b021d205b56149459e2f2da7584407e3",
+ "dist/2023-01-30/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz": "c105e3dabdc7bebebadc6ffa5b6f3f962057948cdac6647cd5adf16d66982701",
+ "dist/2023-01-30/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "09b82ca24ff847e000aed1b2eaca74cdf0f6e533bd6655eaa302281eb7037163",
+ "dist/2023-01-30/rustc-nightly-x86_64-unknown-linux-musl.tar.gz": "e77d81b158b53a94065cd90f68e26dd12d156084b02c53c51172e02c4db58c1c",
+ "dist/2023-01-30/rustc-nightly-x86_64-unknown-linux-musl.tar.xz": "613c7eab1b998aec0673e1781e3ed78c4d038b449d879c11254b1b6d4345e34c",
+ "dist/2023-01-30/rustc-nightly-x86_64-unknown-netbsd.tar.gz": "ac8c53be048049118af9fd9d356dcc69ddfaafcd52020ea93703c94d6167b367",
+ "dist/2023-01-30/rustc-nightly-x86_64-unknown-netbsd.tar.xz": "28b1c8adfffa7863bcd8a46ef407044d06fc16b29f7b6f42072fcbfbdc779e79",
+ "dist/2023-01-30/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "f7e585d9016a012e2cde4d7e0899e52e1c410c53ed9caf6db22d13f6791ffb0f",
+ "dist/2023-01-30/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "bdea28e1700f34dc0a6e57db5f73caf6c8d1671a8356cc51096f8155f58690c8",
+ "dist/2023-01-30/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "e9988193283871e678a0d0e08cfb5bdab37d43cb0bec0e5f63a12a38c164936b",
+ "dist/2023-01-30/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "30d1bad2b730589f9d75ca3e2d410d0f9c90707526ed6a66edac92a19eb3716c",
+ "dist/2023-01-30/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "7c6c93fa25193360e28a90269439b28465b6693b6ce68ff2eb1c4209c36a9d60",
+ "dist/2023-01-30/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "4c8331d14ab428b922135690b433f97acd37291e1801635252ab5da849d42180",
+ "dist/2023-01-30/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "0fb5372bf4cc0b6388194021dc7b6a539bd413e89058c05cdc42c1dfe8d92edc",
+ "dist/2023-01-30/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "0e2452ff037698781157c30c5fd67f552e897feb1d86b7b074c195c70a6a1a3a",
+ "dist/2023-01-30/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "6c079c2dde918cf2d9f029dfb3a2a9bebba2504dfe97c5fdc0ef79022415b9f0",
+ "dist/2023-01-30/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "5ab6fa16d7aaca7e6e36caea8e11b916c089dccb511f79b7f69bba667edabc50",
+ "dist/2023-01-30/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "7b919c9132269fcde24559af58d3d2fee56d93308d731d891f89dcee193bbbdb",
+ "dist/2023-01-30/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "53d7c7d03b64526e013c11c49519a63f51562f9682039479c377c92529e5e026",
+ "dist/2023-01-30/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "c19265cc3a85cd296a85b450e2f4e4b5f3646aa70d6c70dfdfe9ef222fd72136",
+ "dist/2023-01-30/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "66159d87fd85a4534104da3f7f5c0a14403960ff2c836eb72e35bed6a1ebde32",
+ "dist/2023-01-30/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "be84f8558d15dcc802f399f44f0de58e93b28e99cf62e38c0d6e6078a8d73102",
+ "dist/2023-01-30/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "b4e8f18335aa3cba092df29c3aadef79c0b88e00f563604467cb2485e10cced6",
+ "dist/2023-01-30/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "43ce7581f50e05c775b39a6a6d297d6e8c56a40f5a5817ae4d996d319fbe96c1",
+ "dist/2023-01-30/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "2ca2b20996f1a4cbdb619393a3f544ada208caaf381748ee997a70139e52a591",
+ "dist/2023-01-30/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "229fb281ec100e68445b5a402a3d39a0947475054c4f043d55ab2e33bd3d2a57",
+ "dist/2023-01-30/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "65326115afcf1c8e07cfcb9ed294a1e5a136b998557cd60b4cb976520f84cfe1",
+ "dist/2023-01-30/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "337bdf61237c8e47909c3f14b5c8fdf3b8b14f2b265e6da45cd6b4d8180d0afd",
+ "dist/2023-01-30/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "d683349af8320d6bc9f16021fc8937920d70e99cf668ce64cad962705dd20ea5",
+ "dist/2023-01-30/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "08a1ae9e61ef097c5d5ce83e5d2bdda62e72d07b4dd21aad286413c619fefa1a",
+ "dist/2023-01-30/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "cc3f1f86997c5ccf5607c8f873c916d1158da76ff971d75e36ed8e3a87c86924",
+ "dist/2023-01-30/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "f4b7084fc67cf17b3cf1d36136aa03aa5b6af188d311684b15395f05104181f6",
+ "dist/2023-01-30/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "2ab645d5117606f2c7e8decbeae1d8855ec7ba53051144ba4783efee2c58d91d",
+ "dist/2023-01-30/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "cfa8baa60cc59ac2750f799d33b06eb399d330f318783907717a9e360fd7d85f",
+ "dist/2023-01-30/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "bf24570425c064aaef31788bbabd6c4938c9323eca2dedf2ac9084d125623544",
+ "dist/2023-01-30/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "f5437d81735fa67ef24c7b561d1c720395f5d8d4ddcfd88364717a7ed9b96a7d",
+ "dist/2023-01-30/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "8e19c3c95d6445e1ef9b1735191f0d0bc33802bcfa138a9d676d9b266adab17c",
+ "dist/2023-01-30/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "7fd91c2ef7e26c08854c91969d167d1c97538d7678c6ed7914eb0f67290d8d5d",
+ "dist/2023-01-30/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "9e8ada358580b396054278972d532ce2044550071036e9da2eab598e2953a03a",
+ "dist/2023-01-30/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "eec8b1c24ccaea22eed7708e61bd32bac0850d0dff2b06f1a15a95ab86385363",
+ "dist/2023-01-30/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "215f1f3bdd8f347af5969c66ff7f7cbf39753ae483e75e689ac581f9d35a64df",
+ "dist/2023-01-30/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "39460814c429b6a57ce72fafa583d04190053f2c2ce995c8bcb0799ecb7f8bd5",
+ "dist/2023-01-30/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "6bd08db8702f2fcd9f4cd19a1d977962c84856f748552a96b564e5a77cf2fdfc",
+ "dist/2023-01-30/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "81d6335fa1265cdf99682503cfb236b914fa17d45f967e456ddbeb12bae2dcbf",
+ "dist/2023-01-30/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "d36b7517efac2c4a34a1055411f779c386c7a566e4eec408dbc8a319f67f5451",
+ "dist/2023-01-30/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "1a34ec058cb45189c4062ad2a00ab33387a54716f75005d9959cf0691d06ae50",
+ "dist/2023-01-30/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "a2fdcb7cc9fe7819699f511d52da0e8ed4e55ba42c63e7b1d61512e4e14e5c29",
+ "dist/2023-01-30/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "95e3f080394d2e4f9916f17c9cf5137d032da847d9ac1c04519b31177fb1618e",
+ "dist/2023-01-30/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "c306895982f92c24559b18f8ff9e011e8722c3310e5f70010fd04b0d044c49bb",
+ "dist/2023-01-30/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "36331cd76f8e918b73ebf6d9095efd0a07cc9f084f194f74c881c14fbc6e8a77",
+ "dist/2023-01-30/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "2e7caa7209e52a9df17254b17f1930afd5ae973826ce3293f29b8b878aa13042",
+ "dist/2023-01-30/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "dec92f2c27f785f8ae0db18c2e8a9db87e1ae8addb4302f5cbe9f745cd92c4f2",
+ "dist/2023-01-30/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "a8fef2e56d9d2be9072c17d75e7ac695eb8fc266fc35e1055fbb25757e6db29d",
+ "dist/2023-01-30/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "9b5f93f00f61def125436332e4b709bdfe74c441995bae49c0d482f24bd9f8f1",
+ "dist/2023-01-30/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "4f82313dce2e1315bd0d3ebf95f33bbdf7275c59205b0910bbc92d41c47c7c22",
+ "dist/2023-01-30/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "69efa04956d9bcf177a3bd9ba9541fa681b39416a1b7dd2b18415b72311897b9",
+ "dist/2023-01-30/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "0c3c33d744ec05e96298d0bdb9890654ab9ce3e9013b9af14c78683560456820",
+ "dist/2023-01-30/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "cba8b1f086c544d79aa09ac954374f44d5e7d38ad9bbc2f9e84723d0088592e5",
+ "dist/2023-01-30/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "ce73d1d03b62931d6eb9508b701e9dacc08b98b484af3daa79ae600c4883a9f4",
+ "dist/2023-01-30/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "87e1018a3ee4f781b3c1b471fcdf80ebd70096ed58b29db00ad97573626294f4",
+ "dist/2023-01-30/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "c6896ee319403ebb5c909b13feabc7411e3aa80523ef1bc84c8aae181514c923"
}
}
const PATH: &str = "src/stage0.json";
const COMPILER_COMPONENTS: &[&str] = &["rustc", "rust-std", "cargo"];
-const RUSTFMT_COMPONENTS: &[&str] = &["rustfmt-preview"];
+const RUSTFMT_COMPONENTS: &[&str] = &["rustfmt-preview", "rustc"];
struct Tool {
config: Config,
-Subproject commit 3c5af6bed9a1a243a693e8e22ee2486bd5b82a6c
+Subproject commit e84a7928d93a31f284b497c214a2ece69b4d7719
--> $DIR/track-diagnostics.rs:LL:CC
|
LL | const S: A = B;
- | ^ expected struct `A`, found struct `B`
+ | ^ expected `A`, found `B`
-Ztrack-diagnostics: created at compiler/rustc_infer/src/infer/error_reporting/mod.rs:LL:CC
error: aborting due to previous error
["generate", ref base] => (Mode::Generate, PathBuf::from(base)),
["check", ref base] => (Mode::Check, PathBuf::from(base)),
_ => {
- eprintln!("usage: expand-yaml-anchors <source-dir> <dest-dir>");
+ eprintln!("usage: expand-yaml-anchors <generate|check> <base-dir>");
std::process::exit(1);
}
};
protector: None,
}
} else if pointee.is_unpin(*cx.tcx, cx.param_env()) {
- // A regular full mutable reference.
+ // A regular full mutable reference. On `FnEntry` this is `noalias` and `dereferenceable`.
NewPermission::Uniform {
perm: Permission::Unique,
access: Some(AccessKind::Write),
protector,
}
} else {
+ // `!Unpin` dereferences do not get `noalias` nor `dereferenceable`.
NewPermission::Uniform {
perm: Permission::SharedReadWrite,
- // FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we
- // should do fake accesses here. But then we run into
- // <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>, so for now
- // we don't do that.
access: None,
- protector,
+ protector: None,
}
}
}
}
}
ty::Ref(_, _pointee, Mutability::Not) => {
+ // Shared references. If frozen, these get `noalias` and `dereferenceable`; otherwise neither.
NewPermission::FreezeSensitive {
freeze_perm: Permission::SharedReadOnly,
freeze_access: Some(AccessKind::Read),
}
}
+ fn from_box_ty<'tcx>(
+ ty: Ty<'tcx>,
+ kind: RetagKind,
+ cx: &crate::MiriInterpCx<'_, 'tcx>,
+ ) -> Self {
+ // `ty` is not the `Box` but the field of the Box with this pointer (due to allocator handling).
+ let pointee = ty.builtin_deref(true).unwrap().ty;
+ if pointee.is_unpin(*cx.tcx, cx.param_env()) {
+ // A regular box. On `FnEntry` this is `noalias`, but not `dereferenceable` (hence only
+ // a weak protector).
+ NewPermission::Uniform {
+ perm: Permission::Unique,
+ access: Some(AccessKind::Write),
+ protector: (kind == RetagKind::FnEntry)
+ .then_some(ProtectorKind::WeakProtector),
+ }
+ } else {
+ // `!Unpin` boxes do not get `noalias` nor `dereferenceable`.
+ NewPermission::Uniform {
+ perm: Permission::SharedReadWrite,
+ access: None,
+ protector: None,
+ }
+ }
+ }
+
fn protector(&self) -> Option<ProtectorKind> {
match self {
NewPermission::Uniform { protector, .. } => *protector,
fn visit_box(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
// Boxes get a weak protectors, since they may be deallocated.
- let new_perm = NewPermission::Uniform {
- perm: Permission::Unique,
- access: Some(AccessKind::Write),
- protector: (self.kind == RetagKind::FnEntry)
- .then_some(ProtectorKind::WeakProtector),
- };
+ let new_perm = NewPermission::from_box_ty(place.layout.ty, self.kind, self.ecx);
self.retag_ptr_inplace(place, new_perm, self.retag_cause)
}
+++ /dev/null
-//@error-pattern: /deallocating while item \[SharedReadWrite for .*\] is strongly protected/
-use std::marker::PhantomPinned;
-
-pub struct NotUnpin(i32, PhantomPinned);
-
-fn inner(x: &mut NotUnpin, f: fn(&mut NotUnpin)) {
- // `f` may mutate, but it may not deallocate!
- f(x)
-}
-
-fn main() {
- inner(Box::leak(Box::new(NotUnpin(0, PhantomPinned))), |x| {
- let raw = x as *mut _;
- drop(unsafe { Box::from_raw(raw) });
- });
-}
+++ /dev/null
-error: Undefined Behavior: deallocating while item [SharedReadWrite for <TAG>] is strongly protected by call ID
- --> RUSTLIB/alloc/src/alloc.rs:LL:CC
- |
-LL | unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ deallocating while item [SharedReadWrite for <TAG>] is strongly protected by call ID
- |
- = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
- = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
- = note: BACKTRACE:
- = note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
- = note: inside `<std::alloc::Global as std::alloc::Allocator>::deallocate` at RUSTLIB/alloc/src/alloc.rs:LL:CC
- = note: inside `alloc::alloc::box_free::<NotUnpin, std::alloc::Global>` at RUSTLIB/alloc/src/alloc.rs:LL:CC
- = note: inside `std::ptr::drop_in_place::<std::boxed::Box<NotUnpin>> - shim(Some(std::boxed::Box<NotUnpin>))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
- = note: inside `std::mem::drop::<std::boxed::Box<NotUnpin>>` at RUSTLIB/core/src/mem/mod.rs:LL:CC
-note: inside closure
- --> $DIR/deallocate_against_protector2.rs:LL:CC
- |
-LL | drop(unsafe { Box::from_raw(raw) });
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: inside `<[closure@$DIR/deallocate_against_protector2.rs:LL:CC] as std::ops::FnOnce<(&mut NotUnpin,)>>::call_once - shim` at RUSTLIB/core/src/ops/function.rs:LL:CC
-note: inside `inner`
- --> $DIR/deallocate_against_protector2.rs:LL:CC
- |
-LL | f(x)
- | ^^^^
-note: inside `main`
- --> $DIR/deallocate_against_protector2.rs:LL:CC
- |
-LL | / inner(Box::leak(Box::new(NotUnpin(0, PhantomPinned))), |x| {
-LL | | let raw = x as *mut _;
-LL | | drop(unsafe { Box::from_raw(raw) });
-LL | | });
- | |______^
-
-note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
-
-error: aborting due to previous error
-
// This should fail even without validation/SB
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
-#![allow(dead_code, unused_variables, unaligned_references)]
+#![allow(dead_code, unused_variables)]
+
+use std::{ptr, mem};
#[repr(packed)]
struct Foo {
y: i32,
}
+unsafe fn raw_to_ref<'a, T>(x: *const T) -> &'a T {
+ mem::transmute(x)
+}
+
fn main() {
// Try many times as this might work by chance.
for _ in 0..20 {
let foo = Foo { x: 42, y: 99 };
- let p = &foo.x;
- let i = *p; //~ERROR: alignment 4 is required
+ // There seem to be implicit reborrows, which make the error already appear here
+ let p: &i32 = unsafe { raw_to_ref(ptr::addr_of!(foo.x)) }; //~ERROR: alignment 4 is required
+ let i = *p;
}
}
error: Undefined Behavior: accessing memory with alignment ALIGN, but alignment ALIGN is required
--> $DIR/reference_to_packed.rs:LL:CC
|
-LL | let i = *p;
- | ^^ accessing memory with alignment ALIGN, but alignment ALIGN is required
+LL | let p: &i32 = unsafe { raw_to_ref(ptr::addr_of!(foo.x)) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment ALIGN, but alignment ALIGN is required
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
}
}
+fn mk_waker() -> Waker {
+ use std::sync::Arc;
+
+ struct MyWaker;
+ impl Wake for MyWaker {
+ fn wake(self: Arc<Self>) {
+ unimplemented!()
+ }
+ }
+
+ Waker::from(Arc::new(MyWaker))
+}
+
async fn do_stuff() {
(&mut Delay::new(1)).await;
}
}
fn run_fut<T>(fut: impl Future<Output = T>) -> T {
- use std::sync::Arc;
-
- struct MyWaker;
- impl Wake for MyWaker {
- fn wake(self: Arc<Self>) {
- unimplemented!()
- }
- }
-
- let waker = Waker::from(Arc::new(MyWaker));
+ let waker = mk_waker();
let mut context = Context::from_waker(&waker);
let mut pinned = pin!(fut);
}
}
+fn self_referential_box() {
+ let waker = mk_waker();
+ let cx = &mut Context::from_waker(&waker);
+
+ async fn my_fut() -> i32 {
+ let val = 10;
+ let val_ref = &val;
+
+ let _ = Delay::new(1).await;
+
+ *val_ref
+ }
+
+ fn box_poll<F: Future>(
+ mut f: Pin<Box<F>>,
+ cx: &mut Context<'_>,
+ ) -> (Pin<Box<F>>, Poll<F::Output>) {
+ let p = f.as_mut().poll(cx);
+ (f, p)
+ }
+
+ let my_fut = Box::pin(my_fut());
+ let (my_fut, p1) = box_poll(my_fut, cx);
+ assert!(p1.is_pending());
+ let (my_fut, p2) = box_poll(my_fut, cx);
+ assert!(p2.is_ready());
+ drop(my_fut);
+}
+
fn main() {
run_fut(do_stuff());
run_fut(DoStuff::new());
+ self_referential_box();
}
array_casts();
mut_below_shr();
wide_raw_ptr_in_tuple();
+ not_unpin_not_protected();
}
// Make sure that reading from an `&mut` does, like reborrowing to `&`,
// Make sure the fn ptr part of the vtable is still fine.
r.type_id();
}
+
+fn not_unpin_not_protected() {
+ // `&mut !Unpin`, at least for now, does not get `noalias` nor `dereferenceable`, so we also
+ // don't add protectors. (We could, but until we have a better idea for where we want to go with
+ // the self-referntial-generator situation, it does not seem worth the potential trouble.)
+ use std::marker::PhantomPinned;
+
+ pub struct NotUnpin(i32, PhantomPinned);
+
+ fn inner(x: &mut NotUnpin, f: fn(&mut NotUnpin)) {
+ // `f` may mutate, but it may not deallocate!
+ f(x)
+ }
+
+ inner(Box::leak(Box::new(NotUnpin(0, PhantomPinned))), |x| {
+ let raw = x as *mut _;
+ drop(unsafe { Box::from_raw(raw) });
+ });
+}
use std::panic::{catch_unwind, AssertUnwindSafe};
use rustc_ast::token::{BinOpToken, Delimiter, Token, TokenKind};
-use rustc_ast::tokenstream::{Cursor, TokenStream, TokenTree};
+use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
use rustc_ast::{ast, ptr};
use rustc_ast_pretty::pprust;
use rustc_span::{
self.buf.clear();
}
- fn add_meta_variable(&mut self, iter: &mut Cursor) -> Option<()> {
+ fn add_meta_variable(&mut self, iter: &mut TokenTreeCursor) -> Option<()> {
match iter.next() {
Some(TokenTree::Token(
Token {
&mut self,
inner: Vec<ParsedMacroArg>,
delim: Delimiter,
- iter: &mut Cursor,
+ iter: &mut TokenTreeCursor,
) -> Option<()> {
let mut buffer = String::new();
let mut first = true;
// Currently we do not attempt to parse any further than that.
#[derive(new)]
struct MacroParser {
- toks: Cursor,
+ toks: TokenTreeCursor,
}
impl MacroParser {
// Error codes that don't yet have a UI test. This list will eventually be removed.
const IGNORE_UI_TEST_CHECK: &[&str] =
- &["E0461", "E0465", "E0476", "E0514", "E0523", "E0554", "E0640", "E0717", "E0729"];
+ &["E0461", "E0465", "E0476", "E0514", "E0554", "E0640", "E0717", "E0729"];
macro_rules! verbose_print {
($verbose:expr, $($fmt:tt)*) => {
x
}
+// CHECK: align 4 {{i32\*|ptr}} @borrow_mut({{i32\*|ptr}} align 4 %x)
+#[no_mangle]
+pub fn borrow_mut(x: &mut i32) -> &mut i32 {
+ x
+}
+
// CHECK-LABEL: @borrow_call
#[no_mangle]
pub fn borrow_call(x: &i32, f: fn(&i32) -> &i32) -> &i32 {
pub fn readonly_borrow(_: &i32) {
}
+// CHECK: noundef align 4 dereferenceable(4) {{i32\*|ptr}} @readonly_borrow_ret()
+#[no_mangle]
+pub fn readonly_borrow_ret() -> &'static i32 {
+ loop {}
+}
+
// CHECK: @static_borrow({{i32\*|ptr}} noalias noundef readonly align 4 dereferenceable(4) %_1)
// static borrow may be captured
#[no_mangle]
pub fn mutable_borrow(_: &mut i32) {
}
+// CHECK: noundef align 4 dereferenceable(4) {{i32\*|ptr}} @mutable_borrow_ret()
+#[no_mangle]
+pub fn mutable_borrow_ret() -> &'static mut i32 {
+ loop {}
+}
+
#[no_mangle]
-// CHECK: @mutable_notunpin_borrow({{i32\*|ptr}} noundef align 4 dereferenceable(4) %_1)
+// CHECK: @mutable_notunpin_borrow({{i32\*|ptr}} noundef nonnull align 4 %_1)
// This one is *not* `noalias` because it might be self-referential.
+// It is also not `dereferenceable` due to
+// <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>.
pub fn mutable_notunpin_borrow(_: &mut NotUnpin) {
}
x
}
+// CHECK: noundef nonnull align 4 {{i32\*|ptr}} @notunpin_box({{i32\*|ptr}} noundef nonnull align 4 %x)
+#[no_mangle]
+pub fn notunpin_box(x: Box<NotUnpin>) -> Box<NotUnpin> {
+ x
+}
+
// CHECK: @struct_return({{%S\*|ptr}} noalias nocapture noundef sret(%S) dereferenceable(32){{( %0)?}})
#[no_mangle]
pub fn struct_return() -> S {
// CHECK: @trait_box({{\{\}\*|ptr}} noalias noundef nonnull align 1{{( %0)?}}, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}){{( %1)?}})
#[no_mangle]
-pub fn trait_box(_: Box<dyn Drop>) {
+pub fn trait_box(_: Box<dyn Drop + Unpin>) {
}
// CHECK: { {{i8\*|ptr}}, {{i8\*|ptr}} } @trait_option({{i8\*|ptr}} noalias noundef align 1 %x.0, {{i8\*|ptr}} %x.1)
#[no_mangle]
-pub fn trait_option(x: Option<Box<dyn Drop>>) -> Option<Box<dyn Drop>> {
+pub fn trait_option(x: Option<Box<dyn Drop + Unpin>>) -> Option<Box<dyn Drop + Unpin>> {
x
}
bb1: {
_4 = move _2; // scope 0 at $DIR/async_await.rs:+0:14: +0:16
_3 = const (); // scope 0 at $DIR/async_await.rs:+0:14: +0:16
- Deinit(_0); // scope 0 at $DIR/async_await.rs:+0:16: +0:16
- ((_0 as Ready).0: ()) = move _3; // scope 0 at $DIR/async_await.rs:+0:16: +0:16
- discriminant(_0) = 0; // scope 0 at $DIR/async_await.rs:+0:16: +0:16
+ _0 = Poll::<()>::Ready(move _3); // scope 0 at $DIR/async_await.rs:+0:16: +0:16
discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:11:14: 11:16]))) = 1; // scope 0 at $DIR/async_await.rs:+0:16: +0:16
return; // scope 0 at $DIR/async_await.rs:+0:16: +0:16
}
StorageLive(_19); // scope 1 at $DIR/async_await.rs:+1:8: +1:14
StorageLive(_20); // scope 1 at $DIR/async_await.rs:+1:8: +1:14
_20 = (); // scope 1 at $DIR/async_await.rs:+1:8: +1:14
- Deinit(_0); // scope 1 at $DIR/async_await.rs:+1:8: +1:14
- discriminant(_0) = 1; // scope 1 at $DIR/async_await.rs:+1:8: +1:14
+ _0 = Poll::<()>::Pending; // scope 1 at $DIR/async_await.rs:+1:8: +1:14
discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2]))) = 3; // scope 1 at $DIR/async_await.rs:+1:8: +1:14
return; // scope 1 at $DIR/async_await.rs:+1:8: +1:14
}
StorageLive(_35); // scope 4 at $DIR/async_await.rs:+2:8: +2:14
StorageLive(_36); // scope 4 at $DIR/async_await.rs:+2:8: +2:14
_36 = (); // scope 4 at $DIR/async_await.rs:+2:8: +2:14
- Deinit(_0); // scope 4 at $DIR/async_await.rs:+2:8: +2:14
- discriminant(_0) = 1; // scope 4 at $DIR/async_await.rs:+2:8: +2:14
+ _0 = Poll::<()>::Pending; // scope 4 at $DIR/async_await.rs:+2:8: +2:14
discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2]))) = 4; // scope 4 at $DIR/async_await.rs:+2:8: +2:14
return; // scope 4 at $DIR/async_await.rs:+2:8: +2:14
}
}
bb26: {
- Deinit(_0); // scope 0 at $DIR/async_await.rs:+3:2: +3:2
- ((_0 as Ready).0: ()) = move _37; // scope 0 at $DIR/async_await.rs:+3:2: +3:2
- discriminant(_0) = 0; // scope 0 at $DIR/async_await.rs:+3:2: +3:2
+ _0 = Poll::<()>::Ready(move _37); // scope 0 at $DIR/async_await.rs:+3:2: +3:2
discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2]))) = 1; // scope 0 at $DIR/async_await.rs:+3:2: +3:2
return; // scope 0 at $DIR/async_await.rs:+3:2: +3:2
}
bb3: {
StorageDead(_9); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:15: 10:16
- Deinit(_0); // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15
- (_0.0: T) = move _2; // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15
- (_0.1: u64) = move _5; // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15
- (_0.2: [f32; 3]) = move _8; // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15
+ _0 = MyThing::<T> { v: move _2, i: move _5, a: move _8 }; // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15
StorageDead(_8); // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:14: +0:15
StorageDead(_5); // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:14: +0:15
StorageDead(_2); // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:14: +0:15
alloc18 (size: 48, align: 4) {
0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc5──╼ 00 00 00 00 │ ....░░░░╾──╼....
- 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc9──╼ 02 00 00 00 │ ....░░░░╾──╼....
- 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc14─╼ 03 00 00 00 │ ....*...╾──╼....
+ 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc8──╼ 02 00 00 00 │ ....░░░░╾──╼....
+ 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc13─╼ 03 00 00 00 │ ....*...╾──╼....
}
alloc5 (size: 0, align: 4) {}
-alloc9 (size: 16, align: 4) {
- ╾─alloc8──╼ 03 00 00 00 ╾─alloc10─╼ 03 00 00 00 │ ╾──╼....╾──╼....
+alloc8 (size: 16, align: 4) {
+ ╾─alloc9──╼ 03 00 00 00 ╾─alloc10─╼ 03 00 00 00 │ ╾──╼....╾──╼....
}
-alloc8 (size: 3, align: 1) {
+alloc9 (size: 3, align: 1) {
66 6f 6f │ foo
}
62 61 72 │ bar
}
-alloc14 (size: 24, align: 4) {
- 0x00 │ ╾─alloc13─╼ 03 00 00 00 ╾─alloc15─╼ 03 00 00 00 │ ╾──╼....╾──╼....
+alloc13 (size: 24, align: 4) {
+ 0x00 │ ╾─alloc14─╼ 03 00 00 00 ╾─alloc15─╼ 03 00 00 00 │ ╾──╼....╾──╼....
0x10 │ ╾─alloc16─╼ 04 00 00 00 │ ╾──╼....
}
-alloc13 (size: 3, align: 1) {
+alloc14 (size: 3, align: 1) {
6d 65 68 │ meh
}
alloc18 (size: 72, align: 8) {
0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc5────────╼ │ ....░░░░╾──────╼
0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░
- 0x20 │ ╾───────alloc9────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
- 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc14───────╼ │ ....*...╾──────╼
+ 0x20 │ ╾───────alloc8────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
+ 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc13───────╼ │ ....*...╾──────╼
0x40 │ 03 00 00 00 00 00 00 00 │ ........
}
alloc5 (size: 0, align: 8) {}
-alloc9 (size: 32, align: 8) {
- 0x00 │ ╾───────alloc8────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+alloc8 (size: 32, align: 8) {
+ 0x00 │ ╾───────alloc9────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
0x10 │ ╾───────alloc10───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
}
-alloc8 (size: 3, align: 1) {
+alloc9 (size: 3, align: 1) {
66 6f 6f │ foo
}
62 61 72 │ bar
}
-alloc14 (size: 48, align: 8) {
- 0x00 │ ╾───────alloc13───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+alloc13 (size: 48, align: 8) {
+ 0x00 │ ╾───────alloc14───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
0x10 │ ╾───────alloc15───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
0x20 │ ╾───────alloc16───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
}
-alloc13 (size: 3, align: 1) {
+alloc14 (size: 3, align: 1) {
6d 65 68 │ meh
}
}
bb0: {
- StorageLive(_1); // scope 0 at $DIR/const_debuginfo.rs:+1:9: +1:10
_1 = const 1_u8; // scope 0 at $DIR/const_debuginfo.rs:+1:13: +1:16
- StorageLive(_2); // scope 1 at $DIR/const_debuginfo.rs:+2:9: +2:10
_2 = const 2_u8; // scope 1 at $DIR/const_debuginfo.rs:+2:13: +2:16
- StorageLive(_3); // scope 2 at $DIR/const_debuginfo.rs:+3:9: +3:10
_3 = const 3_u8; // scope 2 at $DIR/const_debuginfo.rs:+3:13: +3:16
StorageLive(_4); // scope 3 at $DIR/const_debuginfo.rs:+4:9: +4:12
StorageLive(_5); // scope 3 at $DIR/const_debuginfo.rs:+4:15: +4:20
StorageLive(_14); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
StorageLive(_15); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
StorageLive(_16); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
- Deinit(_14); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
- Deinit(_15); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
- Deinit(_16); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
_14 = const true; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
_15 = const false; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
_16 = const 123_u32; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
StorageLive(_10); // scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10
- Deinit(_10); // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24
- ((_10 as Some).0: u16) = const 99_u16; // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24
- discriminant(_10) = 1; // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24
- StorageLive(_17); // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10
- StorageLive(_18); // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10
- Deinit(_17); // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
- Deinit(_18); // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
+ _10 = Option::<u16>::Some(const 99_u16); // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24
_17 = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
_18 = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
StorageLive(_11); // scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10
- StorageLive(_12); // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16
- _12 = const 32_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16
- StorageLive(_13); // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22
- _13 = const 32_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22
_11 = const 64_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:22
- StorageDead(_13); // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22
- StorageDead(_12); // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22
StorageDead(_11); // scope 8 at $DIR/const_debuginfo.rs:+14:1: +14:2
- StorageDead(_17); // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2
- StorageDead(_18); // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2
StorageDead(_10); // scope 6 at $DIR/const_debuginfo.rs:+14:1: +14:2
StorageDead(_14); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2
StorageDead(_15); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2
bb0: {
StorageLive(_1); // scope 0 at $DIR/const_goto_storage.rs:+1:9: +1:12
- StorageLive(_2); // scope 0 at $DIR/const_goto_storage.rs:+1:21: +1:23
-- Deinit(_2); // scope 0 at $DIR/const_goto_storage.rs:+1:21: +1:23
+- _2 = (); // scope 0 at $DIR/const_goto_storage.rs:+1:21: +1:23
- StorageLive(_3); // scope 0 at $DIR/const_goto_storage.rs:+2:15: +6:10
- StorageLive(_4); // scope 0 at $DIR/const_goto_storage.rs:+2:18: +2:76
- StorageLive(_5); // scope 0 at $DIR/const_goto_storage.rs:+2:21: +2:52
--- /dev/null
+- // MIR for `foo` before ConstProp
++ // MIR for `foo` after ConstProp
+
+ fn foo(_1: u8) -> () {
+ debug x => _1; // in scope 0 at $DIR/aggregate.rs:+0:8: +0:9
+ let mut _0: (); // return place in scope 0 at $DIR/aggregate.rs:+0:15: +0:15
+ let _2: i32; // in scope 0 at $DIR/aggregate.rs:+2:9: +2:14
+ let mut _3: i32; // in scope 0 at $DIR/aggregate.rs:+2:17: +2:25
+ let mut _4: (i32, u8); // in scope 0 at $DIR/aggregate.rs:+2:17: +2:23
+ let mut _5: u8; // in scope 0 at $DIR/aggregate.rs:+2:21: +2:22
+ let mut _7: i32; // in scope 0 at $DIR/aggregate.rs:+3:18: +3:26
+ let mut _8: (u8, i32); // in scope 0 at $DIR/aggregate.rs:+3:18: +3:24
+ let mut _9: u8; // in scope 0 at $DIR/aggregate.rs:+3:19: +3:20
+ scope 1 {
+ debug first => _2; // in scope 1 at $DIR/aggregate.rs:+2:9: +2:14
+ let _6: i32; // in scope 1 at $DIR/aggregate.rs:+3:9: +3:15
+ scope 2 {
+ debug second => _6; // in scope 2 at $DIR/aggregate.rs:+3:9: +3:15
+ }
+ }
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $DIR/aggregate.rs:+2:9: +2:14
+ StorageLive(_3); // scope 0 at $DIR/aggregate.rs:+2:17: +2:25
+ StorageLive(_4); // scope 0 at $DIR/aggregate.rs:+2:17: +2:23
+ StorageLive(_5); // scope 0 at $DIR/aggregate.rs:+2:21: +2:22
+ _5 = _1; // scope 0 at $DIR/aggregate.rs:+2:21: +2:22
+ _4 = (const 0_i32, move _5); // scope 0 at $DIR/aggregate.rs:+2:17: +2:23
+ StorageDead(_5); // scope 0 at $DIR/aggregate.rs:+2:22: +2:23
+- _3 = (_4.0: i32); // scope 0 at $DIR/aggregate.rs:+2:17: +2:25
+- _2 = Add(move _3, const 1_i32); // scope 0 at $DIR/aggregate.rs:+2:17: +2:29
++ _3 = const 0_i32; // scope 0 at $DIR/aggregate.rs:+2:17: +2:25
++ _2 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+2:17: +2:29
+ StorageDead(_3); // scope 0 at $DIR/aggregate.rs:+2:28: +2:29
+ StorageDead(_4); // scope 0 at $DIR/aggregate.rs:+2:29: +2:30
+ StorageLive(_6); // scope 1 at $DIR/aggregate.rs:+3:9: +3:15
+ StorageLive(_7); // scope 1 at $DIR/aggregate.rs:+3:18: +3:26
+ StorageLive(_8); // scope 1 at $DIR/aggregate.rs:+3:18: +3:24
+ StorageLive(_9); // scope 1 at $DIR/aggregate.rs:+3:19: +3:20
+ _9 = _1; // scope 1 at $DIR/aggregate.rs:+3:19: +3:20
+ _8 = (move _9, const 1_i32); // scope 1 at $DIR/aggregate.rs:+3:18: +3:24
+ StorageDead(_9); // scope 1 at $DIR/aggregate.rs:+3:23: +3:24
+- _7 = (_8.1: i32); // scope 1 at $DIR/aggregate.rs:+3:18: +3:26
+- _6 = Add(move _7, const 2_i32); // scope 1 at $DIR/aggregate.rs:+3:18: +3:30
++ _7 = const 1_i32; // scope 1 at $DIR/aggregate.rs:+3:18: +3:26
++ _6 = const 3_i32; // scope 1 at $DIR/aggregate.rs:+3:18: +3:30
+ StorageDead(_7); // scope 1 at $DIR/aggregate.rs:+3:29: +3:30
+ StorageDead(_8); // scope 1 at $DIR/aggregate.rs:+3:30: +3:31
+ _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:15: +4:2
+ StorageDead(_6); // scope 1 at $DIR/aggregate.rs:+4:1: +4:2
+ StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+4:1: +4:2
+ return; // scope 0 at $DIR/aggregate.rs:+4:2: +4:2
+ }
+ }
+
--- /dev/null
+// MIR for `foo` after PreCodegen
+
+fn foo(_1: u8) -> () {
+ debug x => _1; // in scope 0 at $DIR/aggregate.rs:+0:8: +0:9
+ let mut _0: (); // return place in scope 0 at $DIR/aggregate.rs:+0:15: +0:15
+ let _2: i32; // in scope 0 at $DIR/aggregate.rs:+2:9: +2:14
+ let mut _3: i32; // in scope 0 at $DIR/aggregate.rs:+2:17: +2:25
+ let mut _4: (i32, u8); // in scope 0 at $DIR/aggregate.rs:+2:17: +2:23
+ let mut _5: u8; // in scope 0 at $DIR/aggregate.rs:+2:21: +2:22
+ let mut _7: i32; // in scope 0 at $DIR/aggregate.rs:+3:18: +3:26
+ let mut _8: (u8, i32); // in scope 0 at $DIR/aggregate.rs:+3:18: +3:24
+ let mut _9: u8; // in scope 0 at $DIR/aggregate.rs:+3:19: +3:20
+ scope 1 {
+ debug first => _2; // in scope 1 at $DIR/aggregate.rs:+2:9: +2:14
+ let _6: i32; // in scope 1 at $DIR/aggregate.rs:+3:9: +3:15
+ scope 2 {
+ debug second => _6; // in scope 2 at $DIR/aggregate.rs:+3:9: +3:15
+ }
+ }
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $DIR/aggregate.rs:+2:9: +2:14
+ StorageLive(_3); // scope 0 at $DIR/aggregate.rs:+2:17: +2:25
+ StorageLive(_4); // scope 0 at $DIR/aggregate.rs:+2:17: +2:23
+ StorageLive(_5); // scope 0 at $DIR/aggregate.rs:+2:21: +2:22
+ _5 = _1; // scope 0 at $DIR/aggregate.rs:+2:21: +2:22
+ _4 = (const 0_i32, move _5); // scope 0 at $DIR/aggregate.rs:+2:17: +2:23
+ StorageDead(_5); // scope 0 at $DIR/aggregate.rs:+2:22: +2:23
+ _3 = const 0_i32; // scope 0 at $DIR/aggregate.rs:+2:17: +2:25
+ _2 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+2:17: +2:29
+ StorageDead(_3); // scope 0 at $DIR/aggregate.rs:+2:28: +2:29
+ StorageDead(_4); // scope 0 at $DIR/aggregate.rs:+2:29: +2:30
+ StorageLive(_6); // scope 1 at $DIR/aggregate.rs:+3:9: +3:15
+ StorageLive(_7); // scope 1 at $DIR/aggregate.rs:+3:18: +3:26
+ StorageLive(_8); // scope 1 at $DIR/aggregate.rs:+3:18: +3:24
+ StorageLive(_9); // scope 1 at $DIR/aggregate.rs:+3:19: +3:20
+ _9 = _1; // scope 1 at $DIR/aggregate.rs:+3:19: +3:20
+ _8 = (move _9, const 1_i32); // scope 1 at $DIR/aggregate.rs:+3:18: +3:24
+ StorageDead(_9); // scope 1 at $DIR/aggregate.rs:+3:23: +3:24
+ _7 = const 1_i32; // scope 1 at $DIR/aggregate.rs:+3:18: +3:26
+ _6 = const 3_i32; // scope 1 at $DIR/aggregate.rs:+3:18: +3:30
+ StorageDead(_7); // scope 1 at $DIR/aggregate.rs:+3:29: +3:30
+ StorageDead(_8); // scope 1 at $DIR/aggregate.rs:+3:30: +3:31
+ _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:15: +4:2
+ StorageDead(_6); // scope 1 at $DIR/aggregate.rs:+4:1: +4:2
+ StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+4:1: +4:2
+ return; // scope 0 at $DIR/aggregate.rs:+4:2: +4:2
+ }
+}
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/aggregate.rs:+0:11: +0:11
- let _1: i32; // in scope 0 at $DIR/aggregate.rs:+1:9: +1:10
- let mut _2: i32; // in scope 0 at $DIR/aggregate.rs:+1:13: +1:24
- let mut _3: (i32, i32, i32); // in scope 0 at $DIR/aggregate.rs:+1:13: +1:22
+ let _1: u8; // in scope 0 at $DIR/aggregate.rs:+1:9: +1:10
+ let mut _2: u8; // in scope 0 at $DIR/aggregate.rs:+1:13: +1:24
+ let mut _3: (i32, u8, i32); // in scope 0 at $DIR/aggregate.rs:+1:13: +1:22
+ let _4: (); // in scope 0 at $DIR/aggregate.rs:+2:5: +2:11
+ let mut _5: u8; // in scope 0 at $DIR/aggregate.rs:+2:9: +2:10
scope 1 {
debug x => _1; // in scope 1 at $DIR/aggregate.rs:+1:9: +1:10
}
StorageLive(_1); // scope 0 at $DIR/aggregate.rs:+1:9: +1:10
StorageLive(_2); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
StorageLive(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- Deinit(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- (_3.0: i32) = const 0_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- (_3.1: i32) = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- (_3.2: i32) = const 2_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
-- _2 = (_3.1: i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
-- _1 = Add(move _2, const 0_i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
-+ _2 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
-+ _1 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
+ _3 = (const 0_i32, const 1_u8, const 2_i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
+- _2 = (_3.1: u8); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
+- _1 = Add(move _2, const 0_u8); // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
++ _2 = const 1_u8; // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
++ _1 = const 1_u8; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+1:27: +1:28
StorageDead(_3); // scope 0 at $DIR/aggregate.rs:+1:28: +1:29
- _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:11: +2:2
- StorageDead(_1); // scope 0 at $DIR/aggregate.rs:+2:1: +2:2
- return; // scope 0 at $DIR/aggregate.rs:+2:2: +2:2
+ StorageLive(_4); // scope 1 at $DIR/aggregate.rs:+2:5: +2:11
+ StorageLive(_5); // scope 1 at $DIR/aggregate.rs:+2:9: +2:10
+- _5 = _1; // scope 1 at $DIR/aggregate.rs:+2:9: +2:10
++ _5 = const 1_u8; // scope 1 at $DIR/aggregate.rs:+2:9: +2:10
+ _4 = foo(move _5) -> bb1; // scope 1 at $DIR/aggregate.rs:+2:5: +2:11
+ // mir::Constant
+ // + span: $DIR/aggregate.rs:8:5: 8:8
+ // + literal: Const { ty: fn(u8) {foo}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageDead(_5); // scope 1 at $DIR/aggregate.rs:+2:10: +2:11
+ StorageDead(_4); // scope 1 at $DIR/aggregate.rs:+2:11: +2:12
+ _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:11: +3:2
+ StorageDead(_1); // scope 0 at $DIR/aggregate.rs:+3:1: +3:2
+ return; // scope 0 at $DIR/aggregate.rs:+3:2: +3:2
}
}
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/aggregate.rs:+0:11: +0:11
- let _1: i32; // in scope 0 at $DIR/aggregate.rs:+1:9: +1:10
- let mut _2: i32; // in scope 0 at $DIR/aggregate.rs:+1:13: +1:24
- let mut _3: (i32, i32, i32); // in scope 0 at $DIR/aggregate.rs:+1:13: +1:22
+ let _1: u8; // in scope 0 at $DIR/aggregate.rs:+1:9: +1:10
+ let mut _2: u8; // in scope 0 at $DIR/aggregate.rs:+1:13: +1:24
+ let mut _3: (i32, u8, i32); // in scope 0 at $DIR/aggregate.rs:+1:13: +1:22
+ let _4: (); // in scope 0 at $DIR/aggregate.rs:+2:5: +2:11
+ let mut _5: u8; // in scope 0 at $DIR/aggregate.rs:+2:9: +2:10
scope 1 {
debug x => _1; // in scope 1 at $DIR/aggregate.rs:+1:9: +1:10
}
StorageLive(_1); // scope 0 at $DIR/aggregate.rs:+1:9: +1:10
StorageLive(_2); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
StorageLive(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- Deinit(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- (_3.0: i32) = const 0_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- (_3.1: i32) = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- (_3.2: i32) = const 2_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- _2 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
- _1 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
+ _3 = (const 0_i32, const 1_u8, const 2_i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
+ _2 = const 1_u8; // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
+ _1 = const 1_u8; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+1:27: +1:28
StorageDead(_3); // scope 0 at $DIR/aggregate.rs:+1:28: +1:29
- _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:11: +2:2
- StorageDead(_1); // scope 0 at $DIR/aggregate.rs:+2:1: +2:2
- return; // scope 0 at $DIR/aggregate.rs:+2:2: +2:2
+ StorageLive(_4); // scope 1 at $DIR/aggregate.rs:+2:5: +2:11
+ StorageLive(_5); // scope 1 at $DIR/aggregate.rs:+2:9: +2:10
+ _5 = const 1_u8; // scope 1 at $DIR/aggregate.rs:+2:9: +2:10
+ _4 = foo(move _5) -> bb1; // scope 1 at $DIR/aggregate.rs:+2:5: +2:11
+ // mir::Constant
+ // + span: $DIR/aggregate.rs:8:5: 8:8
+ // + literal: Const { ty: fn(u8) {foo}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageDead(_5); // scope 1 at $DIR/aggregate.rs:+2:10: +2:11
+ StorageDead(_4); // scope 1 at $DIR/aggregate.rs:+2:11: +2:12
+ _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:11: +3:2
+ StorageDead(_1); // scope 0 at $DIR/aggregate.rs:+3:1: +3:2
+ return; // scope 0 at $DIR/aggregate.rs:+3:2: +3:2
}
}
// EMIT_MIR aggregate.main.PreCodegen.after.mir
fn main() {
let x = (0, 1, 2).1 + 0;
+ foo(x);
+}
+
+// EMIT_MIR aggregate.foo.ConstProp.diff
+// EMIT_MIR aggregate.foo.PreCodegen.after.mir
+fn foo(x: u8) {
+ // Verify that we still propagate if part of the aggregate is not known.
+ let first = (0, x).0 + 1;
+ let second = (x, 1).1 + 2;
}
}
bb0: {
- StorageLive(_1); // scope 0 at $DIR/bad_op_mod_by_zero.rs:+1:9: +1:10
_1 = const 0_i32; // scope 0 at $DIR/bad_op_mod_by_zero.rs:+1:13: +1:14
StorageLive(_2); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:9: +2:11
- _4 = Eq(_1, const 0_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
StorageLive(_4); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15
StorageLive(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
_5 = const 3_usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
- _6 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
+ _6 = const 3_usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
- _7 = Lt(_5, _6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-+ _7 = Lt(const 3_usize, _6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-+ assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
++ _7 = const false; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
++ assert(const false, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
}
bb1: {
StorageLive(_4); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15
StorageLive(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
_5 = const 3_usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
- _6 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
+ _6 = const 3_usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
- _7 = Lt(_5, _6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-+ _7 = Lt(const 3_usize, _6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-+ assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
++ _7 = const false; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
++ assert(const false, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
}
bb1: {
StorageLive(_1); // scope 0 at $DIR/discriminant.rs:+1:9: +1:10
StorageLive(_2); // scope 0 at $DIR/discriminant.rs:+1:13: +1:64
StorageLive(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- Deinit(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- ((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- discriminant(_3) = 1; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
+- _3 = Option::<bool>::Some(const true); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- _4 = discriminant(_3); // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
- switchInt(move _4) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
++ _3 = const Option::<bool>::Some(true); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
++ // mir::Constant
++ // + span: $DIR/discriminant.rs:12:34: 12:44
++ // + literal: Const { ty: Option<bool>, val: Value(Scalar(0x01)) }
+ _4 = const 1_isize; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+ switchInt(const 1_isize) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
}
bb1: {
- switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+- switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
++ switchInt(const true) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
}
bb2: {
StorageLive(_1); // scope 0 at $DIR/discriminant.rs:+1:9: +1:10
StorageLive(_2); // scope 0 at $DIR/discriminant.rs:+1:13: +1:64
StorageLive(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- Deinit(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- ((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- discriminant(_3) = 1; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
+- _3 = Option::<bool>::Some(const true); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- _4 = discriminant(_3); // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
- switchInt(move _4) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
++ _3 = const Option::<bool>::Some(true); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
++ // mir::Constant
++ // + span: $DIR/discriminant.rs:12:34: 12:44
++ // + literal: Const { ty: Option<bool>, val: Value(Scalar(0x01)) }
+ _4 = const 1_isize; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+ switchInt(const 1_isize) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
}
bb1: {
- switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+- switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
++ switchInt(const true) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
}
bb2: {
bb0: {
StorageLive(_1); // scope 0 at $DIR/invalid_constant.rs:+6:9: +6:22
StorageLive(_2); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63
- Deinit(_2); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63
- (_2.0: u32) = const 1114113_u32; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63
+ _2 = InvalidChar { int: const 1114113_u32 }; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63
- _1 = (_2.1: char); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:67
+ _1 = const {transmute(0x00110001): char}; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:67
StorageDead(_2); // scope 0 at $DIR/invalid_constant.rs:+6:69: +6:70
StorageLive(_3); // scope 1 at $DIR/invalid_constant.rs:+13:9: +13:21
StorageLive(_4); // scope 1 at $DIR/invalid_constant.rs:+13:25: +13:59
StorageLive(_5); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55
- Deinit(_5); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55
- (_5.0: u32) = const 4_u32; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55
+ _5 = InvalidTag { int: const 4_u32 }; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55
- _4 = (_5.1: E); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:57
- _3 = [move _4]; // scope 1 at $DIR/invalid_constant.rs:+13:24: +13:60
+ _4 = const Scalar(0x00000004): E; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:57
let mut _0: (); // return place in scope 0 at $DIR/issue_66971.rs:+0:11: +0:11
let _1: (); // in scope 0 at $DIR/issue_66971.rs:+1:5: +1:23
let mut _2: ((), u8, u8); // in scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
+ let mut _3: (); // in scope 0 at $DIR/issue_66971.rs:+1:13: +1:15
bb0: {
StorageLive(_1); // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23
StorageLive(_2); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
- Deinit(_2); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
- (_2.1: u8) = const 0_u8; // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
- (_2.2: u8) = const 0_u8; // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
+ StorageLive(_3); // scope 0 at $DIR/issue_66971.rs:+1:13: +1:15
+ _2 = (move _3, const 0_u8, const 0_u8); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
+ StorageDead(_3); // scope 0 at $DIR/issue_66971.rs:+1:21: +1:22
_1 = encode(move _2) -> bb1; // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23
// mir::Constant
// + span: $DIR/issue_66971.rs:17:5: 17:11
StorageLive(_1); // scope 0 at $DIR/issue_67019.rs:+1:5: +1:20
StorageLive(_2); // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19
StorageLive(_3); // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
- Deinit(_3); // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
- (_3.0: u8) = const 1_u8; // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
- (_3.1: u8) = const 2_u8; // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
- Deinit(_2); // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19
-- (_2.0: (u8, u8)) = move _3; // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19
-+ (_2.0: (u8, u8)) = const (1_u8, 2_u8); // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19
+- _3 = (const 1_u8, const 2_u8); // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
++ _3 = const (1_u8, 2_u8); // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
+ _2 = (move _3,); // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19
StorageDead(_3); // scope 0 at $DIR/issue_67019.rs:+1:18: +1:19
_1 = test(move _2) -> bb1; // scope 0 at $DIR/issue_67019.rs:+1:5: +1:20
// mir::Constant
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_aggregate.rs:+0:11: +0:11
- let mut _1: (i32, i32); // in scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14
+ let mut _3: i32; // in scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14
+ let mut _4: i32; // in scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14
scope 1 {
- debug x => _1; // in scope 1 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14
- let _2: (i32, i32); // in scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10
+ debug x => (i32, i32){ .0 => _3, .1 => _4, }; // in scope 1 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14
+ let _1: i32; // in scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10
+ let _2: i32; // in scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10
scope 2 {
- debug y => _2; // in scope 2 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10
+ debug y => (i32, i32){ .0 => _3, .1 => _2, }; // in scope 2 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10
}
}
bb0: {
- StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25
- (_1.0: i32) = const 42_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25
- (_1.1: i32) = const 43_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25
- (_1.1: i32) = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:+2:5: +2:13
+ StorageLive(_4); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14
+ _3 = const 42_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25
+ _4 = const 43_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25
+ _4 = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:+2:5: +2:13
StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10
-- _2 = _1; // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14
-+ _2 = const (42_i32, 99_i32); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14
+- _2 = _4; // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14
++ _2 = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14
StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2
- StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2
+ StorageDead(_4); // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2
return; // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:2: +4:2
}
}
let _2: &mut (i32, i32); // in scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:9: +2:10
scope 2 {
debug z => _2; // in scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:9: +2:10
- let _3: (i32, i32); // in scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10
+ let _3: i32; // in scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10
+ let _4: i32; // in scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10
scope 3 {
- debug y => _3; // in scope 3 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10
+ debug y => (i32, i32){ .0 => _3, .1 => _4, }; // in scope 3 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10
}
}
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25
- (_1.0: i32) = const 42_i32; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25
- (_1.1: i32) = const 43_i32; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25
+ _1 = (const 42_i32, const 43_i32); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25
StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:9: +2:10
_2 = &mut _1; // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:13: +2:19
((*_2).1: i32) = const 99_i32; // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+3:5: +3:13
StorageLive(_3); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10
- _3 = _1; // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:13: +4:14
+ StorageLive(_4); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10
+ _3 = (_1.0: i32); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:13: +4:14
+ _4 = (_1.1: i32); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:13: +4:14
StorageDead(_3); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2
+ StorageDead(_4); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2
StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2
StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2
return; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:2: +5:2
debug y => _3; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10
let _4: i32; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10
scope 4 {
- debug z => _4; // in scope 4 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10
+ debug z => _5; // in scope 4 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10
}
}
}
}
bb1: {
- StorageLive(_5); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
StorageLive(_6); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
- Deinit(_5); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
- Deinit(_6); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
_5 = const 1_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
_6 = const 2_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
StorageLive(_2); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12
StorageDead(_2); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12
StorageLive(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10
_3 = _6; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:13: +4:16
- StorageLive(_4); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10
-- _4 = _5; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16
-+ _4 = const 1_i32; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16
- StorageDead(_4); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
StorageDead(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
- StorageDead(_5); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
StorageDead(_6); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
StorageDead(_1); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
return; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+6:2: +6:2
debug y => _3; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
let _8: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
scope 3 {
- debug z => _8; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
+ debug z => _9; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
}
}
}
+ _3 = const 3_i32; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34
StorageDead(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
- StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
- StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
- Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
_9 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- _8 = _9; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
-+ _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
- StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
- StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2
debug y => _3; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
let _8: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
scope 3 {
- debug z => _8; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
+ debug z => _9; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
}
}
}
+ _3 = const 3_i32; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34
StorageDead(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
- StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
- StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
- Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
_9 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- _8 = _9; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
-+ _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
- StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
- StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11
let _1: i32; // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
+ let mut _3: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
scope 1 {
debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
let _2: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
scope 2 {
debug y => _2; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
- let _3: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
scope 3 {
debug z => _3; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
StorageLive(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
- StorageLive(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
- StorageDead(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11
let _1: i32; // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
+ let mut _3: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
scope 1 {
debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
let _2: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
scope 2 {
debug y => _2; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
- let _3: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
scope 3 {
debug z => _3; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
StorageLive(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
- StorageLive(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
- StorageDead(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2
StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
- StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- (_9.0: u32) = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- (_9.1: u32) = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+- _9 = Point { x: const 12_u32, y: const 42_u32 }; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
- _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
- StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
+ StorageLive(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ StorageLive(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ Deinit(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ Deinit(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
++ nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ _10 = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ _11 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
++ nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ _8 = _11; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
+ StorageDead(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
+ StorageDead(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
++ nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2
StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
- StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- (_9.0: u32) = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- (_9.1: u32) = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+- _9 = Point { x: const 12_u32, y: const 42_u32 }; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
- _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
- StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
+ StorageLive(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ StorageLive(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ Deinit(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ Deinit(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
++ nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ _10 = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ _11 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
++ nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ _8 = _11; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
+ StorageDead(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
+ StorageDead(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
++ nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2
StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11
let _1: i32; // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
+ let mut _3: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
scope 1 {
debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
let _2: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
scope 2 {
debug y => _2; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
- let _3: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
scope 3 {
debug z => _3; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
StorageLive(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
- StorageLive(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
- StorageDead(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11
let _1: i32; // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
+ let mut _3: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
scope 1 {
debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
let _2: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
scope 2 {
debug y => _2; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
- let _3: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
scope 3 {
debug z => _3; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
StorageLive(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
- StorageLive(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
- StorageDead(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2
}
bb0: {
- StorageLive(_1); // scope 0 at $DIR/scalar_literal_propagation.rs:+1:9: +1:10
_1 = const 1_u32; // scope 0 at $DIR/scalar_literal_propagation.rs:+1:13: +1:14
StorageLive(_2); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15
- _2 = consume(_1) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15
}
bb0: {
- StorageLive(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:9: +1:10
- Deinit(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
- (_1.0: u32) = const 1_u32; // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
- (_1.1: u32) = const 2_u32; // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
+- _1 = (const 1_u32, const 2_u32); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
++ _1 = const (1_u32, 2_u32); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
StorageLive(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15
- StorageLive(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14
-- _3 = _1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14
-+ _3 = const (1_u32, 2_u32); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14
- _2 = consume(move _3) -> bb1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15
+ _2 = consume(_1) -> bb1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15
// mir::Constant
// + span: $DIR/tuple_literal_propagation.rs:5:5: 5:12
// + literal: Const { ty: fn((u32, u32)) {consume}, val: Value(<ZST>) }
}
bb1: {
- StorageDead(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:14: +3:15
StorageDead(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:15: +3:16
- StorageDead(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+4:1: +4:2
return; // scope 0 at $DIR/tuple_literal_propagation.rs:+4:2: +4:2
}
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
- (_1.0: i32) = const 1_i32; // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
+- _1 = (const 1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
++ _1 = const (1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
StorageLive(_2); // scope 1 at $DIR/const_prop_miscompile.rs:+2:5: +4:6
StorageLive(_3); // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22
_3 = &raw mut (_1.0: i32); // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22
bb0: {
StorageLive(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
- (_1.0: i32) = const 1_i32; // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
+- _1 = (const 1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
++ _1 = const (1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
StorageLive(_2); // scope 1 at $DIR/const_prop_miscompile.rs:+2:6: +2:14
_2 = &mut (_1.0: i32); // scope 1 at $DIR/const_prop_miscompile.rs:+2:6: +2:14
(*_2) = const 5_i32; // scope 1 at $DIR/const_prop_miscompile.rs:+2:5: +2:18
}
bb1: {
- StorageLive(_2); // scope 1 at $DIR/cycle.rs:+2:9: +2:10
+- StorageLive(_2); // scope 1 at $DIR/cycle.rs:+2:9: +2:10
_2 = _1; // scope 1 at $DIR/cycle.rs:+2:13: +2:14
- StorageLive(_3); // scope 2 at $DIR/cycle.rs:+3:9: +3:10
- _3 = _2; // scope 2 at $DIR/cycle.rs:+3:13: +3:14
}
bb0: {
- StorageLive(_2); // scope 0 at $DIR/dead_stores_79191.rs:+1:9: +1:10
_2 = _1; // scope 0 at $DIR/dead_stores_79191.rs:+1:13: +1:14
_1 = const 5_usize; // scope 1 at $DIR/dead_stores_79191.rs:+2:5: +2:10
_1 = _2; // scope 1 at $DIR/dead_stores_79191.rs:+3:5: +3:10
}
bb0: {
- StorageLive(_2); // scope 0 at $DIR/dead_stores_better.rs:+1:9: +1:10
_2 = _1; // scope 0 at $DIR/dead_stores_better.rs:+1:13: +1:14
_1 = const 5_usize; // scope 1 at $DIR/dead_stores_better.rs:+2:5: +2:10
_1 = _2; // scope 1 at $DIR/dead_stores_better.rs:+3:5: +3:10
--- /dev/null
+- // MIR for `main` before CopyProp
++ // MIR for `main` after CopyProp
+
+ fn main() -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/issue_107511.rs:+0:11: +0:11
+ let mut _1: i32; // in scope 0 at $DIR/issue_107511.rs:+1:9: +1:16
+ let mut _3: std::ops::Range<usize>; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24
+ let mut _4: std::ops::Range<usize>; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24
+ let mut _5: usize; // in scope 0 at $DIR/issue_107511.rs:+6:17: +6:24
+ let mut _6: &[i32]; // in scope 0 at $DIR/issue_107511.rs:+6:17: +6:24
+ let mut _7: &[i32; 4]; // in scope 0 at $DIR/issue_107511.rs:+6:17: +6:24
+ let mut _9: (); // in scope 0 at $DIR/issue_107511.rs:+0:1: +9:2
+ let _10: (); // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24
+ let mut _11: std::option::Option<usize>; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24
+ let mut _12: &mut std::ops::Range<usize>; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24
+ let mut _13: &mut std::ops::Range<usize>; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24
+ let mut _14: isize; // in scope 0 at $DIR/issue_107511.rs:+6:5: +8:6
+ let mut _15: !; // in scope 0 at $DIR/issue_107511.rs:+6:5: +8:6
+ let mut _17: i32; // in scope 0 at $DIR/issue_107511.rs:+7:16: +7:20
+ let _18: usize; // in scope 0 at $DIR/issue_107511.rs:+7:18: +7:19
+ let mut _19: usize; // in scope 0 at $DIR/issue_107511.rs:+7:16: +7:20
+ let mut _20: bool; // in scope 0 at $DIR/issue_107511.rs:+7:16: +7:20
+ scope 1 {
+ debug sum => _1; // in scope 1 at $DIR/issue_107511.rs:+1:9: +1:16
+ let _2: [i32; 4]; // in scope 1 at $DIR/issue_107511.rs:+2:9: +2:10
+ scope 2 {
+ debug a => _2; // in scope 2 at $DIR/issue_107511.rs:+2:9: +2:10
+ let mut _8: std::ops::Range<usize>; // in scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+ scope 3 {
+ debug iter => _8; // in scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ let _16: usize; // in scope 3 at $DIR/issue_107511.rs:+6:9: +6:10
+ scope 4 {
+ debug i => _16; // in scope 4 at $DIR/issue_107511.rs:+6:9: +6:10
+ }
+ }
+ }
+ }
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/issue_107511.rs:+1:9: +1:16
+ _1 = const 0_i32; // scope 0 at $DIR/issue_107511.rs:+1:19: +1:20
+ StorageLive(_2); // scope 1 at $DIR/issue_107511.rs:+2:9: +2:10
+ _2 = [const 0_i32, const 10_i32, const 20_i32, const 30_i32]; // scope 1 at $DIR/issue_107511.rs:+2:13: +2:28
+ StorageLive(_3); // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+ StorageLive(_4); // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+ StorageLive(_5); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24
+ StorageLive(_6); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24
+ StorageLive(_7); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24
+ _7 = &_2; // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24
+ _6 = move _7 as &[i32] (Pointer(Unsize)); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24
+ StorageDead(_7); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:18
+ _5 = core::slice::<impl [i32]>::len(move _6) -> bb1; // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24
+ // mir::Constant
+ // + span: $DIR/issue_107511.rs:10:19: 10:22
+ // + literal: Const { ty: for<'a> fn(&'a [i32]) -> usize {core::slice::<impl [i32]>::len}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageDead(_6); // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24
+ _4 = std::ops::Range::<usize> { start: const 0_usize, end: move _5 }; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+ StorageDead(_5); // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24
+ _3 = <std::ops::Range<usize> as IntoIterator>::into_iter(move _4) -> bb2; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+ // mir::Constant
+ // + span: $DIR/issue_107511.rs:10:14: 10:24
+ // + literal: Const { ty: fn(std::ops::Range<usize>) -> <std::ops::Range<usize> as IntoIterator>::IntoIter {<std::ops::Range<usize> as IntoIterator>::into_iter}, val: Value(<ZST>) }
+ }
+
+ bb2: {
+ StorageDead(_4); // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24
+ StorageLive(_8); // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+ _8 = move _3; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+ goto -> bb3; // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6
+ }
+
+ bb3: {
+- StorageLive(_10); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ StorageLive(_11); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ StorageLive(_12); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ StorageLive(_13); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ _13 = &mut _8; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ _12 = &mut (*_13); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ _11 = <std::ops::Range<usize> as Iterator>::next(move _12) -> bb4; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ // mir::Constant
+ // + span: $DIR/issue_107511.rs:10:14: 10:24
+ // + literal: Const { ty: for<'a> fn(&'a mut std::ops::Range<usize>) -> Option<<std::ops::Range<usize> as Iterator>::Item> {<std::ops::Range<usize> as Iterator>::next}, val: Value(<ZST>) }
+ }
+
+ bb4: {
+ StorageDead(_12); // scope 3 at $DIR/issue_107511.rs:+6:23: +6:24
+ _14 = discriminant(_11); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ switchInt(move _14) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ }
+
+ bb5: {
+- StorageLive(_16); // scope 3 at $DIR/issue_107511.rs:+6:9: +6:10
+ _16 = ((_11 as Some).0: usize); // scope 3 at $DIR/issue_107511.rs:+6:9: +6:10
+ StorageLive(_17); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
+- StorageLive(_18); // scope 4 at $DIR/issue_107511.rs:+7:18: +7:19
+- _18 = _16; // scope 4 at $DIR/issue_107511.rs:+7:18: +7:19
+ _19 = Len(_2); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
+- _20 = Lt(_18, _19); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
+- assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, _18) -> bb8; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
++ _20 = Lt(_16, _19); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
++ assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, _16) -> bb8; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
+ }
+
+ bb6: {
+ unreachable; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ }
+
+ bb7: {
+ _0 = const (); // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6
+ StorageDead(_13); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+ StorageDead(_11); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+- StorageDead(_10); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+ StorageDead(_8); // scope 2 at $DIR/issue_107511.rs:+8:5: +8:6
+ StorageDead(_3); // scope 2 at $DIR/issue_107511.rs:+8:5: +8:6
+ StorageDead(_2); // scope 1 at $DIR/issue_107511.rs:+9:1: +9:2
+ StorageDead(_1); // scope 0 at $DIR/issue_107511.rs:+9:1: +9:2
+ return; // scope 0 at $DIR/issue_107511.rs:+9:2: +9:2
+ }
+
+ bb8: {
+- _17 = _2[_18]; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
++ _17 = _2[_16]; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
+ _1 = Add(_1, move _17); // scope 4 at $DIR/issue_107511.rs:+7:9: +7:20
+ StorageDead(_17); // scope 4 at $DIR/issue_107511.rs:+7:19: +7:20
+- StorageDead(_18); // scope 4 at $DIR/issue_107511.rs:+7:20: +7:21
+- _10 = const (); // scope 4 at $DIR/issue_107511.rs:+6:25: +8:6
+- StorageDead(_16); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+ StorageDead(_13); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+ StorageDead(_11); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+- StorageDead(_10); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+- _9 = const (); // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6
+ goto -> bb3; // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6
+ }
+ }
+
--- /dev/null
+// unit-test: CopyProp
+
+// EMIT_MIR issue_107511.main.CopyProp.diff
+fn main() {
+ let mut sum = 0;
+ let a = [0, 10, 20, 30];
+
+ // `i` is assigned in a loop. Only removing its `StorageDead` would mean that
+ // execution sees repeated `StorageLive`. This would be UB.
+ for i in 0..a.len() {
+ sum += a[i];
+ }
+}
bb0: {
StorageLive(_1); // scope 0 at $DIR/enum.rs:+1:9: +1:10
- Deinit(_1); // scope 0 at $DIR/enum.rs:+1:13: +1:21
- ((_1 as V1).0: i32) = const 0_i32; // scope 0 at $DIR/enum.rs:+1:13: +1:21
- discriminant(_1) = 0; // scope 0 at $DIR/enum.rs:+1:13: +1:21
+ _1 = E::V1(const 0_i32); // scope 0 at $DIR/enum.rs:+1:13: +1:21
StorageLive(_2); // scope 1 at $DIR/enum.rs:+2:9: +2:10
_3 = discriminant(_1); // scope 1 at $DIR/enum.rs:+2:19: +2:20
switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 1 at $DIR/enum.rs:+2:13: +2:20
}
bb0: {
- StorageLive(_1); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
_1 = const u8::MAX; // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
- StorageLive(_2); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
_2 = const 1_u8; // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
_5 = CheckedAdd(const u8::MAX, const 1_u8); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> bb1; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
bb0: {
StorageLive(_1); // scope 0 at $DIR/repr_transparent.rs:+1:9: +1:10
- Deinit(_1); // scope 0 at $DIR/repr_transparent.rs:+1:13: +1:19
- (_1.0: i32) = const 0_i32; // scope 0 at $DIR/repr_transparent.rs:+1:13: +1:19
+ _1 = I32(const 0_i32); // scope 0 at $DIR/repr_transparent.rs:+1:13: +1:19
StorageLive(_2); // scope 1 at $DIR/repr_transparent.rs:+2:9: +2:10
StorageLive(_3); // scope 1 at $DIR/repr_transparent.rs:+2:17: +2:26
StorageLive(_4); // scope 1 at $DIR/repr_transparent.rs:+2:17: +2:20
+ _3 = const 0_i32; // scope 1 at $DIR/repr_transparent.rs:+2:17: +2:26
StorageDead(_5); // scope 1 at $DIR/repr_transparent.rs:+2:25: +2:26
StorageDead(_4); // scope 1 at $DIR/repr_transparent.rs:+2:25: +2:26
- Deinit(_2); // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27
-- (_2.0: i32) = move _3; // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27
-+ (_2.0: i32) = const 0_i32; // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27
+- _2 = I32(move _3); // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27
++ _2 = I32(const 0_i32); // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27
StorageDead(_3); // scope 1 at $DIR/repr_transparent.rs:+2:26: +2:27
_0 = const (); // scope 0 at $DIR/repr_transparent.rs:+0:11: +3:2
StorageDead(_2); // scope 1 at $DIR/repr_transparent.rs:+3:1: +3:2
bb0: {
StorageLive(_1); // scope 0 at $DIR/sibling_ptr.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
- (_1.0: u8) = const 0_u8; // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
- (_1.1: u8) = const 0_u8; // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
+ _1 = (const 0_u8, const 0_u8); // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
StorageLive(_2); // scope 1 at $DIR/sibling_ptr.rs:+2:5: +5:6
StorageLive(_3); // scope 2 at $DIR/sibling_ptr.rs:+3:13: +3:14
_3 = &raw mut (_1.0: u8); // scope 2 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
bb0: {
StorageLive(_1); // scope 0 at $DIR/struct.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/struct.rs:+1:17: +1:21
- (_1.0: i32) = const 1_i32; // scope 0 at $DIR/struct.rs:+1:17: +1:21
+ _1 = S(const 1_i32); // scope 0 at $DIR/struct.rs:+1:17: +1:21
StorageLive(_2); // scope 1 at $DIR/struct.rs:+2:9: +2:10
StorageLive(_3); // scope 1 at $DIR/struct.rs:+2:13: +2:16
- _3 = (_1.0: i32); // scope 1 at $DIR/struct.rs:+2:13: +2:16
bb0: {
StorageLive(_1); // scope 0 at $DIR/tuple.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/tuple.rs:+1:17: +1:23
- (_1.0: i32) = const 1_i32; // scope 0 at $DIR/tuple.rs:+1:17: +1:23
- (_1.1: i32) = const 2_i32; // scope 0 at $DIR/tuple.rs:+1:17: +1:23
+ _1 = (const 1_i32, const 2_i32); // scope 0 at $DIR/tuple.rs:+1:17: +1:23
StorageLive(_2); // scope 1 at $DIR/tuple.rs:+2:9: +2:10
StorageLive(_3); // scope 1 at $DIR/tuple.rs:+2:13: +2:22
StorageLive(_4); // scope 1 at $DIR/tuple.rs:+2:13: +2:16
- _2 = Add(move _3, const 3_i32); // scope 1 at $DIR/tuple.rs:+2:13: +2:26
+ _2 = const 6_i32; // scope 1 at $DIR/tuple.rs:+2:13: +2:26
StorageDead(_3); // scope 1 at $DIR/tuple.rs:+2:25: +2:26
- Deinit(_1); // scope 2 at $DIR/tuple.rs:+3:5: +3:15
- (_1.0: i32) = const 2_i32; // scope 2 at $DIR/tuple.rs:+3:5: +3:15
- (_1.1: i32) = const 3_i32; // scope 2 at $DIR/tuple.rs:+3:5: +3:15
+ _1 = (const 2_i32, const 3_i32); // scope 2 at $DIR/tuple.rs:+3:5: +3:15
StorageLive(_6); // scope 2 at $DIR/tuple.rs:+4:9: +4:10
StorageLive(_7); // scope 2 at $DIR/tuple.rs:+4:13: +4:22
StorageLive(_8); // scope 2 at $DIR/tuple.rs:+4:13: +4:16
+++ /dev/null
-- // MIR for `bar` before Deaggregator
-+ // MIR for `bar` after Deaggregator
-
- fn bar(_1: usize) -> Baz {
- debug a => _1; // in scope 0 at $DIR/deaggregator_test.rs:+0:8: +0:9
- let mut _0: Baz; // return place in scope 0 at $DIR/deaggregator_test.rs:+0:21: +0:24
- let mut _2: usize; // in scope 0 at $DIR/deaggregator_test.rs:+1:14: +1:15
-
- bb0: {
- StorageLive(_2); // scope 0 at $DIR/deaggregator_test.rs:+1:14: +1:15
- _2 = _1; // scope 0 at $DIR/deaggregator_test.rs:+1:14: +1:15
-- _0 = Baz { x: move _2, y: const 0f32, z: const false }; // scope 0 at $DIR/deaggregator_test.rs:+1:5: +1:35
-+ Deinit(_0); // scope 0 at $DIR/deaggregator_test.rs:+1:5: +1:35
-+ (_0.0: usize) = move _2; // scope 0 at $DIR/deaggregator_test.rs:+1:5: +1:35
-+ (_0.1: f32) = const 0f32; // scope 0 at $DIR/deaggregator_test.rs:+1:5: +1:35
-+ (_0.2: bool) = const false; // scope 0 at $DIR/deaggregator_test.rs:+1:5: +1:35
- StorageDead(_2); // scope 0 at $DIR/deaggregator_test.rs:+1:34: +1:35
- return; // scope 0 at $DIR/deaggregator_test.rs:+2:2: +2:2
- }
- }
-
+++ /dev/null
-// unit-test: Deaggregator
-
-struct Baz {
- x: usize,
- y: f32,
- z: bool,
-}
-
-// EMIT_MIR deaggregator_test.bar.Deaggregator.diff
-fn bar(a: usize) -> Baz {
- Baz { x: a, y: 0.0, z: false }
-}
-
-fn main() {
- // Make sure the function actually gets instantiated.
- bar(0);
-}
+++ /dev/null
-- // MIR for `bar` before Deaggregator
-+ // MIR for `bar` after Deaggregator
-
- fn bar(_1: usize) -> Baz {
- debug a => _1; // in scope 0 at $DIR/deaggregator_test_enum.rs:+0:8: +0:9
- let mut _0: Baz; // return place in scope 0 at $DIR/deaggregator_test_enum.rs:+0:21: +0:24
- let mut _2: usize; // in scope 0 at $DIR/deaggregator_test_enum.rs:+1:19: +1:20
-
- bb0: {
- StorageLive(_2); // scope 0 at $DIR/deaggregator_test_enum.rs:+1:19: +1:20
- _2 = _1; // scope 0 at $DIR/deaggregator_test_enum.rs:+1:19: +1:20
-- _0 = Baz::Foo { x: move _2 }; // scope 0 at $DIR/deaggregator_test_enum.rs:+1:5: +1:22
-+ Deinit(_0); // scope 0 at $DIR/deaggregator_test_enum.rs:+1:5: +1:22
-+ ((_0 as Foo).0: usize) = move _2; // scope 0 at $DIR/deaggregator_test_enum.rs:+1:5: +1:22
-+ discriminant(_0) = 1; // scope 0 at $DIR/deaggregator_test_enum.rs:+1:5: +1:22
- StorageDead(_2); // scope 0 at $DIR/deaggregator_test_enum.rs:+1:21: +1:22
- return; // scope 0 at $DIR/deaggregator_test_enum.rs:+2:2: +2:2
- }
- }
-
+++ /dev/null
-// unit-test: Deaggregator
-
-enum Baz {
- Empty,
- Foo { x: usize },
-}
-
-// EMIT_MIR deaggregator_test_enum.bar.Deaggregator.diff
-fn bar(a: usize) -> Baz {
- Baz::Foo { x: a }
-}
-
-fn main() {
- let x = bar(10);
- match x {
- Baz::Empty => println!("empty"),
- Baz::Foo { x } => println!("{}", x),
- };
-}
+++ /dev/null
-// unit-test: Deaggregator
-// Test that deaggregate fires in more than one basic block
-
-enum Foo {
- A(i32),
- B(i32),
-}
-
-// EMIT_MIR deaggregator_test_enum_2.test1.Deaggregator.diff
-fn test1(x: bool, y: i32) -> Foo {
- if x {
- Foo::A(y)
- } else {
- Foo::B(y)
- }
-}
-
-fn main() {
- // Make sure the function actually gets instantiated.
- test1(false, 0);
-}
+++ /dev/null
-- // MIR for `test1` before Deaggregator
-+ // MIR for `test1` after Deaggregator
-
- fn test1(_1: bool, _2: i32) -> Foo {
- debug x => _1; // in scope 0 at $DIR/deaggregator_test_enum_2.rs:+0:10: +0:11
- debug y => _2; // in scope 0 at $DIR/deaggregator_test_enum_2.rs:+0:19: +0:20
- let mut _0: Foo; // return place in scope 0 at $DIR/deaggregator_test_enum_2.rs:+0:30: +0:33
- let mut _3: bool; // in scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
- let mut _4: i32; // in scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:16: +2:17
- let mut _5: i32; // in scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:16: +4:17
-
- bb0: {
- StorageLive(_3); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
- _3 = _1; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
- switchInt(move _3) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
- }
-
- bb1: {
- StorageLive(_4); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:16: +2:17
- _4 = _2; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:16: +2:17
-- _0 = Foo::A(move _4); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:9: +2:18
-+ Deinit(_0); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:9: +2:18
-+ ((_0 as A).0: i32) = move _4; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:9: +2:18
-+ discriminant(_0) = 0; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:9: +2:18
- StorageDead(_4); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:17: +2:18
- goto -> bb3; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:5: +5:6
- }
-
- bb2: {
- StorageLive(_5); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:16: +4:17
- _5 = _2; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:16: +4:17
-- _0 = Foo::B(move _5); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:9: +4:18
-+ Deinit(_0); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:9: +4:18
-+ ((_0 as B).0: i32) = move _5; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:9: +4:18
-+ discriminant(_0) = 1; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:9: +4:18
- StorageDead(_5); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:17: +4:18
- goto -> bb3; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:5: +5:6
- }
-
- bb3: {
- StorageDead(_3); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+5:5: +5:6
- return; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+6:2: +6:2
- }
- }
-
+++ /dev/null
-// unit-test: Deaggregator
-// Test that deaggregate fires more than once per block
-
-enum Foo {
- A(i32),
- B,
-}
-
-// EMIT_MIR deaggregator_test_multiple.test.Deaggregator.diff
-fn test(x: i32) -> [Foo; 2] {
- [Foo::A(x), Foo::A(x)]
-}
-
-fn main() {
- // Make sure the function actually gets instantiated.
- test(0);
-}
+++ /dev/null
-- // MIR for `test` before Deaggregator
-+ // MIR for `test` after Deaggregator
-
- fn test(_1: i32) -> [Foo; 2] {
- debug x => _1; // in scope 0 at $DIR/deaggregator_test_multiple.rs:+0:9: +0:10
- let mut _0: [Foo; 2]; // return place in scope 0 at $DIR/deaggregator_test_multiple.rs:+0:20: +0:28
- let mut _2: Foo; // in scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15
- let mut _3: i32; // in scope 0 at $DIR/deaggregator_test_multiple.rs:+1:13: +1:14
- let mut _4: Foo; // in scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26
- let mut _5: i32; // in scope 0 at $DIR/deaggregator_test_multiple.rs:+1:24: +1:25
-
- bb0: {
- StorageLive(_2); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15
- StorageLive(_3); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:13: +1:14
- _3 = _1; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:13: +1:14
-- _2 = Foo::A(move _3); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15
-+ Deinit(_2); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15
-+ ((_2 as A).0: i32) = move _3; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15
-+ discriminant(_2) = 0; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15
- StorageDead(_3); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:14: +1:15
- StorageLive(_4); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26
- StorageLive(_5); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:24: +1:25
- _5 = _1; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:24: +1:25
-- _4 = Foo::A(move _5); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26
-+ Deinit(_4); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26
-+ ((_4 as A).0: i32) = move _5; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26
-+ discriminant(_4) = 0; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26
- StorageDead(_5); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:25: +1:26
- _0 = [move _2, move _4]; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:5: +1:27
- StorageDead(_4); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:26: +1:27
- StorageDead(_2); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:26: +1:27
- return; // scope 0 at $DIR/deaggregator_test_multiple.rs:+2:2: +2:2
- }
- }
-
_4 = _1; // scope 0 at $DIR/early_otherwise_branch.rs:+1:12: +1:13
StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16
_5 = _2; // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16
- Deinit(_3); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
- (_3.0: std::option::Option<u32>) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
- (_3.1: std::option::Option<u32>) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
+ _3 = (move _4, move _5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
_7 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
_4 = _1; // scope 0 at $DIR/early_otherwise_branch.rs:+1:12: +1:13
StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16
_5 = _2; // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16
- Deinit(_3); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
- (_3.0: std::option::Option<u32>) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
- (_3.1: std::option::Option<u32>) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
+ _3 = (move _4, move _5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
_8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
_4 = _1; // scope 0 at $DIR/early_otherwise_branch.rs:+1:12: +1:13
StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16
_5 = _2; // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16
- Deinit(_3); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
- (_3.0: std::option::Option<u32>) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
- (_3.1: std::option::Option<bool>) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
+ _3 = (move _4, move _5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
_7 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
_6 = _2; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:15: +1:16
StorageLive(_7); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:18: +1:19
_7 = _3; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:18: +1:19
- Deinit(_4); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
- (_4.0: std::option::Option<u32>) = move _5; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
- (_4.1: std::option::Option<u32>) = move _6; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
- (_4.2: std::option::Option<u32>) = move _7; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
+ _4 = (move _5, move _6, move _7); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
StorageDead(_7); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:19: +1:20
StorageDead(_6); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:19: +1:20
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:19: +1:20
_5 = _1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:15: +5:16
StorageLive(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:18: +5:23
_6 = _2; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:18: +5:23
- Deinit(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- (_4.0: &ViewportPercentageLength) = move _5; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- (_4.1: &ViewportPercentageLength) = move _6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
+ _4 = (move _5, move _6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
StorageDead(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24
_34 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
bb2: {
StorageLive(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
- Deinit(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
- Deinit(_0); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
- ((_0 as Err).0: ()) = move _33; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
- discriminant(_0) = 1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
+ _33 = (); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
+ _0 = Result::<ViewportPercentageLength, ()>::Err(move _33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
StorageDead(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:27: +10:28
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2
_14 = Add(move _15, move _16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:49
StorageDead(_16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:48: +6:49
StorageDead(_15); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:48: +6:49
- Deinit(_3); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
- ((_3 as Vw).0: f32) = move _14; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
- discriminant(_3) = 0; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
+ _3 = ViewportPercentageLength::Vw(move _14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
StorageDead(_14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
StorageDead(_13); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
_19 = Add(move _20, move _21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:49
StorageDead(_21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:48: +7:49
StorageDead(_20); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:48: +7:49
- Deinit(_3); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
- ((_3 as Vh).0: f32) = move _19; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
- discriminant(_3) = 1; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
+ _3 = ViewportPercentageLength::Vh(move _19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
StorageDead(_19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
StorageDead(_18); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
StorageDead(_17); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
_24 = Add(move _25, move _26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:55
StorageDead(_26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:54: +8:55
StorageDead(_25); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:54: +8:55
- Deinit(_3); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
- ((_3 as Vmin).0: f32) = move _24; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
- discriminant(_3) = 2; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
+ _3 = ViewportPercentageLength::Vmin(move _24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
StorageDead(_24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
StorageDead(_23); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
StorageDead(_22); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
_29 = Add(move _30, move _31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:55
StorageDead(_31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:54: +9:55
StorageDead(_30); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:54: +9:55
- Deinit(_3); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
- ((_3 as Vmax).0: f32) = move _29; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
- discriminant(_3) = 3; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
+ _3 = ViewportPercentageLength::Vmax(move _29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
StorageDead(_29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
StorageDead(_28); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
StorageDead(_27); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
}
bb10: {
- Deinit(_0); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
- ((_0 as Ok).0: ViewportPercentageLength) = move _3; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
- discriminant(_0) = 0; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
+ _0 = Result::<ViewportPercentageLength, ()>::Ok(move _3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2
goto -> bb11; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
_4 = _1; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:12: +1:13
StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:15: +1:16
_5 = _2; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:15: +1:16
- Deinit(_3); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
- (_3.0: std::option::Option<u32>) = move _4; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
- (_3.1: std::option::Option<u32>) = move _5; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
+ _3 = (move _4, move _5); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:16: +1:17
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:16: +1:17
_8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
}
bb2: {
- Deinit(_6); // scope 1 at $DIR/funky_arms.rs:+10:17: +10:41
- discriminant(_6) = 1; // scope 1 at $DIR/funky_arms.rs:+10:17: +10:41
+- _6 = MinusPlus; // scope 1 at $DIR/funky_arms.rs:+10:17: +10:41
++ _6 = const MinusPlus; // scope 1 at $DIR/funky_arms.rs:+10:17: +10:41
++ // mir::Constant
++ // + span: $DIR/funky_arms.rs:21:17: 21:41
++ // + literal: Const { ty: Sign, val: Value(Scalar(0x01)) }
goto -> bb4; // scope 1 at $DIR/funky_arms.rs:+10:17: +10:41
}
bb3: {
- Deinit(_6); // scope 1 at $DIR/funky_arms.rs:+9:18: +9:38
- discriminant(_6) = 0; // scope 1 at $DIR/funky_arms.rs:+9:18: +9:38
+- _6 = Minus; // scope 1 at $DIR/funky_arms.rs:+9:18: +9:38
++ _6 = const Minus; // scope 1 at $DIR/funky_arms.rs:+9:18: +9:38
++ // mir::Constant
++ // + span: $DIR/funky_arms.rs:20:18: 20:38
++ // + literal: Const { ty: Sign, val: Value(Scalar(0x00)) }
goto -> bb4; // scope 1 at $DIR/funky_arms.rs:+9:18: +9:38
}
}
bb6: {
- StorageLive(_10); // scope 3 at $DIR/funky_arms.rs:+13:17: +13:26
_10 = ((_7 as Some).0: usize); // scope 3 at $DIR/funky_arms.rs:+13:17: +13:26
StorageLive(_11); // scope 3 at $DIR/funky_arms.rs:+15:43: +15:46
_11 = &mut (*_1); // scope 3 at $DIR/funky_arms.rs:+15:43: +15:46
StorageLive(_6); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
StorageLive(_7); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
_7 = (); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
- Deinit(_0); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
- ((_0 as Yielded).0: ()) = move _7; // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
- discriminant(_0) = 0; // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
+ _0 = GeneratorState::<(), ()>::Yielded(move _7); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
discriminant((*(_1.0: &mut [generator@$DIR/generator_tiny.rs:19:16: 19:24]))) = 3; // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
return; // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
}
StorageLive(_3); // scope 0 at $DIR/cycle.rs:+1:5: +1:6
_3 = &_1; // scope 0 at $DIR/cycle.rs:+1:5: +1:6
StorageLive(_4); // scope 0 at $DIR/cycle.rs:+1:5: +1:8
- Deinit(_4); // scope 0 at $DIR/cycle.rs:+1:5: +1:8
+ _4 = (); // scope 0 at $DIR/cycle.rs:+1:5: +1:8
_2 = <impl Fn() as Fn<()>>::call(move _3, move _4) -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/cycle.rs:+1:5: +1:8
// mir::Constant
// + span: $DIR/cycle.rs:6:5: 6:6
bb0: {
StorageLive(_3); // scope 0 at $DIR/inline_closure.rs:+1:9: +1:10
- Deinit(_3); // scope 0 at $DIR/inline_closure.rs:+1:13: +1:24
+ _3 = [closure@foo::<T>::{closure#0}]; // scope 0 at $DIR/inline_closure.rs:+1:13: +1:24
+ // closure
+ // + def_id: DefId(0:6 ~ inline_closure[92ba]::foo::{closure#0})
+ // + substs: [
+ // T,
+ // i8,
+ // extern "rust-call" fn((i32, i32)) -> i32,
+ // (),
+ // ]
StorageLive(_4); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:6
_4 = &_3; // scope 1 at $DIR/inline_closure.rs:+2:5: +2:6
StorageLive(_5); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
_6 = _2; // scope 1 at $DIR/inline_closure.rs:+2:7: +2:8
StorageLive(_7); // scope 1 at $DIR/inline_closure.rs:+2:10: +2:11
_7 = _2; // scope 1 at $DIR/inline_closure.rs:+2:10: +2:11
- Deinit(_5); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
- (_5.0: i32) = move _6; // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
- (_5.1: i32) = move _7; // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
+ _5 = (move _6, move _7); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
StorageLive(_8); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
_8 = move (_5.0: i32); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
StorageLive(_9); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
bb0: {
StorageLive(_3); // scope 0 at $DIR/inline_closure_borrows_arg.rs:+1:9: +1:10
- Deinit(_3); // scope 0 at $DIR/inline_closure_borrows_arg.rs:+1:13: +4:6
+ _3 = [closure@foo::<T>::{closure#0}]; // scope 0 at $DIR/inline_closure_borrows_arg.rs:+1:13: +4:6
+ // closure
+ // + def_id: DefId(0:6 ~ inline_closure_borrows_arg[96e9]::foo::{closure#0})
+ // + substs: [
+ // T,
+ // i8,
+ // for<'a, 'b> extern "rust-call" fn((&'a i32, &'b i32)) -> i32,
+ // (),
+ // ]
StorageLive(_4); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:6
_4 = &_3; // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:6
StorageLive(_5); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
_6 = &(*_2); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:7: +5:8
StorageLive(_7); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:10: +5:11
_7 = &(*_2); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:10: +5:11
- Deinit(_5); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
- (_5.0: &i32) = move _6; // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
- (_5.1: &i32) = move _7; // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
+ _5 = (move _6, move _7); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
StorageLive(_8); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
_8 = move (_5.0: &i32); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
StorageLive(_9); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
_4 = &_2; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
StorageLive(_5); // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
_5 = &_1; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
- Deinit(_3); // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
- (_3.0: &i32) = move _4; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
- (_3.1: &T) = move _5; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
+ _3 = [closure@foo::<T>::{closure#0}] { q: move _4, t: move _5 }; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
+ // closure
+ // + def_id: DefId(0:6 ~ inline_closure_captures[8bc0]::foo::{closure#0})
+ // + substs: [
+ // T,
+ // i8,
+ // extern "rust-call" fn((i32,)) -> (i32, T),
+ // (&i32, &T),
+ // ]
StorageDead(_5); // scope 0 at $DIR/inline_closure_captures.rs:+1:16: +1:17
StorageDead(_4); // scope 0 at $DIR/inline_closure_captures.rs:+1:16: +1:17
StorageLive(_6); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:6
StorageLive(_7); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
StorageLive(_8); // scope 1 at $DIR/inline_closure_captures.rs:+2:7: +2:8
_8 = _2; // scope 1 at $DIR/inline_closure_captures.rs:+2:7: +2:8
- Deinit(_7); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
- (_7.0: i32) = move _8; // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
+ _7 = (move _8,); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
StorageLive(_9); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
_9 = move (_7.0: i32); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
StorageLive(_10); // scope 2 at $DIR/inline_closure_captures.rs:+1:19: +1:20
StorageLive(_11); // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23
_13 = deref_copy ((*_6).1: &T); // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23
_11 = (*_13); // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23
- Deinit(_0); // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24
- (_0.0: i32) = move _10; // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24
- (_0.1: T) = move _11; // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24
+ _0 = (move _10, move _11); // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24
StorageDead(_11); // scope 2 at $DIR/inline_closure_captures.rs:+1:23: +1:24
StorageDead(_10); // scope 2 at $DIR/inline_closure_captures.rs:+1:23: +1:24
StorageDead(_9); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
+ StorageDead(_6); // scope 2 at $DIR/inline_diverging.rs:28:15: 28:16
+ StorageLive(_8); // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7
+ _8 = move _3; // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7
-+ Deinit(_1); // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11
-+ (_1.0: !) = move _8; // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11
-+ (_1.1: !) = move _9; // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11
++ _1 = (move _8, move _9); // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11
+ StorageDead(_8); // scope 3 at $DIR/inline_diverging.rs:29:10: 29:11
+ StorageDead(_3); // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
+ drop(_2) -> bb2; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
- }
-
- bb1: {
-+ Deinit(_4); // scope 2 at $DIR/inline_generator.rs:15:5: 15:41
-+ discriminant(_4) = 0; // scope 2 at $DIR/inline_generator.rs:15:5: 15:41
++ _4 = [generator@$DIR/inline_generator.rs:15:5: 15:8 (#0)]; // scope 2 at $DIR/inline_generator.rs:15:5: 15:41
++ // generator
++ // + def_id: DefId(0:7 ~ inline_generator[ea31]::g::{closure#0})
++ // + substs: [
++ // bool,
++ // i32,
++ // bool,
++ // {bool, i32},
++ // (),
++ // ]
++ // + movability: Movable
_3 = &mut _4; // scope 0 at $DIR/inline_generator.rs:+1:23: +1:31
- _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new(move _3) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline_generator.rs:+1:14: +1:32
- // mir::Constant
+ _5 = move _3; // scope 4 at $SRC_DIR/core/src/pin.rs:LL:COL
+ StorageLive(_6); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
+ _6 = move _5; // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
-+ Deinit(_2); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
-+ (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]) = move _6; // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
++ _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]> { pointer: move _6 }; // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
+ StorageDead(_6); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
+ StorageDead(_5); // scope 4 at $SRC_DIR/core/src/pin.rs:LL:COL
StorageDead(_3); // scope 0 at $DIR/inline_generator.rs:+1:31: +1:32
+ }
+
+ bb6: {
-+ Deinit(_1); // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
-+ ((_1 as Yielded).0: i32) = move _8; // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
-+ discriminant(_1) = 0; // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
++ _1 = GeneratorState::<i32, bool>::Yielded(move _8); // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
+ _11 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
+ discriminant((*_11)) = 3; // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
+ goto -> bb1; // scope 0 at $DIR/inline_generator.rs:15:11: 15:39
+ bb7: {
+ StorageLive(_8); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
+ StorageDead(_8); // scope 6 at $DIR/inline_generator.rs:15:38: 15:39
-+ Deinit(_1); // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
-+ ((_1 as Complete).0: bool) = _7; // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
-+ discriminant(_1) = 1; // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
++ _1 = GeneratorState::<i32, bool>::Complete(_7); // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
+ _12 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
+ discriminant((*_12)) = 1; // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
+ goto -> bb1; // scope 0 at $DIR/inline_generator.rs:15:41: 15:41
+ // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ // + user_ty: UserType(0)
+ // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Unevaluated(alloc::raw_vec::RawVec::<T>::NEW, [u32], None) }
-+ Deinit(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-+ (_9.0: alloc::raw_vec::RawVec<u32>) = move _10; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-+ (_9.1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
++ _9 = Vec::<u32> { buf: move _10, len: const 0_usize }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ StorageDead(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ (*_8) = move _9; // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
+ StorageDead(_9); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
bb0: {
StorageLive(_1); // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:9: +1:10
- Deinit(_1); // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:13: +1:33
+ _1 = [closure@$DIR/issue_76997_inline_scopes_parenting.rs:5:13: 5:16]; // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:13: +1:33
+ // closure
+ // + def_id: DefId(0:4 ~ issue_76997_inline_scopes_parenting[bc59]::main::{closure#0})
+ // + substs: [
+ // i8,
+ // extern "rust-call" fn(((),)),
+ // (),
+ // ]
StorageLive(_2); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:6
_2 = &_1; // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:6
StorageLive(_3); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10
StorageLive(_4); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:7: +2:9
- Deinit(_4); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:7: +2:9
- Deinit(_3); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10
- (_3.0: ()) = move _4; // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10
+ _4 = (); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:7: +2:9
+ _3 = (move _4,); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10
StorageLive(_5); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10
_5 = move (_3.0: ()); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10
StorageLive(_6); // scope 2 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:23: +1:24
bb1: {
_3 = &_4; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15
StorageLive(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
- Deinit(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
+ _5 = (); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
- _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
- // mir::Constant
- // + span: $DIR/issue_78442.rs:11:5: 11:15
bb1: {
_3 = &_4; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15
StorageLive(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
- Deinit(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
+ _5 = (); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
- _2 = <impl Fn() as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
+ _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
// mir::Constant
bb0: {
StorageLive(_2); // scope 0 at $DIR/issue_101973.rs:+1:5: +1:65
StorageLive(_3); // scope 0 at $DIR/issue_101973.rs:+1:5: +1:58
- StorageLive(_4); // scope 0 at $DIR/issue_101973.rs:+1:5: +1:17
StorageLive(_12); // scope 2 at $DIR/issue_101973.rs:7:12: 7:27
StorageLive(_13); // scope 2 at $DIR/issue_101973.rs:7:12: 7:20
_14 = CheckedShr(_1, const 0_i32); // scope 2 at $DIR/issue_101973.rs:7:12: 7:20
StorageDead(_13); // scope 2 at $DIR/issue_101973.rs:7:26: 7:27
_4 = BitOr(const 0_u32, move _12); // scope 2 at $DIR/issue_101973.rs:7:5: 7:27
StorageDead(_12); // scope 2 at $DIR/issue_101973.rs:7:26: 7:27
- StorageLive(_6); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
StorageLive(_7); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:52
StorageLive(_8); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
_10 = CheckedShr(_1, const 8_i32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
+// compile-flags: -Zmir-enable-passes=-NormalizeArrayLen
// Check that we do not insert StorageDead at each target if StorageDead was never seen
// EMIT_MIR issue_76432.test.SimplifyComparisonIntegral.diff
bb0: {
StorageLive(_2); // scope 0 at $DIR/issue_76432.rs:+1:9: +1:10
- StorageLive(_4); // scope 0 at $DIR/issue_76432.rs:+1:19: +1:29
StorageLive(_5); // scope 0 at $DIR/issue_76432.rs:+1:20: +1:29
_5 = [_1, _1, _1]; // scope 0 at $DIR/issue_76432.rs:+1:20: +1:29
_4 = &_5; // scope 0 at $DIR/issue_76432.rs:+1:19: +1:29
bb7: {
StorageDead(_6); // scope 4 at $DIR/issue_75439.rs:+5:35: +5:36
- Deinit(_0); // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39
- ((_0 as Some).0: [u8; 4]) = move _5; // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39
- discriminant(_0) = 1; // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39
+ _0 = Option::<[u8; 4]>::Some(move _5); // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39
StorageDead(_5); // scope 3 at $DIR/issue_75439.rs:+5:38: +5:39
StorageDead(_4); // scope 1 at $DIR/issue_75439.rs:+6:5: +6:6
goto -> bb9; // scope 1 at $DIR/issue_75439.rs:+4:5: +8:6
}
bb8: {
- Deinit(_0); // scope 1 at $DIR/issue_75439.rs:+7:9: +7:13
- discriminant(_0) = 0; // scope 1 at $DIR/issue_75439.rs:+7:9: +7:13
+ _0 = Option::<[u8; 4]>::None; // scope 1 at $DIR/issue_75439.rs:+7:9: +7:13
goto -> bb9; // scope 1 at $DIR/issue_75439.rs:+4:5: +8:6
}
let _8: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
let mut _9: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
let mut _10: bool; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+ let mut _11: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
bb0: {
StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
StorageLive(_7); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
_7 = &(*_2); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ StorageLive(_11); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ _11 = _7; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
_6 = move _7 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:+1:20: +1:21
- _5 = Len((*_6)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ _5 = Len((*_11)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ StorageDead(_11); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
++ _5 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
goto -> bb1; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
}
let _11: usize; // in scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
let mut _12: usize; // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
let mut _13: bool; // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-+ let mut _14: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
bb0: {
StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
StorageLive(_7); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
_7 = &(*_2); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ StorageLive(_14); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ _14 = _7; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
_6 = move _7 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:+1:20: +1:21
- _5 = Len((*_6)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ _5 = Len((*_14)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ StorageDead(_14); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
++ _5 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
goto -> bb1; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
}
let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:+0:52: +0:57
let mut _2: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
let mut _3: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ let mut _4: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
bb0: {
StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
_3 = &(*_1); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ _4 = _3; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
_2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+1:7: +1:8
- _0 = Len((*_2)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ _0 = Len((*_4)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
++ _0 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
goto -> bb1; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
}
let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:+0:60: +0:65
let mut _2: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
let mut _3: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ let mut _4: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
bb0: {
StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
_3 = &_1; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ _4 = _3; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
_2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+1:7: +1:8
- _0 = Len((*_2)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ _0 = Len((*_4)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
++ _0 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
goto -> bb1; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
}
--- /dev/null
+- // MIR for `array_len_raw` before NormalizeArrayLen
++ // MIR for `array_len_raw` after NormalizeArrayLen
+
+ fn array_len_raw(_1: [u8; N]) -> usize {
+ debug arr => _1; // in scope 0 at $DIR/lower_array_len.rs:+0:38: +0:41
+ let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:+0:55: +0:60
+ let _2: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:9: +1:12
+ let mut _3: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+ let _4: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+ let mut _6: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+3:5: +3:27
+ let _7: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+3:14: +3:19
+ scope 1 {
+ debug arr => _2; // in scope 1 at $DIR/lower_array_len.rs:+1:9: +1:12
+ let _5: *const [u8]; // in scope 1 at $DIR/lower_array_len.rs:+2:9: +2:12
+ scope 2 {
+ debug arr => _5; // in scope 2 at $DIR/lower_array_len.rs:+2:9: +2:12
+ scope 3 {
+ }
+ }
+ }
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:+1:9: +1:12
+ StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+ StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+ _4 = &_1; // scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+ _3 = &(*_4); // scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+ _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+ StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+1:24: +1:25
+ StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:25: +1:26
+ StorageLive(_5); // scope 1 at $DIR/lower_array_len.rs:+2:9: +2:12
+ _5 = &raw const (*_2); // scope 1 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+ StorageLive(_6); // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:27
+ StorageLive(_7); // scope 2 at $DIR/lower_array_len.rs:+3:14: +3:19
+ _7 = &(*_5); // scope 3 at $DIR/lower_array_len.rs:+3:14: +3:19
+ _6 = &(*_7); // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:27
+- _0 = Len((*_6)); // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:27
++ _0 = const N; // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:27
+ goto -> bb1; // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:27
+ }
+
+ bb1: {
+ StorageDead(_6); // scope 2 at $DIR/lower_array_len.rs:+3:26: +3:27
+ StorageDead(_5); // scope 1 at $DIR/lower_array_len.rs:+4:1: +4:2
+ StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:+4:1: +4:2
+ StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:+4:1: +4:2
+ return; // scope 0 at $DIR/lower_array_len.rs:+4:2: +4:2
+ }
+ }
+
--- /dev/null
+- // MIR for `array_len_reborrow` before NormalizeArrayLen
++ // MIR for `array_len_reborrow` after NormalizeArrayLen
+
+ fn array_len_reborrow(_1: [u8; N]) -> usize {
+ debug arr => _1; // in scope 0 at $DIR/lower_array_len.rs:+0:43: +0:50
+ let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:+0:64: +0:69
+ let _2: &mut [u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:9: +1:12
+ let mut _3: &mut [u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+ let mut _4: &mut [u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+ let mut _6: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+3:5: +3:14
+ scope 1 {
+ debug arr => _2; // in scope 1 at $DIR/lower_array_len.rs:+1:9: +1:12
+ let _5: &[u8]; // in scope 1 at $DIR/lower_array_len.rs:+2:9: +2:12
+ scope 2 {
+ debug arr => _5; // in scope 2 at $DIR/lower_array_len.rs:+2:9: +2:12
+ }
+ }
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:+1:9: +1:12
+ StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+ StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+ _4 = &mut _1; // scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+ _3 = &mut (*_4); // scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+ _2 = move _3 as &mut [u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+ StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+1:32: +1:33
+ StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:33: +1:34
+ StorageLive(_5); // scope 1 at $DIR/lower_array_len.rs:+2:9: +2:12
+ _5 = &(*_2); // scope 1 at $DIR/lower_array_len.rs:+2:15: +2:20
+ StorageLive(_6); // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:14
+ _6 = &(*_5); // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:14
+- _0 = Len((*_6)); // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:14
++ _0 = const N; // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:14
+ goto -> bb1; // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:14
+ }
+
+ bb1: {
+ StorageDead(_6); // scope 2 at $DIR/lower_array_len.rs:+3:13: +3:14
+ StorageDead(_5); // scope 1 at $DIR/lower_array_len.rs:+4:1: +4:2
+ StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:+4:1: +4:2
+ return; // scope 0 at $DIR/lower_array_len.rs:+4:2: +4:2
+ }
+ }
+
arr.len()
}
+// EMIT_MIR lower_array_len.array_len_reborrow.NormalizeArrayLen.diff
+pub fn array_len_reborrow<const N: usize>(mut arr: [u8; N]) -> usize {
+ let arr: &mut [_] = &mut arr;
+ let arr = &*arr;
+ arr.len()
+}
+
+// EMIT_MIR lower_array_len.array_len_raw.NormalizeArrayLen.diff
+pub fn array_len_raw<const N: usize>(arr: [u8; N]) -> usize {
+ let arr: &[_] = &arr;
+ let arr = std::ptr::addr_of!(*arr);
+ unsafe { &*arr }.len()
+}
+
fn main() {
let _ = array_bound(3, &[0, 1, 2, 3]);
let mut tmp = [0, 1, 2, 3, 4];
let _ = array_bound_mut(3, &mut [0, 1, 2, 3]);
let _ = array_len(&[0]);
let _ = array_len_by_value([0, 2]);
+ let _ = array_len_reborrow([0, 2]);
+ let _ = array_len_raw([0, 2]);
}
+++ /dev/null
-// MIR for `array_bound` after PreCodegen
-
-fn array_bound(_1: usize, _2: &[u8; N]) -> u8 {
- debug index => _1; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:36: +0:41
- debug slice => _2; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:50: +0:55
- let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:70: +0:72
- let mut _3: bool; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
- let mut _4: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
- let mut _5: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- let mut _6: bool; // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
-
- bb0: {
- StorageLive(_3); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
- StorageLive(_4); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
- _4 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
- _3 = Lt(_1, move _4); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
- StorageDead(_4); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
- switchInt(move _3) -> [0: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
- }
-
- bb1: {
- _5 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- _6 = Lt(_1, _5); // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _1) -> bb2; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- }
-
- bb2: {
- _0 = (*_2)[_1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- goto -> bb4; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +5:6
- }
-
- bb3: {
- _0 = const 42_u8; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:11
- goto -> bb4; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +5:6
- }
-
- bb4: {
- StorageDead(_3); // scope 0 at $DIR/lower_array_len_e2e.rs:+5:5: +5:6
- return; // scope 0 at $DIR/lower_array_len_e2e.rs:+6:2: +6:2
- }
-}
+++ /dev/null
-// MIR for `array_bound_mut` after PreCodegen
-
-fn array_bound_mut(_1: usize, _2: &mut [u8; N]) -> u8 {
- debug index => _1; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:40: +0:45
- debug slice => _2; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:54: +0:59
- let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:78: +0:80
- let mut _3: bool; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
- let mut _4: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
- let mut _5: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- let mut _6: bool; // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- let _7: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+4:15: +4:16
- let mut _8: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
- let mut _9: bool; // in scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
-
- bb0: {
- StorageLive(_3); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
- StorageLive(_4); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
- _4 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
- _3 = Lt(_1, move _4); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
- StorageDead(_4); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
- switchInt(move _3) -> [0: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
- }
-
- bb1: {
- _5 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- _6 = Lt(_1, _5); // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _1) -> bb2; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- }
-
- bb2: {
- _0 = (*_2)[_1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- goto -> bb5; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +7:6
- }
-
- bb3: {
- StorageLive(_7); // scope 0 at $DIR/lower_array_len_e2e.rs:+4:15: +4:16
- _7 = const 0_usize; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:15: +4:16
- _8 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
- _9 = Lt(const 0_usize, _8); // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
- assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, const 0_usize) -> bb4; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
- }
-
- bb4: {
- (*_2)[_7] = const 42_u8; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:22
- StorageDead(_7); // scope 0 at $DIR/lower_array_len_e2e.rs:+4:22: +4:23
- _0 = const 42_u8; // scope 0 at $DIR/lower_array_len_e2e.rs:+6:9: +6:11
- goto -> bb5; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +7:6
- }
-
- bb5: {
- StorageDead(_3); // scope 0 at $DIR/lower_array_len_e2e.rs:+7:5: +7:6
- return; // scope 0 at $DIR/lower_array_len_e2e.rs:+8:2: +8:2
- }
-}
+++ /dev/null
-// MIR for `array_len` after PreCodegen
-
-fn array_len(_1: &[u8; N]) -> usize {
- debug arr => _1; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:34: +0:37
- let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:52: +0:57
-
- bb0: {
- _0 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +1:14
- return; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:2: +2:2
- }
-}
+++ /dev/null
-// MIR for `array_len_by_value` after PreCodegen
-
-fn array_len_by_value(_1: [u8; N]) -> usize {
- debug arr => _1; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:43: +0:46
- let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:60: +0:65
-
- bb0: {
- _0 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +1:14
- return; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:2: +2:2
- }
-}
+++ /dev/null
-// compile-flags: -Z mir-opt-level=4 -Zunsound-mir-opts
-
-// EMIT_MIR lower_array_len_e2e.array_bound.PreCodegen.after.mir
-pub fn array_bound<const N: usize>(index: usize, slice: &[u8; N]) -> u8 {
- if index < slice.len() {
- slice[index]
- } else {
- 42
- }
-}
-
-// EMIT_MIR lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir
-pub fn array_bound_mut<const N: usize>(index: usize, slice: &mut [u8; N]) -> u8 {
- if index < slice.len() {
- slice[index]
- } else {
- slice[0] = 42;
-
- 42
- }
-}
-
-// EMIT_MIR lower_array_len_e2e.array_len.PreCodegen.after.mir
-pub fn array_len<const N: usize>(arr: &[u8; N]) -> usize {
- arr.len()
-}
-
-// EMIT_MIR lower_array_len_e2e.array_len_by_value.PreCodegen.after.mir
-pub fn array_len_by_value<const N: usize>(arr: [u8; N]) -> usize {
- arr.len()
-}
-
-fn main() {
- let _ = array_bound(3, &[0, 1, 2, 3]);
- let mut tmp = [0, 1, 2, 3, 4];
- let _ = array_bound_mut(3, &mut [0, 1, 2, 3]);
- let _ = array_len(&[0]);
- let _ = array_len_by_value([0, 2]);
-}
bb0: {
StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:12
- Deinit(_1); // scope 0 at $DIR/lower_intrinsics.rs:+1:15: +1:17
+ _1 = (); // scope 0 at $DIR/lower_intrinsics.rs:+1:15: +1:17
StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:16
- Deinit(_2); // scope 1 at $DIR/lower_intrinsics.rs:+2:19: +2:21
+ _2 = (); // scope 1 at $DIR/lower_intrinsics.rs:+2:19: +2:21
StorageLive(_3); // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95
StorageLive(_4); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:59
StorageLive(_5); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:45
- _3 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+16:13: +16:22
- _4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+17:13: +17:22
- _5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:+18:13: +18:21
-- Deinit(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
+- _6 = (); // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
- goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
- }
-
+ _3 = Eq(_11, const 7_i32); // scope 4 at $DIR/matches_reduce_branches.rs:+9:13: +9:21
_4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+10:13: +10:22
_5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:+11:13: +11:21
- Deinit(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
+ _6 = (); // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
- goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
- }
-
_9 = _4; // scope 4 at $DIR/matches_reduce_branches.rs:+23:12: +23:13
StorageLive(_10); // scope 4 at $DIR/matches_reduce_branches.rs:+23:15: +23:16
_10 = _5; // scope 4 at $DIR/matches_reduce_branches.rs:+23:15: +23:16
- Deinit(_0); // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17
- (_0.0: bool) = move _7; // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17
- (_0.1: bool) = move _8; // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17
- (_0.2: bool) = move _9; // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17
- (_0.3: bool) = move _10; // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17
+ _0 = (move _7, move _8, move _9, move _10); // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17
StorageDead(_10); // scope 4 at $DIR/matches_reduce_branches.rs:+23:16: +23:17
StorageDead(_9); // scope 4 at $DIR/matches_reduce_branches.rs:+23:16: +23:17
StorageDead(_8); // scope 4 at $DIR/matches_reduce_branches.rs:+23:16: +23:17
- }
-
- bb4: {
- Deinit(_0); // scope 0 at $DIR/matches_reduce_branches.rs:+2:9: +2:11
+ _0 = (); // scope 0 at $DIR/matches_reduce_branches.rs:+2:9: +2:11
- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
+ goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+1:9: +1:12
StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
- Deinit(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
+ _2 = (); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
StorageLive(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
StorageLive(_5); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
StorageLive(_1); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:9: +1:14
StorageLive(_2); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:24: +1:42
StorageLive(_3); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:32: +1:41
- Deinit(_3); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:32: +1:41
- (_3.0: usize) = const 0_usize; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:32: +1:41
- Deinit(_2); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:24: +1:42
- (_2.0: Droppy) = move _3; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:24: +1:42
+ _3 = Droppy(const 0_usize); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:32: +1:41
+ _2 = Aligned(move _3); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:24: +1:42
StorageDead(_3); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:41: +1:42
- Deinit(_1); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:17: +1:43
- (_1.0: Aligned) = move _2; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:17: +1:43
+ _1 = Packed(move _2); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:17: +1:43
StorageDead(_2); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:42: +1:43
StorageLive(_4); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:11: +2:29
StorageLive(_5); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:19: +2:28
- Deinit(_5); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:19: +2:28
- (_5.0: usize) = const 0_usize; // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:19: +2:28
- Deinit(_4); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:11: +2:29
- (_4.0: Droppy) = move _5; // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:11: +2:29
+ _5 = Droppy(const 0_usize); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:19: +2:28
+ _4 = Aligned(move _5); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:11: +2:29
StorageDead(_5); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:28: +2:29
StorageLive(_6); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8
_6 = move (_1.0: Aligned); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8
_1 = const 0_i32; // scope 0 at $DIR/remove_storage_markers.rs:+1:19: +1:20
- StorageLive(_2); // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
- StorageLive(_3); // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
- Deinit(_3); // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
- (_3.0: i32) = const 0_i32; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
- (_3.1: i32) = const 10_i32; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
+ _3 = std::ops::Range::<i32> { start: const 0_i32, end: const 10_i32 }; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
_2 = <std::ops::Range<i32> as IntoIterator>::into_iter(move _3) -> bb1; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
// mir::Constant
// + span: $DIR/remove_storage_markers.rs:10:14: 10:19
fn get_union() -> Foo {
let mut _0: Foo; // return place in scope 0 at $DIR/remove_zsts.rs:+0:19: +0:22
+ let mut _1: (); // in scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
bb0: {
- Deinit(_0); // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
+ StorageLive(_1); // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
+ _0 = Foo { x: move _1 }; // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
+ StorageDead(_1); // scope 0 at $DIR/remove_zsts.rs:+1:17: +1:18
return; // scope 0 at $DIR/remove_zsts.rs:+2:2: +2:2
}
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
-- Deinit(_1); // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
+- _1 = (); // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
+ nop; // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
- Deinit(_0); // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
-- (_0.0: ()) = move _1; // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
-+ nop; // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
+ _0 = Foo { x: move _1 }; // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
StorageDead(_1); // scope 0 at $DIR/remove_zsts.rs:+1:17: +1:18
return; // scope 0 at $DIR/remove_zsts.rs:+2:2: +2:2
}
// + literal: Const { ty: &usize, val: Unevaluated(array_casts, [], Some(promoted[0])) }
Retag(_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_18 = &(*_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Deinit(_13); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- (_13.0: &usize) = move _14; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- (_13.1: &usize) = move _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ _13 = (move _14, move _18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Retag(_13); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageDead(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageDead(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
bb3: {
StorageLive(_27); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Deinit(_27); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- discriminant(_27) = 0; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ _27 = core::panicking::AssertKind::Eq; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_28); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_29); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_29 = move _27; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_33 = &(*_21); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_32 = &(*_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Deinit(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- discriminant(_34) = 0; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ _34 = Option::<Arguments<'_>>::None; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Retag(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_28 = core::panicking::assert_failed::<usize, usize>(move _29, move _30, move _32, move _34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// mir::Constant
StorageLive(_3); // scope 1 at $DIR/retag.rs:+3:13: +3:14
StorageLive(_4); // scope 1 at $DIR/retag.rs:+3:17: +3:36
StorageLive(_5); // scope 1 at $DIR/retag.rs:+3:17: +3:24
- Deinit(_5); // scope 1 at $DIR/retag.rs:+3:17: +3:24
- (_5.0: i32) = const 0_i32; // scope 1 at $DIR/retag.rs:+3:17: +3:24
+ _5 = Test(const 0_i32); // scope 1 at $DIR/retag.rs:+3:17: +3:24
_4 = &_5; // scope 1 at $DIR/retag.rs:+3:17: +3:36
StorageLive(_6); // scope 1 at $DIR/retag.rs:+3:29: +3:35
StorageLive(_7); // scope 1 at $DIR/retag.rs:+3:29: +3:35
StorageDead(_2); // scope 1 at $DIR/retag.rs:+8:5: +8:6
StorageLive(_13); // scope 1 at $DIR/retag.rs:+11:9: +11:10
StorageLive(_14); // scope 1 at $DIR/retag.rs:+11:31: +14:6
- Deinit(_14); // scope 1 at $DIR/retag.rs:+11:31: +14:6
+ _14 = [closure@main::{closure#0}]; // scope 1 at $DIR/retag.rs:+11:31: +14:6
+ // closure
+ // + def_id: DefId(0:14 ~ retag[4622]::main::{closure#0})
+ // + substs: [
+ // i8,
+ // for<'a> extern "rust-call" fn((&'a i32,)) -> &'a i32,
+ // (),
+ // ]
Retag(_14); // scope 1 at $DIR/retag.rs:+11:31: +14:6
_13 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (Pointer(ClosureFnPointer(Normal))); // scope 1 at $DIR/retag.rs:+11:31: +14:6
StorageDead(_14); // scope 1 at $DIR/retag.rs:+11:47: +11:48
StorageLive(_19); // scope 7 at $DIR/retag.rs:+18:5: +18:24
StorageLive(_20); // scope 7 at $DIR/retag.rs:+18:5: +18:24
StorageLive(_21); // scope 7 at $DIR/retag.rs:+18:5: +18:12
- Deinit(_21); // scope 7 at $DIR/retag.rs:+18:5: +18:12
- (_21.0: i32) = const 0_i32; // scope 7 at $DIR/retag.rs:+18:5: +18:12
+ _21 = Test(const 0_i32); // scope 7 at $DIR/retag.rs:+18:5: +18:12
_20 = &_21; // scope 7 at $DIR/retag.rs:+18:5: +18:24
StorageLive(_22); // scope 7 at $DIR/retag.rs:+18:21: +18:23
StorageLive(_23); // scope 7 at $DIR/retag.rs:+18:21: +18:23
StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9
_4 = _1; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9
_10 = discriminant(_4); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-- switchInt(move _10) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-+ switchInt(move _10) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+ switchInt(move _10) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
}
bb1: {
-- StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
-- _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-- switchInt(move _5) -> [0: bb2, 1: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-- }
--
-- bb2: {
+ StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
+ _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+ switchInt(move _5) -> [0: bb2, 1: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+ }
+
+ bb2: {
StorageLive(_9); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
_9 = ((_3 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
_2 = _9; // scope 4 at $DIR/separate_const_switch.rs:+1:8: +1:10
StorageDead(_9); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
- Deinit(_0); // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11
- ((_0 as Ok).0: i32) = move _2; // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11
- discriminant(_0) = 0; // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11
+ _0 = Result::<i32, i32>::Ok(move _2); // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11
StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:+2:1: +2:2
return; // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2
}
-- bb3: {
-+ bb2: {
+ bb3: {
unreachable; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
}
-- bb4: {
-+ bb3: {
+ bb4: {
StorageLive(_6); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
_6 = ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
StorageLive(_8); // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10
_18 = move _16; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
_17 = move _18; // scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
StorageDead(_18); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- Deinit(_0); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- ((_0 as Err).0: i32) = move _17; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- discriminant(_0) = 1; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+ _0 = Result::<i32, i32>::Err(move _17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
StorageDead(_17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
StorageDead(_16); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
StorageDead(_8); // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10
return; // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2
}
-- bb5: {
-+ bb4: {
+ bb5: {
StorageLive(_13); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
_13 = move ((_4 as Err).0: i32); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
StorageLive(_14); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
StorageLive(_15); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
_15 = move _13; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- Deinit(_14); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- ((_14 as Err).0: i32) = move _15; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- discriminant(_14) = 1; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+ _14 = Result::<Infallible, i32>::Err(move _15); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
StorageDead(_15); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- Deinit(_3); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>) = move _14; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- discriminant(_3) = 1; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+ _3 = ControlFlow::<Result<Infallible, i32>, i32>::Break(move _14); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
StorageDead(_14); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
StorageDead(_13); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-- goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-+ StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
-+ _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-+ switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+ goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
}
-- bb6: {
-+ bb5: {
+ bb6: {
unreachable; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
}
-- bb7: {
-+ bb6: {
+ bb7: {
StorageLive(_11); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
_11 = move ((_4 as Ok).0: i32); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
StorageLive(_12); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
_12 = move _11; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
- Deinit(_3); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
- ((_3 as Continue).0: i32) = move _12; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
- discriminant(_3) = 0; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+ _3 = ControlFlow::<Result<Infallible, i32>, i32>::Continue(move _12); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
StorageDead(_12); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
StorageDead(_11); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-- goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-+ StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
-+ _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-+ switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+ goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
}
}
_6 = ((_1 as Err).0: usize); // scope 0 at $DIR/separate_const_switch.rs:+8:17: +8:18
StorageLive(_7); // scope 2 at $DIR/separate_const_switch.rs:+8:42: +8:43
_7 = _6; // scope 2 at $DIR/separate_const_switch.rs:+8:42: +8:43
- Deinit(_2); // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44
- ((_2 as Break).0: usize) = move _7; // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44
- discriminant(_2) = 1; // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44
+ _2 = ControlFlow::<usize, i32>::Break(move _7); // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44
StorageDead(_7); // scope 2 at $DIR/separate_const_switch.rs:+8:43: +8:44
StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
-- goto -> bb4; // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
-+ _8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
-+ switchInt(move _8) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
+ goto -> bb4; // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
}
bb2: {
_4 = ((_1 as Ok).0: i32); // scope 0 at $DIR/separate_const_switch.rs:+7:16: +7:17
StorageLive(_5); // scope 1 at $DIR/separate_const_switch.rs:+7:44: +7:45
_5 = _4; // scope 1 at $DIR/separate_const_switch.rs:+7:44: +7:45
- Deinit(_2); // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46
- ((_2 as Continue).0: i32) = move _5; // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46
- discriminant(_2) = 0; // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46
+ _2 = ControlFlow::<usize, i32>::Continue(move _5); // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46
StorageDead(_5); // scope 1 at $DIR/separate_const_switch.rs:+7:45: +7:46
StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+7:45: +7:46
-- goto -> bb4; // scope 0 at $DIR/separate_const_switch.rs:+7:45: +7:46
-- }
--
-- bb4: {
+ goto -> bb4; // scope 0 at $DIR/separate_const_switch.rs:+7:45: +7:46
+ }
+
+ bb4: {
_8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
-- switchInt(move _8) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
-+ switchInt(move _8) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
+ switchInt(move _8) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
}
-- bb5: {
-+ bb4: {
+ bb5: {
StorageLive(_11); // scope 0 at $DIR/separate_const_switch.rs:+12:28: +12:29
_11 = ((_2 as Break).0: usize); // scope 0 at $DIR/separate_const_switch.rs:+12:28: +12:29
- Deinit(_0); // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38
- discriminant(_0) = 0; // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38
+ _0 = Option::<i32>::None; // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38
StorageDead(_11); // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
-- goto -> bb8; // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
-+ goto -> bb7; // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
+ goto -> bb8; // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
}
-- bb6: {
-+ bb5: {
+ bb6: {
unreachable; // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
}
-- bb7: {
-+ bb6: {
+ bb7: {
StorageLive(_9); // scope 0 at $DIR/separate_const_switch.rs:+11:31: +11:32
_9 = ((_2 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:+11:31: +11:32
StorageLive(_10); // scope 3 at $DIR/separate_const_switch.rs:+11:42: +11:43
_10 = _9; // scope 3 at $DIR/separate_const_switch.rs:+11:42: +11:43
- Deinit(_0); // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44
- ((_0 as Some).0: i32) = move _10; // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44
- discriminant(_0) = 1; // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44
+ _0 = Option::<i32>::Some(move _10); // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44
StorageDead(_10); // scope 3 at $DIR/separate_const_switch.rs:+11:43: +11:44
StorageDead(_9); // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
-- goto -> bb8; // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
-+ goto -> bb7; // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
+ goto -> bb8; // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
}
-- bb8: {
-+ bb7: {
+ bb8: {
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+14:1: +14:2
return; // scope 0 at $DIR/separate_const_switch.rs:+14:2: +14:2
}
debug slf => _1; // in scope 1 at $DIR/simple_option_map_e2e.rs:2:17: 2:20
debug f => _2; // in scope 1 at $DIR/simple_option_map_e2e.rs:2:33: 2:34
let mut _3: isize; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:9: 7:16
- let mut _4: i32; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
+ let _4: i32; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:14: 7:15
let mut _5: i32; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
scope 2 {
- debug x => _5; // in scope 2 at $DIR/simple_option_map_e2e.rs:7:14: 7:15
+ debug x => _4; // in scope 2 at $DIR/simple_option_map_e2e.rs:7:14: 7:15
scope 3 (inlined ezmap::{closure#0}) { // at $DIR/simple_option_map_e2e.rs:7:25: 7:29
- debug n => _5; // in scope 3 at $DIR/simple_option_map_e2e.rs:+1:13: +1:14
+ debug n => _4; // in scope 3 at $DIR/simple_option_map_e2e.rs:+1:13: +1:14
}
}
}
}
bb1: {
- Deinit(_0); // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21
- discriminant(_0) = 0; // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21
+ _0 = Option::<i32>::None; // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21
goto -> bb4; // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21
}
}
bb3: {
- _5 = move ((_1 as Some).0: i32); // scope 1 at $DIR/simple_option_map_e2e.rs:7:14: 7:15
- StorageLive(_4); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
- _4 = Add(_5, const 1_i32); // scope 3 at $DIR/simple_option_map_e2e.rs:+1:16: +1:21
- Deinit(_0); // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30
- ((_0 as Some).0: i32) = move _4; // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30
- discriminant(_0) = 1; // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30
- StorageDead(_4); // scope 2 at $DIR/simple_option_map_e2e.rs:7:29: 7:30
+ _4 = move ((_1 as Some).0: i32); // scope 1 at $DIR/simple_option_map_e2e.rs:7:14: 7:15
+ StorageLive(_5); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
+ _5 = Add(_4, const 1_i32); // scope 3 at $DIR/simple_option_map_e2e.rs:+1:16: +1:21
+ _0 = Option::<i32>::Some(move _5); // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30
+ StorageDead(_5); // scope 2 at $DIR/simple_option_map_e2e.rs:7:29: 7:30
goto -> bb4; // scope 1 at $DIR/simple_option_map_e2e.rs:10:1: 10:2
}
bb0: {
- StorageLive(_1); // scope 0 at $DIR/simplify_locals.rs:+2:13: +2:17
-- Deinit(_1); // scope 0 at $DIR/simplify_locals.rs:+2:13: +2:17
-- discriminant(_1) = 0; // scope 0 at $DIR/simplify_locals.rs:+2:13: +2:17
+- _1 = E::A; // scope 0 at $DIR/simplify_locals.rs:+2:13: +2:17
- StorageDead(_1); // scope 0 at $DIR/simplify_locals.rs:+2:17: +2:18
_0 = const (); // scope 0 at $DIR/simplify_locals.rs:+0:9: +3:2
return; // scope 0 at $DIR/simplify_locals.rs:+3:2: +3:2
bb0: {
- StorageLive(_1); // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:26
-- Deinit(_1); // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:26
-- discriminant(_1) = 1; // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:26
+- _1 = E::B; // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:26
- StorageLive(_2); // scope 0 at $DIR/simplify_locals.rs:+2:5: +2:17
- StorageLive(_3); // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15
-- Deinit(_3); // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15
-- discriminant(_3) = 0; // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15
-- Deinit(_2); // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16
-- (_2.0: i32) = const 10_i32; // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16
-- (_2.1: E) = move _3; // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16
+- _3 = E::A; // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15
+- _2 = (const 10_i32, move _3); // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16
- StorageDead(_3); // scope 0 at $DIR/simplify_locals.rs:+2:15: +2:16
- (_2.1: E) = move _1; // scope 0 at $DIR/simplify_locals.rs:+2:5: +2:26
- StorageDead(_1); // scope 0 at $DIR/simplify_locals.rs:+2:25: +2:26
bb0: {
StorageLive(_1); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69
StorageLive(_2); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49
- Deinit(_2); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49
- discriminant(_2) = 0; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49
+ _2 = Option::<u8>::None; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49
StorageLive(_3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68
- Deinit(_3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68
- discriminant(_3) = 0; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68
- Deinit(_1); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69
- (_1.0: std::option::Option<u8>) = move _2; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69
- (_1.1: std::option::Option<T>) = move _3; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69
+ _3 = Option::<T>::None; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68
+ _1 = (move _2, move _3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69
StorageDead(_3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:68: +1:69
StorageDead(_2); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:68: +1:69
_5 = discriminant((_1.0: std::option::Option<u8>)); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
bb0: {
- StorageLive(_1); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28
- StorageLive(_2); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:21: +1:23
-- Deinit(_2); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:21: +1:23
+- _2 = (); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:21: +1:23
- StorageLive(_3); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:25: +1:27
-- Deinit(_3); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:25: +1:27
-- Deinit(_1); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28
-- (_1.0: ()) = move _2; // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28
-- (_1.1: ()) = move _3; // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28
+- _3 = (); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:25: +1:27
+- _1 = (move _2, move _3); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28
- StorageDead(_3); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:27: +1:28
- StorageDead(_2); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:27: +1:28
- StorageDead(_1); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:28: +1:29
- StorageLive(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22
- StorageLive(_5); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
- StorageLive(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16
-- Deinit(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16
+- _6 = (); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16
- StorageLive(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20
-- Deinit(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20
-- Deinit(_5); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
-- (_5.0: ()) = move _6; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
-- (_5.1: ()) = move _7; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
+- _7 = (); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20
+- _5 = (move _6, move _7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
- StorageDead(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21
- StorageDead(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21
- _4 = use_zst(move _5) -> bb1; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22
+ StorageLive(_1); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22
+ StorageLive(_2); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
+ StorageLive(_3); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16
-+ Deinit(_3); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16
++ _3 = (); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16
+ StorageLive(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20
-+ Deinit(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20
-+ Deinit(_2); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
-+ (_2.0: ()) = move _3; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
-+ (_2.1: ()) = move _4; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
++ _4 = (); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20
++ _2 = (move _3, move _4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
+ StorageDead(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21
+ StorageDead(_3); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21
+ _1 = use_zst(move _2) -> bb1; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22
- StorageLive(_9); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34
- StorageLive(_10); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30
- StorageLive(_11); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
-- Deinit(_11); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
-- (_11.0: u8) = const 40_u8; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
+- _11 = Temp { x: const 40_u8 }; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
- _10 = (_11.0: u8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30
- _9 = Add(move _10, const 2_u8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34
- StorageDead(_10); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:33: +4:34
+ StorageLive(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34
+ StorageLive(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30
+ StorageLive(_8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
-+ Deinit(_8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
-+ (_8.0: u8) = const 40_u8; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
++ _8 = Temp { x: const 40_u8 }; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
+ _7 = (_8.0: u8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30
+ _6 = Add(move _7, const 2_u8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34
+ StorageDead(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:33: +4:34
_3 = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:14: +3:15
StorageLive(_4); // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:25: +3:26
_4 = move _3; // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:25: +3:26
- Deinit(_0); // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:20: +3:27
- ((_0 as Some).0: std::boxed::Box<()>) = move _4; // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:20: +3:27
- discriminant(_0) = 1; // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:20: +3:27
+ _0 = Option::<Box<()>>::Some(move _4); // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:20: +3:27
StorageDead(_4); // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:26: +3:27
StorageDead(_3); // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:26: +3:27
goto -> bb4; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:26: +3:27
}
bb3: {
- Deinit(_0); // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+2:17: +2:21
- discriminant(_0) = 0; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+2:17: +2:21
+ _0 = Option::<Box<()>>::None; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+2:17: +2:21
goto -> bb4; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+2:17: +2:21
}
}
bb0: {
- StorageLive(_2); // scope 0 at $DIR/simplify_match.rs:+1:17: +1:18
_2 = const false; // scope 0 at $DIR/simplify_match.rs:+1:21: +1:26
- switchInt(_2) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31
+ switchInt(const false) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31
}
bb0: {
- StorageLive(_3); // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+- StorageLive(_3); // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
_25 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
_3 = &((*_25).0: usize); // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
- StorageLive(_4); // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+- StorageLive(_4); // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
_26 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
_4 = &((*_26).1: usize); // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
- StorageLive(_5); // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+- StorageLive(_5); // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
_27 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
_5 = &((*_27).2: usize); // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
- StorageLive(_6); // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+- StorageLive(_6); // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
_28 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
_6 = &((*_28).3: usize); // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
StorageLive(_7); // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
}
bb0: {
- StorageLive(_3); // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
_25 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
_3 = &((*_25).0: usize); // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
- StorageLive(_4); // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
_26 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
_4 = &((*_26).1: usize); // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
- StorageLive(_5); // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
_27 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
_5 = &((*_27).2: usize); // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
- StorageLive(_6); // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
_28 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
_6 = &((*_28).3: usize); // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
- StorageLive(_7); // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
}
bb0: {
- StorageLive(_3); // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
+- StorageLive(_3); // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
_21 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
_3 = ((*_21).0: usize); // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
- StorageLive(_4); // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
+- StorageLive(_4); // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
_22 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
_4 = ((*_22).1: usize); // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
- StorageLive(_5); // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
+- StorageLive(_5); // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
_23 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
_5 = ((*_23).2: usize); // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
- StorageLive(_6); // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
+- StorageLive(_6); // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
_24 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
_6 = ((*_24).3: usize); // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
StorageLive(_7); // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
}
bb0: {
- StorageLive(_3); // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
_13 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
_3 = ((*_13).0: usize); // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
- StorageLive(_4); // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
_14 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
_4 = ((*_14).1: usize); // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
- StorageLive(_5); // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
_15 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
_5 = ((*_15).2: usize); // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
- StorageLive(_6); // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
_16 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
_6 = ((*_16).3: usize); // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
- StorageLive(_7); // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
--- /dev/null
+- // MIR for `copies` before ScalarReplacementOfAggregates
++ // MIR for `copies` after ScalarReplacementOfAggregates
+
+ fn copies(_1: Foo) -> () {
+ debug x => _1; // in scope 0 at $DIR/sroa.rs:+0:11: +0:12
+ let mut _0: (); // return place in scope 0 at $DIR/sroa.rs:+0:19: +0:19
+ let _2: Foo; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ let _11: u8; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ let _12: (); // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ let _13: &str; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ let _14: std::option::Option<isize>; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
+ scope 1 {
+- debug y => _2; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10
++ debug y => Foo{ .0 => _11, .1 => _12, .2 => _13, .3 => _14, }; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10
+ let _3: u8; // in scope 1 at $DIR/sroa.rs:+2:9: +2:10
+ scope 2 {
+ debug t => _3; // in scope 2 at $DIR/sroa.rs:+2:9: +2:10
+ let _4: &str; // in scope 2 at $DIR/sroa.rs:+3:9: +3:10
+ scope 3 {
+ debug u => _4; // in scope 3 at $DIR/sroa.rs:+3:9: +3:10
+ let _5: Foo; // in scope 3 at $DIR/sroa.rs:+4:9: +4:10
++ let _7: u8; // in scope 3 at $DIR/sroa.rs:+4:9: +4:10
++ let _8: (); // in scope 3 at $DIR/sroa.rs:+4:9: +4:10
++ let _9: &str; // in scope 3 at $DIR/sroa.rs:+4:9: +4:10
++ let _10: std::option::Option<isize>; // in scope 3 at $DIR/sroa.rs:+4:9: +4:10
+ scope 4 {
+- debug z => _5; // in scope 4 at $DIR/sroa.rs:+4:9: +4:10
++ debug z => Foo{ .0 => _7, .1 => _8, .2 => _9, .3 => _10, }; // in scope 4 at $DIR/sroa.rs:+4:9: +4:10
+ let _6: (); // in scope 4 at $DIR/sroa.rs:+5:9: +5:10
+ scope 5 {
+ debug a => _6; // in scope 5 at $DIR/sroa.rs:+5:9: +5:10
+ }
+ }
+ }
+ }
+ }
+
+ bb0: {
+- StorageLive(_2); // scope 0 at $DIR/sroa.rs:+1:9: +1:10
+- _2 = _1; // scope 0 at $DIR/sroa.rs:+1:13: +1:14
++ StorageLive(_11); // scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ StorageLive(_12); // scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ StorageLive(_13); // scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ StorageLive(_14); // scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ nop; // scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ _11 = (_1.0: u8); // scope 0 at $DIR/sroa.rs:+1:13: +1:14
++ _12 = (_1.1: ()); // scope 0 at $DIR/sroa.rs:+1:13: +1:14
++ _13 = (_1.2: &str); // scope 0 at $DIR/sroa.rs:+1:13: +1:14
++ _14 = (_1.3: std::option::Option<isize>); // scope 0 at $DIR/sroa.rs:+1:13: +1:14
++ nop; // scope 0 at $DIR/sroa.rs:+1:13: +1:14
+ StorageLive(_3); // scope 1 at $DIR/sroa.rs:+2:9: +2:10
+- _3 = (_2.0: u8); // scope 1 at $DIR/sroa.rs:+2:13: +2:16
++ _3 = _11; // scope 1 at $DIR/sroa.rs:+2:13: +2:16
+ StorageLive(_4); // scope 2 at $DIR/sroa.rs:+3:9: +3:10
+- _4 = (_2.2: &str); // scope 2 at $DIR/sroa.rs:+3:13: +3:16
+- StorageLive(_5); // scope 3 at $DIR/sroa.rs:+4:9: +4:10
+- _5 = _2; // scope 3 at $DIR/sroa.rs:+4:13: +4:14
++ _4 = _13; // scope 2 at $DIR/sroa.rs:+3:13: +3:16
++ StorageLive(_7); // scope 3 at $DIR/sroa.rs:+4:9: +4:10
++ StorageLive(_8); // scope 3 at $DIR/sroa.rs:+4:9: +4:10
++ StorageLive(_9); // scope 3 at $DIR/sroa.rs:+4:9: +4:10
++ StorageLive(_10); // scope 3 at $DIR/sroa.rs:+4:9: +4:10
++ nop; // scope 3 at $DIR/sroa.rs:+4:9: +4:10
++ _7 = _11; // scope 3 at $DIR/sroa.rs:+4:13: +4:14
++ _8 = _12; // scope 3 at $DIR/sroa.rs:+4:13: +4:14
++ _9 = _13; // scope 3 at $DIR/sroa.rs:+4:13: +4:14
++ _10 = _14; // scope 3 at $DIR/sroa.rs:+4:13: +4:14
++ nop; // scope 3 at $DIR/sroa.rs:+4:13: +4:14
+ StorageLive(_6); // scope 4 at $DIR/sroa.rs:+5:9: +5:10
+- _6 = (_5.1: ()); // scope 4 at $DIR/sroa.rs:+5:13: +5:16
++ _6 = _8; // scope 4 at $DIR/sroa.rs:+5:13: +5:16
+ _0 = const (); // scope 0 at $DIR/sroa.rs:+0:19: +6:2
+ StorageDead(_6); // scope 4 at $DIR/sroa.rs:+6:1: +6:2
+- StorageDead(_5); // scope 3 at $DIR/sroa.rs:+6:1: +6:2
++ StorageDead(_7); // scope 3 at $DIR/sroa.rs:+6:1: +6:2
++ StorageDead(_8); // scope 3 at $DIR/sroa.rs:+6:1: +6:2
++ StorageDead(_9); // scope 3 at $DIR/sroa.rs:+6:1: +6:2
++ StorageDead(_10); // scope 3 at $DIR/sroa.rs:+6:1: +6:2
++ nop; // scope 3 at $DIR/sroa.rs:+6:1: +6:2
+ StorageDead(_4); // scope 2 at $DIR/sroa.rs:+6:1: +6:2
+ StorageDead(_3); // scope 1 at $DIR/sroa.rs:+6:1: +6:2
+- StorageDead(_2); // scope 0 at $DIR/sroa.rs:+6:1: +6:2
++ StorageDead(_11); // scope 0 at $DIR/sroa.rs:+6:1: +6:2
++ StorageDead(_12); // scope 0 at $DIR/sroa.rs:+6:1: +6:2
++ StorageDead(_13); // scope 0 at $DIR/sroa.rs:+6:1: +6:2
++ StorageDead(_14); // scope 0 at $DIR/sroa.rs:+6:1: +6:2
++ nop; // scope 0 at $DIR/sroa.rs:+6:1: +6:2
+ return; // scope 0 at $DIR/sroa.rs:+6:2: +6:2
+ }
+ }
+
StorageLive(_1); // scope 0 at $DIR/sroa.rs:+1:5: +1:32
StorageLive(_2); // scope 0 at $DIR/sroa.rs:+1:5: +1:30
StorageLive(_3); // scope 0 at $DIR/sroa.rs:+1:7: +1:13
- Deinit(_3); // scope 0 at $DIR/sroa.rs:+1:7: +1:13
- (_3.0: usize) = const 0_usize; // scope 0 at $DIR/sroa.rs:+1:7: +1:13
+ _3 = Tag(const 0_usize); // scope 0 at $DIR/sroa.rs:+1:7: +1:13
StorageLive(_4); // scope 0 at $DIR/sroa.rs:+1:15: +1:21
- Deinit(_4); // scope 0 at $DIR/sroa.rs:+1:15: +1:21
- (_4.0: usize) = const 1_usize; // scope 0 at $DIR/sroa.rs:+1:15: +1:21
+ _4 = Tag(const 1_usize); // scope 0 at $DIR/sroa.rs:+1:15: +1:21
StorageLive(_5); // scope 0 at $DIR/sroa.rs:+1:23: +1:29
- Deinit(_5); // scope 0 at $DIR/sroa.rs:+1:23: +1:29
- (_5.0: usize) = const 2_usize; // scope 0 at $DIR/sroa.rs:+1:23: +1:29
- Deinit(_2); // scope 0 at $DIR/sroa.rs:+1:5: +1:30
- (_2.0: Tag) = move _3; // scope 0 at $DIR/sroa.rs:+1:5: +1:30
- (_2.1: Tag) = move _4; // scope 0 at $DIR/sroa.rs:+1:5: +1:30
- (_2.2: Tag) = move _5; // scope 0 at $DIR/sroa.rs:+1:5: +1:30
+ _5 = Tag(const 2_usize); // scope 0 at $DIR/sroa.rs:+1:23: +1:29
+ _2 = S(move _3, move _4, move _5); // scope 0 at $DIR/sroa.rs:+1:5: +1:30
StorageDead(_5); // scope 0 at $DIR/sroa.rs:+1:29: +1:30
StorageDead(_4); // scope 0 at $DIR/sroa.rs:+1:29: +1:30
StorageDead(_3); // scope 0 at $DIR/sroa.rs:+1:29: +1:30
StorageLive(_2); // scope 1 at $DIR/sroa.rs:+1:22: +1:29
StorageLive(_3); // scope 1 at $DIR/sroa.rs:+1:27: +1:28
_3 = _1; // scope 1 at $DIR/sroa.rs:+1:27: +1:28
- Deinit(_2); // scope 1 at $DIR/sroa.rs:+1:22: +1:29
- ((_2 as Some).0: usize) = move _3; // scope 1 at $DIR/sroa.rs:+1:22: +1:29
- discriminant(_2) = 1; // scope 1 at $DIR/sroa.rs:+1:22: +1:29
+ _2 = Option::<usize>::Some(move _3); // scope 1 at $DIR/sroa.rs:+1:22: +1:29
StorageDead(_3); // scope 1 at $DIR/sroa.rs:+1:28: +1:29
_4 = discriminant(_2); // scope 1 at $DIR/sroa.rs:+1:12: +1:19
switchInt(move _4) -> [1: bb1, otherwise: bb2]; // scope 1 at $DIR/sroa.rs:+1:12: +1:19
StorageLive(_5); // scope 0 at $DIR/sroa.rs:+2:34: +2:37
_5 = g() -> bb1; // scope 0 at $DIR/sroa.rs:+2:34: +2:37
// mir::Constant
- // + span: $DIR/sroa.rs:78:34: 78:35
+ // + span: $DIR/sroa.rs:73:34: 73:35
// + literal: Const { ty: fn() -> u32 {g}, val: Value(<ZST>) }
}
bb1: {
- Deinit(_4); // scope 0 at $DIR/sroa.rs:+2:8: +2:39
- (_4.0: u32) = const 1_u32; // scope 0 at $DIR/sroa.rs:+2:8: +2:39
- (_4.1: u32) = const 2_u32; // scope 0 at $DIR/sroa.rs:+2:8: +2:39
- (_4.2: u32) = move _5; // scope 0 at $DIR/sroa.rs:+2:8: +2:39
+ _4 = Escaping { a: const 1_u32, b: const 2_u32, c: move _5 }; // scope 0 at $DIR/sroa.rs:+2:8: +2:39
StorageDead(_5); // scope 0 at $DIR/sroa.rs:+2:38: +2:39
_3 = &(_4.0: u32); // scope 0 at $DIR/sroa.rs:+2:7: +2:41
_2 = &raw const (*_3); // scope 0 at $DIR/sroa.rs:+2:7: +2:41
_1 = f(move _2) -> bb2; // scope 0 at $DIR/sroa.rs:+2:5: +2:42
// mir::Constant
- // + span: $DIR/sroa.rs:78:5: 78:6
+ // + span: $DIR/sroa.rs:73:5: 73:6
// + literal: Const { ty: fn(*const u32) {f}, val: Value(<ZST>) }
}
+ StorageLive(_9); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
+ StorageLive(_10); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
+ StorageLive(_11); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
++ nop; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
StorageLive(_6); // scope 0 at $DIR/sroa.rs:+1:45: +1:47
- Deinit(_6); // scope 0 at $DIR/sroa.rs:+1:45: +1:47
+ _6 = (); // scope 0 at $DIR/sroa.rs:+1:45: +1:47
StorageLive(_7); // scope 0 at $DIR/sroa.rs:+1:60: +1:68
- Deinit(_7); // scope 0 at $DIR/sroa.rs:+1:60: +1:68
- ((_7 as Some).0: isize) = const -4_isize; // scope 0 at $DIR/sroa.rs:+1:60: +1:68
- discriminant(_7) = 1; // scope 0 at $DIR/sroa.rs:+1:60: +1:68
-- Deinit(_5); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-- (_5.0: u8) = const 5_u8; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-- (_5.1: ()) = move _6; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-- (_5.2: &str) = const "a"; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ Deinit(_8); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ Deinit(_9); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ Deinit(_10); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ Deinit(_11); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
+ _7 = Option::<isize>::Some(const -4_isize); // scope 0 at $DIR/sroa.rs:+1:60: +1:68
+- _5 = Foo { a: const 5_u8, b: move _6, c: const "a", d: move _7 }; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
+ _8 = const 5_u8; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
+ _9 = move _6; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
+ _10 = const "a"; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
// mir::Constant
- // + span: $DIR/sroa.rs:57:52: 57:55
+ // + span: $DIR/sroa.rs:53:52: 53:55
// + literal: Const { ty: &str, val: Value(Slice(..)) }
-- (_5.3: std::option::Option<isize>) = move _7; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
+ _11 = move _7; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
++ nop; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
StorageDead(_7); // scope 0 at $DIR/sroa.rs:+1:69: +1:70
StorageDead(_6); // scope 0 at $DIR/sroa.rs:+1:69: +1:70
StorageLive(_1); // scope 0 at $DIR/sroa.rs:+1:15: +1:16
+ StorageDead(_9); // scope 0 at $DIR/sroa.rs:+1:70: +1:71
+ StorageDead(_10); // scope 0 at $DIR/sroa.rs:+1:70: +1:71
+ StorageDead(_11); // scope 0 at $DIR/sroa.rs:+1:70: +1:71
++ nop; // scope 0 at $DIR/sroa.rs:+1:70: +1:71
_0 = const (); // scope 0 at $DIR/sroa.rs:+0:15: +6:2
StorageDead(_4); // scope 0 at $DIR/sroa.rs:+6:1: +6:2
StorageDead(_3); // scope 0 at $DIR/sroa.rs:+6:1: +6:2
--- /dev/null
+- // MIR for `ref_copies` before ScalarReplacementOfAggregates
++ // MIR for `ref_copies` after ScalarReplacementOfAggregates
+
+ fn ref_copies(_1: &Foo) -> () {
+ debug x => _1; // in scope 0 at $DIR/sroa.rs:+0:15: +0:16
+ let mut _0: (); // return place in scope 0 at $DIR/sroa.rs:+0:24: +0:24
+ let _2: Foo; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ let _5: u8; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ let _6: (); // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ let _7: &str; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ let _8: std::option::Option<isize>; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
+ scope 1 {
+- debug y => _2; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10
++ debug y => Foo{ .0 => _5, .1 => _6, .2 => _7, .3 => _8, }; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10
+ let _3: u8; // in scope 1 at $DIR/sroa.rs:+2:9: +2:10
+ scope 2 {
+ debug t => _3; // in scope 2 at $DIR/sroa.rs:+2:9: +2:10
+ let _4: &str; // in scope 2 at $DIR/sroa.rs:+3:9: +3:10
+ scope 3 {
+ debug u => _4; // in scope 3 at $DIR/sroa.rs:+3:9: +3:10
+ }
+ }
+ }
+
+ bb0: {
+- StorageLive(_2); // scope 0 at $DIR/sroa.rs:+1:9: +1:10
+- _2 = (*_1); // scope 0 at $DIR/sroa.rs:+1:13: +1:15
++ StorageLive(_5); // scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ StorageLive(_6); // scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ StorageLive(_7); // scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ StorageLive(_8); // scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ nop; // scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ _5 = ((*_1).0: u8); // scope 0 at $DIR/sroa.rs:+1:13: +1:15
++ _6 = ((*_1).1: ()); // scope 0 at $DIR/sroa.rs:+1:13: +1:15
++ _7 = ((*_1).2: &str); // scope 0 at $DIR/sroa.rs:+1:13: +1:15
++ _8 = ((*_1).3: std::option::Option<isize>); // scope 0 at $DIR/sroa.rs:+1:13: +1:15
++ nop; // scope 0 at $DIR/sroa.rs:+1:13: +1:15
+ StorageLive(_3); // scope 1 at $DIR/sroa.rs:+2:9: +2:10
+- _3 = (_2.0: u8); // scope 1 at $DIR/sroa.rs:+2:13: +2:16
++ _3 = _5; // scope 1 at $DIR/sroa.rs:+2:13: +2:16
+ StorageLive(_4); // scope 2 at $DIR/sroa.rs:+3:9: +3:10
+- _4 = (_2.2: &str); // scope 2 at $DIR/sroa.rs:+3:13: +3:16
++ _4 = _7; // scope 2 at $DIR/sroa.rs:+3:13: +3:16
+ _0 = const (); // scope 0 at $DIR/sroa.rs:+0:24: +4:2
+ StorageDead(_4); // scope 2 at $DIR/sroa.rs:+4:1: +4:2
+ StorageDead(_3); // scope 1 at $DIR/sroa.rs:+4:1: +4:2
+- StorageDead(_2); // scope 0 at $DIR/sroa.rs:+4:1: +4:2
++ StorageDead(_5); // scope 0 at $DIR/sroa.rs:+4:1: +4:2
++ StorageDead(_6); // scope 0 at $DIR/sroa.rs:+4:1: +4:2
++ StorageDead(_7); // scope 0 at $DIR/sroa.rs:+4:1: +4:2
++ StorageDead(_8); // scope 0 at $DIR/sroa.rs:+4:1: +4:2
++ nop; // scope 0 at $DIR/sroa.rs:+4:1: +4:2
+ return; // scope 0 at $DIR/sroa.rs:+4:2: +4:2
+ }
+ }
+
fn drop(&mut self) {}
}
-// EMIT_MIR sroa.dropping.ScalarReplacementOfAggregates.diff
pub fn dropping() {
S(Tag(0), Tag(1), Tag(2)).1;
}
-// EMIT_MIR sroa.enums.ScalarReplacementOfAggregates.diff
pub fn enums(a: usize) -> usize {
if let Some(a) = Some(a) { a } else { 0 }
}
-// EMIT_MIR sroa.structs.ScalarReplacementOfAggregates.diff
pub fn structs(a: f32) -> f32 {
struct U {
_foo: usize,
U { _foo: 0, a }.a
}
-// EMIT_MIR sroa.unions.ScalarReplacementOfAggregates.diff
pub fn unions(a: f32) -> u32 {
union Repr {
f: f32,
unsafe { Repr { f: a }.u }
}
+#[derive(Copy, Clone)]
struct Foo {
a: u8,
b: (),
3
}
-// EMIT_MIR sroa.flat.ScalarReplacementOfAggregates.diff
pub fn flat() {
let Foo { a, b, c, d } = Foo { a: 5, b: (), c: "a", d: Some(-4) };
let _ = a;
println!("{}", unsafe { *a.add(2) });
}
-// EMIT_MIR sroa.escaping.ScalarReplacementOfAggregates.diff
pub fn escaping() {
// Verify this struct is not flattened.
f(&Escaping { a: 1, b: 2, c: g() }.a);
}
+fn copies(x: Foo) {
+ let y = x;
+ let t = y.a;
+ let u = y.c;
+ let z = y;
+ let a = z.b;
+}
+
+fn ref_copies(x: &Foo) {
+ let y = *x;
+ let t = y.a;
+ let u = y.c;
+}
+
fn main() {
dropping();
enums(5);
unions(5.);
flat();
escaping();
+ copies(Foo { a: 5, b: (), c: "a", d: Some(-4) });
+ ref_copies(&Foo { a: 5, b: (), c: "a", d: Some(-4) });
}
+
+// EMIT_MIR sroa.dropping.ScalarReplacementOfAggregates.diff
+// EMIT_MIR sroa.enums.ScalarReplacementOfAggregates.diff
+// EMIT_MIR sroa.structs.ScalarReplacementOfAggregates.diff
+// EMIT_MIR sroa.unions.ScalarReplacementOfAggregates.diff
+// EMIT_MIR sroa.flat.ScalarReplacementOfAggregates.diff
+// EMIT_MIR sroa.escaping.ScalarReplacementOfAggregates.diff
+// EMIT_MIR sroa.copies.ScalarReplacementOfAggregates.diff
+// EMIT_MIR sroa.ref_copies.ScalarReplacementOfAggregates.diff
- StorageLive(_2); // scope 0 at $DIR/sroa.rs:+6:5: +6:21
+ StorageLive(_4); // scope 0 at $DIR/sroa.rs:+6:5: +6:21
+ StorageLive(_5); // scope 0 at $DIR/sroa.rs:+6:5: +6:21
++ nop; // scope 0 at $DIR/sroa.rs:+6:5: +6:21
StorageLive(_3); // scope 0 at $DIR/sroa.rs:+6:18: +6:19
_3 = _1; // scope 0 at $DIR/sroa.rs:+6:18: +6:19
-- Deinit(_2); // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-- (_2.0: usize) = const 0_usize; // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-- (_2.1: f32) = move _3; // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-+ Deinit(_4); // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-+ Deinit(_5); // scope 0 at $DIR/sroa.rs:+6:5: +6:21
+- _2 = U { _foo: const 0_usize, a: move _3 }; // scope 0 at $DIR/sroa.rs:+6:5: +6:21
+ _4 = const 0_usize; // scope 0 at $DIR/sroa.rs:+6:5: +6:21
+ _5 = move _3; // scope 0 at $DIR/sroa.rs:+6:5: +6:21
++ nop; // scope 0 at $DIR/sroa.rs:+6:5: +6:21
StorageDead(_3); // scope 0 at $DIR/sroa.rs:+6:20: +6:21
- _0 = (_2.1: f32); // scope 0 at $DIR/sroa.rs:+6:5: +6:23
- StorageDead(_2); // scope 0 at $DIR/sroa.rs:+7:1: +7:2
+ _0 = _5; // scope 0 at $DIR/sroa.rs:+6:5: +6:23
+ StorageDead(_4); // scope 0 at $DIR/sroa.rs:+7:1: +7:2
+ StorageDead(_5); // scope 0 at $DIR/sroa.rs:+7:1: +7:2
++ nop; // scope 0 at $DIR/sroa.rs:+7:1: +7:2
return; // scope 0 at $DIR/sroa.rs:+7:2: +7:2
}
}
StorageLive(_2); // scope 1 at $DIR/sroa.rs:+5:14: +5:27
StorageLive(_3); // scope 1 at $DIR/sroa.rs:+5:24: +5:25
_3 = _1; // scope 1 at $DIR/sroa.rs:+5:24: +5:25
- Deinit(_2); // scope 1 at $DIR/sroa.rs:+5:14: +5:27
- (_2.0: f32) = move _3; // scope 1 at $DIR/sroa.rs:+5:14: +5:27
+ _2 = Repr { f: move _3 }; // scope 1 at $DIR/sroa.rs:+5:14: +5:27
StorageDead(_3); // scope 1 at $DIR/sroa.rs:+5:26: +5:27
_0 = (_2.1: u32); // scope 1 at $DIR/sroa.rs:+5:14: +5:29
StorageDead(_2); // scope 0 at $DIR/sroa.rs:+6:1: +6:2
bb0: {
StorageLive(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
_3 = discriminant(_1); // scope 0 at $DIR/try_identity_e2e.rs:+3:19: +3:20
- switchInt(move _3) -> [0: bb2, 1: bb1, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:20
+ switchInt(move _3) -> [0: bb2, 1: bb1, otherwise: bb5]; // scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:20
}
bb1: {
- StorageLive(_5); // scope 0 at $DIR/try_identity_e2e.rs:+5:21: +5:22
_5 = move ((_1 as Err).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+5:21: +5:22
- Deinit(_2); // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
- ((_2 as Break).0: E) = move _5; // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
- discriminant(_2) = 1; // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
- _6 = discriminant(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
- switchInt(move _6) -> [0: bb5, 1: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
+ _2 = ControlFlow::<E, T>::Break(move _5); // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
+ goto -> bb3; // scope 0 at $DIR/try_identity_e2e.rs:+5:47: +5:48
}
bb2: {
- StorageLive(_4); // scope 0 at $DIR/try_identity_e2e.rs:+4:20: +4:21
_4 = move ((_1 as Ok).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+4:20: +4:21
- Deinit(_2); // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
- ((_2 as Continue).0: T) = move _4; // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
- discriminant(_2) = 0; // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
- _6 = discriminant(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
- switchInt(move _6) -> [0: bb5, 1: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
+ _2 = ControlFlow::<E, T>::Continue(move _4); // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
+ goto -> bb3; // scope 0 at $DIR/try_identity_e2e.rs:+4:49: +4:50
}
bb3: {
- StorageLive(_8); // scope 0 at $DIR/try_identity_e2e.rs:+9:32: +9:33
+ _6 = discriminant(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
+ switchInt(move _6) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
+ }
+
+ bb4: {
_8 = move ((_2 as Break).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+9:32: +9:33
- Deinit(_0); // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51
- ((_0 as Err).0: E) = move _8; // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51
- discriminant(_0) = 1; // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51
+ _0 = Result::<T, E>::Err(move _8); // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51
StorageDead(_2); // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2
return; // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2
}
- bb4: {
+ bb5: {
unreachable; // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
}
- bb5: {
- StorageLive(_7); // scope 0 at $DIR/try_identity_e2e.rs:+8:35: +8:36
+ bb6: {
_7 = move ((_2 as Continue).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+8:35: +8:36
- Deinit(_0); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6
- ((_0 as Ok).0: T) = move _7; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6
- discriminant(_0) = 0; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6
+ _0 = Result::<T, E>::Ok(move _7); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6
StorageDead(_2); // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2
return; // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2
}
}
bb1: {
- StorageLive(_4); // scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:18
_4 = move ((_1 as Err).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:18
- Deinit(_0); // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36
- ((_0 as Err).0: E) = move _4; // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36
- discriminant(_0) = 1; // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36
+ _0 = Result::<T, E>::Err(move _4); // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36
return; // scope 0 at $DIR/try_identity_e2e.rs:+7:1: +7:2
}
}
bb3: {
- StorageLive(_3); // scope 0 at $DIR/try_identity_e2e.rs:+3:16: +3:17
_3 = move ((_1 as Ok).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+3:16: +3:17
- Deinit(_0); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6
- ((_0 as Ok).0: T) = move _3; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6
- discriminant(_0) = 0; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6
+ _0 = Result::<T, E>::Ok(move _3); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6
return; // scope 0 at $DIR/try_identity_e2e.rs:+7:1: +7:2
}
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +5:6
StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
- Deinit(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
- discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
+ _2 = Test1::C; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
_3 = discriminant(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
switchInt(move _3) -> [2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
}
StorageDead(_1); // scope 0 at $DIR/uninhabited_enum_branching.rs:+5:6: +5:7
StorageLive(_6); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +10:6
StorageLive(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
- Deinit(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
- discriminant(_7) = 0; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
+ _7 = Test2::D; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
_8 = discriminant(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
switchInt(move _8) -> [4: bb5, 5: bb3, otherwise: bb4]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +5:6
StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
- Deinit(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
- discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
+ _2 = Test1::C; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
_3 = discriminant(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
- switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
+ switchInt(move _3) -> [2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
StorageDead(_1); // scope 0 at $DIR/uninhabited_enum_branching.rs:+5:6: +5:7
StorageLive(_6); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +10:6
StorageLive(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
- Deinit(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
- discriminant(_7) = 0; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
+ _7 = Test2::D; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
_8 = discriminant(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
switchInt(move _8) -> [4: bb8, 5: bb6, otherwise: bb7]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:9: +1:13
StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
- Deinit(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
- discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
- Deinit(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
- (_1.0: u32) = const 51_u32; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
- (_1.1: Test1) = move _2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
+ _2 = Test1::C; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
+ _1 = Plop { xx: const 51_u32, test1: move _2 }; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
StorageDead(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:47: +1:48
StorageLive(_3); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +8:6
StorageLive(_4); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
bb0: {
StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:9: +1:13
StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
- Deinit(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
- discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
- Deinit(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
- (_1.0: u32) = const 51_u32; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
- (_1.1: Test1) = move _2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
+ _2 = Test1::C; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
+ _1 = Plop { xx: const 51_u32, test1: move _2 }; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
StorageDead(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:47: +1:48
StorageLive(_3); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +8:6
StorageLive(_4); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
let mut _0: Test; // return place in scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6
bb0: {
- Deinit(_0); // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6
- ((_0 as X).0: usize) = move _1; // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6
- discriminant(_0) = 0; // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6
+ _0 = Test::X(move _1); // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6
return; // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6
}
}
StorageLive(_1); // scope 0 at $DIR/while_let_loops.rs:+1:9: +1:15
_1 = const 0_i32; // scope 0 at $DIR/while_let_loops.rs:+1:18: +1:19
StorageLive(_2); // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
- Deinit(_2); // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
- discriminant(_2) = 0; // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
+ _2 = Option::<u32>::None; // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
- _3 = discriminant(_2); // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
- switchInt(move _3) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
+ _3 = const 0_isize; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
tr -d '\r\n' | $(CGREP) -e \
"mismatched types.*\
crateB::try_foo\(foo2\);.*\
- expected struct \`crateA::foo::Foo\`, found struct \`Foo\`.*\
+ expected \`crateA::foo::Foo\`, found \`Foo\`.*\
different versions of crate \`crateA\`.*\
mismatched types.*\
crateB::try_bar\(bar2\);.*\
touch $(SESSION_DIR)
# Check exit code is 1 for an error, and not 101 for ICE.
$(RUSTC) foo.rs --crate-type=rlib -C incremental=$(SESSION_DIR) > $(OUTPUT_FILE) 2>&1; [ $$? -eq 1 ]
- $(CGREP) "Could not create incremental compilation crate directory" < $(OUTPUT_FILE)
+ $(CGREP) "could not create incremental compilation crate directory" < $(OUTPUT_FILE)
# -v tests are fragile, hopefully this text won't change
$(CGREP) -v "internal compiler error" < $(OUTPUT_FILE)
// Check that their content is inside <pre><code>
assert-count: (".example-wrap pre > code", 4)
// Check that function signature is inside <pre><code>
-assert: ".item-decl pre.rust > code"
+assert: "pre.rust.item-decl > code"
goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
-assert: ".item-decl pre.rust > code"
+assert: "pre.rust.item-decl > code"
goto: "file://" + |DOC_PATH| + "/test_docs/enum.AnEnum.html"
-assert: ".item-decl pre.rust > code"
+assert: "pre.rust.item-decl > code"
goto: "file://" + |DOC_PATH| + "/test_docs/trait.AnotherOne.html"
-assert: ".item-decl pre.rust > code"
+assert: "pre.rust.item-decl > code"
goto: "file://" + |DOC_PATH| + "/test_docs/type.SomeType.html"
-assert: ".item-decl pre.rust > code"
+assert: "pre.rust.item-decl > code"
// This test checks that the font weight is correctly applied.
goto: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html"
-assert-css: ("//*[@class='item-decl']//a[text()='Alias']", {"font-weight": "400"})
+assert-css: ("//*[@class='rust item-decl']//a[text()='Alias']", {"font-weight": "400"})
assert-css: (
"//*[@class='structfield small-section-header']//a[text()='Alias']",
{"font-weight": "400"},
// This is a complex selector, so here's how it works:
//
-// * //*[@class='item-decl'] — selects element of any tag with classes docblock and item-decl
-// * /pre[@class='rust'] — selects immediate child with tag pre and class rust
+// * //pre[@class='rust item-decl'] — selects item-decl code block
// * /code — selects immediate child with tag code
// * /a[@class='constant'] — selects immediate child with tag a and class constant
// * //text() — selects child that is text node
// This uses '/parent::*' as a proxy for the style of the text node.
// We can't just select the '<a>' because intermediate tags could be added.
assert-count: (
- "//*[@class='item-decl']/pre[@class='rust']/code/a[@class='constant']//text()/parent::*",
+ "//pre[@class='rust item-decl']/code/a[@class='constant']//text()/parent::*",
1,
)
assert-css: (
- "//*[@class='item-decl']/pre[@class='rust']/code/a[@class='constant']//text()/parent::*",
+ "//pre[@class='rust item-decl']/code/a[@class='constant']//text()/parent::*",
{"font-weight": "400"},
)
// This test checks that code blocks in list are supported.
goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
goto: "./fn.check_list_code_block.html"
-assert: (".item-decl pre.rust")
+assert: ("pre.rust.item-decl")
pub mod doc_block_table {
pub trait DocBlockTableTrait {
- fn func();
+ fn foo();
}
/// Struct doc.
/// | header1 | header2 |
/// |--------------------------|--------------------------|
/// | Lorem Ipsum, Lorem Ipsum | Lorem Ipsum, Lorem Ipsum |
- fn func() {
+ fn foo() {
println!();
}
}
///
/// </sub>
pub mod codeblock_sub {}
+pub mod search_results {
+
+ pub struct SearchResults {
+ pub foo: i32,
+ }
+
+ #[macro_export]
+ macro_rules! foo {
+ () => {};
+ }
+
+}
// Logically, the <body> scroll width should be the width of the window.
assert-property: ("body", {"scrollWidth": "1100"})
// However, since there is overflow in the type declaration, its scroll width is bigger.
-assert-property: (".item-decl pre", {"scrollWidth": "1324"})
+assert-property: ("pre.item-decl", {"scrollWidth": "1324"})
// In the table-ish view on the module index, the name should not be wrapped more than necessary.
goto: "file://" + |DOC_PATH| + "/lib2/too_long/index.html"
// We now check that the section width hasn't grown because of it.
assert-property: ("#main-content", {"scrollWidth": "840"})
// And now checking that it has scrollable content.
-assert-property: (".item-decl pre", {"scrollWidth": "1103"})
+assert-property: ("pre.item-decl", {"scrollWidth": "1103"})
// ... and constant.
// On a sidenote, it also checks that the (very) long title isn't changing the docblock width.
// We now check that the section width hasn't grown because of it.
assert-property: ("#main-content", {"scrollWidth": "840"})
// And now checking that it has scrollable content.
-assert-property: (".item-decl pre", {"scrollWidth": "950"})
+assert-property: ("pre.item-decl", {"scrollWidth": "950"})
// On mobile:
size: (600, 600)
goto: "file://" + |DOC_PATH| + "/lib2/scroll_traits/trait.Iterator.html"
click: ".item-decl .type-contents-toggle"
-assert-property: (".item-decl > pre", {"scrollLeft": 0})
-scroll-to: "//*[@class='item-decl']//details/a[text()='String']"
-assert-property-false: (".item-decl > pre", {"scrollLeft": 0})
+assert-property: ("pre.item-decl", {"scrollLeft": 0})
+scroll-to: "//*[@class='rust item-decl']//details/a[text()='String']"
+assert-property-false: ("pre.item-decl", {"scrollLeft": 0})
// Then on an item without "hidden methods".
goto: "file://" + |DOC_PATH| + "/lib2/scroll_traits/trait.TraitWithLongItemsName.html"
-assert-property: (".item-decl > pre", {"scrollLeft": 0})
-scroll-to: "//*[@class='item-decl']//code/a[text()='String']"
-assert-property-false: (".item-decl > pre", {"scrollLeft": 0})
+assert-property: ("pre.item-decl", {"scrollLeft": 0})
+scroll-to: "//*[@class='rust item-decl']//code/a[text()='String']"
+assert-property-false: ("pre.item-decl", {"scrollLeft": 0})
--- /dev/null
+// exact-check
+
+// https://github.com/rust-lang/rust/issues/103357
+const QUERY = 'regex';
+
+const EXPECTED = {
+ 'others': [],
+ 'in_args': [],
+ 'returned': [],
+};
{ 'path': 'std', 'name': 'println' },
{ 'path': 'std', 'name': 'eprint' },
{ 'path': 'std', 'name': 'eprintln' },
- { 'path': 'std::pin', 'name': 'pin' },
- { 'path': 'std::future', 'name': 'join' },
- { 'path': 'std', 'name': 'line' },
- { 'path': 'std', 'name': 'write' },
],
};
-// exact-check
-
const QUERY = [
'StructItem',
'StructFieldItem',
'others': [
{ 'path': 'module_substring::Sig', 'name': 'pc' },
{ 'path': 'module_substring::Si', 'name': 'pc' },
- { 'path': 'module_substring::Si', 'name': 'pa' },
],
};
-// check-pass
// normalize-stderr-test: "`.*`" -> "`DEF_ID`"
// normalize-stdout-test: "`.*`" -> "`DEF_ID`"
// edition:2018
pub async fn f() -> impl std::fmt::Debug {
- // rustdoc doesn't care that this is infinitely sized
#[derive(Debug)]
- enum E {
+ enum E { //~ ERROR
This(E),
Unit,
}
--- /dev/null
+error[E0072]: recursive type `DEF_ID` has infinite size
+ --> $DIR/infinite-recursive-type-impl-trait-return.rs:7:5
+ |
+LL | enum E {
+ | ^^^^^^
+LL | This(E),
+ | - recursive without indirection
+ |
+help: insert some indirection (e.g., a `DEF_ID`) to break the cycle
+ |
+LL | This(Box<E>),
+ | ++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `DEF_ID`.
-// check-pass
-
fn f() -> impl Sized {
- // rustdoc doesn't care that this is infinitely sized
- enum E {
+ enum E { //~ ERROR
V(E),
}
unimplemented!()
--- /dev/null
+error[E0072]: recursive type `f::E` has infinite size
+ --> $DIR/infinite-recursive-type-impl-trait.rs:2:5
+ |
+LL | enum E {
+ | ^^^^^^
+LL | V(E),
+ | - recursive without indirection
+ |
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
+ |
+LL | V(Box<E>),
+ | ++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
--> $DIR/track-diagnostics.rs:LL:CC
|
LL | const S: A = B;
- | ^ expected struct `A`, found struct `B`
+ | ^ expected `A`, found `B`
-Ztrack-diagnostics: created at compiler/rustc_infer/src/infer/error_reporting/mod.rs:LL:CC
error: aborting due to previous error
pub struct MyBox<T: ?Sized>(*const T);
// @has 'foo/fn.alpha.html'
-// @snapshot link_slice_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_slice_u32 - '//pre[@class="rust item-decl"]/code'
pub fn alpha() -> &'static [u32; 1] {
loop {}
}
// @has 'foo/fn.beta.html'
-// @snapshot link_slice_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_slice_generic - '//pre[@class="rust item-decl"]/code'
pub fn beta<T>() -> &'static [T; 1] {
loop {}
}
// @has 'foo/fn.gamma.html'
-// @snapshot link_box_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_box_u32 - '//pre[@class="rust item-decl"]/code'
pub fn gamma() -> MyBox<[u32; 1]> {
loop {}
}
// @has 'foo/fn.delta.html'
-// @snapshot link_box_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_box_generic - '//pre[@class="rust item-decl"]/code'
pub fn delta<T>() -> MyBox<[T; 1]> {
loop {}
}
pub trait Foo {
- // @has assoc_consts/trait.Foo.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // @has assoc_consts/trait.Foo.html '//pre[@class="rust item-decl"]' \
// 'const FOO: usize = 13usize;'
// @has - '//*[@id="associatedconstant.FOO"]' 'const FOO: usize'
const FOO: usize = 12 + 1;
}
// @has foo/type.AsExprOf.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type AsExprOf<Item, Type> = <Item as AsExpression<Type>>::Expression;'
+// @has - '//pre[@class="rust item-decl"]' 'type AsExprOf<Item, Type> = <Item as AsExpression<Type>>::Expression;'
pub type AsExprOf<Item, Type> = <Item as AsExpression<Type>>::Expression;
}
// @has assoc_types/fn.use_output.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' '-> &T::Output'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]//a[@href="trait.Index.html#associatedtype.Output"]' 'Output'
+// @has - '//pre[@class="rust item-decl"]' '-> &T::Output'
+// @has - '//pre[@class="rust item-decl"]//a[@href="trait.Index.html#associatedtype.Output"]' 'Output'
pub fn use_output<T: Index<usize>>(obj: &T, index: usize) -> &T::Output {
obj.index(index)
}
}
// @has assoc_types/fn.use_input.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'T::Input'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input'
+// @has - '//pre[@class="rust item-decl"]' 'T::Input'
+// @has - '//pre[@class="rust item-decl"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input'
pub fn use_input<T: Feed>(_feed: &T, _element: T::Input) { }
// @has assoc_types/fn.cmp_input.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where T::Input: PartialEq<U::Input>'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input'
+// @has - '//pre[@class="rust item-decl"]' 'where T::Input: PartialEq<U::Input>'
+// @has - '//pre[@class="rust item-decl"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input'
pub fn cmp_input<T: Feed, U: Feed>(a: &T::Input, b: &U::Input) -> bool
where T::Input: PartialEq<U::Input>
{
// edition:2018
-// @has async_fn/fn.foo.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn foo() -> Option<Foo>'
+// @has async_fn/fn.foo.html '//pre[@class="rust item-decl"]' 'pub async fn foo() -> Option<Foo>'
pub async fn foo() -> Option<Foo> {
None
}
-// @has async_fn/fn.bar.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn bar(a: i32, b: i32) -> i32'
+// @has async_fn/fn.bar.html '//pre[@class="rust item-decl"]' 'pub async fn bar(a: i32, b: i32) -> i32'
pub async fn bar(a: i32, b: i32) -> i32 {
0
}
-// @has async_fn/fn.baz.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn baz<T>(a: T) -> T'
+// @has async_fn/fn.baz.html '//pre[@class="rust item-decl"]' 'pub async fn baz<T>(a: T) -> T'
pub async fn baz<T>(a: T) -> T {
a
}
-// @has async_fn/fn.qux.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async unsafe fn qux() -> char'
+// @has async_fn/fn.qux.html '//pre[@class="rust item-decl"]' 'pub async unsafe fn qux() -> char'
pub async unsafe fn qux() -> char {
'⚠'
}
-// @has async_fn/fn.mut_args.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn mut_args(a: usize)'
+// @has async_fn/fn.mut_args.html '//pre[@class="rust item-decl"]' 'pub async fn mut_args(a: usize)'
pub async fn mut_args(mut a: usize) {}
-// @has async_fn/fn.mut_ref.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn mut_ref(x: i32)'
+// @has async_fn/fn.mut_ref.html '//pre[@class="rust item-decl"]' 'pub async fn mut_ref(x: i32)'
pub async fn mut_ref(ref mut x: i32) {}
trait Bar {}
impl Bar for () {}
-// @has async_fn/fn.quux.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn quux() -> impl Bar'
+// @has async_fn/fn.quux.html '//pre[@class="rust item-decl"]' 'pub async fn quux() -> impl Bar'
pub async fn quux() -> impl Bar {
()
}
pub trait Trait<const N: usize> {}
// @has async_fn/fn.const_generics.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn const_generics<const N: usize>(_: impl Trait<N>)'
+// @has - '//pre[@class="rust item-decl"]' 'pub async fn const_generics<const N: usize>(_: impl Trait<N>)'
pub async fn const_generics<const N: usize>(_: impl Trait<N>) {}
// test that elided lifetimes are properly elided and not displayed as `'_`
// regression test for #63037
// @has async_fn/fn.elided.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn elided(foo: &str) -> &str'
+// @has - '//pre[@class="rust item-decl"]' 'pub async fn elided(foo: &str) -> &str'
pub async fn elided(foo: &str) -> &str {}
// This should really be shown as written, but for implementation reasons it's difficult.
// See `impl Clean for TyKind::Ref`.
// @has async_fn/fn.user_elided.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn user_elided(foo: &str) -> &str'
+// @has - '//pre[@class="rust item-decl"]' 'pub async fn user_elided(foo: &str) -> &str'
pub async fn user_elided(foo: &'_ str) -> &str {}
// @has async_fn/fn.static_trait.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn static_trait(foo: &str) -> Box<dyn Bar>'
+// @has - '//pre[@class="rust item-decl"]' 'pub async fn static_trait(foo: &str) -> Box<dyn Bar>'
pub async fn static_trait(foo: &str) -> Box<dyn Bar> {}
// @has async_fn/fn.lifetime_for_trait.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn lifetime_for_trait(foo: &str) -> Box<dyn Bar + '_>"
+// @has - '//pre[@class="rust item-decl"]' "pub async fn lifetime_for_trait(foo: &str) -> Box<dyn Bar + '_>"
pub async fn lifetime_for_trait(foo: &str) -> Box<dyn Bar + '_> {}
// @has async_fn/fn.elided_in_input_trait.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn elided_in_input_trait(t: impl Pattern<'_>)"
+// @has - '//pre[@class="rust item-decl"]' "pub async fn elided_in_input_trait(t: impl Pattern<'_>)"
pub async fn elided_in_input_trait(t: impl Pattern<'_>) {}
struct AsyncFdReadyGuard<'a, T> { x: &'a T }
// test named lifetimes, just in case
// @has async_fn/fn.named.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn named<'a, 'b>(foo: &'a str) -> &'b str"
+// @has - '//pre[@class="rust item-decl"]' "pub async fn named<'a, 'b>(foo: &'a str) -> &'b str"
pub async fn named<'a, 'b>(foo: &'a str) -> &'b str {}
// @has async_fn/fn.named_trait.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b>"
+// @has - '//pre[@class="rust item-decl"]' "pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b>"
pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b> {}
#![crate_name = "foo"]
// @has 'foo/fn.f.html'
-// @has - //*[@'class="item-decl"]' '#[export_name = "f"] pub fn f()'
+// @has - //*[@'class="rust item-decl"]' '#[export_name = "f"] pub fn f()'
#[export_name = "\
f"]
pub fn f() {}
#![crate_name = "foo"]
-// @has foo/fn.f.html '//div[@class="item-decl"]/pre[@class="rust"]' '#[no_mangle]'
+// @has foo/fn.f.html '//pre[@class="rust item-decl"]' '#[no_mangle]'
#[no_mangle]
pub extern "C" fn f() {}
-// @has foo/fn.g.html '//div[@class="item-decl"]/pre[@class="rust"]' '#[export_name = "bar"]'
+// @has foo/fn.g.html '//pre[@class="rust item-decl"]' '#[export_name = "bar"]'
#[export_name = "bar"]
pub extern "C" fn g() {}
-// @has foo/struct.Repr.html '//div[@class="item-decl"]' '#[repr(C, align(8))]'
+// @has foo/struct.Repr.html '//pre[@class="rust item-decl"]' '#[repr(C, align(8))]'
#[repr(C, align(8))]
pub struct Repr;
fn bar(&self);
fn foo(&mut self) {}
}
+
+pub trait Bar {
+ fn bar(&self);
+ fn foo1(&mut self) {}
+ fn foo2(&mut self) {}
+}
+
+pub trait Baz {
+ fn bar1(&self);
+ fn bar2(&self);
+ fn foo(&mut self) {}
+}
// @has issue_85454/trait.FromResidual.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
+// @has - '//pre[@class="rust item-decl"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
pub trait FromResidual<R = <Self as Try>::Residual> {
fn from_residual(residual: R) -> Self;
}
#![crate_name = "foo"]
// @has foo/fn.bar.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub const fn bar() -> '
+// @has - '//pre[@class="rust item-decl"]' 'pub const fn bar() -> '
/// foo
pub const fn bar() -> usize {
2
use std::ops::Add;
-// @has foo/struct.Simd.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Simd<T, const WIDTH: usize>'
+// @has foo/struct.Simd.html '//pre[@class="rust item-decl"]' 'pub struct Simd<T, const WIDTH: usize>'
pub struct Simd<T, const WIDTH: usize> {
inner: T,
}
#![crate_name = "foo"]
-// @has foo/struct.Foo.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/struct.Foo.html '//pre[@class="rust item-decl"]' \
// 'pub struct Foo<const M: usize = 10, const N: usize = M, T = i32>(_);'
pub struct Foo<const M: usize = 10, const N: usize = M, T = i32>(T);
#![crate_name = "foo"]
extern crate extern_crate;
-// @has foo/fn.extern_fn.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.extern_fn.html '//pre[@class="rust item-decl"]' \
// 'pub fn extern_fn<const N: usize>() -> impl Iterator<Item = [u8; N]>'
pub use extern_crate::extern_fn;
-// @has foo/struct.ExternTy.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/struct.ExternTy.html '//pre[@class="rust item-decl"]' \
// 'pub struct ExternTy<const N: usize> {'
pub use extern_crate::ExternTy;
-// @has foo/type.TyAlias.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/type.TyAlias.html '//pre[@class="rust item-decl"]' \
// 'type TyAlias<const N: usize> = ExternTy<N>;'
pub use extern_crate::TyAlias;
-// @has foo/trait.WTrait.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/trait.WTrait.html '//pre[@class="rust item-decl"]' \
// 'pub trait WTrait<const N: usize, const M: usize>'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn hey<const P: usize>() -> usize'
+// @has - '//pre[@class="rust item-decl"]' 'fn hey<const P: usize>() -> usize'
pub use extern_crate::WTrait;
-// @has foo/trait.Trait.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/trait.Trait.html '//pre[@class="rust item-decl"]' \
// 'pub trait Trait<const N: usize>'
// @has - '//*[@id="impl-Trait%3C1%3E-for-u8"]//h3[@class="code-header"]' 'impl Trait<1> for u8'
// @has - '//*[@id="impl-Trait%3C2%3E-for-u8"]//h3[@class="code-header"]' 'impl Trait<2> for u8'
impl Trait<{1 + 2}> for u8 {}
impl<const N: usize> Trait<N> for [u8; N] {}
-// @has foo/struct.Foo.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/struct.Foo.html '//pre[@class="rust item-decl"]' \
// 'pub struct Foo<const N: usize>where u8: Trait<N>'
pub struct Foo<const N: usize> where u8: Trait<N>;
-// @has foo/struct.Bar.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Bar<T, const N: usize>(_)'
+// @has foo/struct.Bar.html '//pre[@class="rust item-decl"]' 'pub struct Bar<T, const N: usize>(_)'
pub struct Bar<T, const N: usize>([T; N]);
// @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header"]' 'impl<const M: usize> Foo<M>where u8: Trait<M>'
}
}
-// @has foo/fn.test.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.test.html '//pre[@class="rust item-decl"]' \
// 'pub fn test<const N: usize>() -> impl Trait<N>where u8: Trait<N>'
pub fn test<const N: usize>() -> impl Trait<N> where u8: Trait<N> {
2u8
}
-// @has foo/fn.a_sink.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.a_sink.html '//pre[@class="rust item-decl"]' \
// 'pub async fn a_sink<const N: usize>(v: [u8; N]) -> impl Trait<N>'
pub async fn a_sink<const N: usize>(v: [u8; N]) -> impl Trait<N> {
v
}
-// @has foo/fn.b_sink.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.b_sink.html '//pre[@class="rust item-decl"]' \
// 'pub async fn b_sink<const N: usize>(_: impl Trait<N>)'
pub async fn b_sink<const N: usize>(_: impl Trait<N>) {}
-// @has foo/fn.concrete.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.concrete.html '//pre[@class="rust item-decl"]' \
// 'pub fn concrete() -> [u8; 22]'
pub fn concrete() -> [u8; 3 + std::mem::size_of::<u64>() << 1] {
Default::default()
}
-// @has foo/type.Faz.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/type.Faz.html '//pre[@class="rust item-decl"]' \
// 'type Faz<const N: usize> = [u8; N];'
pub type Faz<const N: usize> = [u8; N];
-// @has foo/type.Fiz.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/type.Fiz.html '//pre[@class="rust item-decl"]' \
// 'type Fiz<const N: usize> = [[u8; N]; 48];'
pub type Fiz<const N: usize> = [[u8; N]; 3 << 4];
}
}
-// @has foo/struct.Foz.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/struct.Foz.html '//pre[@class="rust item-decl"]' \
// 'pub struct Foz<const N: usize>(_);'
define_me!(Foz<N>);
const ASSOC: usize = N;
}
-// @has foo/fn.q_user.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.q_user.html '//pre[@class="rust item-decl"]' \
// 'pub fn q_user() -> [u8; 13]'
pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {
[0; <[u8; 13] as Q>::ASSOC]
}
-// @has foo/union.Union.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/union.Union.html '//pre[@class="rust item-decl"]' \
// 'pub union Union<const N: usize>'
pub union Union<const N: usize> {
// @has - //pre "pub arr: [u8; N]"
pub another_arr: [(); N],
}
-// @has foo/enum.Enum.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/enum.Enum.html '//pre[@class="rust item-decl"]' \
// 'pub enum Enum<const N: usize>'
pub enum Enum<const N: usize> {
// @has - //pre "Variant([u8; N])"
Unsorted,
}
-// @has foo/struct.VSet.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct VSet<T, const ORDER: Order>'
+// @has foo/struct.VSet.html '//pre[@class="rust item-decl"]' 'pub struct VSet<T, const ORDER: Order>'
// @has foo/struct.VSet.html '//*[@id="impl-Send-for-VSet%3CT%2C%20ORDER%3E"]/h3[@class="code-header"]' 'impl<T, const ORDER: Order> Send for VSet<T, ORDER>'
// @has foo/struct.VSet.html '//*[@id="impl-Sync-for-VSet%3CT%2C%20ORDER%3E"]/h3[@class="code-header"]' 'impl<T, const ORDER: Order> Sync for VSet<T, ORDER>'
pub struct VSet<T, const ORDER: Order> {
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
// make sure that `ConstEvaluatable` predicates dont cause rustdoc to ICE #77647
-// @has foo/struct.Ice.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/struct.Ice.html '//pre[@class="rust item-decl"]' \
// 'pub struct Ice<const N: usize>;'
pub struct Ice<const N: usize> where [(); N + 1]:;
#![crate_name = "foo"]
-// @has foo/type.CellIndex.html '//div[@class="item-decl"]/pre[@class="rust"]' 'type CellIndex<const D: usize> = [i64; D];'
+// @has foo/type.CellIndex.html '//pre[@class="rust item-decl"]' 'type CellIndex<const D: usize> = [i64; D];'
pub type CellIndex<const D: usize> = [i64; D];
extern "rust-intrinsic" {
// @has 'foo/fn.transmute.html'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub const unsafe extern "rust-intrinsic" fn transmute<T, U>(_: T) -> U'
+ // @has - '//pre[@class="rust item-decl"]' 'pub const unsafe extern "rust-intrinsic" fn transmute<T, U>(_: T) -> U'
#[stable(since="1.0.0", feature="rust1")]
#[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
pub fn transmute<T, U>(_: T) -> U;
// @has 'foo/fn.unreachable.html'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
+ // @has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
#[stable(since="1.0.0", feature="rust1")]
pub fn unreachable() -> !;
}
extern "C" {
// @has 'foo/fn.needs_drop.html'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "C" fn needs_drop() -> !'
+ // @has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn needs_drop() -> !'
#[stable(since="1.0.0", feature="rust1")]
pub fn needs_drop() -> !;
}
#![crate_name = "foo"]
// @has 'foo/constant.HOUR_IN_SECONDS.html'
-// @has - '//*[@class="item-decl"]//code' 'pub const HOUR_IN_SECONDS: u64 = _; // 3_600u64'
+// @has - '//*[@class="rust item-decl"]//code' 'pub const HOUR_IN_SECONDS: u64 = _; // 3_600u64'
pub const HOUR_IN_SECONDS: u64 = 60 * 60;
// @has 'foo/constant.NEGATIVE.html'
-// @has - '//*[@class="item-decl"]//code' 'pub const NEGATIVE: i64 = _; // -3_600i64'
+// @has - '//*[@class="rust item-decl"]//code' 'pub const NEGATIVE: i64 = _; // -3_600i64'
pub const NEGATIVE: i64 = -60 * 60;
<code>pub trait Write {
+ // Required methods
fn <a href="#tymethod.poll_write" class="fn">poll_write</a>(<br />        self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        cx: &mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        buf: &mut [<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>]<br />    ) -> <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a><<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>>>;
<span class="item-spacer" /> fn <a href="#tymethod.poll_flush" class="fn">poll_flush</a>(<br />        self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        cx: &mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>><br />    ) -> <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a><<a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>>>;
<span class="item-spacer" /> fn <a href="#tymethod.poll_close" class="fn">poll_close</a>(<br />        self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        cx: &mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>><br />    ) -> <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a><<a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>>>;
+ // Provided method
fn <a href="#method.poll_write_vectored" class="fn">poll_write_vectored</a>(<br />        self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        cx: &mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        bufs: &[<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>]<br />    ) -> <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a><<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>>> { ... }
-}</code>
\ No newline at end of file
+}</code>
// @has 'foo/trait.Write.html'
pub trait Write {
- // @snapshot 'declaration' - '//*[@class="item-decl"]//code'
+ // @snapshot 'declaration' - '//*[@class="rust item-decl"]//code'
fn poll_write(
self: Option<String>,
cx: &mut Option<String>,
-<script type="text/json" id="notable-traits-data">{"SomeStruct":"<h3>Notable traits for <code><a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\">SomeStruct</a></code></h3><pre><code><span class=\"where fmt-newline\">impl <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a> for <a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\">SomeStruct</a></span>","Wrapper<Self>":"<h3>Notable traits for <code><a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</code></h3><pre><code><span class=\"where fmt-newline\">impl&lt;T:&nbsp;<a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a>&gt; <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a> for <a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</span>"}</script>
\ No newline at end of file
+<script type="text/json" id="notable-traits-data">{"SomeStruct":"<h3>Notable traits for <code><a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\">SomeStruct</a></code></h3><pre><code><span class=\"where fmt-newline\">impl <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a> for <a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\">SomeStruct</a></span>","Wrapper<Self>":"<h3>Notable traits for <code><a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</code></h3><pre><code><span class=\"where fmt-newline\">impl&lt;T: <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a>&gt; <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a> for <a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</span>"}</script>
\ No newline at end of file
-<script type="text/json" id="notable-traits-data">{"Wrapper<Self>":"<h3>Notable traits for <code><a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</code></h3><pre><code><span class=\"where fmt-newline\">impl&lt;T:&nbsp;<a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a>&gt; <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a> for <a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</span>"}</script>
\ No newline at end of file
+<script type="text/json" id="notable-traits-data">{"Wrapper<Self>":"<h3>Notable traits for <code><a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</code></h3><pre><code><span class=\"where fmt-newline\">impl&lt;T: <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a>&gt; <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a> for <a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</span>"}</script>
\ No newline at end of file
--- /dev/null
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub trait Enumerable {
+ const N: usize;
+}
+
+#[derive(Clone)]
+pub struct SymmetricGroup<S>
+where
+ S: Enumerable,
+ [(); S::N]: Sized,
+{
+ _phantom: std::marker::PhantomData<S>,
+}
+
+fn main() {}
#![crate_name = "foo"]
// @has foo/fn.f.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f(callback: fn(len: usize, foo: u32))'
+// @has - '//pre[@class="rust item-decl"]' 'pub fn f(callback: fn(len: usize, foo: u32))'
pub fn f(callback: fn(len: usize, foo: u32)) {}
--- /dev/null
+// This is a regression test for <https://github.com/rust-lang/rust/issues/106373>.
+// It ensures that the items in the `doc(hidden)` const block don't show up in the
+// generated docs.
+
+// compile-flags: --document-private-items
+
+#![crate_name = "foo"]
+
+// @has 'foo/index.html'
+// @count - '//*[@class="item-table"]//a[@class="struct"]' 2
+// @count - '//*[@class="item-table"]//a[@class="trait"]' 1
+// @count - '//*[@class="item-table"]//a[@class="macro"]' 0
+#[doc(hidden)]
+const _: () = {
+ macro_rules! stry {
+ () => {};
+ }
+
+ struct ShouldBeHidden;
+
+ // @has 'foo/struct.Foo.html'
+ // @!has - '//*[@class="code-header"]' 'impl Bar for Foo'
+ #[doc(hidden)]
+ impl Bar for Foo {
+ fn bar(&self) {
+ struct SHouldAlsoBeHidden;
+ }
+ }
+
+ // @has 'foo/struct.Private.html'
+ // @has - '//*[@id="impl-Bar-for-Private"]/*[@class="code-header"]' 'impl Bar for Private'
+ // @has - '//*[@id="method.bar"]/*[@class="code-header"]' 'fn bar(&self)'
+ impl Bar for Private {
+ fn bar(&self) {}
+ }
+
+ // @has - '//*[@id="impl-Private"]/*[@class="code-header"]' 'impl Private'
+ // @has - '//*[@id="method.tralala"]/*[@class="code-header"]' 'fn tralala()'
+ impl Private {
+ fn tralala() {}
+ }
+};
+
+
+struct Private;
+pub struct Foo;
+
+pub trait Bar {
+ fn bar(&self);
+}
// this test as long as one can ensure that private fields are not leaked!
//
// @has hide_complex_unevaluated_const_arguments/trait.Sub.html \
-// '//div[@class="item-decl"]/pre[@class="rust"]' \
+// '//pre[@class="rust item-decl"]' \
// 'pub trait Sub: Sup<{ _ }, { _ }> { }'
pub trait Sub: Sup<{ 90 * 20 * 4 }, { Struct { private: () } }> {}
--- /dev/null
+// Regression test for #83026.
+// The goal of this test is to ensure that impl blocks inside
+// const expressions are documented as well.
+
+#![crate_name = "foo"]
+
+// @has 'foo/struct.A.html'
+// @has - '//*[@id="method.new"]/*[@class="code-header"]' 'pub fn new() -> A'
+// @has - '//*[@id="method.bar"]/*[@class="code-header"]' 'pub fn bar(&self)'
+// @has - '//*[@id="method.woo"]/*[@class="code-header"]' 'pub fn woo(&self)'
+// @has - '//*[@id="method.yoo"]/*[@class="code-header"]' 'pub fn yoo()'
+// @has - '//*[@id="method.yuu"]/*[@class="code-header"]' 'pub fn yuu()'
+pub struct A;
+
+const _: () = {
+ impl A {
+ const FOO: () = {
+ impl A {
+ pub fn woo(&self) {}
+ }
+ };
+
+ pub fn new() -> A {
+ A
+ }
+ }
+};
+pub const X: () = {
+ impl A {
+ pub fn bar(&self) {}
+ }
+};
+
+fn foo() {
+ impl A {
+ pub fn yoo() {}
+ }
+ const _: () = {
+ impl A {
+ pub fn yuu() {}
+ }
+ };
+}
extern crate inline_default_methods;
// @has inline_default_methods/trait.Foo.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn bar(&self);'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn foo(&mut self) { ... }'
+// @has - '//pre[@class="rust item-decl"]' '// Required method fn bar(&self);'
+// @has - '//pre[@class="rust item-decl"]' '// Provided method fn foo(&mut self)'
pub use inline_default_methods::Foo;
+
+// @has inline_default_methods/trait.Bar.html
+// @has - '//pre[@class="rust item-decl"]' '// Required method fn bar(&self);'
+// @has - '//pre[@class="rust item-decl"]' '// Provided methods fn foo1(&mut self)'
+// @has - '//pre[@class="rust item-decl"]' 'fn foo2(&mut self)'
+pub use inline_default_methods::Bar;
+
+// @has inline_default_methods/trait.Baz.html
+// @has - '//pre[@class="rust item-decl"]' '// Required methods fn bar1(&self);'
+// @has - '//pre[@class="rust item-decl"]' 'fn bar2(&self);'
+// @has - '//pre[@class="rust item-decl"]' '// Provided method fn foo(&mut self)'
+pub use inline_default_methods::Baz;
// edition:2021
// @has user/type.Ty0.html
-// @has - '//*[@class="item-decl"]//code' "dyn for<'any> FnOnce(&'any str) -> bool + 'static"
+// @has - '//*[@class="rust item-decl"]//code' "dyn for<'any> FnOnce(&'any str) -> bool + 'static"
// FIXME(fmease): Hide default lifetime bound `'static`
pub use dyn_trait::Ty0;
// @has user/type.Ty1.html
-// @has - '//*[@class="item-decl"]//code' "dyn Display + 'obj"
+// @has - '//*[@class="rust item-decl"]//code' "dyn Display + 'obj"
pub use dyn_trait::Ty1;
// @has user/type.Ty2.html
-// @has - '//*[@class="item-decl"]//code' "dyn for<'a, 'r> Container<'r, Item<'a, 'static> = ()>"
+// @has - '//*[@class="rust item-decl"]//code' "dyn for<'a, 'r> Container<'r, Item<'a, 'static> = ()>"
pub use dyn_trait::Ty2;
// @has user/type.Ty3.html
-// @has - '//*[@class="item-decl"]//code' "&'s (dyn ToString + 's)"
+// @has - '//*[@class="rust item-decl"]//code' "&'s (dyn ToString + 's)"
// FIXME(fmease): Hide default lifetime bound, render "&'s dyn ToString"
pub use dyn_trait::Ty3;
// @has user/fn.func0.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func0(_: &dyn Fn())"
+// @has - '//pre[@class="rust item-decl"]' "func0(_: &dyn Fn())"
// FIXME(fmease): Show placeholder-lifetime bound, render "func0(_: &(dyn Fn() + '_))"
pub use dyn_trait::func0;
// @has user/fn.func1.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func1<'func>(_: &(dyn Fn() + 'func))"
+// @has - '//pre[@class="rust item-decl"]' "func1<'func>(_: &(dyn Fn() + 'func))"
pub use dyn_trait::func1;
extern crate impl_trait_aux;
// @has impl_trait/fn.func.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn func<'a>(_x: impl Clone + Into<Vec<u8, Global>> + 'a)"
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where'
+// @has - '//pre[@class="rust item-decl"]' "pub fn func<'a>(_x: impl Clone + Into<Vec<u8, Global>> + 'a)"
+// @!has - '//pre[@class="rust item-decl"]' 'where'
pub use impl_trait_aux::func;
// @has impl_trait/fn.func2.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func2<T>("
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_x: impl Deref<Target = Option<T>> + Iterator<Item = T>,"
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_y: impl Iterator<Item = u8>)"
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where'
+// @has - '//pre[@class="rust item-decl"]' "func2<T>("
+// @has - '//pre[@class="rust item-decl"]' "_x: impl Deref<Target = Option<T>> + Iterator<Item = T>,"
+// @has - '//pre[@class="rust item-decl"]' "_y: impl Iterator<Item = u8>)"
+// @!has - '//pre[@class="rust item-decl"]' 'where'
pub use impl_trait_aux::func2;
// @has impl_trait/fn.func3.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func3("
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_x: impl Iterator<Item = impl Iterator<Item = u8>> + Clone)"
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where'
+// @has - '//pre[@class="rust item-decl"]' "func3("
+// @has - '//pre[@class="rust item-decl"]' "_x: impl Iterator<Item = impl Iterator<Item = u8>> + Clone)"
+// @!has - '//pre[@class="rust item-decl"]' 'where'
pub use impl_trait_aux::func3;
// @has impl_trait/fn.func4.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func4<T>("
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "T: Iterator<Item = impl Clone>,"
+// @has - '//pre[@class="rust item-decl"]' "func4<T>("
+// @has - '//pre[@class="rust item-decl"]' "T: Iterator<Item = impl Clone>,"
pub use impl_trait_aux::func4;
// @has impl_trait/fn.func5.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func5("
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other<T<'r> = ()>,"
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>"
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where'
+// @has - '//pre[@class="rust item-decl"]' "func5("
+// @has - '//pre[@class="rust item-decl"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other<T<'r> = ()>,"
+// @has - '//pre[@class="rust item-decl"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>"
+// @!has - '//pre[@class="rust item-decl"]' 'where'
pub use impl_trait_aux::func5;
// @has impl_trait/fn.async_fn.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn async_fn()"
+// @has - '//pre[@class="rust item-decl"]' "pub async fn async_fn()"
pub use impl_trait_aux::async_fn;
// @has impl_trait/struct.Foo.html
// edition: 2021
// @has usr/trait.U.html
-// @has - '//*[@class="item-decl"]' "pub trait U {"
+// @has - '//*[@class="rust item-decl"]' "pub trait U {"
// @has - '//*[@id="method.modified"]' \
// "fn modified(self) -> Self\
// where \
pub use issue_24183::U;
// @has usr/trait.S.html
-// @has - '//*[@class="item-decl"]' 'pub trait S: Sized {'
+// @has - '//*[@class="rust item-decl"]' 'pub trait S: Sized {'
pub use issue_24183::S;
extern crate macros;
-// @has foo/index.html '//*[@class="item-left unstable deprecated"]/span[@class="stab deprecated"]' \
+// @has foo/index.html '//*[@class="item-left"]/span[@class="stab deprecated"]' \
// Deprecated
-// @has - '//*[@class="item-left unstable deprecated"]/span[@class="stab unstable"]' \
+// @has - '//*[@class="item-left"]/span[@class="stab unstable"]' \
// Experimental
// @has foo/macro.my_macro.html
}
// @has issue_20646/fn.fun.html \
-// '//div[@class="item-decl"]/pre[@class="rust"]' 'where T: Trait<Output = i32>'
+// '//pre[@class="rust item-decl"]' 'where T: Trait<Output = i32>'
pub fn fun<T>(_: T) where T: Trait<Output=i32> {}
pub mod reexport {
// '//*[@id="associatedtype.Output"]' \
// 'type Output'
// @has issue_20646/reexport/fn.fun.html \
- // '//div[@class="item-decl"]/pre[@class="rust"]' 'where T: Trait<Output = i32>'
+ // '//pre[@class="rust item-decl"]' 'where T: Trait<Output = i32>'
pub use issue_20646::{Trait, fun};
}
// @has issue_20727_2/trait.Add.html
pub trait Add<RHS = Self> {
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Add<RHS = Self> {'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output;'
+ // @has - '//pre[@class="rust item-decl"]' 'trait Add<RHS = Self> {'
+ // @has - '//pre[@class="rust item-decl"]' 'type Output;'
type Output;
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn add(self, rhs: RHS) -> Self::Output;'
+ // @has - '//pre[@class="rust item-decl"]' 'fn add(self, rhs: RHS) -> Self::Output;'
fn add(self, rhs: RHS) -> Self::Output;
}
// @has issue_20727_2/reexport/trait.Add.html
pub mod reexport {
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Add<RHS = Self> {'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output;'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn add(self, rhs: RHS) -> Self::Output;'
+ // @has - '//pre[@class="rust item-decl"]' 'trait Add<RHS = Self> {'
+ // @has - '//pre[@class="rust item-decl"]' 'type Output;'
+ // @has - '//pre[@class="rust item-decl"]' 'fn add(self, rhs: RHS) -> Self::Output;'
pub use issue_20727::Add;
}
// @has issue_20727_3/trait.Deref2.html
pub trait Deref2 {
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref2 {'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: Bar;'
+ // @has - '//pre[@class="rust item-decl"]' 'trait Deref2 {'
+ // @has - '//pre[@class="rust item-decl"]' 'type Target: Bar;'
type Target: Bar;
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn deref(&self) -> Self::Target;'
+ // @has - '//pre[@class="rust item-decl"]' 'fn deref(&self) -> Self::Target;'
fn deref(&self) -> Self::Target;
}
// @has issue_20727_3/reexport/trait.Deref2.html
pub mod reexport {
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref2 {'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: Bar;'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn deref(&self) -> Self::Target;'
+ // @has - '//pre[@class="rust item-decl"]' 'trait Deref2 {'
+ // @has - '//pre[@class="rust item-decl"]' 'type Target: Bar;'
+ // @has - '//pre[@class="rust item-decl"]' 'fn deref(&self) -> Self::Target;'
pub use issue_20727::Deref2;
}
// @has issue_20727_4/trait.Index.html
pub trait Index<Idx: ?Sized> {
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Index<Idx: ?Sized> {'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output: ?Sized'
+ // @has - '//pre[@class="rust item-decl"]' 'trait Index<Idx: ?Sized> {'
+ // @has - '//pre[@class="rust item-decl"]' 'type Output: ?Sized'
type Output: ?Sized;
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // @has - '//pre[@class="rust item-decl"]' \
// 'fn index(&self, index: Idx) -> &Self::Output'
fn index(&self, index: Idx) -> &Self::Output;
}
// @has issue_20727_4/trait.IndexMut.html
pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // @has - '//pre[@class="rust item-decl"]' \
// 'trait IndexMut<Idx: ?Sized>: Index<Idx> {'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // @has - '//pre[@class="rust item-decl"]' \
// 'fn index_mut(&mut self, index: Idx) -> &mut Self::Output;'
fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
}
pub mod reexport {
// @has issue_20727_4/reexport/trait.Index.html
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Index<Idx>where Idx: ?Sized,{'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output: ?Sized'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // @has - '//pre[@class="rust item-decl"]' 'trait Index<Idx>where Idx: ?Sized,{'
+ // @has - '//pre[@class="rust item-decl"]' 'type Output: ?Sized'
+ // @has - '//pre[@class="rust item-decl"]' \
// 'fn index(&self, index: Idx) -> &Self::Output'
pub use issue_20727::Index;
// @has issue_20727_4/reexport/trait.IndexMut.html
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // @has - '//pre[@class="rust item-decl"]' \
// 'trait IndexMut<Idx>: Index<Idx>where Idx: ?Sized,{'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // @has - '//pre[@class="rust item-decl"]' \
// 'fn index_mut(&mut self, index: Idx) -> &mut Self::Output;'
pub use issue_20727::IndexMut;
}
// @has issue_20727/trait.Deref.html
pub trait Deref {
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref {'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: ?Sized;'
+ // @has - '//pre[@class="rust item-decl"]' 'trait Deref {'
+ // @has - '//pre[@class="rust item-decl"]' 'type Target: ?Sized;'
type Target: ?Sized;
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // @has - '//pre[@class="rust item-decl"]' \
// "fn deref<'a>(&'a self) -> &'a Self::Target;"
fn deref<'a>(&'a self) -> &'a Self::Target;
}
// @has issue_20727/reexport/trait.Deref.html
pub mod reexport {
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref {'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: ?Sized;'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // @has - '//pre[@class="rust item-decl"]' 'trait Deref {'
+ // @has - '//pre[@class="rust item-decl"]' 'type Target: ?Sized;'
+ // @has - '//pre[@class="rust item-decl"]' \
// "fn deref<'a>(&'a self) -> &'a Self::Target;"
pub use issue_20727::Deref;
}
extern "C" {
// @has issue_22038/fn.foo1.html \
- // '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "C" fn foo1()'
+ // '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn foo1()'
pub fn foo1();
}
extern "system" {
// @has issue_22038/fn.foo2.html \
- // '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "system" fn foo2()'
+ // '//pre[@class="rust item-decl"]' 'pub unsafe extern "system" fn foo2()'
pub fn foo2();
}
// @has issue_22038/fn.bar.html \
-// '//div[@class="item-decl"]/pre[@class="rust"]' 'pub extern "C" fn bar()'
+// '//pre[@class="rust item-decl"]' 'pub extern "C" fn bar()'
pub extern "C" fn bar() {}
// @has issue_22038/fn.baz.html \
-// '//div[@class="item-decl"]/pre[@class="rust"]' 'pub extern "system" fn baz()'
+// '//pre[@class="rust item-decl"]' 'pub extern "system" fn baz()'
pub extern "system" fn baz() {}
#![doc(issue_tracker_base_url = "https://issue_url/")]
#![unstable(feature = "test", issue = "32374")]
-// @matches issue_32374/index.html '//*[@class="item-left unstable deprecated"]/span[@class="stab deprecated"]' \
+// @matches issue_32374/index.html '//*[@class="item-left"]/span[@class="stab deprecated"]' \
// 'Deprecated'
-// @matches issue_32374/index.html '//*[@class="item-left unstable deprecated"]/span[@class="stab unstable"]' \
+// @matches issue_32374/index.html '//*[@class="item-left"]/span[@class="stab unstable"]' \
// 'Experimental'
// @matches issue_32374/index.html '//*[@class="item-right docblock-short"]/text()' 'Docs'
pub struct S;
// @has issue_33302/constant.CST.html \
- // '//div[@class="item-decl"]/pre[@class="rust"]' 'pub const CST: i32'
+ // '//pre[@class="rust item-decl"]' 'pub const CST: i32'
pub const CST: i32 = ($n * $n);
// @has issue_33302/static.ST.html \
- // '//div[@class="item-decl"]/pre[@class="rust"]' 'pub static ST: i32'
+ // '//pre[@class="rust item-decl"]' 'pub static ST: i32'
pub static ST: i32 = ($n * $n);
pub trait T<X> {
fn ignore(_: &X) {}
const C: X;
// @has issue_33302/trait.T.html \
- // '//div[@class="item-decl"]/pre[@class="rust"]' 'const D: i32'
+ // '//pre[@class="rust item-decl"]' 'const D: i32'
// @has - '//*[@id="associatedconstant.D"]' 'const D: i32'
const D: i32 = ($n * $n);
}
extern crate issue_85454;
// @has foo/trait.FromResidual.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
+// @has - '//pre[@class="rust item-decl"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { // Required method fn from_residual(residual: R) -> Self; }'
pub trait FromResidual<R = <Self as Try>::Residual> {
fn from_residual(residual: R) -> Self;
}
pub mod reexport {
// @has foo/reexport/trait.FromResidual.html
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
+ // @has - '//pre[@class="rust item-decl"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { // Required method fn from_residual(residual: R) -> Self; }'
pub use issue_85454::*;
}
extern crate issue_98697_reexport_with_anonymous_lifetime;
-// @has issue_98697/fn.repro.html '//div[@class="item-decl"]/pre[@class="rust"]/code' 'fn repro<F>()where F: Fn(&str)'
-// @!has issue_98697/fn.repro.html '//div[@class="item-decl"]/pre[@class="rust"]/code' 'for<'
+// @has issue_98697/fn.repro.html '//pre[@class="rust item-decl"]/code' 'fn repro<F>()where F: Fn(&str)'
+// @!has issue_98697/fn.repro.html '//pre[@class="rust item-decl"]/code' 'for<'
pub use issue_98697_reexport_with_anonymous_lifetime::repro;
// @has issue_98697/struct.Extra.html '//div[@id="trait-implementations-list"]//h3[@class="code-header"]' 'impl MyTrait<&Extra> for Extra'
#![feature(rustc_attrs)]
// @has 'foo/fn.foo.html'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn foo(x: usize, const Y: usize, z: usize) -> [usize; 3]'
+// @has - '//pre[@class="rust item-decl"]' 'fn foo(x: usize, const Y: usize, z: usize) -> [usize; 3]'
#[rustc_legacy_const_generics(1)]
pub fn foo<const Y: usize>(x: usize, z: usize) -> [usize; 3] {
[x, Y, z]
}
// @has 'foo/fn.bar.html'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn bar(x: usize, const Y: usize, const Z: usize) -> [usize; 3]'
+// @has - '//pre[@class="rust item-decl"]' 'fn bar(x: usize, const Y: usize, const Z: usize) -> [usize; 3]'
#[rustc_legacy_const_generics(1, 2)]
pub fn bar<const Y: usize, const Z: usize>(x: usize) -> [usize; 3] {
[x, Y, z]
#![crate_name = "foo"]
// @has 'foo/type.Resolutions.html'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub type Resolutions<'tcx> = &'tcx u8;"
+// @has - '//pre[@class="rust item-decl"]' "pub type Resolutions<'tcx> = &'tcx u8;"
pub type Resolutions<'tcx> = &'tcx u8;
}
// @has 'foo/struct.Providers.html'
-// @has - '//*[@class="item-decl"]//code' "pub a: for<'tcx> fn(_: TyCtxt<'tcx>, _: u8) -> i8,"
-// @has - '//*[@class="item-decl"]//code' "pub b: for<'tcx> fn(_: TyCtxt<'tcx>, _: u16) -> i16,"
+// @has - '//*[@class="rust item-decl"]//code' "pub a: for<'tcx> fn(_: TyCtxt<'tcx>, _: u8) -> i8,"
+// @has - '//*[@class="rust item-decl"]//code' "pub b: for<'tcx> fn(_: TyCtxt<'tcx>, _: u16) -> i16,"
// @has - '//*[@id="structfield.a"]/code' "a: for<'tcx> fn(_: TyCtxt<'tcx>, _: u8) -> i8"
// @has - '//*[@id="structfield.b"]/code' "b: for<'tcx> fn(_: TyCtxt<'tcx>, _: u16) -> i16"
gen! {
pub fn bar(mut bar: ()) {}
}
-// @count foo/fn.baz.html '//div[@class="item-decl"]/pre[@class="rust"]' 1
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'mut'
+// @count foo/fn.baz.html '//pre[@class="rust item-decl"]' 1
+// @!has - '//pre[@class="rust item-decl"]' 'mut'
pub fn baz(mut foo: Foo) {}
type X = <() as Trait>::X;
}
-// @has 'normalize_assoc_item/fn.f.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f() -> isize'
+// @has 'normalize_assoc_item/fn.f.html' '//pre[@class="rust item-decl"]' 'pub fn f() -> isize'
pub fn f() -> <usize as Trait>::X {
0
}
-// @has 'normalize_assoc_item/fn.f2.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f2() -> fn() -> i32'
+// @has 'normalize_assoc_item/fn.f2.html' '//pre[@class="rust item-decl"]' 'pub fn f2() -> fn() -> i32'
pub fn f2() -> <isize as Trait>::X {
todo!()
}
// These can't be normalized because they depend on a generic parameter.
// However the user can choose whether the text should be displayed as `Inner::X` or `<Inner as Trait>::X`.
-// @has 'normalize_assoc_item/struct.Unknown.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Unknown<Inner: Trait>(pub <Inner as Trait>::X);'
+// @has 'normalize_assoc_item/struct.Unknown.html' '//pre[@class="rust item-decl"]' 'pub struct Unknown<Inner: Trait>(pub <Inner as Trait>::X);'
pub struct Unknown<Inner: Trait>(pub <Inner as Trait>::X);
-// @has 'normalize_assoc_item/struct.Unknown2.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Unknown2<Inner: Trait>(pub Inner::X);'
+// @has 'normalize_assoc_item/struct.Unknown2.html' '//pre[@class="rust item-decl"]' 'pub struct Unknown2<Inner: Trait>(pub Inner::X);'
pub struct Unknown2<Inner: Trait>(pub Inner::X);
trait Lifetimes<'a> {
type Y = &'a isize;
}
-// @has 'normalize_assoc_item/fn.g.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn g() -> &isize"
+// @has 'normalize_assoc_item/fn.g.html' '//pre[@class="rust item-decl"]' "pub fn g() -> &isize"
pub fn g() -> <usize as Lifetimes<'static>>::Y {
&0
}
-// @has 'normalize_assoc_item/constant.A.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub const A: &isize"
+// @has 'normalize_assoc_item/constant.A.html' '//pre[@class="rust item-decl"]' "pub const A: &isize"
pub const A: <usize as Lifetimes<'static>>::Y = &0;
// test cross-crate re-exports
extern crate inner;
-// @has 'normalize_assoc_item/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn foo() -> i32"
+// @has 'normalize_assoc_item/fn.foo.html' '//pre[@class="rust item-decl"]' "pub fn foo() -> i32"
pub use inner::foo;
-// @has 'normalize_assoc_item/fn.h.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn h<T>() -> IntoIter<T, Global>"
+// @has 'normalize_assoc_item/fn.h.html' '//pre[@class="rust item-decl"]' "pub fn h<T>() -> IntoIter<T, Global>"
pub fn h<T>() -> <Vec<T> as IntoIterator>::IntoIter {
vec![].into_iter()
}
#![crate_name = "foo"]
// @has foo/fn.bar.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn bar() -> '
+// @has - '//pre[@class="rust item-decl"]' 'pub fn bar() -> '
/// foo
pub fn bar() -> usize {
2
#![crate_name = "foo"]
// @has foo/fn.f.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f(_: u8)'
+// @has - '//pre[@class="rust item-decl"]' 'pub fn f(_: u8)'
pub fn f(0u8..=255: u8) {}
// @has redirect/index.html
// @has - '//code' 'pub use reexp_stripped::Bar'
// @has - '//code/a' 'Bar'
+// @has - '//a[@href="../reexp_stripped/hidden/struct.Bar.html"]' 'Bar'
// @has reexp_stripped/hidden/struct.Bar.html
-// @has - '//p/a' '../../reexp_stripped/struct.Bar.html'
// @has 'reexp_stripped/struct.Bar.html'
+// @has - '//a[@href="struct.Bar.html"]' 'Bar'
#[doc(no_inline)]
pub use reexp_stripped::Bar;
impl Foo for Bar {}
extern crate reexport_check;
// @!has 'foo/index.html' '//code' 'pub use self::i32;'
-// @has 'foo/index.html' '//div[@class="item-left deprecated"]' 'i32'
// @has 'foo/i32/index.html'
#[allow(deprecated, deprecated_in_future)]
pub use std::i32;
// @has 'foo/index.html' '//div[@class="item-left"]' 'String'
pub use std::string::String;
+// i32 is deprecated, String is not
+// @count 'foo/index.html' '//span[@class="stab deprecated"]' 1
+
// @has 'foo/index.html' '//div[@class="item-right docblock-short"]' 'Docs in original'
// this is a no-op, but shows what happens if there's an attribute that isn't a doc-comment
#[doc(inline)]
extern crate all_item_types;
// @has 'foo/fn.foo_ffn.html'
-// @has - '//*[@class="item-decl"]//code' 'pub unsafe extern "C" fn foo_ffn()'
+// @has - '//*[@class="rust item-decl"]//code' 'pub unsafe extern "C" fn foo_ffn()'
pub use all_item_types::foo_ffn;
extern crate reexports;
-// @has 'foo/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
+// @has 'foo/macro.addr_of.html' '//*[@class="rust item-decl"]' 'pub macro addr_of($place:expr) {'
pub use reexports::addr_of;
// @!has 'foo/macro.addr_of_crate.html'
pub(crate) use reexports::addr_of_crate;
// @!has 'foo/macro.addr_of_local.html'
use reexports::addr_of_local;
-// @has 'foo/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
+// @has 'foo/struct.Foo.html' '//*[@class="rust item-decl"]' 'pub struct Foo;'
pub use reexports::Foo;
// @!has 'foo/struct.FooCrate.html'
pub(crate) use reexports::FooCrate;
// @!has 'foo/struct.FooLocal.html'
use reexports::FooLocal;
-// @has 'foo/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
+// @has 'foo/enum.Bar.html' '//*[@class="rust item-decl"]' 'pub enum Bar {'
pub use reexports::Bar;
// @!has 'foo/enum.BarCrate.html'
pub(crate) use reexports::BarCrate;
// @!has 'foo/enum.BarLocal.html'
use reexports::BarLocal;
-// @has 'foo/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
+// @has 'foo/fn.foo.html' '//pre[@class="rust item-decl"]' 'pub fn foo()'
pub use reexports::foo;
// @!has 'foo/fn.foo_crate.html'
pub(crate) use reexports::foo_crate;
// @!has 'foo/fn.foo_local.html'
use reexports::foo_local;
-// @has 'foo/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
+// @has 'foo/type.Type.html' '//pre[@class="rust item-decl"]' 'pub type Type ='
pub use reexports::Type;
// @!has 'foo/type.TypeCrate.html'
pub(crate) use reexports::TypeCrate;
// @!has 'foo/type.TypeLocal.html'
use reexports::TypeLocal;
-// @has 'foo/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
+// @has 'foo/union.Union.html' '//*[@class="rust item-decl"]' 'pub union Union {'
pub use reexports::Union;
// @!has 'foo/union.UnionCrate.html'
pub(crate) use reexports::UnionCrate;
pub mod outer {
pub mod inner {
- // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
+ // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="rust item-decl"]' 'pub macro addr_of($place:expr) {'
pub use reexports::addr_of;
- // @has 'foo/outer/inner/macro.addr_of_crate.html' '//*[@class="item-decl"]' 'pub(crate) macro addr_of_crate($place:expr) {'
+ // @has 'foo/outer/inner/macro.addr_of_crate.html' '//*[@class="rust item-decl"]' 'pub(crate) macro addr_of_crate($place:expr) {'
pub(crate) use reexports::addr_of_crate;
- // @has 'foo/outer/inner/macro.addr_of_super.html' '//*[@class="item-decl"]' 'pub(in outer) macro addr_of_super($place:expr) {'
+ // @has 'foo/outer/inner/macro.addr_of_super.html' '//*[@class="rust item-decl"]' 'pub(in outer) macro addr_of_super($place:expr) {'
pub(super) use reexports::addr_of_super;
// @!has 'foo/outer/inner/macro.addr_of_self.html'
pub(self) use reexports::addr_of_self;
// @!has 'foo/outer/inner/macro.addr_of_local.html'
use reexports::addr_of_local;
- // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
+ // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="rust item-decl"]' 'pub struct Foo;'
pub use reexports::Foo;
- // @has 'foo/outer/inner/struct.FooCrate.html' '//*[@class="item-decl"]' 'pub(crate) struct FooCrate;'
+ // @has 'foo/outer/inner/struct.FooCrate.html' '//*[@class="rust item-decl"]' 'pub(crate) struct FooCrate;'
pub(crate) use reexports::FooCrate;
- // @has 'foo/outer/inner/struct.FooSuper.html' '//*[@class="item-decl"]' 'pub(in outer) struct FooSuper;'
+ // @has 'foo/outer/inner/struct.FooSuper.html' '//*[@class="rust item-decl"]' 'pub(in outer) struct FooSuper;'
pub(super) use reexports::FooSuper;
// @!has 'foo/outer/inner/struct.FooSelf.html'
pub(self) use reexports::FooSelf;
// @!has 'foo/outer/inner/struct.FooLocal.html'
use reexports::FooLocal;
- // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
+ // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="rust item-decl"]' 'pub enum Bar {'
pub use reexports::Bar;
- // @has 'foo/outer/inner/enum.BarCrate.html' '//*[@class="item-decl"]' 'pub(crate) enum BarCrate {'
+ // @has 'foo/outer/inner/enum.BarCrate.html' '//*[@class="rust item-decl"]' 'pub(crate) enum BarCrate {'
pub(crate) use reexports::BarCrate;
- // @has 'foo/outer/inner/enum.BarSuper.html' '//*[@class="item-decl"]' 'pub(in outer) enum BarSuper {'
+ // @has 'foo/outer/inner/enum.BarSuper.html' '//*[@class="rust item-decl"]' 'pub(in outer) enum BarSuper {'
pub(super) use reexports::BarSuper;
// @!has 'foo/outer/inner/enum.BarSelf.html'
pub(self) use reexports::BarSelf;
// @!has 'foo/outer/inner/enum.BarLocal.html'
use reexports::BarLocal;
- // @has 'foo/outer/inner/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
+ // @has 'foo/outer/inner/fn.foo.html' '//pre[@class="rust item-decl"]' 'pub fn foo()'
pub use reexports::foo;
- // @has 'foo/outer/inner/fn.foo_crate.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(crate) fn foo_crate()'
+ // @has 'foo/outer/inner/fn.foo_crate.html' '//pre[@class="rust item-decl"]' 'pub(crate) fn foo_crate()'
pub(crate) use reexports::foo_crate;
- // @has 'foo/outer/inner/fn.foo_super.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(in outer) fn foo_super()'
+ // @has 'foo/outer/inner/fn.foo_super.html' '//pre[@class="rust item-decl"]' 'pub(in outer) fn foo_super()'
pub(super) use::reexports::foo_super;
// @!has 'foo/outer/inner/fn.foo_self.html'
pub(self) use reexports::foo_self;
// @!has 'foo/outer/inner/fn.foo_local.html'
use reexports::foo_local;
- // @has 'foo/outer/inner/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
+ // @has 'foo/outer/inner/type.Type.html' '//pre[@class="rust item-decl"]' 'pub type Type ='
pub use reexports::Type;
- // @has 'foo/outer/inner/type.TypeCrate.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(crate) type TypeCrate ='
+ // @has 'foo/outer/inner/type.TypeCrate.html' '//pre[@class="rust item-decl"]' 'pub(crate) type TypeCrate ='
pub(crate) use reexports::TypeCrate;
- // @has 'foo/outer/inner/type.TypeSuper.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(in outer) type TypeSuper ='
+ // @has 'foo/outer/inner/type.TypeSuper.html' '//pre[@class="rust item-decl"]' 'pub(in outer) type TypeSuper ='
pub(super) use reexports::TypeSuper;
// @!has 'foo/outer/inner/type.TypeSelf.html'
pub(self) use reexports::TypeSelf;
// @!has 'foo/outer/inner/type.TypeLocal.html'
use reexports::TypeLocal;
- // @has 'foo/outer/inner/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
+ // @has 'foo/outer/inner/union.Union.html' '//*[@class="rust item-decl"]' 'pub union Union {'
pub use reexports::Union;
- // @has 'foo/outer/inner/union.UnionCrate.html' '//*[@class="item-decl"]' 'pub(crate) union UnionCrate {'
+ // @has 'foo/outer/inner/union.UnionCrate.html' '//*[@class="rust item-decl"]' 'pub(crate) union UnionCrate {'
pub(crate) use reexports::UnionCrate;
- // @has 'foo/outer/inner/union.UnionSuper.html' '//*[@class="item-decl"]' 'pub(in outer) union UnionSuper {'
+ // @has 'foo/outer/inner/union.UnionSuper.html' '//*[@class="rust item-decl"]' 'pub(in outer) union UnionSuper {'
pub(super) use reexports::UnionSuper;
// @!has 'foo/outer/inner/union.UnionSelf.html'
pub(self) use reexports::UnionSelf;
extern crate reexports;
-// @has 'foo/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
+// @has 'foo/macro.addr_of.html' '//*[@class="rust item-decl"]' 'pub macro addr_of($place:expr) {'
pub use reexports::addr_of;
// @!has 'foo/macro.addr_of_crate.html'
pub(crate) use reexports::addr_of_crate;
// @!has 'foo/macro.addr_of_local.html'
use reexports::addr_of_local;
-// @has 'foo/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
+// @has 'foo/struct.Foo.html' '//*[@class="rust item-decl"]' 'pub struct Foo;'
pub use reexports::Foo;
// @!has 'foo/struct.FooCrate.html'
pub(crate) use reexports::FooCrate;
// @!has 'foo/struct.FooLocal.html'
use reexports::FooLocal;
-// @has 'foo/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
+// @has 'foo/enum.Bar.html' '//*[@class="rust item-decl"]' 'pub enum Bar {'
pub use reexports::Bar;
// @!has 'foo/enum.BarCrate.html'
pub(crate) use reexports::BarCrate;
// @!has 'foo/enum.BarLocal.html'
use reexports::BarLocal;
-// @has 'foo/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
+// @has 'foo/fn.foo.html' '//pre[@class="rust item-decl"]' 'pub fn foo()'
pub use reexports::foo;
// @!has 'foo/fn.foo_crate.html'
pub(crate) use reexports::foo_crate;
// @!has 'foo/fn.foo_local.html'
use reexports::foo_local;
-// @has 'foo/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
+// @has 'foo/type.Type.html' '//pre[@class="rust item-decl"]' 'pub type Type ='
pub use reexports::Type;
// @!has 'foo/type.TypeCrate.html'
pub(crate) use reexports::TypeCrate;
// @!has 'foo/type.TypeLocal.html'
use reexports::TypeLocal;
-// @has 'foo/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
+// @has 'foo/union.Union.html' '//*[@class="rust item-decl"]' 'pub union Union {'
pub use reexports::Union;
// @!has 'foo/union.UnionCrate.html'
pub(crate) use reexports::UnionCrate;
pub mod outer {
pub mod inner {
- // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
+ // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="rust item-decl"]' 'pub macro addr_of($place:expr) {'
pub use reexports::addr_of;
// @!has 'foo/outer/inner/macro.addr_of_crate.html'
pub(crate) use reexports::addr_of_crate;
// @!has 'foo/outer/inner/macro.addr_of_local.html'
use reexports::addr_of_local;
- // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
+ // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="rust item-decl"]' 'pub struct Foo;'
pub use reexports::Foo;
// @!has 'foo/outer/inner/struct.FooCrate.html'
pub(crate) use reexports::FooCrate;
// @!has 'foo/outer/inner/struct.FooLocal.html'
use reexports::FooLocal;
- // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
+ // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="rust item-decl"]' 'pub enum Bar {'
pub use reexports::Bar;
// @!has 'foo/outer/inner/enum.BarCrate.html'
pub(crate) use reexports::BarCrate;
// @!has 'foo/outer/inner/enum.BarLocal.html'
use reexports::BarLocal;
- // @has 'foo/outer/inner/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
+ // @has 'foo/outer/inner/fn.foo.html' '//pre[@class="rust item-decl"]' 'pub fn foo()'
pub use reexports::foo;
// @!has 'foo/outer/inner/fn.foo_crate.html'
pub(crate) use reexports::foo_crate;
// @!has 'foo/outer/inner/fn.foo_local.html'
use reexports::foo_local;
- // @has 'foo/outer/inner/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
+ // @has 'foo/outer/inner/type.Type.html' '//pre[@class="rust item-decl"]' 'pub type Type ='
pub use reexports::Type;
// @!has 'foo/outer/inner/type.TypeCrate.html'
pub(crate) use reexports::TypeCrate;
// @!has 'foo/outer/inner/type.TypeLocal.html'
use reexports::TypeLocal;
- // @has 'foo/outer/inner/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
+ // @has 'foo/outer/inner/union.Union.html' '//*[@class="rust item-decl"]' 'pub union Union {'
pub use reexports::Union;
// @!has 'foo/outer/inner/union.UnionCrate.html'
pub(crate) use reexports::UnionCrate;
pub struct S<T>(T);
-// @!has foo/trait.Tr.html '//div[@class="item-decl"]/pre[@class="rust"]/code/a[@class="trait"]' '~const'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]/code/a[@class="trait"]' 'Clone'
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]/code/span[@class="where"]' '~const'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]/code/span[@class="where"]' ': Clone'
+// @!has foo/trait.Tr.html '//pre[@class="rust item-decl"]/code/a[@class="trait"]' '~const'
+// @has - '//pre[@class="rust item-decl"]/code/a[@class="trait"]' 'Clone'
+// @!has - '//pre[@class="rust item-decl"]/code/span[@class="where"]' '~const'
+// @has - '//pre[@class="rust item-decl"]/code/span[@class="where"]' ': Clone'
#[const_trait]
pub trait Tr<T> {
// @!has - '//section[@id="method.a"]/h4[@class="code-header"]' '~const'
}
}
-// @!has foo/fn.foo.html '//div[@class="item-decl"]/pre[@class="rust"]/code/a[@class="trait"]' '~const'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]/code/a[@class="trait"]' 'Clone'
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]/code/span[@class="where fmt-newline"]' '~const'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]/code/span[@class="where fmt-newline"]' ': Clone'
+// @!has foo/fn.foo.html '//pre[@class="rust item-decl"]/code/a[@class="trait"]' '~const'
+// @has - '//pre[@class="rust item-decl"]/code/a[@class="trait"]' 'Clone'
+// @!has - '//pre[@class="rust item-decl"]/code/span[@class="where fmt-newline"]' '~const'
+// @has - '//pre[@class="rust item-decl"]/code/span[@class="where fmt-newline"]' ': Clone'
pub const fn foo<F: ~const Clone + ~const Destruct>()
where
Option<F>: ~const Clone + ~const Destruct,
extern "rust-intrinsic" {
// @has 'foo/fn.abort.html'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub extern "rust-intrinsic" fn abort() -> !'
+ // @has - '//pre[@class="rust item-decl"]' 'pub extern "rust-intrinsic" fn abort() -> !'
#[rustc_safe_intrinsic]
pub fn abort() -> !;
// @has 'foo/fn.unreachable.html'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
+ // @has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
pub fn unreachable() -> !;
}
extern "C" {
// @has 'foo/fn.needs_drop.html'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "C" fn needs_drop() -> !'
+ // @has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn needs_drop() -> !'
pub fn needs_drop() -> !;
}
pub struct MyBox<T: ?Sized>(*const T);
// @has 'foo/fn.alpha.html'
-// @snapshot link_slice_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_slice_u32 - '//pre[@class="rust item-decl"]/code'
pub fn alpha() -> &'static [u32] {
loop {}
}
// @has 'foo/fn.beta.html'
-// @snapshot link_slice_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_slice_generic - '//pre[@class="rust item-decl"]/code'
pub fn beta<T>() -> &'static [T] {
loop {}
}
// @has 'foo/fn.gamma.html'
-// @snapshot link_box_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_box_u32 - '//pre[@class="rust item-decl"]/code'
pub fn gamma() -> MyBox<[u32]> {
loop {}
}
// @has 'foo/fn.delta.html'
-// @snapshot link_box_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_box_generic - '//pre[@class="rust item-decl"]/code'
pub fn delta<T>() -> MyBox<[T]> {
loop {}
}
hir_id: usize,
}
-// @has 'foo/fn.body_owner.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn body_owner(_: BodyId)'
+// @has 'foo/fn.body_owner.html' '//pre[@class="rust item-decl"]' 'pub fn body_owner(_: BodyId)'
pub fn body_owner(BodyId { hir_id }: BodyId) {
// ...
}
#![crate_name = "foo"]
// @has foo/fn.foo.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_: &(dyn ToString + 'static)"
+// @has - '//pre[@class="rust item-decl"]' "_: &(dyn ToString + 'static)"
pub fn foo(_: &(ToString + 'static)) {}
// @has 'toggle_item_contents/struct.PrivStruct.html'
// @count - '//details[@class="toggle type-contents-toggle"]' 0
-// @has - '//div[@class="item-decl"]' '/* private fields */'
+// @has - '//pre[@class="rust item-decl"]' '/* private fields */'
pub struct PrivStruct {
a: usize,
b: usize,
}
// @has 'toggle_item_contents/enum.LargeEnum.html'
-// @count - '//div[@class="item-decl"]/pre//details[@class="toggle type-contents-toggle"]' 1
-// @has - '//div[@class="item-decl"]/pre//details[@class="toggle type-contents-toggle"]' 'Show 13 variants'
+// @count - '//pre[@class="rust item-decl"]//details[@class="toggle type-contents-toggle"]' 1
+// @has - '//pre[@class="rust item-decl"]//details[@class="toggle type-contents-toggle"]' 'Show 13 variants'
pub enum LargeEnum {
A, B, C, D, E, F(u8), G, H, I, J, K, L, M
}
// @has foo/index.html '//a[@class="traitalias"]' 'Foo'
// @has foo/traitalias.CopyAlias.html
-// @has - '//section[@id="main-content"]/div[@class="item-decl"]/pre' 'trait CopyAlias = Copy;'
+// @has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait CopyAlias = Copy;'
pub trait CopyAlias = Copy;
// @has foo/traitalias.Alias2.html
-// @has - '//section[@id="main-content"]/div[@class="item-decl"]/pre' 'trait Alias2 = Copy + Debug;'
+// @has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait Alias2 = Copy + Debug;'
pub trait Alias2 = Copy + Debug;
// @has foo/traitalias.Foo.html
-// @has - '//section[@id="main-content"]/div[@class="item-decl"]/pre' 'trait Foo<T> = Into<T> + Debug;'
+// @has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait Foo<T> = Into<T> + Debug;'
pub trait Foo<T> = Into<T> + Debug;
// @has foo/fn.bar.html '//a[@href="traitalias.Alias2.html"]' 'Alias2'
pub fn bar<T>() where T: Alias2 {}
);
// @has foo/enum.Bar.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'BarVariant(String),'
+// @has - '//pre[@class="rust item-decl"]' 'BarVariant(String),'
// @matches - '//*[@id="variant.BarVariant.fields"]/h4' '^Tuple Fields$'
// @has - '//*[@id="variant.BarVariant.field.0"]' '0: String'
// @has - '//*[@id="variant.BarVariant.fields"]//*[@class="docblock"]' 'Hello docs'
#![crate_name = "foo"]
// @has foo/fn.tuple0.html //pre 'pub fn tuple0(x: ())'
-// @snapshot link_unit - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_unit - '//pre[@class="rust item-decl"]/code'
pub fn tuple0(x: ()) -> () { x }
// @has foo/fn.tuple1.html //pre 'pub fn tuple1(x: (i32,)) -> (i32,)'
-// @snapshot link1_i32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link1_i32 - '//pre[@class="rust item-decl"]/code'
pub fn tuple1(x: (i32,)) -> (i32,) { x }
// @has foo/fn.tuple2.html //pre 'pub fn tuple2(x: (i32, i32)) -> (i32, i32)'
-// @snapshot link2_i32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link2_i32 - '//pre[@class="rust item-decl"]/code'
pub fn tuple2(x: (i32, i32)) -> (i32, i32) { x }
// @has foo/fn.tuple1_t.html //pre 'pub fn tuple1_t<T>(x: (T,)) -> (T,)'
-// @snapshot link1_t - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link1_t - '//pre[@class="rust item-decl"]/code'
pub fn tuple1_t<T>(x: (T,)) -> (T,) { x }
// @has foo/fn.tuple2_t.html //pre 'pub fn tuple2_t<T>(x: (T, T)) -> (T, T)'
-// @snapshot link2_t - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link2_t - '//pre[@class="rust item-decl"]/code'
pub fn tuple2_t<T>(x: (T, T)) -> (T, T) { x }
// @has foo/fn.tuple2_tu.html //pre 'pub fn tuple2_tu<T, U>(x: (T, U)) -> (T, U)'
-// @snapshot link2_tu - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link2_tu - '//pre[@class="rust item-decl"]/code'
pub fn tuple2_tu<T, U>(x: (T, U)) -> (T, U) { x }
extern crate unit_return;
-// @has 'foo/fn.f0.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u8) + Clone'
+// @has 'foo/fn.f0.html' '//pre[@class="rust item-decl"]' 'F: FnMut(u8) + Clone'
pub fn f0<F: FnMut(u8) + Clone>(f: F) {}
-// @has 'foo/fn.f1.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u16) + Clone'
+// @has 'foo/fn.f1.html' '//pre[@class="rust item-decl"]' 'F: FnMut(u16) + Clone'
pub fn f1<F: FnMut(u16) -> () + Clone>(f: F) {}
-// @has 'foo/fn.f2.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u32) + Clone'
+// @has 'foo/fn.f2.html' '//pre[@class="rust item-decl"]' 'F: FnMut(u32) + Clone'
pub use unit_return::f2;
-// @has 'foo/fn.f3.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u64) + Clone'
+// @has 'foo/fn.f3.html' '//pre[@class="rust item-decl"]' 'F: FnMut(u64) + Clone'
pub use unit_return::f3;
#![crate_name = "foo"]
// @has foo/fn.foo.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo<X, Y: ?Sized>(_: &X)'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where X: ?Sized,'
+// @has - '//pre[@class="rust item-decl"]' 'pub fn foo<X, Y: ?Sized>(_: &X)'
+// @has - '//pre[@class="rust item-decl"]' 'where X: ?Sized,'
pub fn foo<X, Y: ?Sized>(_: &X) where X: ?Sized {}
-<div class="item-decl"><pre class="rust"><code>pub struct Simd<T>(_)<br /><span class="where">where<br />    T: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code></pre></div>
\ No newline at end of file
+<pre class="rust item-decl"><code>pub struct Simd<T>(_)<br /><span class="where">where<br />    T: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code></pre>
\ No newline at end of file
-<div class="item-decl"><pre class="rust"><code>pub trait TraitWhere {
- type <a href="#associatedtype.Item" class="associatedtype">Item</a><'a><br />    <span class="where">where<br />        Self: 'a</span>;
+<pre class="rust item-decl"><code>pub trait TraitWhere {
+ type <a href="#associatedtype.Item" class="associatedtype">Item</a><'a><br />       <span class="where">where Self: 'a</span>;
- fn <a href="#method.func" class="fn">func</a>(self)<br />    <span class="where">where<br />        Self: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a></span>,
- { ... }
-<span class="item-spacer" /> fn <a href="#method.lines" class="fn">lines</a>(self) -> <a class="struct" href="{{channel}}/std/io/struct.Lines.html" title="struct std::io::Lines">Lines</a><Self><br />    <span class="where">where<br />        Self: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a></span>,
- { ... }
-}</code></pre></div>
\ No newline at end of file
+ // Provided methods
+ fn <a href="#method.func" class="fn">func</a>(self)<br />       <span class="where">where Self: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a></span> { ... }
+<span class="item-spacer" /> fn <a href="#method.lines" class="fn">lines</a>(self) -> <a class="struct" href="{{channel}}/std/io/struct.Lines.html" title="struct std::io::Lines">Lines</a><Self><br />       <span class="where">where Self: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a></span> { ... }
+<span class="item-spacer" /> fn <a href="#method.merge" class="fn">merge</a><T>(self, a: T)<br />       <span class="where">where Self: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a>,<br />             T: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a></span> { ... }
+}</code></pre>
\ No newline at end of file
pub struct Echo<E>(E);
// @has 'foo/struct.Simd.html'
-// @snapshot SWhere_Simd_item-decl - '//div[@class="item-decl"]'
+// @snapshot SWhere_Simd_item-decl - '//pre[@class="rust item-decl"]'
pub struct Simd<T>([T; 1])
where
T: MyTrait;
// @has 'foo/trait.TraitWhere.html'
-// @snapshot SWhere_TraitWhere_item-decl - '//div[@class="item-decl"]'
+// @snapshot SWhere_TraitWhere_item-decl - '//pre[@class="rust item-decl"]'
pub trait TraitWhere {
type Item<'a> where Self: 'a;
where
Self: Sized,
{ todo!() }
+
+ fn merge<T>(self, a: T)
+ where
+ Self: Sized,
+ T: Sized,
+ { todo!() }
}
// @has foo/struct.Echo.html '//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<F> MyTrait for Foxtrot<F>where F: MyTrait"
impl<F> MyTrait for Foxtrot<F>where F: MyTrait {}
-// @has foo/type.Golf.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/type.Golf.html '//pre[@class="rust item-decl"]' \
// "type Golf<T>where T: Clone, = (T, T)"
pub type Golf<T> where T: Clone = (T, T);
-<div class="item-decl"><pre class="rust"><code>pub enum Cow<'a, B><span class="where fmt-newline">where<br />    B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
+<pre class="rust item-decl"><code>pub enum Cow<'a, B><span class="where fmt-newline">where<br />    B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&'a B</a>),
Whatever(<a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>),
-}</code></pre></div>
\ No newline at end of file
+}</code></pre>
\ No newline at end of file
-<div class="item-decl"><pre class="rust"><code>pub enum Cow2<'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + 'a> {
+<pre class="rust item-decl"><code>pub enum Cow2<'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + 'a> {
Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&'a B</a>),
Whatever(<a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>),
-}</code></pre></div>
\ No newline at end of file
+}</code></pre>
\ No newline at end of file
#![crate_name = "foo"]
// @has 'foo/trait.ToOwned.html'
-// @snapshot trait - '//*[@class="item-decl"]'
+// @snapshot trait - '//*[@class="rust item-decl"]'
pub trait ToOwned<T>
where T: Clone
{
}
// @has 'foo/trait.ToOwned2.html'
-// @snapshot trait2 - '//*[@class="item-decl"]'
+// @snapshot trait2 - '//*[@class="rust item-decl"]'
// There should be a whitespace before `{` in this case!
pub trait ToOwned2<T: Clone> {
type Owned;
}
// @has 'foo/enum.Cow.html'
-// @snapshot enum - '//*[@class="item-decl"]'
+// @snapshot enum - '//*[@class="rust item-decl"]'
pub enum Cow<'a, B: ?Sized + 'a>
where
B: ToOwned<Clone>,
}
// @has 'foo/enum.Cow2.html'
-// @snapshot enum2 - '//*[@class="item-decl"]'
+// @snapshot enum2 - '//*[@class="rust item-decl"]'
// There should be a whitespace before `{` in this case!
pub enum Cow2<'a, B: ?Sized + ToOwned<Clone> + 'a> {
Borrowed(&'a B),
}
// @has 'foo/struct.Struct.html'
-// @snapshot struct - '//*[@class="item-decl"]'
+// @snapshot struct - '//*[@class="rust item-decl"]'
pub struct Struct<'a, B: ?Sized + 'a>
where
B: ToOwned<Clone>,
}
// @has 'foo/struct.Struct2.html'
-// @snapshot struct2 - '//*[@class="item-decl"]'
+// @snapshot struct2 - '//*[@class="rust item-decl"]'
// There should be a whitespace before `{` in this case!
pub struct Struct2<'a, B: ?Sized + ToOwned<Clone> + 'a> {
pub a: &'a B,
}
// @has 'foo/union.Union.html'
-// @snapshot union - '//*[@class="item-decl"]'
+// @snapshot union - '//*[@class="rust item-decl"]'
pub union Union<'a, B: ?Sized + 'a>
where
B: ToOwned<Clone>,
}
// @has 'foo/union.Union2.html'
-// @snapshot union2 - '//*[@class="item-decl"]'
+// @snapshot union2 - '//*[@class="rust item-decl"]'
// There should be a whitespace before `{` in this case!
pub union Union2<'a, B: ?Sized + ToOwned<Clone> + 'a> {
a: &'a B,
-<div class="item-decl"><pre class="rust"><code>pub struct Struct<'a, B><span class="where fmt-newline">where<br />    B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
+<pre class="rust item-decl"><code>pub struct Struct<'a, B><span class="where fmt-newline">where<br />    B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&'a B</a>,
pub b: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>,
-}</code></pre></div>
\ No newline at end of file
+}</code></pre>
\ No newline at end of file
-<div class="item-decl"><pre class="rust"><code>pub struct Struct2<'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + 'a> {
+<pre class="rust item-decl"><code>pub struct Struct2<'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + 'a> {
pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&'a B</a>,
pub b: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>,
-}</code></pre></div>
\ No newline at end of file
+}</code></pre>
\ No newline at end of file
-<div class="item-decl"><pre class="rust"><code>pub trait ToOwned<T><span class="where fmt-newline">where<br />    T: <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>,</span>{
+<pre class="rust item-decl"><code>pub trait ToOwned<T><span class="where fmt-newline">where<br />    T: <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>,</span>{
type <a href="#associatedtype.Owned" class="associatedtype">Owned</a>;
+ // Required methods
fn <a href="#tymethod.to_owned" class="fn">to_owned</a>(&self) -> Self::<a class="associatedtype" href="trait.ToOwned.html#associatedtype.Owned" title="type foo::ToOwned::Owned">Owned</a>;
<span class="item-spacer" /> fn <a href="#tymethod.whatever" class="fn">whatever</a>(&self) -> T;
-}</code></pre></div>
\ No newline at end of file
+}</code></pre>
\ No newline at end of file
-<div class="item-decl"><pre class="rust"><code>pub trait ToOwned2<T: <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> {
+<pre class="rust item-decl"><code>pub trait ToOwned2<T: <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> {
type <a href="#associatedtype.Owned" class="associatedtype">Owned</a>;
+ // Required methods
fn <a href="#tymethod.to_owned" class="fn">to_owned</a>(&self) -> Self::<a class="associatedtype" href="trait.ToOwned2.html#associatedtype.Owned" title="type foo::ToOwned2::Owned">Owned</a>;
<span class="item-spacer" /> fn <a href="#tymethod.whatever" class="fn">whatever</a>(&self) -> T;
-}</code></pre></div>
\ No newline at end of file
+}</code></pre>
\ No newline at end of file
-<div class="item-decl"><pre class="rust"><code>pub union Union<'a, B><span class="where fmt-newline">where<br />    B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
+<pre class="rust item-decl"><code>pub union Union<'a, B><span class="where fmt-newline">where<br />    B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
/* private fields */
-}</code></pre></div>
\ No newline at end of file
+}</code></pre>
\ No newline at end of file
-<div class="item-decl"><pre class="rust"><code>pub union Union2<'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + 'a> {
+<pre class="rust item-decl"><code>pub union Union2<'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + 'a> {
/* private fields */
-}</code></pre></div>
\ No newline at end of file
+}</code></pre>
\ No newline at end of file
use std::fmt::Debug;
-// @has 'wrapping/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo() -> impl Debug'
-// @count - '//div[@class="item-decl"]/pre[@class="rust"]/br' 0
+// @has 'wrapping/fn.foo.html' '//pre[@class="rust item-decl"]' 'pub fn foo() -> impl Debug'
+// @count - '//pre[@class="rust item-decl"]/br' 0
pub fn foo() -> impl Debug {}
#[suggestion(code = "", style = "hidden")]
sub: Span,
}
+
+#[derive(Diagnostic)]
+#[diag(compiletest_example)]
+struct SuggestionOnVec {
+ #[suggestion(suggestion, code = "")]
+ //~^ ERROR `#[suggestion(...)]` is not a valid attribute
+ sub: Vec<Span>,
+}
LL | #[suggestion(code = 3)]
| ^^^^^^^^
+error: `#[suggestion(...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:806:5
+ |
+LL | #[suggestion(suggestion, code = "")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[suggestion(...)]` applied to `Vec` field is ambiguous
+ = help: to show a suggestion consisting of multiple parts, use a `Subdiagnostic` annotated with `#[multipart_suggestion(...)]`
+ = help: to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]`
+
error: cannot find attribute `nonsense` in this scope
--> $DIR/diagnostic-derive.rs:55:3
|
--> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC
= note: this error originates in the derive macro `Diagnostic` which comes from the expansion of the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: aborting due to 83 previous errors
+error: aborting due to 84 previous errors
Some errors have detailed explanations: E0277, E0425.
For more information about an error, try `rustc --explain E0277`.
#[primary_span]
sub: Span,
}
+
+#[derive(Subdiagnostic)]
+#[suggestion(parse_add_paren, code = "")]
+//~^ ERROR suggestion without `#[primary_span]` field
+struct PrimarySpanOnVec {
+ #[primary_span]
+ //~^ ERROR `#[primary_span]` is not a valid attribute
+ //~| NOTE there must be exactly one primary span
+ sub: Vec<Span>,
+}
LL | #[suggestion(parse_add_paren, code = "", style("foo"))]
| ^^^^^^^^^^^^
+error: `#[primary_span]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:806:5
+ |
+LL | #[primary_span]
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: there must be exactly one primary span
+ = help: to create a suggestion with multiple spans, use `#[multipart_suggestion]` instead
+
+error: suggestion without `#[primary_span]` field
+ --> $DIR/subdiagnostic-derive.rs:803:1
+ |
+LL | / #[suggestion(parse_add_paren, code = "")]
+LL | |
+LL | | struct PrimarySpanOnVec {
+LL | | #[primary_span]
+... |
+LL | | sub: Vec<Span>,
+LL | | }
+ | |_^
+
error: cannot find attribute `foo` in this scope
--> $DIR/subdiagnostic-derive.rs:63:3
|
LL | #[label(slug)]
| ^^^^ not found in `rustc_errors::fluent`
-error: aborting due to 79 previous errors
+error: aborting due to 81 previous errors
For more information about this error, try `rustc --explain E0425`.
LL | | {
LL | | loop {}
LL | | }
- | |__^ expected `&Layout`, found struct `Layout`
+ | |__^ expected `&Layout`, found `Layout`
|
note: function defined here
--> $DIR/alloc-error-handler-bad-signature-1.rs:10:4
| ||_- arguments to this function are incorrect
LL | | loop {}
LL | | }
- | |__^ expected struct `Layout`, found struct `core::alloc::Layout`
+ | |__^ expected `Layout`, found `core::alloc::Layout`
|
- = note: struct `core::alloc::Layout` and struct `Layout` have similar names, but are actually distinct types
-note: struct `core::alloc::Layout` is defined in crate `core`
+ = note: `core::alloc::Layout` and `Layout` have similar names, but are actually distinct types
+note: `core::alloc::Layout` is defined in crate `core`
--> $SRC_DIR/core/src/alloc/layout.rs:LL:COL
-note: struct `Layout` is defined in the current crate
+note: `Layout` is defined in the current crate
--> $DIR/alloc-error-handler-bad-signature-2.rs:7:1
|
LL | struct Layout;
--> $DIR/formal-and-expected-differ.rs:22:29
|
LL | let _: U<_, u32> = U(1, S(3u32));
- | - ^^^^^^^ expected `f32`, found `u32`
+ | - ^^^^^^^ expected `S<f32>`, found `S<u32>`
| |
| arguments to this struct are incorrect
|
--> $DIR/formal-and-expected-differ.rs:22:24
|
LL | let _: U<_, u32> = U(1, S(3u32));
- | --------- ^^^^^^^^^^^^^ expected `u32`, found `f32`
+ | --------- ^^^^^^^^^^^^^ expected `U<_, u32>`, found `U<i32, f32>`
| |
| expected due to this
|
--> $DIR/invalid_arguments.rs:24:18
|
LL | three_arg_diff(X{}, 1.0, "");
- | -------------- ^^^ expected `i32`, found struct `X`
+ | -------------- ^^^ expected `i32`, found `X`
| |
| arguments to this function are incorrect
|
--> $DIR/invalid_arguments.rs:25:21
|
LL | three_arg_diff(1, X {}, "");
- | -------------- ^^^^ expected `f32`, found struct `X`
+ | -------------- ^^^^ expected `f32`, found `X`
| |
| arguments to this function are incorrect
|
--> $DIR/invalid_arguments.rs:26:26
|
LL | three_arg_diff(1, 1.0, X {});
- | -------------- ^^^^ expected `&str`, found struct `X`
+ | -------------- ^^^^ expected `&str`, found `X`
| |
| arguments to this function are incorrect
|
--> $DIR/invalid_arguments.rs:28:3
|
LL | three_arg_diff(X {}, X {}, "");
- | ^^^^^^^^^^^^^^ ---- ---- expected `f32`, found struct `X`
+ | ^^^^^^^^^^^^^^ ---- ---- expected `f32`, found `X`
| |
- | expected `i32`, found struct `X`
+ | expected `i32`, found `X`
|
note: function defined here
--> $DIR/invalid_arguments.rs:8:4
--> $DIR/invalid_arguments.rs:29:3
|
LL | three_arg_diff(X {}, 1.0, X {});
- | ^^^^^^^^^^^^^^ ---- ---- expected `&str`, found struct `X`
+ | ^^^^^^^^^^^^^^ ---- ---- expected `&str`, found `X`
| |
- | expected `i32`, found struct `X`
+ | expected `i32`, found `X`
|
note: function defined here
--> $DIR/invalid_arguments.rs:8:4
--> $DIR/invalid_arguments.rs:30:3
|
LL | three_arg_diff(1, X {}, X {});
- | ^^^^^^^^^^^^^^ ---- ---- expected `&str`, found struct `X`
+ | ^^^^^^^^^^^^^^ ---- ---- expected `&str`, found `X`
| |
- | expected `f32`, found struct `X`
+ | expected `f32`, found `X`
|
note: function defined here
--> $DIR/invalid_arguments.rs:8:4
--> $DIR/invalid_arguments.rs:32:3
|
LL | three_arg_diff(X {}, X {}, X {});
- | ^^^^^^^^^^^^^^ ---- ---- ---- expected `&str`, found struct `X`
+ | ^^^^^^^^^^^^^^ ---- ---- ---- expected `&str`, found `X`
| | |
- | | expected `f32`, found struct `X`
- | expected `i32`, found struct `X`
+ | | expected `f32`, found `X`
+ | expected `i32`, found `X`
|
note: function defined here
--> $DIR/invalid_arguments.rs:8:4
--> $DIR/invalid_arguments.rs:34:20
|
LL | three_arg_repeat(X {}, 1, "");
- | ---------------- ^^^^ expected `i32`, found struct `X`
+ | ---------------- ^^^^ expected `i32`, found `X`
| |
| arguments to this function are incorrect
|
--> $DIR/invalid_arguments.rs:35:23
|
LL | three_arg_repeat(1, X {}, "");
- | ---------------- ^^^^ expected `i32`, found struct `X`
+ | ---------------- ^^^^ expected `i32`, found `X`
| |
| arguments to this function are incorrect
|
--> $DIR/invalid_arguments.rs:36:26
|
LL | three_arg_repeat(1, 1, X {});
- | ---------------- ^^^^ expected `&str`, found struct `X`
+ | ---------------- ^^^^ expected `&str`, found `X`
| |
| arguments to this function are incorrect
|
--> $DIR/invalid_arguments.rs:38:3
|
LL | three_arg_repeat(X {}, X {}, "");
- | ^^^^^^^^^^^^^^^^ ---- ---- expected `i32`, found struct `X`
+ | ^^^^^^^^^^^^^^^^ ---- ---- expected `i32`, found `X`
| |
- | expected `i32`, found struct `X`
+ | expected `i32`, found `X`
|
note: function defined here
--> $DIR/invalid_arguments.rs:9:4
--> $DIR/invalid_arguments.rs:39:3
|
LL | three_arg_repeat(X {}, 1, X {});
- | ^^^^^^^^^^^^^^^^ ---- ---- expected `&str`, found struct `X`
+ | ^^^^^^^^^^^^^^^^ ---- ---- expected `&str`, found `X`
| |
- | expected `i32`, found struct `X`
+ | expected `i32`, found `X`
|
note: function defined here
--> $DIR/invalid_arguments.rs:9:4
--> $DIR/invalid_arguments.rs:40:3
|
LL | three_arg_repeat(1, X {}, X{});
- | ^^^^^^^^^^^^^^^^ ---- --- expected `&str`, found struct `X`
+ | ^^^^^^^^^^^^^^^^ ---- --- expected `&str`, found `X`
| |
- | expected `i32`, found struct `X`
+ | expected `i32`, found `X`
|
note: function defined here
--> $DIR/invalid_arguments.rs:9:4
--> $DIR/invalid_arguments.rs:42:3
|
LL | three_arg_repeat(X {}, X {}, X {});
- | ^^^^^^^^^^^^^^^^ ---- ---- ---- expected `&str`, found struct `X`
+ | ^^^^^^^^^^^^^^^^ ---- ---- ---- expected `&str`, found `X`
| | |
- | | expected `i32`, found struct `X`
- | expected `i32`, found struct `X`
+ | | expected `i32`, found `X`
+ | expected `i32`, found `X`
|
note: function defined here
--> $DIR/invalid_arguments.rs:9:4
--> $DIR/issue-100478.rs:36:5
|
LL | four_shuffle(T3::default(), T2::default(), T1::default(), T3::default());
- | ^^^^^^^^^^^^ ------------- ------------- ------------- expected struct `T4`, found struct `T3`
+ | ^^^^^^^^^^^^ ------------- ------------- ------------- expected `T4`, found `T3`
| | |
| | expected `T3`, found `T1`
| expected `T1`, found `T3`
| ^ - - - - - expected `C`, found `A`
| | | | |
| | | | expected `C`, found `A`
- | | | expected struct `B`, found struct `A`
+ | | | expected `B`, found `A`
| | expected `A`, found `C`
| expected `A`, found `C`
|
LL | foo(&&A, B, C, D, E, F, G);
| ^^^ - - - - argument of type `F` unexpected
| | | |
- | | | expected `&E`, found struct `E`
+ | | | expected `&E`, found `E`
| | argument of type `C` unexpected
| argument of type `B` unexpected
|
LL | three_args(1, X {});
| ^^^^^^^^^^---------
| | |
- | | expected `f32`, found struct `X`
+ | | expected `f32`, found `X`
| an argument of type `&str` is missing
|
note: function defined here
LL | three_args("", X {}, 1);
| ^^^^^^^^^^ -- ---- - expected `&str`, found `{integer}`
| | |
- | | expected `f32`, found struct `X`
+ | | expected `f32`, found `X`
| expected `i32`, found `&'static str`
|
note: function defined here
LL | foo(f, w);
| ^^^
|
-note: expected `i32`, found `u32`
+note: expected fn pointer, found fn item
--> $DIR/two-mismatch-notes.rs:10:9
|
LL | foo(f, w);
| ^
= note: expected fn pointer `fn(i32)`
found fn item `fn(u32) {f}`
-note: expected `i32`, found `isize`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
+note: expected `Wrapper<i32>`, found `Wrapper<isize>`
--> $DIR/two-mismatch-notes.rs:10:12
|
LL | foo(f, w);
fn main() {
let _x: i32 = [1, 2, 3];
//~^ ERROR mismatched types
- //~| expected `i32`, found array
+ //~| expected `i32`, found `[{integer}; 3]`
let x: &[i32] = &[1, 2, 3];
let _y: &i32 = x;
//~^ ERROR mismatched types
//~| expected reference `&i32`
//~| found reference `&[i32]`
- //~| expected `i32`, found slice
+ //~| expected `&i32`, found `&[i32]`
}
--> $DIR/array-not-vector.rs:2:19
|
LL | let _x: i32 = [1, 2, 3];
- | --- ^^^^^^^^^ expected `i32`, found array `[{integer}; 3]`
+ | --- ^^^^^^^^^ expected `i32`, found `[{integer}; 3]`
| |
| expected due to this
--> $DIR/array-not-vector.rs:7:20
|
LL | let _y: &i32 = x;
- | ---- ^ expected `i32`, found slice `[i32]`
+ | ---- ^ expected `&i32`, found `&[i32]`
| |
| expected due to this
|
--> $DIR/slice-to-vec-comparison.rs:4:9
|
LL | a > b;
- | ^ expected array of 0 elements, found struct `Vec`
+ | ^ expected `&[_; 0]`, found `&Vec<u8>`
|
= note: expected reference `&[_; 0]`
found reference `&Vec<u8>`
--> $DIR/associated-const-generic-obligations.rs:14:17
|
LL | const FROM: &'static str = "foo";
- | ^^^^^^^^^^^^ expected associated type, found `&str`
+ | ^^^^^^^^^^^^ expected associated type, found `&'static str`
|
note: type in trait
--> $DIR/associated-const-generic-obligations.rs:10:17
--> $DIR/elision.rs:5:79
|
LL | fn f(x: &mut dyn Iterator<Item: Iterator<Item = &'_ ()>>) -> Option<&'_ ()> { x.next() }
- | ----------------------------- -------------- ^^^^^^^^ expected `&()`, found type parameter `impl Iterator<Item = &'_ ()>`
+ | ----------------------------- -------------- ^^^^^^^^ expected `Option<&()>`, found `Option<impl Iterator<Item = &'_ ()>>`
| | |
| | expected `Option<&'static ()>` because of return type
| this type parameter
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `ManuallyDrop<(dyn Iterator<Item = impl Copy> + 'static)>`, the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Copy> + 'static)`
- = note: required because it appears within the type `ManuallyDrop<(dyn Iterator<Item = impl Copy> + 'static)>`
+ = note: required because it appears within the type `ManuallyDrop<dyn Iterator<Item = impl Copy>>`
= note: no field of a union may have a dynamically sized type
= help: change the field's type to have a statically known size
help: borrowed types always have a statically known size
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `ManuallyDrop<(dyn Iterator<Item = impl Sized + 'static> + 'static)>`, the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Sized + 'static> + 'static)`
- = note: required because it appears within the type `ManuallyDrop<(dyn Iterator<Item = impl Sized + 'static> + 'static)>`
+ = note: required because it appears within the type `ManuallyDrop<dyn Iterator<Item = impl Sized>>`
= note: no field of a union may have a dynamically sized type
= help: change the field's type to have a statically known size
help: borrowed types always have a statically known size
LL | fn hello<F: for<'a> Iterator<Item: 'a>>() {
| - help: try adding a return type: `-> Incorrect`
LL | Incorrect
- | ^^^^^^^^^ expected `()`, found struct `Incorrect`
+ | ^^^^^^^^^ expected `()`, found `Incorrect`
error: aborting due to previous error
--> $DIR/associated-type-projection-from-supertrait.rs:27:23
|
LL | fn b() { dent(ModelT, Blue); }
- | ---- ^^^^ expected struct `Black`, found struct `Blue`
+ | ---- ^^^^ expected `Black`, found `Blue`
| |
| arguments to this function are incorrect
|
--> $DIR/associated-type-projection-from-supertrait.rs:28:23
|
LL | fn c() { dent(ModelU, Black); }
- | ---- ^^^^^ expected struct `Blue`, found struct `Black`
+ | ---- ^^^^^ expected `Blue`, found `Black`
| |
| arguments to this function are incorrect
|
--> $DIR/associated-type-projection-from-supertrait.rs:32:28
|
LL | fn f() { ModelT.chip_paint(Blue); }
- | ---------- ^^^^ expected struct `Black`, found struct `Blue`
+ | ---------- ^^^^ expected `Black`, found `Blue`
| |
| arguments to this method are incorrect
|
--> $DIR/associated-type-projection-from-supertrait.rs:33:28
|
LL | fn g() { ModelU.chip_paint(Black); }
- | ---------- ^^^^^ expected struct `Blue`, found struct `Black`
+ | ---------- ^^^^^ expected `Blue`, found `Black`
| |
| arguments to this method are incorrect
|
let _: Bar = x.boo();
//~^ ERROR mismatched types
//~| found associated type `<I as Foo>::A`
- //~| expected struct `Bar`, found associated type
+ //~| expected `Bar`, found
//~| expected struct `Bar`
}
--> $DIR/associated-types-eq-3.rs:23:18
|
LL | let _: Bar = x.boo();
- | --- ^^^^^^^ expected struct `Bar`, found associated type
+ | --- ^^^^^^^ expected `Bar`, found associated type
| |
| expected due to this
|
-error[E0271]: type mismatch resolving `for<'x> <UintStruct as TheTrait<&'x isize>>::A == &'x isize`
+error[E0271]: type mismatch resolving `<UintStruct as TheTrait<&isize>>::A == &isize`
--> $DIR/associated-types-eq-hr.rs:87:11
|
LL | foo::<UintStruct>();
- | ^^^^^^^^^^ type mismatch resolving `for<'x> <UintStruct as TheTrait<&'x isize>>::A == &'x isize`
+ | ^^^^^^^^^^ type mismatch resolving `<UintStruct as TheTrait<&isize>>::A == &isize`
|
note: expected this to be `&isize`
--> $DIR/associated-types-eq-hr.rs:26:14
LL | T: for<'x> TheTrait<&'x isize, A = &'x isize>,
| ^^^^^^^^^^^^^ required by this bound in `foo`
-error[E0271]: type mismatch resolving `for<'x> <IntStruct as TheTrait<&'x isize>>::A == &'x usize`
+error[E0271]: type mismatch resolving `<IntStruct as TheTrait<&isize>>::A == &usize`
--> $DIR/associated-types-eq-hr.rs:91:11
|
LL | bar::<IntStruct>();
- | ^^^^^^^^^ type mismatch resolving `for<'x> <IntStruct as TheTrait<&'x isize>>::A == &'x usize`
+ | ^^^^^^^^^ type mismatch resolving `<IntStruct as TheTrait<&isize>>::A == &usize`
|
note: expected this to be `&usize`
--> $DIR/associated-types-eq-hr.rs:14:14
--> $DIR/issue-43924.rs:14:39
|
LL | assert_eq!(<() as Foo<u32>>::Out::default().to_string(), "false");
- | ^^^^^^^ function or associated item not found in `(dyn ToString + 'static)`
+ | ^^^^^^^ function or associated item not found in `dyn ToString`
error: aborting due to 2 previous errors
fn main() {
accepts_trait(returns_opaque());
- //~^ ERROR type mismatch resolving `<impl Trait + 'static as Trait>::Associated == ()`
+ //~^ ERROR type mismatch resolving `<impl Trait as Trait>::Associated == ()`
accepts_trait(returns_opaque_derived());
- //~^ ERROR type mismatch resolving `<impl DerivedTrait + 'static as Trait>::Associated == ()`
+ //~^ ERROR type mismatch resolving `<impl DerivedTrait as Trait>::Associated == ()`
accepts_trait(returns_opaque_foo());
//~^ ERROR type mismatch resolving `<impl Trait + Foo as Trait>::Associated == ()`
//~^ ERROR type mismatch resolving `<impl DerivedTrait + Foo as Trait>::Associated == ()`
accepts_generic_trait(returns_opaque_generic());
- //~^ ERROR type mismatch resolving `<impl GenericTrait<()> + 'static as GenericTrait<()>>::Associated == ()`
+ //~^ ERROR type mismatch resolving `<impl GenericTrait<()> as GenericTrait<()>>::Associated == ()`
accepts_generic_trait(returns_opaque_generic_foo());
//~^ ERROR type mismatch resolving `<impl GenericTrait<()> + Foo as GenericTrait<()>>::Associated == ()`
LL | fn accepts_generic_trait<T: GenericTrait<(), Associated = ()>>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `accepts_generic_trait`
-error[E0271]: type mismatch resolving `<impl Trait + 'static as Trait>::Associated == ()`
+error[E0271]: type mismatch resolving `<impl Trait as Trait>::Associated == ()`
--> $DIR/issue-87261.rs:79:19
|
LL | fn returns_opaque() -> impl Trait + 'static {
LL | fn returns_opaque() -> impl Trait<Associated = ()> + 'static {
| +++++++++++++++++
-error[E0271]: type mismatch resolving `<impl DerivedTrait + 'static as Trait>::Associated == ()`
+error[E0271]: type mismatch resolving `<impl DerivedTrait as Trait>::Associated == ()`
--> $DIR/issue-87261.rs:82:19
|
LL | fn returns_opaque_derived() -> impl DerivedTrait + 'static {
LL | fn accepts_trait<T: Trait<Associated = ()>>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `accepts_trait`
-error[E0271]: type mismatch resolving `<impl GenericTrait<()> + 'static as GenericTrait<()>>::Associated == ()`
+error[E0271]: type mismatch resolving `<impl GenericTrait<()> as GenericTrait<()>>::Associated == ()`
--> $DIR/issue-87261.rs:91:27
|
LL | fn returns_opaque_generic() -> impl GenericTrait<()> + 'static {
--> $DIR/async-block-control-flow-static-semantics.rs:49:44
|
LL | fn rethrow_targets_async_block_not_fn() -> Result<u8, MyErr> {
- | ---------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `Result`, found `()`
+ | ---------------------------------- ^^^^^^^^^^^^^^^^^ expected `Result<u8, MyErr>`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
|
--> $DIR/async-block-control-flow-static-semantics.rs:58:50
|
LL | fn rethrow_targets_async_block_not_async_fn() -> Result<u8, MyErr> {
- | ---------------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `Result`, found `()`
+ | ---------------------------------------- ^^^^^^^^^^^^^^^^^ expected `Result<u8, MyErr>`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
|
| |
| arguments to this function are incorrect
|
-note: while checking the return type of the `async fn`
- --> $DIR/dont-suggest-missing-await.rs:7:24
- |
-LL | async fn make_u32() -> u32 {
- | ^^^ checked the `Output` of this `async fn`, found opaque type
= note: expected type `u32`
found opaque type `impl Future<Output = u32>`
note: function defined here
--- /dev/null
+// edition: 2021
+// run-pass
+
+async fn test(_arg: [u8; 16]) {}
+
+async fn use_future(fut: impl std::future::Future<Output = ()>) {
+ fut.await
+}
+
+fn main() {
+ let actual = std::mem::size_of_val(
+ &use_future(use_future(use_future(use_future(use_future(test([0; 16])))))));
+ // Not using an exact number in case it slightly changes over different commits
+ let expected = 550;
+ assert!(actual > expected, "expected: >{expected}, actual: {actual}");
+}
--- /dev/null
+// compile-flags: -Z print-type-sizes --crate-type=lib
+// edition: 2021
+// build-pass
+// ignore-pass
+
+pub async fn test() {
+ let _ = a([0u8; 1024]).await;
+}
+
+pub async fn a<T>(t: T) -> T {
+ b(t).await
+}
+async fn b<T>(t: T) -> T {
+ c(t).await
+}
+async fn c<T>(t: T) -> T {
+ t
+}
--- /dev/null
+print-type-size type: `[async fn body@$DIR/large-arg.rs:6:21: 8:2]`: 3076 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Unresumed`: 0 bytes
+print-type-size variant `Suspend0`: 3075 bytes
+print-type-size local `.__awaitee`: 3075 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Returned`: 0 bytes
+print-type-size variant `Panicked`: 0 bytes
+print-type-size type: `[async fn body@$DIR/large-arg.rs:10:30: 12:2]`: 3075 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Unresumed`: 1024 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Suspend0`: 3074 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size local `.__awaitee`: 2050 bytes
+print-type-size variant `Returned`: 1024 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Panicked`: 1024 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:10:30: 12:2]>`: 3075 bytes, alignment: 1 bytes
+print-type-size field `.value`: 3075 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:10:30: 12:2]>`: 3075 bytes, alignment: 1 bytes
+print-type-size variant `MaybeUninit`: 3075 bytes
+print-type-size field `.uninit`: 0 bytes
+print-type-size field `.value`: 3075 bytes
+print-type-size type: `[async fn body@$DIR/large-arg.rs:13:26: 15:2]`: 2050 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Unresumed`: 1024 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Suspend0`: 2049 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size local `.__awaitee`: 1025 bytes
+print-type-size variant `Returned`: 1024 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Panicked`: 1024 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:13:26: 15:2]>`: 2050 bytes, alignment: 1 bytes
+print-type-size field `.value`: 2050 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:13:26: 15:2]>`: 2050 bytes, alignment: 1 bytes
+print-type-size variant `MaybeUninit`: 2050 bytes
+print-type-size field `.uninit`: 0 bytes
+print-type-size field `.value`: 2050 bytes
+print-type-size type: `[async fn body@$DIR/large-arg.rs:16:26: 18:2]`: 1025 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Unresumed`: 1024 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Returned`: 1024 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Panicked`: 1024 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:16:26: 18:2]>`: 1025 bytes, alignment: 1 bytes
+print-type-size field `.value`: 1025 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:16:26: 18:2]>`: 1025 bytes, alignment: 1 bytes
+print-type-size variant `MaybeUninit`: 1025 bytes
+print-type-size field `.uninit`: 0 bytes
+print-type-size field `.value`: 1025 bytes
+print-type-size type: `std::task::Poll<[u8; 1024]>`: 1025 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Ready`: 1024 bytes
+print-type-size field `.0`: 1024 bytes
+print-type-size variant `Pending`: 0 bytes
| |
| arguments to this function are incorrect
|
-note: while checking the return type of the `async fn`
- --> $DIR/generator-desc.rs:5:16
- |
-LL | async fn one() {}
- | ^ checked the `Output` of this `async fn`, expected opaque type
-note: while checking the return type of the `async fn`
- --> $DIR/generator-desc.rs:6:16
- |
-LL | async fn two() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
= note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:5:16>)
found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:6:16>)
= help: consider `await`ing on both `Future`s
--> $DIR/async-example-desugared-boxed-in-trait.rs:15:28
|
LL | async fn foo(&self) -> i32 {
- | ^^^ expected struct `Pin`, found opaque type
+ | ^^^ expected `Pin<Box<dyn Future<Output = i32>>>`, found opaque type
|
note: type in trait
--> $DIR/async-example-desugared-boxed-in-trait.rs:11:22
LL | Ok(())
| ^^^^^^- help: consider using a semicolon here: `;`
| |
- | expected `()`, found enum `Result`
+ | expected `()`, found `Result<(), _>`
|
= note: expected unit type `()`
found enum `Result<(), _>`
}
async fn tuple() -> Tuple {
- //~^ NOTE checked the `Output` of this `async fn`, expected opaque type
- //~| NOTE while checking the return type of the `async fn`
- //~| NOTE in this expansion of desugaring of `async` block or function
Tuple(1i32)
}
match tuple() { //~ HELP consider `await`ing on the `Future`
//~^ NOTE this expression has type `impl Future<Output = Tuple>`
Tuple(_) => {} //~ ERROR mismatched types
- //~^ NOTE expected opaque type, found struct `Tuple`
+ //~^ NOTE expected opaque type, found `Tuple`
//~| NOTE expected opaque type `impl Future<Output = Tuple>`
}
}
| ++++++
error[E0277]: the `?` operator can only be applied to values that implement `Try`
- --> $DIR/issue-61076.rs:65:5
+ --> $DIR/issue-61076.rs:62:5
|
LL | t?;
| ^^ the `?` operator cannot be applied to type `T`
| ++++++
error[E0609]: no field `0` on type `impl Future<Output = Tuple>`
- --> $DIR/issue-61076.rs:74:26
+ --> $DIR/issue-61076.rs:71:26
|
LL | let _: i32 = tuple().0;
| ^ field not available in `impl Future`, but it is available in its `Output`
| ++++++
error[E0609]: no field `a` on type `impl Future<Output = Struct>`
- --> $DIR/issue-61076.rs:78:28
+ --> $DIR/issue-61076.rs:75:28
|
LL | let _: i32 = struct_().a;
| ^ field not available in `impl Future`, but it is available in its `Output`
| ++++++
error[E0599]: no method named `method` found for opaque type `impl Future<Output = Struct>` in the current scope
- --> $DIR/issue-61076.rs:82:15
+ --> $DIR/issue-61076.rs:79:15
|
LL | struct_().method();
| ^^^^^^ method not found in `impl Future<Output = Struct>`
| ++++++
error[E0308]: mismatched types
- --> $DIR/issue-61076.rs:91:9
+ --> $DIR/issue-61076.rs:88:9
|
LL | match tuple() {
| ------- this expression has type `impl Future<Output = Tuple>`
LL |
LL | Tuple(_) => {}
- | ^^^^^^^^ expected opaque type, found struct `Tuple`
+ | ^^^^^^^^ expected opaque type, found `Tuple`
|
-note: while checking the return type of the `async fn`
- --> $DIR/issue-61076.rs:56:21
- |
-LL | async fn tuple() -> Tuple {
- | ^^^^^ checked the `Output` of this `async fn`, expected opaque type
= note: expected opaque type `impl Future<Output = Tuple>`
found struct `Tuple`
help: consider `await`ing on the `Future`
fn main() {
Runtime.block_on(async {
StructAsync { callback }.await;
- //~^ ERROR expected `fn() -> impl Future<Output = ()> {callback}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
- //~| ERROR expected `fn() -> impl Future<Output = ()> {callback}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
- //~| ERROR expected `fn() -> impl Future<Output = ()> {callback}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
+ //~^ ERROR expected `callback` to be a fn item that returns `Pin<Box<dyn Future<Output = ()>>>`, but it returns `impl Future<Output = ()>`
+ //~| ERROR expected `callback` to be a fn item that returns `Pin<Box<dyn Future<Output = ()>>>`, but it returns `impl Future<Output = ()>`
+ //~| ERROR expected `callback` to be a fn item that returns `Pin<Box<dyn Future<Output = ()>>>`, but it returns `impl Future<Output = ()>`
});
}
-error[E0271]: expected `fn() -> impl Future<Output = ()> {callback}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
+error[E0271]: expected `callback` to be a fn item that returns `Pin<Box<dyn Future<Output = ()>>>`, but it returns `impl Future<Output = ()>`
--> $DIR/issue-98634.rs:45:23
|
LL | StructAsync { callback }.await;
- | ^^^^^^^^ expected struct `Pin`, found opaque type
+ | ^^^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found opaque type
|
-note: while checking the return type of the `async fn`
- --> $DIR/issue-98634.rs:24:21
- |
-LL | async fn callback() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
= note: expected struct `Pin<Box<(dyn Future<Output = ()> + 'static)>>`
found opaque type `impl Future<Output = ()>`
note: required by a bound in `StructAsync`
LL | pub struct StructAsync<F: Fn() -> Pin<Box<dyn Future<Output = ()>>>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StructAsync`
-error[E0271]: expected `fn() -> impl Future<Output = ()> {callback}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
+error[E0271]: expected `callback` to be a fn item that returns `Pin<Box<dyn Future<Output = ()>>>`, but it returns `impl Future<Output = ()>`
--> $DIR/issue-98634.rs:45:9
|
LL | StructAsync { callback }.await;
- | ^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Pin`, found opaque type
- |
-note: while checking the return type of the `async fn`
- --> $DIR/issue-98634.rs:24:21
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found opaque type
|
-LL | async fn callback() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
= note: expected struct `Pin<Box<(dyn Future<Output = ()> + 'static)>>`
found opaque type `impl Future<Output = ()>`
note: required by a bound in `StructAsync`
LL | pub struct StructAsync<F: Fn() -> Pin<Box<dyn Future<Output = ()>>>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StructAsync`
-error[E0271]: expected `fn() -> impl Future<Output = ()> {callback}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
+error[E0271]: expected `callback` to be a fn item that returns `Pin<Box<dyn Future<Output = ()>>>`, but it returns `impl Future<Output = ()>`
--> $DIR/issue-98634.rs:45:33
|
LL | StructAsync { callback }.await;
- | ^^^^^^ expected struct `Pin`, found opaque type
- |
-note: while checking the return type of the `async fn`
- --> $DIR/issue-98634.rs:24:21
+ | ^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found opaque type
|
-LL | async fn callback() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
= note: expected struct `Pin<Box<(dyn Future<Output = ()> + 'static)>>`
found opaque type `impl Future<Output = ()>`
note: required by a bound in `StructAsync`
LL | std::mem::size_of_val(foo());
| --------------------- ^^^^^
| | |
- | | expected reference, found opaque type
+ | | expected `&_`, found opaque type
| | help: consider borrowing here: `&foo()`
| arguments to this function are incorrect
|
-note: while checking the return type of the `async fn`
- --> $DIR/issue-102206.rs:3:16
- |
-LL | async fn foo() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
= note: expected reference `&_`
found opaque type `impl Future<Output = ()>`
note: function defined here
|
LL | pub const async fn x() {}
| ^^^^^^^^^^^^^^^^^^^^^^
- = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
- = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+ = note: ...which requires computing whether `x::{opaque#0}` is freeze...
+ = note: ...which requires evaluating trait selection obligation `x::{opaque#0}: core::marker::Freeze`...
= note: ...which again requires computing type of `x::{opaque#0}`, completing the cycle
note: cycle used when checking item types in top-level module
--> $DIR/no-const-async.rs:4:1
--> $DIR/proper-span-for-type-error.rs:8:5
|
LL | a().await
- | ^^^^^^^^^ expected enum `Result`, found `()`
+ | ^^^^^^^^^ expected `Result<(), i32>`, found `()`
|
= note: expected enum `Result<(), i32>`
found unit type `()`
| |
| arguments to this function are incorrect
|
-note: while checking the return type of the `async fn`
- --> $DIR/suggest-missing-await-closure.rs:8:24
- |
-LL | async fn make_u32() -> u32 {
- | ^^^ checked the `Output` of this `async fn`, found opaque type
= note: expected type `u32`
found opaque type `impl Future<Output = u32>`
note: function defined here
| |
| arguments to this function are incorrect
|
-note: while checking the return type of the `async fn`
- --> $DIR/suggest-missing-await.rs:5:24
- |
-LL | async fn make_u32() -> u32 {
- | ^^^ checked the `Output` of this `async fn`, found opaque type
= note: expected type `u32`
found opaque type `impl Future<Output = u32>`
note: function defined here
LL | dummy()
| ^^^^^^^ expected `()`, found opaque type
|
-note: while checking the return type of the `async fn`
- --> $DIR/suggest-missing-await.rs:18:18
- |
-LL | async fn dummy() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
= note: expected unit type `()`
found opaque type `impl Future<Output = ()>`
help: consider `await`ing on the `Future`
LL | | };
| |_____- `if` and `else` have incompatible types
|
-note: while checking the return type of the `async fn`
- --> $DIR/suggest-missing-await.rs:18:18
- |
-LL | async fn dummy() {}
- | ^ checked the `Output` of this `async fn`, expected opaque type
= note: expected opaque type `impl Future<Output = ()>`
found unit type `()`
help: consider `await`ing on the `Future`
LL | | };
| |_____- `match` arms have incompatible types
|
-note: while checking the return type of the `async fn`
- --> $DIR/suggest-missing-await.rs:18:18
- |
-LL | async fn dummy() {}
- | ^ checked the `Output` of this `async fn`, expected opaque type
= note: expected opaque type `impl Future<Output = ()>`
found unit type `()`
help: consider `await`ing on the `Future`
LL | () => {}
| ^^ expected opaque type, found `()`
|
-note: while checking the return type of the `async fn`
- --> $DIR/suggest-missing-await.rs:18:18
- |
-LL | async fn dummy() {}
- | ^ checked the `Output` of this `async fn`, expected opaque type
= note: expected opaque type `impl Future<Output = ()>`
found unit type `()`
help: consider `await`ing on the `Future`
| -------------- this expression has type `impl Future<Output = Result<(), ()>>`
...
LL | Ok(_) => {}
- | ^^^^^ expected opaque type, found enum `Result`
- |
-note: while checking the return type of the `async fn`
- --> $DIR/suggest-missing-await.rs:57:28
+ | ^^^^^ expected opaque type, found `Result<_, _>`
|
-LL | async fn dummy_result() -> Result<(), ()> {
- | ^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, expected opaque type
= note: expected opaque type `impl Future<Output = Result<(), ()>>`
found enum `Result<_, _>`
help: consider `await`ing on the `Future`
| -------------- this expression has type `impl Future<Output = Result<(), ()>>`
...
LL | Err(_) => {}
- | ^^^^^^ expected opaque type, found enum `Result`
- |
-note: while checking the return type of the `async fn`
- --> $DIR/suggest-missing-await.rs:57:28
+ | ^^^^^^ expected opaque type, found `Result<_, _>`
|
-LL | async fn dummy_result() -> Result<(), ()> {
- | ^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, expected opaque type
= note: expected opaque type `impl Future<Output = Result<(), ()>>`
found enum `Result<_, _>`
help: consider `await`ing on the `Future`
--> $DIR/issue-38940.rs:49:22
|
LL | let x: &Bottom = &t;
- | ------- ^^ expected struct `Bottom`, found struct `Top`
+ | ------- ^^ expected `&Bottom`, found `&Top`
| |
| expected due to this
|
let u2 = U { a: I(1) };
let p = P { a: &2, b: &3 };
let _ = &p.b; //~ ERROR reference to packed field
- //~^ WARN will become a hard error
let _ = u1.a; // #53114: should eventually signal error as well
let _ = &u2.a; //~ ERROR [E0133]
// variation on above with `_` in substructure
let (_,) = (&p.b,); //~ ERROR reference to packed field
- //~^ WARN will become a hard error
let (_,) = (u1.a,); //~ ERROR [E0133]
let (_,) = (&u2.a,); //~ ERROR [E0133]
}
let u2 = U { a: I(1) };
let p = P { a: &2, b: &3 };
match &p.b { _ => { } } //~ ERROR reference to packed field
- //~^ WARN will become a hard error
match u1.a { _ => { } } //~ ERROR [E0133]
match &u2.a { _ => { } } //~ ERROR [E0133]
// variation on above with `_` in substructure
match (&p.b,) { (_,) => { } } //~ ERROR reference to packed field
- //~^ WARN will become a hard error
match (u1.a,) { (_,) => { } } //~ ERROR [E0133]
match (&u2.a,) { (_,) => { } } //~ ERROR [E0133]
}
-error: reference to packed field is unaligned
+error[E0793]: reference to packed field is unaligned
--> $DIR/issue-53114-safety-checks.rs:23:13
|
LL | let _ = &p.b;
| ^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
-error: reference to packed field is unaligned
- --> $DIR/issue-53114-safety-checks.rs:29:17
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/issue-53114-safety-checks.rs:28:17
|
LL | let (_,) = (&p.b,);
| ^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-error: reference to packed field is unaligned
- --> $DIR/issue-53114-safety-checks.rs:39:11
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/issue-53114-safety-checks.rs:37:11
|
LL | match &p.b { _ => { } }
| ^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-error: reference to packed field is unaligned
- --> $DIR/issue-53114-safety-checks.rs:45:12
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/issue-53114-safety-checks.rs:42:12
|
LL | match (&p.b,) { (_,) => { } }
| ^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/issue-53114-safety-checks.rs:26:13
+ --> $DIR/issue-53114-safety-checks.rs:25:13
|
LL | let _ = &u2.a;
| ^^^^^ access to union field
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/issue-53114-safety-checks.rs:31:17
+ --> $DIR/issue-53114-safety-checks.rs:29:17
|
LL | let (_,) = (u1.a,);
| ^^^^ access to union field
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/issue-53114-safety-checks.rs:32:17
+ --> $DIR/issue-53114-safety-checks.rs:30:17
|
LL | let (_,) = (&u2.a,);
| ^^^^^ access to union field
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/issue-53114-safety-checks.rs:41:11
+ --> $DIR/issue-53114-safety-checks.rs:38:11
|
LL | match u1.a { _ => { } }
| ^^^^ access to union field
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/issue-53114-safety-checks.rs:42:11
+ --> $DIR/issue-53114-safety-checks.rs:39:11
|
LL | match &u2.a { _ => { } }
| ^^^^^ access to union field
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/issue-53114-safety-checks.rs:47:12
+ --> $DIR/issue-53114-safety-checks.rs:43:12
|
LL | match (u1.a,) { (_,) => { } }
| ^^^^ access to union field
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/issue-53114-safety-checks.rs:48:12
+ --> $DIR/issue-53114-safety-checks.rs:44:12
|
LL | match (&u2.a,) { (_,) => { } }
| ^^^^^ access to union field
error: aborting due to 11 previous errors
-For more information about this error, try `rustc --explain E0133`.
-Future incompatibility report: Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/issue-53114-safety-checks.rs:23:13
- |
-LL | let _ = &p.b;
- | ^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
-
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/issue-53114-safety-checks.rs:29:17
- |
-LL | let (_,) = (&p.b,);
- | ^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
-
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/issue-53114-safety-checks.rs:39:11
- |
-LL | match &p.b { _ => { } }
- | ^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
-
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/issue-53114-safety-checks.rs:45:12
- |
-LL | match (&p.b,) { (_,) => { } }
- | ^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
-
+Some errors have detailed explanations: E0133, E0793.
+For more information about an error, try `rustc --explain E0133`.
let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
let vr = v.iter().filter(|x| {
*x % 2 == 0
- //~^ ERROR cannot mod `&&{integer}` by `{integer}`
+ //~^ ERROR cannot calculate the remainder of `&&{integer}` divided by `{integer}`
});
println!("{:?}", vr);
}
let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
let vr = v.iter().filter(|x| {
x % 2 == 0
- //~^ ERROR cannot mod `&&{integer}` by `{integer}`
+ //~^ ERROR cannot calculate the remainder of `&&{integer}` divided by `{integer}`
});
println!("{:?}", vr);
}
-error[E0369]: cannot mod `&&{integer}` by `{integer}`
+error[E0369]: cannot calculate the remainder of `&&{integer}` divided by `{integer}`
--> $DIR/binary-op-on-double-ref.rs:5:11
|
LL | x % 2 == 0
a / a; //~ ERROR cannot divide `A` by `A`
- a % a; //~ ERROR cannot mod `A` by `A`
+ a % a; //~ ERROR cannot calculate the remainder of `A` divided by `A`
a & a; //~ ERROR no implementation for `A & A`
note: the trait `Div` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-error[E0369]: cannot mod `A` by `A`
+error[E0369]: cannot calculate the remainder of `A` divided by `A`
--> $DIR/issue-28837.rs:14:7
|
LL | a % a;
LL | let bar = 5;
| ^^^ - this expression has type `{integer}`
| |
- | expected integer, found struct `bar`
+ | expected integer, found `bar`
| `bar` is interpreted as a unit struct, not a new binding
| help: introduce a new binding instead: `other_bar`
--> $DIR/consider-removing-last-semi.rs:3:15
|
LL | pub fn f() -> String {
- | - ^^^^^^ expected struct `String`, found `()`
+ | - ^^^^^^ expected `String`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
LL | 0u8;
--> $DIR/consider-removing-last-semi.rs:8:15
|
LL | pub fn g() -> String {
- | - ^^^^^^ expected struct `String`, found `()`
+ | - ^^^^^^ expected `String`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
LL | "this won't work".to_string();
--> $DIR/issue-13428.rs:3:13
|
LL | fn foo() -> String {
- | --- ^^^^^^ expected struct `String`, found `()`
+ | --- ^^^^^^ expected `String`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
--> $DIR/issue-13428.rs:11:13
|
LL | fn bar() -> String {
- | --- ^^^^^^ expected struct `String`, found `()`
+ | --- ^^^^^^ expected `String`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
LL | "foobar".to_string()
pub fn get_enum_struct_variant() -> () {
Enum::EnumStructVariant { x: 1, y: 2, z: 3 }
//~^ ERROR mismatched types
- //~| expected `()`, found enum `Enum`
+ //~| expected `()`, found `Enum`
}
}
match enum_struct_variant {
a::Enum::EnumStructVariant { x, y, z } => {
//~^ ERROR mismatched types
- //~| expected `()`, found enum `Enum`
+ //~| expected `()`, found `Enum`
}
}
}
LL | pub fn get_enum_struct_variant() -> () {
| -- expected `()` because of return type
LL | Enum::EnumStructVariant { x: 1, y: 2, z: 3 }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found enum `Enum`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Enum`
error[E0308]: mismatched types
--> $DIR/issue-13624.rs:20:9
LL | match enum_struct_variant {
| ------------------- this expression has type `()`
LL | a::Enum::EnumStructVariant { x, y, z } => {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found enum `Enum`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Enum`
error: aborting due to 2 previous errors
| - expected `()` because of default return type
LL | let b = Bob + 3.5;
LL | b + 3
- | ^^^^^ expected `()`, found struct `Bob`
+ | ^^^^^ expected `()`, found `Bob`
error: aborting due to 2 previous errors
//~^ ERROR mismatched types
//~| expected unit type `()`
//~| found reference `&_`
- //~| expected `()`, found reference
+ //~| expected `()`, found `&_`
}
LL | fn main() {
| - expected `()` because of default return type
LL | &panic!()
- | ^^^^^^^^^ expected `()`, found reference
+ | ^^^^^^^^^ expected `()`, found `&_`
|
= note: expected unit type `()`
found reference `&_`
error[E0594]: cannot assign to `**t1`, which is behind a `&` reference
--> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:9:5
|
-LL | let t1 = t0;
- | -- consider changing this binding's type to be: `&mut &mut isize`
-LL | let p: &isize = &**t0;
LL | **t1 = 22;
| ^^^^^^^^^ `t1` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider specifying this binding's type
+ |
+LL | let t1: &mut &mut isize = t0;
+ | +++++++++++++++++
error[E0502]: cannot borrow `**t0` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:14:21
fn main() {
let mut test = Vec::new();
let rofl: &Vec<Vec<i32>> = &mut test;
- //~^ NOTE consider changing this binding's type to be
+ //~^ HELP consider changing this binding's type
rofl.push(Vec::new());
//~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference
//~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
#[rustfmt::skip]
let x: &usize = &mut{0};
- //~^ NOTE consider changing this binding's type to be
+ //~^ HELP consider changing this binding's type
*x = 1;
//~^ ERROR cannot assign to `*x`, which is behind a `&` reference
//~| NOTE `x` is a `&` reference, so the data it refers to cannot be written
#[rustfmt::skip]
let y: &usize = &mut(0);
- //~^ NOTE consider changing this binding's type to be
+ //~^ HELP consider changing this binding's type
*y = 1;
//~^ ERROR cannot assign to `*y`, which is behind a `&` reference
//~| NOTE `y` is a `&` reference, so the data it refers to cannot be written
error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference
--> $DIR/issue-85765.rs:5:5
|
-LL | let rofl: &Vec<Vec<i32>> = &mut test;
- | ---- consider changing this binding's type to be: `&mut Vec<Vec<i32>>`
-LL |
LL | rofl.push(Vec::new());
| ^^^^^^^^^^^^^^^^^^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+ |
+help: consider changing this binding's type
+ |
+LL | let rofl: &mut Vec<Vec<i32>> = &mut test;
+ | ~~~~~~~~~~~~~~~~~~
error[E0594]: cannot assign to `*r`, which is behind a `&` reference
--> $DIR/issue-85765.rs:12:5
error[E0594]: cannot assign to `*x`, which is behind a `&` reference
--> $DIR/issue-85765.rs:19:5
|
-LL | let x: &usize = &mut{0};
- | - consider changing this binding's type to be: `&mut usize`
-LL |
LL | *x = 1;
| ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider changing this binding's type
+ |
+LL | let x: &mut usize = &mut{0};
+ | ~~~~~~~~~~
error[E0594]: cannot assign to `*y`, which is behind a `&` reference
--> $DIR/issue-85765.rs:26:5
|
-LL | let y: &usize = &mut(0);
- | - consider changing this binding's type to be: `&mut usize`
-LL |
LL | *y = 1;
| ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider changing this binding's type
+ |
+LL | let y: &mut usize = &mut(0);
+ | ~~~~~~~~~~
error: aborting due to 4 previous errors
fn main() {
let client = TestClient;
let inner = client.get_inner_ref();
- //~^ NOTE consider changing this binding's type to be
+ //~^ HELP consider specifying this binding's type
inner.clear();
//~^ ERROR cannot borrow `*inner` as mutable, as it is behind a `&` reference [E0596]
//~| NOTE `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow `*inner` as mutable, as it is behind a `&` reference
--> $DIR/issue-91206.rs:13:5
|
-LL | let inner = client.get_inner_ref();
- | ----- consider changing this binding's type to be: `&mut Vec<usize>`
-LL |
LL | inner.clear();
| ^^^^^^^^^^^^^ `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+ |
+help: consider specifying this binding's type
+ |
+LL | let inner: &mut Vec<usize> = client.get_inner_ref();
+ | +++++++++++++++++
error: aborting due to previous error
error[E0594]: cannot assign to `*foo`, which is behind a `&` reference
--> $DIR/issue-92015.rs:6:5
|
-LL | let foo = Some(&0).unwrap();
- | --- consider changing this binding's type to be: `&mut i32`
LL | *foo = 1;
| ^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider specifying this binding's type
+ |
+LL | let foo: &mut i32 = Some(&0).unwrap();
+ | ++++++++++
error: aborting due to previous error
--- /dev/null
+// run-rustfix
+#![allow(dead_code, path_statements)]
+fn foo1(s: &str) -> impl Iterator<Item = String> + '_ {
+ None.into_iter()
+ .flat_map(move |()| s.chars().map(move |c| format!("{}{}", c, s)))
+ //~^ ERROR captured variable cannot escape `FnMut` closure body
+ //~| HELP consider adding 'move' keyword before the nested closure
+}
+
+fn foo2(s: &str) -> impl Sized + '_ {
+ move |()| s.chars().map(move |c| format!("{}{}", c, s))
+ //~^ ERROR lifetime may not live long enough
+ //~| HELP consider adding 'move' keyword before the nested closure
+}
+
+pub struct X;
+pub fn foo3<'a>(
+ bar: &'a X,
+) -> impl Iterator<Item = ()> + 'a {
+ Some(()).iter().flat_map(move |()| {
+ Some(()).iter().map(move |()| { bar; }) //~ ERROR captured variable cannot escape
+ //~^ HELP consider adding 'move' keyword before the nested closure
+ })
+}
+
+fn main() {}
+// run-rustfix
+#![allow(dead_code, path_statements)]
fn foo1(s: &str) -> impl Iterator<Item = String> + '_ {
None.into_iter()
.flat_map(move |()| s.chars().map(|c| format!("{}{}", c, s)))
//~| HELP consider adding 'move' keyword before the nested closure
}
+pub struct X;
+pub fn foo3<'a>(
+ bar: &'a X,
+) -> impl Iterator<Item = ()> + 'a {
+ Some(()).iter().flat_map(move |()| {
+ Some(()).iter().map(|()| { bar; }) //~ ERROR captured variable cannot escape
+ //~^ HELP consider adding 'move' keyword before the nested closure
+ })
+}
+
fn main() {}
error: captured variable cannot escape `FnMut` closure body
- --> $DIR/issue-95079-missing-move-in-nested-closure.rs:3:29
+ --> $DIR/issue-95079-missing-move-in-nested-closure.rs:5:29
|
LL | fn foo1(s: &str) -> impl Iterator<Item = String> + '_ {
| - variable defined here
LL | .flat_map(move |()| s.chars().map(|c| format!("{}{}", c, s)))
| - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | returns a reference to a captured variable which escapes the closure body
+ | | returns a closure that contains a reference to a captured variable, which then escapes the closure body
| | variable captured here
| inferred to be a `FnMut` closure
|
| ++++
error: lifetime may not live long enough
- --> $DIR/issue-95079-missing-move-in-nested-closure.rs:9:15
+ --> $DIR/issue-95079-missing-move-in-nested-closure.rs:11:15
|
LL | move |()| s.chars().map(|c| format!("{}{}", c, s))
| --------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
| | |
- | | return type of closure `Map<Chars<'_>, [closure@$DIR/issue-95079-missing-move-in-nested-closure.rs:9:29: 9:32]>` contains a lifetime `'2`
+ | | return type of closure `Map<Chars<'_>, [closure@$DIR/issue-95079-missing-move-in-nested-closure.rs:11:29: 11:32]>` contains a lifetime `'2`
| lifetime `'1` represents this closure's body
|
= note: closure implements `Fn`, so references to captured variables can't escape the closure
LL | move |()| s.chars().map(move |c| format!("{}{}", c, s))
| ++++
-error: aborting due to 2 previous errors
+error: captured variable cannot escape `FnMut` closure body
+ --> $DIR/issue-95079-missing-move-in-nested-closure.rs:21:9
+ |
+LL | bar: &'a X,
+ | --- variable defined here
+LL | ) -> impl Iterator<Item = ()> + 'a {
+LL | Some(()).iter().flat_map(move |()| {
+ | - inferred to be a `FnMut` closure
+LL | Some(()).iter().map(|()| { bar; })
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^^^
+ | | |
+ | | variable captured here
+ | returns a closure that contains a reference to a captured variable, which then escapes the closure body
+ |
+ = note: `FnMut` closures only have access to their captured variables while they are executing...
+ = note: ...therefore, they cannot allow references to captured variables to escape
+help: consider adding 'move' keyword before the nested closure
+ |
+LL | Some(()).iter().map(move |()| { bar; })
+ | ++++
+
+error: aborting due to 3 previous errors
--> $DIR/issue-82446.rs:11:9
|
LL | val
- | ^^^ expected struct `Box`, found reference
+ | ^^^ expected `Box<dyn MyTrait>`, found `&Box<dyn MyTrait>`
|
= note: expected struct `Box<(dyn MyTrait + 'static)>`
found reference `&Box<(dyn MyTrait + 'static)>`
|
= note: expected fn pointer `unsafe extern "C" fn(_, _)`
found fn item `unsafe extern "C" fn(_, _, ...) {foo}`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
error[E0308]: mismatched types
--> $DIR/variadic-ffi-1.rs:26:54
|
= note: expected fn pointer `extern "C" fn(_, _, ...)`
found fn item `extern "C" fn(_, _) {bar}`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
error[E0617]: can't pass `f32` to variadic function
--> $DIR/variadic-ffi-1.rs:28:19
let c = || {
println!("{}", foo.x);
//~^ ERROR: reference to packed field is unaligned
- //~| WARNING: this was previously accepted by the compiler but is being phased out
let _z = foo.x;
};
-error: reference to packed field is unaligned
+error[E0793]: reference to packed field is unaligned
--> $DIR/repr_packed.rs:21:24
|
LL | println!("{}", foo.x);
| ^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
-Future incompatibility report: Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/repr_packed.rs:21:24
- |
-LL | println!("{}", foo.x);
- | ^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
- = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
-
+For more information about this error, try `rustc --explain E0793`.
--> $DIR/issue-78720.rs:7:39
|
LL | fn map2<F>(self, f: F) -> Map2<F> {}
- | ^^ expected struct `Map2`, found `()`
+ | ^^ expected `Map2<F>`, found `()`
|
= note: expected struct `Map2<F>`
found unit type `()`
--> $DIR/coerce-block-tail-26978.rs:9:9
|
LL | f(&{x});
- | ^ expected `i32`, found struct `Box`
+ | ^ expected `i32`, found `Box<i32>`
|
= note: expected type `i32`
found struct `Box<i32>`
--> $DIR/coerce-block-tail-57749.rs:33:14
|
LL | reset(&{ Homura });
- | ^^^^^^ expected `u32`, found struct `Homura`
+ | ^^^^^^ expected `u32`, found `Homura`
|
help: consider dereferencing the type
|
--> $DIR/coerce-block-tail-83783.rs:7:32
|
LL | _consume_reference::<i32>(&async { Box::new(7_i32) }.await);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `Box`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `Box<i32>`
|
= note: expected type `i32`
found struct `Box<i32>`
--> $DIR/coerce-block-tail-83850.rs:5:7
|
LL | f(&Box::new([1, 2]));
- | - ^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found struct `Box`
+ | - ^^^^^^^^^^^^^^^^^ expected `&[i32]`, found `&Box<[{integer}; 2]>`
| |
| arguments to this function are incorrect
|
--> $DIR/coerce-block-tail.rs:4:23
|
LL | let _: &i32 = & { Box::new(1i32) };
- | ^^^^^^^^^^^^^^ expected `i32`, found struct `Box`
+ | ^^^^^^^^^^^^^^ expected `i32`, found `Box<i32>`
|
= note: expected type `i32`
found struct `Box<i32>`
--> $DIR/coerce-expect-unsized-ascribed.rs:9:27
|
LL | let _ = type_ascribe!(box { [1, 2, 3] }, Box<[i32]>);
- | ^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]`
+ | ^^^^^^^^^^^^^^^^^ expected `Box<[i32]>`, found `Box<[i32; 3]>`
|
= note: expected struct `Box<[i32]>`
found struct `Box<[i32; 3]>`
--> $DIR/coerce-expect-unsized-ascribed.rs:10:27
|
LL | let _ = type_ascribe!(box if true { [1, 2, 3] } else { [1, 3, 4] }, Box<[i32]>);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Box<[i32]>`, found `Box<[i32; 3]>`
|
= note: expected struct `Box<[i32]>`
found struct `Box<[i32; 3]>`
--> $DIR/coerce-expect-unsized-ascribed.rs:11:27
|
LL | let _ = type_ascribe!(box match true { true => [1, 2, 3], false => [1, 3, 4] }, Box<[i32]>);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Box<[i32]>`, found `Box<[i32; 3]>`
|
= note: expected struct `Box<[i32]>`
found struct `Box<[i32; 3]>`
--> $DIR/coerce-expect-unsized-ascribed.rs:13:27
|
LL | let _ = type_ascribe!(box { |x| (x as u8) }, Box<dyn Fn(i32) -> _>);
- | ^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found closure
+ | ^^^^^^^^^^^^^^^^^^^^^ expected `Box<dyn Fn(i32) -> u8>`, found `Box<[closure@coerce-expect-unsized-ascribed.rs:13:33]>`
|
= note: expected struct `Box<dyn Fn(i32) -> u8>`
found struct `Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:13:33: 13:36]>`
--> $DIR/coerce-expect-unsized-ascribed.rs:14:27
|
LL | let _ = type_ascribe!(box if true { false } else { true }, Box<dyn Debug>);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Debug`, found `bool`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Box<dyn Debug>`, found `Box<bool>`
|
= note: expected struct `Box<dyn Debug>`
found struct `Box<bool>`
--> $DIR/coerce-expect-unsized-ascribed.rs:15:27
|
LL | let _ = type_ascribe!(box match true { true => 'a', false => 'b' }, Box<dyn Debug>);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Debug`, found `char`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Box<dyn Debug>`, found `Box<char>`
|
= note: expected struct `Box<dyn Debug>`
found struct `Box<char>`
--> $DIR/coerce-expect-unsized-ascribed.rs:17:27
|
LL | let _ = type_ascribe!(&{ [1, 2, 3] }, &[i32]);
- | ^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]`
+ | ^^^^^^^^^^^^^^ expected `&[i32]`, found `&[i32; 3]`
|
= note: expected reference `&[i32]`
found reference `&[i32; 3]`
--> $DIR/coerce-expect-unsized-ascribed.rs:18:27
|
LL | let _ = type_ascribe!(&if true { [1, 2, 3] } else { [1, 3, 4] }, &[i32]);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&[i32]`, found `&[i32; 3]`
|
= note: expected reference `&[i32]`
found reference `&[i32; 3]`
--> $DIR/coerce-expect-unsized-ascribed.rs:19:27
|
LL | let _ = type_ascribe!(&match true { true => [1, 2, 3], false => [1, 3, 4] }, &[i32]);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&[i32]`, found `&[i32; 3]`
|
= note: expected reference `&[i32]`
found reference `&[i32; 3]`
--> $DIR/coerce-expect-unsized-ascribed.rs:21:27
|
LL | let _ = type_ascribe!(&{ |x| (x as u8) }, &dyn Fn(i32) -> _);
- | ^^^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found closure
+ | ^^^^^^^^^^^^^^^^^^ expected `&dyn Fn(i32) -> u8`, found `&[closure@coerce-expect-unsized-ascribed.rs:21:30]`
|
= note: expected reference `&dyn Fn(i32) -> u8`
found reference `&[closure@$DIR/coerce-expect-unsized-ascribed.rs:21:30: 21:33]`
--> $DIR/coerce-expect-unsized-ascribed.rs:22:27
|
LL | let _ = type_ascribe!(&if true { false } else { true }, &dyn Debug);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Debug`, found `bool`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&dyn Debug`, found `&bool`
|
= note: expected reference `&dyn Debug`
found reference `&bool`
--> $DIR/coerce-expect-unsized-ascribed.rs:23:27
|
LL | let _ = type_ascribe!(&match true { true => 'a', false => 'b' }, &dyn Debug);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Debug`, found `char`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&dyn Debug`, found `&char`
|
= note: expected reference `&dyn Debug`
found reference `&char`
--> $DIR/coerce-expect-unsized-ascribed.rs:25:27
|
LL | let _ = type_ascribe!(Box::new([1, 2, 3]), Box<[i32]>);
- | ^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]`
+ | ^^^^^^^^^^^^^^^^^^^ expected `Box<[i32]>`, found `Box<[i32; 3]>`
|
= note: expected struct `Box<[i32]>`
found struct `Box<[i32; 3]>`
--> $DIR/coerce-expect-unsized-ascribed.rs:26:27
|
LL | let _ = type_ascribe!(Box::new(|x| (x as u8)), Box<dyn Fn(i32) -> _>);
- | ^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found closure
+ | ^^^^^^^^^^^^^^^^^^^^^^^ expected `Box<dyn Fn(i32) -> u8>`, found `Box<[closure@coerce-expect-unsized-ascribed.rs:26:36]>`
|
= note: expected struct `Box<dyn Fn(i32) -> u8>`
found struct `Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:26:36: 26:39]>`
--> $DIR/coerce-to-bang.rs:50:21
|
LL | let x: [!; 2] = [return, 22];
- | ------ ^^^^^^^^^^^^ expected `!`, found integer
+ | ------ ^^^^^^^^^^^^ expected `[!; 2]`, found `[{integer}; 2]`
| |
| expected due to this
|
--> $DIR/coercion-missing-tail-expected-type.rs:8:13
|
LL | fn foo() -> Result<u8, u64> {
- | --- ^^^^^^^^^^^^^^^ expected enum `Result`, found `()`
+ | --- ^^^^^^^^^^^^^^^ expected `Result<u8, u64>`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
LL | Ok(1);
fn main() {
let _: &[i32] = [0];
//~^ ERROR mismatched types
- //~| expected `&[i32]`, found array `[{integer}; 1]`
+ //~| expected `&[i32]`, found `[{integer}; 1]`
}
LL | let _: &[i32] = [0];
| ------ ^^^
| | |
- | | expected `&[i32]`, found array `[{integer}; 1]`
+ | | expected `&[i32]`, found `[{integer}; 1]`
| | help: consider borrowing here: `&[0]`
| expected due to this
trait Object: Marker1 {}
// A supertrait marker is illegal...
-impl !Marker1 for dyn Object + Marker2 { } //~ ERROR E0371
+impl !Marker1 for dyn Object + Marker2 {} //~ ERROR E0371
+ //~^ ERROR 0321
// ...and also a direct component.
-impl !Marker2 for dyn Object + Marker2 { } //~ ERROR E0371
-
-// But implementing a marker if it is not present is OK.
-impl !Marker2 for dyn Object {} // OK
+impl !Marker2 for dyn Object + Marker2 {} //~ ERROR E0371
+ //~^ ERROR 0321
// A non-principal trait-object type is orphan even in its crate.
impl !Send for dyn Marker2 {} //~ ERROR E0117
-// And impl'ing a remote marker for a local trait object is forbidden
-// by one of these special orphan-like rules.
+// Implementing a marker for a local trait object is forbidden by a special
+// orphan-like rule.
+impl !Marker2 for dyn Object {} //~ ERROR E0321
impl !Send for dyn Object {} //~ ERROR E0321
impl !Send for dyn Object + Marker2 {} //~ ERROR E0321
-fn main() { }
+// Blanket impl that applies to dyn Object is equally problematic.
+auto trait Marker3 {}
+impl<T: ?Sized> !Marker3 for T {} //~ ERROR E0321
+
+auto trait Marker4 {}
+impl<T> !Marker4 for T {} // okay
+
+fn main() {}
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
|
-LL | impl !Marker1 for dyn Object + Marker2 { }
+LL | impl !Marker1 for dyn Object + Marker2 {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
+error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
+ --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
+ |
+LL | impl !Marker1 for dyn Object + Marker2 {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: a trait object implements `Marker1` if and only if `Marker1` is one of the trait object's trait bounds
+
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
- --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:17:1
+ --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1
|
-LL | impl !Marker2 for dyn Object + Marker2 { }
+LL | impl !Marker2 for dyn Object + Marker2 {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
+error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
+ --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1
+ |
+LL | impl !Marker2 for dyn Object + Marker2 {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds
+
+error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + 'static)`
+ --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:26:1
+ |
+LL | impl !Marker2 for dyn Object {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds
+
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
- --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:23:1
+ --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:22:1
|
LL | impl !Send for dyn Marker2 {}
| ^^^^^^^^^^^^^^^-----------
LL | impl !Send for dyn Object + Marker2 {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
-error: aborting due to 5 previous errors
+error[E0321]: traits with a default impl, like `Marker3`, cannot be implemented for generic type `T`
+ --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:32:1
+ |
+LL | impl<T: ?Sized> !Marker3 for T {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: a trait object implements `Marker3` if and only if `Marker3` is one of the trait object's trait bounds
+
+error: aborting due to 9 previous errors
Some errors have detailed explanations: E0117, E0321, E0371.
For more information about an error, try `rustc --explain E0117`.
trait Object: Marker1 {}
// A supertrait marker is illegal...
-impl Marker1 for dyn Object + Marker2 { } //~ ERROR E0371
+impl Marker1 for dyn Object + Marker2 {} //~ ERROR E0371
+ //~^ ERROR E0321
// ...and also a direct component.
-impl Marker2 for dyn Object + Marker2 { } //~ ERROR E0371
-
-// But implementing a marker if it is not present is OK.
-impl Marker2 for dyn Object {} // OK
+impl Marker2 for dyn Object + Marker2 {} //~ ERROR E0371
+ //~^ ERROR E0321
// A non-principal trait-object type is orphan even in its crate.
unsafe impl Send for dyn Marker2 {} //~ ERROR E0117
-// And impl'ing a remote marker for a local trait object is forbidden
-// by one of these special orphan-like rules.
+// Implementing a marker for a local trait object is forbidden by a special
+// orphan-like rule.
+impl Marker2 for dyn Object {} //~ ERROR E0321
unsafe impl Send for dyn Object {} //~ ERROR E0321
unsafe impl Send for dyn Object + Marker2 {} //~ ERROR E0321
-fn main() { }
+// Blanket impl that applies to dyn Object is equally problematic.
+auto trait Marker3 {}
+impl<T: ?Sized> Marker3 for T {} //~ ERROR E0321
+
+auto trait Marker4 {}
+impl<T> Marker4 for T {} // okay
+
+fn main() {}
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1
|
-LL | impl Marker1 for dyn Object + Marker2 { }
+LL | impl Marker1 for dyn Object + Marker2 {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
+error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
+ --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1
+ |
+LL | impl Marker1 for dyn Object + Marker2 {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: a trait object implements `Marker1` if and only if `Marker1` is one of the trait object's trait bounds
+
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
- --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:17:1
+ --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:18:1
|
-LL | impl Marker2 for dyn Object + Marker2 { }
+LL | impl Marker2 for dyn Object + Marker2 {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
+error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
+ --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:18:1
+ |
+LL | impl Marker2 for dyn Object + Marker2 {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds
+
+error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + 'static)`
+ --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:26:1
+ |
+LL | impl Marker2 for dyn Object {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds
+
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
- --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:23:1
+ --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:22:1
|
LL | unsafe impl Send for dyn Marker2 {}
| ^^^^^^^^^^^^^^^^^^^^^-----------
LL | unsafe impl Send for dyn Object + Marker2 {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
-error: aborting due to 5 previous errors
+error[E0321]: traits with a default impl, like `Marker3`, cannot be implemented for generic type `T`
+ --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:32:1
+ |
+LL | impl<T: ?Sized> Marker3 for T {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: a trait object implements `Marker3` if and only if `Marker3` is one of the trait object's trait bounds
+
+error: aborting due to 9 previous errors
Some errors have detailed explanations: E0117, E0321, E0371.
For more information about an error, try `rustc --explain E0117`.
LL | fn poll(self, _: &mut Context<'_>) -> Poll<()> {
| ^^^^
| |
- | expected struct `Pin`, found struct `MyFuture`
+ | expected `Pin<&mut MyFuture>`, found `MyFuture`
| help: change the self-receiver type to match the trait: `self: Pin<&mut MyFuture>`
|
= note: expected signature `fn(Pin<&mut MyFuture>, &mut Context<'_>) -> Poll<_>`
LL | fn foo(self: Box<Self>) {}
| ------^^^^^^^^^
| | |
- | | expected struct `MyFuture`, found struct `Box`
+ | | expected `MyFuture`, found `Box<MyFuture>`
| help: change the self-receiver type to match the trait: `self`
|
note: type in trait
--> $DIR/bad-self-type.rs:24:18
|
LL | fn bar(self) {}
- | ^ expected enum `Option`, found `()`
+ | ^ expected `Option<()>`, found `()`
|
note: type in trait
--> $DIR/bad-self-type.rs:18:21
-error[E0599]: no method named `closure` found for reference `&Obj<[closure@issue-33784.rs:25:43]>` in the current scope
+error[E0599]: no method named `closure` found for reference `&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:45]>` in the current scope
--> $DIR/issue-33784.rs:27:7
|
LL | p.closure();
LL | (p.closure)();
| + +
-error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@issue-33784.rs:25:43]>` in the current scope
+error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:45]>` in the current scope
--> $DIR/issue-33784.rs:29:7
|
LL | q.fn_ptr();
--> $DIR/mismatch.rs:7:26
|
LL | let e: Example<13> = ();
- | ----------- ^^ expected struct `Example`, found `()`
+ | ----------- ^^ expected `Example`, found `()`
| |
| expected due to this
|
--> $DIR/mismatch.rs:10:32
|
LL | let e: Example2<u32, 13> = ();
- | ----------------- ^^ expected struct `Example2`, found `()`
+ | ----------------- ^^ expected `Example2`, found `()`
| |
| expected due to this
|
--> $DIR/mismatch.rs:13:32
|
LL | let e: Example3<13, u32> = ();
- | ----------------- ^^ expected struct `Example3`, found `()`
+ | ----------------- ^^ expected `Example3`, found `()`
| |
| expected due to this
|
--> $DIR/mismatch.rs:16:26
|
LL | let e: Example3<7> = ();
- | ----------- ^^ expected struct `Example3`, found `()`
+ | ----------- ^^ expected `Example3<7>`, found `()`
| |
| expected due to this
|
--> $DIR/mismatch.rs:19:26
|
LL | let e: Example4<7> = ();
- | ----------- ^^ expected struct `Example4`, found `()`
+ | ----------- ^^ expected `Example4<7>`, found `()`
| |
| expected due to this
|
--- /dev/null
+// checks that when we relate a `Expr::Binop` we also relate the types of the
+// const arguments.
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Bar<const B: bool>;
+
+const fn make_generic(_: usize, a: bool) -> bool {
+ a
+}
+
+fn foo<const N: usize>() -> Bar<{ make_generic(N, true == false) }> {
+ Bar::<{ make_generic(N, 1_u8 == 0_u8) }>
+ //~^ error: mismatched types
+ //~| error: unconstrained generic constant
+}
+
+fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/relate_binop_arg_tys.rs:13:5
+ |
+LL | Bar::<{ make_generic(N, 1_u8 == 0_u8) }>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ make_generic(N, true == false) }`, found `{ make_generic(N, 1_u8 == 0_u8) }`
+ |
+ = note: expected constant `{ make_generic(N, true == false) }`
+ found constant `{ make_generic(N, 1_u8 == 0_u8) }`
+
+error: unconstrained generic constant
+ --> $DIR/relate_binop_arg_tys.rs:13:11
+ |
+LL | Bar::<{ make_generic(N, 1_u8 == 0_u8) }>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: try adding a `where` bound using this expression: `where [(); { make_generic(N, 1_u8 == 0_u8) }]:`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// checks that when we relate a `Expr::Cast` we also relate the type of the
+// const argument.
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+fn foo<const N: usize>() -> [(); (true as usize) + N] {
+ [(); (1_u8 as usize) + N]
+ //~^ error: mismatched types
+ //~| error: unconstrained generic constant
+}
+
+fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/relate_cast_arg_ty.rs:7:5
+ |
+LL | [(); (1_u8 as usize) + N]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(true as usize) + N`, found `(1_u8 as usize) + N`
+ |
+ = note: expected constant `(true as usize) + N`
+ found constant `(1_u8 as usize) + N`
+
+error: unconstrained generic constant
+ --> $DIR/relate_cast_arg_ty.rs:7:10
+ |
+LL | [(); (1_u8 as usize) + N]
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = help: try adding a `where` bound using this expression: `where [(); (1_u8 as usize) + N]:`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--> $DIR/issue-79518-default_trait_method_normalization.rs:16:32
|
LL | Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()];
- | ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found array `[(); std::mem::size_of::<Self::Assoc>()]`
+ | ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `[(); std::mem::size_of::<Self::Assoc>()]`
| |
| expected because this is `<Self as Foo>::Assoc`
|
--- /dev/null
+// check-pass
+
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+
+use std::marker::PhantomData;
+
+pub trait Bytes {
+ const BYTES: usize;
+}
+
+#[derive(Clone, Debug)]
+pub struct Conster<OT>
+where
+ OT: Bytes,
+ [(); OT::BYTES]: Sized,
+{
+ _offset_type: PhantomData<fn(OT) -> OT>,
+}
+
+impl<OT> Conster<OT>
+where
+ OT: Bytes,
+ [(); OT::BYTES]: Sized,
+{
+ pub fn new() -> Self {
+ Conster { _offset_type: PhantomData }
+ }
+}
+
+pub fn make_conster<COT>() -> Conster<COT>
+where
+ COT: Bytes,
+ [(); COT::BYTES]: Sized,
+{
+ Conster::new()
+}
+
+fn main() {}
| - this type parameter
...
LL | let x: S = MaybeUninit::uninit();
- | - ^^^^^^^^^^^^^^^^^^^^^ expected type parameter `S`, found union `MaybeUninit`
+ | - ^^^^^^^^^^^^^^^^^^^^^ expected type parameter `S`, found `MaybeUninit<_>`
| |
| expected due to this
|
--> $DIR/type_mismatch.rs:5:26
|
LL | fn bar<const N: u8>() -> [u8; N] {}
- | --- ^^^^^^^ expected array `[u8; N]`, found `()`
+ | --- ^^^^^^^ expected `[u8; N]`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
--> $DIR/type_not_in_scope.rs:7:33
|
LL | fn getn<const N: cfg_attr>() -> [u8; N] {}
- | ---- ^^^^^^^ expected array `[u8; N]`, found `()`
+ | ---- ^^^^^^^ expected `[u8; N]`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
--> $DIR/types-mismatch-const-args.rs:16:41
|
LL | let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
- | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32`
+ | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A<'_, u16, 2, 3>`, found `A<'_, u32, 2, 3>`
| |
| expected due to this
|
--> $DIR/types-mismatch-const-args.rs:18:41
|
LL | let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
- | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32`
+ | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A<'_, u16, 4, 3>`, found `A<'_, u32, 2, 3>`
| |
| expected due to this
|
--> $DIR/types-mismatch-const-args.rs:16:41
|
LL | let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
- | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32`
+ | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A<'_, u16, 2, 3>`, found `A<'_, u32, 2, 3>`
| |
| expected due to this
|
--> $DIR/types-mismatch-const-args.rs:18:41
|
LL | let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
- | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32`
+ | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A<'_, u16, 4, 3>`, found `A<'_, u32, 2, 3>`
| |
| expected due to this
|
LL | black_box((S::<i32>::FOO, S::<u32>::FOO));
| ^^^^^^^^^^^^^
-note: erroneous constant used
- --> $DIR/const-err-late.rs:19:31
- |
-LL | black_box((S::<i32>::FOO, S::<u32>::FOO));
- | ^^^^^^^^^^^^^
-
note: erroneous constant used
--> $DIR/const-err-late.rs:19:16
|
LL | black_box((S::<i32>::FOO, S::<u32>::FOO));
| ^^^^^^^^^^^^^
-note: erroneous constant used
- --> $DIR/const-err-late.rs:19:31
- |
-LL | black_box((S::<i32>::FOO, S::<u32>::FOO));
- | ^^^^^^^^^^^^^
-
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.
enum E {
V = CONSTANT,
//~^ ERROR mismatched types
- //~| expected `isize`, found struct `S`
+ //~| expected `isize`, found `S`
}
fn main() {}
--> $DIR/const-eval-span.rs:9:9
|
LL | V = CONSTANT,
- | ^^^^^^^^ expected `isize`, found struct `S`
+ | ^^^^^^^^ expected `isize`, found `S`
error: aborting due to previous error
const TUP: (usize,) = 5usize << 64;
//~^ ERROR mismatched types
-//~| expected tuple, found `usize`
+//~| expected `(usize,)`, found `usize`
const ARR: [i32; TUP.0] = [];
//~^ constant
--> $DIR/const-tup-index-span.rs:3:23
|
LL | const TUP: (usize,) = 5usize << 64;
- | ^^^^^^^^^^^^ expected tuple, found `usize`
+ | ^^^^^^^^^^^^ expected `(usize,)`, found `usize`
|
= note: expected tuple `(usize,)`
found type `usize`
--> $DIR/nested_erroneous_ctfe.rs:2:16
|
LL | [9; || [9; []]];
- | ^^ expected `usize`, found array of 0 elements
+ | ^^ expected `usize`, found `[_; 0]`
|
= note: expected type `usize`
found array `[_; 0]`
--> $DIR/cross-borrow-trait.rs:10:26
|
LL | let _y: &dyn Trait = x;
- | ---------- ^ expected `&dyn Trait`, found struct `Box`
+ | ---------- ^ expected `&dyn Trait`, found `Box<dyn Trait>`
| |
| expected due to this
|
LL | match String::new() {
| ------------- this expression has type `String`
LL | "" | _ => {}
- | ^^ expected struct `String`, found `&str`
+ | ^^ expected `String`, found `&str`
error: aborting due to previous error
error[E0277]: the trait bound `B<C>: Copy` is not satisfied
- --> $DIR/deriving-copyclone.rs:31:13
+ --> $DIR/deriving-copyclone.rs:31:26
|
LL | is_copy(B { a: 1, b: C });
- | ------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `B<C>`
+ | ------- ^ the trait `Copy` is not implemented for `B<C>`
| |
| required by a bound introduced by this call
|
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider borrowing here
|
-LL | is_copy(&B { a: 1, b: C });
- | +
+LL | is_copy(B { a: 1, b: &C });
+ | +
error[E0277]: the trait bound `B<C>: Clone` is not satisfied
- --> $DIR/deriving-copyclone.rs:32:14
+ --> $DIR/deriving-copyclone.rs:32:27
|
LL | is_clone(B { a: 1, b: C });
- | -------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `B<C>`
+ | -------- ^ the trait `Clone` is not implemented for `B<C>`
| |
| required by a bound introduced by this call
|
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider borrowing here
|
-LL | is_clone(&B { a: 1, b: C });
- | +
+LL | is_clone(B { a: 1, b: &C });
+ | +
error[E0277]: the trait bound `B<D>: Copy` is not satisfied
- --> $DIR/deriving-copyclone.rs:35:13
+ --> $DIR/deriving-copyclone.rs:35:26
|
LL | is_copy(B { a: 1, b: D });
- | ------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `B<D>`
+ | ------- ^ the trait `Copy` is not implemented for `B<D>`
| |
| required by a bound introduced by this call
|
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider borrowing here
|
-LL | is_copy(&B { a: 1, b: D });
- | +
+LL | is_copy(B { a: 1, b: &D });
+ | +
error: aborting due to 3 previous errors
-#![deny(unaligned_references)]
-
// Check that deriving certain builtin traits on certain packed structs cause
// errors. To avoid potentially misaligned references, field copies must be
// used, which involves adding `T: Copy` bounds.
error[E0599]: the method `clone` exists for struct `Foo<NonCopy>`, but its trait bounds were not satisfied
- --> $DIR/deriving-with-repr-packed-2.rs:20:11
+ --> $DIR/deriving-with-repr-packed-2.rs:18:11
|
LL | pub struct Foo<T>(T, T, T);
| -----------------
note: the following trait bounds were not satisfied:
`NonCopy: Clone`
`NonCopy: Copy`
- --> $DIR/deriving-with-repr-packed-2.rs:7:16
+ --> $DIR/deriving-with-repr-packed-2.rs:5:16
|
LL | #[derive(Copy, Clone, Default, PartialEq, Eq)]
| ^^^^^ unsatisfied trait bound introduced in this `derive` macro
-#![deny(unaligned_references)]
-
// Check that deriving certain builtin traits on certain packed structs cause
// errors. To avoid potentially misaligned references, field copies must be
// used, which involves adding `T: Copy` bounds.
warning: byte slice in a packed struct that derives a built-in trait
- --> $DIR/deriving-with-repr-packed.rs:33:5
+ --> $DIR/deriving-with-repr-packed.rs:31:5
|
LL | #[derive(Debug)]
| ----- in this derive macro expansion
= note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0507]: cannot move out of `self` which is behind a shared reference
- --> $DIR/deriving-with-repr-packed.rs:24:10
+ --> $DIR/deriving-with-repr-packed.rs:22:10
|
LL | #[derive(Debug, Default)]
| ----- in this derive macro expansion
For more information about this error, try `rustc --explain E0507`.
Future incompatibility report: Future breakage diagnostic:
warning: byte slice in a packed struct that derives a built-in trait
- --> $DIR/deriving-with-repr-packed.rs:33:5
+ --> $DIR/deriving-with-repr-packed.rs:31:5
|
LL | #[derive(Debug)]
| ----- in this derive macro expansion
impl ::core::fmt::Debug for Point {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "Point", "x",
- &&self.x, "y", &&self.y)
+ &self.x, "y", &&self.y)
}
}
#[automatically_derived]
impl ::core::fmt::Debug for PackedPoint {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "PackedPoint",
- "x", &&{ self.x }, "y", &&{ self.y })
+ "x", &{ self.x }, "y", &&{ self.y })
}
}
#[automatically_derived]
impl ::core::cmp::PartialEq for PackedPoint {
#[inline]
fn eq(&self, other: &PackedPoint) -> bool {
- { self.x } == { other.x } && { self.y } == { other.y }
+ ({ self.x }) == ({ other.x }) && ({ self.y }) == ({ other.y })
}
}
#[automatically_derived]
let names: &'static _ =
&["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8"];
let values: &[&dyn ::core::fmt::Debug] =
- &[&&self.b1, &&self.b2, &&self.b3, &&self.b4, &&self.b5,
- &&self.b6, &&self.b7, &&self.b8];
+ &[&self.b1, &self.b2, &self.b3, &self.b4, &self.b5, &self.b6,
+ &self.b7, &&self.b8];
::core::fmt::Formatter::debug_struct_fields_finish(f, "Big", names,
values)
}
for Generic<T, U> where T::A: ::core::fmt::Debug {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "Generic", "t",
- &&self.t, "ta", &&self.ta, "u", &&self.u)
+ &self.t, "ta", &self.ta, "u", &&self.u)
}
}
#[automatically_derived]
{
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field3_finish(f, "PackedGeneric",
- &&{ self.0 }, &&{ self.1 }, &&{ self.2 })
+ &{ self.0 }, &{ self.1 }, &&{ self.2 })
}
}
#[automatically_derived]
::core::marker::Copy {
#[inline]
fn eq(&self, other: &PackedGeneric<T, U>) -> bool {
- { self.0 } == { other.0 } && { self.1 } == { other.1 } &&
- { self.2 } == { other.2 }
+ ({ self.0 }) == ({ other.0 }) && ({ self.1 }) == ({ other.1 }) &&
+ ({ self.2 }) == ({ other.2 })
}
}
#[automatically_derived]
&__self_0),
Mixed::S { d1: __self_0, d2: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f, "S",
- "d1", &__self_0, "d2", &__self_1),
+ "d1", __self_0, "d2", &__self_1),
}
}
}
LL | let &&x = &1isize as &dyn T;
| ^^ ----------------- this expression has type `&dyn T`
| |
- | expected trait object `dyn T`, found reference
+ | expected `dyn T`, found `&_`
|
= note: expected trait object `dyn T`
found reference `&_`
LL | let &&&x = &(&1isize as &dyn T);
| ^^ -------------------- this expression has type `&&dyn T`
| |
- | expected trait object `dyn T`, found reference
+ | expected `dyn T`, found `&_`
|
= note: expected trait object `dyn T`
found reference `&_`
LL | let box box x = Box::new(1isize) as Box<dyn T>;
| ^^^^^ ------------------------------ this expression has type `Box<dyn T>`
| |
- | expected trait object `dyn T`, found struct `Box`
+ | expected `dyn T`, found `Box<_>`
|
= note: expected trait object `dyn T`
found struct `Box<_>`
LL | (x, y) = &(1, 2);
| ^^^^^^ ------- this expression has type `&({integer}, {integer})`
| |
- | expected reference, found tuple
+ | expected `&({integer}, {integer})`, found `(_, _)`
|
= note: expected reference `&({integer}, {integer})`
found tuple `(_, _)`
LL | | Ok("")
LL | | ))))))))))))))))))))))))))))))
LL | | ))))))))))))))))))))))))))))));
- | |__________________________________^ expected struct `Atype`, found enum `Result`
+ | |__________________________________^ expected `Atype<Btype<..., ...>, ...>`, found `Result<Result<..., ...>, ...>`
|
= note: expected struct `Atype<Btype<..., ...>, ...>`
the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
LL | | ))))))))))))))))))))))))))))))
LL | | ))))))))))))))))))))))));
- | |____________________________^ expected enum `Option`, found enum `Result`
+ | |____________________________^ expected `Option<Result<..., ...>>`, found `Result<Result<..., ...>, ...>`
|
= note: expected enum `Option<Result<..., ...>>`
the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
... |
LL | | i32
LL | | > = ();
- | | - ^^ expected struct `Atype`, found `()`
+ | | - ^^ expected `Atype<Btype<..., ...>, ...>`, found `()`
| |_____|
| expected due to this
|
LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
LL | | ))))))))))))))))))))))))))))))
LL | | ))))))))))))))))))))))));
- | |____________________________^ expected `()`, found enum `Result`
+ | |____________________________^ expected `()`, found `Result<Result<..., ...>, ...>`
|
= note: expected unit type `()`
found enum `Result<Result<..., ...>, ...>`
--> $DIR/brackets-to-braces-single-element.rs:1:24
|
LL | const A: [&str; 1] = { "hello" };
- | ^^^^^^^ expected array `[&'static str; 1]`, found `&str`
+ | ^^^^^^^ expected `[&str; 1]`, found `&str`
|
help: to create an array, use square brackets instead of curly braces
|
--> $DIR/brackets-to-braces-single-element.rs:4:19
|
LL | const B: &[u32] = &{ 1 };
- | ^^^^^^ expected slice `[u32]`, found integer
+ | ^^^^^^ expected `&[u32]`, found `&{integer}`
|
= note: expected reference `&'static [u32]`
found reference `&{integer}`
--> $DIR/brackets-to-braces-single-element.rs:7:27
|
LL | const C: &&[u32; 1] = &&{ 1 };
- | ^ expected array `[u32; 1]`, found integer
+ | ^ expected `[u32; 1]`, found integer
|
help: to create an array, use square brackets instead of curly braces
|
LL | match f {
| - this expression has type `Foo`
LL | Bar { x } => {
- | ^^^^^^^^^ expected enum `Foo`, found struct `Bar`
+ | ^^^^^^^^^ expected `Foo`, found `Bar`
|
help: try wrapping the pattern in `Foo::Bar`
|
LL | S => {
| ^
| |
- | expected enum `Option`, found struct `S`
+ | expected `Option<S>`, found `S`
| `S` is interpreted as a unit struct, not a new binding
|
= note: expected enum `Option<S>`
LL | S => {
| ^
| |
- | expected enum `Result`, found struct `S`
+ | expected `Result<S, S>`, found `S`
| `S` is interpreted as a unit struct, not a new binding
|
= note: expected enum `Result<S, S>`
LL | |
LL | | f();
LL | | }
- | |_____^ expected enum `Option`, found `()`
+ | |_____^ expected `Option<()>`, found `()`
|
= note: expected enum `Option<()>`
found unit type `()`
LL | fn b() -> Result<(), ()> {
| -------------- expected `Result<(), ()>` because of return type
LL | f()
- | ^^^ expected enum `Result`, found `()`
+ | ^^^ expected `Result<(), ()>`, found `()`
|
= note: expected enum `Result<(), ()>`
found unit type `()`
LL | |
LL | | f();
LL | | }
- | |_____^ expected enum `Option`, found `()`
+ | |_____^ expected `Option<()>`, found `()`
|
= note: expected enum `Option<()>`
found unit type `()`
--> $DIR/compatible-variants.rs:35:5
|
LL | c()?
- | ^^^^ expected enum `Option`, found `()`
+ | ^^^^ expected `Option<()>`, found `()`
|
= note: `?` operator cannot convert from `()` to `Option<()>`
= note: expected enum `Option<()>`
--> $DIR/compatible-variants.rs:42:25
|
LL | let _: Option<()> = while false {};
- | ---------- ^^^^^^^^^^^^^^ expected enum `Option`, found `()`
+ | ---------- ^^^^^^^^^^^^^^ expected `Option<()>`, found `()`
| |
| expected due to this
|
--> $DIR/compatible-variants.rs:46:9
|
LL | while false {}
- | ^^^^^^^^^^^^^^ expected enum `Option`, found `()`
+ | ^^^^^^^^^^^^^^ expected `Option<()>`, found `()`
|
= note: expected enum `Option<()>`
found unit type `()`
--> $DIR/compatible-variants.rs:50:31
|
LL | let _: Result<i32, i32> = 1;
- | ---------------- ^ expected enum `Result`, found integer
+ | ---------------- ^ expected `Result<i32, i32>`, found integer
| |
| expected due to this
|
--> $DIR/compatible-variants.rs:53:26
|
LL | let _: Option<i32> = 1;
- | ----------- ^ expected enum `Option`, found integer
+ | ----------- ^ expected `Option<i32>`, found integer
| |
| expected due to this
|
--> $DIR/compatible-variants.rs:56:28
|
LL | let _: Hey<i32, i32> = 1;
- | ------------- ^ expected enum `Hey`, found integer
+ | ------------- ^ expected `Hey<i32, i32>`, found integer
| |
| expected due to this
|
--> $DIR/compatible-variants.rs:59:29
|
LL | let _: Hey<i32, bool> = false;
- | -------------- ^^^^^ expected enum `Hey`, found `bool`
+ | -------------- ^^^^^ expected `Hey<i32, bool>`, found `bool`
| |
| expected due to this
|
--> $DIR/compatible-variants.rs:63:19
|
LL | let _ = Foo { bar };
- | ^^^ expected enum `Option`, found `i32`
+ | ^^^ expected `Option<i32>`, found `i32`
|
= note: expected enum `Option<i32>`
found type `i32`
--> $DIR/compatible-variants.rs:80:16
|
LL | let a: A = B::Fst;
- | - ^^^^^^ expected enum `A`, found enum `B`
+ | - ^^^^^^ expected `A`, found `B`
| |
| expected due to this
|
--> $DIR/compatible-variants.rs:86:17
|
LL | let a: A2 = B::Fst;
- | -- ^^^^^^ expected struct `A2`, found enum `B`
+ | -- ^^^^^^ expected `A2`, found `B`
| |
| expected due to this
|
--> $DIR/issue-42764.rs:11:43
|
LL | this_function_expects_a_double_option(n);
- | ------------------------------------- ^ expected enum `DoubleOption`, found `usize`
+ | ------------------------------------- ^ expected `DoubleOption<_>`, found `usize`
| |
| arguments to this function are incorrect
|
--> $DIR/issue-42764.rs:27:33
|
LL | let _c = Context { wrapper: Payload{} };
- | ^^^^^^^^^ expected struct `Wrapper`, found struct `Payload`
+ | ^^^^^^^^^ expected `Wrapper`, found `Payload`
|
help: try wrapping the expression in `Wrapper`
|
--> $DIR/issue-46718-struct-pattern-dotdotdot.rs:11:55
|
LL | PersonalityInventory { expressivity: exp, ... } => exp
- | ^^^ help: to omit remaining fields, use one fewer `.`: `..`
+ | ^^^
+ |
+help: to omit remaining fields, use `..`
+ |
+LL | PersonalityInventory { expressivity: exp, .. } => exp
+ | ~~
error: aborting due to previous error
--> $DIR/recursion_limit_deref.rs:51:22
|
LL | let x: &Bottom = &t;
- | ------- ^^ expected struct `Bottom`, found struct `Top`
+ | ------- ^^ expected `&Bottom`, found `&Top`
| |
| expected due to this
|
--> $DIR/disambiguate-identical-names.rs:13:10
|
LL | test(&v);
- | ---- ^^ expected struct `Vec`, found struct `HashMap`
+ | ---- ^^ expected `&Vec<Vec<u32>>`, found `&HashMap<u8, u8>`
| |
| arguments to this function are incorrect
|
| - expected `!` because of return type
LL | unsafe {
LL | ::std::mem::transmute::<f64, [u8; 8]>(panic!())
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `!`, found array `[u8; 8]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `!`, found `[u8; 8]`
|
= note: expected type `!`
found array `[u8; 8]`
let z: Box<dyn ToBar> = Box::new(Bar1 {f: 36});
f5.2 = Bar1 {f: 36};
//~^ ERROR mismatched types
- //~| expected trait object `dyn ToBar`, found struct `Bar1`
+ //~| expected `dyn ToBar`, found `Bar1`
//~| expected trait object `dyn ToBar`
//~| found struct `Bar1`
//~| ERROR the size for values of type
--> $DIR/dst-bad-assign-3.rs:33:12
|
LL | f5.2 = Bar1 {f: 36};
- | ---- ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1`
+ | ---- ^^^^^^^^^^^^ expected `dyn ToBar`, found `Bar1`
| |
| expected due to the type of this binding
|
let z: Box<dyn ToBar> = Box::new(Bar1 {f: 36});
f5.ptr = Bar1 {f: 36};
//~^ ERROR mismatched types
- //~| expected trait object `dyn ToBar`, found struct `Bar1`
+ //~| expected `dyn ToBar`, found `Bar1`
//~| expected trait object `dyn ToBar`
//~| found struct `Bar1`
//~| ERROR the size for values of type
--> $DIR/dst-bad-assign.rs:35:14
|
LL | f5.ptr = Bar1 {f: 36};
- | ------ ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1`
+ | ------ ^^^^^^^^^^^^ expected `dyn ToBar`, found `Bar1`
| |
| expected due to the type of this binding
|
--> $DIR/dst-bad-coerce1.rs:16:29
|
LL | let f3: &Fat<[usize]> = f2;
- | ------------- ^^ expected slice `[usize]`, found array `[isize; 3]`
+ | ------------- ^^ expected `&Fat<[usize]>`, found `&Fat<[isize; 3]>`
| |
| expected due to this
|
--> $DIR/dst-bad-coerce1.rs:28:27
|
LL | let f3: &([usize],) = f2;
- | ----------- ^^ expected slice `[usize]`, found array `[isize; 3]`
+ | ----------- ^^ expected `&([usize],)`, found `&([isize; 3],)`
| |
| expected due to this
|
let f1: &Fat<[isize]> = &Fat { ptr: [1, 2, 3] };
let f2: &Fat<[isize; 3]> = f1;
//~^ ERROR mismatched types
- //~| expected array `[isize; 3]`, found slice `[isize]`
+ //~| expected `&Fat<[isize; 3]>`, found `&Fat<[isize]>`
//~| expected reference `&Fat<[isize; 3]>`
//~| found reference `&Fat<[isize]>`
let f1: &([isize],) = &([1, 2, 3],);
let f2: &([isize; 3],) = f1;
//~^ ERROR mismatched types
- //~| expected array `[isize; 3]`, found slice `[isize]`
+ //~| expected `&([isize; 3],)`, found `&([isize],)`
//~| expected reference `&([isize; 3],)`
//~| found reference `&([isize],)`
}
--> $DIR/dst-bad-coerce4.rs:12:32
|
LL | let f2: &Fat<[isize; 3]> = f1;
- | ---------------- ^^ expected array `[isize; 3]`, found slice `[isize]`
+ | ---------------- ^^ expected `&Fat<[isize; 3]>`, found `&Fat<[isize]>`
| |
| expected due to this
|
--> $DIR/dst-bad-coerce4.rs:20:30
|
LL | let f2: &([isize; 3],) = f1;
- | -------------- ^^ expected array `[isize; 3]`, found slice `[isize]`
+ | -------------- ^^ expected `&([isize; 3],)`, found `&([isize],)`
| |
| expected due to this
|
--> $DIR/no-implicit-dyn-star.rs:6:48
|
LL | dyn_star_foreign::require_dyn_star_display(1usize);
- | ------------------------------------------ ^^^^^^ expected trait object `dyn Display`, found `usize`
+ | ------------------------------------------ ^^^^^^ expected `dyn Display`, found `usize`
| |
| arguments to this function are incorrect
|
LL | let xe1 = XEmpty2();
| ~~~~~~~
-error[E0599]: no variant or associated item named `Empty3` found for enum `XE` in the current scope
+error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
--> $DIR/empty-struct-braces-expr.rs:25:19
|
LL | let xe3 = XE::Empty3;
| variant or associated item not found in `XE`
| help: there is a variant with a similar name: `XEmpty3`
-error[E0599]: no variant or associated item named `Empty3` found for enum `XE` in the current scope
+error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
--> $DIR/empty-struct-braces-expr.rs:26:19
|
LL | let xe3 = XE::Empty3();
LL | let empty_struct::XEmpty2 = ();
| ^^^^^^^^^^^^^^^^^^^^^ -- this expression has type `()`
| |
- | expected `()`, found struct `XEmpty2`
+ | expected `()`, found `XEmpty2`
error[E0308]: mismatched types
--> $DIR/issue-37026.rs:7:9
LL | let empty_struct::XEmpty6(..) = ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^ -- this expression has type `()`
| |
- | expected `()`, found struct `XEmpty6`
+ | expected `()`, found `XEmpty6`
error: aborting due to 2 previous errors
fn main() {
let u = FooAlias { value: 0 };
- //~^ ERROR expected struct, variant or union type, found enum `Foo` [E0071]
+ //~^ ERROR expected struct, variant or union type, found `Foo` [E0071]
}
-error[E0071]: expected struct, variant or union type, found enum `Foo`
+error[E0071]: expected struct, variant or union type, found `Foo`
--> $DIR/E0071.rs:5:13
|
LL | let u = FooAlias { value: 0 };
--- /dev/null
+// aux-build:crateresolve1-1.rs
+// aux-build:crateresolve1-2.rs
+// aux-build:crateresolve1-3.rs
+
+// normalize-stderr-test: "\.nll/" -> "/"
+// normalize-stderr-test: "\\\?\\" -> ""
+// normalize-stderr-test: "(lib)?crateresolve1-([123])\.[a-z]+" -> "libcrateresolve1-$2.somelib"
+
+// NOTE: This test is duplicated from `tests/ui/crate-loading/crateresolve1.rs`.
+
+extern crate crateresolve1;
+//~^ ERROR multiple candidates for `rlib` dependency `crateresolve1` found
+
+fn main() {}
--- /dev/null
+error[E0464]: multiple candidates for `rlib` dependency `crateresolve1` found
+ --> $DIR/E0523.rs:11:1
+ |
+LL | extern crate crateresolve1;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: candidate #1: $TEST_BUILD_DIR/error-codes/E0523/auxiliary/libcrateresolve1-1.somelib
+ = note: candidate #2: $TEST_BUILD_DIR/error-codes/E0523/auxiliary/libcrateresolve1-2.somelib
+ = note: candidate #3: $TEST_BUILD_DIR/error-codes/E0523/auxiliary/libcrateresolve1-3.somelib
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0464`.
--- /dev/null
+trait T1 {}
+trait T2 {}
+trait T3 {}
+trait T4 {}
+
+impl<B: T2> T1 for Wrapper<B> {}
+
+impl T2 for i32 {}
+impl T3 for i32 {}
+
+impl<A: T3> T2 for Burrito<A> {}
+
+struct Wrapper<W> {
+ value: W,
+}
+
+struct Burrito<F> {
+ filling: F,
+}
+
+fn want<V: T1>(_x: V) {}
+
+fn example<Q>(q: Q) {
+ want(Wrapper { value: Burrito { filling: q } });
+ //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+}
+
+fn main() {}
--- /dev/null
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error.rs:24:46
+ |
+LL | want(Wrapper { value: Burrito { filling: q } });
+ | ---- ^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `Burrito<Q>` to implement `T2`
+ --> $DIR/blame-trait-error.rs:11:13
+ |
+LL | impl<A: T3> T2 for Burrito<A> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required for `Wrapper<Burrito<Q>>` to implement `T1`
+ --> $DIR/blame-trait-error.rs:6:13
+ |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error.rs:21:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+// This test examines the error spans reported when a generic `impl` fails.
+// For example, if a function wants an `Option<T>` where `T: Copy` but you pass `Some(vec![1, 2])`,
+// then we want to point at the `vec![1, 2]` and not the `Some( ... )` expression.
+
+trait T1 {}
+trait T2 {}
+trait T3 {}
+trait T4 {}
+
+impl T2 for i32 {}
+impl T3 for i32 {}
+
+struct Wrapper<W> {
+ value: W,
+}
+impl<B: T2> T1 for Wrapper<B> {}
+
+struct Burrito<F> {
+ spicy: bool,
+ filling: F,
+}
+impl<A: T3> T2 for Burrito<A> {}
+
+struct BurritoTuple<F>(F);
+impl<C: T3> T2 for BurritoTuple<C> {}
+
+enum BurritoKinds<G> {
+ SmallBurrito { spicy: bool, small_filling: G },
+ LargeBurrito { spicy: bool, large_filling: G },
+ MultiBurrito { first_filling: G, second_filling: G },
+}
+impl<D: T3> T2 for BurritoKinds<D> {}
+
+struct Taco<H>(bool, H);
+impl<E: T3> T2 for Taco<E> {}
+
+enum TacoKinds<H> {
+ OneTaco(bool, H),
+ TwoTacos(bool, H, H),
+}
+impl<F: T3> T2 for TacoKinds<F> {}
+
+struct GenericBurrito<Spiciness, Filling> {
+ spiciness: Spiciness,
+ filling: Filling,
+}
+impl<X, Y: T3> T2 for GenericBurrito<X, Y> {}
+struct NotSpicy;
+
+impl<A: T3, B: T3> T2 for (A, B) {}
+impl<A: T2, B: T2> T1 for (A, B) {}
+
+fn want<V: T1>(_x: V) {}
+
+// Some more-complex examples:
+type AliasBurrito<T> = GenericBurrito<T, T>;
+
+// The following example is fairly confusing. The idea is that we want to "misdirect" the location
+// of the error.
+
+struct Two<A, B> {
+ a: A,
+ b: B,
+}
+
+impl<X, Y: T1, Z> T1 for Two<Two<X, Y>, Z> {}
+
+struct DoubleWrapper<T> {
+ item: Wrapper<T>,
+}
+
+impl<T: T1> T1 for DoubleWrapper<T> {}
+
+fn example<Q>(q: Q) {
+ // In each of the following examples, we expect the error span to point at the 'q' variable,
+ // since the missing constraint is `Q: T3`.
+
+ // Verifies for struct:
+ want(Wrapper { value: Burrito { spicy: false, filling: q } });
+ //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+ // Verifies for enum with named fields in variant:
+ want(Wrapper { value: BurritoKinds::SmallBurrito { spicy: true, small_filling: q } });
+ //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+ // Verifies for tuple struct:
+ want(Wrapper { value: Taco(false, q) });
+ //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+ // Verifies for tuple enum variant:
+ want(Wrapper { value: TacoKinds::OneTaco(false, q) });
+ //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+ // Verifies for generic type with multiple parameters:
+ want(Wrapper { value: GenericBurrito { spiciness: NotSpicy, filling: q } });
+ //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+ // Verifies for tuple:
+ want((3, q));
+ //~^ ERROR the trait bound `Q: T2` is not satisfied [E0277]
+
+ // Verifies for nested tuple:
+ want(Wrapper { value: (3, q) });
+ //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+ // Verifies for nested tuple:
+ want(((3, q), 5));
+ //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+ want(DoubleWrapper { item: Wrapper { value: q } });
+ //~^ ERROR the trait bound `Q: T1` is not satisfied [E0277]
+
+ want(DoubleWrapper { item: Wrapper { value: DoubleWrapper { item: Wrapper { value: q } } } });
+ //~^ ERROR the trait bound `Q: T1` is not satisfied [E0277]
+
+ // Verifies for type alias to struct:
+ want(Wrapper { value: AliasBurrito { spiciness: q, filling: q } });
+ //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+ want(Two { a: Two { a: (), b: q }, b: () });
+ //~^ ERROR the trait bound `Q: T1` is not satisfied [E0277]
+
+ // We *should* blame the 'q'.
+ // FIXME: Right now, the wrong field is blamed.
+ want(
+ Two { a: Two { a: (), b: Two { a: Two { a: (), b: q }, b: () } }, b: () },
+ //~^ ERROR the trait bound `Q: T1` is not satisfied [E0277]
+ );
+}
+
+fn main() {}
--- /dev/null
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:79:60
+ |
+LL | want(Wrapper { value: Burrito { spicy: false, filling: q } });
+ | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
+ |
+note: required for `Burrito<Q>` to implement `T2`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:22:13
+ |
+LL | impl<A: T3> T2 for Burrito<A> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required for `Wrapper<Burrito<Q>>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+ |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:83:84
+ |
+LL | want(Wrapper { value: BurritoKinds::SmallBurrito { spicy: true, small_filling: q } });
+ | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
+ |
+note: required for `BurritoKinds<Q>` to implement `T2`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:32:13
+ |
+LL | impl<D: T3> T2 for BurritoKinds<D> {}
+ | -- ^^ ^^^^^^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required for `Wrapper<BurritoKinds<Q>>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+ |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:87:39
+ |
+LL | want(Wrapper { value: Taco(false, q) });
+ | ---- ^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `Taco<Q>` to implement `T2`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:35:13
+ |
+LL | impl<E: T3> T2 for Taco<E> {}
+ | -- ^^ ^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required for `Wrapper<Taco<Q>>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+ |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:91:27
+ |
+LL | want(Wrapper { value: TacoKinds::OneTaco(false, q) });
+ | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `TacoKinds<Q>` to implement `T2`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:41:13
+ |
+LL | impl<F: T3> T2 for TacoKinds<F> {}
+ | -- ^^ ^^^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required for `Wrapper<TacoKinds<Q>>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+ |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:95:74
+ |
+LL | want(Wrapper { value: GenericBurrito { spiciness: NotSpicy, filling: q } });
+ | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
+ |
+note: required for `GenericBurrito<NotSpicy, Q>` to implement `T2`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:47:16
+ |
+LL | impl<X, Y: T3> T2 for GenericBurrito<X, Y> {}
+ | -- ^^ ^^^^^^^^^^^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required for `Wrapper<GenericBurrito<NotSpicy, Q>>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+ |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T2` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:99:14
+ |
+LL | want((3, q));
+ | ---- ^ the trait `T2` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `(i32, Q)` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:51:20
+ |
+LL | impl<A: T2, B: T2> T1 for (A, B) {}
+ | -- ^^ ^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T2>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:103:31
+ |
+LL | want(Wrapper { value: (3, q) });
+ | ---- ^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `(i32, Q)` to implement `T2`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:50:20
+ |
+LL | impl<A: T3, B: T3> T2 for (A, B) {}
+ | -- ^^ ^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required for `Wrapper<(i32, Q)>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+ |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:107:15
+ |
+LL | want(((3, q), 5));
+ | ---- ^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `(i32, Q)` to implement `T2`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:50:20
+ |
+LL | impl<A: T3, B: T3> T2 for (A, B) {}
+ | -- ^^ ^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required for `((i32, Q), i32)` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:51:20
+ |
+LL | impl<A: T2, B: T2> T1 for (A, B) {}
+ | -- ^^ ^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T1` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:110:49
+ |
+LL | want(DoubleWrapper { item: Wrapper { value: q } });
+ | ---- ^ the trait `T1` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `DoubleWrapper<Q>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:72:13
+ |
+LL | impl<T: T1> T1 for DoubleWrapper<T> {}
+ | -- ^^ ^^^^^^^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T1>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T1` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:113:88
+ |
+LL | want(DoubleWrapper { item: Wrapper { value: DoubleWrapper { item: Wrapper { value: q } } } });
+ | ---- required by a bound introduced by this call ^ the trait `T1` is not implemented for `Q`
+ |
+note: required for `DoubleWrapper<Q>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:72:13
+ |
+LL | impl<T: T1> T1 for DoubleWrapper<T> {}
+ | -- ^^ ^^^^^^^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `DoubleWrapper<DoubleWrapper<Q>>` to implement `T1`
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T1>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:117:27
+ |
+LL | want(Wrapper { value: AliasBurrito { spiciness: q, filling: q } });
+ | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `GenericBurrito<Q, Q>` to implement `T2`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:47:16
+ |
+LL | impl<X, Y: T3> T2 for GenericBurrito<X, Y> {}
+ | -- ^^ ^^^^^^^^^^^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required for `Wrapper<GenericBurrito<Q, Q>>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+ |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T1` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:120:35
+ |
+LL | want(Two { a: Two { a: (), b: q }, b: () });
+ | ---- ^ the trait `T1` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `Two<Two<(), Q>, ()>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:66:19
+ |
+LL | impl<X, Y: T1, Z> T1 for Two<Two<X, Y>, Z> {}
+ | -- ^^ ^^^^^^^^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T1>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T1` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:126:59
+ |
+LL | want(
+ | ---- required by a bound introduced by this call
+LL | Two { a: Two { a: (), b: Two { a: Two { a: (), b: q }, b: () } }, b: () },
+ | ^ the trait `T1` is not implemented for `Q`
+ |
+note: required for `Two<Two<(), Q>, ()>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:66:19
+ |
+LL | impl<X, Y: T1, Z> T1 for Two<Two<X, Y>, Z> {}
+ | -- ^^ ^^^^^^^^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `Two<Two<(), Two<Two<(), Q>, ()>>, ()>` to implement `T1`
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T1>(q: Q) {
+ | ++++
+
+error: aborting due to 13 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
LL | fn foo(r: &A) -> &B {
| -- expected `&B` because of return type
LL | r
- | ^ expected extern type `B`, found extern type `A`
+ | ^ expected `&B`, found `&A`
|
= note: expected reference `&B`
found reference `&A`
| ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `Dst<(dyn A + 'static)>`, the trait `Sized` is not implemented for `(dyn A + 'static)`
-note: required because it appears within the type `Dst<(dyn A + 'static)>`
+note: required because it appears within the type `Dst<dyn A>`
--> $DIR/feature-gate-trivial_bounds.rs:48:8
|
LL | struct Dst<X: ?Sized> {
#[ffi_const] //~ ERROR `#[ffi_const]` may only be used on foreign functions
pub fn foo() {}
+
+#[ffi_const] //~ ERROR `#[ffi_const]` may only be used on foreign functions
+macro_rules! bar {
+ () => ()
+}
+
+extern "C" {
+ #[ffi_const] //~ ERROR `#[ffi_const]` may only be used on foreign functions
+ static INT: i32;
+}
LL | #[ffi_const]
| ^^^^^^^^^^^^
-error: aborting due to previous error
+error[E0756]: `#[ffi_const]` may only be used on foreign functions
+ --> $DIR/ffi_const.rs:7:1
+ |
+LL | #[ffi_const]
+ | ^^^^^^^^^^^^
+
+error[E0756]: `#[ffi_const]` may only be used on foreign functions
+ --> $DIR/ffi_const.rs:13:5
+ |
+LL | #[ffi_const]
+ | ^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0756`.
#[ffi_pure] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
pub fn foo() {}
+
+#[ffi_pure] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
+macro_rules! bar {
+ () => ()
+}
+
+extern "C" {
+ #[ffi_pure] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
+ static INT: i32;
+}
LL | #[ffi_pure]
| ^^^^^^^^^^^
-error: aborting due to previous error
+error[E0755]: `#[ffi_pure]` may only be used on foreign functions
+ --> $DIR/ffi_pure.rs:7:1
+ |
+LL | #[ffi_pure]
+ | ^^^^^^^^^^^
+
+error[E0755]: `#[ffi_pure]` may only be used on foreign functions
+ --> $DIR/ffi_pure.rs:13:5
+ |
+LL | #[ffi_pure]
+ | ^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0755`.
#[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions
pub fn foo() {}
+
+#[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions
+macro_rules! bar {
+ () => ()
+}
+
+extern "C" {
+ #[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions
+ static INT: i32;
+}
LL | #[ffi_returns_twice]
| ^^^^^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions
+ --> $DIR/ffi_returns_twice.rs:7:1
+ |
+LL | #[ffi_returns_twice]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions
+ --> $DIR/ffi_returns_twice.rs:13:5
+ |
+LL | #[ffi_returns_twice]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0724`.
--- /dev/null
+fn main() {
+ let bar = 3;
+ format!("{?:}", bar);
+ //~^ ERROR invalid format string: expected format parameter to occur after `:`
+ format!("{?:bar}");
+ //~^ ERROR invalid format string: expected format parameter to occur after `:`
+ format!("{?:?}", bar);
+ //~^ ERROR invalid format string: expected format parameter to occur after `:`
+ format!("{??}", bar);
+ //~^ ERROR invalid format string: expected `'}'`, found `'?'`
+ format!("{?;bar}");
+ //~^ ERROR invalid format string: expected `'}'`, found `'?'`
+ format!("{?:#?}", bar);
+ //~^ ERROR invalid format string: expected format parameter to occur after `:`
+}
--- /dev/null
+error: invalid format string: expected format parameter to occur after `:`
+ --> $DIR/format-string-wrong-order.rs:3:15
+ |
+LL | format!("{?:}", bar);
+ | ^ expected `?` to occur after `:` in format string
+ |
+ = note: `?` comes after `:`, try `:?` instead
+
+error: invalid format string: expected format parameter to occur after `:`
+ --> $DIR/format-string-wrong-order.rs:5:15
+ |
+LL | format!("{?:bar}");
+ | ^ expected `?` to occur after `:` in format string
+ |
+ = note: `?` comes after `:`, try `bar:?` instead
+
+error: invalid format string: expected format parameter to occur after `:`
+ --> $DIR/format-string-wrong-order.rs:7:15
+ |
+LL | format!("{?:?}", bar);
+ | ^ expected `?` to occur after `:` in format string
+ |
+ = note: `?` comes after `:`, try `:?` instead
+
+error: invalid format string: expected `'}'`, found `'?'`
+ --> $DIR/format-string-wrong-order.rs:9:15
+ |
+LL | format!("{??}", bar);
+ | -^ expected `}` in format string
+ | |
+ | because of this opening brace
+ |
+ = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `'}'`, found `'?'`
+ --> $DIR/format-string-wrong-order.rs:11:15
+ |
+LL | format!("{?;bar}");
+ | -^ expected `}` in format string
+ | |
+ | because of this opening brace
+ |
+ = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected format parameter to occur after `:`
+ --> $DIR/format-string-wrong-order.rs:13:15
+ |
+LL | format!("{?:#?}", bar);
+ | ^ expected `?` to occur after `:` in format string
+ |
+ = note: `?` comes after `:`, try `:?` instead
+
+error: aborting due to 6 previous errors
+
LL | println!("{} {:.*} {}", 1, 3.2, 4);
| ^^^
| |
- | expected `usize`, found floating-point number
+ | expected `&usize`, found `&{float}`
| arguments to this function are incorrect
|
= note: expected reference `&usize`
LL | println!("{} {:07$.*} {}", 1, 3.2, 4);
| ^^^
| |
- | expected `usize`, found floating-point number
+ | expected `&usize`, found `&{float}`
| arguments to this function are incorrect
|
= note: expected reference `&usize`
eq(bar::<String>, bar::<Vec<u8>>);
//~^ ERROR mismatched types
//~| found fn item `fn(_) -> _ {bar::<Vec<u8>>}`
- //~| expected struct `String`, found struct `Vec`
- //~| different fn items have unique types, even if their signatures are the same
+ //~| expected `String`, found `Vec<u8>`
// Make sure we distinguish between trait methods correctly.
eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
--> $DIR/fn-item-type.rs:34:23
|
LL | eq(bar::<String>, bar::<Vec<u8>>);
- | -- ^^^^^^^^^^^^^^ expected struct `String`, found struct `Vec`
+ | -- ^^^^^^^^^^^^^^ expected `String`, found `Vec<u8>`
| |
| arguments to this function are incorrect
|
= help: consider casting both fn items to fn pointers using `as fn(isize) -> isize`
error[E0308]: mismatched types
- --> $DIR/fn-item-type.rs:41:26
+ --> $DIR/fn-item-type.rs:40:26
|
LL | eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
| -- ^^^^^^^^^^^^^^^^^ expected `u8`, found `u16`
= help: consider casting both fn items to fn pointers using `as fn()`
error[E0308]: mismatched types
- --> $DIR/fn-item-type.rs:46:19
+ --> $DIR/fn-item-type.rs:45:19
|
LL | eq(foo::<u8>, bar::<u8> as fn(isize) -> isize);
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn item, found fn pointer
--> $DIR/fn-pointer-mismatch.rs:11:43
|
LL | let g = if n % 2 == 0 { &foo } else { &bar };
- | ---- ^^^^ expected fn item, found a different fn item
+ | ---- ^^^^ expected `&fn(u32) -> u32 {foo}`, found `&fn(u32) -> u32 {bar}`
| |
| expected because of this
|
--> $DIR/fn-pointer-mismatch.rs:36:29
|
LL | let c: fn(u32) -> u32 = &foo;
- | -------------- ^^^^
- | | |
- | | expected fn pointer, found reference
- | | help: consider removing the reference: `foo`
+ | -------------- ^^^^ expected fn pointer, found `&fn(u32) -> u32 {foo}`
+ | |
| expected due to this
|
= note: expected fn pointer `fn(u32) -> u32`
found reference `&fn(u32) -> u32 {foo}`
+help: consider removing the reference
+ |
+LL | let c: fn(u32) -> u32 = foo;
+ | ~~~
error[E0308]: mismatched types
--> $DIR/fn-pointer-mismatch.rs:42:30
|
LL | let d: &fn(u32) -> u32 = foo;
- | --------------- ^^^
- | | |
- | | expected `&fn(u32) -> u32`, found fn item
- | | help: consider using a reference: `&foo`
+ | --------------- ^^^ expected `&fn(u32) -> u32`, found fn item
+ | |
| expected due to this
|
= note: expected reference `&fn(u32) -> u32`
found fn item `fn(u32) -> u32 {foo}`
+help: consider using a reference
+ |
+LL | let d: &fn(u32) -> u32 = &foo;
+ | ~~~~
error[E0308]: mismatched types
--> $DIR/fn-pointer-mismatch.rs:48:30
|
LL | let e: &fn(u32) -> u32 = &foo;
- | --------------- ^^^^
- | | |
- | | expected fn pointer, found fn item
- | | help: consider casting to a fn pointer: `&(foo as fn(u32) -> u32)`
+ | --------------- ^^^^ expected `&fn(u32) -> u32`, found `&fn(u32) -> u32 {foo}`
+ | |
| expected due to this
|
= note: expected reference `&fn(u32) -> u32`
found reference `&fn(u32) -> u32 {foo}`
= note: fn items are distinct from fn pointers
+ = note: when the arguments and return types match, functions can be coerced to function pointers
+help: consider casting to a fn pointer
+ |
+LL | let e: &fn(u32) -> u32 = &(foo as fn(u32) -> u32);
+ | ~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 6 previous errors
--> $DIR/fn-trait-formatting.rs:6:17
|
LL | let _: () = Box::new(|_: isize| {}) as Box<dyn FnOnce(isize)>;
- | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box`
+ | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Box<dyn FnOnce(isize)>`
| |
| expected due to this
|
--> $DIR/fn-trait-formatting.rs:10:17
|
LL | let _: () = Box::new(|_: isize, isize| {}) as Box<dyn Fn(isize, isize)>;
- | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box`
+ | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Box<dyn Fn(isize, isize)>`
| |
| expected due to this
|
--> $DIR/fn-trait-formatting.rs:14:17
|
LL | let _: () = Box::new(|| -> isize { unimplemented!() }) as Box<dyn FnMut() -> isize>;
- | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box`
+ | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Box<dyn FnMut() -> isize>`
| |
| expected due to this
|
fn main() {
needs_ptr(foo);
//~^ ERROR mismatched types
- //~| NOTE expected `u32`, found `i32`
+ //~| NOTE expected fn pointer, found fn item
//~| NOTE expected fn pointer `fn(i32, u32)`
//~| NOTE arguments to this function are incorrect
+ //~| NOTE when the arguments and return types match, functions can be coerced to function pointers
}
--> $DIR/signature-error-reporting-under-verbose.rs:10:15
|
LL | needs_ptr(foo);
- | --------- ^^^ expected `u32`, found `i32`
+ | --------- ^^^ expected fn pointer, found fn item
| |
| arguments to this function are incorrect
|
= note: expected fn pointer `fn(i32, u32)`
found fn item `fn(i32, i32) {foo}`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
note: function defined here
--> $DIR/signature-error-reporting-under-verbose.rs:5:4
|
x = 5;
//~^ ERROR mismatched types
//~| NOTE expected enum `Option<usize>`
- //~| NOTE expected enum `Option`, found integer
+ //~| NOTE expected `Option<usize>`, found integer
}
LL | Option<usize>;
| ------------- expected due to this type
LL | x = 5;
- | ^ expected enum `Option`, found integer
+ | ^ expected `Option<usize>`, found integer
|
= note: expected enum `Option<usize>`
found type `{integer}`
fn bar(x: x::Foo) -> y::Foo {
return x;
//~^ ERROR mismatched types
- //~| expected enum `y::Foo`, found enum `x::Foo`
+ //~| expected `y::Foo`, found `x::Foo`
}
fn main() {
LL | fn bar(x: x::Foo) -> y::Foo {
| ------ expected `y::Foo` because of return type
LL | return x;
- | ^ expected enum `y::Foo`, found enum `x::Foo`
+ | ^ expected `y::Foo`, found `x::Foo`
|
- = note: enum `x::Foo` and enum `y::Foo` have similar names, but are actually distinct types
-note: enum `x::Foo` is defined in module `crate::x` of the current crate
+ = note: `x::Foo` and `y::Foo` have similar names, but are actually distinct types
+note: `x::Foo` is defined in module `crate::x` of the current crate
--> $DIR/fully-qualified-type-name2.rs:4:5
|
LL | pub enum Foo { }
| ^^^^^^^^^^^^
-note: enum `y::Foo` is defined in module `crate::y` of the current crate
+note: `y::Foo` is defined in module `crate::y` of the current crate
--> $DIR/fully-qualified-type-name2.rs:8:5
|
LL | pub enum Foo { }
//~^ ERROR mismatched types
//~| expected enum `Option<usize>`
//~| found type `usize`
- //~| expected enum `Option`, found `usize`
+ //~| expected `Option<usize>`, found `usize`
}
fn main() {
LL | fn bar(x: usize) -> Option<usize> {
| ------------- expected `Option<usize>` because of return type
LL | return x;
- | ^ expected enum `Option`, found `usize`
+ | ^ expected `Option<usize>`, found `usize`
|
= note: expected enum `Option<usize>`
found type `usize`
| required by a bound introduced by this call
|
= help: within `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)`, the trait `for<'a> Sized` is not implemented for `(dyn std::fmt::Display + 'a)`
- = note: required because it appears within the type `for<'a> fn(&'a ()) -> (dyn Display + 'a)`
+ = note: required because it appears within the type `fn(&()) -> dyn Display`
note: required by a bound in `foo`
--> $DIR/unsized-ret.rs:5:11
|
LL | let arc = std::sync::Arc::new(oops);
| ^^^^ not found in this scope
-error[E0599]: no method named `bar` found for struct `Arc<[closure@fn-help-with-err.rs:18:36]>` in the current scope
+error[E0599]: no method named `bar` found for struct `Arc<[closure@$DIR/fn-help-with-err.rs:18:36: 18:38]>` in the current scope
--> $DIR/fn-help-with-err.rs:19:10
|
LL | arc2.bar();
--> $DIR/type-mismatch-signature-deduction.rs:14:9
|
LL | 5
- | ^ expected enum `Result`, found integer
+ | ^ expected `Result<{integer}, _>`, found integer
|
= note: expected enum `Result<{integer}, _>`
found type `{integer}`
--> $DIR/type-mismatch-signature-deduction.rs:5:13
|
LL | fn foo() -> impl Generator<Return = i32> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `i32`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Result<{integer}, _>`, found `i32`
|
= note: expected enum `Result<{integer}, _>`
found type `i32`
| ------------------------------------ expected `<C as Collection<i32>>::Sibling<f32>` because of return type
...
LL | res
- | ^^^ expected Collection::Sibling, found CollectionFamily::Member
+ | ^^^ expected `Collection::Sibling`, found `CollectionFamily::Member`
|
= note: expected associated type `<C as Collection<i32>>::Sibling<f32>`
found associated type `<<C as Collection<i32>>::Family as CollectionFamily>::Member<f32>`
+ = note: an associated type was expected, but a different one was found
error: aborting due to previous error
--> $DIR/constraint-assoc-type-suggestion.rs:10:23
|
LL | let b: Vec<i32> = a;
- | -------- ^ expected struct `Vec`, found associated type
+ | -------- ^ expected `Vec<i32>`, found associated type
| |
| expected due to this
|
LL | as Box<dyn MapLike<u8, u8, VRefCont<'a> = dyn RefCont<'_, u8>>>;
| ++++
-error[E0271]: type mismatch resolving `<BTreeMap<u8, u8> as MapLike<u8, u8>>::VRefCont<'_> == (dyn RefCont<'_, u8> + 'static)`
+error[E0271]: type mismatch resolving `<BTreeMap<u8, u8> as MapLike<u8, u8>>::VRefCont<'_> == dyn RefCont<'_, u8>`
--> $DIR/issue-79422.rs:44:13
|
LL | let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<BTreeMap<u8, u8> as MapLike<u8, u8>>::VRefCont<'_> == (dyn RefCont<'_, u8> + 'static)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<BTreeMap<u8, u8> as MapLike<u8, u8>>::VRefCont<'_> == dyn RefCont<'_, u8>`
|
note: expected this to be `(dyn RefCont<'_, u8> + 'static)`
--> $DIR/issue-79422.rs:28:25
// Ensure that the printed type doesn't include the default type params...
let _: Foo<isize> = ();
//~^ ERROR mismatched types
- //~| expected struct `Foo`, found `()`
+ //~| expected `Foo<isize>`, found `()`
//~| expected struct `Foo<isize>`
//~| found unit type `()`
// ...even when they're present, but the same types as the defaults.
let _: Foo<isize, B, C> = ();
//~^ ERROR mismatched types
- //~| expected struct `Foo`, found `()`
+ //~| expected `Foo<isize>`, found `()`
//~| expected struct `Foo<isize>`
//~| found unit type `()`
// Including cases where the default is using previous type params.
let _: HashMap<String, isize> = ();
//~^ ERROR mismatched types
- //~| expected struct `HashMap`, found `()`
+ //~| expected `HashMap<String, isize>`, found `()`
//~| expected struct `HashMap<String, isize>`
//~| found unit type `()`
let _: HashMap<String, isize, Hash<String>> = ();
//~^ ERROR mismatched types
- //~| expected struct `HashMap`, found `()`
+ //~| expected `HashMap<String, isize>`, found `()`
//~| expected struct `HashMap<String, isize>`
//~| found unit type `()`
// But not when there's a different type in between.
let _: Foo<A, isize, C> = ();
//~^ ERROR mismatched types
- //~| expected struct `Foo`, found `()`
+ //~| expected `Foo<A, isize>`, found `()`
//~| expected struct `Foo<A, isize>`
//~| found unit type `()`
// And don't print <> at all when there's just defaults.
let _: Foo<A, B, C> = ();
//~^ ERROR mismatched types
- //~| expected struct `Foo`, found `()`
+ //~| expected `Foo`, found `()`
//~| expected struct `Foo`
//~| found unit type `()`
}
--> $DIR/generic-type-params-name-repr.rs:13:25
|
LL | let _: Foo<isize> = ();
- | ---------- ^^ expected struct `Foo`, found `()`
+ | ---------- ^^ expected `Foo<isize>`, found `()`
| |
| expected due to this
|
--> $DIR/generic-type-params-name-repr.rs:20:31
|
LL | let _: Foo<isize, B, C> = ();
- | ---------------- ^^ expected struct `Foo`, found `()`
+ | ---------------- ^^ expected `Foo<isize>`, found `()`
| |
| expected due to this
|
--> $DIR/generic-type-params-name-repr.rs:27:37
|
LL | let _: HashMap<String, isize> = ();
- | ---------------------- ^^ expected struct `HashMap`, found `()`
+ | ---------------------- ^^ expected `HashMap<String, isize>`, found `()`
| |
| expected due to this
|
--> $DIR/generic-type-params-name-repr.rs:32:51
|
LL | let _: HashMap<String, isize, Hash<String>> = ();
- | ------------------------------------ ^^ expected struct `HashMap`, found `()`
+ | ------------------------------------ ^^ expected `HashMap<String, isize>`, found `()`
| |
| expected due to this
|
--> $DIR/generic-type-params-name-repr.rs:39:31
|
LL | let _: Foo<A, isize, C> = ();
- | ---------------- ^^ expected struct `Foo`, found `()`
+ | ---------------- ^^ expected `Foo<A, isize>`, found `()`
| |
| expected due to this
|
--> $DIR/generic-type-params-name-repr.rs:46:27
|
LL | let _: Foo<A, B, C> = ();
- | ------------ ^^ expected struct `Foo`, found `()`
+ | ------------ ^^ expected `Foo`, found `()`
| |
| expected due to this
|
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
LL | [_, 99.., _] => {},
- | ^^ expected struct `Range`, found integer
+ | ^^ expected `Range<{integer}>`, found integer
|
= note: expected struct `std::ops::Range<{integer}>`
found type `{integer}`
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
LL | [_, 99..] => {},
- | ^^ expected struct `Range`, found integer
+ | ^^ expected `Range<{integer}>`, found integer
|
= note: expected struct `std::ops::Range<{integer}>`
found type `{integer}`
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
LL | [..9, 99..100, _] => {},
- | ^ expected struct `Range`, found integer
+ | ^ expected `Range<{integer}>`, found integer
|
= note: expected struct `std::ops::Range<{integer}>`
found type `{integer}`
LL | [..9, 99..100, _] => {},
| ^^ --- this is of type `{integer}`
| |
- | expected struct `Range`, found integer
+ | expected `Range<{integer}>`, found integer
|
= note: expected struct `std::ops::Range<{integer}>`
found type `{integer}`
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
LL | [..9, 99..100, _] => {},
- | -- ^^^ expected struct `Range`, found integer
+ | -- ^^^ expected `Range<{integer}>`, found integer
| |
| this is of type `{integer}`
|
let x = 42;
match x {
0..=73 => {},
- 74..=> {}, //~ ERROR unexpected `=>` after open range
- //~^ ERROR expected one of `=>`, `if`, or `|`, found `>`
+ 74..=> {},
+ //~^ ERROR unexpected `>` after inclusive range
+ //~| NOTE this is parsed as an inclusive range `..=`
}
}
-error: unexpected `=>` after open range
- --> $DIR/half-open-range-pats-inclusive-match-arrow.rs:5:11
+error: unexpected `>` after inclusive range
+ --> $DIR/half-open-range-pats-inclusive-match-arrow.rs:5:14
|
LL | 74..=> {},
- | ^^^
+ | ---^
+ | |
+ | this is parsed as an inclusive range `..=`
|
help: add a space between the pattern and `=>`
|
LL | 74.. => {},
| +
-error: expected one of `=>`, `if`, or `|`, found `>`
- --> $DIR/half-open-range-pats-inclusive-match-arrow.rs:5:14
- |
-LL | 74..=> {},
- | ^ expected one of `=>`, `if`, or `|`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
LL | match (0, 1) {
| ------ this expression has type `({integer}, {integer})`
LL | (PAT ..) => {}
- | ^^^ expected tuple, found `u8`
+ | ^^^ expected `({integer}, {integer})`, found `u8`
|
= note: expected tuple `({integer}, {integer})`
found type `u8`
LL | | ) {
| |_- expected `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn Fn(u32) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a))` because of return type
LL | f
- | ^ expected reference, found `u32`
+ | ^ expected `&dyn Fn(&dyn Fn(&dyn Fn(&...)))`, found `&dyn Fn(u32)`
|
- = note: expected reference `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a ...) + 'a)) + 'a)) + 'a))`
+ = note: expected reference `&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&...)))))))))))`
the full type name has been written to '$TEST_BUILD_DIR/higher-rank-trait-bounds/hang-on-deeply-nested-dyn/hang-on-deeply-nested-dyn.long-type-hash.txt'
found reference `&dyn Fn(u32)`
+// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
+
// rust-lang/rust#30786: the use of `for<'b> &'b mut A: Stream<Item=T`
// should act as assertion that item does not borrow from its stream;
// but an earlier buggy rustc allowed `.map(|x: &_| x)` which does
-error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@issue-30786.rs:117:27]>`, but its trait bounds were not satisfied
- --> $DIR/issue-30786.rs:118:22
+error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@issue-30786.rs:119:27]>`, but its trait bounds were not satisfied
+ --> $DIR/issue-30786.rs:120:22
|
LL | pub struct Map<S, F> {
| --------------------
| doesn't satisfy `_: StreamExt`
...
LL | let filter = map.filterx(|x: &_| true);
- | ^^^^^^^ method cannot be called on `Map<Repeat, [closure@issue-30786.rs:117:27]>` due to unsatisfied trait bounds
+ | ^^^^^^^ method cannot be called on `Map<Repeat, [closure@issue-30786.rs:119:27]>` due to unsatisfied trait bounds
|
note: the following trait bounds were not satisfied:
- `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>: Stream`
- `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>: Stream`
- `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>: Stream`
- --> $DIR/issue-30786.rs:96:50
+ `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:119:27: 119:34]>: Stream`
+ `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:119:27: 119:34]>: Stream`
+ `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:119:27: 119:34]>: Stream`
+ --> $DIR/issue-30786.rs:98:50
|
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
| --------- - ^^^^^^ unsatisfied trait bound introduced here
-error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@issue-30786.rs:129:30]>`, but its trait bounds were not satisfied
- --> $DIR/issue-30786.rs:130:24
+error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, fn(&u64) -> &u64 {identity::<u64>}>, [closure@issue-30786.rs:131:30]>`, but its trait bounds were not satisfied
+ --> $DIR/issue-30786.rs:132:24
|
LL | pub struct Filter<S, F> {
| -----------------------
LL | let count = filter.countx();
| ^^^^^^ method cannot be called due to unsatisfied trait bounds
|
+ = note: the full type name has been written to '$TEST_BUILD_DIR/higher-rank-trait-bounds/issue-30786/issue-30786.long-type-hash.txt'
note: the following trait bounds were not satisfied:
- `&'a mut &Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream`
- `&'a mut &mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream`
- `&'a mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream`
- --> $DIR/issue-30786.rs:96:50
+ `&'a mut &Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:131:30: 131:37]>: Stream`
+ `&'a mut &mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:131:30: 131:37]>: Stream`
+ `&'a mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:131:30: 131:37]>: Stream`
+ --> $DIR/issue-30786.rs:98:50
|
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
| --------- - ^^^^^^ unsatisfied trait bound introduced here
-error[E0271]: type mismatch resolving `for<'r> <L<[closure@issue-62203-hrtb-ice.rs:42:16]> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V`
+error[E0271]: type mismatch resolving `<L<[closure@issue-62203-hrtb-ice.rs:42:16]> as T0<'r, (&u8,)>>::O == <_ as Ty<'r>>::V`
--> $DIR/issue-62203-hrtb-ice.rs:39:9
|
LL | let v = Unit2.m(
... |
LL | | },
LL | | },
- | |_________^ type mismatch resolving `for<'r> <L<[closure@issue-62203-hrtb-ice.rs:42:16]> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V`
+ | |_________^ type mismatch resolving `<L<[closure@issue-62203-hrtb-ice.rs:42:16]> as T0<'r, (&u8,)>>::O == <_ as Ty<'r>>::V`
|
note: expected this to be `<_ as Ty<'_>>::V`
--> $DIR/issue-62203-hrtb-ice.rs:21:14
... |
LL | | },
LL | | },
- | |_________^ expected struct `Unit3`, found struct `Unit4`
+ | |_________^ expected `Unit3`, found `Unit4`
|
note: required for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]>` to implement `for<'r> T0<'r, (&'r u8,)>`
--> $DIR/issue-62203-hrtb-ice.rs:17:16
|
LL | send(cycle2().clone());
| ^^^^
- = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
+ = note: ...which requires evaluating trait selection obligation `cycle2::{opaque#0}: core::marker::Send`...
note: ...which requires computing type of `cycle2::{opaque#0}`...
--> $DIR/auto-trait-leak.rs:19:16
|
|
LL | send(cycle1().clone());
| ^^^^
- = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
+ = note: ...which requires evaluating trait selection obligation `cycle1::{opaque#0}: core::marker::Send`...
= note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle
note: cycle used when checking item types in top-level module
--> $DIR/auto-trait-leak.rs:1:1
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:35
|
LL | fn fuz() -> (usize, Trait) { (42, Struct) }
- | ^^^^^^ expected trait object `dyn Trait`, found struct `Struct`
+ | ^^^^^^ expected `dyn Trait`, found `Struct`
|
= note: expected trait object `(dyn Trait + 'static)`
found struct `Struct`
| doesn't have a size known at compile-time
|
= help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`
- = note: required because it appears within the type `(usize, (dyn Trait + 'static))`
+ = note: required because it appears within the type `(usize, dyn Trait)`
= note: the return type of a function must have a statically known size
error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:39
|
LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
- | ^^^^^^ expected trait object `dyn Trait`, found struct `Struct`
+ | ^^^^^^ expected `dyn Trait`, found `Struct`
|
= note: expected trait object `(dyn Trait + 'static)`
found struct `Struct`
| doesn't have a size known at compile-time
|
= help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`
- = note: required because it appears within the type `(usize, (dyn Trait + 'static))`
+ = note: required because it appears within the type `(usize, dyn Trait)`
= note: the return type of a function must have a statically known size
error[E0746]: return type cannot have an unboxed trait object
| | ------ expected because of this
LL | | } else {
LL | | 42
- | | ^^ expected struct `Struct`, found integer
+ | | ^^ expected `Struct`, found integer
LL | | }
| |_____- `if` and `else` have incompatible types
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
LL | if true {
LL | return Struct;
- | ^^^^^^ expected struct `Box`, found struct `Struct`
+ | ^^^^^^ expected `Box<dyn Trait>`, found `Struct`
|
= note: expected struct `Box<(dyn Trait + 'static)>`
found struct `Struct`
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
...
LL | 42
- | ^^ expected struct `Box`, found integer
+ | ^^ expected `Box<dyn Trait>`, found integer
|
= note: expected struct `Box<(dyn Trait + 'static)>`
found type `{integer}`
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
LL | if true {
LL | return 0;
- | ^ expected struct `Box`, found integer
+ | ^ expected `Box<dyn Trait>`, found integer
|
= note: expected struct `Box<(dyn Trait + 'static)>`
found type `{integer}`
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
...
LL | 42
- | ^^ expected struct `Box`, found integer
+ | ^^ expected `Box<dyn Trait>`, found integer
|
= note: expected struct `Box<(dyn Trait + 'static)>`
found type `{integer}`
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
LL | if true {
LL | Struct
- | ^^^^^^ expected struct `Box`, found struct `Struct`
+ | ^^^^^^ expected `Box<dyn Trait>`, found `Struct`
|
= note: expected struct `Box<(dyn Trait + 'static)>`
found struct `Struct`
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
...
LL | 42
- | ^^ expected struct `Box`, found integer
+ | ^^ expected `Box<dyn Trait>`, found integer
|
= note: expected struct `Box<(dyn Trait + 'static)>`
found type `{integer}`
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
LL | if true {
LL | 0
- | ^ expected struct `Box`, found integer
+ | ^ expected `Box<dyn Trait>`, found integer
|
= note: expected struct `Box<(dyn Trait + 'static)>`
found type `{integer}`
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
...
LL | 42
- | ^^ expected struct `Box`, found integer
+ | ^^ expected `Box<dyn Trait>`, found integer
|
= note: expected struct `Box<(dyn Trait + 'static)>`
found type `{integer}`
|
= note: expected opaque type `impl Foo` (`u32`)
found opaque type `impl Foo` (`i32`)
+ = note: distinct uses of `impl Trait` result in different opaque types
error[E0308]: mismatched types
--> $DIR/equality2.rs:41:10
|
= note: expected opaque type `impl Foo` (`i32`)
found opaque type `impl Foo` (`u32`)
+ = note: distinct uses of `impl Trait` result in different opaque types
error: aborting due to 4 previous errors; 1 warning emitted
LL | fn bar() -> i32 { 0 }
| ^^^
| |
- | expected struct `Wrapper`, found `i32`
+ | expected `Wrapper<_>`, found `i32`
| return type in trait
|
= note: expected struct `Wrapper<_>`
LL | 42
| ^^- help: try using a conversion method: `.to_string()`
| |
- | expected struct `String`, found integer
+ | expected `String`, found integer
error: aborting due to previous error
--> $DIR/default-body-type-err.rs:7:22
|
LL | fn lol(&self) -> impl Deref<Target = String> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `String`
LL |
LL | &1i32
| ----- return type was inferred to be `&i32` here
| expected `()`, found `u8`
| help: change the parameter type to match the trait: `()`
|
-note: while checking the return type of the `async fn`
- --> $DIR/method-signature-matches.rs:20:25
- |
-LL | async fn owo(_: u8) {}
- | ^ checked the `Output` of this `async fn`, expected opaque type
-note: while checking the return type of the `async fn`
- --> $DIR/method-signature-matches.rs:20:25
- |
-LL | async fn owo(_: u8) {}
- | ^ checked the `Output` of this `async fn`, found opaque type
note: type in trait
--> $DIR/method-signature-matches.rs:16:21
|
--> $DIR/issue-102605.rs:13:20
|
LL | convert_result(foo())
- | -------------- ^^^^^ expected enum `Result`, found opaque type
+ | -------------- ^^^^^ expected `Result<(), _>`, found opaque type
| |
| arguments to this function are incorrect
|
-note: while checking the return type of the `async fn`
- --> $DIR/issue-102605.rs:3:19
- |
-LL | async fn foo() -> Result<(), String> {
- | ^^^^^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, found opaque type
= note: expected enum `Result<(), _>`
found opaque type `impl Future<Output = Result<(), String>>`
note: function defined here
--> $DIR/issue-99914.rs:9:27
|
LL | t.and_then(|t| -> _ { bar(t) });
- | ^^^^^^ expected enum `Result`, found opaque type
+ | ^^^^^^ expected `Result<_, Error>`, found opaque type
|
-note: while checking the return type of the `async fn`
- --> $DIR/issue-99914.rs:13:23
- |
-LL | async fn bar(t: Okay) {}
- | ^ checked the `Output` of this `async fn`, found opaque type
= note: expected enum `Result<_, Error>`
found opaque type `impl Future<Output = ()>`
help: try wrapping the expression in `Ok`
| | arguments to this struct are incorrect
LL | | 3
LL | | })
- | |_____^ expected closure, found a different closure
+ | |_____^ expected opaque type, found closure
|
= note: expected opaque type `Closure`
found closure `[closure@$DIR/issue-74282.rs:8:15: 8:17]`
LL | | })
| | ^- help: consider using a semicolon here: `;`
| |______|
- | expected `()`, found struct `Anonymous`
+ | expected `()`, found `Anonymous`
error: aborting due to 2 previous errors
LL | pub trait Bar {
| ^^^^^^^^^^^^^
-error[E0599]: no method named `method2` found for struct `Foo` in the current scope
+error[E0599]: no method named `method2` found for struct `no_method_suggested_traits::Foo` in the current scope
--> $DIR/no-method-suggested-traits.rs:50:37
|
LL | no_method_suggested_traits::Foo.method2();
LL | pub trait Bar {
| ^^^^^^^^^^^^^
-error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&Foo>>` in the current scope
+error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&no_method_suggested_traits::Foo>>` in the current scope
--> $DIR/no-method-suggested-traits.rs:52:71
|
LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2();
LL | pub trait Bar {
| ^^^^^^^^^^^^^
-error[E0599]: no method named `method2` found for enum `Bar` in the current scope
+error[E0599]: no method named `method2` found for enum `no_method_suggested_traits::Bar` in the current scope
--> $DIR/no-method-suggested-traits.rs:54:40
|
LL | no_method_suggested_traits::Bar::X.method2();
LL | pub trait Bar {
| ^^^^^^^^^^^^^
-error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&Bar>>` in the current scope
+error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&no_method_suggested_traits::Bar>>` in the current scope
--> $DIR/no-method-suggested-traits.rs:56:74
|
LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2();
LL | std::rc::Rc::new(&mut Box::new(&1_usize)).method3();
| ^^^^^^^ method not found in `Rc<&mut Box<&usize>>`
-error[E0599]: no method named `method3` found for struct `Foo` in the current scope
+error[E0599]: no method named `method3` found for struct `no_method_suggested_traits::Foo` in the current scope
--> $DIR/no-method-suggested-traits.rs:71:37
|
LL | no_method_suggested_traits::Foo.method3();
| ^^^^^^^ method not found in `Foo`
-error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Foo>>` in the current scope
+error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&no_method_suggested_traits::Foo>>` in the current scope
--> $DIR/no-method-suggested-traits.rs:72:71
|
LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method3();
| ^^^^^^^ method not found in `Rc<&mut Box<&Foo>>`
-error[E0599]: no method named `method3` found for enum `Bar` in the current scope
+error[E0599]: no method named `method3` found for enum `no_method_suggested_traits::Bar` in the current scope
--> $DIR/no-method-suggested-traits.rs:74:40
|
LL | no_method_suggested_traits::Bar::X.method3();
| ^^^^^^^ method not found in `Bar`
-error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Bar>>` in the current scope
+error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&no_method_suggested_traits::Bar>>` in the current scope
--> $DIR/no-method-suggested-traits.rs:75:74
|
LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3();
| ------------------ expected `A` because of return type
...
LL | B
- | ^ expected struct `A`, found struct `B`
+ | ^ expected `A`, found `B`
error[E0308]: mismatched types
--> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:43:5
| --------------- expected `A` because of return type
...
LL | B
- | ^ expected struct `A`, found struct `B`
+ | ^ expected `A`, found `B`
error: aborting due to 2 previous errors
LL | fn eq(&self, _other: &(Foo, i32)) -> bool {
| ^^^^^^^^^^^
| |
- | expected struct `Bar`, found opaque type
+ | expected `a::Bar`, found opaque type
| help: change the parameter type to match the trait: `&(a::Bar, i32)`
|
= note: expected signature `fn(&a::Bar, &(a::Bar, i32)) -> _`
LL | fn eq(&self, _other: &(Bar, i32)) -> bool {
| ^^^^^^^^^^^
| |
- | expected opaque type, found struct `Bar`
+ | expected opaque type, found `b::Bar`
| help: change the parameter type to match the trait: `&(b::Foo, i32)`
|
= note: expected signature `fn(&b::Bar, &(b::Foo, i32)) -> _`
| |
| this type parameter
LL | x
- | ^ expected struct `String`, found type parameter `impl Debug`
+ | ^ expected `String`, found type parameter `impl Debug`
|
= note: expected struct `String`
found type parameter `impl Debug`
--> $DIR/mismatched-types.rs:2:20
|
LL | let b: &[u8] = include_str!("file.txt");
- | ----- ^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[u8]`, found `str`
+ | ----- ^^^^^^^^^^^^^^^^^^^^^^^^ expected `&[u8]`, found `&str`
| |
| expected due to this
|
--> $DIR/mismatched-types.rs:3:19
|
LL | let s: &str = include_bytes!("file.txt");
- | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `str`, found array `[u8; 0]`
+ | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&str`, found `&[u8; 0]`
| |
| expected due to this
|
LL | foo(s);
| --- ^- help: try using a conversion method: `.to_string()`
| | |
- | | expected struct `String`, found `&String`
+ | | expected `String`, found `&String`
| arguments to this function are incorrect
|
note: function defined here
--> $DIR/deref-suggestion.rs:30:9
|
LL | foo(&"aaa".to_owned());
- | --- ^^^^^^^^^^^^^^^^^ expected struct `String`, found `&String`
+ | --- ^^^^^^^^^^^^^^^^^ expected `String`, found `&String`
| |
| arguments to this function are incorrect
|
--> $DIR/deref-suggestion.rs:32:9
|
LL | foo(&mut "aaa".to_owned());
- | --- ^^^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&mut String`
+ | --- ^^^^^^^^^^^^^^^^^^^^^ expected `String`, found `&mut String`
| |
| arguments to this function are incorrect
|
const fn return_ty_mismatch() {
const_eval_select((1,), foo, bar);
- //~^ ERROR expected `fn(i32) -> bool {bar}` to be a fn item that returns `i32`, but it returns `bool`
+ //~^ ERROR expected `bar` to be a fn item that returns `i32`, but it returns `bool`
}
const fn args_ty_mismatch() {
note: required by a bound in `const_eval_select`
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
-error[E0271]: expected `fn(i32) -> bool {bar}` to be a fn item that returns `i32`, but it returns `bool`
+error[E0271]: expected `bar` to be a fn item that returns `i32`, but it returns `bool`
--> $DIR/const-eval-select-bad.rs:32:34
|
LL | const_eval_select((1,), foo, bar);
--> $DIR/issue-100605.rs:4:18
|
LL | takes_option(&None);
- | ------------ ^^^^^ expected enum `Option`, found `&Option<_>`
+ | ------------ ^^^^^ expected `Option<&String>`, found `&Option<_>`
| |
| arguments to this function are incorrect
|
LL | takes_option(&res);
| ------------ ^^^^
| | |
- | | expected enum `Option`, found `&Option<String>`
+ | | expected `Option<&String>`, found `&Option<String>`
| | help: you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`: `res.as_ref()`
| arguments to this function are incorrect
|
--> $DIR/issue-102964.rs:5:41
|
LL | fn bar_function<T>(function: Foo<T>) -> RcFoo<T> {
- | ------------ ^^^^^^^^ expected struct `Rc`, found `()`
+ | ------------ ^^^^^^^^ expected `Rc<&dyn Fn(&T)>`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
|
|
= note: expected fn pointer `fn()`
found fn item `extern "C" fn() {bar}`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
note: function defined here
--> $DIR/issue-10764.rs:1:4
|
LL | c.read_to(v);
| ------- ^
| | |
- | | expected `&mut [u8]`, found struct `Vec`
+ | | expected `&mut [u8]`, found `Vec<_>`
| | help: consider mutably borrowing here: `&mut v`
| arguments to this method are incorrect
|
LL | match a {
| - this expression has type `Option<Box<{integer}>>`
LL | Ok(a) =>
- | ^^^^^ expected enum `Option`, found enum `Result`
+ | ^^^^^ expected `Option<Box<{integer}>>`, found `Result<_, _>`
|
= note: expected enum `Option<Box<{integer}>>`
found enum `Result<_, _>`
--> $DIR/issue-13446.rs:3:26
|
LL | static VEC: [u32; 256] = vec![];
- | ^^^^^^ expected array `[u32; 256]`, found struct `Vec`
+ | ^^^^^^ expected `[u32; 256]`, found `Vec<_>`
|
= note: expected array `[u32; 256]`
found struct `Vec<_>`
//~^ ERROR mismatched types
//~| expected enum `Option<{integer}>`
//~| found enum `Result<_, _>`
- //~| expected enum `Option`, found enum `Result`
+ //~| expected `Option<{integer}>`, found `Result<_, _>`
Err(e) => panic!(e)
//~^ ERROR mismatched types
//~| expected enum `Option<{integer}>`
//~| found enum `Result<_, _>`
- //~| expected enum `Option`, found enum `Result`
+ //~| expected `Option<{integer}>`, found `Result<_, _>`
};
}
LL | let _x: usize = match Some(1) {
| ------- this expression has type `Option<{integer}>`
LL | Ok(u) => u,
- | ^^^^^ expected enum `Option`, found enum `Result`
+ | ^^^^^ expected `Option<{integer}>`, found `Result<_, _>`
|
= note: expected enum `Option<{integer}>`
found enum `Result<_, _>`
| ------- this expression has type `Option<{integer}>`
...
LL | Err(e) => panic!(e)
- | ^^^^^^ expected enum `Option`, found enum `Result`
+ | ^^^^^^ expected `Option<{integer}>`, found `Result<_, _>`
|
= note: expected enum `Option<{integer}>`
found enum `Result<_, _>`
fn make(v: Vec2) {
let Vec3 { y: _, z: _ } = v;
//~^ ERROR mismatched types
- //~| expected struct `Vec2`, found struct `Vec3`
+ //~| expected `Vec2`, found `Vec3`
}
fn main() { }
LL | let Vec3 { y: _, z: _ } = v;
| ^^^^^^^^^^^^^^^^^^^ - this expression has type `Vec2`
| |
- | expected struct `Vec2`, found struct `Vec3`
+ | expected `Vec2`, found `Vec3`
error: aborting due to previous error
//~^ ERROR mismatched types
//~| expected enum `Option<&[&str]>`
//~| found enum `Option<&[&str; 1]>`
- //~| expected slice `[&str]`, found array `[&str; 1]`
+ //~| expected `Option<&[&str]>`, found `Option<&[&str; 1]>`
assert_eq!(msg, 3);
}
--> $DIR/issue-15783.rs:8:19
|
LL | let msg = foo(x);
- | --- ^ expected slice `[&str]`, found array `[&str; 1]`
+ | --- ^ expected `Option<&[&str]>`, found `Option<&[&str; 1]>`
| |
| arguments to this function are incorrect
|
| - this expression has type `E`
LL | E::B(
LL | Tau{t: x},
- | ^^^^^^^^^ expected enum `R`, found struct `Tau`
+ | ^^^^^^^^^ expected `R`, found `Tau`
error: aborting due to previous error
LL | let Slice { data: data, len: len } = "foo";
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ----- this expression has type `&str`
| |
- | expected `str`, found struct `Slice`
+ | expected `str`, found `Slice<_>`
|
= note: expected type `str`
found struct `Slice<_>`
//~^ ERROR mismatched types
//~| expected unit type `()`
//~| found struct `Slice<_>`
- //~| expected `()`, found struct `Slice`
+ //~| expected `()`, found `Slice<_>`
_ => unreachable!()
}
}
LL | match () {
| -- this expression has type `()`
LL | Slice { data: data, len: len } => (),
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Slice`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Slice<_>`
|
= note: expected unit type `()`
found struct `Slice<_>`
LL | print_x(X);
| ^^^^^^^--- an argument of type `&str` is missing
|
-note: expected reference, found struct `X`
+note: expected `&dyn Foo<Item = bool>`, found `X`
--> $DIR/issue-18819.rs:16:13
|
LL | print_x(X);
--> $DIR/issue-19521.rs:2:8
|
LL | "".homura()();
- | ^^^^^^ method not found in `&'static str`
+ | ^^^^^^ method not found in `&str`
error: aborting due to previous error
LL | extern "rust-call" fn call(&self, (_,): (T,)) {}
| ^^^^
| |
- | expected `&T`, found type parameter `T`
+ | expected `&'a T`, found type parameter `T`
| help: change the parameter type to match the trait: `(&'a T,)`
|
= note: expected signature `extern "rust-call" fn(&Foo, (&'a T,))`
LL | extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {}
| ^^^^
| |
- | expected `&T`, found type parameter `T`
+ | expected `&'a T`, found type parameter `T`
| help: change the parameter type to match the trait: `(&'a T,)`
|
= note: expected signature `extern "rust-call" fn(&mut Foo, (&'a T,))`
LL | extern "rust-call" fn call_once(self, (_,): (T,)) {}
| ^^^^
| |
- | expected `&T`, found type parameter `T`
+ | expected `&'a T`, found type parameter `T`
| help: change the parameter type to match the trait: `(&'a T,)`
|
= note: expected signature `extern "rust-call" fn(Foo, (&'a T,))`
type Item = i32;
fn next(&mut self) -> Result<i32, i32> { Ok(7) }
//~^ ERROR method `next` has an incompatible type for trait
- //~| expected enum `Option`, found enum `Result`
+ //~| expected `Option<i32>`, found `Result<i32, i32>`
}
fn main() {}
LL | fn next(&mut self) -> Result<i32, i32> { Ok(7) }
| ^^^^^^^^^^^^^^^^
| |
- | expected enum `Option`, found enum `Result`
+ | expected `Option<i32>`, found `Result<i32, i32>`
| help: change the output type to match the trait: `Option<i32>`
|
= note: expected signature `fn(&mut S) -> Option<i32>`
--> $DIR/issue-24322.rs:8:29
|
LL | let x: &fn(&B) -> u32 = &B::func;
- | -------------- ^^^^^^^^ expected fn pointer, found fn item
+ | -------------- ^^^^^^^^ expected `&fn(&B) -> u32`, found `&fn(&B) -> u32 {B::func}`
| |
| expected due to this
|
let mut v = Vec::new();
foo(&mut v);
//~^ ERROR mismatched types
- //~| expected struct `HashSet`, found struct `Vec`
+ //~| expected `&mut HashSet<u32>`, found `&mut Vec<_>`
}
fn foo(h: &mut HashSet<u32>) {
--> $DIR/issue-24819.rs:5:9
|
LL | foo(&mut v);
- | --- ^^^^^^ expected struct `HashSet`, found struct `Vec`
+ | --- ^^^^^^ expected `&mut HashSet<u32>`, found `&mut Vec<_>`
| |
| arguments to this function are incorrect
|
fn main() {
let b = [0; S];
//~^ ERROR mismatched types
- //~| expected `usize`, found struct `S`
+ //~| expected `usize`, found `S`
}
--> $DIR/issue-27008.rs:4:17
|
LL | let b = [0; S];
- | ^ expected `usize`, found struct `S`
+ | ^ expected `usize`, found `S`
error: aborting due to previous error
-error[E0599]: no function or associated item named `new_undirected` found for struct `Graph<i32, i32>` in the current scope
+error[E0599]: no function or associated item named `new_undirected` found for struct `issue_30123_aux::Graph<i32, i32>` in the current scope
--> $DIR/issue-30123.rs:7:33
|
LL | let ug = Graph::<i32, i32>::new_undirected();
--> $DIR/issue-32122-1.rs:16:24
|
LL | let _: *const u8 = &a;
- | --------- ^^ expected `u8`, found struct `Foo`
+ | --------- ^^ expected `*const u8`, found `&Foo`
| |
| expected due to this
|
--> $DIR/issue-32122-2.rs:27:24
|
LL | let _: *const u8 = &a;
- | --------- ^^ expected `u8`, found struct `Emm`
+ | --------- ^^ expected `*const u8`, found `&Emm`
| |
| expected due to this
|
LL | let Test = 1;
| ^^^^ - this expression has type `{integer}`
| |
- | expected integer, found struct `Test`
+ | expected integer, found `Test`
| `Test` is interpreted as a unit struct, not a new binding
| help: introduce a new binding instead: `other_test`
--> $DIR/issue-33941.rs:6:36
|
LL | for _ in HashMap::new().iter().cloned() {}
- | ^^^^^^ expected reference, found tuple
+ | ^^^^^^ expected `&_`, found `(&_, &_)`
|
= note: expected reference `&_`
found tuple `(&_, &_)`
--> $DIR/issue-33941.rs:6:14
|
LL | for _ in HashMap::new().iter().cloned() {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(&_, &_)`, found `&_`
|
= note: expected tuple `(&_, &_)`
found reference `&_`
--> $DIR/issue-33941.rs:6:14
|
LL | for _ in HashMap::new().iter().cloned() {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(&_, &_)`, found `&_`
|
= note: expected tuple `(&_, &_)`
found reference `&_`
| ---------- `Foo` defines a struct constructor here, which should be called
LL |
LL | fn test() -> Foo { Foo }
- | --- ^^^ expected struct `Foo`, found struct constructor
+ | --- ^^^ expected `Foo`, found struct constructor
| |
| expected `Foo` because of return type
|
//~^ ERROR mismatched types
//~| expected enum `Option<_>`
//~| found enum `Result<_, _>`
- //~| expected enum `Option`, found enum `Result`
+ //~| expected `Option<_>`, found `Result<_, _>`
}
}
LL | match None {
| ---- this expression has type `Option<_>`
LL | Err(_) => ()
- | ^^^^^^ expected enum `Option`, found enum `Result`
+ | ^^^^^^ expected `Option<_>`, found `Result<_, _>`
|
= note: expected enum `Option<_>`
found enum `Result<_, _>`
fn main() {
<() as Visit>::visit();
- //~^ ERROR type mismatch resolving `for<'a> <() as Array<'a>>::Element == ()`
+ //~^ ERROR type mismatch resolving `<() as Array<'a>>::Element == ()`
}
-error[E0271]: type mismatch resolving `for<'a> <() as Array<'a>>::Element == ()`
+error[E0271]: type mismatch resolving `<() as Array<'a>>::Element == ()`
--> $DIR/issue-39970.rs:19:5
|
LL | <() as Visit>::visit();
- | ^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `for<'a> <() as Array<'a>>::Element == ()`
+ | ^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Array<'a>>::Element == ()`
|
note: expected this to be `()`
--> $DIR/issue-39970.rs:10:20
--> $DIR/issue-40749.rs:2:9
|
LL | [0; ..10];
- | ^^^^ expected `usize`, found struct `RangeTo`
+ | ^^^^ expected `usize`, found `RangeTo<{integer}>`
|
= note: expected type `usize`
found struct `RangeTo<{integer}>`
--> $DIR/issue-43420-no-over-suggest.rs:8:9
|
LL | foo(&a);
- | --- ^^ expected slice `[u16]`, found struct `Vec`
+ | --- ^^ expected `&[u16]`, found `&Vec<u8>`
| |
| arguments to this function are incorrect
|
let foo: [u8; 4] = [1; 4];
bar(foo);
//~^ ERROR mismatched types
- //~| expected `usize`, found array `[u8; 4]`
+ //~| expected `usize`, found `[u8; 4]`
}
--> $DIR/issue-4517.rs:5:9
|
LL | bar(foo);
- | --- ^^^ expected `usize`, found array `[u8; 4]`
+ | --- ^^^ expected `usize`, found `[u8; 4]`
| |
| arguments to this function are incorrect
|
--> $DIR/issue-48364.rs:2:21
|
LL | b"".starts_with(stringify!(foo))
- | ----------- ^^^^^^^^^^^^^^^ expected slice `[u8]`, found `str`
+ | ----------- ^^^^^^^^^^^^^^^ expected `&[u8]`, found `&str`
| |
| arguments to this method are incorrect
|
//~^ ERROR mismatched types
//~| expected type `{integer}`
//~| found tuple `(isize, isize)`
- //~| expected integer, found tuple
+ //~| expected integer, found `(isize, isize)`
}
LL | match 42 { A => () }
| -- ^
| | |
- | | expected integer, found tuple
+ | | expected integer, found `(isize, isize)`
| | `A` is interpreted as a constant, not a new binding
| | help: introduce a new binding instead: `other_a`
| this expression has type `{integer}`
match (true, false) {
A::B => (),
//~^ ERROR mismatched types
-//~| expected tuple, found enum `A`
+//~| expected `(bool, bool)`, found `A`
//~| expected tuple `(bool, bool)`
//~| found enum `A`
_ => ()
match (true, false) {
&(true, false) => ()
//~^ ERROR mismatched types
-//~| expected tuple, found reference
+//~| expected `(bool, bool)`, found `&_`
//~| expected tuple `(bool, bool)`
//~| found reference `&_`
}
LL | match (true, false) {
| ------------- this expression has type `(bool, bool)`
LL | A::B => (),
- | ^^^^ expected tuple, found enum `A`
+ | ^^^^ expected `(bool, bool)`, found `A`
|
= note: expected tuple `(bool, bool)`
found enum `A`
LL | match (true, false) {
| ------------- this expression has type `(bool, bool)`
LL | box (true, false) => ()
- | ^^^^^^^^^^^^^^^^^ expected tuple, found struct `Box`
+ | ^^^^^^^^^^^^^^^^^ expected `(bool, bool)`, found `Box<_>`
|
= note: expected tuple `(bool, bool)`
found struct `Box<_>`
LL | match (true, false) {
| ------------- this expression has type `(bool, bool)`
LL | &(true, false) => ()
- | ^^^^^^^^^^^^^^ expected tuple, found reference
+ | ^^^^^^^^^^^^^^ expected `(bool, bool)`, found `&_`
|
= note: expected tuple `(bool, bool)`
found reference `&_`
*foo = 32;
//~^ ERROR cannot assign to `*foo`, which is behind a `&` reference
let bar = foo;
+ //~^ HELP consider specifying this binding's type
*bar = 64;
//~^ ERROR cannot assign to `*bar`, which is behind a `&` reference
}
| ~~~~~~~
error[E0594]: cannot assign to `*bar`, which is behind a `&` reference
- --> $DIR/issue-51515.rs:8:5
+ --> $DIR/issue-51515.rs:9:5
|
-LL | let bar = foo;
- | --- consider changing this binding's type to be: `&mut i32`
LL | *bar = 64;
| ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider specifying this binding's type
+ |
+LL | let bar: &mut i32 = foo;
+ | ++++++++++
error: aborting due to 2 previous errors
--> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5
|
LL | missing_discourses()?
- | ^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `isize`
+ | ^^^^^^^^^^^^^^^^^^^^^ expected `Result<isize, ()>`, found `isize`
|
= note: `?` operator cannot convert from `isize` to `Result<isize, ()>`
= note: expected enum `Result<isize, ()>`
for i in v {
a = *i.to_string();
//~^ ERROR mismatched types
- //~| NOTE expected struct `String`, found `str`
+ //~| NOTE expected `String`, found `str`
v2.push(a);
}
}
| ------------- expected due to this value
LL | for i in v {
LL | a = *i.to_string();
- | ^^^^^^^^^^^^^^ expected struct `String`, found `str`
+ | ^^^^^^^^^^^^^^ expected `String`, found `str`
error: aborting due to previous error
match S(Either::Left(5)) {
Either::Right(_) => {}
//~^ ERROR mismatched types
- //~| expected struct `S`, found enum `Either`
+ //~| expected `S`, found `Either<_, _>`
//~| expected struct `S`
//~| found enum `Either<_, _>`
_ => {}
LL | match S(Either::Left(5)) {
| ------------------ this expression has type `S`
LL | Either::Right(_) => {}
- | ^^^^^^^^^^^^^^^^ expected struct `S`, found enum `Either`
+ | ^^^^^^^^^^^^^^^^ expected `S`, found `Either<_, _>`
|
= note: expected struct `S`
found enum `Either<_, _>`
--> $DIR/issue-56943.rs:6:29
|
LL | let _: issue_56943::S = issue_56943::S2;
- | -------------- ^^^^^^^^^^^^^^^ expected struct `S`, found struct `S2`
+ | -------------- ^^^^^^^^^^^^^^^ expected `S`, found `S2`
| |
| expected due to this
-error[E0599]: the function or associated item `make_g` exists for fn pointer `for<'a> fn(&'a ())`, but its trait bounds were not satisfied
+error[E0599]: the function or associated item `make_g` exists for fn pointer `fn(&())`, but its trait bounds were not satisfied
--> $DIR/issue-57362-2.rs:22:25
|
LL | let x = <fn (&())>::make_g();
- | ^^^^^^ function or associated item cannot be called on `for<'a> fn(&'a ())` due to unsatisfied trait bounds
+ | ^^^^^^ function or associated item cannot be called on `fn(&())` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`for<'a> fn(&'a ()): X`
LL | let y = match x {
| - this expression has type `Box<u32>`
LL | S::A { a } | S::B { b: a } => a,
- | ^^^^^^^^^^ expected struct `Box`, found enum `S`
+ | ^^^^^^^^^^ expected `Box<u32>`, found `S`
|
= note: expected struct `Box<u32>`
found enum `S`
LL | let y = match x {
| - this expression has type `Box<u32>`
LL | S::A { a } | S::B { b: a } => a,
- | ^^^^^^^^^^^^^ expected struct `Box`, found enum `S`
+ | ^^^^^^^^^^^^^ expected `Box<u32>`, found `S`
|
= note: expected struct `Box<u32>`
found enum `S`
| this expression has type `Box<T>`
| help: consider dereferencing the boxed value: `*x`
LL | T::A(a) | T::B(a) => a,
- | ^^^^^^^ expected struct `Box`, found enum `T`
+ | ^^^^^^^ expected `Box<T>`, found `T`
|
= note: expected struct `Box<T>`
found enum `T`
| this expression has type `Box<T>`
| help: consider dereferencing the boxed value: `*x`
LL | T::A(a) | T::B(a) => a,
- | ^^^^^^^ expected struct `Box`, found enum `T`
+ | ^^^^^^^ expected `Box<T>`, found `T`
|
= note: expected struct `Box<T>`
found enum `T`
| this expression has type `Box<S>`
| help: consider dereferencing the boxed value: `*x`
LL | S::A { a } | S::B { b: a } => a,
- | ^^^^^^^^^^ expected struct `Box`, found enum `S`
+ | ^^^^^^^^^^ expected `Box<S>`, found `S`
|
= note: expected struct `Box<S>`
found enum `S`
| this expression has type `Box<S>`
| help: consider dereferencing the boxed value: `*x`
LL | S::A { a } | S::B { b: a } => a,
- | ^^^^^^^^^^^^^ expected struct `Box`, found enum `S`
+ | ^^^^^^^^^^^^^ expected `Box<S>`, found `S`
|
= note: expected struct `Box<S>`
found enum `S`
--> $DIR/issue-59488.rs:14:11
|
LL | foo > 12;
- | ^^ expected fn item, found integer
+ | ^^ expected fn item, found `i32`
|
= note: expected fn item `fn() -> i32 {foo}`
found type `i32`
--> $DIR/issue-59488.rs:18:11
|
LL | bar > 13;
- | ^^ expected fn item, found integer
+ | ^^ expected fn item, found `i64`
|
= note: expected fn item `fn(i64) -> i64 {bar}`
found type `i64`
LL | foo(x.clone());
| --- ^^^^^^^^^
| | |
- | | expected `&str`, found struct `String`
+ | | expected `&str`, found `String`
| | help: consider borrowing here: `&x`
| arguments to this function are incorrect
|
--> $DIR/issue-6458-4.rs:1:20
|
LL | fn foo(b: bool) -> Result<bool,String> {
- | --- ^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `()`
+ | --- ^^^^^^^^^^^^^^^^^^^ expected `Result<bool, String>`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
LL | Err("bar".to_string());
--> $DIR/issue-67039-unsound-pin-partialeq.rs:25:29
|
LL | let _ = Pin::new(Apple) == Rc::pin(Apple);
- | ^^ expected struct `Apple`, found struct `Rc`
+ | ^^ expected `Apple`, found `Rc<Apple>`
|
= note: expected struct `Apple`
found struct `Rc<Apple>`
LL | impl<T> S0<T> {
| - this type parameter
LL | const C: S0<u8> = Self(0);
- | ^^^^^^^ expected `u8`, found type parameter `T`
+ | ^^^^^^^ expected `S0<u8>`, found `S0<T>`
|
= note: expected struct `S0<u8>`
found struct `S0<T>`
LL | impl<T> S1<T, u8> {
| - this type parameter
LL | const C: S1<u8, u8> = Self(0, 1);
- | ^^^^^^^^^^ expected `u8`, found type parameter `T`
+ | ^^^^^^^^^^ expected `S1<u8, u8>`, found `S1<T, u8>`
|
= note: expected struct `S1<u8, _>`
found struct `S1<T, _>`
| |
| expected type parameter
LL | Self(x)
- | ^^^^^^^ expected type parameter `U`, found type parameter `T`
+ | ^^^^^^^ expected `S2<U>`, found `S2<T>`
|
= note: expected struct `S2<U>`
found struct `S2<T>`
--> $DIR/issue-7061.rs:4:46
|
LL | fn foo(&'a mut self) -> Box<BarStruct> { self }
- | -------------- ^^^^ expected struct `Box`, found `&mut BarStruct`
+ | -------------- ^^^^ expected `Box<BarStruct>`, found `&mut BarStruct`
| |
| expected `Box<BarStruct>` because of return type
|
match x {
Some(field) =>
//~^ ERROR mismatched types
-//~| expected enum `Whatever`, found enum `Option`
+//~| expected `Whatever`, found `Option<_>`
//~| expected enum `Whatever`
//~| found enum `Option<_>`
field.access(),
LL | match x {
| - this expression has type `Whatever`
LL | Some(field) =>
- | ^^^^^^^^^^^ expected enum `Whatever`, found enum `Option`
+ | ^^^^^^^^^^^ expected `Whatever`, found `Option<_>`
|
= note: expected enum `Whatever`
found enum `Option<_>`
--> $DIR/issue-71676-1.rs:43:24
|
LL | let _: *const u8 = &a;
- | --------- ^^ expected `u8`, found struct `Emm`
+ | --------- ^^ expected `*const u8`, found `&Emm`
| |
| expected due to this
|
--> $DIR/issue-71676-1.rs:49:24
|
LL | let _: *const u8 = &mut a;
- | --------- ^^^^^^ expected `u8`, found struct `Emm`
+ | --------- ^^^^^^ expected `*const u8`, found `&mut Emm`
| |
| expected due to this
|
--> $DIR/issue-71676-1.rs:52:22
|
LL | let _: *mut u8 = &mut a;
- | ------- ^^^^^^ expected `u8`, found struct `Emm`
+ | ------- ^^^^^^ expected `*mut u8`, found `&mut Emm`
| |
| expected due to this
|
LL | let () = dep::Renamed;
| ^^ ------------ this expression has type `Renamed`
| |
- | expected struct `Renamed`, found `()`
+ | expected `Renamed`, found `()`
error: aborting due to previous error
LL | RANGE => {}
| ^^^^^
| |
- | expected `i32`, found struct `RangeInclusive`
+ | expected `i32`, found `RangeInclusive<i32>`
| `RANGE` is interpreted as a constant, not a new binding
|
= note: expected type `i32`
LL | RANGE2 => {}
| ^^^^^^
| |
- | expected `i32`, found struct `RangeInclusive`
+ | expected `i32`, found `RangeInclusive<i32>`
| `RANGE2` is interpreted as a constant, not a new binding
|
= note: expected type `i32`
match (true, false) {
A::B => (),
//~^ ERROR mismatched types
- //~| expected tuple, found enum `A`
+ //~| expected `(bool, bool)`, found `A`
//~| expected tuple `(bool, bool)`
//~| found enum `A`
_ => ()
LL | match (true, false) {
| ------------- this expression has type `(bool, bool)`
LL | A::B => (),
- | ^^^^ expected tuple, found enum `A`
+ | ^^^^ expected `(bool, bool)`, found `A`
|
= note: expected tuple `(bool, bool)`
found enum `A`
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":612,"byte_end":618,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":622,"byte_end":622,"line_start":17,"line_end":17,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":612,"byte_end":618,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":622,"byte_end":622,"line_start":17,"line_end":17,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types
"}
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":672,"byte_end":678,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":682,"byte_end":682,"line_start":19,"line_end":19,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":672,"byte_end":678,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":682,"byte_end":682,"line_start":19,"line_end":19,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types
"}
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":735,"byte_end":741,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":746,"byte_end":746,"line_start":23,"line_end":23,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":735,"byte_end":741,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":746,"byte_end":746,"line_start":23,"line_end":23,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types
"}
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":801,"byte_end":809,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":792,"byte_end":798,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":801,"byte_end":809,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":792,"byte_end":798,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types
"}
{"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors
"}
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":597,"byte_end":603,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":607,"byte_end":607,"line_start":16,"line_end":16,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":597,"byte_end":603,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":607,"byte_end":607,"line_start":16,"line_end":16,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types
"}
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":657,"byte_end":663,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":667,"byte_end":667,"line_start":18,"line_end":18,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":657,"byte_end":663,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":667,"byte_end":667,"line_start":18,"line_end":18,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types
"}
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":720,"byte_end":726,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":731,"byte_end":731,"line_start":22,"line_end":22,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":720,"byte_end":726,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":731,"byte_end":731,"line_start":22,"line_end":22,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types
"}
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":786,"byte_end":794,"line_start":24,"line_end":25,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":777,"byte_end":783,"line_start":24,"line_end":24,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:24:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":786,"byte_end":794,"line_start":24,"line_end":25,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":777,"byte_end":783,"line_start":24,"line_end":24,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:24:22: error[E0308]: mismatched types
"}
{"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors
"}
|
= help: the trait `Send` is not implemented for `(dyn Dummy + 'a)`
= note: required for `Unique<(dyn Dummy + 'a)>` to implement `Send`
- = note: required because it appears within the type `Box<(dyn Dummy + 'a)>`
+ = note: required because it appears within the type `Box<dyn Dummy>`
note: required by a bound in `assert_send`
--> $DIR/kindck-send-object1.rs:5:18
|
+++ /dev/null
-// error-pattern: requires `generator` lang_item
-#![feature(no_core, lang_items, unboxed_closures, tuple_trait)]
-#![no_core]
-
-#[lang = "sized"] pub trait Sized { }
-
-#[lang = "tuple_trait"] pub trait Tuple { }
-
-#[lang = "fn_once"]
-#[rustc_paren_sugar]
-pub trait FnOnce<Args: Tuple> {
- type Output;
-
- extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
-}
-
-pub fn abc() -> impl FnOnce(f32) {
- |_| {}
-}
-
-fn main() {}
+++ /dev/null
-error[E0635]: unknown feature `tuple_trait`
- --> $DIR/lang-item-missing-generator.rs:2:51
- |
-LL | #![feature(no_core, lang_items, unboxed_closures, tuple_trait)]
- | ^^^^^^^^^^^
-
-error: requires `generator` lang_item
- --> $DIR/lang-item-missing-generator.rs:17:17
- |
-LL | pub fn abc() -> impl FnOnce(f32) {
- | ^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0635`.
LL | if let Some(y) = x else {
| ^
help: remove the `if` if you meant to write a `let...else` statement
- --> $DIR/accidental-if.rs:3:5
|
-LL | if let Some(y) = x else {
- | ^^
+LL - if let Some(y) = x else {
+LL + let Some(y) = x else {
+ |
error: aborting due to previous error
--> $DIR/issue-94176.rs:5:32
|
LL | pub fn test(a: Option<u32>) -> Option<u32> {
- | ---- ^^^^^^^^^^^ expected enum `Option`, found `()`
+ | ---- ^^^^^^^^^^^ expected `Option<u32>`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
|
LL | let Bar::Present(z) = self else {
| ^^^^^^^^^^^^^^^ ---- this expression has type `&mut Foo`
| |
- | expected struct `Foo`, found enum `Bar`
+ | expected `Foo`, found `Bar`
error[E0308]: mismatched types
--> $DIR/let-else-deref-coercion.rs:68:13
LL | let Bar(z) = x;
| ^^^^^^ - this expression has type `&mut irrefutable::Foo`
| |
- | expected struct `Foo`, found struct `Bar`
+ | expected `Foo`, found `Bar`
error: aborting due to 2 previous errors
| ________________________________^
LL | | Some(2)
LL | | };
- | |_____^ expected `!`, found enum `Option`
+ | |_____^ expected `!`, found `Option<{integer}>`
|
= note: expected type `!`
found enum `Option<{integer}>`
--> $DIR/let-else-non-diverging.rs:10:32
|
LL | let Some(x) = Some(1) else { Some(2) };
- | ^^^^^^^^^^^ expected `!`, found enum `Option`
+ | ^^^^^^^^^^^ expected `!`, found `Option<{integer}>`
|
= note: expected type `!`
found enum `Option<{integer}>`
--> $DIR/let-else-non-diverging.rs:15:32
|
LL | let Some(x) = Some(1) else { foo::<Uninhabited>() };
- | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `!`, found enum `Uninhabited`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `!`, found `Uninhabited`
|
= note: expected type `!`
found enum `Uninhabited`
--> $DIR/let-else-ref-bindings.rs:16:38
|
LL | let Some(ref a): Option<&[u8]> = some else { return };
- | ^^^^ expected `&[u8]`, found struct `Vec`
+ | ^^^^ expected `Option<&[u8]>`, found `Option<Vec<u8>>`
|
= note: expected enum `Option<&[u8]>`
found enum `Option<Vec<u8>>`
--> $DIR/let-else-ref-bindings.rs:20:38
|
LL | let Some(ref a): Option<&[u8]> = &some else { return };
- | ^^^^^ expected enum `Option`, found `&Option<Vec<u8>>`
+ | ^^^^^ expected `Option<&[u8]>`, found `&Option<Vec<u8>>`
|
= note: expected enum `Option<&[u8]>`
found reference `&Option<Vec<u8>>`
--> $DIR/let-else-ref-bindings.rs:24:34
|
LL | let Some(a): Option<&[u8]> = some else { return };
- | ------------- ^^^^ expected `&[u8]`, found struct `Vec`
+ | ------------- ^^^^ expected `Option<&[u8]>`, found `Option<Vec<u8>>`
| |
| expected due to this
|
--> $DIR/let-else-ref-bindings.rs:27:34
|
LL | let Some(a): Option<&[u8]> = &some else { return };
- | ------------- ^^^^^ expected enum `Option`, found `&Option<Vec<u8>>`
+ | ------------- ^^^^^ expected `Option<&[u8]>`, found `&Option<Vec<u8>>`
| |
| expected due to this
|
--> $DIR/let-else-ref-bindings.rs:44:46
|
LL | let Some(ref mut a): Option<&mut [u8]> = some else { return };
- | ^^^^ expected `&mut [u8]`, found struct `Vec`
+ | ^^^^ expected `Option<&mut [u8]>`, found `Option<Vec<u8>>`
|
= note: expected enum `Option<&mut [u8]>`
found enum `Option<Vec<u8>>`
--> $DIR/let-else-ref-bindings.rs:48:46
|
LL | let Some(ref mut a): Option<&mut [u8]> = &mut some else { return };
- | ^^^^^^^^^ expected enum `Option`, found mutable reference
+ | ^^^^^^^^^ expected `Option<&mut [u8]>`, found `&mut Option<Vec<u8>>`
|
= note: expected enum `Option<&mut [u8]>`
found mutable reference `&mut Option<Vec<u8>>`
--> $DIR/let-else-ref-bindings.rs:52:38
|
LL | let Some(a): Option<&mut [u8]> = some else { return };
- | ----------------- ^^^^ expected `&mut [u8]`, found struct `Vec`
+ | ----------------- ^^^^ expected `Option<&mut [u8]>`, found `Option<Vec<u8>>`
| |
| expected due to this
|
--> $DIR/let-else-ref-bindings.rs:55:38
|
LL | let Some(a): Option<&mut [u8]> = &mut some else { return };
- | ----------------- ^^^^^^^^^ expected enum `Option`, found mutable reference
+ | ----------------- ^^^^^^^^^ expected `Option<&mut [u8]>`, found `&mut Option<Vec<u8>>`
| |
| expected due to this
|
--- /dev/null
+pub struct DefaultLifetime<'a, 'b = 'static> {
+ //~^ ERROR unexpected default lifetime parameter
+ _marker: std::marker::PhantomData<&'a &'b ()>,
+}
+
+fn main(){}
--- /dev/null
+error: unexpected default lifetime parameter
+ --> $DIR/issue-107492-default-value-for-lifetime.rs:1:35
+ |
+LL | pub struct DefaultLifetime<'a, 'b = 'static> {
+ | ^^^^^^^^^ lifetime parameters cannot have default values
+
+error: aborting due to previous error
+
LL | | "down" => RoomDirection::Down,
| | ------------------- this and all prior arms are found to be of type `RoomDirection`
LL | | _ => None
- | | ^^^^ expected enum `RoomDirection`, found enum `Option`
+ | | ^^^^ expected `RoomDirection`, found `Option<_>`
LL | | }
| |_____- `match` arms have incompatible types
|
--> $DIR/issue-26638.rs:1:69
|
LL | fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
- | ---- ^^^^^^^^^^^ expected `&str`, found enum `Option`
+ | ---- ^^^^^^^^^^^ expected `&str`, found `Option<&str>`
| |
| expected `&'static str` because of return type
|
--> $DIR/issue-26638.rs:5:47
|
LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
- | ---- ^^^^^^ expected `str`, found `u8`
+ | ---- ^^^^^^ expected `&str`, found `&u8`
| |
| expected `&'static str` because of return type
|
--> $DIR/tuple-mismatch.rs:6:20
|
LL | yield ((), ());
- | ^^ expected tuple, found `()`
+ | ^^ expected `((), ())`, found `()`
|
= note: expected tuple `((), ())`
found unit type `()`
-#![deny(unaligned_references)]
-
#[repr(packed)]
pub struct Good {
data: u64,
let good = Good { data: 0, ptr: &0, data2: [0, 0], aligned: [0; 32] };
let _ = &good.ptr; //~ ERROR reference to packed field
- //~^ previously accepted
let _ = &good.data; //~ ERROR reference to packed field
- //~^ previously accepted
// Error even when turned into raw pointer immediately.
let _ = &good.data as *const _; //~ ERROR reference to packed field
- //~^ previously accepted
let _: *const _ = &good.data; //~ ERROR reference to packed field
- //~^ previously accepted
// Error on method call.
let _ = good.data.clone(); //~ ERROR reference to packed field
- //~^ previously accepted
// Error for nested fields.
let _ = &good.data2[0]; //~ ERROR reference to packed field
- //~^ previously accepted
let _ = &*good.ptr; // ok, behind a pointer
let _ = &good.aligned; // ok, has align 1
unsafe {
let packed2 = Packed2 { x: 0, y: 0, z: 0 };
let _ = &packed2.x; //~ ERROR reference to packed field
- //~^ previously accepted
let _ = &packed2.y; // ok, has align 2 in packed(2) struct
let _ = &packed2.z; // ok, has align 1
}
},
);
let _ref = &m1.1.a; //~ ERROR reference to packed field
- //~^ previously accepted
let m2 = Misalign(
0,
},
);
let _ref = &m2.1.a; //~ ERROR reference to packed field
- //~^ previously accepted
}
}
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:22:17
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:20:17
|
LL | let _ = &good.ptr;
| ^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:24:17
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:21:17
|
LL | let _ = &good.data;
| ^^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:27:17
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:23:17
|
LL | let _ = &good.data as *const _;
| ^^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:29:27
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:24:27
|
LL | let _: *const _ = &good.data;
| ^^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:32:17
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:26:17
|
LL | let _ = good.data.clone();
| ^^^^^^^^^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:35:17
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:28:17
|
LL | let _ = &good.data2[0];
| ^^^^^^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:45:17
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:37:17
|
LL | let _ = &packed2.x;
| ^^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:90:20
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:81:20
|
LL | let _ref = &m1.1.a;
| ^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:100:20
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:90:20
|
LL | let _ref = &m2.1.a;
| ^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error: aborting due to 9 previous errors
-Future incompatibility report: Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:22:17
- |
-LL | let _ = &good.ptr;
- | ^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:24:17
- |
-LL | let _ = &good.data;
- | ^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:27:17
- |
-LL | let _ = &good.data as *const _;
- | ^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:29:27
- |
-LL | let _: *const _ = &good.data;
- | ^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:32:17
- |
-LL | let _ = good.data.clone();
- | ^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:35:17
- |
-LL | let _ = &good.data2[0];
- | ^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:45:17
- |
-LL | let _ = &packed2.x;
- | ^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:90:20
- |
-LL | let _ref = &m1.1.a;
- | ^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:100:20
- |
-LL | let _ref = &m2.1.a;
- | ^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
+For more information about this error, try `rustc --explain E0793`.
extern crate unaligned_references_external_crate;
unaligned_references_external_crate::mac! { //~ERROR reference to packed field is unaligned
- //~^ previously accepted
#[repr(packed)]
pub struct X {
pub field: u16
-error: reference to packed field is unaligned
+error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references_external_macro.rs:5:1
|
LL | / unaligned_references_external_crate::mac! {
-LL | |
LL | | #[repr(packed)]
LL | | pub struct X {
LL | | pub field: u16
LL | | }
| |_^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references_external_macro.rs:5:1
- |
-LL | / unaligned_references_external_crate::mac! {
-LL | |
-LL | | #[repr(packed)]
-LL | | pub struct X {
-LL | | pub field: u16
-LL | | }
-LL | | }
- | |_^
= note: this error originates in the macro `unaligned_references_external_crate::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
-Future incompatibility report: Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references_external_macro.rs:5:1
- |
-LL | / unaligned_references_external_crate::mac! {
-LL | |
-LL | | #[repr(packed)]
-LL | | pub struct X {
-LL | | pub field: u16
-LL | | }
-LL | | }
- | |_^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references_external_macro.rs:5:1
- |
-LL | / unaligned_references_external_crate::mac! {
-LL | |
-LL | | #[repr(packed)]
-LL | | pub struct X {
-LL | | pub field: u16
-LL | | }
-LL | | }
- | |_^
- = note: this error originates in the macro `unaligned_references_external_crate::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
-
+For more information about this error, try `rustc --explain E0793`.
--- /dev/null
+// check-pass
+
+#![warn(unused_must_use)]
+#![feature(never_type)]
+
+use std::ops::Add;
+use std::ops::Sub;
+use std::ops::Mul;
+use std::ops::Div;
+use std::ops::Rem;
+
+fn main() {
+ let x = 2_u32;
+ (x.add(4), x.sub(4), x.mul(4), x.div(4), x.rem(4));
+
+ x.add(4); //~ WARN unused return value of `add` that must be used
+
+ x.sub(4); //~ WARN unused return value of `sub` that must be used
+
+ x.mul(4); //~ WARN unused return value of `mul` that must be used
+
+ x.div(4); //~ WARN unused return value of `div` that must be used
+
+ x.rem(4); //~ WARN unused return value of `rem` that must be used
+
+ println!("{}", x);
+}
--- /dev/null
+warning: unused return value of `add` that must be used
+ --> $DIR/issue-103320-must-use-ops.rs:16:5
+ |
+LL | x.add(4);
+ | ^^^^^^^^
+ |
+ = note: this returns the result of the operation, without modifying the original
+note: the lint level is defined here
+ --> $DIR/issue-103320-must-use-ops.rs:3:9
+ |
+LL | #![warn(unused_must_use)]
+ | ^^^^^^^^^^^^^^^
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = x.add(4);
+ | +++++++
+
+warning: unused return value of `sub` that must be used
+ --> $DIR/issue-103320-must-use-ops.rs:18:5
+ |
+LL | x.sub(4);
+ | ^^^^^^^^
+ |
+ = note: this returns the result of the operation, without modifying the original
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = x.sub(4);
+ | +++++++
+
+warning: unused return value of `mul` that must be used
+ --> $DIR/issue-103320-must-use-ops.rs:20:5
+ |
+LL | x.mul(4);
+ | ^^^^^^^^
+ |
+ = note: this returns the result of the operation, without modifying the original
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = x.mul(4);
+ | +++++++
+
+warning: unused return value of `div` that must be used
+ --> $DIR/issue-103320-must-use-ops.rs:22:5
+ |
+LL | x.div(4);
+ | ^^^^^^^^
+ |
+ = note: this returns the result of the operation, without modifying the original
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = x.div(4);
+ | +++++++
+
+warning: unused return value of `rem` that must be used
+ --> $DIR/issue-103320-must-use-ops.rs:24:5
+ |
+LL | x.rem(4);
+ | ^^^^^^^^
+ |
+ = note: this returns the result of the operation, without modifying the original
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = x.rem(4);
+ | +++++++
+
+warning: 5 warnings emitted
+
--- /dev/null
+#[deny(unused)]
+fn main() {
+ let arr = [0; 10];
+ let _ = arr[(0)]; //~ ERROR unnecessary parentheses around index expression
+ let _ = arr[{0}]; //~ ERROR unnecessary braces around index expression
+ let _ = arr[1 + (0)];
+ let _ = arr[{ let x = 0; x }];
+}
--- /dev/null
+error: unnecessary parentheses around index expression
+ --> $DIR/issue-96606.rs:4:17
+ |
+LL | let _ = arr[(0)];
+ | ^ ^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-96606.rs:1:8
+ |
+LL | #[deny(unused)]
+ | ^^^^^^
+ = note: `#[deny(unused_parens)]` implied by `#[deny(unused)]`
+help: remove these parentheses
+ |
+LL - let _ = arr[(0)];
+LL + let _ = arr[0];
+ |
+
+error: unnecessary braces around index expression
+ --> $DIR/issue-96606.rs:5:17
+ |
+LL | let _ = arr[{0}];
+ | ^ ^
+ |
+ = note: `#[deny(unused_braces)]` implied by `#[deny(unused)]`
+help: remove these braces
+ |
+LL - let _ = arr[{0}];
+LL + let _ = arr[0];
+ |
+
+error: aborting due to 2 previous errors
+
--> $DIR/loop-break-value.rs:80:15
|
LL | break (break, break);
- | ^^^^^^^^^^^^^^ expected `()`, found tuple
+ | ^^^^^^^^^^^^^^ expected `()`, found `(!, !)`
|
= note: expected unit type `()`
found tuple `(!, !)`
--- /dev/null
+// check that we don't generate a span that points beyond EOF
+
+// error-pattern: unclosed delimiter
+// error-pattern: unclosed delimiter
+// error-pattern: unclosed delimiter
+
+fn a(){{{
--- /dev/null
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-107423-unused-delim-only-one-no-pair.rs:7:11
+ |
+LL | fn a(){{{
+ | --- ^
+ | |||
+ | ||unclosed delimiter
+ | |unclosed delimiter
+ | unclosed delimiter
+
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-107423-unused-delim-only-one-no-pair.rs:7:11
+ |
+LL | fn a(){{{
+ | --- ^
+ | |||
+ | ||unclosed delimiter
+ | |unclosed delimiter
+ | unclosed delimiter
+
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-107423-unused-delim-only-one-no-pair.rs:7:11
+ |
+LL | fn a(){{{
+ | --- ^
+ | |||
+ | ||unclosed delimiter
+ | |unclosed delimiter
+ | unclosed delimiter
+
+error: aborting due to 3 previous errors
+
LL | match t {
| - this expression has type `Result<_, {integer}>`
LL | Some(k) => match k {
- | ^^^^^^^ expected enum `Result`, found enum `Option`
+ | ^^^^^^^ expected `Result<_, {integer}>`, found `Option<_>`
|
= note: expected enum `Result<_, {integer}>`
found enum `Option<_>`
| - this expression has type `Result<_, {integer}>`
...
LL | None => ()
- | ^^^^ expected enum `Result`, found enum `Option`
+ | ^^^^ expected `Result<_, {integer}>`, found `Option<_>`
|
= note: expected enum `Result<_, {integer}>`
found enum `Option<_>`
LL | match array {
| ----- this expression has type `[S; 1]`
LL | [()] => {}
- | ^^ expected struct `S`, found `()`
+ | ^^ expected `S`, found `()`
error: aborting due to previous error
match (S { a: 1 }) {
E::C(_) => (),
//~^ ERROR mismatched types
- //~| expected struct `S`, found enum `E`
+ //~| expected `S`, found `E`
_ => ()
}
}
LL | match (S { a: 1 }) {
| ------------ this expression has type `S`
LL | E::C(_) => (),
- | ^^^^^^^ expected struct `S`, found enum `E`
+ | ^^^^^^^ expected `S`, found `E`
error: aborting due to previous error
| - unit variant defined here
LL |
LL | fn main() { let x: A = A::A; match x { B::B => { } } }
- | - ^^^^ expected enum `A`, found enum `B`
+ | - ^^^^ expected `A`, found `B`
| |
| this expression has type `A`
--> $DIR/match-tag-unary.rs:4:43
|
LL | fn main() { let x: A = A::A(0); match x { B::B(y) => { } } }
- | - ^^^^^^^ expected enum `A`, found enum `B`
+ | - ^^^^^^^ expected `A`, found `B`
| |
| this expression has type `A`
--> $DIR/issue-61525.rs:14:33
|
LL | 1.query::<dyn ToString>("")
- | --------------------- ^^ expected trait object `dyn ToString`, found `&str`
+ | --------------------- ^^ expected `dyn ToString`, found `&str`
| |
| arguments to this method are incorrect
|
--> $DIR/issue-90315.rs:28:8
|
LL | if 1..(end + 1).is_empty() {
- | ^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<{integer}>`
|
= note: expected type `bool`
found struct `std::ops::Range<{integer}>`
--> $DIR/issue-90315.rs:34:8
|
LL | if 1..(end + 1).is_sorted() {
- | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<{integer}>`
|
= note: expected type `bool`
found struct `std::ops::Range<{integer}>`
--> $DIR/issue-90315.rs:40:21
|
LL | let _res: i32 = 3..6.take(2).sum();
- | --- ^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `Range`
+ | --- ^^^^^^^^^^^^^^^^^^ expected `i32`, found `Range<{integer}>`
| |
| expected due to this
|
--> $DIR/issue-90315.rs:45:21
|
LL | let _sum: i32 = 3..6.sum();
- | --- ^^^^^^^^^^ expected `i32`, found struct `Range`
+ | --- ^^^^^^^^^^ expected `i32`, found `Range<{integer}>`
| |
| expected due to this
|
--> $DIR/issue-90315.rs:62:8
|
LL | if 1..end.error_method() {
- | ^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<{integer}>`
|
= note: expected type `bool`
found struct `std::ops::Range<{integer}>`
fn main() {
let x = Foo;
Foo::bar(x); //~ ERROR mismatched types
- //~| expected `&Foo`, found struct `Foo`
+ //~| expected `&Foo`, found `Foo`
Foo::bar(&42); //~ ERROR mismatched types
- //~| expected struct `Foo`, found integer
+ //~| expected `&Foo`, found `&{integer}`
//~| expected reference `&Foo`
//~| found reference `&{integer}`
}
LL | Foo::bar(x);
| -------- ^
| | |
- | | expected `&Foo`, found struct `Foo`
+ | | expected `&Foo`, found `Foo`
| | help: consider borrowing here: `&x`
| arguments to this function are incorrect
|
--> $DIR/method-self-arg-1.rs:13:14
|
LL | Foo::bar(&42);
- | -------- ^^^ expected struct `Foo`, found integer
+ | -------- ^^^ expected `&Foo`, found `&{integer}`
| |
| arguments to this function are incorrect
|
LL | fn a() -> Foo {
| --- expected `Foo` because of return type
LL | Some(Foo { bar: 1 })
- | ^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `Option`
+ | ^^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option<Foo>`
|
= note: expected struct `Foo`
found enum `Option<Foo>`
LL | fn a2() -> Foo {
| --- expected `Foo` because of return type
LL | Ok(Foo { bar: 1})
- | ^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `Result`
+ | ^^^^^^^^^^^^^^^^^ expected `Foo`, found `Result<Foo, _>`
|
= note: expected struct `Foo`
found enum `Result<Foo, _>`
LL | fn b() -> Option<Foo> {
| ----------- expected `Option<Foo>` because of return type
LL | Foo { bar: 1 }
- | ^^^^^^^^^^^^^^ expected enum `Option`, found struct `Foo`
+ | ^^^^^^^^^^^^^^ expected `Option<Foo>`, found `Foo`
|
= note: expected enum `Option<Foo>`
found struct `Foo`
LL | fn c() -> Result<Foo, Bar> {
| ---------------- expected `Result<Foo, Bar>` because of return type
LL | Foo { bar: 1 }
- | ^^^^^^^^^^^^^^ expected enum `Result`, found struct `Foo`
+ | ^^^^^^^^^^^^^^ expected `Result<Foo, Bar>`, found `Foo`
|
= note: expected enum `Result<Foo, Bar>`
found struct `Foo`
| ---------------------------- expected `X<X<String, String>, String>` because of return type
...
LL | x
- | ^ expected struct `String`, found integer
+ | ^ expected `X<X<String, String>, String>`, found `X<X<String, {integer}>, {integer}>`
|
= note: expected struct `X<X<_, String>, String>`
found struct `X<X<_, {integer}>, {integer}>`
| ---------------------------- expected `X<X<String, String>, String>` because of return type
...
LL | x
- | ^ expected struct `String`, found integer
+ | ^ expected `X<X<String, String>, String>`, found `X<X<String, {integer}>, String>`
|
= note: expected struct `X<X<_, String>, _>`
found struct `X<X<_, {integer}>, _>`
LL | fn f() -> String {
| ------ expected `String` because of return type
LL | 1+2
- | ^^^ expected struct `String`, found integer
+ | ^^^ expected `String`, found integer
|
help: try using a conversion method
|
LL | fn g() -> String {
| ------ expected `String` because of return type
LL | -2
- | ^^ expected struct `String`, found integer
+ | ^^ expected `String`, found integer
|
help: try using a conversion method
|
| | - expected because of this
LL | | } else {
LL | | Y
- | | ^ expected struct `S`, found struct `Y`
+ | | ^ expected `S`, found `Y`
LL | | }
| |_____- `if` and `else` have incompatible types
LL | | true => S,
| | - this is found to be of type `S`
LL | | false => Y,
- | | ^ expected struct `S`, found struct `Y`
+ | | ^ expected `S`, found `Y`
LL | | }
| |_____- `match` arms have incompatible types
LL | match x {
| - this expression has type `&_S`
LL | _S(& (mut _y), _v) => {
- | ^^^^^^^^^^ expected `u32`, found reference
+ | ^^^^^^^^^^ expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
LL | fn bgh(&&bar: u32) {}
| ^^^^^ --- expected due to this
| |
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
LL | fn foo(&_a: Foo) {}
| ^^^ --- expected due to this
| |
- | expected struct `Foo`, found reference
+ | expected `Foo`, found `&_`
|
= note: expected struct `Foo`
found reference `&_`
LL | fn agh(&&_a: &u32) {}
| ^^^ ---- expected due to this
| |
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
--> $DIR/non_zero_assigned_something.rs:2:35
|
LL | let _: std::num::NonZeroU64 = 1;
- | -------------------- ^ expected struct `NonZeroU64`, found integer
+ | -------------------- ^ expected `NonZeroU64`, found integer
| |
| expected due to this
|
--> $DIR/non_zero_assigned_something.rs:6:43
|
LL | let _: Option<std::num::NonZeroU64> = 1;
- | ---------------------------- ^ expected enum `Option`, found integer
+ | ---------------------------- ^ expected `Option<NonZeroU64>`, found integer
| |
| expected due to this
|
--> $DIR/normalize-fn-sig.rs:14:22
|
LL | needs_i32_ref_fn(foo::<()>);
- | ---------------- ^^^^^^^^^ expected `&i32`, found `i32`
+ | ---------------- ^^^^^^^^^ expected fn pointer, found fn item
| |
| arguments to this function are incorrect
|
= note: expected fn pointer `fn(&'static i32, i32)`
found fn item `fn(i32, &'static i32) {foo::<()>}`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
note: function defined here
--> $DIR/normalize-fn-sig.rs:11:4
|
LL | fn _f0(&_a: u32) {}
| ^^^ --- expected due to this
| |
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
LL | fn _f2(&&_a: &u32) {}
| ^^^ ---- expected due to this
| |
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
LL | fn _f3(&mut &_a: &mut u32) {}
| ^^^ -------- expected due to this
| |
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
| ^--
| ||
| |expected due to this
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
| ^--
| ||
| |expected due to this
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
| ^--
| ||
| |expected due to this
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
LL | let _ = |&_a: u32| ();
| ^^^ --- expected due to this
| |
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
LL | let _ = |&&_a: &u32| ();
| ^^^ ---- expected due to this
| |
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
LL | let _ = |&mut &_a: &mut u32| ();
| ^^^ -------- expected due to this
| |
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
LL | fn foo() -> Foo {
| --- expected `baz::Foo` because of return type
LL | meh::Foo
- | ^^^^^^^^ expected struct `baz::Foo`, found struct `meh::Foo`
+ | ^^^^^^^^ expected `baz::Foo`, found `meh::Foo`
|
- = note: struct `meh::Foo` and struct `baz::Foo` have similar names, but are actually distinct types
-note: struct `meh::Foo` is defined in module `crate::meh` of the current crate
+ = note: `meh::Foo` and `baz::Foo` have similar names, but are actually distinct types
+note: `meh::Foo` is defined in module `crate::meh` of the current crate
--> $DIR/show_module.rs:8:5
|
LL | pub struct Foo;
| ^^^^^^^^^^^^^^
-note: struct `baz::Foo` is defined in module `crate::blah::baz` of the current crate
+note: `baz::Foo` is defined in module `crate::blah::baz` of the current crate
--> $DIR/show_module.rs:3:9
|
LL | pub struct Foo;
LL | pub fn foo() -> Option<u8> {
| ---------- expected `Option<u8>` because of return type
LL | Some(42_u8)
- | ^^^^^^^^^^^ expected enum `Option`, found enum `std::option::Option`
+ | ^^^^^^^^^^^ expected `Option<u8>`, found `std::option::Option<u8>`
|
- = note: enum `std::option::Option` and enum `Option` have similar names, but are actually distinct types
-note: enum `std::option::Option` is defined in crate `core`
+ = note: `std::option::Option<u8>` and `Option<u8>` have similar names, but are actually distinct types
+note: `std::option::Option<u8>` is defined in crate `core`
--> $SRC_DIR/core/src/option.rs:LL:COL
-note: enum `Option` is defined in the current crate
+note: `Option<u8>` is defined in the current crate
--> $DIR/similar_paths.rs:1:1
|
LL | enum Option<T> {
--> $DIR/similar_paths_primitive.rs:8:9
|
LL | foo(true);
- | --- ^^^^ expected struct `bool`, found `bool`
+ | --- ^^^^ expected `bool`, found a different `bool`
| |
| arguments to this function are incorrect
|
- = note: bool and struct `bool` have similar names, but are actually distinct types
+ = note: bool and `bool` have similar names, but are actually distinct types
= note: bool is a primitive defined by the language
-note: struct `bool` is defined in the current crate
+note: `bool` is defined in the current crate
--> $DIR/similar_paths_primitive.rs:3:1
|
LL | struct bool;
| | - expected because of this
LL | | } else {
LL | | Y
- | | ^ expected struct `S`, found struct `Y`
+ | | ^ expected `S`, found `Y`
LL | | }
| |_____- `if` and `else` have incompatible types
|
LL | | true => S,
| | - this is found to be of type `S`
LL | | false => Y,
- | | ^ expected struct `S`, found struct `Y`
+ | | ^ expected `S`, found `Y`
LL | | }
| |_____- `match` arms have incompatible types
|
--> $DIR/suggest-removing-tuple-struct-field.rs:11:13
|
LL | some_fn(value.0);
- | ------- ^^^^^^^ expected struct `MyWrapper`, found `u32`
+ | ------- ^^^^^^^ expected `MyWrapper`, found `u32`
| |
| arguments to this function are incorrect
|
--> $DIR/suggest-removing-tuple-struct-field.rs:12:13
|
LL | some_fn(my_wrapper!(123).0);
- | ------- ^^^^^^^^^^^^^^^^^^ expected struct `MyWrapper`, found `u32`
+ | ------- ^^^^^^^^^^^^^^^^^^ expected `MyWrapper`, found `u32`
| |
| arguments to this function are incorrect
|
--> $DIR/wrap-suggestion-privacy.rs:12:19
|
LL | needs_wrapper(0);
- | ------------- ^ expected struct `Wrapper`, found integer
+ | ------------- ^ expected `Wrapper<i32>`, found integer
| |
| arguments to this function are incorrect
|
--> $DIR/wrap-suggestion-privacy.rs:17:20
|
LL | needs_wrapping(0);
- | -------------- ^ expected struct `Wrapping`, found integer
+ | -------------- ^ expected `Wrapping<i32>`, found integer
| |
| arguments to this function are incorrect
|
--> $DIR/wrap-suggestion-privacy.rs:22:17
|
LL | needs_ready(Some(0));
- | ----------- ^^^^^^^ expected struct `Ready`, found enum `Option`
+ | ----------- ^^^^^^^ expected `Ready<i32>`, found `Option<{integer}>`
| |
| arguments to this function are incorrect
|
LL | f(x)
| - ^
| | |
- | | expected `&mut isize`, found struct `Box`
+ | | expected `&mut isize`, found `Box<{integer}>`
| | help: consider mutably borrowing here: `&mut x`
| arguments to this function are incorrect
|
--> $DIR/diverging-tuple-parts-39485.rs:8:5
|
LL | &panic!()
- | ^^^^^^^^^ expected `()`, found reference
+ | ^^^^^^^^^ expected `()`, found `&_`
|
= note: expected unit type `()`
found reference `&_`
LL | fn f() -> isize {
| ----- expected `isize` because of return type
LL | (return 1, return 2)
- | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found tuple
+ | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `(!, !)`
|
= note: expected type `isize`
found tuple `(!, !)`
//~^ ERROR mismatched types
//~| expected type `isize`
//~| found tuple `(!, !)`
-//~| expected `isize`, found tuple
+//~| expected `isize`, found `(!, !)`
}
fn main() {}
LL | fn f() -> isize {
| ----- expected `isize` because of return type
LL | (return 1, return 2)
- | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found tuple
+ | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `(!, !)`
|
= note: expected type `isize`
found tuple `(!, !)`
--> $DIR/issue-52443.rs:2:10
|
LL | [(); & { loop { continue } } ];
- | ^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference
+ | ^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_`
|
= note: expected type `usize`
found reference `&_`
LL | 0.....{loop{}1};
| ----^^^^^^^^^^^
| | |
- | | expected integer, found struct `RangeTo`
+ | | expected integer, found `RangeTo<{integer}>`
| arguments to this function are incorrect
|
= note: expected type `{integer}`
-error[E0599]: the function or associated item `make_g` exists for fn pointer `for<'a> fn(&'a ())`, but its trait bounds were not satisfied
+error[E0599]: the function or associated item `make_g` exists for fn pointer `fn(&())`, but its trait bounds were not satisfied
--> $DIR/issue-57642-higher-ranked-subtype.rs:31:25
|
LL | let x = <fn (&())>::make_g();
- | ^^^^^^ function or associated item cannot be called on `for<'a> fn(&'a ())` due to unsatisfied trait bounds
+ | ^^^^^^ function or associated item cannot be called on `fn(&())` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`for<'a> fn(&'a ()): X`
--> $DIR/issue-57642-higher-ranked-subtype.rs:35:25
|
LL | let x = <fn (&())>::make_f();
- | ^^^^^^ function or associated item not found in `for<'a> fn(&'a ())`
+ | ^^^^^^ function or associated item not found in `fn(&())`
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `Y` defines an item `make_f`, perhaps you need to implement it
//~^ ERROR mismatched types
//~| expected type `isize`
//~| found enum `Option<isize>`
- //~| expected `isize`, found enum `Option`
+ //~| expected `isize`, found `Option<isize>`
}
--> $DIR/noexporttypeexe.rs:10:18
|
LL | let x: isize = noexporttypelib::foo();
- | ----- ^^^^^^^^^^^^^^^^^^^^^^ expected `isize`, found enum `Option`
+ | ----- ^^^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `Option<isize>`
| |
| expected due to this
|
--> $DIR/object-pointer-types.rs:23:7
|
LL | x.managed();
- | ^^^^^^^ method not found in `Box<(dyn Foo + 'static)>`
+ | ^^^^^^^ method not found in `Box<dyn Foo>`
error: aborting due to 3 previous errors
LL | let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1));
| - ^ ------- this expression has type `E<E<{integer}>>`
| | |
- | | expected integer, found enum `E`
+ | | expected integer, found `E<{integer}>`
| first introduced with type `{integer}` here
|
= note: expected type `{integer}`
LL | let &A(_) | B(_): F = A(3);
| ^^^^^ - expected due to this
| |
- | expected enum `F`, found reference
+ | expected `F`, found `&_`
|
= note: expected enum `F`
found reference `&_`
LL | let &&A(_) | B(_): F = A(3);
| ^^^^^^ - expected due to this
| |
- | expected enum `F`, found reference
+ | expected `F`, found `&_`
|
= note: expected enum `F`
found reference `&_`
LL | let &mut A(_) | B(_): F = A(3);
| ^^^^^^^^^ - expected due to this
| |
- | expected enum `F`, found `&mut _`
+ | expected `F`, found `&mut _`
|
= note: expected enum `F`
found mutable reference `&mut _`
LL | let &&mut A(_) | B(_): F = A(3);
| ^^^^^^^^^^ - expected due to this
| |
- | expected enum `F`, found reference
+ | expected `F`, found `&_`
|
= note: expected enum `F`
found reference `&_`
+++ /dev/null
-// run-pass
-#![allow(dead_code)]
-#[repr(packed)]
-pub struct Good {
- data: &'static u32,
- data2: [&'static u32; 2],
- aligned: [u8; 32],
-}
-
-// kill this test when that turns to a hard error
-#[allow(unaligned_references)]
-fn main() {
- let good = Good { data: &0, data2: [&0, &0], aligned: [0; 32] };
-
- let _ = &good.data; // ok
- let _ = &good.data2[0]; // ok
-
- let _ = &good.data;
- let _ = &good.data2[0];
- let _ = &*good.data; // ok, behind a pointer
- let _ = &good.aligned; // ok, has align 1
- let _ = &good.aligned[2]; // ok, has align 1
-}
+++ /dev/null
-Future incompatibility report: Future breakage diagnostic:
-warning: reference to packed field is unaligned
- --> $DIR/issue-27060-rpass.rs:15:13
- |
-LL | let _ = &good.data; // ok
- | ^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/issue-27060-rpass.rs:11:9
- |
-LL | #[allow(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-warning: reference to packed field is unaligned
- --> $DIR/issue-27060-rpass.rs:16:13
- |
-LL | let _ = &good.data2[0]; // ok
- | ^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/issue-27060-rpass.rs:11:9
- |
-LL | #[allow(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-warning: reference to packed field is unaligned
- --> $DIR/issue-27060-rpass.rs:18:13
- |
-LL | let _ = &good.data;
- | ^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/issue-27060-rpass.rs:11:9
- |
-LL | #[allow(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-warning: reference to packed field is unaligned
- --> $DIR/issue-27060-rpass.rs:19:13
- |
-LL | let _ = &good.data2[0];
- | ^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/issue-27060-rpass.rs:11:9
- |
-LL | #[allow(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
};
let _ = &good.data; //~ ERROR reference to packed field
- //~| hard error
let _ = &good.data2[0]; //~ ERROR reference to packed field
- //~| hard error
let _ = &good.data; //~ ERROR reference to packed field
- //~| hard error
let _ = &good.data2[0]; //~ ERROR reference to packed field
- //~| hard error
let _ = &*good.data; // ok, behind a pointer
let _ = &good.aligned; // ok, has align 1
let _ = &good.aligned[2]; // ok, has align 1
-error: reference to packed field is unaligned
+error[E0793]: reference to packed field is unaligned
--> $DIR/issue-27060.rs:15:13
|
LL | let _ = &good.data;
| ^^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
-error: reference to packed field is unaligned
- --> $DIR/issue-27060.rs:17:13
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/issue-27060.rs:16:13
|
LL | let _ = &good.data2[0];
| ^^^^^^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-error: reference to packed field is unaligned
- --> $DIR/issue-27060.rs:20:13
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/issue-27060.rs:18:13
|
LL | let _ = &good.data;
| ^^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-error: reference to packed field is unaligned
- --> $DIR/issue-27060.rs:22:13
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/issue-27060.rs:19:13
|
LL | let _ = &good.data2[0];
| ^^^^^^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error: aborting due to 4 previous errors
-Future incompatibility report: Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/issue-27060.rs:15:13
- |
-LL | let _ = &good.data;
- | ^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
-
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/issue-27060.rs:17:13
- |
-LL | let _ = &good.data2[0];
- | ^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
-
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/issue-27060.rs:20:13
- |
-LL | let _ = &good.data;
- | ^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
-
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/issue-27060.rs:22:13
- |
-LL | let _ = &good.data2[0];
- | ^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
-
+For more information about this error, try `rustc --explain E0793`.
-// run-pass (note: this is spec-UB, but it works for now)
// ignore-32bit (needs `usize` to be 8-aligned to reproduce all the errors below)
#![allow(dead_code)]
// ignore-emscripten weird assertion?
baz: usize
}
-#[warn(unaligned_references)]
pub fn main() {
let foo = Foo4C { bar: 1, baz: 2 };
- let brw = &foo.baz; //~WARN reference to packed field is unaligned
- //~^ previously accepted
+ let brw = &foo.baz; //~ERROR reference to packed field is unaligned
assert_eq!(*brw, 2);
}
-warning: reference to packed field is unaligned
- --> $DIR/packed-struct-borrow-element-64bit.rs:15:15
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/packed-struct-borrow-element-64bit.rs:13:15
|
LL | let brw = &foo.baz;
| ^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/packed-struct-borrow-element-64bit.rs:12:8
- |
-LL | #[warn(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-warning: 1 warning emitted
-Future incompatibility report: Future breakage diagnostic:
-warning: reference to packed field is unaligned
- --> $DIR/packed-struct-borrow-element-64bit.rs:15:15
- |
-LL | let brw = &foo.baz;
- | ^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/packed-struct-borrow-element-64bit.rs:12:8
- |
-LL | #[warn(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
+error: aborting due to previous error
+For more information about this error, try `rustc --explain E0793`.
-// run-pass (note: this is spec-UB, but it works for now)
#![allow(dead_code)]
// ignore-emscripten weird assertion?
baz: usize
}
-#[warn(unaligned_references)]
pub fn main() {
let foo = Foo1 { bar: 1, baz: 2 };
- let brw = &foo.baz; //~WARN reference to packed field is unaligned
- //~^ previously accepted
+ let brw = &foo.baz; //~ERROR reference to packed field is unaligned
assert_eq!(*brw, 2);
let foo = Foo2 { bar: 1, baz: 2 };
- let brw = &foo.baz; //~WARN reference to packed field is unaligned
- //~^ previously accepted
+ let brw = &foo.baz; //~ERROR reference to packed field is unaligned
assert_eq!(*brw, 2);
}
-warning: reference to packed field is unaligned
- --> $DIR/packed-struct-borrow-element.rs:26:15
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/packed-struct-borrow-element.rs:24:15
|
LL | let brw = &foo.baz;
| ^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/packed-struct-borrow-element.rs:23:8
- |
-LL | #[warn(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-warning: reference to packed field is unaligned
- --> $DIR/packed-struct-borrow-element.rs:31:15
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/packed-struct-borrow-element.rs:28:15
|
LL | let brw = &foo.baz;
| ^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-warning: 2 warnings emitted
-
-Future incompatibility report: Future breakage diagnostic:
-warning: reference to packed field is unaligned
- --> $DIR/packed-struct-borrow-element.rs:26:15
- |
-LL | let brw = &foo.baz;
- | ^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/packed-struct-borrow-element.rs:23:8
- |
-LL | #[warn(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-warning: reference to packed field is unaligned
- --> $DIR/packed-struct-borrow-element.rs:31:15
- |
-LL | let brw = &foo.baz;
- | ^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/packed-struct-borrow-element.rs:23:8
- |
-LL | #[warn(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
+error: aborting due to 2 previous errors
+For more information about this error, try `rustc --explain E0793`.
--- /dev/null
+// check-pass
+
+macro_rules! test_expr {
+ ($expr:expr) => {};
+}
+
+macro_rules! test_ty {
+ ($a:ty | $b:ty) => {};
+}
+
+fn main() {
+ test_expr!(a as fn() -> B | C);
+ // Do not break the `|` operator.
+
+ test_expr!(|_: fn() -> B| C | D);
+ // Do not break `-> Ret` in closure args.
+
+ test_ty!(A | B);
+ // We can't support anon enums in arbitrary positions.
+
+ test_ty!(fn() -> A | B);
+ // Don't break fn ptrs.
+
+ test_ty!(impl Fn() -> A | B);
+ // Don't break parenthesized generics.
+}
+++ /dev/null
-fn foo(x: bool | i32) -> i32 | f64 {
-//~^ ERROR anonymous enums are not supported
-//~| ERROR anonymous enums are not supported
- match x {
- x: i32 => x, //~ ERROR expected
- true => 42.,
- false => 0.333,
- }
-}
-
-fn main() {
- match foo(true) {
- 42: i32 => (), //~ ERROR expected
- _: f64 => (), //~ ERROR expected
- x: i32 => (), //~ ERROR expected
- }
-}
+++ /dev/null
-error: anonymous enums are not supported
- --> $DIR/anon-enums.rs:1:16
- |
-LL | fn foo(x: bool | i32) -> i32 | f64 {
- | ---- ^ ---
- |
- = help: create a named `enum` and use it here instead:
- enum Name {
- Variant1(bool),
- Variant2(i32),
- }
-
-error: anonymous enums are not supported
- --> $DIR/anon-enums.rs:1:30
- |
-LL | fn foo(x: bool | i32) -> i32 | f64 {
- | --- ^ ---
- |
- = help: create a named `enum` and use it here instead:
- enum Name {
- Variant1(i32),
- Variant2(f64),
- }
-
-error: expected one of `@` or `|`, found `:`
- --> $DIR/anon-enums.rs:5:10
- |
-LL | x: i32 => x,
- | ^ --- specifying the type of a pattern isn't supported
- | |
- | expected one of `@` or `|`
- |
-help: maybe write a path separator here
- |
-LL | x::i32 => x,
- | ~~
-
-error: expected one of `...`, `..=`, `..`, or `|`, found `:`
- --> $DIR/anon-enums.rs:13:11
- |
-LL | 42: i32 => (),
- | ^ --- specifying the type of a pattern isn't supported
- | |
- | expected one of `...`, `..=`, `..`, or `|`
-
-error: expected `|`, found `:`
- --> $DIR/anon-enums.rs:14:10
- |
-LL | _: f64 => (),
- | ^ --- specifying the type of a pattern isn't supported
- | |
- | expected `|`
-
-error: expected one of `@` or `|`, found `:`
- --> $DIR/anon-enums.rs:15:10
- |
-LL | x: i32 => (),
- | ^ --- specifying the type of a pattern isn't supported
- | |
- | expected one of `@` or `|`
- |
-help: maybe write a path separator here
- |
-LL | x::i32 => (),
- | ~~
-
-error: aborting due to 6 previous errors
-
// See https://github.com/rust-lang/rust/pull/53562
// and https://github.com/rust-lang/rfcs/pull/2527
-// and https://twitter.com/garblefart/status/1393236602856611843
+// and https://web.archive.org/web/20211010063452/https://twitter.com/garblefart/status/1393236602856611843
// for context.
fn main() {
+++ /dev/null
-// build-pass
-macro_rules! check_ty {
- ($Z:ty) => { compile_error!("triggered"); };
- ($X:ty | $Y:ty) => { $X };
-}
-
-macro_rules! check {
- ($Z:ty) => { compile_error!("triggered"); };
- ($X:ty | $Y:ty) => { };
-}
-
-check! { i32 | u8 }
-
-fn foo(x: check_ty! { i32 | u8 }) -> check_ty! { i32 | u8 } {
- x
-}
-fn main() {
- let x: check_ty! { i32 | u8 } = 42;
- let _: check_ty! { i32 | u8 } = foo(x);
-}
|
LL | const async unsafe extern "C" fn ff5() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
- = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+ = note: ...which requires computing whether `main::ff5::{opaque#0}` is freeze...
+ = note: ...which requires evaluating trait selection obligation `main::ff5::{opaque#0}: core::marker::Freeze`...
= note: ...which again requires computing type of `main::ff5::{opaque#0}`, completing the cycle
note: cycle used when checking item types in top-level module
--> $DIR/fn-header-semantic-fail.rs:5:1
|
LL | const async unsafe extern "C" fn ft5() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
- = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+ = note: ...which requires computing whether `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5::{opaque#0}` is freeze...
+ = note: ...which requires evaluating trait selection obligation `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5::{opaque#0}: core::marker::Freeze`...
= note: ...which again requires computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5::{opaque#0}`, completing the cycle
note: cycle used when checking item types in top-level module
--> $DIR/fn-header-semantic-fail.rs:5:1
|
LL | const async unsafe extern "C" fn fi5() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
- = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+ = note: ...which requires computing whether `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 40:11>::fi5::{opaque#0}` is freeze...
+ = note: ...which requires evaluating trait selection obligation `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 40:11>::fi5::{opaque#0}: core::marker::Freeze`...
= note: ...which again requires computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 40:11>::fi5::{opaque#0}`, completing the cycle
note: cycle used when checking item types in top-level module
--> $DIR/fn-header-semantic-fail.rs:5:1
--> $DIR/issue-102806.rs:21:22
|
LL | let V3 { z: val, ... } = v;
- | ^^^ help: to omit remaining fields, use one fewer `.`: `..`
+ | ^^^
+ |
+help: to omit remaining fields, use `..`
+ |
+LL | let V3 { z: val, .. } = v;
+ | ~~
error[E0063]: missing fields `x` and `y` in initializer of `V3`
--> $DIR/issue-102806.rs:17:13
--> $DIR/issue-63135.rs:3:8
|
LL | fn i(n{...,f #
- | ^^^ help: to omit remaining fields, use one fewer `.`: `..`
+ | ^^^
+ |
+help: to omit remaining fields, use `..`
+ |
+LL | fn i(n{..,f #
+ | ~~
error: expected `}`, found `,`
--> $DIR/issue-63135.rs:3:11
--> $DIR/issue-87812-path.rs:3:24
|
LL | let _: usize = $f;
- | ----- ^^ expected `usize`, found struct `Baz`
+ | ----- ^^ expected `usize`, found `Baz`
| |
| expected due to this
...
--- /dev/null
+fn main() {
+ for i in {
+ //~^ ERROR missing expression to iterate on in `for` loop
+ }
+}
--- /dev/null
+error: missing expression to iterate on in `for` loop
+ --> $DIR/missing-expression-in-for-loop.rs:2:14
+ |
+LL | for i in {
+ | ^
+ |
+help: try adding an expression to the `for` loop
+ |
+LL | for i in /* expression */ {
+ | ++++++++++++++++
+
+error: aborting due to previous error
+
enum Foo { Bar }
fn foo(x: impl Iterator<Item = Foo>) {
for <Foo>::Bar in x {}
- //~^ ERROR expected one of `const`, `move`, `static`, `|`
+ //~^ ERROR expected one of `move`, `static`, `|`
//~^^ ERROR `for<...>` binders for closures are experimental
}
-error: expected one of `const`, `move`, `static`, `|`, or `||`, found `::`
+error: expected one of `move`, `static`, `|`, or `||`, found `::`
--> $DIR/recover-quantified-closure.rs:9:14
|
LL | for <Foo>::Bar in x {}
- | ^^ expected one of `const`, `move`, `static`, `|`, or `||`
+ | ^^ expected one of `move`, `static`, `|`, or `||`
error[E0658]: `for<...>` binders for closures are experimental
--> $DIR/recover-quantified-closure.rs:2:5
LL | if let X.. .0 = 0 {}
| - ^^ - this expression has type `u8`
| | |
- | | expected integer, found floating-point number
+ | | expected `u8`, found floating-point number
| this is of type `u8`
|
= note: expected type `u8`
LL | if let X..=.0 = 0 {}
| - ^^ - this expression has type `u8`
| | |
- | | expected integer, found floating-point number
+ | | expected `u8`, found floating-point number
| this is of type `u8`
|
= note: expected type `u8`
LL | if let X... .0 = 0 {}
| - ^^ - this expression has type `u8`
| | |
- | | expected integer, found floating-point number
+ | | expected `u8`, found floating-point number
| this is of type `u8`
|
= note: expected type `u8`
--- /dev/null
+fn foo(x: bool) -> i32 {
+ match x {
+ x: i32 => x, //~ ERROR expected
+ //~^ ERROR mismatched types
+ true => 42.,
+ false => 0.333,
+ }
+}
+
+fn main() {
+ match foo(true) {
+ 42: i32 => (), //~ ERROR expected
+ _: f64 => (), //~ ERROR expected
+ x: i32 => (), //~ ERROR expected
+ }
+}
--- /dev/null
+error: expected one of `@` or `|`, found `:`
+ --> $DIR/type-ascription-in-pattern.rs:3:10
+ |
+LL | x: i32 => x,
+ | ^ --- specifying the type of a pattern isn't supported
+ | |
+ | expected one of `@` or `|`
+ |
+help: maybe write a path separator here
+ |
+LL | x::i32 => x,
+ | ~~
+
+error: expected one of `...`, `..=`, `..`, or `|`, found `:`
+ --> $DIR/type-ascription-in-pattern.rs:12:11
+ |
+LL | 42: i32 => (),
+ | ^ --- specifying the type of a pattern isn't supported
+ | |
+ | expected one of `...`, `..=`, `..`, or `|`
+
+error: expected `|`, found `:`
+ --> $DIR/type-ascription-in-pattern.rs:13:10
+ |
+LL | _: f64 => (),
+ | ^ --- specifying the type of a pattern isn't supported
+ | |
+ | expected `|`
+
+error: expected one of `@` or `|`, found `:`
+ --> $DIR/type-ascription-in-pattern.rs:14:10
+ |
+LL | x: i32 => (),
+ | ^ --- specifying the type of a pattern isn't supported
+ | |
+ | expected one of `@` or `|`
+ |
+help: maybe write a path separator here
+ |
+LL | x::i32 => (),
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/type-ascription-in-pattern.rs:3:19
+ |
+LL | fn foo(x: bool) -> i32 {
+ | --- expected `i32` because of return type
+LL | match x {
+LL | x: i32 => x,
+ | ^ expected `i32`, found `bool`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--> $DIR/unclosed-delimiter-in-dep.rs:4:20
|
LL | let _: usize = unclosed_delim_mod::new();
- | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found enum `Result`
+ | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `Result<Value, ()>`
| |
| expected due to this
|
LL | for Some(Qux(_)) | None in [Some(""), None] {
| ^^^^^^ ---------------- this is an iterator with items of type `Option<&str>`
| |
- | expected `str`, found struct `Qux`
+ | expected `str`, found `Qux`
error: aborting due to 2 previous errors
LL | let P() = U {};
| ^^^ ---- this expression has type `U`
| |
- | expected struct `U`, found struct `P`
+ | expected `U`, found `P<_>`
|
= note: expected struct `U`
found struct `P<_>`
LL | match (S { f: 42 }) {
| ------------- this expression has type `S`
LL | S { f: Ok(_) } => {}
- | ^^^^^ expected `u8`, found enum `Result`
+ | ^^^^^ expected `u8`, found `Result<_, _>`
|
= note: expected type `u8`
found enum `Result<_, _>`
LL | fn foo(Tuple(_): String) {}
| ^^^^^^^^ ------ expected due to this
| |
- | expected struct `String`, found struct `Tuple`
+ | expected `String`, found `Tuple`
error: aborting due to previous error
--> $DIR/pat-type-err-let-stmt.rs:6:29
|
LL | let Ok(0): Option<u8> = 42u8;
- | ---------- ^^^^ expected enum `Option`, found `u8`
+ | ---------- ^^^^ expected `Option<u8>`, found `u8`
| |
| expected due to this
|
LL | let Ok(0): Option<u8> = 42u8;
| ^^^^^ ---------- expected due to this
| |
- | expected enum `Option`, found enum `Result`
+ | expected `Option<u8>`, found `Result<_, _>`
|
= note: expected enum `Option<u8>`
found enum `Result<_, _>`
LL | let Ok(0): Option<u8>;
| ^^^^^ ---------- expected due to this
| |
- | expected enum `Option`, found enum `Result`
+ | expected `Option<u8>`, found `Result<_, _>`
|
= note: expected enum `Option<u8>`
found enum `Result<_, _>`
LL | let Ok(0) = 42u8;
| ^^^^^ ---- this expression has type `u8`
| |
- | expected `u8`, found enum `Result`
+ | expected `u8`, found `Result<_, _>`
|
= note: expected type `u8`
found enum `Result<_, _>`
match 'c' {
S { .. } => (),
//~^ ERROR mismatched types
- //~| expected `char`, found struct `S`
+ //~| expected `char`, found `S`
_ => ()
}
LL | match 'c' {
| --- this expression has type `char`
LL | S { .. } => (),
- | ^^^^^^^^ expected `char`, found struct `S`
+ | ^^^^^^^^ expected `char`, found `S`
error[E0308]: mismatched types
--> $DIR/pattern-error-continue.rs:28:7
LL | match Some("foo") {
| ----------- this expression has type `Option<&str>`
LL | None::<isize> => {}
- | ^^^^^^^^^^^^^ expected `&str`, found `isize`
+ | ^^^^^^^^^^^^^ expected `Option<&str>`, found `Option<isize>`
|
= note: expected enum `Option<&str>`
found enum `Option<isize>`
LL | match t {
| - this expression has type `Bar`
LL | Bar::T1(_, Some::<isize>(x)) => {
- | ^^^^^^^^^^^^^^^^ expected struct `Vec`, found `isize`
+ | ^^^^^^^^^^^^^^^^ expected `Option<Vec<isize>>`, found `Option<isize>`
|
= note: expected enum `Option<Vec<isize>>`
found enum `Option<isize>`
--> $DIR/point-to-type-err-cause-on-impl-trait-return-2.rs:9:41
|
LL | let value: &bool = unsafe { &42 };
- | ^^^ expected `bool`, found integer
+ | ^^^ expected `&bool`, found `&{integer}`
|
= note: expected reference `&bool`
found reference `&{integer}`
print-type-size type: `[async fn body@$DIR/async.rs:8:36: 11:2]`: 16386 bytes, alignment: 1 bytes
print-type-size discriminant: 1 bytes
-print-type-size variant `Suspend0`: 16385 bytes
-print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
-print-type-size field `.arg`: 8192 bytes
-print-type-size field `.__awaitee`: 1 bytes
print-type-size variant `Unresumed`: 8192 bytes
-print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size upvar `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Suspend0`: 16385 bytes
+print-type-size upvar `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size local `.arg`: 8192 bytes
+print-type-size local `.__awaitee`: 1 bytes
print-type-size variant `Returned`: 8192 bytes
-print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size upvar `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size variant `Panicked`: 8192 bytes
-print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size upvar `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size type: `std::mem::ManuallyDrop<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes
print-type-size field `.value`: 8192 bytes
print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes
print-type-size type: `[generator@$DIR/generator.rs:10:5: 10:14]`: 8193 bytes, alignment: 1 bytes
print-type-size discriminant: 1 bytes
print-type-size variant `Unresumed`: 8192 bytes
-print-type-size field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size upvar `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Suspend0`: 8192 bytes
+print-type-size upvar `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size variant `Returned`: 8192 bytes
-print-type-size field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size upvar `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size variant `Panicked`: 8192 bytes
-print-type-size field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
-print-type-size variant `Suspend0`: 8192 bytes
-print-type-size field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size upvar `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size type: `[generator@$DIR/generator_discr_placement.rs:11:13: 11:15]`: 8 bytes, alignment: 4 bytes
print-type-size discriminant: 1 bytes
+print-type-size variant `Unresumed`: 0 bytes
print-type-size variant `Suspend0`: 7 bytes
print-type-size padding: 3 bytes
-print-type-size field `.w`: 4 bytes, alignment: 4 bytes
+print-type-size local `.w`: 4 bytes, alignment: 4 bytes
print-type-size variant `Suspend1`: 7 bytes
print-type-size padding: 3 bytes
-print-type-size field `.z`: 4 bytes, alignment: 4 bytes
-print-type-size variant `Unresumed`: 0 bytes
+print-type-size local `.z`: 4 bytes, alignment: 4 bytes
print-type-size variant `Returned`: 0 bytes
print-type-size variant `Panicked`: 0 bytes
--> $DIR/break-token-spans.rs:14:32
|
LL | let a: Option<Option<u8>>= true;
- | ------------------ ^^^^ expected enum `Option`, found `bool`
+ | ------------------ ^^^^ expected `Option<Option<u8>>`, found `bool`
| |
| expected due to this
|
// ignore-wasm32
// ignore-sgx no support for proc-macro crate type
// build-pass
+// force-host
+// no-prefer-dynamic
+
#![crate_type = "proc-macro"]
// FIXME: This don't work when crate-type is specified by attribute
LL | std::cell::Cell::new(0)
| ^^^^^^^^^^^^^^^^^^^^^^^- help: consider using a semicolon here: `;`
| |
- | expected `()`, found struct `Cell`
+ | expected `()`, found `Cell<{integer}>`
|
= note: expected unit type `()`
found struct `Cell<{integer}>`
LL | fn main() {
| - expected `()` because of default return type
LL | resolve_located_at!(a b)
- | ^ expected `()`, found struct `S`
+ | ^ expected `()`, found `S`
|
= note: this error originates in the macro `resolve_located_at` (in Nightly builds, run with -Z macro-backtrace for more info)
+++ /dev/null
-// #60115
-
-mod foo {
- pub bar();
- //~^ ERROR missing `fn` or `struct` for function or struct definition
-}
-
-fn main() {}
+++ /dev/null
-error: missing `fn` or `struct` for function or struct definition
- --> $DIR/pub-ident-fn-3.rs:4:8
- |
-LL | pub bar();
- | ---^--- help: if you meant to call a macro, try: `bar!`
-
-error: aborting due to previous error
-
+++ /dev/null
-pub S();
-//~^ ERROR missing `fn` or `struct` for function or struct definition
-
-fn main() {}
+++ /dev/null
-error: missing `fn` or `struct` for function or struct definition
- --> $DIR/pub-ident-fn-or-struct-2.rs:1:4
- |
-LL | pub S();
- | ---^- help: if you meant to call a macro, try: `S!`
-
-error: aborting due to previous error
-
--- /dev/null
+// #60115
+
+mod foo {
+ pub bar();
+ //~^ ERROR missing `struct` for struct definition
+}
+
+fn main() {}
--- /dev/null
+error: missing `struct` for struct definition
+ --> $DIR/pub-ident-struct-2.rs:4:8
+ |
+LL | pub bar();
+ | ^
+ |
+help: add `struct` here to parse `bar` as a public struct
+ |
+LL | pub struct bar();
+ | ++++++
+
+error: aborting due to previous error
+
--- /dev/null
+pub S();
+//~^ ERROR missing `struct` for struct definition
+
+fn main() {}
--- /dev/null
+error: missing `struct` for struct definition
+ --> $DIR/pub-ident-struct-3.rs:1:4
+ |
+LL | pub S();
+ | ^
+ |
+help: add `struct` here to parse `S` as a public struct
+ |
+LL | pub struct S();
+ | ++++++
+
+error: aborting due to previous error
+
--- /dev/null
+// run-rustfix
+
+pub struct T(String);
+//~^ ERROR missing `struct` for struct definition
+
+fn main() {}
--- /dev/null
+// run-rustfix
+
+pub T(String);
+//~^ ERROR missing `struct` for struct definition
+
+fn main() {}
--- /dev/null
+error: missing `struct` for struct definition
+ --> $DIR/pub-ident-struct-4.rs:3:4
+ |
+LL | pub T(String);
+ | ^
+ |
+help: add `struct` here to parse `T` as a public struct
+ |
+LL | pub struct T(String);
+ | ++++++
+
+error: aborting due to previous error
+
--- /dev/null
+fn a() -> _ {
+ //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
+ &a
+}
+
+fn main() {}
--- /dev/null
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+ --> $DIR/no-query-in-printing-during-query-descr.rs:1:11
+ |
+LL | fn a() -> _ {
+ | ^ not allowed in type signatures
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0121`.
LL | take_range(std::ops::Range { start: 0, end: 1 });
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `Range`
+ | | expected `&_`, found `Range<{integer}>`
| | help: consider borrowing here: `&std::ops::Range { start: 0, end: 1 }`
| arguments to this function are incorrect
|
LL | take_range(::std::ops::Range { start: 0, end: 1 });
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `Range`
+ | | expected `&_`, found `Range<{integer}>`
| | help: consider borrowing here: `&::std::ops::Range { start: 0, end: 1 }`
| arguments to this function are incorrect
|
LL | take_range(std::ops::RangeFrom { start: 1 });
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `RangeFrom`
+ | | expected `&_`, found `RangeFrom<{integer}>`
| | help: consider borrowing here: `&std::ops::RangeFrom { start: 1 }`
| arguments to this function are incorrect
|
LL | take_range(::std::ops::RangeFrom { start: 1 });
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `RangeFrom`
+ | | expected `&_`, found `RangeFrom<{integer}>`
| | help: consider borrowing here: `&::std::ops::RangeFrom { start: 1 }`
| arguments to this function are incorrect
|
LL | take_range(std::ops::RangeFull {});
| ---------- ^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `RangeFull`
+ | | expected `&_`, found `RangeFull`
| | help: consider borrowing here: `&std::ops::RangeFull {}`
| arguments to this function are incorrect
|
LL | take_range(::std::ops::RangeFull {});
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `RangeFull`
+ | | expected `&_`, found `RangeFull`
| | help: consider borrowing here: `&::std::ops::RangeFull {}`
| arguments to this function are incorrect
|
LL | take_range(std::ops::RangeInclusive::new(0, 1));
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `RangeInclusive`
+ | | expected `&_`, found `RangeInclusive<{integer}>`
| | help: consider borrowing here: `&std::ops::RangeInclusive::new(0, 1)`
| arguments to this function are incorrect
|
LL | take_range(::std::ops::RangeInclusive::new(0, 1));
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `RangeInclusive`
+ | | expected `&_`, found `RangeInclusive<{integer}>`
| | help: consider borrowing here: `&::std::ops::RangeInclusive::new(0, 1)`
| arguments to this function are incorrect
|
LL | take_range(std::ops::RangeTo { end: 5 });
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `RangeTo`
+ | | expected `&_`, found `RangeTo<{integer}>`
| | help: consider borrowing here: `&std::ops::RangeTo { end: 5 }`
| arguments to this function are incorrect
|
LL | take_range(::std::ops::RangeTo { end: 5 });
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `RangeTo`
+ | | expected `&_`, found `RangeTo<{integer}>`
| | help: consider borrowing here: `&::std::ops::RangeTo { end: 5 }`
| arguments to this function are incorrect
|
LL | take_range(std::ops::RangeToInclusive { end: 5 });
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `RangeToInclusive`
+ | | expected `&_`, found `RangeToInclusive<{integer}>`
| | help: consider borrowing here: `&std::ops::RangeToInclusive { end: 5 }`
| arguments to this function are incorrect
|
LL | take_range(::std::ops::RangeToInclusive { end: 5 });
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `RangeToInclusive`
+ | | expected `&_`, found `RangeToInclusive<{integer}>`
| | help: consider borrowing here: `&::std::ops::RangeToInclusive { end: 5 }`
| arguments to this function are incorrect
|
LL | take_range(0..1);
| ---------- ^^^^
| | |
- | | expected reference, found struct `Range`
+ | | expected `&_`, found `Range<{integer}>`
| | help: consider borrowing here: `&(0..1)`
| arguments to this function are incorrect
|
LL | take_range(1..);
| ---------- ^^^
| | |
- | | expected reference, found struct `RangeFrom`
+ | | expected `&_`, found `RangeFrom<{integer}>`
| | help: consider borrowing here: `&(1..)`
| arguments to this function are incorrect
|
LL | take_range(..);
| ---------- ^^
| | |
- | | expected reference, found struct `RangeFull`
+ | | expected `&_`, found `RangeFull`
| | help: consider borrowing here: `&(..)`
| arguments to this function are incorrect
|
LL | take_range(0..=1);
| ---------- ^^^^^
| | |
- | | expected reference, found struct `RangeInclusive`
+ | | expected `&_`, found `RangeInclusive<{integer}>`
| | help: consider borrowing here: `&(0..=1)`
| arguments to this function are incorrect
|
LL | take_range(..5);
| ---------- ^^^
| | |
- | | expected reference, found struct `RangeTo`
+ | | expected `&_`, found `RangeTo<{integer}>`
| | help: consider borrowing here: `&(..5)`
| arguments to this function are incorrect
|
LL | take_range(..=42);
| ---------- ^^^^^
| | |
- | | expected reference, found struct `RangeToInclusive`
+ | | expected `&_`, found `RangeToInclusive<{integer}>`
| | help: consider borrowing here: `&(..=42)`
| arguments to this function are incorrect
|
LL | take_range(0..1);
| ---------- ^^^^
| | |
- | | expected reference, found struct `Range`
+ | | expected `&_`, found `Range<{integer}>`
| | help: consider borrowing here: `&(0..1)`
| arguments to this function are incorrect
|
LL | take_range(1..);
| ---------- ^^^
| | |
- | | expected reference, found struct `RangeFrom`
+ | | expected `&_`, found `RangeFrom<{integer}>`
| | help: consider borrowing here: `&(1..)`
| arguments to this function are incorrect
|
LL | take_range(..);
| ---------- ^^
| | |
- | | expected reference, found struct `RangeFull`
+ | | expected `&_`, found `RangeFull`
| | help: consider borrowing here: `&(..)`
| arguments to this function are incorrect
|
LL | take_range(0..=1);
| ---------- ^^^^^
| | |
- | | expected reference, found struct `RangeInclusive`
+ | | expected `&_`, found `RangeInclusive<{integer}>`
| | help: consider borrowing here: `&(0..=1)`
| arguments to this function are incorrect
|
LL | take_range(..5);
| ---------- ^^^
| | |
- | | expected reference, found struct `RangeTo`
+ | | expected `&_`, found `RangeTo<{integer}>`
| | help: consider borrowing here: `&(..5)`
| arguments to this function are incorrect
|
LL | take_range(..=42);
| ---------- ^^^^^
| | |
- | | expected reference, found struct `RangeToInclusive`
+ | | expected `&_`, found `RangeToInclusive<{integer}>`
| | help: consider borrowing here: `&(..=42)`
| arguments to this function are incorrect
|
LL | demo(tell(1)..tell(10));
| ---- ^^^^^^^^^^^^^^^^^
| | |
- | | expected `&Range<usize>`, found struct `Range`
+ | | expected `&Range<usize>`, found `Range<usize>`
| | help: consider borrowing here: `&(tell(1)..tell(10))`
| arguments to this function are incorrect
|
LL | demo(1..10);
| ---- ^^^^^
| | |
- | | expected `&Range<usize>`, found struct `Range`
+ | | expected `&Range<usize>`, found `Range<{integer}>`
| | help: consider borrowing here: `&(1..10)`
| arguments to this function are incorrect
|
| ^ expected `i32`, found fn pointer
|
= note: expected type `i32`
- found fn pointer `for<'z1, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, 'y, 'z, 'z0> fn(Cell<...>)`
+ found fn pointer `fn(Cell<...>)`
the full type name has been written to '$TEST_BUILD_DIR/regions/issue-102374/issue-102374.long-type-hash.txt'
error: aborting due to previous error
|
= note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)`
found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
error: aborting due to previous error
|
= note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b isize, &'c mut &'d isize, &'e mut &'f isize)`
found fn item `for<'a, 'b, 'c> fn(&'a mut &isize, &'b mut &isize, &'c mut &isize) {a::<'_, '_, '_>}`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
error: aborting due to previous error
|
= note: expected fn pointer `for<'cx> fn(&'cx S) -> &'static S`
found fn item `for<'a> fn(&'a S) -> &'a S {baz}`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
note: function defined here
--> $DIR/regions-fn-subtyping-return-static-fail.rs:20:4
|
|
= note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)`
found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
error: aborting due to previous error
|
= note: expected fn pointer `unsafe extern "rust-intrinsic" fn(isize) -> usize`
found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid
--> $DIR/reify-intrinsic.rs:11:13
}
let g = [0; G { g: () }];
//~^ ERROR mismatched types
- //~| expected `usize`, found struct `G`
+ //~| expected `usize`, found `G`
}
--> $DIR/repeat_count.rs:31:17
|
LL | let g = [0; G { g: () }];
- | ^^^^^^^^^^^ expected `usize`, found struct `G`
+ | ^^^^^^^^^^^ expected `usize`, found `G`
error[E0308]: mismatched types
--> $DIR/repeat_count.rs:19:17
LL | let None: isize = 42;
| ^^^^ ----- expected due to this
| |
- | expected `isize`, found enum `Option`
+ | expected `isize`, found `Option<_>`
|
= note: expected type `isize`
found enum `Option<_>`
| -- `Fn` defines an enum variant constructor here, which should be called
...
LL | let _: Z = Z::Fn;
- | - ^^^^^ expected enum `Z`, found enum constructor
+ | - ^^^^^ expected `Z`, found enum constructor
| |
| expected due to this
|
| -- `Fn` defines an enum variant constructor here, which should be called
...
LL | let _: E = m::E::Fn;
- | - ^^^^^^^^ expected enum `E`, found enum constructor
+ | - ^^^^^^^^ expected `E`, found enum constructor
| |
| expected due to this
|
| -- `Fn` defines an enum variant constructor here, which should be called
...
LL | let _: E = E::Fn;
- | - ^^^^^ expected enum `E`, found enum constructor
+ | - ^^^^^ expected `E`, found enum constructor
| |
| expected due to this
|
LL | match x {
| - this expression has type `(E, E)`
LL | (A, B) | (ref B, c) | (c, A) => ()
- | - ^^^^^ expected enum `E`, found `&E`
+ | - ^^^^^ expected `E`, found `&E`
| |
| first introduced with type `E` here
|
--> $DIR/return-type.rs:10:5
|
LL | foo(4 as usize)
- | ^^^^^^^^^^^^^^^ expected `()`, found struct `S`
+ | ^^^^^^^^^^^^^^^ expected `()`, found `S<usize>`
|
= note: expected unit type `()`
found struct `S<usize>`
|
LL | / if x {
LL | | Err(42)
- | | ^^^^^^^ expected `()`, found enum `Result`
+ | | ^^^^^^^ expected `()`, found `Result<_, {integer}>`
LL | | //| HELP you might have meant to return this value
LL | | }
| |_____- expected this to be `()`
|
LL | / if x {
LL | | Err(42)
- | | ^^^^^^^ expected `()`, found enum `Result`
+ | | ^^^^^^^ expected `()`, found `Result<_, {integer}>`
LL | | //| HELP you might have meant to return this value
LL | | }
| |_____- expected this to be `()`
LL | FOO => {},
| ^^^
| |
- | expected `&Foo`, found struct `Foo`
+ | expected `&Foo`, found `Foo`
| `FOO` is interpreted as a constant, not a new binding
| help: introduce a new binding instead: `other_foo`
LL | match &s {
| -- this expression has type `&&str`
LL | "abc" => true,
- | ^^^^^ expected `&str`, found `str`
+ | ^^^^^ expected `&&str`, found `&str`
|
= note: expected reference `&&str`
found reference `&'static str`
LL | match &s {
| -- this expression has type `&&[u8]`
LL | b"abc" => true,
- | ^^^^^^ expected `&[u8]`, found array `[u8; 3]`
+ | ^^^^^^ expected `&&[u8]`, found `&[u8; 3]`
|
= note: expected reference `&&[u8]`
found reference `&'static [u8; 3]`
LL | fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A {
| - expected `A` because of return type
LL | x
- | ^ expected struct `A`, found enum `UninhabitedEnum`
+ | ^ expected `A`, found `UninhabitedEnum`
error[E0308]: mismatched types
--> $DIR/coercions.rs:27:5
LL | fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
| - expected `A` because of return type
LL | x
- | ^ expected struct `A`, found struct `UninhabitedTupleStruct`
+ | ^ expected `A`, found `UninhabitedTupleStruct`
error[E0308]: mismatched types
--> $DIR/coercions.rs:31:5
LL | fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A {
| - expected `A` because of return type
LL | x
- | ^ expected struct `A`, found struct `UninhabitedStruct`
+ | ^ expected `A`, found `UninhabitedStruct`
error[E0308]: mismatched types
--> $DIR/coercions.rs:35:5
LL | fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A {
| - expected `A` because of return type
LL | x
- | ^ expected struct `A`, found enum `UninhabitedVariants`
+ | ^ expected `A`, found `UninhabitedVariants`
error: aborting due to 4 previous errors
LL | fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A {
| - expected `A` because of return type
LL | x
- | ^ expected struct `A`, found enum `UninhabitedEnum`
+ | ^ expected `A`, found `UninhabitedEnum`
error[E0308]: mismatched types
--> $DIR/coercions_same_crate.rs:34:5
LL | fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
| - expected `A` because of return type
LL | x
- | ^ expected struct `A`, found struct `UninhabitedTupleStruct`
+ | ^ expected `A`, found `UninhabitedTupleStruct`
error[E0308]: mismatched types
--> $DIR/coercions_same_crate.rs:38:5
LL | fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A {
| - expected `A` because of return type
LL | x
- | ^ expected struct `A`, found struct `UninhabitedStruct`
+ | ^ expected `A`, found `UninhabitedStruct`
error[E0308]: mismatched types
--> $DIR/coercions_same_crate.rs:42:5
LL | fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A {
| - expected `A` because of return type
LL | x
- | ^ expected struct `A`, found enum `UninhabitedVariants`
+ | ^ expected `A`, found `UninhabitedVariants`
error: aborting due to 4 previous errors
LL | Ok(x) if let Err(_) = x => {},
| ^^^^^^ - this expression has type `Option<bool>`
| |
- | expected enum `Option`, found enum `Result`
+ | expected `Option<bool>`, found `Result<_, _>`
|
= note: expected enum `Option<bool>`
found enum `Result<_, _>`
LL | Ok(x) if let 0 = x => {},
| ^ - this expression has type `Option<bool>`
| |
- | expected enum `Option`, found integer
+ | expected `Option<bool>`, found integer
|
= note: expected enum `Option<bool>`
found type `{integer}`
--> $DIR/disallowed-positions.rs:157:8
|
LL | if true..(let 0 = 0) {}
- | ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
--> $DIR/disallowed-positions.rs:161:8
|
LL | if ..(let 0 = 0) {}
- | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo`
+ | ^^^^^^^^^^^^^ expected `bool`, found `RangeTo<bool>`
|
= note: expected type `bool`
found struct `RangeTo<bool>`
--> $DIR/disallowed-positions.rs:165:8
|
LL | if (let 0 = 0).. {}
- | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom`
+ | ^^^^^^^^^^^^^ expected `bool`, found `RangeFrom<bool>`
|
= note: expected type `bool`
found struct `RangeFrom<bool>`
LL | if let Range { start: _, end: _ } = true..true && false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
| |
- | expected `bool`, found struct `Range`
+ | expected `bool`, found `Range<_>`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
--> $DIR/disallowed-positions.rs:171:8
|
LL | if let Range { start: _, end: _ } = true..true && false {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
LL | if let Range { start: _, end: _ } = true..true || false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
| |
- | expected `bool`, found struct `Range`
+ | expected `bool`, found `Range<_>`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
--> $DIR/disallowed-positions.rs:175:8
|
LL | if let Range { start: _, end: _ } = true..true || false {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
LL | if let Range { start: F, end } = F..|| true {}
| ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool`
| |
- | expected fn pointer, found struct `Range`
+ | expected fn pointer, found `Range<_>`
|
= note: expected fn pointer `fn() -> bool`
found struct `std::ops::Range<_>`
--> $DIR/disallowed-positions.rs:182:8
|
LL | if let Range { start: F, end } = F..|| true {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
LL | if let Range { start: true, end } = t..&&false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool`
| |
- | expected `bool`, found struct `Range`
+ | expected `bool`, found `Range<_>`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
--> $DIR/disallowed-positions.rs:190:8
|
LL | if let Range { start: true, end } = t..&&false {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
--> $DIR/disallowed-positions.rs:249:11
|
LL | while true..(let 0 = 0) {}
- | ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
--> $DIR/disallowed-positions.rs:253:11
|
LL | while ..(let 0 = 0) {}
- | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo`
+ | ^^^^^^^^^^^^^ expected `bool`, found `RangeTo<bool>`
|
= note: expected type `bool`
found struct `RangeTo<bool>`
--> $DIR/disallowed-positions.rs:257:11
|
LL | while (let 0 = 0).. {}
- | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom`
+ | ^^^^^^^^^^^^^ expected `bool`, found `RangeFrom<bool>`
|
= note: expected type `bool`
found struct `RangeFrom<bool>`
LL | while let Range { start: _, end: _ } = true..true && false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
| |
- | expected `bool`, found struct `Range`
+ | expected `bool`, found `Range<_>`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
--> $DIR/disallowed-positions.rs:263:11
|
LL | while let Range { start: _, end: _ } = true..true && false {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
LL | while let Range { start: _, end: _ } = true..true || false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
| |
- | expected `bool`, found struct `Range`
+ | expected `bool`, found `Range<_>`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
--> $DIR/disallowed-positions.rs:267:11
|
LL | while let Range { start: _, end: _ } = true..true || false {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
LL | while let Range { start: F, end } = F..|| true {}
| ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool`
| |
- | expected fn pointer, found struct `Range`
+ | expected fn pointer, found `Range<_>`
|
= note: expected fn pointer `fn() -> bool`
found struct `std::ops::Range<_>`
--> $DIR/disallowed-positions.rs:274:11
|
LL | while let Range { start: F, end } = F..|| true {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
LL | while let Range { start: true, end } = t..&&false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool`
| |
- | expected `bool`, found struct `Range`
+ | expected `bool`, found `Range<_>`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
--> $DIR/disallowed-positions.rs:282:11
|
LL | while let Range { start: true, end } = t..&&false {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
LL | (let Range { start: _, end: _ } = true..true || false);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
| |
- | expected `bool`, found struct `Range`
+ | expected `bool`, found `Range<_>`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
LL | if let Some(n) = opt else {
| ^
help: remove the `if` if you meant to write a `let...else` statement
- --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:24:5
|
-LL | if let Some(n) = opt else {
- | ^^
+LL - if let Some(n) = opt else {
+LL + let Some(n) = opt else {
+ |
error: this `if` expression is missing a block after the condition
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:28:5
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:9:19
|
LL | let Some(n) = opt && n == 1 else {
- | ^^^ expected `bool`, found enum `Option`
+ | ^^^ expected `bool`, found `Option<i32>`
|
= note: expected type `bool`
found enum `Option<i32>`
LL | let Some(n) = opt && n == 1 else {
| ^^^^^^^ ------------- this expression has type `bool`
| |
- | expected `bool`, found enum `Option`
+ | expected `bool`, found `Option<_>`
|
= note: expected type `bool`
found enum `Option<_>`
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:19
|
LL | let Some(n) = opt && let another = n else {
- | ^^^ expected `bool`, found enum `Option`
+ | ^^^ expected `bool`, found `Option<i32>`
|
= note: expected type `bool`
found enum `Option<i32>`
LL | let Some(n) = opt && let another = n else {
| ^^^^^^^ ---------------------- this expression has type `bool`
| |
- | expected `bool`, found enum `Option`
+ | expected `bool`, found `Option<_>`
|
= note: expected type `bool`
found enum `Option<_>`
--- /dev/null
+// check-pass
+
+#![feature(const_trait_impl, const_closures)]
+#![allow(incomplete_features)]
+
+const fn test() -> impl ~const Fn() {
+ const move || {}
+}
+
+fn main() {}
| ---------------------------------- `#[target_feature]` added here
...
LL | let foo: fn() = foo;
- | ---- ^^^
- | | |
- | | cannot coerce functions with `#[target_feature]` to safe function pointers
- | | help: consider casting to a fn pointer: `foo as fn()`
+ | ---- ^^^ cannot coerce functions with `#[target_feature]` to safe function pointers
+ | |
| expected due to this
|
= note: expected fn pointer `fn()`
found fn item `fn() {foo}`
= note: fn items are distinct from fn pointers
= note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers
+ = note: when the arguments and return types match, functions can be coerced to function pointers
+help: consider casting to a fn pointer
+ |
+LL | let foo: fn() = foo as fn();
+ | ~~~~~~~~~~~
error: aborting due to previous error
| ---------------------------------- `#[target_feature]` added here
...
LL | let foo: fn() = foo;
- | ---- ^^^
- | | |
- | | cannot coerce functions with `#[target_feature]` to safe function pointers
- | | help: consider casting to a fn pointer: `foo as fn()`
+ | ---- ^^^ cannot coerce functions with `#[target_feature]` to safe function pointers
+ | |
| expected due to this
|
= note: expected fn pointer `fn()`
found fn item `fn() {foo}`
= note: fn items are distinct from fn pointers
= note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers
+ = note: when the arguments and return types match, functions can be coerced to function pointers
+help: consider casting to a fn pointer
+ |
+LL | let foo: fn() = foo as fn();
+ | ~~~~~~~~~~~
error: aborting due to previous error
--> $DIR/feature-gate.rs:22:11
|
LL | ..m1
- | ^^ expected struct `State2`, found struct `State1`
+ | ^^ expected `Machine<State2>`, found `Machine<State1>`
|
= note: expected struct `Machine<State2>`
found struct `Machine<State1>`
--> $DIR/issue-92010-trait-bound-not-satisfied.rs:8:43
|
LL | fn y(&self, y: f64) -> Self { P{y, .. self.clone() } }
- | ^^^^^^^^^^^^ expected struct `P`, found `&P<T>`
+ | ^^^^^^^^^^^^ expected `P<T>`, found `&P<T>`
|
= note: expected struct `P<T>`
found reference `&P<T>`
--> $DIR/type-generic-update.rs:46:11
|
LL | ..m1
- | ^^ expected `i32`, found `f64`
+ | ^^ expected `Machine<'_, i32, f64>`, found `Machine<'_, f64, f64>`
|
= note: expected struct `Machine<'_, i32, _>`
found struct `Machine<'_, f64, _>`
--> $DIR/type-generic-update.rs:51:11
|
LL | ..m1
- | ^^ expected `i32`, found `f64`
+ | ^^ expected `Machine<'_, i32, i32>`, found `Machine<'_, f64, f64>`
|
= note: expected struct `Machine<'_, i32, i32>`
found struct `Machine<'_, f64, f64>`
--> $DIR/issue-61882.rs:4:22
|
LL | const B: A<u8> = Self(0);
- | ^^^^^^^ expected `u8`, found `bool`
+ | ^^^^^^^ expected `A<u8>`, found `A<bool>`
|
= note: expected struct `A<u8>`
found struct `A<bool>`
//~^ ERROR mismatched types
//~| expected struct `Foo<{float}, _>`
//~| found type `{integer}`
- //~| expected struct `Foo`, found integer
+ //~| expected `Foo<{float}, _>`, found integer
}
}
LL | match Foo(1.1, marker::PhantomData) {
| ----------------------------- this expression has type `Foo<{float}, _>`
LL | 1 => {}
- | ^ expected struct `Foo`, found integer
+ | ^ expected `Foo<{float}, _>`, found integer
|
= note: expected struct `Foo<{float}, _>`
found type `{integer}`
--> $DIR/coerce-suggestions.rs:7:20
|
LL | let x: usize = String::new();
- | ----- ^^^^^^^^^^^^^ expected `usize`, found struct `String`
+ | ----- ^^^^^^^^^^^^^ expected `usize`, found `String`
| |
| expected due to this
LL | let x: &str = String::new();
| ---- ^^^^^^^^^^^^^
| | |
- | | expected `&str`, found struct `String`
+ | | expected `&str`, found `String`
| | help: consider borrowing here: `&String::new()`
| expected due to this
--> $DIR/coerce-suggestions.rs:21:9
|
LL | s = format!("foo");
- | ^^^^^^^^^^^^^^ expected `&mut String`, found struct `String`
+ | ^^^^^^^^^^^^^^ expected `&mut String`, found `String`
|
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
--> $DIR/issue-33884.rs:6:22
|
LL | stream.write_fmt(format!("message received"))
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Arguments`, found struct `String`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Arguments<'_>`, found `String`
|
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
LL | let _ = a + b;
| ^
| |
- | expected `&str`, found struct `String`
+ | expected `&str`, found `String`
| help: consider borrowing here: `&b`
error[E0369]: cannot add `String` to `&String`
LL | default fn generate(self) -> Self::Output {
| ------------ expected `<T as Example>::Output` because of return type
LL | Box::new(self)
- | ^^^^^^^^^^^^^^ expected associated type, found struct `Box`
+ | ^^^^^^^^^^^^^^ expected associated type, found `Box<T>`
|
= note: expected associated type `<T as Example>::Output`
found struct `Box<T>`
LL | fn trouble<T>(t: T) -> Box<T> {
| ------ expected `Box<T>` because of return type
LL | Example::generate(t)
- | ^^^^^^^^^^^^^^^^^^^^ expected struct `Box`, found associated type
+ | ^^^^^^^^^^^^^^^^^^^^ expected `Box<T>`, found associated type
|
= note: expected struct `Box<T>`
found associated type `<T as Example>::Output`
static i: String = 10;
//~^ ERROR mismatched types
-//~| expected struct `String`, found integer
+//~| expected `String`, found integer
fn main() { println!("{}", i); }
LL | static i: String = 10;
| ^^- help: try using a conversion method: `.to_string()`
| |
- | expected struct `String`, found integer
+ | expected `String`, found integer
error: aborting due to previous error
--> $DIR/issue-5216.rs:3:21
|
LL | pub static C: S = S(f);
- | - ^ expected struct `Box`, found fn item
+ | - ^ expected `Box<dyn FnMut() + Sync>`, found fn item
| |
| arguments to this struct are incorrect
|
--> $DIR/issue-5216.rs:8:19
|
LL | pub static D: T = g;
- | ^ expected struct `Box`, found fn item
+ | ^ expected `Box<dyn FnMut() + Sync>`, found fn item
|
= note: expected struct `Box<(dyn FnMut() + Sync + 'static)>`
found fn item `fn() {g}`
--> $DIR/static-reference-to-fn-1.rs:17:15
|
LL | func: &foo,
- | ^^^^
- | |
- | expected fn pointer, found fn item
- | help: consider casting to a fn pointer: `&(foo as fn() -> Option<isize>)`
+ | ^^^^ expected `&fn() -> Option<isize>`, found `&fn() -> Option<isize> {foo}`
|
= note: expected reference `&fn() -> Option<isize>`
found reference `&fn() -> Option<isize> {foo}`
= note: fn items are distinct from fn pointers
+ = note: when the arguments and return types match, functions can be coerced to function pointers
+help: consider casting to a fn pointer
+ |
+LL | func: &(foo as fn() -> Option<isize>),
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
// check-pass
// compile-flags: -Zhir-stats
// only-x86_64
-// ignore-stage1 FIXME: remove after next bootstrap bump
+
+// Type layouts sometimes change. When that happens, until the next bootstrap
+// bump occurs, stage1 and stage2 will give different outputs for this test.
+// Add an `ignore-stage1` comment marker to work around that problem during
+// that time.
// The aim here is to include at least one of every different type of top-level
// AST/HIR node reported by `-Zhir-stats`.
--> $DIR/str-lit-type-mismatch.rs:2:20
|
LL | let x: &[u8] = "foo";
- | ----- ^^^^^ expected slice `[u8]`, found `str`
+ | ----- ^^^^^ expected `&[u8]`, found `&str`
| |
| expected due to this
|
--> $DIR/str-lit-type-mismatch.rs:3:23
|
LL | let y: &[u8; 4] = "baaa";
- | -------- ^^^^^^ expected array `[u8; 4]`, found `str`
+ | -------- ^^^^^^ expected `&[u8; 4]`, found `&str`
| |
| expected due to this
|
--> $DIR/str-lit-type-mismatch.rs:4:19
|
LL | let z: &str = b"foo";
- | ---- ^^^^^^ expected `str`, found array `[u8; 3]`
+ | ---- ^^^^^^ expected `&str`, found `&[u8; 3]`
| |
| expected due to this
|
let foo = Some(Foo::Other);
if let Some(Foo::Bar {_}) = foo {}
- //~^ ERROR expected identifier, found reserved identifier `_`
- //~| ERROR pattern does not mention field `bar` [E0027]
+ //~^ ERROR expected field pattern, found `_`
}
-error: expected identifier, found reserved identifier `_`
+error: expected field pattern, found `_`
--> $DIR/struct-enum-ignoring-field-with-underscore.rs:9:27
|
LL | if let Some(Foo::Bar {_}) = foo {}
- | ^ expected identifier, found reserved identifier
-
-error[E0027]: pattern does not mention field `bar`
- --> $DIR/struct-enum-ignoring-field-with-underscore.rs:9:17
- |
-LL | if let Some(Foo::Bar {_}) = foo {}
- | ^^^^^^^^^^^^ missing field `bar`
- |
-help: include the missing field in the pattern
+ | ^
|
-LL | if let Some(Foo::Bar {_, bar }) = foo {}
- | ~~~~~~~
-help: if you don't care about this missing field, you can explicitly ignore it
+help: to omit remaining fields, use `..`
|
-LL | if let Some(Foo::Bar {_, .. }) = foo {}
- | ~~~~~~
+LL | if let Some(Foo::Bar {..}) = foo {}
+ | ~~
-error: aborting due to 2 previous errors
+error: aborting due to previous error
-For more information about this error, try `rustc --explain E0027`.
--> $DIR/struct-base-wrong-type.rs:7:33
|
LL | static foo: Foo = Foo { a: 2, ..bar };
- | ^^^ expected struct `Foo`, found struct `Bar`
+ | ^^^ expected `Foo`, found `Bar`
error[E0308]: mismatched types
--> $DIR/struct-base-wrong-type.rs:8:35
|
LL | static foo_i: Foo = Foo { a: 2, ..4 };
- | ^ expected struct `Foo`, found integer
+ | ^ expected `Foo`, found integer
error[E0308]: mismatched types
--> $DIR/struct-base-wrong-type.rs:12:27
|
LL | let f = Foo { a: 2, ..b };
- | ^ expected struct `Foo`, found struct `Bar`
+ | ^ expected `Foo`, found `Bar`
error[E0308]: mismatched types
--> $DIR/struct-base-wrong-type.rs:13:34
|
LL | let f__isize = Foo { a: 2, ..4 };
- | ^ expected struct `Foo`, found integer
+ | ^ expected `Foo`, found integer
error: aborting due to 4 previous errors
LL | | inner: u
LL | |
LL | | }
- | |_________^ expected type parameter `U`, found type parameter `T`
+ | |_________^ expected `Foo<U>`, found `Foo<T>`
|
= note: expected struct `Foo<U>`
found struct `Foo<T>`
--> $DIR/struct-record-suggestion.rs:23:20
|
LL | let q = B { b: 1..Default::default() };
- | ^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `Range<{integer}>`
|
= note: expected type `u32`
found struct `std::ops::Range<{integer}>`
LL | match (Point { x: 1, y: 2 }) {
| ---------------------- this expression has type `Point<{integer}>`
LL | PointF::<u32> { .. } => {}
- | ^^^^^^^^^^^^^^^^^^^^ expected integer, found `f32`
+ | ^^^^^^^^^^^^^^^^^^^^ expected `Point<{integer}>`, found `Point<f32>`
|
= note: expected struct `Point<{integer}>`
found struct `Point<f32>`
LL | match (Point { x: 1, y: 2 }) {
| ---------------------- this expression has type `Point<{integer}>`
LL | PointF { .. } => {}
- | ^^^^^^^^^^^^^ expected integer, found `f32`
+ | ^^^^^^^^^^^^^ expected `Point<{integer}>`, found `Point<f32>`
|
= note: expected struct `Point<{integer}>`
found struct `Point<f32>`
LL | match (Pair { x: 1, y: 2 }) {
| --------------------- this expression has type `Pair<{integer}, {integer}>`
LL | PairF::<u32> { .. } => {}
- | ^^^^^^^^^^^^^^^^^^^ expected integer, found `f32`
+ | ^^^^^^^^^^^^^^^^^^^ expected `Pair<{integer}, {integer}>`, found `Pair<f32, u32>`
|
= note: expected struct `Pair<{integer}, {integer}>`
found struct `Pair<f32, u32>`
--- /dev/null
+// run-rustfix
+
+// Suggest providing a std::ptr::null{,_mut}() to a function that takes in a raw
+// pointer if a literal 0 was provided by the user.
+
+extern "C" {
+ fn foo(ptr: *const u8);
+
+ fn foo_mut(ptr: *mut u8);
+
+ fn usize(ptr: *const usize);
+
+ fn usize_mut(ptr: *mut usize);
+}
+
+fn main() {
+ unsafe {
+ foo(std::ptr::null());
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null()`
+ foo_mut(std::ptr::null_mut());
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null_mut()`
+ usize(std::ptr::null());
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null()`
+ usize_mut(std::ptr::null_mut());
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null_mut()`
+ }
+}
--- /dev/null
+// run-rustfix
+
+// Suggest providing a std::ptr::null{,_mut}() to a function that takes in a raw
+// pointer if a literal 0 was provided by the user.
+
+extern "C" {
+ fn foo(ptr: *const u8);
+
+ fn foo_mut(ptr: *mut u8);
+
+ fn usize(ptr: *const usize);
+
+ fn usize_mut(ptr: *mut usize);
+}
+
+fn main() {
+ unsafe {
+ foo(0);
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null()`
+ foo_mut(0);
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null_mut()`
+ usize(0);
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null()`
+ usize_mut(0);
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null_mut()`
+ }
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/suggest-null-ptr.rs:18:13
+ |
+LL | foo(0);
+ | --- ^ expected `*const u8`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected raw pointer `*const u8`
+ found type `usize`
+note: function defined here
+ --> $DIR/suggest-null-ptr.rs:7:8
+ |
+LL | fn foo(ptr: *const u8);
+ | ^^^
+help: if you meant to create a null pointer, use `std::ptr::null()`
+ |
+LL | foo(std::ptr::null());
+ | ~~~~~~~~~~~~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/suggest-null-ptr.rs:21:17
+ |
+LL | foo_mut(0);
+ | ------- ^ expected `*mut u8`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected raw pointer `*mut u8`
+ found type `usize`
+note: function defined here
+ --> $DIR/suggest-null-ptr.rs:9:8
+ |
+LL | fn foo_mut(ptr: *mut u8);
+ | ^^^^^^^
+help: if you meant to create a null pointer, use `std::ptr::null_mut()`
+ |
+LL | foo_mut(std::ptr::null_mut());
+ | ~~~~~~~~~~~~~~~~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/suggest-null-ptr.rs:24:15
+ |
+LL | usize(0);
+ | ----- ^ expected `*const usize`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected raw pointer `*const usize`
+ found type `usize`
+note: function defined here
+ --> $DIR/suggest-null-ptr.rs:11:8
+ |
+LL | fn usize(ptr: *const usize);
+ | ^^^^^
+help: if you meant to create a null pointer, use `std::ptr::null()`
+ |
+LL | usize(std::ptr::null());
+ | ~~~~~~~~~~~~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/suggest-null-ptr.rs:27:19
+ |
+LL | usize_mut(0);
+ | --------- ^ expected `*mut usize`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected raw pointer `*mut usize`
+ found type `usize`
+note: function defined here
+ --> $DIR/suggest-null-ptr.rs:13:8
+ |
+LL | fn usize_mut(ptr: *mut usize);
+ | ^^^^^^^^^
+help: if you meant to create a null pointer, use `std::ptr::null_mut()`
+ |
+LL | usize_mut(std::ptr::null_mut());
+ | ~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
LL | let _: Option<(i32, bool)> = Some(1, 2);
| ^^^^ - argument of type `{integer}` unexpected
|
-note: expected tuple, found integer
+note: expected `(i32, bool)`, found integer
--> $DIR/args-instead-of-tuple-errors.rs:6:39
|
LL | let _: Option<(i32, bool)> = Some(1, 2);
LL | int_bool(1, 2);
| ^^^^^^^^ - argument of type `{integer}` unexpected
|
-note: expected tuple, found integer
+note: expected `(i32, bool)`, found integer
--> $DIR/args-instead-of-tuple-errors.rs:8:14
|
LL | int_bool(1, 2);
--> $DIR/args-instead-of-tuple-errors.rs:14:34
|
LL | let _: Option<(i32,)> = Some(5_usize);
- | ---- ^^^^^^^ expected tuple, found `usize`
+ | ---- ^^^^^^^ expected `(i32,)`, found `usize`
| |
| arguments to this enum variant are incorrect
|
--> $DIR/args-instead-of-tuple-errors.rs:17:34
|
LL | let _: Option<(i32,)> = Some((5_usize));
- | ---- ^^^^^^^^^ expected tuple, found `usize`
+ | ---- ^^^^^^^^^ expected `(i32,)`, found `usize`
| |
| arguments to this enum variant are incorrect
|
--> $DIR/args-instead-of-tuple.rs:14:34
|
LL | let _: Option<(i32,)> = Some(3);
- | ---- ^ expected tuple, found integer
+ | ---- ^ expected `(i32,)`, found integer
| |
| arguments to this enum variant are incorrect
|
--> $DIR/args-instead-of-tuple.rs:17:34
|
LL | let _: Option<(i32,)> = Some((3));
- | ---- ^^^ expected tuple, found integer
+ | ---- ^^^ expected `(i32,)`, found integer
| |
| arguments to this enum variant are incorrect
|
--> $DIR/as-ref.rs:7:29
|
LL | opt.map(|arg| takes_ref(arg));
- | --- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | --- --------- ^^^ expected `&Foo`, found `Foo`
| | |
| | arguments to this function are incorrect
| help: consider using `as_ref` instead: `as_ref().map`
--> $DIR/as-ref.rs:8:39
|
LL | opt.and_then(|arg| Some(takes_ref(arg)));
- | -------- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | -------- --------- ^^^ expected `&Foo`, found `Foo`
| | |
| | arguments to this function are incorrect
| help: consider using `as_ref` instead: `as_ref().and_then`
--> $DIR/as-ref.rs:10:29
|
LL | opt.map(|arg| takes_ref(arg));
- | --- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | --- --------- ^^^ expected `&Foo`, found `Foo`
| | |
| | arguments to this function are incorrect
| help: consider using `as_ref` instead: `as_ref().map`
--> $DIR/as-ref.rs:11:37
|
LL | opt.and_then(|arg| Ok(takes_ref(arg)));
- | -------- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | -------- --------- ^^^ expected `&Foo`, found `Foo`
| | |
| | arguments to this function are incorrect
| help: consider using `as_ref` instead: `as_ref().and_then`
LL | let y: Option<&usize> = x;
| -------------- ^
| | |
- | | expected enum `Option`, found `&Option<usize>`
+ | | expected `Option<&usize>`, found `&Option<usize>`
| | help: you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`: `x.as_ref()`
| expected due to this
|
--> $DIR/as-ref.rs:15:37
|
LL | let y: Result<&usize, &usize> = x;
- | ---------------------- ^ expected enum `Result`, found reference
+ | ---------------------- ^ expected `Result<&usize, &usize>`, found `&Result<usize, usize>`
| |
| expected due to this
|
--> $DIR/as-ref.rs:19:36
|
LL | let y: Result<&usize, usize> = x;
- | --------------------- ^ expected enum `Result`, found reference
+ | --------------------- ^ expected `Result<&usize, usize>`, found `&Result<usize, usize>`
| |
| expected due to this
|
--> $DIR/as-ref.rs:22:42
|
LL | multiple_ref_opt.map(|arg| takes_ref(arg));
- | --- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | --- --------- ^^^ expected `&Foo`, found `Foo`
| | |
| | arguments to this function are incorrect
| help: consider using `as_ref` instead: `as_ref().map`
--> $DIR/as-ref.rs:23:52
|
LL | multiple_ref_opt.and_then(|arg| Some(takes_ref(arg)));
- | -------- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | -------- --------- ^^^ expected `&Foo`, found `Foo`
| | |
| | arguments to this function are incorrect
| help: consider using `as_ref` instead: `as_ref().and_then`
--> $DIR/as-ref.rs:25:45
|
LL | multiple_ref_result.map(|arg| takes_ref(arg));
- | --- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | --- --------- ^^^ expected `&Foo`, found `Foo`
| | |
| | arguments to this function are incorrect
| help: consider using `as_ref` instead: `as_ref().map`
--> $DIR/as-ref.rs:26:53
|
LL | multiple_ref_result.and_then(|arg| Ok(takes_ref(arg)));
- | -------- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | -------- --------- ^^^ expected `&Foo`, found `Foo`
| | |
| | arguments to this function are incorrect
| help: consider using `as_ref` instead: `as_ref().and_then`
--> $DIR/boxed-variant-field.rs:9:31
|
LL | Ty::List(elem) => foo(elem),
- | --- ^^^^ expected enum `Ty`, found struct `Box`
+ | --- ^^^^ expected `Ty`, found `Box<Ty>`
| |
| arguments to this function are incorrect
|
LL | let y = Box::new(|| 1);
| -- the found closure
LL | x = y;
- | ^ expected `i32`, found struct `Box`
+ | ^ expected `i32`, found `Box<[closure@call-boxed.rs:3:22]>`
|
= note: expected type `i32`
found struct `Box<[closure@$DIR/call-boxed.rs:3:22: 3:24]>`
LL | fn foo(mut s: String) -> String {
| ------ expected `String` because of return type
LL | s.push_str("asdf")
- | ^^^^^^^^^^^^^^^^^^ expected struct `String`, found `()`
+ | ^^^^^^^^^^^^^^^^^^ expected `String`, found `()`
|
note: method `push_str` modifies its receiver in-place
--> $DIR/chain-method-call-mutation-in-place.rs:3:7
LL | fn wut(t: &Foo) -> Foo {
| --- expected `Foo` because of return type
LL | t.clone()
- | ^^^^^^^^^ expected struct `Foo`, found `&Foo`
+ | ^^^^^^^^^ expected `Foo`, found `&Foo`
|
note: `Foo` does not implement `Clone`, so `&Foo` was cloned instead
--> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5
LL | let Thing { foo } = t;
| ^^^ - this expression has type `Thing`
| |
- | expected struct `String`, found struct `foo`
+ | expected `String`, found `foo`
| `foo` is interpreted as a unit struct, not a new binding
|
help: bind the struct field to a different name instead
--> $DIR/copied-and-cloned.rs:7:26
|
LL | expect::<Option<()>>(x);
- | -------------------- ^ expected `()`, found `&()`
+ | -------------------- ^ expected `Option<()>`, found `Option<&()>`
| |
| arguments to this function are incorrect
|
--> $DIR/copied-and-cloned.rs:11:30
|
LL | expect::<Result<(), ()>>(x);
- | ------------------------ ^ expected `()`, found `&()`
+ | ------------------------ ^ expected `Result<(), ()>`, found `Result<&(), _>`
| |
| arguments to this function are incorrect
|
--> $DIR/copied-and-cloned.rs:16:30
|
LL | expect::<Option<String>>(x);
- | ------------------------ ^ expected struct `String`, found `&String`
+ | ------------------------ ^ expected `Option<String>`, found `Option<&String>`
| |
| arguments to this function are incorrect
|
--> $DIR/copied-and-cloned.rs:20:34
|
LL | expect::<Result<String, ()>>(x);
- | ---------------------------- ^ expected struct `String`, found `&String`
+ | ---------------------------- ^ expected `Result<String, ()>`, found `Result<&String, _>`
| |
| arguments to this function are incorrect
|
LL | / intrinsic_match! {
LL | | "abc"
LL | | };
- | |_____^ expected `&str`, found struct `String`
+ | |_____^ expected `&str`, found `String`
|
= note: this error originates in the macro `format` which comes from the expansion of the macro `intrinsic_match` (in Nightly builds, run with -Z macro-backtrace for more info)
--> $DIR/hidden-child.rs:9:26
|
LL | let x: Option<i32> = 1i32;
- | ----------- ^^^^ expected enum `Option`, found `i32`
+ | ----------- ^^^^ expected `Option<i32>`, found `i32`
| |
| expected due to this
|
--> $DIR/hidden-parent.rs:6:26
|
LL | let x: Option<i32> = 1i32;
- | ----------- ^^^^ expected enum `Option`, found `i32`
+ | ----------- ^^^^ expected `Option<i32>`, found `i32`
| |
| expected due to this
|
| - this type parameter ----------------------- expected `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>` because of return type
LL | // We could instead use an `async` block, but this way we have no std spans.
LL | x
- | ^ expected struct `Pin`, found type parameter `F`
+ | ^ expected `Pin<Box<...>>`, found type parameter `F`
|
= note: expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>`
found type parameter `F`
LL | fn bar<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
| ----------------------- expected `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>` because of return type
LL | Box::new(x)
- | ^^^^^^^^^^^ expected struct `Pin`, found struct `Box`
+ | ^^^^^^^^^^^ expected `Pin<Box<...>>`, found `Box<F>`
|
= note: expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>`
found struct `Box<F>`
LL | fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
| - this type parameter
LL | Pin::new(x)
- | -------- ^ expected struct `Box`, found type parameter `F`
+ | -------- ^ expected `Box<dyn Future<Output = ...> + Send>`, found type parameter `F`
| |
| arguments to this function are incorrect
| help: use `Box::pin` to pin and box this expression: `Box::pin`
LL | | }
| | ^
| | |
- | |_____expected struct `Pin`, found `async` block
+ | |_____expected `Pin<Box<...>>`, found `async` block
| arguments to this function are incorrect
|
= note: expected struct `Pin<Box<dyn Future<Output = i32> + Send>>`
LL | if let B::Fst = a {};
| ^^^^^^ - this expression has type `A`
| |
- | expected struct `A`, found enum `B`
+ | expected `A`, found `B`
|
help: you might have meant to use field `b` whose type is `B`
|
| - this expression has type `A`
...
LL | B::Fst => (),
- | ^^^^^^ expected struct `A`, found enum `B`
+ | ^^^^^^ expected `A`, found `B`
|
help: you might have meant to use field `b` whose type is `B`
|
| - this expression has type `A`
...
LL | B::Snd => (),
- | ^^^^^^ expected struct `A`, found enum `B`
+ | ^^^^^^ expected `A`, found `B`
|
help: you might have meant to use field `b` whose type is `B`
|
| --- this expression has type `Foo`
LL |
LL | 1u32 => (),
- | ^^^^ expected union `Foo`, found `u32`
+ | ^^^^ expected `Foo`, found `u32`
|
help: you might have meant to use field `bar` whose type is `u32`
|
| -------- `S` defines a struct constructor here, which should be called
...
LL | let _: S = S;
- | - ^ expected struct `S`, found struct constructor
+ | - ^ expected `S`, found struct constructor
| |
| expected due to this
|
| -------- `V` defines a struct constructor here, which should be called
...
LL | let _: V = V;
- | - ^ expected struct `V`, found struct constructor
+ | - ^ expected `V`, found struct constructor
| |
| expected due to this
|
| - `A` defines an enum variant constructor here, which should be called
...
LL | let _: E = E::A;
- | - ^^^^ expected enum `E`, found enum constructor
+ | - ^^^^ expected `E`, found enum constructor
| |
| expected due to this
|
--> $DIR/format-borrow.rs:2:21
|
LL | let a: String = &String::from("a");
- | ------ ^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&String`
+ | ------ ^^^^^^^^^^^^^^^^^^ expected `String`, found `&String`
| |
| expected due to this
|
--> $DIR/format-borrow.rs:4:21
|
LL | let b: String = &format!("b");
- | ------ ^^^^^^^^^^^^^ expected struct `String`, found `&String`
+ | ------ ^^^^^^^^^^^^^ expected `String`, found `&String`
| |
| expected due to this
|
--> $DIR/format-borrow.rs:6:21
|
LL | let c: String = &mut format!("c");
- | ------ ^^^^^^^^^^^^^^^^^ expected struct `String`, found `&mut String`
+ | ------ ^^^^^^^^^^^^^^^^^ expected `String`, found `&mut String`
| |
| expected due to this
|
--> $DIR/format-borrow.rs:8:21
|
LL | let d: String = &mut (format!("d"));
- | ------ ^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&mut String`
+ | ------ ^^^^^^^^^^^^^^^^^^^ expected `String`, found `&mut String`
| |
| expected due to this
|
};
}
-async fn async_dummy() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type
-//~| NOTE while checking the return type of the `async fn`
-//~| NOTE in this expansion of desugaring of `async` block or function
-//~| NOTE checked the `Output` of this `async fn`, expected opaque type
-//~| NOTE while checking the return type of the `async fn`
-//~| NOTE in this expansion of desugaring of `async` block or function
-async fn async_dummy2() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type
-//~| NOTE checked the `Output` of this `async fn`, found opaque type
-//~| NOTE while checking the return type of the `async fn`
-//~| NOTE in this expansion of desugaring of `async` block or function
-//~| NOTE while checking the return type of the `async fn`
-//~| NOTE in this expansion of desugaring of `async` block or function
+async fn async_dummy() {}
+
+async fn async_dummy2() {}
async fn async_extra_semicolon_same() {
let _ = if true {
error[E0308]: `if` and `else` have incompatible types
- --> $DIR/if-then-neeing-semi.rs:37:9
+ --> $DIR/if-then-neeing-semi.rs:28:9
|
LL | let _ = if true {
| _____________-
LL | | };
| |_____- `if` and `else` have incompatible types
|
-note: while checking the return type of the `async fn`
- --> $DIR/if-then-neeing-semi.rs:18:24
- |
-LL | async fn async_dummy() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
= note: expected unit type `()`
found opaque type `impl Future<Output = ()>`
help: consider `await`ing on the `Future`
|
error[E0308]: `if` and `else` have incompatible types
- --> $DIR/if-then-neeing-semi.rs:50:9
+ --> $DIR/if-then-neeing-semi.rs:41:9
|
LL | let _ = if true {
| _____________-
LL | | };
| |_____- `if` and `else` have incompatible types
|
-note: while checking the return type of the `async fn`
- --> $DIR/if-then-neeing-semi.rs:24:25
- |
-LL | async fn async_dummy2() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
= note: expected unit type `()`
found opaque type `impl Future<Output = ()>`
help: consider `await`ing on the `Future`
|
error[E0308]: `if` and `else` have incompatible types
- --> $DIR/if-then-neeing-semi.rs:63:9
+ --> $DIR/if-then-neeing-semi.rs:54:9
|
LL | let _ = if true {
| _____________-
LL | | };
| |_____- `if` and `else` have incompatible types
|
-note: while checking the return type of the `async fn`
- --> $DIR/if-then-neeing-semi.rs:18:24
- |
-LL | async fn async_dummy() {}
- | ^ checked the `Output` of this `async fn`, expected opaque type
-note: while checking the return type of the `async fn`
- --> $DIR/if-then-neeing-semi.rs:24:25
- |
-LL | async fn async_dummy2() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
= note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/if-then-neeing-semi.rs:18:24>)
- found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/if-then-neeing-semi.rs:24:25>)
+ found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/if-then-neeing-semi.rs:20:25>)
= note: distinct uses of `impl Trait` result in different opaque types
help: consider `await`ing on both `Future`s
|
--> $DIR/into-convert.rs:6:16
|
LL | let x: A = B;
- | - ^ expected struct `A`, found struct `B`
+ | - ^ expected `A`, found `B`
| |
| expected due to this
|
--> $DIR/into-convert.rs:10:24
|
LL | let y: Arc<Path> = PathBuf::new();
- | --------- ^^^^^^^^^^^^^^ expected struct `Arc`, found struct `PathBuf`
+ | --------- ^^^^^^^^^^^^^^ expected `Arc<Path>`, found `PathBuf`
| |
| expected due to this
|
--> $DIR/into-convert.rs:14:24
|
LL | let z: AtomicU32 = 1;
- | --------- ^ expected struct `AtomicU32`, found integer
+ | --------- ^ expected `AtomicU32`, found integer
| |
| expected due to this
|
| | ---------------------------------- expected because of this
LL | | } else {
LL | | FakeResult::Ok(())
- | | ^^^^^^^^^^^^^^^^^^ expected enum `FakeResult`, found `()`
+ | | ^^^^^^^^^^^^^^^^^^ expected `FakeResult<FakeResult<()>>`, found `FakeResult<()>`
LL | | };
| |_____- `if` and `else` have incompatible types
|
LL | | true => B,
| | - this is found to be of type `B`
LL | | false => C,
- | | ^ expected struct `B`, found struct `C`
+ | | ^ expected `B`, found `C`
LL | |
LL | | }
| |_____- `match` arms have incompatible types
LL | let (cmp, router) = self.router.at()?;
| ^^^^^^^^^^^^^ ----------------- this expression has type `Match<&(for<'a> fn(&'a ()), Box<Wrapper>)>`
| |
- | expected struct `Match`, found tuple
+ | expected `Match<&(fn(&()), Box<Wrapper>)>`, found `(_, _)`
|
= note: expected struct `Match<&(for<'a> fn(&'a ()), Box<Wrapper>)>`
found tuple `(_, _)`
--> $DIR/issue-102892.rs:15:26
|
LL | let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too
- | ------ ^^^^^^ expected tuple, found `&(A, B)`
+ | ------ ^^^^^^ expected `(A, B)`, found `&(A, B)`
| |
| expected due to this
|
--> $DIR/issue-102892.rs:20:32
|
LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
- | ^^^^^^^^^^^^^^ expected tuple, found `&mut (A, B)`
+ | ^^^^^^^^^^^^^^ expected `(A, B)`, found `&mut (A, B)`
|
= note: expected tuple `(A, B)`
found mutable reference `&mut (A, B)`
--> $DIR/issue-102892.rs:20:48
|
LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
- | ^^^^^^^^^^ expected struct `A`, found `&A`
+ | ^^^^^^^^^^ expected `A`, found `&A`
|
help: consider removing the borrow
|
--> $DIR/issue-105494.rs:2:19
|
LL | let _v: i32 = (1 as i32).to_string();
- | --- ^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String`
+ | --- ^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `String`
| |
| expected due to this
|
--> $DIR/issue-105494.rs:5:19
|
LL | let _v: i32 = (1 as i128).to_string();
- | --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String`
+ | --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `String`
| |
| expected due to this
--> $DIR/issue-105494.rs:7:20
|
LL | let _v: &str = "foo".to_string();
- | ---- ^^^^^^^^^^^^^^^^^ expected `&str`, found struct `String`
+ | ---- ^^^^^^^^^^^^^^^^^ expected `&str`, found `String`
| |
| expected due to this
|
| ------ expected due to this type
...
LL | path = format!("{}/{}", path, folder).as_str();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&str`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `String`, found `&str`
|
help: try removing the method call
|
--> $DIR/issue-106443-sugg-clone-for-arg.rs:11:9
|
LL | foo(s);
- | --- ^ expected struct `S`, found `&S`
+ | --- ^ expected `S`, found `&S`
| |
| arguments to this function are incorrect
|
--> $DIR/issue-106443-sugg-clone-for-arg.rs:17:9
|
LL | bar(t);
- | --- ^ expected struct `T`, found `&T`
+ | --- ^ expected `T`, found `&T`
| |
| arguments to this function are incorrect
|
--> $DIR/issue-52820.rs:12:9
|
LL | guts,
- | ^^^^ expected struct `String`, found `&str`
+ | ^^^^ expected `String`, found `&str`
|
help: try using a conversion method
|
| ^^^^^-----^^
| | |
| | help: try using a conversion method: `to_string`
- | expected struct `String`, found `&str`
+ | expected `String`, found `&str`
error: aborting due to 2 previous errors
| -------- ^^^^^^^^^^-----^^
| | | |
| | | help: try using a conversion method: `to_vec`
- | | expected struct `Vec`, found `&[i32]`
+ | | expected `Vec<i32>`, found `&[i32]`
| expected due to this
|
= note: expected struct `Vec<i32>`
| ------ ^^-----^^
| | | |
| | | help: try using a conversion method: `to_string`
- | | expected struct `String`, found `&str`
+ | | expected `String`, found `&str`
| expected due to this
error: aborting due to 2 previous errors
--> $DIR/issue-59819.rs:28:18
|
LL | let y: i32 = x;
- | --- ^ expected `i32`, found struct `Foo`
+ | --- ^ expected `i32`, found `Foo`
| |
| expected due to this
|
LL | let g: String = f;
| ------ ^- help: try using a conversion method: `.to_string()`
| | |
- | | expected struct `String`, found struct `Bar`
+ | | expected `String`, found `Bar`
| expected due to this
error: aborting due to 3 previous errors
LL | | }
| |_____- `match` arms have incompatible types
|
-note: while checking the return type of the `async fn`
- --> $DIR/auxiliary/issue-81839.rs:6:49
- |
-LL | pub async fn answer_str(&self, _s: &str) -> Test {
- | ^^^^ checked the `Output` of this `async fn`, found opaque type
= note: expected unit type `()`
found opaque type `impl Future<Output = Test>`
LL | | "B"
| | ^^^- help: try using a conversion method: `.to_string()`
| | |
- | | expected struct `String`, found `&str`
+ | | expected `String`, found `&str`
LL | | };
| |_____- `if` and `else` have incompatible types
--> $DIR/issue-86100-tuple-paren-comma.rs:9:22
|
LL | let _x: (i32,) = (5);
- | ------ ^^^ expected tuple, found integer
+ | ------ ^^^ expected `(i32,)`, found integer
| |
| expected due to this
|
--> $DIR/issue-86100-tuple-paren-comma.rs:13:9
|
LL | foo((Some(3)));
- | --- ^^^^^^^^^ expected tuple, found enum `Option`
+ | --- ^^^^^^^^^ expected `(_,)`, found `Option<{integer}>`
| |
| arguments to this function are incorrect
|
--> $DIR/issue-86100-tuple-paren-comma.rs:17:22
|
LL | let _s = S { _s: ("abc".to_string()) };
- | ^^^^^^^^^^^^^^^^^^^ expected tuple, found struct `String`
+ | ^^^^^^^^^^^^^^^^^^^ expected `(String,)`, found `String`
|
= note: expected tuple `(String,)`
found struct `String`
--> $DIR/issue-90213-expected-boxfuture-self-ice.rs:9:19
|
LL | Self::foo(None)
- | --------- ^^^^ expected struct `Box`, found enum `Option`
+ | --------- ^^^^ expected `Box<Option<S>>`, found `Option<_>`
| |
| arguments to this function are incorrect
|
LL | match &x[..] {
| ------ this expression has type `&[i32]`
LL | [&v] => {},
- | ^^ expected `i32`, found reference
+ | ^^ expected `i32`, found `&_`
|
= note: expected type `i32`
found reference `&_`
LL | match y {
| - this expression has type `i32`
LL | &v => {},
- | ^^ expected `i32`, found reference
+ | ^^ expected `i32`, found `&_`
|
= note: expected type `i32`
found reference `&_`
LL | if let [&v] = &x[..] {}
| ^^ ------ this expression has type `&[i32]`
| |
- | expected `i32`, found reference
+ | expected `i32`, found `&_`
|
= note: expected type `i32`
found reference `&_`
};
}
-async fn async_dummy() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type
-//~| NOTE while checking the return type of the `async fn`
-//~| NOTE in this expansion of desugaring of `async` block or function
-//~| NOTE checked the `Output` of this `async fn`, expected opaque type
-//~| NOTE while checking the return type of the `async fn`
-//~| NOTE in this expansion of desugaring of `async` block or function
-async fn async_dummy2() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type
-//~| NOTE checked the `Output` of this `async fn`, found opaque type
-//~| NOTE while checking the return type of the `async fn`
-//~| NOTE in this expansion of desugaring of `async` block or function
-//~| NOTE while checking the return type of the `async fn`
-//~| NOTE in this expansion of desugaring of `async` block or function
+async fn async_dummy() {}
+
+async fn async_dummy2() {}
async fn async_extra_semicolon_same() {
let _ = match true { //~ NOTE `match` arms have incompatible types
error[E0308]: `match` arms have incompatible types
- --> $DIR/match-prev-arm-needing-semi.rs:35:18
+ --> $DIR/match-prev-arm-needing-semi.rs:26:18
|
LL | let _ = match true {
| _____________-
LL | | };
| |_____- `match` arms have incompatible types
|
-note: while checking the return type of the `async fn`
- --> $DIR/match-prev-arm-needing-semi.rs:16:24
- |
-LL | async fn async_dummy() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
= note: expected unit type `()`
found opaque type `impl Future<Output = ()>`
help: consider `await`ing on the `Future`
|
error[E0308]: `match` arms have incompatible types
- --> $DIR/match-prev-arm-needing-semi.rs:48:18
+ --> $DIR/match-prev-arm-needing-semi.rs:39:18
|
LL | let _ = match true {
| _____________-
LL | | };
| |_____- `match` arms have incompatible types
|
-note: while checking the return type of the `async fn`
- --> $DIR/match-prev-arm-needing-semi.rs:22:25
- |
-LL | async fn async_dummy2() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
= note: expected unit type `()`
found opaque type `impl Future<Output = ()>`
help: consider `await`ing on the `Future`
|
error[E0308]: `match` arms have incompatible types
- --> $DIR/match-prev-arm-needing-semi.rs:59:18
+ --> $DIR/match-prev-arm-needing-semi.rs:50:18
|
LL | let _ = match true {
| _____________-
LL | | };
| |_____- `match` arms have incompatible types
|
-note: while checking the return type of the `async fn`
- --> $DIR/match-prev-arm-needing-semi.rs:16:24
- |
-LL | async fn async_dummy() {}
- | ^ checked the `Output` of this `async fn`, expected opaque type
-note: while checking the return type of the `async fn`
- --> $DIR/match-prev-arm-needing-semi.rs:22:25
- |
-LL | async fn async_dummy2() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
= note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>)
- found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:22:25>)
+ found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:18:25>)
= note: distinct uses of `impl Trait` result in different opaque types
help: consider `await`ing on both `Future`s
|
LL | | "baz" => Box::new(Baz),
| | ------------- this is found to be of type `Box<Baz>`
LL | | _ => Box::new(Bar),
- | | ^^^^^^^^^^^^^ expected struct `Baz`, found struct `Bar`
+ | | ^^^^^^^^^^^^^ expected `Box<Baz>`, found `Box<Bar>`
LL | | };
| |_____- `match` arms have incompatible types
|
--> $DIR/match-with-different-arm-types-as-stmt-instead-of-expr.rs:23:22
|
LL | fn wrong(c: &str) -> Box<dyn Foo> {
- | ----- ^^^^^^^^^^^^ expected struct `Box`, found `()`
+ | ----- ^^^^^^^^^^^^ expected `Box<dyn Foo>`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
|
LL | fn method(&self) -> Option<&Vec<u8>> {
| ---------------- expected `Option<&Vec<u8>>` because of return type
LL | self.option..as_ref().map(|x| x)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Option<&Vec<u8>>`, found `Range<Option<Vec<u8>>>`
|
= note: expected enum `Option<&Vec<u8>>`
found struct `std::ops::Range<Option<Vec<u8>>>`
LL | fn method2(&self) -> Option<&u8> {
| ----------- expected `Option<&u8>` because of return type
LL | self.option..foo().get(0)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Option<&u8>`, found `Range<Option<Vec<u8>>>`
|
= note: expected enum `Option<&u8>`
found struct `std::ops::Range<Option<Vec<u8>>>`
LL | fn suggestion(opt: &mut Option<String>) {
| ------------------- expected due to this parameter type
LL | opt = None;
- | ^^^^ expected mutable reference, found enum `Option`
+ | ^^^^ expected `&mut Option<String>`, found `Option<_>`
|
= note: expected mutable reference `&mut Option<String>`
found enum `Option<_>`
LL | fn no_suggestion(opt: &mut Result<String, ()>) {
| ----------------------- expected due to this parameter type
LL | opt = None
- | ^^^^ expected mutable reference, found enum `Option`
+ | ^^^^ expected `&mut Result<String, ()>`, found `Option<_>`
|
= note: expected mutable reference `&mut Result<String, ()>`
found enum `Option<_>`
LL | fn suggestion2(opt: &mut Option<String>) {
| ------------------- expected due to this parameter type
LL | opt = Some(String::new())
- | ^^^^^^^^^^^^^^^^^^^ expected mutable reference, found enum `Option`
+ | ^^^^^^^^^^^^^^^^^^^ expected `&mut Option<String>`, found `Option<String>`
|
= note: expected mutable reference `&mut Option<String>`
found enum `Option<String>`
LL | fn no_suggestion2(opt: &mut Option<String>) {
| ------------------- expected due to this parameter type
LL | opt = Some(42)
- | ^^^^^^^^ expected mutable reference, found enum `Option`
+ | ^^^^^^^^ expected `&mut Option<String>`, found `Option<{integer}>`
|
= note: expected mutable reference `&mut Option<String>`
found enum `Option<{integer}>`
--> $DIR/option-to-bool.rs:4:16
|
LL | if true && x {}
- | ---- ^ expected `bool`, found enum `Option`
+ | ---- ^ expected `bool`, found `Option<i32>`
| |
| expected because this is `bool`
|
--> $DIR/recover-from-semicolon-trailing-item.rs:10:20
|
LL | let _: usize = S {};
- | ----- ^^^^ expected `usize`, found struct `S`
+ | ----- ^^^^ expected `usize`, found `S`
| |
| expected due to this
--> $DIR/recover-from-semicolon-trailing-item.rs:12:20
|
LL | let _: usize = X {};
- | ----- ^^^^ expected `usize`, found struct `X`
+ | ----- ^^^^ expected `usize`, found `X`
| |
| expected due to this
--- /dev/null
+// Check that suggestions to add a zero to integers with a preceding dot only appear when the change
+// will result in a valid floating point literal.
+
+fn main() {}
+
+fn a() {
+ _ = .3u32;
+ //~^ ERROR expected expression, found `.`
+}
+
+fn b() {
+ _ = .0b0;
+ //~^ ERROR expected expression, found `.`
+}
+
+fn c() {
+ _ = .0o07;
+ //~^ ERROR expected expression, found `.`
+}
+
+fn d() {
+ _ = .0x0ABC;
+ //~^ ERROR expected expression, found `.`
+}
--- /dev/null
+error: expected expression, found `.`
+ --> $DIR/recover-invalid-float-invalid.rs:7:9
+ |
+LL | _ = .3u32;
+ | ^ expected expression
+
+error: expected expression, found `.`
+ --> $DIR/recover-invalid-float-invalid.rs:12:9
+ |
+LL | _ = .0b0;
+ | ^ expected expression
+
+error: expected expression, found `.`
+ --> $DIR/recover-invalid-float-invalid.rs:17:9
+ |
+LL | _ = .0o07;
+ | ^ expected expression
+
+error: expected expression, found `.`
+ --> $DIR/recover-invalid-float-invalid.rs:22:9
+ |
+LL | _ = .0x0ABC;
+ | ^ expected expression
+
+error: aborting due to 4 previous errors
+
| ______________________________________________^
LL | |
LL | | } else {
- | |_____^ expected struct `String`, found `()`
+ | |_____^ expected `String`, found `()`
|
help: consider returning the local binding `s`
|
--> $DIR/return-bindings.rs:14:11
|
LL | fn c() -> Option<i32> {
- | - ^^^^^^^^^^^ expected enum `Option`, found `()`
+ | - ^^^^^^^^^^^ expected `Option<i32>`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
|
| ______________________________________________^
LL | |
LL | | } else {
- | |_____^ expected struct `String`, found `()`
+ | |_____^ expected `String`, found `()`
|
help: consider returning the local binding `s`
|
LL | | } else {
| |_____- expected because of this
LL | String::new()
- | ^^^^^^^^^^^^^ expected `()`, found struct `String`
+ | ^^^^^^^^^^^^^ expected `()`, found `String`
|
help: consider returning the local binding `s`
|
--> $DIR/return-bindings.rs:37:20
|
LL | Some(s) => {}
- | ^^ expected struct `String`, found `()`
+ | ^^ expected `String`, found `()`
|
help: consider returning the local binding `s`
|
LL | | Some(s) => {}
| | -- this is found to be of type `()`
LL | | None => String::new(),
- | | ^^^^^^^^^^^^^ expected `()`, found struct `String`
+ | | ^^^^^^^^^^^^^ expected `()`, found `String`
LL | |
LL | | };
| |_____- `match` arms have incompatible types
--> $DIR/shadowed-lplace-method-2.rs:22:17
|
LL | *x.foo(0) = ();
- | --------- ^^ expected struct `X`, found `()`
+ | --------- ^^ expected `X`, found `()`
| |
| expected due to the type of this binding
|
--> $DIR/shadowed-lplace-method.rs:9:24
|
LL | *rc.borrow_mut() = false;
- | ---------------- ^^^^^ expected struct `Rc`, found `bool`
+ | ---------------- ^^^^^ expected `Rc<RefCell<bool>>`, found `bool`
| |
| expected due to the type of this binding
|
LL | | Err(())?;
LL | | Ok(())
LL | | };
- | |_____^ expected struct `Box`, found closure
+ | |_____^ expected `Box<dyn Fn() -> Result<(), ()>>`, found closure
|
= note: expected struct `Box<dyn Fn() -> Result<(), ()>>`
found closure `[closure@$DIR/suggest-box.rs:4:47: 4:49]`
--- /dev/null
+// run-rustfix
+
+#![allow(unused)]
+
+struct Wrapper<T>(T);
+
+fn bar() -> Wrapper<fn()> { Wrapper(foo) }
+//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
+
+fn foo() {}
+
+fn main() {}
--- /dev/null
+// run-rustfix
+
+#![allow(unused)]
+
+struct Wrapper<T>(T);
+
+fn bar() -> _ { Wrapper(foo) }
+//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
+
+fn foo() {}
+
+fn main() {}
--- /dev/null
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+ --> $DIR/suggest-fn-ptr-for-fn-item-in-fn-ret.rs:7:13
+ |
+LL | fn bar() -> _ { Wrapper(foo) }
+ | ^
+ | |
+ | not allowed in type signatures
+ | help: replace with the correct return type: `Wrapper<fn()>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0121`.
--> $DIR/suggest-full-enum-variant-for-local-module.rs:9:28
|
LL | let _: option::O<()> = ();
- | ------------- ^^ expected enum `O`, found `()`
+ | ------------- ^^ expected `O<()>`, found `()`
| |
| expected due to this
|
--> $DIR/suggest-remove-deref.rs:13:9
|
LL | foo(*hello);
- | --- ^^^^^^ expected reference, found struct `S`
+ | --- ^^^^^^ expected `&_`, found `S`
| |
| arguments to this function are incorrect
|
--> $DIR/suggest-remove-deref.rs:21:9
|
LL | bar(*s);
- | --- ^^ expected `&String`, found struct `String`
+ | --- ^^ expected `&String`, found `String`
| |
| arguments to this function are incorrect
|
--> $DIR/suggest-using-chars.rs:2:19
|
LL | let _ = "foo".iter();
- | ^^^^ method not found in `&'static str`
+ | ^^^^ method not found in `&str`
|
help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars`
|
--> $DIR/suggest-using-chars.rs:3:19
|
LL | let _ = "foo".foo();
- | ^^^ method not found in `&'static str`
+ | ^^^ method not found in `&str`
error[E0599]: no method named `iter` found for struct `String` in the current scope
--> $DIR/suggest-using-chars.rs:4:33
--> $DIR/unnecessary_dot_for_floating_point_literal.rs:2:18
|
LL | let _: f64 = 0..10;
- | --- ^^^^^ expected `f64`, found struct `Range`
+ | --- ^^^^^ expected `f64`, found `Range<{integer}>`
| |
| expected due to this
|
--> $DIR/unnecessary_dot_for_floating_point_literal.rs:3:18
|
LL | let _: f64 = 1..;
- | --- ^^^ expected `f64`, found struct `RangeFrom`
+ | --- ^^^ expected `f64`, found `RangeFrom<{integer}>`
| |
| expected due to this
|
--> $DIR/unnecessary_dot_for_floating_point_literal.rs:4:18
|
LL | let _: f64 = ..10;
- | --- ^^^^ expected `f64`, found struct `RangeTo`
+ | --- ^^^^ expected `f64`, found `RangeTo<{integer}>`
| |
| expected due to this
|
--> $DIR/unnecessary_dot_for_floating_point_literal.rs:5:18
|
LL | let _: f64 = std::ops::Range { start: 0, end: 1 };
- | --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `f64`, found struct `Range`
+ | --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `f64`, found `Range<{integer}>`
| |
| expected due to this
|
//~^ ERROR mismatched types
//~| expected unit type `()`
//~| found tuple `(_, _)`
-//~| expected `()`, found tuple
+//~| expected `()`, found
return x;
}
LL | let (x, y) = ();
| ^^^^^^ -- this expression has type `()`
| |
- | expected `()`, found tuple
+ | expected `()`, found `(_, _)`
|
= note: expected unit type `()`
found tuple `(_, _)`
--> $DIR/switched-expectations.rs:3:30
|
LL | let ref string: String = var;
- | ^^^ expected struct `String`, found `i32`
+ | ^^^ expected `String`, found `i32`
error: aborting due to previous error
//~^ ERROR mismatched types
//~| expected type `char`
//~| found enum `Option<_>`
- //~| expected `char`, found enum `Option`
+ //~| expected `char`, found `Option<_>`
}
--> $DIR/tag-that-dare-not-speak-its-name.rs:11:20
|
LL | let x : char = last(y);
- | ---- ^^^^^^^ expected `char`, found enum `Option`
+ | ---- ^^^^^^^ expected `char`, found `Option<_>`
| |
| expected due to this
|
fn want_foo(f: Foo) {}
fn have_bar(b: Bar) {
want_foo(b); //~ ERROR mismatched types
- //~| expected struct `Foo`, found struct `Bar`
+ //~| expected `Foo`, found `Bar`
}
fn main() {}
--> $DIR/terr-in-field.rs:13:14
|
LL | want_foo(b);
- | -------- ^ expected struct `Foo`, found struct `Bar`
+ | -------- ^ expected `Foo`, found `Bar`
| |
| arguments to this function are incorrect
|
--> $DIR/terr-sorts.rs:10:14
|
LL | want_foo(b);
- | -------- ^ expected struct `Foo`, found struct `Box`
+ | -------- ^ expected `Foo`, found `Box<Foo>`
| |
| arguments to this function are incorrect
|
|
LL | pub onion {
| ^
--Ztrack-diagnostics: created at compiler/rustc_parse/src/parser/diagnostics.rs:LL:CC
+-Ztrack-diagnostics: created at compiler/rustc_parse/src/parser/item.rs:LL:CC
|
help: add `struct` here to parse `onion` as a public struct
|
| - this type parameter
...
LL | builder.push(output);
- | ---- ^^^^^^ expected type parameter `F`, found struct `Class`
+ | ---- ^^^^^^ expected type parameter `F`, found `Class<P>`
| |
| arguments to this method are incorrect
|
| ----------------- expected `Matrix<R, C, u32>` because of return type
...
LL | input.into_owned()
- | ^^^^^^^^^^^^^^^^^^ expected `u32`, found associated type
+ | ^^^^^^^^^^^^^^^^^^ expected `Matrix<R, C, u32>`, found `Matrix<R, C, ...>`
|
= note: expected struct `Matrix<_, _, u32>`
found struct `Matrix<_, _, <() as Allocator<R, C>>::Buffer>`
| ^^^^ required by this bound in `is_send`
error[E0277]: `main::TestType` cannot be sent between threads safely
- --> $DIR/negated-auto-traits-error.rs:66:13
+ --> $DIR/negated-auto-traits-error.rs:66:20
|
LL | is_sync(Outer2(TestType));
- | ------- ^^^^^^^^^^^^^^^^ `main::TestType` cannot be sent between threads safely
+ | ------- ^^^^^^^^ `main::TestType` cannot be sent between threads safely
| |
| required by a bound introduced by this call
|
--- /dev/null
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+#![feature(unsized_tuple_coercion)]
+
+trait Foo {}
+
+impl Foo for i32 {}
+
+fn main() {
+ // Unsizing via struct
+ let _: Box<dyn Foo> = Box::new(1i32);
+
+ // Slice unsizing
+ let y = [1, 2, 3];
+ let _: &[i32] = &y;
+
+ // Tuple unsizing
+ let hi = (1i32,);
+ let _: &(dyn Foo,) = &hi;
+
+ // Dropping auto traits
+ let a: &(dyn Foo + Send) = &1;
+ let _: &dyn Foo = a;
+}
--- /dev/null
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+#![feature(trait_upcasting)]
+
+trait Foo: Bar<i32> + Bar<u32> {}
+
+trait Bar<T> {}
+
+fn main() {
+ let x: &dyn Foo = todo!();
+ let y: &dyn Bar<i32> = x;
+ let z: &dyn Bar<u32> = x;
+}
--- /dev/null
+// compile-flags: -Ztrait-solver=next
+
+#![feature(trait_upcasting)]
+
+trait Foo: Bar<i32> + Bar<u32> {}
+
+trait Bar<T> {}
+
+fn main() {
+ let x: &dyn Foo = todo!();
+ let y: &dyn Bar<usize> = x;
+ //~^ ERROR mismatched types
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/upcast-wrong-substs.rs:11:30
+ |
+LL | let y: &dyn Bar<usize> = x;
+ | --------------- ^ expected trait `Bar`, found trait `Foo`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&dyn Bar<usize>`
+ found reference `&dyn Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
--> $DIR/issue-101739-1.rs:8:50
|
LL | Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>,
- | ^^^^^^^^^^^^^^^^ expected struct `Assume`, found `bool`
+ | ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool`
error: aborting due to 2 previous errors
--> $DIR/add-tuple-within-arguments.rs:8:15
|
LL | bar("hi", "hi", "hi");
- | --- ^^^^ expected tuple, found `&str`
+ | --- ^^^^ expected `(&str,)`, found `&str`
| |
| arguments to this function are incorrect
|
LL | groups.push(new_group, vec![process]);
| ^^^^ ------------- argument of type `Vec<&Process>` unexpected
|
-note: expected tuple, found struct `Vec`
+note: expected `(Vec<String>, Vec<Process>)`, found `Vec<String>`
--> $DIR/wrong_argument_ice-3.rs:9:21
|
LL | groups.push(new_group, vec![process]);
--> $DIR/enum-variant-priority-higher-than-other-inherent.rs:22:17
|
LL | let _: u8 = <E2>::V;
- | -- ^^^^^^^ expected `u8`, found enum `E2`
+ | -- ^^^^^^^ expected `u8`, found `E2`
| |
| expected due to this
#[allow(unused_must_use)]
fn main() {
Box::new(test) as AsyncFnPtr;
- //~^ ERROR expected `fn() -> impl Future<Output = ()> {test}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
+ //~^ ERROR expected `test` to be a fn item that returns `Pin<Box<dyn Future<Output = ()>>>`, but it returns `impl Future<Output = ()>
}
-error[E0271]: expected `fn() -> impl Future<Output = ()> {test}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
+error[E0271]: expected `test` to be a fn item that returns `Pin<Box<dyn Future<Output = ()>>>`, but it returns `impl Future<Output = ()>`
--> $DIR/issue-98604.rs:9:5
|
LL | Box::new(test) as AsyncFnPtr;
- | ^^^^^^^^^^^^^^ expected struct `Pin`, found opaque type
+ | ^^^^^^^^^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found opaque type
|
-note: while checking the return type of the `async fn`
- --> $DIR/issue-98604.rs:5:17
- |
-LL | async fn test() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
= note: expected struct `Pin<Box<(dyn Future<Output = ()> + 'static)>>`
found opaque type `impl Future<Output = ()>`
= note: required for the cast from `fn() -> impl Future<Output = ()> {test}` to the object type `dyn Fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>>`
fn main() {
let b: Box<dyn Fn() -> Box<u8>> = Box::new(hi);
- //~^ ERROR expected `fn() -> impl Sized {hi}` to be a fn item that returns `Box<u8>`, but it returns `impl Sized`
+ //~^ ERROR expected `hi` to be a fn item that returns `Box<u8>`, but it returns `impl Sized`
let boxed = b();
let null = *boxed;
println!("{null:?}");
-error[E0271]: expected `fn() -> impl Sized {hi}` to be a fn item that returns `Box<u8>`, but it returns `impl Sized`
+error[E0271]: expected `hi` to be a fn item that returns `Box<u8>`, but it returns `impl Sized`
--> $DIR/issue-98608.rs:6:39
|
LL | fn hi() -> impl Sized {
| ---------- the found opaque type
...
LL | let b: Box<dyn Fn() -> Box<u8>> = Box::new(hi);
- | ^^^^^^^^^^^^ expected struct `Box`, found opaque type
+ | ^^^^^^^^^^^^ expected `Box<u8>`, found opaque type
|
= note: expected struct `Box<u8>`
found opaque type `impl Sized`
LL | fn dont_define_this(_private: MyPrivate) {}
| ^^^^^^^^^
| |
- | expected struct `Private`, found opaque type
+ | expected `Private`, found opaque type
| help: change the parameter type to match the trait: `Private`
|
note: type in trait
--> $DIR/issue-30225.rs:31:9
|
LL | u = v; // mark $0 and $1 in a subtype relationship
- | ^ expected struct `A`, found struct `B`
+ | ^ expected `A`, found `B`
error: aborting due to previous error
--> $DIR/type-ascription-precedence.rs:31:7
|
LL | &(S: &S);
- | ^ expected `&S`, found struct `S`
+ | ^ expected `&S`, found `S`
error[E0308]: mismatched types
--> $DIR/type-ascription-precedence.rs:35:7
|
LL | *(S: Z);
- | ^ expected struct `Z`, found struct `S`
+ | ^ expected `Z`, found `S`
error[E0614]: type `Z` cannot be dereferenced
--> $DIR/type-ascription-precedence.rs:35:5
--> $DIR/type-ascription-precedence.rs:40:7
|
LL | -(S: Z);
- | ^ expected struct `Z`, found struct `S`
+ | ^ expected `Z`, found `S`
error[E0600]: cannot apply unary operator `-` to type `Z`
--> $DIR/type-ascription-precedence.rs:40:5
--> $DIR/type-ascription-precedence.rs:45:5
|
LL | (S + Z): Z;
- | ^^^^^^^ expected struct `Z`, found struct `S`
+ | ^^^^^^^ expected `Z`, found `S`
error[E0308]: mismatched types
--> $DIR/type-ascription-precedence.rs:49:5
|
LL | (S * Z): Z;
- | ^^^^^^^ expected struct `Z`, found struct `S`
+ | ^^^^^^^ expected `Z`, found `S`
error[E0308]: mismatched types
--> $DIR/type-ascription-precedence.rs:53:5
|
LL | (S .. S): S;
- | ^^^^^^^^ expected struct `S`, found struct `Range`
+ | ^^^^^^^^ expected `S`, found `Range<S>`
|
= note: expected struct `S`
found struct `std::ops::Range<S>`
--> $DIR/type-ascription-soundness.rs:7:31
|
LL | let ref x = type_ascribe!(arr, &[u8]);
- | ^^^ expected slice `[u8]`, found array `[u8; 3]`
+ | ^^^ expected `&[u8]`, found `&[u8; 3]`
|
= note: expected reference `&[u8]`
found reference `&[u8; 3]`
--> $DIR/type-ascription-soundness.rs:8:35
|
LL | let ref mut x = type_ascribe!(arr, &[u8]);
- | ^^^ expected slice `[u8]`, found array `[u8; 3]`
+ | ^^^ expected `&[u8]`, found `&[u8; 3]`
|
= note: expected reference `&[u8]`
found reference `&[u8; 3]`
--> $DIR/type-ascription-soundness.rs:9:25
|
LL | match type_ascribe!(arr, &[u8]) {
- | ^^^ expected slice `[u8]`, found array `[u8; 3]`
+ | ^^^ expected `&[u8]`, found `&[u8; 3]`
|
= note: expected reference `&[u8]`
found reference `&[u8; 3]`
--> $DIR/type-ascription-soundness.rs:12:30
|
LL | let _len = type_ascribe!(arr, &[u8]).len();
- | ^^^ expected slice `[u8]`, found array `[u8; 3]`
+ | ^^^ expected `&[u8]`, found `&[u8; 3]`
|
= note: expected reference `&[u8]`
found reference `&[u8; 3]`
| ------------- expected `Result<(), B>` because of return type
LL | match true {
LL | true => x,
- | ^ expected struct `B`, found struct `A`
+ | ^ expected `Result<(), B>`, found `Result<(), A>`
|
= note: expected enum `Result<_, B>`
found enum `Result<_, A>`
| ------------- expected `Result<(), B>` because of return type
LL | match true {
LL | true => return x,
- | ^ expected struct `B`, found struct `A`
+ | ^ expected `Result<(), B>`, found `Result<(), A>`
|
= note: expected enum `Result<_, B>`
found enum `Result<_, A>`
| ____________________________^
LL | | Err(A);
LL | | };
- | |_____^ expected enum `Result`, found `()`
+ | |_____^ expected `Result<(), B>`, found `()`
|
= note: expected enum `Result<(), B>`
found unit type `()`
LL | fn foo1(x: Result<(), A>) -> Result<(), B> {
| ------------- expected `Result<(), B>` because of return type
LL | x
- | ^ expected struct `B`, found struct `A`
+ | ^ expected `Result<(), B>`, found `Result<(), A>`
|
= note: expected enum `Result<_, B>`
found enum `Result<_, A>`
LL | fn foo2(x: Result<(), A>) -> Result<(), B> {
| ------------- expected `Result<(), B>` because of return type
LL | return x;
- | ^ expected struct `B`, found struct `A`
+ | ^ expected `Result<(), B>`, found `Result<(), A>`
|
= note: expected enum `Result<_, B>`
found enum `Result<_, A>`
| ------------- expected `Result<(), B>` because of return type
LL | if true {
LL | x
- | ^ expected struct `B`, found struct `A`
+ | ^ expected `Result<(), B>`, found `Result<(), A>`
|
= note: expected enum `Result<_, B>`
found enum `Result<_, A>`
| ------------- expected `Result<(), B>` because of return type
...
LL | x
- | ^ expected struct `B`, found struct `A`
+ | ^ expected `Result<(), B>`, found `Result<(), A>`
|
= note: expected enum `Result<_, B>`
found enum `Result<_, A>`
--> $DIR/point-at-inference-2.rs:5:9
|
LL | bar(v);
- | --- ^ expected `i32`, found `&{integer}`
+ | --- ^ expected `Vec<i32>`, found `Vec<&{integer}>`
| |
| arguments to this function are incorrect
|
| - here the type of `v` is inferred to be `Vec<&i32>`
LL | baz(&v);
LL | bar(v);
- | --- ^ expected `i32`, found `&i32`
+ | --- ^ expected `Vec<i32>`, found `Vec<&i32>`
| |
| arguments to this function are incorrect
|
LL | baz(&v);
| - here the type of `v` is inferred to be `Vec<&i32>`
LL | bar(v);
- | --- ^ expected `i32`, found `&i32`
+ | --- ^ expected `Vec<i32>`, found `Vec<&i32>`
| |
| arguments to this function are incorrect
|
| - this is of type `&{integer}`, which causes `foo` to be inferred as `Vec<&{integer}>`
...
LL | bar(foo);
- | --- ^^^ expected `i32`, found `&{integer}`
+ | --- ^^^ expected `Vec<i32>`, found `Vec<&{integer}>`
| |
| arguments to this function are incorrect
|
a::try_foo(foo2);
//~^ ERROR mismatched types
//~| perhaps two different versions of crate `crate_a1`
- //~| expected struct `main::a::Foo`
+ //~| expected `main::a::Foo`, found a different `main::a::Foo`
a::try_bar(bar2);
//~^ ERROR mismatched types
//~| perhaps two different versions of crate `crate_a1`
--> $DIR/type-mismatch-same-crate-name.rs:16:20
|
LL | a::try_foo(foo2);
- | ---------- ^^^^ expected struct `main::a::Foo`, found a different struct `main::a::Foo`
+ | ---------- ^^^^ expected `main::a::Foo`, found a different `main::a::Foo`
| |
| arguments to this function are incorrect
|
- = note: struct `main::a::Foo` and struct `main::a::Foo` have similar names, but are actually distinct types
-note: struct `main::a::Foo` is defined in crate `crate_a2`
+ = note: `main::a::Foo` and `main::a::Foo` have similar names, but are actually distinct types
+note: `main::a::Foo` is defined in crate `crate_a2`
--> $DIR/auxiliary/crate_a2.rs:1:1
|
LL | pub struct Foo;
| ^^^^^^^^^^^^^^
-note: struct `main::a::Foo` is defined in crate `crate_a1`
+note: `main::a::Foo` is defined in crate `crate_a1`
--> $DIR/auxiliary/crate_a1.rs:1:1
|
LL | pub struct Foo;
--> $DIR/type-mismatch.rs:17:17
|
LL | want::<foo>(f);
- | ----------- ^ expected struct `foo`, found `usize`
+ | ----------- ^ expected `foo`, found `usize`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:18:17
|
LL | want::<bar>(f);
- | ----------- ^ expected struct `bar`, found `usize`
+ | ----------- ^ expected `bar`, found `usize`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:19:24
|
LL | want::<Foo<usize>>(f);
- | ------------------ ^ expected struct `Foo`, found `usize`
+ | ------------------ ^ expected `Foo<usize>`, found `usize`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:20:27
|
LL | want::<Foo<usize, B>>(f);
- | --------------------- ^ expected struct `Foo`, found `usize`
+ | --------------------- ^ expected `Foo<usize, B>`, found `usize`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:21:22
|
LL | want::<Foo<foo>>(f);
- | ---------------- ^ expected struct `Foo`, found `usize`
+ | ---------------- ^ expected `Foo<foo>`, found `usize`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:22:25
|
LL | want::<Foo<foo, B>>(f);
- | ------------------- ^ expected struct `Foo`, found `usize`
+ | ------------------- ^ expected `Foo<foo, B>`, found `usize`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:23:22
|
LL | want::<Foo<bar>>(f);
- | ---------------- ^ expected struct `Foo`, found `usize`
+ | ---------------- ^ expected `Foo<bar>`, found `usize`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:24:25
|
LL | want::<Foo<bar, B>>(f);
- | ------------------- ^ expected struct `Foo`, found `usize`
+ | ------------------- ^ expected `Foo<bar, B>`, found `usize`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:28:19
|
LL | want::<usize>(f);
- | ------------- ^ expected `usize`, found struct `foo`
+ | ------------- ^ expected `usize`, found `foo`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:29:17
|
LL | want::<bar>(f);
- | ----------- ^ expected struct `bar`, found struct `foo`
+ | ----------- ^ expected `bar`, found `foo`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:30:24
|
LL | want::<Foo<usize>>(f);
- | ------------------ ^ expected struct `Foo`, found struct `foo`
+ | ------------------ ^ expected `Foo<usize>`, found `foo`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:31:27
|
LL | want::<Foo<usize, B>>(f);
- | --------------------- ^ expected struct `Foo`, found struct `foo`
+ | --------------------- ^ expected `Foo<usize, B>`, found `foo`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:32:22
|
LL | want::<Foo<foo>>(f);
- | ---------------- ^ expected struct `Foo`, found struct `foo`
+ | ---------------- ^ expected `Foo<foo>`, found `foo`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:33:25
|
LL | want::<Foo<foo, B>>(f);
- | ------------------- ^ expected struct `Foo`, found struct `foo`
+ | ------------------- ^ expected `Foo<foo, B>`, found `foo`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:34:22
|
LL | want::<Foo<bar>>(f);
- | ---------------- ^ expected struct `Foo`, found struct `foo`
+ | ---------------- ^ expected `Foo<bar>`, found `foo`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:35:25
|
LL | want::<Foo<bar, B>>(f);
- | ------------------- ^ expected struct `Foo`, found struct `foo`
+ | ------------------- ^ expected `Foo<bar, B>`, found `foo`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:39:19
|
LL | want::<usize>(f);
- | ------------- ^ expected `usize`, found struct `Foo`
+ | ------------- ^ expected `usize`, found `Foo<foo>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:40:17
|
LL | want::<foo>(f);
- | ----------- ^ expected struct `foo`, found struct `Foo`
+ | ----------- ^ expected `foo`, found `Foo<foo>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:41:17
|
LL | want::<bar>(f);
- | ----------- ^ expected struct `bar`, found struct `Foo`
+ | ----------- ^ expected `bar`, found `Foo<foo>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:42:24
|
LL | want::<Foo<usize>>(f);
- | ------------------ ^ expected `usize`, found struct `foo`
+ | ------------------ ^ expected `Foo<usize>`, found `Foo<foo>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:43:27
|
LL | want::<Foo<usize, B>>(f);
- | --------------------- ^ expected `usize`, found struct `foo`
+ | --------------------- ^ expected `Foo<usize, B>`, found `Foo<foo>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:44:25
|
LL | want::<Foo<foo, B>>(f);
- | ------------------- ^ expected struct `B`, found struct `A`
+ | ------------------- ^ expected `Foo<foo, B>`, found `Foo<foo>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:45:22
|
LL | want::<Foo<bar>>(f);
- | ---------------- ^ expected struct `bar`, found struct `foo`
+ | ---------------- ^ expected `Foo<bar>`, found `Foo<foo>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:46:25
|
LL | want::<Foo<bar, B>>(f);
- | ------------------- ^ expected struct `bar`, found struct `foo`
+ | ------------------- ^ expected `Foo<bar, B>`, found `Foo<foo>`
| |
| arguments to this function are incorrect
|
LL | want::<&Foo<foo>>(f);
| ----------------- ^
| | |
- | | expected `&Foo<foo>`, found struct `Foo`
+ | | expected `&Foo<foo>`, found `Foo<foo>`
| | help: consider borrowing here: `&f`
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:48:26
|
LL | want::<&Foo<foo, B>>(f);
- | -------------------- ^ expected `&Foo<foo, B>`, found struct `Foo`
+ | -------------------- ^ expected `&Foo<foo, B>`, found `Foo<foo>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:52:19
|
LL | want::<usize>(f);
- | ------------- ^ expected `usize`, found struct `Foo`
+ | ------------- ^ expected `usize`, found `Foo<foo, B>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:53:17
|
LL | want::<foo>(f);
- | ----------- ^ expected struct `foo`, found struct `Foo`
+ | ----------- ^ expected `foo`, found `Foo<foo, B>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:54:17
|
LL | want::<bar>(f);
- | ----------- ^ expected struct `bar`, found struct `Foo`
+ | ----------- ^ expected `bar`, found `Foo<foo, B>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:55:24
|
LL | want::<Foo<usize>>(f);
- | ------------------ ^ expected `usize`, found struct `foo`
+ | ------------------ ^ expected `Foo<usize>`, found `Foo<foo, B>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:56:27
|
LL | want::<Foo<usize, B>>(f);
- | --------------------- ^ expected `usize`, found struct `foo`
+ | --------------------- ^ expected `Foo<usize, B>`, found `Foo<foo, B>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:57:22
|
LL | want::<Foo<foo>>(f);
- | ---------------- ^ expected struct `A`, found struct `B`
+ | ---------------- ^ expected `Foo<foo>`, found `Foo<foo, B>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:58:22
|
LL | want::<Foo<bar>>(f);
- | ---------------- ^ expected struct `bar`, found struct `foo`
+ | ---------------- ^ expected `Foo<bar>`, found `Foo<foo, B>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:59:25
|
LL | want::<Foo<bar, B>>(f);
- | ------------------- ^ expected struct `bar`, found struct `foo`
+ | ------------------- ^ expected `Foo<bar, B>`, found `Foo<foo, B>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:60:23
|
LL | want::<&Foo<foo>>(f);
- | ----------------- ^ expected `&Foo<foo>`, found struct `Foo`
+ | ----------------- ^ expected `&Foo<foo>`, found `Foo<foo, B>`
| |
| arguments to this function are incorrect
|
LL | want::<&Foo<foo, B>>(f);
| -------------------- ^
| | |
- | | expected `&Foo<foo, B>`, found struct `Foo`
+ | | expected `&Foo<foo, B>`, found `Foo<foo, B>`
| | help: consider borrowing here: `&f`
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:65:19
|
LL | want::<usize>(f);
- | ------------- ^ expected `usize`, found struct `Foo`
+ | ------------- ^ expected `usize`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:66:17
|
LL | want::<foo>(f);
- | ----------- ^ expected struct `foo`, found struct `Foo`
+ | ----------- ^ expected `foo`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:67:17
|
LL | want::<bar>(f);
- | ----------- ^ expected struct `bar`, found struct `Foo`
+ | ----------- ^ expected `bar`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:68:24
|
LL | want::<Foo<usize>>(f);
- | ------------------ ^ expected `usize`, found struct `foo`
+ | ------------------ ^ expected `Foo<usize>`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:69:27
|
LL | want::<Foo<usize, B>>(f);
- | --------------------- ^ expected `usize`, found struct `foo`
+ | --------------------- ^ expected `Foo<usize, B>`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:70:22
|
LL | want::<Foo<foo>>(f);
- | ---------------- ^ expected struct `A`, found struct `B`
+ | ---------------- ^ expected `Foo<foo>`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:71:25
|
LL | want::<Foo<foo, B>>(f);
- | ------------------- ^ expected struct `B`, found struct `A`
+ | ------------------- ^ expected `Foo<foo, B>`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:72:22
|
LL | want::<Foo<bar>>(f);
- | ---------------- ^ expected struct `bar`, found struct `foo`
+ | ---------------- ^ expected `Foo<bar>`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:73:25
|
LL | want::<Foo<bar, B>>(f);
- | ------------------- ^ expected struct `bar`, found struct `foo`
+ | ------------------- ^ expected `Foo<bar, B>`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:74:23
|
LL | want::<&Foo<foo>>(f);
- | ----------------- ^ expected `&Foo<foo>`, found struct `Foo`
+ | ----------------- ^ expected `&Foo<foo>`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
--> $DIR/type-mismatch.rs:75:26
|
LL | want::<&Foo<foo, B>>(f);
- | -------------------- ^ expected `&Foo<foo, B>`, found struct `Foo`
+ | -------------------- ^ expected `&Foo<foo, B>`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
LL | let mut y = x.lock().unwrap();
| ----------------- expected due to this value
LL | y = 2;
- | ^ expected struct `MutexGuard`, found integer
+ | ^ expected `MutexGuard<'_, usize>`, found integer
|
= note: expected struct `MutexGuard<'_, usize>`
found type `{integer}`
LL | vector.sort();
| ------ here the type of `vector` is inferred to be `Vec<_>`
LL | result.push(vector);
- | ---- ^^^^^^ expected integer, found struct `Vec`
+ | ---- ^^^^^^ expected integer, found `Vec<_>`
| |
| arguments to this method are incorrect
|
LL | let _tis_an_instants_play: String = "'Tis a fond Ambush—";
| ------ ^^^^^^^^^^^^^^^^^^^^^- help: try using a conversion method: `.to_string()`
| | |
- | | expected struct `String`, found `&str`
+ | | expected `String`, found `&str`
| expected due to this
error[E0308]: mismatched types
LL | let _just_to_make_bliss: PathBuf = Path::new("/ern/her/own/surprise");
| ------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try using a conversion method: `.to_path_buf()`
| | |
- | | expected struct `PathBuf`, found `&Path`
+ | | expected `PathBuf`, found `&Path`
| expected due to this
error[E0308]: mismatched types
LL | let _but_should_the_play: String = 2; // Perhaps surprisingly, we suggest .to_string() here
| ------ ^- help: try using a conversion method: `.to_string()`
| | |
- | | expected struct `String`, found integer
+ | | expected `String`, found integer
| expected due to this
error[E0308]: mismatched types
--> $DIR/conversion-methods.rs:12:47
|
LL | let _prove_piercing_earnest: Vec<usize> = &[1, 2, 3];
- | ---------- ^^^^^^^^^^ expected struct `Vec`, found `&[{integer}; 3]`
+ | ---------- ^^^^^^^^^^ expected `Vec<usize>`, found `&[{integer}; 3]`
| |
| expected due to this
|
LL | fn d(x: std::sync::Mutex<&i32>) -> i32 {
| --- expected `i32` because of return type
LL | x.lock().unwrap()
- | ^^^^^^^^^^^^^^^^^ expected `i32`, found struct `MutexGuard`
+ | ^^^^^^^^^^^^^^^^^ expected `i32`, found `MutexGuard<'_, &i32>`
|
= note: expected type `i32`
found struct `MutexGuard<'_, &i32>`
nc.clone()
//~^ ERROR mismatched type
//~| NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
- //~| NOTE expected struct `NotClone`, found `&NotClone`
+ //~| NOTE expected `NotClone`, found `&NotClone`
}
| -------- expected `NotClone` because of return type
LL |
LL | nc.clone()
- | ^^^^^^^^^^ expected struct `NotClone`, found `&NotClone`
+ | ^^^^^^^^^^ expected `NotClone`, found `&NotClone`
|
note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
--> $DIR/explain_clone_autoref.rs:9:5
--> $DIR/issue-100246.rs:28:24
|
LL | let other: Other = downcast()?;
- | ^^^^^^^^^^^ expected struct `Other`, found reference
+ | ^^^^^^^^^^^ expected `Other`, found `&_`
|
= note: `?` operator cannot convert from `&_` to `Other`
= note: expected struct `Other`
| - this type parameter - expected `I` because of return type
...
LL | self.iter()
- | ^^^^^^^^^^^ expected type parameter `I`, found struct `Iter`
+ | ^^^^^^^^^^^ expected type parameter `I`, found `Iter<'_, N>`
|
= note: expected type parameter `I`
found struct `std::slice::Iter<'_, N>`
LL | iterate(graph);
| ------- ^^^^^
| | |
- | | expected reference, found struct `Vec`
+ | | expected `&_`, found `Vec<Stuff>`
| | help: consider borrowing here: `&graph`
| arguments to this function are incorrect
|
--> $DIR/issue-31173.rs:11:10
|
LL | .cloned()
- | ^^^^^^ expected reference, found `u8`
+ | ^^^^^^ expected `&_`, found `u8`
|
= note: expected reference `&_`
found type `u8`
--> $DIR/issue-46112.rs:9:21
|
LL | fn main() { test(Ok(())); }
- | -- ^^ expected enum `Option`, found `()`
+ | -- ^^ expected `Option<()>`, found `()`
| |
| arguments to this enum variant are incorrect
|
--> $DIR/issue-50687-ice-on-borrow.rs:40:17
|
LL | let _: () = Borrow::borrow(&owned);
- | -- ^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found reference
+ | -- ^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `&_`
| |
| expected due to this
|
LL | fn ice(x: Box<dyn Iterator<Item=()>>) {
| - help: try adding a return type: `-> (dyn Iterator<Item = ()> + 'static)`
LL | *x
- | ^^ expected `()`, found trait object `dyn Iterator`
+ | ^^ expected `()`, found `dyn Iterator`
|
= note: expected unit type `()`
found trait object `(dyn Iterator<Item = ()> + 'static)`
--> $DIR/issue-67971.rs:3:24
|
LL | fn foo(ctx: &mut S) -> String {
- | --- ^^^^^^ expected struct `String`, found `()`
+ | --- ^^^^^^ expected `String`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
| ---- expected `&u32` because of return type
...
LL | return "test";
- | ^^^^^^ expected `u32`, found `str`
+ | ^^^^^^ expected `&u32`, found `&str`
|
= note: expected reference `&u32`
found reference `&'static str`
--> $DIR/issue-84768.rs:7:42
|
LL | <F as FnOnce(&mut u8)>::call_once(f, 1)
- | --------------------------------- ^ expected tuple, found integer
+ | --------------------------------- ^ expected `(&mut u8,)`, found integer
| |
| arguments to this function are incorrect
|
--- /dev/null
+// run-rustfix
+
+fn take_str_maybe(_: Option<&str>) { }
+fn main() {
+ let string = String::from("Hello, world");
+
+ let option: Option<String> = Some(string.clone());
+ take_str_maybe(option.as_deref());
+ //~^ ERROR: mismatched types [E0308]
+
+ let option_ref = Some(&string);
+ take_str_maybe(option_ref.map(|x| x.as_str()));
+ //~^ ERROR: mismatched types [E0308]
+
+ let option_ref_ref = option_ref.as_ref();
+ take_str_maybe(option_ref_ref.map(|x| x.as_str()));
+ //~^ ERROR: mismatched types [E0308]
+}
-fn take_str_maybe(x: Option<&str>) -> Option<&str> { None }
+// run-rustfix
+fn take_str_maybe(_: Option<&str>) { }
fn main() {
let string = String::from("Hello, world");
- let option = Some(&string);
+
+ let option: Option<String> = Some(string.clone());
take_str_maybe(option);
//~^ ERROR: mismatched types [E0308]
+
+ let option_ref = Some(&string);
+ take_str_maybe(option_ref);
+ //~^ ERROR: mismatched types [E0308]
+
+ let option_ref_ref = option_ref.as_ref();
+ take_str_maybe(option_ref_ref);
+ //~^ ERROR: mismatched types [E0308]
}
error[E0308]: mismatched types
- --> $DIR/issue-89856.rs:6:20
+ --> $DIR/issue-89856.rs:8:20
|
LL | take_str_maybe(option);
- | -------------- ^^^^^^ expected `str`, found struct `String`
+ | -------------- ^^^^^^ expected `Option<&str>`, found `Option<String>`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected enum `Option<&str>`
+ found enum `Option<String>`
+note: function defined here
+ --> $DIR/issue-89856.rs:3:4
+ |
+LL | fn take_str_maybe(_: Option<&str>) { }
+ | ^^^^^^^^^^^^^^ ---------------
+help: try converting the passed type into a `&str`
+ |
+LL | take_str_maybe(option.as_deref());
+ | +++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/issue-89856.rs:12:20
+ |
+LL | take_str_maybe(option_ref);
+ | -------------- ^^^^^^^^^^ expected `Option<&str>`, found `Option<&String>`
| |
| arguments to this function are incorrect
|
= note: expected enum `Option<&str>`
found enum `Option<&String>`
note: function defined here
- --> $DIR/issue-89856.rs:1:4
+ --> $DIR/issue-89856.rs:3:4
+ |
+LL | fn take_str_maybe(_: Option<&str>) { }
+ | ^^^^^^^^^^^^^^ ---------------
+help: try converting the passed type into a `&str`
+ |
+LL | take_str_maybe(option_ref.map(|x| x.as_str()));
+ | ++++++++++++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/issue-89856.rs:16:20
+ |
+LL | take_str_maybe(option_ref_ref);
+ | -------------- ^^^^^^^^^^^^^^ expected `Option<&str>`, found `Option<&&String>`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected enum `Option<&str>`
+ found enum `Option<&&String>`
+note: function defined here
+ --> $DIR/issue-89856.rs:3:4
|
-LL | fn take_str_maybe(x: Option<&str>) -> Option<&str> { None }
+LL | fn take_str_maybe(_: Option<&str>) { }
| ^^^^^^^^^^^^^^ ---------------
help: try converting the passed type into a `&str`
|
-LL | take_str_maybe(option.map(|x| &**x));
- | ++++++++++++++
+LL | take_str_maybe(option_ref_ref.map(|x| x.as_str()));
+ | ++++++++++++++++++++
-error: aborting due to previous error
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// edition:2018
+
+async fn hello() { //~ HELP try adding a return type
+ 0
+ //~^ ERROR [E0308]
+}
+
+async fn world() -> () {
+ 0
+ //~^ ERROR [E0308]
+}
+
+async fn suggest_await_in_async_fn_return() {
+ hello()
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider `await`ing on the `Future`
+ //~| HELP consider using a semicolon here
+ //~| SUGGESTION .await
+}
+
+fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/issue-90027-async-fn-return-suggestion.rs:4:5
+ |
+LL | async fn hello() {
+ | - help: try adding a return type: `-> i32`
+LL | 0
+ | ^ expected `()`, found integer
+
+error[E0308]: mismatched types
+ --> $DIR/issue-90027-async-fn-return-suggestion.rs:9:5
+ |
+LL | async fn world() -> () {
+ | -- expected `()` because of return type
+LL | 0
+ | ^ expected `()`, found integer
+
+error[E0308]: mismatched types
+ --> $DIR/issue-90027-async-fn-return-suggestion.rs:14:5
+ |
+LL | hello()
+ | ^^^^^^^ expected `()`, found opaque type
+ |
+ = note: expected unit type `()`
+ found opaque type `impl Future<Output = ()>`
+help: consider `await`ing on the `Future`
+ |
+LL | hello().await
+ | ++++++
+help: consider using a semicolon here
+ |
+LL | hello();
+ | +
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--> $DIR/issue-91450-inner-ty-error.rs:4:13
|
LL | fn foo() -> Option<_> {}
- | --- ^^^^^^^^^ expected enum `Option`, found `()`
+ | --- ^^^^^^^^^ expected `Option<_>`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
|
LL | / Ok {
LL | | d..||_=m
LL | | }
- | |_____^ expected `()`, found enum `Result`
+ | |_____^ expected `()`, found `Result<_, _>`
|
= note: expected unit type `()`
found enum `Result<_, _>`
--> $DIR/issue-96530.rs:9:11
|
LL | ..man.clone()
- | ^^^^^^^^^^^ expected struct `Person`, found `&Person`
+ | ^^^^^^^^^^^ expected `Person`, found `&Person`
error: aborting due to previous error
fn foo() { //~ HELP a return type might be missing here
vec!['a'].iter().map(|c| c)
//~^ ERROR mismatched types [E0308]
- //~| NOTE expected `()`, found struct `Map`
+ //~| NOTE expected `()`, found `Map<Iter<'_, char>, ...>`
//~| NOTE expected unit type `()`
//~| HELP consider using a semicolon here
}
--> $DIR/return_type_containing_closure.rs:3:5
|
LL | vec!['a'].iter().map(|c| c)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Map`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Map<Iter<'_, char>, ...>`
|
= note: expected unit type `()`
found struct `Map<std::slice::Iter<'_, char>, [closure@$DIR/return_type_containing_closure.rs:3:26: 3:29]>`
//~^ ERROR mismatched types
//~| expected struct `Foo<_>`
//~| found struct `Bar<usize>`
- //~| expected struct `Foo`, found struct `Bar`
+ //~| expected `Foo<_>`, found `Bar<usize>`
let y: Foo<usize> = x;
}
//~^ ERROR mismatched types
//~| expected struct `Foo<_>`
//~| found struct `Bar<usize>`
- //~| expected struct `Foo`, found struct `Bar`
+ //~| expected `Foo<_>`, found `Bar<usize>`
}
--> $DIR/typeck_type_placeholder_mismatch.rs:13:21
|
LL | let x: Foo<_> = Bar::<usize>(PhantomData);
- | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found struct `Bar`
+ | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo<_>`, found `Bar<usize>`
| |
| expected due to this
|
--> $DIR/typeck_type_placeholder_mismatch.rs:22:21
|
LL | let x: Foo<_> = Bar::<usize>(PhantomData);
- | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found struct `Bar`
+ | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo<_>`, found `Bar<usize>`
| |
| expected due to this
|
-error[E0599]: no method named `call` found for closure `[closure@unboxed-closures-static-call-wrong-trait.rs:6:26]` in the current scope
+error[E0599]: no method named `call` found for closure `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:29]` in the current scope
--> $DIR/unboxed-closures-static-call-wrong-trait.rs:7:10
|
LL | mut_.call((0, ));
--- /dev/null
+// compile-flags: --crate-type=lib
+// check-pass
+
+// Make sure we don't pass inference variables to uninhabitedness checks in borrowck
+
+struct Command<'s> {
+ session: &'s (),
+ imp: std::convert::Infallible,
+}
+
+fn command(_: &()) -> Command<'_> {
+ unreachable!()
+}
+
+fn with_session<'s>(a: &std::process::Command, b: &'s ()) -> Command<'s> {
+ a.get_program();
+ command(b)
+}
LL | let x: &[u8] = vec!(1, 2, 3)[..];
| ----- ^^^^^^^^^^^^^^^^^
| | |
- | | expected `&[u8]`, found slice `[{integer}]`
+ | | expected `&[u8]`, found `[{integer}]`
| | help: consider borrowing here: `&vec!(1, 2, 3)[..]`
| expected due to this
--> $DIR/suggest-borrow.rs:4:19
|
LL | let x: [u8] = &vec!(1, 2, 3)[..];
- | ---- ^^^^^^^^^^^^^^^^^^ expected slice `[u8]`, found `&[{integer}]`
+ | ---- ^^^^^^^^^^^^^^^^^^ expected `[u8]`, found `&[{integer}]`
| |
| expected due to this
|
| | expected because of this
LL | | } else {
LL | | Box::new(move || println!("{}", b))
- | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found struct `Box`
+ | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found `Box<[closure@box-instead-of-dyn-fn.rs:10:18]>`
LL | |
LL | | }
| |_____- `if` and `else` have incompatible types
--> $DIR/param-mentioned-by-different-field.rs:8:25
|
LL | let y: &Foo<[u8]> = &x;
- | ---------- ^^ expected slice `[u8]`, found array `[u8; 1]`
+ | ---------- ^^ expected `&Foo<[u8]>`, found `&Foo<[u8; 1]>`
| |
| expected due to this
|
LL | | Some(()) => &S,
| | -- this is found to be of type `&S`
LL | | None => &R,
- | | ^^ expected struct `S`, found struct `R`
+ | | ^^ expected `&S`, found `&R`
LL | | }
| |_____- `match` arms have incompatible types
|
--- /dev/null
+// check-fail
+
+#![feature(auto_traits)]
+#![deny(where_clauses_object_safety)]
+
+auto trait AutoTrait {}
+
+trait Trait {
+ fn static_lifetime_bound(&self) where Self: 'static {}
+
+ fn arg_lifetime_bound<'a>(&self, _arg: &'a ()) where Self: 'a {}
+
+ fn autotrait_bound(&self) where Self: AutoTrait {}
+}
+
+impl Trait for () {}
+
+fn main() {
+ let trait_object = &() as &dyn Trait;
+ trait_object.static_lifetime_bound();
+ trait_object.arg_lifetime_bound(&());
+ trait_object.autotrait_bound(); //~ ERROR: the trait bound `dyn Trait: AutoTrait` is not satisfied
+}
--- /dev/null
+error[E0277]: the trait bound `dyn Trait: AutoTrait` is not satisfied
+ --> $DIR/self-in-where-clause-allowed.rs:22:18
+ |
+LL | trait_object.autotrait_bound();
+ | ^^^^^^^^^^^^^^^ the trait `AutoTrait` is not implemented for `dyn Trait`
+ |
+note: required by a bound in `Trait::autotrait_bound`
+ --> $DIR/self-in-where-clause-allowed.rs:13:43
+ |
+LL | fn autotrait_bound(&self) where Self: AutoTrait {}
+ | ^^^^^^^^^ required by this bound in `Trait::autotrait_bound`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
LL | fn mul(self, s: f64) -> Vec2 {
| ^^^
| |
- | expected struct `Vec2`, found `f64`
+ | expected `Vec2`, found `f64`
| help: change the parameter type to match the trait: `Vec2`
|
= note: expected signature `fn(Vec2, Vec2) -> f64`
--> $DIR/wrong-mul-method-signature.rs:63:45
|
LL | let x: Vec2 = Vec2 { x: 1.0, y: 2.0 } * 2.0; // trait had reversed order
- | ----------------------- ^^^ expected struct `Vec2`, found floating-point number
+ | ----------------------- ^^^ expected `Vec2`, found floating-point number
| |
| expected because this is `Vec2`
--> $DIR/wrong-mul-method-signature.rs:63:19
|
LL | let x: Vec2 = Vec2 { x: 1.0, y: 2.0 } * 2.0; // trait had reversed order
- | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Vec2`, found `f64`
+ | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Vec2`, found `f64`
| |
| expected due to this
[autolabel."WG-trait-system-refactor"]
trigger_files = [
- "compiler/rustc_trait_selection/src/solve"
+ "compiler/rustc_trait_selection/src/solve",
+ "compiler/rustc_middle/src/traits/solve.rs"
]
[notify-zulip."I-prioritize"]
[mentions."compiler/rustc_error_messages"]
message = "`rustc_error_messages` was changed"
-cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"]
+cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@TaKO8Ki"]
[mentions."compiler/rustc_errors/src/translation.rs"]
message = "`rustc_errors::translation` was changed"
-cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"]
+cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@TaKO8Ki"]
[mentions."compiler/rustc_macros/src/diagnostics"]
message = "`rustc_macros::diagnostics` was changed"
-cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"]
+cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@TaKO8Ki"]
[mentions."compiler/rustc_target/src/spec"]
message = """
[mentions."src/doc/style-guide"]
cc = ["@rust-lang/style"]
+[mentions."Cargo.lock"]
+message = """
+These commits modify the `Cargo.lock` file. Random changes to `Cargo.lock` can be introduced when switching branches and rebasing PRs.
+This was probably unintentional and should be reverted before this PR is merged.
+
+If this was intentional then you can ignore this comment.
+"""
+
[assign]
warn_non_default_branch = true
contributing_url = "https://rustc-dev-guide.rust-lang.org/contributing.html"
[assign.adhoc_groups]
compiler-team = [
"@cjgillot",
- "@estebank",
"@petrochenkov",
"@davidtwco",
"@oli-obk",
diagnostics = [
"@compiler-errors",
"@davidtwco",
- "@estebank",
"@oli-obk",
"@TaKO8Ki",
]
parser = [
"@davidtwco",
- "@estebank",
"@nnethercote",
"@petrochenkov",
]
pass
rust_dir = os.path.dirname(os.path.abspath(__file__))
-sys.path.append(os.path.join(rust_dir, "src", "bootstrap"))
+# For the import below, have Python search in src/bootstrap first.
+sys.path.insert(0, os.path.join(rust_dir, "src", "bootstrap"))
import bootstrap
bootstrap.main()