mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-16 17:03:35 +00:00
Auto merge of #132349 - matthiaskrgr:rollup-9g6s4p2, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #129394 (Don't lint `irrefutable_let_patterns` on leading patterns if `else if` let-chains) - #131856 (TypingMode: merge intercrate, reveal, and defining_opaque_types) - #132322 (powerpc64-ibm-aix: update maintainters) - #132327 (Point to Fuchsia team in platform support docs) - #132332 (Use `token_descr` more in error messages) - #132338 (Remove `Engine`) - #132340 (cg_llvm: Consistently use safe wrapper function `set_section`) - #132342 (cg_llvm: Clean up FFI calls for operand bundles) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
8b9f0f9c1c
@ -34,7 +34,7 @@ use rustc_infer::infer::{
|
||||
use rustc_middle::mir::tcx::PlaceTy;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt};
|
||||
use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_mir_dataflow::Analysis;
|
||||
use rustc_mir_dataflow::impls::{
|
||||
@ -193,9 +193,7 @@ fn do_mir_borrowck<'tcx>(
|
||||
.map(|(idx, body)| (idx, MoveData::gather_moves(body, tcx, |_| true)));
|
||||
|
||||
let mut flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
|
||||
.into_engine(tcx, body)
|
||||
.pass_name("borrowck")
|
||||
.iterate_to_fixpoint()
|
||||
.iterate_to_fixpoint(tcx, body, Some("borrowck"))
|
||||
.into_results_cursor(body);
|
||||
|
||||
let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(def).is_fn_or_closure();
|
||||
@ -243,18 +241,21 @@ fn do_mir_borrowck<'tcx>(
|
||||
// usage significantly on some benchmarks.
|
||||
drop(flow_inits);
|
||||
|
||||
let flow_borrows = Borrows::new(tcx, body, ®ioncx, &borrow_set)
|
||||
.into_engine(tcx, body)
|
||||
.pass_name("borrowck")
|
||||
.iterate_to_fixpoint();
|
||||
let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data)
|
||||
.into_engine(tcx, body)
|
||||
.pass_name("borrowck")
|
||||
.iterate_to_fixpoint();
|
||||
let flow_ever_inits = EverInitializedPlaces::new(body, &move_data)
|
||||
.into_engine(tcx, body)
|
||||
.pass_name("borrowck")
|
||||
.iterate_to_fixpoint();
|
||||
let flow_borrows = Borrows::new(tcx, body, ®ioncx, &borrow_set).iterate_to_fixpoint(
|
||||
tcx,
|
||||
body,
|
||||
Some("borrowck"),
|
||||
);
|
||||
let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data).iterate_to_fixpoint(
|
||||
tcx,
|
||||
body,
|
||||
Some("borrowck"),
|
||||
);
|
||||
let flow_ever_inits = EverInitializedPlaces::new(body, &move_data).iterate_to_fixpoint(
|
||||
tcx,
|
||||
body,
|
||||
Some("borrowck"),
|
||||
);
|
||||
|
||||
let movable_coroutine =
|
||||
// The first argument is the coroutine type passed by value
|
||||
@ -440,7 +441,7 @@ pub struct BorrowckInferCtxt<'tcx> {
|
||||
|
||||
impl<'tcx> BorrowckInferCtxt<'tcx> {
|
||||
pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
|
||||
let infcx = tcx.infer_ctxt().with_opaque_type_inference(def_id).build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, def_id));
|
||||
BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()) }
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ use rustc_macros::extension;
|
||||
use rustc_middle::ty::visit::TypeVisitableExt;
|
||||
use rustc_middle::ty::{
|
||||
self, GenericArgKind, GenericArgs, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable,
|
||||
TypingMode,
|
||||
};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
@ -340,14 +341,13 @@ fn check_opaque_type_well_formed<'tcx>(
|
||||
parent_def_id = tcx.local_parent(parent_def_id);
|
||||
}
|
||||
|
||||
// FIXME(-Znext-solver): We probably should use `&[]` instead of
|
||||
// and prepopulate this `InferCtxt` with known opaque values, rather than
|
||||
// allowing opaque types to be defined and checking them after the fact.
|
||||
// FIXME(#132279): This should eventually use the already defined hidden types
|
||||
// instead. Alternatively we'll entirely remove this function given we also check
|
||||
// the opaque in `check_opaque_meets_bounds` later.
|
||||
let infcx = tcx
|
||||
.infer_ctxt()
|
||||
.with_next_trait_solver(next_trait_solver)
|
||||
.with_opaque_type_inference(parent_def_id)
|
||||
.build();
|
||||
.build(TypingMode::analysis_in_body(tcx, parent_def_id));
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
let identity_args = GenericArgs::identity_for_item(tcx, def_id);
|
||||
|
||||
@ -517,7 +517,9 @@ impl<'tcx> LazyOpaqueTyEnv<'tcx> {
|
||||
},
|
||||
);
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
// FIXME(#132279): It feels wrong to use `non_body_analysis` here given that we're
|
||||
// in a body here.
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
|
||||
let wf_tys = ocx.assumed_wf_types(param_env, parent).unwrap_or_else(|_| {
|
||||
|
@ -154,7 +154,7 @@ fn create_wrapper_function(
|
||||
.enumerate()
|
||||
.map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint))
|
||||
.collect::<Vec<_>>();
|
||||
let ret = llvm::LLVMRustBuildCall(
|
||||
let ret = llvm::LLVMBuildCallWithOperandBundles(
|
||||
llbuilder,
|
||||
ty,
|
||||
callee,
|
||||
@ -162,6 +162,7 @@ fn create_wrapper_function(
|
||||
args.len() as c_uint,
|
||||
[].as_ptr(),
|
||||
0 as c_uint,
|
||||
c"".as_ptr(),
|
||||
);
|
||||
llvm::LLVMSetTailCall(ret, True);
|
||||
if output.is_some() {
|
||||
|
@ -165,13 +165,14 @@ fn get_bitcode_slice_from_object_data<'a>(
|
||||
// We drop the "__LLVM," prefix here because on Apple platforms there's a notion of "segment
|
||||
// name" which in the public API for sections gets treated as part of the section name, but
|
||||
// internally in MachOObjectFile.cpp gets treated separately.
|
||||
let section_name = bitcode_section_name(cgcx).trim_start_matches("__LLVM,");
|
||||
let section_name = bitcode_section_name(cgcx).to_str().unwrap().trim_start_matches("__LLVM,");
|
||||
let mut len = 0;
|
||||
let data = unsafe {
|
||||
llvm::LLVMRustGetSliceFromObjectDataByName(
|
||||
obj.as_ptr(),
|
||||
obj.len(),
|
||||
section_name.as_ptr(),
|
||||
section_name.len(),
|
||||
&mut len,
|
||||
)
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::ffi::CString;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::io::{self, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
@ -958,14 +958,13 @@ fn target_is_aix(cgcx: &CodegenContext<LlvmCodegenBackend>) -> bool {
|
||||
cgcx.opts.target_triple.triple().contains("-aix")
|
||||
}
|
||||
|
||||
//FIXME use c string literals here too
|
||||
pub(crate) fn bitcode_section_name(cgcx: &CodegenContext<LlvmCodegenBackend>) -> &'static str {
|
||||
pub(crate) fn bitcode_section_name(cgcx: &CodegenContext<LlvmCodegenBackend>) -> &'static CStr {
|
||||
if target_is_apple(cgcx) {
|
||||
"__LLVM,__bitcode\0"
|
||||
c"__LLVM,__bitcode"
|
||||
} else if target_is_aix(cgcx) {
|
||||
".ipa\0"
|
||||
c".ipa"
|
||||
} else {
|
||||
".llvmbc\0"
|
||||
c".llvmbc"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1042,8 +1041,7 @@ unsafe fn embed_bitcode(
|
||||
);
|
||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||
|
||||
let section = bitcode_section_name(cgcx);
|
||||
llvm::LLVMSetSection(llglobal, section.as_c_char_ptr());
|
||||
llvm::set_section(llglobal, bitcode_section_name(cgcx));
|
||||
llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
|
||||
|
||||
@ -1061,7 +1059,7 @@ unsafe fn embed_bitcode(
|
||||
} else {
|
||||
c".llvmcmd"
|
||||
};
|
||||
llvm::LLVMSetSection(llglobal, section.as_ptr());
|
||||
llvm::set_section(llglobal, section);
|
||||
llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
} else {
|
||||
// We need custom section flags, so emit module-level inline assembly.
|
||||
|
@ -145,10 +145,8 @@ pub(crate) fn compile_codegen_unit(
|
||||
|
||||
pub(crate) fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) {
|
||||
let Some(sect) = attrs.link_section else { return };
|
||||
unsafe {
|
||||
let buf = SmallCStr::new(sect.as_str());
|
||||
llvm::LLVMSetSection(llval, buf.as_ptr());
|
||||
}
|
||||
let buf = SmallCStr::new(sect.as_str());
|
||||
llvm::set_section(llval, &buf);
|
||||
}
|
||||
|
||||
pub(crate) fn linkage_to_llvm(linkage: Linkage) -> llvm::Linkage {
|
||||
|
@ -239,7 +239,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||
|
||||
let args = self.check_call("invoke", llty, llfn, args);
|
||||
let funclet_bundle = funclet.map(|funclet| funclet.bundle());
|
||||
let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
|
||||
let mut bundles: SmallVec<[_; 2]> = SmallVec::new();
|
||||
if let Some(funclet_bundle) = funclet_bundle {
|
||||
bundles.push(funclet_bundle);
|
||||
@ -250,13 +249,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||
|
||||
// Emit KCFI operand bundle
|
||||
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn);
|
||||
let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
|
||||
if let Some(kcfi_bundle) = kcfi_bundle {
|
||||
if let Some(kcfi_bundle) = kcfi_bundle.as_deref() {
|
||||
bundles.push(kcfi_bundle);
|
||||
}
|
||||
|
||||
let invoke = unsafe {
|
||||
llvm::LLVMRustBuildInvoke(
|
||||
llvm::LLVMBuildInvokeWithOperandBundles(
|
||||
self.llbuilder,
|
||||
llty,
|
||||
llfn,
|
||||
@ -1179,7 +1177,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||
|
||||
let args = self.check_call("call", llty, llfn, args);
|
||||
let funclet_bundle = funclet.map(|funclet| funclet.bundle());
|
||||
let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
|
||||
let mut bundles: SmallVec<[_; 2]> = SmallVec::new();
|
||||
if let Some(funclet_bundle) = funclet_bundle {
|
||||
bundles.push(funclet_bundle);
|
||||
@ -1190,13 +1187,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||
|
||||
// Emit KCFI operand bundle
|
||||
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn);
|
||||
let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
|
||||
if let Some(kcfi_bundle) = kcfi_bundle {
|
||||
if let Some(kcfi_bundle) = kcfi_bundle.as_deref() {
|
||||
bundles.push(kcfi_bundle);
|
||||
}
|
||||
|
||||
let call = unsafe {
|
||||
llvm::LLVMRustBuildCall(
|
||||
llvm::LLVMBuildCallWithOperandBundles(
|
||||
self.llbuilder,
|
||||
llty,
|
||||
llfn,
|
||||
@ -1204,6 +1200,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||
args.len() as c_uint,
|
||||
bundles.as_ptr(),
|
||||
bundles.len() as c_uint,
|
||||
c"".as_ptr(),
|
||||
)
|
||||
};
|
||||
if let Some(fn_abi) = fn_abi {
|
||||
@ -1509,7 +1506,6 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
||||
|
||||
let args = self.check_call("callbr", llty, llfn, args);
|
||||
let funclet_bundle = funclet.map(|funclet| funclet.bundle());
|
||||
let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
|
||||
let mut bundles: SmallVec<[_; 2]> = SmallVec::new();
|
||||
if let Some(funclet_bundle) = funclet_bundle {
|
||||
bundles.push(funclet_bundle);
|
||||
@ -1520,13 +1516,12 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
||||
|
||||
// Emit KCFI operand bundle
|
||||
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn);
|
||||
let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
|
||||
if let Some(kcfi_bundle) = kcfi_bundle {
|
||||
if let Some(kcfi_bundle) = kcfi_bundle.as_deref() {
|
||||
bundles.push(kcfi_bundle);
|
||||
}
|
||||
|
||||
let callbr = unsafe {
|
||||
llvm::LLVMRustBuildCallBr(
|
||||
llvm::LLVMBuildCallBr(
|
||||
self.llbuilder,
|
||||
llty,
|
||||
llfn,
|
||||
@ -1601,7 +1596,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
||||
fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
|
||||
instance: Option<Instance<'tcx>>,
|
||||
llfn: &'ll Value,
|
||||
) -> Option<llvm::OperandBundleDef<'ll>> {
|
||||
) -> Option<llvm::OperandBundleOwned<'ll>> {
|
||||
let is_indirect_call = unsafe { llvm::LLVMRustIsNonGVFunctionPointerTy(llfn) };
|
||||
let kcfi_bundle = if self.tcx.sess.is_sanitizer_kcfi_enabled()
|
||||
&& let Some(fn_abi) = fn_abi
|
||||
@ -1627,7 +1622,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
||||
kcfi::typeid_for_fnabi(self.tcx, fn_abi, options)
|
||||
};
|
||||
|
||||
Some(llvm::OperandBundleDef::new("kcfi", &[self.const_u32(kcfi_typeid)]))
|
||||
Some(llvm::OperandBundleOwned::new("kcfi", &[self.const_u32(kcfi_typeid)]))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -17,7 +17,7 @@ use tracing::debug;
|
||||
|
||||
use crate::consts::const_alloc_to_llvm;
|
||||
pub(crate) use crate::context::CodegenCx;
|
||||
use crate::llvm::{self, BasicBlock, Bool, ConstantInt, False, Metadata, OperandBundleDef, True};
|
||||
use crate::llvm::{self, BasicBlock, Bool, ConstantInt, False, Metadata, True};
|
||||
use crate::type_::Type;
|
||||
use crate::value::Value;
|
||||
|
||||
@ -63,19 +63,19 @@ use crate::value::Value;
|
||||
/// the `OperandBundleDef` value created for MSVC landing pads.
|
||||
pub(crate) struct Funclet<'ll> {
|
||||
cleanuppad: &'ll Value,
|
||||
operand: OperandBundleDef<'ll>,
|
||||
operand: llvm::OperandBundleOwned<'ll>,
|
||||
}
|
||||
|
||||
impl<'ll> Funclet<'ll> {
|
||||
pub(crate) fn new(cleanuppad: &'ll Value) -> Self {
|
||||
Funclet { cleanuppad, operand: OperandBundleDef::new("funclet", &[cleanuppad]) }
|
||||
Funclet { cleanuppad, operand: llvm::OperandBundleOwned::new("funclet", &[cleanuppad]) }
|
||||
}
|
||||
|
||||
pub(crate) fn cleanuppad(&self) -> &'ll Value {
|
||||
self.cleanuppad
|
||||
}
|
||||
|
||||
pub(crate) fn bundle(&self) -> &OperandBundleDef<'ll> {
|
||||
pub(crate) fn bundle(&self) -> &llvm::OperandBundle<'ll> {
|
||||
&self.operand
|
||||
}
|
||||
}
|
||||
|
@ -565,7 +565,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
||||
let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr());
|
||||
llvm::LLVMSetInitializer(g, array);
|
||||
llvm::set_linkage(g, llvm::Linkage::AppendingLinkage);
|
||||
llvm::LLVMSetSection(g, c"llvm.metadata".as_ptr());
|
||||
llvm::set_section(g, c"llvm.metadata");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ pub(crate) fn get_or_insert_gdb_debug_scripts_section_global<'ll>(
|
||||
let section_var = cx
|
||||
.define_global(section_var_name, llvm_type)
|
||||
.unwrap_or_else(|| bug!("symbol `{}` is already defined", section_var_name));
|
||||
llvm::LLVMSetSection(section_var, c".debug_gdb_scripts".as_ptr());
|
||||
llvm::set_section(section_var, c".debug_gdb_scripts");
|
||||
llvm::LLVMSetInitializer(section_var, cx.const_bytes(section_contents));
|
||||
llvm::LLVMSetGlobalConstant(section_var, llvm::True);
|
||||
llvm::LLVMSetUnnamedAddress(section_var, llvm::UnnamedAddr::Global);
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PhantomData;
|
||||
use std::ptr;
|
||||
|
||||
use libc::{c_char, c_int, c_uint, c_ulonglong, c_void, size_t};
|
||||
use rustc_macros::TryFromU32;
|
||||
@ -708,8 +709,9 @@ unsafe extern "C" {
|
||||
}
|
||||
#[repr(C)]
|
||||
pub struct RustArchiveMember<'a>(InvariantOpaque<'a>);
|
||||
/// Opaque pointee of `LLVMOperandBundleRef`.
|
||||
#[repr(C)]
|
||||
pub struct OperandBundleDef<'a>(InvariantOpaque<'a>);
|
||||
pub(crate) struct OperandBundle<'a>(InvariantOpaque<'a>);
|
||||
#[repr(C)]
|
||||
pub struct Linker<'a>(InvariantOpaque<'a>);
|
||||
|
||||
@ -1538,6 +1540,50 @@ unsafe extern "C" {
|
||||
|
||||
pub fn LLVMGetOrInsertComdat(M: &Module, Name: *const c_char) -> &Comdat;
|
||||
pub fn LLVMSetComdat(V: &Value, C: &Comdat);
|
||||
|
||||
pub(crate) fn LLVMCreateOperandBundle(
|
||||
Tag: *const c_char,
|
||||
TagLen: size_t,
|
||||
Args: *const &'_ Value,
|
||||
NumArgs: c_uint,
|
||||
) -> *mut OperandBundle<'_>;
|
||||
pub(crate) fn LLVMDisposeOperandBundle(Bundle: ptr::NonNull<OperandBundle<'_>>);
|
||||
|
||||
pub(crate) fn LLVMBuildCallWithOperandBundles<'a>(
|
||||
B: &Builder<'a>,
|
||||
Ty: &'a Type,
|
||||
Fn: &'a Value,
|
||||
Args: *const &'a Value,
|
||||
NumArgs: c_uint,
|
||||
Bundles: *const &OperandBundle<'a>,
|
||||
NumBundles: c_uint,
|
||||
Name: *const c_char,
|
||||
) -> &'a Value;
|
||||
pub(crate) fn LLVMBuildInvokeWithOperandBundles<'a>(
|
||||
B: &Builder<'a>,
|
||||
Ty: &'a Type,
|
||||
Fn: &'a Value,
|
||||
Args: *const &'a Value,
|
||||
NumArgs: c_uint,
|
||||
Then: &'a BasicBlock,
|
||||
Catch: &'a BasicBlock,
|
||||
Bundles: *const &OperandBundle<'a>,
|
||||
NumBundles: c_uint,
|
||||
Name: *const c_char,
|
||||
) -> &'a Value;
|
||||
pub(crate) fn LLVMBuildCallBr<'a>(
|
||||
B: &Builder<'a>,
|
||||
Ty: &'a Type,
|
||||
Fn: &'a Value,
|
||||
DefaultDest: &'a BasicBlock,
|
||||
IndirectDests: *const &'a BasicBlock,
|
||||
NumIndirectDests: c_uint,
|
||||
Args: *const &'a Value,
|
||||
NumArgs: c_uint,
|
||||
Bundles: *const &OperandBundle<'a>,
|
||||
NumBundles: c_uint,
|
||||
Name: *const c_char,
|
||||
) -> &'a Value;
|
||||
}
|
||||
|
||||
#[link(name = "llvm-wrapper", kind = "static")]
|
||||
@ -1623,47 +1669,11 @@ unsafe extern "C" {
|
||||
AttrsLen: size_t,
|
||||
);
|
||||
|
||||
pub fn LLVMRustBuildInvoke<'a>(
|
||||
B: &Builder<'a>,
|
||||
Ty: &'a Type,
|
||||
Fn: &'a Value,
|
||||
Args: *const &'a Value,
|
||||
NumArgs: c_uint,
|
||||
Then: &'a BasicBlock,
|
||||
Catch: &'a BasicBlock,
|
||||
OpBundles: *const &OperandBundleDef<'a>,
|
||||
NumOpBundles: c_uint,
|
||||
Name: *const c_char,
|
||||
) -> &'a Value;
|
||||
|
||||
pub fn LLVMRustBuildCallBr<'a>(
|
||||
B: &Builder<'a>,
|
||||
Ty: &'a Type,
|
||||
Fn: &'a Value,
|
||||
DefaultDest: &'a BasicBlock,
|
||||
IndirectDests: *const &'a BasicBlock,
|
||||
NumIndirectDests: c_uint,
|
||||
Args: *const &'a Value,
|
||||
NumArgs: c_uint,
|
||||
OpBundles: *const &OperandBundleDef<'a>,
|
||||
NumOpBundles: c_uint,
|
||||
Name: *const c_char,
|
||||
) -> &'a Value;
|
||||
|
||||
pub fn LLVMRustSetFastMath(Instr: &Value);
|
||||
pub fn LLVMRustSetAlgebraicMath(Instr: &Value);
|
||||
pub fn LLVMRustSetAllowReassoc(Instr: &Value);
|
||||
|
||||
// Miscellaneous instructions
|
||||
pub fn LLVMRustBuildCall<'a>(
|
||||
B: &Builder<'a>,
|
||||
Ty: &'a Type,
|
||||
Fn: &'a Value,
|
||||
Args: *const &'a Value,
|
||||
NumArgs: c_uint,
|
||||
OpBundles: *const &OperandBundleDef<'a>,
|
||||
NumOpBundles: c_uint,
|
||||
) -> &'a Value;
|
||||
pub fn LLVMRustBuildMemCpy<'a>(
|
||||
B: &Builder<'a>,
|
||||
Dst: &'a Value,
|
||||
@ -2357,13 +2367,6 @@ unsafe extern "C" {
|
||||
|
||||
pub fn LLVMRustSetDataLayoutFromTargetMachine<'a>(M: &'a Module, TM: &'a TargetMachine);
|
||||
|
||||
pub fn LLVMRustBuildOperandBundleDef(
|
||||
Name: *const c_char,
|
||||
Inputs: *const &'_ Value,
|
||||
NumInputs: c_uint,
|
||||
) -> &mut OperandBundleDef<'_>;
|
||||
pub fn LLVMRustFreeOperandBundleDef<'a>(Bundle: &'a mut OperandBundleDef<'a>);
|
||||
|
||||
pub fn LLVMRustPositionBuilderAtStart<'a>(B: &Builder<'a>, BB: &'a BasicBlock);
|
||||
|
||||
pub fn LLVMRustSetModulePICLevel(M: &Module);
|
||||
@ -2416,6 +2419,7 @@ unsafe extern "C" {
|
||||
data: *const u8,
|
||||
len: usize,
|
||||
name: *const u8,
|
||||
name_len: usize,
|
||||
out_len: &mut usize,
|
||||
) -> *const u8;
|
||||
|
||||
|
@ -2,11 +2,12 @@
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::ops::Deref;
|
||||
use std::ptr;
|
||||
use std::str::FromStr;
|
||||
use std::string::FromUtf8Error;
|
||||
|
||||
use libc::c_uint;
|
||||
use rustc_data_structures::small_c_str::SmallCStr;
|
||||
use rustc_llvm::RustString;
|
||||
use rustc_target::abi::{Align, Size, WrappingRange};
|
||||
|
||||
@ -331,28 +332,43 @@ pub fn last_error() -> Option<String> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OperandBundleDef<'a> {
|
||||
pub raw: &'a mut ffi::OperandBundleDef<'a>,
|
||||
/// Owns an [`OperandBundle`], and will dispose of it when dropped.
|
||||
pub(crate) struct OperandBundleOwned<'a> {
|
||||
raw: ptr::NonNull<OperandBundle<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> OperandBundleDef<'a> {
|
||||
pub fn new(name: &str, vals: &[&'a Value]) -> Self {
|
||||
let name = SmallCStr::new(name);
|
||||
let def = unsafe {
|
||||
LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint)
|
||||
impl<'a> OperandBundleOwned<'a> {
|
||||
pub(crate) fn new(name: &str, vals: &[&'a Value]) -> Self {
|
||||
let raw = unsafe {
|
||||
LLVMCreateOperandBundle(
|
||||
name.as_c_char_ptr(),
|
||||
name.len(),
|
||||
vals.as_ptr(),
|
||||
vals.len() as c_uint,
|
||||
)
|
||||
};
|
||||
OperandBundleDef { raw: def }
|
||||
OperandBundleOwned { raw: ptr::NonNull::new(raw).unwrap() }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for OperandBundleDef<'_> {
|
||||
impl Drop for OperandBundleOwned<'_> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
LLVMRustFreeOperandBundleDef(&mut *(self.raw as *mut _));
|
||||
LLVMDisposeOperandBundle(self.raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Deref for OperandBundleOwned<'a> {
|
||||
type Target = OperandBundle<'a>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
// SAFETY: The returned reference is opaque and can only used for FFI.
|
||||
// It is valid for as long as `&self` is.
|
||||
unsafe { self.raw.as_ref() }
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn add_module_flag_u32(
|
||||
module: &Module,
|
||||
merge_behavior: ModuleFlagMergeBehavior,
|
||||
|
@ -21,7 +21,7 @@ use rustc_middle::mir::BinOp;
|
||||
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::{self, Instance, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypingMode};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType};
|
||||
use rustc_span::symbol::sym;
|
||||
@ -119,7 +119,7 @@ pub fn validate_trivial_unsize<'tcx>(
|
||||
) -> bool {
|
||||
match (source_data.principal(), target_data.principal()) {
|
||||
(Some(hr_source_principal), Some(hr_target_principal)) => {
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis);
|
||||
let universe = infcx.universe();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
infcx.enter_forall(hr_target_principal, |target_principal| {
|
||||
|
@ -16,7 +16,7 @@ use rustc_middle::mir::visit::Visitor;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::adjustment::PointerCoercion;
|
||||
use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TypeVisitableExt, TypingMode};
|
||||
use rustc_mir_dataflow::Analysis;
|
||||
use rustc_mir_dataflow::impls::MaybeStorageLive;
|
||||
use rustc_mir_dataflow::storage::always_storage_live_locals;
|
||||
@ -64,8 +64,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
|
||||
let ConstCx { tcx, body, .. } = *ccx;
|
||||
|
||||
FlowSensitiveAnalysis::new(NeedsDrop, ccx)
|
||||
.into_engine(tcx, body)
|
||||
.iterate_to_fixpoint()
|
||||
.iterate_to_fixpoint(tcx, body, None)
|
||||
.into_results_cursor(body)
|
||||
});
|
||||
|
||||
@ -94,8 +93,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
|
||||
let ConstCx { tcx, body, .. } = *ccx;
|
||||
|
||||
FlowSensitiveAnalysis::new(NeedsNonConstDrop, ccx)
|
||||
.into_engine(tcx, body)
|
||||
.iterate_to_fixpoint()
|
||||
.iterate_to_fixpoint(tcx, body, None)
|
||||
.into_results_cursor(body)
|
||||
});
|
||||
|
||||
@ -124,8 +122,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
|
||||
let ConstCx { tcx, body, .. } = *ccx;
|
||||
|
||||
FlowSensitiveAnalysis::new(HasMutInterior, ccx)
|
||||
.into_engine(tcx, body)
|
||||
.iterate_to_fixpoint()
|
||||
.iterate_to_fixpoint(tcx, body, None)
|
||||
.into_results_cursor(body)
|
||||
});
|
||||
|
||||
@ -240,8 +237,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
|
||||
let always_live_locals = &always_storage_live_locals(&ccx.body);
|
||||
let mut maybe_storage_live =
|
||||
MaybeStorageLive::new(Cow::Borrowed(always_live_locals))
|
||||
.into_engine(ccx.tcx, &ccx.body)
|
||||
.iterate_to_fixpoint()
|
||||
.iterate_to_fixpoint(ccx.tcx, &ccx.body, None)
|
||||
.into_results_cursor(&ccx.body);
|
||||
|
||||
// And then check all `Return` in the MIR, and if a local is "maybe live" at a
|
||||
@ -593,7 +589,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||
// Typeck only does a "non-const" check since it operates on HIR and cannot distinguish
|
||||
// which path expressions are getting called on and which path expressions are only used
|
||||
// as function pointers. This is required for correctness.
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
|
||||
let predicates = tcx.predicates_of(callee).instantiate(tcx, fn_args);
|
||||
|
@ -12,7 +12,7 @@ use rustc_middle::mir::CallSource;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
|
||||
use rustc_middle::ty::{
|
||||
self, Closure, FnDef, FnPtr, GenericArgKind, GenericArgsRef, Param, TraitRef, Ty,
|
||||
self, Closure, FnDef, FnPtr, GenericArgKind, GenericArgsRef, Param, TraitRef, Ty, TypingMode,
|
||||
suggest_constraining_type_param,
|
||||
};
|
||||
use rustc_middle::util::{CallDesugaringKind, CallKind, call_kind};
|
||||
@ -116,7 +116,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
|
||||
let obligation =
|
||||
Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
|
||||
let mut selcx = SelectionContext::new(&infcx);
|
||||
let implsrc = selcx.select(&obligation);
|
||||
|
||||
|
@ -114,11 +114,11 @@ impl Qualif for HasMutInterior {
|
||||
ty::TraitRef::new(cx.tcx, freeze_def_id, [ty::GenericArg::from(ty)]),
|
||||
);
|
||||
|
||||
let infcx = cx
|
||||
.tcx
|
||||
.infer_ctxt()
|
||||
.with_opaque_type_inference(cx.body.source.def_id().expect_local())
|
||||
.build();
|
||||
// FIXME(#132279): This should eventually use the already defined hidden types.
|
||||
let infcx = cx.tcx.infer_ctxt().build(ty::TypingMode::analysis_in_body(
|
||||
cx.tcx,
|
||||
cx.body.source.def_id().expect_local(),
|
||||
));
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
ocx.register_obligation(obligation);
|
||||
let errors = ocx.select_all_or_error();
|
||||
|
@ -9,7 +9,9 @@ use rustc_middle::query::TyCtxtAt;
|
||||
use rustc_middle::ty::layout::{
|
||||
self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout,
|
||||
};
|
||||
use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, Variance};
|
||||
use rustc_middle::ty::{
|
||||
self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, TypingMode, Variance,
|
||||
};
|
||||
use rustc_middle::{mir, span_bug};
|
||||
use rustc_session::Limit;
|
||||
use rustc_span::Span;
|
||||
@ -325,7 +327,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
return true;
|
||||
}
|
||||
// Slow path: spin up an inference context to check if these traits are sufficiently equal.
|
||||
let infcx = self.tcx.infer_ctxt().build();
|
||||
let infcx = self.tcx.infer_ctxt().build(TypingMode::from_param_env(self.param_env));
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let cause = ObligationCause::dummy_with_span(self.cur_span());
|
||||
// equate the two trait refs after normalization
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, Variance};
|
||||
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, TypingMode, Variance};
|
||||
use rustc_trait_selection::traits::ObligationCtxt;
|
||||
|
||||
/// Returns whether the two types are equal up to subtyping.
|
||||
@ -45,7 +45,8 @@ pub fn relate_types<'tcx>(
|
||||
}
|
||||
|
||||
let mut builder = tcx.infer_ctxt().ignoring_regions();
|
||||
let infcx = builder.build();
|
||||
// FIXME(#132279): This should eventually use the already defined hidden types.
|
||||
let infcx = builder.build(TypingMode::from_param_env(param_env));
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let cause = ObligationCause::dummy();
|
||||
let src = ocx.normalize(&cause, param_env, src);
|
||||
|
@ -74,7 +74,7 @@ expand_helper_attribute_name_invalid =
|
||||
`{$name}` cannot be a name of derive helper attribute
|
||||
|
||||
expand_incomplete_parse =
|
||||
macro expansion ignores token `{$token}` and any following
|
||||
macro expansion ignores {$descr} and any tokens following
|
||||
.label = caused by the macro expansion here
|
||||
.note = the usage of `{$macro_path}!` is likely invalid in {$kind_name} context
|
||||
.suggestion_add_semi = you might be missing a semicolon here
|
||||
|
@ -275,7 +275,7 @@ pub(crate) struct UnsupportedKeyValue {
|
||||
pub(crate) struct IncompleteParse<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub token: Cow<'a, str>,
|
||||
pub descr: String,
|
||||
#[label]
|
||||
pub label_span: Span,
|
||||
pub macro_path: &'a ast::Path,
|
||||
|
@ -21,6 +21,7 @@ use rustc_errors::PResult;
|
||||
use rustc_feature::Features;
|
||||
use rustc_parse::parser::{
|
||||
AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma,
|
||||
token_descr,
|
||||
};
|
||||
use rustc_parse::validate_attr;
|
||||
use rustc_session::lint::BuiltinLintDiag;
|
||||
@ -1013,7 +1014,7 @@ pub(crate) fn ensure_complete_parse<'a>(
|
||||
span: Span,
|
||||
) {
|
||||
if parser.token != token::Eof {
|
||||
let token = pprust::token_to_string(&parser.token);
|
||||
let descr = token_descr(&parser.token);
|
||||
// Avoid emitting backtrace info twice.
|
||||
let def_site_span = parser.token.span.with_ctxt(SyntaxContext::root());
|
||||
|
||||
@ -1029,7 +1030,7 @@ pub(crate) fn ensure_complete_parse<'a>(
|
||||
|
||||
parser.dcx().emit_err(IncompleteParse {
|
||||
span: def_site_span,
|
||||
token,
|
||||
descr,
|
||||
label_span: span,
|
||||
macro_path,
|
||||
kind_name,
|
||||
|
@ -2,10 +2,9 @@ use std::borrow::Cow;
|
||||
|
||||
use rustc_ast::token::{self, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_errors::{Applicability, Diag, DiagCtxtHandle, DiagMessage};
|
||||
use rustc_macros::Subdiagnostic;
|
||||
use rustc_parse::parser::{Parser, Recovery};
|
||||
use rustc_parse::parser::{Parser, Recovery, token_descr};
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::symbol::Ident;
|
||||
@ -336,17 +335,11 @@ pub(super) fn annotate_doc_comment(err: &mut Diag<'_>, sm: &SourceMap, span: Spa
|
||||
/// other tokens, this is "unexpected token...".
|
||||
pub(super) fn parse_failure_msg(tok: &Token, expected_token: Option<&Token>) -> Cow<'static, str> {
|
||||
if let Some(expected_token) = expected_token {
|
||||
Cow::from(format!(
|
||||
"expected `{}`, found `{}`",
|
||||
pprust::token_to_string(expected_token),
|
||||
pprust::token_to_string(tok),
|
||||
))
|
||||
Cow::from(format!("expected {}, found {}", token_descr(expected_token), token_descr(tok)))
|
||||
} else {
|
||||
match tok.kind {
|
||||
token::Eof => Cow::from("unexpected end of macro invocation"),
|
||||
_ => {
|
||||
Cow::from(format!("no rules expected the token `{}`", pprust::token_to_string(tok)))
|
||||
}
|
||||
_ => Cow::from(format!("no rules expected {}", token_descr(tok))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,11 +78,10 @@ use std::rc::Rc;
|
||||
pub(crate) use NamedMatch::*;
|
||||
pub(crate) use ParseResult::*;
|
||||
use rustc_ast::token::{self, DocComment, NonterminalKind, Token};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_lint_defs::pluralize;
|
||||
use rustc_parse::parser::{ParseNtResult, Parser};
|
||||
use rustc_parse::parser::{ParseNtResult, Parser, token_descr};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent};
|
||||
|
||||
@ -150,7 +149,7 @@ impl Display for MatcherLoc {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
MatcherLoc::Token { token } | MatcherLoc::SequenceSep { separator: token } => {
|
||||
write!(f, "`{}`", pprust::token_to_string(token))
|
||||
write!(f, "{}", token_descr(token))
|
||||
}
|
||||
MatcherLoc::MetaVarDecl { bind, kind, .. } => {
|
||||
write!(f, "meta-variable `${bind}")?;
|
||||
|
@ -30,6 +30,7 @@ use rustc_trait_selection::traits;
|
||||
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
|
||||
use rustc_type_ir::fold::TypeFoldable;
|
||||
use tracing::{debug, instrument};
|
||||
use ty::TypingMode;
|
||||
use {rustc_attr as attr, rustc_hir as hir};
|
||||
|
||||
use super::compare_impl_item::{check_type_bounds, compare_impl_method, compare_impl_ty};
|
||||
@ -276,7 +277,8 @@ fn check_opaque_meets_bounds<'tcx>(
|
||||
};
|
||||
let param_env = tcx.param_env(defining_use_anchor);
|
||||
|
||||
let infcx = tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).build();
|
||||
// FIXME(#132279): This should eventually use the already defined hidden types.
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, defining_use_anchor));
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
|
||||
let args = match *origin {
|
||||
@ -1675,8 +1677,8 @@ pub(super) fn check_coroutine_obligations(
|
||||
// typeck writeback gives us predicates with their regions erased.
|
||||
// As borrowck already has checked lifetimes, we do not need to do it again.
|
||||
.ignoring_regions()
|
||||
.with_opaque_type_inference(def_id)
|
||||
.build();
|
||||
// FIXME(#132279): This should eventually use the already defined hidden types.
|
||||
.build(TypingMode::analysis_in_body(tcx, def_id));
|
||||
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
for (predicate, cause) in &typeck_results.coroutine_stalled_predicates {
|
||||
|
@ -17,7 +17,7 @@ use rustc_middle::ty::fold::BottomUpFolder;
|
||||
use rustc_middle::ty::util::ExplicitSelf;
|
||||
use rustc_middle::ty::{
|
||||
self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeFolder,
|
||||
TypeSuperFoldable, TypeVisitableExt, Upcast,
|
||||
TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::Span;
|
||||
@ -228,7 +228,7 @@ fn compare_method_predicate_entailment<'tcx>(
|
||||
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
|
||||
debug!(caller_bounds=?param_env.caller_bounds());
|
||||
|
||||
let infcx = &tcx.infer_ctxt().build();
|
||||
let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
|
||||
|
||||
// Create obligations for each predicate declared by the impl
|
||||
@ -516,7 +516,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
||||
ObligationCause::misc(tcx.def_span(impl_m_def_id), impl_m_def_id),
|
||||
);
|
||||
|
||||
let infcx = &tcx.infer_ctxt().build();
|
||||
let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
|
||||
|
||||
// Normalize the impl signature with fresh variables for lifetime inference.
|
||||
@ -1196,7 +1196,7 @@ fn compare_self_type<'tcx>(
|
||||
let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().input(0);
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty);
|
||||
let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty);
|
||||
match ExplicitSelf::determine(self_arg_ty, can_eq_self) {
|
||||
@ -1801,7 +1801,7 @@ fn compare_const_predicate_entailment<'tcx>(
|
||||
ObligationCause::misc(impl_ct_span, impl_ct_def_id),
|
||||
);
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
|
||||
let impl_ct_own_bounds = impl_ct_predicates.instantiate_own_identity();
|
||||
@ -1951,7 +1951,7 @@ fn compare_type_predicate_entailment<'tcx>(
|
||||
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
|
||||
debug!(caller_bounds=?param_env.caller_bounds());
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
|
||||
for (predicate, span) in impl_ty_own_bounds {
|
||||
@ -2036,7 +2036,7 @@ pub(super) fn check_type_bounds<'tcx>(
|
||||
let impl_ty_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id);
|
||||
let rebased_args = impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
|
||||
// A synthetic impl Trait for RPITIT desugaring or assoc type for effects desugaring has no HIR,
|
||||
|
@ -8,7 +8,7 @@ use rustc_middle::span_bug;
|
||||
use rustc_middle::traits::{ObligationCause, Reveal};
|
||||
use rustc_middle::ty::{
|
||||
self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable,
|
||||
TypeVisitableExt, TypeVisitor,
|
||||
TypeVisitableExt, TypeVisitor, TypingMode,
|
||||
};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::regions::InferCtxtRegionExt;
|
||||
@ -132,7 +132,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
|
||||
let param_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(hybrid_preds), Reveal::UserFacing);
|
||||
let param_env = normalize_param_env_or_error(tcx, param_env, ObligationCause::dummy());
|
||||
|
||||
let ref infcx = tcx.infer_ctxt().build();
|
||||
let ref infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
|
||||
// Normalize the bounds. This has two purposes:
|
||||
|
@ -9,7 +9,7 @@ use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
|
||||
use rustc_infer::traits::{ObligationCause, ObligationCauseCode};
|
||||
use rustc_middle::ty::util::CheckRegions;
|
||||
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypingMode};
|
||||
use rustc_trait_selection::regions::InferCtxtRegionExt;
|
||||
use rustc_trait_selection::traits::{self, ObligationCtxt};
|
||||
|
||||
@ -124,7 +124,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
||||
adt_def_id: LocalDefId,
|
||||
adt_to_impl_args: GenericArgsRef<'tcx>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
|
||||
let impl_span = tcx.def_span(drop_impl_def_id.to_def_id());
|
||||
|
@ -4,7 +4,7 @@ use rustc_hir as hir;
|
||||
use rustc_hir::Node;
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode};
|
||||
use rustc_session::config::EntryFnType;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
|
||||
@ -128,7 +128,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
|
||||
tcx.dcx().emit_err(errors::MainFunctionReturnTypeGeneric { span: return_ty_span });
|
||||
return;
|
||||
};
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let cause = traits::ObligationCause::new(
|
||||
return_ty_span,
|
||||
main_diagnostics_def_id,
|
||||
|
@ -85,7 +85,7 @@ use rustc_infer::infer::{self, TyCtxtInferExt as _};
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::{self, GenericArgs, GenericArgsRef, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypingMode};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::def_id::CRATE_DEF_ID;
|
||||
@ -530,7 +530,7 @@ fn suggestion_signature<'tcx>(
|
||||
let ty = tcx.type_of(assoc.def_id).instantiate_identity();
|
||||
let val = tcx
|
||||
.infer_ctxt()
|
||||
.build()
|
||||
.build(TypingMode::non_body_analysis())
|
||||
.err_ctxt()
|
||||
.ty_kind_suggestion(tcx.param_env(assoc.def_id), ty)
|
||||
.unwrap_or_else(|| "value".to_string());
|
||||
@ -620,7 +620,7 @@ pub fn check_function_signature<'tcx>(
|
||||
|
||||
let param_env = ty::ParamEnv::empty();
|
||||
|
||||
let infcx = &tcx.infer_ctxt().build();
|
||||
let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
|
||||
|
||||
let actual_sig = tcx.fn_sig(fn_id).instantiate_identity();
|
||||
|
@ -17,7 +17,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::trait_def::TraitSpecializationKind;
|
||||
use rustc_middle::ty::{
|
||||
self, AdtKind, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable,
|
||||
TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, Upcast,
|
||||
TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::parse::feature_err;
|
||||
@ -106,7 +106,7 @@ where
|
||||
F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>) -> Result<(), ErrorGuaranteed>,
|
||||
{
|
||||
let param_env = tcx.param_env(body_def_id);
|
||||
let infcx = &tcx.infer_ctxt().build();
|
||||
let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
|
||||
|
||||
let mut wfcx = WfCheckingCtxt { ocx, span, body_def_id, param_env };
|
||||
@ -765,7 +765,7 @@ fn test_region_obligations<'tcx>(
|
||||
// Unfortunately, we have to use a new `InferCtxt` each call, because
|
||||
// region constraints get added and solved there and we need to test each
|
||||
// call individually.
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
|
||||
add_constraints(&infcx);
|
||||
|
||||
|
@ -15,7 +15,9 @@ use rustc_infer::infer::{self, RegionResolutionError, TyCtxtInferExt};
|
||||
use rustc_infer::traits::Obligation;
|
||||
use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
|
||||
use rustc_middle::ty::print::PrintTraitRefExt as _;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, suggest_constraining_type_params};
|
||||
use rustc_middle::ty::{
|
||||
self, Ty, TyCtxt, TypeVisitableExt, TypingMode, suggest_constraining_type_params,
|
||||
};
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::traits::misc::{
|
||||
@ -213,7 +215,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
|
||||
|
||||
let param_env = tcx.param_env(impl_did);
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let cause = ObligationCause::misc(span, impl_did);
|
||||
|
||||
// Later parts of the compiler rely on all DispatchFromDyn types to be ABI-compatible with raw
|
||||
@ -354,7 +356,7 @@ pub(crate) fn coerce_unsized_info<'tcx>(
|
||||
|
||||
debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)", source, target);
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let cause = ObligationCause::misc(span, impl_did);
|
||||
let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
|
||||
mt_b: ty::TypeAndMut<'tcx>,
|
||||
|
@ -7,7 +7,7 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||
use rustc_lint_defs::builtin::UNCOVERED_PARAM_IN_PROJECTION;
|
||||
use rustc_middle::ty::{
|
||||
self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable,
|
||||
TypeVisitable, TypeVisitableExt, TypeVisitor,
|
||||
TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::def_id::{DefId, LocalDefId};
|
||||
@ -302,7 +302,7 @@ fn orphan_check<'tcx>(
|
||||
}
|
||||
|
||||
// (1) Instantiate all generic params with fresh inference vars.
|
||||
let infcx = tcx.infer_ctxt().intercrate(true).build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::Coherence);
|
||||
let cause = traits::ObligationCause::dummy();
|
||||
let args = infcx.fresh_args_for_item(cause.span, impl_def_id.to_def_id());
|
||||
let trait_ref = trait_ref.instantiate(tcx, args);
|
||||
|
@ -34,7 +34,7 @@ use rustc_infer::traits::ObligationCause;
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::util::{Discr, IntTypeExt};
|
||||
use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypingMode};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::symbol::{Ident, Symbol, kw, sym};
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
@ -1438,9 +1438,11 @@ fn infer_return_ty_for_fn_sig<'tcx>(
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
recovered_ret_ty = Some(suggestable_ret_ty);
|
||||
} else if let Some(sugg) =
|
||||
suggest_impl_trait(&tcx.infer_ctxt().build(), tcx.param_env(def_id), ret_ty)
|
||||
{
|
||||
} else if let Some(sugg) = suggest_impl_trait(
|
||||
&tcx.infer_ctxt().build(TypingMode::non_body_analysis()),
|
||||
tcx.param_env(def_id),
|
||||
ret_ty,
|
||||
) {
|
||||
diag.span_suggestion(
|
||||
ty.span,
|
||||
"replace with an appropriate return type",
|
||||
|
@ -39,7 +39,7 @@ use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
|
||||
use rustc_middle::ty::print::PrintPolyTraitRefExt as _;
|
||||
use rustc_middle::ty::{
|
||||
self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt,
|
||||
TypeVisitableExt,
|
||||
TypeVisitableExt, TypingMode,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
|
||||
@ -1300,7 +1300,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
Some(infcx) => infcx,
|
||||
None => {
|
||||
assert!(!self_ty.has_infer());
|
||||
infcx_ = tcx.infer_ctxt().ignoring_regions().build();
|
||||
infcx_ = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis());
|
||||
&infcx_
|
||||
}
|
||||
};
|
||||
@ -1492,7 +1492,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
infcx
|
||||
} else {
|
||||
assert!(!qself_ty.has_infer());
|
||||
infcx_ = tcx.infer_ctxt().build();
|
||||
infcx_ = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
&infcx_
|
||||
};
|
||||
|
||||
|
@ -5,7 +5,7 @@ use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_infer::traits::{ObligationCause, WellFormedLoc};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_middle::ty::{self, TyCtxt, TypingMode};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_trait_selection::traits::{self, ObligationCtxt};
|
||||
use tracing::debug;
|
||||
@ -68,7 +68,7 @@ fn diagnostic_hir_wf_check<'tcx>(
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> {
|
||||
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
|
||||
let infcx = self.tcx.infer_ctxt().build();
|
||||
let infcx = self.tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
|
||||
let tcx_ty = self.icx.lower_ty(ty);
|
||||
|
@ -72,7 +72,9 @@ use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||
use rustc_infer::traits::specialization_graph::Node;
|
||||
use rustc_middle::ty::trait_def::TraitSpecializationKind;
|
||||
use rustc_middle::ty::{self, GenericArg, GenericArgs, GenericArgsRef, TyCtxt, TypeVisitableExt};
|
||||
use rustc_middle::ty::{
|
||||
self, GenericArg, GenericArgs, GenericArgsRef, TyCtxt, TypeVisitableExt, TypingMode,
|
||||
};
|
||||
use rustc_span::{ErrorGuaranteed, Span};
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
|
||||
@ -195,7 +197,7 @@ fn get_impl_args(
|
||||
impl1_def_id: LocalDefId,
|
||||
impl2_node: Node,
|
||||
) -> Result<(GenericArgsRef<'_>, GenericArgsRef<'_>), ErrorGuaranteed> {
|
||||
let infcx = &tcx.infer_ctxt().build();
|
||||
let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
|
||||
let param_env = tcx.param_env(impl1_def_id);
|
||||
let impl1_span = tcx.def_span(impl1_def_id);
|
||||
@ -409,7 +411,7 @@ fn check_predicates<'tcx>(
|
||||
|
||||
// Include the well-formed predicates of the type parameters of the impl.
|
||||
for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().instantiate_identity().args {
|
||||
let infcx = &tcx.infer_ctxt().build();
|
||||
let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let obligations =
|
||||
wf::obligations(infcx, tcx.param_env(impl1_def_id), impl1_def_id, 0, arg, span)
|
||||
.unwrap();
|
||||
|
@ -8,7 +8,7 @@ use rustc_hir::{HirId, HirIdMap};
|
||||
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::visit::TypeVisitableExt;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::def_id::LocalDefIdMap;
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
@ -81,7 +81,8 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
|
||||
pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
|
||||
let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner;
|
||||
|
||||
let infcx = tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(def_id).build();
|
||||
let infcx =
|
||||
tcx.infer_ctxt().ignoring_regions().build(TypingMode::analysis_in_body(tcx, def_id));
|
||||
let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner));
|
||||
|
||||
TypeckRootCtxt {
|
||||
|
@ -28,7 +28,7 @@
|
||||
use relate::lattice::{LatticeOp, LatticeOpKind};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::relate::solver_relating::RelateExt as NextSolverRelate;
|
||||
use rustc_middle::ty::{Const, ImplSubject};
|
||||
use rustc_middle::ty::{Const, ImplSubject, TypingMode};
|
||||
|
||||
use super::*;
|
||||
use crate::infer::relate::type_relating::TypeRelating;
|
||||
@ -67,16 +67,9 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
/// variables in the same state. This can be used to "branch off" many tests from the same
|
||||
/// common state.
|
||||
pub fn fork(&self) -> Self {
|
||||
self.fork_with_intercrate(self.intercrate)
|
||||
}
|
||||
|
||||
/// Forks the inference context, creating a new inference context with the same inference
|
||||
/// variables in the same state, except possibly changing the intercrate mode. This can be
|
||||
/// used to "branch off" many tests from the same common state. Used in negative coherence.
|
||||
pub fn fork_with_intercrate(&self, intercrate: bool) -> Self {
|
||||
Self {
|
||||
tcx: self.tcx,
|
||||
defining_opaque_types: self.defining_opaque_types,
|
||||
typing_mode: self.typing_mode,
|
||||
considering_regions: self.considering_regions,
|
||||
skip_leak_check: self.skip_leak_check,
|
||||
inner: self.inner.clone(),
|
||||
@ -87,11 +80,36 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
reported_signature_mismatch: self.reported_signature_mismatch.clone(),
|
||||
tainted_by_errors: self.tainted_by_errors.clone(),
|
||||
universe: self.universe.clone(),
|
||||
intercrate,
|
||||
next_trait_solver: self.next_trait_solver,
|
||||
obligation_inspector: self.obligation_inspector.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Forks the inference context, creating a new inference context with the same inference
|
||||
/// variables in the same state, except possibly changing the intercrate mode. This can be
|
||||
/// used to "branch off" many tests from the same common state. Used in negative coherence.
|
||||
pub fn fork_with_typing_mode(&self, typing_mode: TypingMode<'tcx>) -> Self {
|
||||
// Unlike `fork`, this invalidates all cache entries as they may depend on the
|
||||
// typing mode.
|
||||
let forked = Self {
|
||||
tcx: self.tcx,
|
||||
typing_mode,
|
||||
considering_regions: self.considering_regions,
|
||||
skip_leak_check: self.skip_leak_check,
|
||||
inner: self.inner.clone(),
|
||||
lexical_region_resolutions: self.lexical_region_resolutions.clone(),
|
||||
selection_cache: Default::default(),
|
||||
evaluation_cache: Default::default(),
|
||||
reported_trait_errors: self.reported_trait_errors.clone(),
|
||||
reported_signature_mismatch: self.reported_signature_mismatch.clone(),
|
||||
tainted_by_errors: self.tainted_by_errors.clone(),
|
||||
universe: self.universe.clone(),
|
||||
next_trait_solver: self.next_trait_solver,
|
||||
obligation_inspector: self.obligation_inspector.clone(),
|
||||
};
|
||||
forked.inner.borrow_mut().projection_cache().clear();
|
||||
forked
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ToTrace<'tcx>: Relate<TyCtxt<'tcx>> + Copy {
|
||||
|
@ -46,7 +46,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
V: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
let (param_env, value) = value.into_parts();
|
||||
let param_env = self.tcx.canonical_param_env_cache.get_or_insert(
|
||||
let canonical_param_env = self.tcx.canonical_param_env_cache.get_or_insert(
|
||||
self.tcx,
|
||||
param_env,
|
||||
query_state,
|
||||
@ -64,7 +64,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
);
|
||||
|
||||
let canonical = Canonicalizer::canonicalize_with_base(
|
||||
param_env,
|
||||
canonical_param_env,
|
||||
value,
|
||||
Some(self),
|
||||
self.tcx,
|
||||
@ -72,7 +72,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
query_state,
|
||||
)
|
||||
.unchecked_map(|(param_env, value)| param_env.and(value));
|
||||
CanonicalQueryInput { canonical, defining_opaque_types: self.defining_opaque_types() }
|
||||
CanonicalQueryInput { canonical, typing_mode: self.typing_mode(param_env) }
|
||||
}
|
||||
|
||||
/// Canonicalizes a query *response* `V`. When we canonicalize a
|
||||
|
@ -1,7 +1,6 @@
|
||||
///! Definition of `InferCtxtLike` from the librarified type layer.
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::traits::solve::SolverMode;
|
||||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::relate::RelateResult;
|
||||
use rustc_middle::ty::relate::combine::PredicateEmittingRelation;
|
||||
@ -21,11 +20,11 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
|
||||
self.next_trait_solver
|
||||
}
|
||||
|
||||
fn solver_mode(&self) -> ty::solve::SolverMode {
|
||||
match self.intercrate {
|
||||
true => SolverMode::Coherence,
|
||||
false => SolverMode::Normal,
|
||||
}
|
||||
fn typing_mode(
|
||||
&self,
|
||||
param_env_for_debug_assertion: ty::ParamEnv<'tcx>,
|
||||
) -> ty::TypingMode<'tcx> {
|
||||
self.typing_mode(param_env_for_debug_assertion)
|
||||
}
|
||||
|
||||
fn universe(&self) -> ty::UniverseIndex {
|
||||
@ -91,10 +90,6 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
|
||||
self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
|
||||
}
|
||||
|
||||
fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
|
||||
self.defining_opaque_types()
|
||||
}
|
||||
|
||||
fn next_ty_infer(&self) -> Ty<'tcx> {
|
||||
self.next_ty_var(DUMMY_SP)
|
||||
}
|
||||
|
@ -38,11 +38,12 @@ use rustc_middle::ty::fold::{
|
||||
use rustc_middle::ty::visit::TypeVisitableExt;
|
||||
use rustc_middle::ty::{
|
||||
self, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, GenericArgsRef,
|
||||
GenericParamDefKind, InferConst, IntVid, Ty, TyCtxt, TyVid,
|
||||
GenericParamDefKind, InferConst, IntVid, Ty, TyCtxt, TyVid, TypingMode,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_type_ir::solve::Reveal;
|
||||
use snapshot::undo_log::InferCtxtUndoLogs;
|
||||
use tracing::{debug, instrument};
|
||||
use type_variable::TypeVariableOrigin;
|
||||
@ -243,8 +244,9 @@ impl<'tcx> InferCtxtInner<'tcx> {
|
||||
pub struct InferCtxt<'tcx> {
|
||||
pub tcx: TyCtxt<'tcx>,
|
||||
|
||||
/// The `DefIds` of the opaque types that may have their hidden types constrained.
|
||||
defining_opaque_types: &'tcx ty::List<LocalDefId>,
|
||||
/// The mode of this inference context, see the struct documentation
|
||||
/// for more details.
|
||||
typing_mode: TypingMode<'tcx>,
|
||||
|
||||
/// Whether this inference context should care about region obligations in
|
||||
/// the root universe. Most notably, this is used during hir typeck as region
|
||||
@ -296,26 +298,6 @@ pub struct InferCtxt<'tcx> {
|
||||
/// bound.
|
||||
universe: Cell<ty::UniverseIndex>,
|
||||
|
||||
/// During coherence we have to assume that other crates may add
|
||||
/// additional impls which we currently don't know about.
|
||||
///
|
||||
/// To deal with this evaluation, we should be conservative
|
||||
/// and consider the possibility of impls from outside this crate.
|
||||
/// This comes up primarily when resolving ambiguity. Imagine
|
||||
/// there is some trait reference `$0: Bar` where `$0` is an
|
||||
/// inference variable. If `intercrate` is true, then we can never
|
||||
/// say for sure that this reference is not implemented, even if
|
||||
/// there are *no impls at all for `Bar`*, because `$0` could be
|
||||
/// bound to some type that in a downstream crate that implements
|
||||
/// `Bar`.
|
||||
///
|
||||
/// Outside of coherence, we set this to false because we are only
|
||||
/// interested in types that the user could actually have written.
|
||||
/// In other words, we consider `$0: Bar` to be unimplemented if
|
||||
/// there is no type that the user could *actually name* that
|
||||
/// would satisfy it. This avoids crippling inference, basically.
|
||||
pub intercrate: bool,
|
||||
|
||||
next_trait_solver: bool,
|
||||
|
||||
pub obligation_inspector: Cell<Option<ObligationInspector<'tcx>>>,
|
||||
@ -529,11 +511,8 @@ pub struct RegionObligation<'tcx> {
|
||||
/// Used to configure inference contexts before their creation.
|
||||
pub struct InferCtxtBuilder<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
defining_opaque_types: &'tcx ty::List<LocalDefId>,
|
||||
considering_regions: bool,
|
||||
skip_leak_check: bool,
|
||||
/// Whether we are in coherence mode.
|
||||
intercrate: bool,
|
||||
/// Whether we should use the new trait solver in the local inference context,
|
||||
/// which affects things like which solver is used in `predicate_may_hold`.
|
||||
next_trait_solver: bool,
|
||||
@ -544,37 +523,19 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> {
|
||||
InferCtxtBuilder {
|
||||
tcx: self,
|
||||
defining_opaque_types: ty::List::empty(),
|
||||
considering_regions: true,
|
||||
skip_leak_check: false,
|
||||
intercrate: false,
|
||||
next_trait_solver: self.next_trait_solver_globally(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> InferCtxtBuilder<'tcx> {
|
||||
/// Whenever the `InferCtxt` should be able to handle defining uses of opaque types,
|
||||
/// you need to call this function. Otherwise the opaque type will be treated opaquely.
|
||||
///
|
||||
/// It is only meant to be called in two places, for typeck
|
||||
/// (via `Inherited::build`) and for the inference context used
|
||||
/// in mir borrowck.
|
||||
pub fn with_opaque_type_inference(mut self, defining_anchor: LocalDefId) -> Self {
|
||||
self.defining_opaque_types = self.tcx.opaque_types_defined_by(defining_anchor);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_next_trait_solver(mut self, next_trait_solver: bool) -> Self {
|
||||
self.next_trait_solver = next_trait_solver;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn intercrate(mut self, intercrate: bool) -> Self {
|
||||
self.intercrate = intercrate;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn ignoring_regions(mut self) -> Self {
|
||||
self.considering_regions = false;
|
||||
self
|
||||
@ -600,24 +561,17 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
self.defining_opaque_types = input.defining_opaque_types;
|
||||
let infcx = self.build();
|
||||
let infcx = self.build(input.typing_mode);
|
||||
let (value, args) = infcx.instantiate_canonical(span, &input.canonical);
|
||||
(infcx, value, args)
|
||||
}
|
||||
|
||||
pub fn build(&mut self) -> InferCtxt<'tcx> {
|
||||
let InferCtxtBuilder {
|
||||
tcx,
|
||||
defining_opaque_types,
|
||||
considering_regions,
|
||||
skip_leak_check,
|
||||
intercrate,
|
||||
next_trait_solver,
|
||||
} = *self;
|
||||
pub fn build(&mut self, typing_mode: TypingMode<'tcx>) -> InferCtxt<'tcx> {
|
||||
let InferCtxtBuilder { tcx, considering_regions, skip_leak_check, next_trait_solver } =
|
||||
*self;
|
||||
InferCtxt {
|
||||
tcx,
|
||||
defining_opaque_types,
|
||||
typing_mode,
|
||||
considering_regions,
|
||||
skip_leak_check,
|
||||
inner: RefCell::new(InferCtxtInner::new()),
|
||||
@ -628,7 +582,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
||||
reported_signature_mismatch: Default::default(),
|
||||
tainted_by_errors: Cell::new(None),
|
||||
universe: Cell::new(ty::UniverseIndex::ROOT),
|
||||
intercrate,
|
||||
next_trait_solver,
|
||||
obligation_inspector: Cell::new(None),
|
||||
}
|
||||
@ -659,14 +612,30 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
self.tcx.dcx().taintable_handle(&self.tainted_by_errors)
|
||||
}
|
||||
|
||||
pub fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
|
||||
self.defining_opaque_types
|
||||
}
|
||||
|
||||
pub fn next_trait_solver(&self) -> bool {
|
||||
self.next_trait_solver
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn typing_mode(
|
||||
&self,
|
||||
param_env_for_debug_assertion: ty::ParamEnv<'tcx>,
|
||||
) -> TypingMode<'tcx> {
|
||||
if cfg!(debug_assertions) {
|
||||
match (param_env_for_debug_assertion.reveal(), self.typing_mode) {
|
||||
(Reveal::All, TypingMode::PostAnalysis)
|
||||
| (Reveal::UserFacing, TypingMode::Coherence | TypingMode::Analysis { .. }) => {}
|
||||
(r, t) => unreachable!("TypingMode x Reveal mismatch: {r:?} {t:?}"),
|
||||
}
|
||||
}
|
||||
self.typing_mode
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn typing_mode_unchecked(&self) -> TypingMode<'tcx> {
|
||||
self.typing_mode
|
||||
}
|
||||
|
||||
pub fn freshen<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
|
||||
t.fold_with(&mut self.freshener())
|
||||
}
|
||||
@ -1029,8 +998,12 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
|
||||
#[inline(always)]
|
||||
pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
|
||||
let Some(id) = id.into().as_local() else { return false };
|
||||
self.defining_opaque_types.contains(&id)
|
||||
match self.typing_mode_unchecked() {
|
||||
TypingMode::Analysis { defining_opaque_types } => {
|
||||
id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id))
|
||||
}
|
||||
TypingMode::Coherence | TypingMode::PostAnalysis => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {
|
||||
|
@ -2,6 +2,7 @@ use hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::traits::solve::Goal;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
@ -100,7 +101,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => {
|
||||
let def_id = def_id.expect_local();
|
||||
if self.intercrate {
|
||||
if let ty::TypingMode::Coherence = self.typing_mode(param_env) {
|
||||
// See comment on `insert_hidden_type` for why this is sufficient in coherence
|
||||
return Some(self.register_hidden_type(
|
||||
OpaqueTypeKey { def_id, args },
|
||||
@ -519,28 +520,32 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
// value being folded. In simple cases like `-> impl Foo`,
|
||||
// these are the same span, but not in cases like `-> (impl
|
||||
// Foo, impl Bar)`.
|
||||
if self.intercrate {
|
||||
// During intercrate we do not define opaque types but instead always
|
||||
// force ambiguity unless the hidden type is known to not implement
|
||||
// our trait.
|
||||
goals.push(Goal::new(self.tcx, param_env, ty::PredicateKind::Ambiguous))
|
||||
} else {
|
||||
let prev = self
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.opaque_types()
|
||||
.register(opaque_type_key, OpaqueHiddenType { ty: hidden_ty, span });
|
||||
if let Some(prev) = prev {
|
||||
goals.extend(
|
||||
self.at(&ObligationCause::dummy_with_span(span), param_env)
|
||||
.eq(DefineOpaqueTypes::Yes, prev, hidden_ty)?
|
||||
.obligations
|
||||
.into_iter()
|
||||
// FIXME: Shuttling between obligations and goals is awkward.
|
||||
.map(Goal::from),
|
||||
);
|
||||
match self.typing_mode(param_env) {
|
||||
ty::TypingMode::Coherence => {
|
||||
// During intercrate we do not define opaque types but instead always
|
||||
// force ambiguity unless the hidden type is known to not implement
|
||||
// our trait.
|
||||
goals.push(Goal::new(self.tcx, param_env, ty::PredicateKind::Ambiguous));
|
||||
}
|
||||
};
|
||||
ty::TypingMode::Analysis { .. } => {
|
||||
let prev = self
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.opaque_types()
|
||||
.register(opaque_type_key, OpaqueHiddenType { ty: hidden_ty, span });
|
||||
if let Some(prev) = prev {
|
||||
goals.extend(
|
||||
self.at(&ObligationCause::dummy_with_span(span), param_env)
|
||||
.eq(DefineOpaqueTypes::Yes, prev, hidden_ty)?
|
||||
.obligations
|
||||
.into_iter()
|
||||
// FIXME: Shuttling between obligations and goals is awkward.
|
||||
.map(Goal::from),
|
||||
);
|
||||
}
|
||||
}
|
||||
ty::TypingMode::PostAnalysis => bug!("insert hidden type post-analysis"),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::visit::MaxUniverse;
|
||||
use rustc_middle::ty::{
|
||||
self, AliasRelationDirection, InferConst, Term, Ty, TyCtxt, TypeVisitable, TypeVisitableExt,
|
||||
TypingMode,
|
||||
};
|
||||
use rustc_span::Span;
|
||||
use tracing::{debug, instrument, warn};
|
||||
@ -519,7 +520,10 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
|
||||
//
|
||||
// cc trait-system-refactor-initiative#108
|
||||
if self.infcx.next_trait_solver()
|
||||
&& !self.infcx.intercrate
|
||||
&& !matches!(
|
||||
self.infcx.typing_mode_unchecked(),
|
||||
TypingMode::Coherence
|
||||
)
|
||||
&& self.in_alias
|
||||
{
|
||||
inner.type_variables().equate(vid, new_var_id);
|
||||
@ -650,7 +654,10 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
|
||||
// See the comment for type inference variables
|
||||
// for more details.
|
||||
if self.infcx.next_trait_solver()
|
||||
&& !self.infcx.intercrate
|
||||
&& !matches!(
|
||||
self.infcx.typing_mode_unchecked(),
|
||||
TypingMode::Coherence
|
||||
)
|
||||
&& self.in_alias
|
||||
{
|
||||
variable_table.union(vid, new_var_id);
|
||||
|
@ -31,7 +31,7 @@ use rustc_middle::bug;
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, Upcast, VariantDef};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode, Upcast, VariantDef};
|
||||
use rustc_session::lint::FutureIncompatibilityReason;
|
||||
// hardwired lints from rustc_lint_defs
|
||||
pub use rustc_session::lint::builtin::*;
|
||||
@ -604,7 +604,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
|
||||
&& cx
|
||||
.tcx
|
||||
.infer_ctxt()
|
||||
.build()
|
||||
.build(cx.typing_mode())
|
||||
.type_implements_trait(iter_trait, [ty], cx.param_env)
|
||||
.must_apply_modulo_regions()
|
||||
{
|
||||
@ -648,7 +648,9 @@ fn type_implements_negative_copy_modulo_regions<'tcx>(
|
||||
predicate: pred.upcast(tcx),
|
||||
};
|
||||
|
||||
tcx.infer_ctxt().build().predicate_must_hold_modulo_regions(&obligation)
|
||||
tcx.infer_ctxt()
|
||||
.build(TypingMode::non_body_analysis())
|
||||
.predicate_must_hold_modulo_regions(&obligation)
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
|
@ -14,11 +14,12 @@ use rustc_feature::Features;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::def_id::{CrateNum, DefId};
|
||||
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
|
||||
use rustc_infer::traits::Reveal;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::middle::privacy::EffectiveVisibilities;
|
||||
use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
|
||||
use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, Printer, with_no_trimmed_paths};
|
||||
use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingMode};
|
||||
use rustc_session::lint::{
|
||||
BuiltinLintDiag, FutureIncompatibleInfo, Level, Lint, LintBuffer, LintExpectationId, LintId,
|
||||
};
|
||||
@ -698,6 +699,15 @@ impl LintContext for EarlyContext<'_> {
|
||||
}
|
||||
|
||||
impl<'tcx> LateContext<'tcx> {
|
||||
/// The typing mode of the currently visited node. Use this when
|
||||
/// building a new `InferCtxt`.
|
||||
pub fn typing_mode(&self) -> TypingMode<'tcx> {
|
||||
debug_assert_eq!(self.param_env.reveal(), Reveal::UserFacing);
|
||||
// FIXME(#132279): In case we're in a body, we should use a typing
|
||||
// mode which reveals the opaque types defined by that body.
|
||||
TypingMode::non_body_analysis()
|
||||
}
|
||||
|
||||
/// Gets the type-checking results for the current body,
|
||||
/// or `None` if outside a body.
|
||||
pub fn maybe_typeck_results(&self) -> Option<&'tcx ty::TypeckResults<'tcx>> {
|
||||
|
@ -166,7 +166,7 @@ fn suggest_question_mark<'tcx>(
|
||||
}
|
||||
|
||||
let ty = args.type_at(0);
|
||||
let infcx = cx.tcx.infer_ctxt().build();
|
||||
let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
|
||||
let body_def_id = cx.tcx.hir().body_owner_def_id(body_id);
|
||||
|
@ -15,7 +15,7 @@ use rustc_middle::ty::relate::{
|
||||
Relate, RelateResult, TypeRelation, structurally_relate_consts, structurally_relate_tys,
|
||||
};
|
||||
use rustc_middle::ty::{
|
||||
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
|
||||
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::lint::FutureIncompatibilityReason;
|
||||
@ -184,7 +184,7 @@ fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) {
|
||||
}),
|
||||
outlives_env: LazyCell::new(|| {
|
||||
let param_env = tcx.param_env(parent_def_id);
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let assumed_wf_tys = ocx.assumed_wf_types(param_env, parent_def_id).unwrap_or_default();
|
||||
let implied_bounds =
|
||||
|
@ -157,7 +157,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
||||
Some(ty_def) if cx.tcx.is_lang_item(ty_def.did(), LangItem::String),
|
||||
);
|
||||
|
||||
let infcx = cx.tcx.infer_ctxt().build();
|
||||
let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
|
||||
let suggest_display = is_str
|
||||
|| cx.tcx.get_diagnostic_item(sym::Display).is_some_and(|t| {
|
||||
infcx.type_implements_trait(t, [ty], cx.param_env).may_apply()
|
||||
|
@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
|
||||
}
|
||||
|
||||
let def_id = opaque.def_id.to_def_id();
|
||||
let infcx = &cx.tcx.infer_ctxt().build();
|
||||
let infcx = &cx.tcx.infer_ctxt().build(cx.typing_mode());
|
||||
// For every projection predicate in the opaque type's explicit bounds,
|
||||
// check that the type that we're assigning actually satisfies the bounds
|
||||
// of the associated type.
|
||||
|
@ -1559,8 +1559,10 @@ extern "C" LLVMModuleRef LLVMRustParseBitcodeForLTO(LLVMContextRef Context,
|
||||
extern "C" const char *LLVMRustGetSliceFromObjectDataByName(const char *data,
|
||||
size_t len,
|
||||
const char *name,
|
||||
size_t name_len,
|
||||
size_t *out_len) {
|
||||
*out_len = 0;
|
||||
auto Name = StringRef(name, name_len);
|
||||
auto Data = StringRef(data, len);
|
||||
auto Buffer = MemoryBufferRef(Data, ""); // The id is unused.
|
||||
file_magic Type = identify_magic(Buffer.getBuffer());
|
||||
@ -1571,8 +1573,8 @@ extern "C" const char *LLVMRustGetSliceFromObjectDataByName(const char *data,
|
||||
return nullptr;
|
||||
}
|
||||
for (const object::SectionRef &Sec : (*ObjFileOrError)->sections()) {
|
||||
Expected<StringRef> Name = Sec.getName();
|
||||
if (Name && *Name == name) {
|
||||
Expected<StringRef> SecName = Sec.getName();
|
||||
if (SecName && *SecName == Name) {
|
||||
Expected<StringRef> SectionOrError = Sec.getContents();
|
||||
if (!SectionOrError) {
|
||||
LLVMRustSetLastError(toString(SectionOrError.takeError()).c_str());
|
||||
|
@ -1537,38 +1537,6 @@ LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, RustStringRef MessageOut,
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
|
||||
LLVMValueRef *Inputs,
|
||||
unsigned NumInputs) {
|
||||
return new OperandBundleDef(Name,
|
||||
ArrayRef<Value *>(unwrap(Inputs), NumInputs));
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
|
||||
delete Bundle;
|
||||
}
|
||||
|
||||
// OpBundlesIndirect is an array of pointers (*not* a pointer to an array).
|
||||
extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty,
|
||||
LLVMValueRef Fn, LLVMValueRef *Args,
|
||||
unsigned NumArgs,
|
||||
OperandBundleDef **OpBundlesIndirect,
|
||||
unsigned NumOpBundles) {
|
||||
Value *Callee = unwrap(Fn);
|
||||
FunctionType *FTy = unwrap<FunctionType>(Ty);
|
||||
|
||||
// FIXME: Is there a way around this?
|
||||
SmallVector<OperandBundleDef> OpBundles;
|
||||
OpBundles.reserve(NumOpBundles);
|
||||
for (unsigned i = 0; i < NumOpBundles; ++i) {
|
||||
OpBundles.push_back(*OpBundlesIndirect[i]);
|
||||
}
|
||||
|
||||
return wrap(unwrap(B)->CreateCall(FTy, Callee,
|
||||
ArrayRef<Value *>(unwrap(Args), NumArgs),
|
||||
ArrayRef<OperandBundleDef>(OpBundles)));
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst,
|
||||
unsigned DstAlign, LLVMValueRef Src,
|
||||
unsigned SrcAlign,
|
||||
@ -1596,37 +1564,18 @@ extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B, LLVMValueRef Dst,
|
||||
MaybeAlign(DstAlign), IsVolatile));
|
||||
}
|
||||
|
||||
// OpBundlesIndirect is an array of pointers (*not* a pointer to an array).
|
||||
// Polyfill for `LLVMBuildCallBr`, which was added in LLVM 19.
|
||||
// <https://github.com/llvm/llvm-project/commit/584253c4e2f788f870488fc32193b52d67ddaccc>
|
||||
// FIXME: Remove when Rust's minimum supported LLVM version reaches 19.
|
||||
#if LLVM_VERSION_LT(19, 0)
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OperandBundleDef, LLVMOperandBundleRef)
|
||||
|
||||
extern "C" LLVMValueRef
|
||||
LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
|
||||
LLVMValueRef *Args, unsigned NumArgs,
|
||||
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
|
||||
OperandBundleDef **OpBundlesIndirect, unsigned NumOpBundles,
|
||||
const char *Name) {
|
||||
Value *Callee = unwrap(Fn);
|
||||
FunctionType *FTy = unwrap<FunctionType>(Ty);
|
||||
|
||||
// FIXME: Is there a way around this?
|
||||
SmallVector<OperandBundleDef> OpBundles;
|
||||
OpBundles.reserve(NumOpBundles);
|
||||
for (unsigned i = 0; i < NumOpBundles; ++i) {
|
||||
OpBundles.push_back(*OpBundlesIndirect[i]);
|
||||
}
|
||||
|
||||
return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
|
||||
ArrayRef<Value *>(unwrap(Args), NumArgs),
|
||||
ArrayRef<OperandBundleDef>(OpBundles),
|
||||
Name));
|
||||
}
|
||||
|
||||
// OpBundlesIndirect is an array of pointers (*not* a pointer to an array).
|
||||
extern "C" LLVMValueRef
|
||||
LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
|
||||
LLVMBasicBlockRef DefaultDest,
|
||||
LLVMBasicBlockRef *IndirectDests, unsigned NumIndirectDests,
|
||||
LLVMValueRef *Args, unsigned NumArgs,
|
||||
OperandBundleDef **OpBundlesIndirect, unsigned NumOpBundles,
|
||||
const char *Name) {
|
||||
LLVMBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
|
||||
LLVMBasicBlockRef DefaultDest, LLVMBasicBlockRef *IndirectDests,
|
||||
unsigned NumIndirectDests, LLVMValueRef *Args, unsigned NumArgs,
|
||||
LLVMOperandBundleRef *Bundles, unsigned NumBundles,
|
||||
const char *Name) {
|
||||
Value *Callee = unwrap(Fn);
|
||||
FunctionType *FTy = unwrap<FunctionType>(Ty);
|
||||
|
||||
@ -1639,9 +1588,9 @@ LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
|
||||
|
||||
// FIXME: Is there a way around this?
|
||||
SmallVector<OperandBundleDef> OpBundles;
|
||||
OpBundles.reserve(NumOpBundles);
|
||||
for (unsigned i = 0; i < NumOpBundles; ++i) {
|
||||
OpBundles.push_back(*OpBundlesIndirect[i]);
|
||||
OpBundles.reserve(NumBundles);
|
||||
for (unsigned i = 0; i < NumBundles; ++i) {
|
||||
OpBundles.push_back(*unwrap(Bundles[i]));
|
||||
}
|
||||
|
||||
return wrap(
|
||||
@ -1650,6 +1599,7 @@ LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
|
||||
ArrayRef<Value *>(unwrap(Args), NumArgs),
|
||||
ArrayRef<OperandBundleDef>(OpBundles), Name));
|
||||
}
|
||||
#endif
|
||||
|
||||
extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
|
||||
LLVMBasicBlockRef BB) {
|
||||
|
@ -323,7 +323,7 @@ macro_rules! define_callbacks {
|
||||
// Increase this limit if necessary, but do try to keep the size low if possible
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const _: () = {
|
||||
if mem::size_of::<Key<'static>>() > 72 {
|
||||
if mem::size_of::<Key<'static>>() > 80 {
|
||||
panic!("{}", concat!(
|
||||
"the query `",
|
||||
stringify!($name),
|
||||
|
@ -54,7 +54,6 @@ use rustc_type_ir::TyKind::*;
|
||||
use rustc_type_ir::fold::TypeFoldable;
|
||||
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
||||
pub use rustc_type_ir::lift::Lift;
|
||||
use rustc_type_ir::solve::SolverMode;
|
||||
use rustc_type_ir::{CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo, search_graph};
|
||||
use tracing::{debug, trace};
|
||||
|
||||
@ -170,15 +169,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||
tracked.get(self)
|
||||
}
|
||||
|
||||
fn with_global_cache<R>(
|
||||
self,
|
||||
mode: SolverMode,
|
||||
f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R,
|
||||
) -> R {
|
||||
match mode {
|
||||
SolverMode::Normal => f(&mut *self.new_solver_evaluation_cache.lock()),
|
||||
SolverMode::Coherence => f(&mut *self.new_solver_coherence_evaluation_cache.lock()),
|
||||
}
|
||||
fn with_global_cache<R>(self, f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R) -> R {
|
||||
f(&mut *self.new_solver_evaluation_cache.lock())
|
||||
}
|
||||
|
||||
fn evaluation_is_concurrent(&self) -> bool {
|
||||
@ -629,6 +621,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||
) -> ty::Binder<'tcx, T> {
|
||||
self.anonymize_bound_vars(binder)
|
||||
}
|
||||
|
||||
fn opaque_types_defined_by(self, defining_anchor: LocalDefId) -> Self::DefiningOpaqueTypes {
|
||||
self.opaque_types_defined_by(defining_anchor)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! bidirectional_lang_item_map {
|
||||
@ -1334,7 +1330,6 @@ pub struct GlobalCtxt<'tcx> {
|
||||
|
||||
/// Caches the results of goal evaluation in the new solver.
|
||||
pub new_solver_evaluation_cache: Lock<search_graph::GlobalCache<TyCtxt<'tcx>>>,
|
||||
pub new_solver_coherence_evaluation_cache: Lock<search_graph::GlobalCache<TyCtxt<'tcx>>>,
|
||||
|
||||
pub canonical_param_env_cache: CanonicalParamEnvCache<'tcx>,
|
||||
|
||||
@ -1561,7 +1556,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
selection_cache: Default::default(),
|
||||
evaluation_cache: Default::default(),
|
||||
new_solver_evaluation_cache: Default::default(),
|
||||
new_solver_coherence_evaluation_cache: Default::default(),
|
||||
canonical_param_env_cache: Default::default(),
|
||||
data_layout,
|
||||
alloc_map: Lock::new(interpret::AllocMap::new()),
|
||||
|
@ -100,7 +100,7 @@ pub use self::rvalue_scopes::RvalueScopes;
|
||||
pub use self::sty::{
|
||||
AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig,
|
||||
CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs, InlineConstArgsParts, ParamConst,
|
||||
ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs,
|
||||
ParamTy, PolyFnSig, TyKind, TypeAndMut, TypingMode, UpvarArgs,
|
||||
};
|
||||
pub use self::trait_def::TraitDef;
|
||||
pub use self::typeck_results::{
|
||||
|
@ -40,6 +40,7 @@ pub type AliasTy<'tcx> = ir::AliasTy<TyCtxt<'tcx>>;
|
||||
pub type FnSig<'tcx> = ir::FnSig<TyCtxt<'tcx>>;
|
||||
pub type Binder<'tcx, T> = ir::Binder<TyCtxt<'tcx>, T>;
|
||||
pub type EarlyBinder<'tcx, T> = ir::EarlyBinder<TyCtxt<'tcx>, T>;
|
||||
pub type TypingMode<'tcx> = ir::TypingMode<TyCtxt<'tcx>>;
|
||||
|
||||
pub trait Article {
|
||||
fn article(&self) -> &'static str;
|
||||
|
@ -16,7 +16,7 @@ use rustc_middle::middle::region;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::query::TyCtxtAt;
|
||||
use rustc_middle::thir::{self, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir};
|
||||
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt, TypeVisitableExt, TypingMode};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Span, Symbol};
|
||||
@ -500,7 +500,9 @@ fn construct_fn<'tcx>(
|
||||
);
|
||||
}
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
// FIXME(#132279): This should be able to reveal opaque
|
||||
// types defined during HIR typeck.
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let mut builder = Builder::new(
|
||||
thir,
|
||||
infcx,
|
||||
@ -578,7 +580,9 @@ fn construct_const<'a, 'tcx>(
|
||||
_ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def),
|
||||
};
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
// FIXME(#132279): We likely want to be able to use the hidden types of
|
||||
// opaques used by this function here.
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let mut builder =
|
||||
Builder::new(thir, infcx, def, hir_id, span, 0, const_ty, const_ty_span, None);
|
||||
|
||||
|
@ -79,6 +79,8 @@ enum LetSource {
|
||||
IfLetGuard,
|
||||
LetElse,
|
||||
WhileLet,
|
||||
Else,
|
||||
ElseIfLet,
|
||||
}
|
||||
|
||||
struct MatchVisitor<'p, 'tcx> {
|
||||
@ -129,15 +131,20 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> {
|
||||
// Give a specific `let_source` for the condition.
|
||||
let let_source = match ex.span.desugaring_kind() {
|
||||
Some(DesugaringKind::WhileLoop) => LetSource::WhileLet,
|
||||
_ => LetSource::IfLet,
|
||||
_ => match self.let_source {
|
||||
LetSource::Else => LetSource::ElseIfLet,
|
||||
_ => LetSource::IfLet,
|
||||
},
|
||||
};
|
||||
self.with_let_source(let_source, |this| this.visit_expr(&self.thir[cond]));
|
||||
self.with_let_source(LetSource::None, |this| {
|
||||
this.visit_expr(&this.thir[then]);
|
||||
if let Some(else_) = else_opt {
|
||||
this.visit_expr(&this.thir[else_]);
|
||||
}
|
||||
});
|
||||
if let Some(else_) = else_opt {
|
||||
self.with_let_source(LetSource::Else, |this| {
|
||||
this.visit_expr(&this.thir[else_])
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
ExprKind::Match { scrutinee, scrutinee_hir_id: _, box ref arms, match_source } => {
|
||||
@ -573,9 +580,13 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
||||
// and we shouldn't lint.
|
||||
// For let guards inside a match, prefixes might use bindings of the match pattern,
|
||||
// so can't always be moved out.
|
||||
// For `else if let`, an extra indentation level would be required to move the bindings.
|
||||
// FIXME: Add checking whether the bindings are actually used in the prefix,
|
||||
// and lint if they are not.
|
||||
if !matches!(self.let_source, LetSource::WhileLet | LetSource::IfLetGuard) {
|
||||
if !matches!(
|
||||
self.let_source,
|
||||
LetSource::WhileLet | LetSource::IfLetGuard | LetSource::ElseIfLet
|
||||
) {
|
||||
// Emit the lint
|
||||
let prefix = &chain_refutabilities[..until];
|
||||
let span_start = prefix[0].unwrap().0;
|
||||
@ -906,8 +917,8 @@ fn report_irrefutable_let_patterns(
|
||||
}
|
||||
|
||||
match source {
|
||||
LetSource::None | LetSource::PlainLet => bug!(),
|
||||
LetSource::IfLet => emit_diag!(IrrefutableLetPatternsIfLet),
|
||||
LetSource::None | LetSource::PlainLet | LetSource::Else => bug!(),
|
||||
LetSource::IfLet | LetSource::ElseIfLet => emit_diag!(IrrefutableLetPatternsIfLet),
|
||||
LetSource::IfLetGuard => emit_diag!(IrrefutableLetPatternsIfLetGuard),
|
||||
LetSource::LetElse => emit_diag!(IrrefutableLetPatternsLetElse),
|
||||
LetSource::WhileLet => emit_diag!(IrrefutableLetPatternsWhileLet),
|
||||
|
@ -7,7 +7,7 @@ use rustc_infer::traits::Obligation;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::thir::{FieldPat, Pat, PatKind};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, ValTree};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode, ValTree};
|
||||
use rustc_span::Span;
|
||||
use rustc_target::abi::{FieldIdx, VariantIdx};
|
||||
use rustc_trait_selection::traits::ObligationCause;
|
||||
@ -36,7 +36,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
id: hir::HirId,
|
||||
span: Span,
|
||||
) -> Box<Pat<'tcx>> {
|
||||
let infcx = self.tcx.infer_ctxt().build();
|
||||
// FIXME(#132279): We likely want to be able to reveal the hidden types
|
||||
// of opaques defined in this function here.
|
||||
let infcx = self.tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let mut convert = ConstToPat::new(self, id, span, infcx);
|
||||
convert.to_pat(c, ty)
|
||||
}
|
||||
|
@ -7,18 +7,17 @@
|
||||
//!
|
||||
//! The `impls` module contains several examples of dataflow analyses.
|
||||
//!
|
||||
//! Create an `Engine` for your analysis using the `into_engine` method on the `Analysis` trait,
|
||||
//! then call `iterate_to_fixpoint`. From there, you can use a `ResultsCursor` to inspect the
|
||||
//! fixpoint solution to your dataflow problem, or implement the `ResultsVisitor` interface and use
|
||||
//! `visit_results`. The following example uses the `ResultsCursor` approach.
|
||||
//! Then call `iterate_to_fixpoint` on your type that impls `Analysis` to get a `Results`. From
|
||||
//! there, you can use a `ResultsCursor` to inspect the fixpoint solution to your dataflow problem,
|
||||
//! or implement the `ResultsVisitor` interface and use `visit_results`. The following example uses
|
||||
//! the `ResultsCursor` approach.
|
||||
//!
|
||||
//! ```ignore (cross-crate-imports)
|
||||
//! use rustc_const_eval::dataflow::Analysis; // Makes `into_engine` available.
|
||||
//! use rustc_const_eval::dataflow::Analysis; // Makes `iterate_to_fixpoint` available.
|
||||
//!
|
||||
//! fn do_my_analysis(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) {
|
||||
//! let analysis = MyAnalysis::new()
|
||||
//! .into_engine(tcx, body)
|
||||
//! .iterate_to_fixpoint()
|
||||
//! .iterate_to_fixpoint(tcx, body, None)
|
||||
//! .into_results_cursor(body);
|
||||
//!
|
||||
//! // Print the dataflow state *after* each statement in the start block.
|
||||
@ -34,23 +33,29 @@
|
||||
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use rustc_index::Idx;
|
||||
use rustc_data_structures::work_queue::WorkQueue;
|
||||
use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet};
|
||||
use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges};
|
||||
use rustc_index::{Idx, IndexVec};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges, traversal};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use tracing::error;
|
||||
|
||||
use self::results::write_graphviz_results;
|
||||
use super::fmt::DebugWithContext;
|
||||
|
||||
mod cursor;
|
||||
mod direction;
|
||||
mod engine;
|
||||
pub mod fmt;
|
||||
pub mod graphviz;
|
||||
pub mod lattice;
|
||||
mod results;
|
||||
mod visitor;
|
||||
|
||||
pub use self::cursor::ResultsCursor;
|
||||
pub use self::direction::{Backward, Direction, Forward};
|
||||
pub use self::engine::{Engine, Results};
|
||||
pub use self::lattice::{JoinSemiLattice, MaybeReachable};
|
||||
pub use self::results::Results;
|
||||
pub use self::visitor::{ResultsVisitable, ResultsVisitor, visit_results};
|
||||
|
||||
/// Analysis domains are all bitsets of various kinds. This trait holds
|
||||
@ -223,26 +228,92 @@ pub trait Analysis<'tcx> {
|
||||
|
||||
/* Extension methods */
|
||||
|
||||
/// Creates an `Engine` to find the fixpoint for this dataflow problem.
|
||||
/// Finds the fixpoint for this dataflow problem.
|
||||
///
|
||||
/// You shouldn't need to override this. Its purpose is to enable method chaining like so:
|
||||
///
|
||||
/// ```ignore (cross-crate-imports)
|
||||
/// let results = MyAnalysis::new(tcx, body)
|
||||
/// .into_engine(tcx, body, def_id)
|
||||
/// .iterate_to_fixpoint()
|
||||
/// .iterate_to_fixpoint(tcx, body, None)
|
||||
/// .into_results_cursor(body);
|
||||
/// ```
|
||||
#[inline]
|
||||
fn into_engine<'mir>(
|
||||
self,
|
||||
/// You can optionally add a `pass_name` to the graphviz output for this particular run of a
|
||||
/// dataflow analysis. Some analyses are run multiple times in the compilation pipeline.
|
||||
/// Without a `pass_name` to differentiates them, only the results for the latest run will be
|
||||
/// saved.
|
||||
fn iterate_to_fixpoint<'mir>(
|
||||
mut self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &'mir mir::Body<'tcx>,
|
||||
) -> Engine<'mir, 'tcx, Self>
|
||||
pass_name: Option<&'static str>,
|
||||
) -> Results<'tcx, Self>
|
||||
where
|
||||
Self: Sized,
|
||||
Self::Domain: DebugWithContext<Self>,
|
||||
{
|
||||
Engine::new(tcx, body, self)
|
||||
let mut entry_sets =
|
||||
IndexVec::from_fn_n(|_| self.bottom_value(body), body.basic_blocks.len());
|
||||
self.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]);
|
||||
|
||||
if Self::Direction::IS_BACKWARD && entry_sets[mir::START_BLOCK] != self.bottom_value(body) {
|
||||
bug!("`initialize_start_block` is not yet supported for backward dataflow analyses");
|
||||
}
|
||||
|
||||
let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_none(body.basic_blocks.len());
|
||||
|
||||
if Self::Direction::IS_FORWARD {
|
||||
for (bb, _) in traversal::reverse_postorder(body) {
|
||||
dirty_queue.insert(bb);
|
||||
}
|
||||
} else {
|
||||
// Reverse post-order on the reverse CFG may generate a better iteration order for
|
||||
// backward dataflow analyses, but probably not enough to matter.
|
||||
for (bb, _) in traversal::postorder(body) {
|
||||
dirty_queue.insert(bb);
|
||||
}
|
||||
}
|
||||
|
||||
// `state` is not actually used between iterations;
|
||||
// this is just an optimization to avoid reallocating
|
||||
// every iteration.
|
||||
let mut state = self.bottom_value(body);
|
||||
while let Some(bb) = dirty_queue.pop() {
|
||||
let bb_data = &body[bb];
|
||||
|
||||
// Set the state to the entry state of the block.
|
||||
// This is equivalent to `state = entry_sets[bb].clone()`,
|
||||
// but it saves an allocation, thus improving compile times.
|
||||
state.clone_from(&entry_sets[bb]);
|
||||
|
||||
// Apply the block transfer function, using the cached one if it exists.
|
||||
let edges = Self::Direction::apply_effects_in_block(&mut self, &mut state, bb, bb_data);
|
||||
|
||||
Self::Direction::join_state_into_successors_of(
|
||||
&mut self,
|
||||
body,
|
||||
&mut state,
|
||||
bb,
|
||||
edges,
|
||||
|target: BasicBlock, state: &Self::Domain| {
|
||||
let set_changed = entry_sets[target].join(state);
|
||||
if set_changed {
|
||||
dirty_queue.insert(target);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
let results = Results { analysis: self, entry_sets };
|
||||
|
||||
if tcx.sess.opts.unstable_opts.dump_mir_dataflow {
|
||||
let (res, results) = write_graphviz_results(tcx, body, results, pass_name);
|
||||
if let Err(e) = res {
|
||||
error!("Failed to write graphviz dataflow results: {}", e);
|
||||
}
|
||||
results
|
||||
} else {
|
||||
results
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,23 +1,19 @@
|
||||
//! A solver for dataflow problems.
|
||||
//! Dataflow analysis results.
|
||||
|
||||
use std::ffi::OsString;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use rustc_data_structures::work_queue::WorkQueue;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::{self, BasicBlock, create_dump_file, dump_enabled, traversal};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_span::symbol::{Symbol, sym};
|
||||
use tracing::{debug, error};
|
||||
use tracing::debug;
|
||||
use {rustc_ast as ast, rustc_graphviz as dot};
|
||||
|
||||
use super::fmt::DebugWithContext;
|
||||
use super::{
|
||||
Analysis, Direction, JoinSemiLattice, ResultsCursor, ResultsVisitor, graphviz, visit_results,
|
||||
};
|
||||
use super::{Analysis, ResultsCursor, ResultsVisitor, graphviz, visit_results};
|
||||
use crate::errors::{
|
||||
DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter,
|
||||
};
|
||||
@ -65,124 +61,17 @@ where
|
||||
body: &'mir mir::Body<'tcx>,
|
||||
vis: &mut impl ResultsVisitor<'mir, 'tcx, Self, Domain = A::Domain>,
|
||||
) {
|
||||
let blocks = mir::traversal::reachable(body);
|
||||
let blocks = traversal::reachable(body);
|
||||
visit_results(body, blocks.map(|(bb, _)| bb), self, vis)
|
||||
}
|
||||
}
|
||||
|
||||
/// A solver for dataflow problems.
|
||||
pub struct Engine<'mir, 'tcx, A>
|
||||
where
|
||||
A: Analysis<'tcx>,
|
||||
{
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &'mir mir::Body<'tcx>,
|
||||
entry_sets: IndexVec<BasicBlock, A::Domain>,
|
||||
pass_name: Option<&'static str>,
|
||||
analysis: A,
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx, A, D> Engine<'mir, 'tcx, A>
|
||||
where
|
||||
A: Analysis<'tcx, Domain = D>,
|
||||
D: Clone + JoinSemiLattice,
|
||||
{
|
||||
/// Creates a new `Engine` to solve a dataflow problem with an arbitrary transfer
|
||||
/// function.
|
||||
pub(crate) fn new(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, analysis: A) -> Self {
|
||||
let mut entry_sets =
|
||||
IndexVec::from_fn_n(|_| analysis.bottom_value(body), body.basic_blocks.len());
|
||||
analysis.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]);
|
||||
|
||||
if A::Direction::IS_BACKWARD && entry_sets[mir::START_BLOCK] != analysis.bottom_value(body)
|
||||
{
|
||||
bug!("`initialize_start_block` is not yet supported for backward dataflow analyses");
|
||||
}
|
||||
|
||||
Engine { analysis, tcx, body, pass_name: None, entry_sets }
|
||||
}
|
||||
|
||||
/// Adds an identifier to the graphviz output for this particular run of a dataflow analysis.
|
||||
///
|
||||
/// Some analyses are run multiple times in the compilation pipeline. Give them a `pass_name`
|
||||
/// to differentiate them. Otherwise, only the results for the latest run will be saved.
|
||||
pub fn pass_name(mut self, name: &'static str) -> Self {
|
||||
self.pass_name = Some(name);
|
||||
self
|
||||
}
|
||||
|
||||
/// Computes the fixpoint for this dataflow problem and returns it.
|
||||
pub fn iterate_to_fixpoint(self) -> Results<'tcx, A>
|
||||
where
|
||||
A::Domain: DebugWithContext<A>,
|
||||
{
|
||||
let Engine { mut analysis, body, mut entry_sets, tcx, pass_name } = self;
|
||||
|
||||
let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_none(body.basic_blocks.len());
|
||||
|
||||
if A::Direction::IS_FORWARD {
|
||||
for (bb, _) in traversal::reverse_postorder(body) {
|
||||
dirty_queue.insert(bb);
|
||||
}
|
||||
} else {
|
||||
// Reverse post-order on the reverse CFG may generate a better iteration order for
|
||||
// backward dataflow analyses, but probably not enough to matter.
|
||||
for (bb, _) in traversal::postorder(body) {
|
||||
dirty_queue.insert(bb);
|
||||
}
|
||||
}
|
||||
|
||||
// `state` is not actually used between iterations;
|
||||
// this is just an optimization to avoid reallocating
|
||||
// every iteration.
|
||||
let mut state = analysis.bottom_value(body);
|
||||
while let Some(bb) = dirty_queue.pop() {
|
||||
let bb_data = &body[bb];
|
||||
|
||||
// Set the state to the entry state of the block.
|
||||
// This is equivalent to `state = entry_sets[bb].clone()`,
|
||||
// but it saves an allocation, thus improving compile times.
|
||||
state.clone_from(&entry_sets[bb]);
|
||||
|
||||
// Apply the block transfer function, using the cached one if it exists.
|
||||
let edges =
|
||||
A::Direction::apply_effects_in_block(&mut analysis, &mut state, bb, bb_data);
|
||||
|
||||
A::Direction::join_state_into_successors_of(
|
||||
&mut analysis,
|
||||
body,
|
||||
&mut state,
|
||||
bb,
|
||||
edges,
|
||||
|target: BasicBlock, state: &A::Domain| {
|
||||
let set_changed = entry_sets[target].join(state);
|
||||
if set_changed {
|
||||
dirty_queue.insert(target);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
let results = Results { analysis, entry_sets };
|
||||
|
||||
if tcx.sess.opts.unstable_opts.dump_mir_dataflow {
|
||||
let (res, results) = write_graphviz_results(tcx, body, results, pass_name);
|
||||
if let Err(e) = res {
|
||||
error!("Failed to write graphviz dataflow results: {}", e);
|
||||
}
|
||||
results
|
||||
} else {
|
||||
results
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Graphviz
|
||||
|
||||
/// Writes a DOT file containing the results of a dataflow analysis if the user requested it via
|
||||
/// `rustc_mir` attributes and `-Z dump-mir-dataflow`. The `Result` in and the `Results` out are
|
||||
/// the same.
|
||||
fn write_graphviz_results<'tcx, A>(
|
||||
pub(super) fn write_graphviz_results<'tcx, A>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &mir::Body<'tcx>,
|
||||
results: Results<'tcx, A>,
|
@ -18,9 +18,9 @@ pub use self::drop_flag_effects::{
|
||||
move_path_children_matching, on_all_children_bits, on_lookup_result_bits,
|
||||
};
|
||||
pub use self::framework::{
|
||||
Analysis, Backward, Direction, Engine, Forward, GenKill, JoinSemiLattice, MaybeReachable,
|
||||
Results, ResultsCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz,
|
||||
lattice, visit_results,
|
||||
Analysis, Backward, Direction, Forward, GenKill, JoinSemiLattice, MaybeReachable, Results,
|
||||
ResultsCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz, lattice,
|
||||
visit_results,
|
||||
};
|
||||
use self::move_paths::MoveData;
|
||||
|
||||
|
@ -43,31 +43,28 @@ pub fn sanity_check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
|
||||
let move_data = MoveData::gather_moves(body, tcx, |_| true);
|
||||
|
||||
if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_init).is_some() {
|
||||
let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
|
||||
.into_engine(tcx, body)
|
||||
.iterate_to_fixpoint();
|
||||
let flow_inits =
|
||||
MaybeInitializedPlaces::new(tcx, body, &move_data).iterate_to_fixpoint(tcx, body, None);
|
||||
|
||||
sanity_check_via_rustc_peek(tcx, flow_inits.into_results_cursor(body));
|
||||
}
|
||||
|
||||
if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_uninit).is_some() {
|
||||
let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data)
|
||||
.into_engine(tcx, body)
|
||||
.iterate_to_fixpoint();
|
||||
.iterate_to_fixpoint(tcx, body, None);
|
||||
|
||||
sanity_check_via_rustc_peek(tcx, flow_uninits.into_results_cursor(body));
|
||||
}
|
||||
|
||||
if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_definite_init).is_some() {
|
||||
let flow_def_inits = DefinitelyInitializedPlaces::new(body, &move_data)
|
||||
.into_engine(tcx, body)
|
||||
.iterate_to_fixpoint();
|
||||
let flow_def_inits =
|
||||
DefinitelyInitializedPlaces::new(body, &move_data).iterate_to_fixpoint(tcx, body, None);
|
||||
|
||||
sanity_check_via_rustc_peek(tcx, flow_def_inits.into_results_cursor(body));
|
||||
}
|
||||
|
||||
if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_liveness).is_some() {
|
||||
let flow_liveness = MaybeLiveLocals.into_engine(tcx, body).iterate_to_fixpoint();
|
||||
let flow_liveness = MaybeLiveLocals.iterate_to_fixpoint(tcx, body, None);
|
||||
|
||||
sanity_check_via_rustc_peek(tcx, flow_liveness.into_results_cursor(body));
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ use rustc_index::{Idx, IndexVec};
|
||||
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::{
|
||||
self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt,
|
||||
self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt, TypingMode,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_mir_dataflow::Analysis;
|
||||
@ -666,14 +666,13 @@ fn locals_live_across_suspend_points<'tcx>(
|
||||
// Calculate when MIR locals have live storage. This gives us an upper bound of their
|
||||
// lifetimes.
|
||||
let mut storage_live = MaybeStorageLive::new(std::borrow::Cow::Borrowed(always_live_locals))
|
||||
.into_engine(tcx, body)
|
||||
.iterate_to_fixpoint()
|
||||
.iterate_to_fixpoint(tcx, body, None)
|
||||
.into_results_cursor(body);
|
||||
|
||||
// Calculate the MIR locals which have been previously
|
||||
// borrowed (even if they are still active).
|
||||
let borrowed_locals_results =
|
||||
MaybeBorrowedLocals.into_engine(tcx, body).pass_name("coroutine").iterate_to_fixpoint();
|
||||
MaybeBorrowedLocals.iterate_to_fixpoint(tcx, body, Some("coroutine"));
|
||||
|
||||
let mut borrowed_locals_cursor = borrowed_locals_results.clone().into_results_cursor(body);
|
||||
|
||||
@ -681,16 +680,12 @@ fn locals_live_across_suspend_points<'tcx>(
|
||||
// for.
|
||||
let mut requires_storage_cursor =
|
||||
MaybeRequiresStorage::new(borrowed_locals_results.into_results_cursor(body))
|
||||
.into_engine(tcx, body)
|
||||
.iterate_to_fixpoint()
|
||||
.iterate_to_fixpoint(tcx, body, None)
|
||||
.into_results_cursor(body);
|
||||
|
||||
// Calculate the liveness of MIR locals ignoring borrows.
|
||||
let mut liveness = MaybeLiveLocals
|
||||
.into_engine(tcx, body)
|
||||
.pass_name("coroutine")
|
||||
.iterate_to_fixpoint()
|
||||
.into_results_cursor(body);
|
||||
let mut liveness =
|
||||
MaybeLiveLocals.iterate_to_fixpoint(tcx, body, Some("coroutine")).into_results_cursor(body);
|
||||
|
||||
let mut storage_liveness_map = IndexVec::from_elem(None, &body.basic_blocks);
|
||||
let mut live_locals_at_suspension_points = Vec::new();
|
||||
@ -1501,7 +1496,11 @@ fn check_field_tys_sized<'tcx>(
|
||||
return;
|
||||
}
|
||||
|
||||
let infcx = tcx.infer_ctxt().ignoring_regions().build();
|
||||
// FIXME(#132279): @lcnr believes that we may want to support coroutines
|
||||
// whose `Sized`-ness relies on the hidden types of opaques defined by the
|
||||
// parent function. In this case we'd have to be able to reveal only these
|
||||
// opaques here.
|
||||
let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis());
|
||||
let param_env = tcx.param_env(def_id);
|
||||
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
|
@ -59,7 +59,7 @@ impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp {
|
||||
// Perform the actual dataflow analysis.
|
||||
let analysis = ConstAnalysis::new(tcx, body, map);
|
||||
let mut results = debug_span!("analyze")
|
||||
.in_scope(|| analysis.wrap().into_engine(tcx, body).iterate_to_fixpoint());
|
||||
.in_scope(|| analysis.wrap().iterate_to_fixpoint(tcx, body, None));
|
||||
|
||||
// Collect results and patch the body afterwards.
|
||||
let mut visitor = Collector::new(tcx, &body.local_decls);
|
||||
|
@ -37,8 +37,7 @@ fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
always_live.union(&borrowed_locals);
|
||||
|
||||
let mut live = MaybeTransitiveLiveLocals::new(&always_live)
|
||||
.into_engine(tcx, body)
|
||||
.iterate_to_fixpoint()
|
||||
.iterate_to_fixpoint(tcx, body, None)
|
||||
.into_results_cursor(body);
|
||||
|
||||
// For blocks with a call terminator, if an argument copy can be turned into a move,
|
||||
|
@ -169,10 +169,7 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
|
||||
|
||||
let borrowed = rustc_mir_dataflow::impls::borrowed_locals(body);
|
||||
|
||||
let live = MaybeLiveLocals
|
||||
.into_engine(tcx, body)
|
||||
.pass_name("MaybeLiveLocals-DestinationPropagation")
|
||||
.iterate_to_fixpoint();
|
||||
let live = MaybeLiveLocals.iterate_to_fixpoint(tcx, body, Some("MaybeLiveLocals-DestProp"));
|
||||
let points = DenseLocationMap::new(body);
|
||||
let mut live = save_as_intervals(&points, body, live);
|
||||
|
||||
|
@ -64,18 +64,14 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops {
|
||||
|
||||
let mut inits = MaybeInitializedPlaces::new(tcx, body, &env.move_data)
|
||||
.skipping_unreachable_unwind()
|
||||
.into_engine(tcx, body)
|
||||
.pass_name("elaborate_drops")
|
||||
.iterate_to_fixpoint()
|
||||
.iterate_to_fixpoint(tcx, body, Some("elaborate_drops"))
|
||||
.into_results_cursor(body);
|
||||
let dead_unwinds = compute_dead_unwinds(body, &mut inits);
|
||||
|
||||
let uninits = MaybeUninitializedPlaces::new(tcx, body, &env.move_data)
|
||||
.mark_inactive_variants_as_uninit()
|
||||
.skipping_unreachable_unwind(dead_unwinds)
|
||||
.into_engine(tcx, body)
|
||||
.pass_name("elaborate_drops")
|
||||
.iterate_to_fixpoint()
|
||||
.iterate_to_fixpoint(tcx, body, Some("elaborate_drops"))
|
||||
.into_results_cursor(body);
|
||||
|
||||
let drop_flags = IndexVec::from_elem(None, &env.move_data.move_paths);
|
||||
|
@ -17,13 +17,11 @@ pub(super) fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String
|
||||
let always_live_locals = &always_storage_live_locals(body);
|
||||
|
||||
let maybe_storage_live = MaybeStorageLive::new(Cow::Borrowed(always_live_locals))
|
||||
.into_engine(tcx, body)
|
||||
.iterate_to_fixpoint()
|
||||
.iterate_to_fixpoint(tcx, body, None)
|
||||
.into_results_cursor(body);
|
||||
|
||||
let maybe_storage_dead = MaybeStorageDead::new(Cow::Borrowed(always_live_locals))
|
||||
.into_engine(tcx, body)
|
||||
.iterate_to_fixpoint()
|
||||
.iterate_to_fixpoint(tcx, body, None)
|
||||
.into_results_cursor(body);
|
||||
|
||||
let mut lint = Lint {
|
||||
|
@ -126,8 +126,7 @@ fn compute_replacement<'tcx>(
|
||||
// Compute `MaybeStorageDead` dataflow to check that we only replace when the pointee is
|
||||
// definitely live.
|
||||
let mut maybe_dead = MaybeStorageDead::new(Cow::Owned(always_live_locals))
|
||||
.into_engine(tcx, body)
|
||||
.iterate_to_fixpoint()
|
||||
.iterate_to_fixpoint(tcx, body, None)
|
||||
.into_results_cursor(body);
|
||||
|
||||
// Map for each local to the pointee.
|
||||
|
@ -22,9 +22,7 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops {
|
||||
let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, param_env));
|
||||
|
||||
let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
|
||||
.into_engine(tcx, body)
|
||||
.pass_name("remove_uninit_drops")
|
||||
.iterate_to_fixpoint()
|
||||
.iterate_to_fixpoint(tcx, body, Some("remove_uninit_drops"))
|
||||
.into_results_cursor(body);
|
||||
|
||||
let mut to_remove = vec![];
|
||||
|
@ -12,7 +12,7 @@ use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::adjustment::PointerCoercion;
|
||||
use rustc_middle::ty::{
|
||||
self, CoroutineArgsExt, InstanceKind, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt,
|
||||
Variance,
|
||||
TypingMode, Variance,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_target::abi::{FIRST_VARIANT, Size};
|
||||
@ -606,7 +606,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
return true;
|
||||
}
|
||||
|
||||
let infcx = self.tcx.infer_ctxt().build();
|
||||
let infcx = self.tcx.infer_ctxt().build(TypingMode::from_param_env(self.param_env));
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
ocx.register_obligation(Obligation::new(
|
||||
self.tcx,
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::ops::Deref;
|
||||
|
||||
use rustc_type_ir::fold::TypeFoldable;
|
||||
use rustc_type_ir::solve::{Certainty, Goal, NoSolution, SolverMode};
|
||||
use rustc_type_ir::solve::{Certainty, Goal, NoSolution};
|
||||
use rustc_type_ir::{self as ty, InferCtxtLike, Interner};
|
||||
|
||||
pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Sized {
|
||||
@ -15,7 +15,6 @@ pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Size
|
||||
|
||||
fn build_with_canonical<V>(
|
||||
cx: Self::Interner,
|
||||
solver_mode: SolverMode,
|
||||
canonical: &ty::CanonicalQueryInput<Self::Interner, V>,
|
||||
) -> (Self, V, ty::CanonicalVarValues<Self::Interner>)
|
||||
where
|
||||
@ -93,7 +92,6 @@ pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Size
|
||||
|
||||
fn fetch_eligible_assoc_item(
|
||||
&self,
|
||||
param_env: <Self::Interner as Interner>::ParamEnv,
|
||||
goal_trait_ref: ty::TraitRef<Self::Interner>,
|
||||
trait_assoc_def_id: <Self::Interner as Interner>::DefId,
|
||||
impl_def_id: <Self::Interner as Interner>::DefId,
|
||||
|
@ -8,14 +8,14 @@ use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
||||
use rustc_type_ir::solve::inspect;
|
||||
use rustc_type_ir::visit::TypeVisitableExt as _;
|
||||
use rustc_type_ir::{self as ty, Interner, Upcast as _, elaborate};
|
||||
use rustc_type_ir::{self as ty, Interner, TypingMode, Upcast as _, elaborate};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::delegate::SolverDelegate;
|
||||
use crate::solve::inspect::ProbeKind;
|
||||
use crate::solve::{
|
||||
BuiltinImplSource, CandidateSource, CanonicalResponse, Certainty, EvalCtxt, Goal, GoalSource,
|
||||
MaybeCause, NoSolution, QueryResult, SolverMode,
|
||||
MaybeCause, NoSolution, QueryResult,
|
||||
};
|
||||
|
||||
/// A candidate is a possible way to prove a goal.
|
||||
@ -328,11 +328,12 @@ where
|
||||
|
||||
let mut candidates = vec![];
|
||||
|
||||
if self.solver_mode() == SolverMode::Coherence {
|
||||
if let TypingMode::Coherence = self.typing_mode(goal.param_env) {
|
||||
if let Ok(candidate) = self.consider_coherence_unknowable_candidate(goal) {
|
||||
return vec![candidate];
|
||||
}
|
||||
}
|
||||
|
||||
self.assemble_impl_candidates(goal, &mut candidates);
|
||||
|
||||
self.assemble_builtin_impl_candidates(goal, &mut candidates);
|
||||
@ -343,8 +344,11 @@ where
|
||||
|
||||
self.assemble_param_env_candidates(goal, &mut candidates);
|
||||
|
||||
if self.solver_mode() == SolverMode::Normal {
|
||||
self.discard_impls_shadowed_by_env(goal, &mut candidates);
|
||||
match self.typing_mode(goal.param_env) {
|
||||
TypingMode::Coherence => {}
|
||||
TypingMode::Analysis { .. } | TypingMode::PostAnalysis => {
|
||||
self.discard_impls_shadowed_by_env(goal, &mut candidates);
|
||||
}
|
||||
}
|
||||
|
||||
candidates
|
||||
|
@ -55,6 +55,7 @@ where
|
||||
&self,
|
||||
goal: Goal<I, T>,
|
||||
) -> (Vec<I::GenericArg>, CanonicalInput<I, T>) {
|
||||
let param_env_for_debug_assertion = goal.param_env;
|
||||
let opaque_types = self.delegate.clone_opaque_types_for_query_response();
|
||||
let (goal, opaque_types) =
|
||||
(goal, opaque_types).fold_with(&mut EagerResolver::new(self.delegate));
|
||||
@ -73,7 +74,7 @@ where
|
||||
);
|
||||
let query_input = ty::CanonicalQueryInput {
|
||||
canonical,
|
||||
defining_opaque_types: self.delegate.defining_opaque_types(),
|
||||
typing_mode: self.typing_mode(param_env_for_debug_assertion),
|
||||
};
|
||||
(orig_values, query_input)
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::relate::Relate;
|
||||
use rustc_type_ir::relate::solver_relating::RelateExt;
|
||||
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
|
||||
use rustc_type_ir::{self as ty, CanonicalVarValues, InferCtxtLike, Interner};
|
||||
use rustc_type_ir::{self as ty, CanonicalVarValues, InferCtxtLike, Interner, TypingMode};
|
||||
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
|
||||
use tracing::{instrument, trace};
|
||||
|
||||
@ -21,7 +21,6 @@ use crate::solve::search_graph::SearchGraph;
|
||||
use crate::solve::{
|
||||
CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, GoalSource,
|
||||
HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryResult,
|
||||
SolverMode,
|
||||
};
|
||||
|
||||
pub(super) mod canonical;
|
||||
@ -215,8 +214,8 @@ where
|
||||
D: SolverDelegate<Interner = I>,
|
||||
I: Interner,
|
||||
{
|
||||
pub(super) fn solver_mode(&self) -> SolverMode {
|
||||
self.search_graph.solver_mode()
|
||||
pub(super) fn typing_mode(&self, param_env_for_debug_assertion: I::ParamEnv) -> TypingMode<I> {
|
||||
self.delegate.typing_mode(param_env_for_debug_assertion)
|
||||
}
|
||||
|
||||
pub(super) fn set_is_normalizes_to_goal(&mut self) {
|
||||
@ -232,7 +231,7 @@ where
|
||||
generate_proof_tree: GenerateProofTree,
|
||||
f: impl FnOnce(&mut EvalCtxt<'_, D>) -> R,
|
||||
) -> (R, Option<inspect::GoalEvaluation<I>>) {
|
||||
let mut search_graph = SearchGraph::new(delegate.solver_mode(), root_depth);
|
||||
let mut search_graph = SearchGraph::new(root_depth);
|
||||
|
||||
let mut ecx = EvalCtxt {
|
||||
delegate,
|
||||
@ -279,7 +278,7 @@ where
|
||||
f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal<I, I::Predicate>) -> R,
|
||||
) -> R {
|
||||
let (ref delegate, input, var_values) =
|
||||
SolverDelegate::build_with_canonical(cx, search_graph.solver_mode(), &canonical_input);
|
||||
SolverDelegate::build_with_canonical(cx, &canonical_input);
|
||||
|
||||
let mut ecx = EvalCtxt {
|
||||
delegate,
|
||||
@ -942,21 +941,11 @@ where
|
||||
|
||||
pub(super) fn fetch_eligible_assoc_item(
|
||||
&self,
|
||||
param_env: I::ParamEnv,
|
||||
goal_trait_ref: ty::TraitRef<I>,
|
||||
trait_assoc_def_id: I::DefId,
|
||||
impl_def_id: I::DefId,
|
||||
) -> Result<Option<I::DefId>, NoSolution> {
|
||||
self.delegate.fetch_eligible_assoc_item(
|
||||
param_env,
|
||||
goal_trait_ref,
|
||||
trait_assoc_def_id,
|
||||
impl_def_id,
|
||||
)
|
||||
}
|
||||
|
||||
pub(super) fn can_define_opaque_ty(&self, def_id: I::LocalDefId) -> bool {
|
||||
self.delegate.defining_opaque_types().contains(&def_id)
|
||||
self.delegate.fetch_eligible_assoc_item(goal_trait_ref, trait_assoc_def_id, impl_def_id)
|
||||
}
|
||||
|
||||
pub(super) fn insert_hidden_type(
|
||||
|
@ -6,7 +6,7 @@ mod weak_types;
|
||||
use rustc_type_ir::fast_reject::DeepRejectCtxt;
|
||||
use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
||||
use rustc_type_ir::{self as ty, Interner, NormalizesTo, Upcast as _};
|
||||
use rustc_type_ir::{self as ty, Interner, NormalizesTo, TypingMode, Upcast as _};
|
||||
use tracing::instrument;
|
||||
|
||||
use crate::delegate::SolverDelegate;
|
||||
@ -15,7 +15,7 @@ use crate::solve::assembly::{self, Candidate};
|
||||
use crate::solve::inspect::ProbeKind;
|
||||
use crate::solve::{
|
||||
BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause,
|
||||
NoSolution, QueryResult, Reveal,
|
||||
NoSolution, QueryResult,
|
||||
};
|
||||
|
||||
impl<D, I> EvalCtxt<'_, D>
|
||||
@ -71,21 +71,21 @@ where
|
||||
Ok(())
|
||||
}
|
||||
ty::AliasTermKind::OpaqueTy => {
|
||||
match param_env.reveal() {
|
||||
// In user-facing mode, paques are only rigid if we may not define it.
|
||||
Reveal::UserFacing => {
|
||||
match self.typing_mode(param_env) {
|
||||
// Opaques are never rigid outside of analysis mode.
|
||||
TypingMode::Coherence | TypingMode::PostAnalysis => Err(NoSolution),
|
||||
// During analysis, opaques are only rigid if we may not define it.
|
||||
TypingMode::Analysis { defining_opaque_types } => {
|
||||
if rigid_alias
|
||||
.def_id
|
||||
.as_local()
|
||||
.is_some_and(|def_id| self.can_define_opaque_ty(def_id))
|
||||
.is_some_and(|def_id| defining_opaque_types.contains(&def_id))
|
||||
{
|
||||
Err(NoSolution)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
// Opaques are never rigid in reveal-all mode.
|
||||
Reveal::All => Err(NoSolution),
|
||||
}
|
||||
}
|
||||
// FIXME(generic_const_exprs): we would need to support generic consts here
|
||||
@ -252,7 +252,6 @@ where
|
||||
// return ambiguity this would otherwise be incomplete, resulting in
|
||||
// unsoundness during coherence (#105782).
|
||||
let Some(target_item_def_id) = ecx.fetch_eligible_assoc_item(
|
||||
goal.param_env,
|
||||
goal_trait_ref,
|
||||
goal.predicate.def_id(),
|
||||
impl_def_id,
|
||||
|
@ -4,12 +4,10 @@
|
||||
|
||||
use rustc_index::bit_set::GrowableBitSet;
|
||||
use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::{self as ty, Interner};
|
||||
use rustc_type_ir::{self as ty, Interner, TypingMode};
|
||||
|
||||
use crate::delegate::SolverDelegate;
|
||||
use crate::solve::{
|
||||
Certainty, EvalCtxt, Goal, NoSolution, QueryResult, Reveal, SolverMode, inspect,
|
||||
};
|
||||
use crate::solve::{Certainty, EvalCtxt, Goal, NoSolution, QueryResult, inspect};
|
||||
|
||||
impl<D, I> EvalCtxt<'_, D>
|
||||
where
|
||||
@ -24,17 +22,27 @@ where
|
||||
let opaque_ty = goal.predicate.alias;
|
||||
let expected = goal.predicate.term.as_type().expect("no such thing as an opaque const");
|
||||
|
||||
match (goal.param_env.reveal(), self.solver_mode()) {
|
||||
(Reveal::UserFacing, SolverMode::Normal) => {
|
||||
let Some(opaque_ty_def_id) = opaque_ty.def_id.as_local() else {
|
||||
match self.typing_mode(goal.param_env) {
|
||||
TypingMode::Coherence => {
|
||||
// An impossible opaque type bound is the only way this goal will fail
|
||||
// e.g. assigning `impl Copy := NotCopy`
|
||||
self.add_item_bounds_for_hidden_type(
|
||||
opaque_ty.def_id,
|
||||
opaque_ty.args,
|
||||
goal.param_env,
|
||||
expected,
|
||||
);
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
|
||||
}
|
||||
TypingMode::Analysis { defining_opaque_types } => {
|
||||
let Some(def_id) = opaque_ty.def_id.as_local() else {
|
||||
return Err(NoSolution);
|
||||
};
|
||||
// FIXME: at some point we should call queries without defining
|
||||
// new opaque types but having the existing opaque type definitions.
|
||||
// This will require moving this below "Prefer opaques registered already".
|
||||
if !self.can_define_opaque_ty(opaque_ty_def_id) {
|
||||
|
||||
if !defining_opaque_types.contains(&def_id) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
// FIXME: This may have issues when the args contain aliases...
|
||||
match uses_unique_placeholders_ignoring_regions(self.cx(), opaque_ty.args) {
|
||||
Err(NotUniqueParam::NotParam(param)) if param.is_non_region_infer() => {
|
||||
@ -48,8 +56,7 @@ where
|
||||
Ok(()) => {}
|
||||
}
|
||||
// Prefer opaques registered already.
|
||||
let opaque_type_key =
|
||||
ty::OpaqueTypeKey { def_id: opaque_ty_def_id, args: opaque_ty.args };
|
||||
let opaque_type_key = ty::OpaqueTypeKey { def_id, args: opaque_ty.args };
|
||||
// FIXME: This also unifies the previous hidden type with the expected.
|
||||
//
|
||||
// If that fails, we insert `expected` as a new hidden type instead of
|
||||
@ -69,7 +76,7 @@ where
|
||||
}
|
||||
ecx.eq(goal.param_env, candidate_ty, expected)?;
|
||||
ecx.add_item_bounds_for_hidden_type(
|
||||
candidate_key.def_id.into(),
|
||||
def_id.into(),
|
||||
candidate_key.args,
|
||||
goal.param_env,
|
||||
candidate_ty,
|
||||
@ -82,25 +89,14 @@ where
|
||||
// FIXME: should we use `inject_hidden_type_unchecked` here?
|
||||
self.insert_hidden_type(opaque_type_key, goal.param_env, expected)?;
|
||||
self.add_item_bounds_for_hidden_type(
|
||||
opaque_ty.def_id,
|
||||
def_id.into(),
|
||||
opaque_ty.args,
|
||||
goal.param_env,
|
||||
expected,
|
||||
);
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
}
|
||||
(Reveal::UserFacing, SolverMode::Coherence) => {
|
||||
// An impossible opaque type bound is the only way this goal will fail
|
||||
// e.g. assigning `impl Copy := NotCopy`
|
||||
self.add_item_bounds_for_hidden_type(
|
||||
opaque_ty.def_id,
|
||||
opaque_ty.args,
|
||||
goal.param_env,
|
||||
expected,
|
||||
);
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
|
||||
}
|
||||
(Reveal::All, _) => {
|
||||
TypingMode::PostAnalysis => {
|
||||
// FIXME: Add an assertion that opaque type storage is empty.
|
||||
let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args);
|
||||
self.eq(goal.param_env, expected, actual)?;
|
||||
|
@ -6,7 +6,7 @@ use rustc_type_ir::fast_reject::DeepRejectCtxt;
|
||||
use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
||||
use rustc_type_ir::visit::TypeVisitableExt as _;
|
||||
use rustc_type_ir::{self as ty, Interner, TraitPredicate, Upcast as _, elaborate};
|
||||
use rustc_type_ir::{self as ty, Interner, TraitPredicate, TypingMode, Upcast as _, elaborate};
|
||||
use tracing::{instrument, trace};
|
||||
|
||||
use crate::delegate::SolverDelegate;
|
||||
@ -15,7 +15,7 @@ use crate::solve::assembly::{self, Candidate};
|
||||
use crate::solve::inspect::ProbeKind;
|
||||
use crate::solve::{
|
||||
BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause,
|
||||
NoSolution, QueryResult, Reveal, SolverMode,
|
||||
NoSolution, QueryResult,
|
||||
};
|
||||
|
||||
impl<D, I> assembly::GoalKind<D> for TraitPredicate<I>
|
||||
@ -67,9 +67,9 @@ where
|
||||
let maximal_certainty = match (impl_polarity, goal.predicate.polarity) {
|
||||
// In intercrate mode, this is ambiguous. But outside of intercrate,
|
||||
// it's not a real impl.
|
||||
(ty::ImplPolarity::Reservation, _) => match ecx.solver_mode() {
|
||||
SolverMode::Coherence => Certainty::AMBIGUOUS,
|
||||
SolverMode::Normal => return Err(NoSolution),
|
||||
(ty::ImplPolarity::Reservation, _) => match ecx.typing_mode(goal.param_env) {
|
||||
TypingMode::Coherence => Certainty::AMBIGUOUS,
|
||||
TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Err(NoSolution),
|
||||
},
|
||||
|
||||
// Impl matches polarity
|
||||
@ -167,30 +167,26 @@ where
|
||||
return result;
|
||||
}
|
||||
|
||||
// Don't call `type_of` on a local TAIT that's in the defining scope,
|
||||
// since that may require calling `typeck` on the same item we're
|
||||
// We only look into opaque types during analysis for opaque types
|
||||
// outside of their defining scope. Doing so for opaques in the
|
||||
// defining scope may require calling `typeck` on the same item we're
|
||||
// currently type checking, which will result in a fatal cycle that
|
||||
// ideally we want to avoid, since we can make progress on this goal
|
||||
// via an alias bound or a locally-inferred hidden type instead.
|
||||
//
|
||||
// Also, don't call `type_of` on a TAIT in `Reveal::All` mode, since
|
||||
// we already normalize the self type in
|
||||
// `assemble_candidates_after_normalizing_self_ty`, and we'd
|
||||
// just be registering an identical candidate here.
|
||||
//
|
||||
// We always return `Err(NoSolution)` here in `SolverMode::Coherence`
|
||||
// since we'll always register an ambiguous candidate in
|
||||
// `assemble_candidates_after_normalizing_self_ty` due to normalizing
|
||||
// the TAIT.
|
||||
if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
|
||||
if matches!(goal.param_env.reveal(), Reveal::All)
|
||||
|| matches!(ecx.solver_mode(), SolverMode::Coherence)
|
||||
|| opaque_ty
|
||||
.def_id
|
||||
.as_local()
|
||||
.is_some_and(|def_id| ecx.can_define_opaque_ty(def_id))
|
||||
{
|
||||
return Err(NoSolution);
|
||||
match ecx.typing_mode(goal.param_env) {
|
||||
TypingMode::Coherence | TypingMode::PostAnalysis => {
|
||||
unreachable!("rigid opaque outside of analysis: {goal:?}");
|
||||
}
|
||||
TypingMode::Analysis { defining_opaque_types } => {
|
||||
if opaque_ty
|
||||
.def_id
|
||||
.as_local()
|
||||
.is_some_and(|def_id| defining_opaque_types.contains(&def_id))
|
||||
{
|
||||
return Err(NoSolution);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -424,7 +424,7 @@ impl TokenDescription {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn token_descr(token: &Token) -> String {
|
||||
pub fn token_descr(token: &Token) -> String {
|
||||
let name = pprust::token_to_string(token).to_string();
|
||||
|
||||
let kind = match (TokenDescription::from_token(token), &token.kind) {
|
||||
|
@ -25,7 +25,7 @@ use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_middle::ty::{self, TyCtxt, TypingMode};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::lint::builtin::{
|
||||
CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS,
|
||||
@ -2267,7 +2267,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||
let def_id = hir_id.expect_owner().def_id;
|
||||
let param_env = ty::ParamEnv::empty();
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
|
||||
let span = tcx.def_span(def_id);
|
||||
|
@ -2,6 +2,7 @@ use rustc_abi::{HasDataLayout, TargetDataLayout};
|
||||
use rustc_ast::Attribute;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::infer::canonical::ir::TypingMode;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers};
|
||||
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
|
||||
@ -54,7 +55,7 @@ pub fn ensure_wf<'tcx>(
|
||||
param_env,
|
||||
pred,
|
||||
);
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
|
||||
let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
ocx.register_obligation(obligation);
|
||||
let errors = ocx.select_all_or_error();
|
||||
|
@ -7,13 +7,13 @@ use rustc_infer::infer::canonical::{
|
||||
Canonical, CanonicalExt as _, CanonicalQueryInput, CanonicalVarInfo, CanonicalVarValues,
|
||||
};
|
||||
use rustc_infer::infer::{InferCtxt, RegionVariableOrigin, TyCtxtInferExt};
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_infer::traits::solve::Goal;
|
||||
use rustc_infer::traits::{ObligationCause, Reveal};
|
||||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt as _};
|
||||
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
|
||||
use rustc_type_ir::solve::{Certainty, NoSolution, SolverMode};
|
||||
use tracing::trace;
|
||||
use rustc_type_ir::TypingMode;
|
||||
use rustc_type_ir::solve::{Certainty, NoSolution};
|
||||
|
||||
use crate::traits::specialization_graph;
|
||||
|
||||
@ -47,7 +47,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
|
||||
|
||||
fn build_with_canonical<V>(
|
||||
interner: TyCtxt<'tcx>,
|
||||
solver_mode: SolverMode,
|
||||
canonical: &CanonicalQueryInput<'tcx, V>,
|
||||
) -> (Self, V, CanonicalVarValues<'tcx>)
|
||||
where
|
||||
@ -56,10 +55,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
|
||||
let (infcx, value, vars) = interner
|
||||
.infer_ctxt()
|
||||
.with_next_trait_solver(true)
|
||||
.intercrate(match solver_mode {
|
||||
SolverMode::Normal => false,
|
||||
SolverMode::Coherence => true,
|
||||
})
|
||||
.build_with_canonical(DUMMY_SP, canonical);
|
||||
(SolverDelegate(infcx), value, vars)
|
||||
}
|
||||
@ -195,7 +190,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
|
||||
|
||||
fn fetch_eligible_assoc_item(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
goal_trait_ref: ty::TraitRef<'tcx>,
|
||||
trait_assoc_def_id: DefId,
|
||||
impl_def_id: DefId,
|
||||
@ -211,12 +205,12 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
|
||||
// and the obligation is monomorphic, otherwise passes such as
|
||||
// transmute checking and polymorphic MIR optimizations could
|
||||
// get a result which isn't correct for all monomorphizations.
|
||||
if param_env.reveal() == Reveal::All {
|
||||
let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref);
|
||||
!poly_trait_ref.still_further_specializable()
|
||||
} else {
|
||||
trace!(?node_item.item.def_id, "not eligible due to default");
|
||||
false
|
||||
match self.typing_mode_unchecked() {
|
||||
TypingMode::Coherence | TypingMode::Analysis { .. } => false,
|
||||
TypingMode::PostAnalysis => {
|
||||
let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref);
|
||||
!poly_trait_ref.still_further_specializable()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -10,6 +10,7 @@ use rustc_infer::infer::DefineOpaqueTypes;
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::ty::{Region, RegionVid};
|
||||
use tracing::debug;
|
||||
use ty::TypingMode;
|
||||
|
||||
use super::*;
|
||||
use crate::errors::UnableToConstructConstantValue;
|
||||
@ -79,7 +80,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||
|
||||
let trait_ref = ty::TraitRef::new(tcx, trait_did, [ty]);
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let mut selcx = SelectionContext::new(&infcx);
|
||||
for polarity in [ty::PredicatePolarity::Positive, ty::PredicatePolarity::Negative] {
|
||||
let result = selcx.select(&Obligation::new(
|
||||
@ -99,7 +100,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let mut fresh_preds = FxIndexSet::default();
|
||||
|
||||
// Due to the way projections are handled by SelectionContext, we need to run
|
||||
|
@ -18,7 +18,7 @@ use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal};
|
||||
use rustc_middle::traits::specialization_graph::OverlapMode;
|
||||
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
|
||||
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode};
|
||||
pub use rustc_next_trait_solver::coherence::*;
|
||||
use rustc_next_trait_solver::solve::SolverDelegateEvalExt;
|
||||
use rustc_span::symbol::sym;
|
||||
@ -195,9 +195,8 @@ fn overlap<'tcx>(
|
||||
let infcx = tcx
|
||||
.infer_ctxt()
|
||||
.skip_leak_check(skip_leak_check.is_yes())
|
||||
.intercrate(true)
|
||||
.with_next_trait_solver(tcx.next_trait_solver_in_coherence())
|
||||
.build();
|
||||
.build(TypingMode::Coherence);
|
||||
let selcx = &mut SelectionContext::new(&infcx);
|
||||
if track_ambiguity_causes.is_yes() {
|
||||
selcx.enable_tracking_intercrate_ambiguity_causes();
|
||||
@ -419,7 +418,7 @@ fn impl_intersection_has_negative_obligation(
|
||||
|
||||
// N.B. We need to unify impl headers *with* intercrate mode, even if proving negative predicates
|
||||
// do not need intercrate mode enabled.
|
||||
let ref infcx = tcx.infer_ctxt().intercrate(true).with_next_trait_solver(true).build();
|
||||
let ref infcx = tcx.infer_ctxt().with_next_trait_solver(true).build(TypingMode::Coherence);
|
||||
let root_universe = infcx.universe();
|
||||
assert_eq!(root_universe, ty::UniverseIndex::ROOT);
|
||||
|
||||
@ -570,7 +569,9 @@ fn try_prove_negated_where_clause<'tcx>(
|
||||
// the *existence* of a negative goal, not the non-existence of a positive goal.
|
||||
// Without this, we over-eagerly register coherence ambiguity candidates when
|
||||
// impl candidates do exist.
|
||||
let ref infcx = root_infcx.fork_with_intercrate(false);
|
||||
// FIXME(#132279): `TypingMode::non_body_analysis` is a bit questionable here as it
|
||||
// would cause us to reveal opaque types to leak their auto traits.
|
||||
let ref infcx = root_infcx.fork_with_typing_mode(TypingMode::non_body_analysis());
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
ocx.register_obligation(Obligation::new(
|
||||
infcx.tcx,
|
||||
@ -714,7 +715,10 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
|
||||
|
||||
// It is only relevant that a goal is unknowable if it would have otherwise
|
||||
// failed.
|
||||
let non_intercrate_infcx = infcx.fork_with_intercrate(false);
|
||||
// FIXME(#132279): Forking with `TypingMode::non_body_analysis` is a bit questionable
|
||||
// as it would allow us to reveal opaque types, potentially causing unexpected
|
||||
// cycles.
|
||||
let non_intercrate_infcx = infcx.fork_with_typing_mode(TypingMode::non_body_analysis());
|
||||
if non_intercrate_infcx.predicate_may_hold(&Obligation::new(
|
||||
infcx.tcx,
|
||||
ObligationCause::dummy(),
|
||||
|
@ -14,7 +14,7 @@ use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{
|
||||
self, EarlyBinder, ExistentialPredicateStableCmpExt as _, GenericArgs, Ty, TyCtxt,
|
||||
TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable,
|
||||
TypeVisitableExt, TypeVisitor, Upcast,
|
||||
TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
|
||||
};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::Symbol;
|
||||
@ -718,7 +718,7 @@ fn receiver_is_dispatchable<'tcx>(
|
||||
Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
|
||||
};
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
// the receiver is dispatchable iff the obligation holds
|
||||
infcx.predicate_must_hold_modulo_regions(&obligation)
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
use rustc_hir as hir;
|
||||
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt};
|
||||
use rustc_infer::traits::{ImplSource, Obligation, PredicateObligation};
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
|
||||
use rustc_middle::{span_bug, ty};
|
||||
use rustc_middle::ty::{self, TypingMode};
|
||||
use rustc_type_ir::solve::NoSolution;
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
@ -19,7 +20,7 @@ pub fn evaluate_host_effect_obligation<'tcx>(
|
||||
selcx: &mut SelectionContext<'_, 'tcx>,
|
||||
obligation: &HostEffectObligation<'tcx>,
|
||||
) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
|
||||
if selcx.infcx.intercrate {
|
||||
if matches!(selcx.infcx.typing_mode(obligation.param_env), TypingMode::Coherence) {
|
||||
span_bug!(
|
||||
obligation.cause.span,
|
||||
"should not select host obligation in old solver in intercrate mode"
|
||||
|
@ -13,7 +13,7 @@ use rustc_middle::bug;
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::{self, Binder, Const, GenericArgsRef, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, Binder, Const, GenericArgsRef, TypeVisitableExt, TypingMode};
|
||||
use thin_vec::ThinVec;
|
||||
use tracing::{debug, debug_span, instrument};
|
||||
|
||||
@ -760,7 +760,9 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
|
||||
stalled_on: &mut Vec<TyOrConstInferVar>,
|
||||
) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
|
||||
let infcx = self.selcx.infcx;
|
||||
if obligation.predicate.is_global() && !self.selcx.is_intercrate() {
|
||||
if obligation.predicate.is_global()
|
||||
&& !matches!(infcx.typing_mode(obligation.param_env), TypingMode::Coherence)
|
||||
{
|
||||
// no type variables present, can use evaluation for better caching.
|
||||
// FIXME: consider caching errors too.
|
||||
if infcx.predicate_must_hold_considering_regions(obligation) {
|
||||
@ -813,11 +815,13 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
|
||||
stalled_on: &mut Vec<TyOrConstInferVar>,
|
||||
) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
|
||||
let tcx = self.selcx.tcx();
|
||||
|
||||
if obligation.predicate.is_global() && !self.selcx.is_intercrate() {
|
||||
let infcx = self.selcx.infcx;
|
||||
if obligation.predicate.is_global()
|
||||
&& !matches!(infcx.typing_mode(obligation.param_env), TypingMode::Coherence)
|
||||
{
|
||||
// no type variables present, can use evaluation for better caching.
|
||||
// FIXME: consider caching errors too.
|
||||
if self.selcx.infcx.predicate_must_hold_considering_regions(obligation) {
|
||||
if infcx.predicate_must_hold_considering_regions(obligation) {
|
||||
if let Some(key) = ProjectionCacheKey::from_poly_projection_obligation(
|
||||
&mut self.selcx,
|
||||
&project_obligation,
|
||||
@ -825,8 +829,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
|
||||
// If `predicate_must_hold_considering_regions` succeeds, then we've
|
||||
// evaluated all sub-obligations. We can therefore mark the 'root'
|
||||
// obligation as complete, and skip evaluating sub-obligations.
|
||||
self.selcx
|
||||
.infcx
|
||||
infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.projection_cache()
|
||||
|
@ -8,7 +8,7 @@ use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_hir as hir;
|
||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
|
||||
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt, TypingMode};
|
||||
|
||||
use super::outlives_bounds::InferCtxtExt;
|
||||
use crate::regions::InferCtxtRegionExt;
|
||||
@ -143,7 +143,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
|
||||
let mut infringing_inner_tys = vec![];
|
||||
for inner_ty in inner_tys {
|
||||
// We use an ocx per inner ty for better diagnostics
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
|
||||
ocx.register_bound(
|
||||
@ -200,7 +200,7 @@ pub fn all_fields_implement_trait<'tcx>(
|
||||
for variant in adt.variants() {
|
||||
for field in &variant.fields {
|
||||
// Do this per-field to get better error messages.
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
|
||||
let unnormalized_ty = field.ty(tcx, args);
|
||||
|
@ -34,7 +34,8 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
|
||||
use rustc_middle::ty::{
|
||||
self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFolder, TypeSuperVisitable, Upcast,
|
||||
self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFolder, TypeSuperVisitable, TypingMode,
|
||||
Upcast,
|
||||
};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::def_id::DefId;
|
||||
@ -274,7 +275,7 @@ fn do_normalize_predicates<'tcx>(
|
||||
// by wfcheck anyway, so I'm not sure we have to check
|
||||
// them here too, and we will remove this function when
|
||||
// we move over to lazy normalization *anyway*.
|
||||
let infcx = tcx.infer_ctxt().ignoring_regions().build();
|
||||
let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis());
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
let predicates = ocx.normalize(&cause, elaborated_env, predicates);
|
||||
|
||||
@ -475,11 +476,11 @@ pub fn normalize_param_env_or_error<'tcx>(
|
||||
|
||||
/// Normalizes the predicates and checks whether they hold in an empty environment. If this
|
||||
/// returns true, then either normalize encountered an error or one of the predicates did not
|
||||
/// hold. Used when creating vtables to check for unsatisfiable methods.
|
||||
/// hold. Used when creating vtables to check for unsatisfiable methods. This should not be
|
||||
/// used during analysis.
|
||||
pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec<ty::Clause<'tcx>>) -> bool {
|
||||
debug!("impossible_predicates(predicates={:?})", predicates);
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis);
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let predicates = ocx.normalize(&ObligationCause::dummy(), param_env, predicates);
|
||||
@ -568,8 +569,11 @@ fn is_impossible_associated_item(
|
||||
// since that method *may* have some substitutions where the predicates hold.
|
||||
//
|
||||
// This replicates the logic we use in coherence.
|
||||
let infcx =
|
||||
tcx.infer_ctxt().ignoring_regions().with_next_trait_solver(true).intercrate(true).build();
|
||||
let infcx = tcx
|
||||
.infer_ctxt()
|
||||
.ignoring_regions()
|
||||
.with_next_trait_solver(true)
|
||||
.build(TypingMode::Coherence);
|
||||
let param_env = ty::ParamEnv::empty();
|
||||
let fresh_args = infcx.fresh_args_for_item(tcx.def_span(impl_def_id), impl_def_id);
|
||||
|
||||
|
@ -334,11 +334,6 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
|
||||
) -> Result<Option<Term<'tcx>>, InProgress> {
|
||||
let infcx = selcx.infcx;
|
||||
debug_assert!(!selcx.infcx.next_trait_solver());
|
||||
// Don't use the projection cache in intercrate mode -
|
||||
// the `infcx` may be re-used between intercrate in non-intercrate
|
||||
// mode, which could lead to using incorrect cache results.
|
||||
let use_cache = !selcx.is_intercrate();
|
||||
|
||||
let projection_term = infcx.resolve_vars_if_possible(projection_term);
|
||||
let cache_key = ProjectionCacheKey::new(projection_term, param_env);
|
||||
|
||||
@ -349,13 +344,8 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
|
||||
// would not benefit from caching when proving `T: Trait<U=Foo>`
|
||||
// bounds. It might be the case that we want two distinct caches,
|
||||
// or else another kind of cache entry.
|
||||
|
||||
let cache_result = if use_cache {
|
||||
infcx.inner.borrow_mut().projection_cache().try_start(cache_key)
|
||||
} else {
|
||||
Ok(())
|
||||
};
|
||||
match cache_result {
|
||||
let cache_entry = infcx.inner.borrow_mut().projection_cache().try_start(cache_key);
|
||||
match cache_entry {
|
||||
Ok(()) => debug!("no cache"),
|
||||
Err(ProjectionCacheEntry::Ambiguous) => {
|
||||
// If we found ambiguity the last time, that means we will continue
|
||||
@ -378,10 +368,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
|
||||
// Cache that normalizing this projection resulted in a cycle. This
|
||||
// should ensure that, unless this happens within a snapshot that's
|
||||
// rolled back, fulfillment or evaluation will notice the cycle.
|
||||
|
||||
if use_cache {
|
||||
infcx.inner.borrow_mut().projection_cache().recur(cache_key);
|
||||
}
|
||||
infcx.inner.borrow_mut().projection_cache().recur(cache_key);
|
||||
return Err(InProgress);
|
||||
}
|
||||
Err(ProjectionCacheEntry::Recur) => {
|
||||
@ -445,26 +432,20 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
|
||||
let mut deduped = SsoHashSet::with_capacity(result.obligations.len());
|
||||
result.obligations.retain(|obligation| deduped.insert(obligation.clone()));
|
||||
|
||||
if use_cache {
|
||||
infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone());
|
||||
}
|
||||
infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone());
|
||||
obligations.extend(result.obligations);
|
||||
Ok(Some(result.value))
|
||||
}
|
||||
Ok(Projected::NoProgress(projected_ty)) => {
|
||||
let result =
|
||||
Normalized { value: projected_ty, obligations: PredicateObligations::new() };
|
||||
if use_cache {
|
||||
infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone());
|
||||
}
|
||||
infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone());
|
||||
// No need to extend `obligations`.
|
||||
Ok(Some(result.value))
|
||||
}
|
||||
Err(ProjectionError::TooManyCandidates) => {
|
||||
debug!("opt_normalize_projection_type: too many candidates");
|
||||
if use_cache {
|
||||
infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
|
||||
}
|
||||
infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
|
||||
Ok(None)
|
||||
}
|
||||
Err(ProjectionError::TraitSelectionError(_)) => {
|
||||
@ -473,10 +454,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
|
||||
// just return `ty::err` but add the obligation `T :
|
||||
// Trait`, which when processed will cause the error to be
|
||||
// reported later
|
||||
|
||||
if use_cache {
|
||||
infcx.inner.borrow_mut().projection_cache().error(cache_key);
|
||||
}
|
||||
infcx.inner.borrow_mut().projection_cache().error(cache_key);
|
||||
let result = normalize_to_error(selcx, param_env, projection_term, cause, depth);
|
||||
obligations.extend(result.obligations);
|
||||
Ok(Some(result.value))
|
||||
|
@ -87,7 +87,6 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
Ok(result)
|
||||
})
|
||||
} else {
|
||||
assert!(!self.intercrate);
|
||||
let c_pred =
|
||||
self.canonicalize_query(param_env.and(obligation.predicate), &mut _orig_values);
|
||||
self.tcx.at(obligation.cause.span).evaluate_obligation(c_pred)
|
||||
|
@ -16,7 +16,7 @@ use rustc_infer::traits::{
|
||||
Obligation, ObligationCause, PolyTraitObligation, PredicateObligations, SelectionError,
|
||||
};
|
||||
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
|
||||
use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt, TypingMode};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
@ -790,7 +790,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
//
|
||||
// Note that this is only sound as projection candidates of opaque types
|
||||
// are always applicable for auto traits.
|
||||
} else if self.infcx.intercrate {
|
||||
} else if let TypingMode::Coherence =
|
||||
self.infcx.typing_mode(obligation.param_env)
|
||||
{
|
||||
// We do not emit auto trait candidates for opaque types in coherence.
|
||||
// Doing so can result in weird dependency cycles.
|
||||
candidates.ambiguous = true;
|
||||
@ -930,7 +932,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
) -> Option<ty::PolyExistentialTraitRef<'tcx>> {
|
||||
// Don't drop any candidates in intercrate mode, as it's incomplete.
|
||||
// (Not that it matters, since `Unsize` is not a stable trait.)
|
||||
if self.infcx.intercrate {
|
||||
//
|
||||
// FIXME(@lcnr): This should probably only trigger during analysis,
|
||||
// disabling candidates during codegen is also questionable.
|
||||
if let TypingMode::Coherence = self.infcx.typing_mode(param_env) {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
//!
|
||||
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection
|
||||
|
||||
use std::assert_matches::assert_matches;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::fmt::{self, Display};
|
||||
use std::ops::ControlFlow;
|
||||
@ -28,7 +29,7 @@ use rustc_middle::ty::error::TypeErrorToStringExt;
|
||||
use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
|
||||
use rustc_middle::ty::{
|
||||
self, GenericArgsRef, PolyProjectionPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitableExt,
|
||||
Upcast,
|
||||
TypingMode, Upcast,
|
||||
};
|
||||
use rustc_span::Symbol;
|
||||
use rustc_span::symbol::sym;
|
||||
@ -222,7 +223,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
/// Enables tracking of intercrate ambiguity causes. See
|
||||
/// the documentation of [`Self::intercrate_ambiguity_causes`] for more.
|
||||
pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) {
|
||||
assert!(self.is_intercrate());
|
||||
assert_matches!(self.infcx.typing_mode_unchecked(), TypingMode::Coherence);
|
||||
assert!(self.intercrate_ambiguity_causes.is_none());
|
||||
self.intercrate_ambiguity_causes = Some(FxIndexSet::default());
|
||||
debug!("selcx: enable_tracking_intercrate_ambiguity_causes");
|
||||
@ -234,7 +235,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
pub fn take_intercrate_ambiguity_causes(
|
||||
&mut self,
|
||||
) -> FxIndexSet<IntercrateAmbiguityCause<'tcx>> {
|
||||
assert!(self.is_intercrate());
|
||||
assert_matches!(self.infcx.typing_mode_unchecked(), TypingMode::Coherence);
|
||||
self.intercrate_ambiguity_causes.take().unwrap_or_default()
|
||||
}
|
||||
|
||||
@ -242,10 +243,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
self.infcx.tcx
|
||||
}
|
||||
|
||||
pub fn is_intercrate(&self) -> bool {
|
||||
self.infcx.intercrate
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Selection
|
||||
//
|
||||
@ -1029,7 +1026,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
previous_stack: TraitObligationStackList<'o, 'tcx>,
|
||||
mut obligation: PolyTraitObligation<'tcx>,
|
||||
) -> Result<EvaluationResult, OverflowError> {
|
||||
if !self.is_intercrate()
|
||||
if !matches!(self.infcx.typing_mode(obligation.param_env), TypingMode::Coherence)
|
||||
&& obligation.is_global()
|
||||
&& obligation.param_env.caller_bounds().iter().all(|bound| bound.has_param())
|
||||
{
|
||||
@ -1312,14 +1309,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
) -> Option<EvaluationResult> {
|
||||
// Neither the global nor local cache is aware of intercrate
|
||||
// mode, so don't do any caching. In particular, we might
|
||||
// re-use the same `InferCtxt` with both an intercrate
|
||||
// and non-intercrate `SelectionContext`
|
||||
if self.is_intercrate() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let tcx = self.tcx();
|
||||
if self.can_use_global_caches(param_env) {
|
||||
if let Some(res) = tcx.evaluation_cache.get(&(param_env, trait_pred), tcx) {
|
||||
@ -1342,14 +1331,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
return;
|
||||
}
|
||||
|
||||
// Neither the global nor local cache is aware of intercrate
|
||||
// mode, so don't do any caching. In particular, we might
|
||||
// re-use the same `InferCtxt` with both an intercrate
|
||||
// and non-intercrate `SelectionContext`
|
||||
if self.is_intercrate() {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.can_use_global_caches(param_env) && !trait_pred.has_infer() {
|
||||
debug!(?trait_pred, ?result, "insert_evaluation_cache global");
|
||||
// This may overwrite the cache with the same value
|
||||
@ -1476,13 +1457,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Result<(), Conflict> {
|
||||
debug!("is_knowable(intercrate={:?})", self.is_intercrate());
|
||||
|
||||
if !self.is_intercrate() {
|
||||
return Ok(());
|
||||
let obligation = &stack.obligation;
|
||||
match self.infcx.typing_mode(obligation.param_env) {
|
||||
TypingMode::Coherence => {}
|
||||
TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Ok(()),
|
||||
}
|
||||
|
||||
let obligation = &stack.obligation;
|
||||
debug!("is_knowable()");
|
||||
|
||||
let predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
|
||||
|
||||
// Okay to skip binder because of the nature of the
|
||||
@ -1502,25 +1484,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Avoid using the global cache during coherence and just rely
|
||||
// on the local cache. This effectively disables caching
|
||||
// during coherence. It is really just a simplification to
|
||||
// avoid us having to fear that coherence results "pollute"
|
||||
// the master cache. Since coherence executes pretty quickly,
|
||||
// it's not worth going to more trouble to increase the
|
||||
// hit-rate, I don't think.
|
||||
if self.is_intercrate() {
|
||||
return false;
|
||||
match self.infcx.typing_mode(param_env) {
|
||||
// Avoid using the global cache during coherence and just rely
|
||||
// on the local cache. It is really just a simplification to
|
||||
// avoid us having to fear that coherence results "pollute"
|
||||
// the master cache. Since coherence executes pretty quickly,
|
||||
// it's not worth going to more trouble to increase the
|
||||
// hit-rate, I don't think.
|
||||
TypingMode::Coherence => false,
|
||||
// Avoid using the global cache when we're defining opaque types
|
||||
// as their hidden type may impact the result of candidate selection.
|
||||
TypingMode::Analysis { defining_opaque_types } => defining_opaque_types.is_empty(),
|
||||
// The global cache is only used if there are no opaque types in
|
||||
// the defining scope or we're outside of analysis.
|
||||
//
|
||||
// FIXME(#132279): This is still incorrect as we treat opaque types
|
||||
// and default associated items differently between these two modes.
|
||||
TypingMode::PostAnalysis => true,
|
||||
}
|
||||
|
||||
// Avoid using the global cache when we're defining opaque types
|
||||
// as their hidden type may impact the result of candidate selection.
|
||||
if !self.infcx.defining_opaque_types().is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise, we can use the global cache.
|
||||
true
|
||||
}
|
||||
|
||||
fn check_candidate_cache(
|
||||
@ -1528,13 +1509,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
|
||||
// Neither the global nor local cache is aware of intercrate
|
||||
// mode, so don't do any caching. In particular, we might
|
||||
// re-use the same `InferCtxt` with both an intercrate
|
||||
// and non-intercrate `SelectionContext`
|
||||
if self.is_intercrate() {
|
||||
return None;
|
||||
}
|
||||
let tcx = self.tcx();
|
||||
let pred = cache_fresh_trait_pred.skip_binder();
|
||||
|
||||
@ -1566,13 +1540,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
&self,
|
||||
result: &SelectionResult<'tcx, SelectionCandidate<'tcx>>,
|
||||
) -> bool {
|
||||
// Neither the global nor local cache is aware of intercrate
|
||||
// mode, so don't do any caching. In particular, we might
|
||||
// re-use the same `InferCtxt` with both an intercrate
|
||||
// and non-intercrate `SelectionContext`
|
||||
if self.is_intercrate() {
|
||||
return false;
|
||||
}
|
||||
match result {
|
||||
Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.has_infer(),
|
||||
_ => true,
|
||||
@ -2541,7 +2508,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
})?;
|
||||
nested_obligations.extend(obligations);
|
||||
|
||||
if !self.is_intercrate() && impl_trait_header.polarity == ty::ImplPolarity::Reservation {
|
||||
if impl_trait_header.polarity == ty::ImplPolarity::Reservation
|
||||
&& !matches!(self.infcx.typing_mode(obligation.param_env), TypingMode::Coherence)
|
||||
{
|
||||
debug!("reservation impls only apply in intercrate mode");
|
||||
return Err(());
|
||||
}
|
||||
|
@ -19,7 +19,9 @@ use rustc_infer::infer::DefineOpaqueTypes;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::query::LocalCrate;
|
||||
use rustc_middle::ty::print::PrintTraitRefExt as _;
|
||||
use rustc_middle::ty::{self, GenericArgsRef, ImplSubject, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_middle::ty::{
|
||||
self, GenericArgsRef, ImplSubject, Ty, TyCtxt, TypeVisitableExt, TypingMode,
|
||||
};
|
||||
use rustc_session::lint::builtin::{COHERENCE_LEAK_CHECK, ORDER_DEPENDENT_TRAIT_OBJECTS};
|
||||
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, sym};
|
||||
use specialization_graph::GraphExt;
|
||||
@ -184,7 +186,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
|
||||
let penv = tcx.param_env(impl1_def_id);
|
||||
|
||||
// Create an infcx, taking the predicates of impl1 as assumptions:
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
|
||||
// Attempt to prove that impl2 applies, given all of the above.
|
||||
fulfill_implication(
|
||||
|
@ -9,7 +9,8 @@ use rustc_infer::traits::util::PredicateSet;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{
|
||||
self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, Upcast, VtblEntry,
|
||||
self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, TypingMode, Upcast,
|
||||
VtblEntry,
|
||||
};
|
||||
use rustc_span::{DUMMY_SP, Span, sym};
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
@ -439,7 +440,7 @@ fn trait_refs_are_compatible<'tcx>(
|
||||
return false;
|
||||
}
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis);
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let hr_source_principal =
|
||||
|
@ -6,7 +6,7 @@
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::traits::CodegenObligationError;
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode};
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::traits::{
|
||||
ImplSource, Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext,
|
||||
@ -30,7 +30,7 @@ pub(crate) fn codegen_select_candidate<'tcx>(
|
||||
|
||||
// Do the initial selection for the obligation. This yields the
|
||||
// shallow result we are looking for -- that is, what specific impl.
|
||||
let infcx = tcx.infer_ctxt().ignoring_regions().build();
|
||||
let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::from_param_env(param_env));
|
||||
let mut selcx = SelectionContext::new(&infcx);
|
||||
|
||||
let obligation_cause = ObligationCause::dummy();
|
||||
|
@ -1,7 +1,7 @@
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::traits::query::NoSolution;
|
||||
use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable, TypeVisitableExt, TypingMode};
|
||||
use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
|
||||
use rustc_trait_selection::traits::{Normalized, ObligationCause};
|
||||
use tracing::debug;
|
||||
@ -22,7 +22,7 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<TyCtxt<'tcx>> + Par
|
||||
goal: ParamEnvAnd<'tcx, T>,
|
||||
) -> Result<T, NoSolution> {
|
||||
let ParamEnvAnd { param_env, value } = goal;
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
|
||||
let cause = ObligationCause::dummy();
|
||||
match infcx.at(&cause, param_env).query_normalize(value) {
|
||||
Ok(Normalized { value: normalized_value, obligations: normalized_obligations }) => {
|
||||
|
@ -3,7 +3,7 @@
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode};
|
||||
use rustc_trait_selection::traits;
|
||||
|
||||
fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
@ -29,7 +29,7 @@ fn is_item_raw<'tcx>(
|
||||
) -> bool {
|
||||
let (param_env, ty) = query.into_parts();
|
||||
let trait_def_id = tcx.require_lang_item(item, None);
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
|
||||
traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, ty, trait_def_id)
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ use rustc_middle::bug;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::traits::{BuiltinImplSource, CodegenObligationError};
|
||||
use rustc_middle::ty::util::AsyncDropGlueMorphology;
|
||||
use rustc_middle::ty::{self, GenericArgsRef, Instance, TyCtxt, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, GenericArgsRef, Instance, TyCtxt, TypeVisitableExt, TypingMode};
|
||||
use rustc_span::sym;
|
||||
use rustc_trait_selection::traits;
|
||||
use rustc_type_ir::ClosureKind;
|
||||
@ -130,7 +130,7 @@ fn resolve_associated_item<'tcx>(
|
||||
.unwrap_or_else(|| {
|
||||
bug!("{:?} not found in {:?}", trait_item_id, impl_data.impl_def_id);
|
||||
});
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis);
|
||||
let param_env = param_env.with_reveal_all_normalized(tcx);
|
||||
let args = rcvr_args.rebase_onto(tcx, trait_def_id, impl_data.args);
|
||||
let args = translate_args(
|
||||
|
@ -1,7 +1,7 @@
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode};
|
||||
use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
|
||||
|
||||
/// This method returns true if and only if `adt_ty` itself has been marked as
|
||||
@ -11,7 +11,7 @@ use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
|
||||
/// Note that this does *not* recursively check if the substructure of `adt_ty`
|
||||
/// implements the trait.
|
||||
fn has_structural_eq_impl<'tcx>(tcx: TyCtxt<'tcx>, adt_ty: Ty<'tcx>) -> bool {
|
||||
let infcx = &tcx.infer_ctxt().build();
|
||||
let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let cause = ObligationCause::dummy();
|
||||
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user