commit
33515d7497
371 changed files with 2476 additions and 1833 deletions
33
Cargo.lock
33
Cargo.lock
|
|
@ -509,9 +509,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "4.3.1"
|
||||
version = "4.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f6b5c519bab3ea61843a7923d074b04245624bb84a64a8c150f5deb014e388b"
|
||||
checksum = "bffe91f06a11b4b9420f62103854e90867812cd5d01557f853c5ee8e791b12ae"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
|
@ -580,7 +580,7 @@ dependencies = [
|
|||
"clap",
|
||||
"indoc",
|
||||
"itertools",
|
||||
"opener",
|
||||
"opener 0.5.2",
|
||||
"shell-escape",
|
||||
"walkdir",
|
||||
]
|
||||
|
|
@ -2340,9 +2340,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "mdbook"
|
||||
version = "0.4.31"
|
||||
version = "0.4.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b67ee4a744f36e6280792016c17e69921b51df357181d1eb17d620fcc3609f3"
|
||||
checksum = "80992cb0e05f22cc052c99f8e883f1593b891014b96a8b4637fd274d7030c85e"
|
||||
dependencies = [
|
||||
"ammonia",
|
||||
"anyhow",
|
||||
|
|
@ -2355,7 +2355,8 @@ dependencies = [
|
|||
"log",
|
||||
"memchr",
|
||||
"once_cell",
|
||||
"opener",
|
||||
"opener 0.6.1",
|
||||
"pathdiff",
|
||||
"pulldown-cmark",
|
||||
"regex",
|
||||
"serde",
|
||||
|
|
@ -2544,6 +2545,15 @@ dependencies = [
|
|||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "normpath"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec60c60a693226186f5d6edf073232bfb6464ed97eb22cf3b01c1e8198fd97f5"
|
||||
dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.4.1"
|
||||
|
|
@ -2631,6 +2641,17 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opener"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c62dcb6174f9cb326eac248f07e955d5d559c272730b6c03e396b443b562788"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"normpath",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.55"
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use crate::{
|
|||
pub trait LayoutCalculator {
|
||||
type TargetDataLayoutRef: Borrow<TargetDataLayout>;
|
||||
|
||||
fn delay_bug(&self, txt: String);
|
||||
fn delayed_bug(&self, txt: String);
|
||||
fn current_data_layout(&self) -> Self::TargetDataLayoutRef;
|
||||
|
||||
fn scalar_pair<FieldIdx: Idx, VariantIdx: Idx>(
|
||||
|
|
@ -792,7 +792,7 @@ pub trait LayoutCalculator {
|
|||
let only_variant = &variants[VariantIdx::new(0)];
|
||||
for field in only_variant {
|
||||
if field.is_unsized() {
|
||||
self.delay_bug("unsized field in union".to_string());
|
||||
self.delayed_bug("unsized field in union".to_string());
|
||||
}
|
||||
|
||||
align = align.max(field.align);
|
||||
|
|
@ -1038,7 +1038,7 @@ fn univariant<
|
|||
for &i in &inverse_memory_index {
|
||||
let field = &fields[i];
|
||||
if !sized {
|
||||
this.delay_bug(format!(
|
||||
this.delayed_bug(format!(
|
||||
"univariant: field #{} comes after unsized field",
|
||||
offsets.len(),
|
||||
));
|
||||
|
|
|
|||
|
|
@ -327,7 +327,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
),
|
||||
ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
|
||||
ExprKind::Err => hir::ExprKind::Err(
|
||||
self.tcx.sess.delay_span_bug(e.span, "lowered ExprKind::Err"),
|
||||
self.tcx.sess.span_delayed_bug(e.span, "lowered ExprKind::Err"),
|
||||
),
|
||||
ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),
|
||||
|
||||
|
|
@ -799,7 +799,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
self.expr_ident_mut(span, task_context_ident, task_context_hid)
|
||||
} else {
|
||||
// Use of `await` outside of an async context, we cannot use `task_context` here.
|
||||
self.expr_err(span, self.tcx.sess.delay_span_bug(span, "no task_context hir id"))
|
||||
self.expr_err(span, self.tcx.sess.span_delayed_bug(span, "no task_context hir id"))
|
||||
};
|
||||
let new_unchecked = self.expr_call_lang_item_fn_mut(
|
||||
span,
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ fn make_count<'hir>(
|
|||
ctx.expr(
|
||||
sp,
|
||||
hir::ExprKind::Err(
|
||||
ctx.tcx.sess.delay_span_bug(sp, "lowered bad format_args count"),
|
||||
ctx.tcx.sess.span_delayed_bug(sp, "lowered bad format_args count"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -306,7 +306,7 @@ fn make_format_spec<'hir>(
|
|||
}
|
||||
Err(_) => ctx.expr(
|
||||
sp,
|
||||
hir::ExprKind::Err(ctx.tcx.sess.delay_span_bug(sp, "lowered bad format_args count")),
|
||||
hir::ExprKind::Err(ctx.tcx.sess.span_delayed_bug(sp, "lowered bad format_args count")),
|
||||
),
|
||||
};
|
||||
let &FormatOptions {
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| match ty {
|
||||
None => {
|
||||
let guar = this.tcx.sess.delay_span_bug(
|
||||
let guar = this.tcx.sess.span_delayed_bug(
|
||||
span,
|
||||
"expected to lower type alias type, but it was missing",
|
||||
);
|
||||
|
|
@ -863,7 +863,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| match ty {
|
||||
None => {
|
||||
let guar = this.tcx.sess.delay_span_bug(
|
||||
let guar = this.tcx.sess.span_delayed_bug(
|
||||
i.span,
|
||||
"expected to lower associated type, but it was missing",
|
||||
);
|
||||
|
|
@ -996,7 +996,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
fn lower_block_expr_opt(&mut self, span: Span, block: Option<&Block>) -> hir::Expr<'hir> {
|
||||
match block {
|
||||
Some(block) => self.lower_block_expr(block),
|
||||
None => self.expr_err(span, self.tcx.sess.delay_span_bug(span, "no block")),
|
||||
None => self.expr_err(span, self.tcx.sess.span_delayed_bug(span, "no block")),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1006,7 +1006,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
&[],
|
||||
match expr {
|
||||
Some(expr) => this.lower_expr_mut(expr),
|
||||
None => this.expr_err(span, this.tcx.sess.delay_span_bug(span, "no block")),
|
||||
None => this.expr_err(span, this.tcx.sess.span_delayed_bug(span, "no block")),
|
||||
},
|
||||
)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ use rustc_data_structures::fx::FxHashMap;
|
|||
use rustc_data_structures::sorted_map::SortedMap;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::{DiagnosticArgFromDisplay, Handler, StashKey};
|
||||
use rustc_errors::{DiagnosticArgFromDisplay, StashKey};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
|
||||
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
|
||||
|
|
@ -763,10 +763,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
self.resolver.get_import_res(id).present_items()
|
||||
}
|
||||
|
||||
fn diagnostic(&self) -> &Handler {
|
||||
self.tcx.sess.diagnostic()
|
||||
}
|
||||
|
||||
/// Reuses the span but adds information like the kind of the desugaring and features that are
|
||||
/// allowed inside this span.
|
||||
fn mark_span_with_reason(
|
||||
|
|
@ -1326,7 +1322,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
let kind = match &t.kind {
|
||||
TyKind::Infer => hir::TyKind::Infer,
|
||||
TyKind::Err => {
|
||||
hir::TyKind::Err(self.tcx.sess.delay_span_bug(t.span, "TyKind::Err lowered"))
|
||||
hir::TyKind::Err(self.tcx.sess.span_delayed_bug(t.span, "TyKind::Err lowered"))
|
||||
}
|
||||
// FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
|
|
@ -1510,7 +1506,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
TyKind::MacCall(_) => panic!("`TyKind::MacCall` should have been expanded by now"),
|
||||
TyKind::CVarArgs => {
|
||||
let guar = self.tcx.sess.delay_span_bug(
|
||||
let guar = self.tcx.sess.span_delayed_bug(
|
||||
t.span,
|
||||
"`TyKind::CVarArgs` should have been handled elsewhere",
|
||||
);
|
||||
|
|
@ -1653,7 +1649,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
} else {
|
||||
self.tcx
|
||||
.sess
|
||||
.delay_span_bug(lifetime.ident.span, "no def-id for fresh lifetime");
|
||||
.span_delayed_bug(lifetime.ident.span, "no def-id for fresh lifetime");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
@ -2515,9 +2511,10 @@ impl<'hir> GenericArgsCtor<'hir> {
|
|||
let hir_id = lcx.next_id();
|
||||
|
||||
let Some(host_param_id) = lcx.host_param_id else {
|
||||
lcx.tcx
|
||||
.sess
|
||||
.delay_span_bug(span, "no host param id for call in const yet no errors reported");
|
||||
lcx.tcx.sess.span_delayed_bug(
|
||||
span,
|
||||
"no host param id for call in const yet no errors reported",
|
||||
);
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
|
||||
// We should've returned in the for loop above.
|
||||
|
||||
self.diagnostic().span_bug(
|
||||
self.tcx.sess.diagnostic().span_bug(
|
||||
p.span,
|
||||
format!(
|
||||
"lower_qpath: no final extension segment in {}..{}",
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ impl<'a> PostExpansionVisitor<'a> {
|
|||
}
|
||||
Err(abi::AbiDisabled::Unrecognized) => {
|
||||
if self.sess.opts.pretty.map_or(true, |ppm| ppm.needs_hir()) {
|
||||
self.sess.parse_sess.span_diagnostic.delay_span_bug(
|
||||
self.sess.diagnostic().span_delayed_bug(
|
||||
span,
|
||||
format!(
|
||||
"unrecognized ABI not caught in lowering: {}",
|
||||
|
|
@ -515,7 +515,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
}
|
||||
};
|
||||
}
|
||||
gate_all!(c_str_literals, "`c\"..\"` literals are experimental");
|
||||
gate_all!(
|
||||
if_let_guard,
|
||||
"`if let` guards are experimental",
|
||||
|
|
@ -628,7 +627,7 @@ fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate)
|
|||
if all_stable {
|
||||
err.sugg = Some(attr.span);
|
||||
}
|
||||
sess.parse_sess.span_diagnostic.emit_err(err);
|
||||
sess.diagnostic().emit_err(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -945,7 +945,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
|||
assert!(attr.has_name(sym::repr), "expected `#[repr(..)]`, found: {attr:?}");
|
||||
use ReprAttr::*;
|
||||
let mut acc = Vec::new();
|
||||
let diagnostic = &sess.parse_sess.span_diagnostic;
|
||||
let diagnostic = sess.diagnostic();
|
||||
|
||||
if let Some(items) = attr.meta_item_list() {
|
||||
for item in items {
|
||||
|
|
@ -1060,9 +1060,9 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
|||
// Not a word we recognize. This will be caught and reported by
|
||||
// the `check_mod_attrs` pass, but this pass doesn't always run
|
||||
// (e.g. if we only pretty-print the source), so we have to gate
|
||||
// the `delay_span_bug` call as follows:
|
||||
// the `span_delayed_bug` call as follows:
|
||||
if sess.opts.pretty.map_or(true, |pp| pp.needs_analysis()) {
|
||||
diagnostic.delay_span_bug(item.span(), "unrecognized representation hint");
|
||||
diagnostic.span_delayed_bug(item.span(), "unrecognized representation hint");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,248 +0,0 @@
|
|||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_middle::mir::visit::TyContext;
|
||||
use rustc_middle::mir::visit::Visitor;
|
||||
use rustc_middle::mir::{
|
||||
Body, Local, Location, Place, PlaceRef, ProjectionElem, Rvalue, SourceInfo, Statement,
|
||||
StatementKind, Terminator, TerminatorKind, UserTypeProjection,
|
||||
};
|
||||
use rustc_middle::ty::visit::TypeVisitable;
|
||||
use rustc_middle::ty::GenericArgsRef;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
|
||||
use crate::{
|
||||
borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, places_conflict,
|
||||
region_infer::values::LivenessValues,
|
||||
};
|
||||
|
||||
pub(super) fn generate_constraints<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
liveness_constraints: &mut LivenessValues,
|
||||
all_facts: &mut Option<AllFacts>,
|
||||
location_table: &LocationTable,
|
||||
body: &Body<'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
) {
|
||||
let mut cg = ConstraintGeneration {
|
||||
borrow_set,
|
||||
infcx,
|
||||
liveness_constraints,
|
||||
location_table,
|
||||
all_facts,
|
||||
body,
|
||||
};
|
||||
|
||||
for (bb, data) in body.basic_blocks.iter_enumerated() {
|
||||
cg.visit_basic_block_data(bb, data);
|
||||
}
|
||||
}
|
||||
|
||||
/// 'cg = the duration of the constraint generation process itself.
|
||||
struct ConstraintGeneration<'cg, 'tcx> {
|
||||
infcx: &'cg InferCtxt<'tcx>,
|
||||
all_facts: &'cg mut Option<AllFacts>,
|
||||
location_table: &'cg LocationTable,
|
||||
liveness_constraints: &'cg mut LivenessValues,
|
||||
borrow_set: &'cg BorrowSet<'tcx>,
|
||||
body: &'cg Body<'tcx>,
|
||||
}
|
||||
|
||||
impl<'cg, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'tcx> {
|
||||
/// We sometimes have `args` within an rvalue, or within a
|
||||
/// call. Make them live at the location where they appear.
|
||||
fn visit_args(&mut self, args: &GenericArgsRef<'tcx>, location: Location) {
|
||||
self.add_regular_live_constraint(*args, location);
|
||||
self.super_args(args);
|
||||
}
|
||||
|
||||
/// We sometimes have `region` within an rvalue, or within a
|
||||
/// call. Make them live at the location where they appear.
|
||||
fn visit_region(&mut self, region: ty::Region<'tcx>, location: Location) {
|
||||
self.add_regular_live_constraint(region, location);
|
||||
self.super_region(region);
|
||||
}
|
||||
|
||||
/// We sometimes have `ty` within an rvalue, or within a
|
||||
/// call. Make them live at the location where they appear.
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>, ty_context: TyContext) {
|
||||
match ty_context {
|
||||
TyContext::ReturnTy(SourceInfo { span, .. })
|
||||
| TyContext::YieldTy(SourceInfo { span, .. })
|
||||
| TyContext::UserTy(span)
|
||||
| TyContext::LocalDecl { source_info: SourceInfo { span, .. }, .. } => {
|
||||
span_bug!(span, "should not be visiting outside of the CFG: {:?}", ty_context);
|
||||
}
|
||||
TyContext::Location(location) => {
|
||||
self.add_regular_live_constraint(ty, location);
|
||||
}
|
||||
}
|
||||
|
||||
self.super_ty(ty);
|
||||
}
|
||||
|
||||
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
|
||||
if let Some(all_facts) = self.all_facts {
|
||||
let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation");
|
||||
all_facts.cfg_edge.push((
|
||||
self.location_table.start_index(location),
|
||||
self.location_table.mid_index(location),
|
||||
));
|
||||
|
||||
all_facts.cfg_edge.push((
|
||||
self.location_table.mid_index(location),
|
||||
self.location_table.start_index(location.successor_within_block()),
|
||||
));
|
||||
|
||||
// If there are borrows on this now dead local, we need to record them as `killed`.
|
||||
if let StatementKind::StorageDead(local) = statement.kind {
|
||||
record_killed_borrows_for_local(
|
||||
all_facts,
|
||||
self.borrow_set,
|
||||
self.location_table,
|
||||
local,
|
||||
location,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self.super_statement(statement, location);
|
||||
}
|
||||
|
||||
fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
|
||||
// When we see `X = ...`, then kill borrows of
|
||||
// `(*X).foo` and so forth.
|
||||
self.record_killed_borrows_for_place(*place, location);
|
||||
|
||||
self.super_assign(place, rvalue, location);
|
||||
}
|
||||
|
||||
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
|
||||
if let Some(all_facts) = self.all_facts {
|
||||
let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation");
|
||||
all_facts.cfg_edge.push((
|
||||
self.location_table.start_index(location),
|
||||
self.location_table.mid_index(location),
|
||||
));
|
||||
|
||||
let successor_blocks = terminator.successors();
|
||||
all_facts.cfg_edge.reserve(successor_blocks.size_hint().0);
|
||||
for successor_block in successor_blocks {
|
||||
all_facts.cfg_edge.push((
|
||||
self.location_table.mid_index(location),
|
||||
self.location_table.start_index(successor_block.start_location()),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// A `Call` terminator's return value can be a local which has borrows,
|
||||
// so we need to record those as `killed` as well.
|
||||
if let TerminatorKind::Call { destination, .. } = terminator.kind {
|
||||
self.record_killed_borrows_for_place(destination, location);
|
||||
}
|
||||
|
||||
self.super_terminator(terminator, location);
|
||||
}
|
||||
|
||||
fn visit_ascribe_user_ty(
|
||||
&mut self,
|
||||
_place: &Place<'tcx>,
|
||||
_variance: ty::Variance,
|
||||
_user_ty: &UserTypeProjection,
|
||||
_location: Location,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> ConstraintGeneration<'cx, 'tcx> {
|
||||
/// Some variable with type `live_ty` is "regular live" at
|
||||
/// `location` -- i.e., it may be used later. This means that all
|
||||
/// regions appearing in the type `live_ty` must be live at
|
||||
/// `location`.
|
||||
fn add_regular_live_constraint<T>(&mut self, live_ty: T, location: Location)
|
||||
where
|
||||
T: TypeVisitable<TyCtxt<'tcx>>,
|
||||
{
|
||||
debug!("add_regular_live_constraint(live_ty={:?}, location={:?})", live_ty, location);
|
||||
|
||||
self.infcx.tcx.for_each_free_region(&live_ty, |live_region| {
|
||||
let vid = live_region.as_var();
|
||||
self.liveness_constraints.add_location(vid, location);
|
||||
});
|
||||
}
|
||||
|
||||
/// When recording facts for Polonius, records the borrows on the specified place
|
||||
/// as `killed`. For example, when assigning to a local, or on a call's return destination.
|
||||
fn record_killed_borrows_for_place(&mut self, place: Place<'tcx>, location: Location) {
|
||||
if let Some(all_facts) = self.all_facts {
|
||||
let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation");
|
||||
|
||||
// Depending on the `Place` we're killing:
|
||||
// - if it's a local, or a single deref of a local,
|
||||
// we kill all the borrows on the local.
|
||||
// - if it's a deeper projection, we have to filter which
|
||||
// of the borrows are killed: the ones whose `borrowed_place`
|
||||
// conflicts with the `place`.
|
||||
match place.as_ref() {
|
||||
PlaceRef { local, projection: &[] }
|
||||
| PlaceRef { local, projection: &[ProjectionElem::Deref] } => {
|
||||
debug!(
|
||||
"Recording `killed` facts for borrows of local={:?} at location={:?}",
|
||||
local, location
|
||||
);
|
||||
|
||||
record_killed_borrows_for_local(
|
||||
all_facts,
|
||||
self.borrow_set,
|
||||
self.location_table,
|
||||
local,
|
||||
location,
|
||||
);
|
||||
}
|
||||
|
||||
PlaceRef { local, projection: &[.., _] } => {
|
||||
// Kill conflicting borrows of the innermost local.
|
||||
debug!(
|
||||
"Recording `killed` facts for borrows of \
|
||||
innermost projected local={:?} at location={:?}",
|
||||
local, location
|
||||
);
|
||||
|
||||
if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) {
|
||||
for &borrow_index in borrow_indices {
|
||||
let places_conflict = places_conflict::places_conflict(
|
||||
self.infcx.tcx,
|
||||
self.body,
|
||||
self.borrow_set[borrow_index].borrowed_place,
|
||||
place,
|
||||
places_conflict::PlaceConflictBias::NoOverlap,
|
||||
);
|
||||
|
||||
if places_conflict {
|
||||
let location_index = self.location_table.mid_index(location);
|
||||
all_facts.loan_killed_at.push((borrow_index, location_index));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// When recording facts for Polonius, records the borrows on the specified local as `killed`.
|
||||
fn record_killed_borrows_for_local(
|
||||
all_facts: &mut AllFacts,
|
||||
borrow_set: &BorrowSet<'_>,
|
||||
location_table: &LocationTable,
|
||||
local: Local,
|
||||
location: Location,
|
||||
) {
|
||||
if let Some(borrow_indices) = borrow_set.local_map.get(&local) {
|
||||
all_facts.loan_killed_at.reserve(borrow_indices.len());
|
||||
for &borrow_index in borrow_indices {
|
||||
let location_index = location_table.mid_index(location);
|
||||
all_facts.loan_killed_at.push((borrow_index, location_index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -432,7 +432,8 @@ impl<'mir, 'tcx> Borrows<'mir, 'tcx> {
|
|||
|
||||
assert_eq!(
|
||||
borrows_out_of_scope_at_location, polonius_prec.loans_out_of_scope_at_location,
|
||||
"the loans out of scope must be the same as the borrows out of scope"
|
||||
"polonius loan scopes differ from NLL borrow scopes, for body {:?}",
|
||||
body.span,
|
||||
);
|
||||
|
||||
borrows_out_of_scope_at_location = polonius_prec.loans_out_of_scope_at_location;
|
||||
|
|
|
|||
|
|
@ -385,7 +385,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
|
|||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
// We generally shouldn't have errors here because the query was
|
||||
// already run, but there's no point using `delay_span_bug`
|
||||
// already run, but there's no point using `span_delayed_bug`
|
||||
// when we're going to emit an error here anyway.
|
||||
let _errors = ocx.select_all_or_error();
|
||||
let region_constraints = ocx.infcx.with_region_constraints(|r| r.clone());
|
||||
|
|
|
|||
|
|
@ -1135,7 +1135,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
});
|
||||
} else {
|
||||
issued_spans.var_subdiag(
|
||||
Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic),
|
||||
Some(self.infcx.tcx.sess.diagnostic()),
|
||||
&mut err,
|
||||
Some(issued_borrow.kind),
|
||||
|kind, var_span| {
|
||||
|
|
@ -1152,7 +1152,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
);
|
||||
|
||||
borrow_spans.var_subdiag(
|
||||
Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic),
|
||||
Some(self.infcx.tcx.sess.diagnostic()),
|
||||
&mut err,
|
||||
Some(gen_borrow_kind),
|
||||
|kind, var_span| {
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
let did = did.expect_local();
|
||||
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
|
||||
diag.eager_subdiagnostic(
|
||||
&self.infcx.tcx.sess.parse_sess.span_diagnostic,
|
||||
self.infcx.tcx.sess.diagnostic(),
|
||||
OnClosureNote::InvokedTwice {
|
||||
place_name: &ty::place_to_string_for_capture(
|
||||
self.infcx.tcx,
|
||||
|
|
@ -146,7 +146,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
let did = did.expect_local();
|
||||
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
|
||||
diag.eager_subdiagnostic(
|
||||
&self.infcx.tcx.sess.parse_sess.span_diagnostic,
|
||||
self.infcx.tcx.sess.diagnostic(),
|
||||
OnClosureNote::MovedTwice {
|
||||
place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place),
|
||||
span: *span,
|
||||
|
|
@ -1119,7 +1119,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
&& self.infcx.can_eq(self.param_env, ty, self_ty)
|
||||
{
|
||||
err.eager_subdiagnostic(
|
||||
&self.infcx.tcx.sess.parse_sess.span_diagnostic,
|
||||
self.infcx.tcx.sess.diagnostic(),
|
||||
CaptureReasonSuggest::FreshReborrow {
|
||||
span: move_span.shrink_to_hi(),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ impl<'tcx> RegionErrors<'tcx> {
|
|||
#[track_caller]
|
||||
pub fn push(&mut self, val: impl Into<RegionErrorKind<'tcx>>) {
|
||||
let val = val.into();
|
||||
self.1.sess.delay_span_bug(DUMMY_SP, format!("{val:?}"));
|
||||
self.1.sess.span_delayed_bug(DUMMY_SP, format!("{val:?}"));
|
||||
self.0.push(val);
|
||||
}
|
||||
pub fn is_empty(&self) -> bool {
|
||||
|
|
|
|||
|
|
@ -619,8 +619,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
_,
|
||||
) => {
|
||||
// HIR lowering sometimes doesn't catch this in erroneous
|
||||
// programs, so we need to use delay_span_bug here. See #82126.
|
||||
self.infcx.tcx.sess.delay_span_bug(
|
||||
// programs, so we need to use span_delayed_bug here. See #82126.
|
||||
self.infcx.tcx.sess.span_delayed_bug(
|
||||
hir_arg.span(),
|
||||
format!("unmatched arg and hir arg: found {kind:?} vs {hir_arg:?}"),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -65,19 +65,18 @@ use self::path_utils::*;
|
|||
|
||||
pub mod borrow_set;
|
||||
mod borrowck_errors;
|
||||
mod constraint_generation;
|
||||
mod constraints;
|
||||
mod dataflow;
|
||||
mod def_use;
|
||||
mod diagnostics;
|
||||
mod facts;
|
||||
mod invalidation;
|
||||
mod location;
|
||||
mod member_constraints;
|
||||
mod nll;
|
||||
mod path_utils;
|
||||
mod place_ext;
|
||||
mod places_conflict;
|
||||
mod polonius;
|
||||
mod prefixes;
|
||||
mod region_infer;
|
||||
mod renumber;
|
||||
|
|
@ -195,8 +194,7 @@ fn do_mir_borrowck<'tcx>(
|
|||
nll::replace_regions_in_mir(&infcx, param_env, &mut body_owned, &mut promoted);
|
||||
let body = &body_owned; // no further changes
|
||||
|
||||
let location_table_owned = LocationTable::new(body);
|
||||
let location_table = &location_table_owned;
|
||||
let location_table = LocationTable::new(body);
|
||||
|
||||
let move_data = MoveData::gather_moves(body, tcx, param_env, |_| true);
|
||||
let promoted_move_data = promoted
|
||||
|
|
@ -228,7 +226,7 @@ fn do_mir_borrowck<'tcx>(
|
|||
free_regions,
|
||||
body,
|
||||
&promoted,
|
||||
location_table,
|
||||
&location_table,
|
||||
param_env,
|
||||
&mut flow_inits,
|
||||
&mdpe.move_data,
|
||||
|
|
@ -292,7 +290,7 @@ fn do_mir_borrowck<'tcx>(
|
|||
param_env,
|
||||
body: promoted_body,
|
||||
move_data: &move_data,
|
||||
location_table, // no need to create a real one for the promoted, it is not used
|
||||
location_table: &location_table, // no need to create a real one for the promoted, it is not used
|
||||
movable_coroutine,
|
||||
fn_self_span_reported: Default::default(),
|
||||
locals_are_invalidated_at_exit,
|
||||
|
|
@ -333,7 +331,7 @@ fn do_mir_borrowck<'tcx>(
|
|||
param_env,
|
||||
body,
|
||||
move_data: &mdpe.move_data,
|
||||
location_table,
|
||||
location_table: &location_table,
|
||||
movable_coroutine,
|
||||
locals_are_invalidated_at_exit,
|
||||
fn_self_span_reported: Default::default(),
|
||||
|
|
@ -435,7 +433,7 @@ fn do_mir_borrowck<'tcx>(
|
|||
promoted,
|
||||
borrow_set,
|
||||
region_inference_context: regioncx,
|
||||
location_table: polonius_input.as_ref().map(|_| location_table_owned),
|
||||
location_table: polonius_input.as_ref().map(|_| location_table),
|
||||
input_facts: polonius_input,
|
||||
output_facts,
|
||||
}))
|
||||
|
|
@ -1020,9 +1018,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
flow_state: &Flows<'cx, 'tcx>,
|
||||
) -> bool {
|
||||
let mut error_reported = false;
|
||||
let tcx = self.infcx.tcx;
|
||||
let body = self.body;
|
||||
let borrow_set = self.borrow_set.clone();
|
||||
let borrow_set = Rc::clone(&self.borrow_set);
|
||||
|
||||
// Use polonius output if it has been enabled.
|
||||
let mut polonius_output;
|
||||
|
|
@ -1039,8 +1035,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
|
||||
each_borrow_involving_path(
|
||||
self,
|
||||
tcx,
|
||||
body,
|
||||
self.infcx.tcx,
|
||||
self.body,
|
||||
location,
|
||||
(sd, place_span.0),
|
||||
&borrow_set,
|
||||
|
|
@ -2134,11 +2130,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
&& !self.has_buffered_errors()
|
||||
{
|
||||
// rust-lang/rust#46908: In pure NLL mode this code path should be
|
||||
// unreachable, but we use `delay_span_bug` because we can hit this when
|
||||
// unreachable, but we use `span_delayed_bug` because we can hit this when
|
||||
// dereferencing a non-Copy raw pointer *and* have `-Ztreat-err-as-bug`
|
||||
// enabled. We don't want to ICE for that case, as other errors will have
|
||||
// been emitted (#52262).
|
||||
self.infcx.tcx.sess.delay_span_bug(
|
||||
self.infcx.tcx.sess.span_delayed_bug(
|
||||
span,
|
||||
format!(
|
||||
"Accessing `{place:?}` with the kind `{kind:?}` shouldn't be possible",
|
||||
|
|
@ -2432,7 +2428,7 @@ mod error {
|
|||
|
||||
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorGuaranteed>) {
|
||||
if let None = self.tainted_by_errors {
|
||||
self.tainted_by_errors = Some(self.tcx.sess.delay_span_bug(
|
||||
self.tainted_by_errors = Some(self.tcx.sess.span_delayed_bug(
|
||||
t.span.clone_ignoring_labels(),
|
||||
"diagnostic buffered but not emitted",
|
||||
))
|
||||
|
|
|
|||
|
|
@ -2,16 +2,17 @@
|
|||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
//! The entry point of the NLL borrow checker.
|
||||
|
||||
use polonius_engine::{Algorithm, Output};
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_index::IndexSlice;
|
||||
use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere};
|
||||
use rustc_middle::mir::{
|
||||
Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted,
|
||||
START_BLOCK,
|
||||
};
|
||||
use rustc_middle::mir::{Body, ClosureOutlivesSubject, ClosureRegionRequirements, Promoted};
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt};
|
||||
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
||||
use rustc_mir_dataflow::move_paths::MoveData;
|
||||
use rustc_mir_dataflow::ResultsCursor;
|
||||
use rustc_span::symbol::sym;
|
||||
use std::env;
|
||||
use std::io;
|
||||
|
|
@ -19,20 +20,13 @@ use std::path::PathBuf;
|
|||
use std::rc::Rc;
|
||||
use std::str::FromStr;
|
||||
|
||||
use polonius_engine::{Algorithm, Output};
|
||||
|
||||
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
||||
use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData};
|
||||
use rustc_mir_dataflow::ResultsCursor;
|
||||
|
||||
use crate::{
|
||||
borrow_set::BorrowSet,
|
||||
constraint_generation,
|
||||
consumers::ConsumerOptions,
|
||||
diagnostics::RegionErrors,
|
||||
facts::{AllFacts, AllFactsExt, RustcFacts},
|
||||
invalidation,
|
||||
location::LocationTable,
|
||||
polonius,
|
||||
region_infer::{values::RegionValueElements, RegionInferenceContext},
|
||||
renumber,
|
||||
type_check::{self, MirTypeckRegionConstraints, MirTypeckResults},
|
||||
|
|
@ -78,81 +72,6 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
|
|||
universal_regions
|
||||
}
|
||||
|
||||
// This function populates an AllFacts instance with base facts related to
|
||||
// MovePaths and needed for the move analysis.
|
||||
fn populate_polonius_move_facts(
|
||||
all_facts: &mut AllFacts,
|
||||
move_data: &MoveData<'_>,
|
||||
location_table: &LocationTable,
|
||||
body: &Body<'_>,
|
||||
) {
|
||||
all_facts
|
||||
.path_is_var
|
||||
.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(l, r)| (r, l)));
|
||||
|
||||
for (child, move_path) in move_data.move_paths.iter_enumerated() {
|
||||
if let Some(parent) = move_path.parent {
|
||||
all_facts.child_path.push((child, parent));
|
||||
}
|
||||
}
|
||||
|
||||
let fn_entry_start =
|
||||
location_table.start_index(Location { block: START_BLOCK, statement_index: 0 });
|
||||
|
||||
// initialized_at
|
||||
for init in move_data.inits.iter() {
|
||||
match init.location {
|
||||
InitLocation::Statement(location) => {
|
||||
let block_data = &body[location.block];
|
||||
let is_terminator = location.statement_index == block_data.statements.len();
|
||||
|
||||
if is_terminator && init.kind == InitKind::NonPanicPathOnly {
|
||||
// We are at the terminator of an init that has a panic path,
|
||||
// and where the init should not happen on panic
|
||||
|
||||
for successor in block_data.terminator().successors() {
|
||||
if body[successor].is_cleanup {
|
||||
continue;
|
||||
}
|
||||
|
||||
// The initialization happened in (or rather, when arriving at)
|
||||
// the successors, but not in the unwind block.
|
||||
let first_statement = Location { block: successor, statement_index: 0 };
|
||||
all_facts
|
||||
.path_assigned_at_base
|
||||
.push((init.path, location_table.start_index(first_statement)));
|
||||
}
|
||||
} else {
|
||||
// In all other cases, the initialization just happens at the
|
||||
// midpoint, like any other effect.
|
||||
all_facts
|
||||
.path_assigned_at_base
|
||||
.push((init.path, location_table.mid_index(location)));
|
||||
}
|
||||
}
|
||||
// Arguments are initialized on function entry
|
||||
InitLocation::Argument(local) => {
|
||||
assert!(body.local_kind(local) == LocalKind::Arg);
|
||||
all_facts.path_assigned_at_base.push((init.path, fn_entry_start));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (local, path) in move_data.rev_lookup.iter_locals_enumerated() {
|
||||
if body.local_kind(local) != LocalKind::Arg {
|
||||
// Non-arguments start out deinitialised; we simulate this with an
|
||||
// initial move:
|
||||
all_facts.path_moved_at_base.push((path, fn_entry_start));
|
||||
}
|
||||
}
|
||||
|
||||
// moved_out_at
|
||||
// deinitialisation is assumed to always happen!
|
||||
all_facts
|
||||
.path_moved_at_base
|
||||
.extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source))));
|
||||
}
|
||||
|
||||
/// Computes the (non-lexical) regions from the input MIR.
|
||||
///
|
||||
/// This may result in errors being reported.
|
||||
|
|
@ -182,67 +101,23 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
|||
let elements = &Rc::new(RegionValueElements::new(body));
|
||||
|
||||
// Run the MIR type-checker.
|
||||
let MirTypeckResults {
|
||||
constraints,
|
||||
universal_region_relations,
|
||||
opaque_type_values,
|
||||
live_loans,
|
||||
} = type_check::type_check(
|
||||
infcx,
|
||||
param_env,
|
||||
body,
|
||||
promoted,
|
||||
&universal_regions,
|
||||
location_table,
|
||||
borrow_set,
|
||||
&mut all_facts,
|
||||
flow_inits,
|
||||
move_data,
|
||||
elements,
|
||||
upvars,
|
||||
polonius_input,
|
||||
);
|
||||
|
||||
if let Some(all_facts) = &mut all_facts {
|
||||
let _prof_timer = infcx.tcx.prof.generic_activity("polonius_fact_generation");
|
||||
all_facts.universal_region.extend(universal_regions.universal_regions());
|
||||
populate_polonius_move_facts(all_facts, move_data, location_table, body);
|
||||
|
||||
// Emit universal regions facts, and their relations, for Polonius.
|
||||
//
|
||||
// 1: universal regions are modeled in Polonius as a pair:
|
||||
// - the universal region vid itself.
|
||||
// - a "placeholder loan" associated to this universal region. Since they don't exist in
|
||||
// the `borrow_set`, their `BorrowIndex` are synthesized as the universal region index
|
||||
// added to the existing number of loans, as if they succeeded them in the set.
|
||||
//
|
||||
let borrow_count = borrow_set.len();
|
||||
debug!(
|
||||
"compute_regions: polonius placeholders, num_universals={}, borrow_count={}",
|
||||
universal_regions.len(),
|
||||
borrow_count
|
||||
let MirTypeckResults { constraints, universal_region_relations, opaque_type_values } =
|
||||
type_check::type_check(
|
||||
infcx,
|
||||
param_env,
|
||||
body,
|
||||
promoted,
|
||||
&universal_regions,
|
||||
location_table,
|
||||
borrow_set,
|
||||
&mut all_facts,
|
||||
flow_inits,
|
||||
move_data,
|
||||
elements,
|
||||
upvars,
|
||||
polonius_input,
|
||||
);
|
||||
|
||||
for universal_region in universal_regions.universal_regions() {
|
||||
let universal_region_idx = universal_region.index();
|
||||
let placeholder_loan_idx = borrow_count + universal_region_idx;
|
||||
all_facts.placeholder.push((universal_region, placeholder_loan_idx.into()));
|
||||
}
|
||||
|
||||
// 2: the universal region relations `outlives` constraints are emitted as
|
||||
// `known_placeholder_subset` facts.
|
||||
for (fr1, fr2) in universal_region_relations.known_outlives() {
|
||||
if fr1 != fr2 {
|
||||
debug!(
|
||||
"compute_regions: emitting polonius `known_placeholder_subset` \
|
||||
fr1={:?}, fr2={:?}",
|
||||
fr1, fr2
|
||||
);
|
||||
all_facts.known_placeholder_subset.push((fr1, fr2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create the region inference context, taking ownership of the
|
||||
// region inference data that was contained in `infcx`, and the
|
||||
// base constraints generated by the type-check.
|
||||
|
|
@ -250,7 +125,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
|||
let MirTypeckRegionConstraints {
|
||||
placeholder_indices,
|
||||
placeholder_index_to_region: _,
|
||||
mut liveness_constraints,
|
||||
liveness_constraints,
|
||||
outlives_constraints,
|
||||
member_constraints,
|
||||
universe_causes,
|
||||
|
|
@ -258,13 +133,16 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
|||
} = constraints;
|
||||
let placeholder_indices = Rc::new(placeholder_indices);
|
||||
|
||||
constraint_generation::generate_constraints(
|
||||
infcx,
|
||||
&mut liveness_constraints,
|
||||
// If requested, emit legacy polonius facts.
|
||||
polonius::emit_facts(
|
||||
&mut all_facts,
|
||||
infcx.tcx,
|
||||
location_table,
|
||||
body,
|
||||
borrow_set,
|
||||
move_data,
|
||||
&universal_regions,
|
||||
&universal_region_relations,
|
||||
);
|
||||
|
||||
let mut regioncx = RegionInferenceContext::new(
|
||||
|
|
@ -279,17 +157,12 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
|||
type_tests,
|
||||
liveness_constraints,
|
||||
elements,
|
||||
live_loans,
|
||||
);
|
||||
|
||||
// Generate various additional constraints.
|
||||
invalidation::generate_invalidates(infcx.tcx, &mut all_facts, location_table, body, borrow_set);
|
||||
|
||||
let def_id = body.source.def_id();
|
||||
|
||||
// Dump facts if requested.
|
||||
// If requested: dump NLL facts, and run legacy polonius analysis.
|
||||
let polonius_output = all_facts.as_ref().and_then(|all_facts| {
|
||||
if infcx.tcx.sess.opts.unstable_opts.nll_facts {
|
||||
let def_id = body.source.def_id();
|
||||
let def_path = infcx.tcx.def_path(def_id);
|
||||
let dir_path = PathBuf::from(&infcx.tcx.sess.opts.unstable_opts.nll_facts_dir)
|
||||
.join(def_path.to_filename_friendly_no_crate());
|
||||
|
|
@ -314,7 +187,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
|||
|
||||
if !nll_errors.is_empty() {
|
||||
// Suppress unhelpful extra errors in `infer_opaque_types`.
|
||||
infcx.set_tainted_by_errors(infcx.tcx.sess.delay_span_bug(
|
||||
infcx.set_tainted_by_errors(infcx.tcx.sess.span_delayed_bug(
|
||||
body.span,
|
||||
"`compute_regions` tainted `infcx` with errors but did not emit any errors",
|
||||
));
|
||||
|
|
@ -407,7 +280,7 @@ pub(super) fn dump_annotation<'tcx>(
|
|||
|
||||
let def_span = tcx.def_span(body.source.def_id());
|
||||
let mut err = if let Some(closure_region_requirements) = closure_region_requirements {
|
||||
let mut err = tcx.sess.diagnostic().span_note_diag(def_span, "external requirements");
|
||||
let mut err = tcx.sess.diagnostic().struct_span_note(def_span, "external requirements");
|
||||
|
||||
regioncx.annotate(tcx, &mut err);
|
||||
|
||||
|
|
@ -426,7 +299,7 @@ pub(super) fn dump_annotation<'tcx>(
|
|||
|
||||
err
|
||||
} else {
|
||||
let mut err = tcx.sess.diagnostic().span_note_diag(def_span, "no external requirements");
|
||||
let mut err = tcx.sess.diagnostic().struct_span_note(def_span, "no external requirements");
|
||||
regioncx.annotate(tcx, &mut err);
|
||||
|
||||
err
|
||||
|
|
|
|||
|
|
@ -14,34 +14,21 @@ use crate::{
|
|||
ReadOrWrite, Reservation, Shallow, Write, WriteKind,
|
||||
};
|
||||
|
||||
pub(super) fn generate_invalidates<'tcx>(
|
||||
/// Emit `loan_invalidated_at` facts.
|
||||
pub(super) fn emit_loan_invalidations<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
all_facts: &mut Option<AllFacts>,
|
||||
all_facts: &mut AllFacts,
|
||||
location_table: &LocationTable,
|
||||
body: &Body<'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
) {
|
||||
if all_facts.is_none() {
|
||||
// Nothing to do if we don't have any facts
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(all_facts) = all_facts {
|
||||
let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation");
|
||||
let dominators = body.basic_blocks.dominators();
|
||||
let mut ig = InvalidationGenerator {
|
||||
all_facts,
|
||||
borrow_set,
|
||||
tcx,
|
||||
location_table,
|
||||
body: body,
|
||||
dominators,
|
||||
};
|
||||
ig.visit_body(body);
|
||||
}
|
||||
let dominators = body.basic_blocks.dominators();
|
||||
let mut visitor =
|
||||
LoanInvalidationsGenerator { all_facts, borrow_set, tcx, location_table, body, dominators };
|
||||
visitor.visit_body(body);
|
||||
}
|
||||
|
||||
struct InvalidationGenerator<'cx, 'tcx> {
|
||||
struct LoanInvalidationsGenerator<'cx, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
all_facts: &'cx mut AllFacts,
|
||||
location_table: &'cx LocationTable,
|
||||
|
|
@ -52,7 +39,7 @@ struct InvalidationGenerator<'cx, 'tcx> {
|
|||
|
||||
/// Visits the whole MIR and generates `invalidates()` facts.
|
||||
/// Most of the code implementing this was stolen from `borrow_check/mod.rs`.
|
||||
impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
|
||||
impl<'cx, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'cx, 'tcx> {
|
||||
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
|
||||
self.check_activations(location);
|
||||
|
||||
|
|
@ -214,7 +201,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
|
||||
impl<'cx, 'tcx> LoanInvalidationsGenerator<'cx, 'tcx> {
|
||||
/// Simulates mutation of a place.
|
||||
fn mutate_place(&mut self, location: Location, place: Place<'tcx>, kind: AccessDepth) {
|
||||
self.access_place(
|
||||
|
|
@ -348,20 +335,16 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
|
|||
rw: ReadOrWrite,
|
||||
) {
|
||||
debug!(
|
||||
"invalidation::check_access_for_conflict(location={:?}, place={:?}, sd={:?}, \
|
||||
rw={:?})",
|
||||
"check_access_for_conflict(location={:?}, place={:?}, sd={:?}, rw={:?})",
|
||||
location, place, sd, rw,
|
||||
);
|
||||
let tcx = self.tcx;
|
||||
let body = self.body;
|
||||
let borrow_set = self.borrow_set;
|
||||
each_borrow_involving_path(
|
||||
self,
|
||||
tcx,
|
||||
body,
|
||||
self.tcx,
|
||||
self.body,
|
||||
location,
|
||||
(sd, place),
|
||||
borrow_set,
|
||||
self.borrow_set,
|
||||
|_| true,
|
||||
|this, borrow_index, borrow| {
|
||||
match (rw, borrow.kind) {
|
||||
147
compiler/rustc_borrowck/src/polonius/loan_kills.rs
Normal file
147
compiler/rustc_borrowck/src/polonius/loan_kills.rs
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
use rustc_middle::mir::visit::Visitor;
|
||||
use rustc_middle::mir::{
|
||||
Body, Local, Location, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind,
|
||||
Terminator, TerminatorKind,
|
||||
};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
||||
use crate::{borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, places_conflict};
|
||||
|
||||
/// Emit `loan_killed_at` and `cfg_edge` facts at the same time.
|
||||
pub(super) fn emit_loan_kills<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
all_facts: &mut AllFacts,
|
||||
location_table: &LocationTable,
|
||||
body: &Body<'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
) {
|
||||
let mut visitor = LoanKillsGenerator { borrow_set, tcx, location_table, all_facts, body };
|
||||
for (bb, data) in body.basic_blocks.iter_enumerated() {
|
||||
visitor.visit_basic_block_data(bb, data);
|
||||
}
|
||||
}
|
||||
|
||||
struct LoanKillsGenerator<'cx, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
all_facts: &'cx mut AllFacts,
|
||||
location_table: &'cx LocationTable,
|
||||
borrow_set: &'cx BorrowSet<'tcx>,
|
||||
body: &'cx Body<'tcx>,
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> Visitor<'tcx> for LoanKillsGenerator<'cx, 'tcx> {
|
||||
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
|
||||
// Also record CFG facts here.
|
||||
self.all_facts.cfg_edge.push((
|
||||
self.location_table.start_index(location),
|
||||
self.location_table.mid_index(location),
|
||||
));
|
||||
|
||||
self.all_facts.cfg_edge.push((
|
||||
self.location_table.mid_index(location),
|
||||
self.location_table.start_index(location.successor_within_block()),
|
||||
));
|
||||
|
||||
// If there are borrows on this now dead local, we need to record them as `killed`.
|
||||
if let StatementKind::StorageDead(local) = statement.kind {
|
||||
self.record_killed_borrows_for_local(local, location);
|
||||
}
|
||||
|
||||
self.super_statement(statement, location);
|
||||
}
|
||||
|
||||
fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
|
||||
// When we see `X = ...`, then kill borrows of
|
||||
// `(*X).foo` and so forth.
|
||||
self.record_killed_borrows_for_place(*place, location);
|
||||
self.super_assign(place, rvalue, location);
|
||||
}
|
||||
|
||||
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
|
||||
// Also record CFG facts here.
|
||||
self.all_facts.cfg_edge.push((
|
||||
self.location_table.start_index(location),
|
||||
self.location_table.mid_index(location),
|
||||
));
|
||||
|
||||
let successor_blocks = terminator.successors();
|
||||
self.all_facts.cfg_edge.reserve(successor_blocks.size_hint().0);
|
||||
for successor_block in successor_blocks {
|
||||
self.all_facts.cfg_edge.push((
|
||||
self.location_table.mid_index(location),
|
||||
self.location_table.start_index(successor_block.start_location()),
|
||||
));
|
||||
}
|
||||
|
||||
// A `Call` terminator's return value can be a local which has borrows,
|
||||
// so we need to record those as `killed` as well.
|
||||
if let TerminatorKind::Call { destination, .. } = terminator.kind {
|
||||
self.record_killed_borrows_for_place(destination, location);
|
||||
}
|
||||
|
||||
self.super_terminator(terminator, location);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> LoanKillsGenerator<'_, 'tcx> {
|
||||
/// Records the borrows on the specified place as `killed`. For example, when assigning to a
|
||||
/// local, or on a call's return destination.
|
||||
fn record_killed_borrows_for_place(&mut self, place: Place<'tcx>, location: Location) {
|
||||
// Depending on the `Place` we're killing:
|
||||
// - if it's a local, or a single deref of a local,
|
||||
// we kill all the borrows on the local.
|
||||
// - if it's a deeper projection, we have to filter which
|
||||
// of the borrows are killed: the ones whose `borrowed_place`
|
||||
// conflicts with the `place`.
|
||||
match place.as_ref() {
|
||||
PlaceRef { local, projection: &[] }
|
||||
| PlaceRef { local, projection: &[ProjectionElem::Deref] } => {
|
||||
debug!(
|
||||
"Recording `killed` facts for borrows of local={:?} at location={:?}",
|
||||
local, location
|
||||
);
|
||||
|
||||
self.record_killed_borrows_for_local(local, location);
|
||||
}
|
||||
|
||||
PlaceRef { local, projection: &[.., _] } => {
|
||||
// Kill conflicting borrows of the innermost local.
|
||||
debug!(
|
||||
"Recording `killed` facts for borrows of \
|
||||
innermost projected local={:?} at location={:?}",
|
||||
local, location
|
||||
);
|
||||
|
||||
if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) {
|
||||
for &borrow_index in borrow_indices {
|
||||
let places_conflict = places_conflict::places_conflict(
|
||||
self.tcx,
|
||||
self.body,
|
||||
self.borrow_set[borrow_index].borrowed_place,
|
||||
place,
|
||||
places_conflict::PlaceConflictBias::NoOverlap,
|
||||
);
|
||||
|
||||
if places_conflict {
|
||||
let location_index = self.location_table.mid_index(location);
|
||||
self.all_facts.loan_killed_at.push((borrow_index, location_index));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Records the borrows on the specified local as `killed`.
|
||||
fn record_killed_borrows_for_local(&mut self, local: Local, location: Location) {
|
||||
if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) {
|
||||
let location_index = self.location_table.mid_index(location);
|
||||
self.all_facts.loan_killed_at.reserve(borrow_indices.len());
|
||||
for &borrow_index in borrow_indices {
|
||||
self.all_facts.loan_killed_at.push((borrow_index, location_index));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
188
compiler/rustc_borrowck/src/polonius/mod.rs
Normal file
188
compiler/rustc_borrowck/src/polonius/mod.rs
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
//! Functions dedicated to fact generation for the `-Zpolonius=legacy` datalog implementation.
|
||||
//!
|
||||
//! Will be removed in the future, once the in-tree `-Zpolonius=next` implementation reaches feature
|
||||
//! parity.
|
||||
|
||||
use rustc_middle::mir::{Body, LocalKind, Location, START_BLOCK};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData};
|
||||
|
||||
use crate::borrow_set::BorrowSet;
|
||||
use crate::facts::AllFacts;
|
||||
use crate::location::LocationTable;
|
||||
use crate::type_check::free_region_relations::UniversalRegionRelations;
|
||||
use crate::universal_regions::UniversalRegions;
|
||||
|
||||
mod loan_invalidations;
|
||||
mod loan_kills;
|
||||
|
||||
/// When requested, emit most of the facts needed by polonius:
|
||||
/// - moves and assignments
|
||||
/// - universal regions and their relations
|
||||
/// - CFG points and edges
|
||||
/// - loan kills
|
||||
/// - loan invalidations
|
||||
///
|
||||
/// The rest of the facts are emitted during typeck and liveness.
|
||||
pub(crate) fn emit_facts<'tcx>(
|
||||
all_facts: &mut Option<AllFacts>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
location_table: &LocationTable,
|
||||
body: &Body<'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
move_data: &MoveData<'_>,
|
||||
universal_regions: &UniversalRegions<'_>,
|
||||
universal_region_relations: &UniversalRegionRelations<'_>,
|
||||
) {
|
||||
let Some(all_facts) = all_facts else {
|
||||
// We don't do anything if there are no facts to fill.
|
||||
return;
|
||||
};
|
||||
let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation");
|
||||
emit_move_facts(all_facts, move_data, location_table, body);
|
||||
emit_universal_region_facts(
|
||||
all_facts,
|
||||
borrow_set,
|
||||
&universal_regions,
|
||||
&universal_region_relations,
|
||||
);
|
||||
emit_cfg_and_loan_kills_facts(all_facts, tcx, location_table, body, borrow_set);
|
||||
emit_loan_invalidations_facts(all_facts, tcx, location_table, body, borrow_set);
|
||||
}
|
||||
|
||||
/// Emit facts needed for move/init analysis: moves and assignments.
|
||||
fn emit_move_facts(
|
||||
all_facts: &mut AllFacts,
|
||||
move_data: &MoveData<'_>,
|
||||
location_table: &LocationTable,
|
||||
body: &Body<'_>,
|
||||
) {
|
||||
all_facts
|
||||
.path_is_var
|
||||
.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(l, r)| (r, l)));
|
||||
|
||||
for (child, move_path) in move_data.move_paths.iter_enumerated() {
|
||||
if let Some(parent) = move_path.parent {
|
||||
all_facts.child_path.push((child, parent));
|
||||
}
|
||||
}
|
||||
|
||||
let fn_entry_start =
|
||||
location_table.start_index(Location { block: START_BLOCK, statement_index: 0 });
|
||||
|
||||
// initialized_at
|
||||
for init in move_data.inits.iter() {
|
||||
match init.location {
|
||||
InitLocation::Statement(location) => {
|
||||
let block_data = &body[location.block];
|
||||
let is_terminator = location.statement_index == block_data.statements.len();
|
||||
|
||||
if is_terminator && init.kind == InitKind::NonPanicPathOnly {
|
||||
// We are at the terminator of an init that has a panic path,
|
||||
// and where the init should not happen on panic
|
||||
|
||||
for successor in block_data.terminator().successors() {
|
||||
if body[successor].is_cleanup {
|
||||
continue;
|
||||
}
|
||||
|
||||
// The initialization happened in (or rather, when arriving at)
|
||||
// the successors, but not in the unwind block.
|
||||
let first_statement = Location { block: successor, statement_index: 0 };
|
||||
all_facts
|
||||
.path_assigned_at_base
|
||||
.push((init.path, location_table.start_index(first_statement)));
|
||||
}
|
||||
} else {
|
||||
// In all other cases, the initialization just happens at the
|
||||
// midpoint, like any other effect.
|
||||
all_facts
|
||||
.path_assigned_at_base
|
||||
.push((init.path, location_table.mid_index(location)));
|
||||
}
|
||||
}
|
||||
// Arguments are initialized on function entry
|
||||
InitLocation::Argument(local) => {
|
||||
assert!(body.local_kind(local) == LocalKind::Arg);
|
||||
all_facts.path_assigned_at_base.push((init.path, fn_entry_start));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (local, path) in move_data.rev_lookup.iter_locals_enumerated() {
|
||||
if body.local_kind(local) != LocalKind::Arg {
|
||||
// Non-arguments start out deinitialised; we simulate this with an
|
||||
// initial move:
|
||||
all_facts.path_moved_at_base.push((path, fn_entry_start));
|
||||
}
|
||||
}
|
||||
|
||||
// moved_out_at
|
||||
// deinitialisation is assumed to always happen!
|
||||
all_facts
|
||||
.path_moved_at_base
|
||||
.extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source))));
|
||||
}
|
||||
|
||||
/// Emit universal regions facts, and their relations.
|
||||
fn emit_universal_region_facts(
|
||||
all_facts: &mut AllFacts,
|
||||
borrow_set: &BorrowSet<'_>,
|
||||
universal_regions: &UniversalRegions<'_>,
|
||||
universal_region_relations: &UniversalRegionRelations<'_>,
|
||||
) {
|
||||
// 1: universal regions are modeled in Polonius as a pair:
|
||||
// - the universal region vid itself.
|
||||
// - a "placeholder loan" associated to this universal region. Since they don't exist in
|
||||
// the `borrow_set`, their `BorrowIndex` are synthesized as the universal region index
|
||||
// added to the existing number of loans, as if they succeeded them in the set.
|
||||
//
|
||||
all_facts.universal_region.extend(universal_regions.universal_regions());
|
||||
let borrow_count = borrow_set.len();
|
||||
debug!(
|
||||
"emit_universal_region_facts: polonius placeholders, num_universals={}, borrow_count={}",
|
||||
universal_regions.len(),
|
||||
borrow_count
|
||||
);
|
||||
|
||||
for universal_region in universal_regions.universal_regions() {
|
||||
let universal_region_idx = universal_region.index();
|
||||
let placeholder_loan_idx = borrow_count + universal_region_idx;
|
||||
all_facts.placeholder.push((universal_region, placeholder_loan_idx.into()));
|
||||
}
|
||||
|
||||
// 2: the universal region relations `outlives` constraints are emitted as
|
||||
// `known_placeholder_subset` facts.
|
||||
for (fr1, fr2) in universal_region_relations.known_outlives() {
|
||||
if fr1 != fr2 {
|
||||
debug!(
|
||||
"emit_universal_region_facts: emitting polonius `known_placeholder_subset` \
|
||||
fr1={:?}, fr2={:?}",
|
||||
fr1, fr2
|
||||
);
|
||||
all_facts.known_placeholder_subset.push((fr1, fr2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Emit facts about loan invalidations.
|
||||
fn emit_loan_invalidations_facts<'tcx>(
|
||||
all_facts: &mut AllFacts,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
location_table: &LocationTable,
|
||||
body: &Body<'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
) {
|
||||
loan_invalidations::emit_loan_invalidations(tcx, all_facts, location_table, body, borrow_set);
|
||||
}
|
||||
|
||||
/// Emit facts about CFG points and edges, as well as locations where loans are killed.
|
||||
fn emit_cfg_and_loan_kills_facts<'tcx>(
|
||||
all_facts: &mut AllFacts,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
location_table: &LocationTable,
|
||||
body: &Body<'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
) {
|
||||
loan_kills::emit_loan_kills(tcx, all_facts, location_table, body, borrow_set);
|
||||
}
|
||||
|
|
@ -7,7 +7,6 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
|||
use rustc_data_structures::graph::scc::Sccs;
|
||||
use rustc_errors::Diagnostic;
|
||||
use rustc_hir::def_id::CRATE_DEF_ID;
|
||||
use rustc_index::bit_set::SparseBitMatrix;
|
||||
use rustc_index::{IndexSlice, IndexVec};
|
||||
use rustc_infer::infer::outlives::test_type_match;
|
||||
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
|
||||
|
|
@ -31,8 +30,8 @@ use crate::{
|
|||
nll::PoloniusOutput,
|
||||
region_infer::reverse_sccs::ReverseSccGraph,
|
||||
region_infer::values::{
|
||||
LivenessValues, PlaceholderIndices, PointIndex, RegionElement, RegionValueElements,
|
||||
RegionValues, ToElementIndex,
|
||||
LivenessValues, PlaceholderIndices, RegionElement, RegionValueElements, RegionValues,
|
||||
ToElementIndex,
|
||||
},
|
||||
type_check::{free_region_relations::UniversalRegionRelations, Locations},
|
||||
universal_regions::UniversalRegions,
|
||||
|
|
@ -120,9 +119,6 @@ pub struct RegionInferenceContext<'tcx> {
|
|||
/// Information about how the universally quantified regions in
|
||||
/// scope on this function relate to one another.
|
||||
universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
|
||||
|
||||
/// The set of loans that are live at a given point in the CFG, when using `-Zpolonius=next`.
|
||||
live_loans: SparseBitMatrix<PointIndex, BorrowIndex>,
|
||||
}
|
||||
|
||||
/// Each time that `apply_member_constraint` is successful, it appends
|
||||
|
|
@ -335,7 +331,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
type_tests: Vec<TypeTest<'tcx>>,
|
||||
liveness_constraints: LivenessValues,
|
||||
elements: &Rc<RegionValueElements>,
|
||||
live_loans: SparseBitMatrix<PointIndex, BorrowIndex>,
|
||||
) -> Self {
|
||||
debug!("universal_regions: {:#?}", universal_regions);
|
||||
debug!("outlives constraints: {:#?}", outlives_constraints);
|
||||
|
|
@ -389,7 +384,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
type_tests,
|
||||
universal_regions,
|
||||
universal_region_relations,
|
||||
live_loans,
|
||||
};
|
||||
|
||||
result.init_free_and_bound_regions();
|
||||
|
|
@ -2325,7 +2319,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
/// Note: for now, the sets of live loans is only available when using `-Zpolonius=next`.
|
||||
pub(crate) fn is_loan_live_at(&self, loan_idx: BorrowIndex, location: Location) -> bool {
|
||||
let point = self.liveness_constraints.point_from_location(location);
|
||||
self.live_loans.contains(point, loan_idx)
|
||||
self.liveness_constraints.is_loan_live_at(loan_idx, point)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ use rustc_middle::ty::{self, RegionVid};
|
|||
use std::fmt::Debug;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::dataflow::BorrowIndex;
|
||||
|
||||
/// Maps between a `Location` and a `PointIndex` (and vice versa).
|
||||
pub(crate) struct RegionValueElements {
|
||||
/// For each basic block, how many points are contained within?
|
||||
|
|
@ -120,14 +122,45 @@ pub(crate) enum RegionElement {
|
|||
/// Records the CFG locations where each region is live. When we initially compute liveness, we use
|
||||
/// an interval matrix storing liveness ranges for each region-vid.
|
||||
pub(crate) struct LivenessValues {
|
||||
/// The map from locations to points.
|
||||
elements: Rc<RegionValueElements>,
|
||||
|
||||
/// For each region: the points where it is live.
|
||||
points: SparseIntervalMatrix<RegionVid, PointIndex>,
|
||||
|
||||
/// When using `-Zpolonius=next`, for each point: the loans flowing into the live regions at
|
||||
/// that point.
|
||||
pub(crate) loans: Option<LiveLoans>,
|
||||
}
|
||||
|
||||
/// Data used to compute the loans that are live at a given point in the CFG, when using
|
||||
/// `-Zpolonius=next`.
|
||||
pub(crate) struct LiveLoans {
|
||||
/// The set of loans that flow into a given region. When individual regions are marked as live
|
||||
/// in the CFG, these inflowing loans are recorded as live.
|
||||
pub(crate) inflowing_loans: SparseBitMatrix<RegionVid, BorrowIndex>,
|
||||
|
||||
/// The set of loans that are live at a given point in the CFG.
|
||||
pub(crate) live_loans: SparseBitMatrix<PointIndex, BorrowIndex>,
|
||||
}
|
||||
|
||||
impl LiveLoans {
|
||||
pub(crate) fn new(num_loans: usize) -> Self {
|
||||
LiveLoans {
|
||||
live_loans: SparseBitMatrix::new(num_loans),
|
||||
inflowing_loans: SparseBitMatrix::new(num_loans),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LivenessValues {
|
||||
/// Create an empty map of regions to locations where they're live.
|
||||
pub(crate) fn new(elements: Rc<RegionValueElements>) -> Self {
|
||||
Self { points: SparseIntervalMatrix::new(elements.num_points), elements }
|
||||
LivenessValues {
|
||||
points: SparseIntervalMatrix::new(elements.num_points),
|
||||
elements,
|
||||
loans: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterate through each region that has a value in this set.
|
||||
|
|
@ -140,12 +173,30 @@ impl LivenessValues {
|
|||
debug!("LivenessValues::add_location(region={:?}, location={:?})", region, location);
|
||||
let point = self.elements.point_from_location(location);
|
||||
self.points.insert(region, point);
|
||||
|
||||
// When available, record the loans flowing into this region as live at the given point.
|
||||
if let Some(loans) = self.loans.as_mut() {
|
||||
if let Some(inflowing) = loans.inflowing_loans.row(region) {
|
||||
loans.live_loans.union_row(point, inflowing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Records `region` as being live at all the given `points`.
|
||||
pub(crate) fn add_points(&mut self, region: RegionVid, points: &IntervalSet<PointIndex>) {
|
||||
debug!("LivenessValues::add_points(region={:?}, points={:?})", region, points);
|
||||
self.points.union_row(region, points);
|
||||
|
||||
// When available, record the loans flowing into this region as live at the given points.
|
||||
if let Some(loans) = self.loans.as_mut() {
|
||||
if let Some(inflowing) = loans.inflowing_loans.row(region) {
|
||||
if !inflowing.is_empty() {
|
||||
for point in points.iter() {
|
||||
loans.live_loans.union_row(point, inflowing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Records `region` as being live at all the control-flow points.
|
||||
|
|
@ -185,6 +236,15 @@ impl LivenessValues {
|
|||
pub(crate) fn point_from_location(&self, location: Location) -> PointIndex {
|
||||
self.elements.point_from_location(location)
|
||||
}
|
||||
|
||||
/// When using `-Zpolonius=next`, returns whether the `loan_idx` is live at the given `point`.
|
||||
pub(crate) fn is_loan_live_at(&self, loan_idx: BorrowIndex, point: PointIndex) -> bool {
|
||||
self.loans
|
||||
.as_ref()
|
||||
.expect("Accessing live loans requires `-Zpolonius=next`")
|
||||
.live_loans
|
||||
.contains(point, loan_idx)
|
||||
}
|
||||
}
|
||||
|
||||
/// Maps from `ty::PlaceholderRegion` values that are used in the rest of
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
if argument_index + 1 >= body.local_decls.len() {
|
||||
self.tcx()
|
||||
.sess
|
||||
.delay_span_bug(body.span, "found more normalized_input_ty than local_decls");
|
||||
.span_delayed_bug(body.span, "found more normalized_input_ty than local_decls");
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -101,10 +101,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
);
|
||||
|
||||
// We will not have a universal_regions.yield_ty if we yield (by accident)
|
||||
// outside of a coroutine and return an `impl Trait`, so emit a delay_span_bug
|
||||
// outside of a coroutine and return an `impl Trait`, so emit a span_delayed_bug
|
||||
// because we don't want to panic in an assert here if we've already got errors.
|
||||
if body.yield_ty().is_some() != universal_regions.yield_ty.is_some() {
|
||||
self.tcx().sess.delay_span_bug(
|
||||
self.tcx().sess.span_delayed_bug(
|
||||
body.span,
|
||||
format!(
|
||||
"Expected body to have yield_ty ({:?}) iff we have a UR yield_ty ({:?})",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
use itertools::{Either, Itertools};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_middle::mir::{Body, Local};
|
||||
use rustc_middle::ty::{RegionVid, TyCtxt};
|
||||
use rustc_middle::mir::visit::{TyContext, Visitor};
|
||||
use rustc_middle::mir::{Body, Local, Location, SourceInfo};
|
||||
use rustc_middle::ty::visit::TypeVisitable;
|
||||
use rustc_middle::ty::{GenericArgsRef, Region, RegionVid, Ty, TyCtxt};
|
||||
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
||||
use rustc_mir_dataflow::move_paths::MoveData;
|
||||
use rustc_mir_dataflow::ResultsCursor;
|
||||
|
|
@ -11,7 +13,7 @@ use crate::{
|
|||
constraints::OutlivesConstraintSet,
|
||||
facts::{AllFacts, AllFactsExt},
|
||||
location::LocationTable,
|
||||
region_infer::values::RegionValueElements,
|
||||
region_infer::values::{LivenessValues, RegionValueElements},
|
||||
universal_regions::UniversalRegions,
|
||||
};
|
||||
|
||||
|
|
@ -65,6 +67,14 @@ pub(super) fn generate<'mir, 'tcx>(
|
|||
boring_locals,
|
||||
polonius_drop_used,
|
||||
);
|
||||
|
||||
// Mark regions that should be live where they appear within rvalues or within a call: like
|
||||
// args, regions, and types.
|
||||
record_regular_live_regions(
|
||||
typeck.tcx(),
|
||||
&mut typeck.borrowck_context.constraints.liveness_constraints,
|
||||
body,
|
||||
);
|
||||
}
|
||||
|
||||
// The purpose of `compute_relevant_live_locals` is to define the subset of `Local`
|
||||
|
|
@ -132,3 +142,71 @@ fn regions_that_outlive_free_regions<'tcx>(
|
|||
// Return the final set of things we visited.
|
||||
outlives_free_region
|
||||
}
|
||||
|
||||
/// Some variables are "regular live" at `location` -- i.e., they may be used later. This means that
|
||||
/// all regions appearing in their type must be live at `location`.
|
||||
fn record_regular_live_regions<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
liveness_constraints: &mut LivenessValues,
|
||||
body: &Body<'tcx>,
|
||||
) {
|
||||
let mut visitor = LiveVariablesVisitor { tcx, liveness_constraints };
|
||||
for (bb, data) in body.basic_blocks.iter_enumerated() {
|
||||
visitor.visit_basic_block_data(bb, data);
|
||||
}
|
||||
}
|
||||
|
||||
/// Visitor looking for regions that should be live within rvalues or calls.
|
||||
struct LiveVariablesVisitor<'cx, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
liveness_constraints: &'cx mut LivenessValues,
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> Visitor<'tcx> for LiveVariablesVisitor<'cx, 'tcx> {
|
||||
/// We sometimes have `args` within an rvalue, or within a
|
||||
/// call. Make them live at the location where they appear.
|
||||
fn visit_args(&mut self, args: &GenericArgsRef<'tcx>, location: Location) {
|
||||
self.record_regions_live_at(*args, location);
|
||||
self.super_args(args);
|
||||
}
|
||||
|
||||
/// We sometimes have `region`s within an rvalue, or within a
|
||||
/// call. Make them live at the location where they appear.
|
||||
fn visit_region(&mut self, region: Region<'tcx>, location: Location) {
|
||||
self.record_regions_live_at(region, location);
|
||||
self.super_region(region);
|
||||
}
|
||||
|
||||
/// We sometimes have `ty`s within an rvalue, or within a
|
||||
/// call. Make them live at the location where they appear.
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>, ty_context: TyContext) {
|
||||
match ty_context {
|
||||
TyContext::ReturnTy(SourceInfo { span, .. })
|
||||
| TyContext::YieldTy(SourceInfo { span, .. })
|
||||
| TyContext::UserTy(span)
|
||||
| TyContext::LocalDecl { source_info: SourceInfo { span, .. }, .. } => {
|
||||
span_bug!(span, "should not be visiting outside of the CFG: {:?}", ty_context);
|
||||
}
|
||||
TyContext::Location(location) => {
|
||||
self.record_regions_live_at(ty, location);
|
||||
}
|
||||
}
|
||||
|
||||
self.super_ty(ty);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> LiveVariablesVisitor<'cx, 'tcx> {
|
||||
/// Some variable is "regular live" at `location` -- i.e., it may be used later. This means that
|
||||
/// all regions appearing in the type of `value` must be live at `location`.
|
||||
fn record_regions_live_at<T>(&mut self, value: T, location: Location)
|
||||
where
|
||||
T: TypeVisitable<TyCtxt<'tcx>>,
|
||||
{
|
||||
debug!("record_regions_live_at(value={:?}, location={:?})", value, location);
|
||||
self.tcx.for_each_free_region(&value, |live_region| {
|
||||
let live_region_vid = live_region.as_var();
|
||||
self.liveness_constraints.add_location(live_region_vid, location);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::graph::WithSuccessors;
|
||||
use rustc_index::bit_set::{HybridBitSet, SparseBitMatrix};
|
||||
use rustc_index::bit_set::HybridBitSet;
|
||||
use rustc_index::interval::IntervalSet;
|
||||
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
||||
use rustc_infer::infer::outlives::for_liveness;
|
||||
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
|
||||
use rustc_middle::traits::query::DropckOutlivesResult;
|
||||
use rustc_middle::ty::{RegionVid, Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
|
||||
use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
|
||||
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
|
||||
|
|
@ -16,9 +16,8 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
|||
use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex};
|
||||
use rustc_mir_dataflow::ResultsCursor;
|
||||
|
||||
use crate::dataflow::BorrowIndex;
|
||||
use crate::{
|
||||
region_infer::values::{self, PointIndex, RegionValueElements},
|
||||
region_infer::values::{self, LiveLoans, PointIndex, RegionValueElements},
|
||||
type_check::liveness::local_use_map::LocalUseMap,
|
||||
type_check::liveness::polonius,
|
||||
type_check::NormalizeLocation,
|
||||
|
|
@ -49,22 +48,17 @@ pub(super) fn trace<'mir, 'tcx>(
|
|||
boring_locals: Vec<Local>,
|
||||
polonius_drop_used: Option<Vec<(Local, Location)>>,
|
||||
) {
|
||||
debug!("trace()");
|
||||
|
||||
let local_use_map = &LocalUseMap::build(&relevant_live_locals, elements, body);
|
||||
|
||||
// When using `-Zpolonius=next`, compute the set of loans that can reach a given region.
|
||||
let num_loans = typeck.borrowck_context.borrow_set.len();
|
||||
let mut inflowing_loans = SparseBitMatrix::new(num_loans);
|
||||
if typeck.tcx().sess.opts.unstable_opts.polonius.is_next_enabled() {
|
||||
let borrowck_context = &typeck.borrowck_context;
|
||||
let borrowck_context = &mut typeck.borrowck_context;
|
||||
let borrow_set = &borrowck_context.borrow_set;
|
||||
let constraint_set = &borrowck_context.constraints.outlives_constraints;
|
||||
|
||||
let num_region_vars = typeck.infcx.num_region_vars();
|
||||
let graph = constraint_set.graph(num_region_vars);
|
||||
let mut live_loans = LiveLoans::new(borrow_set.len());
|
||||
let outlives_constraints = &borrowck_context.constraints.outlives_constraints;
|
||||
let graph = outlives_constraints.graph(typeck.infcx.num_region_vars());
|
||||
let region_graph =
|
||||
graph.region_graph(constraint_set, borrowck_context.universal_regions.fr_static);
|
||||
graph.region_graph(outlives_constraints, borrowck_context.universal_regions.fr_static);
|
||||
|
||||
// Traverse each issuing region's constraints, and record the loan as flowing into the
|
||||
// outlived region.
|
||||
|
|
@ -75,9 +69,13 @@ pub(super) fn trace<'mir, 'tcx>(
|
|||
continue;
|
||||
}
|
||||
|
||||
inflowing_loans.insert(succ, loan);
|
||||
live_loans.inflowing_loans.insert(succ, loan);
|
||||
}
|
||||
}
|
||||
|
||||
// Store the inflowing loans in the liveness constraints: they will be used to compute live
|
||||
// loans when liveness data is recorded there.
|
||||
borrowck_context.constraints.liveness_constraints.loans = Some(live_loans);
|
||||
};
|
||||
|
||||
let cx = LivenessContext {
|
||||
|
|
@ -88,7 +86,6 @@ pub(super) fn trace<'mir, 'tcx>(
|
|||
local_use_map,
|
||||
move_data,
|
||||
drop_data: FxIndexMap::default(),
|
||||
inflowing_loans,
|
||||
};
|
||||
|
||||
let mut results = LivenessResults::new(cx);
|
||||
|
|
@ -126,9 +123,6 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> {
|
|||
/// Index indicating where each variable is assigned, used, or
|
||||
/// dropped.
|
||||
local_use_map: &'me LocalUseMap,
|
||||
|
||||
/// Set of loans that flow into a given region, when using `-Zpolonius=next`.
|
||||
inflowing_loans: SparseBitMatrix<RegionVid, BorrowIndex>,
|
||||
}
|
||||
|
||||
struct DropData<'tcx> {
|
||||
|
|
@ -519,14 +513,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
|
|||
live_at: &IntervalSet<PointIndex>,
|
||||
) {
|
||||
debug!("add_use_live_facts_for(value={:?})", value);
|
||||
|
||||
Self::make_all_regions_live(
|
||||
self.elements,
|
||||
self.typeck,
|
||||
value,
|
||||
live_at,
|
||||
&self.inflowing_loans,
|
||||
);
|
||||
Self::make_all_regions_live(self.elements, self.typeck, value, live_at);
|
||||
}
|
||||
|
||||
/// Some variable with type `live_ty` is "drop live" at `location`
|
||||
|
|
@ -577,14 +564,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
|
|||
// All things in the `outlives` array may be touched by
|
||||
// the destructor and must be live at this point.
|
||||
for &kind in &drop_data.dropck_result.kinds {
|
||||
Self::make_all_regions_live(
|
||||
self.elements,
|
||||
self.typeck,
|
||||
kind,
|
||||
live_at,
|
||||
&self.inflowing_loans,
|
||||
);
|
||||
|
||||
Self::make_all_regions_live(self.elements, self.typeck, kind, live_at);
|
||||
polonius::add_drop_of_var_derefs_origin(self.typeck, dropped_local, &kind);
|
||||
}
|
||||
}
|
||||
|
|
@ -594,7 +574,6 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
|
|||
typeck: &mut TypeChecker<'_, 'tcx>,
|
||||
value: impl TypeVisitable<TyCtxt<'tcx>>,
|
||||
live_at: &IntervalSet<PointIndex>,
|
||||
inflowing_loans: &SparseBitMatrix<RegionVid, BorrowIndex>,
|
||||
) {
|
||||
debug!("make_all_regions_live(value={:?})", value);
|
||||
debug!(
|
||||
|
|
@ -602,12 +581,6 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
|
|||
values::pretty_print_points(elements, live_at.iter()),
|
||||
);
|
||||
|
||||
// When using `-Zpolonius=next`, we want to record the loans that flow into this value's
|
||||
// regions as being live at the given `live_at` points: this will be used to compute the
|
||||
// location where a loan goes out of scope.
|
||||
let num_loans = typeck.borrowck_context.borrow_set.len();
|
||||
let value_loans = &mut HybridBitSet::new_empty(num_loans);
|
||||
|
||||
value.visit_with(&mut for_liveness::FreeRegionsVisitor {
|
||||
tcx: typeck.tcx(),
|
||||
param_env: typeck.param_env,
|
||||
|
|
@ -619,21 +592,8 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
|
|||
.constraints
|
||||
.liveness_constraints
|
||||
.add_points(live_region_vid, live_at);
|
||||
|
||||
// There can only be inflowing loans for this region when we are using
|
||||
// `-Zpolonius=next`.
|
||||
if let Some(inflowing) = inflowing_loans.row(live_region_vid) {
|
||||
value_loans.union(inflowing);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// Record the loans reaching the value.
|
||||
if !value_loans.is_empty() {
|
||||
for point in live_at.iter() {
|
||||
typeck.borrowck_context.live_loans.union_row(point, value_loans);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_drop_data(
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ use rustc_hir as hir;
|
|||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_index::bit_set::SparseBitMatrix;
|
||||
use rustc_index::{IndexSlice, IndexVec};
|
||||
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
||||
use rustc_infer::infer::outlives::env::RegionBoundPairs;
|
||||
|
|
@ -51,8 +50,6 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
|||
use rustc_mir_dataflow::move_paths::MoveData;
|
||||
use rustc_mir_dataflow::ResultsCursor;
|
||||
|
||||
use crate::dataflow::BorrowIndex;
|
||||
use crate::region_infer::values::PointIndex;
|
||||
use crate::session_diagnostics::{MoveUnsized, SimdShuffleLastConst};
|
||||
use crate::{
|
||||
borrow_set::BorrowSet,
|
||||
|
|
@ -166,9 +163,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
|||
|
||||
debug!(?normalized_inputs_and_output);
|
||||
|
||||
// When using `-Zpolonius=next`, liveness will record the set of live loans per point.
|
||||
let mut live_loans = SparseBitMatrix::new(borrow_set.len());
|
||||
|
||||
let mut borrowck_context = BorrowCheckContext {
|
||||
universal_regions,
|
||||
location_table,
|
||||
|
|
@ -176,7 +170,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
|||
all_facts,
|
||||
constraints: &mut constraints,
|
||||
upvars,
|
||||
live_loans: &mut live_loans,
|
||||
};
|
||||
|
||||
let mut checker = TypeChecker::new(
|
||||
|
|
@ -232,7 +225,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
|||
let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
|
||||
trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
|
||||
if hidden_type.has_non_region_infer() {
|
||||
let reported = infcx.tcx.sess.delay_span_bug(
|
||||
let reported = infcx.tcx.sess.span_delayed_bug(
|
||||
decl.hidden_type.span,
|
||||
format!("could not resolve {:#?}", hidden_type.ty.kind()),
|
||||
);
|
||||
|
|
@ -243,7 +236,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
|||
})
|
||||
.collect();
|
||||
|
||||
MirTypeckResults { constraints, universal_region_relations, opaque_type_values, live_loans }
|
||||
MirTypeckResults { constraints, universal_region_relations, opaque_type_values }
|
||||
}
|
||||
|
||||
fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) {
|
||||
|
|
@ -274,9 +267,9 @@ fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) {
|
|||
#[track_caller]
|
||||
fn mirbug(tcx: TyCtxt<'_>, span: Span, msg: String) {
|
||||
// We sometimes see MIR failures (notably predicate failures) due to
|
||||
// the fact that we check rvalue sized predicates here. So use `delay_span_bug`
|
||||
// the fact that we check rvalue sized predicates here. So use `span_delayed_bug`
|
||||
// to avoid reporting bugs in those cases.
|
||||
tcx.sess.diagnostic().delay_span_bug(span, msg);
|
||||
tcx.sess.diagnostic().span_delayed_bug(span, msg);
|
||||
}
|
||||
|
||||
enum FieldAccessError {
|
||||
|
|
@ -858,10 +851,6 @@ struct BorrowCheckContext<'a, 'tcx> {
|
|||
borrow_set: &'a BorrowSet<'tcx>,
|
||||
pub(crate) constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
|
||||
upvars: &'a [&'a ty::CapturedPlace<'tcx>],
|
||||
|
||||
/// The set of loans that are live at a given point in the CFG, filled in by `liveness::trace`,
|
||||
/// when using `-Zpolonius=next`.
|
||||
pub(crate) live_loans: &'a mut SparseBitMatrix<PointIndex, BorrowIndex>,
|
||||
}
|
||||
|
||||
/// Holder struct for passing results from MIR typeck to the rest of the non-lexical regions
|
||||
|
|
@ -870,9 +859,6 @@ pub(crate) struct MirTypeckResults<'tcx> {
|
|||
pub(crate) constraints: MirTypeckRegionConstraints<'tcx>,
|
||||
pub(crate) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
|
||||
pub(crate) opaque_type_values: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
|
||||
|
||||
/// The set of loans that are live at a given point in the CFG, when using `-Zpolonius=next`.
|
||||
pub(crate) live_loans: SparseBitMatrix<PointIndex, BorrowIndex>,
|
||||
}
|
||||
|
||||
/// A collection of region constraints that must be satisfied for the
|
||||
|
|
@ -1082,7 +1068,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
);
|
||||
|
||||
if result.is_err() {
|
||||
self.infcx.tcx.sess.delay_span_bug(
|
||||
self.infcx.tcx.sess.span_delayed_bug(
|
||||
self.body.span,
|
||||
"failed re-defining predefined opaques in mir typeck",
|
||||
);
|
||||
|
|
|
|||
|
|
@ -31,10 +31,7 @@ pub fn expand(
|
|||
{
|
||||
(item, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
|
||||
} else {
|
||||
ecx.sess
|
||||
.parse_sess
|
||||
.span_diagnostic
|
||||
.emit_err(errors::AllocErrorMustBeFn { span: item.span() });
|
||||
ecx.sess.diagnostic().emit_err(errors::AllocErrorMustBeFn { span: item.span() });
|
||||
return vec![orig_item];
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ fn invalid_type_err(
|
|||
let snippet = cx.sess.source_map().span_to_snippet(span).ok();
|
||||
match ast::LitKind::from_token_lit(token_lit) {
|
||||
Ok(ast::LitKind::CStr(_, _)) => {
|
||||
// FIXME(c_str_literals): should concatenation of C string literals
|
||||
// include the null bytes in the end?
|
||||
// Avoid ambiguity in handling of terminal `NUL` by refusing to
|
||||
// concatenate C string literals as bytes.
|
||||
cx.emit_err(errors::ConcatCStrLit { span: span });
|
||||
}
|
||||
Ok(ast::LitKind::Char(_)) => {
|
||||
|
|
|
|||
|
|
@ -34,10 +34,7 @@ pub fn expand(
|
|||
{
|
||||
(item, true, ecx.with_def_site_ctxt(ty.span))
|
||||
} else {
|
||||
ecx.sess
|
||||
.parse_sess
|
||||
.span_diagnostic
|
||||
.emit_err(errors::AllocMustStatics { span: item.span() });
|
||||
ecx.sess.diagnostic().emit_err(errors::AllocMustStatics { span: item.span() });
|
||||
return vec![orig_item];
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -389,7 +389,7 @@ pub fn expand_test_or_bench(
|
|||
}
|
||||
|
||||
fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>) {
|
||||
let diag = &cx.sess.parse_sess.span_diagnostic;
|
||||
let diag = cx.sess.diagnostic();
|
||||
let msg = "the `#[test]` attribute may only be used on a non-associated function";
|
||||
let mut err = match item.map(|i| &i.kind) {
|
||||
// These were a warning before #92959 and need to continue being that to avoid breaking
|
||||
|
|
@ -466,7 +466,7 @@ fn should_ignore_message(i: &ast::Item) -> Option<Symbol> {
|
|||
fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic {
|
||||
match attr::find_by_name(&i.attrs, sym::should_panic) {
|
||||
Some(attr) => {
|
||||
let sd = &cx.sess.parse_sess.span_diagnostic;
|
||||
let sd = cx.sess.diagnostic();
|
||||
|
||||
match attr.meta_item_list() {
|
||||
// Handle #[should_panic(expected = "foo")]
|
||||
|
|
@ -535,7 +535,7 @@ fn check_test_signature(
|
|||
f: &ast::Fn,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic);
|
||||
let sd = &cx.sess.parse_sess.span_diagnostic;
|
||||
let sd = cx.sess.diagnostic();
|
||||
|
||||
if let ast::Unsafe::Yes(span) = f.sig.header.unsafety {
|
||||
return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" }));
|
||||
|
|
@ -579,7 +579,7 @@ fn check_bench_signature(
|
|||
// N.B., inadequate check, but we're running
|
||||
// well before resolve, can't get too deep.
|
||||
if f.sig.decl.inputs.len() != 1 {
|
||||
return Err(cx.sess.parse_sess.span_diagnostic.emit_err(errors::BenchSig { span: i.span }));
|
||||
return Err(cx.sess.diagnostic().emit_err(errors::BenchSig { span: i.span }));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ use std::ffi::{CStr, CString};
|
|||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::iter;
|
||||
use std::mem::ManuallyDrop;
|
||||
use std::path::Path;
|
||||
use std::slice;
|
||||
use std::sync::Arc;
|
||||
|
|
@ -734,7 +735,7 @@ pub unsafe fn optimize_thin_module(
|
|||
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
|
||||
let llmod_raw = parse_module(llcx, module_name, thin_module.data(), &diag_handler)? as *const _;
|
||||
let mut module = ModuleCodegen {
|
||||
module_llvm: ModuleLlvm { llmod_raw, llcx, tm },
|
||||
module_llvm: ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) },
|
||||
name: thin_module.name().to_string(),
|
||||
kind: ModuleKind::Regular,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -571,7 +571,6 @@ pub(crate) unsafe fn llvm_optimize(
|
|||
unroll_loops,
|
||||
config.vectorize_slp,
|
||||
config.vectorize_loop,
|
||||
config.no_builtins,
|
||||
config.emit_lifetime_markers,
|
||||
sanitizer_options.as_ref(),
|
||||
pgo_gen_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
||||
|
|
@ -686,7 +685,6 @@ pub(crate) unsafe fn codegen(
|
|||
unsafe fn with_codegen<'ll, F, R>(
|
||||
tm: &'ll llvm::TargetMachine,
|
||||
llmod: &'ll llvm::Module,
|
||||
no_builtins: bool,
|
||||
f: F,
|
||||
) -> R
|
||||
where
|
||||
|
|
@ -694,7 +692,7 @@ pub(crate) unsafe fn codegen(
|
|||
{
|
||||
let cpm = llvm::LLVMCreatePassManager();
|
||||
llvm::LLVMAddAnalysisPasses(tm, cpm);
|
||||
llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
|
||||
llvm::LLVMRustAddLibraryInfo(cpm, llmod);
|
||||
f(cpm)
|
||||
}
|
||||
|
||||
|
|
@ -797,7 +795,7 @@ pub(crate) unsafe fn codegen(
|
|||
} else {
|
||||
llmod
|
||||
};
|
||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||
with_codegen(tm, llmod, |cpm| {
|
||||
write_output_file(
|
||||
diag_handler,
|
||||
tm,
|
||||
|
|
@ -832,7 +830,7 @@ pub(crate) unsafe fn codegen(
|
|||
(_, SplitDwarfKind::Split) => Some(dwo_out.as_path()),
|
||||
};
|
||||
|
||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||
with_codegen(tm, llmod, |cpm| {
|
||||
write_output_file(
|
||||
diag_handler,
|
||||
tm,
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ use rustc_span::symbol::Symbol;
|
|||
use std::any::Any;
|
||||
use std::ffi::CStr;
|
||||
use std::io::Write;
|
||||
use std::mem::ManuallyDrop;
|
||||
|
||||
mod back {
|
||||
pub mod archive;
|
||||
|
|
@ -407,8 +408,9 @@ pub struct ModuleLlvm {
|
|||
llcx: &'static mut llvm::Context,
|
||||
llmod_raw: *const llvm::Module,
|
||||
|
||||
// independent from llcx and llmod_raw, resources get disposed by drop impl
|
||||
tm: OwnedTargetMachine,
|
||||
// This field is `ManuallyDrop` because it is important that the `TargetMachine`
|
||||
// is disposed prior to the `Context` being disposed otherwise UAFs can occur.
|
||||
tm: ManuallyDrop<OwnedTargetMachine>,
|
||||
}
|
||||
|
||||
unsafe impl Send for ModuleLlvm {}
|
||||
|
|
@ -419,7 +421,11 @@ impl ModuleLlvm {
|
|||
unsafe {
|
||||
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
|
||||
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
|
||||
ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx, mod_name) }
|
||||
ModuleLlvm {
|
||||
llmod_raw,
|
||||
llcx,
|
||||
tm: ManuallyDrop::new(create_target_machine(tcx, mod_name)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -427,7 +433,11 @@ impl ModuleLlvm {
|
|||
unsafe {
|
||||
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
|
||||
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
|
||||
ModuleLlvm { llmod_raw, llcx, tm: create_informational_target_machine(tcx.sess) }
|
||||
ModuleLlvm {
|
||||
llmod_raw,
|
||||
llcx,
|
||||
tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -448,7 +458,7 @@ impl ModuleLlvm {
|
|||
}
|
||||
};
|
||||
|
||||
Ok(ModuleLlvm { llmod_raw, llcx, tm })
|
||||
Ok(ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -460,6 +470,7 @@ impl ModuleLlvm {
|
|||
impl Drop for ModuleLlvm {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ManuallyDrop::drop(&mut self.tm);
|
||||
llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2163,13 +2163,8 @@ extern "C" {
|
|||
ArgsCstrBuff: *const c_char,
|
||||
ArgsCstrBuffLen: usize,
|
||||
) -> *mut TargetMachine;
|
||||
|
||||
pub fn LLVMRustDisposeTargetMachine(T: *mut TargetMachine);
|
||||
pub fn LLVMRustAddLibraryInfo<'a>(
|
||||
PM: &PassManager<'a>,
|
||||
M: &'a Module,
|
||||
DisableSimplifyLibCalls: bool,
|
||||
);
|
||||
pub fn LLVMRustAddLibraryInfo<'a>(PM: &PassManager<'a>, M: &'a Module);
|
||||
pub fn LLVMRustWriteOutputFile<'a>(
|
||||
T: &'a TargetMachine,
|
||||
PM: &PassManager<'a>,
|
||||
|
|
@ -2191,7 +2186,6 @@ extern "C" {
|
|||
UnrollLoops: bool,
|
||||
SLPVectorize: bool,
|
||||
LoopVectorize: bool,
|
||||
DisableSimplifyLibCalls: bool,
|
||||
EmitLifetimeMarkers: bool,
|
||||
SanitizerOptions: Option<&SanitizerOptions>,
|
||||
PGOGenPath: *const c_char,
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ pub fn link_binary<'a>(
|
|||
}
|
||||
}
|
||||
if sess.opts.json_artifact_notifications {
|
||||
sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename, "link");
|
||||
sess.diagnostic().emit_artifact_notification(&out_filename, "link");
|
||||
}
|
||||
|
||||
if sess.prof.enabled() {
|
||||
|
|
@ -270,8 +270,14 @@ pub fn each_linked_rlib(
|
|||
|
||||
for &cnum in crates {
|
||||
match fmts.get(cnum.as_usize() - 1) {
|
||||
Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue,
|
||||
Some(_) => {}
|
||||
Some(&Linkage::NotLinked | &Linkage::Dynamic) => continue,
|
||||
Some(&Linkage::IncludedFromDylib) => {
|
||||
// We always link crate `compiler_builtins` statically. When enabling LTO, we include it as well.
|
||||
if info.compiler_builtins != Some(cnum) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Some(&Linkage::Static) => {}
|
||||
None => return Err(errors::LinkRlibError::MissingFormat),
|
||||
}
|
||||
let crate_name = info.crate_name[&cnum];
|
||||
|
|
@ -520,8 +526,7 @@ fn link_staticlib<'a>(
|
|||
&codegen_results.crate_info,
|
||||
Some(CrateType::Staticlib),
|
||||
&mut |cnum, path| {
|
||||
let lto = are_upstream_rust_objects_already_included(sess)
|
||||
&& !ignored_for_lto(sess, &codegen_results.crate_info, cnum);
|
||||
let lto = are_upstream_rust_objects_already_included(sess);
|
||||
|
||||
let native_libs = codegen_results.crate_info.native_libraries[&cnum].iter();
|
||||
let relevant = native_libs.clone().filter(|lib| relevant_lib(sess, lib));
|
||||
|
|
@ -1256,24 +1261,6 @@ fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns a boolean indicating whether the specified crate should be ignored
|
||||
/// during LTO.
|
||||
///
|
||||
/// Crates ignored during LTO are not lumped together in the "massive object
|
||||
/// file" that we create and are linked in their normal rlib states. See
|
||||
/// comments below for what crates do not participate in LTO.
|
||||
///
|
||||
/// It's unusual for a crate to not participate in LTO. Typically only
|
||||
/// compiler-specific and unstable crates have a reason to not participate in
|
||||
/// LTO.
|
||||
pub fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool {
|
||||
// If our target enables builtin function lowering in LLVM then the
|
||||
// crates providing these functions don't participate in LTO (e.g.
|
||||
// no_builtins or compiler builtins crates).
|
||||
!sess.target.no_builtins
|
||||
&& (info.compiler_builtins == Some(cnum) || info.is_no_builtins.contains(&cnum))
|
||||
}
|
||||
|
||||
/// This functions tries to determine the appropriate linker (and corresponding LinkerFlavor) to use
|
||||
pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
|
||||
fn infer_from(
|
||||
|
|
@ -1477,7 +1464,7 @@ fn print_native_static_libs(
|
|||
sess.emit_note(errors::StaticLibraryNativeArtifacts);
|
||||
// Prefix for greppability
|
||||
// Note: This must not be translated as tools are allowed to depend on this exact string.
|
||||
sess.note_without_error(format!("native-static-libs: {}", &lib_args.join(" ")));
|
||||
sess.note(format!("native-static-libs: {}", &lib_args.join(" ")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2739,10 +2726,6 @@ fn rehome_sysroot_lib_dir<'a>(sess: &'a Session, lib_dir: &Path) -> PathBuf {
|
|||
// symbols). We must continue to include the rest of the rlib, however, as
|
||||
// it may contain static native libraries which must be linked in.
|
||||
//
|
||||
// (*) Crates marked with `#![no_builtins]` don't participate in LTO and
|
||||
// their bytecode wasn't included. The object files in those libraries must
|
||||
// still be passed to the linker.
|
||||
//
|
||||
// Note, however, that if we're not doing LTO we can just pass the rlib
|
||||
// blindly to the linker (fast) because it's fine if it's not actually
|
||||
// included as we're at the end of the dependency chain.
|
||||
|
|
@ -2768,9 +2751,7 @@ fn add_static_crate<'a>(
|
|||
cmd.link_rlib(&rlib_path);
|
||||
};
|
||||
|
||||
if !are_upstream_rust_objects_already_included(sess)
|
||||
|| ignored_for_lto(sess, &codegen_results.crate_info, cnum)
|
||||
{
|
||||
if !are_upstream_rust_objects_already_included(sess) {
|
||||
link_upstream(cratepath);
|
||||
return;
|
||||
}
|
||||
|
|
@ -2784,8 +2765,6 @@ fn add_static_crate<'a>(
|
|||
let canonical_name = name.replace('-', "_");
|
||||
let upstream_rust_objects_already_included =
|
||||
are_upstream_rust_objects_already_included(sess);
|
||||
let is_builtins =
|
||||
sess.target.no_builtins || !codegen_results.crate_info.is_no_builtins.contains(&cnum);
|
||||
|
||||
let mut archive = archive_builder_builder.new_archive_builder(sess);
|
||||
if let Err(error) = archive.add_archive(
|
||||
|
|
@ -2802,9 +2781,8 @@ fn add_static_crate<'a>(
|
|||
|
||||
// If we're performing LTO and this is a rust-generated object
|
||||
// file, then we don't need the object file as it's part of the
|
||||
// LTO module. Note that `#![no_builtins]` is excluded from LTO,
|
||||
// though, so we let that object file slide.
|
||||
if upstream_rust_objects_already_included && is_rust_object && is_builtins {
|
||||
// LTO module.
|
||||
if upstream_rust_objects_already_included && is_rust_object {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@ use object::{
|
|||
|
||||
use rustc_data_structures::memmap::Mmap;
|
||||
use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice};
|
||||
use rustc_metadata::creader::MetadataLoader;
|
||||
use rustc_metadata::fs::METADATA_FILENAME;
|
||||
use rustc_metadata::EncodedMetadata;
|
||||
use rustc_session::cstore::MetadataLoader;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::sym;
|
||||
use rustc_target::abi::Endian;
|
||||
|
|
|
|||
|
|
@ -54,8 +54,8 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
|
|||
// export level, however, as they're just implementation details.
|
||||
// Down below we'll hardwire all of the symbols to the `Rust` export
|
||||
// level instead.
|
||||
let special_runtime_crate =
|
||||
tcx.is_panic_runtime(LOCAL_CRATE) || tcx.is_compiler_builtins(LOCAL_CRATE);
|
||||
let is_compiler_builtins = tcx.is_compiler_builtins(LOCAL_CRATE);
|
||||
let special_runtime_crate = tcx.is_panic_runtime(LOCAL_CRATE) || is_compiler_builtins;
|
||||
|
||||
let mut reachable_non_generics: DefIdMap<_> = tcx
|
||||
.reachable_set(())
|
||||
|
|
@ -107,7 +107,11 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
|
|||
.map(|def_id| {
|
||||
// We won't link right if this symbol is stripped during LTO.
|
||||
let name = tcx.symbol_name(Instance::mono(tcx, def_id.to_def_id())).name;
|
||||
let used = name == "rust_eh_personality";
|
||||
// We have to preserve the symbols of the built-in functions during LTO.
|
||||
let is_builtin_fn = is_compiler_builtins
|
||||
&& symbol_export_level(tcx, def_id.to_def_id())
|
||||
.is_below_threshold(SymbolExportLevel::C);
|
||||
let used = is_builtin_fn || name == "rust_eh_personality";
|
||||
|
||||
let export_level = if special_runtime_crate {
|
||||
SymbolExportLevel::Rust
|
||||
|
|
|
|||
|
|
@ -148,23 +148,12 @@ impl ModuleConfig {
|
|||
|
||||
let emit_obj = if !should_emit_obj {
|
||||
EmitObj::None
|
||||
} else if sess.target.obj_is_bitcode
|
||||
|| (sess.opts.cg.linker_plugin_lto.enabled() && !no_builtins)
|
||||
{
|
||||
} else if sess.target.obj_is_bitcode || sess.opts.cg.linker_plugin_lto.enabled() {
|
||||
// This case is selected if the target uses objects as bitcode, or
|
||||
// if linker plugin LTO is enabled. In the linker plugin LTO case
|
||||
// the assumption is that the final link-step will read the bitcode
|
||||
// and convert it to object code. This may be done by either the
|
||||
// native linker or rustc itself.
|
||||
//
|
||||
// Note, however, that the linker-plugin-lto requested here is
|
||||
// explicitly ignored for `#![no_builtins]` crates. These crates are
|
||||
// specifically ignored by rustc's LTO passes and wouldn't work if
|
||||
// loaded into the linker. These crates define symbols that LLVM
|
||||
// lowers intrinsics to, and these symbol dependencies aren't known
|
||||
// until after codegen. As a result any crate marked
|
||||
// `#![no_builtins]` is assumed to not participate in LTO and
|
||||
// instead goes on to generate object code.
|
||||
EmitObj::Bitcode
|
||||
} else if need_bitcode_in_object(tcx) {
|
||||
EmitObj::ObjectCode(BitcodeSection::Full)
|
||||
|
|
@ -1037,9 +1026,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
|
||||
let mut each_linked_rlib_for_lto = Vec::new();
|
||||
drop(link::each_linked_rlib(crate_info, None, &mut |cnum, path| {
|
||||
if link::ignored_for_lto(sess, crate_info, cnum) {
|
||||
return;
|
||||
}
|
||||
each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
|
||||
}));
|
||||
|
||||
|
|
@ -1870,7 +1856,7 @@ impl SharedEmitterMain {
|
|||
let mut err = match level {
|
||||
Level::Error { lint: false } => sess.struct_err(msg).forget_guarantee(),
|
||||
Level::Warning(_) => sess.struct_warn(msg),
|
||||
Level::Note => sess.struct_note_without_error(msg),
|
||||
Level::Note => sess.struct_note(msg),
|
||||
_ => bug!("Invalid inline asm diagnostic level"),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -858,7 +858,6 @@ impl CrateInfo {
|
|||
local_crate_name,
|
||||
compiler_builtins,
|
||||
profiler_runtime: None,
|
||||
is_no_builtins: Default::default(),
|
||||
native_libraries: Default::default(),
|
||||
used_libraries: tcx.native_libraries(LOCAL_CRATE).iter().map(Into::into).collect(),
|
||||
crate_name: Default::default(),
|
||||
|
|
@ -885,9 +884,6 @@ impl CrateInfo {
|
|||
if tcx.is_profiler_runtime(cnum) {
|
||||
info.profiler_runtime = Some(cnum);
|
||||
}
|
||||
if tcx.is_no_builtins(cnum) {
|
||||
info.is_no_builtins.insert(cnum);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle circular dependencies in the standard library.
|
||||
|
|
@ -895,9 +891,7 @@ impl CrateInfo {
|
|||
// If global LTO is enabled then almost everything (*) is glued into a single object file,
|
||||
// so this logic is not necessary and can cause issues on some targets (due to weak lang
|
||||
// item symbols being "privatized" to that object file), so we disable it.
|
||||
// (*) Native libs, and `#[compiler_builtins]` and `#[no_builtins]` crates are not glued,
|
||||
// and we assume that they cannot define weak lang items. This is not currently enforced
|
||||
// by the compiler, but that's ok because all this stuff is unstable anyway.
|
||||
// (*) Native libs are not glued, and we assume that they cannot define weak lang items.
|
||||
let target = &tcx.sess.target;
|
||||
if !are_upstream_rust_objects_already_included(tcx.sess) {
|
||||
let missing_weak_lang_items: FxHashSet<Symbol> = info
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
Some(tcx.fn_sig(did))
|
||||
} else {
|
||||
tcx.sess
|
||||
.delay_span_bug(attr.span, "this attribute can only be applied to functions");
|
||||
.span_delayed_bug(attr.span, "this attribute can only be applied to functions");
|
||||
None
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ extern crate tracing;
|
|||
extern crate rustc_middle;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_hir::def_id::CrateNum;
|
||||
use rustc_middle::dep_graph::WorkProduct;
|
||||
|
|
@ -157,7 +157,6 @@ pub struct CrateInfo {
|
|||
pub local_crate_name: Symbol,
|
||||
pub compiler_builtins: Option<CrateNum>,
|
||||
pub profiler_runtime: Option<CrateNum>,
|
||||
pub is_no_builtins: FxHashSet<CrateNum>,
|
||||
pub native_libraries: FxHashMap<CrateNum, Vec<NativeLib>>,
|
||||
pub crate_name: FxHashMap<CrateNum, Symbol>,
|
||||
pub used_libraries: Vec<NativeLib>,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use rustc_ast::expand::allocator::AllocatorKind;
|
|||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::sync::{DynSend, DynSync};
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_metadata::creader::MetadataLoaderDyn;
|
||||
use rustc_metadata::EncodedMetadata;
|
||||
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
||||
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout};
|
||||
|
|
@ -16,7 +17,6 @@ use rustc_middle::ty::{Ty, TyCtxt};
|
|||
use rustc_middle::util::Providers;
|
||||
use rustc_session::{
|
||||
config::{self, OutputFilenames, PrintRequest},
|
||||
cstore::MetadataLoaderDyn,
|
||||
Session,
|
||||
};
|
||||
use rustc_span::symbol::Symbol;
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ where
|
|||
let mut err = tcx.sess.create_err(err);
|
||||
|
||||
let msg = error.diagnostic_message();
|
||||
error.add_args(&tcx.sess.parse_sess.span_diagnostic, &mut err);
|
||||
error.add_args(tcx.sess.diagnostic(), &mut err);
|
||||
|
||||
// Use *our* span to label the interp error
|
||||
err.span_label(our_span, msg);
|
||||
|
|
|
|||
|
|
@ -391,7 +391,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
if ecx.tcx.is_ctfe_mir_available(def) {
|
||||
Ok(ecx.tcx.mir_for_ctfe(def))
|
||||
} else if ecx.tcx.def_kind(def) == DefKind::AssocConst {
|
||||
let guar = ecx.tcx.sess.delay_span_bug(
|
||||
let guar = ecx.tcx.sess.span_delayed_bug(
|
||||
rustc_span::DUMMY_SP,
|
||||
"This is likely a const item that is missing from its impl",
|
||||
);
|
||||
|
|
@ -622,7 +622,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
let guard = ecx
|
||||
.tcx
|
||||
.sess
|
||||
.delay_span_bug(span, "The deny lint should have already errored");
|
||||
.span_delayed_bug(span, "The deny lint should have already errored");
|
||||
throw_inval!(AlreadyReported(guard.into()));
|
||||
}
|
||||
} else if new_steps > start && new_steps.is_power_of_two() {
|
||||
|
|
|
|||
|
|
@ -437,7 +437,7 @@ pub trait ReportErrorExt {
|
|||
{
|
||||
ty::tls::with(move |tcx| {
|
||||
let mut builder = tcx.sess.struct_allow(DiagnosticMessage::Str(String::new().into()));
|
||||
let handler = &tcx.sess.parse_sess.span_diagnostic;
|
||||
let handler = tcx.sess.diagnostic();
|
||||
let message = self.diagnostic_message();
|
||||
self.add_args(handler, &mut builder);
|
||||
let s = handler.eagerly_translate_to_string(message, builder.args());
|
||||
|
|
|
|||
|
|
@ -173,6 +173,9 @@ impl<Prov: Provenance> std::fmt::Debug for LocalState<'_, Prov> {
|
|||
}
|
||||
|
||||
/// Current value of a local variable
|
||||
///
|
||||
/// This does not store the type of the local; the type is given by `body.local_decls` and can never
|
||||
/// change, so by not storing here we avoid having to maintain that as an invariant.
|
||||
#[derive(Copy, Clone, Debug)] // Miri debug-prints these
|
||||
pub(super) enum LocalValue<Prov: Provenance = AllocId> {
|
||||
/// This local is not currently alive, and cannot be used at all.
|
||||
|
|
@ -284,9 +287,9 @@ impl<'tcx> fmt::Display for FrameInfo<'tcx> {
|
|||
{
|
||||
write!(f, "inside closure")
|
||||
} else {
|
||||
// Note: this triggers a `good_path_bug` state, which means that if we ever get here
|
||||
// we must emit a diagnostic. We should never display a `FrameInfo` unless we
|
||||
// actually want to emit a warning or error to the user.
|
||||
// Note: this triggers a `good_path_delayed_bug` state, which means that if we ever
|
||||
// get here we must emit a diagnostic. We should never display a `FrameInfo` unless
|
||||
// we actually want to emit a warning or error to the user.
|
||||
write!(f, "inside `{}`", self.instance)
|
||||
}
|
||||
})
|
||||
|
|
@ -300,8 +303,8 @@ impl<'tcx> FrameInfo<'tcx> {
|
|||
errors::FrameNote { where_: "closure", span, instance: String::new(), times: 0 }
|
||||
} else {
|
||||
let instance = format!("{}", self.instance);
|
||||
// Note: this triggers a `good_path_bug` state, which means that if we ever get here
|
||||
// we must emit a diagnostic. We should never display a `FrameInfo` unless we
|
||||
// Note: this triggers a `good_path_delayed_bug` state, which means that if we ever get
|
||||
// here we must emit a diagnostic. We should never display a `FrameInfo` unless we
|
||||
// actually want to emit a warning or error to the user.
|
||||
errors::FrameNote { where_: "instance", span, instance, times: 0 }
|
||||
}
|
||||
|
|
@ -470,7 +473,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
backtrace.print_backtrace();
|
||||
// FIXME(fee1-dead), HACK: we want to use the error as title therefore we can just extract the
|
||||
// label and arguments from the InterpError.
|
||||
let handler = &self.tcx.sess.parse_sess.span_diagnostic;
|
||||
let handler = self.tcx.sess.diagnostic();
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
let mut diag = self.tcx.sess.struct_allow("");
|
||||
let msg = e.diagnostic_message();
|
||||
|
|
|
|||
|
|
@ -94,9 +94,9 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval:
|
|||
// If the pointer is dangling (neither in local nor global memory), we leave it
|
||||
// to validation to error -- it has the much better error messages, pointing out where
|
||||
// in the value the dangling reference lies.
|
||||
// The `delay_span_bug` ensures that we don't forget such a check in validation.
|
||||
// The `span_delayed_bug` ensures that we don't forget such a check in validation.
|
||||
if tcx.try_get_global_alloc(alloc_id).is_none() {
|
||||
tcx.sess.delay_span_bug(ecx.tcx.span, "tried to intern dangling pointer");
|
||||
tcx.sess.span_delayed_bug(ecx.tcx.span, "tried to intern dangling pointer");
|
||||
}
|
||||
// treat dangling pointers like other statics
|
||||
// just to stop trying to recurse into them
|
||||
|
|
@ -186,7 +186,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory
|
|||
// Validation will error (with a better message) on an invalid vtable pointer.
|
||||
// Let validation show the error message, but make sure it *does* error.
|
||||
tcx.sess
|
||||
.delay_span_bug(tcx.span, "vtables pointers cannot be integer pointers");
|
||||
.span_delayed_bug(tcx.span, "vtables pointers cannot be integer pointers");
|
||||
}
|
||||
}
|
||||
// Check if we have encountered this pointer+layout combination before.
|
||||
|
|
@ -375,7 +375,7 @@ pub fn intern_const_alloc_recursive<
|
|||
match res {
|
||||
Ok(()) => {}
|
||||
Err(error) => {
|
||||
ecx.tcx.sess.delay_span_bug(
|
||||
ecx.tcx.sess.span_delayed_bug(
|
||||
ecx.tcx.span,
|
||||
format!(
|
||||
"error during interning should later cause validation failure: {}",
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
|
|||
// `async` functions cannot be `const fn`. This is checked during AST lowering, so there's
|
||||
// no need to emit duplicate errors here.
|
||||
if self.ccx.is_async() || body.coroutine.is_some() {
|
||||
tcx.sess.delay_span_bug(body.span, "`async` functions cannot be `const fn`");
|
||||
tcx.sess.span_delayed_bug(body.span, "`async` functions cannot be `const fn`");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -357,7 +357,9 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
|
|||
|
||||
fn check_static(&mut self, def_id: DefId, span: Span) {
|
||||
if self.tcx.is_thread_local_static(def_id) {
|
||||
self.tcx.sess.delay_span_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef`");
|
||||
self.tcx
|
||||
.sess
|
||||
.span_delayed_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef`");
|
||||
}
|
||||
self.check_op_spanned(ops::StaticAccess, span)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ pub fn is_const_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
|||
None if is_parent_const_stable_trait(tcx, def_id) => {
|
||||
// Remove this when `#![feature(const_trait_impl)]` is stabilized,
|
||||
// returning `true` unconditionally.
|
||||
tcx.sess.delay_span_bug(
|
||||
tcx.sess.span_delayed_bug(
|
||||
tcx.def_span(def_id),
|
||||
"trait implementations cannot be const stable yet",
|
||||
);
|
||||
|
|
|
|||
|
|
@ -128,9 +128,9 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> {
|
|||
#[track_caller]
|
||||
fn fail(&self, location: Location, msg: impl AsRef<str>) {
|
||||
let span = self.body.source_info(location).span;
|
||||
// We use `delay_span_bug` as we might see broken MIR when other errors have already
|
||||
// We use `span_delayed_bug` as we might see broken MIR when other errors have already
|
||||
// occurred.
|
||||
self.tcx.sess.diagnostic().delay_span_bug(
|
||||
self.tcx.sess.diagnostic().span_delayed_bug(
|
||||
span,
|
||||
format!(
|
||||
"broken MIR in {:?} ({}) at {:?}:\n{}",
|
||||
|
|
@ -571,7 +571,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
|
|||
|
||||
fn visit_source_scope(&mut self, scope: SourceScope) {
|
||||
if self.body.source_scopes.get(scope).is_none() {
|
||||
self.tcx.sess.diagnostic().delay_span_bug(
|
||||
self.tcx.sess.diagnostic().span_delayed_bug(
|
||||
self.body.span,
|
||||
format!(
|
||||
"broken MIR in {:?} ({}):\ninvalid source scope {:?}",
|
||||
|
|
|
|||
|
|
@ -33,10 +33,10 @@ use rustc_feature::find_gated_cfg;
|
|||
use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
|
||||
use rustc_interface::{interface, Queries};
|
||||
use rustc_lint::unerased_lint_store;
|
||||
use rustc_metadata::creader::MetadataLoader;
|
||||
use rustc_metadata::locator;
|
||||
use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS};
|
||||
use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType, TrimmedDefPaths};
|
||||
use rustc_session::cstore::MetadataLoader;
|
||||
use rustc_session::getopts::{self, Matches};
|
||||
use rustc_session::lint::{Lint, LintId};
|
||||
use rustc_session::{config, EarlyErrorHandler, Session};
|
||||
|
|
|
|||
|
|
@ -351,18 +351,10 @@ impl<'a> DiagnosticBuilder<'a, !> {
|
|||
/// `struct_*` methods on [`Handler`].
|
||||
#[track_caller]
|
||||
pub(crate) fn new_fatal(handler: &'a Handler, message: impl Into<DiagnosticMessage>) -> Self {
|
||||
let diagnostic = Diagnostic::new_with_code(Level::Fatal, None, message);
|
||||
Self::new_diagnostic_fatal(handler, diagnostic)
|
||||
}
|
||||
|
||||
/// Creates a new `DiagnosticBuilder` with an already constructed
|
||||
/// diagnostic.
|
||||
pub(crate) fn new_diagnostic_fatal(handler: &'a Handler, diagnostic: Diagnostic) -> Self {
|
||||
debug!("Created new diagnostic");
|
||||
Self {
|
||||
inner: DiagnosticBuilderInner {
|
||||
state: DiagnosticBuilderState::Emittable(handler),
|
||||
diagnostic: Box::new(diagnostic),
|
||||
diagnostic: Box::new(Diagnostic::new_with_code(Level::Fatal, None, message)),
|
||||
},
|
||||
_marker: PhantomData,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -431,10 +431,10 @@ struct HandlerInner {
|
|||
warn_count: usize,
|
||||
deduplicated_err_count: usize,
|
||||
emitter: Box<DynEmitter>,
|
||||
delayed_span_bugs: Vec<DelayedDiagnostic>,
|
||||
delayed_good_path_bugs: Vec<DelayedDiagnostic>,
|
||||
span_delayed_bugs: Vec<DelayedDiagnostic>,
|
||||
good_path_delayed_bugs: Vec<DelayedDiagnostic>,
|
||||
/// This flag indicates that an expected diagnostic was emitted and suppressed.
|
||||
/// This is used for the `delayed_good_path_bugs` check.
|
||||
/// This is used for the `good_path_delayed_bugs` check.
|
||||
suppressed_expected_diag: bool,
|
||||
|
||||
/// This set contains the `DiagnosticId` of all emitted diagnostics to avoid
|
||||
|
|
@ -528,7 +528,7 @@ pub struct HandlerFlags {
|
|||
/// If true, immediately emit diagnostics that would otherwise be buffered.
|
||||
/// (rustc: see `-Z dont-buffer-diagnostics` and `-Z treat-err-as-bug`)
|
||||
pub dont_buffer_diagnostics: bool,
|
||||
/// If true, immediately print bugs registered with `delay_span_bug`.
|
||||
/// If true, immediately print bugs registered with `span_delayed_bug`.
|
||||
/// (rustc: see `-Z report-delayed-bugs`)
|
||||
pub report_delayed_bugs: bool,
|
||||
/// Show macro backtraces.
|
||||
|
|
@ -545,20 +545,20 @@ impl Drop for HandlerInner {
|
|||
self.emit_stashed_diagnostics();
|
||||
|
||||
if !self.has_errors() {
|
||||
let bugs = std::mem::replace(&mut self.delayed_span_bugs, Vec::new());
|
||||
self.flush_delayed(bugs, "no errors encountered even though `delay_span_bug` issued");
|
||||
let bugs = std::mem::replace(&mut self.span_delayed_bugs, Vec::new());
|
||||
self.flush_delayed(bugs, "no errors encountered even though `span_delayed_bug` issued");
|
||||
}
|
||||
|
||||
// FIXME(eddyb) this explains what `delayed_good_path_bugs` are!
|
||||
// They're `delayed_span_bugs` but for "require some diagnostic happened"
|
||||
// FIXME(eddyb) this explains what `good_path_delayed_bugs` are!
|
||||
// They're `span_delayed_bugs` but for "require some diagnostic happened"
|
||||
// instead of "require some error happened". Sadly that isn't ideal, as
|
||||
// lints can be `#[allow]`'d, potentially leading to this triggering.
|
||||
// Also, "good path" should be replaced with a better naming.
|
||||
if !self.has_any_message() && !self.suppressed_expected_diag && !std::thread::panicking() {
|
||||
let bugs = std::mem::replace(&mut self.delayed_good_path_bugs, Vec::new());
|
||||
let bugs = std::mem::replace(&mut self.good_path_delayed_bugs, Vec::new());
|
||||
self.flush_delayed(
|
||||
bugs,
|
||||
"no warnings or errors encountered even though `delayed_good_path_bugs` issued",
|
||||
"no warnings or errors encountered even though `good_path_delayed_bugs` issued",
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -609,8 +609,8 @@ impl Handler {
|
|||
deduplicated_err_count: 0,
|
||||
deduplicated_warn_count: 0,
|
||||
emitter,
|
||||
delayed_span_bugs: Vec::new(),
|
||||
delayed_good_path_bugs: Vec::new(),
|
||||
span_delayed_bugs: Vec::new(),
|
||||
good_path_delayed_bugs: Vec::new(),
|
||||
suppressed_expected_diag: false,
|
||||
taught_diagnostics: Default::default(),
|
||||
emitted_diagnostic_codes: Default::default(),
|
||||
|
|
@ -648,7 +648,7 @@ impl Handler {
|
|||
// This is here to not allow mutation of flags;
|
||||
// as of this writing it's only used in tests in librustc_middle.
|
||||
pub fn can_emit_warnings(&self) -> bool {
|
||||
self.inner.lock().flags.can_emit_warnings
|
||||
self.inner.borrow_mut().flags.can_emit_warnings
|
||||
}
|
||||
|
||||
/// Resets the diagnostic error count as well as the cached emitted diagnostics.
|
||||
|
|
@ -664,8 +664,8 @@ impl Handler {
|
|||
inner.deduplicated_warn_count = 0;
|
||||
|
||||
// actually free the underlying memory (which `clear` would not do)
|
||||
inner.delayed_span_bugs = Default::default();
|
||||
inner.delayed_good_path_bugs = Default::default();
|
||||
inner.span_delayed_bugs = Default::default();
|
||||
inner.good_path_delayed_bugs = Default::default();
|
||||
inner.taught_diagnostics = Default::default();
|
||||
inner.emitted_diagnostic_codes = Default::default();
|
||||
inner.emitted_diagnostics = Default::default();
|
||||
|
|
@ -675,14 +675,13 @@ impl Handler {
|
|||
/// Stash a given diagnostic with the given `Span` and [`StashKey`] as the key.
|
||||
/// Retrieve a stashed diagnostic with `steal_diagnostic`.
|
||||
pub fn stash_diagnostic(&self, span: Span, key: StashKey, diag: Diagnostic) {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
inner.stash((span.with_parent(None), key), diag);
|
||||
self.inner.borrow_mut().stash((span.with_parent(None), key), diag);
|
||||
}
|
||||
|
||||
/// Steal a previously stashed diagnostic with the given `Span` and [`StashKey`] as the key.
|
||||
pub fn steal_diagnostic(&self, span: Span, key: StashKey) -> Option<DiagnosticBuilder<'_, ()>> {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
inner
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.steal((span.with_parent(None), key))
|
||||
.map(|diag| DiagnosticBuilder::new_diagnostic(self, diag))
|
||||
}
|
||||
|
|
@ -927,10 +926,7 @@ impl Handler {
|
|||
/// Construct a builder at the `Note` level with the `msg`.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_note_without_error(
|
||||
&self,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, ()> {
|
||||
pub fn struct_note(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
|
||||
DiagnosticBuilder::new(self, Level::Note, msg)
|
||||
}
|
||||
|
||||
|
|
@ -970,11 +966,12 @@ impl Handler {
|
|||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) {
|
||||
) -> ErrorGuaranteed {
|
||||
self.emit_diag_at_span(
|
||||
Diagnostic::new_with_code(Error { lint: false }, Some(code), msg),
|
||||
span,
|
||||
);
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
|
|
@ -998,20 +995,20 @@ impl Handler {
|
|||
self.inner.borrow_mut().span_bug(span, msg)
|
||||
}
|
||||
|
||||
/// For documentation on this, see `Session::delay_span_bug`.
|
||||
/// For documentation on this, see `Session::span_delayed_bug`.
|
||||
#[track_caller]
|
||||
pub fn delay_span_bug(
|
||||
pub fn span_delayed_bug(
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<String>,
|
||||
) -> ErrorGuaranteed {
|
||||
self.inner.borrow_mut().delay_span_bug(span, msg)
|
||||
self.inner.borrow_mut().span_delayed_bug(span, msg)
|
||||
}
|
||||
|
||||
// FIXME(eddyb) note the comment inside `impl Drop for HandlerInner`, that's
|
||||
// where the explanation of what "good path" is (also, it should be renamed).
|
||||
pub fn delay_good_path_bug(&self, msg: impl Into<DiagnosticMessage>) {
|
||||
self.inner.borrow_mut().delay_good_path_bug(msg)
|
||||
pub fn good_path_delayed_bug(&self, msg: impl Into<DiagnosticMessage>) {
|
||||
self.inner.borrow_mut().good_path_delayed_bug(msg)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
|
|
@ -1021,17 +1018,13 @@ impl Handler {
|
|||
|
||||
#[track_caller]
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_note_without_error(
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) {
|
||||
pub fn span_note(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) {
|
||||
self.emit_diag_at_span(Diagnostic::new(Note, msg), span);
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_note_diag(
|
||||
pub fn struct_span_note(
|
||||
&self,
|
||||
span: Span,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
|
|
@ -1054,12 +1047,11 @@ impl Handler {
|
|||
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn warn(&self, msg: impl Into<DiagnosticMessage>) {
|
||||
let mut db = DiagnosticBuilder::new(self, Warning(None), msg);
|
||||
db.emit();
|
||||
DiagnosticBuilder::new(self, Warning(None), msg).emit();
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn note_without_error(&self, msg: impl Into<DiagnosticMessage>) {
|
||||
pub fn note(&self, msg: impl Into<DiagnosticMessage>) {
|
||||
DiagnosticBuilder::new(self, Note, msg).emit();
|
||||
}
|
||||
|
||||
|
|
@ -1085,8 +1077,8 @@ impl Handler {
|
|||
ErrorGuaranteed::unchecked_claim_error_was_emitted()
|
||||
})
|
||||
}
|
||||
pub fn has_errors_or_delayed_span_bugs(&self) -> Option<ErrorGuaranteed> {
|
||||
self.inner.borrow().has_errors_or_delayed_span_bugs().then(|| {
|
||||
pub fn has_errors_or_span_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
|
||||
self.inner.borrow().has_errors_or_span_delayed_bugs().then(|| {
|
||||
#[allow(deprecated)]
|
||||
ErrorGuaranteed::unchecked_claim_error_was_emitted()
|
||||
})
|
||||
|
|
@ -1204,8 +1196,7 @@ impl Handler {
|
|||
mut diag: Diagnostic,
|
||||
sp: impl Into<MultiSpan>,
|
||||
) -> Option<ErrorGuaranteed> {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
inner.emit_diagnostic(diag.set_span(sp))
|
||||
self.inner.borrow_mut().emit_diagnostic(diag.set_span(sp))
|
||||
}
|
||||
|
||||
pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
|
||||
|
|
@ -1273,9 +1264,9 @@ impl Handler {
|
|||
}
|
||||
|
||||
pub fn flush_delayed(&self) {
|
||||
let mut inner = self.inner.lock();
|
||||
let bugs = std::mem::replace(&mut inner.delayed_span_bugs, Vec::new());
|
||||
inner.flush_delayed(bugs, "no errors encountered even though `delay_span_bug` issued");
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
let bugs = std::mem::replace(&mut inner.span_delayed_bugs, Vec::new());
|
||||
inner.flush_delayed(bugs, "no errors encountered even though `span_delayed_bug` issued");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1332,11 +1323,11 @@ impl HandlerInner {
|
|||
|
||||
if diagnostic.level == Level::DelayedBug {
|
||||
// FIXME(eddyb) this should check for `has_errors` and stop pushing
|
||||
// once *any* errors were emitted (and truncate `delayed_span_bugs`
|
||||
// once *any* errors were emitted (and truncate `span_delayed_bugs`
|
||||
// when an error is first emitted, also), but maybe there's a case
|
||||
// in which that's not sound? otherwise this is really inefficient.
|
||||
let backtrace = std::backtrace::Backtrace::capture();
|
||||
self.delayed_span_bugs
|
||||
self.span_delayed_bugs
|
||||
.push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace));
|
||||
|
||||
if !self.flags.report_delayed_bugs {
|
||||
|
|
@ -1451,7 +1442,7 @@ impl HandlerInner {
|
|||
}
|
||||
|
||||
fn delayed_bug_count(&self) -> usize {
|
||||
self.delayed_span_bugs.len() + self.delayed_good_path_bugs.len()
|
||||
self.span_delayed_bugs.len() + self.good_path_delayed_bugs.len()
|
||||
}
|
||||
|
||||
fn print_error_count(&mut self, registry: &Registry) {
|
||||
|
|
@ -1502,18 +1493,18 @@ impl HandlerInner {
|
|||
error_codes.sort();
|
||||
if error_codes.len() > 1 {
|
||||
let limit = if error_codes.len() > 9 { 9 } else { error_codes.len() };
|
||||
self.failure(format!(
|
||||
self.failure_note(format!(
|
||||
"Some errors have detailed explanations: {}{}",
|
||||
error_codes[..limit].join(", "),
|
||||
if error_codes.len() > 9 { "..." } else { "." }
|
||||
));
|
||||
self.failure(format!(
|
||||
self.failure_note(format!(
|
||||
"For more information about an error, try \
|
||||
`rustc --explain {}`.",
|
||||
&error_codes[0]
|
||||
));
|
||||
} else {
|
||||
self.failure(format!(
|
||||
self.failure_note(format!(
|
||||
"For more information about this error, try \
|
||||
`rustc --explain {}`.",
|
||||
&error_codes[0]
|
||||
|
|
@ -1572,15 +1563,15 @@ impl HandlerInner {
|
|||
fn has_errors_or_lint_errors(&self) -> bool {
|
||||
self.has_errors() || self.lint_err_count > 0
|
||||
}
|
||||
fn has_errors_or_delayed_span_bugs(&self) -> bool {
|
||||
self.has_errors() || !self.delayed_span_bugs.is_empty()
|
||||
fn has_errors_or_span_delayed_bugs(&self) -> bool {
|
||||
self.has_errors() || !self.span_delayed_bugs.is_empty()
|
||||
}
|
||||
fn has_any_message(&self) -> bool {
|
||||
self.err_count() > 0 || self.lint_err_count > 0 || self.warn_count > 0
|
||||
}
|
||||
|
||||
fn is_compilation_going_to_fail(&self) -> bool {
|
||||
self.has_errors() || self.lint_err_count > 0 || !self.delayed_span_bugs.is_empty()
|
||||
self.has_errors() || self.lint_err_count > 0 || !self.span_delayed_bugs.is_empty()
|
||||
}
|
||||
|
||||
fn abort_if_errors(&mut self) {
|
||||
|
|
@ -1601,14 +1592,17 @@ impl HandlerInner {
|
|||
self.emit_diagnostic(diag.set_span(sp));
|
||||
}
|
||||
|
||||
/// For documentation on this, see `Session::delay_span_bug`.
|
||||
/// For documentation on this, see `Session::span_delayed_bug`.
|
||||
///
|
||||
/// Note: this function used to be called `delay_span_bug`. It was renamed
|
||||
/// to match similar functions like `span_bug`, `span_err`, etc.
|
||||
#[track_caller]
|
||||
fn delay_span_bug(
|
||||
fn span_delayed_bug(
|
||||
&mut self,
|
||||
sp: impl Into<MultiSpan>,
|
||||
msg: impl Into<String>,
|
||||
) -> ErrorGuaranteed {
|
||||
// This is technically `self.treat_err_as_bug()` but `delay_span_bug` is called before
|
||||
// This is technically `self.treat_err_as_bug()` but `span_delayed_bug` is called before
|
||||
// incrementing `err_count` by one, so we need to +1 the comparing.
|
||||
// FIXME: Would be nice to increment err_count in a more coherent way.
|
||||
if self.flags.treat_err_as_bug.is_some_and(|c| {
|
||||
|
|
@ -1624,16 +1618,16 @@ impl HandlerInner {
|
|||
|
||||
// FIXME(eddyb) note the comment inside `impl Drop for HandlerInner`, that's
|
||||
// where the explanation of what "good path" is (also, it should be renamed).
|
||||
fn delay_good_path_bug(&mut self, msg: impl Into<DiagnosticMessage>) {
|
||||
fn good_path_delayed_bug(&mut self, msg: impl Into<DiagnosticMessage>) {
|
||||
let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg);
|
||||
if self.flags.report_delayed_bugs {
|
||||
self.emit_diagnostic(&mut diagnostic);
|
||||
}
|
||||
let backtrace = std::backtrace::Backtrace::capture();
|
||||
self.delayed_good_path_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace));
|
||||
self.good_path_delayed_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace));
|
||||
}
|
||||
|
||||
fn failure(&mut self, msg: impl Into<DiagnosticMessage>) {
|
||||
fn failure_note(&mut self, msg: impl Into<DiagnosticMessage>) {
|
||||
self.emit_diagnostic(&mut Diagnostic::new(FailureNote, msg));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1119,7 +1119,7 @@ impl<'a> ExtCtxt<'a> {
|
|||
sp: S,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
self.sess.parse_sess.span_diagnostic.struct_span_err(sp, msg)
|
||||
self.sess.diagnostic().struct_span_err(sp, msg)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
|
|
@ -1143,15 +1143,15 @@ impl<'a> ExtCtxt<'a> {
|
|||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) {
|
||||
self.sess.parse_sess.span_diagnostic.span_err(sp, msg);
|
||||
self.sess.diagnostic().span_err(sp, msg);
|
||||
}
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) {
|
||||
self.sess.parse_sess.span_diagnostic.span_warn(sp, msg);
|
||||
self.sess.diagnostic().span_warn(sp, msg);
|
||||
}
|
||||
pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<String>) -> ! {
|
||||
self.sess.parse_sess.span_diagnostic.span_bug(sp, msg);
|
||||
self.sess.diagnostic().span_bug(sp, msg);
|
||||
}
|
||||
pub fn trace_macros_diag(&mut self) {
|
||||
for (span, notes) in self.expansions.iter() {
|
||||
|
|
@ -1165,7 +1165,7 @@ impl<'a> ExtCtxt<'a> {
|
|||
self.expansions.clear();
|
||||
}
|
||||
pub fn bug(&self, msg: &'static str) -> ! {
|
||||
self.sess.parse_sess.span_diagnostic.bug(msg);
|
||||
self.sess.diagnostic().bug(msg);
|
||||
}
|
||||
pub fn trace_macros(&self) -> bool {
|
||||
self.ecfg.trace_mac
|
||||
|
|
@ -1286,9 +1286,8 @@ pub fn expr_to_string(
|
|||
|
||||
/// Non-fatally assert that `tts` is empty. Note that this function
|
||||
/// returns even when `tts` is non-empty, macros that *need* to stop
|
||||
/// compilation should call
|
||||
/// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be
|
||||
/// done as rarely as possible).
|
||||
/// compilation should call `cx.diagnostic().abort_if_errors()`
|
||||
/// (this should be 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(errors::TakesNoArguments { span, name });
|
||||
|
|
|
|||
|
|
@ -435,7 +435,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
invocations = mem::take(&mut undetermined_invocations);
|
||||
force = !mem::replace(&mut progress, false);
|
||||
if force && self.monotonic {
|
||||
self.cx.sess.delay_span_bug(
|
||||
self.cx.sess.span_delayed_bug(
|
||||
invocations.last().unwrap().0.span(),
|
||||
"expansion entered force mode without producing any errors",
|
||||
);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ pub(super) fn failed_to_match_macro<'cx>(
|
|||
if try_success_result.is_ok() {
|
||||
// Nonterminal parser recovery might turn failed matches into successful ones,
|
||||
// but for that it must have emitted an error already
|
||||
tracker.cx.sess.delay_span_bug(sp, "Macro matching returned a success on the second try");
|
||||
tracker.cx.sess.span_delayed_bug(sp, "Macro matching returned a success on the second try");
|
||||
}
|
||||
|
||||
if let Some(result) = tracker.result {
|
||||
|
|
@ -151,7 +151,7 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx,
|
|||
Success(_) => {
|
||||
// Nonterminal parser recovery might turn failed matches into successful ones,
|
||||
// but for that it must have emitted an error already
|
||||
self.cx.sess.delay_span_bug(
|
||||
self.cx.sess.span_delayed_bug(
|
||||
self.root_span,
|
||||
"should not collect detailed info for successful macro match",
|
||||
);
|
||||
|
|
|
|||
|
|
@ -475,17 +475,14 @@ pub fn compile_declarative_macro(
|
|||
|
||||
let s = parse_failure_msg(&token);
|
||||
let sp = token.span.substitute_dummy(def.span);
|
||||
let mut err = sess.parse_sess.span_diagnostic.struct_span_err(sp, s);
|
||||
let mut err = sess.diagnostic().struct_span_err(sp, s);
|
||||
err.span_label(sp, msg);
|
||||
annotate_doc_comment(&mut err, sess.source_map(), sp);
|
||||
err.emit();
|
||||
return dummy_syn_ext();
|
||||
}
|
||||
Error(sp, msg) => {
|
||||
sess.parse_sess
|
||||
.span_diagnostic
|
||||
.struct_span_err(sp.substitute_dummy(def.span), msg)
|
||||
.emit();
|
||||
sess.diagnostic().struct_span_err(sp.substitute_dummy(def.span), msg).emit();
|
||||
return dummy_syn_ext();
|
||||
}
|
||||
ErrorReported(_) => {
|
||||
|
|
@ -514,10 +511,10 @@ pub fn compile_declarative_macro(
|
|||
valid &= check_lhs_nt_follows(&sess.parse_sess, def, &tt);
|
||||
return tt;
|
||||
}
|
||||
sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs")
|
||||
sess.diagnostic().span_bug(def.span, "wrong-structured lhs")
|
||||
})
|
||||
.collect::<Vec<mbe::TokenTree>>(),
|
||||
_ => sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs"),
|
||||
_ => sess.diagnostic().span_bug(def.span, "wrong-structured lhs"),
|
||||
};
|
||||
|
||||
let rhses = match &argument_map[&MacroRulesNormalizedIdent::new(rhs_nm)] {
|
||||
|
|
@ -536,10 +533,10 @@ pub fn compile_declarative_macro(
|
|||
.pop()
|
||||
.unwrap();
|
||||
}
|
||||
sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs")
|
||||
sess.diagnostic().span_bug(def.span, "wrong-structured rhs")
|
||||
})
|
||||
.collect::<Vec<mbe::TokenTree>>(),
|
||||
_ => sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs"),
|
||||
_ => sess.diagnostic().span_bug(def.span, "wrong-structured rhs"),
|
||||
};
|
||||
|
||||
for rhs in &rhses {
|
||||
|
|
@ -595,7 +592,7 @@ pub fn compile_declarative_macro(
|
|||
mbe::TokenTree::Delimited(_, delimited) => {
|
||||
mbe::macro_parser::compute_locs(&delimited.tts)
|
||||
}
|
||||
_ => sess.parse_sess.span_diagnostic.span_bug(def.span, "malformed macro lhs"),
|
||||
_ => sess.diagnostic().span_bug(def.span, "malformed macro lhs"),
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
|
|
@ -648,10 +645,8 @@ fn is_empty_token_tree(sess: &ParseSess, seq: &mbe::SequenceRepetition) -> bool
|
|||
iter.next();
|
||||
}
|
||||
let span = t.span.to(now.span);
|
||||
sess.span_diagnostic.span_note_without_error(
|
||||
span,
|
||||
"doc comments are ignored in matcher position",
|
||||
);
|
||||
sess.span_diagnostic
|
||||
.span_note(span, "doc comments are ignored in matcher position");
|
||||
}
|
||||
mbe::TokenTree::Sequence(_, sub_seq)
|
||||
if (sub_seq.kleene.op == mbe::KleeneOp::ZeroOrMore
|
||||
|
|
|
|||
|
|
@ -357,7 +357,7 @@ fn parse_sep_and_kleene_op<'a>(
|
|||
fn span_dollar_dollar_or_metavar_in_the_lhs_err(sess: &ParseSess, token: &Token) {
|
||||
sess.span_diagnostic
|
||||
.span_err(token.span, format!("unexpected token: {}", pprust::token_to_string(token)));
|
||||
sess.span_diagnostic.span_note_without_error(
|
||||
sess.span_diagnostic.span_note(
|
||||
token.span,
|
||||
"`$$` and meta-variable expressions are not allowed inside macro parameter definitions",
|
||||
);
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ impl MultiItemModifier for DeriveProcMacro {
|
|||
}
|
||||
};
|
||||
|
||||
let error_count_before = ecx.sess.parse_sess.span_diagnostic.err_count();
|
||||
let error_count_before = ecx.sess.diagnostic().err_count();
|
||||
let mut parser =
|
||||
rustc_parse::stream_to_parser(&ecx.sess.parse_sess, stream, Some("proc-macro derive"));
|
||||
let mut items = vec![];
|
||||
|
|
@ -179,7 +179,7 @@ impl MultiItemModifier for DeriveProcMacro {
|
|||
}
|
||||
|
||||
// fail if there have been errors emitted
|
||||
if ecx.sess.parse_sess.span_diagnostic.err_count() > error_count_before {
|
||||
if ecx.sess.diagnostic().err_count() > error_count_before {
|
||||
ecx.sess.emit_err(errors::ProcMacroDeriveTokens { span });
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,8 @@ declare_features! (
|
|||
(accepted, bindings_after_at, "1.56.0", Some(65490), None),
|
||||
/// Allows empty structs and enum variants with braces.
|
||||
(accepted, braced_empty_structs, "1.8.0", Some(29720), None),
|
||||
/// Allows `c"foo"` literals.
|
||||
(accepted, c_str_literals, "CURRENT_RUSTC_VERSION", Some(105723), None),
|
||||
/// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`.
|
||||
(accepted, cfg_attr_multi, "1.33.0", Some(54881), None),
|
||||
/// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests.
|
||||
|
|
|
|||
|
|
@ -813,7 +813,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
rustc_attr!(TEST, rustc_regions, Normal, template!(Word), WarnFollowing),
|
||||
rustc_attr!(
|
||||
TEST, rustc_error, Normal,
|
||||
template!(Word, List: "delay_span_bug_from_inside_query"), WarnFollowingWordOnly
|
||||
template!(Word, List: "span_delayed_bug_from_inside_query"), WarnFollowingWordOnly
|
||||
),
|
||||
rustc_attr!(TEST, rustc_dump_user_args, Normal, template!(Word), WarnFollowing),
|
||||
rustc_attr!(TEST, rustc_evaluate_where_clauses, Normal, template!(Word), WarnFollowing),
|
||||
|
|
|
|||
|
|
@ -354,8 +354,6 @@ declare_features! (
|
|||
(unstable, async_fn_track_caller, "1.73.0", Some(110011), None),
|
||||
/// Allows builtin # foo() syntax
|
||||
(unstable, builtin_syntax, "1.71.0", Some(110680), None),
|
||||
/// Allows `c"foo"` literals.
|
||||
(unstable, c_str_literals, "1.71.0", Some(105723), None),
|
||||
/// Treat `extern "C"` function as nounwind.
|
||||
(unstable, c_unwind, "1.52.0", Some(74990), None),
|
||||
/// Allows using C-variadics.
|
||||
|
|
@ -500,6 +498,9 @@ declare_features! (
|
|||
(incomplete, lazy_type_alias, "1.72.0", Some(112792), None),
|
||||
/// Allows `if/while p && let q = r && ...` chains.
|
||||
(unstable, let_chains, "1.37.0", Some(53667), None),
|
||||
/// Allows using `#[link(kind = "link-arg", name = "...")]`
|
||||
/// to pass custom arguments to the linker.
|
||||
(unstable, link_arg_attribute, "CURRENT_RUSTC_VERSION", Some(99427), None),
|
||||
/// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check.
|
||||
(unstable, lint_reasons, "1.31.0", Some(54503), None),
|
||||
/// Give access to additional metadata about declarative macro meta-variables.
|
||||
|
|
|
|||
|
|
@ -720,9 +720,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
// since we should have emitten an error for them earlier, and they will
|
||||
// not be well-formed!
|
||||
if polarity == ty::ImplPolarity::Negative {
|
||||
self.tcx()
|
||||
.sess
|
||||
.delay_span_bug(binding.span, "negative trait bounds should not have bindings");
|
||||
self.tcx().sess.span_delayed_bug(
|
||||
binding.span,
|
||||
"negative trait bounds should not have bindings",
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1419,7 +1420,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
// trait reference.
|
||||
let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else {
|
||||
// A cycle error occurred, most likely.
|
||||
let guar = tcx.sess.delay_span_bug(span, "expected cycle error");
|
||||
let guar = tcx.sess.span_delayed_bug(span, "expected cycle error");
|
||||
return Err(guar);
|
||||
};
|
||||
|
||||
|
|
@ -2376,7 +2377,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
let e = self
|
||||
.tcx()
|
||||
.sess
|
||||
.delay_span_bug(path.span, "path with `Res::Err` but no error emitted");
|
||||
.span_delayed_bug(path.span, "path with `Res::Err` but no error emitted");
|
||||
self.set_tainted_by_errors(e);
|
||||
Ty::new_error(self.tcx(), e)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -325,7 +325,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
false
|
||||
});
|
||||
if references_self {
|
||||
let guar = tcx.sess.delay_span_bug(
|
||||
let guar = tcx.sess.span_delayed_bug(
|
||||
span,
|
||||
"trait object projection bounds reference `Self`",
|
||||
);
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
|
|||
for field in &def.non_enum_variant().fields {
|
||||
let Ok(field_ty) = tcx.try_normalize_erasing_regions(param_env, field.ty(tcx, args))
|
||||
else {
|
||||
tcx.sess.delay_span_bug(span, "could not normalize field type");
|
||||
tcx.sess.span_delayed_bug(span, "could not normalize field type");
|
||||
continue;
|
||||
};
|
||||
|
||||
|
|
@ -151,7 +151,8 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
|
|||
return false;
|
||||
} else if field_ty.needs_drop(tcx, param_env) {
|
||||
// This should never happen. But we can get here e.g. in case of name resolution errors.
|
||||
tcx.sess.delay_span_bug(span, "we should never accept maybe-dropping union fields");
|
||||
tcx.sess
|
||||
.span_delayed_bug(span, "we should never accept maybe-dropping union fields");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -181,7 +182,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
}
|
||||
// Generic statics are rejected, but we still reach this case.
|
||||
Err(e) => {
|
||||
tcx.sess.delay_span_bug(span, format!("{e:?}"));
|
||||
tcx.sess.span_delayed_bug(span, format!("{e:?}"));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
|
@ -204,7 +205,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
|
||||
let item = tcx.hir().item(id);
|
||||
let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else {
|
||||
tcx.sess.delay_span_bug(item.span, "expected opaque item");
|
||||
tcx.sess.span_delayed_bug(item.span, "expected opaque item");
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
@ -313,7 +314,7 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||
Ok(()) => {}
|
||||
Err(ty_err) => {
|
||||
let ty_err = ty_err.to_string(tcx);
|
||||
return Err(tcx.sess.delay_span_bug(
|
||||
return Err(tcx.sess.span_delayed_bug(
|
||||
span,
|
||||
format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"),
|
||||
));
|
||||
|
|
@ -655,7 +656,7 @@ pub(super) fn check_specialization_validity<'tcx>(
|
|||
if !tcx.is_impl_trait_in_trait(impl_item) {
|
||||
report_forbidden_specialization(tcx, impl_item, parent_impl);
|
||||
} else {
|
||||
tcx.sess.delay_span_bug(
|
||||
tcx.sess.span_delayed_bug(
|
||||
DUMMY_SP,
|
||||
format!("parent item: {parent_impl:?} not marked as default"),
|
||||
);
|
||||
|
|
@ -703,7 +704,7 @@ fn check_impl_items_against_trait<'tcx>(
|
|||
tcx.associated_item(trait_item_id)
|
||||
} else {
|
||||
// Checked in `associated_item`.
|
||||
tcx.sess.delay_span_bug(tcx.def_span(impl_item), "missing associated item in trait");
|
||||
tcx.sess.span_delayed_bug(tcx.def_span(impl_item), "missing associated item in trait");
|
||||
continue;
|
||||
};
|
||||
match ty_impl_item.kind {
|
||||
|
|
|
|||
|
|
@ -439,7 +439,7 @@ fn compare_method_predicate_entailment<'tcx>(
|
|||
}
|
||||
return Err(tcx
|
||||
.sess
|
||||
.delay_span_bug(rustc_span::DUMMY_SP, "error should have been emitted"));
|
||||
.span_delayed_bug(rustc_span::DUMMY_SP, "error should have been emitted"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -937,7 +937,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||
remapped_types.insert(def_id, ty::EarlyBinder::bind(ty));
|
||||
}
|
||||
Err(err) => {
|
||||
let reported = tcx.sess.delay_span_bug(
|
||||
let reported = tcx.sess.span_delayed_bug(
|
||||
return_span,
|
||||
format!("could not fully resolve: {ty} => {err:?}"),
|
||||
);
|
||||
|
|
@ -1114,7 +1114,9 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
|
|||
.note(format!("hidden type inferred to be `{}`", self.ty))
|
||||
.emit()
|
||||
}
|
||||
_ => self.tcx.sess.delay_span_bug(DUMMY_SP, "should've been able to remap region"),
|
||||
_ => {
|
||||
self.tcx.sess.span_delayed_bug(DUMMY_SP, "should've been able to remap region")
|
||||
}
|
||||
};
|
||||
return Err(guar);
|
||||
};
|
||||
|
|
@ -1473,7 +1475,7 @@ fn compare_number_of_generics<'tcx>(
|
|||
// inheriting the generics from will also have mismatched arguments, and
|
||||
// we'll report an error for that instead. Delay a bug for safety, though.
|
||||
if trait_.is_impl_trait_in_trait() {
|
||||
return Err(tcx.sess.delay_span_bug(
|
||||
return Err(tcx.sess.span_delayed_bug(
|
||||
rustc_span::DUMMY_SP,
|
||||
"errors comparing numbers of generics of trait/impl functions were not emitted",
|
||||
));
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
|
|||
trait_m_sig.inputs_and_output,
|
||||
));
|
||||
if !ocx.select_all_or_error().is_empty() {
|
||||
tcx.sess.delay_span_bug(
|
||||
tcx.sess.span_delayed_bug(
|
||||
DUMMY_SP,
|
||||
"encountered errors when checking RPITIT refinement (selection)",
|
||||
);
|
||||
|
|
@ -165,7 +165,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
|
|||
);
|
||||
let errors = infcx.resolve_regions(&outlives_env);
|
||||
if !errors.is_empty() {
|
||||
tcx.sess.delay_span_bug(
|
||||
tcx.sess.span_delayed_bug(
|
||||
DUMMY_SP,
|
||||
"encountered errors when checking RPITIT refinement (regions)",
|
||||
);
|
||||
|
|
@ -173,7 +173,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
|
|||
}
|
||||
// Resolve any lifetime variables that may have been introduced during normalization.
|
||||
let Ok((trait_bounds, impl_bounds)) = infcx.fully_resolve((trait_bounds, impl_bounds)) else {
|
||||
tcx.sess.delay_span_bug(
|
||||
tcx.sess.span_delayed_bug(
|
||||
DUMMY_SP,
|
||||
"encountered errors when checking RPITIT refinement (resolution)",
|
||||
);
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro
|
|||
// already checked by coherence, but compilation may
|
||||
// not have been terminated.
|
||||
let span = tcx.def_span(drop_impl_did);
|
||||
let reported = tcx.sess.delay_span_bug(
|
||||
let reported = tcx.sess.span_delayed_bug(
|
||||
span,
|
||||
format!("should have been rejected by coherence check: {dtor_self_type}"),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -281,7 +281,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>, enclosing_id: LocalDefId) {
|
||||
let target_features = self.tcx.asm_target_features(enclosing_id.to_def_id());
|
||||
let Some(asm_arch) = self.tcx.sess.asm_arch else {
|
||||
self.tcx.sess.delay_span_bug(DUMMY_SP, "target architecture does not support asm");
|
||||
self.tcx.sess.span_delayed_bug(DUMMY_SP, "target architecture does not support asm");
|
||||
return;
|
||||
};
|
||||
for (idx, (op, op_sp)) in asm.operands.iter().enumerate() {
|
||||
|
|
|
|||
|
|
@ -118,10 +118,10 @@ where
|
|||
if tcx.sess.err_count() > 0 {
|
||||
return Err(err);
|
||||
} else {
|
||||
// HACK(oli-obk): tests/ui/specialization/min_specialization/specialize_on_type_error.rs causes an
|
||||
// error (delay_span_bug) during normalization, without reporting an error, so we need to act as if
|
||||
// no error happened, in order to let our callers continue and report an error later in
|
||||
// check_impl_items_against_trait.
|
||||
// HACK(oli-obk): tests/ui/specialization/min_specialization/specialize_on_type_error.rs
|
||||
// causes an error (span_delayed_bug) during normalization, without reporting an error,
|
||||
// so we need to act as if no error happened, in order to let our callers continue and
|
||||
// report an error later in check_impl_items_against_trait.
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
|
@ -1040,7 +1040,7 @@ fn check_type_defn<'tcx>(
|
|||
let ty = tcx.erase_regions(ty);
|
||||
if ty.has_infer() {
|
||||
tcx.sess
|
||||
.delay_span_bug(item.span, format!("inference variables in {ty:?}"));
|
||||
.span_delayed_bug(item.span, format!("inference variables in {ty:?}"));
|
||||
// Just treat unresolved type expression as if it needs drop.
|
||||
true
|
||||
} else {
|
||||
|
|
@ -1812,8 +1812,10 @@ fn check_variances_for_type_defn<'tcx>(
|
|||
//
|
||||
// if they aren't in the same order, then the user has written invalid code, and already
|
||||
// got an error about it (or I'm wrong about this)
|
||||
tcx.sess
|
||||
.delay_span_bug(hir_param.span, "hir generics and ty generics in different order");
|
||||
tcx.sess.span_delayed_bug(
|
||||
hir_param.span,
|
||||
"hir generics and ty generics in different order",
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -453,7 +453,7 @@ fn lint_auto_trait_impl<'tcx>(
|
|||
impl_def_id: LocalDefId,
|
||||
) {
|
||||
if trait_ref.args.len() != 1 {
|
||||
tcx.sess.diagnostic().delay_span_bug(
|
||||
tcx.sess.diagnostic().span_delayed_bug(
|
||||
tcx.def_span(impl_def_id),
|
||||
"auto traits cannot have generic parameters",
|
||||
);
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
|
||||
(_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => {
|
||||
// Reported in AST validation
|
||||
tcx.sess.delay_span_bug(item.span, "unsafe negative impl");
|
||||
tcx.sess.span_delayed_bug(item.span, "unsafe negative impl");
|
||||
}
|
||||
(_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_))
|
||||
| (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive)
|
||||
|
|
|
|||
|
|
@ -335,7 +335,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
// though this may happen when we call `poly_trait_ref_binder_info` with
|
||||
// an (erroneous, #113423) associated return type bound in an impl header.
|
||||
if !supertrait_bound_vars.is_empty() {
|
||||
self.tcx.sess.delay_span_bug(
|
||||
self.tcx.sess.span_delayed_bug(
|
||||
DUMMY_SP,
|
||||
format!(
|
||||
"found supertrait lifetimes without a binder to append \
|
||||
|
|
@ -1363,7 +1363,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
self.tcx.sess.delay_span_bug(
|
||||
self.tcx.sess.span_delayed_bug(
|
||||
lifetime_ref.ident.span,
|
||||
format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,),
|
||||
);
|
||||
|
|
@ -1493,7 +1493,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
self.tcx.sess.delay_span_bug(
|
||||
self.tcx.sess.span_delayed_bug(
|
||||
self.tcx.hir().span(hir_id),
|
||||
format!("could not resolve {param_def_id:?}"),
|
||||
);
|
||||
|
|
@ -1724,7 +1724,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
} else {
|
||||
self.tcx
|
||||
.sess
|
||||
.delay_span_bug(binding.ident.span, "bad return type notation here");
|
||||
.span_delayed_bug(binding.ident.span, "bad return type notation here");
|
||||
vec![]
|
||||
};
|
||||
self.with(scope, |this| {
|
||||
|
|
@ -2057,7 +2057,7 @@ fn is_late_bound_map(
|
|||
Some(true) => Some(arg),
|
||||
Some(false) => None,
|
||||
None => {
|
||||
tcx.sess.delay_span_bug(
|
||||
tcx.sess.span_delayed_bug(
|
||||
*span,
|
||||
format!(
|
||||
"Incorrect generic arg count for alias {alias_def:?}"
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ fn diagnostic_hir_wf_check<'tcx>(
|
|||
|
||||
// HIR wfcheck should only ever happen as part of improving an existing error
|
||||
tcx.sess
|
||||
.delay_span_bug(tcx.def_span(def_id), "Performed HIR wfcheck without an existing error!");
|
||||
.span_delayed_bug(tcx.def_span(def_id), "Performed HIR wfcheck without an existing error!");
|
||||
|
||||
let icx = ItemCtxt::new(tcx, def_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId)
|
|||
if impl_self_ty.references_error() {
|
||||
// Don't complain about unconstrained type params when self ty isn't known due to errors.
|
||||
// (#36836)
|
||||
tcx.sess.delay_span_bug(
|
||||
tcx.sess.span_delayed_bug(
|
||||
tcx.def_span(impl_def_id),
|
||||
format!(
|
||||
"potentially unconstrained type parameters weren't evaluated: {impl_self_ty:?}",
|
||||
|
|
|
|||
|
|
@ -209,8 +209,8 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
|
|||
tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
|
||||
});
|
||||
|
||||
// HACK: `check_mod_type_wf` may spuriously emit errors due to `delay_span_bug`, even if those errors
|
||||
// only actually get emitted in `check_mod_item_types`.
|
||||
// HACK: `check_mod_type_wf` may spuriously emit errors due to `span_delayed_bug`, even if
|
||||
// those errors only actually get emitted in `check_mod_item_types`.
|
||||
errs?;
|
||||
|
||||
if tcx.features().rustc_attrs {
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
) {
|
||||
// Check for `self` receiver on the method, otherwise we can't use this as a `Fn*` trait.
|
||||
if !self.tcx.associated_item(ok.value.def_id).fn_has_self_parameter {
|
||||
self.tcx.sess.delay_span_bug(
|
||||
self.tcx.sess.span_delayed_bug(
|
||||
call_expr.span,
|
||||
"input to overloaded call fn is not a self receiver",
|
||||
);
|
||||
|
|
@ -259,9 +259,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind() else {
|
||||
// The `fn`/`fn_mut` lang item is ill-formed, which should have
|
||||
// caused an error elsewhere.
|
||||
self.tcx
|
||||
.sess
|
||||
.delay_span_bug(call_expr.span, "input to call/call_mut is not a ref");
|
||||
self.tcx.sess.span_delayed_bug(
|
||||
call_expr.span,
|
||||
"input to call/call_mut is not a ref",
|
||||
);
|
||||
return None;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let reported = self
|
||||
.tcx
|
||||
.sess
|
||||
.delay_span_bug(span, format!("`{t:?}` should be sized but is not?"));
|
||||
.span_delayed_bug(span, format!("`{t:?}` should be sized but is not?"));
|
||||
return Err(reported);
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1549,7 +1549,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
|||
// any superfluous errors we might encounter while trying to
|
||||
// emit or provide suggestions on how to fix the initial error.
|
||||
fcx.set_tainted_by_errors(
|
||||
fcx.tcx.sess.delay_span_bug(cause.span, "coercion error but no error emitted"),
|
||||
fcx.tcx
|
||||
.sess
|
||||
.span_delayed_bug(cause.span, "coercion error but no error emitted"),
|
||||
);
|
||||
let (expected, found) = if label_expression_as_expected {
|
||||
// In the case where this is a "forced unit", like
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
self.adjust_expr_for_assert_eq_macro(&mut expr, &mut expected_ty_expr);
|
||||
|
||||
self.set_tainted_by_errors(self.tcx.sess.delay_span_bug(
|
||||
self.set_tainted_by_errors(self.tcx.sess.span_delayed_bug(
|
||||
expr.span,
|
||||
"`TypeError` when attempting coercion but no error emitted",
|
||||
));
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// coercions from ! to `expected`.
|
||||
if ty.is_never() {
|
||||
if let Some(adjustments) = self.typeck_results.borrow().adjustments().get(expr.hir_id) {
|
||||
let reported = self.tcx().sess.delay_span_bug(
|
||||
let reported = self.tcx().sess.span_delayed_bug(
|
||||
expr.span,
|
||||
"expression with never type wound up being adjusted",
|
||||
);
|
||||
|
|
@ -514,7 +514,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Res::Err => {
|
||||
self.suggest_assoc_method_call(segs);
|
||||
let e =
|
||||
self.tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted");
|
||||
self.tcx.sess.span_delayed_bug(qpath.span(), "`Res::Err` but no error emitted");
|
||||
self.set_tainted_by_errors(e);
|
||||
Ty::new_error(tcx, e)
|
||||
}
|
||||
|
|
@ -623,7 +623,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Set expectation to error in that case and set tainted
|
||||
// by error (#114529)
|
||||
let coerce_to = opt_coerce_to.unwrap_or_else(|| {
|
||||
let guar = tcx.sess.delay_span_bug(
|
||||
let guar = tcx.sess.span_delayed_bug(
|
||||
expr.span,
|
||||
"illegal break with value found but no error reported",
|
||||
);
|
||||
|
|
@ -1292,7 +1292,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// permit break with a value [1].
|
||||
if ctxt.coerce.is_none() && !ctxt.may_break {
|
||||
// [1]
|
||||
self.tcx.sess.delay_span_bug(body.span, "no coercion, but loop may not break");
|
||||
self.tcx.sess.span_delayed_bug(body.span, "no coercion, but loop may not break");
|
||||
}
|
||||
ctxt.coerce.map(|c| c.complete(self)).unwrap_or_else(|| Ty::new_unit(self.tcx))
|
||||
}
|
||||
|
|
@ -2090,7 +2090,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
[] => unreachable!(),
|
||||
};
|
||||
err.note(format!(
|
||||
"... and other private field{s} {names}that {were} not provided",
|
||||
"{}private field{s} {names}that {were} not provided",
|
||||
if used_fields.is_empty() { "" } else { "...and other " },
|
||||
s = pluralize!(remaining_private_fields_len),
|
||||
were = pluralize!("was", remaining_private_fields_len),
|
||||
));
|
||||
|
|
@ -2186,7 +2187,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let guar = self
|
||||
.tcx
|
||||
.sess
|
||||
.delay_span_bug(expr.span, "parser recovered but no error was emitted");
|
||||
.span_delayed_bug(expr.span, "parser recovered but no error was emitted");
|
||||
self.set_tainted_by_errors(guar);
|
||||
return guar;
|
||||
}
|
||||
|
|
@ -2402,7 +2403,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
let guar = if field.name == kw::Empty {
|
||||
self.tcx.sess.delay_span_bug(field.span, "field name with no name")
|
||||
self.tcx.sess.span_delayed_bug(field.span, "field name with no name")
|
||||
} else if self.method_exists(field, base_ty, expr.hir_id, expected.only_has_type(self)) {
|
||||
self.ban_take_value_of_method(expr, base_ty, field)
|
||||
} else if !base_ty.is_primitive_ty() {
|
||||
|
|
|
|||
|
|
@ -538,7 +538,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
|||
|
||||
// The struct path probably didn't resolve
|
||||
if self.mc.typeck_results.opt_field_index(field.hir_id).is_none() {
|
||||
self.tcx().sess.delay_span_bug(field.span, "couldn't resolve index for field");
|
||||
self.tcx().sess.span_delayed_bug(field.span, "couldn't resolve index for field");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -277,7 +277,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// FIXME: currently we never try to compose autoderefs
|
||||
// and ReifyFnPointer/UnsafeFnPointer, but we could.
|
||||
_ => {
|
||||
self.tcx.sess.delay_span_bug(
|
||||
self.tcx.sess.span_delayed_bug(
|
||||
expr.span,
|
||||
format!(
|
||||
"while adjusting {:?}, can't compose {:?} and {:?}",
|
||||
|
|
@ -866,7 +866,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let guar = self
|
||||
.tcx
|
||||
.sess
|
||||
.delay_span_bug(span, "method resolution should've emitted an error");
|
||||
.span_delayed_bug(span, "method resolution should've emitted an error");
|
||||
let result = match error {
|
||||
method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)),
|
||||
_ => Err(guar),
|
||||
|
|
@ -1440,7 +1440,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
) {
|
||||
Ok(ok) => self.register_infer_ok_obligations(ok),
|
||||
Err(_) => {
|
||||
self.tcx.sess.delay_span_bug(
|
||||
self.tcx.sess.span_delayed_bug(
|
||||
span,
|
||||
format!(
|
||||
"instantiate_value_path: (UFCS) {self_ty:?} was a subtype of {impl_ty:?} but now is not?",
|
||||
|
|
|
|||
|
|
@ -517,7 +517,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let tcx = self.tcx;
|
||||
// FIXME: taint after emitting errors and pass through an `ErrorGuaranteed`
|
||||
self.set_tainted_by_errors(
|
||||
tcx.sess.delay_span_bug(call_span, "no errors reported for args"),
|
||||
tcx.sess.span_delayed_bug(call_span, "no errors reported for args"),
|
||||
);
|
||||
|
||||
// Get the argument span in the context of the call span so that
|
||||
|
|
@ -1361,7 +1361,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let variant = match def {
|
||||
Res::Err => {
|
||||
let guar =
|
||||
self.tcx.sess.delay_span_bug(path_span, "`Res::Err` but no error emitted");
|
||||
self.tcx.sess.span_delayed_bug(path_span, "`Res::Err` but no error emitted");
|
||||
self.set_tainted_by_errors(guar);
|
||||
return Err(guar);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let to = normalize(to);
|
||||
trace!(?from, ?to);
|
||||
if from.has_non_region_infer() || to.has_non_region_infer() {
|
||||
tcx.sess.delay_span_bug(span, "argument to transmute has inference variables");
|
||||
tcx.sess.span_delayed_bug(span, "argument to transmute has inference variables");
|
||||
return;
|
||||
}
|
||||
// Transmutes that are only changing lifetimes are always ok.
|
||||
|
|
|
|||
|
|
@ -420,20 +420,16 @@ fn fatally_break_rust(tcx: TyCtxt<'_>) {
|
|||
MultiSpan::new(),
|
||||
"It looks like you're trying to break rust; would you like some ICE?",
|
||||
);
|
||||
handler.note_without_error("the compiler expectedly panicked. this is a feature.");
|
||||
handler.note_without_error(
|
||||
handler.note("the compiler expectedly panicked. this is a feature.");
|
||||
handler.note(
|
||||
"we would appreciate a joke overview: \
|
||||
https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675",
|
||||
);
|
||||
handler.note_without_error(format!(
|
||||
"rustc {} running on {}",
|
||||
tcx.sess.cfg_version,
|
||||
config::host_triple(),
|
||||
));
|
||||
handler.note(format!("rustc {} running on {}", tcx.sess.cfg_version, config::host_triple(),));
|
||||
if let Some((flags, excluded_cargo_defaults)) = rustc_session::utils::extra_compiler_flags() {
|
||||
handler.note_without_error(format!("compiler flags: {}", flags.join(" ")));
|
||||
handler.note(format!("compiler flags: {}", flags.join(" ")));
|
||||
if excluded_cargo_defaults {
|
||||
handler.note_without_error("some of the compiler flags provided by cargo are hidden");
|
||||
handler.note("some of the compiler flags provided by cargo are hidden");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -540,7 +540,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
|||
let ty::Adt(adt_def, _) = ty.kind() else {
|
||||
self.tcx()
|
||||
.sess
|
||||
.delay_span_bug(span, "struct or tuple struct pattern not applied to an ADT");
|
||||
.span_delayed_bug(span, "struct or tuple struct pattern not applied to an ADT");
|
||||
return Err(());
|
||||
};
|
||||
|
||||
|
|
@ -575,7 +575,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
|||
_ => {
|
||||
self.tcx()
|
||||
.sess
|
||||
.delay_span_bug(span, "struct or tuple struct pattern not applied to an ADT");
|
||||
.span_delayed_bug(span, "struct or tuple struct pattern not applied to an ADT");
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
|
@ -588,7 +588,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
|||
match ty.kind() {
|
||||
ty::Tuple(args) => Ok(args.len()),
|
||||
_ => {
|
||||
self.tcx().sess.delay_span_bug(span, "tuple pattern not applied to a tuple");
|
||||
self.tcx().sess.span_delayed_bug(span, "tuple pattern not applied to a tuple");
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -385,7 +385,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// type parameters or early-bound regions.
|
||||
let tcx = self.tcx;
|
||||
let Some(method_item) = self.associated_value(trait_def_id, m_name) else {
|
||||
tcx.sess.delay_span_bug(
|
||||
tcx.sess.span_delayed_bug(
|
||||
obligation.cause.span,
|
||||
"operator trait does not have corresponding operator method",
|
||||
);
|
||||
|
|
@ -393,7 +393,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
};
|
||||
|
||||
if method_item.kind != ty::AssocKind::Fn {
|
||||
self.tcx.sess.delay_span_bug(tcx.def_span(method_item.def_id), "not a method");
|
||||
self.tcx.sess.span_delayed_bug(tcx.def_span(method_item.def_id), "not a method");
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -802,7 +802,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
let trait_ref = principal.with_self_ty(self.tcx, self_ty);
|
||||
self.elaborate_bounds(iter::once(trait_ref), |this, new_trait_ref, item| {
|
||||
if new_trait_ref.has_non_region_bound_vars() {
|
||||
this.tcx.sess.delay_span_bug(
|
||||
this.tcx.sess.span_delayed_bug(
|
||||
this.span,
|
||||
"tried to select method from HRTB with non-lifetime bound vars",
|
||||
);
|
||||
|
|
|
|||
|
|
@ -813,7 +813,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
span: item_span,
|
||||
..
|
||||
})) => {
|
||||
tcx.sess.delay_span_bug(
|
||||
tcx.sess.span_delayed_bug(
|
||||
*item_span,
|
||||
"auto trait is invoked with no method error, but no error reported?",
|
||||
);
|
||||
|
|
|
|||
|
|
@ -900,7 +900,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
) {
|
||||
self.tcx
|
||||
.sess
|
||||
.delay_span_bug(span, "operator didn't have the right number of generic args");
|
||||
.span_delayed_bug(span, "operator didn't have the right number of generic args");
|
||||
return Err(vec![]);
|
||||
}
|
||||
|
||||
|
|
@ -933,7 +933,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// This path may do some inference, so make sure we've really
|
||||
// doomed compilation so as to not accidentally stabilize new
|
||||
// inference or something here...
|
||||
self.tcx.sess.delay_span_bug(span, "this path really should be doomed...");
|
||||
self.tcx.sess.span_delayed_bug(span, "this path really should be doomed...");
|
||||
// Guide inference for the RHS expression if it's provided --
|
||||
// this will allow us to better error reporting, at the expense
|
||||
// of making some error messages a bit more specific.
|
||||
|
|
|
|||
|
|
@ -899,7 +899,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let (res, opt_ty, segments) = path_resolution;
|
||||
match res {
|
||||
Res::Err => {
|
||||
let e = tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted");
|
||||
let e = tcx.sess.span_delayed_bug(qpath.span(), "`Res::Err` but no error emitted");
|
||||
self.set_tainted_by_errors(e);
|
||||
return Ty::new_error(tcx, e);
|
||||
}
|
||||
|
|
@ -1068,7 +1068,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let (res, opt_ty, segments) =
|
||||
self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None);
|
||||
if res == Res::Err {
|
||||
let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted");
|
||||
let e = tcx.sess.span_delayed_bug(pat.span, "`Res::Err` but no error emitted");
|
||||
self.set_tainted_by_errors(e);
|
||||
on_error(e);
|
||||
return Ty::new_error(tcx, e);
|
||||
|
|
@ -1084,7 +1084,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
let variant = match res {
|
||||
Res::Err => {
|
||||
let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted");
|
||||
let e = tcx.sess.span_delayed_bug(pat.span, "`Res::Err` but no error emitted");
|
||||
self.set_tainted_by_errors(e);
|
||||
on_error(e);
|
||||
return Ty::new_error(tcx, e);
|
||||
|
|
|
|||
|
|
@ -725,7 +725,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
self.tcx.sess.delay_span_bug(
|
||||
self.tcx.sess.span_delayed_bug(
|
||||
closure_span,
|
||||
format!(
|
||||
"two identical projections: ({:?}, {:?})",
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
|||
// When encountering `return [0][0]` outside of a `fn` body we can encounter a base
|
||||
// that isn't in the type table. We assume more relevant errors have already been
|
||||
// emitted, so we delay an ICE if none have. (#64638)
|
||||
self.tcx().sess.delay_span_bug(e.span, format!("bad base: `{base:?}`"));
|
||||
self.tcx().sess.span_delayed_bug(e.span, format!("bad base: `{base:?}`"));
|
||||
}
|
||||
if let Some(base_ty) = base_ty
|
||||
&& let ty::Ref(_, base_ty_inner, _) = *base_ty.kind()
|
||||
|
|
@ -311,7 +311,9 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
|
|||
// Nothing to write back here
|
||||
}
|
||||
hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => {
|
||||
self.tcx().sess.delay_span_bug(p.span, format!("unexpected generic param: {p:?}"));
|
||||
self.tcx()
|
||||
.sess
|
||||
.span_delayed_bug(p.span, format!("unexpected generic param: {p:?}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@ pub(crate) fn prepare_session_directory(
|
|||
directory."
|
||||
);
|
||||
|
||||
sess.init_incr_comp_session(session_dir, directory_lock, false);
|
||||
sess.init_incr_comp_session(session_dir, directory_lock);
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
|
|
@ -276,7 +276,7 @@ pub(crate) fn prepare_session_directory(
|
|||
sess.emit_warning(errors::HardLinkFailed { path: &session_dir });
|
||||
}
|
||||
|
||||
sess.init_incr_comp_session(session_dir, directory_lock, true);
|
||||
sess.init_incr_comp_session(session_dir, directory_lock);
|
||||
return Ok(());
|
||||
} else {
|
||||
debug!("copying failed - trying next directory");
|
||||
|
|
@ -312,7 +312,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Option<Svh>) {
|
|||
|
||||
let incr_comp_session_dir: PathBuf = sess.incr_comp_session_dir().clone();
|
||||
|
||||
if let Some(_) = sess.has_errors_or_delayed_span_bugs() {
|
||||
if let Some(_) = sess.has_errors_or_span_delayed_bugs() {
|
||||
// If there have been any errors during compilation, we don't want to
|
||||
// publish this session directory. Rather, we'll just delete it.
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) {
|
|||
return;
|
||||
}
|
||||
// This is going to be deleted in finalize_session_directory, so let's not create it
|
||||
if let Some(_) = sess.has_errors_or_delayed_span_bugs() {
|
||||
if let Some(_) = sess.has_errors_or_span_delayed_bugs() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ pub fn save_work_product_index(
|
|||
return;
|
||||
}
|
||||
// This is going to be deleted in finalize_session_directory, so let's not create it
|
||||
if let Some(_) = sess.has_errors_or_delayed_span_bugs() {
|
||||
if let Some(_) = sess.has_errors_or_span_delayed_bugs() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -194,8 +194,8 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
|
|||
//
|
||||
// rust-lang/rust#57464: `impl Trait` can leak local
|
||||
// scopes (in manner violating typeck). Therefore, use
|
||||
// `delay_span_bug` to allow type error over an ICE.
|
||||
canonicalizer.tcx.sess.delay_span_bug(
|
||||
// `span_delayed_bug` to allow type error over an ICE.
|
||||
canonicalizer.tcx.sess.span_delayed_bug(
|
||||
rustc_span::DUMMY_SP,
|
||||
format!("unexpected region in query response: `{r:?}`"),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
&mut OriginalQueryValues::default(),
|
||||
);
|
||||
self.tcx.check_tys_might_be_eq(canonical).map_err(|_| {
|
||||
self.tcx.sess.delay_span_bug(
|
||||
self.tcx.sess.span_delayed_bug(
|
||||
DUMMY_SP,
|
||||
format!("cannot relate consts of different types (a={a:?}, b={b:?})",),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -131,13 +131,13 @@ pub struct TypeErrCtxt<'a, 'tcx> {
|
|||
|
||||
impl Drop for TypeErrCtxt<'_, '_> {
|
||||
fn drop(&mut self) {
|
||||
if let Some(_) = self.infcx.tcx.sess.has_errors_or_delayed_span_bugs() {
|
||||
if let Some(_) = self.infcx.tcx.sess.has_errors_or_span_delayed_bugs() {
|
||||
// ok, emitted an error.
|
||||
} else {
|
||||
self.infcx
|
||||
.tcx
|
||||
.sess
|
||||
.delay_good_path_bug("used a `TypeErrCtxt` without raising an error or lint");
|
||||
.good_path_delayed_bug("used a `TypeErrCtxt` without raising an error or lint");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -517,7 +517,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
|
||||
self.tcx
|
||||
.sess
|
||||
.delay_span_bug(self.tcx.def_span(generic_param_scope), "expected region errors")
|
||||
.span_delayed_bug(self.tcx.def_span(generic_param_scope), "expected region errors")
|
||||
}
|
||||
|
||||
// This method goes through all the errors and try to group certain types
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue