mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 03:38:29 +00:00
Auto merge of #105456 - matthiaskrgr:rollup-yennygf, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - #104922 (Detect long types in E0308 and write them to disk) - #105120 (kmc-solid: `std::sys` code maintenance) - #105255 (Make nested RPIT inherit the parent opaque's generics.) - #105317 (make retagging work even with 'unstable' places) - #105405 (Stop passing -export-dynamic to wasm-ld.) - #105408 (Add help for `#![feature(impl_trait_in_fn_trait_return)]`) - #105423 (Use `Symbol` for the crate name instead of `String`/`str`) - #105433 (CI: add missing line continuation marker) - #105434 (Fix warning when libcore is compiled with no_fp_fmt_parse) - #105441 (Remove `UnsafetyState`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
7701a7e7d4
@ -4348,6 +4348,7 @@ dependencies = [
|
|||||||
"rustc_span",
|
"rustc_span",
|
||||||
"rustc_target",
|
"rustc_target",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
|
"termize",
|
||||||
"tracing",
|
"tracing",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
@ -259,6 +259,8 @@ enum ImplTraitContext {
|
|||||||
},
|
},
|
||||||
/// Impl trait in type aliases.
|
/// Impl trait in type aliases.
|
||||||
TypeAliasesOpaqueTy,
|
TypeAliasesOpaqueTy,
|
||||||
|
/// `impl Trait` is unstably accepted in this position.
|
||||||
|
FeatureGated(ImplTraitPosition, Symbol),
|
||||||
/// `impl Trait` is not accepted in this position.
|
/// `impl Trait` is not accepted in this position.
|
||||||
Disallowed(ImplTraitPosition),
|
Disallowed(ImplTraitPosition),
|
||||||
}
|
}
|
||||||
@ -1372,17 +1374,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
}
|
}
|
||||||
path
|
path
|
||||||
}
|
}
|
||||||
ImplTraitContext::Disallowed(
|
ImplTraitContext::FeatureGated(position, feature) => {
|
||||||
position @ (ImplTraitPosition::TraitReturn | ImplTraitPosition::ImplReturn),
|
|
||||||
) => {
|
|
||||||
self.tcx
|
self.tcx
|
||||||
.sess
|
.sess
|
||||||
.create_feature_err(
|
.create_feature_err(
|
||||||
MisplacedImplTrait {
|
MisplacedImplTrait {
|
||||||
span: t.span,
|
span: t.span,
|
||||||
position: DiagnosticArgFromDisplay(&position),
|
position: DiagnosticArgFromDisplay(position),
|
||||||
},
|
},
|
||||||
sym::return_position_impl_trait_in_trait,
|
*feature,
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
hir::TyKind::Err
|
hir::TyKind::Err
|
||||||
@ -1390,7 +1390,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
ImplTraitContext::Disallowed(position) => {
|
ImplTraitContext::Disallowed(position) => {
|
||||||
self.tcx.sess.emit_err(MisplacedImplTrait {
|
self.tcx.sess.emit_err(MisplacedImplTrait {
|
||||||
span: t.span,
|
span: t.span,
|
||||||
position: DiagnosticArgFromDisplay(&position),
|
position: DiagnosticArgFromDisplay(position),
|
||||||
});
|
});
|
||||||
hir::TyKind::Err
|
hir::TyKind::Err
|
||||||
}
|
}
|
||||||
@ -1739,14 +1739,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
} else {
|
} else {
|
||||||
match &decl.output {
|
match &decl.output {
|
||||||
FnRetTy::Ty(ty) => {
|
FnRetTy::Ty(ty) => {
|
||||||
let mut context = if kind.return_impl_trait_allowed(self.tcx) {
|
let context = if kind.return_impl_trait_allowed(self.tcx) {
|
||||||
let fn_def_id = self.local_def_id(fn_node_id);
|
let fn_def_id = self.local_def_id(fn_node_id);
|
||||||
ImplTraitContext::ReturnPositionOpaqueTy {
|
ImplTraitContext::ReturnPositionOpaqueTy {
|
||||||
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
||||||
in_trait: matches!(kind, FnDeclKind::Trait),
|
in_trait: matches!(kind, FnDeclKind::Trait),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ImplTraitContext::Disallowed(match kind {
|
let position = match kind {
|
||||||
FnDeclKind::Fn | FnDeclKind::Inherent => {
|
FnDeclKind::Fn | FnDeclKind::Inherent => {
|
||||||
unreachable!("fn should allow in-band lifetimes")
|
unreachable!("fn should allow in-band lifetimes")
|
||||||
}
|
}
|
||||||
@ -1755,9 +1755,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
FnDeclKind::Pointer => ImplTraitPosition::PointerReturn,
|
FnDeclKind::Pointer => ImplTraitPosition::PointerReturn,
|
||||||
FnDeclKind::Trait => ImplTraitPosition::TraitReturn,
|
FnDeclKind::Trait => ImplTraitPosition::TraitReturn,
|
||||||
FnDeclKind::Impl => ImplTraitPosition::ImplReturn,
|
FnDeclKind::Impl => ImplTraitPosition::ImplReturn,
|
||||||
})
|
};
|
||||||
|
match kind {
|
||||||
|
FnDeclKind::Trait | FnDeclKind::Impl => ImplTraitContext::FeatureGated(
|
||||||
|
position,
|
||||||
|
sym::return_position_impl_trait_in_trait,
|
||||||
|
),
|
||||||
|
_ => ImplTraitContext::Disallowed(position),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
hir::FnRetTy::Return(self.lower_ty(ty, &mut context))
|
hir::FnRetTy::Return(self.lower_ty(ty, &context))
|
||||||
}
|
}
|
||||||
FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)),
|
FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)),
|
||||||
}
|
}
|
||||||
@ -1938,7 +1945,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
output,
|
output,
|
||||||
span,
|
span,
|
||||||
if in_trait && !this.tcx.features().return_position_impl_trait_in_trait {
|
if in_trait && !this.tcx.features().return_position_impl_trait_in_trait {
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::TraitReturn)
|
ImplTraitContext::FeatureGated(
|
||||||
|
ImplTraitPosition::TraitReturn,
|
||||||
|
sym::return_position_impl_trait_in_trait,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
ImplTraitContext::ReturnPositionOpaqueTy {
|
ImplTraitContext::ReturnPositionOpaqueTy {
|
||||||
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
||||||
|
@ -9,7 +9,7 @@ use rustc_ast::{self as ast, *};
|
|||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, PartialRes, Res};
|
use rustc_hir::def::{DefKind, PartialRes, Res};
|
||||||
use rustc_hir::GenericArg;
|
use rustc_hir::GenericArg;
|
||||||
use rustc_span::symbol::{kw, Ident};
|
use rustc_span::symbol::{kw, sym, Ident};
|
||||||
use rustc_span::{BytePos, Span, DUMMY_SP};
|
use rustc_span::{BytePos, Span, DUMMY_SP};
|
||||||
|
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
@ -352,11 +352,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
// fn f(_: impl Fn() -> impl Debug) -> impl Fn() -> impl Debug
|
// fn f(_: impl Fn() -> impl Debug) -> impl Fn() -> impl Debug
|
||||||
// // disallowed --^^^^^^^^^^ allowed --^^^^^^^^^^
|
// // disallowed --^^^^^^^^^^ allowed --^^^^^^^^^^
|
||||||
// ```
|
// ```
|
||||||
FnRetTy::Ty(ty)
|
FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) => {
|
||||||
if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. })
|
if self.tcx.features().impl_trait_in_fn_trait_return {
|
||||||
&& self.tcx.features().impl_trait_in_fn_trait_return =>
|
self.lower_ty(&ty, itctx)
|
||||||
{
|
} else {
|
||||||
self.lower_ty(&ty, itctx)
|
self.lower_ty(
|
||||||
|
&ty,
|
||||||
|
&ImplTraitContext::FeatureGated(
|
||||||
|
ImplTraitPosition::FnTraitReturn,
|
||||||
|
sym::impl_trait_in_fn_trait_return,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
FnRetTy::Ty(ty) => {
|
FnRetTy::Ty(ty) => {
|
||||||
self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn))
|
self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn))
|
||||||
|
@ -102,7 +102,7 @@ pub fn link_binary<'a>(
|
|||||||
sess,
|
sess,
|
||||||
crate_type,
|
crate_type,
|
||||||
outputs,
|
outputs,
|
||||||
codegen_results.crate_info.local_crate_name.as_str(),
|
codegen_results.crate_info.local_crate_name,
|
||||||
);
|
);
|
||||||
match crate_type {
|
match crate_type {
|
||||||
CrateType::Rlib => {
|
CrateType::Rlib => {
|
||||||
|
@ -373,9 +373,21 @@ pub trait Machine<'mir, 'tcx>: Sized {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Executes a retagging operation.
|
/// Executes a retagging operation for a single pointer.
|
||||||
|
/// Returns the possibly adjusted pointer.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn retag(
|
fn retag_ptr_value(
|
||||||
|
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||||
|
_kind: mir::RetagKind,
|
||||||
|
val: &ImmTy<'tcx, Self::Provenance>,
|
||||||
|
) -> InterpResult<'tcx, ImmTy<'tcx, Self::Provenance>> {
|
||||||
|
Ok(val.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Executes a retagging operation on a compound value.
|
||||||
|
/// Replaces all pointers stored in the given place.
|
||||||
|
#[inline]
|
||||||
|
fn retag_place_contents(
|
||||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||||
_kind: mir::RetagKind,
|
_kind: mir::RetagKind,
|
||||||
_place: &PlaceTy<'tcx, Self::Provenance>,
|
_place: &PlaceTy<'tcx, Self::Provenance>,
|
||||||
|
@ -8,7 +8,7 @@ use rustc_middle::mir;
|
|||||||
use rustc_middle::mir::interpret::{InterpResult, Scalar};
|
use rustc_middle::mir::interpret::{InterpResult, Scalar};
|
||||||
use rustc_middle::ty::layout::LayoutOf;
|
use rustc_middle::ty::layout::LayoutOf;
|
||||||
|
|
||||||
use super::{InterpCx, Machine};
|
use super::{ImmTy, InterpCx, Machine};
|
||||||
|
|
||||||
/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
|
/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
|
||||||
/// same type as the result.
|
/// same type as the result.
|
||||||
@ -108,7 +108,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
// Stacked Borrows.
|
// Stacked Borrows.
|
||||||
Retag(kind, place) => {
|
Retag(kind, place) => {
|
||||||
let dest = self.eval_place(**place)?;
|
let dest = self.eval_place(**place)?;
|
||||||
M::retag(self, *kind, &dest)?;
|
M::retag_place_contents(self, *kind, &dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Intrinsic(box ref intrinsic) => self.emulate_nondiverging_intrinsic(intrinsic)?,
|
Intrinsic(box ref intrinsic) => self.emulate_nondiverging_intrinsic(intrinsic)?,
|
||||||
@ -247,10 +247,41 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?;
|
self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddressOf(_, place) | Ref(_, _, place) => {
|
Ref(_, borrow_kind, place) => {
|
||||||
let src = self.eval_place(place)?;
|
let src = self.eval_place(place)?;
|
||||||
let place = self.force_allocation(&src)?;
|
let place = self.force_allocation(&src)?;
|
||||||
self.write_immediate(place.to_ref(self), &dest)?;
|
let val = ImmTy::from_immediate(place.to_ref(self), dest.layout);
|
||||||
|
// A fresh reference was created, make sure it gets retagged.
|
||||||
|
let val = M::retag_ptr_value(
|
||||||
|
self,
|
||||||
|
if borrow_kind.allows_two_phase_borrow() {
|
||||||
|
mir::RetagKind::TwoPhase
|
||||||
|
} else {
|
||||||
|
mir::RetagKind::Default
|
||||||
|
},
|
||||||
|
&val,
|
||||||
|
)?;
|
||||||
|
self.write_immediate(*val, &dest)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddressOf(_, place) => {
|
||||||
|
// Figure out whether this is an addr_of of an already raw place.
|
||||||
|
let place_base_raw = if place.has_deref() {
|
||||||
|
let ty = self.frame().body.local_decls[place.local].ty;
|
||||||
|
ty.is_unsafe_ptr()
|
||||||
|
} else {
|
||||||
|
// Not a deref, and thus not raw.
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
let src = self.eval_place(place)?;
|
||||||
|
let place = self.force_allocation(&src)?;
|
||||||
|
let mut val = ImmTy::from_immediate(place.to_ref(self), dest.layout);
|
||||||
|
if !place_base_raw {
|
||||||
|
// If this was not already raw, it needs retagging.
|
||||||
|
val = M::retag_ptr_value(self, mir::RetagKind::Raw, &val)?;
|
||||||
|
}
|
||||||
|
self.write_immediate(*val, &dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
NullaryOp(null_op, ty) => {
|
NullaryOp(null_op, ty) => {
|
||||||
|
@ -25,6 +25,7 @@ use rustc_data_structures::sync::SeqCst;
|
|||||||
use rustc_errors::registry::{InvalidErrorCode, Registry};
|
use rustc_errors::registry::{InvalidErrorCode, Registry};
|
||||||
use rustc_errors::{ErrorGuaranteed, PResult};
|
use rustc_errors::{ErrorGuaranteed, PResult};
|
||||||
use rustc_feature::find_gated_cfg;
|
use rustc_feature::find_gated_cfg;
|
||||||
|
use rustc_hir::def_id::LOCAL_CRATE;
|
||||||
use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
|
use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
|
||||||
use rustc_interface::{interface, Queries};
|
use rustc_interface::{interface, Queries};
|
||||||
use rustc_lint::LintStore;
|
use rustc_lint::LintStore;
|
||||||
@ -374,14 +375,14 @@ fn run_compiler(
|
|||||||
queries.global_ctxt()?.peek_mut().enter(|tcx| {
|
queries.global_ctxt()?.peek_mut().enter(|tcx| {
|
||||||
let result = tcx.analysis(());
|
let result = tcx.analysis(());
|
||||||
if sess.opts.unstable_opts.save_analysis {
|
if sess.opts.unstable_opts.save_analysis {
|
||||||
let crate_name = queries.crate_name()?.peek().clone();
|
let crate_name = tcx.crate_name(LOCAL_CRATE);
|
||||||
sess.time("save_analysis", || {
|
sess.time("save_analysis", || {
|
||||||
save::process_crate(
|
save::process_crate(
|
||||||
tcx,
|
tcx,
|
||||||
&crate_name,
|
crate_name,
|
||||||
compiler.input(),
|
compiler.input(),
|
||||||
None,
|
None,
|
||||||
DumpHandler::new(compiler.output_dir().as_deref(), &crate_name),
|
DumpHandler::new(compiler.output_dir().as_deref(), crate_name),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -678,7 +679,7 @@ fn print_crate_info(
|
|||||||
let crate_types = collect_crate_types(sess, attrs);
|
let crate_types = collect_crate_types(sess, attrs);
|
||||||
for &style in &crate_types {
|
for &style in &crate_types {
|
||||||
let fname =
|
let fname =
|
||||||
rustc_session::output::filename_for_input(sess, style, &id, &t_outputs);
|
rustc_session::output::filename_for_input(sess, style, id, &t_outputs);
|
||||||
println!("{}", fname.file_name().unwrap().to_string_lossy());
|
println!("{}", fname.file_name().unwrap().to_string_lossy());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -960,7 +960,7 @@ pub trait LintStoreExpand {
|
|||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
attrs: &[Attribute],
|
attrs: &[Attribute],
|
||||||
items: &[P<Item>],
|
items: &[P<Item>],
|
||||||
name: &str,
|
name: Symbol,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1122,7 +1122,7 @@ impl InvocationCollectorNode for P<ast::Item> {
|
|||||||
ecx.current_expansion.lint_node_id,
|
ecx.current_expansion.lint_node_id,
|
||||||
&attrs,
|
&attrs,
|
||||||
&items,
|
&items,
|
||||||
ident.name.as_str(),
|
ident.name,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -827,7 +827,7 @@ impl<'tcx> AttributeMap<'tcx> {
|
|||||||
pub struct OwnerNodes<'tcx> {
|
pub struct OwnerNodes<'tcx> {
|
||||||
/// Pre-computed hash of the full HIR.
|
/// Pre-computed hash of the full HIR.
|
||||||
pub hash_including_bodies: Fingerprint,
|
pub hash_including_bodies: Fingerprint,
|
||||||
/// Pre-computed hash of the item signature, sithout recursing into the body.
|
/// Pre-computed hash of the item signature, without recursing into the body.
|
||||||
pub hash_without_bodies: Fingerprint,
|
pub hash_without_bodies: Fingerprint,
|
||||||
/// Full HIR for the current owner.
|
/// Full HIR for the current owner.
|
||||||
// The zeroth node's parent should never be accessed: the owner's parent is computed by the
|
// The zeroth node's parent should never be accessed: the owner's parent is computed by the
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData};
|
use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData};
|
||||||
use rustc_span::def_id::{DefPathHash, StableCrateId};
|
use rustc_span::def_id::{DefPathHash, StableCrateId};
|
||||||
|
use rustc_span::edition::Edition;
|
||||||
|
use rustc_span::{create_session_if_not_set_then, Symbol};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn def_path_hash_depends_on_crate_id() {
|
fn def_path_hash_depends_on_crate_id() {
|
||||||
@ -11,26 +13,28 @@ fn def_path_hash_depends_on_crate_id() {
|
|||||||
// the crate by changing the crate disambiguator (e.g. via bumping the
|
// the crate by changing the crate disambiguator (e.g. via bumping the
|
||||||
// crate's version number).
|
// crate's version number).
|
||||||
|
|
||||||
let id0 = StableCrateId::new("foo", false, vec!["1".to_string()]);
|
create_session_if_not_set_then(Edition::Edition2024, |_| {
|
||||||
let id1 = StableCrateId::new("foo", false, vec!["2".to_string()]);
|
let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()]);
|
||||||
|
let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()]);
|
||||||
|
|
||||||
let h0 = mk_test_hash(id0);
|
let h0 = mk_test_hash(id0);
|
||||||
let h1 = mk_test_hash(id1);
|
let h1 = mk_test_hash(id1);
|
||||||
|
|
||||||
assert_ne!(h0.stable_crate_id(), h1.stable_crate_id());
|
assert_ne!(h0.stable_crate_id(), h1.stable_crate_id());
|
||||||
assert_ne!(h0.local_hash(), h1.local_hash());
|
assert_ne!(h0.local_hash(), h1.local_hash());
|
||||||
|
|
||||||
fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash {
|
fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash {
|
||||||
let parent_hash = DefPathHash::new(stable_crate_id, 0);
|
let parent_hash = DefPathHash::new(stable_crate_id, 0);
|
||||||
|
|
||||||
let key = DefKey {
|
let key = DefKey {
|
||||||
parent: None,
|
parent: None,
|
||||||
disambiguated_data: DisambiguatedDefPathData {
|
disambiguated_data: DisambiguatedDefPathData {
|
||||||
data: DefPathData::CrateRoot,
|
data: DefPathData::CrateRoot,
|
||||||
disambiguator: 0,
|
disambiguator: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
key.compute_stable_hash(parent_hash)
|
key.compute_stable_hash(parent_hash)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ use hir::{
|
|||||||
GenericParamKind, HirId, Node,
|
GenericParamKind, HirId, Node,
|
||||||
};
|
};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::DefKind;
|
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_session::lint;
|
use rustc_session::lint;
|
||||||
@ -143,20 +142,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
|
|||||||
Some(tcx.typeck_root_def_id(def_id))
|
Some(tcx.typeck_root_def_id(def_id))
|
||||||
}
|
}
|
||||||
Node::Item(item) => match item.kind {
|
Node::Item(item) => match item.kind {
|
||||||
ItemKind::OpaqueTy(hir::OpaqueTy {
|
ItemKind::OpaqueTy(hir::OpaqueTy { .. }) => {
|
||||||
origin:
|
|
||||||
hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
|
|
||||||
in_trait,
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
if in_trait {
|
|
||||||
assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn))
|
|
||||||
} else {
|
|
||||||
assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn))
|
|
||||||
}
|
|
||||||
Some(fn_def_id.to_def_id())
|
|
||||||
}
|
|
||||||
ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
|
|
||||||
let parent_id = tcx.hir().get_parent_item(hir_id);
|
let parent_id = tcx.hir().get_parent_item(hir_id);
|
||||||
assert_ne!(parent_id, hir::CRATE_OWNER_ID);
|
assert_ne!(parent_id, hir::CRATE_OWNER_ID);
|
||||||
debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
|
debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::coercion::CoerceMany;
|
use crate::coercion::CoerceMany;
|
||||||
use crate::gather_locals::GatherLocalsVisitor;
|
use crate::gather_locals::GatherLocalsVisitor;
|
||||||
use crate::FnCtxt;
|
use crate::FnCtxt;
|
||||||
use crate::{GeneratorTypes, UnsafetyState};
|
use crate::GeneratorTypes;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::Visitor;
|
||||||
@ -30,7 +30,6 @@ pub(super) fn check_fn<'a, 'tcx>(
|
|||||||
can_be_generator: Option<hir::Movability>,
|
can_be_generator: Option<hir::Movability>,
|
||||||
) -> Option<GeneratorTypes<'tcx>> {
|
) -> Option<GeneratorTypes<'tcx>> {
|
||||||
let fn_id = fcx.tcx.hir().local_def_id_to_hir_id(fn_def_id);
|
let fn_id = fcx.tcx.hir().local_def_id_to_hir_id(fn_def_id);
|
||||||
fcx.ps.set(UnsafetyState::function(fn_sig.unsafety, fn_id));
|
|
||||||
|
|
||||||
let tcx = fcx.tcx;
|
let tcx = fcx.tcx;
|
||||||
let hir = tcx.hir();
|
let hir = tcx.hir();
|
||||||
|
@ -1393,8 +1393,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
blk: &'tcx hir::Block<'tcx>,
|
blk: &'tcx hir::Block<'tcx>,
|
||||||
expected: Expectation<'tcx>,
|
expected: Expectation<'tcx>,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
let prev = self.ps.replace(self.ps.get().recurse(blk));
|
|
||||||
|
|
||||||
// In some cases, blocks have just one exit, but other blocks
|
// In some cases, blocks have just one exit, but other blocks
|
||||||
// can be targeted by multiple breaks. This can happen both
|
// can be targeted by multiple breaks. This can happen both
|
||||||
// with labeled blocks as well as when we desugar
|
// with labeled blocks as well as when we desugar
|
||||||
@ -1558,7 +1556,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
self.write_ty(blk.hir_id, ty);
|
self.write_ty(blk.hir_id, ty);
|
||||||
|
|
||||||
self.ps.set(prev);
|
|
||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ use rustc_errors::ErrorGuaranteed;
|
|||||||
pub use suggestions::*;
|
pub use suggestions::*;
|
||||||
|
|
||||||
use crate::coercion::DynamicCoerceMany;
|
use crate::coercion::DynamicCoerceMany;
|
||||||
use crate::{Diverges, EnclosingBreakables, Inherited, UnsafetyState};
|
use crate::{Diverges, EnclosingBreakables, Inherited};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir_analysis::astconv::AstConv;
|
use rustc_hir_analysis::astconv::AstConv;
|
||||||
@ -74,8 +74,6 @@ pub struct FnCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
pub(super) resume_yield_tys: Option<(Ty<'tcx>, Ty<'tcx>)>,
|
pub(super) resume_yield_tys: Option<(Ty<'tcx>, Ty<'tcx>)>,
|
||||||
|
|
||||||
pub(super) ps: Cell<UnsafetyState>,
|
|
||||||
|
|
||||||
/// Whether the last checked node generates a divergence (e.g.,
|
/// Whether the last checked node generates a divergence (e.g.,
|
||||||
/// `return` will set this to `Always`). In general, when entering
|
/// `return` will set this to `Always`). In general, when entering
|
||||||
/// an expression or other node in the tree, the initial value
|
/// an expression or other node in the tree, the initial value
|
||||||
@ -129,7 +127,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
ret_coercion: None,
|
ret_coercion: None,
|
||||||
ret_coercion_span: Cell::new(None),
|
ret_coercion_span: Cell::new(None),
|
||||||
resume_yield_tys: None,
|
resume_yield_tys: None,
|
||||||
ps: Cell::new(UnsafetyState::function(hir::Unsafety::Normal, hir::CRATE_HIR_ID)),
|
|
||||||
diverges: Cell::new(Diverges::Maybe),
|
diverges: Cell::new(Diverges::Maybe),
|
||||||
enclosing_breakables: RefCell::new(EnclosingBreakables {
|
enclosing_breakables: RefCell::new(EnclosingBreakables {
|
||||||
stack: Vec::new(),
|
stack: Vec::new(),
|
||||||
|
@ -89,38 +89,6 @@ pub struct LocalTy<'tcx> {
|
|||||||
revealed_ty: Ty<'tcx>,
|
revealed_ty: Ty<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
pub struct UnsafetyState {
|
|
||||||
pub def: hir::HirId,
|
|
||||||
pub unsafety: hir::Unsafety,
|
|
||||||
from_fn: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UnsafetyState {
|
|
||||||
pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState {
|
|
||||||
UnsafetyState { def, unsafety, from_fn: true }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState {
|
|
||||||
use hir::BlockCheckMode;
|
|
||||||
match self.unsafety {
|
|
||||||
// If this unsafe, then if the outer function was already marked as
|
|
||||||
// unsafe we shouldn't attribute the unsafe'ness to the block. This
|
|
||||||
// way the block can be warned about instead of ignoring this
|
|
||||||
// extraneous block (functions are never warned about).
|
|
||||||
hir::Unsafety::Unsafe if self.from_fn => self,
|
|
||||||
|
|
||||||
unsafety => {
|
|
||||||
let (unsafety, def) = match blk.rules {
|
|
||||||
BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id),
|
|
||||||
BlockCheckMode::DefaultBlock => (unsafety, self.def),
|
|
||||||
};
|
|
||||||
UnsafetyState { def, unsafety, from_fn: false }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If this `DefId` is a "primary tables entry", returns
|
/// If this `DefId` is a "primary tables entry", returns
|
||||||
/// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`.
|
/// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`.
|
||||||
///
|
///
|
||||||
|
@ -109,6 +109,7 @@ use rustc_data_structures::{base_n, flock};
|
|||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_fs_util::{link_or_copy, LinkOrCopy};
|
use rustc_fs_util::{link_or_copy, LinkOrCopy};
|
||||||
use rustc_session::{Session, StableCrateId};
|
use rustc_session::{Session, StableCrateId};
|
||||||
|
use rustc_span::Symbol;
|
||||||
|
|
||||||
use std::fs as std_fs;
|
use std::fs as std_fs;
|
||||||
use std::io::{self, ErrorKind};
|
use std::io::{self, ErrorKind};
|
||||||
@ -202,7 +203,7 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu
|
|||||||
/// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph
|
/// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph
|
||||||
pub fn prepare_session_directory(
|
pub fn prepare_session_directory(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
crate_name: &str,
|
crate_name: Symbol,
|
||||||
stable_crate_id: StableCrateId,
|
stable_crate_id: StableCrateId,
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
if sess.opts.incremental.is_none() {
|
if sess.opts.incremental.is_none() {
|
||||||
@ -657,7 +658,7 @@ fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> {
|
|||||||
Ok(UNIX_EPOCH + duration)
|
Ok(UNIX_EPOCH + duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn crate_path(sess: &Session, crate_name: &str, stable_crate_id: StableCrateId) -> PathBuf {
|
fn crate_path(sess: &Session, crate_name: Symbol, stable_crate_id: StableCrateId) -> PathBuf {
|
||||||
let incr_dir = sess.opts.incremental.as_ref().unwrap().clone();
|
let incr_dir = sess.opts.incremental.as_ref().unwrap().clone();
|
||||||
|
|
||||||
let stable_crate_id = base_n::encode(stable_crate_id.to_u64() as u128, INT_ENCODE_BASE);
|
let stable_crate_id = base_n::encode(stable_crate_id.to_u64() as u128, INT_ENCODE_BASE);
|
||||||
|
@ -80,6 +80,7 @@ use rustc_middle::ty::{
|
|||||||
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
|
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
|
||||||
use rustc_target::spec::abi;
|
use rustc_target::spec::abi;
|
||||||
use std::ops::{ControlFlow, Deref};
|
use std::ops::{ControlFlow, Deref};
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::{cmp, fmt, iter};
|
use std::{cmp, fmt, iter};
|
||||||
|
|
||||||
mod note;
|
mod note;
|
||||||
@ -1352,10 +1353,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
.map(|(mod_str, _)| mod_str.len() + separator_len)
|
.map(|(mod_str, _)| mod_str.len() + separator_len)
|
||||||
.sum();
|
.sum();
|
||||||
|
|
||||||
debug!(
|
debug!(?separator_len, ?split_idx, ?min_len, "cmp");
|
||||||
"cmp: separator_len={}, split_idx={}, min_len={}",
|
|
||||||
separator_len, split_idx, min_len
|
|
||||||
);
|
|
||||||
|
|
||||||
if split_idx >= min_len {
|
if split_idx >= min_len {
|
||||||
// paths are identical, highlight everything
|
// paths are identical, highlight everything
|
||||||
@ -1366,7 +1364,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
} else {
|
} else {
|
||||||
let (common, uniq1) = t1_str.split_at(split_idx);
|
let (common, uniq1) = t1_str.split_at(split_idx);
|
||||||
let (_, uniq2) = t2_str.split_at(split_idx);
|
let (_, uniq2) = t2_str.split_at(split_idx);
|
||||||
debug!("cmp: common={}, uniq1={}, uniq2={}", common, uniq1, uniq2);
|
debug!(?common, ?uniq1, ?uniq2, "cmp");
|
||||||
|
|
||||||
values.0.push_normal(common);
|
values.0.push_normal(common);
|
||||||
values.0.push_highlighted(uniq1);
|
values.0.push_highlighted(uniq1);
|
||||||
@ -1659,17 +1657,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
}
|
}
|
||||||
ValuePairs::Regions(_) => (false, Mismatch::Fixed("lifetime")),
|
ValuePairs::Regions(_) => (false, Mismatch::Fixed("lifetime")),
|
||||||
};
|
};
|
||||||
let vals = match self.values_str(values) {
|
let Some(vals) = self.values_str(values) else {
|
||||||
Some((expected, found)) => Some((expected, found)),
|
// Derived error. Cancel the emitter.
|
||||||
None => {
|
// NOTE(eddyb) this was `.cancel()`, but `diag`
|
||||||
// Derived error. Cancel the emitter.
|
// is borrowed, so we can't fully defuse it.
|
||||||
// NOTE(eddyb) this was `.cancel()`, but `diag`
|
diag.downgrade_to_delayed_bug();
|
||||||
// is borrowed, so we can't fully defuse it.
|
return;
|
||||||
diag.downgrade_to_delayed_bug();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
(vals, exp_found, is_simple_error, Some(values))
|
(Some(vals), exp_found, is_simple_error, Some(values))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1701,7 +1696,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
label_or_note(span, &terr.to_string());
|
label_or_note(span, &terr.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((expected, found)) = expected_found {
|
if let Some((expected, found, exp_p, found_p)) = expected_found {
|
||||||
let (expected_label, found_label, exp_found) = match exp_found {
|
let (expected_label, found_label, exp_found) = match exp_found {
|
||||||
Mismatch::Variable(ef) => (
|
Mismatch::Variable(ef) => (
|
||||||
ef.expected.prefix_string(self.tcx),
|
ef.expected.prefix_string(self.tcx),
|
||||||
@ -1818,32 +1813,41 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
}
|
}
|
||||||
TypeError::Sorts(values) => {
|
TypeError::Sorts(values) => {
|
||||||
let extra = expected == found;
|
let extra = expected == found;
|
||||||
let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) {
|
let sort_string = |ty: Ty<'tcx>, path: Option<PathBuf>| {
|
||||||
(true, ty::Opaque(def_id, _)) => {
|
let mut s = match (extra, ty.kind()) {
|
||||||
let sm = self.tcx.sess.source_map();
|
(true, ty::Opaque(def_id, _)) => {
|
||||||
let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
|
let sm = self.tcx.sess.source_map();
|
||||||
format!(
|
let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
|
||||||
" (opaque type at <{}:{}:{}>)",
|
format!(
|
||||||
sm.filename_for_diagnostics(&pos.file.name),
|
" (opaque type at <{}:{}:{}>)",
|
||||||
pos.line,
|
sm.filename_for_diagnostics(&pos.file.name),
|
||||||
pos.col.to_usize() + 1,
|
pos.line,
|
||||||
)
|
pos.col.to_usize() + 1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
(true, ty::Projection(proj))
|
||||||
|
if self.tcx.def_kind(proj.item_def_id)
|
||||||
|
== DefKind::ImplTraitPlaceholder =>
|
||||||
|
{
|
||||||
|
let sm = self.tcx.sess.source_map();
|
||||||
|
let pos = sm.lookup_char_pos(self.tcx.def_span(proj.item_def_id).lo());
|
||||||
|
format!(
|
||||||
|
" (trait associated opaque type at <{}:{}:{}>)",
|
||||||
|
sm.filename_for_diagnostics(&pos.file.name),
|
||||||
|
pos.line,
|
||||||
|
pos.col.to_usize() + 1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
(true, _) => format!(" ({})", ty.sort_string(self.tcx)),
|
||||||
|
(false, _) => "".to_string(),
|
||||||
|
};
|
||||||
|
if let Some(path) = path {
|
||||||
|
s.push_str(&format!(
|
||||||
|
"\nthe full type name has been written to '{}'",
|
||||||
|
path.display(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
(true, ty::Projection(proj))
|
s
|
||||||
if self.tcx.def_kind(proj.item_def_id)
|
|
||||||
== DefKind::ImplTraitPlaceholder =>
|
|
||||||
{
|
|
||||||
let sm = self.tcx.sess.source_map();
|
|
||||||
let pos = sm.lookup_char_pos(self.tcx.def_span(proj.item_def_id).lo());
|
|
||||||
format!(
|
|
||||||
" (trait associated opaque type at <{}:{}:{}>)",
|
|
||||||
sm.filename_for_diagnostics(&pos.file.name),
|
|
||||||
pos.line,
|
|
||||||
pos.col.to_usize() + 1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
(true, _) => format!(" ({})", ty.sort_string(self.tcx)),
|
|
||||||
(false, _) => "".to_string(),
|
|
||||||
};
|
};
|
||||||
if !(values.expected.is_simple_text() && values.found.is_simple_text())
|
if !(values.expected.is_simple_text() && values.found.is_simple_text())
|
||||||
|| (exp_found.map_or(false, |ef| {
|
|| (exp_found.map_or(false, |ef| {
|
||||||
@ -1865,8 +1869,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
expected,
|
expected,
|
||||||
&found_label,
|
&found_label,
|
||||||
found,
|
found,
|
||||||
&sort_string(values.expected),
|
&sort_string(values.expected, exp_p),
|
||||||
&sort_string(values.found),
|
&sort_string(values.found, found_p),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2339,7 +2343,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
let code = trace.cause.code();
|
let code = trace.cause.code();
|
||||||
if let &MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = code
|
if let &MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = code
|
||||||
&& let hir::MatchSource::TryDesugar = source
|
&& let hir::MatchSource::TryDesugar = source
|
||||||
&& let Some((expected_ty, found_ty)) = self.values_str(trace.values)
|
&& let Some((expected_ty, found_ty, _, _)) = self.values_str(trace.values)
|
||||||
{
|
{
|
||||||
err.note(&format!(
|
err.note(&format!(
|
||||||
"`?` operator cannot convert from `{}` to `{}`",
|
"`?` operator cannot convert from `{}` to `{}`",
|
||||||
@ -2455,7 +2459,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
fn values_str(
|
fn values_str(
|
||||||
&self,
|
&self,
|
||||||
values: ValuePairs<'tcx>,
|
values: ValuePairs<'tcx>,
|
||||||
) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
|
) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
|
||||||
|
{
|
||||||
match values {
|
match values {
|
||||||
infer::Regions(exp_found) => self.expected_found_str(exp_found),
|
infer::Regions(exp_found) => self.expected_found_str(exp_found),
|
||||||
infer::Terms(exp_found) => self.expected_found_str_term(exp_found),
|
infer::Terms(exp_found) => self.expected_found_str_term(exp_found),
|
||||||
@ -2465,7 +2470,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
found: exp_found.found.print_only_trait_path(),
|
found: exp_found.found.print_only_trait_path(),
|
||||||
};
|
};
|
||||||
match self.expected_found_str(pretty_exp_found) {
|
match self.expected_found_str(pretty_exp_found) {
|
||||||
Some((expected, found)) if expected == found => {
|
Some((expected, found, _, _)) if expected == found => {
|
||||||
self.expected_found_str(exp_found)
|
self.expected_found_str(exp_found)
|
||||||
}
|
}
|
||||||
ret => ret,
|
ret => ret,
|
||||||
@ -2477,7 +2482,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
found: exp_found.found.print_only_trait_path(),
|
found: exp_found.found.print_only_trait_path(),
|
||||||
};
|
};
|
||||||
match self.expected_found_str(pretty_exp_found) {
|
match self.expected_found_str(pretty_exp_found) {
|
||||||
Some((expected, found)) if expected == found => {
|
Some((expected, found, _, _)) if expected == found => {
|
||||||
self.expected_found_str(exp_found)
|
self.expected_found_str(exp_found)
|
||||||
}
|
}
|
||||||
ret => ret,
|
ret => ret,
|
||||||
@ -2489,17 +2494,41 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
fn expected_found_str_term(
|
fn expected_found_str_term(
|
||||||
&self,
|
&self,
|
||||||
exp_found: ty::error::ExpectedFound<ty::Term<'tcx>>,
|
exp_found: ty::error::ExpectedFound<ty::Term<'tcx>>,
|
||||||
) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
|
) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
|
||||||
|
{
|
||||||
let exp_found = self.resolve_vars_if_possible(exp_found);
|
let exp_found = self.resolve_vars_if_possible(exp_found);
|
||||||
if exp_found.references_error() {
|
if exp_found.references_error() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(match (exp_found.expected.unpack(), exp_found.found.unpack()) {
|
Some(match (exp_found.expected.unpack(), exp_found.found.unpack()) {
|
||||||
(ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => self.cmp(expected, found),
|
(ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => {
|
||||||
|
let (mut exp, mut fnd) = self.cmp(expected, found);
|
||||||
|
// Use the terminal width as the basis to determine when to compress the printed
|
||||||
|
// out type, but give ourselves some leeway to avoid ending up creating a file for
|
||||||
|
// a type that is somewhat shorter than the path we'd write to.
|
||||||
|
let len = self.tcx.sess().diagnostic_width() + 40;
|
||||||
|
let exp_s = exp.content();
|
||||||
|
let fnd_s = fnd.content();
|
||||||
|
let mut exp_p = None;
|
||||||
|
let mut fnd_p = None;
|
||||||
|
if exp_s.len() > len {
|
||||||
|
let (exp_s, exp_path) = self.tcx.short_ty_string(expected);
|
||||||
|
exp = DiagnosticStyledString::highlighted(exp_s);
|
||||||
|
exp_p = exp_path;
|
||||||
|
}
|
||||||
|
if fnd_s.len() > len {
|
||||||
|
let (fnd_s, fnd_path) = self.tcx.short_ty_string(found);
|
||||||
|
fnd = DiagnosticStyledString::highlighted(fnd_s);
|
||||||
|
fnd_p = fnd_path;
|
||||||
|
}
|
||||||
|
(exp, fnd, exp_p, fnd_p)
|
||||||
|
}
|
||||||
_ => (
|
_ => (
|
||||||
DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
|
DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
|
||||||
DiagnosticStyledString::highlighted(exp_found.found.to_string()),
|
DiagnosticStyledString::highlighted(exp_found.found.to_string()),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -2508,7 +2537,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
|
fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
|
||||||
&self,
|
&self,
|
||||||
exp_found: ty::error::ExpectedFound<T>,
|
exp_found: ty::error::ExpectedFound<T>,
|
||||||
) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
|
) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
|
||||||
|
{
|
||||||
let exp_found = self.resolve_vars_if_possible(exp_found);
|
let exp_found = self.resolve_vars_if_possible(exp_found);
|
||||||
if exp_found.references_error() {
|
if exp_found.references_error() {
|
||||||
return None;
|
return None;
|
||||||
@ -2517,6 +2547,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
Some((
|
Some((
|
||||||
DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
|
DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
|
||||||
DiagnosticStyledString::highlighted(exp_found.found.to_string()),
|
DiagnosticStyledString::highlighted(exp_found.found.to_string()),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2850,36 +2882,29 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
debug!("report_sub_sup_conflict: sup_region={:?}", sup_region);
|
debug!("report_sub_sup_conflict: sup_region={:?}", sup_region);
|
||||||
debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin);
|
debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin);
|
||||||
|
|
||||||
if let (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) =
|
if let infer::Subtype(ref sup_trace) = sup_origin
|
||||||
(&sup_origin, &sub_origin)
|
&& let infer::Subtype(ref sub_trace) = sub_origin
|
||||||
|
&& let Some((sup_expected, sup_found, _, _)) = self.values_str(sup_trace.values)
|
||||||
|
&& let Some((sub_expected, sub_found, _, _)) = self.values_str(sub_trace.values)
|
||||||
|
&& sub_expected == sup_expected
|
||||||
|
&& sub_found == sup_found
|
||||||
{
|
{
|
||||||
debug!("report_sub_sup_conflict: sup_trace={:?}", sup_trace);
|
note_and_explain_region(
|
||||||
debug!("report_sub_sup_conflict: sub_trace={:?}", sub_trace);
|
self.tcx,
|
||||||
debug!("report_sub_sup_conflict: sup_trace.values={:?}", sup_trace.values);
|
&mut err,
|
||||||
debug!("report_sub_sup_conflict: sub_trace.values={:?}", sub_trace.values);
|
"...but the lifetime must also be valid for ",
|
||||||
|
sub_region,
|
||||||
|
"...",
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
err.span_note(
|
||||||
|
sup_trace.cause.span,
|
||||||
|
&format!("...so that the {}", sup_trace.cause.as_requirement_str()),
|
||||||
|
);
|
||||||
|
|
||||||
if let (Some((sup_expected, sup_found)), Some((sub_expected, sub_found))) =
|
err.note_expected_found(&"", sup_expected, &"", sup_found);
|
||||||
(self.values_str(sup_trace.values), self.values_str(sub_trace.values))
|
err.emit();
|
||||||
{
|
return;
|
||||||
if sub_expected == sup_expected && sub_found == sup_found {
|
|
||||||
note_and_explain_region(
|
|
||||||
self.tcx,
|
|
||||||
&mut err,
|
|
||||||
"...but the lifetime must also be valid for ",
|
|
||||||
sub_region,
|
|
||||||
"...",
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
err.span_note(
|
|
||||||
sup_trace.cause.span,
|
|
||||||
&format!("...so that the {}", sup_trace.cause.as_requirement_str()),
|
|
||||||
);
|
|
||||||
|
|
||||||
err.note_expected_found(&"", sup_expected, &"", sup_found);
|
|
||||||
err.emit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.note_region_origin(&mut err, &sup_origin);
|
self.note_region_origin(&mut err, &sup_origin);
|
||||||
|
@ -16,7 +16,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
|
infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
|
||||||
span: trace.cause.span,
|
span: trace.cause.span,
|
||||||
requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
|
requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
|
||||||
expected_found: self.values_str(trace.values),
|
expected_found: self.values_str(trace.values).map(|(e, f, _, _)| (e, f)),
|
||||||
}
|
}
|
||||||
.add_to_diagnostic(err),
|
.add_to_diagnostic(err),
|
||||||
infer::Reborrow(span) => {
|
infer::Reborrow(span) => {
|
||||||
|
@ -158,7 +158,7 @@ pub fn create_resolver(
|
|||||||
sess: Lrc<Session>,
|
sess: Lrc<Session>,
|
||||||
metadata_loader: Box<MetadataLoaderDyn>,
|
metadata_loader: Box<MetadataLoaderDyn>,
|
||||||
krate: &ast::Crate,
|
krate: &ast::Crate,
|
||||||
crate_name: &str,
|
crate_name: Symbol,
|
||||||
) -> BoxedResolver {
|
) -> BoxedResolver {
|
||||||
trace!("create_resolver");
|
trace!("create_resolver");
|
||||||
BoxedResolver::new(sess, move |sess, resolver_arenas| {
|
BoxedResolver::new(sess, move |sess, resolver_arenas| {
|
||||||
@ -171,7 +171,7 @@ pub fn register_plugins<'a>(
|
|||||||
metadata_loader: &'a dyn MetadataLoader,
|
metadata_loader: &'a dyn MetadataLoader,
|
||||||
register_lints: impl Fn(&Session, &mut LintStore),
|
register_lints: impl Fn(&Session, &mut LintStore),
|
||||||
mut krate: ast::Crate,
|
mut krate: ast::Crate,
|
||||||
crate_name: &str,
|
crate_name: Symbol,
|
||||||
) -> Result<(ast::Crate, LintStore)> {
|
) -> Result<(ast::Crate, LintStore)> {
|
||||||
krate = sess.time("attributes_injection", || {
|
krate = sess.time("attributes_injection", || {
|
||||||
rustc_builtin_macros::cmdline_attrs::inject(
|
rustc_builtin_macros::cmdline_attrs::inject(
|
||||||
@ -228,19 +228,21 @@ fn pre_expansion_lint<'a>(
|
|||||||
lint_store: &LintStore,
|
lint_store: &LintStore,
|
||||||
registered_tools: &RegisteredTools,
|
registered_tools: &RegisteredTools,
|
||||||
check_node: impl EarlyCheckNode<'a>,
|
check_node: impl EarlyCheckNode<'a>,
|
||||||
node_name: &str,
|
node_name: Symbol,
|
||||||
) {
|
) {
|
||||||
sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name).run(|| {
|
sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name.as_str()).run(
|
||||||
rustc_lint::check_ast_node(
|
|| {
|
||||||
sess,
|
rustc_lint::check_ast_node(
|
||||||
true,
|
sess,
|
||||||
lint_store,
|
true,
|
||||||
registered_tools,
|
lint_store,
|
||||||
None,
|
registered_tools,
|
||||||
rustc_lint::BuiltinCombinedPreExpansionLintPass::new(),
|
None,
|
||||||
check_node,
|
rustc_lint::BuiltinCombinedPreExpansionLintPass::new(),
|
||||||
);
|
check_node,
|
||||||
});
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cannot implement directly for `LintStore` due to trait coherence.
|
// Cannot implement directly for `LintStore` due to trait coherence.
|
||||||
@ -254,7 +256,7 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> {
|
|||||||
node_id: ast::NodeId,
|
node_id: ast::NodeId,
|
||||||
attrs: &[ast::Attribute],
|
attrs: &[ast::Attribute],
|
||||||
items: &[rustc_ast::ptr::P<ast::Item>],
|
items: &[rustc_ast::ptr::P<ast::Item>],
|
||||||
name: &str,
|
name: Symbol,
|
||||||
) {
|
) {
|
||||||
pre_expansion_lint(sess, self.0, registered_tools, (node_id, attrs, items), name);
|
pre_expansion_lint(sess, self.0, registered_tools, (node_id, attrs, items), name);
|
||||||
}
|
}
|
||||||
@ -268,7 +270,7 @@ pub fn configure_and_expand(
|
|||||||
sess: &Session,
|
sess: &Session,
|
||||||
lint_store: &LintStore,
|
lint_store: &LintStore,
|
||||||
mut krate: ast::Crate,
|
mut krate: ast::Crate,
|
||||||
crate_name: &str,
|
crate_name: Symbol,
|
||||||
resolver: &mut Resolver<'_>,
|
resolver: &mut Resolver<'_>,
|
||||||
) -> Result<ast::Crate> {
|
) -> Result<ast::Crate> {
|
||||||
trace!("configure_and_expand");
|
trace!("configure_and_expand");
|
||||||
@ -462,7 +464,7 @@ fn generated_output_paths(
|
|||||||
sess: &Session,
|
sess: &Session,
|
||||||
outputs: &OutputFilenames,
|
outputs: &OutputFilenames,
|
||||||
exact_name: bool,
|
exact_name: bool,
|
||||||
crate_name: &str,
|
crate_name: Symbol,
|
||||||
) -> Vec<PathBuf> {
|
) -> Vec<PathBuf> {
|
||||||
let mut out_filenames = Vec::new();
|
let mut out_filenames = Vec::new();
|
||||||
for output_type in sess.opts.output_types.keys() {
|
for output_type in sess.opts.output_types.keys() {
|
||||||
@ -661,7 +663,7 @@ pub fn prepare_outputs(
|
|||||||
compiler: &Compiler,
|
compiler: &Compiler,
|
||||||
krate: &ast::Crate,
|
krate: &ast::Crate,
|
||||||
boxed_resolver: &RefCell<BoxedResolver>,
|
boxed_resolver: &RefCell<BoxedResolver>,
|
||||||
crate_name: &str,
|
crate_name: Symbol,
|
||||||
) -> Result<OutputFilenames> {
|
) -> Result<OutputFilenames> {
|
||||||
let _timer = sess.timer("prepare_outputs");
|
let _timer = sess.timer("prepare_outputs");
|
||||||
|
|
||||||
@ -771,7 +773,7 @@ pub fn create_global_ctxt<'tcx>(
|
|||||||
dep_graph: DepGraph,
|
dep_graph: DepGraph,
|
||||||
resolver: Rc<RefCell<BoxedResolver>>,
|
resolver: Rc<RefCell<BoxedResolver>>,
|
||||||
outputs: OutputFilenames,
|
outputs: OutputFilenames,
|
||||||
crate_name: &str,
|
crate_name: Symbol,
|
||||||
queries: &'tcx OnceCell<TcxQueries<'tcx>>,
|
queries: &'tcx OnceCell<TcxQueries<'tcx>>,
|
||||||
global_ctxt: &'tcx OnceCell<GlobalCtxt<'tcx>>,
|
global_ctxt: &'tcx OnceCell<GlobalCtxt<'tcx>>,
|
||||||
arena: &'tcx WorkerLocal<Arena<'tcx>>,
|
arena: &'tcx WorkerLocal<Arena<'tcx>>,
|
||||||
|
@ -17,6 +17,7 @@ use rustc_query_impl::Queries as TcxQueries;
|
|||||||
use rustc_session::config::{self, OutputFilenames, OutputType};
|
use rustc_session::config::{self, OutputFilenames, OutputType};
|
||||||
use rustc_session::{output::find_crate_name, Session};
|
use rustc_session::{output::find_crate_name, Session};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
|
use rustc_span::Symbol;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::cell::{Ref, RefCell, RefMut};
|
use std::cell::{Ref, RefCell, RefMut};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@ -74,7 +75,7 @@ pub struct Queries<'tcx> {
|
|||||||
|
|
||||||
dep_graph_future: Query<Option<DepGraphFuture>>,
|
dep_graph_future: Query<Option<DepGraphFuture>>,
|
||||||
parse: Query<ast::Crate>,
|
parse: Query<ast::Crate>,
|
||||||
crate_name: Query<String>,
|
crate_name: Query<Symbol>,
|
||||||
register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
|
register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
|
||||||
expansion: Query<(Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>,
|
expansion: Query<(Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>,
|
||||||
dep_graph: Query<DepGraph>,
|
dep_graph: Query<DepGraph>,
|
||||||
@ -135,7 +136,7 @@ impl<'tcx> Queries<'tcx> {
|
|||||||
&*self.codegen_backend().metadata_loader(),
|
&*self.codegen_backend().metadata_loader(),
|
||||||
self.compiler.register_lints.as_deref().unwrap_or_else(|| empty),
|
self.compiler.register_lints.as_deref().unwrap_or_else(|| empty),
|
||||||
krate,
|
krate,
|
||||||
&crate_name,
|
crate_name,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Compute the dependency graph (in the background). We want to do
|
// Compute the dependency graph (in the background). We want to do
|
||||||
@ -149,7 +150,7 @@ impl<'tcx> Queries<'tcx> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn crate_name(&self) -> Result<&Query<String>> {
|
pub fn crate_name(&self) -> Result<&Query<Symbol>> {
|
||||||
self.crate_name.compute(|| {
|
self.crate_name.compute(|| {
|
||||||
Ok({
|
Ok({
|
||||||
let parse_result = self.parse()?;
|
let parse_result = self.parse()?;
|
||||||
@ -165,7 +166,7 @@ impl<'tcx> Queries<'tcx> {
|
|||||||
) -> Result<&Query<(Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>> {
|
) -> Result<&Query<(Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>> {
|
||||||
trace!("expansion");
|
trace!("expansion");
|
||||||
self.expansion.compute(|| {
|
self.expansion.compute(|| {
|
||||||
let crate_name = self.crate_name()?.peek().clone();
|
let crate_name = *self.crate_name()?.peek();
|
||||||
let (krate, lint_store) = self.register_plugins()?.take();
|
let (krate, lint_store) = self.register_plugins()?.take();
|
||||||
let _timer = self.session().timer("configure_and_expand");
|
let _timer = self.session().timer("configure_and_expand");
|
||||||
let sess = self.session();
|
let sess = self.session();
|
||||||
@ -173,10 +174,10 @@ impl<'tcx> Queries<'tcx> {
|
|||||||
sess.clone(),
|
sess.clone(),
|
||||||
self.codegen_backend().metadata_loader(),
|
self.codegen_backend().metadata_loader(),
|
||||||
&krate,
|
&krate,
|
||||||
&crate_name,
|
crate_name,
|
||||||
);
|
);
|
||||||
let krate = resolver.access(|resolver| {
|
let krate = resolver.access(|resolver| {
|
||||||
passes::configure_and_expand(sess, &lint_store, krate, &crate_name, resolver)
|
passes::configure_and_expand(sess, &lint_store, krate, crate_name, resolver)
|
||||||
})?;
|
})?;
|
||||||
Ok((Lrc::new(krate), Rc::new(RefCell::new(resolver)), lint_store))
|
Ok((Lrc::new(krate), Rc::new(RefCell::new(resolver)), lint_store))
|
||||||
})
|
})
|
||||||
@ -201,20 +202,20 @@ impl<'tcx> Queries<'tcx> {
|
|||||||
pub fn prepare_outputs(&self) -> Result<&Query<OutputFilenames>> {
|
pub fn prepare_outputs(&self) -> Result<&Query<OutputFilenames>> {
|
||||||
self.prepare_outputs.compute(|| {
|
self.prepare_outputs.compute(|| {
|
||||||
let (krate, boxed_resolver, _) = &*self.expansion()?.peek();
|
let (krate, boxed_resolver, _) = &*self.expansion()?.peek();
|
||||||
let crate_name = self.crate_name()?.peek();
|
let crate_name = *self.crate_name()?.peek();
|
||||||
passes::prepare_outputs(
|
passes::prepare_outputs(
|
||||||
self.session(),
|
self.session(),
|
||||||
self.compiler,
|
self.compiler,
|
||||||
krate,
|
krate,
|
||||||
&*boxed_resolver,
|
&*boxed_resolver,
|
||||||
&crate_name,
|
crate_name,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn global_ctxt(&'tcx self) -> Result<&Query<QueryContext<'tcx>>> {
|
pub fn global_ctxt(&'tcx self) -> Result<&Query<QueryContext<'tcx>>> {
|
||||||
self.global_ctxt.compute(|| {
|
self.global_ctxt.compute(|| {
|
||||||
let crate_name = self.crate_name()?.peek().clone();
|
let crate_name = *self.crate_name()?.peek();
|
||||||
let outputs = self.prepare_outputs()?.take();
|
let outputs = self.prepare_outputs()?.take();
|
||||||
let dep_graph = self.dep_graph()?.peek().clone();
|
let dep_graph = self.dep_graph()?.peek().clone();
|
||||||
let (krate, resolver, lint_store) = self.expansion()?.take();
|
let (krate, resolver, lint_store) = self.expansion()?.take();
|
||||||
@ -225,7 +226,7 @@ impl<'tcx> Queries<'tcx> {
|
|||||||
dep_graph,
|
dep_graph,
|
||||||
resolver,
|
resolver,
|
||||||
outputs,
|
outputs,
|
||||||
&crate_name,
|
crate_name,
|
||||||
&self.queries,
|
&self.queries,
|
||||||
&self.gcx,
|
&self.gcx,
|
||||||
&self.arena,
|
&self.arena,
|
||||||
|
@ -245,7 +245,7 @@ impl<'a> CrateLoader<'a> {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
metadata_loader: Box<MetadataLoaderDyn>,
|
metadata_loader: Box<MetadataLoaderDyn>,
|
||||||
local_crate_name: &str,
|
local_crate_name: Symbol,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut stable_crate_ids = FxHashMap::default();
|
let mut stable_crate_ids = FxHashMap::default();
|
||||||
stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE);
|
stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE);
|
||||||
@ -253,7 +253,7 @@ impl<'a> CrateLoader<'a> {
|
|||||||
CrateLoader {
|
CrateLoader {
|
||||||
sess,
|
sess,
|
||||||
metadata_loader,
|
metadata_loader,
|
||||||
local_crate_name: Symbol::intern(local_crate_name),
|
local_crate_name,
|
||||||
cstore: CStore {
|
cstore: CStore {
|
||||||
// We add an empty entry for LOCAL_CRATE (which maps to zero) in
|
// We add an empty entry for LOCAL_CRATE (which maps to zero) in
|
||||||
// order to make array indices in `metas` match with the
|
// order to make array indices in `metas` match with the
|
||||||
@ -1000,7 +1000,7 @@ impl<'a> CrateLoader<'a> {
|
|||||||
);
|
);
|
||||||
let name = match orig_name {
|
let name = match orig_name {
|
||||||
Some(orig_name) => {
|
Some(orig_name) => {
|
||||||
validate_crate_name(self.sess, orig_name.as_str(), Some(item.span));
|
validate_crate_name(self.sess, orig_name, Some(item.span));
|
||||||
orig_name
|
orig_name
|
||||||
}
|
}
|
||||||
None => item.ident.name,
|
None => item.ident.name,
|
||||||
|
@ -61,8 +61,7 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
|
|||||||
.unwrap_or(MetadataKind::None);
|
.unwrap_or(MetadataKind::None);
|
||||||
|
|
||||||
let crate_name = tcx.crate_name(LOCAL_CRATE);
|
let crate_name = tcx.crate_name(LOCAL_CRATE);
|
||||||
let out_filename =
|
let out_filename = filename_for_metadata(tcx.sess, crate_name, tcx.output_filenames(()));
|
||||||
filename_for_metadata(tcx.sess, crate_name.as_str(), tcx.output_filenames(()));
|
|
||||||
// To avoid races with another rustc process scanning the output directory,
|
// To avoid races with another rustc process scanning the output directory,
|
||||||
// we need to write the file somewhere else and atomically move it to its
|
// we need to write the file somewhere else and atomically move it to its
|
||||||
// final destination, with an `fs::rename` call. In order for the rename to
|
// final destination, with an `fs::rename` call. In order for the rename to
|
||||||
|
@ -400,7 +400,7 @@ impl std::fmt::Display for NonDivergingIntrinsic<'_> {
|
|||||||
#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, HashStable)]
|
#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, HashStable)]
|
||||||
#[rustc_pass_by_value]
|
#[rustc_pass_by_value]
|
||||||
pub enum RetagKind {
|
pub enum RetagKind {
|
||||||
/// The initial retag when entering a function.
|
/// The initial retag of arguments when entering a function.
|
||||||
FnEntry,
|
FnEntry,
|
||||||
/// Retag preparing for a two-phase borrow.
|
/// Retag preparing for a two-phase borrow.
|
||||||
TwoPhase,
|
TwoPhase,
|
||||||
|
@ -1285,7 +1285,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
|
on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
|
||||||
queries: &'tcx dyn query::QueryEngine<'tcx>,
|
queries: &'tcx dyn query::QueryEngine<'tcx>,
|
||||||
query_kinds: &'tcx [DepKindStruct<'tcx>],
|
query_kinds: &'tcx [DepKindStruct<'tcx>],
|
||||||
crate_name: &str,
|
crate_name: Symbol,
|
||||||
output_filenames: OutputFilenames,
|
output_filenames: OutputFilenames,
|
||||||
) -> GlobalCtxt<'tcx> {
|
) -> GlobalCtxt<'tcx> {
|
||||||
let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
|
let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
|
||||||
@ -1325,7 +1325,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
pred_rcache: Default::default(),
|
pred_rcache: Default::default(),
|
||||||
selection_cache: Default::default(),
|
selection_cache: Default::default(),
|
||||||
evaluation_cache: Default::default(),
|
evaluation_cache: Default::default(),
|
||||||
crate_name: Symbol::intern(crate_name),
|
crate_name,
|
||||||
data_layout,
|
data_layout,
|
||||||
alloc_map: Lock::new(interpret::AllocMap::new()),
|
alloc_map: Lock::new(interpret::AllocMap::new()),
|
||||||
output_filenames: Arc::new(output_filenames),
|
output_filenames: Arc::new(output_filenames),
|
||||||
|
@ -986,23 +986,32 @@ fn foo(&self) -> Self::T { String::new() }
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
|
pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
|
||||||
let length_limit = 50;
|
let width = self.sess.diagnostic_width();
|
||||||
let type_limit = 4;
|
let length_limit = width.saturating_sub(30);
|
||||||
|
let mut type_limit = 50;
|
||||||
let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS)
|
let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS)
|
||||||
.pretty_print_type(ty)
|
.pretty_print_type(ty)
|
||||||
.expect("could not write to `String`")
|
.expect("could not write to `String`")
|
||||||
.into_buffer();
|
.into_buffer();
|
||||||
if regular.len() <= length_limit {
|
if regular.len() <= width {
|
||||||
return (regular, None);
|
return (regular, None);
|
||||||
}
|
}
|
||||||
let short = FmtPrinter::new_with_limit(
|
let mut short;
|
||||||
self,
|
loop {
|
||||||
hir::def::Namespace::TypeNS,
|
// Look for the longest properly trimmed path that still fits in lenght_limit.
|
||||||
rustc_session::Limit(type_limit),
|
short = FmtPrinter::new_with_limit(
|
||||||
)
|
self,
|
||||||
.pretty_print_type(ty)
|
hir::def::Namespace::TypeNS,
|
||||||
.expect("could not write to `String`")
|
rustc_session::Limit(type_limit),
|
||||||
.into_buffer();
|
)
|
||||||
|
.pretty_print_type(ty)
|
||||||
|
.expect("could not write to `String`")
|
||||||
|
.into_buffer();
|
||||||
|
if short.len() <= length_limit || type_limit == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
type_limit -= 1;
|
||||||
|
}
|
||||||
if regular == short {
|
if regular == short {
|
||||||
return (regular, None);
|
return (regular, None);
|
||||||
}
|
}
|
||||||
|
@ -10,16 +10,6 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
|
|||||||
|
|
||||||
pub struct AddRetag;
|
pub struct AddRetag;
|
||||||
|
|
||||||
/// Determines whether this place is "stable": Whether, if we evaluate it again
|
|
||||||
/// after the assignment, we can be sure to obtain the same place value.
|
|
||||||
/// (Concurrent accesses by other threads are no problem as these are anyway non-atomic
|
|
||||||
/// copies. Data races are UB.)
|
|
||||||
fn is_stable(place: PlaceRef<'_>) -> bool {
|
|
||||||
// Which place this evaluates to can change with any memory write,
|
|
||||||
// so cannot assume deref to be stable.
|
|
||||||
!place.has_deref()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Determine whether this type may contain a reference (or box), and thus needs retagging.
|
/// Determine whether this type may contain a reference (or box), and thus needs retagging.
|
||||||
/// We will only recurse `depth` times into Tuples/ADTs to bound the cost of this.
|
/// We will only recurse `depth` times into Tuples/ADTs to bound the cost of this.
|
||||||
fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> bool {
|
fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> bool {
|
||||||
@ -69,22 +59,10 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
|
|||||||
let basic_blocks = body.basic_blocks.as_mut();
|
let basic_blocks = body.basic_blocks.as_mut();
|
||||||
let local_decls = &body.local_decls;
|
let local_decls = &body.local_decls;
|
||||||
let needs_retag = |place: &Place<'tcx>| {
|
let needs_retag = |place: &Place<'tcx>| {
|
||||||
// FIXME: Instead of giving up for unstable places, we should introduce
|
!place.has_deref() // we're not eally interested in stores to "outside" locations, they are hard to keep track of anyway
|
||||||
// a temporary and retag on that.
|
|
||||||
is_stable(place.as_ref())
|
|
||||||
&& may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx)
|
&& may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx)
|
||||||
&& !local_decls[place.local].is_deref_temp()
|
&& !local_decls[place.local].is_deref_temp()
|
||||||
};
|
};
|
||||||
let place_base_raw = |place: &Place<'tcx>| {
|
|
||||||
// If this is a `Deref`, get the type of what we are deref'ing.
|
|
||||||
if place.has_deref() {
|
|
||||||
let ty = &local_decls[place.local].ty;
|
|
||||||
ty.is_unsafe_ptr()
|
|
||||||
} else {
|
|
||||||
// Not a deref, and thus not raw.
|
|
||||||
false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// PART 1
|
// PART 1
|
||||||
// Retag arguments at the beginning of the start block.
|
// Retag arguments at the beginning of the start block.
|
||||||
@ -108,7 +86,7 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PART 2
|
// PART 2
|
||||||
// Retag return values of functions. Also escape-to-raw the argument of `drop`.
|
// Retag return values of functions.
|
||||||
// We collect the return destinations because we cannot mutate while iterating.
|
// We collect the return destinations because we cannot mutate while iterating.
|
||||||
let returns = basic_blocks
|
let returns = basic_blocks
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
@ -140,30 +118,25 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PART 3
|
// PART 3
|
||||||
// Add retag after assignment.
|
// Add retag after assignments where data "enters" this function: the RHS is behind a deref and the LHS is not.
|
||||||
for block_data in basic_blocks {
|
for block_data in basic_blocks {
|
||||||
// We want to insert statements as we iterate. To this end, we
|
// We want to insert statements as we iterate. To this end, we
|
||||||
// iterate backwards using indices.
|
// iterate backwards using indices.
|
||||||
for i in (0..block_data.statements.len()).rev() {
|
for i in (0..block_data.statements.len()).rev() {
|
||||||
let (retag_kind, place) = match block_data.statements[i].kind {
|
let (retag_kind, place) = match block_data.statements[i].kind {
|
||||||
// Retag-as-raw after escaping to a raw pointer, if the referent
|
|
||||||
// is not already a raw pointer.
|
|
||||||
StatementKind::Assign(box (lplace, Rvalue::AddressOf(_, ref rplace)))
|
|
||||||
if !place_base_raw(rplace) =>
|
|
||||||
{
|
|
||||||
(RetagKind::Raw, lplace)
|
|
||||||
}
|
|
||||||
// Retag after assignments of reference type.
|
// Retag after assignments of reference type.
|
||||||
StatementKind::Assign(box (ref place, ref rvalue)) if needs_retag(place) => {
|
StatementKind::Assign(box (ref place, ref rvalue)) if needs_retag(place) => {
|
||||||
let kind = match rvalue {
|
let add_retag = match rvalue {
|
||||||
Rvalue::Ref(_, borrow_kind, _)
|
// Ptr-creating operations already do their own internal retagging, no
|
||||||
if borrow_kind.allows_two_phase_borrow() =>
|
// need to also add a retag statement.
|
||||||
{
|
Rvalue::Ref(..) | Rvalue::AddressOf(..) => false,
|
||||||
RetagKind::TwoPhase
|
_ => true,
|
||||||
}
|
|
||||||
_ => RetagKind::Default,
|
|
||||||
};
|
};
|
||||||
(kind, *place)
|
if add_retag {
|
||||||
|
(RetagKind::Default, *place)
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Do nothing for the rest
|
// Do nothing for the rest
|
||||||
_ => continue,
|
_ => continue,
|
||||||
|
@ -985,16 +985,6 @@ fn create_generator_drop_shim<'tcx>(
|
|||||||
tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }),
|
tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }),
|
||||||
source_info,
|
source_info,
|
||||||
);
|
);
|
||||||
if tcx.sess.opts.unstable_opts.mir_emit_retag {
|
|
||||||
// Alias tracking must know we changed the type
|
|
||||||
body.basic_blocks_mut()[START_BLOCK].statements.insert(
|
|
||||||
0,
|
|
||||||
Statement {
|
|
||||||
source_info,
|
|
||||||
kind: StatementKind::Retag(RetagKind::Raw, Box::new(Place::from(SELF_ARG))),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we remove dead blocks to remove
|
// Make sure we remove dead blocks to remove
|
||||||
// unrelated code from the resume part of the function
|
// unrelated code from the resume part of the function
|
||||||
|
@ -177,16 +177,6 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
|
|||||||
if ty.is_some() {
|
if ty.is_some() {
|
||||||
// The first argument (index 0), but add 1 for the return value.
|
// The first argument (index 0), but add 1 for the return value.
|
||||||
let dropee_ptr = Place::from(Local::new(1 + 0));
|
let dropee_ptr = Place::from(Local::new(1 + 0));
|
||||||
if tcx.sess.opts.unstable_opts.mir_emit_retag {
|
|
||||||
// Function arguments should be retagged, and we make this one raw.
|
|
||||||
body.basic_blocks_mut()[START_BLOCK].statements.insert(
|
|
||||||
0,
|
|
||||||
Statement {
|
|
||||||
source_info,
|
|
||||||
kind: StatementKind::Retag(RetagKind::Raw, Box::new(dropee_ptr)),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
let patch = {
|
let patch = {
|
||||||
let param_env = tcx.param_env_reveal_all_normalized(def_id);
|
let param_env = tcx.param_env_reveal_all_normalized(def_id);
|
||||||
let mut elaborator =
|
let mut elaborator =
|
||||||
|
@ -1196,7 +1196,7 @@ impl<'a> Resolver<'a> {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
session: &'a Session,
|
session: &'a Session,
|
||||||
krate: &Crate,
|
krate: &Crate,
|
||||||
crate_name: &str,
|
crate_name: Symbol,
|
||||||
metadata_loader: Box<MetadataLoaderDyn>,
|
metadata_loader: Box<MetadataLoaderDyn>,
|
||||||
arenas: &'a ResolverArenas<'a>,
|
arenas: &'a ResolverArenas<'a>,
|
||||||
) -> Resolver<'a> {
|
) -> Resolver<'a> {
|
||||||
|
@ -111,7 +111,7 @@ impl<'tcx> DumpVisitor<'tcx> {
|
|||||||
self.save_ctxt.lookup_def_id(ref_id)
|
self.save_ctxt.lookup_def_id(ref_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dump_crate_info(&mut self, name: &str) {
|
pub fn dump_crate_info(&mut self, name: Symbol) {
|
||||||
let source_file = self.tcx.sess.local_crate_source_file.as_ref();
|
let source_file = self.tcx.sess.local_crate_source_file.as_ref();
|
||||||
let crate_root = source_file.map(|source_file| {
|
let crate_root = source_file.map(|source_file| {
|
||||||
let source_file = Path::new(source_file);
|
let source_file = Path::new(source_file);
|
||||||
@ -124,7 +124,7 @@ impl<'tcx> DumpVisitor<'tcx> {
|
|||||||
|
|
||||||
let data = CratePreludeData {
|
let data = CratePreludeData {
|
||||||
crate_id: GlobalCrateId {
|
crate_id: GlobalCrateId {
|
||||||
name: name.into(),
|
name: name.to_string(),
|
||||||
disambiguator: (self.tcx.sess.local_stable_crate_id().to_u64(), 0),
|
disambiguator: (self.tcx.sess.local_stable_crate_id().to_u64(), 0),
|
||||||
},
|
},
|
||||||
crate_root: crate_root.unwrap_or_else(|| "<no source>".to_owned()),
|
crate_root: crate_root.unwrap_or_else(|| "<no source>".to_owned()),
|
||||||
@ -135,7 +135,7 @@ impl<'tcx> DumpVisitor<'tcx> {
|
|||||||
self.dumper.crate_prelude(data);
|
self.dumper.crate_prelude(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dump_compilation_options(&mut self, input: &Input, crate_name: &str) {
|
pub fn dump_compilation_options(&mut self, input: &Input, crate_name: Symbol) {
|
||||||
// Apply possible `remap-path-prefix` remapping to the input source file
|
// Apply possible `remap-path-prefix` remapping to the input source file
|
||||||
// (and don't include remapping args anymore)
|
// (and don't include remapping args anymore)
|
||||||
let (program, arguments) = {
|
let (program, arguments) = {
|
||||||
|
@ -95,7 +95,7 @@ impl<'tcx> SaveContext<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns path to the compilation output (e.g., libfoo-12345678.rmeta)
|
/// Returns path to the compilation output (e.g., libfoo-12345678.rmeta)
|
||||||
pub fn compilation_output(&self, crate_name: &str) -> PathBuf {
|
pub fn compilation_output(&self, crate_name: Symbol) -> PathBuf {
|
||||||
let sess = &self.tcx.sess;
|
let sess = &self.tcx.sess;
|
||||||
// Save-analysis is emitted per whole session, not per each crate type
|
// Save-analysis is emitted per whole session, not per each crate type
|
||||||
let crate_type = sess.crate_types()[0];
|
let crate_type = sess.crate_types()[0];
|
||||||
@ -894,8 +894,8 @@ pub struct DumpHandler<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DumpHandler<'a> {
|
impl<'a> DumpHandler<'a> {
|
||||||
pub fn new(odir: Option<&'a Path>, cratename: &str) -> DumpHandler<'a> {
|
pub fn new(odir: Option<&'a Path>, cratename: Symbol) -> DumpHandler<'a> {
|
||||||
DumpHandler { odir, cratename: cratename.to_owned() }
|
DumpHandler { odir, cratename: cratename.to_string() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn output_file(&self, ctx: &SaveContext<'_>) -> (BufWriter<File>, PathBuf) {
|
fn output_file(&self, ctx: &SaveContext<'_>) -> (BufWriter<File>, PathBuf) {
|
||||||
@ -960,7 +960,7 @@ impl SaveHandler for CallbackHandler<'_> {
|
|||||||
|
|
||||||
pub fn process_crate<'l, 'tcx, H: SaveHandler>(
|
pub fn process_crate<'l, 'tcx, H: SaveHandler>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
cratename: &str,
|
cratename: Symbol,
|
||||||
input: &'l Input,
|
input: &'l Input,
|
||||||
config: Option<Config>,
|
config: Option<Config>,
|
||||||
mut handler: H,
|
mut handler: H,
|
||||||
|
@ -18,6 +18,7 @@ rustc_fs_util = { path = "../rustc_fs_util" }
|
|||||||
rustc_ast = { path = "../rustc_ast" }
|
rustc_ast = { path = "../rustc_ast" }
|
||||||
rustc_lint_defs = { path = "../rustc_lint_defs" }
|
rustc_lint_defs = { path = "../rustc_lint_defs" }
|
||||||
smallvec = "1.8.1"
|
smallvec = "1.8.1"
|
||||||
|
termize = "0.1.1"
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
@ -129,10 +129,10 @@ pub struct FileIsNotWriteable<'a> {
|
|||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(session_crate_name_does_not_match)]
|
#[diag(session_crate_name_does_not_match)]
|
||||||
pub struct CrateNameDoesNotMatch<'a> {
|
pub struct CrateNameDoesNotMatch {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub s: &'a str,
|
pub s: Symbol,
|
||||||
pub name: Symbol,
|
pub name: Symbol,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,11 +151,11 @@ pub struct CrateNameEmpty {
|
|||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(session_invalid_character_in_create_name)]
|
#[diag(session_invalid_character_in_create_name)]
|
||||||
pub struct InvalidCharacterInCrateName<'a> {
|
pub struct InvalidCharacterInCrateName {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Option<Span>,
|
pub span: Option<Span>,
|
||||||
pub character: char,
|
pub character: char,
|
||||||
pub crate_name: &'a str,
|
pub crate_name: Symbol,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subdiagnostic)]
|
#[derive(Subdiagnostic)]
|
||||||
|
@ -7,14 +7,14 @@ use crate::errors::{
|
|||||||
use crate::Session;
|
use crate::Session;
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::Span;
|
use rustc_span::{Span, Symbol};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
pub fn out_filename(
|
pub fn out_filename(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
crate_type: CrateType,
|
crate_type: CrateType,
|
||||||
outputs: &OutputFilenames,
|
outputs: &OutputFilenames,
|
||||||
crate_name: &str,
|
crate_name: Symbol,
|
||||||
) -> PathBuf {
|
) -> PathBuf {
|
||||||
let default_filename = filename_for_input(sess, crate_type, crate_name, outputs);
|
let default_filename = filename_for_input(sess, crate_type, crate_name, outputs);
|
||||||
let out_filename = outputs
|
let out_filename = outputs
|
||||||
@ -45,9 +45,9 @@ fn is_writeable(p: &Path) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) -> String {
|
pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) -> Symbol {
|
||||||
let validate = |s: String, span: Option<Span>| {
|
let validate = |s: Symbol, span: Option<Span>| {
|
||||||
validate_crate_name(sess, &s, span);
|
validate_crate_name(sess, s, span);
|
||||||
s
|
s
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -59,38 +59,39 @@ pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input)
|
|||||||
sess.find_by_name(attrs, sym::crate_name).and_then(|at| at.value_str().map(|s| (at, s)));
|
sess.find_by_name(attrs, sym::crate_name).and_then(|at| at.value_str().map(|s| (at, s)));
|
||||||
|
|
||||||
if let Some(ref s) = sess.opts.crate_name {
|
if let Some(ref s) = sess.opts.crate_name {
|
||||||
|
let s = Symbol::intern(s);
|
||||||
if let Some((attr, name)) = attr_crate_name {
|
if let Some((attr, name)) = attr_crate_name {
|
||||||
if name.as_str() != s {
|
if name != s {
|
||||||
sess.emit_err(CrateNameDoesNotMatch { span: attr.span, s, name });
|
sess.emit_err(CrateNameDoesNotMatch { span: attr.span, s, name });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return validate(s.clone(), None);
|
return validate(s, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((attr, s)) = attr_crate_name {
|
if let Some((attr, s)) = attr_crate_name {
|
||||||
return validate(s.to_string(), Some(attr.span));
|
return validate(s, Some(attr.span));
|
||||||
}
|
}
|
||||||
if let Input::File(ref path) = *input {
|
if let Input::File(ref path) = *input {
|
||||||
if let Some(s) = path.file_stem().and_then(|s| s.to_str()) {
|
if let Some(s) = path.file_stem().and_then(|s| s.to_str()) {
|
||||||
if s.starts_with('-') {
|
if s.starts_with('-') {
|
||||||
sess.emit_err(CrateNameInvalid { s });
|
sess.emit_err(CrateNameInvalid { s });
|
||||||
} else {
|
} else {
|
||||||
return validate(s.replace('-', "_"), None);
|
return validate(Symbol::intern(&s.replace('-', "_")), None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"rust_out".to_string()
|
Symbol::intern("rust_out")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn validate_crate_name(sess: &Session, s: &str, sp: Option<Span>) {
|
pub fn validate_crate_name(sess: &Session, s: Symbol, sp: Option<Span>) {
|
||||||
let mut err_count = 0;
|
let mut err_count = 0;
|
||||||
{
|
{
|
||||||
if s.is_empty() {
|
if s.is_empty() {
|
||||||
err_count += 1;
|
err_count += 1;
|
||||||
sess.emit_err(CrateNameEmpty { span: sp });
|
sess.emit_err(CrateNameEmpty { span: sp });
|
||||||
}
|
}
|
||||||
for c in s.chars() {
|
for c in s.as_str().chars() {
|
||||||
if c.is_alphanumeric() {
|
if c.is_alphanumeric() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -109,7 +110,7 @@ pub fn validate_crate_name(sess: &Session, s: &str, sp: Option<Span>) {
|
|||||||
|
|
||||||
pub fn filename_for_metadata(
|
pub fn filename_for_metadata(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
crate_name: &str,
|
crate_name: Symbol,
|
||||||
outputs: &OutputFilenames,
|
outputs: &OutputFilenames,
|
||||||
) -> PathBuf {
|
) -> PathBuf {
|
||||||
// If the command-line specified the path, use that directly.
|
// If the command-line specified the path, use that directly.
|
||||||
@ -132,7 +133,7 @@ pub fn filename_for_metadata(
|
|||||||
pub fn filename_for_input(
|
pub fn filename_for_input(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
crate_type: CrateType,
|
crate_type: CrateType,
|
||||||
crate_name: &str,
|
crate_name: Symbol,
|
||||||
outputs: &OutputFilenames,
|
outputs: &OutputFilenames,
|
||||||
) -> PathBuf {
|
) -> PathBuf {
|
||||||
let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);
|
let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);
|
||||||
|
@ -952,6 +952,17 @@ impl Session {
|
|||||||
) -> Option<Symbol> {
|
) -> Option<Symbol> {
|
||||||
attrs.iter().find(|at| at.has_name(name)).and_then(|at| at.value_str())
|
attrs.iter().find(|at| at.has_name(name)).and_then(|at| at.value_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn diagnostic_width(&self) -> usize {
|
||||||
|
let default_column_width = 140;
|
||||||
|
if let Some(width) = self.opts.diagnostic_width {
|
||||||
|
width
|
||||||
|
} else if self.opts.unstable_opts.ui_testing {
|
||||||
|
default_column_width
|
||||||
|
} else {
|
||||||
|
termize::dimensions().map_or(default_column_width, |(w, _)| w)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// JUSTIFICATION: defn of the suggested wrapper fns
|
// JUSTIFICATION: defn of the suggested wrapper fns
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::HashStableContext;
|
use crate::{HashStableContext, Symbol};
|
||||||
use rustc_data_structures::fingerprint::Fingerprint;
|
use rustc_data_structures::fingerprint::Fingerprint;
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
|
||||||
use rustc_data_structures::AtomicRef;
|
use rustc_data_structures::AtomicRef;
|
||||||
@ -149,9 +149,11 @@ impl StableCrateId {
|
|||||||
|
|
||||||
/// Computes the stable ID for a crate with the given name and
|
/// Computes the stable ID for a crate with the given name and
|
||||||
/// `-Cmetadata` arguments.
|
/// `-Cmetadata` arguments.
|
||||||
pub fn new(crate_name: &str, is_exe: bool, mut metadata: Vec<String>) -> StableCrateId {
|
pub fn new(crate_name: Symbol, is_exe: bool, mut metadata: Vec<String>) -> StableCrateId {
|
||||||
let mut hasher = StableHasher::new();
|
let mut hasher = StableHasher::new();
|
||||||
crate_name.hash(&mut hasher);
|
// We must hash the string text of the crate name, not the id, as the id is not stable
|
||||||
|
// across builds.
|
||||||
|
crate_name.as_str().hash(&mut hasher);
|
||||||
|
|
||||||
// We don't want the stable crate ID to depend on the order of
|
// We don't want the stable crate ID to depend on the order of
|
||||||
// -C metadata arguments, so sort them:
|
// -C metadata arguments, so sort them:
|
||||||
|
@ -33,12 +33,6 @@ pub fn target() -> Target {
|
|||||||
// For now this target just never has an entry symbol no matter the output
|
// For now this target just never has an entry symbol no matter the output
|
||||||
// type, so unconditionally pass this.
|
// type, so unconditionally pass this.
|
||||||
"--no-entry",
|
"--no-entry",
|
||||||
// Rust really needs a way for users to specify exports and imports in
|
|
||||||
// the source code. --export-dynamic isn't the right tool for this job,
|
|
||||||
// however it does have the side effect of automatically exporting a lot
|
|
||||||
// of symbols, which approximates what people want when compiling for
|
|
||||||
// wasm32-unknown-unknown expect, so use it for now.
|
|
||||||
"--export-dynamic",
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
options.add_pre_link_args(
|
options.add_pre_link_args(
|
||||||
@ -48,7 +42,6 @@ pub fn target() -> Target {
|
|||||||
// otherwise
|
// otherwise
|
||||||
"--target=wasm32-unknown-unknown",
|
"--target=wasm32-unknown-unknown",
|
||||||
"-Wl,--no-entry",
|
"-Wl,--no-entry",
|
||||||
"-Wl,--export-dynamic",
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -4,12 +4,14 @@
|
|||||||
|
|
||||||
use crate::ascii;
|
use crate::ascii;
|
||||||
use crate::convert::TryInto;
|
use crate::convert::TryInto;
|
||||||
use crate::error::Error;
|
|
||||||
use crate::intrinsics;
|
use crate::intrinsics;
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
use crate::ops::{Add, Mul, Sub};
|
use crate::ops::{Add, Mul, Sub};
|
||||||
use crate::str::FromStr;
|
use crate::str::FromStr;
|
||||||
|
|
||||||
|
#[cfg(not(no_fp_fmt_parse))]
|
||||||
|
use crate::error::Error;
|
||||||
|
|
||||||
// Used because the `?` operator is not allowed in a const context.
|
// Used because the `?` operator is not allowed in a const context.
|
||||||
macro_rules! try_opt {
|
macro_rules! try_opt {
|
||||||
($e:expr) => {
|
($e:expr) => {
|
||||||
|
@ -71,7 +71,7 @@ impl Condvar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe { mutex.lock() };
|
mutex.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
|
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
|
||||||
@ -109,7 +109,7 @@ impl Condvar {
|
|||||||
// we woke up because of `notify_*`.
|
// we woke up because of `notify_*`.
|
||||||
let success = self.waiters.with_locked(|waiters| unsafe { !waiters.remove(waiter) });
|
let success = self.waiters.with_locked(|waiters| unsafe { !waiters.remove(waiter) });
|
||||||
|
|
||||||
unsafe { mutex.lock() };
|
mutex.lock();
|
||||||
success
|
success
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ pub(super) struct MutexGuard<'a>(&'a Mutex);
|
|||||||
impl<'a> MutexGuard<'a> {
|
impl<'a> MutexGuard<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) fn lock(x: &'a Mutex) -> Self {
|
pub(super) fn lock(x: &'a Mutex) -> Self {
|
||||||
unsafe { x.lock() };
|
x.lock();
|
||||||
Self(x)
|
Self(x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,18 +11,25 @@ use crate::{
|
|||||||
ffi::CStr,
|
ffi::CStr,
|
||||||
hint, io,
|
hint, io,
|
||||||
mem::ManuallyDrop,
|
mem::ManuallyDrop,
|
||||||
|
ptr::NonNull,
|
||||||
sync::atomic::{AtomicUsize, Ordering},
|
sync::atomic::{AtomicUsize, Ordering},
|
||||||
sys::thread_local_dtor::run_dtors,
|
sys::thread_local_dtor::run_dtors,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Thread {
|
pub struct Thread {
|
||||||
inner: ManuallyDrop<Box<ThreadInner>>,
|
p_inner: NonNull<ThreadInner>,
|
||||||
|
|
||||||
/// The ID of the underlying task.
|
/// The ID of the underlying task.
|
||||||
task: abi::ID,
|
task: abi::ID,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Safety: There's nothing in `Thread` that ties it to the original creator. It
|
||||||
|
// can be dropped by any threads.
|
||||||
|
unsafe impl Send for Thread {}
|
||||||
|
// Safety: `Thread` provides no methods that take `&self`.
|
||||||
|
unsafe impl Sync for Thread {}
|
||||||
|
|
||||||
/// State data shared between a parent thread and child thread. It's dropped on
|
/// State data shared between a parent thread and child thread. It's dropped on
|
||||||
/// a transition to one of the final states.
|
/// a transition to one of the final states.
|
||||||
struct ThreadInner {
|
struct ThreadInner {
|
||||||
@ -90,8 +97,9 @@ impl Thread {
|
|||||||
});
|
});
|
||||||
|
|
||||||
unsafe extern "C" fn trampoline(exinf: isize) {
|
unsafe extern "C" fn trampoline(exinf: isize) {
|
||||||
|
let p_inner: *mut ThreadInner = crate::ptr::from_exposed_addr_mut(exinf as usize);
|
||||||
// Safety: `ThreadInner` is alive at this point
|
// Safety: `ThreadInner` is alive at this point
|
||||||
let inner = unsafe { &*(exinf as *const ThreadInner) };
|
let inner = unsafe { &*p_inner };
|
||||||
|
|
||||||
// Safety: Since `trampoline` is called only once for each
|
// Safety: Since `trampoline` is called only once for each
|
||||||
// `ThreadInner` and only `trampoline` touches `start`,
|
// `ThreadInner` and only `trampoline` touches `start`,
|
||||||
@ -119,13 +127,13 @@ impl Thread {
|
|||||||
// No one will ever join, so we'll ask the collector task to
|
// No one will ever join, so we'll ask the collector task to
|
||||||
// delete the task.
|
// delete the task.
|
||||||
|
|
||||||
// In this case, `inner`'s ownership has been moved to us,
|
// In this case, `*p_inner`'s ownership has been moved to
|
||||||
// And we are responsible for dropping it. The acquire
|
// us, and we are responsible for dropping it. The acquire
|
||||||
// ordering is not necessary because the parent thread made
|
// ordering is not necessary because the parent thread made
|
||||||
// no memory access needing synchronization since the call
|
// no memory access needing synchronization since the call
|
||||||
// to `acre_tsk`.
|
// to `acre_tsk`.
|
||||||
// Safety: See above.
|
// Safety: See above.
|
||||||
let _ = unsafe { Box::from_raw(inner as *const _ as *mut ThreadInner) };
|
let _ = unsafe { Box::from_raw(p_inner) };
|
||||||
|
|
||||||
// Safety: There are no pinned references to the stack
|
// Safety: There are no pinned references to the stack
|
||||||
unsafe { terminate_and_delete_current_task() };
|
unsafe { terminate_and_delete_current_task() };
|
||||||
@ -162,13 +170,14 @@ impl Thread {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let inner_ptr = (&*inner) as *const ThreadInner;
|
// Safety: `Box::into_raw` returns a non-null pointer
|
||||||
|
let p_inner = unsafe { NonNull::new_unchecked(Box::into_raw(inner)) };
|
||||||
|
|
||||||
let new_task = ItronError::err_if_negative(unsafe {
|
let new_task = ItronError::err_if_negative(unsafe {
|
||||||
abi::acre_tsk(&abi::T_CTSK {
|
abi::acre_tsk(&abi::T_CTSK {
|
||||||
// Activate this task immediately
|
// Activate this task immediately
|
||||||
tskatr: abi::TA_ACT,
|
tskatr: abi::TA_ACT,
|
||||||
exinf: inner_ptr as abi::EXINF,
|
exinf: p_inner.as_ptr().expose_addr() as abi::EXINF,
|
||||||
// The entry point
|
// The entry point
|
||||||
task: Some(trampoline),
|
task: Some(trampoline),
|
||||||
// Inherit the calling task's base priority
|
// Inherit the calling task's base priority
|
||||||
@ -180,7 +189,7 @@ impl Thread {
|
|||||||
})
|
})
|
||||||
.map_err(|e| e.as_io_error())?;
|
.map_err(|e| e.as_io_error())?;
|
||||||
|
|
||||||
Ok(Self { inner: ManuallyDrop::new(inner), task: new_task })
|
Ok(Self { p_inner, task: new_task })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn yield_now() {
|
pub fn yield_now() {
|
||||||
@ -197,8 +206,9 @@ impl Thread {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn join(mut self) {
|
pub fn join(self) {
|
||||||
let inner = &*self.inner;
|
// Safety: `ThreadInner` is alive at this point
|
||||||
|
let inner = unsafe { self.p_inner.as_ref() };
|
||||||
// Get the current task ID. Panicking here would cause a resource leak,
|
// Get the current task ID. Panicking here would cause a resource leak,
|
||||||
// so just abort on failure.
|
// so just abort on failure.
|
||||||
let current_task = task::current_task_id_aborting();
|
let current_task = task::current_task_id_aborting();
|
||||||
@ -243,8 +253,8 @@ impl Thread {
|
|||||||
unsafe { terminate_and_delete_task(self.task) };
|
unsafe { terminate_and_delete_task(self.task) };
|
||||||
|
|
||||||
// In either case, we are responsible for dropping `inner`.
|
// In either case, we are responsible for dropping `inner`.
|
||||||
// Safety: The contents of `self.inner` will not be accessed hereafter
|
// Safety: The contents of `*p_inner` will not be accessed hereafter
|
||||||
let _inner = unsafe { ManuallyDrop::take(&mut self.inner) };
|
let _inner = unsafe { Box::from_raw(self.p_inner.as_ptr()) };
|
||||||
|
|
||||||
// Skip the destructor (because it would attempt to detach the thread)
|
// Skip the destructor (because it would attempt to detach the thread)
|
||||||
crate::mem::forget(self);
|
crate::mem::forget(self);
|
||||||
@ -253,13 +263,16 @@ impl Thread {
|
|||||||
|
|
||||||
impl Drop for Thread {
|
impl Drop for Thread {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
// Safety: `ThreadInner` is alive at this point
|
||||||
|
let inner = unsafe { self.p_inner.as_ref() };
|
||||||
|
|
||||||
// Detach the thread.
|
// Detach the thread.
|
||||||
match self.inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::Acquire) {
|
match inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::Acquire) {
|
||||||
LIFECYCLE_INIT => {
|
LIFECYCLE_INIT => {
|
||||||
// [INIT → DETACHED]
|
// [INIT → DETACHED]
|
||||||
// When the time comes, the child will figure out that no
|
// When the time comes, the child will figure out that no
|
||||||
// one will ever join it.
|
// one will ever join it.
|
||||||
// The ownership of `self.inner` is moved to the child thread.
|
// The ownership of `*p_inner` is moved to the child thread.
|
||||||
// However, the release ordering is not necessary because we
|
// However, the release ordering is not necessary because we
|
||||||
// made no memory access needing synchronization since the call
|
// made no memory access needing synchronization since the call
|
||||||
// to `acre_tsk`.
|
// to `acre_tsk`.
|
||||||
@ -278,10 +291,9 @@ impl Drop for Thread {
|
|||||||
// delete by entering the `FINISHED` state.
|
// delete by entering the `FINISHED` state.
|
||||||
unsafe { terminate_and_delete_task(self.task) };
|
unsafe { terminate_and_delete_task(self.task) };
|
||||||
|
|
||||||
// Wwe are responsible for dropping `inner`.
|
// Wwe are responsible for dropping `*p_inner`.
|
||||||
// Safety: The contents of `self.inner` will not be accessed
|
// Safety: The contents of `*p_inner` will not be accessed hereafter
|
||||||
// hereafter
|
let _ = unsafe { Box::from_raw(self.p_inner.as_ptr()) };
|
||||||
unsafe { ManuallyDrop::drop(&mut self.inner) };
|
|
||||||
}
|
}
|
||||||
_ => unsafe { hint::unreachable_unchecked() },
|
_ => unsafe { hint::unreachable_unchecked() },
|
||||||
}
|
}
|
||||||
|
@ -75,3 +75,7 @@ impl<'a> IoSliceMut<'a> {
|
|||||||
unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
|
unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_terminal<T>(_: &T) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use super::unsupported;
|
use super::unsupported;
|
||||||
use crate::convert::TryFrom;
|
|
||||||
use crate::error::Error as StdError;
|
use crate::error::Error as StdError;
|
||||||
use crate::ffi::{CStr, CString, OsStr, OsString};
|
use crate::ffi::{CStr, OsStr, OsString};
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
use crate::os::{
|
use crate::os::{
|
||||||
|
@ -25,7 +25,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||||||
zlib1g-dev \
|
zlib1g-dev \
|
||||||
xz-utils \
|
xz-utils \
|
||||||
nodejs \
|
nodejs \
|
||||||
|
\
|
||||||
# Install powershell so we can test x.ps1 on Linux
|
# Install powershell so we can test x.ps1 on Linux
|
||||||
apt-transport-https software-properties-common && \
|
apt-transport-https software-properties-common && \
|
||||||
curl -s "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb" > packages-microsoft-prod.deb && \
|
curl -s "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb" > packages-microsoft-prod.deb && \
|
||||||
|
@ -15,7 +15,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||||||
sudo \
|
sudo \
|
||||||
xz-utils \
|
xz-utils \
|
||||||
tidy \
|
tidy \
|
||||||
|
\
|
||||||
# Install dependencies for chromium browser
|
# Install dependencies for chromium browser
|
||||||
gconf-service \
|
gconf-service \
|
||||||
libasound2 \
|
libasound2 \
|
||||||
|
@ -38,9 +38,7 @@ fn bar() -> bool {
|
|||||||
// + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[1])) }
|
// + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[1])) }
|
||||||
Retag(_10); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
|
Retag(_10); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
|
||||||
_4 = &(*_10); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
|
_4 = &(*_10); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
|
||||||
Retag(_4); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
|
|
||||||
_3 = &(*_4); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
|
_3 = &(*_4); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
|
||||||
Retag(_3); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
|
|
||||||
StorageLive(_6); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
|
StorageLive(_6); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
|
||||||
StorageLive(_7); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
|
StorageLive(_7); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
|
||||||
_9 = const _; // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
|
_9 = const _; // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
|
||||||
@ -49,9 +47,7 @@ fn bar() -> bool {
|
|||||||
// + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[0])) }
|
// + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[0])) }
|
||||||
Retag(_9); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
|
Retag(_9); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
|
||||||
_7 = &(*_9); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
|
_7 = &(*_9); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
|
||||||
Retag(_7); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
|
|
||||||
_6 = &(*_7); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
|
_6 = &(*_7); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
|
||||||
Retag(_6); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
|
|
||||||
Retag(_3); // scope 2 at $DIR/inline_retag.rs:16:8: 16:9
|
Retag(_3); // scope 2 at $DIR/inline_retag.rs:16:8: 16:9
|
||||||
Retag(_6); // scope 2 at $DIR/inline_retag.rs:16:17: 16:18
|
Retag(_6); // scope 2 at $DIR/inline_retag.rs:16:17: 16:18
|
||||||
StorageLive(_11); // scope 2 at $DIR/inline_retag.rs:17:5: 17:7
|
StorageLive(_11); // scope 2 at $DIR/inline_retag.rs:17:5: 17:7
|
||||||
|
@ -68,9 +68,7 @@ fn array_casts() -> () {
|
|||||||
StorageLive(_3); // scope 1 at $DIR/retag.rs:+2:13: +2:19
|
StorageLive(_3); // scope 1 at $DIR/retag.rs:+2:13: +2:19
|
||||||
StorageLive(_4); // scope 1 at $DIR/retag.rs:+2:13: +2:19
|
StorageLive(_4); // scope 1 at $DIR/retag.rs:+2:13: +2:19
|
||||||
_4 = &mut _1; // scope 1 at $DIR/retag.rs:+2:13: +2:19
|
_4 = &mut _1; // scope 1 at $DIR/retag.rs:+2:13: +2:19
|
||||||
Retag(_4); // scope 1 at $DIR/retag.rs:+2:13: +2:19
|
|
||||||
_3 = &raw mut (*_4); // scope 1 at $DIR/retag.rs:+2:13: +2:19
|
_3 = &raw mut (*_4); // scope 1 at $DIR/retag.rs:+2:13: +2:19
|
||||||
Retag([raw] _3); // scope 1 at $DIR/retag.rs:+2:13: +2:19
|
|
||||||
_2 = move _3 as *mut usize (Pointer(ArrayToPointer)); // scope 1 at $DIR/retag.rs:+2:13: +2:33
|
_2 = move _3 as *mut usize (Pointer(ArrayToPointer)); // scope 1 at $DIR/retag.rs:+2:13: +2:33
|
||||||
StorageDead(_3); // scope 1 at $DIR/retag.rs:+2:32: +2:33
|
StorageDead(_3); // scope 1 at $DIR/retag.rs:+2:32: +2:33
|
||||||
StorageDead(_4); // scope 1 at $DIR/retag.rs:+2:33: +2:34
|
StorageDead(_4); // scope 1 at $DIR/retag.rs:+2:33: +2:34
|
||||||
@ -96,9 +94,7 @@ fn array_casts() -> () {
|
|||||||
StorageLive(_10); // scope 4 at $DIR/retag.rs:+6:13: +6:15
|
StorageLive(_10); // scope 4 at $DIR/retag.rs:+6:13: +6:15
|
||||||
StorageLive(_11); // scope 4 at $DIR/retag.rs:+6:13: +6:15
|
StorageLive(_11); // scope 4 at $DIR/retag.rs:+6:13: +6:15
|
||||||
_11 = &_8; // scope 4 at $DIR/retag.rs:+6:13: +6:15
|
_11 = &_8; // scope 4 at $DIR/retag.rs:+6:13: +6:15
|
||||||
Retag(_11); // scope 4 at $DIR/retag.rs:+6:13: +6:15
|
|
||||||
_10 = &raw const (*_11); // scope 4 at $DIR/retag.rs:+6:13: +6:15
|
_10 = &raw const (*_11); // scope 4 at $DIR/retag.rs:+6:13: +6:15
|
||||||
Retag([raw] _10); // scope 4 at $DIR/retag.rs:+6:13: +6:15
|
|
||||||
_9 = move _10 as *const usize (Pointer(ArrayToPointer)); // scope 4 at $DIR/retag.rs:+6:13: +6:31
|
_9 = move _10 as *const usize (Pointer(ArrayToPointer)); // scope 4 at $DIR/retag.rs:+6:13: +6:31
|
||||||
StorageDead(_10); // scope 4 at $DIR/retag.rs:+6:30: +6:31
|
StorageDead(_10); // scope 4 at $DIR/retag.rs:+6:30: +6:31
|
||||||
StorageDead(_11); // scope 4 at $DIR/retag.rs:+6:31: +6:32
|
StorageDead(_11); // scope 4 at $DIR/retag.rs:+6:31: +6:32
|
||||||
@ -119,7 +115,6 @@ fn array_casts() -> () {
|
|||||||
StorageDead(_17); // scope 6 at $DIR/retag.rs:+7:33: +7:34
|
StorageDead(_17); // scope 6 at $DIR/retag.rs:+7:33: +7:34
|
||||||
_15 = (*_16); // scope 6 at $DIR/retag.rs:+7:25: +7:34
|
_15 = (*_16); // scope 6 at $DIR/retag.rs:+7:25: +7:34
|
||||||
_14 = &_15; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
_14 = &_15; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
Retag(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
|
||||||
StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
_35 = const _; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
_35 = const _; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
@ -127,7 +122,6 @@ fn array_casts() -> () {
|
|||||||
// + literal: Const { ty: &usize, val: Unevaluated(array_casts, [], Some(promoted[0])) }
|
// + literal: Const { ty: &usize, val: Unevaluated(array_casts, [], Some(promoted[0])) }
|
||||||
Retag(_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
Retag(_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
_18 = &(*_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
_18 = &(*_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
Retag(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
|
||||||
Deinit(_13); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
Deinit(_13); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
(_13.0: &usize) = move _14; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
(_13.0: &usize) = move _14; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
(_13.1: &usize) = move _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
(_13.1: &usize) = move _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
@ -164,15 +158,11 @@ fn array_casts() -> () {
|
|||||||
StorageLive(_30); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_30); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
StorageLive(_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
_31 = &(*_20); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
_31 = &(*_20); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
Retag(_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
|
||||||
_30 = &(*_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
_30 = &(*_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
Retag(_30); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
|
||||||
StorageLive(_32); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_32); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
StorageLive(_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
_33 = &(*_21); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
_33 = &(*_21); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
Retag(_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
|
||||||
_32 = &(*_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
_32 = &(*_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
Retag(_32); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
|
||||||
StorageLive(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
Deinit(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
Deinit(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
discriminant(_34) = 0; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
discriminant(_34) = 0; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
@ -6,7 +6,6 @@ fn std::ptr::drop_in_place(_1: *mut Test) -> () {
|
|||||||
let mut _3: (); // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
let mut _3: (); // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
Retag([raw] _1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
|
||||||
_2 = &mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
_2 = &mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||||
_3 = <Test as Drop>::drop(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
_3 = <Test as Drop>::drop(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
|
@ -15,7 +15,6 @@ fn main::{closure#0}(_1: &[closure@main::{closure#0}], _2: &i32) -> &i32 {
|
|||||||
_3 = _2; // scope 0 at $DIR/retag.rs:+1:18: +1:19
|
_3 = _2; // scope 0 at $DIR/retag.rs:+1:18: +1:19
|
||||||
Retag(_3); // scope 0 at $DIR/retag.rs:+1:18: +1:19
|
Retag(_3); // scope 0 at $DIR/retag.rs:+1:18: +1:19
|
||||||
_0 = &(*_2); // scope 1 at $DIR/retag.rs:+2:9: +2:10
|
_0 = &(*_2); // scope 1 at $DIR/retag.rs:+2:9: +2:10
|
||||||
Retag(_0); // scope 1 at $DIR/retag.rs:+2:9: +2:10
|
|
||||||
StorageDead(_3); // scope 0 at $DIR/retag.rs:+3:5: +3:6
|
StorageDead(_3); // scope 0 at $DIR/retag.rs:+3:5: +3:6
|
||||||
return; // scope 0 at $DIR/retag.rs:+3:6: +3:6
|
return; // scope 0 at $DIR/retag.rs:+3:6: +3:6
|
||||||
}
|
}
|
||||||
|
@ -65,13 +65,10 @@ fn main() -> () {
|
|||||||
Deinit(_5); // scope 1 at $DIR/retag.rs:+3:17: +3:24
|
Deinit(_5); // scope 1 at $DIR/retag.rs:+3:17: +3:24
|
||||||
(_5.0: i32) = const 0_i32; // scope 1 at $DIR/retag.rs:+3:17: +3:24
|
(_5.0: i32) = const 0_i32; // scope 1 at $DIR/retag.rs:+3:17: +3:24
|
||||||
_4 = &_5; // scope 1 at $DIR/retag.rs:+3:17: +3:36
|
_4 = &_5; // scope 1 at $DIR/retag.rs:+3:17: +3:36
|
||||||
Retag(_4); // scope 1 at $DIR/retag.rs:+3:17: +3:36
|
|
||||||
StorageLive(_6); // scope 1 at $DIR/retag.rs:+3:29: +3:35
|
StorageLive(_6); // scope 1 at $DIR/retag.rs:+3:29: +3:35
|
||||||
StorageLive(_7); // scope 1 at $DIR/retag.rs:+3:29: +3:35
|
StorageLive(_7); // scope 1 at $DIR/retag.rs:+3:29: +3:35
|
||||||
_7 = &mut _1; // scope 1 at $DIR/retag.rs:+3:29: +3:35
|
_7 = &mut _1; // scope 1 at $DIR/retag.rs:+3:29: +3:35
|
||||||
Retag(_7); // scope 1 at $DIR/retag.rs:+3:29: +3:35
|
|
||||||
_6 = &mut (*_7); // scope 1 at $DIR/retag.rs:+3:29: +3:35
|
_6 = &mut (*_7); // scope 1 at $DIR/retag.rs:+3:29: +3:35
|
||||||
Retag([2phase] _6); // scope 1 at $DIR/retag.rs:+3:29: +3:35
|
|
||||||
_3 = Test::foo(move _4, move _6) -> [return: bb1, unwind: bb8]; // scope 1 at $DIR/retag.rs:+3:17: +3:36
|
_3 = Test::foo(move _4, move _6) -> [return: bb1, unwind: bb8]; // scope 1 at $DIR/retag.rs:+3:17: +3:36
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/retag.rs:33:25: 33:28
|
// + span: $DIR/retag.rs:33:25: 33:28
|
||||||
@ -93,7 +90,6 @@ fn main() -> () {
|
|||||||
_9 = move _3; // scope 2 at $DIR/retag.rs:+4:19: +4:20
|
_9 = move _3; // scope 2 at $DIR/retag.rs:+4:19: +4:20
|
||||||
Retag(_9); // scope 2 at $DIR/retag.rs:+4:19: +4:20
|
Retag(_9); // scope 2 at $DIR/retag.rs:+4:19: +4:20
|
||||||
_8 = &mut (*_9); // scope 2 at $DIR/retag.rs:+4:19: +4:20
|
_8 = &mut (*_9); // scope 2 at $DIR/retag.rs:+4:19: +4:20
|
||||||
Retag(_8); // scope 2 at $DIR/retag.rs:+4:19: +4:20
|
|
||||||
StorageDead(_9); // scope 2 at $DIR/retag.rs:+4:22: +4:23
|
StorageDead(_9); // scope 2 at $DIR/retag.rs:+4:22: +4:23
|
||||||
StorageLive(_10); // scope 3 at $DIR/retag.rs:+5:13: +5:14
|
StorageLive(_10); // scope 3 at $DIR/retag.rs:+5:13: +5:14
|
||||||
_10 = move _8; // scope 3 at $DIR/retag.rs:+5:17: +5:18
|
_10 = move _8; // scope 3 at $DIR/retag.rs:+5:17: +5:18
|
||||||
@ -101,7 +97,6 @@ fn main() -> () {
|
|||||||
StorageLive(_11); // scope 4 at $DIR/retag.rs:+7:13: +7:15
|
StorageLive(_11); // scope 4 at $DIR/retag.rs:+7:13: +7:15
|
||||||
StorageLive(_12); // scope 4 at $DIR/retag.rs:+7:18: +7:29
|
StorageLive(_12); // scope 4 at $DIR/retag.rs:+7:18: +7:29
|
||||||
_12 = &raw mut (*_10); // scope 4 at $DIR/retag.rs:+7:18: +7:19
|
_12 = &raw mut (*_10); // scope 4 at $DIR/retag.rs:+7:18: +7:19
|
||||||
Retag([raw] _12); // scope 4 at $DIR/retag.rs:+7:18: +7:19
|
|
||||||
_11 = _12; // scope 4 at $DIR/retag.rs:+7:18: +7:29
|
_11 = _12; // scope 4 at $DIR/retag.rs:+7:18: +7:29
|
||||||
StorageDead(_12); // scope 4 at $DIR/retag.rs:+7:29: +7:30
|
StorageDead(_12); // scope 4 at $DIR/retag.rs:+7:29: +7:30
|
||||||
_2 = const (); // scope 1 at $DIR/retag.rs:+2:5: +8:6
|
_2 = const (); // scope 1 at $DIR/retag.rs:+2:5: +8:6
|
||||||
@ -122,9 +117,7 @@ fn main() -> () {
|
|||||||
StorageLive(_17); // scope 6 at $DIR/retag.rs:+15:16: +15:18
|
StorageLive(_17); // scope 6 at $DIR/retag.rs:+15:16: +15:18
|
||||||
StorageLive(_18); // scope 6 at $DIR/retag.rs:+15:16: +15:18
|
StorageLive(_18); // scope 6 at $DIR/retag.rs:+15:16: +15:18
|
||||||
_18 = &_1; // scope 6 at $DIR/retag.rs:+15:16: +15:18
|
_18 = &_1; // scope 6 at $DIR/retag.rs:+15:16: +15:18
|
||||||
Retag(_18); // scope 6 at $DIR/retag.rs:+15:16: +15:18
|
|
||||||
_17 = &(*_18); // scope 6 at $DIR/retag.rs:+15:16: +15:18
|
_17 = &(*_18); // scope 6 at $DIR/retag.rs:+15:16: +15:18
|
||||||
Retag(_17); // scope 6 at $DIR/retag.rs:+15:16: +15:18
|
|
||||||
_15 = move _16(move _17) -> bb3; // scope 6 at $DIR/retag.rs:+15:14: +15:19
|
_15 = move _16(move _17) -> bb3; // scope 6 at $DIR/retag.rs:+15:14: +15:19
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +132,6 @@ fn main() -> () {
|
|||||||
Deinit(_21); // scope 7 at $DIR/retag.rs:+18:5: +18:12
|
Deinit(_21); // scope 7 at $DIR/retag.rs:+18:5: +18:12
|
||||||
(_21.0: i32) = const 0_i32; // scope 7 at $DIR/retag.rs:+18:5: +18:12
|
(_21.0: i32) = const 0_i32; // scope 7 at $DIR/retag.rs:+18:5: +18:12
|
||||||
_20 = &_21; // scope 7 at $DIR/retag.rs:+18:5: +18:24
|
_20 = &_21; // scope 7 at $DIR/retag.rs:+18:5: +18:24
|
||||||
Retag(_20); // scope 7 at $DIR/retag.rs:+18:5: +18:24
|
|
||||||
StorageLive(_22); // scope 7 at $DIR/retag.rs:+18:21: +18:23
|
StorageLive(_22); // scope 7 at $DIR/retag.rs:+18:21: +18:23
|
||||||
StorageLive(_23); // scope 7 at $DIR/retag.rs:+18:21: +18:23
|
StorageLive(_23); // scope 7 at $DIR/retag.rs:+18:21: +18:23
|
||||||
_28 = const _; // scope 7 at $DIR/retag.rs:+18:21: +18:23
|
_28 = const _; // scope 7 at $DIR/retag.rs:+18:21: +18:23
|
||||||
@ -148,9 +140,7 @@ fn main() -> () {
|
|||||||
// + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) }
|
// + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) }
|
||||||
Retag(_28); // scope 7 at $DIR/retag.rs:+18:21: +18:23
|
Retag(_28); // scope 7 at $DIR/retag.rs:+18:21: +18:23
|
||||||
_23 = &(*_28); // scope 7 at $DIR/retag.rs:+18:21: +18:23
|
_23 = &(*_28); // scope 7 at $DIR/retag.rs:+18:21: +18:23
|
||||||
Retag(_23); // scope 7 at $DIR/retag.rs:+18:21: +18:23
|
|
||||||
_22 = &(*_23); // scope 7 at $DIR/retag.rs:+18:21: +18:23
|
_22 = &(*_23); // scope 7 at $DIR/retag.rs:+18:21: +18:23
|
||||||
Retag(_22); // scope 7 at $DIR/retag.rs:+18:21: +18:23
|
|
||||||
_19 = Test::foo_shr(move _20, move _22) -> [return: bb4, unwind: bb7]; // scope 7 at $DIR/retag.rs:+18:5: +18:24
|
_19 = Test::foo_shr(move _20, move _22) -> [return: bb4, unwind: bb7]; // scope 7 at $DIR/retag.rs:+18:5: +18:24
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/retag.rs:48:13: 48:20
|
// + span: $DIR/retag.rs:48:13: 48:20
|
||||||
@ -171,7 +161,6 @@ fn main() -> () {
|
|||||||
StorageLive(_25); // scope 7 at $DIR/retag.rs:+21:9: +21:11
|
StorageLive(_25); // scope 7 at $DIR/retag.rs:+21:9: +21:11
|
||||||
StorageLive(_26); // scope 7 at $DIR/retag.rs:+21:14: +21:28
|
StorageLive(_26); // scope 7 at $DIR/retag.rs:+21:14: +21:28
|
||||||
_26 = &raw const (*_15); // scope 7 at $DIR/retag.rs:+21:14: +21:16
|
_26 = &raw const (*_15); // scope 7 at $DIR/retag.rs:+21:14: +21:16
|
||||||
Retag([raw] _26); // scope 7 at $DIR/retag.rs:+21:14: +21:16
|
|
||||||
_25 = _26; // scope 7 at $DIR/retag.rs:+21:14: +21:28
|
_25 = _26; // scope 7 at $DIR/retag.rs:+21:14: +21:28
|
||||||
StorageDead(_26); // scope 7 at $DIR/retag.rs:+21:28: +21:29
|
StorageDead(_26); // scope 7 at $DIR/retag.rs:+21:28: +21:29
|
||||||
StorageLive(_27); // scope 8 at $DIR/retag.rs:+23:5: +23:18
|
StorageLive(_27); // scope 8 at $DIR/retag.rs:+23:5: +23:18
|
||||||
|
@ -11,9 +11,7 @@ fn <impl at $DIR/retag.rs:12:1: 12:10>::foo(_1: &Test, _2: &mut i32) -> &mut i32
|
|||||||
Retag([fn entry] _2); // scope 0 at $DIR/retag.rs:+0:23: +0:24
|
Retag([fn entry] _2); // scope 0 at $DIR/retag.rs:+0:23: +0:24
|
||||||
StorageLive(_3); // scope 0 at $DIR/retag.rs:+1:9: +1:10
|
StorageLive(_3); // scope 0 at $DIR/retag.rs:+1:9: +1:10
|
||||||
_3 = &mut (*_2); // scope 0 at $DIR/retag.rs:+1:9: +1:10
|
_3 = &mut (*_2); // scope 0 at $DIR/retag.rs:+1:9: +1:10
|
||||||
Retag(_3); // scope 0 at $DIR/retag.rs:+1:9: +1:10
|
|
||||||
_0 = &mut (*_3); // scope 0 at $DIR/retag.rs:+1:9: +1:10
|
_0 = &mut (*_3); // scope 0 at $DIR/retag.rs:+1:9: +1:10
|
||||||
Retag(_0); // scope 0 at $DIR/retag.rs:+1:9: +1:10
|
|
||||||
StorageDead(_3); // scope 0 at $DIR/retag.rs:+2:5: +2:6
|
StorageDead(_3); // scope 0 at $DIR/retag.rs:+2:5: +2:6
|
||||||
return; // scope 0 at $DIR/retag.rs:+2:6: +2:6
|
return; // scope 0 at $DIR/retag.rs:+2:6: +2:6
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ impl CodegenBackend for TheBackend {
|
|||||||
if crate_type != CrateType::Rlib {
|
if crate_type != CrateType::Rlib {
|
||||||
sess.fatal(&format!("Crate type is {:?}", crate_type));
|
sess.fatal(&format!("Crate type is {:?}", crate_type));
|
||||||
}
|
}
|
||||||
let output_name = out_filename(sess, crate_type, &outputs, &*crate_name.as_str());
|
let output_name = out_filename(sess, crate_type, &outputs, crate_name);
|
||||||
let mut out_file = ::std::fs::File::create(output_name).unwrap();
|
let mut out_file = ::std::fs::File::create(output_name).unwrap();
|
||||||
write!(out_file, "This has been \"compiled\" successfully.").unwrap();
|
write!(out_file, "This has been \"compiled\" successfully.").unwrap();
|
||||||
}
|
}
|
||||||
|
17
src/test/ui/async-await/in-trait/nested-rpit.rs
Normal file
17
src/test/ui/async-await/in-trait/nested-rpit.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// check-pass
|
||||||
|
// edition: 2021
|
||||||
|
|
||||||
|
#![feature(async_fn_in_trait)]
|
||||||
|
#![feature(return_position_impl_trait_in_trait)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
use std::future::Future;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
trait Lockable<K, V> {
|
||||||
|
async fn lock_all_entries(&self) -> impl Future<Output = Guard<'_>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Guard<'a>(PhantomData<&'a ()>);
|
||||||
|
|
||||||
|
fn main() {}
|
86
src/test/ui/diagnostic-width/long-E0308.rs
Normal file
86
src/test/ui/diagnostic-width/long-E0308.rs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
// compile-flags: --diagnostic-width=60
|
||||||
|
// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
|
||||||
|
|
||||||
|
struct Atype<T, K>(T, K);
|
||||||
|
struct Btype<T, K>(T, K);
|
||||||
|
struct Ctype<T, K>(T, K);
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x: Atype<
|
||||||
|
Btype<
|
||||||
|
Ctype<
|
||||||
|
Atype<
|
||||||
|
Btype<
|
||||||
|
Ctype<
|
||||||
|
Atype<
|
||||||
|
Btype<
|
||||||
|
Ctype<i32, i32>,
|
||||||
|
i32
|
||||||
|
>,
|
||||||
|
i32
|
||||||
|
>,
|
||||||
|
i32
|
||||||
|
>,
|
||||||
|
i32
|
||||||
|
>,
|
||||||
|
i32
|
||||||
|
>,
|
||||||
|
i32
|
||||||
|
>,
|
||||||
|
i32
|
||||||
|
>,
|
||||||
|
i32
|
||||||
|
> = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
|
||||||
|
Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
|
||||||
|
Ok("")
|
||||||
|
))))))))))))))))))))))))))))))
|
||||||
|
))))))))))))))))))))))))))))));
|
||||||
|
//~^^^^^ ERROR E0308
|
||||||
|
|
||||||
|
let _ = Some(Ok(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(
|
||||||
|
Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(
|
||||||
|
Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(
|
||||||
|
Some(Some(Some(Some(Some(Some(Some(Some(Some("")))))))))
|
||||||
|
)))))))))))))))))
|
||||||
|
))))))))))))))))))
|
||||||
|
))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
|
||||||
|
Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
|
||||||
|
Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
|
||||||
|
))))))))))))))))))))))))))))))
|
||||||
|
))))))))))))))))))))))));
|
||||||
|
//~^^^^^ ERROR E0308
|
||||||
|
|
||||||
|
let x: Atype<
|
||||||
|
Btype<
|
||||||
|
Ctype<
|
||||||
|
Atype<
|
||||||
|
Btype<
|
||||||
|
Ctype<
|
||||||
|
Atype<
|
||||||
|
Btype<
|
||||||
|
Ctype<i32, i32>,
|
||||||
|
i32
|
||||||
|
>,
|
||||||
|
i32
|
||||||
|
>,
|
||||||
|
i32
|
||||||
|
>,
|
||||||
|
i32
|
||||||
|
>,
|
||||||
|
i32
|
||||||
|
>,
|
||||||
|
i32
|
||||||
|
>,
|
||||||
|
i32
|
||||||
|
>,
|
||||||
|
i32
|
||||||
|
> = ();
|
||||||
|
//~^ ERROR E0308
|
||||||
|
|
||||||
|
let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
|
||||||
|
Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
|
||||||
|
Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
|
||||||
|
))))))))))))))))))))))))))))))
|
||||||
|
))))))))))))))))))))))));
|
||||||
|
//~^^^^^ ERROR E0308
|
||||||
|
}
|
80
src/test/ui/diagnostic-width/long-E0308.stderr
Normal file
80
src/test/ui/diagnostic-width/long-E0308.stderr
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/long-E0308.rs:33:9
|
||||||
|
|
|
||||||
|
LL | let x: Atype<
|
||||||
|
| _____________-
|
||||||
|
LL | | Btype<
|
||||||
|
LL | | Ctype<
|
||||||
|
LL | | Atype<
|
||||||
|
... |
|
||||||
|
LL | | i32
|
||||||
|
LL | | > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok...
|
||||||
|
| | _____-___^
|
||||||
|
| ||_____|
|
||||||
|
| | expected due to this
|
||||||
|
LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok...
|
||||||
|
LL | | Ok("")
|
||||||
|
LL | | ))))))))))))))))))))))))))))))
|
||||||
|
LL | | ))))))))))))))))))))))))))))));
|
||||||
|
| |__________________________________^ expected struct `Atype`, found enum `Result`
|
||||||
|
|
|
||||||
|
= note: expected struct `Atype<Btype<..., ...>, ...>`
|
||||||
|
the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
|
||||||
|
found enum `Result<Result<..., ...>, ...>`
|
||||||
|
the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/long-E0308.rs:46:26
|
||||||
|
|
|
||||||
|
LL | ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O...
|
||||||
|
| __________________________^
|
||||||
|
LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(...
|
||||||
|
LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
|
||||||
|
LL | | ))))))))))))))))))))))))))))))
|
||||||
|
LL | | ))))))))))))))))))))))));
|
||||||
|
| |____________________________^ expected enum `Option`, found enum `Result`
|
||||||
|
|
|
||||||
|
= note: expected enum `Option<Result<..., ...>>`
|
||||||
|
the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
|
||||||
|
found enum `Result<Result<..., ...>, ...>`
|
||||||
|
the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/long-E0308.rs:77:9
|
||||||
|
|
|
||||||
|
LL | let x: Atype<
|
||||||
|
| ____________-
|
||||||
|
LL | | Btype<
|
||||||
|
LL | | Ctype<
|
||||||
|
LL | | Atype<
|
||||||
|
... |
|
||||||
|
LL | | i32
|
||||||
|
LL | | > = ();
|
||||||
|
| | - ^^ expected struct `Atype`, found `()`
|
||||||
|
| |_____|
|
||||||
|
| expected due to this
|
||||||
|
|
|
||||||
|
= note: expected struct `Atype<Btype<..., ...>, ...>`
|
||||||
|
the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
|
||||||
|
found unit type `()`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/long-E0308.rs:80:17
|
||||||
|
|
|
||||||
|
LL | let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O...
|
||||||
|
| ____________--___^
|
||||||
|
| | |
|
||||||
|
| | expected due to this
|
||||||
|
LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(...
|
||||||
|
LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
|
||||||
|
LL | | ))))))))))))))))))))))))))))))
|
||||||
|
LL | | ))))))))))))))))))))))));
|
||||||
|
| |____________________________^ expected `()`, found enum `Result`
|
||||||
|
|
|
||||||
|
= note: expected unit type `()`
|
||||||
|
found enum `Result<Result<..., ...>, ...>`
|
||||||
|
the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
@ -5,7 +5,7 @@ LL | impl<T> Foo for T where Bar<T>: Foo {}
|
|||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
|
||||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`)
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`)
|
||||||
note: required for `Bar<Bar<Bar<Bar<Bar<Bar<...>>>>>>` to implement `Foo`
|
note: required for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<...>>>>>>>>>>>>>>>>>>>>>` to implement `Foo`
|
||||||
--> $DIR/E0275.rs:6:9
|
--> $DIR/E0275.rs:6:9
|
||||||
|
|
|
|
||||||
LL | impl<T> Foo for T where Bar<T>: Foo {}
|
LL | impl<T> Foo for T where Bar<T>: Foo {}
|
||||||
|
@ -3,12 +3,18 @@ error[E0562]: `impl Trait` only allowed in function and inherent method return t
|
|||||||
|
|
|
|
||||||
LL | fn f() -> impl Fn() -> impl Sized { || () }
|
LL | fn f() -> impl Fn() -> impl Sized { || () }
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #99697 <https://github.com/rust-lang/rust/issues/99697> for more information
|
||||||
|
= help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable
|
||||||
|
|
||||||
error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
|
error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
|
||||||
--> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:3:32
|
--> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:3:32
|
||||||
|
|
|
|
||||||
LL | fn g() -> &'static dyn Fn() -> impl Sized { &|| () }
|
LL | fn g() -> &'static dyn Fn() -> impl Sized { &|| () }
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #99697 <https://github.com/rust-lang/rust/issues/99697> for more information
|
||||||
|
= help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ LL | impl<T> Foo for T where NoData<T>: Foo {
|
|||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
|
||||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
|
||||||
note: required for `NoData<NoData<NoData<NoData<NoData<NoData<...>>>>>>` to implement `Foo`
|
note: required for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<...>>>>>>>>>>>>>` to implement `Foo`
|
||||||
--> $DIR/issue-20413.rs:9:9
|
--> $DIR/issue-20413.rs:9:9
|
||||||
|
|
|
|
||||||
LL | impl<T> Foo for T where NoData<T>: Foo {
|
LL | impl<T> Foo for T where NoData<T>: Foo {
|
||||||
@ -30,13 +30,13 @@ LL | impl<T> Bar for T where EvenLessData<T>: Baz {
|
|||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
|
||||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
|
||||||
note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>` to implement `Bar`
|
note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>>` to implement `Bar`
|
||||||
--> $DIR/issue-20413.rs:28:9
|
--> $DIR/issue-20413.rs:28:9
|
||||||
|
|
|
|
||||||
LL | impl<T> Bar for T where EvenLessData<T>: Baz {
|
LL | impl<T> Bar for T where EvenLessData<T>: Baz {
|
||||||
| ^^^ ^
|
| ^^^ ^
|
||||||
= note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
|
= note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
|
||||||
note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>` to implement `Baz`
|
note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>>` to implement `Baz`
|
||||||
--> $DIR/issue-20413.rs:35:9
|
--> $DIR/issue-20413.rs:35:9
|
||||||
|
|
|
|
||||||
LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
|
LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
|
||||||
@ -52,13 +52,13 @@ LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
|
|||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
|
||||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
|
||||||
note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>` to implement `Baz`
|
note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>>` to implement `Baz`
|
||||||
--> $DIR/issue-20413.rs:35:9
|
--> $DIR/issue-20413.rs:35:9
|
||||||
|
|
|
|
||||||
LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
|
LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
|
||||||
| ^^^ ^
|
| ^^^ ^
|
||||||
= note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
|
= note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
|
||||||
note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>` to implement `Bar`
|
note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>>` to implement `Bar`
|
||||||
--> $DIR/issue-20413.rs:28:9
|
--> $DIR/issue-20413.rs:28:9
|
||||||
|
|
|
|
||||||
LL | impl<T> Bar for T where EvenLessData<T>: Baz {
|
LL | impl<T> Bar for T where EvenLessData<T>: Baz {
|
||||||
|
@ -5,7 +5,7 @@ LL | type Next = <GetNext<T::Next> as Next>::Next;
|
|||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_23122_2`)
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_23122_2`)
|
||||||
note: required for `GetNext<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next`
|
note: required for `GetNext<<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next`
|
||||||
--> $DIR/issue-23122-2.rs:10:15
|
--> $DIR/issue-23122-2.rs:10:15
|
||||||
|
|
|
|
||||||
LL | impl<T: Next> Next for GetNext<T> {
|
LL | impl<T: Next> Next for GetNext<T> {
|
||||||
|
@ -12,7 +12,7 @@ LL | func(&mut iter.map(|x| x + 1))
|
|||||||
error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>: Iterator`
|
error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>: Iterator`
|
||||||
|
|
|
|
||||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`)
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`)
|
||||||
= note: required for `&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>` to implement `Iterator`
|
= note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>, ...>, ...>, ...>` to implement `Iterator`
|
||||||
= note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-83150/issue-83150.long-type-hash.txt'
|
= note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-83150/issue-83150.long-type-hash.txt'
|
||||||
|
|
||||||
error: aborting due to previous error; 1 warning emitted
|
error: aborting due to previous error; 1 warning emitted
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-102374.rs:16:5
|
--> $DIR/issue-102374.rs:17:5
|
||||||
|
|
|
|
||||||
LL | ) -> i32 {
|
LL | ) -> i32 {
|
||||||
| --- expected `i32` because of return type
|
| --- expected `i32` because of return type
|
||||||
@ -7,7 +7,8 @@ LL | f
|
|||||||
| ^ expected `i32`, found fn pointer
|
| ^ expected `i32`, found fn pointer
|
||||||
|
|
|
|
||||||
= note: expected type `i32`
|
= note: expected type `i32`
|
||||||
found fn pointer `for<'z1, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, 'y, 'z, 'z0> fn(Cell<(&'z1 i32, &'a i32, &'b i32, &'c i32, &'d i32, &'e i32, &'f i32, &'g i32, &'h i32, &'i i32, &'j i32, &'k i32, &'l i32, &'m i32, &'n i32, &'o i32, &'p i32, &'q i32, &'r i32, &'s i32, &'t i32, &'u i32, &'v i32, &'w i32, &'x i32, &'y i32, &'z i32, &'z0 i32)>)`
|
found fn pointer `for<'z1, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, 'y, 'z, 'z0> fn(Cell<...>)`
|
||||||
|
the full type name has been written to '$TEST_BUILD_DIR/regions/issue-102374/issue-102374.long-type-hash.txt'
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ error[E0275]: overflow evaluating the requirement `(): Sized`
|
|||||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "512"]` attribute to your crate (`issue_91949_hangs_on_recursion`)
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "512"]` attribute to your crate (`issue_91949_hangs_on_recursion`)
|
||||||
= note: required for `std::iter::Empty<()>` to implement `Iterator`
|
= note: required for `std::iter::Empty<()>` to implement `Iterator`
|
||||||
= note: 171 redundant requirements hidden
|
= note: 171 redundant requirements hidden
|
||||||
= note: required for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<..., ...>>, ...>>` to implement `Iterator`
|
= note: required for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<..., ...>>, ...>>, ...>>` to implement `Iterator`
|
||||||
= note: the full type name has been written to '$TEST_BUILD_DIR/traits/issue-91949-hangs-on-recursion/issue-91949-hangs-on-recursion.long-type-hash.txt'
|
= note: the full type name has been written to '$TEST_BUILD_DIR/traits/issue-91949-hangs-on-recursion/issue-91949-hangs-on-recursion.long-type-hash.txt'
|
||||||
|
|
||||||
error: aborting due to previous error; 1 warning emitted
|
error: aborting due to previous error; 1 warning emitted
|
||||||
|
@ -11,7 +11,6 @@ use rustc_target::abi::Size;
|
|||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
pub mod stacked_borrows;
|
pub mod stacked_borrows;
|
||||||
use stacked_borrows::diagnostics::RetagCause;
|
|
||||||
|
|
||||||
pub type CallId = NonZeroU64;
|
pub type CallId = NonZeroU64;
|
||||||
|
|
||||||
@ -265,11 +264,19 @@ impl GlobalStateInner {
|
|||||||
|
|
||||||
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
||||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
fn retag(&mut self, kind: RetagKind, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
fn retag_ptr_value(&mut self, kind: RetagKind, val: &ImmTy<'tcx, Provenance>) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
|
||||||
let this = self.eval_context_mut();
|
let this = self.eval_context_mut();
|
||||||
let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
|
let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
|
||||||
match method {
|
match method {
|
||||||
BorrowTrackerMethod::StackedBorrows => this.sb_retag(kind, place),
|
BorrowTrackerMethod::StackedBorrows => this.sb_retag_ptr_value(kind, val),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn retag_place_contents(&mut self, kind: RetagKind, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||||
|
let this = self.eval_context_mut();
|
||||||
|
let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
|
||||||
|
match method {
|
||||||
|
BorrowTrackerMethod::StackedBorrows => this.sb_retag_place_contents(kind, place),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,10 +459,10 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
|
|||||||
Operation::Dealloc(_) => format!(" due to deallocation"),
|
Operation::Dealloc(_) => format!(" due to deallocation"),
|
||||||
Operation::Access(AccessOp { kind, tag, .. }) =>
|
Operation::Access(AccessOp { kind, tag, .. }) =>
|
||||||
format!(" due to {kind:?} access for {tag:?}"),
|
format!(" due to {kind:?} access for {tag:?}"),
|
||||||
Operation::Retag(RetagOp { orig_tag, permission, .. }) => {
|
Operation::Retag(RetagOp { orig_tag, permission, new_tag, .. }) => {
|
||||||
let permission = permission
|
let permission = permission
|
||||||
.expect("start_grant should set the current permission before popping a tag");
|
.expect("start_grant should set the current permission before popping a tag");
|
||||||
format!(" due to {permission:?} retag from {orig_tag:?}")
|
format!(" due to {permission:?} retag from {orig_tag:?} (that retag created {new_tag:?})")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
//! Implements "Stacked Borrows". See <https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md>
|
//! Implements "Stacked Borrows". See <https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md>
|
||||||
//! for further information.
|
//! for further information.
|
||||||
|
|
||||||
|
pub mod diagnostics;
|
||||||
|
mod item;
|
||||||
|
mod stack;
|
||||||
|
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::Write;
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_middle::mir::{Mutability, RetagKind};
|
use rustc_middle::mir::{Mutability, RetagKind};
|
||||||
@ -15,15 +19,13 @@ use rustc_target::abi::{Abi, Size};
|
|||||||
|
|
||||||
use crate::borrow_tracker::{
|
use crate::borrow_tracker::{
|
||||||
stacked_borrows::diagnostics::{AllocHistory, DiagnosticCx, DiagnosticCxBuilder, TagHistory},
|
stacked_borrows::diagnostics::{AllocHistory, DiagnosticCx, DiagnosticCxBuilder, TagHistory},
|
||||||
AccessKind, GlobalStateInner, ProtectorKind, RetagCause, RetagFields,
|
AccessKind, GlobalStateInner, ProtectorKind, RetagFields,
|
||||||
};
|
};
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
mod item;
|
use diagnostics::RetagCause;
|
||||||
pub use item::{Item, Permission};
|
pub use item::{Item, Permission};
|
||||||
mod stack;
|
|
||||||
pub use stack::Stack;
|
pub use stack::Stack;
|
||||||
pub mod diagnostics;
|
|
||||||
|
|
||||||
pub type AllocState = Stacks;
|
pub type AllocState = Stacks;
|
||||||
|
|
||||||
@ -40,30 +42,104 @@ pub struct Stacks {
|
|||||||
modified_since_last_gc: bool,
|
modified_since_last_gc: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Indicates which kind of reference is being created.
|
/// Indicates which permissions to grant to the retagged pointer.
|
||||||
/// Used by high-level `reborrow` to compute which permissions to grant to the
|
#[derive(Clone, Debug)]
|
||||||
/// new pointer.
|
enum NewPermission {
|
||||||
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
|
Uniform {
|
||||||
enum RefKind {
|
perm: Permission,
|
||||||
/// `Box`.
|
access: Option<AccessKind>,
|
||||||
Box,
|
protector: Option<ProtectorKind>,
|
||||||
/// `&mut`.
|
},
|
||||||
Unique { two_phase: bool },
|
FreezeSensitive {
|
||||||
/// `&` with or without interior mutability.
|
freeze_perm: Permission,
|
||||||
Shared,
|
freeze_access: Option<AccessKind>,
|
||||||
/// `*mut`/`*const` (raw pointers).
|
freeze_protector: Option<ProtectorKind>,
|
||||||
Raw { mutable: bool },
|
nonfreeze_perm: Permission,
|
||||||
|
nonfreeze_access: Option<AccessKind>,
|
||||||
|
// nonfreeze_protector must always be None
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for RefKind {
|
impl NewPermission {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
/// A key function: determine the permissions to grant at a retag for the given kind of
|
||||||
|
/// reference/pointer.
|
||||||
|
fn from_ref_ty<'tcx>(
|
||||||
|
ty: ty::Ty<'tcx>,
|
||||||
|
kind: RetagKind,
|
||||||
|
cx: &crate::MiriInterpCx<'_, 'tcx>,
|
||||||
|
) -> Self {
|
||||||
|
let protector = (kind == RetagKind::FnEntry).then_some(ProtectorKind::StrongProtector);
|
||||||
|
match ty.kind() {
|
||||||
|
ty::Ref(_, pointee, Mutability::Mut) => {
|
||||||
|
if kind == RetagKind::TwoPhase {
|
||||||
|
// We mostly just give up on 2phase-borrows, and treat these exactly like raw pointers.
|
||||||
|
assert!(protector.is_none()); // RetagKind can't be both FnEntry and TwoPhase.
|
||||||
|
NewPermission::Uniform {
|
||||||
|
perm: Permission::SharedReadWrite,
|
||||||
|
access: None,
|
||||||
|
protector: None,
|
||||||
|
}
|
||||||
|
} else if pointee.is_unpin(*cx.tcx, cx.param_env()) {
|
||||||
|
// A regular full mutable reference.
|
||||||
|
NewPermission::Uniform {
|
||||||
|
perm: Permission::Unique,
|
||||||
|
access: Some(AccessKind::Write),
|
||||||
|
protector,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NewPermission::Uniform {
|
||||||
|
perm: Permission::SharedReadWrite,
|
||||||
|
// FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we
|
||||||
|
// should do fake accesses here. But then we run into
|
||||||
|
// <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>, so for now
|
||||||
|
// we don't do that.
|
||||||
|
access: None,
|
||||||
|
protector,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ty::RawPtr(ty::TypeAndMut { mutbl: Mutability::Mut, .. }) => {
|
||||||
|
assert!(protector.is_none()); // RetagKind can't be both FnEntry and Raw.
|
||||||
|
// Mutable raw pointer. No access, not protected.
|
||||||
|
NewPermission::Uniform {
|
||||||
|
perm: Permission::SharedReadWrite,
|
||||||
|
access: None,
|
||||||
|
protector: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ty::Ref(_, _pointee, Mutability::Not) => {
|
||||||
|
NewPermission::FreezeSensitive {
|
||||||
|
freeze_perm: Permission::SharedReadOnly,
|
||||||
|
freeze_access: Some(AccessKind::Read),
|
||||||
|
freeze_protector: protector,
|
||||||
|
nonfreeze_perm: Permission::SharedReadWrite,
|
||||||
|
// Inside UnsafeCell, this does *not* count as an access, as there
|
||||||
|
// might actually be mutable references further up the stack that
|
||||||
|
// we have to keep alive.
|
||||||
|
nonfreeze_access: None,
|
||||||
|
// We do not protect inside UnsafeCell.
|
||||||
|
// This fixes https://github.com/rust-lang/rust/issues/55005.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ty::RawPtr(ty::TypeAndMut { mutbl: Mutability::Not, .. }) => {
|
||||||
|
assert!(protector.is_none()); // RetagKind can't be both FnEntry and Raw.
|
||||||
|
// `*const T`, when freshly created, are read-only in the frozen part.
|
||||||
|
NewPermission::FreezeSensitive {
|
||||||
|
freeze_perm: Permission::SharedReadOnly,
|
||||||
|
freeze_access: Some(AccessKind::Read),
|
||||||
|
freeze_protector: None,
|
||||||
|
nonfreeze_perm: Permission::SharedReadWrite,
|
||||||
|
nonfreeze_access: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn protector(&self) -> Option<ProtectorKind> {
|
||||||
match self {
|
match self {
|
||||||
RefKind::Box => write!(f, "Box"),
|
NewPermission::Uniform { protector, .. } => *protector,
|
||||||
RefKind::Unique { two_phase: false } => write!(f, "unique reference"),
|
NewPermission::FreezeSensitive { freeze_protector, .. } => *freeze_protector,
|
||||||
RefKind::Unique { two_phase: true } => write!(f, "unique reference (two-phase)"),
|
|
||||||
RefKind::Shared => write!(f, "shared reference"),
|
|
||||||
RefKind::Raw { mutable: true } => write!(f, "raw (mutable) pointer"),
|
|
||||||
RefKind::Raw { mutable: false } => write!(f, "raw (constant) pointer"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -518,10 +594,9 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
|
|||||||
&mut self,
|
&mut self,
|
||||||
place: &MPlaceTy<'tcx, Provenance>,
|
place: &MPlaceTy<'tcx, Provenance>,
|
||||||
size: Size,
|
size: Size,
|
||||||
kind: RefKind,
|
new_perm: NewPermission,
|
||||||
retag_cause: RetagCause, // What caused this retag, for diagnostics only
|
|
||||||
new_tag: BorTag,
|
new_tag: BorTag,
|
||||||
protect: Option<ProtectorKind>,
|
retag_cause: RetagCause, // What caused this retag, for diagnostics only
|
||||||
) -> InterpResult<'tcx, Option<AllocId>> {
|
) -> InterpResult<'tcx, Option<AllocId>> {
|
||||||
let this = self.eval_context_mut();
|
let this = self.eval_context_mut();
|
||||||
|
|
||||||
@ -532,20 +607,16 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
|
|||||||
let global = this.machine.borrow_tracker.as_ref().unwrap().borrow();
|
let global = this.machine.borrow_tracker.as_ref().unwrap().borrow();
|
||||||
let ty = place.layout.ty;
|
let ty = place.layout.ty;
|
||||||
if global.tracked_pointer_tags.contains(&new_tag) {
|
if global.tracked_pointer_tags.contains(&new_tag) {
|
||||||
let mut kind_str = format!("{kind}");
|
let mut kind_str = String::new();
|
||||||
match kind {
|
match new_perm {
|
||||||
RefKind::Unique { two_phase: false }
|
NewPermission::Uniform { perm, .. } =>
|
||||||
if !ty.is_unpin(*this.tcx, this.param_env()) =>
|
write!(kind_str, "{perm:?} permission").unwrap(),
|
||||||
{
|
NewPermission::FreezeSensitive { freeze_perm, .. } if ty.is_freeze(*this.tcx, this.param_env()) =>
|
||||||
write!(kind_str, " (!Unpin pointee type {ty})").unwrap()
|
write!(kind_str, "{freeze_perm:?} permission").unwrap(),
|
||||||
},
|
NewPermission::FreezeSensitive { freeze_perm, nonfreeze_perm, .. } =>
|
||||||
RefKind::Shared
|
write!(kind_str, "{freeze_perm:?}/{nonfreeze_perm:?} permission for frozen/non-frozen parts").unwrap(),
|
||||||
if !ty.is_freeze(*this.tcx, this.param_env()) =>
|
}
|
||||||
{
|
write!(kind_str, " (pointee type {ty})").unwrap();
|
||||||
write!(kind_str, " (!Freeze pointee type {ty})").unwrap()
|
|
||||||
},
|
|
||||||
_ => write!(kind_str, " (pointee type {ty})").unwrap(),
|
|
||||||
};
|
|
||||||
this.emit_diagnostic(NonHaltingDiagnostic::CreatedPointerTag(
|
this.emit_diagnostic(NonHaltingDiagnostic::CreatedPointerTag(
|
||||||
new_tag.inner(),
|
new_tag.inner(),
|
||||||
Some(kind_str),
|
Some(kind_str),
|
||||||
@ -579,7 +650,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
|
|||||||
);
|
);
|
||||||
let mut dcx = dcx.build(&mut stacked_borrows.history, base_offset);
|
let mut dcx = dcx.build(&mut stacked_borrows.history, base_offset);
|
||||||
dcx.log_creation();
|
dcx.log_creation();
|
||||||
if protect.is_some() {
|
if new_perm.protector().is_some() {
|
||||||
dcx.log_protector();
|
dcx.log_protector();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -592,8 +663,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
|
|||||||
|
|
||||||
if size == Size::ZERO {
|
if size == Size::ZERO {
|
||||||
trace!(
|
trace!(
|
||||||
"reborrow of size 0: {} reference {:?} derived from {:?} (pointee {})",
|
"reborrow of size 0: reference {:?} derived from {:?} (pointee {})",
|
||||||
kind,
|
|
||||||
new_tag,
|
new_tag,
|
||||||
place.ptr,
|
place.ptr,
|
||||||
place.layout.ty,
|
place.layout.ty,
|
||||||
@ -630,8 +700,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
|
|||||||
}
|
}
|
||||||
|
|
||||||
trace!(
|
trace!(
|
||||||
"reborrow: {} reference {:?} derived from {:?} (pointee {}): {:?}, size {}",
|
"reborrow: reference {:?} derived from {:?} (pointee {}): {:?}, size {}",
|
||||||
kind,
|
|
||||||
new_tag,
|
new_tag,
|
||||||
orig_tag,
|
orig_tag,
|
||||||
place.layout.ty,
|
place.layout.ty,
|
||||||
@ -639,7 +708,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
|
|||||||
size.bytes()
|
size.bytes()
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(protect) = protect {
|
if let Some(protect) = new_perm.protector() {
|
||||||
// See comment in `Stack::item_invalidated` for why we store the tag twice.
|
// See comment in `Stack::item_invalidated` for why we store the tag twice.
|
||||||
this.frame_mut().extra.borrow_tracker.as_mut().unwrap().protected_tags.push(new_tag);
|
this.frame_mut().extra.borrow_tracker.as_mut().unwrap().protected_tags.push(new_tag);
|
||||||
this.machine
|
this.machine
|
||||||
@ -651,30 +720,45 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
|
|||||||
.insert(new_tag, protect);
|
.insert(new_tag, protect);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the stacks.
|
// Update the stacks, according to the new permission information we are given.
|
||||||
// Make sure that raw pointers and mutable shared references are reborrowed "weak":
|
match new_perm {
|
||||||
// There could be existing unique pointers reborrowed from them that should remain valid!
|
NewPermission::Uniform { perm, access, protector } => {
|
||||||
let (perm, access) = match kind {
|
assert!(perm != Permission::SharedReadOnly);
|
||||||
RefKind::Unique { two_phase } => {
|
// Here we can avoid `borrow()` calls because we have mutable references.
|
||||||
// Permission is Unique only if the type is `Unpin` and this is not twophase
|
// Note that this asserts that the allocation is mutable -- but since we are creating a
|
||||||
if !two_phase && place.layout.ty.is_unpin(*this.tcx, this.param_env()) {
|
// mutable pointer, that seems reasonable.
|
||||||
(Permission::Unique, Some(AccessKind::Write))
|
let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc_id)?;
|
||||||
} else {
|
let stacked_borrows = alloc_extra.borrow_tracker_sb_mut().get_mut();
|
||||||
// FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we
|
let item = Item::new(new_tag, perm, protector.is_some());
|
||||||
// should do fake accesses here. But then we run into
|
let range = alloc_range(base_offset, size);
|
||||||
// <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>, so for now
|
let global = machine.borrow_tracker.as_ref().unwrap().borrow();
|
||||||
// we don't do that.
|
let dcx = DiagnosticCxBuilder::retag(
|
||||||
(Permission::SharedReadWrite, None)
|
machine,
|
||||||
|
retag_cause,
|
||||||
|
new_tag,
|
||||||
|
orig_tag,
|
||||||
|
alloc_range(base_offset, size),
|
||||||
|
);
|
||||||
|
stacked_borrows.for_each(range, dcx, |stack, dcx, exposed_tags| {
|
||||||
|
stack.grant(orig_tag, item, access, &global, dcx, exposed_tags)
|
||||||
|
})?;
|
||||||
|
drop(global);
|
||||||
|
if let Some(access) = access {
|
||||||
|
assert_eq!(access, AccessKind::Write);
|
||||||
|
// Make sure the data race model also knows about this.
|
||||||
|
if let Some(data_race) = alloc_extra.data_race.as_mut() {
|
||||||
|
data_race.write(alloc_id, range, machine)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RefKind::Box => (Permission::Unique, Some(AccessKind::Write)),
|
NewPermission::FreezeSensitive {
|
||||||
RefKind::Raw { mutable: true } => {
|
freeze_perm,
|
||||||
// Creating a raw ptr does not count as an access
|
freeze_access,
|
||||||
(Permission::SharedReadWrite, None)
|
freeze_protector,
|
||||||
}
|
nonfreeze_perm,
|
||||||
RefKind::Shared | RefKind::Raw { mutable: false } => {
|
nonfreeze_access,
|
||||||
// Shared references and *const are a whole different kind of game, the
|
} => {
|
||||||
// permission is not uniform across the entire range!
|
// The permission is not uniform across the entire range!
|
||||||
// We need a frozen-sensitive reborrow.
|
// We need a frozen-sensitive reborrow.
|
||||||
// We have to use shared references to alloc/memory_extra here since
|
// We have to use shared references to alloc/memory_extra here since
|
||||||
// `visit_freeze_sensitive` needs to access the global state.
|
// `visit_freeze_sensitive` needs to access the global state.
|
||||||
@ -684,22 +768,12 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
|
|||||||
// Adjust range.
|
// Adjust range.
|
||||||
range.start += base_offset;
|
range.start += base_offset;
|
||||||
// We are only ever `SharedReadOnly` inside the frozen bits.
|
// We are only ever `SharedReadOnly` inside the frozen bits.
|
||||||
let (perm, access) = if frozen {
|
let (perm, access, protector) = if frozen {
|
||||||
(Permission::SharedReadOnly, Some(AccessKind::Read))
|
(freeze_perm, freeze_access, freeze_protector)
|
||||||
} else {
|
} else {
|
||||||
// Inside UnsafeCell, this does *not* count as an access, as there
|
(nonfreeze_perm, nonfreeze_access, None)
|
||||||
// might actually be mutable references further up the stack that
|
|
||||||
// we have to keep alive.
|
|
||||||
(Permission::SharedReadWrite, None)
|
|
||||||
};
|
};
|
||||||
let protected = if frozen {
|
let item = Item::new(new_tag, perm, protector.is_some());
|
||||||
protect.is_some()
|
|
||||||
} else {
|
|
||||||
// We do not protect inside UnsafeCell.
|
|
||||||
// This fixes https://github.com/rust-lang/rust/issues/55005.
|
|
||||||
false
|
|
||||||
};
|
|
||||||
let item = Item::new(new_tag, perm, protected);
|
|
||||||
let global = this.machine.borrow_tracker.as_ref().unwrap().borrow();
|
let global = this.machine.borrow_tracker.as_ref().unwrap().borrow();
|
||||||
let dcx = DiagnosticCxBuilder::retag(
|
let dcx = DiagnosticCxBuilder::retag(
|
||||||
&this.machine,
|
&this.machine,
|
||||||
@ -721,34 +795,6 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
return Ok(Some(alloc_id));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Here we can avoid `borrow()` calls because we have mutable references.
|
|
||||||
// Note that this asserts that the allocation is mutable -- but since we are creating a
|
|
||||||
// mutable pointer, that seems reasonable.
|
|
||||||
let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc_id)?;
|
|
||||||
let stacked_borrows = alloc_extra.borrow_tracker_sb_mut().get_mut();
|
|
||||||
let item = Item::new(new_tag, perm, protect.is_some());
|
|
||||||
let range = alloc_range(base_offset, size);
|
|
||||||
let global = machine.borrow_tracker.as_ref().unwrap().borrow();
|
|
||||||
let dcx = DiagnosticCxBuilder::retag(
|
|
||||||
machine,
|
|
||||||
retag_cause,
|
|
||||||
new_tag,
|
|
||||||
orig_tag,
|
|
||||||
alloc_range(base_offset, size),
|
|
||||||
);
|
|
||||||
stacked_borrows.for_each(range, dcx, |stack, dcx, exposed_tags| {
|
|
||||||
stack.grant(orig_tag, item, access, &global, dcx, exposed_tags)
|
|
||||||
})?;
|
|
||||||
drop(global);
|
|
||||||
if let Some(access) = access {
|
|
||||||
assert_eq!(access, AccessKind::Write);
|
|
||||||
// Make sure the data race model also knows about this.
|
|
||||||
if let Some(data_race) = alloc_extra.data_race.as_mut() {
|
|
||||||
data_race.write(alloc_id, range, machine)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -760,9 +806,8 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
|
|||||||
fn sb_retag_reference(
|
fn sb_retag_reference(
|
||||||
&mut self,
|
&mut self,
|
||||||
val: &ImmTy<'tcx, Provenance>,
|
val: &ImmTy<'tcx, Provenance>,
|
||||||
kind: RefKind,
|
new_perm: NewPermission,
|
||||||
retag_cause: RetagCause, // What caused this retag, for diagnostics only
|
cause: RetagCause, // What caused this retag, for diagnostics only
|
||||||
protect: Option<ProtectorKind>,
|
|
||||||
) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
|
) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
|
||||||
let this = self.eval_context_mut();
|
let this = self.eval_context_mut();
|
||||||
// We want a place for where the ptr *points to*, so we get one.
|
// We want a place for where the ptr *points to*, so we get one.
|
||||||
@ -780,7 +825,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
|
|||||||
let new_tag = this.machine.borrow_tracker.as_mut().unwrap().get_mut().new_ptr();
|
let new_tag = this.machine.borrow_tracker.as_mut().unwrap().get_mut().new_ptr();
|
||||||
|
|
||||||
// Reborrow.
|
// Reborrow.
|
||||||
let alloc_id = this.sb_reborrow(&place, size, kind, retag_cause, new_tag, protect)?;
|
let alloc_id = this.sb_reborrow(&place, size, new_perm, new_tag, cause)?;
|
||||||
|
|
||||||
// Adjust pointer.
|
// Adjust pointer.
|
||||||
let new_place = place.map_provenance(|p| {
|
let new_place = place.map_provenance(|p| {
|
||||||
@ -807,7 +852,22 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
|
|||||||
|
|
||||||
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
||||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
fn sb_retag(
|
fn sb_retag_ptr_value(
|
||||||
|
&mut self,
|
||||||
|
kind: RetagKind,
|
||||||
|
val: &ImmTy<'tcx, Provenance>,
|
||||||
|
) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
|
||||||
|
let this = self.eval_context_mut();
|
||||||
|
let new_perm = NewPermission::from_ref_ty(val.layout.ty, kind, this);
|
||||||
|
let retag_cause = match kind {
|
||||||
|
RetagKind::TwoPhase { .. } => RetagCause::TwoPhase,
|
||||||
|
RetagKind::FnEntry => unreachable!(),
|
||||||
|
RetagKind::Raw | RetagKind::Default => RetagCause::Normal,
|
||||||
|
};
|
||||||
|
this.sb_retag_reference(&val, new_perm, retag_cause)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sb_retag_place_contents(
|
||||||
&mut self,
|
&mut self,
|
||||||
kind: RetagKind,
|
kind: RetagKind,
|
||||||
place: &PlaceTy<'tcx, Provenance>,
|
place: &PlaceTy<'tcx, Provenance>,
|
||||||
@ -815,9 +875,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
let this = self.eval_context_mut();
|
let this = self.eval_context_mut();
|
||||||
let retag_fields = this.machine.borrow_tracker.as_mut().unwrap().get_mut().retag_fields;
|
let retag_fields = this.machine.borrow_tracker.as_mut().unwrap().get_mut().retag_fields;
|
||||||
let retag_cause = match kind {
|
let retag_cause = match kind {
|
||||||
RetagKind::TwoPhase { .. } => RetagCause::TwoPhase,
|
RetagKind::Raw | RetagKind::TwoPhase { .. } => unreachable!(), // these can only happen in `retag_ptr_value`
|
||||||
RetagKind::FnEntry => RetagCause::FnEntry,
|
RetagKind::FnEntry => RetagCause::FnEntry,
|
||||||
RetagKind::Raw | RetagKind::Default => RetagCause::Normal,
|
RetagKind::Default => RetagCause::Normal,
|
||||||
};
|
};
|
||||||
let mut visitor = RetagVisitor { ecx: this, kind, retag_cause, retag_fields };
|
let mut visitor = RetagVisitor { ecx: this, kind, retag_cause, retag_fields };
|
||||||
return visitor.visit_value(place);
|
return visitor.visit_value(place);
|
||||||
@ -831,15 +891,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
}
|
}
|
||||||
impl<'ecx, 'mir, 'tcx> RetagVisitor<'ecx, 'mir, 'tcx> {
|
impl<'ecx, 'mir, 'tcx> RetagVisitor<'ecx, 'mir, 'tcx> {
|
||||||
#[inline(always)] // yes this helps in our benchmarks
|
#[inline(always)] // yes this helps in our benchmarks
|
||||||
fn retag_place(
|
fn retag_ptr_inplace(
|
||||||
&mut self,
|
&mut self,
|
||||||
place: &PlaceTy<'tcx, Provenance>,
|
place: &PlaceTy<'tcx, Provenance>,
|
||||||
ref_kind: RefKind,
|
new_perm: NewPermission,
|
||||||
retag_cause: RetagCause,
|
retag_cause: RetagCause,
|
||||||
protector: Option<ProtectorKind>,
|
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?;
|
let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?;
|
||||||
let val = self.ecx.sb_retag_reference(&val, ref_kind, retag_cause, protector)?;
|
let val = self.ecx.sb_retag_reference(&val, new_perm, retag_cause)?;
|
||||||
self.ecx.write_immediate(*val, place)?;
|
self.ecx.write_immediate(*val, place)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -856,13 +915,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
|
|
||||||
fn visit_box(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
fn visit_box(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||||
// Boxes get a weak protectors, since they may be deallocated.
|
// Boxes get a weak protectors, since they may be deallocated.
|
||||||
self.retag_place(
|
let new_perm = NewPermission::Uniform {
|
||||||
place,
|
perm: Permission::Unique,
|
||||||
RefKind::Box,
|
access: Some(AccessKind::Write),
|
||||||
self.retag_cause,
|
protector: (self.kind == RetagKind::FnEntry)
|
||||||
/*protector*/
|
.then_some(ProtectorKind::WeakProtector),
|
||||||
(self.kind == RetagKind::FnEntry).then_some(ProtectorKind::WeakProtector),
|
};
|
||||||
)
|
self.retag_ptr_inplace(place, new_perm, self.retag_cause)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_value(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
fn visit_value(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||||
@ -876,36 +935,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
|
|
||||||
// Check the type of this value to see what to do with it (retag, or recurse).
|
// Check the type of this value to see what to do with it (retag, or recurse).
|
||||||
match place.layout.ty.kind() {
|
match place.layout.ty.kind() {
|
||||||
ty::Ref(_, _, mutbl) => {
|
ty::Ref(..) => {
|
||||||
let ref_kind = match mutbl {
|
let new_perm =
|
||||||
Mutability::Mut =>
|
NewPermission::from_ref_ty(place.layout.ty, self.kind, self.ecx);
|
||||||
RefKind::Unique { two_phase: self.kind == RetagKind::TwoPhase },
|
self.retag_ptr_inplace(place, new_perm, self.retag_cause)?;
|
||||||
Mutability::Not => RefKind::Shared,
|
|
||||||
};
|
|
||||||
self.retag_place(
|
|
||||||
place,
|
|
||||||
ref_kind,
|
|
||||||
self.retag_cause,
|
|
||||||
/*protector*/
|
|
||||||
(self.kind == RetagKind::FnEntry)
|
|
||||||
.then_some(ProtectorKind::StrongProtector),
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
ty::RawPtr(tym) => {
|
ty::RawPtr(..) => {
|
||||||
// We definitely do *not* want to recurse into raw pointers -- wide raw
|
// We do *not* want to recurse into raw pointers -- wide raw pointers have
|
||||||
// pointers have fields, and for dyn Trait pointees those can have reference
|
// fields, and for dyn Trait pointees those can have reference type!
|
||||||
// type!
|
|
||||||
if self.kind == RetagKind::Raw {
|
|
||||||
// Raw pointers need to be enabled.
|
|
||||||
self.retag_place(
|
|
||||||
place,
|
|
||||||
RefKind::Raw { mutable: tym.mutbl == Mutability::Mut },
|
|
||||||
self.retag_cause,
|
|
||||||
/*protector*/ None,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ if place.layout.ty.ty_adt_def().is_some_and(|adt| adt.is_box()) => {
|
ty::Adt(adt, _) if adt.is_box() => {
|
||||||
// Recurse for boxes, they require some tricky handling and will end up in `visit_box` above.
|
// Recurse for boxes, they require some tricky handling and will end up in `visit_box` above.
|
||||||
// (Yes this means we technically also recursively retag the allocator itself
|
// (Yes this means we technically also recursively retag the allocator itself
|
||||||
// even if field retagging is not enabled. *shrug*)
|
// even if field retagging is not enabled. *shrug*)
|
||||||
@ -953,12 +992,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
let ptr_layout = this.layout_of(this.tcx.mk_mut_ptr(return_place.layout.ty))?;
|
let ptr_layout = this.layout_of(this.tcx.mk_mut_ptr(return_place.layout.ty))?;
|
||||||
let val = ImmTy::from_immediate(return_place.to_ref(this), ptr_layout);
|
let val = ImmTy::from_immediate(return_place.to_ref(this), ptr_layout);
|
||||||
// Reborrow it. With protection! That is part of the point.
|
// Reborrow it. With protection! That is part of the point.
|
||||||
let val = this.sb_retag_reference(
|
let new_perm = NewPermission::Uniform {
|
||||||
&val,
|
perm: Permission::Unique,
|
||||||
RefKind::Unique { two_phase: false },
|
access: Some(AccessKind::Write),
|
||||||
RetagCause::FnReturn,
|
protector: Some(ProtectorKind::StrongProtector),
|
||||||
/*protector*/ Some(ProtectorKind::StrongProtector),
|
};
|
||||||
)?;
|
let val = this.sb_retag_reference(&val, new_perm, RetagCause::FnReturn)?;
|
||||||
// And use reborrowed pointer for return place.
|
// And use reborrowed pointer for return place.
|
||||||
let return_place = this.ref_to_mplace(&val)?;
|
let return_place = this.ref_to_mplace(&val)?;
|
||||||
this.frame_mut().return_place = return_place.into();
|
this.frame_mut().return_place = return_place.into();
|
||||||
|
@ -63,9 +63,9 @@ impl MachineStopType for TerminationInfo {}
|
|||||||
|
|
||||||
/// Miri specific diagnostics
|
/// Miri specific diagnostics
|
||||||
pub enum NonHaltingDiagnostic {
|
pub enum NonHaltingDiagnostic {
|
||||||
/// (new_tag, new_kind, (alloc_id, base_offset, orig_tag))
|
/// (new_tag, new_perm, (alloc_id, base_offset, orig_tag))
|
||||||
///
|
///
|
||||||
/// new_kind is `None` for base tags.
|
/// new_perm is `None` for base tags.
|
||||||
CreatedPointerTag(NonZeroU64, Option<String>, Option<(AllocId, AllocRange, ProvenanceExtra)>),
|
CreatedPointerTag(NonZeroU64, Option<String>, Option<(AllocId, AllocRange, ProvenanceExtra)>),
|
||||||
/// This `Item` was popped from the borrow stack. The string explains the reason.
|
/// This `Item` was popped from the borrow stack. The string explains the reason.
|
||||||
PoppedPointerTag(Item, String),
|
PoppedPointerTag(Item, String),
|
||||||
@ -393,10 +393,10 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
|
|||||||
|
|
||||||
let msg = match &e {
|
let msg = match &e {
|
||||||
CreatedPointerTag(tag, None, _) => format!("created base tag {tag:?}"),
|
CreatedPointerTag(tag, None, _) => format!("created base tag {tag:?}"),
|
||||||
CreatedPointerTag(tag, Some(kind), None) => format!("created {tag:?} for {kind}"),
|
CreatedPointerTag(tag, Some(perm), None) => format!("created {tag:?} with {perm} derived from unknown tag"),
|
||||||
CreatedPointerTag(tag, Some(kind), Some((alloc_id, range, orig_tag))) =>
|
CreatedPointerTag(tag, Some(perm), Some((alloc_id, range, orig_tag))) =>
|
||||||
format!(
|
format!(
|
||||||
"created tag {tag:?} for {kind} at {alloc_id:?}{range:?} derived from {orig_tag:?}"
|
"created tag {tag:?} with {perm} at {alloc_id:?}{range:?} derived from {orig_tag:?}"
|
||||||
),
|
),
|
||||||
PoppedPointerTag(item, cause) => format!("popped tracked tag for item {item:?}{cause}"),
|
PoppedPointerTag(item, cause) => format!("popped tracked tag for item {item:?}{cause}"),
|
||||||
CreatedCallId(id) => format!("function call with id {id}"),
|
CreatedCallId(id) => format!("function call with id {id}"),
|
||||||
|
@ -967,8 +967,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
|||||||
ptr: Pointer<Self::Provenance>,
|
ptr: Pointer<Self::Provenance>,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
match ptr.provenance {
|
match ptr.provenance {
|
||||||
Provenance::Concrete { alloc_id, tag } =>
|
Provenance::Concrete { alloc_id, tag } => {
|
||||||
intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag),
|
intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag)
|
||||||
|
}
|
||||||
Provenance::Wildcard => {
|
Provenance::Wildcard => {
|
||||||
// No need to do anything for wildcard pointers as
|
// No need to do anything for wildcard pointers as
|
||||||
// their provenances have already been previously exposed.
|
// their provenances have already been previously exposed.
|
||||||
@ -1055,13 +1056,26 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn retag(
|
fn retag_ptr_value(
|
||||||
|
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||||
|
kind: mir::RetagKind,
|
||||||
|
val: &ImmTy<'tcx, Provenance>,
|
||||||
|
) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
|
||||||
|
if ecx.machine.borrow_tracker.is_some() {
|
||||||
|
ecx.retag_ptr_value(kind, val)
|
||||||
|
} else {
|
||||||
|
Ok(val.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn retag_place_contents(
|
||||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||||
kind: mir::RetagKind,
|
kind: mir::RetagKind,
|
||||||
place: &PlaceTy<'tcx, Provenance>,
|
place: &PlaceTy<'tcx, Provenance>,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
if ecx.machine.borrow_tracker.is_some() {
|
if ecx.machine.borrow_tracker.is_some() {
|
||||||
ecx.retag(kind, place)?;
|
ecx.retag_place_contents(kind, place)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user