Merge from rustc
This commit is contained in:
commit
b1f5c6683b
459 changed files with 8314 additions and 3508 deletions
138
Cargo.lock
138
Cargo.lock
|
|
@ -118,16 +118,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.3.2"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
|
||||
checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is-terminal",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
|
|
@ -157,9 +156,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "1.0.1"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188"
|
||||
checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys 0.48.0",
|
||||
|
|
@ -291,9 +290,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.3.3"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
|
||||
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
|
|
@ -459,25 +458,23 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.3.10"
|
||||
version = "4.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "384e169cc618c613d5e3ca6404dda77a8685a63e08660dcc64abaf7da7cb0c7a"
|
||||
checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.3.10"
|
||||
version = "4.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef137bbe35aab78bdb468ccfba75a5f4d8321ae011d34063770780545176af2d"
|
||||
checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"once_cell",
|
||||
"strsim",
|
||||
"terminal_size",
|
||||
]
|
||||
|
|
@ -493,9 +490,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.3.2"
|
||||
version = "4.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f"
|
||||
checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
|
|
@ -515,7 +512,6 @@ version = "0.1.74"
|
|||
dependencies = [
|
||||
"clippy_lints",
|
||||
"clippy_utils",
|
||||
"derive-new",
|
||||
"filetime",
|
||||
"futures",
|
||||
"if_chain",
|
||||
|
|
@ -944,17 +940,6 @@ dependencies = [
|
|||
"syn 2.0.29",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive-new"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder"
|
||||
version = "0.12.0"
|
||||
|
|
@ -1253,12 +1238,9 @@ checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
|
|||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.9.0"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
|
||||
dependencies = [
|
||||
"instant",
|
||||
]
|
||||
checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
|
||||
|
||||
[[package]]
|
||||
name = "field-offset"
|
||||
|
|
@ -1993,17 +1975,6 @@ dependencies = [
|
|||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
|
||||
dependencies = [
|
||||
"hermit-abi 0.3.2",
|
||||
"libc",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.7.2"
|
||||
|
|
@ -2017,7 +1988,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb"
|
||||
dependencies = [
|
||||
"hermit-abi 0.3.2",
|
||||
"rustix 0.38.2",
|
||||
"rustix",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
|
|
@ -2214,15 +2185,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.3.8"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0"
|
||||
checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128"
|
||||
|
||||
[[package]]
|
||||
name = "litemap"
|
||||
|
|
@ -3006,6 +2971,27 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "4.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "575fc2d9b3da54adbdfaddf6eca48fec256d977c8630a1750b8991347d1ac911"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi-alloc"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31d6f09fe2b6ad044bc3d2c34ce4979796581afd2f1ebc185837e02421e02fd7"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"r-efi",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
|
|
@ -3259,6 +3245,7 @@ dependencies = [
|
|||
"rustc_driver",
|
||||
"rustc_driver_impl",
|
||||
"rustc_smir",
|
||||
"stable_mir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4423,7 +4410,7 @@ dependencies = [
|
|||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"scoped-tls",
|
||||
"stable_mir",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
|
@ -4690,28 +4677,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.37.22"
|
||||
version = "0.38.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8818fa822adcc98b18fedbb3632a6a33213c070556b5aa7c4c8cc21cff565c4c"
|
||||
checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"errno",
|
||||
"io-lifetimes",
|
||||
"libc",
|
||||
"linux-raw-sys 0.3.8",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aabcb0461ebd01d6b79945797c27f8529082226cb630a9865a71870ff63532a4"
|
||||
dependencies = [
|
||||
"bitflags 2.3.3",
|
||||
"bitflags 2.4.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.3",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
|
|
@ -4974,6 +4947,14 @@ version = "1.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "stable_mir"
|
||||
version = "0.1.0-preview"
|
||||
dependencies = [
|
||||
"scoped-tls",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stacker"
|
||||
version = "0.1.15"
|
||||
|
|
@ -5012,6 +4993,8 @@ dependencies = [
|
|||
"panic_abort",
|
||||
"panic_unwind",
|
||||
"profiler_builtins",
|
||||
"r-efi",
|
||||
"r-efi-alloc",
|
||||
"rand",
|
||||
"rand_xorshift",
|
||||
"rustc-demangle",
|
||||
|
|
@ -5173,15 +5156,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.6.0"
|
||||
version = "3.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6"
|
||||
checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"redox_syscall 0.3.5",
|
||||
"rustix 0.37.22",
|
||||
"rustix",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
|
|
@ -5218,11 +5200,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "terminal_size"
|
||||
version = "0.2.6"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237"
|
||||
checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7"
|
||||
dependencies = [
|
||||
"rustix 0.37.22",
|
||||
"rustix",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
|
|||
# Make sure rustc_smir ends up in the sysroot, because this
|
||||
# crate is intended to be used by stable MIR consumers, which are not in-tree
|
||||
rustc_smir = { path = "../rustc_smir" }
|
||||
stable_mir = { path = "../stable_mir" }
|
||||
|
||||
[dependencies.jemalloc-sys]
|
||||
version = "0.5.0"
|
||||
|
|
|
|||
|
|
@ -37,9 +37,10 @@ use std::ptr::{self, NonNull};
|
|||
use std::slice;
|
||||
use std::{cmp, intrinsics};
|
||||
|
||||
/// This calls the passed function while ensuring it won't be inlined into the caller.
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
fn cold_path<F: FnOnce() -> R, R>(f: F) -> R {
|
||||
fn outline<F: FnOnce() -> R, R>(f: F) -> R {
|
||||
f()
|
||||
}
|
||||
|
||||
|
|
@ -600,7 +601,7 @@ impl DroplessArena {
|
|||
unsafe { self.write_from_iter(iter, len, mem) }
|
||||
}
|
||||
(_, _) => {
|
||||
cold_path(move || -> &mut [T] {
|
||||
outline(move || -> &mut [T] {
|
||||
let mut vec: SmallVec<[_; 8]> = iter.collect();
|
||||
if vec.is_empty() {
|
||||
return &mut [];
|
||||
|
|
|
|||
|
|
@ -1664,7 +1664,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
lifetime.ident,
|
||||
));
|
||||
|
||||
// Now make an arg that we can use for the substs of the opaque tykind.
|
||||
// Now make an arg that we can use for the generic params of the opaque tykind.
|
||||
let id = self.next_node_id();
|
||||
let lifetime_arg = self.new_named_lifetime_with_res(id, lifetime.ident, res);
|
||||
let duplicated_lifetime_def_id = self.local_def_id(duplicated_lifetime_node_id);
|
||||
|
|
|
|||
|
|
@ -578,11 +578,11 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
}
|
||||
}
|
||||
|
||||
// All uses of `gate_all!` below this point were added in #65742,
|
||||
// All uses of `gate_all_legacy_dont_use!` below this point were added in #65742,
|
||||
// and subsequently disabled (with the non-early gating readded).
|
||||
// We emit an early future-incompatible warning for these.
|
||||
// New syntax gates should go above here to get a hard error gate.
|
||||
macro_rules! gate_all {
|
||||
macro_rules! gate_all_legacy_dont_use {
|
||||
($gate:ident, $msg:literal) => {
|
||||
for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
|
||||
gate_feature_post!(future_incompatible; &visitor, $gate, *span, $msg);
|
||||
|
|
@ -590,13 +590,19 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
};
|
||||
}
|
||||
|
||||
gate_all!(trait_alias, "trait aliases are experimental");
|
||||
gate_all!(associated_type_bounds, "associated type bounds are unstable");
|
||||
gate_all!(return_type_notation, "return type notation is experimental");
|
||||
gate_all!(decl_macro, "`macro` is experimental");
|
||||
gate_all!(box_patterns, "box pattern syntax is experimental");
|
||||
gate_all!(exclusive_range_pattern, "exclusive range pattern syntax is experimental");
|
||||
gate_all!(try_blocks, "`try` blocks are unstable");
|
||||
gate_all_legacy_dont_use!(trait_alias, "trait aliases are experimental");
|
||||
gate_all_legacy_dont_use!(associated_type_bounds, "associated type bounds are unstable");
|
||||
// Despite being a new feature, `where T: Trait<Assoc(): Sized>`, which is RTN syntax now,
|
||||
// used to be gated under associated_type_bounds, which are right above, so RTN needs to
|
||||
// be too.
|
||||
gate_all_legacy_dont_use!(return_type_notation, "return type notation is experimental");
|
||||
gate_all_legacy_dont_use!(decl_macro, "`macro` is experimental");
|
||||
gate_all_legacy_dont_use!(box_patterns, "box pattern syntax is experimental");
|
||||
gate_all_legacy_dont_use!(
|
||||
exclusive_range_pattern,
|
||||
"exclusive range pattern syntax is experimental"
|
||||
);
|
||||
gate_all_legacy_dont_use!(try_blocks, "`try` blocks are unstable");
|
||||
|
||||
visit::walk_crate(&mut visitor, krate);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ pub(crate) struct RegionName {
|
|||
/// This helps to print the right kinds of diagnostics.
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) enum RegionNameSource {
|
||||
/// A bound (not free) region that was substituted at the def site (not an HRTB).
|
||||
/// A bound (not free) region that was instantiated at the def site (not an HRTB).
|
||||
NamedEarlyBoundRegion(Span),
|
||||
/// A free region that the user has a name (`'a`) for.
|
||||
NamedFreeRegion(Span),
|
||||
|
|
@ -354,7 +354,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
ty::BoundRegionKind::BrAnon(..) => None,
|
||||
ty::BoundRegionKind::BrAnon => None,
|
||||
},
|
||||
|
||||
ty::ReLateBound(..)
|
||||
|
|
@ -516,7 +516,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
// be the same as those of the ADT.
|
||||
// FIXME: We should be able to do something similar to
|
||||
// match_adt_and_segment in this case.
|
||||
Res::Def(DefKind::TyAlias { .. }, _) => (),
|
||||
Res::Def(DefKind::TyAlias, _) => (),
|
||||
_ => {
|
||||
if let Some(last_segment) = path.segments.last() {
|
||||
if let Some(highlight) = self.match_adt_and_segment(
|
||||
|
|
@ -619,7 +619,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
// programs, so we need to use delay_span_bug here. See #82126.
|
||||
self.infcx.tcx.sess.delay_span_bug(
|
||||
hir_arg.span(),
|
||||
format!("unmatched subst and hir arg: found {kind:?} vs {hir_arg:?}"),
|
||||
format!("unmatched arg and hir arg: found {kind:?} vs {hir_arg:?}"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2250,7 +2250,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
|
||||
pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
|
||||
// Query canonicalization can create local superuniverses (for example in
|
||||
// `InferCtx::query_response_substitution_guess`), but they don't have an associated
|
||||
// `InferCtx::query_response_instantiation_guess`), but they don't have an associated
|
||||
// `UniverseInfo` explaining why they were created.
|
||||
// This can cause ICEs if these causes are accessed in diagnostics, for example in issue
|
||||
// #114907 where this happens via liveness and dropck outlives results.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use rustc_middle::mir::visit::{MutVisitor, TyContext};
|
|||
use rustc_middle::mir::{Body, ConstOperand, Location, Promoted};
|
||||
use rustc_middle::ty::GenericArgsRef;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_span::Symbol;
|
||||
|
||||
/// Replaces all free regions appearing in the MIR with fresh
|
||||
/// inference variables, returning the number of variables created.
|
||||
|
|
@ -28,21 +28,15 @@ pub fn renumber_mir<'tcx>(
|
|||
renumberer.visit_body(body);
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub(crate) enum BoundRegionInfo {
|
||||
Name(Symbol),
|
||||
Span(Span),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub(crate) enum RegionCtxt {
|
||||
Location(Location),
|
||||
TyContext(TyContext),
|
||||
Free(Symbol),
|
||||
Bound(BoundRegionInfo),
|
||||
LateBound(BoundRegionInfo),
|
||||
Bound(Symbol),
|
||||
LateBound(Symbol),
|
||||
Existential(Option<Symbol>),
|
||||
Placeholder(BoundRegionInfo),
|
||||
Placeholder(Symbol),
|
||||
Unknown,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1007,7 +1007,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
|
||||
pub(super) fn register_predefined_opaques_in_new_solver(&mut self) {
|
||||
// OK to use the identity substitutions for each opaque type key, since
|
||||
// OK to use the identity arguments for each opaque type key, since
|
||||
// we remap opaques from HIR typeck back to their definition params.
|
||||
let opaques: Vec<_> = self
|
||||
.infcx
|
||||
|
|
@ -1367,14 +1367,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
};
|
||||
let (sig, map) = tcx.replace_late_bound_regions(sig, |br| {
|
||||
use crate::renumber::{BoundRegionInfo, RegionCtxt};
|
||||
use crate::renumber::RegionCtxt;
|
||||
|
||||
let region_ctxt_fn = || {
|
||||
let reg_info = match br.kind {
|
||||
ty::BoundRegionKind::BrAnon(Some(span)) => BoundRegionInfo::Span(span),
|
||||
ty::BoundRegionKind::BrAnon(..) => BoundRegionInfo::Name(sym::anon),
|
||||
ty::BoundRegionKind::BrNamed(_, name) => BoundRegionInfo::Name(name),
|
||||
ty::BoundRegionKind::BrEnv => BoundRegionInfo::Name(sym::env),
|
||||
ty::BoundRegionKind::BrAnon => sym::anon,
|
||||
ty::BoundRegionKind::BrNamed(_, name) => name,
|
||||
ty::BoundRegionKind::BrEnv => sym::env,
|
||||
};
|
||||
|
||||
RegionCtxt::LateBound(reg_info)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc_span::{Span, Symbol};
|
|||
|
||||
use crate::constraints::OutlivesConstraint;
|
||||
use crate::diagnostics::UniverseInfo;
|
||||
use crate::renumber::{BoundRegionInfo, RegionCtxt};
|
||||
use crate::renumber::RegionCtxt;
|
||||
use crate::type_check::{InstantiateOpaqueType, Locations, TypeChecker};
|
||||
|
||||
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
|
|
@ -126,10 +126,9 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
|
|||
.placeholder_region(self.type_checker.infcx, placeholder);
|
||||
|
||||
let reg_info = match placeholder.bound.kind {
|
||||
ty::BoundRegionKind::BrAnon(Some(span)) => BoundRegionInfo::Span(span),
|
||||
ty::BoundRegionKind::BrAnon(..) => BoundRegionInfo::Name(sym::anon),
|
||||
ty::BoundRegionKind::BrNamed(_, name) => BoundRegionInfo::Name(name),
|
||||
ty::BoundRegionKind::BrEnv => BoundRegionInfo::Name(sym::env),
|
||||
ty::BoundRegionKind::BrAnon => sym::anon,
|
||||
ty::BoundRegionKind::BrNamed(_, name) => name,
|
||||
ty::BoundRegionKind::BrEnv => sym::env,
|
||||
};
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ use rustc_span::symbol::{kw, sym};
|
|||
use rustc_span::Symbol;
|
||||
use std::iter;
|
||||
|
||||
use crate::renumber::{BoundRegionInfo, RegionCtxt};
|
||||
use crate::renumber::RegionCtxt;
|
||||
use crate::BorrowckInferCtxt;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -446,9 +446,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||
if !indices.indices.contains_key(&r) {
|
||||
let region_vid = {
|
||||
let name = r.get_name_or_anon();
|
||||
self.infcx.next_nll_region_var(FR, || {
|
||||
RegionCtxt::LateBound(BoundRegionInfo::Name(name))
|
||||
})
|
||||
self.infcx.next_nll_region_var(FR, || RegionCtxt::LateBound(name))
|
||||
};
|
||||
|
||||
debug!(?region_vid);
|
||||
|
|
@ -480,9 +478,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||
if !indices.indices.contains_key(&r) {
|
||||
let region_vid = {
|
||||
let name = r.get_name_or_anon();
|
||||
self.infcx.next_nll_region_var(FR, || {
|
||||
RegionCtxt::LateBound(BoundRegionInfo::Name(name))
|
||||
})
|
||||
self.infcx.next_nll_region_var(FR, || RegionCtxt::LateBound(name))
|
||||
};
|
||||
|
||||
debug!(?region_vid);
|
||||
|
|
@ -643,10 +639,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||
};
|
||||
|
||||
let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static));
|
||||
let subst_mapping =
|
||||
iter::zip(identity_args.regions(), fr_args.regions().map(|r| r.as_var()));
|
||||
let arg_mapping = iter::zip(identity_args.regions(), fr_args.regions().map(|r| r.as_var()));
|
||||
|
||||
UniversalRegionIndices { indices: global_mapping.chain(subst_mapping).collect(), fr_static }
|
||||
UniversalRegionIndices { indices: global_mapping.chain(arg_mapping).collect(), fr_static }
|
||||
}
|
||||
|
||||
fn compute_inputs_and_output(
|
||||
|
|
@ -796,7 +791,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
|
|||
_ => sym::anon,
|
||||
};
|
||||
|
||||
self.next_nll_region_var(origin, || RegionCtxt::Bound(BoundRegionInfo::Name(name)))
|
||||
self.next_nll_region_var(origin, || RegionCtxt::Bound(name))
|
||||
};
|
||||
|
||||
indices.insert_late_bound_region(liberated_region, region_vid.as_var());
|
||||
|
|
@ -826,9 +821,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
|
|||
if !indices.indices.contains_key(&r) {
|
||||
let region_vid = {
|
||||
let name = r.get_name_or_anon();
|
||||
self.next_nll_region_var(FR, || {
|
||||
RegionCtxt::LateBound(BoundRegionInfo::Name(name))
|
||||
})
|
||||
self.next_nll_region_var(FR, || RegionCtxt::LateBound(name))
|
||||
};
|
||||
|
||||
debug!(?region_vid);
|
||||
|
|
@ -848,9 +841,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
|
|||
if !indices.indices.contains_key(&r) {
|
||||
let region_vid = {
|
||||
let name = r.get_name_or_anon();
|
||||
self.next_nll_region_var(FR, || {
|
||||
RegionCtxt::LateBound(BoundRegionInfo::Name(name))
|
||||
})
|
||||
self.next_nll_region_var(FR, || RegionCtxt::LateBound(name))
|
||||
};
|
||||
|
||||
indices.insert_late_bound_region(r, region_vid.as_var());
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ pub fn expand_deriving_const_param_ty(
|
|||
path: path_std!(marker::ConstParamTy),
|
||||
skip_path_as_bound: false,
|
||||
needs_copy_as_bound_if_packed: false,
|
||||
additional_bounds: Vec::new(),
|
||||
additional_bounds: vec![ty::Ty::Path(path_std!(cmp::Eq))],
|
||||
supports_unions: false,
|
||||
methods: Vec::new(),
|
||||
associated_types: Vec::new(),
|
||||
|
|
|
|||
|
|
@ -100,9 +100,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
stack = &stack[..index + ENCODE_METADATA.len()];
|
||||
}
|
||||
|
||||
const SUBST_AND_NORMALIZE_ERASING_REGIONS: &str = "rustc_middle::ty::normalize_erasing_regions::<impl rustc_middle::ty::context::TyCtxt>::subst_and_normalize_erasing_regions";
|
||||
if let Some(index) = stack.find(SUBST_AND_NORMALIZE_ERASING_REGIONS) {
|
||||
stack = &stack[..index + SUBST_AND_NORMALIZE_ERASING_REGIONS.len()];
|
||||
const INSTANTIATE_AND_NORMALIZE_ERASING_REGIONS: &str = "rustc_middle::ty::normalize_erasing_regions::<impl rustc_middle::ty::context::TyCtxt>::instantiate_and_normalize_erasing_regions";
|
||||
if let Some(index) = stack.find(INSTANTIATE_AND_NORMALIZE_ERASING_REGIONS) {
|
||||
stack = &stack[..index + INSTANTIATE_AND_NORMALIZE_ERASING_REGIONS.len()];
|
||||
}
|
||||
|
||||
const NORMALIZE_ERASING_LATE_BOUND_REGIONS: &str = "rustc_middle::ty::normalize_erasing_regions::<impl rustc_middle::ty::context::TyCtxt>::normalize_erasing_late_bound_regions";
|
||||
|
|
|
|||
|
|
@ -359,7 +359,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
|
|||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>> + Copy,
|
||||
{
|
||||
self.instance.subst_mir_and_normalize_erasing_regions(
|
||||
self.instance.instantiate_mir_and_normalize_erasing_regions(
|
||||
self.tcx,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
ty::EarlyBinder::bind(value),
|
||||
|
|
|
|||
103
compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs
Normal file
103
compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
use std::{
|
||||
ffi::{c_char, CStr},
|
||||
marker::PhantomData,
|
||||
ops::Deref,
|
||||
ptr::NonNull,
|
||||
};
|
||||
|
||||
use rustc_data_structures::small_c_str::SmallCStr;
|
||||
|
||||
use crate::{errors::LlvmError, llvm};
|
||||
|
||||
/// Responsible for safely creating and disposing llvm::TargetMachine via ffi functions.
|
||||
/// Not cloneable as there is no clone function for llvm::TargetMachine.
|
||||
#[repr(transparent)]
|
||||
pub struct OwnedTargetMachine {
|
||||
tm_unique: NonNull<llvm::TargetMachine>,
|
||||
phantom: PhantomData<llvm::TargetMachine>,
|
||||
}
|
||||
|
||||
impl OwnedTargetMachine {
|
||||
pub fn new(
|
||||
triple: &CStr,
|
||||
cpu: &CStr,
|
||||
features: &CStr,
|
||||
abi: &CStr,
|
||||
model: llvm::CodeModel,
|
||||
reloc: llvm::RelocModel,
|
||||
level: llvm::CodeGenOptLevel,
|
||||
use_soft_fp: bool,
|
||||
function_sections: bool,
|
||||
data_sections: bool,
|
||||
unique_section_names: bool,
|
||||
trap_unreachable: bool,
|
||||
singletree: bool,
|
||||
asm_comments: bool,
|
||||
emit_stack_size_section: bool,
|
||||
relax_elf_relocations: bool,
|
||||
use_init_array: bool,
|
||||
split_dwarf_file: &CStr,
|
||||
output_obj_file: &CStr,
|
||||
debug_info_compression: &CStr,
|
||||
force_emulated_tls: bool,
|
||||
args_cstr_buff: &[u8],
|
||||
) -> Result<Self, LlvmError<'static>> {
|
||||
assert!(args_cstr_buff.len() > 0);
|
||||
assert!(
|
||||
*args_cstr_buff.last().unwrap() == 0,
|
||||
"The last character must be a null terminator."
|
||||
);
|
||||
|
||||
// SAFETY: llvm::LLVMRustCreateTargetMachine copies pointed to data
|
||||
let tm_ptr = unsafe {
|
||||
llvm::LLVMRustCreateTargetMachine(
|
||||
triple.as_ptr(),
|
||||
cpu.as_ptr(),
|
||||
features.as_ptr(),
|
||||
abi.as_ptr(),
|
||||
model,
|
||||
reloc,
|
||||
level,
|
||||
use_soft_fp,
|
||||
function_sections,
|
||||
data_sections,
|
||||
unique_section_names,
|
||||
trap_unreachable,
|
||||
singletree,
|
||||
asm_comments,
|
||||
emit_stack_size_section,
|
||||
relax_elf_relocations,
|
||||
use_init_array,
|
||||
split_dwarf_file.as_ptr(),
|
||||
output_obj_file.as_ptr(),
|
||||
debug_info_compression.as_ptr(),
|
||||
force_emulated_tls,
|
||||
args_cstr_buff.as_ptr() as *const c_char,
|
||||
args_cstr_buff.len(),
|
||||
)
|
||||
};
|
||||
|
||||
NonNull::new(tm_ptr)
|
||||
.map(|tm_unique| Self { tm_unique, phantom: PhantomData })
|
||||
.ok_or_else(|| LlvmError::CreateTargetMachine { triple: SmallCStr::from(triple) })
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for OwnedTargetMachine {
|
||||
type Target = llvm::TargetMachine;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
// SAFETY: constructing ensures we have a valid pointer created by llvm::LLVMRustCreateTargetMachine
|
||||
unsafe { self.tm_unique.as_ref() }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for OwnedTargetMachine {
|
||||
fn drop(&mut self) {
|
||||
// SAFETY: constructing ensures we have a valid pointer created by llvm::LLVMRustCreateTargetMachine
|
||||
// OwnedTargetMachine is not copyable so there is no double free or use after free
|
||||
unsafe {
|
||||
llvm::LLVMRustDisposeTargetMachine(self.tm_unique.as_mut());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::back::lto::ThinBuffer;
|
||||
use crate::back::owned_target_machine::OwnedTargetMachine;
|
||||
use crate::back::profiling::{
|
||||
selfprofile_after_pass_callback, selfprofile_before_pass_callback, LlvmSelfProfiler,
|
||||
};
|
||||
|
|
@ -98,8 +99,8 @@ pub fn write_output_file<'ll>(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn create_informational_target_machine(sess: &Session) -> &'static mut llvm::TargetMachine {
|
||||
let config = TargetMachineFactoryConfig { split_dwarf_file: None };
|
||||
pub fn create_informational_target_machine(sess: &Session) -> OwnedTargetMachine {
|
||||
let config = TargetMachineFactoryConfig { split_dwarf_file: None, output_obj_file: None };
|
||||
// Can't use query system here quite yet because this function is invoked before the query
|
||||
// system/tcx is set up.
|
||||
let features = llvm_util::global_llvm_features(sess, false);
|
||||
|
|
@ -107,7 +108,7 @@ pub fn create_informational_target_machine(sess: &Session) -> &'static mut llvm:
|
|||
.unwrap_or_else(|err| llvm_err(sess.diagnostic(), err).raise())
|
||||
}
|
||||
|
||||
pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> &'static mut llvm::TargetMachine {
|
||||
pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTargetMachine {
|
||||
let split_dwarf_file = if tcx.sess.target_can_use_split_dwarf() {
|
||||
tcx.output_filenames(()).split_dwarf_path(
|
||||
tcx.sess.split_debuginfo(),
|
||||
|
|
@ -117,7 +118,11 @@ pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> &'static mut ll
|
|||
} else {
|
||||
None
|
||||
};
|
||||
let config = TargetMachineFactoryConfig { split_dwarf_file };
|
||||
|
||||
let output_obj_file =
|
||||
Some(tcx.output_filenames(()).temp_path(OutputType::Object, Some(mod_name)));
|
||||
let config = TargetMachineFactoryConfig { split_dwarf_file, output_obj_file };
|
||||
|
||||
target_machine_factory(
|
||||
&tcx.sess,
|
||||
tcx.backend_optimization_level(()),
|
||||
|
|
@ -255,38 +260,38 @@ pub fn target_machine_factory(
|
|||
let debuginfo_compression = SmallCStr::new(&debuginfo_compression);
|
||||
|
||||
Arc::new(move |config: TargetMachineFactoryConfig| {
|
||||
let split_dwarf_file =
|
||||
path_mapping.map_prefix(config.split_dwarf_file.unwrap_or_default()).0;
|
||||
let split_dwarf_file = CString::new(split_dwarf_file.to_str().unwrap()).unwrap();
|
||||
|
||||
let tm = unsafe {
|
||||
llvm::LLVMRustCreateTargetMachine(
|
||||
triple.as_ptr(),
|
||||
cpu.as_ptr(),
|
||||
features.as_ptr(),
|
||||
abi.as_ptr(),
|
||||
code_model,
|
||||
reloc_model,
|
||||
opt_level,
|
||||
use_softfp,
|
||||
ffunction_sections,
|
||||
fdata_sections,
|
||||
funique_section_names,
|
||||
trap_unreachable,
|
||||
singlethread,
|
||||
asm_comments,
|
||||
emit_stack_size_section,
|
||||
relax_elf_relocations,
|
||||
use_init_array,
|
||||
split_dwarf_file.as_ptr(),
|
||||
debuginfo_compression.as_ptr(),
|
||||
force_emulated_tls,
|
||||
args_cstr_buff.as_ptr() as *const c_char,
|
||||
args_cstr_buff.len(),
|
||||
)
|
||||
let path_to_cstring_helper = |path: Option<PathBuf>| -> CString {
|
||||
let path = path_mapping.map_prefix(path.unwrap_or_default()).0;
|
||||
CString::new(path.to_str().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
tm.ok_or_else(|| LlvmError::CreateTargetMachine { triple: triple.clone() })
|
||||
let split_dwarf_file = path_to_cstring_helper(config.split_dwarf_file);
|
||||
let output_obj_file = path_to_cstring_helper(config.output_obj_file);
|
||||
|
||||
OwnedTargetMachine::new(
|
||||
&triple,
|
||||
&cpu,
|
||||
&features,
|
||||
&abi,
|
||||
code_model,
|
||||
reloc_model,
|
||||
opt_level,
|
||||
use_softfp,
|
||||
ffunction_sections,
|
||||
fdata_sections,
|
||||
funique_section_names,
|
||||
trap_unreachable,
|
||||
singlethread,
|
||||
asm_comments,
|
||||
emit_stack_size_section,
|
||||
relax_elf_relocations,
|
||||
use_init_array,
|
||||
&split_dwarf_file,
|
||||
&output_obj_file,
|
||||
&debuginfo_compression,
|
||||
force_emulated_tls,
|
||||
&args_cstr_buff,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -160,9 +160,9 @@ pub unsafe fn create_module<'ll>(
|
|||
|
||||
// Ensure the data-layout values hardcoded remain the defaults.
|
||||
if sess.target.is_builtin {
|
||||
// tm is disposed by its drop impl
|
||||
let tm = crate::back::write::create_informational_target_machine(tcx.sess);
|
||||
llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm);
|
||||
llvm::LLVMRustDisposeTargetMachine(tm);
|
||||
llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm);
|
||||
|
||||
let llvm_data_layout = llvm::LLVMGetDataLayoutStr(llmod);
|
||||
let llvm_data_layout = str::from_utf8(CStr::from_ptr(llvm_data_layout).to_bytes())
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ fn make_mir_scope<'ll, 'tcx>(
|
|||
Some((callee, _)) => {
|
||||
// FIXME(eddyb) this would be `self.monomorphize(&callee)`
|
||||
// if this is moved to `rustc_codegen_ssa::mir::debuginfo`.
|
||||
let callee = cx.tcx.subst_and_normalize_erasing_regions(
|
||||
let callee = cx.tcx.instantiate_and_normalize_erasing_regions(
|
||||
instance.args,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
ty::EarlyBinder::bind(callee),
|
||||
|
|
|
|||
|
|
@ -529,7 +529,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
if let Some(impl_def_id) = cx.tcx.impl_of_method(instance.def_id()) {
|
||||
// If the method does *not* belong to a trait, proceed
|
||||
if cx.tcx.trait_id_of_impl(impl_def_id).is_none() {
|
||||
let impl_self_ty = cx.tcx.subst_and_normalize_erasing_regions(
|
||||
let impl_self_ty = cx.tcx.instantiate_and_normalize_erasing_regions(
|
||||
instance.args,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
cx.tcx.type_of(impl_def_id),
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ extern crate rustc_macros;
|
|||
#[macro_use]
|
||||
extern crate tracing;
|
||||
|
||||
use back::owned_target_machine::OwnedTargetMachine;
|
||||
use back::write::{create_informational_target_machine, create_target_machine};
|
||||
|
||||
use errors::ParseTargetMachineConfig;
|
||||
|
|
@ -52,6 +53,7 @@ use std::io::Write;
|
|||
mod back {
|
||||
pub mod archive;
|
||||
pub mod lto;
|
||||
pub mod owned_target_machine;
|
||||
mod profiling;
|
||||
pub mod write;
|
||||
}
|
||||
|
|
@ -162,7 +164,7 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
|
|||
impl WriteBackendMethods for LlvmCodegenBackend {
|
||||
type Module = ModuleLlvm;
|
||||
type ModuleBuffer = back::lto::ModuleBuffer;
|
||||
type TargetMachine = &'static mut llvm::TargetMachine;
|
||||
type TargetMachine = OwnedTargetMachine;
|
||||
type TargetMachineError = crate::errors::LlvmError<'static>;
|
||||
type ThinData = back::lto::ThinData;
|
||||
type ThinBuffer = back::lto::ThinBuffer;
|
||||
|
|
@ -401,7 +403,9 @@ impl CodegenBackend for LlvmCodegenBackend {
|
|||
pub struct ModuleLlvm {
|
||||
llcx: &'static mut llvm::Context,
|
||||
llmod_raw: *const llvm::Module,
|
||||
tm: &'static mut llvm::TargetMachine,
|
||||
|
||||
// independent from llcx and llmod_raw, resources get disposed by drop impl
|
||||
tm: OwnedTargetMachine,
|
||||
}
|
||||
|
||||
unsafe impl Send for ModuleLlvm {}
|
||||
|
|
@ -453,7 +457,6 @@ impl ModuleLlvm {
|
|||
impl Drop for ModuleLlvm {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
llvm::LLVMRustDisposeTargetMachine(&mut *(self.tm as *mut _));
|
||||
llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2112,6 +2112,8 @@ extern "C" {
|
|||
);
|
||||
|
||||
pub fn LLVMRustGetHostCPUName(len: *mut usize) -> *const c_char;
|
||||
|
||||
// This function makes copies of pointed to data, so the data's lifetime may end after this function returns
|
||||
pub fn LLVMRustCreateTargetMachine(
|
||||
Triple: *const c_char,
|
||||
CPU: *const c_char,
|
||||
|
|
@ -2131,13 +2133,14 @@ extern "C" {
|
|||
RelaxELFRelocations: bool,
|
||||
UseInitArray: bool,
|
||||
SplitDwarfFile: *const c_char,
|
||||
OutputObjFile: *const c_char,
|
||||
DebugInfoCompression: *const c_char,
|
||||
ForceEmulatedTls: bool,
|
||||
ArgsCstrBuff: *const c_char,
|
||||
ArgsCstrBuffLen: usize,
|
||||
) -> Option<&'static mut TargetMachine>;
|
||||
) -> *mut TargetMachine;
|
||||
|
||||
pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine);
|
||||
pub fn LLVMRustDisposeTargetMachine(T: *mut TargetMachine);
|
||||
pub fn LLVMRustAddLibraryInfo<'a>(
|
||||
PM: &PassManager<'a>,
|
||||
M: &'a Module,
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
|
|||
// check that all features in a given smallvec are enabled
|
||||
for llvm_feature in to_llvm_features(sess, feature) {
|
||||
let cstr = SmallCStr::new(llvm_feature);
|
||||
if !unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) } {
|
||||
if !unsafe { llvm::LLVMRustHasFeature(&target_machine, cstr.as_ptr()) } {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -422,14 +422,14 @@ pub(crate) fn print(req: &PrintRequest, mut out: &mut dyn PrintBackendInfo, sess
|
|||
}
|
||||
unsafe {
|
||||
llvm::LLVMRustPrintTargetCPUs(
|
||||
tm,
|
||||
&tm,
|
||||
cpu_cstring.as_ptr(),
|
||||
callback,
|
||||
&mut out as *mut &mut dyn PrintBackendInfo as *mut c_void,
|
||||
);
|
||||
}
|
||||
}
|
||||
PrintKind::TargetFeatures => print_target_features(out, sess, tm),
|
||||
PrintKind::TargetFeatures => print_target_features(out, sess, &tm),
|
||||
_ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -286,6 +286,10 @@ pub struct TargetMachineFactoryConfig {
|
|||
/// so the path to the dwarf object has to be provided when we create the target machine.
|
||||
/// This can be ignored by backends which do not need it for their Split DWARF support.
|
||||
pub split_dwarf_file: Option<PathBuf>,
|
||||
|
||||
/// The name of the output object file. Used for setting OutputFilenames in target options
|
||||
/// so that LLVM can emit the CodeView S_OBJNAME record in pdb files
|
||||
pub output_obj_file: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl TargetMachineFactoryConfig {
|
||||
|
|
@ -302,7 +306,10 @@ impl TargetMachineFactoryConfig {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
TargetMachineFactoryConfig { split_dwarf_file }
|
||||
|
||||
let output_obj_file =
|
||||
Some(cgcx.output_filenames.temp_path(OutputType::Object, Some(module_name)));
|
||||
TargetMachineFactoryConfig { split_dwarf_file, output_obj_file }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -420,9 +420,11 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
rust_main_def_id: DefId,
|
||||
entry_type: EntryFnType,
|
||||
) -> Bx::Function {
|
||||
// The entry function is either `int main(void)` or `int main(int argc, char **argv)`,
|
||||
// depending on whether the target needs `argc` and `argv` to be passed in.
|
||||
let llfty = if cx.sess().target.main_needs_argc_argv {
|
||||
// The entry function is either `int main(void)` or `int main(int argc, char **argv)`, or
|
||||
// `usize efi_main(void *handle, void *system_table)` depending on the target.
|
||||
let llfty = if cx.sess().target.os.contains("uefi") {
|
||||
cx.type_func(&[cx.type_ptr(), cx.type_ptr()], cx.type_isize())
|
||||
} else if cx.sess().target.main_needs_argc_argv {
|
||||
cx.type_func(&[cx.type_int(), cx.type_ptr()], cx.type_int())
|
||||
} else {
|
||||
cx.type_func(&[], cx.type_int())
|
||||
|
|
@ -485,8 +487,12 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
};
|
||||
|
||||
let result = bx.call(start_ty, None, None, start_fn, &args, None);
|
||||
let cast = bx.intcast(result, cx.type_int(), true);
|
||||
bx.ret(cast);
|
||||
if cx.sess().target.os.contains("uefi") {
|
||||
bx.ret(result);
|
||||
} else {
|
||||
let cast = bx.intcast(result, cx.type_int(), true);
|
||||
bx.ret(cast);
|
||||
}
|
||||
|
||||
llfn
|
||||
}
|
||||
|
|
@ -497,7 +503,17 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
cx: &'a Bx::CodegenCx,
|
||||
bx: &mut Bx,
|
||||
) -> (Bx::Value, Bx::Value) {
|
||||
if cx.sess().target.main_needs_argc_argv {
|
||||
if cx.sess().target.os.contains("uefi") {
|
||||
// Params for UEFI
|
||||
let param_handle = bx.get_param(0);
|
||||
let param_system_table = bx.get_param(1);
|
||||
let arg_argc = bx.const_int(cx.type_isize(), 2);
|
||||
let arg_argv = bx.alloca(cx.type_array(cx.type_ptr(), 2), Align::ONE);
|
||||
bx.store(param_handle, arg_argv, Align::ONE);
|
||||
let arg_argv_el1 = bx.gep(cx.type_ptr(), arg_argv, &[bx.const_int(cx.type_int(), 1)]);
|
||||
bx.store(param_system_table, arg_argv_el1, Align::ONE);
|
||||
(arg_argc, arg_argv)
|
||||
} else if cx.sess().target.main_needs_argc_argv {
|
||||
// Params from native `main()` used as args for rust start function
|
||||
let param_argc = bx.get_param(0);
|
||||
let param_argv = bx.get_param(1);
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
T: Copy + TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
debug!("monomorphize: self.instance={:?}", self.instance);
|
||||
self.instance.subst_mir_and_normalize_erasing_regions(
|
||||
self.instance.instantiate_mir_and_normalize_erasing_regions(
|
||||
self.cx.tcx(),
|
||||
ty::ParamEnv::reveal_all(),
|
||||
ty::EarlyBinder::bind(value),
|
||||
|
|
|
|||
|
|
@ -135,15 +135,14 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
|
|||
assert_eq!(alloc_align, layout.align.abi);
|
||||
|
||||
let read_scalar = |start, size, s: abi::Scalar, ty| {
|
||||
let val = alloc
|
||||
.0
|
||||
.read_scalar(
|
||||
bx,
|
||||
alloc_range(start, size),
|
||||
/*read_provenance*/ matches!(s.primitive(), abi::Pointer(_)),
|
||||
)
|
||||
.unwrap();
|
||||
bx.scalar_to_backend(val, s, ty)
|
||||
match alloc.0.read_scalar(
|
||||
bx,
|
||||
alloc_range(start, size),
|
||||
/*read_provenance*/ matches!(s.primitive(), abi::Pointer(_)),
|
||||
) {
|
||||
Ok(val) => bx.scalar_to_backend(val, s, ty),
|
||||
Err(_) => bx.const_poison(ty),
|
||||
}
|
||||
};
|
||||
|
||||
// It may seem like all types with `Scalar` or `ScalarPair` ABI are fair game at this point.
|
||||
|
|
@ -156,7 +155,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
|
|||
Abi::Scalar(s @ abi::Scalar::Initialized { .. }) => {
|
||||
let size = s.size(bx);
|
||||
assert_eq!(size, layout.size, "abi::Scalar size does not match layout size");
|
||||
let val = read_scalar(Size::ZERO, size, s, bx.type_ptr());
|
||||
let val = read_scalar(offset, size, s, bx.backend_type(layout));
|
||||
OperandRef { val: OperandValue::Immediate(val), layout }
|
||||
}
|
||||
Abi::ScalarPair(
|
||||
|
|
@ -164,10 +163,10 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
|
|||
b @ abi::Scalar::Initialized { .. },
|
||||
) => {
|
||||
let (a_size, b_size) = (a.size(bx), b.size(bx));
|
||||
let b_offset = a_size.align_to(b.align(bx).abi);
|
||||
let b_offset = (offset + a_size).align_to(b.align(bx).abi);
|
||||
assert!(b_offset.bytes() > 0);
|
||||
let a_val = read_scalar(
|
||||
Size::ZERO,
|
||||
offset,
|
||||
a_size,
|
||||
a,
|
||||
bx.scalar_pair_element_backend_type(layout, 0, true),
|
||||
|
|
|
|||
|
|
@ -569,7 +569,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
) -> Result<T, ErrorHandled> {
|
||||
frame
|
||||
.instance
|
||||
.try_subst_mir_and_normalize_erasing_regions(
|
||||
.try_instantiate_mir_and_normalize_erasing_regions(
|
||||
*self.tcx,
|
||||
self.param_env,
|
||||
ty::EarlyBinder::bind(value),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use rustc_middle::ty::{
|
|||
};
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
/// Checks whether a type contains generic parameters which require substitution.
|
||||
/// Checks whether a type contains generic parameters which must be instantiated.
|
||||
///
|
||||
/// In case it does, returns a `TooGeneric` const eval error. Note that due to polymorphization
|
||||
/// types may be "concrete enough" even though they still contain generic parameters in
|
||||
|
|
@ -43,7 +43,8 @@ where
|
|||
.try_into()
|
||||
.expect("more generic parameters than can fit into a `u32`");
|
||||
// Only recurse when generic parameters in fns, closures and generators
|
||||
// are used and require substitution.
|
||||
// are used and have to be instantiated.
|
||||
//
|
||||
// Just in case there are closures or generators within this subst,
|
||||
// recurse.
|
||||
if unused_params.is_used(index) && subst.has_param() {
|
||||
|
|
|
|||
|
|
@ -558,8 +558,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A faster version of the validation pass that only checks those things which may break when apply
|
||||
/// generic substitutions.
|
||||
/// A faster version of the validation pass that only checks those things which may break when
|
||||
/// instantiating any generic parameters.
|
||||
pub fn validate_types<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
mir_phase: MirPhase,
|
||||
|
|
|
|||
|
|
@ -51,9 +51,10 @@ use std::fmt;
|
|||
|
||||
pub use rustc_index::static_assert_size;
|
||||
|
||||
/// This calls the passed function while ensuring it won't be inlined into the caller.
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
pub fn cold_path<F: FnOnce() -> R, R>(f: F) -> R {
|
||||
pub fn outline<F: FnOnce() -> R, R>(f: F) -> R {
|
||||
f()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -81,8 +81,8 @@
|
|||
//!
|
||||
//! [mm]: https://github.com/rust-lang/measureme/
|
||||
|
||||
use crate::cold_path;
|
||||
use crate::fx::FxHashMap;
|
||||
use crate::outline;
|
||||
|
||||
use std::borrow::Borrow;
|
||||
use std::collections::hash_map::Entry;
|
||||
|
|
@ -697,7 +697,7 @@ impl<'a> TimingGuard<'a> {
|
|||
#[inline]
|
||||
pub fn finish_with_query_invocation_id(self, query_invocation_id: QueryInvocationId) {
|
||||
if let Some(guard) = self.0 {
|
||||
cold_path(|| {
|
||||
outline(|| {
|
||||
let event_id = StringId::new_virtual(query_invocation_id.0);
|
||||
let event_id = EventId::from_virtual(event_id);
|
||||
guard.finish_with_override_event_id(event_id);
|
||||
|
|
|
|||
|
|
@ -79,3 +79,9 @@ impl<'a> FromIterator<&'a str> for SmallCStr {
|
|||
Self { data }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ffi::CStr> for SmallCStr {
|
||||
fn from(s: &ffi::CStr) -> Self {
|
||||
Self { data: SmallVec::from_slice(s.to_bytes()) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use std::ptr;
|
|||
use std::sync::Arc;
|
||||
|
||||
#[cfg(parallel_compiler)]
|
||||
use {crate::cold_path, crate::sync::CacheAligned};
|
||||
use {crate::outline, crate::sync::CacheAligned};
|
||||
|
||||
/// A pointer to the `RegistryData` which uniquely identifies a registry.
|
||||
/// This identifier can be reused if the registry gets freed.
|
||||
|
|
@ -25,11 +25,7 @@ impl RegistryId {
|
|||
fn verify(self) -> usize {
|
||||
let (id, index) = THREAD_DATA.with(|data| (data.registry_id.get(), data.index.get()));
|
||||
|
||||
if id == self {
|
||||
index
|
||||
} else {
|
||||
cold_path(|| panic!("Unable to verify registry association"))
|
||||
}
|
||||
if id == self { index } else { outline(|| panic!("Unable to verify registry association")) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -162,14 +162,13 @@ fn foo<T>(x: T) {
|
|||
```
|
||||
|
||||
The machine code for `foo::<u8>()`, `foo::<bool>()`, `foo::<String>()`, or any
|
||||
other type substitution is different. Hence the compiler generates the
|
||||
other instantiation is different. Hence the compiler generates the
|
||||
implementation on-demand. If you call `foo()` with a `bool` parameter, the
|
||||
compiler will only generate code for `foo::<bool>()`. When we have additional
|
||||
type parameters, the number of monomorphized implementations the compiler
|
||||
generates does not grow drastically, since the compiler will only generate an
|
||||
implementation if the function is called with unparameterized substitutions
|
||||
(i.e., substitutions where none of the substituted types are themselves
|
||||
parameterized).
|
||||
implementation if the function is called with fully concrete arguments
|
||||
(i.e., arguments which do not contain any generic parameters).
|
||||
|
||||
However, with trait objects we have to make a table containing _every_ object
|
||||
that implements the trait. Now, if it has type parameters, we need to add
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ An invalid number of generic parameters was passed to an intrinsic function.
|
|||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0094
|
||||
#![feature(intrinsics)]
|
||||
#![feature(intrinsics, rustc_attrs)]
|
||||
#![allow(internal_features)]
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
|
|
@ -18,7 +18,7 @@ and verify with the function declaration in the Rust source code.
|
|||
Example:
|
||||
|
||||
```
|
||||
#![feature(intrinsics)]
|
||||
#![feature(intrinsics, rustc_attrs)]
|
||||
#![allow(internal_features)]
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ You used a function or type which doesn't fit the requirements for where it was
|
|||
used. Erroneous code examples:
|
||||
|
||||
```compile_fail
|
||||
#![feature(intrinsics)]
|
||||
#![feature(intrinsics, rustc_attrs)]
|
||||
#![allow(internal_features)]
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
|
|
@ -41,7 +41,7 @@ impl Foo {
|
|||
For the first code example, please check the function definition. Example:
|
||||
|
||||
```
|
||||
#![feature(intrinsics)]
|
||||
#![feature(intrinsics, rustc_attrs)]
|
||||
#![allow(internal_features)]
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
|
|
|
|||
|
|
@ -537,7 +537,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
allow_internal_unsafe, Normal, template!(Word), WarnFollowing,
|
||||
"allow_internal_unsafe side-steps the unsafe_code lint",
|
||||
),
|
||||
ungated!(rustc_safe_intrinsic, Normal, template!(Word), DuplicatesOk),
|
||||
rustc_attr!(rustc_allowed_through_unstable_modules, Normal, template!(Word), WarnFollowing,
|
||||
"rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \
|
||||
through unstable paths"),
|
||||
|
|
@ -806,6 +805,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
rustc_doc_primitive, Normal, template!(NameValueStr: "primitive name"), ErrorFollowing,
|
||||
r#"`rustc_doc_primitive` is a rustc internal attribute"#,
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_safe_intrinsic, Normal, template!(Word), WarnFollowing,
|
||||
"the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe"
|
||||
),
|
||||
|
||||
// ==========================================================================
|
||||
// Internal attributes, Testing:
|
||||
|
|
|
|||
|
|
@ -61,9 +61,7 @@ pub enum DefKind {
|
|||
Variant,
|
||||
Trait,
|
||||
/// Type alias: `type Foo = Bar;`
|
||||
TyAlias {
|
||||
lazy: bool,
|
||||
},
|
||||
TyAlias,
|
||||
/// Type from an `extern` block.
|
||||
ForeignTy,
|
||||
/// Trait alias: `trait IntIterator = Iterator<Item = i32>;`
|
||||
|
|
@ -143,7 +141,7 @@ impl DefKind {
|
|||
DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) => "tuple struct",
|
||||
DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => "unit struct",
|
||||
DefKind::OpaqueTy => "opaque type",
|
||||
DefKind::TyAlias { .. } => "type alias",
|
||||
DefKind::TyAlias => "type alias",
|
||||
DefKind::TraitAlias => "trait alias",
|
||||
DefKind::AssocTy => "associated type",
|
||||
DefKind::Union => "union",
|
||||
|
|
@ -199,7 +197,7 @@ impl DefKind {
|
|||
| DefKind::Variant
|
||||
| DefKind::Trait
|
||||
| DefKind::OpaqueTy
|
||||
| DefKind::TyAlias { .. }
|
||||
| DefKind::TyAlias
|
||||
| DefKind::ForeignTy
|
||||
| DefKind::TraitAlias
|
||||
| DefKind::AssocTy
|
||||
|
|
@ -250,7 +248,7 @@ impl DefKind {
|
|||
| DefKind::Enum
|
||||
| DefKind::Variant
|
||||
| DefKind::Trait
|
||||
| DefKind::TyAlias { .. }
|
||||
| DefKind::TyAlias
|
||||
| DefKind::ForeignTy
|
||||
| DefKind::TraitAlias
|
||||
| DefKind::AssocTy
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ impl Target {
|
|||
DefKind::Mod => Target::Mod,
|
||||
DefKind::ForeignMod => Target::ForeignMod,
|
||||
DefKind::GlobalAsm => Target::GlobalAsm,
|
||||
DefKind::TyAlias { .. } => Target::TyAlias,
|
||||
DefKind::TyAlias => Target::TyAlias,
|
||||
DefKind::OpaqueTy => Target::OpaqueTy,
|
||||
DefKind::Enum => Target::Enum,
|
||||
DefKind::Struct => Target::Struct,
|
||||
|
|
|
|||
|
|
@ -427,7 +427,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
|||
let bound_vars = tcx.late_bound_vars(binding.hir_id);
|
||||
ty::Binder::bind_with_vars(subst_output, bound_vars)
|
||||
} else {
|
||||
// Include substitutions for generic parameters of associated types
|
||||
// Append the generic arguments of the associated type to the `trait_ref`.
|
||||
candidate.map_bound(|trait_ref| {
|
||||
let ident = Ident::new(assoc_item.name, binding.item_name.span);
|
||||
let item_segment = hir::PathSegment {
|
||||
|
|
|
|||
|
|
@ -139,22 +139,22 @@ fn generic_arg_mismatch_err(
|
|||
err.emit()
|
||||
}
|
||||
|
||||
/// Creates the relevant generic argument substitutions
|
||||
/// Creates the relevant generic arguments
|
||||
/// corresponding to a set of generic parameters. This is a
|
||||
/// rather complex function. Let us try to explain the role
|
||||
/// of each of its parameters:
|
||||
///
|
||||
/// To start, we are given the `def_id` of the thing we are
|
||||
/// creating the substitutions for, and a partial set of
|
||||
/// substitutions `parent_args`. In general, the substitutions
|
||||
/// for an item begin with substitutions for all the "parents" of
|
||||
/// To start, we are given the `def_id` of the thing whose generic
|
||||
/// parameters we are instantiating, and a partial set of
|
||||
/// arguments `parent_args`. In general, the generic arguments
|
||||
/// for an item begin with arguments for all the "parents" of
|
||||
/// that item -- e.g., for a method it might include the
|
||||
/// parameters from the impl.
|
||||
///
|
||||
/// Therefore, the method begins by walking down these parents,
|
||||
/// starting with the outermost parent and proceed inwards until
|
||||
/// it reaches `def_id`. For each parent `P`, it will check `parent_args`
|
||||
/// first to see if the parent's substitutions are listed in there. If so,
|
||||
/// first to see if the parent's arguments are listed in there. If so,
|
||||
/// we can append those and move on. Otherwise, it invokes the
|
||||
/// three callback functions:
|
||||
///
|
||||
|
|
@ -188,7 +188,7 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>(
|
|||
stack.push((def_id, parent_defs));
|
||||
}
|
||||
|
||||
// We manually build up the substitution, rather than using convenience
|
||||
// We manually build up the generic arguments, rather than using convenience
|
||||
// methods in `subst.rs`, so that we can iterate over the arguments and
|
||||
// parameters in lock-step linearly, instead of trying to match each pair.
|
||||
let mut args: SmallVec<[ty::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count);
|
||||
|
|
@ -196,7 +196,8 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>(
|
|||
while let Some((def_id, defs)) = stack.pop() {
|
||||
let mut params = defs.params.iter().peekable();
|
||||
|
||||
// If we have already computed substitutions for parents, we can use those directly.
|
||||
// If we have already computed the generic arguments for parents,
|
||||
// we can use those directly.
|
||||
while let Some(¶m) = params.peek() {
|
||||
if let Some(&kind) = parent_args.get(param.index as usize) {
|
||||
args.push(kind);
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
}
|
||||
|
||||
/// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
|
||||
/// returns an appropriate set of substitutions for this particular reference to `I`.
|
||||
/// returns an appropriate set of generic arguments for this particular reference to `I`.
|
||||
pub fn ast_path_args_for_ty(
|
||||
&self,
|
||||
span: Span,
|
||||
|
|
@ -315,7 +315,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
|
||||
/// Given the type/lifetime/const arguments provided to some path (along with
|
||||
/// an implicit `Self`, if this is a trait reference), returns the complete
|
||||
/// set of substitutions. This may involve applying defaulted type parameters.
|
||||
/// set of generic arguments. This may involve applying defaulted type parameters.
|
||||
/// Constraints on associated types are created from `create_assoc_bindings_for_generic_args`.
|
||||
///
|
||||
/// Example:
|
||||
|
|
@ -909,23 +909,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
let tcx = self.tcx();
|
||||
let args = self.ast_path_args_for_ty(span, did, item_segment);
|
||||
|
||||
if let DefKind::TyAlias { lazy: true } = tcx.def_kind(did) {
|
||||
if let DefKind::TyAlias = tcx.def_kind(did)
|
||||
&& tcx.type_alias_is_lazy(did)
|
||||
{
|
||||
// Type aliases defined in crates that have the
|
||||
// feature `lazy_type_alias` enabled get encoded as a type alias that normalization will
|
||||
// then actually instantiate the where bounds of.
|
||||
let alias_ty = tcx.mk_alias_ty(did, args);
|
||||
Ty::new_alias(tcx, ty::Weak, alias_ty)
|
||||
} else {
|
||||
let ty = tcx.at(span).type_of(did);
|
||||
if ty.skip_binder().has_opaque_types() {
|
||||
// Type aliases referring to types that contain opaque types (but aren't just directly
|
||||
// referencing a single opaque type) get encoded as a type alias that normalization will
|
||||
// then actually instantiate the where bounds of.
|
||||
let alias_ty = tcx.mk_alias_ty(did, args);
|
||||
Ty::new_alias(tcx, ty::Weak, alias_ty)
|
||||
} else {
|
||||
ty.instantiate(tcx, args)
|
||||
}
|
||||
tcx.at(span).type_of(did).instantiate(tcx, args)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2164,7 +2157,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
}
|
||||
Res::Def(
|
||||
DefKind::Enum
|
||||
| DefKind::TyAlias { .. }
|
||||
| DefKind::TyAlias
|
||||
| DefKind::Struct
|
||||
| DefKind::Union
|
||||
| DefKind::ForeignTy,
|
||||
|
|
@ -2781,7 +2774,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
) {
|
||||
for br in referenced_regions.difference(&constrained_regions) {
|
||||
let br_name = match *br {
|
||||
ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) | ty::BrEnv => {
|
||||
ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon | ty::BrEnv => {
|
||||
"an anonymous lifetime".to_string()
|
||||
}
|
||||
ty::BrNamed(_, name) => format!("lifetime `{name}`"),
|
||||
|
|
@ -2789,7 +2782,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
|
||||
let mut err = generate_err(&br_name);
|
||||
|
||||
if let ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) = *br {
|
||||
if let ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon = *br {
|
||||
// The only way for an anonymous lifetime to wind up
|
||||
// in the return type but **also** be unconstrained is
|
||||
// if it only appears in "associated types" in the
|
||||
|
|
|
|||
|
|
@ -640,7 +640,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
|
|||
check_opaque(tcx, id);
|
||||
}
|
||||
}
|
||||
DefKind::TyAlias { .. } => {
|
||||
DefKind::TyAlias => {
|
||||
let pty_ty = tcx.type_of(id.owner_id).instantiate_identity();
|
||||
let generics = tcx.generics_of(id.owner_id);
|
||||
check_type_params_are_used(tcx, &generics, pty_ty);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
|
|||
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
|
||||
use rustc_infer::traits::util;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::fold::BottomUpFolder;
|
||||
use rustc_middle::ty::util::ExplicitSelf;
|
||||
use rustc_middle::ty::{
|
||||
self, GenericArgs, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
|
||||
|
|
@ -661,8 +662,6 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||
let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap();
|
||||
let impl_trait_ref =
|
||||
tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().instantiate_identity();
|
||||
let param_env = tcx.param_env(impl_m_def_id);
|
||||
|
||||
// First, check a few of the same things as `compare_impl_method`,
|
||||
// just so we don't ICE during substitution later.
|
||||
check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?;
|
||||
|
|
@ -688,13 +687,26 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||
let trait_to_placeholder_args =
|
||||
impl_to_placeholder_args.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_args);
|
||||
|
||||
let hybrid_preds = tcx
|
||||
.predicates_of(impl_m.container_id(tcx))
|
||||
.instantiate_identity(tcx)
|
||||
.into_iter()
|
||||
.chain(tcx.predicates_of(trait_m.def_id).instantiate_own(tcx, trait_to_placeholder_args))
|
||||
.map(|(clause, _)| clause);
|
||||
let param_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(hybrid_preds), Reveal::UserFacing);
|
||||
let param_env = traits::normalize_param_env_or_error(
|
||||
tcx,
|
||||
param_env,
|
||||
ObligationCause::misc(tcx.def_span(impl_m_def_id), impl_m_def_id),
|
||||
);
|
||||
|
||||
let infcx = &tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
|
||||
// Normalize the impl signature with fresh variables for lifetime inference.
|
||||
let norm_cause = ObligationCause::misc(return_span, impl_m_def_id);
|
||||
let misc_cause = ObligationCause::misc(return_span, impl_m_def_id);
|
||||
let impl_sig = ocx.normalize(
|
||||
&norm_cause,
|
||||
&misc_cause,
|
||||
param_env,
|
||||
tcx.liberate_late_bound_regions(
|
||||
impl_m.def_id,
|
||||
|
|
@ -725,12 +737,68 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||
);
|
||||
}
|
||||
|
||||
let trait_sig = ocx.normalize(&norm_cause, param_env, unnormalized_trait_sig);
|
||||
let trait_sig = ocx.normalize(&misc_cause, param_env, unnormalized_trait_sig);
|
||||
trait_sig.error_reported()?;
|
||||
let trait_return_ty = trait_sig.output();
|
||||
|
||||
// RPITITs are allowed to use the implied predicates of the method that
|
||||
// defines them. This is because we want code like:
|
||||
// ```
|
||||
// trait Foo {
|
||||
// fn test<'a, T>(_: &'a T) -> impl Sized;
|
||||
// }
|
||||
// impl Foo for () {
|
||||
// fn test<'a, T>(x: &'a T) -> &'a T { x }
|
||||
// }
|
||||
// ```
|
||||
// .. to compile. However, since we use both the normalized and unnormalized
|
||||
// inputs and outputs from the substituted trait signature, we will end up
|
||||
// seeing the hidden type of an RPIT in the signature itself. Naively, this
|
||||
// means that we will use the hidden type to imply the hidden type's own
|
||||
// well-formedness.
|
||||
//
|
||||
// To avoid this, we replace the infer vars used for hidden type inference
|
||||
// with placeholders, which imply nothing about outlives bounds, and then
|
||||
// prove below that the hidden types are well formed.
|
||||
let universe = infcx.create_next_universe();
|
||||
let mut idx = 0;
|
||||
let mapping: FxHashMap<_, _> = collector
|
||||
.types
|
||||
.iter()
|
||||
.map(|(_, &(ty, _))| {
|
||||
assert!(
|
||||
infcx.resolve_vars_if_possible(ty) == ty && ty.is_ty_var(),
|
||||
"{ty:?} should not have been constrained via normalization",
|
||||
ty = infcx.resolve_vars_if_possible(ty)
|
||||
);
|
||||
idx += 1;
|
||||
(
|
||||
ty,
|
||||
Ty::new_placeholder(
|
||||
tcx,
|
||||
ty::Placeholder {
|
||||
universe,
|
||||
bound: ty::BoundTy {
|
||||
var: ty::BoundVar::from_usize(idx),
|
||||
kind: ty::BoundTyKind::Anon,
|
||||
},
|
||||
},
|
||||
),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let mut type_mapper = BottomUpFolder {
|
||||
tcx,
|
||||
ty_op: |ty| *mapping.get(&ty).unwrap_or(&ty),
|
||||
lt_op: |lt| lt,
|
||||
ct_op: |ct| ct,
|
||||
};
|
||||
let wf_tys = FxIndexSet::from_iter(
|
||||
unnormalized_trait_sig.inputs_and_output.iter().chain(trait_sig.inputs_and_output.iter()),
|
||||
unnormalized_trait_sig
|
||||
.inputs_and_output
|
||||
.iter()
|
||||
.chain(trait_sig.inputs_and_output.iter())
|
||||
.map(|ty| ty.fold_with(&mut type_mapper)),
|
||||
);
|
||||
|
||||
match ocx.eq(&cause, param_env, trait_return_ty, impl_return_ty) {
|
||||
|
|
@ -787,6 +855,20 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME: This has the same issue as #108544, but since this isn't breaking
|
||||
// existing code, I'm not particularly inclined to do the same hack as above
|
||||
// where we process wf obligations manually. This can be fixed in a forward-
|
||||
// compatible way later.
|
||||
let collected_types = collector.types;
|
||||
for (_, &(ty, _)) in &collected_types {
|
||||
ocx.register_obligation(traits::Obligation::new(
|
||||
tcx,
|
||||
misc_cause.clone(),
|
||||
param_env,
|
||||
ty::ClauseKind::WellFormed(ty.into()),
|
||||
));
|
||||
}
|
||||
|
||||
// Check that all obligations are satisfied by the implementation's
|
||||
// RPITs.
|
||||
let errors = ocx.select_all_or_error();
|
||||
|
|
@ -795,8 +877,6 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||
return Err(reported);
|
||||
}
|
||||
|
||||
let collected_types = collector.types;
|
||||
|
||||
// Finally, resolve all regions. This catches wily misuses of
|
||||
// lifetime parameters.
|
||||
let outlives_env = OutlivesEnvironment::with_bounds(
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use rustc_infer::infer::{outlives::env::OutlivesEnvironment, TyCtxtInferExt};
|
|||
use rustc_lint_defs::builtin::REFINING_IMPL_TRAIT;
|
||||
use rustc_middle::traits::{ObligationCause, Reveal};
|
||||
use rustc_middle::ty::{
|
||||
self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor,
|
||||
self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, TypeVisitor,
|
||||
};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_trait_selection::traits::{
|
||||
|
|
@ -176,9 +176,13 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
|
|||
return;
|
||||
};
|
||||
|
||||
// For quicker lookup, use an `IndexSet`
|
||||
// (we don't use one earlier because it's not foldable..)
|
||||
let trait_bounds = FxIndexSet::from_iter(trait_bounds);
|
||||
// For quicker lookup, use an `IndexSet` (we don't use one earlier because
|
||||
// it's not foldable..).
|
||||
// Also, We have to anonymize binders in these types because they may contain
|
||||
// `BrNamed` bound vars, which contain unique `DefId`s which correspond to syntax
|
||||
// locations that we don't care about when checking bound equality.
|
||||
let trait_bounds = FxIndexSet::from_iter(trait_bounds.fold_with(&mut Anonymize { tcx }));
|
||||
let impl_bounds = impl_bounds.fold_with(&mut Anonymize { tcx });
|
||||
|
||||
// Find any clauses that are present in the impl's RPITITs that are not
|
||||
// present in the trait's RPITITs. This will trigger on trivial predicates,
|
||||
|
|
@ -309,3 +313,20 @@ fn type_visibility<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<ty::Visibili
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
struct Anonymize<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Anonymize<'tcx> {
|
||||
fn interner(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
self.tcx.anonymize_bound_vars(t)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
|||
let name_str = intrinsic_name.as_str();
|
||||
|
||||
let bound_vars = tcx.mk_bound_variable_kinds(&[
|
||||
ty::BoundVariableKind::Region(ty::BrAnon(None)),
|
||||
ty::BoundVariableKind::Region(ty::BrAnon),
|
||||
ty::BoundVariableKind::Region(ty::BrEnv),
|
||||
]);
|
||||
let mk_va_list_ty = |mutbl| {
|
||||
|
|
@ -145,7 +145,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
|||
let region = ty::Region::new_late_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) },
|
||||
ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon },
|
||||
);
|
||||
let env_region = ty::Region::new_late_bound(
|
||||
tcx,
|
||||
|
|
@ -405,7 +405,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
|||
);
|
||||
let discriminant_def_id = assoc_items[0];
|
||||
|
||||
let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) };
|
||||
let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon };
|
||||
(
|
||||
1,
|
||||
vec![Ty::new_imm_ref(
|
||||
|
|
@ -463,7 +463,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
|||
}
|
||||
|
||||
sym::raw_eq => {
|
||||
let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) };
|
||||
let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon };
|
||||
let param_ty = Ty::new_imm_ref(
|
||||
tcx,
|
||||
ty::Region::new_late_bound(tcx, ty::INNERMOST, br),
|
||||
|
|
|
|||
|
|
@ -246,9 +246,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
|
|||
// `ForeignItem`s are handled separately.
|
||||
hir::ItemKind::ForeignMod { .. } => {}
|
||||
hir::ItemKind::TyAlias(hir_ty, ast_generics) => {
|
||||
if tcx.features().lazy_type_alias
|
||||
|| tcx.type_of(item.owner_id).skip_binder().has_opaque_types()
|
||||
{
|
||||
if tcx.type_alias_is_lazy(item.owner_id) {
|
||||
// Bounds of lazy type aliases and of eager ones that contain opaque types are respected.
|
||||
// E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`.
|
||||
check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow);
|
||||
|
|
@ -1711,10 +1709,8 @@ fn check_variances_for_type_defn<'tcx>(
|
|||
}
|
||||
}
|
||||
ItemKind::TyAlias(..) => {
|
||||
let ty = tcx.type_of(item.owner_id).instantiate_identity();
|
||||
|
||||
if tcx.features().lazy_type_alias || ty.has_opaque_types() {
|
||||
if ty.references_error() {
|
||||
if tcx.type_alias_is_lazy(item.owner_id) {
|
||||
if tcx.type_of(item.owner_id).skip_binder().references_error() {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ pub fn provide(providers: &mut Providers) {
|
|||
*providers = Providers {
|
||||
type_of: type_of::type_of,
|
||||
type_of_opaque: type_of::type_of_opaque,
|
||||
type_alias_is_lazy: type_of::type_alias_is_lazy,
|
||||
item_bounds: item_bounds::item_bounds,
|
||||
explicit_item_bounds: item_bounds::explicit_item_bounds,
|
||||
generics_of: generics_of::generics_of,
|
||||
|
|
|
|||
|
|
@ -856,22 +856,6 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
|||
let scope = Scope::TraitRefBoundary { s: self.scope };
|
||||
self.with(scope, |this| {
|
||||
walk_list!(this, visit_generic_param, generics.params);
|
||||
for param in generics.params {
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {}
|
||||
GenericParamKind::Type { default, .. } => {
|
||||
if let Some(ty) = default {
|
||||
this.visit_ty(ty);
|
||||
}
|
||||
}
|
||||
GenericParamKind::Const { ty, default } => {
|
||||
this.visit_ty(ty);
|
||||
if let Some(default) = default {
|
||||
this.visit_body(this.tcx.hir().body(default.body));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
walk_list!(this, visit_where_predicate, generics.predicates);
|
||||
})
|
||||
}
|
||||
|
|
@ -1000,6 +984,21 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
|||
// like implicit `?Sized` or const-param-has-ty predicates.
|
||||
}
|
||||
}
|
||||
|
||||
match p.kind {
|
||||
GenericParamKind::Lifetime { .. } => {}
|
||||
GenericParamKind::Type { default, .. } => {
|
||||
if let Some(ty) = default {
|
||||
self.visit_ty(ty);
|
||||
}
|
||||
}
|
||||
GenericParamKind::Const { ty, default } => {
|
||||
self.visit_ty(ty);
|
||||
if let Some(default) = default {
|
||||
self.visit_body(self.tcx.hir().body(default.body));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1520,7 +1519,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
DefKind::Struct
|
||||
| DefKind::Union
|
||||
| DefKind::Enum
|
||||
| DefKind::TyAlias { .. }
|
||||
| DefKind::TyAlias
|
||||
| DefKind::Trait,
|
||||
def_id,
|
||||
) if depth == 0 => Some(def_id),
|
||||
|
|
@ -2030,7 +2029,7 @@ fn is_late_bound_map(
|
|||
|
||||
hir::TyKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
hir::Path { res: Res::Def(DefKind::TyAlias { .. }, alias_def), segments, span },
|
||||
hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span },
|
||||
)) => {
|
||||
// See comments on `ConstrainedCollectorPostAstConv` for why this arm does not just consider
|
||||
// args to be unconstrained.
|
||||
|
|
|
|||
|
|
@ -623,3 +623,25 @@ fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) {
|
|||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
|
||||
use hir::intravisit::Visitor;
|
||||
if tcx.features().lazy_type_alias {
|
||||
return true;
|
||||
}
|
||||
struct HasTait {
|
||||
has_type_alias_impl_trait: bool,
|
||||
}
|
||||
impl<'tcx> Visitor<'tcx> for HasTait {
|
||||
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
|
||||
if let hir::TyKind::OpaqueDef(..) = t.kind {
|
||||
self.has_type_alias_impl_trait = true;
|
||||
} else {
|
||||
hir::intravisit::walk_ty(self, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut has_tait = HasTait { has_type_alias_impl_trait: false };
|
||||
has_tait.visit_ty(tcx.hir().expect_item(def_id).expect_ty_alias().0);
|
||||
has_tait.has_type_alias_impl_trait
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
use hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
|
||||
|
||||
use super::terms::VarianceTerm::*;
|
||||
|
|
@ -78,9 +78,7 @@ pub fn add_constraints_from_crate<'a, 'tcx>(
|
|||
}
|
||||
}
|
||||
DefKind::Fn | DefKind::AssocFn => constraint_cx.build_constraints_for_item(def_id),
|
||||
DefKind::TyAlias { lazy }
|
||||
if lazy || tcx.type_of(def_id).instantiate_identity().has_opaque_types() =>
|
||||
{
|
||||
DefKind::TyAlias if tcx.type_alias_is_lazy(def_id) => {
|
||||
constraint_cx.build_constraints_for_item(def_id)
|
||||
}
|
||||
_ => {}
|
||||
|
|
@ -110,8 +108,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
|||
|
||||
// The type as returned by `type_of` is the underlying type and generally not a weak projection.
|
||||
// Therefore we need to check the `DefKind` first.
|
||||
if let DefKind::TyAlias { lazy } = tcx.def_kind(def_id)
|
||||
&& (lazy || ty.has_opaque_types())
|
||||
if let DefKind::TyAlias = tcx.def_kind(def_id)
|
||||
&& tcx.type_alias_is_lazy(def_id)
|
||||
{
|
||||
self.add_constraints_from_ty(current_item, ty, self.covariant);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc_hir::def::DefKind;
|
|||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
|
||||
use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
/// Defines the `TermsContext` basically houses an arena where we can
|
||||
|
|
@ -56,9 +56,7 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
|
|||
let crate_map = tcx.crate_variances(());
|
||||
return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
|
||||
}
|
||||
DefKind::TyAlias { lazy }
|
||||
if lazy || tcx.type_of(item_def_id).instantiate_identity().has_opaque_types() =>
|
||||
{
|
||||
DefKind::TyAlias if tcx.type_alias_is_lazy(item_def_id) => {
|
||||
// These are inferred.
|
||||
let crate_map = tcx.crate_variances(());
|
||||
return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
use rustc_arena::DroplessArena;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{LocalDefId, LocalDefIdMap};
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use std::fmt;
|
||||
|
||||
use self::VarianceTerm::*;
|
||||
|
|
@ -97,9 +97,7 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(
|
|||
}
|
||||
}
|
||||
DefKind::Fn | DefKind::AssocFn => terms_cx.add_inferreds_for_item(def_id),
|
||||
DefKind::TyAlias { lazy }
|
||||
if lazy || tcx.type_of(def_id).instantiate_identity().has_opaque_types() =>
|
||||
{
|
||||
DefKind::TyAlias if tcx.type_alias_is_lazy(def_id) => {
|
||||
terms_cx.add_inferreds_for_item(def_id)
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_>
|
|||
&[ty::GenericArg::from(ty::Region::new_late_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrAnon(None) },
|
||||
ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrAnon },
|
||||
))],
|
||||
);
|
||||
let panic_info_ref_ty = Ty::new_imm_ref(
|
||||
|
|
@ -212,14 +212,14 @@ fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_>
|
|||
ty::Region::new_late_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) },
|
||||
ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon },
|
||||
),
|
||||
panic_info_ty,
|
||||
);
|
||||
|
||||
let bounds = tcx.mk_bound_variable_kinds(&[
|
||||
ty::BoundVariableKind::Region(ty::BrAnon(None)),
|
||||
ty::BoundVariableKind::Region(ty::BrAnon(None)),
|
||||
ty::BoundVariableKind::Region(ty::BrAnon),
|
||||
ty::BoundVariableKind::Region(ty::BrAnon),
|
||||
]);
|
||||
let expected_sig = ty::Binder::bind_with_vars(
|
||||
tcx.mk_fn_sig([panic_info_ref_ty], tcx.types.never, false, fn_sig.unsafety, Abi::Rust),
|
||||
|
|
|
|||
|
|
@ -530,7 +530,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// When encountering a type error on the value of a `break`, try to point at the reason for the
|
||||
// expected type.
|
||||
fn annotate_loop_expected_due_to_inference(
|
||||
pub fn annotate_loop_expected_due_to_inference(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
expr: &hir::Expr<'_>,
|
||||
|
|
@ -540,16 +540,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return;
|
||||
};
|
||||
let mut parent_id = self.tcx.hir().parent_id(expr.hir_id);
|
||||
loop {
|
||||
let mut parent;
|
||||
'outer: loop {
|
||||
// Climb the HIR tree to see if the current `Expr` is part of a `break;` statement.
|
||||
let Some(hir::Node::Expr(parent)) = self.tcx.hir().find(parent_id) else {
|
||||
let Some(
|
||||
hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Semi(&ref p), .. })
|
||||
| hir::Node::Block(hir::Block { expr: Some(&ref p), .. })
|
||||
| hir::Node::Expr(&ref p),
|
||||
) = self.tcx.hir().find(parent_id)
|
||||
else {
|
||||
break;
|
||||
};
|
||||
parent_id = self.tcx.hir().parent_id(parent.hir_id);
|
||||
parent = p;
|
||||
parent_id = self.tcx.hir().parent_id(parent_id);
|
||||
let hir::ExprKind::Break(destination, _) = parent.kind else {
|
||||
continue;
|
||||
};
|
||||
let mut parent_id = parent.hir_id;
|
||||
let mut parent_id = parent_id;
|
||||
let mut direct = false;
|
||||
loop {
|
||||
// Climb the HIR tree to find the (desugared) `loop` this `break` corresponds to.
|
||||
let parent = match self.tcx.hir().find(parent_id) {
|
||||
|
|
@ -565,14 +573,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
parent_id = self.tcx.hir().parent_id(*hir_id);
|
||||
parent
|
||||
}
|
||||
Some(hir::Node::Block(hir::Block { .. })) => {
|
||||
Some(hir::Node::Block(_)) => {
|
||||
parent_id = self.tcx.hir().parent_id(parent_id);
|
||||
parent
|
||||
}
|
||||
_ => break,
|
||||
};
|
||||
if let hir::ExprKind::Loop(_, label, _, span) = parent.kind
|
||||
&& destination.label == label
|
||||
if let hir::ExprKind::Loop(..) = parent.kind {
|
||||
// When you have `'a: loop { break; }`, the `break` corresponds to the labeled
|
||||
// loop, so we need to account for that.
|
||||
direct = !direct;
|
||||
}
|
||||
if let hir::ExprKind::Loop(block, label, _, span) = parent.kind
|
||||
&& (destination.label == label || direct)
|
||||
{
|
||||
if let Some((reason_span, message)) =
|
||||
self.maybe_get_coercion_reason(parent_id, parent.span)
|
||||
|
|
@ -582,8 +595,64 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
span,
|
||||
format!("this loop is expected to be of type `{expected}`"),
|
||||
);
|
||||
break 'outer;
|
||||
} else {
|
||||
// Locate all other `break` statements within the same `loop` that might
|
||||
// have affected inference.
|
||||
struct FindBreaks<'tcx> {
|
||||
label: Option<rustc_ast::Label>,
|
||||
uses: Vec<&'tcx hir::Expr<'tcx>>,
|
||||
nest_depth: usize,
|
||||
}
|
||||
impl<'tcx> Visitor<'tcx> for FindBreaks<'tcx> {
|
||||
fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
|
||||
let nest_depth = self.nest_depth;
|
||||
if let hir::ExprKind::Loop(_, label, _, _) = ex.kind {
|
||||
if label == self.label {
|
||||
// Account for `'a: loop { 'a: loop {...} }`.
|
||||
return;
|
||||
}
|
||||
self.nest_depth += 1;
|
||||
}
|
||||
if let hir::ExprKind::Break(destination, _) = ex.kind
|
||||
&& (self.label == destination.label
|
||||
// Account for `loop { 'a: loop { loop { break; } } }`.
|
||||
|| destination.label.is_none() && self.nest_depth == 0)
|
||||
{
|
||||
self.uses.push(ex);
|
||||
}
|
||||
hir::intravisit::walk_expr(self, ex);
|
||||
self.nest_depth = nest_depth;
|
||||
}
|
||||
}
|
||||
let mut expr_finder = FindBreaks { label, uses: vec![], nest_depth: 0 };
|
||||
expr_finder.visit_block(block);
|
||||
let mut exit = false;
|
||||
for ex in expr_finder.uses {
|
||||
let hir::ExprKind::Break(_, val) = ex.kind else {
|
||||
continue;
|
||||
};
|
||||
let ty = match val {
|
||||
Some(val) => {
|
||||
match self.typeck_results.borrow().expr_ty_adjusted_opt(val) {
|
||||
None => continue,
|
||||
Some(ty) => ty,
|
||||
}
|
||||
}
|
||||
None => self.tcx.types.unit,
|
||||
};
|
||||
if self.can_eq(self.param_env, ty, expected) {
|
||||
err.span_label(
|
||||
ex.span,
|
||||
format!("expected because of this `break`"),
|
||||
);
|
||||
exit = true;
|
||||
}
|
||||
}
|
||||
if exit {
|
||||
break 'outer;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,10 @@ use rustc_infer::traits::query::NoSolution;
|
|||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_middle::middle::stability;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
|
||||
use rustc_middle::ty::error::TypeError::FieldMisMatch;
|
||||
use rustc_middle::ty::error::{
|
||||
ExpectedFound,
|
||||
TypeError::{FieldMisMatch, Sorts},
|
||||
};
|
||||
use rustc_middle::ty::GenericArgsRef;
|
||||
use rustc_middle::ty::{self, AdtKind, Ty, TypeVisitableExt};
|
||||
use rustc_session::errors::ExprParenthesesNeeded;
|
||||
|
|
@ -664,15 +667,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.suggest_mismatched_types_on_tail(
|
||||
&mut err, expr, ty, e_ty, target_id,
|
||||
);
|
||||
let error = Some(Sorts(ExpectedFound { expected: ty, found: e_ty }));
|
||||
self.annotate_loop_expected_due_to_inference(&mut err, expr, error);
|
||||
if let Some(val) = ty_kind_suggestion(ty) {
|
||||
let label = destination
|
||||
.label
|
||||
.map(|l| format!(" {}", l.ident))
|
||||
.unwrap_or_else(String::new);
|
||||
err.span_suggestion(
|
||||
expr.span,
|
||||
err.span_suggestion_verbose(
|
||||
expr.span.shrink_to_hi(),
|
||||
"give it a value of the expected type",
|
||||
format!("break{label} {val}"),
|
||||
format!(" {val}"),
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
|
|
@ -717,7 +718,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// ... except when we try to 'break rust;'.
|
||||
// ICE this expression in particular (see #43162).
|
||||
if let ExprKind::Path(QPath::Resolved(_, path)) = e.kind {
|
||||
if path.segments.len() == 1 && path.segments[0].ident.name == sym::rust {
|
||||
if let [segment] = path.segments && segment.ident.name == sym::rust {
|
||||
fatally_break_rust(self.tcx);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1370,10 +1370,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
_ => bug!("unexpected type: {:?}", ty.normalized),
|
||||
},
|
||||
Res::Def(
|
||||
DefKind::Struct | DefKind::Union | DefKind::TyAlias { .. } | DefKind::AssocTy,
|
||||
_,
|
||||
)
|
||||
Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
|
||||
| Res::SelfTyParam { .. }
|
||||
| Res::SelfTyAlias { .. } => match ty.normalized.ty_adt_def() {
|
||||
Some(adt) if !adt.is_enum() => {
|
||||
|
|
|
|||
|
|
@ -65,6 +65,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let expr = expr.peel_drop_temps();
|
||||
self.suggest_missing_semicolon(err, expr, expected, false);
|
||||
let mut pointing_at_return_type = false;
|
||||
if let hir::ExprKind::Break(..) = expr.kind {
|
||||
// `break` type mismatches provide better context for tail `loop` expressions.
|
||||
return false;
|
||||
}
|
||||
if let Some((fn_id, fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
|
||||
pointing_at_return_type = self.suggest_missing_return_type(
|
||||
err,
|
||||
|
|
|
|||
|
|
@ -464,7 +464,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
|||
// Opaque types can't have field projections, but we can instead convert
|
||||
// the current place in-place (heh) to the hidden type, and then apply all
|
||||
// follow up projections on that.
|
||||
if node_ty != place_ty && place_ty.has_opaque_types() {
|
||||
if node_ty != place_ty && matches!(place_ty.kind(), ty::Alias(ty::Opaque, ..)) {
|
||||
projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty });
|
||||
}
|
||||
projections.push(Projection { kind, ty });
|
||||
|
|
@ -557,10 +557,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
|||
Ok(adt_def.variant_index_with_ctor_id(variant_ctor_id))
|
||||
}
|
||||
Res::Def(DefKind::Ctor(CtorOf::Struct, ..), _)
|
||||
| Res::Def(
|
||||
DefKind::Struct | DefKind::Union | DefKind::TyAlias { .. } | DefKind::AssocTy,
|
||||
_,
|
||||
)
|
||||
| Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
|
||||
| Res::SelfCtor(..)
|
||||
| Res::SelfTyParam { .. }
|
||||
| Res::SelfTyAlias { .. } => {
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ pub use persist::load_query_result_cache;
|
|||
pub use persist::prepare_session_directory;
|
||||
pub use persist::save_dep_graph;
|
||||
pub use persist::save_work_product_index;
|
||||
pub use persist::setup_dep_graph;
|
||||
pub use persist::LoadResult;
|
||||
pub use persist::{build_dep_graph, load_dep_graph, DepGraphFuture};
|
||||
|
||||
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
|
||||
use rustc_fluent_macro::fluent_messages;
|
||||
|
|
|
|||
|
|
@ -3,17 +3,19 @@
|
|||
use crate::errors;
|
||||
use rustc_data_structures::memmap::Mmap;
|
||||
use rustc_data_structures::unord::UnordMap;
|
||||
use rustc_middle::dep_graph::{DepsType, SerializedDepGraph, WorkProductMap};
|
||||
use rustc_middle::dep_graph::{DepGraph, DepsType, SerializedDepGraph, WorkProductMap};
|
||||
use rustc_middle::query::on_disk_cache::OnDiskCache;
|
||||
use rustc_serialize::opaque::MemDecoder;
|
||||
use rustc_serialize::Decodable;
|
||||
use rustc_session::config::IncrementalStateAssertion;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::{Session, StableCrateId};
|
||||
use rustc_span::{ErrorGuaranteed, Symbol};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use super::data::*;
|
||||
use super::file_format;
|
||||
use super::fs::*;
|
||||
use super::save::build_dep_graph;
|
||||
use super::work_product;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -72,21 +74,12 @@ impl<T: Default> LoadResult<T> {
|
|||
}
|
||||
|
||||
fn load_data(path: &Path, sess: &Session) -> LoadResult<(Mmap, usize)> {
|
||||
load_data_no_sess(
|
||||
match file_format::read_file(
|
||||
path,
|
||||
sess.opts.unstable_opts.incremental_info,
|
||||
sess.is_nightly_build(),
|
||||
sess.cfg_version,
|
||||
)
|
||||
}
|
||||
|
||||
fn load_data_no_sess(
|
||||
path: &Path,
|
||||
report_incremental_info: bool,
|
||||
is_nightly_build: bool,
|
||||
cfg_version: &'static str,
|
||||
) -> LoadResult<(Mmap, usize)> {
|
||||
match file_format::read_file(path, report_incremental_info, is_nightly_build, cfg_version) {
|
||||
) {
|
||||
Ok(Some(data_and_pos)) => LoadResult::Ok { data: data_and_pos },
|
||||
Ok(None) => {
|
||||
// The file either didn't exist or was produced by an incompatible
|
||||
|
|
@ -102,39 +95,12 @@ fn delete_dirty_work_product(sess: &Session, swp: SerializedWorkProduct) {
|
|||
work_product::delete_workproduct_files(sess, &swp.work_product);
|
||||
}
|
||||
|
||||
/// Either a result that has already be computed or a
|
||||
/// handle that will let us wait until it is computed
|
||||
/// by a background thread.
|
||||
pub enum MaybeAsync<T> {
|
||||
Sync(T),
|
||||
Async(std::thread::JoinHandle<T>),
|
||||
}
|
||||
|
||||
impl<T> MaybeAsync<LoadResult<T>> {
|
||||
/// Accesses the data returned in [`LoadResult::Ok`] in an asynchronous way if possible.
|
||||
pub fn open(self) -> LoadResult<T> {
|
||||
match self {
|
||||
MaybeAsync::Sync(result) => result,
|
||||
MaybeAsync::Async(handle) => {
|
||||
handle.join().unwrap_or_else(|e| LoadResult::DecodeIncrCache(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An asynchronous type for computing the dependency graph.
|
||||
pub type DepGraphFuture = MaybeAsync<LoadResult<(SerializedDepGraph, WorkProductMap)>>;
|
||||
|
||||
/// Launch a thread and load the dependency graph in the background.
|
||||
pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
|
||||
// Since `sess` isn't `Sync`, we perform all accesses to `sess`
|
||||
// before we fire the background thread.
|
||||
|
||||
fn load_dep_graph(sess: &Session) -> LoadResult<(SerializedDepGraph, WorkProductMap)> {
|
||||
let prof = sess.prof.clone();
|
||||
|
||||
if sess.opts.incremental.is_none() {
|
||||
// No incremental compilation.
|
||||
return MaybeAsync::Sync(LoadResult::Ok { data: Default::default() });
|
||||
return LoadResult::Ok { data: Default::default() };
|
||||
}
|
||||
|
||||
let _timer = sess.prof.generic_activity("incr_comp_prepare_load_dep_graph");
|
||||
|
|
@ -142,7 +108,6 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
|
|||
// Calling `sess.incr_comp_session_dir()` will panic if `sess.opts.incremental.is_none()`.
|
||||
// Fortunately, we just checked that this isn't the case.
|
||||
let path = dep_graph_path(&sess);
|
||||
let report_incremental_info = sess.opts.unstable_opts.incremental_info;
|
||||
let expected_hash = sess.opts.dep_tracking_hash(false);
|
||||
|
||||
let mut prev_work_products = UnordMap::default();
|
||||
|
|
@ -180,40 +145,35 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
|
|||
}
|
||||
}
|
||||
|
||||
let is_nightly_build = sess.is_nightly_build();
|
||||
let cfg_version = sess.cfg_version;
|
||||
let _prof_timer = prof.generic_activity("incr_comp_load_dep_graph");
|
||||
|
||||
MaybeAsync::Async(std::thread::spawn(move || {
|
||||
let _prof_timer = prof.generic_activity("incr_comp_load_dep_graph");
|
||||
match load_data(&path, sess) {
|
||||
LoadResult::DataOutOfDate => LoadResult::DataOutOfDate,
|
||||
LoadResult::LoadDepGraph(path, err) => LoadResult::LoadDepGraph(path, err),
|
||||
LoadResult::DecodeIncrCache(err) => LoadResult::DecodeIncrCache(err),
|
||||
LoadResult::Ok { data: (bytes, start_pos) } => {
|
||||
let mut decoder = MemDecoder::new(&bytes, start_pos);
|
||||
let prev_commandline_args_hash = u64::decode(&mut decoder);
|
||||
|
||||
match load_data_no_sess(&path, report_incremental_info, is_nightly_build, cfg_version) {
|
||||
LoadResult::DataOutOfDate => LoadResult::DataOutOfDate,
|
||||
LoadResult::LoadDepGraph(path, err) => LoadResult::LoadDepGraph(path, err),
|
||||
LoadResult::DecodeIncrCache(err) => LoadResult::DecodeIncrCache(err),
|
||||
LoadResult::Ok { data: (bytes, start_pos) } => {
|
||||
let mut decoder = MemDecoder::new(&bytes, start_pos);
|
||||
let prev_commandline_args_hash = u64::decode(&mut decoder);
|
||||
|
||||
if prev_commandline_args_hash != expected_hash {
|
||||
if report_incremental_info {
|
||||
eprintln!(
|
||||
"[incremental] completely ignoring cache because of \
|
||||
if prev_commandline_args_hash != expected_hash {
|
||||
if sess.opts.unstable_opts.incremental_info {
|
||||
eprintln!(
|
||||
"[incremental] completely ignoring cache because of \
|
||||
differing commandline arguments"
|
||||
);
|
||||
}
|
||||
// We can't reuse the cache, purge it.
|
||||
debug!("load_dep_graph_new: differing commandline arg hashes");
|
||||
|
||||
// No need to do any further work
|
||||
return LoadResult::DataOutOfDate;
|
||||
);
|
||||
}
|
||||
// We can't reuse the cache, purge it.
|
||||
debug!("load_dep_graph_new: differing commandline arg hashes");
|
||||
|
||||
let dep_graph = SerializedDepGraph::decode::<DepsType>(&mut decoder);
|
||||
|
||||
LoadResult::Ok { data: (dep_graph, prev_work_products) }
|
||||
// No need to do any further work
|
||||
return LoadResult::DataOutOfDate;
|
||||
}
|
||||
|
||||
let dep_graph = SerializedDepGraph::decode::<DepsType>(&mut decoder);
|
||||
|
||||
LoadResult::Ok { data: (dep_graph, prev_work_products) }
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempts to load the query result cache from disk
|
||||
|
|
@ -235,3 +195,35 @@ pub fn load_query_result_cache(sess: &Session) -> Option<OnDiskCache<'_>> {
|
|||
_ => Some(OnDiskCache::new_empty(sess.source_map())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Setups the dependency graph by loading an existing graph from disk and set up streaming of a
|
||||
/// new graph to an incremental session directory.
|
||||
pub fn setup_dep_graph(
|
||||
sess: &Session,
|
||||
crate_name: Symbol,
|
||||
stable_crate_id: StableCrateId,
|
||||
) -> Result<DepGraph, ErrorGuaranteed> {
|
||||
// `load_dep_graph` can only be called after `prepare_session_directory`.
|
||||
prepare_session_directory(sess, crate_name, stable_crate_id)?;
|
||||
|
||||
let res = sess.opts.build_dep_graph().then(|| load_dep_graph(sess));
|
||||
|
||||
if sess.opts.incremental.is_some() {
|
||||
sess.time("incr_comp_garbage_collect_session_directories", || {
|
||||
if let Err(e) = garbage_collect_session_directories(sess) {
|
||||
warn!(
|
||||
"Error while trying to garbage collect incremental \
|
||||
compilation cache directory: {}",
|
||||
e
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Ok(res
|
||||
.and_then(|result| {
|
||||
let (prev_graph, prev_work_products) = result.open(sess);
|
||||
build_dep_graph(sess, prev_graph, prev_work_products)
|
||||
})
|
||||
.unwrap_or_else(DepGraph::new_disabled))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,9 +16,8 @@ pub use fs::in_incr_comp_dir;
|
|||
pub use fs::in_incr_comp_dir_sess;
|
||||
pub use fs::prepare_session_directory;
|
||||
pub use load::load_query_result_cache;
|
||||
pub use load::setup_dep_graph;
|
||||
pub use load::LoadResult;
|
||||
pub use load::{load_dep_graph, DepGraphFuture};
|
||||
pub use save::build_dep_graph;
|
||||
pub use save::save_dep_graph;
|
||||
pub use save::save_work_product_index;
|
||||
pub use work_product::copy_cgu_workproduct_to_incr_comp_cache_dir;
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ fn encode_query_cache(tcx: TyCtxt<'_>, encoder: FileEncoder) -> FileEncodeResult
|
|||
/// execution, the new dependency information is not kept in memory but directly
|
||||
/// output to this file. `save_dep_graph` then finalizes the staging dep-graph
|
||||
/// and moves it to the permanent dep-graph path
|
||||
pub fn build_dep_graph(
|
||||
pub(crate) fn build_dep_graph(
|
||||
sess: &Session,
|
||||
prev_graph: SerializedDepGraph,
|
||||
prev_work_products: WorkProductMap,
|
||||
|
|
|
|||
|
|
@ -56,11 +56,8 @@ impl<'a> DescriptionCtx<'a> {
|
|||
(Some(span), "as_defined", name.to_string())
|
||||
}
|
||||
}
|
||||
ty::BrAnon(span) => {
|
||||
let span = match span {
|
||||
Some(_) => span,
|
||||
None => Some(tcx.def_span(scope)),
|
||||
};
|
||||
ty::BrAnon => {
|
||||
let span = Some(tcx.def_span(scope));
|
||||
(span, "defined_here", String::new())
|
||||
}
|
||||
_ => {
|
||||
|
|
|
|||
|
|
@ -775,7 +775,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
|
|||
r: ty::Region<'tcx>,
|
||||
) -> ty::Region<'tcx> {
|
||||
let var = self.canonical_var(info, r.into());
|
||||
let br = ty::BoundRegion { var, kind: ty::BrAnon(None) };
|
||||
let br = ty::BoundRegion { var, kind: ty::BrAnon };
|
||||
ty::Region::new_late_bound(self.interner(), self.binder_index, br)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -242,12 +242,9 @@ fn msg_span_from_named_region<'tcx>(
|
|||
};
|
||||
(text, Some(span))
|
||||
}
|
||||
ty::BrAnon(span) => (
|
||||
ty::BrAnon => (
|
||||
"the anonymous lifetime as defined here".to_string(),
|
||||
Some(match span {
|
||||
Some(span) => span,
|
||||
None => tcx.def_span(scope)
|
||||
})
|
||||
Some(tcx.def_span(scope))
|
||||
),
|
||||
_ => (
|
||||
format!("the lifetime `{region}` as defined here"),
|
||||
|
|
@ -262,11 +259,7 @@ fn msg_span_from_named_region<'tcx>(
|
|||
..
|
||||
}) => (format!("the lifetime `{name}` as defined here"), Some(tcx.def_span(def_id))),
|
||||
ty::RePlaceholder(ty::PlaceholderRegion {
|
||||
bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(Some(span)), .. },
|
||||
..
|
||||
}) => ("the anonymous lifetime defined here".to_owned(), Some(span)),
|
||||
ty::RePlaceholder(ty::PlaceholderRegion {
|
||||
bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(None), .. },
|
||||
bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon, .. },
|
||||
..
|
||||
}) => ("an anonymous lifetime".to_owned(), None),
|
||||
_ => bug!("{:?}", region),
|
||||
|
|
|
|||
|
|
@ -918,7 +918,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
|
|||
//
|
||||
// See the `need_type_info/issue-103053.rs` test for
|
||||
// a example.
|
||||
if !matches!(path.res, Res::Def(DefKind::TyAlias { .. }, _)) => {
|
||||
if !matches!(path.res, Res::Def(DefKind::TyAlias, _)) => {
|
||||
if let Some(ty) = self.opt_node_type(expr.hir_id)
|
||||
&& let ty::Adt(_, args) = ty.kind()
|
||||
{
|
||||
|
|
@ -1047,7 +1047,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
|
|||
) => {
|
||||
if tcx.res_generics_def_id(path.res) != Some(def.did()) {
|
||||
match path.res {
|
||||
Res::Def(DefKind::TyAlias { .. }, _) => {
|
||||
Res::Def(DefKind::TyAlias, _) => {
|
||||
// FIXME: Ideally we should support this. For that
|
||||
// we have to map back from the self type to the
|
||||
// type alias though. That's difficult.
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
let is_impl_item = region_info.is_impl_item;
|
||||
|
||||
match br {
|
||||
ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) => {}
|
||||
ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon => {}
|
||||
_ => {
|
||||
/* not an anonymous region */
|
||||
debug!("try_report_named_anon_conflict: not an anonymous region");
|
||||
|
|
|
|||
|
|
@ -36,15 +36,13 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
|
|||
ty::BrNamed(def_id, symbol) => {
|
||||
(Some(self.tcx().def_span(def_id)), Some(symbol))
|
||||
}
|
||||
ty::BrAnon(span) => (*span, None),
|
||||
ty::BrEnv => (None, None),
|
||||
ty::BrAnon | ty::BrEnv => (None, None),
|
||||
};
|
||||
let (sup_span, sup_symbol) = match sup_name {
|
||||
ty::BrNamed(def_id, symbol) => {
|
||||
(Some(self.tcx().def_span(def_id)), Some(symbol))
|
||||
}
|
||||
ty::BrAnon(span) => (*span, None),
|
||||
ty::BrEnv => (None, None),
|
||||
ty::BrAnon | ty::BrEnv => (None, None),
|
||||
};
|
||||
let diag = match (sub_span, sup_span, sub_symbol, sup_symbol) {
|
||||
(Some(sub_span), Some(sup_span), Some(&sub_symbol), Some(&sup_symbol)) => {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use rustc_data_structures::svh::Svh;
|
|||
use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, Lrc, OnceLock, WorkerLocal};
|
||||
use rustc_hir::def_id::{StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
|
||||
use rustc_hir::definitions::Definitions;
|
||||
use rustc_incremental::DepGraphFuture;
|
||||
use rustc_incremental::setup_dep_graph;
|
||||
use rustc_metadata::creader::CStore;
|
||||
use rustc_middle::arena::Arena;
|
||||
use rustc_middle::dep_graph::DepGraph;
|
||||
|
|
@ -19,7 +19,6 @@ use rustc_session::config::{self, CrateType, OutputFilenames, OutputType};
|
|||
use rustc_session::cstore::Untracked;
|
||||
use rustc_session::{output::find_crate_name, Session};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Symbol;
|
||||
use std::any::Any;
|
||||
use std::cell::{RefCell, RefMut};
|
||||
use std::sync::Arc;
|
||||
|
|
@ -132,43 +131,6 @@ impl<'tcx> Queries<'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
fn dep_graph_future(
|
||||
&self,
|
||||
crate_name: Symbol,
|
||||
stable_crate_id: StableCrateId,
|
||||
) -> Result<Option<DepGraphFuture>> {
|
||||
let sess = self.session();
|
||||
|
||||
// `load_dep_graph` can only be called after `prepare_session_directory`.
|
||||
rustc_incremental::prepare_session_directory(sess, crate_name, stable_crate_id)?;
|
||||
let res = sess.opts.build_dep_graph().then(|| rustc_incremental::load_dep_graph(sess));
|
||||
|
||||
if sess.opts.incremental.is_some() {
|
||||
sess.time("incr_comp_garbage_collect_session_directories", || {
|
||||
if let Err(e) = rustc_incremental::garbage_collect_session_directories(sess) {
|
||||
warn!(
|
||||
"Error while trying to garbage collect incremental \
|
||||
compilation cache directory: {}",
|
||||
e
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
fn dep_graph(&self, dep_graph_future: Option<DepGraphFuture>) -> DepGraph {
|
||||
dep_graph_future
|
||||
.and_then(|future| {
|
||||
let sess = self.session();
|
||||
let (prev_graph, prev_work_products) =
|
||||
sess.time("blocked_on_dep_graph_loading", || future.open().open(sess));
|
||||
rustc_incremental::build_dep_graph(sess, prev_graph, prev_work_products)
|
||||
})
|
||||
.unwrap_or_else(DepGraph::new_disabled)
|
||||
}
|
||||
|
||||
pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> {
|
||||
self.gcx.compute(|| {
|
||||
let sess = self.session();
|
||||
|
|
@ -184,10 +146,7 @@ impl<'tcx> Queries<'tcx> {
|
|||
sess.opts.cg.metadata.clone(),
|
||||
sess.cfg_version,
|
||||
);
|
||||
|
||||
// Compute the dependency graph (in the background). We want to do this as early as
|
||||
// possible, to give the DepGraph maximum time to load before `dep_graph` is called.
|
||||
let dep_graph_future = self.dep_graph_future(crate_name, stable_crate_id)?;
|
||||
let dep_graph = setup_dep_graph(sess, crate_name, stable_crate_id)?;
|
||||
|
||||
let lint_store = Lrc::new(passes::create_lint_store(
|
||||
sess,
|
||||
|
|
@ -210,7 +169,7 @@ impl<'tcx> Queries<'tcx> {
|
|||
crate_types,
|
||||
stable_crate_id,
|
||||
lint_store,
|
||||
self.dep_graph(dep_graph_future),
|
||||
dep_graph,
|
||||
untracked,
|
||||
&self.gcx_cell,
|
||||
&self.arena,
|
||||
|
|
|
|||
|
|
@ -1454,13 +1454,13 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
|
|||
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
|
||||
let hir::ItemKind::TyAlias(hir_ty, type_alias_generics) = &item.kind else { return };
|
||||
|
||||
if cx.tcx.features().lazy_type_alias {
|
||||
// Bounds of lazy type aliases are respected.
|
||||
// Bounds of lazy type aliases and TAITs are respected.
|
||||
if cx.tcx.type_alias_is_lazy(item.owner_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
let ty = cx.tcx.type_of(item.owner_id).skip_binder();
|
||||
if ty.has_opaque_types() || ty.has_inherent_projections() {
|
||||
if ty.has_inherent_projections() {
|
||||
// Bounds of type aliases that contain opaque types or inherent projections are respected.
|
||||
// E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`, `type X = Type::Inherent;`.
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -2311,6 +2311,57 @@ declare_lint! {
|
|||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `const_patterns_without_partial_eq` lint detects constants that are used in patterns,
|
||||
/// whose type does not implement `PartialEq`.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,compile_fail
|
||||
/// #![deny(const_patterns_without_partial_eq)]
|
||||
///
|
||||
/// trait EnumSetType {
|
||||
/// type Repr;
|
||||
/// }
|
||||
///
|
||||
/// enum Enum8 { }
|
||||
/// impl EnumSetType for Enum8 {
|
||||
/// type Repr = u8;
|
||||
/// }
|
||||
///
|
||||
/// #[derive(PartialEq, Eq)]
|
||||
/// struct EnumSet<T: EnumSetType> {
|
||||
/// __enumset_underlying: T::Repr,
|
||||
/// }
|
||||
///
|
||||
/// const CONST_SET: EnumSet<Enum8> = EnumSet { __enumset_underlying: 3 };
|
||||
///
|
||||
/// fn main() {
|
||||
/// match CONST_SET {
|
||||
/// CONST_SET => { /* ok */ }
|
||||
/// _ => panic!("match fell through?"),
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Previous versions of Rust accepted constants in patterns, even if those constants' types
|
||||
/// did not have `PartialEq` implemented. The compiler falls back to comparing the value
|
||||
/// field-by-field. In the future we'd like to ensure that pattern matching always
|
||||
/// follows `PartialEq` semantics, so that trait bound will become a requirement for
|
||||
/// matching on constants.
|
||||
pub CONST_PATTERNS_WITHOUT_PARTIAL_EQ,
|
||||
Warn,
|
||||
"constant in pattern does not implement `PartialEq`",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
|
||||
reference: "issue #116122 <https://github.com/rust-lang/rust/issues/116122>",
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `ambiguous_associated_items` lint detects ambiguity between
|
||||
/// [associated items] and [enum variants].
|
||||
|
|
@ -3357,6 +3408,7 @@ declare_lint_pass! {
|
|||
CONFLICTING_REPR_HINTS,
|
||||
CONST_EVALUATABLE_UNCHECKED,
|
||||
CONST_ITEM_MUTATION,
|
||||
CONST_PATTERNS_WITHOUT_PARTIAL_EQ,
|
||||
DEAD_CODE,
|
||||
DEPRECATED,
|
||||
DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
|
||||
|
|
|
|||
|
|
@ -416,6 +416,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
|
|||
bool RelaxELFRelocations,
|
||||
bool UseInitArray,
|
||||
const char *SplitDwarfFile,
|
||||
const char *OutputObjFile,
|
||||
const char *DebugInfoCompression,
|
||||
bool ForceEmulatedTls,
|
||||
const char *ArgsCstrBuff, size_t ArgsCstrBuffLen) {
|
||||
|
|
@ -448,6 +449,9 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
|
|||
if (SplitDwarfFile) {
|
||||
Options.MCOptions.SplitDwarfFile = SplitDwarfFile;
|
||||
}
|
||||
if (OutputObjFile) {
|
||||
Options.ObjectFilenameForDebug = OutputObjFile;
|
||||
}
|
||||
#if LLVM_VERSION_GE(16, 0)
|
||||
if (!strcmp("zlib", DebugInfoCompression) && llvm::compression::zlib::isAvailable()) {
|
||||
Options.CompressDebugSections = DebugCompressionType::Zlib;
|
||||
|
|
|
|||
|
|
@ -210,6 +210,7 @@ provide! { tcx, def_id, other, cdata,
|
|||
inferred_outlives_of => { table_defaulted_array }
|
||||
super_predicates_of => { table }
|
||||
type_of => { table }
|
||||
type_alias_is_lazy => { cdata.root.tables.type_alias_is_lazy.get(cdata, def_id.index) }
|
||||
variances_of => { table }
|
||||
fn_sig => { table }
|
||||
codegen_fn_attrs => { table }
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ use rustc_middle::query::Providers;
|
|||
use rustc_middle::traits::specialization_graph;
|
||||
use rustc_middle::ty::codec::TyEncoder;
|
||||
use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
|
||||
use rustc_middle::ty::TypeVisitableExt;
|
||||
use rustc_middle::ty::{self, AssocItemContainer, SymbolName, Ty, TyCtxt};
|
||||
use rustc_middle::util::common::to_readable_str;
|
||||
use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
|
||||
|
|
@ -827,7 +826,7 @@ fn should_encode_span(def_kind: DefKind) -> bool {
|
|||
| DefKind::Enum
|
||||
| DefKind::Variant
|
||||
| DefKind::Trait
|
||||
| DefKind::TyAlias { .. }
|
||||
| DefKind::TyAlias
|
||||
| DefKind::ForeignTy
|
||||
| DefKind::TraitAlias
|
||||
| DefKind::AssocTy
|
||||
|
|
@ -862,7 +861,7 @@ fn should_encode_attrs(def_kind: DefKind) -> bool {
|
|||
| DefKind::Enum
|
||||
| DefKind::Variant
|
||||
| DefKind::Trait
|
||||
| DefKind::TyAlias { .. }
|
||||
| DefKind::TyAlias
|
||||
| DefKind::ForeignTy
|
||||
| DefKind::TraitAlias
|
||||
| DefKind::AssocTy
|
||||
|
|
@ -903,7 +902,7 @@ fn should_encode_expn_that_defined(def_kind: DefKind) -> bool {
|
|||
| DefKind::Variant
|
||||
| DefKind::Trait
|
||||
| DefKind::Impl { .. } => true,
|
||||
DefKind::TyAlias { .. }
|
||||
DefKind::TyAlias
|
||||
| DefKind::ForeignTy
|
||||
| DefKind::TraitAlias
|
||||
| DefKind::AssocTy
|
||||
|
|
@ -938,7 +937,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool {
|
|||
| DefKind::Enum
|
||||
| DefKind::Variant
|
||||
| DefKind::Trait
|
||||
| DefKind::TyAlias { .. }
|
||||
| DefKind::TyAlias
|
||||
| DefKind::ForeignTy
|
||||
| DefKind::TraitAlias
|
||||
| DefKind::AssocTy
|
||||
|
|
@ -982,7 +981,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool {
|
|||
| DefKind::Const
|
||||
| DefKind::Fn
|
||||
| DefKind::ForeignMod
|
||||
| DefKind::TyAlias { .. }
|
||||
| DefKind::TyAlias
|
||||
| DefKind::OpaqueTy
|
||||
| DefKind::Enum
|
||||
| DefKind::Union
|
||||
|
|
@ -1092,9 +1091,7 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def
|
|||
| DefKind::Closure
|
||||
| DefKind::Generator
|
||||
| DefKind::ExternCrate => false,
|
||||
DefKind::TyAlias { lazy } => {
|
||||
lazy || tcx.type_of(def_id).instantiate_identity().has_opaque_types()
|
||||
}
|
||||
DefKind::TyAlias => tcx.type_alias_is_lazy(def_id),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1105,7 +1102,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool {
|
|||
| DefKind::Enum
|
||||
| DefKind::Variant
|
||||
| DefKind::Trait
|
||||
| DefKind::TyAlias { .. }
|
||||
| DefKind::TyAlias
|
||||
| DefKind::ForeignTy
|
||||
| DefKind::TraitAlias
|
||||
| DefKind::AssocTy
|
||||
|
|
@ -1145,7 +1142,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
|
|||
| DefKind::Fn
|
||||
| DefKind::Const
|
||||
| DefKind::Static(..)
|
||||
| DefKind::TyAlias { .. }
|
||||
| DefKind::TyAlias
|
||||
| DefKind::ForeignTy
|
||||
| DefKind::Impl { .. }
|
||||
| DefKind::AssocFn
|
||||
|
|
@ -1205,7 +1202,7 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool {
|
|||
| DefKind::Const
|
||||
| DefKind::Static(..)
|
||||
| DefKind::Ctor(..)
|
||||
| DefKind::TyAlias { .. }
|
||||
| DefKind::TyAlias
|
||||
| DefKind::OpaqueTy
|
||||
| DefKind::ForeignTy
|
||||
| DefKind::Impl { .. }
|
||||
|
|
@ -1246,7 +1243,7 @@ fn should_encode_constness(def_kind: DefKind) -> bool {
|
|||
| DefKind::AssocConst
|
||||
| DefKind::AnonConst
|
||||
| DefKind::Static(..)
|
||||
| DefKind::TyAlias { .. }
|
||||
| DefKind::TyAlias
|
||||
| DefKind::OpaqueTy
|
||||
| DefKind::Impl { of_trait: false }
|
||||
| DefKind::ForeignTy
|
||||
|
|
@ -1279,7 +1276,7 @@ fn should_encode_const(def_kind: DefKind) -> bool {
|
|||
| DefKind::Field
|
||||
| DefKind::Fn
|
||||
| DefKind::Static(..)
|
||||
| DefKind::TyAlias { .. }
|
||||
| DefKind::TyAlias
|
||||
| DefKind::OpaqueTy
|
||||
| DefKind::ForeignTy
|
||||
| DefKind::Impl { .. }
|
||||
|
|
@ -1451,6 +1448,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
if let DefKind::Macro(_) = def_kind {
|
||||
self.encode_info_for_macro(local_id);
|
||||
}
|
||||
if let DefKind::TyAlias = def_kind {
|
||||
self.tables
|
||||
.type_alias_is_lazy
|
||||
.set(def_id.index, self.tcx.type_alias_is_lazy(def_id));
|
||||
}
|
||||
if let DefKind::OpaqueTy = def_kind {
|
||||
self.encode_explicit_item_bounds(def_id);
|
||||
self.tables
|
||||
|
|
|
|||
|
|
@ -383,6 +383,7 @@ define_tables! {
|
|||
is_intrinsic: Table<DefIndex, bool>,
|
||||
is_macro_rules: Table<DefIndex, bool>,
|
||||
is_type_alias_impl_trait: Table<DefIndex, bool>,
|
||||
type_alias_is_lazy: Table<DefIndex, bool>,
|
||||
attr_flags: Table<DefIndex, AttrFlags>,
|
||||
def_path_hashes: Table<DefIndex, DefPathHash>,
|
||||
explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
|
||||
|
|
|
|||
|
|
@ -145,8 +145,7 @@ fixed_size_enum! {
|
|||
( Enum )
|
||||
( Variant )
|
||||
( Trait )
|
||||
( TyAlias { lazy: false } )
|
||||
( TyAlias { lazy: true } )
|
||||
( TyAlias )
|
||||
( ForeignTy )
|
||||
( TraitAlias )
|
||||
( AssocTy )
|
||||
|
|
|
|||
|
|
@ -196,9 +196,7 @@ impl<'hir> Map<'hir> {
|
|||
ItemKind::Macro(_, macro_kind) => DefKind::Macro(macro_kind),
|
||||
ItemKind::Mod(..) => DefKind::Mod,
|
||||
ItemKind::OpaqueTy(..) => DefKind::OpaqueTy,
|
||||
ItemKind::TyAlias(..) => {
|
||||
DefKind::TyAlias { lazy: self.tcx.features().lazy_type_alias }
|
||||
}
|
||||
ItemKind::TyAlias(..) => DefKind::TyAlias,
|
||||
ItemKind::Enum(..) => DefKind::Enum,
|
||||
ItemKind::Struct(..) => DefKind::Struct,
|
||||
ItemKind::Union(..) => DefKind::Union,
|
||||
|
|
|
|||
|
|
@ -455,7 +455,7 @@ impl<'tcx> CanonicalVarValues<'tcx> {
|
|||
CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => {
|
||||
let br = ty::BoundRegion {
|
||||
var: ty::BoundVar::from_usize(i),
|
||||
kind: ty::BrAnon(None),
|
||||
kind: ty::BrAnon,
|
||||
};
|
||||
ty::Region::new_late_bound(tcx, ty::INNERMOST, br).into()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -414,8 +414,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
|
|||
pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
|
||||
let inner = tcx.fold_regions(ty, |r, depth| match r.kind() {
|
||||
ty::ReVar(vid) => {
|
||||
let br =
|
||||
ty::BoundRegion { var: ty::BoundVar::new(vid.index()), kind: ty::BrAnon(None) };
|
||||
let br = ty::BoundRegion { var: ty::BoundVar::new(vid.index()), kind: ty::BrAnon };
|
||||
ty::Region::new_late_bound(tcx, depth, br)
|
||||
}
|
||||
_ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"),
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ rustc_queries! {
|
|||
action = {
|
||||
use rustc_hir::def::DefKind;
|
||||
match tcx.def_kind(key) {
|
||||
DefKind::TyAlias { .. } => "expanding type alias",
|
||||
DefKind::TyAlias => "expanding type alias",
|
||||
DefKind::TraitAlias => "expanding trait alias",
|
||||
_ => "computing type of",
|
||||
}
|
||||
|
|
@ -251,6 +251,14 @@ rustc_queries! {
|
|||
}
|
||||
}
|
||||
|
||||
query type_alias_is_lazy(key: DefId) -> bool {
|
||||
desc { |tcx|
|
||||
"computing whether `{path}` is a lazy type alias",
|
||||
path = tcx.def_path_str(key),
|
||||
}
|
||||
separate_provide_extern
|
||||
}
|
||||
|
||||
query collect_return_position_impl_trait_in_trait_tys(key: DefId)
|
||||
-> Result<&'tcx FxHashMap<DefId, ty::EarlyBinder<Ty<'tcx>>>, ErrorGuaranteed>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -448,7 +448,7 @@ impl<'tcx> AdtDef<'tcx> {
|
|||
Res::Def(DefKind::Ctor(..), cid) => self.variant_with_ctor_id(cid),
|
||||
Res::Def(DefKind::Struct, _)
|
||||
| Res::Def(DefKind::Union, _)
|
||||
| Res::Def(DefKind::TyAlias { .. }, _)
|
||||
| Res::Def(DefKind::TyAlias, _)
|
||||
| Res::Def(DefKind::AssocTy, _)
|
||||
| Res::SelfTyParam { .. }
|
||||
| Res::SelfTyAlias { .. }
|
||||
|
|
|
|||
|
|
@ -318,7 +318,7 @@ pub struct CommonLifetimes<'tcx> {
|
|||
pub re_vars: Vec<Region<'tcx>>,
|
||||
|
||||
/// Pre-interned values of the form:
|
||||
/// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(None) })`
|
||||
/// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon })`
|
||||
/// for small values of `i` and `v`.
|
||||
pub re_late_bounds: Vec<Vec<Region<'tcx>>>,
|
||||
}
|
||||
|
|
@ -395,7 +395,7 @@ impl<'tcx> CommonLifetimes<'tcx> {
|
|||
.map(|v| {
|
||||
mk(ty::ReLateBound(
|
||||
ty::DebruijnIndex::from(i),
|
||||
ty::BoundRegion { var: ty::BoundVar::from(v), kind: ty::BrAnon(None) },
|
||||
ty::BoundRegion { var: ty::BoundVar::from(v), kind: ty::BrAnon },
|
||||
))
|
||||
})
|
||||
.collect()
|
||||
|
|
@ -1114,7 +1114,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
if let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id)
|
||||
&& let hir::TyKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
hir::Path { res: hir::def::Res::Def(DefKind::TyAlias { .. }, def_id), .. }, )) = hir_output.kind
|
||||
hir::Path { res: hir::def::Res::Def(DefKind::TyAlias, def_id), .. }, )) = hir_output.kind
|
||||
&& let Some(local_id) = def_id.as_local()
|
||||
&& let Some(alias_ty) = self.hir().get_by_def_id(local_id).alias_ty() // it is type alias
|
||||
&& let Some(alias_generics) = self.hir().get_by_def_id(local_id).generics()
|
||||
|
|
|
|||
|
|
@ -493,7 +493,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsSuggestableVisitor<'tcx> {
|
|||
Alias(Opaque, AliasTy { def_id, .. }) => {
|
||||
let parent = self.tcx.parent(def_id);
|
||||
let parent_ty = self.tcx.type_of(parent).instantiate_identity();
|
||||
if let DefKind::TyAlias { .. } | DefKind::AssocTy = self.tcx.def_kind(parent)
|
||||
if let DefKind::TyAlias | DefKind::AssocTy = self.tcx.def_kind(parent)
|
||||
&& let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *parent_ty.kind()
|
||||
&& parent_opaque_def_id == def_id
|
||||
{
|
||||
|
|
@ -577,7 +577,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> {
|
|||
Alias(Opaque, AliasTy { def_id, .. }) => {
|
||||
let parent = self.tcx.parent(def_id);
|
||||
let parent_ty = self.tcx.type_of(parent).instantiate_identity();
|
||||
if let hir::def::DefKind::TyAlias { .. } | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent)
|
||||
if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent)
|
||||
&& let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *parent_ty.kind()
|
||||
&& parent_opaque_def_id == def_id
|
||||
{
|
||||
|
|
|
|||
|
|
@ -385,7 +385,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
let index = entry.index();
|
||||
let var = ty::BoundVar::from_usize(index);
|
||||
let kind = entry
|
||||
.or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon(None)))
|
||||
.or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon))
|
||||
.expect_region();
|
||||
let br = ty::BoundRegion { var, kind };
|
||||
ty::Region::new_late_bound(self.tcx, ty::INNERMOST, br)
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ impl<'tcx> Instance<'tcx> {
|
|||
/// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization.
|
||||
pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
|
||||
let ty = tcx.type_of(self.def.def_id());
|
||||
tcx.subst_and_normalize_erasing_regions(self.args, param_env, ty)
|
||||
tcx.instantiate_and_normalize_erasing_regions(self.args, param_env, ty)
|
||||
}
|
||||
|
||||
/// Finds a crate that contains a monomorphization of this instance that
|
||||
|
|
@ -580,7 +580,7 @@ impl<'tcx> Instance<'tcx> {
|
|||
self.def.has_polymorphic_mir_body().then_some(self.args)
|
||||
}
|
||||
|
||||
pub fn subst_mir<T>(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<&T>) -> T
|
||||
pub fn instantiate_mir<T>(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<&T>) -> T
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>> + Copy,
|
||||
{
|
||||
|
|
@ -593,7 +593,7 @@ impl<'tcx> Instance<'tcx> {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn subst_mir_and_normalize_erasing_regions<T>(
|
||||
pub fn instantiate_mir_and_normalize_erasing_regions<T>(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
|
@ -603,14 +603,14 @@ impl<'tcx> Instance<'tcx> {
|
|||
T: TypeFoldable<TyCtxt<'tcx>> + Clone,
|
||||
{
|
||||
if let Some(args) = self.args_for_mir_body() {
|
||||
tcx.subst_and_normalize_erasing_regions(args, param_env, v)
|
||||
tcx.instantiate_and_normalize_erasing_regions(args, param_env, v)
|
||||
} else {
|
||||
tcx.normalize_erasing_regions(param_env, v.skip_binder())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn try_subst_mir_and_normalize_erasing_regions<T>(
|
||||
pub fn try_instantiate_mir_and_normalize_erasing_regions<T>(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
|
@ -620,7 +620,7 @@ impl<'tcx> Instance<'tcx> {
|
|||
T: TypeFoldable<TyCtxt<'tcx>> + Clone,
|
||||
{
|
||||
if let Some(args) = self.args_for_mir_body() {
|
||||
tcx.try_subst_and_normalize_erasing_regions(args, param_env, v)
|
||||
tcx.try_instantiate_and_normalize_erasing_regions(args, param_env, v)
|
||||
} else {
|
||||
tcx.try_normalize_erasing_regions(param_env, v.skip_binder())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,8 +134,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// in-scope substitutions and then normalizing any associated
|
||||
/// types.
|
||||
/// Panics if normalization fails. In case normalization might fail
|
||||
/// use `try_subst_and_normalize_erasing_regions` instead.
|
||||
pub fn subst_and_normalize_erasing_regions<T>(
|
||||
/// use `try_instantiate_and_normalize_erasing_regions` instead.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub fn instantiate_and_normalize_erasing_regions<T>(
|
||||
self,
|
||||
param_args: GenericArgsRef<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
|
@ -144,22 +145,16 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
debug!(
|
||||
"subst_and_normalize_erasing_regions(\
|
||||
param_args={:?}, \
|
||||
value={:?}, \
|
||||
param_env={:?})",
|
||||
param_args, value, param_env,
|
||||
);
|
||||
let substituted = value.instantiate(self, param_args);
|
||||
self.normalize_erasing_regions(param_env, substituted)
|
||||
}
|
||||
|
||||
/// Monomorphizes a type from the AST by first applying the
|
||||
/// in-scope substitutions and then trying to normalize any associated
|
||||
/// types. Contrary to `subst_and_normalize_erasing_regions` this does
|
||||
/// types. Contrary to `instantiate_and_normalize_erasing_regions` this does
|
||||
/// not assume that normalization succeeds.
|
||||
pub fn try_subst_and_normalize_erasing_regions<T>(
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub fn try_instantiate_and_normalize_erasing_regions<T>(
|
||||
self,
|
||||
param_args: GenericArgsRef<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
|
@ -168,13 +163,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
debug!(
|
||||
"subst_and_normalize_erasing_regions(\
|
||||
param_args={:?}, \
|
||||
value={:?}, \
|
||||
param_env={:?})",
|
||||
param_args, value, param_env,
|
||||
);
|
||||
let substituted = value.instantiate(self, param_args);
|
||||
self.try_normalize_erasing_regions(param_env, substituted)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -360,7 +360,7 @@ pub trait PrettyPrinter<'tcx>:
|
|||
self.write_str(get_local_name(&self, symbol, parent, parent_key).as_str())?;
|
||||
self.write_str("::")?;
|
||||
} else if let DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::Trait
|
||||
| DefKind::TyAlias { .. } | DefKind::Fn | DefKind::Const | DefKind::Static(_) = kind
|
||||
| DefKind::TyAlias | DefKind::Fn | DefKind::Const | DefKind::Static(_) = kind
|
||||
{
|
||||
} else {
|
||||
// If not covered above, like for example items out of `impl` blocks, fallback.
|
||||
|
|
@ -766,7 +766,7 @@ pub trait PrettyPrinter<'tcx>:
|
|||
|
||||
let parent = self.tcx().parent(def_id);
|
||||
match self.tcx().def_kind(parent) {
|
||||
DefKind::TyAlias { .. } | DefKind::AssocTy => {
|
||||
DefKind::TyAlias | DefKind::AssocTy => {
|
||||
// NOTE: I know we should check for NO_QUERIES here, but it's alright.
|
||||
// `type_of` on a type alias or assoc type should never cause a cycle.
|
||||
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: d, .. }) =
|
||||
|
|
@ -2330,7 +2330,7 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
|
|||
// If this is an anonymous placeholder, don't rename. Otherwise, in some
|
||||
// async fns, we get a `for<'r> Send` bound
|
||||
match kind {
|
||||
ty::BrAnon(..) | ty::BrEnv => r,
|
||||
ty::BrAnon | ty::BrEnv => r,
|
||||
_ => {
|
||||
// Index doesn't matter, since this is just for naming and these never get bound
|
||||
let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind };
|
||||
|
|
@ -2451,7 +2451,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
|
|||
binder_level_idx: ty::DebruijnIndex,
|
||||
br: ty::BoundRegion| {
|
||||
let (name, kind) = match br.kind {
|
||||
ty::BrAnon(..) | ty::BrEnv => {
|
||||
ty::BrAnon | ty::BrEnv => {
|
||||
let name = next_name(&self);
|
||||
|
||||
if let Some(lt_idx) = lifetime_idx {
|
||||
|
|
@ -2998,7 +2998,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
|
|||
|
||||
match child.res {
|
||||
def::Res::Def(DefKind::AssocTy, _) => {}
|
||||
def::Res::Def(DefKind::TyAlias { .. }, _) => {}
|
||||
def::Res::Def(DefKind::TyAlias, _) => {}
|
||||
def::Res::Def(defkind, def_id) => {
|
||||
if let Some(ns) = defkind.ns() {
|
||||
collect_fn(&child.ident, ns, def_id);
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> {
|
|||
impl fmt::Debug for ty::BoundRegionKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
ty::BrAnon(span) => write!(f, "BrAnon({span:?})"),
|
||||
ty::BrAnon => write!(f, "BrAnon"),
|
||||
ty::BrNamed(did, name) => {
|
||||
if did.is_crate_root() {
|
||||
write!(f, "BrNamed({name})")
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ pub struct FreeRegion {
|
|||
#[derive(HashStable)]
|
||||
pub enum BoundRegionKind {
|
||||
/// An anonymous region parameter for a given fn (&T)
|
||||
BrAnon(Option<Span>),
|
||||
BrAnon,
|
||||
|
||||
/// Named region parameters for functions (a in &'a T)
|
||||
///
|
||||
|
|
@ -1223,7 +1223,7 @@ impl<'tcx> AliasTy<'tcx> {
|
|||
DefKind::AssocTy if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) => ty::Inherent,
|
||||
DefKind::AssocTy => ty::Projection,
|
||||
DefKind::OpaqueTy => ty::Opaque,
|
||||
DefKind::TyAlias { .. } => ty::Weak,
|
||||
DefKind::TyAlias => ty::Weak,
|
||||
kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
|
||||
}
|
||||
}
|
||||
|
|
@ -1465,7 +1465,7 @@ impl<'tcx> Region<'tcx> {
|
|||
bound_region: ty::BoundRegion,
|
||||
) -> Region<'tcx> {
|
||||
// Use a pre-interned one when possible.
|
||||
if let ty::BoundRegion { var, kind: ty::BrAnon(None) } = bound_region
|
||||
if let ty::BoundRegion { var, kind: ty::BrAnon } = bound_region
|
||||
&& let Some(inner) = tcx.lifetimes.re_late_bounds.get(debruijn.as_usize())
|
||||
&& let Some(re) = inner.get(var.as_usize()).copied()
|
||||
{
|
||||
|
|
@ -1959,7 +1959,7 @@ impl<'tcx> Ty<'tcx> {
|
|||
(kind, tcx.def_kind(alias_ty.def_id)),
|
||||
(ty::Opaque, DefKind::OpaqueTy)
|
||||
| (ty::Projection | ty::Inherent, DefKind::AssocTy)
|
||||
| (ty::Weak, DefKind::TyAlias { .. })
|
||||
| (ty::Weak, DefKind::TyAlias)
|
||||
);
|
||||
Ty::new(tcx, Alias(kind, alias_ty))
|
||||
}
|
||||
|
|
@ -3010,7 +3010,7 @@ mod size_asserts {
|
|||
use super::*;
|
||||
use rustc_data_structures::static_assert_size;
|
||||
// tidy-alphabetical-start
|
||||
static_assert_size!(RegionKind<'_>, 28);
|
||||
static_assert_size!(RegionKind<'_>, 24);
|
||||
static_assert_size!(TyKind<'_>, 32);
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
| DefKind::Enum
|
||||
| DefKind::Trait
|
||||
| DefKind::OpaqueTy
|
||||
| DefKind::TyAlias { .. }
|
||||
| DefKind::TyAlias
|
||||
| DefKind::ForeignTy
|
||||
| DefKind::TraitAlias
|
||||
| DefKind::AssocTy
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ fn find_item_ty_spans(
|
|||
match ty.kind {
|
||||
hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
|
||||
if let Res::Def(kind, def_id) = path.res
|
||||
&& !matches!(kind, DefKind::TyAlias { .. }) {
|
||||
&& !matches!(kind, DefKind::TyAlias) {
|
||||
let check_params = def_id.as_local().map_or(true, |def_id| {
|
||||
if def_id == needle {
|
||||
spans.push(ty.span);
|
||||
|
|
|
|||
|
|
@ -229,6 +229,9 @@ mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type
|
|||
.suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
|
||||
.help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
|
||||
|
||||
mir_build_non_partial_eq_match =
|
||||
to use a constant of type `{$non_peq_ty}` in a pattern, the type must implement `PartialEq`
|
||||
|
||||
mir_build_nontrivial_structural_match =
|
||||
to use a constant of type `{$non_sm_ty}` in a pattern, the constant's initializer must be trivial or `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
|
||||
|
|
|
|||
|
|
@ -748,6 +748,12 @@ pub struct NontrivialStructuralMatch<'tcx> {
|
|||
pub non_sm_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(mir_build_non_partial_eq_match)]
|
||||
pub struct NonPartialEqMatch<'tcx> {
|
||||
pub non_peq_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(mir_build_overlapping_range_endpoints)]
|
||||
#[note]
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ use std::cell::Cell;
|
|||
|
||||
use super::PatCtxt;
|
||||
use crate::errors::{
|
||||
FloatPattern, IndirectStructuralMatch, InvalidPattern, NontrivialStructuralMatch,
|
||||
PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern,
|
||||
FloatPattern, IndirectStructuralMatch, InvalidPattern, NonPartialEqMatch,
|
||||
NontrivialStructuralMatch, PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern,
|
||||
};
|
||||
|
||||
impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
|
|
@ -155,8 +155,9 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
};
|
||||
|
||||
if !self.saw_const_match_error.get() {
|
||||
// If we were able to successfully convert the const to some pat,
|
||||
// double-check that all types in the const implement `Structural`.
|
||||
// If we were able to successfully convert the const to some pat (possibly with some
|
||||
// lints, but no errors), double-check that all types in the const implement
|
||||
// `Structural` and `PartialEq`.
|
||||
|
||||
let structural =
|
||||
traits::search_for_structural_match_violation(self.span, self.tcx(), cv.ty());
|
||||
|
|
@ -178,7 +179,7 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
}
|
||||
|
||||
if let Some(non_sm_ty) = structural {
|
||||
if !self.type_may_have_partial_eq_impl(cv.ty()) {
|
||||
if !self.type_has_partial_eq_impl(cv.ty()) {
|
||||
if let ty::Adt(def, ..) = non_sm_ty.kind() {
|
||||
if def.is_union() {
|
||||
let err = UnionPattern { span: self.span };
|
||||
|
|
@ -192,8 +193,10 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
} else {
|
||||
let err = InvalidPattern { span: self.span, non_sm_ty };
|
||||
self.tcx().sess.emit_err(err);
|
||||
return Box::new(Pat { span: self.span, ty: cv.ty(), kind: PatKind::Wild });
|
||||
}
|
||||
// All branches above emitted an error. Don't print any more lints.
|
||||
// The pattern we return is irrelevant since we errored.
|
||||
return Box::new(Pat { span: self.span, ty: cv.ty(), kind: PatKind::Wild });
|
||||
} else if !self.saw_const_match_lint.get() {
|
||||
if let Some(mir_structural_match_violation) = mir_structural_match_violation {
|
||||
match non_sm_ty.kind() {
|
||||
|
|
@ -238,13 +241,24 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// Always check for `PartialEq`, even if we emitted other lints. (But not if there were
|
||||
// any errors.) This ensures it shows up in cargo's future-compat reports as well.
|
||||
if !self.type_has_partial_eq_impl(cv.ty()) {
|
||||
self.tcx().emit_spanned_lint(
|
||||
lint::builtin::CONST_PATTERNS_WITHOUT_PARTIAL_EQ,
|
||||
self.id,
|
||||
self.span,
|
||||
NonPartialEqMatch { non_peq_ty: cv.ty() },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
inlined_const_as_pat
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self), ret)]
|
||||
fn type_may_have_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool {
|
||||
fn type_has_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool {
|
||||
// double-check there even *is* a semantic `PartialEq` to dispatch to.
|
||||
//
|
||||
// (If there isn't, then we can safely issue a hard
|
||||
|
|
@ -259,8 +273,13 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
ty::TraitRef::new(self.tcx(), partial_eq_trait_id, [ty, ty]),
|
||||
);
|
||||
|
||||
// FIXME: should this call a `predicate_must_hold` variant instead?
|
||||
self.infcx.predicate_may_hold(&partial_eq_obligation)
|
||||
// This *could* accept a type that isn't actually `PartialEq`, because region bounds get
|
||||
// ignored. However that should be pretty much impossible since consts that do not depend on
|
||||
// generics can only mention the `'static` lifetime, and how would one have a type that's
|
||||
// `PartialEq` for some lifetime but *not* for `'static`? If this ever becomes a problem
|
||||
// we'll need to leave some sort of trace of this requirement in the MIR so that borrowck
|
||||
// can ensure that the type really implements `PartialEq`.
|
||||
self.infcx.predicate_must_hold_modulo_regions(&partial_eq_obligation)
|
||||
}
|
||||
|
||||
fn field_pats(
|
||||
|
|
|
|||
|
|
@ -439,7 +439,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
DefKind::Struct
|
||||
| DefKind::Ctor(CtorOf::Struct, ..)
|
||||
| DefKind::Union
|
||||
| DefKind::TyAlias { .. }
|
||||
| DefKind::TyAlias
|
||||
| DefKind::AssocTy,
|
||||
_,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -758,7 +758,9 @@ impl Map {
|
|||
self.value_count += 1;
|
||||
}
|
||||
|
||||
if let Some(ref_ty) = ty.builtin_deref(true) && let ty::Slice(..) = ref_ty.ty.kind() {
|
||||
if let ty::Ref(_, ref_ty, _) | ty::RawPtr(ty::TypeAndMut { ty: ref_ty, .. }) = ty.kind()
|
||||
&& let ty::Slice(..) = ref_ty.kind()
|
||||
{
|
||||
assert!(self.places[place].value_index.is_none(), "slices are not scalars");
|
||||
|
||||
// Prepend new child to the linked list.
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ impl<'tcx> Inliner<'tcx> {
|
|||
return Err("optimization fuel exhausted");
|
||||
}
|
||||
|
||||
let Ok(callee_body) = callsite.callee.try_subst_mir_and_normalize_erasing_regions(
|
||||
let Ok(callee_body) = callsite.callee.try_instantiate_mir_and_normalize_erasing_regions(
|
||||
self.tcx,
|
||||
self.param_env,
|
||||
ty::EarlyBinder::bind(callee_body.clone()),
|
||||
|
|
@ -481,9 +481,10 @@ impl<'tcx> Inliner<'tcx> {
|
|||
work_list.push(target);
|
||||
|
||||
// If the place doesn't actually need dropping, treat it like a regular goto.
|
||||
let ty = callsite
|
||||
.callee
|
||||
.subst_mir(self.tcx, ty::EarlyBinder::bind(&place.ty(callee_body, tcx).ty));
|
||||
let ty = callsite.callee.instantiate_mir(
|
||||
self.tcx,
|
||||
ty::EarlyBinder::bind(&place.ty(callee_body, tcx).ty),
|
||||
);
|
||||
if ty.needs_drop(tcx, self.param_env) && let UnwindAction::Cleanup(unwind) = unwind {
|
||||
work_list.push(unwind);
|
||||
}
|
||||
|
|
@ -650,7 +651,7 @@ impl<'tcx> Inliner<'tcx> {
|
|||
// Copy only unevaluated constants from the callee_body into the caller_body.
|
||||
// Although we are only pushing `ConstKind::Unevaluated` consts to
|
||||
// `required_consts`, here we may not only have `ConstKind::Unevaluated`
|
||||
// because we are calling `subst_and_normalize_erasing_regions`.
|
||||
// because we are calling `instantiate_and_normalize_erasing_regions`.
|
||||
caller_body.required_consts.extend(
|
||||
callee_body.required_consts.iter().copied().filter(|&ct| match ct.const_ {
|
||||
Const::Ty(_) => {
|
||||
|
|
@ -811,9 +812,10 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
|
|||
match terminator.kind {
|
||||
TerminatorKind::Drop { ref place, unwind, .. } => {
|
||||
// If the place doesn't actually need dropping, treat it like a regular goto.
|
||||
let ty = self
|
||||
.instance
|
||||
.subst_mir(tcx, ty::EarlyBinder::bind(&place.ty(self.callee_body, tcx).ty));
|
||||
let ty = self.instance.instantiate_mir(
|
||||
tcx,
|
||||
ty::EarlyBinder::bind(&place.ty(self.callee_body, tcx).ty),
|
||||
);
|
||||
if ty.needs_drop(tcx, self.param_env) {
|
||||
self.cost += CALL_PENALTY;
|
||||
if let UnwindAction::Cleanup(_) = unwind {
|
||||
|
|
@ -824,7 +826,8 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
TerminatorKind::Call { func: Operand::Constant(ref f), unwind, .. } => {
|
||||
let fn_ty = self.instance.subst_mir(tcx, ty::EarlyBinder::bind(&f.const_.ty()));
|
||||
let fn_ty =
|
||||
self.instance.instantiate_mir(tcx, ty::EarlyBinder::bind(&f.const_.ty()));
|
||||
self.cost += if let ty::FnDef(def_id, _) = *fn_ty.kind() && tcx.is_intrinsic(def_id) {
|
||||
// Don't give intrinsics the extra penalty for calls
|
||||
INSTR_COST
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
|
|||
) -> bool {
|
||||
trace!(%caller);
|
||||
for &(callee, args) in tcx.mir_inliner_callees(caller.def) {
|
||||
let Ok(args) = caller.try_subst_mir_and_normalize_erasing_regions(
|
||||
let Ok(args) = caller.try_instantiate_mir_and_normalize_erasing_regions(
|
||||
tcx,
|
||||
param_env,
|
||||
ty::EarlyBinder::bind(args),
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
use crate::MirPass;
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_index::{Idx, IndexSlice, IndexVec};
|
||||
use rustc_middle::mir::coverage::*;
|
||||
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
|
||||
|
|
@ -345,24 +346,22 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
|||
|
||||
let basic_blocks = body.basic_blocks.as_mut();
|
||||
let source_scopes = &body.source_scopes;
|
||||
let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect();
|
||||
let mut used_blocks = 0;
|
||||
for alive_index in reachable.iter() {
|
||||
let alive_index = alive_index.index();
|
||||
replacements[alive_index] = BasicBlock::new(used_blocks);
|
||||
if alive_index != used_blocks {
|
||||
// Swap the next alive block data with the current available slot. Since
|
||||
// alive_index is non-decreasing this is a valid operation.
|
||||
basic_blocks.raw.swap(alive_index, used_blocks);
|
||||
}
|
||||
used_blocks += 1;
|
||||
}
|
||||
|
||||
if tcx.sess.instrument_coverage() {
|
||||
save_unreachable_coverage(basic_blocks, source_scopes, used_blocks);
|
||||
save_unreachable_coverage(basic_blocks, source_scopes, &reachable);
|
||||
}
|
||||
|
||||
basic_blocks.raw.truncate(used_blocks);
|
||||
let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect();
|
||||
let mut orig_index = 0;
|
||||
let mut used_index = 0;
|
||||
basic_blocks.raw.retain(|_| {
|
||||
let keep = reachable.contains(BasicBlock::new(orig_index));
|
||||
if keep {
|
||||
replacements[orig_index] = BasicBlock::new(used_index);
|
||||
used_index += 1;
|
||||
}
|
||||
orig_index += 1;
|
||||
keep
|
||||
});
|
||||
|
||||
for block in basic_blocks {
|
||||
for target in block.terminator_mut().successors_mut() {
|
||||
|
|
@ -404,11 +403,12 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
|||
fn save_unreachable_coverage(
|
||||
basic_blocks: &mut IndexSlice<BasicBlock, BasicBlockData<'_>>,
|
||||
source_scopes: &IndexSlice<SourceScope, SourceScopeData<'_>>,
|
||||
first_dead_block: usize,
|
||||
reachable: &BitSet<BasicBlock>,
|
||||
) {
|
||||
// Identify instances that still have some live coverage counters left.
|
||||
let mut live = FxHashSet::default();
|
||||
for basic_block in &basic_blocks.raw[0..first_dead_block] {
|
||||
for bb in reachable.iter() {
|
||||
let basic_block = &basic_blocks[bb];
|
||||
for statement in &basic_block.statements {
|
||||
let StatementKind::Coverage(coverage) = &statement.kind else { continue };
|
||||
let CoverageKind::Counter { .. } = coverage.kind else { continue };
|
||||
|
|
@ -417,7 +417,8 @@ fn save_unreachable_coverage(
|
|||
}
|
||||
}
|
||||
|
||||
for block in &mut basic_blocks.raw[..first_dead_block] {
|
||||
for bb in reachable.iter() {
|
||||
let block = &mut basic_blocks[bb];
|
||||
for statement in &mut block.statements {
|
||||
let StatementKind::Coverage(_) = &statement.kind else { continue };
|
||||
let instance = statement.source_info.scope.inlined_instance(source_scopes);
|
||||
|
|
@ -433,7 +434,11 @@ fn save_unreachable_coverage(
|
|||
|
||||
// Retain coverage for instances that still have some live counters left.
|
||||
let mut retained_coverage = Vec::new();
|
||||
for dead_block in &basic_blocks.raw[first_dead_block..] {
|
||||
for dead_block in basic_blocks.indices() {
|
||||
if reachable.contains(dead_block) {
|
||||
continue;
|
||||
}
|
||||
let dead_block = &basic_blocks[dead_block];
|
||||
for statement in &dead_block.statements {
|
||||
let StatementKind::Coverage(coverage) = &statement.kind else { continue };
|
||||
let Some(code_region) = &coverage.code_region else { continue };
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue