Merge from rustc
This commit is contained in:
commit
ed0573fb2a
275 changed files with 7688 additions and 2669 deletions
34
Cargo.lock
34
Cargo.lock
|
|
@ -854,7 +854,7 @@ dependencies = [
|
|||
"autocfg",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"memoffset",
|
||||
"memoffset 0.7.1",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
|
|
@ -1241,6 +1241,16 @@ dependencies = [
|
|||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "field-offset"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3cf3a800ff6e860c863ca6d4b16fd999db8b752819c1606884047b73e468535"
|
||||
dependencies = [
|
||||
"memoffset 0.8.0",
|
||||
"rustc_version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.20"
|
||||
|
|
@ -2188,6 +2198,15 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.7.1"
|
||||
|
|
@ -2197,6 +2216,15 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.16"
|
||||
|
|
@ -3306,6 +3334,7 @@ dependencies = [
|
|||
"rustc-hash",
|
||||
"rustc-rayon",
|
||||
"rustc-rayon-core",
|
||||
"rustc_arena",
|
||||
"rustc_graphviz",
|
||||
"rustc_index",
|
||||
"rustc_macros",
|
||||
|
|
@ -3781,6 +3810,7 @@ dependencies = [
|
|||
"chalk-ir",
|
||||
"derive_more",
|
||||
"either",
|
||||
"field-offset",
|
||||
"gsgdt",
|
||||
"measureme",
|
||||
"polonius-engine",
|
||||
|
|
@ -3995,7 +4025,9 @@ dependencies = [
|
|||
name = "rustc_query_impl"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"field-offset",
|
||||
"measureme",
|
||||
"memoffset 0.6.5",
|
||||
"rustc-rayon-core",
|
||||
"rustc_ast",
|
||||
"rustc_data_structures",
|
||||
|
|
|
|||
|
|
@ -48,14 +48,15 @@ pub enum TokenTree {
|
|||
Delimited(DelimSpan, Delimiter, TokenStream),
|
||||
}
|
||||
|
||||
// Ensure all fields of `TokenTree` is `Send` and `Sync`.
|
||||
// Ensure all fields of `TokenTree` are `DynSend` and `DynSync`.
|
||||
#[cfg(parallel_compiler)]
|
||||
fn _dummy()
|
||||
where
|
||||
Token: Send + Sync,
|
||||
DelimSpan: Send + Sync,
|
||||
Delimiter: Send + Sync,
|
||||
TokenStream: Send + Sync,
|
||||
Token: sync::DynSend + sync::DynSync,
|
||||
Spacing: sync::DynSend + sync::DynSync,
|
||||
DelimSpan: sync::DynSend + sync::DynSync,
|
||||
Delimiter: sync::DynSend + sync::DynSync,
|
||||
TokenStream: sync::DynSend + sync::DynSync,
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -118,7 +119,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub trait ToAttrTokenStream: sync::Send + sync::Sync {
|
||||
pub trait ToAttrTokenStream: sync::DynSend + sync::DynSync {
|
||||
fn to_attr_token_stream(&self) -> AttrTokenStream;
|
||||
}
|
||||
|
||||
|
|
@ -550,6 +551,10 @@ impl TokenStream {
|
|||
vec_mut.extend(stream_iter);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chunks(&self, chunk_size: usize) -> core::slice::Chunks<'_, TokenTree> {
|
||||
self.0.chunks(chunk_size)
|
||||
}
|
||||
}
|
||||
|
||||
/// By-reference iterator over a [`TokenStream`], that produces `&TokenTree`
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ use rustc_middle::mir::{
|
|||
use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
|
||||
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
|
||||
use rustc_middle::mir::{ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, CapturedPlace, ParamEnv, RegionVid, TyCtxt};
|
||||
use rustc_session::lint::builtin::UNUSED_MUT;
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
|
|
|||
|
|
@ -63,7 +63,8 @@ pub fn expand_env<'cx>(
|
|||
Some(exprs) => exprs.into_iter(),
|
||||
};
|
||||
|
||||
let Some((var, _style)) = expr_to_string(cx, exprs.next().unwrap(), "expected string literal") else {
|
||||
let var_expr = exprs.next().unwrap();
|
||||
let Some((var, _)) = expr_to_string(cx, var_expr.clone(), "expected string literal") else {
|
||||
return DummyResult::any(sp);
|
||||
};
|
||||
|
||||
|
|
@ -71,7 +72,7 @@ pub fn expand_env<'cx>(
|
|||
None => None,
|
||||
Some(second) => match expr_to_string(cx, second, "expected string literal") {
|
||||
None => return DummyResult::any(sp),
|
||||
Some((s, _style)) => Some(s),
|
||||
Some((s, _)) => Some(s),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -80,10 +81,15 @@ pub fn expand_env<'cx>(
|
|||
cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
|
||||
let e = match value {
|
||||
None => {
|
||||
// Use the string literal in the code in the diagnostic to avoid confusing diagnostics,
|
||||
// e.g. when the literal contains escape sequences.
|
||||
let ast::ExprKind::Lit(ast::token::Lit { kind: ast::token::LitKind::Str, symbol: original_var, ..}) = &var_expr.kind else {
|
||||
unreachable!("`expr_to_string` ensures this is a string lit")
|
||||
};
|
||||
cx.emit_err(errors::EnvNotDefined {
|
||||
span: sp,
|
||||
msg: custom_msg,
|
||||
var,
|
||||
var: *original_var,
|
||||
help: custom_msg.is_none().then(|| help_for_missing_env_var(var.as_str())),
|
||||
});
|
||||
return DummyResult::any(sp);
|
||||
|
|
|
|||
|
|
@ -80,8 +80,8 @@ use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, Handler, SubdiagnosticMes
|
|||
use rustc_fluent_macro::fluent_messages;
|
||||
use rustc_metadata::EncodedMetadata;
|
||||
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_session::config::{Lto, OptLevel, OutputFilenames};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::Symbol;
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, FatalError, Handler, Subd
|
|||
use rustc_fluent_macro::fluent_messages;
|
||||
use rustc_metadata::EncodedMetadata;
|
||||
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::{OptLevel, OutputFilenames, PrintRequest};
|
||||
use rustc_session::Session;
|
||||
|
|
|
|||
|
|
@ -155,12 +155,6 @@ pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]
|
|||
("x86", "rdrand") => smallvec!["rdrnd"],
|
||||
("x86", "bmi1") => smallvec!["bmi"],
|
||||
("x86", "cmpxchg16b") => smallvec!["cx16"],
|
||||
// FIXME: These aliases are misleading, and should be removed before avx512_target_feature is
|
||||
// stabilized. They must remain until std::arch switches off them.
|
||||
// rust#100752
|
||||
("x86", "avx512vaes") => smallvec!["vaes"],
|
||||
("x86", "avx512gfni") => smallvec!["gfni"],
|
||||
("x86", "avx512vpclmulqdq") => smallvec!["vpclmulqdq"],
|
||||
("aarch64", "rcpc2") => smallvec!["rcpc-immo"],
|
||||
("aarch64", "dpb") => smallvec!["ccpp"],
|
||||
("aarch64", "dpb2") => smallvec!["ccdp"],
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc_middle::middle::exported_symbols::{
|
|||
metadata_symbol_name, ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel,
|
||||
};
|
||||
use rustc_middle::query::LocalCrate;
|
||||
use rustc_middle::ty::query::{ExternProviders, Providers};
|
||||
use rustc_middle::query::{ExternProviders, Providers};
|
||||
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
|
||||
use rustc_middle::ty::Instance;
|
||||
use rustc_middle::ty::{self, SymbolName, TyCtxt};
|
||||
|
|
|
|||
|
|
@ -17,10 +17,7 @@ use rustc_ast::expand::allocator::AllocatorKind;
|
|||
use rustc_attr as attr;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
|
||||
|
||||
use rustc_data_structures::sync::par_iter;
|
||||
#[cfg(parallel_compiler)]
|
||||
use rustc_data_structures::sync::ParallelIterator;
|
||||
use rustc_data_structures::sync::par_map;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
|
|
@ -30,8 +27,8 @@ use rustc_middle::middle::exported_symbols;
|
|||
use rustc_middle::middle::exported_symbols::SymbolExportKind;
|
||||
use rustc_middle::middle::lang_items;
|
||||
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
|
||||
use rustc_session::cgu_reuse_tracker::CguReuse;
|
||||
use rustc_session::config::{self, CrateType, EntryFnType, OutputType};
|
||||
|
|
@ -689,7 +686,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
|||
// This likely is a temporary measure. Once we don't have to support the
|
||||
// non-parallel compiler anymore, we can compile CGUs end-to-end in
|
||||
// parallel and get rid of the complicated scheduling logic.
|
||||
let mut pre_compiled_cgus = if cfg!(parallel_compiler) {
|
||||
let mut pre_compiled_cgus = if tcx.sess.threads() > 1 {
|
||||
tcx.sess.time("compile_first_CGU_batch", || {
|
||||
// Try to find one CGU to compile per thread.
|
||||
let cgus: Vec<_> = cgu_reuse
|
||||
|
|
@ -702,12 +699,10 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
|||
// Compile the found CGUs in parallel.
|
||||
let start_time = Instant::now();
|
||||
|
||||
let pre_compiled_cgus = par_iter(cgus)
|
||||
.map(|(i, _)| {
|
||||
let module = backend.compile_codegen_unit(tcx, codegen_units[i].name());
|
||||
(i, module)
|
||||
})
|
||||
.collect();
|
||||
let pre_compiled_cgus = par_map(cgus, |(i, _)| {
|
||||
let module = backend.compile_codegen_unit(tcx, codegen_units[i].name());
|
||||
(i, module)
|
||||
});
|
||||
|
||||
total_codegen_time += start_time.elapsed();
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
|
|||
use rustc_hir::{lang_items, weak_lang_items::WEAK_LANG_ITEMS, LangItem};
|
||||
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
||||
use rustc_middle::mir::mono::Linkage;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self as ty, TyCtxt};
|
||||
use rustc_session::{lint, parse::feature_err};
|
||||
use rustc_span::symbol::Ident;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ use rustc_hir::def_id::CrateNum;
|
|||
use rustc_middle::dep_graph::WorkProduct;
|
||||
use rustc_middle::middle::dependency_format::Dependencies;
|
||||
use rustc_middle::middle::exported_symbols::SymbolExportKind;
|
||||
use rustc_middle::ty::query::{ExternProviders, Providers};
|
||||
use rustc_middle::query::{ExternProviders, Providers};
|
||||
use rustc_serialize::opaque::{FileEncoder, MemDecoder};
|
||||
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
||||
use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
|
|||
use rustc_session::config::DebugInfo;
|
||||
use rustc_span::symbol::{kw, Symbol};
|
||||
use rustc_span::{BytePos, Span};
|
||||
use rustc_target::abi::{Abi, FieldIdx, Size, VariantIdx};
|
||||
use rustc_target::abi::{Abi, FieldIdx, FieldsShape, Size, VariantIdx};
|
||||
|
||||
use super::operand::{OperandRef, OperandValue};
|
||||
use super::place::PlaceRef;
|
||||
|
|
@ -41,6 +41,9 @@ pub struct PerLocalVarDebugInfo<'tcx, D> {
|
|||
|
||||
/// `.place.projection` from `mir::VarDebugInfo`.
|
||||
pub projection: &'tcx ty::List<mir::PlaceElem<'tcx>>,
|
||||
|
||||
/// `references` from `mir::VarDebugInfo`.
|
||||
pub references: u8,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
|
@ -80,6 +83,7 @@ trait DebugInfoOffsetLocation<'tcx, Bx> {
|
|||
fn deref(&self, bx: &mut Bx) -> Self;
|
||||
fn layout(&self) -> TyAndLayout<'tcx>;
|
||||
fn project_field(&self, bx: &mut Bx, field: FieldIdx) -> Self;
|
||||
fn project_constant_index(&self, bx: &mut Bx, offset: u64) -> Self;
|
||||
fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self;
|
||||
}
|
||||
|
||||
|
|
@ -98,6 +102,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
|
|||
PlaceRef::project_field(*self, bx, field.index())
|
||||
}
|
||||
|
||||
fn project_constant_index(&self, bx: &mut Bx, offset: u64) -> Self {
|
||||
let lloffset = bx.cx().const_usize(offset);
|
||||
self.project_index(bx, lloffset)
|
||||
}
|
||||
|
||||
fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self {
|
||||
self.project_downcast(bx, variant)
|
||||
}
|
||||
|
|
@ -120,6 +129,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
|
|||
self.field(bx.cx(), field.index())
|
||||
}
|
||||
|
||||
fn project_constant_index(&self, bx: &mut Bx, index: u64) -> Self {
|
||||
self.field(bx.cx(), index as usize)
|
||||
}
|
||||
|
||||
fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self {
|
||||
self.for_variant(bx.cx(), variant)
|
||||
}
|
||||
|
|
@ -165,6 +178,18 @@ fn calculate_debuginfo_offset<
|
|||
mir::ProjectionElem::Downcast(_, variant) => {
|
||||
place = place.downcast(bx, variant);
|
||||
}
|
||||
mir::ProjectionElem::ConstantIndex {
|
||||
offset: index,
|
||||
min_length: _,
|
||||
from_end: false,
|
||||
} => {
|
||||
let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset);
|
||||
let FieldsShape::Array { stride, count: _ } = place.layout().fields else {
|
||||
span_bug!(var.source_info.span, "ConstantIndex on non-array type {:?}", place.layout())
|
||||
};
|
||||
*offset += stride * index;
|
||||
place = place.project_constant_index(bx, index);
|
||||
}
|
||||
_ => {
|
||||
// Sanity check for `can_use_in_debuginfo`.
|
||||
debug_assert!(!elem.can_use_in_debuginfo());
|
||||
|
|
@ -293,6 +318,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
dbg_var,
|
||||
fragment: None,
|
||||
projection: ty::List::empty(),
|
||||
references: 0,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
|
|
@ -358,57 +384,76 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let vars = vars.iter().cloned().chain(fallback_var);
|
||||
|
||||
for var in vars {
|
||||
let Some(dbg_var) = var.dbg_var else { continue };
|
||||
let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue };
|
||||
|
||||
let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
|
||||
calculate_debuginfo_offset(bx, local, &var, base.layout);
|
||||
|
||||
// When targeting MSVC, create extra allocas for arguments instead of pointing multiple
|
||||
// dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
|
||||
// not DWARF and LLVM doesn't support translating the resulting
|
||||
// [DW_OP_deref, DW_OP_plus_uconst, offset, DW_OP_deref] debug info to CodeView.
|
||||
// Creating extra allocas on the stack makes the resulting debug info simple enough
|
||||
// that LLVM can generate correct CodeView records and thus the values appear in the
|
||||
// debugger. (#83709)
|
||||
let should_create_individual_allocas = bx.cx().sess().target.is_like_msvc
|
||||
&& self.mir.local_kind(local) == mir::LocalKind::Arg
|
||||
// LLVM can handle simple things but anything more complex than just a direct
|
||||
// offset or one indirect offset of 0 is too complex for it to generate CV records
|
||||
// correctly.
|
||||
&& (direct_offset != Size::ZERO
|
||||
|| !matches!(&indirect_offsets[..], [Size::ZERO] | []));
|
||||
|
||||
if should_create_individual_allocas {
|
||||
let DebugInfoOffset { direct_offset: _, indirect_offsets: _, result: place } =
|
||||
calculate_debuginfo_offset(bx, local, &var, base);
|
||||
|
||||
// Create a variable which will be a pointer to the actual value
|
||||
let ptr_ty = bx
|
||||
.tcx()
|
||||
.mk_ptr(ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: place.layout.ty });
|
||||
let ptr_layout = bx.layout_of(ptr_ty);
|
||||
let alloca = PlaceRef::alloca(bx, ptr_layout);
|
||||
bx.set_var_name(alloca.llval, &(var.name.to_string() + ".dbg.spill"));
|
||||
|
||||
// Write the pointer to the variable
|
||||
bx.store(place.llval, alloca.llval, alloca.align);
|
||||
|
||||
// Point the debug info to `*alloca` for the current variable
|
||||
bx.dbg_var_addr(dbg_var, dbg_loc, alloca.llval, Size::ZERO, &[Size::ZERO], None);
|
||||
} else {
|
||||
bx.dbg_var_addr(
|
||||
dbg_var,
|
||||
dbg_loc,
|
||||
base.llval,
|
||||
direct_offset,
|
||||
&indirect_offsets,
|
||||
None,
|
||||
);
|
||||
}
|
||||
self.debug_introduce_local_as_var(bx, local, base, var);
|
||||
}
|
||||
}
|
||||
|
||||
fn debug_introduce_local_as_var(
|
||||
&self,
|
||||
bx: &mut Bx,
|
||||
local: mir::Local,
|
||||
mut base: PlaceRef<'tcx, Bx::Value>,
|
||||
var: PerLocalVarDebugInfo<'tcx, Bx::DIVariable>,
|
||||
) {
|
||||
let Some(dbg_var) = var.dbg_var else { return };
|
||||
let Some(dbg_loc) = self.dbg_loc(var.source_info) else { return };
|
||||
|
||||
let DebugInfoOffset { mut direct_offset, indirect_offsets, result: _ } =
|
||||
calculate_debuginfo_offset(bx, local, &var, base.layout);
|
||||
let mut indirect_offsets = &indirect_offsets[..];
|
||||
|
||||
// When targeting MSVC, create extra allocas for arguments instead of pointing multiple
|
||||
// dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
|
||||
// not DWARF and LLVM doesn't support translating the resulting
|
||||
// [DW_OP_deref, DW_OP_plus_uconst, offset, DW_OP_deref] debug info to CodeView.
|
||||
// Creating extra allocas on the stack makes the resulting debug info simple enough
|
||||
// that LLVM can generate correct CodeView records and thus the values appear in the
|
||||
// debugger. (#83709)
|
||||
let should_create_individual_allocas = bx.cx().sess().target.is_like_msvc
|
||||
&& self.mir.local_kind(local) == mir::LocalKind::Arg
|
||||
// LLVM can handle simple things but anything more complex than just a direct
|
||||
// offset or one indirect offset of 0 is too complex for it to generate CV records
|
||||
// correctly.
|
||||
&& (direct_offset != Size::ZERO || !matches!(indirect_offsets, [Size::ZERO] | []));
|
||||
|
||||
let create_alloca = |bx: &mut Bx, place: PlaceRef<'tcx, Bx::Value>, refcount| {
|
||||
// Create a variable which will be a pointer to the actual value
|
||||
let ptr_ty = bx
|
||||
.tcx()
|
||||
.mk_ptr(ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: place.layout.ty });
|
||||
let ptr_layout = bx.layout_of(ptr_ty);
|
||||
let alloca = PlaceRef::alloca(bx, ptr_layout);
|
||||
bx.set_var_name(alloca.llval, &format!("{}.ref{}.dbg.spill", var.name, refcount));
|
||||
|
||||
// Write the pointer to the variable
|
||||
bx.store(place.llval, alloca.llval, alloca.align);
|
||||
|
||||
// Point the debug info to `*alloca` for the current variable
|
||||
alloca
|
||||
};
|
||||
|
||||
if var.references > 0 {
|
||||
base = calculate_debuginfo_offset(bx, local, &var, base).result;
|
||||
|
||||
// Point the debug info to `&...&base == alloca` for the current variable
|
||||
for refcount in 0..var.references {
|
||||
base = create_alloca(bx, base, refcount);
|
||||
}
|
||||
|
||||
direct_offset = Size::ZERO;
|
||||
indirect_offsets = &[];
|
||||
} else if should_create_individual_allocas {
|
||||
let place = calculate_debuginfo_offset(bx, local, &var, base).result;
|
||||
|
||||
// Point the debug info to `*alloca` for the current variable
|
||||
base = create_alloca(bx, place, 0);
|
||||
direct_offset = Size::ZERO;
|
||||
indirect_offsets = &[Size::ZERO];
|
||||
}
|
||||
|
||||
bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, indirect_offsets, None);
|
||||
}
|
||||
|
||||
pub fn debug_introduce_locals(&self, bx: &mut Bx) {
|
||||
if bx.sess().opts.debuginfo == DebugInfo::Full || !bx.sess().fewer_names() {
|
||||
for local in self.locals.indices() {
|
||||
|
|
@ -439,7 +484,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
};
|
||||
|
||||
let dbg_var = dbg_scope_and_span.map(|(dbg_scope, _, span)| {
|
||||
let (var_ty, var_kind) = match var.value {
|
||||
let (mut var_ty, var_kind) = match var.value {
|
||||
mir::VarDebugInfoContents::Place(place) => {
|
||||
let var_ty = self.monomorphized_place_ty(place.as_ref());
|
||||
let var_kind = if let Some(arg_index) = var.argument_index
|
||||
|
|
@ -476,6 +521,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
};
|
||||
|
||||
for _ in 0..var.references {
|
||||
var_ty =
|
||||
bx.tcx().mk_ptr(ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: var_ty });
|
||||
}
|
||||
|
||||
self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
|
||||
});
|
||||
|
||||
|
|
@ -487,6 +537,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
dbg_var,
|
||||
fragment: None,
|
||||
projection: place.projection,
|
||||
references: var.references,
|
||||
});
|
||||
}
|
||||
mir::VarDebugInfoContents::Const(c) => {
|
||||
|
|
@ -540,6 +591,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
Some(fragment_start..fragment_start + fragment_layout.size)
|
||||
},
|
||||
projection: place.projection,
|
||||
references: var.references,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -402,8 +402,6 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
|
|||
indirect_dest: PlaceRef<'tcx, V>,
|
||||
) {
|
||||
debug!("OperandRef::store_unsized: operand={:?}, indirect_dest={:?}", self, indirect_dest);
|
||||
let flags = MemFlags::empty();
|
||||
|
||||
// `indirect_dest` must have `*mut T` type. We extract `T` out of it.
|
||||
let unsized_ty = indirect_dest
|
||||
.layout
|
||||
|
|
@ -416,17 +414,23 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
|
|||
bug!("store_unsized called with a sized value")
|
||||
};
|
||||
|
||||
// FIXME: choose an appropriate alignment, or use dynamic align somehow
|
||||
let max_align = Align::from_bits(128).unwrap();
|
||||
let min_align = Align::from_bits(8).unwrap();
|
||||
|
||||
// Allocate an appropriate region on the stack, and copy the value into it
|
||||
let (llsize, _) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra));
|
||||
let lldst = bx.byte_array_alloca(llsize, max_align);
|
||||
bx.memcpy(lldst, max_align, llptr, min_align, llsize, flags);
|
||||
// Allocate an appropriate region on the stack, and copy the value into it. Since alloca
|
||||
// doesn't support dynamic alignment, we allocate an extra align - 1 bytes, and align the
|
||||
// pointer manually.
|
||||
let (size, align) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra));
|
||||
let one = bx.const_usize(1);
|
||||
let align_minus_1 = bx.sub(align, one);
|
||||
let size_extra = bx.add(size, align_minus_1);
|
||||
let min_align = Align::ONE;
|
||||
let alloca = bx.byte_array_alloca(size_extra, min_align);
|
||||
let address = bx.ptrtoint(alloca, bx.type_isize());
|
||||
let neg_address = bx.neg(address);
|
||||
let offset = bx.and(neg_address, align_minus_1);
|
||||
let dst = bx.inbounds_gep(bx.type_i8(), alloca, &[offset]);
|
||||
bx.memcpy(dst, min_align, llptr, min_align, size, MemFlags::empty());
|
||||
|
||||
// Store the allocated region and the extra to the indirect place.
|
||||
let indirect_operand = OperandValue::Pair(lldst, llextra);
|
||||
let indirect_operand = OperandValue::Pair(dst, llextra);
|
||||
indirect_operand.store(bx, indirect_dest);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc_hir::def::DefKind;
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::def_id::LOCAL_CRATE;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_session::Session;
|
||||
|
|
@ -173,16 +173,13 @@ const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
|||
("avx512dq", Some(sym::avx512_target_feature)),
|
||||
("avx512er", Some(sym::avx512_target_feature)),
|
||||
("avx512f", Some(sym::avx512_target_feature)),
|
||||
("avx512gfni", Some(sym::avx512_target_feature)),
|
||||
("avx512ifma", Some(sym::avx512_target_feature)),
|
||||
("avx512pf", Some(sym::avx512_target_feature)),
|
||||
("avx512vaes", Some(sym::avx512_target_feature)),
|
||||
("avx512vbmi", Some(sym::avx512_target_feature)),
|
||||
("avx512vbmi2", Some(sym::avx512_target_feature)),
|
||||
("avx512vl", Some(sym::avx512_target_feature)),
|
||||
("avx512vnni", Some(sym::avx512_target_feature)),
|
||||
("avx512vp2intersect", Some(sym::avx512_target_feature)),
|
||||
("avx512vpclmulqdq", Some(sym::avx512_target_feature)),
|
||||
("avx512vpopcntdq", Some(sym::avx512_target_feature)),
|
||||
("bmi1", None),
|
||||
("bmi2", None),
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ use rustc_data_structures::fx::FxHashMap;
|
|||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_metadata::EncodedMetadata;
|
||||
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
||||
use rustc_middle::query::{ExternProviders, Providers};
|
||||
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::query::{ExternProviders, Providers};
|
||||
use rustc_middle::ty::{Ty, TyCtxt};
|
||||
use rustc_session::{
|
||||
config::{self, OutputFilenames, PrintRequest},
|
||||
|
|
@ -22,6 +22,7 @@ use rustc_target::spec::Target;
|
|||
|
||||
pub use rustc_data_structures::sync::MetadataRef;
|
||||
|
||||
use rustc_data_structures::sync::{DynSend, DynSync};
|
||||
use std::any::Any;
|
||||
|
||||
pub trait BackendTypes {
|
||||
|
|
@ -117,7 +118,9 @@ pub trait CodegenBackend {
|
|||
) -> Result<(), ErrorGuaranteed>;
|
||||
}
|
||||
|
||||
pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Send + Sync {
|
||||
pub trait ExtraBackendMethods:
|
||||
CodegenBackend + WriteBackendMethods + Sized + Send + Sync + DynSend + DynSync
|
||||
{
|
||||
fn codegen_allocator<'tcx>(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use rustc_attr as attr;
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::symbol::Symbol;
|
||||
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ pub mod util;
|
|||
|
||||
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
|
||||
use rustc_fluent_macro::fluent_messages;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
|
||||
fluent_messages! { "../messages.ftl" }
|
||||
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
if let Some(root) = post_contract_node.get(&bb) {
|
||||
break *root;
|
||||
}
|
||||
let parent = doms.immediate_dominator(bb);
|
||||
let parent = doms.immediate_dominator(bb).unwrap();
|
||||
dom_path.push(bb);
|
||||
if !self.body.basic_blocks[parent].is_cleanup {
|
||||
break bb;
|
||||
|
|
@ -448,7 +448,15 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
};
|
||||
match debuginfo.value {
|
||||
VarDebugInfoContents::Const(_) => {}
|
||||
VarDebugInfoContents::Place(place) => check_place(place),
|
||||
VarDebugInfoContents::Place(place) => {
|
||||
check_place(place);
|
||||
if debuginfo.references != 0 && place.projection.last() == Some(&PlaceElem::Deref) {
|
||||
self.fail(
|
||||
START_BLOCK.start_location(),
|
||||
format!("debuginfo {:?}, has both ref and deref", debuginfo),
|
||||
);
|
||||
}
|
||||
}
|
||||
VarDebugInfoContents::Composite { ty, ref fragments } => {
|
||||
for f in fragments {
|
||||
check_place(f.contents);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ libc = "0.2"
|
|||
measureme = "10.0.0"
|
||||
rustc-rayon-core = { version = "0.5.0", optional = true }
|
||||
rustc-rayon = { version = "0.5.0", optional = true }
|
||||
rustc_arena = { path = "../rustc_arena" }
|
||||
rustc_graphviz = { path = "../rustc_graphviz" }
|
||||
rustc-hash = "1.1.0"
|
||||
rustc_index = { path = "../rustc_index", package = "rustc_index" }
|
||||
|
|
|
|||
|
|
@ -242,7 +242,9 @@ pub fn dominators<G: ControlFlowGraph>(graph: G) -> Dominators<G::Node> {
|
|||
immediate_dominators[*node] = Some(pre_order_to_real[idom[idx]]);
|
||||
}
|
||||
|
||||
Dominators { post_order_rank, immediate_dominators }
|
||||
let start_node = graph.start_node();
|
||||
immediate_dominators[start_node] = None;
|
||||
Dominators { start_node, post_order_rank, immediate_dominators }
|
||||
}
|
||||
|
||||
/// Evaluate the link-eval virtual forest, providing the currently minimum semi
|
||||
|
|
@ -308,6 +310,7 @@ fn compress(
|
|||
/// Tracks the list of dominators for each node.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Dominators<N: Idx> {
|
||||
start_node: N,
|
||||
post_order_rank: IndexVec<N, usize>,
|
||||
// Even though we track only the immediate dominator of each node, it's
|
||||
// possible to get its full list of dominators by looking up the dominator
|
||||
|
|
@ -316,14 +319,14 @@ pub struct Dominators<N: Idx> {
|
|||
}
|
||||
|
||||
impl<Node: Idx> Dominators<Node> {
|
||||
/// Whether the given Node has an immediate dominator.
|
||||
/// Returns true if node is reachable from the start node.
|
||||
pub fn is_reachable(&self, node: Node) -> bool {
|
||||
self.immediate_dominators[node].is_some()
|
||||
node == self.start_node || self.immediate_dominators[node].is_some()
|
||||
}
|
||||
|
||||
pub fn immediate_dominator(&self, node: Node) -> Node {
|
||||
assert!(self.is_reachable(node), "node {node:?} is not reachable");
|
||||
self.immediate_dominators[node].unwrap()
|
||||
/// Returns the immediate dominator of node, if any.
|
||||
pub fn immediate_dominator(&self, node: Node) -> Option<Node> {
|
||||
self.immediate_dominators[node]
|
||||
}
|
||||
|
||||
/// Provides an iterator over each dominator up the CFG, for the given Node.
|
||||
|
|
@ -357,12 +360,7 @@ impl<'dom, Node: Idx> Iterator for Iter<'dom, Node> {
|
|||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let Some(node) = self.node {
|
||||
let dom = self.dominators.immediate_dominator(node);
|
||||
if dom == node {
|
||||
self.node = None; // reached the root
|
||||
} else {
|
||||
self.node = Some(dom);
|
||||
}
|
||||
self.node = self.dominators.immediate_dominator(node);
|
||||
Some(node)
|
||||
} else {
|
||||
None
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ fn diamond() {
|
|||
|
||||
let dominators = dominators(&graph);
|
||||
let immediate_dominators = &dominators.immediate_dominators;
|
||||
assert_eq!(immediate_dominators[0], Some(0));
|
||||
assert_eq!(immediate_dominators[0], None);
|
||||
assert_eq!(immediate_dominators[1], Some(0));
|
||||
assert_eq!(immediate_dominators[2], Some(0));
|
||||
assert_eq!(immediate_dominators[3], Some(0));
|
||||
|
|
@ -30,7 +30,7 @@ fn paper() {
|
|||
assert_eq!(immediate_dominators[3], Some(6));
|
||||
assert_eq!(immediate_dominators[4], Some(6));
|
||||
assert_eq!(immediate_dominators[5], Some(6));
|
||||
assert_eq!(immediate_dominators[6], Some(6));
|
||||
assert_eq!(immediate_dominators[6], None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -43,3 +43,13 @@ fn paper_slt() {
|
|||
|
||||
dominators(&graph);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn immediate_dominator() {
|
||||
let graph = TestGraph::new(1, &[(1, 2), (2, 3)]);
|
||||
let dominators = dominators(&graph);
|
||||
assert_eq!(dominators.immediate_dominator(0), None);
|
||||
assert_eq!(dominators.immediate_dominator(1), None);
|
||||
assert_eq!(dominators.immediate_dominator(2), Some(1));
|
||||
assert_eq!(dominators.immediate_dominator(3), Some(2));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#![feature(test)]
|
||||
#![feature(thread_id_value)]
|
||||
#![feature(vec_into_raw_parts)]
|
||||
#![feature(allocator_api)]
|
||||
#![feature(get_mut_unchecked)]
|
||||
#![feature(lint_reasons)]
|
||||
#![feature(unwrap_infallible)]
|
||||
|
|
@ -77,6 +78,7 @@ pub mod sorted_map;
|
|||
pub mod stable_hasher;
|
||||
mod atomic_ref;
|
||||
pub mod fingerprint;
|
||||
pub mod marker;
|
||||
pub mod profiling;
|
||||
pub mod sharded;
|
||||
pub mod stack;
|
||||
|
|
|
|||
257
compiler/rustc_data_structures/src/marker.rs
Normal file
257
compiler/rustc_data_structures/src/marker.rs
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
cfg_if!(
|
||||
if #[cfg(not(parallel_compiler))] {
|
||||
pub auto trait DynSend {}
|
||||
pub auto trait DynSync {}
|
||||
|
||||
impl<T> DynSend for T {}
|
||||
impl<T> DynSync for T {}
|
||||
} else {
|
||||
#[rustc_on_unimplemented(
|
||||
message = "`{Self}` doesn't implement `DynSend`. \
|
||||
Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Send`"
|
||||
)]
|
||||
// This is an auto trait for types which can be sent across threads if `sync::is_dyn_thread_safe()`
|
||||
// is true. These types can be wrapped in a `FromDyn` to get a `Send` type. Wrapping a
|
||||
// `Send` type in `IntoDynSyncSend` will create a `DynSend` type.
|
||||
pub unsafe auto trait DynSend {}
|
||||
|
||||
#[rustc_on_unimplemented(
|
||||
message = "`{Self}` doesn't implement `DynSync`. \
|
||||
Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Sync`"
|
||||
)]
|
||||
// This is an auto trait for types which can be shared across threads if `sync::is_dyn_thread_safe()`
|
||||
// is true. These types can be wrapped in a `FromDyn` to get a `Sync` type. Wrapping a
|
||||
// `Sync` type in `IntoDynSyncSend` will create a `DynSync` type.
|
||||
pub unsafe auto trait DynSync {}
|
||||
|
||||
// Same with `Sync` and `Send`.
|
||||
unsafe impl<T: DynSync + ?Sized> DynSend for &T {}
|
||||
|
||||
macro_rules! impls_dyn_send_neg {
|
||||
($([$t1: ty $(where $($generics1: tt)*)?])*) => {
|
||||
$(impl$(<$($generics1)*>)? !DynSend for $t1 {})*
|
||||
};
|
||||
}
|
||||
|
||||
// Consistent with `std`
|
||||
impls_dyn_send_neg!(
|
||||
[std::env::Args]
|
||||
[std::env::ArgsOs]
|
||||
[*const T where T: ?Sized]
|
||||
[*mut T where T: ?Sized]
|
||||
[std::ptr::NonNull<T> where T: ?Sized]
|
||||
[std::rc::Rc<T> where T: ?Sized]
|
||||
[std::rc::Weak<T> where T: ?Sized]
|
||||
[std::sync::MutexGuard<'_, T> where T: ?Sized]
|
||||
[std::sync::RwLockReadGuard<'_, T> where T: ?Sized]
|
||||
[std::sync::RwLockWriteGuard<'_, T> where T: ?Sized]
|
||||
[std::io::StdoutLock<'_>]
|
||||
[std::io::StderrLock<'_>]
|
||||
);
|
||||
cfg_if!(
|
||||
// Consistent with `std`
|
||||
// `os_imp::Env` is `!Send` in these platforms
|
||||
if #[cfg(any(unix, target_os = "hermit", target_os = "wasi", target_os = "solid_asp3"))] {
|
||||
impl !DynSend for std::env::VarsOs {}
|
||||
}
|
||||
);
|
||||
|
||||
macro_rules! already_send {
|
||||
($([$ty: ty])*) => {
|
||||
$(unsafe impl DynSend for $ty where $ty: Send {})*
|
||||
};
|
||||
}
|
||||
|
||||
// These structures are already `Send`.
|
||||
already_send!(
|
||||
[std::backtrace::Backtrace]
|
||||
[std::io::Stdout]
|
||||
[std::io::Stderr]
|
||||
[std::io::Error]
|
||||
[std::fs::File]
|
||||
[rustc_arena::DroplessArena]
|
||||
[crate::memmap::Mmap]
|
||||
[crate::profiling::SelfProfiler]
|
||||
[crate::owned_slice::OwnedSlice]
|
||||
);
|
||||
|
||||
macro_rules! impl_dyn_send {
|
||||
($($($attr: meta)* [$ty: ty where $($generics2: tt)*])*) => {
|
||||
$(unsafe impl<$($generics2)*> DynSend for $ty {})*
|
||||
};
|
||||
}
|
||||
|
||||
impl_dyn_send!(
|
||||
[std::sync::atomic::AtomicPtr<T> where T]
|
||||
[std::sync::Mutex<T> where T: ?Sized+ DynSend]
|
||||
[std::sync::mpsc::Sender<T> where T: DynSend]
|
||||
[std::sync::Arc<T> where T: ?Sized + DynSync + DynSend]
|
||||
[std::sync::LazyLock<T, F> where T: DynSend, F: DynSend]
|
||||
[std::collections::HashSet<K, S> where K: DynSend, S: DynSend]
|
||||
[std::collections::HashMap<K, V, S> where K: DynSend, V: DynSend, S: DynSend]
|
||||
[std::collections::BTreeMap<K, V, A> where K: DynSend, V: DynSend, A: std::alloc::Allocator + Clone + DynSend]
|
||||
[Vec<T, A> where T: DynSend, A: std::alloc::Allocator + DynSend]
|
||||
[Box<T, A> where T: ?Sized + DynSend, A: std::alloc::Allocator + DynSend]
|
||||
[crate::sync::Lock<T> where T: DynSend]
|
||||
[crate::sync::RwLock<T> where T: DynSend]
|
||||
[crate::tagged_ptr::CopyTaggedPtr<P, T, CP> where P: Send + crate::tagged_ptr::Pointer, T: Send + crate::tagged_ptr::Tag, const CP: bool]
|
||||
[rustc_arena::TypedArena<T> where T: DynSend]
|
||||
[indexmap::IndexSet<V, S> where V: DynSend, S: DynSend]
|
||||
[indexmap::IndexMap<K, V, S> where K: DynSend, V: DynSend, S: DynSend]
|
||||
[thin_vec::ThinVec<T> where T: DynSend]
|
||||
[smallvec::SmallVec<A> where A: smallvec::Array + DynSend]
|
||||
);
|
||||
|
||||
macro_rules! impls_dyn_sync_neg {
|
||||
($([$t1: ty $(where $($generics1: tt)*)?])*) => {
|
||||
$(impl$(<$($generics1)*>)? !DynSync for $t1 {})*
|
||||
};
|
||||
}
|
||||
|
||||
// Consistent with `std`
|
||||
impls_dyn_sync_neg!(
|
||||
[std::env::Args]
|
||||
[std::env::ArgsOs]
|
||||
[*const T where T: ?Sized]
|
||||
[*mut T where T: ?Sized]
|
||||
[std::cell::Cell<T> where T: ?Sized]
|
||||
[std::cell::RefCell<T> where T: ?Sized]
|
||||
[std::cell::UnsafeCell<T> where T: ?Sized]
|
||||
[std::ptr::NonNull<T> where T: ?Sized]
|
||||
[std::rc::Rc<T> where T: ?Sized]
|
||||
[std::rc::Weak<T> where T: ?Sized]
|
||||
[std::cell::OnceCell<T> where T]
|
||||
[std::sync::mpsc::Receiver<T> where T]
|
||||
[std::sync::mpsc::Sender<T> where T]
|
||||
);
|
||||
cfg_if!(
|
||||
// Consistent with `std`
|
||||
// `os_imp::Env` is `!Sync` in these platforms
|
||||
if #[cfg(any(unix, target_os = "hermit", target_os = "wasi", target_os = "solid_asp3"))] {
|
||||
impl !DynSync for std::env::VarsOs {}
|
||||
}
|
||||
);
|
||||
|
||||
macro_rules! already_sync {
|
||||
($([$ty: ty])*) => {
|
||||
$(unsafe impl DynSync for $ty where $ty: Sync {})*
|
||||
};
|
||||
}
|
||||
|
||||
// These structures are already `Sync`.
|
||||
already_sync!(
|
||||
[std::sync::atomic::AtomicBool]
|
||||
[std::sync::atomic::AtomicUsize]
|
||||
[std::sync::atomic::AtomicU8]
|
||||
[std::sync::atomic::AtomicU32]
|
||||
[std::sync::atomic::AtomicU64]
|
||||
[std::backtrace::Backtrace]
|
||||
[std::io::Error]
|
||||
[std::fs::File]
|
||||
[jobserver_crate::Client]
|
||||
[crate::memmap::Mmap]
|
||||
[crate::profiling::SelfProfiler]
|
||||
[crate::owned_slice::OwnedSlice]
|
||||
);
|
||||
|
||||
macro_rules! impl_dyn_sync {
|
||||
($($($attr: meta)* [$ty: ty where $($generics2: tt)*])*) => {
|
||||
$(unsafe impl<$($generics2)*> DynSync for $ty {})*
|
||||
};
|
||||
}
|
||||
|
||||
impl_dyn_sync!(
|
||||
[std::sync::atomic::AtomicPtr<T> where T]
|
||||
[std::sync::OnceLock<T> where T: DynSend + DynSync]
|
||||
[std::sync::Mutex<T> where T: ?Sized + DynSend]
|
||||
[std::sync::Arc<T> where T: ?Sized + DynSync + DynSend]
|
||||
[std::sync::LazyLock<T, F> where T: DynSend + DynSync, F: DynSend]
|
||||
[std::collections::HashSet<K, S> where K: DynSync, S: DynSync]
|
||||
[std::collections::HashMap<K, V, S> where K: DynSync, V: DynSync, S: DynSync]
|
||||
[std::collections::BTreeMap<K, V, A> where K: DynSync, V: DynSync, A: std::alloc::Allocator + Clone + DynSync]
|
||||
[Vec<T, A> where T: DynSync, A: std::alloc::Allocator + DynSync]
|
||||
[Box<T, A> where T: ?Sized + DynSync, A: std::alloc::Allocator + DynSync]
|
||||
[crate::sync::Lock<T> where T: DynSend]
|
||||
[crate::sync::RwLock<T> where T: DynSend + DynSync]
|
||||
[crate::sync::OneThread<T> where T]
|
||||
[crate::sync::WorkerLocal<T> where T: DynSend]
|
||||
[crate::intern::Interned<'a, T> where 'a, T: DynSync]
|
||||
[crate::tagged_ptr::CopyTaggedPtr<P, T, CP> where P: Sync + crate::tagged_ptr::Pointer, T: Sync + crate::tagged_ptr::Tag, const CP: bool]
|
||||
[parking_lot::lock_api::Mutex<R, T> where R: DynSync, T: ?Sized + DynSend]
|
||||
[parking_lot::lock_api::RwLock<R, T> where R: DynSync, T: ?Sized + DynSend + DynSync]
|
||||
[indexmap::IndexSet<V, S> where V: DynSync, S: DynSync]
|
||||
[indexmap::IndexMap<K, V, S> where K: DynSync, V: DynSync, S: DynSync]
|
||||
[smallvec::SmallVec<A> where A: smallvec::Array + DynSync]
|
||||
[thin_vec::ThinVec<T> where T: DynSync]
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
pub fn assert_dyn_sync<T: ?Sized + DynSync>() {}
|
||||
pub fn assert_dyn_send<T: ?Sized + DynSend>() {}
|
||||
pub fn assert_dyn_send_val<T: ?Sized + DynSend>(_t: &T) {}
|
||||
pub fn assert_dyn_send_sync_val<T: ?Sized + DynSync + DynSend>(_t: &T) {}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct FromDyn<T>(T);
|
||||
|
||||
impl<T> FromDyn<T> {
|
||||
#[inline(always)]
|
||||
pub fn from(val: T) -> Self {
|
||||
// Check that `sync::is_dyn_thread_safe()` is true on creation so we can
|
||||
// implement `Send` and `Sync` for this structure when `T`
|
||||
// implements `DynSend` and `DynSync` respectively.
|
||||
#[cfg(parallel_compiler)]
|
||||
assert!(crate::sync::is_dyn_thread_safe());
|
||||
FromDyn(val)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn into_inner(self) -> T {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
// `FromDyn` is `Send` if `T` is `DynSend`, since it ensures that sync::is_dyn_thread_safe() is true.
|
||||
#[cfg(parallel_compiler)]
|
||||
unsafe impl<T: DynSend> Send for FromDyn<T> {}
|
||||
|
||||
// `FromDyn` is `Sync` if `T` is `DynSync`, since it ensures that sync::is_dyn_thread_safe() is true.
|
||||
#[cfg(parallel_compiler)]
|
||||
unsafe impl<T: DynSync> Sync for FromDyn<T> {}
|
||||
|
||||
impl<T> std::ops::Deref for FromDyn<T> {
|
||||
type Target = T;
|
||||
|
||||
#[inline(always)]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
// A wrapper to convert a struct that is already a `Send` or `Sync` into
|
||||
// an instance of `DynSend` and `DynSync`, since the compiler cannot infer
|
||||
// it automatically in some cases. (e.g. Box<dyn Send / Sync>)
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct IntoDynSyncSend<T: ?Sized>(pub T);
|
||||
|
||||
#[cfg(parallel_compiler)]
|
||||
unsafe impl<T: ?Sized + Send> DynSend for IntoDynSyncSend<T> {}
|
||||
#[cfg(parallel_compiler)]
|
||||
unsafe impl<T: ?Sized + Sync> DynSync for IntoDynSyncSend<T> {}
|
||||
|
||||
impl<T> std::ops::Deref for IntoDynSyncSend<T> {
|
||||
type Target = T;
|
||||
|
||||
#[inline(always)]
|
||||
fn deref(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::ops::DerefMut for IntoDynSyncSend<T> {
|
||||
#[inline(always)]
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
|
@ -69,6 +69,6 @@ fn drop_drops() {
|
|||
|
||||
#[test]
|
||||
fn send_sync() {
|
||||
crate::sync::assert_send::<OwnedSlice>();
|
||||
crate::sync::assert_sync::<OwnedSlice>();
|
||||
crate::sync::assert_dyn_send::<OwnedSlice>();
|
||||
crate::sync::assert_dyn_sync::<OwnedSlice>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
//!
|
||||
//! [^2] `MTLockRef` is a typedef.
|
||||
|
||||
pub use crate::marker::*;
|
||||
use crate::owned_slice::OwnedSlice;
|
||||
use std::collections::HashMap;
|
||||
use std::hash::{BuildHasher, Hash};
|
||||
|
|
@ -55,6 +56,42 @@ pub use vec::{AppendOnlyIndexVec, AppendOnlyVec};
|
|||
|
||||
mod vec;
|
||||
|
||||
mod mode {
|
||||
use super::Ordering;
|
||||
use std::sync::atomic::AtomicU8;
|
||||
|
||||
const UNINITIALIZED: u8 = 0;
|
||||
const DYN_NOT_THREAD_SAFE: u8 = 1;
|
||||
const DYN_THREAD_SAFE: u8 = 2;
|
||||
|
||||
static DYN_THREAD_SAFE_MODE: AtomicU8 = AtomicU8::new(UNINITIALIZED);
|
||||
|
||||
// Whether thread safety is enabled (due to running under multiple threads).
|
||||
#[inline]
|
||||
pub fn is_dyn_thread_safe() -> bool {
|
||||
match DYN_THREAD_SAFE_MODE.load(Ordering::Relaxed) {
|
||||
DYN_NOT_THREAD_SAFE => false,
|
||||
DYN_THREAD_SAFE => true,
|
||||
_ => panic!("uninitialized dyn_thread_safe mode!"),
|
||||
}
|
||||
}
|
||||
|
||||
// Only set by the `-Z threads` compile option
|
||||
pub fn set_dyn_thread_safe_mode(mode: bool) {
|
||||
let set: u8 = if mode { DYN_THREAD_SAFE } else { DYN_NOT_THREAD_SAFE };
|
||||
let previous = DYN_THREAD_SAFE_MODE.compare_exchange(
|
||||
UNINITIALIZED,
|
||||
set,
|
||||
Ordering::Relaxed,
|
||||
Ordering::Relaxed,
|
||||
);
|
||||
|
||||
// Check that the mode was either uninitialized or was already set to the requested mode.
|
||||
assert!(previous.is_ok() || previous == Err(set));
|
||||
}
|
||||
}
|
||||
|
||||
pub use mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode};
|
||||
cfg_if! {
|
||||
if #[cfg(not(parallel_compiler))] {
|
||||
pub unsafe auto trait Send {}
|
||||
|
|
@ -149,7 +186,7 @@ cfg_if! {
|
|||
|
||||
#[macro_export]
|
||||
macro_rules! parallel {
|
||||
($($blocks:tt),*) => {
|
||||
($($blocks:block),*) => {
|
||||
// We catch panics here ensuring that all the blocks execute.
|
||||
// This makes behavior consistent with the parallel compiler.
|
||||
let mut panic = None;
|
||||
|
|
@ -168,12 +205,6 @@ cfg_if! {
|
|||
}
|
||||
}
|
||||
|
||||
pub use Iterator as ParallelIterator;
|
||||
|
||||
pub fn par_iter<T: IntoIterator>(t: T) -> T::IntoIter {
|
||||
t.into_iter()
|
||||
}
|
||||
|
||||
pub fn par_for_each_in<T: IntoIterator>(t: T, mut for_each: impl FnMut(T::Item) + Sync + Send) {
|
||||
// We catch panics here ensuring that all the loop iterations execute.
|
||||
// This makes behavior consistent with the parallel compiler.
|
||||
|
|
@ -190,6 +221,29 @@ cfg_if! {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn par_map<T: IntoIterator, R, C: FromIterator<R>>(
|
||||
t: T,
|
||||
mut map: impl FnMut(<<T as IntoIterator>::IntoIter as Iterator>::Item) -> R,
|
||||
) -> C {
|
||||
// We catch panics here ensuring that all the loop iterations execute.
|
||||
let mut panic = None;
|
||||
let r = t.into_iter().filter_map(|i| {
|
||||
match catch_unwind(AssertUnwindSafe(|| map(i))) {
|
||||
Ok(r) => Some(r),
|
||||
Err(p) => {
|
||||
if panic.is_none() {
|
||||
panic = Some(p);
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
}).collect();
|
||||
if let Some(panic) = panic {
|
||||
resume_unwind(panic);
|
||||
}
|
||||
r
|
||||
}
|
||||
|
||||
pub type MetadataRef = OwnedSlice;
|
||||
|
||||
pub use std::rc::Rc as Lrc;
|
||||
|
|
@ -302,46 +356,165 @@ cfg_if! {
|
|||
use parking_lot::RwLock as InnerRwLock;
|
||||
|
||||
use std::thread;
|
||||
pub use rayon::{join, scope};
|
||||
|
||||
#[inline]
|
||||
pub fn join<A, B, RA: DynSend, RB: DynSend>(oper_a: A, oper_b: B) -> (RA, RB)
|
||||
where
|
||||
A: FnOnce() -> RA + DynSend,
|
||||
B: FnOnce() -> RB + DynSend,
|
||||
{
|
||||
if mode::is_dyn_thread_safe() {
|
||||
let oper_a = FromDyn::from(oper_a);
|
||||
let oper_b = FromDyn::from(oper_b);
|
||||
let (a, b) = rayon::join(move || FromDyn::from(oper_a.into_inner()()), move || FromDyn::from(oper_b.into_inner()()));
|
||||
(a.into_inner(), b.into_inner())
|
||||
} else {
|
||||
(oper_a(), oper_b())
|
||||
}
|
||||
}
|
||||
|
||||
// This function only works when `mode::is_dyn_thread_safe()`.
|
||||
pub fn scope<'scope, OP, R>(op: OP) -> R
|
||||
where
|
||||
OP: FnOnce(&rayon::Scope<'scope>) -> R + DynSend,
|
||||
R: DynSend,
|
||||
{
|
||||
let op = FromDyn::from(op);
|
||||
rayon::scope(|s| FromDyn::from(op.into_inner()(s))).into_inner()
|
||||
}
|
||||
|
||||
/// Runs a list of blocks in parallel. The first block is executed immediately on
|
||||
/// the current thread. Use that for the longest running block.
|
||||
#[macro_export]
|
||||
macro_rules! parallel {
|
||||
(impl $fblock:tt [$($c:tt,)*] [$block:tt $(, $rest:tt)*]) => {
|
||||
(impl $fblock:block [$($c:expr,)*] [$block:expr $(, $rest:expr)*]) => {
|
||||
parallel!(impl $fblock [$block, $($c,)*] [$($rest),*])
|
||||
};
|
||||
(impl $fblock:tt [$($blocks:tt,)*] []) => {
|
||||
(impl $fblock:block [$($blocks:expr,)*] []) => {
|
||||
::rustc_data_structures::sync::scope(|s| {
|
||||
$(let block = rustc_data_structures::sync::FromDyn::from(|| $blocks);
|
||||
s.spawn(move |_| block.into_inner()());)*
|
||||
(|| $fblock)();
|
||||
});
|
||||
};
|
||||
($fblock:block, $($blocks:block),*) => {
|
||||
if rustc_data_structures::sync::is_dyn_thread_safe() {
|
||||
// Reverse the order of the later blocks since Rayon executes them in reverse order
|
||||
// when using a single thread. This ensures the execution order matches that
|
||||
// of a single threaded rustc.
|
||||
parallel!(impl $fblock [] [$($blocks),*]);
|
||||
} else {
|
||||
// We catch panics here ensuring that all the blocks execute.
|
||||
// This makes behavior consistent with the parallel compiler.
|
||||
let mut panic = None;
|
||||
if let Err(p) = ::std::panic::catch_unwind(
|
||||
::std::panic::AssertUnwindSafe(|| $fblock)
|
||||
) {
|
||||
if panic.is_none() {
|
||||
panic = Some(p);
|
||||
}
|
||||
}
|
||||
$(
|
||||
s.spawn(|_| $blocks);
|
||||
if let Err(p) = ::std::panic::catch_unwind(
|
||||
::std::panic::AssertUnwindSafe(|| $blocks)
|
||||
) {
|
||||
if panic.is_none() {
|
||||
panic = Some(p);
|
||||
}
|
||||
}
|
||||
)*
|
||||
$fblock;
|
||||
})
|
||||
};
|
||||
($fblock:tt, $($blocks:tt),*) => {
|
||||
// Reverse the order of the later blocks since Rayon executes them in reverse order
|
||||
// when using a single thread. This ensures the execution order matches that
|
||||
// of a single threaded rustc
|
||||
parallel!(impl $fblock [] [$($blocks),*]);
|
||||
if let Some(panic) = panic {
|
||||
::std::panic::resume_unwind(panic);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub use rayon::iter::ParallelIterator;
|
||||
use rayon::iter::IntoParallelIterator;
|
||||
use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelIterator};
|
||||
|
||||
pub fn par_iter<T: IntoParallelIterator>(t: T) -> T::Iter {
|
||||
t.into_par_iter()
|
||||
}
|
||||
|
||||
pub fn par_for_each_in<T: IntoParallelIterator>(
|
||||
pub fn par_for_each_in<I, T: IntoIterator<Item = I> + IntoParallelIterator<Item = I>>(
|
||||
t: T,
|
||||
for_each: impl Fn(T::Item) + Sync + Send,
|
||||
for_each: impl Fn(I) + DynSync + DynSend
|
||||
) {
|
||||
let ps: Vec<_> = t.into_par_iter().map(|i| catch_unwind(AssertUnwindSafe(|| for_each(i)))).collect();
|
||||
ps.into_iter().for_each(|p| if let Err(panic) = p {
|
||||
resume_unwind(panic)
|
||||
});
|
||||
if mode::is_dyn_thread_safe() {
|
||||
let for_each = FromDyn::from(for_each);
|
||||
let panic: Lock<Option<_>> = Lock::new(None);
|
||||
t.into_par_iter().for_each(|i| if let Err(p) = catch_unwind(AssertUnwindSafe(|| for_each(i))) {
|
||||
let mut l = panic.lock();
|
||||
if l.is_none() {
|
||||
*l = Some(p)
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(panic) = panic.into_inner() {
|
||||
resume_unwind(panic);
|
||||
}
|
||||
} else {
|
||||
// We catch panics here ensuring that all the loop iterations execute.
|
||||
// This makes behavior consistent with the parallel compiler.
|
||||
let mut panic = None;
|
||||
t.into_iter().for_each(|i| {
|
||||
if let Err(p) = catch_unwind(AssertUnwindSafe(|| for_each(i))) {
|
||||
if panic.is_none() {
|
||||
panic = Some(p);
|
||||
}
|
||||
}
|
||||
});
|
||||
if let Some(panic) = panic {
|
||||
resume_unwind(panic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn par_map<
|
||||
I,
|
||||
T: IntoIterator<Item = I> + IntoParallelIterator<Item = I>,
|
||||
R: std::marker::Send,
|
||||
C: FromIterator<R> + FromParallelIterator<R>
|
||||
>(
|
||||
t: T,
|
||||
map: impl Fn(I) -> R + DynSync + DynSend
|
||||
) -> C {
|
||||
if mode::is_dyn_thread_safe() {
|
||||
let panic: Lock<Option<_>> = Lock::new(None);
|
||||
let map = FromDyn::from(map);
|
||||
// We catch panics here ensuring that all the loop iterations execute.
|
||||
let r = t.into_par_iter().filter_map(|i| {
|
||||
match catch_unwind(AssertUnwindSafe(|| map(i))) {
|
||||
Ok(r) => Some(r),
|
||||
Err(p) => {
|
||||
let mut l = panic.lock();
|
||||
if l.is_none() {
|
||||
*l = Some(p);
|
||||
}
|
||||
None
|
||||
},
|
||||
}
|
||||
}).collect();
|
||||
|
||||
if let Some(panic) = panic.into_inner() {
|
||||
resume_unwind(panic);
|
||||
}
|
||||
r
|
||||
} else {
|
||||
// We catch panics here ensuring that all the loop iterations execute.
|
||||
let mut panic = None;
|
||||
let r = t.into_iter().filter_map(|i| {
|
||||
match catch_unwind(AssertUnwindSafe(|| map(i))) {
|
||||
Ok(r) => Some(r),
|
||||
Err(p) => {
|
||||
if panic.is_none() {
|
||||
panic = Some(p);
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
}).collect();
|
||||
if let Some(panic) = panic {
|
||||
resume_unwind(panic);
|
||||
}
|
||||
r
|
||||
}
|
||||
}
|
||||
|
||||
pub type MetadataRef = OwnedSlice;
|
||||
|
|
@ -352,11 +525,6 @@ cfg_if! {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn assert_sync<T: ?Sized + Sync>() {}
|
||||
pub fn assert_send<T: ?Sized + Send>() {}
|
||||
pub fn assert_send_val<T: ?Sized + Send>(_t: &T) {}
|
||||
pub fn assert_send_sync_val<T: ?Sized + Sync + Send>(_t: &T) {}
|
||||
|
||||
#[derive(Default)]
|
||||
#[cfg_attr(parallel_compiler, repr(align(64)))]
|
||||
pub struct CacheAligned<T>(pub T);
|
||||
|
|
|
|||
|
|
@ -256,6 +256,9 @@ fn run_compiler(
|
|||
|
||||
let sopts = config::build_session_options(&matches);
|
||||
|
||||
// Set parallel mode before thread pool creation, which will create `Lock`s.
|
||||
interface::set_thread_safe_mode(&sopts.unstable_opts);
|
||||
|
||||
if let Some(ref code) = matches.opt_str("explain") {
|
||||
handle_explain(diagnostics_registry(), code, sopts.error_format);
|
||||
return Ok(());
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ extern crate tracing;
|
|||
use fluent_bundle::FluentResource;
|
||||
use fluent_syntax::parser::ParserError;
|
||||
use icu_provider_adapters::fallback::{LocaleFallbackProvider, LocaleFallbacker};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
|
||||
use rustc_fluent_macro::fluent_messages;
|
||||
use rustc_macros::{Decodable, Encodable};
|
||||
use rustc_span::Span;
|
||||
|
|
@ -37,16 +37,17 @@ pub use unic_langid::{langid, LanguageIdentifier};
|
|||
|
||||
fluent_messages! { "../messages.ftl" }
|
||||
|
||||
pub type FluentBundle = fluent_bundle::bundle::FluentBundle<FluentResource, IntlLangMemoizer>;
|
||||
|
||||
#[cfg(parallel_compiler)]
|
||||
fn new_bundle(locales: Vec<LanguageIdentifier>) -> FluentBundle {
|
||||
FluentBundle::new_concurrent(locales)
|
||||
}
|
||||
pub type FluentBundle =
|
||||
IntoDynSyncSend<fluent_bundle::bundle::FluentBundle<FluentResource, IntlLangMemoizer>>;
|
||||
|
||||
#[cfg(not(parallel_compiler))]
|
||||
fn new_bundle(locales: Vec<LanguageIdentifier>) -> FluentBundle {
|
||||
FluentBundle::new(locales)
|
||||
IntoDynSyncSend(fluent_bundle::bundle::FluentBundle::new(locales))
|
||||
}
|
||||
|
||||
#[cfg(parallel_compiler)]
|
||||
fn new_bundle(locales: Vec<LanguageIdentifier>) -> FluentBundle {
|
||||
IntoDynSyncSend(fluent_bundle::bundle::FluentBundle::new_concurrent(locales))
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ use emitter::{is_case_difference, Emitter, EmitterWriter};
|
|||
use registry::Registry;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::stable_hasher::{Hash128, StableHasher};
|
||||
use rustc_data_structures::sync::{self, Lock, Lrc};
|
||||
use rustc_data_structures::sync::{self, IntoDynSyncSend, Lock, Lrc};
|
||||
use rustc_data_structures::AtomicRef;
|
||||
pub use rustc_error_messages::{
|
||||
fallback_fluent_bundle, fluent_bundle, DelayDm, DiagnosticMessage, FluentBundle,
|
||||
|
|
@ -409,7 +409,7 @@ struct HandlerInner {
|
|||
err_count: usize,
|
||||
warn_count: usize,
|
||||
deduplicated_err_count: usize,
|
||||
emitter: Box<dyn Emitter + sync::Send>,
|
||||
emitter: IntoDynSyncSend<Box<dyn Emitter + sync::Send>>,
|
||||
delayed_span_bugs: Vec<DelayedDiagnostic>,
|
||||
delayed_good_path_bugs: Vec<DelayedDiagnostic>,
|
||||
/// This flag indicates that an expected diagnostic was emitted and suppressed.
|
||||
|
|
@ -605,7 +605,7 @@ impl Handler {
|
|||
warn_count: 0,
|
||||
deduplicated_err_count: 0,
|
||||
deduplicated_warn_count: 0,
|
||||
emitter,
|
||||
emitter: IntoDynSyncSend(emitter),
|
||||
delayed_span_bugs: Vec::new(),
|
||||
delayed_good_path_bugs: Vec::new(),
|
||||
suppressed_expected_diag: false,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use crate::error::{TranslateError, TranslateErrorKind};
|
|||
use crate::fluent_bundle::*;
|
||||
use crate::translation::Translate;
|
||||
use crate::FluentBundle;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
|
||||
use rustc_error_messages::fluent_bundle::resolver::errors::{ReferenceKind, ResolverError};
|
||||
use rustc_error_messages::langid;
|
||||
use rustc_error_messages::DiagnosticMessage;
|
||||
|
|
@ -27,10 +27,14 @@ fn make_dummy(ftl: &'static str) -> Dummy {
|
|||
let langid_en = langid!("en-US");
|
||||
|
||||
#[cfg(parallel_compiler)]
|
||||
let mut bundle = FluentBundle::new_concurrent(vec![langid_en]);
|
||||
let mut bundle: FluentBundle =
|
||||
IntoDynSyncSend(crate::fluent_bundle::bundle::FluentBundle::new_concurrent(vec![
|
||||
langid_en,
|
||||
]));
|
||||
|
||||
#[cfg(not(parallel_compiler))]
|
||||
let mut bundle = FluentBundle::new(vec![langid_en]);
|
||||
let mut bundle: FluentBundle =
|
||||
IntoDynSyncSend(crate::fluent_bundle::bundle::FluentBundle::new(vec![langid_en]));
|
||||
|
||||
bundle.add_resource(resource).expect("Failed to add FTL resources to the bundle.");
|
||||
|
||||
|
|
|
|||
|
|
@ -653,13 +653,13 @@ pub enum SyntaxExtensionKind {
|
|||
/// A token-based function-like macro.
|
||||
Bang(
|
||||
/// An expander with signature TokenStream -> TokenStream.
|
||||
Box<dyn BangProcMacro + sync::Sync + sync::Send>,
|
||||
Box<dyn BangProcMacro + sync::DynSync + sync::DynSend>,
|
||||
),
|
||||
|
||||
/// An AST-based function-like macro.
|
||||
LegacyBang(
|
||||
/// An expander with signature TokenStream -> AST.
|
||||
Box<dyn TTMacroExpander + sync::Sync + sync::Send>,
|
||||
Box<dyn TTMacroExpander + sync::DynSync + sync::DynSend>,
|
||||
),
|
||||
|
||||
/// A token-based attribute macro.
|
||||
|
|
@ -667,7 +667,7 @@ pub enum SyntaxExtensionKind {
|
|||
/// An expander with signature (TokenStream, TokenStream) -> TokenStream.
|
||||
/// The first TokenSteam is the attribute itself, the second is the annotated item.
|
||||
/// The produced TokenSteam replaces the input TokenSteam.
|
||||
Box<dyn AttrProcMacro + sync::Sync + sync::Send>,
|
||||
Box<dyn AttrProcMacro + sync::DynSync + sync::DynSend>,
|
||||
),
|
||||
|
||||
/// An AST-based attribute macro.
|
||||
|
|
@ -675,7 +675,7 @@ pub enum SyntaxExtensionKind {
|
|||
/// An expander with signature (AST, AST) -> AST.
|
||||
/// The first AST fragment is the attribute itself, the second is the annotated item.
|
||||
/// The produced AST fragment replaces the input AST fragment.
|
||||
Box<dyn MultiItemModifier + sync::Sync + sync::Send>,
|
||||
Box<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
|
||||
),
|
||||
|
||||
/// A trivial attribute "macro" that does nothing,
|
||||
|
|
@ -692,14 +692,14 @@ pub enum SyntaxExtensionKind {
|
|||
/// is handled identically to `LegacyDerive`. It should be migrated to
|
||||
/// a token-based representation like `Bang` and `Attr`, instead of
|
||||
/// using `MultiItemModifier`.
|
||||
Box<dyn MultiItemModifier + sync::Sync + sync::Send>,
|
||||
Box<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
|
||||
),
|
||||
|
||||
/// An AST-based derive macro.
|
||||
LegacyDerive(
|
||||
/// An expander with signature AST -> AST.
|
||||
/// The produced AST fragment is appended to the input AST fragment.
|
||||
Box<dyn MultiItemModifier + sync::Sync + sync::Send>,
|
||||
Box<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
|
||||
),
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -464,7 +464,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
self.astconv.ct_infer(ty, Some(param), inf.span).into()
|
||||
} else {
|
||||
self.inferred_params.push(inf.span);
|
||||
tcx.const_error(ty).into()
|
||||
tcx.const_error_misc(ty).into()
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
|
|
@ -518,7 +518,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
.no_bound_vars()
|
||||
.expect("const parameter types cannot be generic");
|
||||
if let Err(guar) = ty.error_reported() {
|
||||
return tcx.const_error_with_guaranteed(ty, guar).into();
|
||||
return tcx.const_error(ty, guar).into();
|
||||
}
|
||||
if !infer_args && has_default {
|
||||
tcx.const_param_default(param.def_id).subst(tcx, substs.unwrap()).into()
|
||||
|
|
@ -527,7 +527,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
self.astconv.ct_infer(ty, Some(param), self.span).into()
|
||||
} else {
|
||||
// We've already errored above about the mismatch.
|
||||
tcx.const_error(ty).into()
|
||||
tcx.const_error_misc(ty).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1387,7 +1387,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
term = match def_kind {
|
||||
hir::def::DefKind::AssocTy => tcx.ty_error(reported).into(),
|
||||
hir::def::DefKind::AssocConst => tcx
|
||||
.const_error_with_guaranteed(
|
||||
.const_error(
|
||||
tcx.type_of(assoc_item_def_id)
|
||||
.subst(tcx, projection_ty.skip_binder().substs),
|
||||
reported,
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ use rustc_errors::{pluralize, struct_span_err, Diagnostic, DiagnosticBuilder};
|
|||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{InternalSubsts, SubstsRef};
|
||||
use rustc_session::parse::feature_err;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs};
|
|||
use rustc_infer::infer::outlives::obligations::TypeOutlives;
|
||||
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::trait_def::TraitSpecializationKind;
|
||||
use rustc_middle::ty::{
|
||||
self, AdtKind, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
use crate::errors;
|
||||
use rustc_errors::{error_code, struct_span_err};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::sym;
|
||||
use rustc_trait_selection::traits;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ use rustc_hir::{GenericParamKind, Node};
|
|||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::util::{Discr, IntTypeExt};
|
||||
use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyCtxt};
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeNa
|
|||
use rustc_middle::bug;
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::middle::resolve_bound_vars::*;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::def_id::DefId;
|
||||
|
|
@ -232,8 +233,8 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
|
|||
|
||||
type ScopeRef<'a> = &'a Scope<'a>;
|
||||
|
||||
pub(crate) fn provide(providers: &mut ty::query::Providers) {
|
||||
*providers = ty::query::Providers {
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
*providers = Providers {
|
||||
resolve_bound_vars,
|
||||
|
||||
named_variable_map: |tcx, id| tcx.resolve_bound_vars(id).defs.get(&id),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use rustc_hir::intravisit::{self, Visitor};
|
|||
use rustc_hir::{ForeignItem, ForeignItemKind};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_infer::traits::{ObligationCause, WellFormedLoc};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, Region, TyCtxt, TypeFoldable, TypeFolder};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_trait_selection::traits::{self, ObligationCtxt};
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ use rustc_data_structures::fx::FxHashSet;
|
|||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ use rustc_hir as hir;
|
|||
use rustc_hir::Node;
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::middle;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::util;
|
||||
use rustc_session::{config::EntryFnType, parse::feature_err};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use hir::Node;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::subst::GenericArgKind;
|
||||
use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt};
|
||||
use rustc_span::symbol::sym;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
use rustc_arena::DroplessArena;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
|
||||
use std::ops::ControlFlow;
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@ use rustc_hir::{HirIdMap, Node};
|
|||
use rustc_hir_analysis::astconv::AstConv;
|
||||
use rustc_hir_analysis::check::check_abi;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::traits;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_session::config;
|
||||
use rustc_session::Session;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ use rustc_hir as hir;
|
|||
use rustc_hir::def::{CtorOf, DefKind, Namespace};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_infer::infer::{self, InferOk};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
|
||||
use rustc_middle::ty::{self, GenericParamDefKind, Ty, TypeVisitableExt};
|
||||
|
|
@ -28,7 +29,7 @@ use rustc_trait_selection::traits::{self, NormalizeExt};
|
|||
|
||||
use self::probe::{IsSuggestion, ProbeScope};
|
||||
|
||||
pub fn provide(providers: &mut ty::query::Providers) {
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
probe::provide(providers);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse};
|
|||
use rustc_infer::infer::DefineOpaqueTypes;
|
||||
use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
|
||||
use rustc_middle::middle::stability;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
|
||||
use rustc_middle::ty::AssocItem;
|
||||
use rustc_middle::ty::GenericParamDefKind;
|
||||
|
|
@ -495,7 +496,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut ty::query::Providers) {
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
providers.method_autoderef_steps = method_autoderef_steps;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -836,7 +836,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
|
|||
debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
|
||||
let e = self.report_error(ct);
|
||||
self.replaced_with_error = Some(e);
|
||||
self.interner().const_error_with_guaranteed(ct.ty(), e)
|
||||
self.interner().const_error(ct.ty(), e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,24 +26,17 @@ use super::equate::Equate;
|
|||
use super::glb::Glb;
|
||||
use super::lub::Lub;
|
||||
use super::sub::Sub;
|
||||
use super::type_variable::TypeVariableValue;
|
||||
use super::{DefineOpaqueTypes, InferCtxt, MiscVariable, TypeTrace};
|
||||
use super::{DefineOpaqueTypes, InferCtxt, TypeTrace};
|
||||
use crate::infer::generalize::{self, CombineDelegate, Generalization};
|
||||
use crate::traits::{Obligation, PredicateObligations};
|
||||
use rustc_data_structures::sso::SsoHashMap;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::infer::canonical::OriginalQueryValues;
|
||||
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
|
||||
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::subst::SubstsRef;
|
||||
use rustc_middle::ty::{
|
||||
self, AliasKind, FallibleTypeFolder, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable,
|
||||
TypeSuperFoldable, TypeVisitableExt,
|
||||
};
|
||||
use rustc_middle::ty::relate::{RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::{self, AliasKind, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_middle::ty::{IntType, UintType};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_span::DUMMY_SP;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CombineFields<'infcx, 'tcx> {
|
||||
|
|
@ -55,13 +48,6 @@ pub struct CombineFields<'infcx, 'tcx> {
|
|||
pub define_opaque_types: DefineOpaqueTypes,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum RelationDir {
|
||||
SubtypeOf,
|
||||
SupertypeOf,
|
||||
EqTo,
|
||||
}
|
||||
|
||||
impl<'tcx> InferCtxt<'tcx> {
|
||||
pub fn super_combine_tys<R>(
|
||||
&self,
|
||||
|
|
@ -152,7 +138,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
Ok(a)
|
||||
}
|
||||
|
||||
_ => ty::relate::super_relate_tys(relation, a, b),
|
||||
_ => ty::relate::structurally_relate_tys(relation, a, b),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -209,13 +195,13 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
// HACK: equating both sides with `[const error]` eagerly prevents us
|
||||
// from leaving unconstrained inference vars during things like impl
|
||||
// matching in the solver.
|
||||
let a_error = self.tcx.const_error_with_guaranteed(a.ty(), guar);
|
||||
let a_error = self.tcx.const_error(a.ty(), guar);
|
||||
if let ty::ConstKind::Infer(InferConst::Var(vid)) = a.kind() {
|
||||
return self.unify_const_variable(vid, a_error);
|
||||
return self.unify_const_variable(vid, a_error, relation.param_env());
|
||||
}
|
||||
let b_error = self.tcx.const_error_with_guaranteed(b.ty(), guar);
|
||||
let b_error = self.tcx.const_error(b.ty(), guar);
|
||||
if let ty::ConstKind::Infer(InferConst::Var(vid)) = b.kind() {
|
||||
return self.unify_const_variable(vid, b_error);
|
||||
return self.unify_const_variable(vid, b_error, relation.param_env());
|
||||
}
|
||||
|
||||
return Ok(if relation.a_is_expected() { a_error } else { b_error });
|
||||
|
|
@ -237,11 +223,11 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
}
|
||||
|
||||
(ty::ConstKind::Infer(InferConst::Var(vid)), _) => {
|
||||
return self.unify_const_variable(vid, b);
|
||||
return self.unify_const_variable(vid, b, relation.param_env());
|
||||
}
|
||||
|
||||
(_, ty::ConstKind::Infer(InferConst::Var(vid))) => {
|
||||
return self.unify_const_variable(vid, a);
|
||||
return self.unify_const_variable(vid, a, relation.param_env());
|
||||
}
|
||||
(ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..))
|
||||
if self.tcx.lazy_normalization() =>
|
||||
|
|
@ -252,7 +238,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
_ => {}
|
||||
}
|
||||
|
||||
ty::relate::super_relate_consts(relation, a, b)
|
||||
ty::relate::structurally_relate_consts(relation, a, b)
|
||||
}
|
||||
|
||||
/// Unifies the const variable `target_vid` with the given constant.
|
||||
|
|
@ -294,24 +280,17 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
&self,
|
||||
target_vid: ty::ConstVid<'tcx>,
|
||||
ct: ty::Const<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::Const<'tcx>> {
|
||||
let (for_universe, span) = {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
let variable_table = &mut inner.const_unification_table();
|
||||
let var_value = variable_table.probe_value(target_vid);
|
||||
match var_value.val {
|
||||
ConstVariableValue::Known { value } => {
|
||||
bug!("instantiating {:?} which has a known value {:?}", target_vid, value)
|
||||
}
|
||||
ConstVariableValue::Unknown { universe } => (universe, var_value.origin.span),
|
||||
}
|
||||
};
|
||||
let value = ct.try_fold_with(&mut ConstInferUnifier {
|
||||
infcx: self,
|
||||
span,
|
||||
for_universe,
|
||||
let span =
|
||||
self.inner.borrow_mut().const_unification_table().probe_value(target_vid).origin.span;
|
||||
let Generalization { value, needs_wf: _ } = generalize::generalize(
|
||||
self,
|
||||
&mut CombineDelegate { infcx: self, span, param_env },
|
||||
ct,
|
||||
target_vid,
|
||||
})?;
|
||||
ty::Variance::Invariant,
|
||||
)?;
|
||||
|
||||
self.inner.borrow_mut().const_unification_table().union_value(
|
||||
target_vid,
|
||||
|
|
@ -392,12 +371,10 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||
pub fn instantiate(
|
||||
&mut self,
|
||||
a_ty: Ty<'tcx>,
|
||||
dir: RelationDir,
|
||||
ambient_variance: ty::Variance,
|
||||
b_vid: ty::TyVid,
|
||||
a_is_expected: bool,
|
||||
) -> RelateResult<'tcx, ()> {
|
||||
use self::RelationDir::*;
|
||||
|
||||
// Get the actual variable that b_vid has been inferred to
|
||||
debug_assert!(self.infcx.inner.borrow_mut().type_variables().probe(b_vid).is_unknown());
|
||||
|
||||
|
|
@ -412,7 +389,18 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||
// `'?2` and `?3` are fresh region/type inference
|
||||
// variables. (Down below, we will relate `a_ty <: b_ty`,
|
||||
// adding constraints like `'x: '?2` and `?1 <: ?3`.)
|
||||
let Generalization { ty: b_ty, needs_wf } = self.generalize(a_ty, b_vid, dir)?;
|
||||
let Generalization { value: b_ty, needs_wf } = generalize::generalize(
|
||||
self.infcx,
|
||||
&mut CombineDelegate {
|
||||
infcx: self.infcx,
|
||||
param_env: self.param_env,
|
||||
span: self.trace.span(),
|
||||
},
|
||||
a_ty,
|
||||
b_vid,
|
||||
ambient_variance,
|
||||
)?;
|
||||
|
||||
debug!(?b_ty);
|
||||
self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty);
|
||||
|
||||
|
|
@ -431,78 +419,23 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||
// relations wind up attributed to the same spans. We need
|
||||
// to associate causes/spans with each of the relations in
|
||||
// the stack to get this right.
|
||||
match dir {
|
||||
EqTo => self.equate(a_is_expected).relate(a_ty, b_ty),
|
||||
SubtypeOf => self.sub(a_is_expected).relate(a_ty, b_ty),
|
||||
SupertypeOf => self.sub(a_is_expected).relate_with_variance(
|
||||
match ambient_variance {
|
||||
ty::Variance::Invariant => self.equate(a_is_expected).relate(a_ty, b_ty),
|
||||
ty::Variance::Covariant => self.sub(a_is_expected).relate(a_ty, b_ty),
|
||||
ty::Variance::Contravariant => self.sub(a_is_expected).relate_with_variance(
|
||||
ty::Contravariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
a_ty,
|
||||
b_ty,
|
||||
),
|
||||
ty::Variance::Bivariant => {
|
||||
unreachable!("no code should be generalizing bivariantly (currently)")
|
||||
}
|
||||
}?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Attempts to generalize `ty` for the type variable `for_vid`.
|
||||
/// This checks for cycle -- that is, whether the type `ty`
|
||||
/// references `for_vid`. The `dir` is the "direction" for which we
|
||||
/// a performing the generalization (i.e., are we producing a type
|
||||
/// that can be used as a supertype etc).
|
||||
///
|
||||
/// Preconditions:
|
||||
///
|
||||
/// - `for_vid` is a "root vid"
|
||||
#[instrument(skip(self), level = "trace", ret)]
|
||||
fn generalize(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
for_vid: ty::TyVid,
|
||||
dir: RelationDir,
|
||||
) -> RelateResult<'tcx, Generalization<'tcx>> {
|
||||
// Determine the ambient variance within which `ty` appears.
|
||||
// The surrounding equation is:
|
||||
//
|
||||
// ty [op] ty2
|
||||
//
|
||||
// where `op` is either `==`, `<:`, or `:>`. This maps quite
|
||||
// naturally.
|
||||
let ambient_variance = match dir {
|
||||
RelationDir::EqTo => ty::Invariant,
|
||||
RelationDir::SubtypeOf => ty::Covariant,
|
||||
RelationDir::SupertypeOf => ty::Contravariant,
|
||||
};
|
||||
|
||||
trace!(?ambient_variance);
|
||||
|
||||
let for_universe = match self.infcx.inner.borrow_mut().type_variables().probe(for_vid) {
|
||||
v @ TypeVariableValue::Known { .. } => {
|
||||
bug!("instantiating {:?} which has a known value {:?}", for_vid, v,)
|
||||
}
|
||||
TypeVariableValue::Unknown { universe } => universe,
|
||||
};
|
||||
|
||||
trace!(?for_universe);
|
||||
trace!(?self.trace);
|
||||
|
||||
let mut generalize = Generalizer {
|
||||
infcx: self.infcx,
|
||||
cause: &self.trace.cause,
|
||||
for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid),
|
||||
for_universe,
|
||||
ambient_variance,
|
||||
needs_wf: false,
|
||||
root_ty: ty,
|
||||
param_env: self.param_env,
|
||||
cache: SsoHashMap::new(),
|
||||
};
|
||||
|
||||
let ty = generalize.relate(ty, ty)?;
|
||||
let needs_wf = generalize.needs_wf;
|
||||
Ok(Generalization { ty, needs_wf })
|
||||
}
|
||||
|
||||
pub fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
|
||||
self.obligations.extend(obligations.into_iter());
|
||||
}
|
||||
|
|
@ -514,313 +447,6 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
struct Generalizer<'cx, 'tcx> {
|
||||
infcx: &'cx InferCtxt<'tcx>,
|
||||
|
||||
/// The span, used when creating new type variables and things.
|
||||
cause: &'cx ObligationCause<'tcx>,
|
||||
|
||||
/// The vid of the type variable that is in the process of being
|
||||
/// instantiated; if we find this within the type we are folding,
|
||||
/// that means we would have created a cyclic type.
|
||||
for_vid_sub_root: ty::TyVid,
|
||||
|
||||
/// The universe of the type variable that is in the process of
|
||||
/// being instantiated. Any fresh variables that we create in this
|
||||
/// process should be in that same universe.
|
||||
for_universe: ty::UniverseIndex,
|
||||
|
||||
/// Track the variance as we descend into the type.
|
||||
ambient_variance: ty::Variance,
|
||||
|
||||
/// See the field `needs_wf` in `Generalization`.
|
||||
needs_wf: bool,
|
||||
|
||||
/// The root type that we are generalizing. Used when reporting cycles.
|
||||
root_ty: Ty<'tcx>,
|
||||
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
||||
cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
|
||||
}
|
||||
|
||||
/// Result from a generalization operation. This includes
|
||||
/// not only the generalized type, but also a bool flag
|
||||
/// indicating whether further WF checks are needed.
|
||||
#[derive(Debug)]
|
||||
struct Generalization<'tcx> {
|
||||
ty: Ty<'tcx>,
|
||||
|
||||
/// If true, then the generalized type may not be well-formed,
|
||||
/// even if the source type is well-formed, so we should add an
|
||||
/// additional check to enforce that it is. This arises in
|
||||
/// particular around 'bivariant' type parameters that are only
|
||||
/// constrained by a where-clause. As an example, imagine a type:
|
||||
///
|
||||
/// struct Foo<A, B> where A: Iterator<Item = B> {
|
||||
/// data: A
|
||||
/// }
|
||||
///
|
||||
/// here, `A` will be covariant, but `B` is
|
||||
/// unconstrained. However, whatever it is, for `Foo` to be WF, it
|
||||
/// must be equal to `A::Item`. If we have an input `Foo<?A, ?B>`,
|
||||
/// then after generalization we will wind up with a type like
|
||||
/// `Foo<?C, ?D>`. When we enforce that `Foo<?A, ?B> <: Foo<?C,
|
||||
/// ?D>` (or `>:`), we will wind up with the requirement that `?A
|
||||
/// <: ?C`, but no particular relationship between `?B` and `?D`
|
||||
/// (after all, we do not know the variance of the normalized form
|
||||
/// of `A::Item` with respect to `A`). If we do nothing else, this
|
||||
/// may mean that `?D` goes unconstrained (as in #41677). So, in
|
||||
/// this scenario where we create a new type variable in a
|
||||
/// bivariant context, we set the `needs_wf` flag to true. This
|
||||
/// will force the calling code to check that `WF(Foo<?C, ?D>)`
|
||||
/// holds, which in turn implies that `?C::Item == ?D`. So once
|
||||
/// `?C` is constrained, that should suffice to restrict `?D`.
|
||||
needs_wf: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.infcx.tcx
|
||||
}
|
||||
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
self.param_env
|
||||
}
|
||||
|
||||
fn tag(&self) -> &'static str {
|
||||
"Generalizer"
|
||||
}
|
||||
|
||||
fn a_is_expected(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn binders<T>(
|
||||
&mut self,
|
||||
a: ty::Binder<'tcx, T>,
|
||||
b: ty::Binder<'tcx, T>,
|
||||
) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
|
||||
where
|
||||
T: Relate<'tcx>,
|
||||
{
|
||||
Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
|
||||
}
|
||||
|
||||
fn relate_item_substs(
|
||||
&mut self,
|
||||
item_def_id: DefId,
|
||||
a_subst: SubstsRef<'tcx>,
|
||||
b_subst: SubstsRef<'tcx>,
|
||||
) -> RelateResult<'tcx, SubstsRef<'tcx>> {
|
||||
if self.ambient_variance == ty::Variance::Invariant {
|
||||
// Avoid fetching the variance if we are in an invariant
|
||||
// context; no need, and it can induce dependency cycles
|
||||
// (e.g., #41849).
|
||||
relate::relate_substs(self, a_subst, b_subst)
|
||||
} else {
|
||||
let tcx = self.tcx();
|
||||
let opt_variances = tcx.variances_of(item_def_id);
|
||||
relate::relate_substs_with_variances(
|
||||
self,
|
||||
item_def_id,
|
||||
&opt_variances,
|
||||
a_subst,
|
||||
b_subst,
|
||||
true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
&mut self,
|
||||
variance: ty::Variance,
|
||||
_info: ty::VarianceDiagInfo<'tcx>,
|
||||
a: T,
|
||||
b: T,
|
||||
) -> RelateResult<'tcx, T> {
|
||||
let old_ambient_variance = self.ambient_variance;
|
||||
self.ambient_variance = self.ambient_variance.xform(variance);
|
||||
|
||||
let result = self.relate(a, b);
|
||||
self.ambient_variance = old_ambient_variance;
|
||||
result
|
||||
}
|
||||
|
||||
fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
assert_eq!(t, t2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
|
||||
|
||||
if let Some(&result) = self.cache.get(&t) {
|
||||
return Ok(result);
|
||||
}
|
||||
debug!("generalize: t={:?}", t);
|
||||
|
||||
// Check to see whether the type we are generalizing references
|
||||
// any other type variable related to `vid` via
|
||||
// subtyping. This is basically our "occurs check", preventing
|
||||
// us from creating infinitely sized types.
|
||||
let result = match *t.kind() {
|
||||
ty::Infer(ty::TyVar(vid)) => {
|
||||
let vid = self.infcx.inner.borrow_mut().type_variables().root_var(vid);
|
||||
let sub_vid = self.infcx.inner.borrow_mut().type_variables().sub_root_var(vid);
|
||||
if sub_vid == self.for_vid_sub_root {
|
||||
// If sub-roots are equal, then `for_vid` and
|
||||
// `vid` are related via subtyping.
|
||||
Err(TypeError::CyclicTy(self.root_ty))
|
||||
} else {
|
||||
let probe = self.infcx.inner.borrow_mut().type_variables().probe(vid);
|
||||
match probe {
|
||||
TypeVariableValue::Known { value: u } => {
|
||||
debug!("generalize: known value {:?}", u);
|
||||
self.relate(u, u)
|
||||
}
|
||||
TypeVariableValue::Unknown { universe } => {
|
||||
match self.ambient_variance {
|
||||
// Invariant: no need to make a fresh type variable.
|
||||
ty::Invariant => {
|
||||
if self.for_universe.can_name(universe) {
|
||||
return Ok(t);
|
||||
}
|
||||
}
|
||||
|
||||
// Bivariant: make a fresh var, but we
|
||||
// may need a WF predicate. See
|
||||
// comment on `needs_wf` field for
|
||||
// more info.
|
||||
ty::Bivariant => self.needs_wf = true,
|
||||
|
||||
// Co/contravariant: this will be
|
||||
// sufficiently constrained later on.
|
||||
ty::Covariant | ty::Contravariant => (),
|
||||
}
|
||||
|
||||
let origin =
|
||||
*self.infcx.inner.borrow_mut().type_variables().var_origin(vid);
|
||||
let new_var_id = self
|
||||
.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.type_variables()
|
||||
.new_var(self.for_universe, origin);
|
||||
let u = self.tcx().mk_ty_var(new_var_id);
|
||||
|
||||
// Record that we replaced `vid` with `new_var_id` as part of a generalization
|
||||
// operation. This is needed to detect cyclic types. To see why, see the
|
||||
// docs in the `type_variables` module.
|
||||
self.infcx.inner.borrow_mut().type_variables().sub(vid, new_var_id);
|
||||
debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
|
||||
Ok(u)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
|
||||
// No matter what mode we are in,
|
||||
// integer/floating-point types must be equal to be
|
||||
// relatable.
|
||||
Ok(t)
|
||||
}
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
|
||||
let s = self.relate(substs, substs)?;
|
||||
Ok(if s == substs { t } else { self.infcx.tcx.mk_opaque(def_id, s) })
|
||||
}
|
||||
_ => relate::super_relate_tys(self, t, t),
|
||||
}?;
|
||||
|
||||
self.cache.insert(t, result);
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn regions(
|
||||
&mut self,
|
||||
r: ty::Region<'tcx>,
|
||||
r2: ty::Region<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::Region<'tcx>> {
|
||||
assert_eq!(r, r2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
|
||||
|
||||
debug!("generalize: regions r={:?}", r);
|
||||
|
||||
match *r {
|
||||
// Never make variables for regions bound within the type itself,
|
||||
// nor for erased regions.
|
||||
ty::ReLateBound(..) | ty::ReErased => {
|
||||
return Ok(r);
|
||||
}
|
||||
|
||||
ty::ReError(_) => {
|
||||
return Ok(r);
|
||||
}
|
||||
|
||||
ty::RePlaceholder(..)
|
||||
| ty::ReVar(..)
|
||||
| ty::ReStatic
|
||||
| ty::ReEarlyBound(..)
|
||||
| ty::ReFree(..) => {
|
||||
// see common code below
|
||||
}
|
||||
}
|
||||
|
||||
// If we are in an invariant context, we can re-use the region
|
||||
// as is, unless it happens to be in some universe that we
|
||||
// can't name. (In the case of a region *variable*, we could
|
||||
// use it if we promoted it into our universe, but we don't
|
||||
// bother.)
|
||||
if let ty::Invariant = self.ambient_variance {
|
||||
let r_universe = self.infcx.universe_of_region(r);
|
||||
if self.for_universe.can_name(r_universe) {
|
||||
return Ok(r);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: This is non-ideal because we don't give a
|
||||
// very descriptive origin for this region variable.
|
||||
Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.cause.span), self.for_universe))
|
||||
}
|
||||
|
||||
fn consts(
|
||||
&mut self,
|
||||
c: ty::Const<'tcx>,
|
||||
c2: ty::Const<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::Const<'tcx>> {
|
||||
assert_eq!(c, c2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
|
||||
|
||||
match c.kind() {
|
||||
ty::ConstKind::Infer(InferConst::Var(vid)) => {
|
||||
let mut inner = self.infcx.inner.borrow_mut();
|
||||
let variable_table = &mut inner.const_unification_table();
|
||||
let var_value = variable_table.probe_value(vid);
|
||||
match var_value.val {
|
||||
ConstVariableValue::Known { value: u } => {
|
||||
drop(inner);
|
||||
self.relate(u, u)
|
||||
}
|
||||
ConstVariableValue::Unknown { universe } => {
|
||||
if self.for_universe.can_name(universe) {
|
||||
Ok(c)
|
||||
} else {
|
||||
let new_var_id = variable_table.new_key(ConstVarValue {
|
||||
origin: var_value.origin,
|
||||
val: ConstVariableValue::Unknown { universe: self.for_universe },
|
||||
});
|
||||
Ok(self.tcx().mk_const(new_var_id, c.ty()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
|
||||
let substs = self.relate_with_variance(
|
||||
ty::Variance::Invariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
substs,
|
||||
substs,
|
||||
)?;
|
||||
Ok(self.tcx().mk_const(ty::UnevaluatedConst { def, substs }, c.ty()))
|
||||
}
|
||||
_ => relate::super_relate_consts(self, c, c),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
|
||||
/// Register obligations that must hold in order for this relation to hold
|
||||
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>);
|
||||
|
|
@ -873,135 +499,3 @@ fn float_unification_error<'tcx>(
|
|||
let (ty::FloatVarValue(a), ty::FloatVarValue(b)) = v;
|
||||
TypeError::FloatMismatch(ExpectedFound::new(a_is_expected, a, b))
|
||||
}
|
||||
|
||||
struct ConstInferUnifier<'cx, 'tcx> {
|
||||
infcx: &'cx InferCtxt<'tcx>,
|
||||
|
||||
span: Span,
|
||||
|
||||
for_universe: ty::UniverseIndex,
|
||||
|
||||
/// The vid of the const variable that is in the process of being
|
||||
/// instantiated; if we find this within the const we are folding,
|
||||
/// that means we would have created a cyclic const.
|
||||
target_vid: ty::ConstVid<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for ConstInferUnifier<'_, 'tcx> {
|
||||
type Error = TypeError<'tcx>;
|
||||
|
||||
fn interner(&self) -> TyCtxt<'tcx> {
|
||||
self.infcx.tcx
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, TypeError<'tcx>> {
|
||||
match t.kind() {
|
||||
&ty::Infer(ty::TyVar(vid)) => {
|
||||
let vid = self.infcx.inner.borrow_mut().type_variables().root_var(vid);
|
||||
let probe = self.infcx.inner.borrow_mut().type_variables().probe(vid);
|
||||
match probe {
|
||||
TypeVariableValue::Known { value: u } => {
|
||||
debug!("ConstOccursChecker: known value {:?}", u);
|
||||
u.try_fold_with(self)
|
||||
}
|
||||
TypeVariableValue::Unknown { universe } => {
|
||||
if self.for_universe.can_name(universe) {
|
||||
return Ok(t);
|
||||
}
|
||||
|
||||
let origin =
|
||||
*self.infcx.inner.borrow_mut().type_variables().var_origin(vid);
|
||||
let new_var_id = self
|
||||
.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.type_variables()
|
||||
.new_var(self.for_universe, origin);
|
||||
Ok(self.interner().mk_ty_var(new_var_id))
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => Ok(t),
|
||||
_ => t.try_super_fold_with(self),
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
fn try_fold_region(
|
||||
&mut self,
|
||||
r: ty::Region<'tcx>,
|
||||
) -> Result<ty::Region<'tcx>, TypeError<'tcx>> {
|
||||
debug!("ConstInferUnifier: r={:?}", r);
|
||||
|
||||
match *r {
|
||||
// Never make variables for regions bound within the type itself,
|
||||
// nor for erased regions.
|
||||
ty::ReLateBound(..) | ty::ReErased | ty::ReError(_) => {
|
||||
return Ok(r);
|
||||
}
|
||||
|
||||
ty::RePlaceholder(..)
|
||||
| ty::ReVar(..)
|
||||
| ty::ReStatic
|
||||
| ty::ReEarlyBound(..)
|
||||
| ty::ReFree(..) => {
|
||||
// see common code below
|
||||
}
|
||||
}
|
||||
|
||||
let r_universe = self.infcx.universe_of_region(r);
|
||||
if self.for_universe.can_name(r_universe) {
|
||||
return Ok(r);
|
||||
} else {
|
||||
// FIXME: This is non-ideal because we don't give a
|
||||
// very descriptive origin for this region variable.
|
||||
Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.span), self.for_universe))
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, TypeError<'tcx>> {
|
||||
match c.kind() {
|
||||
ty::ConstKind::Infer(InferConst::Var(vid)) => {
|
||||
// Check if the current unification would end up
|
||||
// unifying `target_vid` with a const which contains
|
||||
// an inference variable which is unioned with `target_vid`.
|
||||
//
|
||||
// Not doing so can easily result in stack overflows.
|
||||
if self
|
||||
.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.const_unification_table()
|
||||
.unioned(self.target_vid, vid)
|
||||
{
|
||||
return Err(TypeError::CyclicConst(c));
|
||||
}
|
||||
|
||||
let var_value =
|
||||
self.infcx.inner.borrow_mut().const_unification_table().probe_value(vid);
|
||||
match var_value.val {
|
||||
ConstVariableValue::Known { value: u } => u.try_fold_with(self),
|
||||
ConstVariableValue::Unknown { universe } => {
|
||||
if self.for_universe.can_name(universe) {
|
||||
Ok(c)
|
||||
} else {
|
||||
let new_var_id =
|
||||
self.infcx.inner.borrow_mut().const_unification_table().new_key(
|
||||
ConstVarValue {
|
||||
origin: var_value.origin,
|
||||
val: ConstVariableValue::Unknown {
|
||||
universe: self.for_universe,
|
||||
},
|
||||
},
|
||||
);
|
||||
Ok(self.interner().mk_const(new_var_id, c.ty()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => c.try_super_fold_with(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::infer::DefineOpaqueTypes;
|
||||
use crate::traits::PredicateObligations;
|
||||
|
||||
use super::combine::{CombineFields, ObligationEmittingRelation, RelationDir};
|
||||
use super::combine::{CombineFields, ObligationEmittingRelation};
|
||||
use super::Subtype;
|
||||
|
||||
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
|
||||
|
|
@ -88,11 +88,11 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
|
|||
}
|
||||
|
||||
(&ty::Infer(TyVar(a_id)), _) => {
|
||||
self.fields.instantiate(b, RelationDir::EqTo, a_id, self.a_is_expected)?;
|
||||
self.fields.instantiate(b, ty::Invariant, a_id, self.a_is_expected)?;
|
||||
}
|
||||
|
||||
(_, &ty::Infer(TyVar(b_id))) => {
|
||||
self.fields.instantiate(a, RelationDir::EqTo, b_id, self.a_is_expected)?;
|
||||
self.fields.instantiate(a, ty::Invariant, b_id, self.a_is_expected)?;
|
||||
}
|
||||
|
||||
(
|
||||
|
|
|
|||
|
|
@ -2723,7 +2723,7 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
|
|||
| (ty::Infer(ty::InferTy::TyVar(_)), _)
|
||||
| (_, ty::Infer(ty::InferTy::TyVar(_))) => Ok(a),
|
||||
(ty::Infer(_), _) | (_, ty::Infer(_)) => Err(TypeError::Mismatch),
|
||||
_ => relate::super_relate_tys(self, a, b),
|
||||
_ => relate::structurally_relate_tys(self, a, b),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
479
compiler/rustc_infer/src/infer/generalize.rs
Normal file
479
compiler/rustc_infer/src/infer/generalize.rs
Normal file
|
|
@ -0,0 +1,479 @@
|
|||
use rustc_data_structures::sso::SsoHashMap;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::{self, InferConst, Term, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::Span;
|
||||
|
||||
use crate::infer::nll_relate::TypeRelatingDelegate;
|
||||
use crate::infer::type_variable::TypeVariableValue;
|
||||
use crate::infer::{InferCtxt, RegionVariableOrigin};
|
||||
|
||||
/// Attempts to generalize `term` for the type variable `for_vid`.
|
||||
/// This checks for cycles -- that is, whether the type `term`
|
||||
/// references `for_vid`.
|
||||
pub(super) fn generalize<'tcx, D: GeneralizerDelegate<'tcx>, T: Into<Term<'tcx>> + Relate<'tcx>>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
delegate: &mut D,
|
||||
term: T,
|
||||
for_vid: impl Into<ty::TermVid<'tcx>>,
|
||||
ambient_variance: ty::Variance,
|
||||
) -> RelateResult<'tcx, Generalization<T>> {
|
||||
let (for_universe, root_vid) = match for_vid.into() {
|
||||
ty::TermVid::Ty(ty_vid) => (
|
||||
infcx.probe_ty_var(ty_vid).unwrap_err(),
|
||||
ty::TermVid::Ty(infcx.inner.borrow_mut().type_variables().sub_root_var(ty_vid)),
|
||||
),
|
||||
ty::TermVid::Const(ct_vid) => (
|
||||
infcx.probe_const_var(ct_vid).unwrap_err(),
|
||||
ty::TermVid::Const(infcx.inner.borrow_mut().const_unification_table().find(ct_vid)),
|
||||
),
|
||||
};
|
||||
|
||||
let mut generalizer = Generalizer {
|
||||
infcx,
|
||||
delegate,
|
||||
ambient_variance,
|
||||
root_vid,
|
||||
for_universe,
|
||||
root_term: term.into(),
|
||||
needs_wf: false,
|
||||
cache: Default::default(),
|
||||
};
|
||||
|
||||
assert!(!term.has_escaping_bound_vars());
|
||||
let value = generalizer.relate(term, term)?;
|
||||
let needs_wf = generalizer.needs_wf;
|
||||
Ok(Generalization { value, needs_wf })
|
||||
}
|
||||
|
||||
/// Abstracts the handling of region vars between HIR and MIR/NLL typechecking
|
||||
/// in the generalizer code.
|
||||
pub trait GeneralizerDelegate<'tcx> {
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx>;
|
||||
|
||||
fn forbid_inference_vars() -> bool;
|
||||
|
||||
fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx>;
|
||||
}
|
||||
|
||||
pub struct CombineDelegate<'cx, 'tcx> {
|
||||
pub infcx: &'cx InferCtxt<'tcx>,
|
||||
pub param_env: ty::ParamEnv<'tcx>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'tcx> GeneralizerDelegate<'tcx> for CombineDelegate<'_, 'tcx> {
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
self.param_env
|
||||
}
|
||||
|
||||
fn forbid_inference_vars() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
|
||||
// FIXME: This is non-ideal because we don't give a
|
||||
// very descriptive origin for this region variable.
|
||||
self.infcx
|
||||
.next_region_var_in_universe(RegionVariableOrigin::MiscVariable(self.span), universe)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T> GeneralizerDelegate<'tcx> for T
|
||||
where
|
||||
T: TypeRelatingDelegate<'tcx>,
|
||||
{
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
<Self as TypeRelatingDelegate<'tcx>>::param_env(self)
|
||||
}
|
||||
|
||||
fn forbid_inference_vars() -> bool {
|
||||
<Self as TypeRelatingDelegate<'tcx>>::forbid_inference_vars()
|
||||
}
|
||||
|
||||
fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
|
||||
<Self as TypeRelatingDelegate<'tcx>>::generalize_existential(self, universe)
|
||||
}
|
||||
}
|
||||
|
||||
/// The "generalizer" is used when handling inference variables.
|
||||
///
|
||||
/// The basic strategy for handling a constraint like `?A <: B` is to
|
||||
/// apply a "generalization strategy" to the term `B` -- this replaces
|
||||
/// all the lifetimes in the term `B` with fresh inference variables.
|
||||
/// (You can read more about the strategy in this [blog post].)
|
||||
///
|
||||
/// As an example, if we had `?A <: &'x u32`, we would generalize `&'x
|
||||
/// u32` to `&'0 u32` where `'0` is a fresh variable. This becomes the
|
||||
/// value of `A`. Finally, we relate `&'0 u32 <: &'x u32`, which
|
||||
/// establishes `'0: 'x` as a constraint.
|
||||
///
|
||||
/// [blog post]: https://is.gd/0hKvIr
|
||||
struct Generalizer<'me, 'tcx, D> {
|
||||
infcx: &'me InferCtxt<'tcx>,
|
||||
|
||||
/// This is used to abstract the behaviors of the three previous
|
||||
/// generalizer-like implementations (`Generalizer`, `TypeGeneralizer`,
|
||||
/// and `ConstInferUnifier`). See [`GeneralizerDelegate`] for more
|
||||
/// information.
|
||||
delegate: &'me mut D,
|
||||
|
||||
/// After we generalize this type, we are going to relate it to
|
||||
/// some other type. What will be the variance at this point?
|
||||
ambient_variance: ty::Variance,
|
||||
|
||||
/// The vid of the type variable that is in the process of being
|
||||
/// instantiated. If we find this within the value we are folding,
|
||||
/// that means we would have created a cyclic value.
|
||||
root_vid: ty::TermVid<'tcx>,
|
||||
|
||||
/// The universe of the type variable that is in the process of being
|
||||
/// instantiated. If we find anything that this universe cannot name,
|
||||
/// we reject the relation.
|
||||
for_universe: ty::UniverseIndex,
|
||||
|
||||
/// The root term (const or type) we're generalizing. Used for cycle errors.
|
||||
root_term: Term<'tcx>,
|
||||
|
||||
cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
|
||||
|
||||
/// See the field `needs_wf` in `Generalization`.
|
||||
needs_wf: bool,
|
||||
}
|
||||
|
||||
impl<'tcx, D> Generalizer<'_, 'tcx, D> {
|
||||
/// Create an error that corresponds to the term kind in `root_term`
|
||||
fn cyclic_term_error(&self) -> TypeError<'tcx> {
|
||||
match self.root_term.unpack() {
|
||||
ty::TermKind::Ty(ty) => TypeError::CyclicTy(ty),
|
||||
ty::TermKind::Const(ct) => TypeError::CyclicConst(ct),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, D> TypeRelation<'tcx> for Generalizer<'_, 'tcx, D>
|
||||
where
|
||||
D: GeneralizerDelegate<'tcx>,
|
||||
{
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.infcx.tcx
|
||||
}
|
||||
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
self.delegate.param_env()
|
||||
}
|
||||
|
||||
fn tag(&self) -> &'static str {
|
||||
"Generalizer"
|
||||
}
|
||||
|
||||
fn a_is_expected(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn relate_item_substs(
|
||||
&mut self,
|
||||
item_def_id: DefId,
|
||||
a_subst: ty::SubstsRef<'tcx>,
|
||||
b_subst: ty::SubstsRef<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::SubstsRef<'tcx>> {
|
||||
if self.ambient_variance == ty::Variance::Invariant {
|
||||
// Avoid fetching the variance if we are in an invariant
|
||||
// context; no need, and it can induce dependency cycles
|
||||
// (e.g., #41849).
|
||||
relate::relate_substs(self, a_subst, b_subst)
|
||||
} else {
|
||||
let tcx = self.tcx();
|
||||
let opt_variances = tcx.variances_of(item_def_id);
|
||||
relate::relate_substs_with_variances(
|
||||
self,
|
||||
item_def_id,
|
||||
opt_variances,
|
||||
a_subst,
|
||||
b_subst,
|
||||
true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, variance, b), ret)]
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
&mut self,
|
||||
variance: ty::Variance,
|
||||
_info: ty::VarianceDiagInfo<'tcx>,
|
||||
a: T,
|
||||
b: T,
|
||||
) -> RelateResult<'tcx, T> {
|
||||
let old_ambient_variance = self.ambient_variance;
|
||||
self.ambient_variance = self.ambient_variance.xform(variance);
|
||||
debug!(?self.ambient_variance, "new ambient variance");
|
||||
let r = self.relate(a, b)?;
|
||||
self.ambient_variance = old_ambient_variance;
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, t2), ret)]
|
||||
fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
assert_eq!(t, t2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
|
||||
|
||||
if let Some(&result) = self.cache.get(&t) {
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
// Check to see whether the type we are generalizing references
|
||||
// any other type variable related to `vid` via
|
||||
// subtyping. This is basically our "occurs check", preventing
|
||||
// us from creating infinitely sized types.
|
||||
let g = match *t.kind() {
|
||||
ty::Infer(ty::TyVar(_)) | ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_))
|
||||
if D::forbid_inference_vars() =>
|
||||
{
|
||||
bug!("unexpected inference variable encountered in NLL generalization: {t}");
|
||||
}
|
||||
|
||||
ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
||||
bug!("unexpected infer type: {t}")
|
||||
}
|
||||
|
||||
ty::Infer(ty::TyVar(vid)) => {
|
||||
let mut inner = self.infcx.inner.borrow_mut();
|
||||
let vid = inner.type_variables().root_var(vid);
|
||||
let sub_vid = inner.type_variables().sub_root_var(vid);
|
||||
|
||||
if ty::TermVid::Ty(sub_vid) == self.root_vid {
|
||||
// If sub-roots are equal, then `root_vid` and
|
||||
// `vid` are related via subtyping.
|
||||
Err(self.cyclic_term_error())
|
||||
} else {
|
||||
let probe = inner.type_variables().probe(vid);
|
||||
match probe {
|
||||
TypeVariableValue::Known { value: u } => {
|
||||
drop(inner);
|
||||
self.relate(u, u)
|
||||
}
|
||||
TypeVariableValue::Unknown { universe } => {
|
||||
match self.ambient_variance {
|
||||
// Invariant: no need to make a fresh type variable
|
||||
// if we can name the universe.
|
||||
ty::Invariant => {
|
||||
if self.for_universe.can_name(universe) {
|
||||
return Ok(t);
|
||||
}
|
||||
}
|
||||
|
||||
// Bivariant: make a fresh var, but we
|
||||
// may need a WF predicate. See
|
||||
// comment on `needs_wf` field for
|
||||
// more info.
|
||||
ty::Bivariant => self.needs_wf = true,
|
||||
|
||||
// Co/contravariant: this will be
|
||||
// sufficiently constrained later on.
|
||||
ty::Covariant | ty::Contravariant => (),
|
||||
}
|
||||
|
||||
let origin = *inner.type_variables().var_origin(vid);
|
||||
let new_var_id =
|
||||
inner.type_variables().new_var(self.for_universe, origin);
|
||||
let u = self.tcx().mk_ty_var(new_var_id);
|
||||
|
||||
// Record that we replaced `vid` with `new_var_id` as part of a generalization
|
||||
// operation. This is needed to detect cyclic types. To see why, see the
|
||||
// docs in the `type_variables` module.
|
||||
inner.type_variables().sub(vid, new_var_id);
|
||||
debug!("replacing original vid={:?} with new={:?}", vid, u);
|
||||
Ok(u)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
|
||||
// No matter what mode we are in,
|
||||
// integer/floating-point types must be equal to be
|
||||
// relatable.
|
||||
Ok(t)
|
||||
}
|
||||
|
||||
ty::Placeholder(placeholder) => {
|
||||
if self.for_universe.can_name(placeholder.universe) {
|
||||
Ok(t)
|
||||
} else {
|
||||
debug!(
|
||||
"root universe {:?} cannot name placeholder in universe {:?}",
|
||||
self.for_universe, placeholder.universe
|
||||
);
|
||||
Err(TypeError::Mismatch)
|
||||
}
|
||||
}
|
||||
|
||||
_ => relate::structurally_relate_tys(self, t, t),
|
||||
}?;
|
||||
|
||||
self.cache.insert(t, g);
|
||||
Ok(g)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, r2), ret)]
|
||||
fn regions(
|
||||
&mut self,
|
||||
r: ty::Region<'tcx>,
|
||||
r2: ty::Region<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::Region<'tcx>> {
|
||||
assert_eq!(r, r2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
|
||||
|
||||
match *r {
|
||||
// Never make variables for regions bound within the type itself,
|
||||
// nor for erased regions.
|
||||
ty::ReLateBound(..) | ty::ReErased => {
|
||||
return Ok(r);
|
||||
}
|
||||
|
||||
// It doesn't really matter for correctness if we generalize ReError,
|
||||
// since we're already on a doomed compilation path.
|
||||
ty::ReError(_) => {
|
||||
return Ok(r);
|
||||
}
|
||||
|
||||
ty::RePlaceholder(..)
|
||||
| ty::ReVar(..)
|
||||
| ty::ReStatic
|
||||
| ty::ReEarlyBound(..)
|
||||
| ty::ReFree(..) => {
|
||||
// see common code below
|
||||
}
|
||||
}
|
||||
|
||||
// If we are in an invariant context, we can re-use the region
|
||||
// as is, unless it happens to be in some universe that we
|
||||
// can't name.
|
||||
if let ty::Invariant = self.ambient_variance {
|
||||
let r_universe = self.infcx.universe_of_region(r);
|
||||
if self.for_universe.can_name(r_universe) {
|
||||
return Ok(r);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(self.delegate.generalize_region(self.for_universe))
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, c2), ret)]
|
||||
fn consts(
|
||||
&mut self,
|
||||
c: ty::Const<'tcx>,
|
||||
c2: ty::Const<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::Const<'tcx>> {
|
||||
assert_eq!(c, c2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
|
||||
|
||||
match c.kind() {
|
||||
ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
|
||||
bug!("unexpected inference variable encountered in NLL generalization: {:?}", c);
|
||||
}
|
||||
ty::ConstKind::Infer(InferConst::Var(vid)) => {
|
||||
// If root const vids are equal, then `root_vid` and
|
||||
// `vid` are related and we'd be inferring an infinitely
|
||||
// deep const.
|
||||
if ty::TermVid::Const(
|
||||
self.infcx.inner.borrow_mut().const_unification_table().find(vid),
|
||||
) == self.root_vid
|
||||
{
|
||||
return Err(self.cyclic_term_error());
|
||||
}
|
||||
|
||||
let mut inner = self.infcx.inner.borrow_mut();
|
||||
let variable_table = &mut inner.const_unification_table();
|
||||
let var_value = variable_table.probe_value(vid);
|
||||
match var_value.val {
|
||||
ConstVariableValue::Known { value: u } => {
|
||||
drop(inner);
|
||||
self.relate(u, u)
|
||||
}
|
||||
ConstVariableValue::Unknown { universe } => {
|
||||
if self.for_universe.can_name(universe) {
|
||||
Ok(c)
|
||||
} else {
|
||||
let new_var_id = variable_table.new_key(ConstVarValue {
|
||||
origin: var_value.origin,
|
||||
val: ConstVariableValue::Unknown { universe: self.for_universe },
|
||||
});
|
||||
Ok(self.tcx().mk_const(new_var_id, c.ty()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// FIXME: remove this branch once `structurally_relate_consts` is fully
|
||||
// structural.
|
||||
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
|
||||
let substs = self.relate_with_variance(
|
||||
ty::Variance::Invariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
substs,
|
||||
substs,
|
||||
)?;
|
||||
Ok(self.tcx().mk_const(ty::UnevaluatedConst { def, substs }, c.ty()))
|
||||
}
|
||||
ty::ConstKind::Placeholder(placeholder) => {
|
||||
if self.for_universe.can_name(placeholder.universe) {
|
||||
Ok(c)
|
||||
} else {
|
||||
debug!(
|
||||
"root universe {:?} cannot name placeholder in universe {:?}",
|
||||
self.for_universe, placeholder.universe
|
||||
);
|
||||
Err(TypeError::Mismatch)
|
||||
}
|
||||
}
|
||||
_ => relate::structurally_relate_consts(self, c, c),
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
fn binders<T>(
|
||||
&mut self,
|
||||
a: ty::Binder<'tcx, T>,
|
||||
_: ty::Binder<'tcx, T>,
|
||||
) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
|
||||
where
|
||||
T: Relate<'tcx>,
|
||||
{
|
||||
let result = self.relate(a.skip_binder(), a.skip_binder())?;
|
||||
Ok(a.rebind(result))
|
||||
}
|
||||
}
|
||||
|
||||
/// Result from a generalization operation. This includes
|
||||
/// not only the generalized type, but also a bool flag
|
||||
/// indicating whether further WF checks are needed.
|
||||
#[derive(Debug)]
|
||||
pub struct Generalization<T> {
|
||||
pub value: T,
|
||||
|
||||
/// If true, then the generalized type may not be well-formed,
|
||||
/// even if the source type is well-formed, so we should add an
|
||||
/// additional check to enforce that it is. This arises in
|
||||
/// particular around 'bivariant' type parameters that are only
|
||||
/// constrained by a where-clause. As an example, imagine a type:
|
||||
///
|
||||
/// struct Foo<A, B> where A: Iterator<Item = B> {
|
||||
/// data: A
|
||||
/// }
|
||||
///
|
||||
/// here, `A` will be covariant, but `B` is
|
||||
/// unconstrained. However, whatever it is, for `Foo` to be WF, it
|
||||
/// must be equal to `A::Item`. If we have an input `Foo<?A, ?B>`,
|
||||
/// then after generalization we will wind up with a type like
|
||||
/// `Foo<?C, ?D>`. When we enforce that `Foo<?A, ?B> <: Foo<?C,
|
||||
/// ?D>` (or `>:`), we will wind up with the requirement that `?A
|
||||
/// <: ?C`, but no particular relationship between `?B` and `?D`
|
||||
/// (after all, we do not know the variance of the normalized form
|
||||
/// of `A::Item` with respect to `A`). If we do nothing else, this
|
||||
/// may mean that `?D` goes unconstrained (as in #41677). So, in
|
||||
/// this scenario where we create a new type variable in a
|
||||
/// bivariant context, we set the `needs_wf` flag to true. This
|
||||
/// will force the calling code to check that `WF(Foo<?C, ?D>)`
|
||||
/// holds, which in turn implies that `?C::Item == ?D`. So once
|
||||
/// `?C` is constrained, that should suffice to restrict `?D`.
|
||||
pub needs_wf: bool,
|
||||
}
|
||||
|
|
@ -58,6 +58,7 @@ pub mod error_reporting;
|
|||
pub mod free_regions;
|
||||
mod freshen;
|
||||
mod fudge;
|
||||
mod generalize;
|
||||
mod glb;
|
||||
mod higher_ranked;
|
||||
pub mod lattice;
|
||||
|
|
|
|||
|
|
@ -21,21 +21,20 @@
|
|||
//! thing we relate in chalk are basically domain goals and their
|
||||
//! constituents)
|
||||
|
||||
use crate::infer::InferCtxt;
|
||||
use crate::infer::{ConstVarValue, ConstVariableValue};
|
||||
use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use crate::traits::{Obligation, PredicateObligations};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::fold::FnMutDelegate;
|
||||
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::visit::TypeVisitableExt;
|
||||
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt};
|
||||
use rustc_span::{Span, Symbol};
|
||||
use std::fmt::Debug;
|
||||
|
||||
use super::combine::ObligationEmittingRelation;
|
||||
use crate::infer::combine::ObligationEmittingRelation;
|
||||
use crate::infer::generalize::{self, Generalization};
|
||||
use crate::infer::InferCtxt;
|
||||
use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use crate::traits::{Obligation, PredicateObligations};
|
||||
|
||||
pub struct TypeRelating<'me, 'tcx, D>
|
||||
where
|
||||
|
|
@ -198,7 +197,7 @@ where
|
|||
_ => (),
|
||||
}
|
||||
|
||||
let generalized_ty = self.generalize_value(value_ty, vid)?;
|
||||
let generalized_ty = self.generalize(value_ty, vid)?;
|
||||
debug!("relate_ty_var: generalized_ty = {:?}", generalized_ty);
|
||||
|
||||
if D::forbid_inference_vars() {
|
||||
|
|
@ -217,26 +216,15 @@ where
|
|||
result
|
||||
}
|
||||
|
||||
fn generalize_value<T: Relate<'tcx>>(
|
||||
&mut self,
|
||||
value: T,
|
||||
for_vid: ty::TyVid,
|
||||
) -> RelateResult<'tcx, T> {
|
||||
let universe = self.infcx.probe_ty_var(for_vid).unwrap_err();
|
||||
|
||||
if value.has_escaping_bound_vars() {
|
||||
bug!("trying to instantiate {for_vid:?} with escaping bound vars: {value:?}");
|
||||
}
|
||||
|
||||
let mut generalizer = TypeGeneralizer {
|
||||
infcx: self.infcx,
|
||||
delegate: &mut self.delegate,
|
||||
ambient_variance: self.ambient_variance,
|
||||
for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid),
|
||||
universe,
|
||||
};
|
||||
|
||||
generalizer.relate(value, value)
|
||||
fn generalize(&mut self, ty: Ty<'tcx>, for_vid: ty::TyVid) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
let Generalization { value: ty, needs_wf: _ } = generalize::generalize(
|
||||
self.infcx,
|
||||
&mut self.delegate,
|
||||
ty,
|
||||
for_vid,
|
||||
self.ambient_variance,
|
||||
)?;
|
||||
Ok(ty)
|
||||
}
|
||||
|
||||
fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
|
|
@ -716,235 +704,3 @@ where
|
|||
})]);
|
||||
}
|
||||
}
|
||||
|
||||
/// The "type generalizer" is used when handling inference variables.
|
||||
///
|
||||
/// The basic strategy for handling a constraint like `?A <: B` is to
|
||||
/// apply a "generalization strategy" to the type `B` -- this replaces
|
||||
/// all the lifetimes in the type `B` with fresh inference
|
||||
/// variables. (You can read more about the strategy in this [blog
|
||||
/// post].)
|
||||
///
|
||||
/// As an example, if we had `?A <: &'x u32`, we would generalize `&'x
|
||||
/// u32` to `&'0 u32` where `'0` is a fresh variable. This becomes the
|
||||
/// value of `A`. Finally, we relate `&'0 u32 <: &'x u32`, which
|
||||
/// establishes `'0: 'x` as a constraint.
|
||||
///
|
||||
/// [blog post]: https://is.gd/0hKvIr
|
||||
struct TypeGeneralizer<'me, 'tcx, D>
|
||||
where
|
||||
D: TypeRelatingDelegate<'tcx>,
|
||||
{
|
||||
infcx: &'me InferCtxt<'tcx>,
|
||||
|
||||
delegate: &'me mut D,
|
||||
|
||||
/// After we generalize this type, we are going to relate it to
|
||||
/// some other type. What will be the variance at this point?
|
||||
ambient_variance: ty::Variance,
|
||||
|
||||
/// The vid of the type variable that is in the process of being
|
||||
/// instantiated. If we find this within the value we are folding,
|
||||
/// that means we would have created a cyclic value.
|
||||
for_vid_sub_root: ty::TyVid,
|
||||
|
||||
/// The universe of the type variable that is in the process of being
|
||||
/// instantiated. If we find anything that this universe cannot name,
|
||||
/// we reject the relation.
|
||||
universe: ty::UniverseIndex,
|
||||
}
|
||||
|
||||
impl<'tcx, D> TypeRelation<'tcx> for TypeGeneralizer<'_, 'tcx, D>
|
||||
where
|
||||
D: TypeRelatingDelegate<'tcx>,
|
||||
{
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.infcx.tcx
|
||||
}
|
||||
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
self.delegate.param_env()
|
||||
}
|
||||
|
||||
fn tag(&self) -> &'static str {
|
||||
"nll::generalizer"
|
||||
}
|
||||
|
||||
fn a_is_expected(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
&mut self,
|
||||
variance: ty::Variance,
|
||||
_info: ty::VarianceDiagInfo<'tcx>,
|
||||
a: T,
|
||||
b: T,
|
||||
) -> RelateResult<'tcx, T> {
|
||||
debug!(
|
||||
"TypeGeneralizer::relate_with_variance(variance={:?}, a={:?}, b={:?})",
|
||||
variance, a, b
|
||||
);
|
||||
|
||||
let old_ambient_variance = self.ambient_variance;
|
||||
self.ambient_variance = self.ambient_variance.xform(variance);
|
||||
|
||||
debug!(
|
||||
"TypeGeneralizer::relate_with_variance: ambient_variance = {:?}",
|
||||
self.ambient_variance
|
||||
);
|
||||
|
||||
let r = self.relate(a, b)?;
|
||||
|
||||
self.ambient_variance = old_ambient_variance;
|
||||
|
||||
debug!("TypeGeneralizer::relate_with_variance: r={:?}", r);
|
||||
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
fn tys(&mut self, a: Ty<'tcx>, _: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
use crate::infer::type_variable::TypeVariableValue;
|
||||
|
||||
debug!("TypeGeneralizer::tys(a={:?})", a);
|
||||
|
||||
match *a.kind() {
|
||||
ty::Infer(ty::TyVar(_)) | ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_))
|
||||
if D::forbid_inference_vars() =>
|
||||
{
|
||||
bug!("unexpected inference variable encountered in NLL generalization: {:?}", a);
|
||||
}
|
||||
|
||||
ty::Infer(ty::TyVar(vid)) => {
|
||||
let mut inner = self.infcx.inner.borrow_mut();
|
||||
let variables = &mut inner.type_variables();
|
||||
let vid = variables.root_var(vid);
|
||||
let sub_vid = variables.sub_root_var(vid);
|
||||
if sub_vid == self.for_vid_sub_root {
|
||||
// If sub-roots are equal, then `for_vid` and
|
||||
// `vid` are related via subtyping.
|
||||
debug!("TypeGeneralizer::tys: occurs check failed");
|
||||
Err(TypeError::Mismatch)
|
||||
} else {
|
||||
match variables.probe(vid) {
|
||||
TypeVariableValue::Known { value: u } => {
|
||||
drop(inner);
|
||||
self.relate(u, u)
|
||||
}
|
||||
TypeVariableValue::Unknown { universe: _universe } => {
|
||||
if self.ambient_variance == ty::Bivariant {
|
||||
// FIXME: we may need a WF predicate (related to #54105).
|
||||
}
|
||||
|
||||
let origin = *variables.var_origin(vid);
|
||||
|
||||
// Replacing with a new variable in the universe `self.universe`,
|
||||
// it will be unified later with the original type variable in
|
||||
// the universe `_universe`.
|
||||
let new_var_id = variables.new_var(self.universe, origin);
|
||||
|
||||
let u = self.tcx().mk_ty_var(new_var_id);
|
||||
debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
|
||||
Ok(u)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
|
||||
// No matter what mode we are in,
|
||||
// integer/floating-point types must be equal to be
|
||||
// relatable.
|
||||
Ok(a)
|
||||
}
|
||||
|
||||
ty::Placeholder(placeholder) => {
|
||||
if self.universe.cannot_name(placeholder.universe) {
|
||||
debug!(
|
||||
"TypeGeneralizer::tys: root universe {:?} cannot name\
|
||||
placeholder in universe {:?}",
|
||||
self.universe, placeholder.universe
|
||||
);
|
||||
Err(TypeError::Mismatch)
|
||||
} else {
|
||||
Ok(a)
|
||||
}
|
||||
}
|
||||
|
||||
_ => relate::super_relate_tys(self, a, a),
|
||||
}
|
||||
}
|
||||
|
||||
fn regions(
|
||||
&mut self,
|
||||
a: ty::Region<'tcx>,
|
||||
_: ty::Region<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::Region<'tcx>> {
|
||||
debug!("TypeGeneralizer::regions(a={:?})", a);
|
||||
|
||||
if let ty::ReLateBound(..) = *a {
|
||||
return Ok(a);
|
||||
}
|
||||
|
||||
// For now, we just always create a fresh region variable to
|
||||
// replace all the regions in the source type. In the main
|
||||
// type checker, we special case the case where the ambient
|
||||
// variance is `Invariant` and try to avoid creating a fresh
|
||||
// region variable, but since this comes up so much less in
|
||||
// NLL (only when users use `_` etc) it is much less
|
||||
// important.
|
||||
//
|
||||
// As an aside, since these new variables are created in
|
||||
// `self.universe` universe, this also serves to enforce the
|
||||
// universe scoping rules.
|
||||
//
|
||||
// FIXME(#54105) -- if the ambient variance is bivariant,
|
||||
// though, we may however need to check well-formedness or
|
||||
// risk a problem like #41677 again.
|
||||
let replacement_region_vid = self.delegate.generalize_existential(self.universe);
|
||||
|
||||
Ok(replacement_region_vid)
|
||||
}
|
||||
|
||||
fn consts(
|
||||
&mut self,
|
||||
a: ty::Const<'tcx>,
|
||||
_: ty::Const<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::Const<'tcx>> {
|
||||
match a.kind() {
|
||||
ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
|
||||
bug!("unexpected inference variable encountered in NLL generalization: {:?}", a);
|
||||
}
|
||||
ty::ConstKind::Infer(InferConst::Var(vid)) => {
|
||||
let mut inner = self.infcx.inner.borrow_mut();
|
||||
let variable_table = &mut inner.const_unification_table();
|
||||
let var_value = variable_table.probe_value(vid);
|
||||
match var_value.val.known() {
|
||||
Some(u) => self.relate(u, u),
|
||||
None => {
|
||||
let new_var_id = variable_table.new_key(ConstVarValue {
|
||||
origin: var_value.origin,
|
||||
val: ConstVariableValue::Unknown { universe: self.universe },
|
||||
});
|
||||
Ok(self.tcx().mk_const(new_var_id, a.ty()))
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::ConstKind::Unevaluated(..) if self.tcx().lazy_normalization() => Ok(a),
|
||||
_ => relate::super_relate_consts(self, a, a),
|
||||
}
|
||||
}
|
||||
|
||||
fn binders<T>(
|
||||
&mut self,
|
||||
a: ty::Binder<'tcx, T>,
|
||||
_: ty::Binder<'tcx, T>,
|
||||
) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
|
||||
where
|
||||
T: Relate<'tcx>,
|
||||
{
|
||||
debug!("TypeGeneralizer::binders(a={:?})", a);
|
||||
let result = self.relate(a.skip_binder(), a.skip_binder())?;
|
||||
Ok(a.rebind(result))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
|
|||
} else if pattern == value {
|
||||
Ok(pattern)
|
||||
} else {
|
||||
relate::super_relate_tys(self, pattern, value)
|
||||
relate::structurally_relate_tys(self, pattern, value)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -201,7 +201,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
|
|||
if pattern == value {
|
||||
Ok(pattern)
|
||||
} else {
|
||||
relate::super_relate_consts(self, pattern, value)
|
||||
relate::structurally_relate_consts(self, pattern, value)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use super::combine::{CombineFields, RelationDir};
|
||||
use super::combine::CombineFields;
|
||||
use super::{DefineOpaqueTypes, ObligationEmittingRelation, SubregionOrigin};
|
||||
|
||||
use crate::traits::{Obligation, PredicateObligations};
|
||||
|
|
@ -108,11 +108,11 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
|
|||
Ok(a)
|
||||
}
|
||||
(&ty::Infer(TyVar(a_id)), _) => {
|
||||
self.fields.instantiate(b, RelationDir::SupertypeOf, a_id, !self.a_is_expected)?;
|
||||
self.fields.instantiate(b, ty::Contravariant, a_id, !self.a_is_expected)?;
|
||||
Ok(a)
|
||||
}
|
||||
(_, &ty::Infer(TyVar(b_id))) => {
|
||||
self.fields.instantiate(a, RelationDir::SubtypeOf, b_id, self.a_is_expected)?;
|
||||
self.fields.instantiate(a, ty::Covariant, b_id, self.a_is_expected)?;
|
||||
Ok(a)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use rustc_data_structures::OnDrop;
|
|||
use rustc_errors::registry::Registry;
|
||||
use rustc_errors::{ErrorGuaranteed, Handler};
|
||||
use rustc_lint::LintStore;
|
||||
use rustc_middle::query::{ExternProviders, Providers};
|
||||
use rustc_middle::{bug, ty};
|
||||
use rustc_parse::maybe_new_parser_from_source_str;
|
||||
use rustc_query_impl::QueryCtxt;
|
||||
|
|
@ -37,8 +38,7 @@ pub struct Compiler {
|
|||
pub(crate) sess: Lrc<Session>,
|
||||
codegen_backend: Lrc<Box<dyn CodegenBackend>>,
|
||||
pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>>,
|
||||
pub(crate) override_queries:
|
||||
Option<fn(&Session, &mut ty::query::Providers, &mut ty::query::ExternProviders)>,
|
||||
pub(crate) override_queries: Option<fn(&Session, &mut Providers, &mut ExternProviders)>,
|
||||
}
|
||||
|
||||
impl Compiler {
|
||||
|
|
@ -60,6 +60,11 @@ impl Compiler {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(rustc::bad_opt_access)]
|
||||
pub fn set_thread_safe_mode(sopts: &config::UnstableOptions) {
|
||||
rustc_data_structures::sync::set_dyn_thread_safe_mode(sopts.threads > 1);
|
||||
}
|
||||
|
||||
/// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`.
|
||||
pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String>)> {
|
||||
rustc_span::create_default_session_if_not_set_then(move |_| {
|
||||
|
|
@ -270,8 +275,7 @@ pub struct Config {
|
|||
/// the list of queries.
|
||||
///
|
||||
/// The second parameter is local providers and the third parameter is external providers.
|
||||
pub override_queries:
|
||||
Option<fn(&Session, &mut ty::query::Providers, &mut ty::query::ExternProviders)>,
|
||||
pub override_queries: Option<fn(&Session, &mut Providers, &mut ExternProviders)>,
|
||||
|
||||
/// This is a callback from the driver that is called to create a codegen backend.
|
||||
pub make_codegen_backend:
|
||||
|
|
@ -347,7 +351,7 @@ pub fn try_print_query_stack(handler: &Handler, num_frames: Option<usize>) {
|
|||
// state if it was responsible for triggering the panic.
|
||||
let i = ty::tls::with_context_opt(|icx| {
|
||||
if let Some(icx) = icx {
|
||||
print_query_stack(QueryCtxt { tcx: icx.tcx }, icx.query, handler, num_frames)
|
||||
print_query_stack(QueryCtxt::new(icx.tcx), icx.query, handler, num_frames)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintSto
|
|||
use rustc_metadata::creader::CStore;
|
||||
use rustc_middle::arena::Arena;
|
||||
use rustc_middle::dep_graph::DepGraph;
|
||||
use rustc_middle::ty::query::{ExternProviders, Providers};
|
||||
use rustc_middle::query::{ExternProviders, Providers};
|
||||
use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt};
|
||||
use rustc_mir_build as mir_build;
|
||||
use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr};
|
||||
|
|
@ -700,9 +700,12 @@ pub fn create_global_ctxt<'tcx>(
|
|||
hir_arena,
|
||||
untracked,
|
||||
dep_graph,
|
||||
query_result_on_disk_cache,
|
||||
rustc_query_impl::query_callbacks(arena),
|
||||
rustc_query_impl::query_system_fns(local_providers, extern_providers),
|
||||
rustc_query_impl::query_system(
|
||||
local_providers,
|
||||
extern_providers,
|
||||
query_result_on_disk_cache,
|
||||
),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use rustc_ast::attr;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
|
|
|
|||
|
|
@ -582,34 +582,38 @@ impl Cursor<'_> {
|
|||
let mut base = Base::Decimal;
|
||||
if first_digit == '0' {
|
||||
// Attempt to parse encoding base.
|
||||
let has_digits = match self.first() {
|
||||
match self.first() {
|
||||
'b' => {
|
||||
base = Base::Binary;
|
||||
self.bump();
|
||||
self.eat_decimal_digits()
|
||||
if !self.eat_decimal_digits() {
|
||||
return Int { base, empty_int: true };
|
||||
}
|
||||
}
|
||||
'o' => {
|
||||
base = Base::Octal;
|
||||
self.bump();
|
||||
self.eat_decimal_digits()
|
||||
if !self.eat_decimal_digits() {
|
||||
return Int { base, empty_int: true };
|
||||
}
|
||||
}
|
||||
'x' => {
|
||||
base = Base::Hexadecimal;
|
||||
self.bump();
|
||||
self.eat_hexadecimal_digits()
|
||||
if !self.eat_hexadecimal_digits() {
|
||||
return Int { base, empty_int: true };
|
||||
}
|
||||
}
|
||||
// Not a base prefix.
|
||||
'0'..='9' | '_' | '.' | 'e' | 'E' => {
|
||||
// Not a base prefix; consume additional digits.
|
||||
'0'..='9' | '_' => {
|
||||
self.eat_decimal_digits();
|
||||
true
|
||||
}
|
||||
|
||||
// Also not a base prefix; nothing more to do here.
|
||||
'.' | 'e' | 'E' => {}
|
||||
|
||||
// Just a 0.
|
||||
_ => return Int { base, empty_int: false },
|
||||
};
|
||||
// Base prefix was provided, but there were no digits
|
||||
// after it, e.g. "0x".
|
||||
if !has_digits {
|
||||
return Int { base, empty_int: true };
|
||||
}
|
||||
} else {
|
||||
// No base prefix, parse number in the usual way.
|
||||
|
|
|
|||
|
|
@ -647,7 +647,9 @@ declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS])
|
|||
|
||||
impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
|
||||
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
|
||||
if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) {
|
||||
if !(cx.effective_visibilities.is_reachable(item.owner_id.def_id)
|
||||
&& cx.tcx.local_visibility(item.owner_id.def_id).is_public())
|
||||
{
|
||||
return;
|
||||
}
|
||||
let (def, ty) = match item.kind {
|
||||
|
|
@ -766,7 +768,9 @@ impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]);
|
|||
|
||||
impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
|
||||
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
|
||||
if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) {
|
||||
if !(cx.effective_visibilities.is_reachable(item.owner_id.def_id)
|
||||
&& cx.tcx.local_visibility(item.owner_id.def_id).is_public())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,9 +49,9 @@ use std::cell::Cell;
|
|||
use std::iter;
|
||||
use std::slice;
|
||||
|
||||
type EarlyLintPassFactory = dyn Fn() -> EarlyLintPassObject + sync::Send + sync::Sync;
|
||||
type EarlyLintPassFactory = dyn Fn() -> EarlyLintPassObject + sync::DynSend + sync::DynSync;
|
||||
type LateLintPassFactory =
|
||||
dyn for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::Send + sync::Sync;
|
||||
dyn for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::DynSend + sync::DynSync;
|
||||
|
||||
/// Information about the registered lints.
|
||||
///
|
||||
|
|
@ -169,7 +169,7 @@ impl LintStore {
|
|||
|
||||
pub fn register_early_pass(
|
||||
&mut self,
|
||||
pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync,
|
||||
pass: impl Fn() -> EarlyLintPassObject + 'static + sync::DynSend + sync::DynSync,
|
||||
) {
|
||||
self.early_passes.push(Box::new(pass));
|
||||
}
|
||||
|
|
@ -182,7 +182,7 @@ impl LintStore {
|
|||
/// * See [rust-clippy#5518](https://github.com/rust-lang/rust-clippy/pull/5518)
|
||||
pub fn register_pre_expansion_pass(
|
||||
&mut self,
|
||||
pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync,
|
||||
pass: impl Fn() -> EarlyLintPassObject + 'static + sync::DynSend + sync::DynSync,
|
||||
) {
|
||||
self.pre_expansion_passes.push(Box::new(pass));
|
||||
}
|
||||
|
|
@ -191,8 +191,8 @@ impl LintStore {
|
|||
&mut self,
|
||||
pass: impl for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx>
|
||||
+ 'static
|
||||
+ sync::Send
|
||||
+ sync::Sync,
|
||||
+ sync::DynSend
|
||||
+ sync::DynSync,
|
||||
) {
|
||||
self.late_passes.push(Box::new(pass));
|
||||
}
|
||||
|
|
@ -201,8 +201,8 @@ impl LintStore {
|
|||
&mut self,
|
||||
pass: impl for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx>
|
||||
+ 'static
|
||||
+ sync::Send
|
||||
+ sync::Sync,
|
||||
+ sync::DynSend
|
||||
+ sync::DynSync,
|
||||
) {
|
||||
self.late_module_passes.push(Box::new(pass));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::lints::{Expectation, ExpectationNote};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::lint::builtin::UNFULFILLED_LINT_EXPECTATIONS;
|
||||
use rustc_session::lint::LintExpectationId;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore};
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::sync::join;
|
||||
use rustc_data_structures::sync::{join, DynSend};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::intravisit as hir_visit;
|
||||
|
|
@ -429,7 +429,7 @@ fn late_lint_crate_inner<'tcx, T: LateLintPass<'tcx>>(
|
|||
/// Performs lint checking on a crate.
|
||||
pub fn check_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
builtin_lints: impl FnOnce() -> T + Send,
|
||||
builtin_lints: impl FnOnce() -> T + Send + DynSend,
|
||||
) {
|
||||
join(
|
||||
|| {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ use rustc_middle::lint::{
|
|||
reveal_actual_level, struct_lint_level, LevelAndSource, LintExpectation, LintLevelSource,
|
||||
ShallowLintLevelMap,
|
||||
};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{RegisteredTools, TyCtxt};
|
||||
use rustc_session::lint::builtin::{RENAMED_AND_REMOVED_LINTS, UNKNOWN_LINTS, UNUSED_ATTRIBUTES};
|
||||
use rustc_session::lint::{
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
|
|||
use rustc_fluent_macro::fluent_messages;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::lint::builtin::{
|
||||
BARE_TRAIT_OBJECTS, ELIDED_LIFETIMES_IN_PATHS, EXPLICIT_OUTLIVES_REQUIREMENTS,
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@ fn add_query_desc_cached_impl(
|
|||
quote! {
|
||||
#[allow(unused_variables, unused_braces, rustc::pass_by_value)]
|
||||
#[inline]
|
||||
pub fn #name<'tcx>(#tcx: TyCtxt<'tcx>, #key: &crate::ty::query::query_keys::#name<'tcx>) -> bool {
|
||||
pub fn #name<'tcx>(#tcx: TyCtxt<'tcx>, #key: &crate::query::query_keys::#name<'tcx>) -> bool {
|
||||
#expr
|
||||
}
|
||||
}
|
||||
|
|
@ -262,7 +262,7 @@ fn add_query_desc_cached_impl(
|
|||
// we're taking `key` by reference, but some rustc types usually prefer being passed by value
|
||||
#[allow(rustc::pass_by_value)]
|
||||
#[inline]
|
||||
pub fn #name<'tcx>(_: TyCtxt<'tcx>, _: &crate::ty::query::query_keys::#name<'tcx>) -> bool {
|
||||
pub fn #name<'tcx>(_: TyCtxt<'tcx>, _: &crate::query::query_keys::#name<'tcx>) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
@ -273,7 +273,7 @@ fn add_query_desc_cached_impl(
|
|||
|
||||
let desc = quote! {
|
||||
#[allow(unused_variables)]
|
||||
pub fn #name<'tcx>(tcx: TyCtxt<'tcx>, key: crate::ty::query::query_keys::#name<'tcx>) -> String {
|
||||
pub fn #name<'tcx>(tcx: TyCtxt<'tcx>, key: crate::query::query_keys::#name<'tcx>) -> String {
|
||||
let (#tcx, #key) = (tcx, key);
|
||||
::rustc_middle::ty::print::with_no_trimmed_paths!(
|
||||
format!(#desc)
|
||||
|
|
|
|||
|
|
@ -1472,28 +1472,30 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
|||
..
|
||||
} = source_file_to_import;
|
||||
|
||||
// If this file is under $sysroot/lib/rustlib/src/ but has not been remapped
|
||||
// during rust bootstrapping by `remap-debuginfo = true`, and the user
|
||||
// wish to simulate that behaviour by -Z simulate-remapped-rust-src-base,
|
||||
// If this file is under $sysroot/lib/rustlib/src/
|
||||
// and the user wish to simulate remapping with -Z simulate-remapped-rust-src-base,
|
||||
// then we change `name` to a similar state as if the rust was bootstrapped
|
||||
// with `remap-debuginfo = true`.
|
||||
// This is useful for testing so that tests about the effects of
|
||||
// `try_to_translate_virtual_to_real` don't have to worry about how the
|
||||
// compiler is bootstrapped.
|
||||
if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base
|
||||
{
|
||||
if let Some(real_dir) = &sess.opts.real_rust_source_base_dir {
|
||||
for subdir in ["library", "compiler"] {
|
||||
if let rustc_span::FileName::Real(ref mut old_name) = name {
|
||||
if let rustc_span::RealFileName::LocalPath(local) = old_name {
|
||||
if let Ok(rest) = local.strip_prefix(real_dir.join(subdir)) {
|
||||
*old_name = rustc_span::RealFileName::Remapped {
|
||||
local_path: None,
|
||||
virtual_name: virtual_dir.join(subdir).join(rest),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
&& let Some(real_dir) = &sess.opts.real_rust_source_base_dir
|
||||
&& let rustc_span::FileName::Real(ref mut old_name) = name {
|
||||
let relative_path = match old_name {
|
||||
rustc_span::RealFileName::LocalPath(local) => local.strip_prefix(real_dir).ok(),
|
||||
rustc_span::RealFileName::Remapped { virtual_name, .. } => {
|
||||
option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").and_then(|virtual_dir| virtual_name.strip_prefix(virtual_dir).ok())
|
||||
}
|
||||
};
|
||||
debug!(?relative_path, ?virtual_dir, "simulate_remapped_rust_src_base");
|
||||
for subdir in ["library", "compiler"] {
|
||||
if let Some(rest) = relative_path.and_then(|p| p.strip_prefix(subdir).ok()) {
|
||||
*old_name = rustc_span::RealFileName::Remapped {
|
||||
local_path: None, // FIXME: maybe we should preserve this?
|
||||
virtual_name: virtual_dir.join(subdir).join(rest),
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ use rustc_middle::metadata::ModChild;
|
|||
use rustc_middle::middle::exported_symbols::ExportedSymbol;
|
||||
use rustc_middle::middle::stability::DeprecationEntry;
|
||||
use rustc_middle::query::LocalCrate;
|
||||
use rustc_middle::query::{ExternProviders, Providers};
|
||||
use rustc_middle::ty::fast_reject::SimplifiedType;
|
||||
use rustc_middle::ty::query::{ExternProviders, Providers};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_session::cstore::CrateStore;
|
||||
use rustc_session::{Session, StableCrateId};
|
||||
|
|
@ -114,8 +114,8 @@ macro_rules! provide_one {
|
|||
($tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => $compute:block) => {
|
||||
fn $name<'tcx>(
|
||||
$tcx: TyCtxt<'tcx>,
|
||||
def_id_arg: ty::query::query_keys::$name<'tcx>,
|
||||
) -> ty::query::query_provided::$name<'tcx> {
|
||||
def_id_arg: rustc_middle::query::query_keys::$name<'tcx>,
|
||||
) -> rustc_middle::query::query_provided::$name<'tcx> {
|
||||
let _prof_timer =
|
||||
$tcx.prof.generic_activity(concat!("metadata_decode_entry_", stringify!($name)));
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc_data_structures::fingerprint::Fingerprint;
|
|||
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
|
||||
use rustc_data_structures::memmap::{Mmap, MmapMut};
|
||||
use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
|
||||
use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator};
|
||||
use rustc_data_structures::sync::{join, par_for_each_in, Lrc};
|
||||
use rustc_data_structures::temp_dir::MaybeTempDir;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
|
|
@ -25,10 +25,10 @@ use rustc_middle::middle::exported_symbols::{
|
|||
};
|
||||
use rustc_middle::mir::interpret;
|
||||
use rustc_middle::query::LocalCrate;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::traits::specialization_graph;
|
||||
use rustc_middle::ty::codec::TyEncoder;
|
||||
use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
|
||||
use rustc_middle::util::common::to_readable_str;
|
||||
use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
|
||||
|
|
@ -2131,7 +2131,7 @@ fn prefetch_mir(tcx: TyCtxt<'_>) {
|
|||
return;
|
||||
}
|
||||
|
||||
par_iter(tcx.mir_keys(())).for_each(|&def_id| {
|
||||
par_for_each_in(tcx.mir_keys(()), |&def_id| {
|
||||
let (encode_const, encode_opt) = should_encode_mir(tcx, def_id);
|
||||
|
||||
if encode_const {
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
|
|||
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
|
||||
use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::fast_reject::SimplifiedType;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::{self, ReprOptions, Ty, UnusedGenericParams};
|
||||
use rustc_middle::ty::{DeducedParamAttrs, GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt};
|
||||
use rustc_serialize::opaque::FileEncoder;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ chalk-ir = "0.87.0"
|
|||
derive_more = "0.99.17"
|
||||
either = "1.5.0"
|
||||
gsgdt = "0.1.2"
|
||||
field-offset = "0.3.5"
|
||||
measureme = "10.0.0"
|
||||
polonius-engine = "0.13.0"
|
||||
rustc_apfloat = { path = "../rustc_apfloat" }
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use rustc_ast as ast;
|
|||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::svh::Svh;
|
||||
use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
|
||||
use rustc_data_structures::sync::{par_for_each_in, DynSend, DynSync};
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
|
||||
use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
|
||||
|
|
@ -150,11 +150,6 @@ impl<'hir> Map<'hir> {
|
|||
self.tcx.hir_module_items(module).items()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn par_for_each_item(self, f: impl Fn(ItemId) + Sync + Send) {
|
||||
par_for_each_in(&self.tcx.hir_crate_items(()).items[..], |id| f(*id));
|
||||
}
|
||||
|
||||
pub fn def_key(self, def_id: LocalDefId) -> DefKey {
|
||||
// Accessing the DefKey is ok, since it is part of DefPathHash.
|
||||
self.tcx.definitions_untracked().def_key(def_id)
|
||||
|
|
@ -502,7 +497,7 @@ impl<'hir> Map<'hir> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn par_body_owners(self, f: impl Fn(LocalDefId) + Sync + Send) {
|
||||
pub fn par_body_owners(self, f: impl Fn(LocalDefId) + DynSend + DynSync) {
|
||||
par_for_each_in(&self.tcx.hir_crate_items(()).body_owners[..], |&def_id| f(def_id));
|
||||
}
|
||||
|
||||
|
|
@ -640,7 +635,7 @@ impl<'hir> Map<'hir> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn par_for_each_module(self, f: impl Fn(LocalDefId) + Sync + Send) {
|
||||
pub fn par_for_each_module(self, f: impl Fn(LocalDefId) + DynSend + DynSync) {
|
||||
let crate_items = self.tcx.hir_crate_items(());
|
||||
par_for_each_in(&crate_items.submodules[..], |module| f(module.def_id))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ pub mod map;
|
|||
pub mod nested_filter;
|
||||
pub mod place;
|
||||
|
||||
use crate::ty::query::Providers;
|
||||
use crate::query::Providers;
|
||||
use crate::ty::{EarlyBinder, ImplSubject, TyCtxt};
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
|
||||
use rustc_data_structures::sync::{par_for_each_in, DynSend, DynSync};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::*;
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
|
|
@ -77,19 +77,19 @@ impl ModuleItems {
|
|||
self.owners().map(|id| id.def_id)
|
||||
}
|
||||
|
||||
pub fn par_items(&self, f: impl Fn(ItemId) + Send + Sync) {
|
||||
pub fn par_items(&self, f: impl Fn(ItemId) + DynSend + DynSync) {
|
||||
par_for_each_in(&self.items[..], |&id| f(id))
|
||||
}
|
||||
|
||||
pub fn par_trait_items(&self, f: impl Fn(TraitItemId) + Send + Sync) {
|
||||
pub fn par_trait_items(&self, f: impl Fn(TraitItemId) + DynSend + DynSync) {
|
||||
par_for_each_in(&self.trait_items[..], |&id| f(id))
|
||||
}
|
||||
|
||||
pub fn par_impl_items(&self, f: impl Fn(ImplItemId) + Send + Sync) {
|
||||
pub fn par_impl_items(&self, f: impl Fn(ImplItemId) + DynSend + DynSync) {
|
||||
par_for_each_in(&self.impl_items[..], |&id| f(id))
|
||||
}
|
||||
|
||||
pub fn par_foreign_items(&self, f: impl Fn(ForeignItemId) + Send + Sync) {
|
||||
pub fn par_foreign_items(&self, f: impl Fn(ForeignItemId) + DynSend + DynSync) {
|
||||
par_for_each_in(&self.foreign_items[..], |&id| f(id))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,13 +84,8 @@ mod tests;
|
|||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
#[macro_use]
|
||||
pub mod query;
|
||||
|
||||
#[macro_use]
|
||||
pub mod arena;
|
||||
#[macro_use]
|
||||
pub mod dep_graph;
|
||||
pub(crate) mod error;
|
||||
pub mod hir;
|
||||
pub mod infer;
|
||||
|
|
@ -100,10 +95,16 @@ pub mod middle;
|
|||
pub mod mir;
|
||||
pub mod thir;
|
||||
pub mod traits;
|
||||
#[macro_use]
|
||||
pub mod ty;
|
||||
pub mod util;
|
||||
mod values;
|
||||
|
||||
#[macro_use]
|
||||
pub mod query;
|
||||
#[macro_use]
|
||||
pub mod dep_graph;
|
||||
|
||||
// Allows macros to refer to this crate as `::rustc_middle`
|
||||
extern crate self as rustc_middle;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
use crate::bug;
|
||||
use crate::error::LimitInvalid;
|
||||
use crate::ty;
|
||||
use crate::query::Providers;
|
||||
use rustc_ast::Attribute;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::{Limit, Limits};
|
||||
|
|
@ -19,7 +19,7 @@ use rustc_span::symbol::{sym, Symbol};
|
|||
|
||||
use std::num::IntErrorKind;
|
||||
|
||||
pub fn provide(providers: &mut ty::query::Providers) {
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
providers.limits = |tcx, ()| Limits {
|
||||
recursion_limit: get_recursion_limit(tcx.hir().krate_attrs(), tcx.sess),
|
||||
move_size_limit: get_limit(
|
||||
|
|
|
|||
|
|
@ -32,6 +32,6 @@ pub mod region;
|
|||
pub mod resolve_bound_vars;
|
||||
pub mod stability;
|
||||
|
||||
pub fn provide(providers: &mut crate::ty::query::Providers) {
|
||||
pub fn provide(providers: &mut crate::query::Providers) {
|
||||
limits::provide(providers);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ impl EffectiveVisibility {
|
|||
self.at_level(level).is_public()
|
||||
}
|
||||
|
||||
pub fn from_vis(vis: Visibility) -> EffectiveVisibility {
|
||||
pub const fn from_vis(vis: Visibility) -> EffectiveVisibility {
|
||||
EffectiveVisibility {
|
||||
direct: vis,
|
||||
reexported: vis,
|
||||
|
|
@ -72,6 +72,18 @@ impl EffectiveVisibility {
|
|||
reachable_through_impl_trait: vis,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn min(mut self, lhs: EffectiveVisibility, tcx: TyCtxt<'_>) -> Self {
|
||||
for l in Level::all_levels() {
|
||||
let rhs_vis = self.at_level_mut(l);
|
||||
let lhs_vis = *lhs.at_level(l);
|
||||
if rhs_vis.is_at_least(lhs_vis, tcx) {
|
||||
*rhs_vis = lhs_vis;
|
||||
};
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Holds a map of effective visibilities for reachable HIR nodes.
|
||||
|
|
@ -137,24 +149,6 @@ impl EffectiveVisibilities {
|
|||
};
|
||||
}
|
||||
|
||||
pub fn set_public_at_level(
|
||||
&mut self,
|
||||
id: LocalDefId,
|
||||
lazy_private_vis: impl FnOnce() -> Visibility,
|
||||
level: Level,
|
||||
) {
|
||||
let mut effective_vis = self
|
||||
.effective_vis(id)
|
||||
.copied()
|
||||
.unwrap_or_else(|| EffectiveVisibility::from_vis(lazy_private_vis()));
|
||||
for l in Level::all_levels() {
|
||||
if l <= level {
|
||||
*effective_vis.at_level_mut(l) = Visibility::Public;
|
||||
}
|
||||
}
|
||||
self.map.insert(id, effective_vis);
|
||||
}
|
||||
|
||||
pub fn check_invariants(&self, tcx: TyCtxt<'_>, early: bool) {
|
||||
if !cfg!(debug_assertions) {
|
||||
return;
|
||||
|
|
@ -219,7 +213,7 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
|
|||
pub fn update(
|
||||
&mut self,
|
||||
id: Id,
|
||||
nominal_vis: Visibility,
|
||||
nominal_vis: Option<Visibility>,
|
||||
lazy_private_vis: impl FnOnce() -> Visibility,
|
||||
inherited_effective_vis: EffectiveVisibility,
|
||||
level: Level,
|
||||
|
|
@ -243,12 +237,11 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
|
|||
if !(inherited_effective_vis_at_prev_level == inherited_effective_vis_at_level
|
||||
&& level != l)
|
||||
{
|
||||
calculated_effective_vis =
|
||||
if nominal_vis.is_at_least(inherited_effective_vis_at_level, tcx) {
|
||||
inherited_effective_vis_at_level
|
||||
} else {
|
||||
nominal_vis
|
||||
};
|
||||
calculated_effective_vis = if let Some(nominal_vis) = nominal_vis && !nominal_vis.is_at_least(inherited_effective_vis_at_level, tcx) {
|
||||
nominal_vis
|
||||
} else {
|
||||
inherited_effective_vis_at_level
|
||||
}
|
||||
}
|
||||
// effective visibility can't be decreased at next update call for the
|
||||
// same id
|
||||
|
|
|
|||
|
|
@ -1111,6 +1111,10 @@ pub struct VarDebugInfo<'tcx> {
|
|||
/// originated from (starting from 1). Note, if MIR inlining is enabled, then this is the
|
||||
/// argument number in the original function before it was inlined.
|
||||
pub argument_index: Option<u16>,
|
||||
|
||||
/// The data represents `name` dereferenced `references` times,
|
||||
/// and not the direct value.
|
||||
pub references: u8,
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -1550,8 +1554,11 @@ impl<V, T> ProjectionElem<V, T> {
|
|||
/// Returns `true` if this is accepted inside `VarDebugInfoContents::Place`.
|
||||
pub fn can_use_in_debuginfo(&self) -> bool {
|
||||
match self {
|
||||
Self::Deref | Self::Downcast(_, _) | Self::Field(_, _) => true,
|
||||
Self::ConstantIndex { .. }
|
||||
Self::ConstantIndex { from_end: false, .. }
|
||||
| Self::Deref
|
||||
| Self::Downcast(_, _)
|
||||
| Self::Field(_, _) => true,
|
||||
Self::ConstantIndex { from_end: true, .. }
|
||||
| Self::Index(_)
|
||||
| Self::OpaqueCast(_)
|
||||
| Self::Subslice { .. } => false,
|
||||
|
|
@ -1639,18 +1646,7 @@ impl<'tcx> Place<'tcx> {
|
|||
return self;
|
||||
}
|
||||
|
||||
let mut v: Vec<PlaceElem<'tcx>>;
|
||||
|
||||
let new_projections = if self.projection.is_empty() {
|
||||
more_projections
|
||||
} else {
|
||||
v = Vec::with_capacity(self.projection.len() + more_projections.len());
|
||||
v.extend(self.projection);
|
||||
v.extend(more_projections);
|
||||
&v
|
||||
};
|
||||
|
||||
Place { local: self.local, projection: tcx.mk_place_elems(new_projections) }
|
||||
self.as_ref().project_deeper(more_projections, tcx)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1721,6 +1717,27 @@ impl<'tcx> PlaceRef<'tcx> {
|
|||
(base, *proj)
|
||||
})
|
||||
}
|
||||
|
||||
/// Generates a new place by appending `more_projections` to the existing ones
|
||||
/// and interning the result.
|
||||
pub fn project_deeper(
|
||||
self,
|
||||
more_projections: &[PlaceElem<'tcx>],
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> Place<'tcx> {
|
||||
let mut v: Vec<PlaceElem<'tcx>>;
|
||||
|
||||
let new_projections = if self.projection.is_empty() {
|
||||
more_projections
|
||||
} else {
|
||||
v = Vec::with_capacity(self.projection.len() + more_projections.len());
|
||||
v.extend(self.projection);
|
||||
v.extend(more_projections);
|
||||
&v
|
||||
};
|
||||
|
||||
Place { local: self.local, projection: tcx.mk_place_elems(new_projections) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Place<'_> {
|
||||
|
|
@ -2313,7 +2330,7 @@ impl<'tcx> ConstantKind<'tcx> {
|
|||
if let Some(val) = c.kind().try_eval_for_mir(tcx, param_env) {
|
||||
match val {
|
||||
Ok(val) => Self::Val(val, c.ty()),
|
||||
Err(_) => Self::Ty(tcx.const_error(self.ty())),
|
||||
Err(guar) => Self::Ty(tcx.const_error(self.ty(), guar)),
|
||||
}
|
||||
} else {
|
||||
self
|
||||
|
|
@ -2325,9 +2342,7 @@ impl<'tcx> ConstantKind<'tcx> {
|
|||
match tcx.const_eval_resolve(param_env, uneval, None) {
|
||||
Ok(val) => Self::Val(val, ty),
|
||||
Err(ErrorHandled::TooGeneric) => self,
|
||||
Err(ErrorHandled::Reported(guar)) => {
|
||||
Self::Ty(tcx.const_error_with_guaranteed(ty, guar))
|
||||
}
|
||||
Err(ErrorHandled::Reported(guar)) => Self::Ty(tcx.const_error(ty, guar)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -551,8 +551,13 @@ fn write_scope_tree(
|
|||
}
|
||||
|
||||
let indented_debug_info = format!(
|
||||
"{0:1$}debug {2} => {3:?};",
|
||||
INDENT, indent, var_debug_info.name, var_debug_info.value,
|
||||
"{0:1$}debug {2} => {3:&<4$}{5:?};",
|
||||
INDENT,
|
||||
indent,
|
||||
var_debug_info.name,
|
||||
"",
|
||||
var_debug_info.references as usize,
|
||||
var_debug_info.value,
|
||||
);
|
||||
|
||||
writeln!(
|
||||
|
|
|
|||
|
|
@ -842,6 +842,7 @@ macro_rules! make_mir_visitor {
|
|||
source_info,
|
||||
value,
|
||||
argument_index: _,
|
||||
references: _,
|
||||
} = var_debug_info;
|
||||
|
||||
self.visit_source_info(source_info);
|
||||
|
|
|
|||
|
|
@ -4,8 +4,89 @@
|
|||
//! ["Queries: demand-driven compilation"](https://rustc-dev-guide.rust-lang.org/query.html).
|
||||
//! This chapter includes instructions for adding new queries.
|
||||
|
||||
use crate::ty::{self, print::describe_as_module, TyCtxt};
|
||||
#![allow(unused_parens)]
|
||||
|
||||
use crate::dep_graph;
|
||||
use crate::dep_graph::DepKind;
|
||||
use crate::infer::canonical::{self, Canonical};
|
||||
use crate::lint::LintExpectation;
|
||||
use crate::metadata::ModChild;
|
||||
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||
use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
|
||||
use crate::middle::lib_features::LibFeatures;
|
||||
use crate::middle::privacy::EffectiveVisibilities;
|
||||
use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg};
|
||||
use crate::middle::stability::{self, DeprecationEntry};
|
||||
use crate::mir;
|
||||
use crate::mir::interpret::GlobalId;
|
||||
use crate::mir::interpret::{
|
||||
ConstValue, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult,
|
||||
};
|
||||
use crate::mir::interpret::{LitToConstError, LitToConstInput};
|
||||
use crate::mir::mono::CodegenUnit;
|
||||
use crate::query::erase::{erase, restore, Erase};
|
||||
use crate::thir;
|
||||
use crate::traits::query::{
|
||||
CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
|
||||
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
|
||||
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, NoSolution,
|
||||
};
|
||||
use crate::traits::query::{
|
||||
DropckConstraint, DropckOutlivesResult, MethodAutoderefStepsResult, NormalizationResult,
|
||||
OutlivesBound,
|
||||
};
|
||||
use crate::traits::specialization_graph;
|
||||
use crate::traits::{self, ImplSource};
|
||||
use crate::ty::fast_reject::SimplifiedType;
|
||||
use crate::ty::layout::ValidityRequirement;
|
||||
use crate::ty::query::{
|
||||
query_ensure, query_get_at, DynamicQuery, IntoQueryParam, TyCtxtAt, TyCtxtEnsure,
|
||||
TyCtxtEnsureWithValue,
|
||||
};
|
||||
use crate::ty::subst::{GenericArg, SubstsRef};
|
||||
use crate::ty::util::AlwaysRequiresDrop;
|
||||
use crate::ty::GeneratorDiagnosticData;
|
||||
use crate::ty::TyCtxtFeed;
|
||||
use crate::ty::{
|
||||
self, print::describe_as_module, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt,
|
||||
UnusedGenericParams,
|
||||
};
|
||||
use rustc_arena::TypedArena;
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::expand::allocator::AllocatorKind;
|
||||
use rustc_attr as attr;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::steal::Steal;
|
||||
use rustc_data_structures::svh::Svh;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::sync::WorkerLocal;
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, DocLinkResMap};
|
||||
use rustc_hir::def_id::{
|
||||
CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LocalDefIdMap, LocalDefIdSet,
|
||||
};
|
||||
use rustc_hir::lang_items::{LangItem, LanguageItems};
|
||||
use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
use rustc_query_system::query::{try_get_cached, CacheSelector, QueryCache, QueryMode, QueryState};
|
||||
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
|
||||
use rustc_session::cstore::{CrateDepKind, CrateSource};
|
||||
use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
|
||||
use rustc_session::lint::LintExpectationId;
|
||||
use rustc_session::Limits;
|
||||
use rustc_span::def_id::LOCAL_CRATE;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::abi;
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub mod erase;
|
||||
mod keys;
|
||||
|
|
@ -2102,3 +2183,6 @@ rustc_queries! {
|
|||
desc { "check whether two const param are definitely not equal to eachother"}
|
||||
}
|
||||
}
|
||||
|
||||
rustc_query_append! { define_callbacks! }
|
||||
rustc_feedable_queries! { define_feedable! }
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
|
|||
|
||||
(&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(self.tcx().ty_error(guar)),
|
||||
|
||||
_ => relate::super_relate_tys(self, a, b),
|
||||
_ => relate::structurally_relate_tys(self, a, b),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -109,7 +109,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
|
|||
_ => {}
|
||||
}
|
||||
|
||||
relate::super_relate_consts(self, a, b)
|
||||
relate::structurally_relate_consts(self, a, b)
|
||||
}
|
||||
|
||||
fn binders<T>(
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> {
|
||||
let ct = match c.kind() {
|
||||
ty::ConstKind::Unevaluated(uv) => match self.tcx.thir_abstract_const(uv.def) {
|
||||
Err(e) => self.tcx.const_error_with_guaranteed(c.ty(), e),
|
||||
Err(e) => self.tcx.const_error(c.ty(), e),
|
||||
Ok(Some(bac)) => {
|
||||
let substs = self.tcx.erase_regions(uv.substs);
|
||||
let bac = bac.subst(self.tcx, substs);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use crate::{mir, ty};
|
|||
|
||||
use std::fmt::Write;
|
||||
|
||||
use crate::query::Providers;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::{self as hir, LangItem};
|
||||
|
|
@ -457,6 +458,6 @@ impl BorrowKind {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut ty::query::Providers) {
|
||||
*providers = ty::query::Providers { closure_typeinfo, ..*providers }
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
*providers = Providers { closure_typeinfo, ..*providers }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,9 +142,7 @@ impl<'tcx> Const<'tcx> {
|
|||
ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)),
|
||||
param_ty,
|
||||
)),
|
||||
Some(rbv::ResolvedArg::Error(guar)) => {
|
||||
Some(tcx.const_error_with_guaranteed(param_ty, guar))
|
||||
}
|
||||
Some(rbv::ResolvedArg::Error(guar)) => Some(tcx.const_error(param_ty, guar)),
|
||||
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
|
||||
}
|
||||
}
|
||||
|
|
@ -228,7 +226,7 @@ impl<'tcx> Const<'tcx> {
|
|||
if let Some(val) = self.kind().try_eval_for_typeck(tcx, param_env) {
|
||||
match val {
|
||||
Ok(val) => tcx.mk_const(val, self.ty()),
|
||||
Err(guar) => tcx.const_error_with_guaranteed(self.ty(), guar),
|
||||
Err(guar) => tcx.const_error(self.ty(), guar),
|
||||
}
|
||||
} else {
|
||||
// Either the constant isn't evaluatable or ValTree creation failed.
|
||||
|
|
|
|||
|
|
@ -14,14 +14,13 @@ use crate::middle::resolve_bound_vars;
|
|||
use crate::middle::stability;
|
||||
use crate::mir::interpret::{self, Allocation, ConstAllocation};
|
||||
use crate::mir::{Body, Local, Place, PlaceElem, ProjectionKind, Promoted};
|
||||
use crate::query::on_disk_cache::OnDiskCache;
|
||||
use crate::query::LocalCrate;
|
||||
use crate::query::Providers;
|
||||
use crate::thir::Thir;
|
||||
use crate::traits;
|
||||
use crate::traits::solve;
|
||||
use crate::traits::solve::{ExternalConstraints, ExternalConstraintsData};
|
||||
use crate::ty::query::QuerySystem;
|
||||
use crate::ty::query::QuerySystemFns;
|
||||
use crate::ty::query::{self, TyCtxtAt};
|
||||
use crate::ty::{
|
||||
self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, FloatTy, FloatVar, FloatVid,
|
||||
|
|
@ -496,7 +495,7 @@ pub struct GlobalCtxt<'tcx> {
|
|||
///
|
||||
/// FIXME(Centril): consider `dyn LintStoreMarker` once
|
||||
/// we can upcast to `Any` for some additional type safety.
|
||||
pub lint_store: Lrc<dyn Any + sync::Sync + sync::Send>,
|
||||
pub lint_store: Lrc<dyn Any + sync::DynSync + sync::DynSend>,
|
||||
|
||||
pub dep_graph: DepGraph,
|
||||
|
||||
|
|
@ -648,14 +647,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// reference to the context, to allow formatting values that need it.
|
||||
pub fn create_global_ctxt(
|
||||
s: &'tcx Session,
|
||||
lint_store: Lrc<dyn Any + sync::Send + sync::Sync>,
|
||||
lint_store: Lrc<dyn Any + sync::DynSend + sync::DynSync>,
|
||||
arena: &'tcx WorkerLocal<Arena<'tcx>>,
|
||||
hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
|
||||
untracked: Untracked,
|
||||
dep_graph: DepGraph,
|
||||
on_disk_cache: Option<OnDiskCache<'tcx>>,
|
||||
query_kinds: &'tcx [DepKindStruct<'tcx>],
|
||||
query_system_fns: QuerySystemFns<'tcx>,
|
||||
query_system: QuerySystem<'tcx>,
|
||||
) -> GlobalCtxt<'tcx> {
|
||||
let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
|
||||
s.emit_fatal(err);
|
||||
|
|
@ -677,7 +675,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
lifetimes: common_lifetimes,
|
||||
consts: common_consts,
|
||||
untracked,
|
||||
query_system: QuerySystem::new(query_system_fns, on_disk_cache),
|
||||
query_system,
|
||||
query_kinds,
|
||||
ty_rcache: Default::default(),
|
||||
pred_rcache: Default::default(),
|
||||
|
|
@ -735,17 +733,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
|
||||
/// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed`
|
||||
#[track_caller]
|
||||
pub fn const_error_with_guaranteed(
|
||||
self,
|
||||
ty: Ty<'tcx>,
|
||||
reported: ErrorGuaranteed,
|
||||
) -> Const<'tcx> {
|
||||
pub fn const_error(self, ty: Ty<'tcx>, reported: ErrorGuaranteed) -> Const<'tcx> {
|
||||
self.mk_const(ty::ConstKind::Error(reported), ty)
|
||||
}
|
||||
|
||||
/// Like [TyCtxt::ty_error] but for constants.
|
||||
#[track_caller]
|
||||
pub fn const_error(self, ty: Ty<'tcx>) -> Const<'tcx> {
|
||||
pub fn const_error_misc(self, ty: Ty<'tcx>) -> Const<'tcx> {
|
||||
self.const_error_with_message(
|
||||
ty,
|
||||
DUMMY_SP,
|
||||
|
|
@ -2461,7 +2455,7 @@ pub struct DeducedParamAttrs {
|
|||
pub read_only: bool,
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut ty::query::Providers) {
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
providers.maybe_unused_trait_imports =
|
||||
|tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports;
|
||||
providers.names_imported_by_glob_use = |tcx, id| {
|
||||
|
|
|
|||
|
|
@ -94,8 +94,8 @@ where
|
|||
f(None)
|
||||
} else {
|
||||
// We could get an `ImplicitCtxt` pointer from another thread.
|
||||
// Ensure that `ImplicitCtxt` is `Sync`.
|
||||
sync::assert_sync::<ImplicitCtxt<'_, '_>>();
|
||||
// Ensure that `ImplicitCtxt` is `DynSync`.
|
||||
sync::assert_dyn_sync::<ImplicitCtxt<'_, '_>>();
|
||||
|
||||
unsafe { f(Some(downcast(context))) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use crate::query::Providers;
|
||||
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
||||
use crate::ty::{self, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
|
||||
|
||||
pub(super) fn provide(providers: &mut ty::query::Providers) {
|
||||
*providers = ty::query::Providers { erase_regions_ty, ..*providers };
|
||||
pub(super) fn provide(providers: &mut Providers) {
|
||||
*providers = Providers { erase_regions_ty, ..*providers };
|
||||
}
|
||||
|
||||
fn erase_regions_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ impl GenericParamDef {
|
|||
ty::GenericParamDefKind::Lifetime => tcx.mk_re_error_misc().into(),
|
||||
ty::GenericParamDefKind::Type { .. } => tcx.ty_error_misc().into(),
|
||||
ty::GenericParamDefKind::Const { .. } => {
|
||||
tcx.const_error(tcx.type_of(self.def_id).subst(tcx, preceding_substs)).into()
|
||||
tcx.const_error_misc(tcx.type_of(self.def_id).subst(tcx, preceding_substs)).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
//! This code should only compile in modules where the uninhabitedness of `Foo`
|
||||
//! is visible.
|
||||
|
||||
use crate::query::Providers;
|
||||
use crate::ty::context::TyCtxt;
|
||||
use crate::ty::{self, DefId, Ty, VariantDef, Visibility};
|
||||
|
||||
|
|
@ -52,9 +53,8 @@ pub mod inhabited_predicate;
|
|||
|
||||
pub use inhabited_predicate::InhabitedPredicate;
|
||||
|
||||
pub(crate) fn provide(providers: &mut ty::query::Providers) {
|
||||
*providers =
|
||||
ty::query::Providers { inhabited_predicate_adt, inhabited_predicate_type, ..*providers };
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
*providers = Providers { inhabited_predicate_adt, inhabited_predicate_type, ..*providers };
|
||||
}
|
||||
|
||||
/// Returns an `InhabitedPredicate` that is generic over type parameters and
|
||||
|
|
|
|||
|
|
@ -199,6 +199,12 @@ impl<'a, T: Copy> IntoIterator for &'a List<T> {
|
|||
|
||||
unsafe impl<T: Sync> Sync for List<T> {}
|
||||
|
||||
// We need this since `List` uses extern type `OpaqueListContents`.
|
||||
#[cfg(parallel_compiler)]
|
||||
use rustc_data_structures::sync::DynSync;
|
||||
#[cfg(parallel_compiler)]
|
||||
unsafe impl<T: DynSync> DynSync for List<T> {}
|
||||
|
||||
// Safety:
|
||||
// Layouts of `Equivalent<T>` and `List<T>` are the same, modulo opaque tail,
|
||||
// thus aligns of `Equivalent<T>` and `List<T>` must be the same.
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason};
|
|||
use crate::metadata::ModChild;
|
||||
use crate::middle::privacy::EffectiveVisibilities;
|
||||
use crate::mir::{Body, GeneratorLayout};
|
||||
use crate::query::Providers;
|
||||
use crate::traits::{self, Reveal};
|
||||
use crate::ty;
|
||||
use crate::ty::fast_reject::SimplifiedType;
|
||||
|
|
@ -121,6 +122,7 @@ pub mod inhabitedness;
|
|||
pub mod layout;
|
||||
pub mod normalize_erasing_regions;
|
||||
pub mod print;
|
||||
#[macro_use]
|
||||
pub mod query;
|
||||
pub mod relate;
|
||||
pub mod subst;
|
||||
|
|
@ -1070,6 +1072,24 @@ impl ParamTerm {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
pub enum TermVid<'tcx> {
|
||||
Ty(ty::TyVid),
|
||||
Const(ty::ConstVid<'tcx>),
|
||||
}
|
||||
|
||||
impl From<ty::TyVid> for TermVid<'_> {
|
||||
fn from(value: ty::TyVid) -> Self {
|
||||
TermVid::Ty(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> From<ty::ConstVid<'tcx>> for TermVid<'tcx> {
|
||||
fn from(value: ty::ConstVid<'tcx>) -> Self {
|
||||
TermVid::Const(value)
|
||||
}
|
||||
}
|
||||
|
||||
/// This kind of predicate has no *direct* correspondent in the
|
||||
/// syntax, but it roughly corresponds to the syntactic forms:
|
||||
///
|
||||
|
|
@ -2590,7 +2610,7 @@ pub fn ast_uint_ty(uty: UintTy) -> ast::UintTy {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut ty::query::Providers) {
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
closure::provide(providers);
|
||||
context::provide(providers);
|
||||
erase_regions::provide(providers);
|
||||
|
|
@ -2599,7 +2619,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
|
|||
print::provide(providers);
|
||||
super::util::bug::provide(providers);
|
||||
super::middle::provide(providers);
|
||||
*providers = ty::query::Providers {
|
||||
*providers = Providers {
|
||||
trait_impls_of: trait_def::trait_impls_of_provider,
|
||||
incoherent_impls: trait_def::incoherent_impls_provider,
|
||||
const_param_default: consts::const_param_default,
|
||||
|
|
|
|||
|
|
@ -207,14 +207,16 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
|
|||
Some(GenericArgKind::Const(c1)) => c1,
|
||||
Some(u) => panic!("const mapped to unexpected kind: {:?}", u),
|
||||
None => {
|
||||
if !self.ignore_errors {
|
||||
self.tcx.sess.emit_err(ConstNotUsedTraitAlias {
|
||||
let guar = self
|
||||
.tcx
|
||||
.sess
|
||||
.create_err(ConstNotUsedTraitAlias {
|
||||
ct: ct.to_string(),
|
||||
span: self.span,
|
||||
});
|
||||
}
|
||||
})
|
||||
.emit_unless(self.ignore_errors);
|
||||
|
||||
self.interner().const_error(ct.ty())
|
||||
self.interner().const_error(ct.ty(), guar)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
|
||||
use crate::query::Providers;
|
||||
use crate::ty::query::IntoQueryParam;
|
||||
use crate::ty::{
|
||||
self, ConstInt, ParamConst, ScalarInt, Term, TermKind, Ty, TyCtxt, TypeFoldable,
|
||||
|
|
@ -3054,8 +3055,8 @@ fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> {
|
|||
map
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut ty::query::Providers) {
|
||||
*providers = ty::query::Providers { trimmed_def_paths, ..*providers };
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
*providers = Providers { trimmed_def_paths, ..*providers };
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
|
|||
|
|
@ -1,89 +1,26 @@
|
|||
#![allow(unused_parens)]
|
||||
|
||||
use crate::dep_graph;
|
||||
use crate::dep_graph::DepKind;
|
||||
use crate::infer::canonical::{self, Canonical};
|
||||
use crate::lint::LintExpectation;
|
||||
use crate::metadata::ModChild;
|
||||
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||
use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
|
||||
use crate::middle::lib_features::LibFeatures;
|
||||
use crate::middle::privacy::EffectiveVisibilities;
|
||||
use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg};
|
||||
use crate::middle::stability::{self, DeprecationEntry};
|
||||
use crate::mir;
|
||||
use crate::mir::interpret::GlobalId;
|
||||
use crate::mir::interpret::{
|
||||
ConstValue, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult,
|
||||
};
|
||||
use crate::mir::interpret::{LitToConstError, LitToConstInput};
|
||||
use crate::mir::mono::CodegenUnit;
|
||||
|
||||
use crate::query::erase::{erase, restore, Erase};
|
||||
use crate::query::on_disk_cache::CacheEncoder;
|
||||
use crate::query::on_disk_cache::EncodedDepNodeIndex;
|
||||
use crate::query::on_disk_cache::OnDiskCache;
|
||||
use crate::query::{AsLocalKey, Key};
|
||||
use crate::thir;
|
||||
use crate::traits::query::{
|
||||
CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
|
||||
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
|
||||
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, NoSolution,
|
||||
use crate::query::{
|
||||
DynamicQueries, ExternProviders, Providers, QueryArenas, QueryCaches, QueryEngine, QueryStates,
|
||||
};
|
||||
use crate::traits::query::{
|
||||
DropckConstraint, DropckOutlivesResult, MethodAutoderefStepsResult, NormalizationResult,
|
||||
OutlivesBound,
|
||||
};
|
||||
use crate::traits::specialization_graph;
|
||||
use crate::traits::{self, ImplSource};
|
||||
use crate::ty::context::TyCtxtFeed;
|
||||
use crate::ty::fast_reject::SimplifiedType;
|
||||
use crate::ty::layout::ValidityRequirement;
|
||||
use crate::ty::subst::{GenericArg, SubstsRef};
|
||||
use crate::ty::util::AlwaysRequiresDrop;
|
||||
use crate::ty::GeneratorDiagnosticData;
|
||||
use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt, UnusedGenericParams};
|
||||
use crate::ty::TyCtxt;
|
||||
use field_offset::FieldOffset;
|
||||
use measureme::StringId;
|
||||
use rustc_arena::TypedArena;
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::expand::allocator::AllocatorKind;
|
||||
use rustc_attr as attr;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::steal::Steal;
|
||||
use rustc_data_structures::svh::Svh;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sync::AtomicU64;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::sync::WorkerLocal;
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, DocLinkResMap};
|
||||
use rustc_hir::def_id::{
|
||||
CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LocalDefIdMap, LocalDefIdSet,
|
||||
};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::hir_id::OwnerId;
|
||||
use rustc_hir::lang_items::{LangItem, LanguageItems};
|
||||
use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
use rustc_query_system::dep_graph::DepNodeIndex;
|
||||
use rustc_query_system::dep_graph::SerializedDepNodeIndex;
|
||||
pub(crate) use rustc_query_system::query::QueryJobId;
|
||||
use rustc_query_system::query::*;
|
||||
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
|
||||
use rustc_session::cstore::{CrateDepKind, CrateSource};
|
||||
use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
|
||||
use rustc_session::lint::LintExpectationId;
|
||||
use rustc_session::Limits;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_query_system::HandleCycleError;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::abi;
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct QueryKeyStringCache {
|
||||
pub def_id_cache: FxHashMap<DefId, StringId>,
|
||||
|
|
@ -103,6 +40,31 @@ pub struct QueryStruct<'tcx> {
|
|||
Option<fn(TyCtxt<'tcx>, &mut CacheEncoder<'_, 'tcx>, &mut EncodedDepNodeIndex)>,
|
||||
}
|
||||
|
||||
pub struct DynamicQuery<'tcx, C: QueryCache> {
|
||||
pub name: &'static str,
|
||||
pub eval_always: bool,
|
||||
pub dep_kind: rustc_middle::dep_graph::DepKind,
|
||||
pub handle_cycle_error: HandleCycleError,
|
||||
pub query_state: FieldOffset<QueryStates<'tcx>, QueryState<C::Key, crate::dep_graph::DepKind>>,
|
||||
pub query_cache: FieldOffset<QueryCaches<'tcx>, C>,
|
||||
pub cache_on_disk: fn(tcx: TyCtxt<'tcx>, key: &C::Key) -> bool,
|
||||
pub execute_query: fn(tcx: TyCtxt<'tcx>, k: C::Key) -> C::Value,
|
||||
pub compute: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value,
|
||||
pub can_load_from_disk: bool,
|
||||
pub try_load_from_disk: fn(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
key: &C::Key,
|
||||
prev_index: SerializedDepNodeIndex,
|
||||
index: DepNodeIndex,
|
||||
) -> Option<C::Value>,
|
||||
pub loadable_from_disk:
|
||||
fn(tcx: TyCtxt<'tcx>, key: &C::Key, index: SerializedDepNodeIndex) -> bool,
|
||||
pub hash_result: HashResult<C::Value>,
|
||||
pub value_from_cycle_error:
|
||||
fn(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo<crate::dep_graph::DepKind>]) -> C::Value,
|
||||
pub format_value: fn(&C::Value) -> String,
|
||||
}
|
||||
|
||||
pub struct QuerySystemFns<'tcx> {
|
||||
pub engine: QueryEngine,
|
||||
pub local_providers: Providers,
|
||||
|
|
@ -120,6 +82,7 @@ pub struct QuerySystem<'tcx> {
|
|||
pub states: QueryStates<'tcx>,
|
||||
pub arenas: QueryArenas<'tcx>,
|
||||
pub caches: QueryCaches<'tcx>,
|
||||
pub dynamic_queries: DynamicQueries<'tcx>,
|
||||
|
||||
/// This provides access to the incremental compilation on-disk cache for query results.
|
||||
/// Do not access this directly. It is only meant to be used by
|
||||
|
|
@ -130,23 +93,6 @@ pub struct QuerySystem<'tcx> {
|
|||
pub fns: QuerySystemFns<'tcx>,
|
||||
|
||||
pub jobs: AtomicU64,
|
||||
|
||||
// Since we erase query value types we tell the typesystem about them with `PhantomData`.
|
||||
_phantom_values: QueryPhantomValues<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> QuerySystem<'tcx> {
|
||||
pub fn new(fns: QuerySystemFns<'tcx>, on_disk_cache: Option<OnDiskCache<'tcx>>) -> Self {
|
||||
QuerySystem {
|
||||
states: Default::default(),
|
||||
arenas: Default::default(),
|
||||
caches: Default::default(),
|
||||
on_disk_cache,
|
||||
fns,
|
||||
jobs: AtomicU64::new(1),
|
||||
_phantom_values: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
|
|
@ -203,7 +149,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn query_get_at<'tcx, Cache>(
|
||||
pub fn query_get_at<'tcx, Cache>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
execute_query: fn(TyCtxt<'tcx>, Span, Cache::Key, QueryMode) -> Option<Cache::Value>,
|
||||
query_cache: &Cache,
|
||||
|
|
@ -221,7 +167,7 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn query_ensure<'tcx, Cache>(
|
||||
pub fn query_ensure<'tcx, Cache>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
execute_query: fn(TyCtxt<'tcx>, Span, Cache::Key, QueryMode) -> Option<Cache::Value>,
|
||||
query_cache: &Cache,
|
||||
|
|
@ -427,11 +373,6 @@ macro_rules! define_callbacks {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct QueryPhantomValues<'tcx> {
|
||||
$($(#[$attr])* pub $name: PhantomData<query_values::$name<'tcx>>,)*
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct QueryCaches<'tcx> {
|
||||
$($(#[$attr])* pub $name: query_storage::$name<'tcx>,)*
|
||||
|
|
@ -490,6 +431,12 @@ macro_rules! define_callbacks {
|
|||
})*
|
||||
}
|
||||
|
||||
pub struct DynamicQueries<'tcx> {
|
||||
$(
|
||||
pub $name: DynamicQuery<'tcx, query_storage::$name<'tcx>>,
|
||||
)*
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct QueryStates<'tcx> {
|
||||
$(
|
||||
|
|
@ -627,9 +574,6 @@ macro_rules! define_feedable {
|
|||
// Queries marked with `fatal_cycle` do not need the latter implementation,
|
||||
// as they will raise an fatal error on query cycles instead.
|
||||
|
||||
rustc_query_append! { define_callbacks! }
|
||||
rustc_feedable_queries! { define_feedable! }
|
||||
|
||||
mod sealed {
|
||||
use super::{DefId, LocalDefId, OwnerId};
|
||||
|
||||
|
|
|
|||
|
|
@ -388,24 +388,24 @@ impl<'tcx> Relate<'tcx> for Ty<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// The main "type relation" routine. Note that this does not handle
|
||||
/// inference artifacts, so you should filter those out before calling
|
||||
/// it.
|
||||
pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
|
||||
/// Relates `a` and `b` structurally, calling the relation for all nested values.
|
||||
/// Any semantic equality, e.g. of projections, and inference variables have to be
|
||||
/// handled by the caller.
|
||||
pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
a: Ty<'tcx>,
|
||||
b: Ty<'tcx>,
|
||||
) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
let tcx = relation.tcx();
|
||||
debug!("super_relate_tys: a={:?} b={:?}", a, b);
|
||||
debug!("structurally_relate_tys: a={:?} b={:?}", a, b);
|
||||
match (a.kind(), b.kind()) {
|
||||
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
|
||||
// The caller should handle these cases!
|
||||
bug!("var types encountered in super_relate_tys")
|
||||
bug!("var types encountered in structurally_relate_tys")
|
||||
}
|
||||
|
||||
(ty::Bound(..), _) | (_, ty::Bound(..)) => {
|
||||
bug!("bound types encountered in super_relate_tys")
|
||||
bug!("bound types encountered in structurally_relate_tys")
|
||||
}
|
||||
|
||||
(&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(tcx.ty_error(guar)),
|
||||
|
|
@ -575,15 +575,18 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
|
|||
}
|
||||
}
|
||||
|
||||
/// The main "const relation" routine. Note that this does not handle
|
||||
/// inference artifacts, so you should filter those out before calling
|
||||
/// it.
|
||||
pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
||||
/// Relates `a` and `b` structurally, calling the relation for all nested values.
|
||||
/// Any semantic equality, e.g. of unevaluated consts, and inference variables have
|
||||
/// to be handled by the caller.
|
||||
///
|
||||
/// FIXME: This is not totally structual, which probably should be fixed.
|
||||
/// See the HACKs below.
|
||||
pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
mut a: ty::Const<'tcx>,
|
||||
mut b: ty::Const<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::Const<'tcx>> {
|
||||
debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
|
||||
debug!("{}.structurally_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
|
||||
let tcx = relation.tcx();
|
||||
|
||||
// HACK(const_generics): We still need to eagerly evaluate consts when
|
||||
|
|
@ -602,7 +605,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
|||
b = tcx.expand_abstract_consts(b);
|
||||
}
|
||||
|
||||
debug!("{}.super_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b);
|
||||
debug!("{}.structurally_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b);
|
||||
|
||||
// Currently, the values that can be unified are primitive types,
|
||||
// and those that derive both `PartialEq` and `Eq`, corresponding
|
||||
|
|
@ -610,7 +613,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
|||
let is_match = match (a.kind(), b.kind()) {
|
||||
(ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
|
||||
// The caller should handle these cases!
|
||||
bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b)
|
||||
bug!("var types encountered in structurally_relate_consts: {:?} {:?}", a, b)
|
||||
}
|
||||
|
||||
(ty::ConstKind::Error(_), _) => return Ok(a),
|
||||
|
|
|
|||
|
|
@ -204,6 +204,7 @@ CloneLiftImpls! {
|
|||
(),
|
||||
bool,
|
||||
usize,
|
||||
u8,
|
||||
u16,
|
||||
u32,
|
||||
u64,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use crate::mir;
|
||||
use crate::query::Providers;
|
||||
use crate::ty::layout::IntegerExt;
|
||||
use crate::ty::{
|
||||
self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
||||
|
|
@ -1484,8 +1485,8 @@ pub fn is_intrinsic(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
|||
matches!(tcx.fn_sig(def_id).skip_binder().abi(), Abi::RustIntrinsic | Abi::PlatformIntrinsic)
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut ty::query::Providers) {
|
||||
*providers = ty::query::Providers {
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
*providers = Providers {
|
||||
reveal_opaque_types_in_bounds,
|
||||
is_doc_hidden,
|
||||
is_doc_notable_trait,
|
||||
|
|
|
|||
|
|
@ -48,6 +48,6 @@ pub fn trigger_delay_span_bug(tcx: TyCtxt<'_>, key: rustc_hir::def_id::DefId) {
|
|||
);
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut crate::ty::query::Providers) {
|
||||
*providers = crate::ty::query::Providers { trigger_delay_span_bug, ..*providers };
|
||||
pub fn provide(providers: &mut crate::query::Providers) {
|
||||
*providers = crate::query::Providers { trigger_delay_span_bug, ..*providers };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
|
|||
Ok(Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, offset))))
|
||||
},
|
||||
@call("mir_len", args) => Ok(Rvalue::Len(self.parse_place(args[0])?)),
|
||||
@call("mir_copy_for_deref", args) => Ok(Rvalue::CopyForDeref(self.parse_place(args[0])?)),
|
||||
ExprKind::Borrow { borrow_kind, arg } => Ok(
|
||||
Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
|
||||
),
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ pub fn as_constant_inner<'tcx>(
|
|||
match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) {
|
||||
Ok(c) => c,
|
||||
Err(LitToConstError::Reported(guar)) => {
|
||||
ConstantKind::Ty(tcx.const_error_with_guaranteed(ty, guar))
|
||||
ConstantKind::Ty(tcx.const_error(ty, guar))
|
||||
}
|
||||
Err(LitToConstError::TypeError) => {
|
||||
bug!("encountered type error in `lit_to_mir_constant`")
|
||||
|
|
|
|||
|
|
@ -2241,6 +2241,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
self.var_debug_info.push(VarDebugInfo {
|
||||
name,
|
||||
source_info: debug_source_info,
|
||||
references: 0,
|
||||
value: VarDebugInfoContents::Place(for_arm_body.into()),
|
||||
argument_index: None,
|
||||
});
|
||||
|
|
@ -2260,6 +2261,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
self.var_debug_info.push(VarDebugInfo {
|
||||
name,
|
||||
source_info: debug_source_info,
|
||||
references: 0,
|
||||
value: VarDebugInfoContents::Place(ref_for_guard.into()),
|
||||
argument_index: None,
|
||||
});
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue