+Version 1.57.0 (2021-12-02)
+==========================
+
+Language
+--------
+
+- [Macro attributes may follow `#[derive]` and will see the original (pre-`cfg`) input.][87220]
+- [Accept curly-brace macros in expressions, like `m!{ .. }.method()` and `m!{ .. }?`.][88690]
+- [Allow panicking in constant evaluation.][89508]
+
+Compiler
+--------
+
+- [Create more accurate debuginfo for vtables.][89597]
+- [Add `armv6k-nintendo-3ds` at Tier 3\*.][88529]
+- [Add `armv7-unknown-linux-uclibceabihf` at Tier 3\*.][88952]
+- [Add `m68k-unknown-linux-gnu` at Tier 3\*.][88321]
+- [Add SOLID targets at Tier 3\*:][86191] `aarch64-kmc-solid_asp3`, `armv7a-kmc-solid_asp3-eabi`, `armv7a-kmc-solid_asp3-eabihf`
+
+\* Refer to Rust's [platform support page][platform-support-doc] for more
+ information on Rust's tiered platform support.
+
+Libraries
+---------
+
+- [Avoid allocations and copying in `Vec::leak`][89337]
+- [Add `#[repr(i8)]` to `Ordering`][89507]
+- [Optimize `File::read_to_end` and `read_to_string`][89582]
+- [Update to Unicode 14.0][89614]
+- [Many more functions are marked `#[must_use]`][89692], producing a warning
+ when ignoring their return value. This helps catch mistakes such as expecting
+ a function to mutate a value in place rather than return a new value.
+
+Stabilised APIs
+---------------
+
+- [`[T; N]::as_mut_slice`][`array::as_mut_slice`]
+- [`[T; N]::as_slice`][`array::as_slice`]
+- [`collections::TryReserveError`]
+- [`HashMap::try_reserve`]
+- [`HashSet::try_reserve`]
+- [`String::try_reserve`]
+- [`String::try_reserve_exact`]
+- [`Vec::try_reserve`]
+- [`Vec::try_reserve_exact`]
+- [`VecDeque::try_reserve`]
+- [`VecDeque::try_reserve_exact`]
+- [`Iterator::map_while`]
+- [`iter::MapWhile`]
+- [`proc_macro::is_available`]
+- [`Command::get_program`]
+- [`Command::get_args`]
+- [`Command::get_envs`]
+- [`Command::get_current_dir`]
+- [`CommandArgs`]
+- [`CommandEnvs`]
+
+These APIs are now usable in const contexts:
+
+- [`hint::unreachable_unchecked`]
+
+Cargo
+-----
+
+- [Stabilize custom profiles][cargo/9943]
+
+Compatibility notes
+-------------------
+
+Internal changes
+----------------
+These changes provide no direct user facing benefits, but represent significant
+improvements to the internals and overall performance of rustc
+and related tools.
+
+- [Added an experimental backend for codegen with `libgccjit`.][87260]
+
+[86191]: https://github.com/rust-lang/rust/pull/86191/
+[87220]: https://github.com/rust-lang/rust/pull/87220/
+[87260]: https://github.com/rust-lang/rust/pull/87260/
+[88243]: https://github.com/rust-lang/rust/pull/88243/
+[88321]: https://github.com/rust-lang/rust/pull/88321/
+[88529]: https://github.com/rust-lang/rust/pull/88529/
+[88690]: https://github.com/rust-lang/rust/pull/88690/
+[88952]: https://github.com/rust-lang/rust/pull/88952/
+[89337]: https://github.com/rust-lang/rust/pull/89337/
+[89507]: https://github.com/rust-lang/rust/pull/89507/
+[89508]: https://github.com/rust-lang/rust/pull/89508/
+[89582]: https://github.com/rust-lang/rust/pull/89582/
+[89597]: https://github.com/rust-lang/rust/pull/89597/
+[89614]: https://github.com/rust-lang/rust/pull/89614/
+[89692]: https://github.com/rust-lang/rust/issues/89692/
+[cargo/9943]: https://github.com/rust-lang/cargo/pull/9943/
+[`array::as_mut_slice`]: https://doc.rust-lang.org/std/primitive.array.html#method.as_mut_slice
+[`array::as_slice`]: https://doc.rust-lang.org/std/primitive.array.html#method.as_slice
+[`collections::TryReserveError`]: https://doc.rust-lang.org/std/collections/struct.TryReserveError.html
+[`HashMap::try_reserve`]: https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.try_reserve
+[`HashSet::try_reserve`]: https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.try_reserve
+[`String::try_reserve`]: https://doc.rust-lang.org/alloc/string/struct.String.html#method.try_reserve
+[`String::try_reserve_exact`]: https://doc.rust-lang.org/alloc/string/struct.String.html#method.try_reserve_exact
+[`Vec::try_reserve`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.try_reserve
+[`Vec::try_reserve_exact`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.try_reserve_exact
+[`VecDeque::try_reserve`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.try_reserve
+[`VecDeque::try_reserve_exact`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.try_reserve_exact
+[`Iterator::map_while`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map_while
+[`iter::MapWhile`]: https://doc.rust-lang.org/std/iter/struct.MapWhile.html
+[`proc_macro::is_available`]: https://doc.rust-lang.org/proc_macro/fn.is_available.html
+[`Command::get_program`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_program
+[`Command::get_args`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_args
+[`Command::get_envs`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_envs
+[`Command::get_current_dir`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_current_dir
+[`CommandArgs`]: https://doc.rust-lang.org/std/process/struct.CommandArgs.html
+[`CommandEnvs`]: https://doc.rust-lang.org/std/process/struct.CommandEnvs.html
+
Version 1.56.1 (2021-11-01)
===========================
use rustc_index::vec::IndexVec;
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
use rustc_middle::mir::visit::{MutVisitor, TyContext};
-use rustc_middle::mir::{Body, Location, PlaceElem, Promoted};
+use rustc_middle::mir::{Body, Location, Promoted};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
debug!(?ty);
}
- fn process_projection_elem(
- &mut self,
- elem: PlaceElem<'tcx>,
- _: Location,
- ) -> Option<PlaceElem<'tcx>> {
- if let PlaceElem::Field(field, ty) = elem {
- let new_ty = self.renumber_regions(ty);
-
- if new_ty != ty {
- return Some(PlaceElem::Field(field, new_ty));
- }
- }
-
- None
- }
-
#[instrument(skip(self), level = "debug")]
fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) {
*substs = self.renumber_regions(*substs);
debug!("build: input_or_output={:?}", ty);
// We add implied bounds from both the unnormalized and normalized ty
// See issue #87748
- let constraints_implied_1 = self.add_implied_bounds(ty);
let TypeOpOutput { output: norm_ty, constraints: constraints1, .. } = self
.param_env
.and(type_op::normalize::Normalize::new(ty))
// }
// ```
// Both &Self::Bar and &() are WF
- let constraints_implied_2 =
- if ty != norm_ty { self.add_implied_bounds(norm_ty) } else { None };
+ let constraints_implied = self.add_implied_bounds(norm_ty);
normalized_inputs_and_output.push(norm_ty);
- constraints1.into_iter().chain(constraints_implied_1).chain(constraints_implied_2)
+ constraints1.into_iter().chain(constraints_implied)
})
.collect();
/// * Implicit argument resolution: `"{1:.0$} {2:.foo$} {1:.3$} {4:.0$}"`
/// * Name resolution: `"{1:.0$} {2:.5$} {1:.3$} {4:.0$}"`
/// * `count_positions` (in JSON): `{0: 0, 5: 1, 3: 2}`
- /// * `count_args`: `vec![Exact(0), Exact(5), Exact(3)]`
- count_args: Vec<Position>,
+ /// * `count_args`: `vec![0, 5, 3]`
+ count_args: Vec<usize>,
/// Relative slot numbers for count arguments.
count_positions: FxHashMap<usize, usize>,
/// Number of count slots assigned.
if let Entry::Vacant(e) = self.count_positions.entry(arg) {
let i = self.count_positions_count;
e.insert(i);
- self.count_args.push(Exact(arg));
+ self.count_args.push(arg);
self.count_positions_count += 1;
}
}
for arg_ty in self.arg_unique_types[i].iter() {
args.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, i));
}
- heads.push(self.ecx.expr_addr_of(e.span, e));
+ // use the arg span for `&arg` so that borrowck errors
+ // point to the specific expression passed to the macro
+ // (the span is otherwise unavailable in MIR)
+ heads.push(self.ecx.expr_addr_of(e.span.with_ctxt(self.macsp.ctxt()), e));
}
- for pos in self.count_args {
- let index = match pos {
- Exact(i) => i,
- _ => panic!("should never happen"),
- };
+ for index in self.count_args {
let span = spans_pos[index];
args.push(Context::format_arg(self.ecx, self.macsp, span, &Count, index));
}
pub struct DiagnosticHandlers<'a> {
data: *mut (&'a CodegenContext<LlvmCodegenBackend>, &'a Handler),
llcx: &'a llvm::Context,
+ old_handler: Option<&'a llvm::DiagnosticHandler>,
}
impl<'a> DiagnosticHandlers<'a> {
handler: &'a Handler,
llcx: &'a llvm::Context,
) -> Self {
+ let remark_passes_all: bool;
+ let remark_passes: Vec<CString>;
+ match &cgcx.remark {
+ Passes::All => {
+ remark_passes_all = true;
+ remark_passes = Vec::new();
+ }
+ Passes::Some(passes) => {
+ remark_passes_all = false;
+ remark_passes =
+ passes.iter().map(|name| CString::new(name.as_str()).unwrap()).collect();
+ }
+ };
+ let remark_passes: Vec<*const c_char> =
+ remark_passes.iter().map(|name: &CString| name.as_ptr()).collect();
let data = Box::into_raw(Box::new((cgcx, handler)));
unsafe {
+ let old_handler = llvm::LLVMRustContextGetDiagnosticHandler(llcx);
+ llvm::LLVMRustContextConfigureDiagnosticHandler(
+ llcx,
+ diagnostic_handler,
+ data.cast(),
+ remark_passes_all,
+ remark_passes.as_ptr(),
+ remark_passes.len(),
+ );
llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, data.cast());
- llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, data.cast());
+ DiagnosticHandlers { data, llcx, old_handler }
}
- DiagnosticHandlers { data, llcx }
}
}
use std::ptr::null_mut;
unsafe {
llvm::LLVMRustSetInlineAsmDiagnosticHandler(self.llcx, inline_asm_handler, null_mut());
- llvm::LLVMContextSetDiagnosticHandler(self.llcx, diagnostic_handler, null_mut());
+ llvm::LLVMRustContextSetDiagnosticHandler(self.llcx, self.old_handler);
drop(Box::from_raw(self.data));
}
}
if enabled {
diag_handler.note_without_error(&format!(
- "optimization {} for {} at {}:{}:{}: {}",
- opt.kind.describe(),
- opt.pass_name,
- opt.filename,
- opt.line,
- opt.column,
- opt.message
+ "{}:{}:{}: {}: {}",
+ opt.filename, opt.line, opt.column, opt.pass_name, opt.message,
));
}
}
#[repr(C)]
pub struct Linker<'a>(InvariantOpaque<'a>);
-pub type DiagnosticHandler = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void);
-pub type InlineAsmDiagHandler = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint);
+extern "C" {
+ pub type DiagnosticHandler;
+}
+
+pub type DiagnosticHandlerTy = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void);
+pub type InlineAsmDiagHandlerTy = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint);
pub mod coverageinfo {
use super::coverage_map;
#[allow(improper_ctypes)]
pub fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString);
- pub fn LLVMContextSetDiagnosticHandler(
- C: &Context,
- Handler: DiagnosticHandler,
- DiagnosticContext: *mut c_void,
- );
-
#[allow(improper_ctypes)]
pub fn LLVMRustUnpackOptimizationDiagnostic(
DI: &'a DiagnosticInfo,
pub fn LLVMRustSetInlineAsmDiagnosticHandler(
C: &Context,
- H: InlineAsmDiagHandler,
+ H: InlineAsmDiagHandlerTy,
CX: *mut c_void,
);
mod_id: *const c_char,
data: &ThinLTOData,
);
+
+ pub fn LLVMRustContextGetDiagnosticHandler(Context: &Context) -> Option<&DiagnosticHandler>;
+ pub fn LLVMRustContextSetDiagnosticHandler(
+ context: &Context,
+ diagnostic_handler: Option<&DiagnosticHandler>,
+ );
+ pub fn LLVMRustContextConfigureDiagnosticHandler(
+ context: &Context,
+ diagnostic_handler_callback: DiagnosticHandlerTy,
+ diagnostic_handler_context: *mut c_void,
+ remark_all_passes: bool,
+ remark_passes: *const *const c_char,
+ remark_passes_len: usize,
+ );
+
}
sym::transmute => {
self.copy_op_transmute(&args[0], dest)?;
}
- sym::assert_inhabited => {
+ sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => {
let ty = instance.substs.type_at(0);
let layout = self.layout_of(ty)?;
+ // For *all* intrinsics we first check `is_uninhabited` to give a more specific
+ // error message.
if layout.abi.is_uninhabited() {
// The run-time intrinsic panics just to get a good backtrace; here we abort
// since there is no problem showing a backtrace even for aborts.
),
)?;
}
+ if intrinsic_name == sym::assert_zero_valid
+ && !layout.might_permit_raw_init(self, /*zero:*/ true)
+ {
+ M::abort(
+ self,
+ format!(
+ "aborted execution: attempted to zero-initialize type `{}`, which is invalid",
+ ty
+ ),
+ )?;
+ }
+ if intrinsic_name == sym::assert_uninit_valid
+ && !layout.might_permit_raw_init(self, /*zero:*/ false)
+ {
+ M::abort(
+ self,
+ format!(
+ "aborted execution: attempted to leave type `{}` uninitialized, which is invalid",
+ ty
+ ),
+ )?;
+ }
}
sym::simd_insert => {
let index = u64::from(self.read_scalar(&args[1])?.to_u32()?);
pub mod check_consts;
pub mod promote_consts;
pub mod validate;
-
-pub use rustc_middle::mir::MirPass;
use std::{cmp, iter, mem};
use crate::transform::check_consts::{qualifs, ConstCx};
-use crate::transform::MirPass;
/// A `MirPass` for promotion.
///
//! Validates the MIR to ensure that invariants are upheld.
-use super::MirPass;
use rustc_index::bit_set::BitSet;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::traversal;
use rustc_middle::mir::visit::{PlaceContext, Visitor};
use rustc_middle::mir::{
- AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceElem,
- PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator,
+ AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPass, MirPhase, Operand,
+ PlaceElem, PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator,
TerminatorKind, START_BLOCK,
};
use rustc_middle::ty::fold::BottomUpFolder;
/// Formats the substitutions of the primary_span
///
- /// The are a lot of conditions to this method, but in short:
+ /// There are a lot of conditions to this method, but in short:
///
/// * If the current `Diagnostic` has only one visible `CodeSuggestion`,
/// we format the `help` suggestion depending on the content of the
let line_offset = buffer.num_lines();
- let left = margin.left(source_string.len()); // Left trim
+ // Left trim
+ let left = margin.left(source_string.len());
+
// Account for unicode characters of width !=0 that were removed.
let left = source_string
.chars()
suggestions.iter().take(MAX_SUGGESTIONS)
{
notice_capitalization |= only_capitalization;
- // Only show underline if the suggestion spans a single line and doesn't cover the
- // entirety of the code output. If you have multiple replacements in the same line
- // of code, show the underline.
- let show_underline = !(parts.len() == 1 && parts[0].snippet.trim() == complete.trim())
- && complete.lines().count() == 1;
let has_deletion = parts.iter().any(|p| p.is_deletion());
let is_multiline = complete.lines().count() > 1;
- let show_diff = has_deletion && !is_multiline;
+ enum DisplaySuggestion {
+ Underline,
+ Diff,
+ None,
+ }
+
+ let show_code_change = if has_deletion && !is_multiline {
+ DisplaySuggestion::Diff
+ } else if (parts.len() != 1 || parts[0].snippet.trim() != complete.trim())
+ && !is_multiline
+ {
+ DisplaySuggestion::Underline
+ } else {
+ DisplaySuggestion::None
+ };
- if show_diff {
+ if let DisplaySuggestion::Diff = show_code_change {
row_num += 1;
}
&self.maybe_anonymized(line_start + line_pos),
Style::LineNumber,
);
- if show_diff {
+ if let DisplaySuggestion::Diff = show_code_change {
// Add the line number for both addition and removal to drive the point home.
//
// N - fn foo<A: T>(bar: A) {
let mut offsets: Vec<(usize, isize)> = Vec::new();
// Only show an underline in the suggestions if the suggestion is not the
// entirety of the code being shown and the displayed code is not multiline.
- if show_underline {
+ if let DisplaySuggestion::Diff | DisplaySuggestion::Underline = show_code_change {
draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
for part in parts {
let span_start_pos = sm.lookup_char_pos(part.span.lo()).col_display;
assert!(underline_start >= 0 && underline_end >= 0);
let padding: usize = max_line_num_len + 3;
for p in underline_start..underline_end {
- if !show_diff {
+ if let DisplaySuggestion::Underline = show_code_change {
// If this is a replacement, underline with `^`, if this is an addition
// underline with `+`.
buffer.putc(
);
}
}
- if show_diff {
+ if let DisplaySuggestion::Diff = show_code_change {
// Colorize removal with red in diff format.
buffer.set_style_range(
row_num - 2,
// if we elided some lines, add an ellipsis
if lines.next().is_some() {
buffer.puts(row_num, max_line_num_len - 1, "...", Style::LineNumber);
- } else if !show_underline {
+ } else if let DisplaySuggestion::None = show_code_change {
draw_col_separator_no_space(&mut buffer, row_num, max_line_num_len + 1);
row_num += 1;
}
('\t', " "), // We do our own tab replacement
('\u{200D}', ""), // Replace ZWJ with nothing for consistent terminal output of grapheme clusters.
('\u{202A}', ""), // The following unicode text flow control characters are inconsistently
- ('\u{202B}', ""), // supported accross CLIs and can cause confusion due to the bytes on disk
+ ('\u{202B}', ""), // supported across CLIs and can cause confusion due to the bytes on disk
('\u{202D}', ""), // not corresponding to the visible source code, so we replace them always.
('\u{202E}', ""),
('\u{2066}', ""),
parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
};
let (in_definition_scope, origin) =
- match tcx.hir().expect_item(opaque_hir_id).kind {
+ match tcx.hir().expect_item(def_id).kind {
// Anonymous `impl Trait`
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
impl_trait_fn: Some(parent),
this_decl_ty,
CItemKind::Declaration,
) {
- let orig_fi = tcx.hir().expect_foreign_item(existing_hid);
+ let orig_fi = tcx.hir().expect_foreign_item(existing_hid.expect_owner());
let orig = Self::name_of_extern_decl(tcx, orig_fi);
// We want to ensure that we use spans for both decls that include where the
#include "LLVMWrapper.h"
#include "llvm/IR/DebugInfoMetadata.h"
+#include "llvm/IR/DiagnosticHandler.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/GlobalVariable.h"
case DK_SampleProfile:
return LLVMRustDiagnosticKind::SampleProfile;
case DK_OptimizationRemark:
+ case DK_MachineOptimizationRemark:
return LLVMRustDiagnosticKind::OptimizationRemark;
case DK_OptimizationRemarkMissed:
+ case DK_MachineOptimizationRemarkMissed:
return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
case DK_OptimizationRemarkAnalysis:
+ case DK_MachineOptimizationRemarkAnalysis:
return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
case DK_OptimizationRemarkAnalysisFPCommute:
return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
return LLVMRustResult::Success;
}
}
+
+// Transfers ownership of DiagnosticHandler unique_ptr to the caller.
+extern "C" DiagnosticHandler *
+LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) {
+ std::unique_ptr<DiagnosticHandler> DH = unwrap(C)->getDiagnosticHandler();
+ return DH.release();
+}
+
+// Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic
+// handling. Ownership of the handler is moved to the LLVMContext.
+extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C,
+ DiagnosticHandler *DH) {
+ unwrap(C)->setDiagnosticHandler(std::unique_ptr<DiagnosticHandler>(DH));
+}
+
+using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
+
+// Configures a diagnostic handler that invokes provided callback when a
+// backend needs to emit a diagnostic.
+//
+// When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
+// the RemarkPasses array specifies individual passes for which remarks will be
+// enabled.
+extern "C" void LLVMRustContextConfigureDiagnosticHandler(
+ LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
+ void *DiagnosticHandlerContext, bool RemarkAllPasses,
+ const char * const * RemarkPasses, size_t RemarkPassesLen) {
+
+ class RustDiagnosticHandler final : public DiagnosticHandler {
+ public:
+ RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
+ void *DiagnosticHandlerContext,
+ bool RemarkAllPasses,
+ std::vector<std::string> RemarkPasses)
+ : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
+ DiagnosticHandlerContext(DiagnosticHandlerContext),
+ RemarkAllPasses(RemarkAllPasses),
+ RemarkPasses(RemarkPasses) {}
+
+ virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
+ if (DiagnosticHandlerCallback) {
+ DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
+ return true;
+ }
+ return false;
+ }
+
+ bool isAnalysisRemarkEnabled(StringRef PassName) const override {
+ return isRemarkEnabled(PassName);
+ }
+
+ bool isMissedOptRemarkEnabled(StringRef PassName) const override {
+ return isRemarkEnabled(PassName);
+ }
+
+ bool isPassedOptRemarkEnabled(StringRef PassName) const override {
+ return isRemarkEnabled(PassName);
+ }
+
+ bool isAnyRemarkEnabled() const override {
+ return RemarkAllPasses || !RemarkPasses.empty();
+ }
+
+ private:
+ bool isRemarkEnabled(StringRef PassName) const {
+ if (RemarkAllPasses)
+ return true;
+
+ for (auto &Pass : RemarkPasses)
+ if (Pass == PassName)
+ return true;
+
+ return false;
+ }
+
+ LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr;
+ void *DiagnosticHandlerContext = nullptr;
+
+ bool RemarkAllPasses = false;
+ std::vector<std::string> RemarkPasses;
+ };
+
+ std::vector<std::string> Passes;
+ for (size_t I = 0; I != RemarkPassesLen; ++I)
+ Passes.push_back(RemarkPasses[I]);
+
+ unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
+ DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));
+}
debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id);
let tcx = self.tcx;
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
- let ast_item = tcx.hir().expect_trait_item(hir_id);
+ let ast_item = tcx.hir().expect_trait_item(def_id.expect_local());
let trait_item = tcx.associated_item(def_id);
let container = match trait_item.defaultness {
debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id);
let tcx = self.tcx;
- let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
- let ast_item = self.tcx.hir().expect_impl_item(hir_id);
+ let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local());
let impl_item = self.tcx.associated_item(def_id);
let container = match impl_item.defaultness {
fn encode_lib_features(&mut self) -> Lazy<[(Symbol, Option<Symbol>)]> {
empty_proc_macro!(self);
let tcx = self.tcx;
- let lib_features = tcx.lib_features();
+ let lib_features = tcx.lib_features(());
self.lazy(lib_features.to_vec())
}
bug!("expected foreign mod or inlined parent, found {}", self.node_to_string(parent))
}
- pub fn expect_item(&self, id: HirId) -> &'hir Item<'hir> {
- match self.tcx.hir_owner(id.expect_owner()) {
+ pub fn expect_item(&self, id: LocalDefId) -> &'hir Item<'hir> {
+ match self.tcx.hir_owner(id) {
Some(Owner { node: OwnerNode::Item(item), .. }) => item,
- _ => bug!("expected item, found {}", self.node_to_string(id)),
+ _ => bug!("expected item, found {}", self.node_to_string(HirId::make_owner(id))),
}
}
- pub fn expect_impl_item(&self, id: HirId) -> &'hir ImplItem<'hir> {
- match self.tcx.hir_owner(id.expect_owner()) {
+ pub fn expect_impl_item(&self, id: LocalDefId) -> &'hir ImplItem<'hir> {
+ match self.tcx.hir_owner(id) {
Some(Owner { node: OwnerNode::ImplItem(item), .. }) => item,
- _ => bug!("expected impl item, found {}", self.node_to_string(id)),
+ _ => bug!("expected impl item, found {}", self.node_to_string(HirId::make_owner(id))),
}
}
- pub fn expect_trait_item(&self, id: HirId) -> &'hir TraitItem<'hir> {
- match self.tcx.hir_owner(id.expect_owner()) {
+ pub fn expect_trait_item(&self, id: LocalDefId) -> &'hir TraitItem<'hir> {
+ match self.tcx.hir_owner(id) {
Some(Owner { node: OwnerNode::TraitItem(item), .. }) => item,
- _ => bug!("expected trait item, found {}", self.node_to_string(id)),
+ _ => bug!("expected trait item, found {}", self.node_to_string(HirId::make_owner(id))),
}
}
}
}
- pub fn expect_foreign_item(&self, id: HirId) -> &'hir ForeignItem<'hir> {
- match self.tcx.hir_owner(id.expect_owner()) {
+ pub fn expect_foreign_item(&self, id: LocalDefId) -> &'hir ForeignItem<'hir> {
+ match self.tcx.hir_owner(id) {
Some(Owner { node: OwnerNode::ForeignItem(item), .. }) => item,
- _ => bug!("expected foreign item, found {}", self.node_to_string(id)),
+ _ => {
+ bug!("expected foreign item, found {}", self.node_to_string(HirId::make_owner(id)))
+ }
}
}
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html
use crate::ty::TyCtxt;
-use rustc_hir as hir;
-use rustc_hir::Node;
-use rustc_query_system::ich::{NodeIdHashingMode, StableHashingContext};
-
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir as hir;
+use rustc_hir::Node;
use rustc_macros::HashStable;
+use rustc_query_system::ich::{NodeIdHashingMode, StableHashingContext};
use rustc_span::{Span, DUMMY_SP};
use std::fmt;
/// If not empty, this body is the root of this region hierarchy.
pub root_body: Option<hir::HirId>,
- /// The parent of the root body owner, if the latter is an
- /// an associated const or method, as impls/traits can also
- /// have lifetime parameters free in this body.
- pub root_parent: Option<hir::HirId>,
-
/// Maps from a scope ID to the enclosing scope id;
/// this is usually corresponding to the lexical nesting, though
/// in the case of closures the parent scope is the innermost
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
let ScopeTree {
root_body,
- root_parent,
ref body_expr_count,
ref parent_map,
ref var_map,
} = *self;
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
- root_body.hash_stable(hcx, hasher);
- root_parent.hash_stable(hcx, hasher);
+ root_body.hash_stable(hcx, hasher)
});
body_expr_count.hash_stable(hcx, hasher);
if new_local == local { None } else { Some(PlaceElem::Index(new_local)) }
}
+ PlaceElem::Field(field, ty) => {
+ let mut new_ty = ty;
+ self.visit_ty(&mut new_ty, TyContext::Location(location));
+ if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None }
+ }
PlaceElem::Deref
- | PlaceElem::Field(..)
| PlaceElem::ConstantIndex { .. }
| PlaceElem::Subslice { .. }
| PlaceElem::Downcast(..) => None,
desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id.to_def_id()) }
}
- query get_lib_features(_: ()) -> LibFeatures {
+ query lib_features(_: ()) -> LibFeatures {
storage(ArenaCacheSelector<'tcx>)
- eval_always
desc { "calculating the lib features map" }
}
query defined_lib_features(_: CrateNum)
use crate::hir::place::Place as HirPlace;
use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource};
-use crate::middle;
use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath, ObjectLifetimeDefault};
use crate::middle::stability;
use crate::mir::interpret::{self, Allocation, ConstValue, Scalar};
self.sess.consider_optimizing(&cname, msg)
}
- pub fn lib_features(self) -> &'tcx middle::lib_features::LibFeatures {
- self.get_lib_features(())
- }
-
/// Obtain all lang items of this crate and all dependencies (recursively)
pub fn lang_items(self) -> &'tcx rustc_hir::lang_items::LanguageItems {
self.get_lang_items(())
if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() {
let opaque_local_def_id = def_id.as_local();
let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id {
- let hir = self.hir();
- let opaque_hir_id = hir.local_def_id_to_hir_id(opaque_local_def_id);
- match &hir.expect_item(opaque_hir_id).kind {
+ match &self.hir().expect_item(opaque_local_def_id).kind {
hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty,
_ => bug!("The HirId comes from a `ty::Opaque`"),
}
}
}
- fn process_projection_elem(
- &mut self,
- elem: PlaceElem<'tcx>,
- _: Location,
- ) -> Option<PlaceElem<'tcx>> {
- match elem {
- PlaceElem::Index(local) => {
- if let Some(replacement) = self.replacements.for_src(local) {
- bug!(
- "cannot replace {:?} with {:?} in index projection {:?}",
- local,
- replacement,
- elem,
- );
- } else {
- None
- }
- }
- _ => None,
- }
- }
-
fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
if let Some(replacement) = self.replacements.for_src(place.local) {
// Rebase `place`s projections onto `replacement`'s.
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_index::vec::IndexVec;
use rustc_middle::mir::visit::Visitor as _;
-use rustc_middle::mir::{dump_mir, traversal, Body, ConstQualifs, MirPhase, Promoted};
+use rustc_middle::mir::{dump_mir, traversal, Body, ConstQualifs, MirPass, MirPhase, Promoted};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
use rustc_span::{Span, Symbol};
use rustc_const_eval::transform::check_consts;
use rustc_const_eval::transform::promote_consts;
use rustc_const_eval::transform::validate;
-pub use rustc_const_eval::transform::MirPass;
use rustc_mir_dataflow::rustc_peek;
pub fn provide(providers: &mut Providers) {
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
*ty = self.tcx.normalize_erasing_regions(self.param_env, ty);
}
-
- #[inline]
- fn process_projection_elem(
- &mut self,
- elem: PlaceElem<'tcx>,
- _: Location,
- ) -> Option<PlaceElem<'tcx>> {
- match elem {
- PlaceElem::Field(field, ty) => {
- let new_ty = self.tcx.normalize_erasing_regions(self.param_env, ty);
- if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None }
- }
- // None of those contain a Ty.
- PlaceElem::Index(..)
- | PlaceElem::Deref
- | PlaceElem::ConstantIndex { .. }
- | PlaceElem::Subslice { .. }
- | PlaceElem::Downcast(..) => None,
- }
- }
}
match impl_item.kind {
hir::ImplItemKind::Const(..) => Target::AssocConst,
hir::ImplItemKind::Fn(..) => {
- let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id());
+ let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id()).expect_owner();
let containing_item = tcx.hir().expect_item(parent_hir_id);
let containing_impl_is_for_trait = match &containing_item.kind {
hir::ItemKind::Impl(impl_) => impl_.of_trait.is_some(),
Target::Impl => Some("implementation block"),
Target::ForeignMod => Some("extern block"),
Target::AssocTy => {
- let parent_hir_id = self.tcx.hir().get_parent_item(hir_id);
+ let parent_hir_id = self.tcx.hir().get_parent_item(hir_id).expect_owner();
let containing_item = self.tcx.hir().expect_item(parent_hir_id);
if Target::from_item(containing_item) == Target::Impl {
Some("type alias in implementation block")
}
}
Target::AssocConst => {
- let parent_hir_id = self.tcx.hir().get_parent_item(hir_id);
+ let parent_hir_id = self.tcx.hir().get_parent_item(hir_id).expect_owner();
let containing_item = self.tcx.hir().expect_item(parent_hir_id);
// We can't link to trait impl's consts.
let err = "associated constant in trait implementation block";
}
}
-fn get_lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures {
+fn lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures {
let mut collector = LibFeatureCollector::new(tcx);
tcx.hir().walk_attributes(&mut collector);
collector.lib_features
}
pub fn provide(providers: &mut Providers) {
- providers.get_lib_features = get_lib_features;
+ providers.lib_features = lib_features;
}
// Check the impl. If the generics on the self
// type of the impl require inlining, this method
// does too.
- let impl_hir_id = self.tcx.hir().local_def_id_to_hir_id(impl_did);
- match self.tcx.hir().expect_item(impl_hir_id).kind {
+ match self.tcx.hir().expect_item(impl_did).kind {
hir::ItemKind::Impl { .. } => {
let generics = self.tcx.generics_of(impl_did);
generics.requires_monomorphization(self.tcx)
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc_hir::{Arm, Block, Expr, Local, Node, Pat, PatKind, Stmt};
+use rustc_hir::{Arm, Block, Expr, Local, Pat, PatKind, Stmt};
use rustc_index::vec::Idx;
use rustc_middle::middle::region::*;
use rustc_middle::ty::query::Providers;
let body = tcx.hir().body(body_id);
visitor.scope_tree.root_body = Some(body.value.hir_id);
-
- // If the item is an associated const or a method,
- // record its impl/trait parent, as it can also have
- // lifetime parameters free in this body.
- match tcx.hir().get(id) {
- Node::ImplItem(_) | Node::TraitItem(_) => {
- visitor.scope_tree.root_parent = Some(tcx.hir().get_parent_item(id));
- }
- _ => {}
- }
-
visitor.visit_body(body);
-
visitor.scope_tree
} else {
ScopeTree::default()
// We always collect the lib features declared in the current crate, even if there are
// no unknown features, because the collection also does feature attribute validation.
- let local_defined_features = tcx.lib_features().to_vec();
+ let local_defined_features = tcx.lib_features(()).to_vec();
if !remaining_lib_features.is_empty() {
check_features(&mut remaining_lib_features, &local_defined_features);
// have normal hygine, so we can treat them like other items without type
// privacy and mark them reachable.
DefKind::Macro(_) => {
- let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
- let item = self.tcx.hir().expect_item(hir_id);
+ let item = self.tcx.hir().expect_item(def_id);
if let hir::ItemKind::Macro(MacroDef { macro_rules: false, .. }) = item.kind {
if vis.is_accessible_from(module.to_def_id(), self.tcx) {
self.update(def_id, level);
DefKind::Struct | DefKind::Union => {
// While structs and unions have type privacy, their fields do not.
if vis.is_public() {
- let item =
- self.tcx.hir().expect_item(self.tcx.hir().local_def_id_to_hir_id(def_id));
+ let item = self.tcx.hir().expect_item(def_id);
if let hir::ItemKind::Struct(ref struct_def, _)
| hir::ItemKind::Union(ref struct_def, _) = item.kind
{
// If the module is `self`, i.e. the current crate,
// there will be no corresponding item.
.filter(|def_id| def_id.index != CRATE_DEF_INDEX || def_id.krate != LOCAL_CRATE)
- .and_then(|def_id| {
- def_id.as_local().map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id))
- })
+ .and_then(|def_id| def_id.as_local())
.map(|module_hir_id| self.tcx.hir().expect_item(module_hir_id))
{
if let hir::ItemKind::Mod(m) = &item.kind {
trait_definition_only: bool,
with_scope_for_path: bool,
) -> NamedRegionMap {
- let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(local_def_id));
+ let item = tcx.hir().expect_item(local_def_id);
let mut named_region_map = NamedRegionMap {
defs: Default::default(),
late_bound: Default::default(),
self.missing_named_lifetime_spots.push((&trait_item.generics).into());
let tcx = self.tcx;
self.visit_early_late(
- Some(tcx.hir().get_parent_item(trait_item.hir_id())),
+ Some(tcx.hir().get_parent_did(trait_item.hir_id())),
trait_item.hir_id(),
&sig.decl,
&trait_item.generics,
self.missing_named_lifetime_spots.push((&impl_item.generics).into());
let tcx = self.tcx;
self.visit_early_late(
- Some(tcx.hir().get_parent_item(impl_item.hir_id())),
+ Some(tcx.hir().get_parent_did(impl_item.hir_id())),
impl_item.hir_id(),
&sig.decl,
&impl_item.generics,
/// ordering is not important there.
fn visit_early_late<F>(
&mut self,
- parent_id: Option<hir::HirId>,
+ parent_id: Option<LocalDefId>,
hir_id: hir::HirId,
decl: &'tcx hir::FnDecl<'tcx>,
generics: &'tcx hir::Generics<'tcx>,
Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Fn(_, ref m), .. }) => {
if let hir::ItemKind::Trait(.., ref trait_items) =
- self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind
+ self.tcx.hir().expect_item(self.tcx.hir().get_parent_did(parent)).kind
{
assoc_item_kind =
trait_items.iter().find(|ti| ti.id.hir_id() == parent).map(|ti| ti.kind);
Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body), .. }) => {
if let hir::ItemKind::Impl(hir::Impl { ref self_ty, ref items, .. }) =
- self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind
+ self.tcx.hir().expect_item(self.tcx.hir().get_parent_did(parent)).kind
{
impl_self = Some(self_ty);
assoc_item_kind =
Passes::All => false,
}
}
+
+ pub fn extend(&mut self, passes: impl IntoIterator<Item = String>) {
+ match *self {
+ Passes::Some(ref mut v) => v.extend(passes),
+ Passes::All => {}
+ }
+ }
}
pub const fn default_lib_output() -> CrateType {
v => {
let mut passes = vec![];
if parse_list(&mut passes, v) {
- *slot = Passes::Some(passes);
+ slot.extend(passes);
true
} else {
false
HygieneData::with(|data| data.expn_data(self).clone())
}
+ #[inline]
pub fn is_descendant_of(self, ancestor: ExpnId) -> bool {
+ // a few "fast path" cases to avoid locking HygieneData
+ if ancestor == ExpnId::root() || ancestor == self {
+ return true;
+ }
+ if ancestor.krate != self.krate {
+ return false;
+ }
HygieneData::with(|data| data.is_descendant_of(self, ancestor))
}
}
fn is_descendant_of(&self, mut expn_id: ExpnId, ancestor: ExpnId) -> bool {
- while expn_id != ancestor {
+ // a couple "fast path" cases to avoid traversing parents in the loop below
+ if ancestor == ExpnId::root() {
+ return true;
+ }
+ if expn_id.krate != ancestor.krate {
+ return false;
+ }
+ loop {
+ if expn_id == ancestor {
+ return true;
+ }
if expn_id == ExpnId::root() {
return false;
}
expn_id = self.expn_data(expn_id).parent;
}
- true
}
fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext {
data: ExpnData,
hash: ExpnHash,
) -> ExpnId {
+ debug_assert!(data.parent == ExpnId::root() || krate == data.parent.krate);
let expn_id = ExpnId { krate, local_id };
HygieneData::with(|hygiene_data| {
let _old_data = hygiene_data.foreign_expn_data.insert(expn_id, data);
let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let parent_id = tcx.hir().get_parent_item(id);
let parent_def_id = tcx.hir().local_def_id(parent_id);
- let parent_item = tcx.hir().expect_item(parent_id);
+ let parent_item = tcx.hir().expect_item(parent_def_id);
match parent_item.kind {
hir::ItemKind::Impl(ref impl_) => {
if let Some(impl_item_ref) =
}
fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
- let item = tcx.hir().expect_item(hir_id);
+ let item = tcx.hir().expect_item(def_id.expect_local());
if let hir::ItemKind::Impl(impl_) = &item.kind {
impl_.defaultness
} else {
}
fn impl_constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
- let item = tcx.hir().expect_item(hir_id);
+ let item = tcx.hir().expect_item(def_id.expect_local());
if let hir::ItemKind::Impl(impl_) = &item.kind {
impl_.constness
} else {
}
fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
- let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
- let item = tcx.hir().expect_item(id);
+ let item = tcx.hir().expect_item(def_id.expect_local());
match item.kind {
hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter(
trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.def_id.to_def_id()),
def_id: LocalDefId,
span: Span,
) {
- let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(def_id));
+ let item = tcx.hir().expect_item(def_id);
debug!(?item, ?span);
struct FoundParentLifetime;
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(fcx, ty);
// Get the `impl Trait`'s `DefId`.
if let ty::Opaque(def_id, _) = ty.kind() {
- let hir_id = fcx.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
// Get the `impl Trait`'s `Item` so that we can get its trait bounds and
// get the `Trait`'s `DefId`.
if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) =
- fcx.tcx.hir().expect_item(hir_id).kind
+ fcx.tcx.hir().expect_item(def_id.expect_local()).kind
{
// Are of this `impl Trait`'s traits object safe?
is_object_safe = bounds.iter().all(|bound| {
// First liberate late bound regions and subst placeholders
let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id));
let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs);
- // Next, add all inputs and output as well-formed tys. Importantly,
- // we have to do this before normalization, since the normalized ty may
- // not contain the input parameters. See issue #87748.
- wf_tys.extend(trait_sig.inputs_and_output.iter());
let trait_sig =
inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig);
- // Also add the resulting inputs and output as well-formed.
- // This probably isn't strictly necessary.
+ // Add the resulting inputs and output as well-formed.
wf_tys.extend(trait_sig.inputs_and_output.iter());
let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
// 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 impl_m_hir_id =
- tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
- let span = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
+ let span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
ImplItemKind::Fn(ref sig, body) => tcx
.hir()
.body_param_names(body)
if trait_sig.inputs().len() == *i {
// Suggestion to change output type. We do not suggest in `async` functions
// to avoid complex logic or incorrect output.
- let impl_m_hir_id =
- tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
- match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
+ match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
ImplItemKind::Fn(ref sig, _)
if sig.header.asyncness == hir::IsAsync::NotAsync =>
{
trait_m: &ty::AssocItem,
) -> (Span, Option<Span>) {
let tcx = infcx.tcx;
- let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
- let mut impl_args = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
+ let mut impl_args = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
ImplItemKind::Fn(ref sig, _) => {
sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
}
_ => bug!("{:?} is not a method", impl_m),
};
- let trait_args = trait_m.def_id.as_local().map(|def_id| {
- let trait_m_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- match tcx.hir().expect_trait_item(trait_m_hir_id).kind {
+ let trait_args =
+ trait_m.def_id.as_local().map(|def_id| match tcx.hir().expect_trait_item(def_id).kind {
TraitItemKind::Fn(ref sig, _) => {
sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
}
_ => bug!("{:?} is not a TraitItemKind::Fn", trait_m),
- }
- });
+ });
match *terr {
TypeError::ArgumentMutability(i) => {
err_occurred = true;
let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() {
- let trait_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- let trait_item = tcx.hir().expect_trait_item(trait_hir_id);
+ let trait_item = tcx.hir().expect_trait_item(def_id);
if trait_item.generics.params.is_empty() {
(Some(vec![trait_item.generics.span]), vec![])
} else {
(trait_span.map(|s| vec![s]), vec![])
};
- let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_.def_id.expect_local());
- let impl_item = tcx.hir().expect_impl_item(impl_hir_id);
+ let impl_item = tcx.hir().expect_impl_item(impl_.def_id.expect_local());
let impl_item_impl_trait_spans: Vec<Span> = impl_item
.generics
.params
let impl_number_args = impl_m_fty.inputs().skip_binder().len();
if trait_number_args != impl_number_args {
let trait_span = if let Some(def_id) = trait_m.def_id.as_local() {
- let trait_id = tcx.hir().local_def_id_to_hir_id(def_id);
- match tcx.hir().expect_trait_item(trait_id).kind {
+ match tcx.hir().expect_trait_item(def_id).kind {
TraitItemKind::Fn(ref trait_m_sig, _) => {
let pos = if trait_number_args > 0 { trait_number_args - 1 } else { 0 };
if let Some(arg) = trait_m_sig.decl.inputs.get(pos) {
} else {
trait_item_span
};
- let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
- let impl_span = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
+ let impl_span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
ImplItemKind::Fn(ref impl_m_sig, _) => {
let pos = if impl_number_args > 0 { impl_number_args - 1 } else { 0 };
if let Some(arg) = impl_m_sig.decl.inputs.get(pos) {
);
// Locate the Span containing just the type of the offending impl
- match tcx.hir().expect_impl_item(impl_c_hir_id).kind {
+ match tcx.hir().expect_impl_item(impl_c.def_id.expect_local()).kind {
ImplItemKind::Const(ref ty, _) => cause.make_mut().span = ty.span,
_ => bug!("{:?} is not a impl const", impl_c),
}
trait_c.ident
);
- let trait_c_hir_id =
- trait_c.def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id));
- let trait_c_span = trait_c_hir_id.map(|trait_c_hir_id| {
+ let trait_c_span = trait_c.def_id.as_local().map(|trait_c_def_id| {
// Add a label to the Span containing just the type of the const
- match tcx.hir().expect_trait_item(trait_c_hir_id).kind {
+ match tcx.hir().expect_trait_item(trait_c_def_id).kind {
TraitItemKind::Const(ref ty, _) => ty.span,
_ => bug!("{:?} is not a trait const", trait_c),
}
(_, _) => return None,
};
- let last_hir_id = self.tcx.hir().local_def_id_to_hir_id(last_local_id);
- let exp_hir_id = self.tcx.hir().local_def_id_to_hir_id(exp_local_id);
-
match (
- &self.tcx.hir().expect_item(last_hir_id).kind,
- &self.tcx.hir().expect_item(exp_hir_id).kind,
+ &self.tcx.hir().expect_item(last_local_id).kind,
+ &self.tcx.hir().expect_item(exp_local_id).kind,
) {
(
hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }),
let import_items: Vec<_> = applicable_trait
.import_ids
.iter()
- .map(|&import_id| {
- let hir_id = self.tcx.hir().local_def_id_to_hir_id(import_id);
- self.tcx.hir().expect_item(hir_id)
- })
+ .map(|&import_id| self.tcx.hir().expect_item(import_id))
.collect();
// Find an identifier with which this trait was imported (note that `_` doesn't count).
let mut wf_tys = FxHashSet::default();
// Compute the fty from point of view of inside the fn.
let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
- wf_tys.extend(fn_sig.inputs_and_output.iter());
let fn_sig = inh.normalize_associated_types_in(
body.value.span,
body_id.hir_id,
/// the types first.
#[instrument(skip(tcx), level = "debug")]
pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- let item = tcx.hir().expect_item(hir_id);
+ let item = tcx.hir().expect_item(def_id);
debug!(
?item.def_id,
pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- let trait_item = tcx.hir().expect_trait_item(hir_id);
+ let trait_item = tcx.hir().expect_trait_item(def_id);
let (method_sig, span) = match trait_item.kind {
hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span),
check_object_unsafe_self_trait_by_name(tcx, trait_item);
check_associated_item(tcx, trait_item.def_id, span, method_sig);
- let encl_trait_hir_id = tcx.hir().get_parent_item(hir_id);
- let encl_trait = tcx.hir().expect_item(encl_trait_hir_id);
+ let encl_trait_def_id = tcx.hir().get_parent_did(hir_id);
+ let encl_trait = tcx.hir().expect_item(encl_trait_def_id);
let encl_trait_def_id = encl_trait.def_id.to_def_id();
let fn_lang_item_name = if Some(encl_trait_def_id) == tcx.lang_items().fn_trait() {
Some("fn")
}
pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- let impl_item = tcx.hir().expect_impl_item(hir_id);
+ let impl_item = tcx.hir().expect_impl_item(def_id);
let (method_sig, span) = match impl_item.kind {
hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span),
) {
let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig);
- // Unnormalized types in signature are WF too
- implied_bounds.extend(sig.inputs());
- // FIXME(#27579) return types should not be implied bounds
- implied_bounds.insert(sig.output());
-
// Normalize the input and output types one at a time, using a different
// `WellFormedLoc` for each. We cannot call `normalize_associated_types`
// on the entire `FnSig`, since this would use the same `WellFormedLoc`
for extern_crate in &crates_to_lint {
let def_id = extern_crate.def_id.expect_local();
- let id = tcx.hir().local_def_id_to_hir_id(def_id);
- let item = tcx.hir().expect_item(id);
+ let item = tcx.hir().expect_item(def_id);
// If the crate is fully unused, we suggest removing it altogether.
// We do this in any edition.
if extern_crate.warn_if_unused {
if let Some(&span) = unused_extern_crates.get(&def_id) {
+ let id = tcx.hir().local_def_id_to_hir_id(def_id);
tcx.struct_span_lint_hir(lint, id, span, |lint| {
// Removal suggestion span needs to include attributes (Issue #54400)
let span_with_attrs = tcx
if !tcx.get_attrs(extern_crate.def_id).is_empty() {
continue;
}
+ let id = tcx.hir().local_def_id_to_hir_id(def_id);
tcx.struct_span_lint_hir(lint, id, extern_crate.span, |lint| {
// Otherwise, we can convert it into a `use` of some kind.
let base_replacement = match extern_crate.orig_name {
return;
}
- let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
- let sp = match tcx.hir().expect_item(impl_hir_id).kind {
+ let sp = match tcx.hir().expect_item(impl_did).kind {
ItemKind::Impl(ref impl_) => impl_.self_ty.span,
_ => bug!("expected Drop impl item"),
};
match can_type_implement_copy(tcx, param_env, self_type) {
Ok(()) => {}
Err(CopyImplementationError::InfrigingFields(fields)) => {
- let item = tcx.hir().expect_item(impl_hir_id);
+ let item = tcx.hir().expect_item(impl_did);
let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(ref tr), .. }) = item.kind {
tr.path.span
} else {
err.emit()
}
Err(CopyImplementationError::NotAnAdt) => {
- let item = tcx.hir().expect_item(impl_hir_id);
+ let item = tcx.hir().expect_item(impl_did);
let span =
if let ItemKind::Impl(ref impl_) = item.kind { impl_.self_ty.span } else { span };
debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
// this provider should only get invoked for local def-ids
- let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did.expect_local());
- let span = tcx.hir().span(impl_hir_id);
+ let impl_did = impl_did.expect_local();
+ let span = tcx.def_span(impl_did);
let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span));
debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)", source, target);
tcx.infer_ctxt().enter(|infcx| {
+ let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
let cause = ObligationCause::misc(span, impl_hir_id);
let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
mt_b: ty::TypeAndMut<'tcx>,
.emit();
return err_info;
} else if diff_fields.len() > 1 {
- let item = tcx.hir().expect_item(impl_hir_id);
+ let item = tcx.hir().expect_item(impl_did);
let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(ref t), .. }) =
item.kind
{
t.path.span
} else {
- tcx.hir().span(impl_hir_id)
+ tcx.def_span(impl_did)
};
struct_span_err!(
// Finally, resolve all regions.
let outlives_env = OutlivesEnvironment::new(param_env);
- infcx.resolve_regions_and_report_errors(impl_did, &outlives_env, RegionckMode::default());
+ infcx.resolve_regions_and_report_errors(
+ impl_did.to_def_id(),
+ &outlives_env,
+ RegionckMode::default(),
+ );
CoerceUnsizedInfo { custom_kind: kind }
})
match self.node() {
hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => {
let item =
- self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(self.hir_id()));
+ self.tcx.hir().expect_item(self.tcx.hir().get_parent_did(self.hir_id()));
match &item.kind {
hir::ItemKind::Enum(_, generics)
| hir::ItemKind::Struct(_, generics)
}
fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
- let item = tcx.hir().expect_item(hir_id);
+ let item = tcx.hir().expect_item(def_id.expect_local());
let (is_auto, unsafety) = match item.kind {
hir::ItemKind::Trait(is_auto, unsafety, ..) => (is_auto == hir::IsAuto::Yes, unsafety),
fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
let icx = ItemCtxt::new(tcx, def_id);
-
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
- match tcx.hir().expect_item(hir_id).kind {
+ match tcx.hir().expect_item(def_id.expect_local()).kind {
hir::ItemKind::Impl(ref impl_) => impl_.of_trait.as_ref().map(|ast_trait_ref| {
let selfty = tcx.type_of(def_id);
<dyn AstConv<'_>>::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty)
}
fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
- let item = tcx.hir().expect_item(hir_id);
+ let item = tcx.hir().expect_item(def_id.expect_local());
match &item.kind {
hir::ItemKind::Impl(hir::Impl {
polarity: hir::ImplPolarity::Negative(span),
let hir_id = tcx.hir().local_def_id_to_hir_id(id);
let node = tcx.hir().get(hir_id);
if let Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node {
- let parent_id = tcx.hir().get_parent_item(hir_id);
+ let parent_id = tcx.hir().get_parent_did(hir_id);
let parent_item = tcx.hir().expect_item(parent_id);
if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind {
tcx.sess
}
}
+ /// A specialized version of `reserve()` used only by the hot and
+ /// oft-instantiated `Vec::push()`, which does its own capacity check.
+ #[cfg(not(no_global_oom_handling))]
+ #[inline(never)]
+ pub fn reserve_for_push(&mut self, len: usize) {
+ handle_reserve(self.grow_amortized(len, 1));
+ }
+
/// The same as `reserve`, but returns on errors instead of panicking or aborting.
pub fn try_reserve(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> {
if self.needs_to_grow(len, additional) {
// This will panic or abort if we would allocate > isize::MAX bytes
// or if the length increment would overflow for zero-sized types.
if self.len == self.buf.capacity() {
- self.reserve(1);
+ self.buf.reserve_for_push(self.len);
}
unsafe {
let end = self.as_mut_ptr().add(self.len);
/// zero-initialization: This will statically either panic, or do nothing.
///
/// This intrinsic does not have a stable counterpart.
+ #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
pub fn assert_zero_valid<T>();
/// A guard for unsafe functions that cannot ever be executed if `T` has invalid
/// bit patterns: This will statically either panic, or do nothing.
///
/// This intrinsic does not have a stable counterpart.
+ #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
pub fn assert_uninit_valid<T>();
/// Gets a reference to a static `Location` indicating where it was called.
/// assert_eq!(iter.next(), None);
/// ```
#[inline]
+ #[doc(alias = "drop_while")]
#[stable(feature = "rust1", since = "1.0.0")]
fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
where
}
let mut i = 0;
+ let mut valid_up_to = 0;
while i < self.source.len() {
- let i_ = i;
-
- // SAFETY: `i` starts at `0`, is less than `self.source.len()`, and
- // only increases, so `0 <= i < self.source.len()`.
+ // SAFETY: `i < self.source.len()` per previous line.
+ // For some reason the following are both significantly slower:
+ // while let Some(&byte) = self.source.get(i) {
+ // while let Some(byte) = self.source.get(i).copied() {
let byte = unsafe { *self.source.get_unchecked(i) };
i += 1;
if byte < 128 {
+ // This could be a `1 => ...` case in the match below, but for
+ // the common case of all-ASCII inputs, we bypass loading the
+ // sizeable UTF8_CHAR_WIDTH table into cache.
} else {
let w = utf8_char_width(byte);
- macro_rules! error {
- () => {{
- // SAFETY: We have checked up to `i` that source is valid UTF-8.
- unsafe {
- let r = Utf8LossyChunk {
- valid: from_utf8_unchecked(&self.source[0..i_]),
- broken: &self.source[i_..i],
- };
- self.source = &self.source[i..];
- return Some(r);
- }
- }};
- }
-
match w {
2 => {
if safe_get(self.source, i) & 192 != TAG_CONT_U8 {
- error!();
+ break;
}
i += 1;
}
(0xE1..=0xEC, 0x80..=0xBF) => (),
(0xED, 0x80..=0x9F) => (),
(0xEE..=0xEF, 0x80..=0xBF) => (),
- _ => {
- error!();
- }
+ _ => break,
}
i += 1;
if safe_get(self.source, i) & 192 != TAG_CONT_U8 {
- error!();
+ break;
}
i += 1;
}
(0xF0, 0x90..=0xBF) => (),
(0xF1..=0xF3, 0x80..=0xBF) => (),
(0xF4, 0x80..=0x8F) => (),
- _ => {
- error!();
- }
+ _ => break,
}
i += 1;
if safe_get(self.source, i) & 192 != TAG_CONT_U8 {
- error!();
+ break;
}
i += 1;
if safe_get(self.source, i) & 192 != TAG_CONT_U8 {
- error!();
+ break;
}
i += 1;
}
- _ => {
- error!();
- }
+ _ => break,
}
}
+
+ valid_up_to = i;
}
- let r = Utf8LossyChunk {
- // SAFETY: We have checked that the entire source is valid UTF-8.
- valid: unsafe { from_utf8_unchecked(self.source) },
- broken: &[],
- };
- self.source = &[];
- Some(r)
+ // SAFETY: `i <= self.source.len()` because it is only ever incremented
+ // via `i += 1` and in between every single one of those increments, `i`
+ // is compared against `self.source.len()`. That happens either
+ // literally by `i < self.source.len()` in the while-loop's condition,
+ // or indirectly by `safe_get(self.source, i) & 192 != TAG_CONT_U8`. The
+ // loop is terminated as soon as the latest `i += 1` has made `i` no
+ // longer less than `self.source.len()`, which means it'll be at most
+ // equal to `self.source.len()`.
+ let (inspected, remaining) = unsafe { self.source.split_at_unchecked(i) };
+ self.source = remaining;
+
+ // SAFETY: `valid_up_to <= i` because it is only ever assigned via
+ // `valid_up_to = i` and `i` only increases.
+ let (valid, broken) = unsafe { inspected.split_at_unchecked(valid_up_to) };
+
+ Some(Utf8LossyChunk {
+ // SAFETY: All bytes up to `valid_up_to` are valid UTF-8.
+ valid: unsafe { from_utf8_unchecked(valid) },
+ broken,
+ })
}
}
/// Ok(())
/// }
/// ```
+///
+/// # Limitations
+///
+/// Windows treats symlink creation as a [privileged action][symlink-security],
+/// therefore this function is likely to fail unless the user makes changes to
+/// their system to permit symlink creation. Users can try enabling Developer
+/// Mode, granting the `SeCreateSymbolicLinkPrivilege` privilege, or running
+/// the process as an administrator.
+///
+/// [symlink-security]: https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links
#[stable(feature = "symlink", since = "1.1.0")]
pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
sys::fs::symlink_inner(original.as_ref(), link.as_ref(), false)
/// Ok(())
/// }
/// ```
+///
+/// # Limitations
+///
+/// Windows treats symlink creation as a [privileged action][symlink-security],
+/// therefore this function is likely to fail unless the user makes changes to
+/// their system to permit symlink creation. Users can try enabling Developer
+/// Mode, granting the `SeCreateSymbolicLinkPrivilege` privilege, or running
+/// the process as an administrator.
+///
+/// [symlink-security]: https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links
#[stable(feature = "symlink", since = "1.1.0")]
pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
sys::fs::symlink_inner(original.as_ref(), link.as_ref(), true)
}
let impl_item = match did.as_local() {
- Some(did) => {
- let hir_id = tcx.hir().local_def_id_to_hir_id(did);
- match &tcx.hir().expect_item(hir_id).kind {
- hir::ItemKind::Impl(impl_) => Some(impl_),
- _ => panic!("`DefID` passed to `build_impl` is not an `impl"),
- }
- }
+ Some(did) => match &tcx.hir().expect_item(did).kind {
+ hir::ItemKind::Impl(impl_) => Some(impl_),
+ _ => panic!("`DefID` passed to `build_impl` is not an `impl"),
+ },
None => None,
};
let what_rustc_thinks =
Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx);
- let parent_item = cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(self.hir_id()));
+ let parent_item = cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_did(self.hir_id()));
if let hir::ItemKind::Impl(impl_) = &parent_item.kind {
if impl_.of_trait.is_some() {
// Trait impl items always inherit the impl's visibility --
let Res::Def(DefKind::TyAlias, def_id) = path.res else { return None };
// Substitute private type aliases
let Some(def_id) = def_id.as_local() else { return None };
- let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
let alias = if !cx.cache.access_levels.is_exported(def_id.to_def_id()) {
- &cx.tcx.hir().expect_item(hir_id).kind
+ &cx.tcx.hir().expect_item(def_id).kind
} else {
return None;
};
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 hir_id = self.cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
- let item = self.cx.tcx.hir().expect_item(hir_id);
+ let item = self.cx.tcx.hir().expect_item(local_def_id);
top_level_module.items.push((item, None));
}
}
-// pretty-printers are not loaded
+// ignore-windows-gnu: pretty-printers are not loaded
// compile-flags:-g
// min-gdb-version: 8.1
extern crate rustc_lint;
#[macro_use]
extern crate rustc_session;
-extern crate rustc_span;
extern crate rustc_ast;
+extern crate rustc_span;
use rustc_ast_pretty::pprust;
use rustc_driver::plugin::Registry;
) {
let item = match cx.tcx.hir().get(id) {
Node::Item(item) => item,
- _ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(id)),
+ _ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(id).expect_owner()),
};
let allowed = |attr| pprust::attribute_to_string(attr).contains("allowed_attr");
|
LL | println!("{}", i);
| ^ use of possibly-uninitialized `i`
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
|
LL | println!("{}", x);
| ^ use of possibly-uninitialized `x`
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
|
LL | println!("{}", x);
| ^ use of possibly-uninitialized `x`
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
|
LL | println!("{}", i);
| ^ use of possibly-uninitialized `i`
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
|
LL | println!("{}", v);
| ^ use of possibly-uninitialized `v`
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
|
LL | println!("{}", x);
| ^ use of possibly-uninitialized `x`
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0381]: borrow of possibly-uninitialized variable: `x`
--> $DIR/issue-24267-flow-exit.rs:18:20
|
LL | println!("{}", x);
| ^ use of possibly-uninitialized `x`
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors
...
LL | c();
| - mutable borrow later used here
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0502]: cannot borrow `arr` as immutable because it is also borrowed as mutable
--> $DIR/arrays.rs:73:24
LL |
LL | c();
| - mutable borrow later used here
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed
--> $DIR/box.rs:55:5
= 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)
+ = note: this warning originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: 1 warning emitted
LL |
LL | c();
| - mutable borrow later used here
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
|
LL | fn into_iter(self) -> Self::IntoIter;
| ^^^^
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
--- /dev/null
+// error-pattern: any use of this value will cause an error
+
+#![feature(never_type)]
+#![feature(const_maybe_uninit_assume_init, const_assert_type2)]
+#![feature(core_intrinsics)]
+
+use std::intrinsics;
+
+#[allow(invalid_value)]
+fn main() {
+ use std::mem::MaybeUninit;
+
+ const _BAD1: () = unsafe {
+ MaybeUninit::<!>::uninit().assume_init();
+ };
+ const _BAD2: () = unsafe {
+ intrinsics::assert_uninit_valid::<bool>();
+ };
+ const _BAD3: () = unsafe {
+ intrinsics::assert_zero_valid::<&'static i32>();
+ };
+}
--- /dev/null
+error: any use of this value will cause an error
+ --> $DIR/assert-type-intrinsics.rs:14:9
+ |
+LL | / const _BAD1: () = unsafe {
+LL | | MaybeUninit::<!>::uninit().assume_init();
+ | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!`
+LL | | };
+ | |______-
+ |
+ = note: `#[deny(const_err)]` on by default
+ = 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 #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: any use of this value will cause an error
+ --> $DIR/assert-type-intrinsics.rs:17:9
+ |
+LL | / const _BAD2: () = unsafe {
+LL | | intrinsics::assert_uninit_valid::<bool>();
+ | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to leave type `bool` uninitialized, which is invalid
+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 #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: any use of this value will cause an error
+ --> $DIR/assert-type-intrinsics.rs:20:9
+ |
+LL | / const _BAD3: () = unsafe {
+LL | | intrinsics::assert_zero_valid::<&'static i32>();
+ | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `&i32`, which is invalid
+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 #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: aborting due to 3 previous errors
+
+++ /dev/null
-// error-pattern: any use of this value will cause an error
-
-#![feature(never_type)]
-#![feature(const_maybe_uninit_assume_init)]
-
-#[allow(invalid_value)]
-fn main() {
- use std::mem::MaybeUninit;
-
- const _BAD: () = unsafe {
- MaybeUninit::<!>::uninit().assume_init();
- };
-}
+++ /dev/null
-error: any use of this value will cause an error
- --> $DIR/assume-type-intrinsics.rs:11:9
- |
-LL | / const _BAD: () = unsafe {
-LL | | MaybeUninit::<!>::uninit().assume_init();
- | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!`
-LL | | };
- | |______-
- |
- = note: `#[deny(const_err)]` on by default
- = 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 #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: aborting due to previous error
-
|
= 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 #71800 <https://github.com/rust-lang/rust/issues/71800>
+ = note: this warning originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error; 2 warnings emitted
|
= 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 #71800 <https://github.com/rust-lang/rust/issues/71800>
+ = note: this warning originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: evaluation of constant value failed
--> $DIR/issue-43197.rs:16:26
|
= 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 #71800 <https://github.com/rust-lang/rust/issues/71800>
+ = note: this warning originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors; 4 warnings emitted
--- /dev/null
+error: lifetime may not live long enough
+ --> $DIR/implied-bounds-unnorm-associated-type.rs:14:5
+ |
+LL | fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | s
+ | ^ returning this value requires that `'b` must outlive `'a`
+ |
+ = help: consider adding the following bound: `'b: 'a`
+
+error: aborting due to previous error
+
--- /dev/null
+// check-fail
+// See issue #91068. Types in the substs of an associated type can't be implied
+// to be WF, since they don't actually have to be constructed.
+
+trait Trait {
+ type Type;
+}
+
+impl<T> Trait for T {
+ type Type = ();
+}
+
+fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str {
+ s //~ ERROR lifetime mismatch [E0623]
+}
+
+fn main() {
+ let x = String::from("Hello World!");
+ let y = f(&x, ());
+ drop(x);
+ println!("{}", y);
+}
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/implied-bounds-unnorm-associated-type.rs:14:5
+ |
+LL | fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str {
+ | ------- ----------
+ | |
+ | these two types are declared with different lifetimes...
+LL | s
+ | ^ ...but data from `s` flows here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
| ^ second borrow occurs here
LL | Pin::new(&mut b).resume(());
| ------ first borrow later used here
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
+++ /dev/null
-// Checks that we properly add implied bounds from unnormalized projections in
-// inputs when typechecking functions.
-
-// check-pass
-
-#![feature(generic_associated_types)]
-
-trait MyTrait {
- type Assoc<'a, 'b> where 'b: 'a;
- fn do_sth(arg: Self::Assoc<'_, '_>);
-}
-
-struct A;
-struct B;
-struct C;
-
-impl MyTrait for A {
- type Assoc<'a, 'b> where 'b: 'a = u32;
- fn do_sth(_: u32) {}
-}
-impl MyTrait for B {
- type Assoc<'a, 'b> where 'b: 'a = u32;
- fn do_sth(_: Self::Assoc<'_, '_>) {}
-}
-impl MyTrait for C {
- type Assoc<'a, 'b> where 'b: 'a = u32;
- fn do_sth(_: Self::Assoc<'static, 'static>) {}
-}
-
-fn main () {}
...
LL | println!("{}", s);
| ^ value borrowed here after move
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
...
LL | };
| - ... and the mutable borrow might be used here, when that temporary is dropped and runs the destructor for type `(Option<PeekMut<'_, i32>>, ())`
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
= note: `#[deny(const_err)]` on by default
= 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 #71800 <https://github.com/rust-lang/rust/issues/71800>
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors
| ^ value borrowed here after move
LL | while true { while true { while true { x = y; x.clone(); } } }
| - value moved here, in previous iteration of loop
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error; 3 warnings emitted
LL |
LL | println!("{}", *x);
| ^^ value borrowed here after move
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
| ------- value moved here
LL | println!("{}", message);
| ^^^^^^^ value borrowed here after move
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
|
LL | println!("{:?}", x);
| ^ use of possibly-uninitialized `x`
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
LL | });
LL | println!("{}", x);
| ^ value borrowed here after move
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
--- /dev/null
+// build-pass
+// ignore-pass
+// no-system-llvm
+// revisions: all inline merge1 merge2
+// compile-flags: --crate-type=lib -Cdebuginfo=1 -Copt-level=2
+//
+// Check that remarks can be enabled individually or with "all":
+//
+// [all] compile-flags: -Cremark=all
+// [inline] compile-flags: -Cremark=inline
+//
+// Check that values of -Cremark flag are accumulated:
+//
+// [merge1] compile-flags: -Cremark=all -Cremark=giraffe
+// [merge2] compile-flags: -Cremark=inline -Cremark=giraffe
+//
+// error-pattern: inline: f not inlined into g
+// dont-check-compiler-stderr
+
+#[no_mangle]
+#[inline(never)]
+pub fn f() {
+}
+
+#[no_mangle]
+pub fn g() {
+ f();
+}
pub enum NonExhaustiveSingleVariant {
A(bool),
}
+
+#[repr(u8)]
+pub enum FieldLessWithNonExhaustiveVariant {
+ A,
+ B,
+ #[non_exhaustive]
+ C,
+}
+
+impl Default for FieldLessWithNonExhaustiveVariant {
+ fn default() -> Self { Self::A }
+}
--- /dev/null
+// aux-build:enums.rs
+// run-pass
+
+extern crate enums;
+
+use enums::FieldLessWithNonExhaustiveVariant;
+
+fn main() {
+ let e = FieldLessWithNonExhaustiveVariant::default();
+ // FIXME: https://github.com/rust-lang/rust/issues/91161
+ // This `as` cast *should* be an error, since it would fail
+ // if the non-exhaustive variant got fields. But today it
+ // doesn't. The fix for that will update this test to
+ // show an error (and not be run-pass any more).
+ let d = e as u8;
+ assert_eq!(d, 0);
+}
LL | };
LL | println!("{}", x);
| ^ value borrowed here after move
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0506]: cannot assign to `i` because it is borrowed
--> $DIR/try-block-maybe-bad-lifetime.rs:40:9
| - value moved here
LL | println!("{}", x);
| ^ value borrowed here after move
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
|
LL | fn make_string_bar(mut self) -> Mine{
| ^^^^
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
-Subproject commit 7f08ace4f1305de7f3b1b0e2f765911957226bd4
+Subproject commit 294967c53f0c70d598fc54ca189313c86c576ea7
use clippy_utils::ty::{implements_trait, is_copy};
use clippy_utils::{get_trait_def_id, is_automatically_derived, is_lint_allowed, match_def_path};
use if_chain::if_chain;
-use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, NestedVisitorMap, Visitor};
use rustc_hir::{
BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, HirId, Impl, Item, ItemKind, TraitRef, UnsafeSource, Unsafety,
trait_ref: &TraitRef<'_>,
ty: Ty<'tcx>,
) {
- fn item_from_def_id<'tcx>(cx: &LateContext<'tcx>, def_id: DefId) -> &'tcx Item<'tcx> {
- let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
- cx.tcx.hir().expect_item(hir_id)
- }
-
fn has_unsafe<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>) -> bool {
let mut visitor = UnsafeVisitor { cx, has_unsafe: false };
walk_item(&mut visitor, item);
if !is_lint_allowed(cx, UNSAFE_DERIVE_DESERIALIZE, adt_hir_id);
if cx.tcx.inherent_impls(def.did)
.iter()
- .map(|imp_did| item_from_def_id(cx, *imp_did))
+ .map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local()))
.any(|imp| has_unsafe(cx, imp));
then {
span_lint_and_help(
return;
}
let name = impl_item.ident.name.as_str();
- let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
+ let parent = cx.tcx.hir().get_parent_did(impl_item.hir_id());
let item = cx.tcx.hir().expect_item(parent);
let self_ty = cx.tcx.type_of(item.def_id);
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) {
if let ImplItemKind::Const(hir_ty, body_id) = &impl_item.kind {
- let item_hir_id = cx.tcx.hir().get_parent_node(impl_item.hir_id());
- let item = cx.tcx.hir().expect_item(item_hir_id);
+ let item_def_id = cx.tcx.hir().get_parent_did(impl_item.hir_id());
+ let item = cx.tcx.hir().expect_item(item_def_id);
match &item.kind {
ItemKind::Impl(Impl {
_ => return,
}
- let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
+ let parent = cx.tcx.hir().get_parent_did(impl_item.hir_id());
let item = cx.tcx.hir().expect_item(parent);
let self_ty = cx.tcx.type_of(item.def_id);
let ret_ty = return_ty(cx, impl_item.hir_id());
if impl_item.span.from_expansion() {
return;
}
- let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
+ let parent = cx.tcx.hir().get_parent_did(impl_item.hir_id());
let parent_item = cx.tcx.hir().expect_item(parent);
let assoc_item = cx.tcx.associated_item(impl_item.def_id);
if_chain! {
-Subproject commit 76a3329f51439ff2cacda4d26d478a9dc1682a06
+Subproject commit 9983e0fc634e11717eb457a73fe84cfc9409ba8f
-Subproject commit 183ef048f61ae36aa389d1d0345cde940fe788e9
+Subproject commit d9b2291f546abc77d24499339a72a89127464b95