commit
93566275e3
575 changed files with 8441 additions and 4441 deletions
165
Cargo.lock
165
Cargo.lock
|
|
@ -2,34 +2,15 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"gimli 0.25.0",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
|
||||
dependencies = [
|
||||
"gimli 0.26.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"gimli",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
|
|
@ -38,6 +19,10 @@ name = "adler"
|
|||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
|
|
@ -185,12 +170,12 @@ version = "0.3.66"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7"
|
||||
dependencies = [
|
||||
"addr2line 0.17.0",
|
||||
"addr2line",
|
||||
"cc",
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"miniz_oxide 0.5.3",
|
||||
"object 0.29.0",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
]
|
||||
|
||||
|
|
@ -1295,15 +1280,15 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
|
|||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.16"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68c90b0fc46cf89d227cc78b40e494ff81287a92dd07631e5af0d06fe3cf885e"
|
||||
checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"cfg-if 1.0.0",
|
||||
"crc32fast",
|
||||
"libc",
|
||||
"libz-sys",
|
||||
"miniz_oxide 0.4.0",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1545,25 +1530,17 @@ dependencies = [
|
|||
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.26.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"fallible-iterator",
|
||||
"indexmap",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
|
|
@ -2226,25 +2203,16 @@ version = "0.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be0f75932c1f6cfae3c04000e40114adf955636e19040f9c0a2c380702aa1c7f"
|
||||
dependencies = [
|
||||
"adler 0.2.3",
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
|
||||
dependencies = [
|
||||
"adler 1.0.2",
|
||||
"adler",
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2346,29 +2314,20 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.26.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"memchr",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"crc32fast",
|
||||
"flate2",
|
||||
"hashbrown",
|
||||
"indexmap",
|
||||
"memchr",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2522,7 +2481,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core 0.9.3",
|
||||
"parking_lot_core 0.9.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2541,15 +2500,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.3"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
|
||||
checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-sys 0.36.1",
|
||||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2774,9 +2733,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "psm"
|
||||
version = "0.1.16"
|
||||
version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd136ff4382c4753fc061cb9e4712ab2af263376b95bbd5bd8cd50c020b78e69"
|
||||
checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
|
@ -3305,7 +3264,7 @@ dependencies = [
|
|||
"cstr",
|
||||
"libc",
|
||||
"measureme",
|
||||
"object 0.29.0",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"rustc_ast",
|
||||
"rustc_attr",
|
||||
|
|
@ -3339,7 +3298,7 @@ dependencies = [
|
|||
"itertools",
|
||||
"jobserver",
|
||||
"libc",
|
||||
"object 0.29.0",
|
||||
"object",
|
||||
"pathdiff",
|
||||
"regex",
|
||||
"rustc_arena",
|
||||
|
|
@ -4677,9 +4636,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
|||
|
||||
[[package]]
|
||||
name = "stacker"
|
||||
version = "0.1.14"
|
||||
version = "0.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90939d5171a4420b3ff5fbc8954d641e7377335454c259dcb80786f3f21dc9b4"
|
||||
checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if 1.0.0",
|
||||
|
|
@ -4698,7 +4657,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
|||
name = "std"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"addr2line 0.16.0",
|
||||
"addr2line",
|
||||
"alloc",
|
||||
"cfg-if 1.0.0",
|
||||
"compiler_builtins",
|
||||
|
|
@ -4708,8 +4667,8 @@ dependencies = [
|
|||
"hashbrown",
|
||||
"hermit-abi 0.2.6",
|
||||
"libc",
|
||||
"miniz_oxide 0.4.0",
|
||||
"object 0.26.2",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"panic_abort",
|
||||
"panic_unwind",
|
||||
"profiler_builtins",
|
||||
|
|
@ -4926,9 +4885,9 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6cb0c7868d7f90407531108ab03263d9452a8811b7cdd87675343a40d4aa254"
|
||||
dependencies = [
|
||||
"gimli 0.26.1",
|
||||
"gimli",
|
||||
"hashbrown",
|
||||
"object 0.29.0",
|
||||
"object",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
|
@ -5499,17 +5458,25 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.36.1"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
|
||||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc 0.36.1",
|
||||
"windows_i686_gnu 0.36.1",
|
||||
"windows_i686_msvc 0.36.1",
|
||||
"windows_x86_64_gnu 0.36.1",
|
||||
"windows_x86_64_msvc 0.36.1",
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc 0.42.0",
|
||||
"windows_i686_gnu 0.42.0",
|
||||
"windows_i686_msvc 0.42.0",
|
||||
"windows_x86_64_gnu 0.42.0",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.28.0"
|
||||
|
|
@ -5518,9 +5485,9 @@ checksum = "52695a41e536859d5308cc613b4a022261a274390b25bd29dfff4bf08505f3c2"
|
|||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.36.1"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
|
||||
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
|
|
@ -5530,9 +5497,9 @@ checksum = "f54725ac23affef038fecb177de6c9bf065787c2f432f79e3c373da92f3e1d8a"
|
|||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.36.1"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
|
||||
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
|
|
@ -5542,9 +5509,9 @@ checksum = "51d5158a43cc43623c0729d1ad6647e62fa384a3d135fd15108d37c683461f64"
|
|||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.36.1"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
|
||||
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
|
|
@ -5554,9 +5521,15 @@ checksum = "bc31f409f565611535130cfe7ee8e6655d3fa99c1c61013981e491921b5ce954"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.36.1"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
|
||||
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
|
|
@ -5566,9 +5539,9 @@ checksum = "3f2b8c7cbd3bfdddd9ab98769f9746a7fad1bca236554cd032b78d768bc0e89f"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.36.1"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
|
||||
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
|
||||
|
||||
[[package]]
|
||||
name = "xattr"
|
||||
|
|
|
|||
|
|
@ -2,12 +2,9 @@
|
|||
|
||||
use crate::ast::{self, Lit, LitKind};
|
||||
use crate::token::{self, Token};
|
||||
|
||||
use rustc_lexer::unescape::{unescape_byte, unescape_char};
|
||||
use rustc_lexer::unescape::{unescape_byte_literal, unescape_literal, Mode};
|
||||
use rustc_lexer::unescape::{byte_from_char, unescape_byte, unescape_char, unescape_literal, Mode};
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
||||
use std::ascii;
|
||||
|
||||
pub enum LitError {
|
||||
|
|
@ -109,13 +106,11 @@ impl LitKind {
|
|||
let s = symbol.as_str();
|
||||
let mut buf = Vec::with_capacity(s.len());
|
||||
let mut error = Ok(());
|
||||
unescape_byte_literal(&s, Mode::ByteStr, &mut |_, unescaped_byte| {
|
||||
match unescaped_byte {
|
||||
Ok(c) => buf.push(c),
|
||||
Err(err) => {
|
||||
if err.is_fatal() {
|
||||
error = Err(LitError::LexerError);
|
||||
}
|
||||
unescape_literal(&s, Mode::ByteStr, &mut |_, c| match c {
|
||||
Ok(c) => buf.push(byte_from_char(c)),
|
||||
Err(err) => {
|
||||
if err.is_fatal() {
|
||||
error = Err(LitError::LexerError);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -127,13 +122,11 @@ impl LitKind {
|
|||
let bytes = if s.contains('\r') {
|
||||
let mut buf = Vec::with_capacity(s.len());
|
||||
let mut error = Ok(());
|
||||
unescape_byte_literal(&s, Mode::RawByteStr, &mut |_, unescaped_byte| {
|
||||
match unescaped_byte {
|
||||
Ok(c) => buf.push(c),
|
||||
Err(err) => {
|
||||
if err.is_fatal() {
|
||||
error = Err(LitError::LexerError);
|
||||
}
|
||||
unescape_literal(&s, Mode::RawByteStr, &mut |_, c| match c {
|
||||
Ok(c) => buf.push(byte_from_char(c)),
|
||||
Err(err) => {
|
||||
if err.is_fatal() {
|
||||
error = Err(LitError::LexerError);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@ impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Edges<'s, 'tcx, D> {
|
|||
span: DUMMY_SP,
|
||||
category: ConstraintCategory::Internal,
|
||||
variance_info: VarianceDiagInfo::default(),
|
||||
from_closure: false,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
|
|
|||
|
|
@ -96,6 +96,9 @@ pub struct OutlivesConstraint<'tcx> {
|
|||
|
||||
/// Variance diagnostic information
|
||||
pub variance_info: VarianceDiagInfo<'tcx>,
|
||||
|
||||
/// If this constraint is promoted from closure requirements.
|
||||
pub from_closure: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for OutlivesConstraint<'tcx> {
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ trait TypeOpInfo<'tcx> {
|
|||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>;
|
||||
|
||||
#[instrument(level = "debug", skip(self, mbcx))]
|
||||
fn report_error(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
|
||||
|
|
@ -167,6 +168,7 @@ trait TypeOpInfo<'tcx> {
|
|||
) {
|
||||
let tcx = mbcx.infcx.tcx;
|
||||
let base_universe = self.base_universe();
|
||||
debug!(?base_universe);
|
||||
|
||||
let Some(adjusted_universe) =
|
||||
placeholder.universe.as_u32().checked_sub(base_universe.as_u32())
|
||||
|
|
@ -389,6 +391,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
|
|||
)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(infcx, region_var_origin, universe_of_region))]
|
||||
fn try_extract_error_from_region_constraints<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
|
|
|
|||
|
|
@ -724,13 +724,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
borrow_span,
|
||||
&self.describe_any_place(borrow.borrowed_place.as_ref()),
|
||||
);
|
||||
|
||||
borrow_spans.var_span_label(
|
||||
borrow_spans.var_subdiag(
|
||||
&mut err,
|
||||
{
|
||||
|var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
let place = &borrow.borrowed_place;
|
||||
let desc_place = self.describe_any_place(place.as_ref());
|
||||
format!("borrow occurs due to use of {}{}", desc_place, borrow_spans.describe())
|
||||
match borrow_spans {
|
||||
UseSpans::ClosureUse { generator_kind, .. } => match generator_kind {
|
||||
Some(_) => BorrowUsePlaceGenerator { place: desc_place, var_span },
|
||||
None => BorrowUsePlaceClosure { place: desc_place, var_span },
|
||||
},
|
||||
_ => BorrowUsePlace { place: desc_place, var_span },
|
||||
}
|
||||
},
|
||||
"mutable",
|
||||
);
|
||||
|
|
@ -1551,7 +1557,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
|
||||
let mut err = self.temporary_value_borrowed_for_too_long(proper_span);
|
||||
err.span_label(proper_span, "creates a temporary which is freed while still in use");
|
||||
err.span_label(proper_span, "creates a temporary value which is freed while still in use");
|
||||
err.span_label(drop_span, "temporary value is freed at the end of this statement");
|
||||
|
||||
match explanation {
|
||||
|
|
|
|||
|
|
@ -623,6 +623,26 @@ impl UseSpans<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Add a subdiagnostic to the use of the captured variable, if it exists.
|
||||
pub(super) fn var_subdiag(
|
||||
self,
|
||||
err: &mut Diagnostic,
|
||||
f: impl Fn(Span) -> crate::session_diagnostics::CaptureVarCause,
|
||||
kind_desc: impl Into<String>,
|
||||
) {
|
||||
if let UseSpans::ClosureUse { capture_kind_span, path_span, .. } = self {
|
||||
if capture_kind_span == path_span {
|
||||
err.subdiagnostic(f(capture_kind_span));
|
||||
} else {
|
||||
err.subdiagnostic(crate::session_diagnostics::CaptureVarKind {
|
||||
kind_desc: kind_desc.into(),
|
||||
kind_span: capture_kind_span,
|
||||
});
|
||||
err.subdiagnostic(f(path_span));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `false` if this place is not used in a closure.
|
||||
pub(super) fn for_closure(&self) -> bool {
|
||||
match *self {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
//! Error reporting machinery for lifetime errors.
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
|
|
@ -181,7 +181,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
// Try to convert the lower-bound region into something named we can print for the user.
|
||||
let lower_bound_region = self.to_error_region(type_test.lower_bound);
|
||||
|
||||
let type_test_span = type_test.locations.span(&self.body);
|
||||
let type_test_span = type_test.span;
|
||||
|
||||
if let Some(lower_bound_region) = lower_bound_region {
|
||||
let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx);
|
||||
|
|
@ -276,7 +276,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
fn get_impl_ident_and_self_ty_from_trait(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
trait_objects: &FxHashSet<DefId>,
|
||||
trait_objects: &FxIndexSet<DefId>,
|
||||
) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> {
|
||||
let tcx = self.infcx.tcx;
|
||||
match tcx.hir().get_if_local(def_id) {
|
||||
|
|
@ -830,7 +830,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
};
|
||||
debug!(?param);
|
||||
|
||||
let mut visitor = TraitObjectVisitor(FxHashSet::default());
|
||||
let mut visitor = TraitObjectVisitor(FxIndexSet::default());
|
||||
visitor.visit_ty(param.param_ty);
|
||||
|
||||
let Some((ident, self_ty)) =
|
||||
|
|
@ -843,7 +843,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
fn suggest_constrain_dyn_trait_in_impl(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
found_dids: &FxHashSet<DefId>,
|
||||
found_dids: &FxIndexSet<DefId>,
|
||||
ident: Ident,
|
||||
self_ty: &hir::Ty<'_>,
|
||||
) -> bool {
|
||||
|
|
|
|||
|
|
@ -355,7 +355,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
ty::BoundRegionKind::BrAnon(_) => None,
|
||||
ty::BoundRegionKind::BrAnon(..) => None,
|
||||
},
|
||||
|
||||
ty::ReLateBound(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased => None,
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ extern crate tracing;
|
|||
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::graph::dominators::Dominators;
|
||||
use rustc_data_structures::vec_map::VecMap;
|
||||
use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
|
|
@ -129,6 +130,19 @@ fn mir_borrowck<'tcx>(
|
|||
) -> &'tcx BorrowCheckResult<'tcx> {
|
||||
let (input_body, promoted) = tcx.mir_promoted(def);
|
||||
debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
|
||||
|
||||
if input_body.borrow().should_skip() {
|
||||
debug!("Skipping borrowck because of injected body");
|
||||
// Let's make up a borrowck result! Fun times!
|
||||
let result = BorrowCheckResult {
|
||||
concrete_opaque_types: VecMap::new(),
|
||||
closure_requirements: None,
|
||||
used_mut_upvars: SmallVec::new(),
|
||||
tainted_by_errors: None,
|
||||
};
|
||||
return tcx.arena.alloc(result);
|
||||
}
|
||||
|
||||
let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
|
||||
|
||||
let infcx =
|
||||
|
|
|
|||
|
|
@ -242,7 +242,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
|||
mut liveness_constraints,
|
||||
outlives_constraints,
|
||||
member_constraints,
|
||||
closure_bounds_mapping,
|
||||
universe_causes,
|
||||
type_tests,
|
||||
} = constraints;
|
||||
|
|
@ -264,7 +263,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
|||
universal_region_relations,
|
||||
outlives_constraints,
|
||||
member_constraints,
|
||||
closure_bounds_mapping,
|
||||
universe_causes,
|
||||
type_tests,
|
||||
liveness_constraints,
|
||||
|
|
|
|||
|
|
@ -74,8 +74,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
|
||||
constraints.sort_by_key(|c| (c.sup, c.sub));
|
||||
for constraint in &constraints {
|
||||
let OutlivesConstraint { sup, sub, locations, category, span, variance_info: _ } =
|
||||
constraint;
|
||||
let OutlivesConstraint { sup, sub, locations, category, span, .. } = constraint;
|
||||
let (name, arg) = match locations {
|
||||
Locations::All(span) => {
|
||||
("All", tcx.sess.source_map().span_to_embeddable_string(*span))
|
||||
|
|
|
|||
|
|
@ -6,10 +6,9 @@ use rustc_data_structures::frozen::Frozen;
|
|||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::graph::scc::Sccs;
|
||||
use rustc_errors::Diagnostic;
|
||||
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
|
||||
use rustc_hir::def_id::CRATE_DEF_ID;
|
||||
use rustc_hir::CRATE_HIR_ID;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_infer::infer::canonical::QueryOutlivesConstraint;
|
||||
use rustc_infer::infer::outlives::test_type_match;
|
||||
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
|
||||
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
|
||||
|
|
@ -19,9 +18,7 @@ use rustc_middle::mir::{
|
|||
};
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::traits::ObligationCauseCode;
|
||||
use rustc_middle::ty::{
|
||||
self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable,
|
||||
};
|
||||
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable};
|
||||
use rustc_span::Span;
|
||||
|
||||
use crate::{
|
||||
|
|
@ -89,10 +86,6 @@ pub struct RegionInferenceContext<'tcx> {
|
|||
/// `member_region_scc`.
|
||||
member_constraints_applied: Vec<AppliedMemberConstraint>,
|
||||
|
||||
/// Map closure bounds to a `Span` that should be used for error reporting.
|
||||
closure_bounds_mapping:
|
||||
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>,
|
||||
|
||||
/// Map universe indexes to information on why we created it.
|
||||
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
|
||||
|
||||
|
|
@ -221,8 +214,8 @@ pub struct TypeTest<'tcx> {
|
|||
/// The region `'x` that the type must outlive.
|
||||
pub lower_bound: RegionVid,
|
||||
|
||||
/// Where did this constraint arise and why?
|
||||
pub locations: Locations,
|
||||
/// The span to blame.
|
||||
pub span: Span,
|
||||
|
||||
/// A test which, if met by the region `'x`, proves that this type
|
||||
/// constraint is satisfied.
|
||||
|
|
@ -265,10 +258,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
|
||||
outlives_constraints: OutlivesConstraintSet<'tcx>,
|
||||
member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
|
||||
closure_bounds_mapping: FxHashMap<
|
||||
Location,
|
||||
FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>,
|
||||
>,
|
||||
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
|
||||
type_tests: Vec<TypeTest<'tcx>>,
|
||||
liveness_constraints: LivenessValues<RegionVid>,
|
||||
|
|
@ -310,7 +299,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
rev_scc_graph: None,
|
||||
member_constraints,
|
||||
member_constraints_applied: Vec::new(),
|
||||
closure_bounds_mapping,
|
||||
universe_causes,
|
||||
scc_universes,
|
||||
scc_representatives,
|
||||
|
|
@ -882,13 +870,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
if deduplicate_errors.insert((
|
||||
erased_generic_kind,
|
||||
type_test.lower_bound,
|
||||
type_test.locations,
|
||||
type_test.span,
|
||||
)) {
|
||||
debug!(
|
||||
"check_type_test: reporting error for erased_generic_kind={:?}, \
|
||||
lower_bound_region={:?}, \
|
||||
type_test.locations={:?}",
|
||||
erased_generic_kind, type_test.lower_bound, type_test.locations,
|
||||
type_test.span={:?}",
|
||||
erased_generic_kind, type_test.lower_bound, type_test.span,
|
||||
);
|
||||
|
||||
errors_buffer.push(RegionErrorKind::TypeTestError { type_test: type_test.clone() });
|
||||
|
|
@ -931,7 +919,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
) -> bool {
|
||||
let tcx = infcx.tcx;
|
||||
|
||||
let TypeTest { generic_kind, lower_bound, locations, verify_bound: _ } = type_test;
|
||||
let TypeTest { generic_kind, lower_bound, span: _, verify_bound: _ } = type_test;
|
||||
|
||||
let generic_ty = generic_kind.to_ty(tcx);
|
||||
let Some(subject) = self.try_promote_type_test_subject(infcx, generic_ty) else {
|
||||
|
|
@ -959,7 +947,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
propagated_outlives_requirements.push(ClosureOutlivesRequirement {
|
||||
subject,
|
||||
outlived_free_region: static_r,
|
||||
blame_span: locations.span(body),
|
||||
blame_span: type_test.span,
|
||||
category: ConstraintCategory::Boring,
|
||||
});
|
||||
|
||||
|
|
@ -1011,7 +999,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
let requirement = ClosureOutlivesRequirement {
|
||||
subject,
|
||||
outlived_free_region: upper_bound,
|
||||
blame_span: locations.span(body),
|
||||
blame_span: type_test.span,
|
||||
category: ConstraintCategory::Boring,
|
||||
};
|
||||
debug!("try_promote_type_test: pushing {:#?}", requirement);
|
||||
|
|
@ -1804,18 +1792,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn retrieve_closure_constraint_info(
|
||||
&self,
|
||||
constraint: OutlivesConstraint<'tcx>,
|
||||
) -> Option<(ConstraintCategory<'tcx>, Span)> {
|
||||
match constraint.locations {
|
||||
Locations::All(_) => None,
|
||||
Locations::Single(loc) => {
|
||||
self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub)).copied()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`.
|
||||
pub(crate) fn find_outlives_blame_span(
|
||||
&self,
|
||||
|
|
@ -1921,6 +1897,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
span: p_c.definition_span,
|
||||
category: ConstraintCategory::OpaqueType,
|
||||
variance_info: ty::VarianceDiagInfo::default(),
|
||||
from_closure: false,
|
||||
};
|
||||
handle_constraint(constraint);
|
||||
}
|
||||
|
|
@ -2066,31 +2043,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
// Classify each of the constraints along the path.
|
||||
let mut categorized_path: Vec<BlameConstraint<'tcx>> = path
|
||||
.iter()
|
||||
.map(|constraint| {
|
||||
let (category, span, from_closure, cause_code) =
|
||||
if constraint.category == ConstraintCategory::ClosureBounds {
|
||||
if let Some((category, span)) =
|
||||
self.retrieve_closure_constraint_info(*constraint)
|
||||
{
|
||||
(category, span, true, ObligationCauseCode::MiscObligation)
|
||||
} else {
|
||||
(
|
||||
constraint.category,
|
||||
constraint.span,
|
||||
false,
|
||||
ObligationCauseCode::MiscObligation,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
(constraint.category, constraint.span, false, cause_code.clone())
|
||||
};
|
||||
BlameConstraint {
|
||||
category,
|
||||
from_closure,
|
||||
cause: ObligationCause::new(span, CRATE_HIR_ID, cause_code),
|
||||
variance_info: constraint.variance_info,
|
||||
outlives_constraint: *constraint,
|
||||
}
|
||||
.map(|constraint| BlameConstraint {
|
||||
category: constraint.category,
|
||||
from_closure: constraint.from_closure,
|
||||
cause: ObligationCause::new(constraint.span, CRATE_HIR_ID, cause_code.clone()),
|
||||
variance_info: constraint.variance_info,
|
||||
outlives_constraint: *constraint,
|
||||
})
|
||||
.collect();
|
||||
debug!("categorized_path={:#?}", categorized_path);
|
||||
|
|
@ -2274,92 +2232,6 @@ impl<'tcx> RegionDefinition<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait ClosureRegionRequirementsExt<'tcx> {
|
||||
fn apply_requirements(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
closure_def_id: DefId,
|
||||
closure_substs: SubstsRef<'tcx>,
|
||||
) -> Vec<QueryOutlivesConstraint<'tcx>>;
|
||||
}
|
||||
|
||||
impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx> {
|
||||
/// Given an instance T of the closure type, this method
|
||||
/// instantiates the "extra" requirements that we computed for the
|
||||
/// closure into the inference context. This has the effect of
|
||||
/// adding new outlives obligations to existing variables.
|
||||
///
|
||||
/// As described on `ClosureRegionRequirements`, the extra
|
||||
/// requirements are expressed in terms of regionvids that index
|
||||
/// into the free regions that appear on the closure type. So, to
|
||||
/// do this, we first copy those regions out from the type T into
|
||||
/// a vector. Then we can just index into that vector to extract
|
||||
/// out the corresponding region from T and apply the
|
||||
/// requirements.
|
||||
fn apply_requirements(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
closure_def_id: DefId,
|
||||
closure_substs: SubstsRef<'tcx>,
|
||||
) -> Vec<QueryOutlivesConstraint<'tcx>> {
|
||||
debug!(
|
||||
"apply_requirements(closure_def_id={:?}, closure_substs={:?})",
|
||||
closure_def_id, closure_substs
|
||||
);
|
||||
|
||||
// Extract the values of the free regions in `closure_substs`
|
||||
// into a vector. These are the regions that we will be
|
||||
// relating to one another.
|
||||
let closure_mapping = &UniversalRegions::closure_mapping(
|
||||
tcx,
|
||||
closure_substs,
|
||||
self.num_external_vids,
|
||||
closure_def_id.expect_local(),
|
||||
);
|
||||
debug!("apply_requirements: closure_mapping={:?}", closure_mapping);
|
||||
|
||||
// Create the predicates.
|
||||
self.outlives_requirements
|
||||
.iter()
|
||||
.map(|outlives_requirement| {
|
||||
let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
|
||||
|
||||
match outlives_requirement.subject {
|
||||
ClosureOutlivesSubject::Region(region) => {
|
||||
let region = closure_mapping[region];
|
||||
debug!(
|
||||
"apply_requirements: region={:?} \
|
||||
outlived_region={:?} \
|
||||
outlives_requirement={:?}",
|
||||
region, outlived_region, outlives_requirement,
|
||||
);
|
||||
(
|
||||
ty::Binder::dummy(ty::OutlivesPredicate(
|
||||
region.into(),
|
||||
outlived_region,
|
||||
)),
|
||||
ConstraintCategory::BoringNoLocation,
|
||||
)
|
||||
}
|
||||
|
||||
ClosureOutlivesSubject::Ty(ty) => {
|
||||
debug!(
|
||||
"apply_requirements: ty={:?} \
|
||||
outlived_region={:?} \
|
||||
outlives_requirement={:?}",
|
||||
ty, outlived_region, outlives_requirement,
|
||||
);
|
||||
(
|
||||
ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), outlived_region)),
|
||||
ConstraintCategory::BoringNoLocation,
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BlameConstraint<'tcx> {
|
||||
pub category: ConstraintCategory<'tcx>,
|
||||
|
|
|
|||
|
|
@ -299,8 +299,8 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
|||
if errors.is_empty() {
|
||||
definition_ty
|
||||
} else {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
||||
self.tcx.ty_error()
|
||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||
self.tcx.ty_error_with_guaranteed(reported)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,3 +148,33 @@ pub(crate) enum RequireStaticErr {
|
|||
multi_span: MultiSpan,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[label(borrowck_capture_kind_label)]
|
||||
pub(crate) struct CaptureVarKind {
|
||||
pub kind_desc: String,
|
||||
#[primary_span]
|
||||
pub kind_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum CaptureVarCause {
|
||||
#[label(borrowck_var_borrow_by_use_place)]
|
||||
BorrowUsePlace {
|
||||
place: String,
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_borrow_by_use_place_in_generator)]
|
||||
BorrowUsePlaceGenerator {
|
||||
place: String,
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_borrow_by_use_place_in_closure)]
|
||||
BorrowUsePlaceClosure {
|
||||
place: String,
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use rustc_infer::infer::canonical::QueryOutlivesConstraint;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
||||
use rustc_infer::infer::outlives::env::RegionBoundPairs;
|
||||
use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
|
||||
use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
|
||||
use rustc_infer::infer::{self, InferCtxt, SubregionOrigin};
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
|
||||
use rustc_middle::ty::subst::GenericArgKind;
|
||||
use rustc_middle::ty::TypeFoldable;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
|
|
@ -38,6 +38,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
|
|||
locations: Locations,
|
||||
span: Span,
|
||||
category: ConstraintCategory<'tcx>,
|
||||
from_closure: bool,
|
||||
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
|
||||
}
|
||||
|
||||
|
|
@ -64,6 +65,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
span,
|
||||
category,
|
||||
constraints,
|
||||
from_closure: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -81,12 +83,62 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
}
|
||||
self.constraints.member_constraints = tmp;
|
||||
|
||||
for query_constraint in outlives {
|
||||
self.convert(query_constraint);
|
||||
for (predicate, constraint_category) in outlives {
|
||||
// At the moment, we never generate any "higher-ranked"
|
||||
// region constraints like `for<'a> 'a: 'b`. At some point
|
||||
// when we move to universes, we will, and this assertion
|
||||
// will start to fail.
|
||||
let predicate = predicate.no_bound_vars().unwrap_or_else(|| {
|
||||
bug!("query_constraint {:?} contained bound vars", predicate,);
|
||||
});
|
||||
|
||||
self.convert(predicate, *constraint_category);
|
||||
}
|
||||
}
|
||||
|
||||
fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) {
|
||||
/// Given an instance of the closure type, this method instantiates the "extra" requirements
|
||||
/// that we computed for the closure. This has the effect of adding new outlives obligations
|
||||
/// to existing region variables in `closure_substs`.
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub fn apply_closure_requirements(
|
||||
&mut self,
|
||||
closure_requirements: &ClosureRegionRequirements<'tcx>,
|
||||
closure_def_id: DefId,
|
||||
closure_substs: ty::SubstsRef<'tcx>,
|
||||
) {
|
||||
// Extract the values of the free regions in `closure_substs`
|
||||
// into a vector. These are the regions that we will be
|
||||
// relating to one another.
|
||||
let closure_mapping = &UniversalRegions::closure_mapping(
|
||||
self.tcx,
|
||||
closure_substs,
|
||||
closure_requirements.num_external_vids,
|
||||
closure_def_id.expect_local(),
|
||||
);
|
||||
debug!(?closure_mapping);
|
||||
|
||||
// Create the predicates.
|
||||
let backup = (self.category, self.span, self.from_closure);
|
||||
self.from_closure = true;
|
||||
for outlives_requirement in &closure_requirements.outlives_requirements {
|
||||
let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
|
||||
let subject = match outlives_requirement.subject {
|
||||
ClosureOutlivesSubject::Region(re) => closure_mapping[re].into(),
|
||||
ClosureOutlivesSubject::Ty(ty) => ty.into(),
|
||||
};
|
||||
|
||||
self.category = outlives_requirement.category;
|
||||
self.span = outlives_requirement.blame_span;
|
||||
self.convert(ty::OutlivesPredicate(subject, outlived_region), self.category);
|
||||
}
|
||||
(self.category, self.span, self.from_closure) = backup;
|
||||
}
|
||||
|
||||
fn convert(
|
||||
&mut self,
|
||||
predicate: ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>,
|
||||
constraint_category: ConstraintCategory<'tcx>,
|
||||
) {
|
||||
debug!("generate: constraints at: {:#?}", self.locations);
|
||||
|
||||
// Extract out various useful fields we'll need below.
|
||||
|
|
@ -94,17 +146,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
tcx, region_bound_pairs, implicit_region_bound, param_env, ..
|
||||
} = *self;
|
||||
|
||||
// At the moment, we never generate any "higher-ranked"
|
||||
// region constraints like `for<'a> 'a: 'b`. At some point
|
||||
// when we move to universes, we will, and this assertion
|
||||
// will start to fail.
|
||||
let ty::OutlivesPredicate(k1, r2) =
|
||||
query_constraint.0.no_bound_vars().unwrap_or_else(|| {
|
||||
bug!("query_constraint {:?} contained bound vars", query_constraint,);
|
||||
});
|
||||
|
||||
let constraint_category = query_constraint.1;
|
||||
|
||||
let ty::OutlivesPredicate(k1, r2) = predicate;
|
||||
match k1.unpack() {
|
||||
GenericArgKind::Lifetime(r1) => {
|
||||
let r1_vid = self.to_region_vid(r1);
|
||||
|
|
@ -127,10 +169,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
.type_must_outlive(origin, t1, r2, constraint_category);
|
||||
}
|
||||
|
||||
GenericArgKind::Const(_) => {
|
||||
// Consts cannot outlive one another, so we
|
||||
// don't need to handle any relations here.
|
||||
}
|
||||
GenericArgKind::Const(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -160,7 +199,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
verify_bound: VerifyBound<'tcx>,
|
||||
) -> TypeTest<'tcx> {
|
||||
let lower_bound = self.to_region_vid(region);
|
||||
TypeTest { generic_kind, lower_bound, locations: self.locations, verify_bound }
|
||||
TypeTest { generic_kind, lower_bound, span: self.span, verify_bound }
|
||||
}
|
||||
|
||||
fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid {
|
||||
|
|
@ -188,6 +227,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
sub,
|
||||
sup,
|
||||
variance_info: ty::VarianceDiagInfo::default(),
|
||||
from_closure: self.from_closure,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -247,12 +247,13 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||
.and(type_op::normalize::Normalize::new(ty))
|
||||
.fully_perform(self.infcx)
|
||||
.unwrap_or_else(|_| {
|
||||
self.infcx
|
||||
let reported = self
|
||||
.infcx
|
||||
.tcx
|
||||
.sess
|
||||
.delay_span_bug(span, &format!("failed to normalize {:?}", ty));
|
||||
TypeOpOutput {
|
||||
output: self.infcx.tcx.ty_error(),
|
||||
output: self.infcx.tcx.ty_error_with_guaranteed(reported),
|
||||
constraints: None,
|
||||
error_info: None,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ use rustc_middle::mir::AssertKind;
|
|||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::adjustment::PointerCast;
|
||||
use rustc_middle::ty::cast::CastTy;
|
||||
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts};
|
||||
use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
|
||||
use rustc_middle::ty::visit::TypeVisitable;
|
||||
use rustc_middle::ty::{
|
||||
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
|
||||
|
|
@ -61,7 +61,7 @@ use crate::{
|
|||
region_infer::values::{
|
||||
LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements,
|
||||
},
|
||||
region_infer::{ClosureRegionRequirementsExt, TypeTest},
|
||||
region_infer::TypeTest,
|
||||
type_check::free_region_relations::{CreateResult, UniversalRegionRelations},
|
||||
universal_regions::{DefiningTy, UniversalRegions},
|
||||
Upvar,
|
||||
|
|
@ -144,7 +144,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
|||
liveness_constraints: LivenessValues::new(elements.clone()),
|
||||
outlives_constraints: OutlivesConstraintSet::default(),
|
||||
member_constraints: MemberConstraintSet::default(),
|
||||
closure_bounds_mapping: Default::default(),
|
||||
type_tests: Vec::default(),
|
||||
universe_causes: FxHashMap::default(),
|
||||
};
|
||||
|
|
@ -234,11 +233,11 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
|||
let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
|
||||
trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
|
||||
if hidden_type.has_non_region_infer() {
|
||||
infcx.tcx.sess.delay_span_bug(
|
||||
let reported = infcx.tcx.sess.delay_span_bug(
|
||||
decl.hidden_type.span,
|
||||
&format!("could not resolve {:#?}", hidden_type.ty.kind()),
|
||||
);
|
||||
hidden_type.ty = infcx.tcx.ty_error();
|
||||
hidden_type.ty = infcx.tcx.ty_error_with_guaranteed(reported);
|
||||
}
|
||||
|
||||
(opaque_type_key, (hidden_type, decl.origin))
|
||||
|
|
@ -584,8 +583,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||
// modify their locations.
|
||||
let all_facts = &mut None;
|
||||
let mut constraints = Default::default();
|
||||
let mut type_tests = Default::default();
|
||||
let mut closure_bounds = Default::default();
|
||||
let mut liveness_constraints =
|
||||
LivenessValues::new(Rc::new(RegionValueElements::new(&promoted_body)));
|
||||
// Don't try to add borrow_region facts for the promoted MIR
|
||||
|
|
@ -596,11 +593,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||
&mut this.cx.borrowck_context.constraints.outlives_constraints,
|
||||
&mut constraints,
|
||||
);
|
||||
mem::swap(&mut this.cx.borrowck_context.constraints.type_tests, &mut type_tests);
|
||||
mem::swap(
|
||||
&mut this.cx.borrowck_context.constraints.closure_bounds_mapping,
|
||||
&mut closure_bounds,
|
||||
);
|
||||
mem::swap(
|
||||
&mut this.cx.borrowck_context.constraints.liveness_constraints,
|
||||
&mut liveness_constraints,
|
||||
|
|
@ -621,13 +613,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||
swap_constraints(self);
|
||||
|
||||
let locations = location.to_locations();
|
||||
|
||||
// Use location of promoted const in collected constraints
|
||||
for type_test in type_tests.iter() {
|
||||
let mut type_test = type_test.clone();
|
||||
type_test.locations = locations;
|
||||
self.cx.borrowck_context.constraints.type_tests.push(type_test)
|
||||
}
|
||||
for constraint in constraints.outlives().iter() {
|
||||
let mut constraint = constraint.clone();
|
||||
constraint.locations = locations;
|
||||
|
|
@ -653,18 +638,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||
.add_element(region, location);
|
||||
}
|
||||
}
|
||||
|
||||
if !closure_bounds.is_empty() {
|
||||
let combined_bounds_mapping =
|
||||
closure_bounds.into_iter().flat_map(|(_, value)| value).collect();
|
||||
let existing = self
|
||||
.cx
|
||||
.borrowck_context
|
||||
.constraints
|
||||
.closure_bounds_mapping
|
||||
.insert(location, combined_bounds_mapping);
|
||||
assert!(existing.is_none(), "Multiple promoteds/closures at the same location.");
|
||||
}
|
||||
}
|
||||
|
||||
fn sanitize_projection(
|
||||
|
|
@ -941,9 +914,6 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
|
|||
|
||||
pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>,
|
||||
|
||||
pub(crate) closure_bounds_mapping:
|
||||
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>,
|
||||
|
||||
pub(crate) universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
|
||||
|
||||
pub(crate) type_tests: Vec<TypeTest<'tcx>>,
|
||||
|
|
@ -2562,6 +2532,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
span: location.to_locations().span(body),
|
||||
category,
|
||||
variance_info: ty::VarianceDiagInfo::default(),
|
||||
from_closure: false,
|
||||
});
|
||||
|
||||
match mutbl {
|
||||
|
|
@ -2679,62 +2650,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
substs: SubstsRef<'tcx>,
|
||||
location: Location,
|
||||
) -> ty::InstantiatedPredicates<'tcx> {
|
||||
if let Some(ref closure_region_requirements) = tcx.mir_borrowck(def_id).closure_requirements
|
||||
{
|
||||
let closure_constraints = QueryRegionConstraints {
|
||||
outlives: closure_region_requirements.apply_requirements(
|
||||
tcx,
|
||||
def_id.to_def_id(),
|
||||
substs,
|
||||
),
|
||||
|
||||
// Presently, closures never propagate member
|
||||
// constraints to their parents -- they are enforced
|
||||
// locally. This is largely a non-issue as member
|
||||
// constraints only come from `-> impl Trait` and
|
||||
// friends which don't appear (thus far...) in
|
||||
// closures.
|
||||
member_constraints: vec![],
|
||||
};
|
||||
|
||||
let bounds_mapping = closure_constraints
|
||||
.outlives
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(idx, constraint)| {
|
||||
let ty::OutlivesPredicate(k1, r2) =
|
||||
constraint.0.no_bound_vars().unwrap_or_else(|| {
|
||||
bug!("query_constraint {:?} contained bound vars", constraint,);
|
||||
});
|
||||
|
||||
match k1.unpack() {
|
||||
GenericArgKind::Lifetime(r1) => {
|
||||
// constraint is r1: r2
|
||||
let r1_vid = self.borrowck_context.universal_regions.to_region_vid(r1);
|
||||
let r2_vid = self.borrowck_context.universal_regions.to_region_vid(r2);
|
||||
let outlives_requirements =
|
||||
&closure_region_requirements.outlives_requirements[idx];
|
||||
Some((
|
||||
(r1_vid, r2_vid),
|
||||
(outlives_requirements.category, outlives_requirements.blame_span),
|
||||
))
|
||||
}
|
||||
GenericArgKind::Type(_) | GenericArgKind::Const(_) => None,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let existing = self
|
||||
.borrowck_context
|
||||
.constraints
|
||||
.closure_bounds_mapping
|
||||
.insert(location, bounds_mapping);
|
||||
assert!(existing.is_none(), "Multiple closures at the same location.");
|
||||
|
||||
self.push_region_constraints(
|
||||
if let Some(ref closure_requirements) = tcx.mir_borrowck(def_id).closure_requirements {
|
||||
constraint_conversion::ConstraintConversion::new(
|
||||
self.infcx,
|
||||
self.borrowck_context.universal_regions,
|
||||
self.region_bound_pairs,
|
||||
self.implicit_region_bound,
|
||||
self.param_env,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::ClosureBounds,
|
||||
&closure_constraints,
|
||||
DUMMY_SP, // irrelevant; will be overrided.
|
||||
ConstraintCategory::Boring, // same as above.
|
||||
&mut self.borrowck_context.constraints,
|
||||
)
|
||||
.apply_closure_requirements(
|
||||
&closure_requirements,
|
||||
def_id.to_def_id(),
|
||||
substs,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
|
|||
span: self.locations.span(self.type_checker.body),
|
||||
category: self.category,
|
||||
variance_info: info,
|
||||
from_closure: false,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ impl DebugContext {
|
|||
|
||||
let producer = format!(
|
||||
"cg_clif (rustc {}, cranelift {})",
|
||||
rustc_interface::util::version_str().unwrap_or("unknown version"),
|
||||
rustc_interface::util::rustc_version_str().unwrap_or("unknown version"),
|
||||
cranelift_codegen::VERSION,
|
||||
);
|
||||
let comp_dir = tcx
|
||||
|
|
|
|||
|
|
@ -201,6 +201,27 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
fn val_ty(&self, value: RValue<'gcc>) -> Type<'gcc> {
|
||||
value.get_type()
|
||||
}
|
||||
|
||||
fn type_array(&self, ty: Type<'gcc>, mut len: u64) -> Type<'gcc> {
|
||||
if let Some(struct_type) = ty.is_struct() {
|
||||
if struct_type.get_field_count() == 0 {
|
||||
// NOTE: since gccjit only supports i32 for the array size and libcore's tests uses a
|
||||
// size of usize::MAX in test_binary_search, we workaround this by setting the size to
|
||||
// zero for ZSTs.
|
||||
// FIXME(antoyo): fix gccjit API.
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: see note above. Some other test uses usize::MAX.
|
||||
if len == u64::MAX {
|
||||
len = 0;
|
||||
}
|
||||
|
||||
let len: i32 = len.try_into().expect("array len");
|
||||
|
||||
self.context.new_array_type(None, ty, len)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||
|
|
@ -227,27 +248,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
self.context.new_opaque_struct_type(None, name)
|
||||
}
|
||||
|
||||
pub fn type_array(&self, ty: Type<'gcc>, mut len: u64) -> Type<'gcc> {
|
||||
if let Some(struct_type) = ty.is_struct() {
|
||||
if struct_type.get_field_count() == 0 {
|
||||
// NOTE: since gccjit only supports i32 for the array size and libcore's tests uses a
|
||||
// size of usize::MAX in test_binary_search, we workaround this by setting the size to
|
||||
// zero for ZSTs.
|
||||
// FIXME(antoyo): fix gccjit API.
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: see note above. Some other test uses usize::MAX.
|
||||
if len == u64::MAX {
|
||||
len = 0;
|
||||
}
|
||||
|
||||
let len: i32 = len.try_into().expect("array len");
|
||||
|
||||
self.context.new_array_type(None, ty, len)
|
||||
}
|
||||
|
||||
pub fn type_bool(&self) -> Type<'gcc> {
|
||||
self.context.new_type::<bool>()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtec
|
|||
use smallvec::SmallVec;
|
||||
|
||||
use crate::attributes;
|
||||
use crate::errors::{MissingFeatures, SanitizerMemtagRequiresMte, TargetFeatureDisableOrEnable};
|
||||
use crate::llvm::AttributePlace::Function;
|
||||
use crate::llvm::{self, AllocKindFlags, Attribute, AttributeKind, AttributePlace, MemoryEffects};
|
||||
use crate::llvm_util;
|
||||
|
|
@ -82,7 +83,7 @@ pub fn sanitize_attrs<'ll>(
|
|||
let mte_feature =
|
||||
features.iter().map(|s| &s[..]).rfind(|n| ["+mte", "-mte"].contains(&&n[..]));
|
||||
if let None | Some("-mte") = mte_feature {
|
||||
cx.tcx.sess.err("`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`");
|
||||
cx.tcx.sess.emit_err(SanitizerMemtagRequiresMte);
|
||||
}
|
||||
|
||||
attrs.push(llvm::AttributeKind::SanitizeMemTag.create_attr(cx.llcx));
|
||||
|
|
@ -393,13 +394,14 @@ pub fn from_fn_attrs<'ll, 'tcx>(
|
|||
.get_attrs(instance.def_id(), sym::target_feature)
|
||||
.next()
|
||||
.map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span);
|
||||
let msg = format!(
|
||||
"the target features {} must all be either enabled or disabled together",
|
||||
f.join(", ")
|
||||
);
|
||||
let mut err = cx.tcx.sess.struct_span_err(span, &msg);
|
||||
err.help("add the missing features in a `target_feature` attribute");
|
||||
err.emit();
|
||||
cx.tcx
|
||||
.sess
|
||||
.create_err(TargetFeatureDisableOrEnable {
|
||||
features: f,
|
||||
span: Some(span),
|
||||
missing_features: Some(MissingFeatures),
|
||||
})
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@ use std::str;
|
|||
use object::read::macho::FatArch;
|
||||
|
||||
use crate::common;
|
||||
use crate::errors::{
|
||||
ArchiveBuildFailure, DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary,
|
||||
ErrorWritingDEFFile, UnknownArchiveKind,
|
||||
};
|
||||
use crate::llvm::archive_ro::{ArchiveRO, Child};
|
||||
use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
|
||||
use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
|
||||
|
|
@ -147,7 +151,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
|
|||
fn build(mut self: Box<Self>, output: &Path) -> bool {
|
||||
match self.build_with_llvm(output) {
|
||||
Ok(any_members) => any_members,
|
||||
Err(e) => self.sess.fatal(&format!("failed to build archive: {}", e)),
|
||||
Err(e) => self.sess.emit_fatal(ArchiveBuildFailure { error: e }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -217,7 +221,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
|||
match std::fs::write(&def_file_path, def_file_content) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
sess.fatal(&format!("Error writing .DEF file: {}", e));
|
||||
sess.emit_fatal(ErrorWritingDEFFile { error: e });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -239,13 +243,14 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
|||
|
||||
match result {
|
||||
Err(e) => {
|
||||
sess.fatal(&format!("Error calling dlltool: {}", e));
|
||||
sess.emit_fatal(ErrorCallingDllTool { error: e });
|
||||
}
|
||||
Ok(output) if !output.status.success() => {
|
||||
sess.emit_fatal(DlltoolFailImportLibrary {
|
||||
stdout: String::from_utf8_lossy(&output.stdout),
|
||||
stderr: String::from_utf8_lossy(&output.stderr),
|
||||
})
|
||||
}
|
||||
Ok(output) if !output.status.success() => sess.fatal(&format!(
|
||||
"Dlltool could not create import library: {}\n{}",
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
)),
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -293,11 +298,10 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
|||
};
|
||||
|
||||
if result == crate::llvm::LLVMRustResult::Failure {
|
||||
sess.fatal(&format!(
|
||||
"Error creating import library for {}: {}",
|
||||
sess.emit_fatal(ErrorCreatingImportLibrary {
|
||||
lib_name,
|
||||
llvm::last_error().unwrap_or("unknown LLVM error".to_string())
|
||||
));
|
||||
error: llvm::last_error().unwrap_or("unknown LLVM error".to_string()),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -308,9 +312,10 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
|||
impl<'a> LlvmArchiveBuilder<'a> {
|
||||
fn build_with_llvm(&mut self, output: &Path) -> io::Result<bool> {
|
||||
let kind = &*self.sess.target.archive_format;
|
||||
let kind = kind.parse::<ArchiveKind>().map_err(|_| kind).unwrap_or_else(|kind| {
|
||||
self.sess.fatal(&format!("Don't know how to build archive of type: {}", kind))
|
||||
});
|
||||
let kind = kind
|
||||
.parse::<ArchiveKind>()
|
||||
.map_err(|_| kind)
|
||||
.unwrap_or_else(|kind| self.sess.emit_fatal(UnknownArchiveKind { kind }));
|
||||
|
||||
let mut additions = mem::take(&mut self.additions);
|
||||
let mut strings = Vec::new();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::back::write::{self, save_temp_bitcode, DiagnosticHandlers};
|
||||
use crate::errors::DynamicLinkingWithLTO;
|
||||
use crate::llvm::{self, build_string};
|
||||
use crate::{LlvmCodegenBackend, ModuleLlvm};
|
||||
use object::read::archive::ArchiveFile;
|
||||
|
|
@ -90,13 +91,7 @@ fn prepare_lto(
|
|||
}
|
||||
|
||||
if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto {
|
||||
diag_handler
|
||||
.struct_err("cannot prefer dynamic linking when performing LTO")
|
||||
.note(
|
||||
"only 'staticlib', 'bin', and 'cdylib' outputs are \
|
||||
supported with LTO",
|
||||
)
|
||||
.emit();
|
||||
diag_handler.emit_err(DynamicLinkingWithLTO);
|
||||
return Err(FatalError);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::base;
|
||||
use crate::common::{self, CodegenCx};
|
||||
use crate::debuginfo;
|
||||
use crate::errors::{InvalidMinimumAlignment, LinkageConstOrMutType, SymbolAlreadyDefined};
|
||||
use crate::llvm::{self, True};
|
||||
use crate::llvm_util;
|
||||
use crate::type_::Type;
|
||||
|
|
@ -19,6 +20,7 @@ use rustc_middle::mir::mono::MonoItem;
|
|||
use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::{self, Instance, Ty};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::config::Lto;
|
||||
use rustc_target::abi::{
|
||||
AddressSpace, Align, HasDataLayout, Primitive, Scalar, Size, WrappingRange,
|
||||
};
|
||||
|
|
@ -145,7 +147,7 @@ fn set_global_alignment<'ll>(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align:
|
|||
match Align::from_bits(min) {
|
||||
Ok(min) => align = align.max(min),
|
||||
Err(err) => {
|
||||
cx.sess().err(&format!("invalid minimum global alignment: {}", err));
|
||||
cx.sess().emit_err(InvalidMinimumAlignment { err });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -173,10 +175,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
|
|||
let llty2 = if let ty::RawPtr(ref mt) = ty.kind() {
|
||||
cx.layout_of(mt.ty).llvm_type(cx)
|
||||
} else {
|
||||
cx.sess().span_fatal(
|
||||
cx.tcx.def_span(def_id),
|
||||
"must have type `*const T` or `*mut T` due to `#[linkage]` attribute",
|
||||
)
|
||||
cx.sess().emit_fatal(LinkageConstOrMutType { span: cx.tcx.def_span(def_id) })
|
||||
};
|
||||
unsafe {
|
||||
// Declare a symbol `foo` with the desired linkage.
|
||||
|
|
@ -192,10 +191,10 @@ fn check_and_apply_linkage<'ll, 'tcx>(
|
|||
let mut real_name = "_rust_extern_with_linkage_".to_string();
|
||||
real_name.push_str(sym);
|
||||
let g2 = cx.define_global(&real_name, llty).unwrap_or_else(|| {
|
||||
cx.sess().span_fatal(
|
||||
cx.tcx.def_span(def_id),
|
||||
&format!("symbol `{}` is already defined", &sym),
|
||||
)
|
||||
cx.sess().emit_fatal(SymbolAlreadyDefined {
|
||||
span: cx.tcx.def_span(def_id),
|
||||
symbol_name: sym,
|
||||
})
|
||||
});
|
||||
llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
|
||||
llvm::LLVMSetInitializer(g2, g1);
|
||||
|
|
@ -303,7 +302,8 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
// ThinLTO can't handle this workaround in all cases, so we don't
|
||||
// emit the attrs. Instead we make them unnecessary by disallowing
|
||||
// dynamic linking when linker plugin based LTO is enabled.
|
||||
!self.tcx.sess.opts.cg.linker_plugin_lto.enabled();
|
||||
!self.tcx.sess.opts.cg.linker_plugin_lto.enabled() &&
|
||||
self.tcx.sess.lto() != Lto::Thin;
|
||||
|
||||
// If this assertion triggers, there's something wrong with commandline
|
||||
// argument validation.
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use crate::back::write::to_llvm_code_model;
|
|||
use crate::callee::get_fn;
|
||||
use crate::coverageinfo;
|
||||
use crate::debuginfo;
|
||||
use crate::errors::BranchProtectionRequiresAArch64;
|
||||
use crate::llvm;
|
||||
use crate::llvm_util;
|
||||
use crate::type_::Type;
|
||||
|
|
@ -26,6 +27,7 @@ use rustc_session::config::{BranchProtection, CFGuard, CFProtection};
|
|||
use rustc_session::config::{CrateType, DebugInfo, PAuthKey, PacRet};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_target::abi::{
|
||||
call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx,
|
||||
};
|
||||
|
|
@ -158,6 +160,10 @@ pub unsafe fn create_module<'ll>(
|
|||
if sess.target.arch == "s390x" {
|
||||
target_data_layout = target_data_layout.replace("-v128:64", "");
|
||||
}
|
||||
|
||||
if sess.target.arch == "riscv64" {
|
||||
target_data_layout = target_data_layout.replace("-n32:64-", "-n64-");
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the data-layout values hardcoded remain the defaults.
|
||||
|
|
@ -271,7 +277,7 @@ pub unsafe fn create_module<'ll>(
|
|||
|
||||
if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection {
|
||||
if sess.target.arch != "aarch64" {
|
||||
sess.err("-Zbranch-protection is only supported on aarch64");
|
||||
sess.emit_err(BranchProtectionRequiresAArch64);
|
||||
} else {
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llmod,
|
||||
|
|
@ -947,7 +953,7 @@ impl<'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
|
|||
#[inline]
|
||||
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
|
||||
if let LayoutError::SizeOverflow(_) = err {
|
||||
self.sess().span_fatal(span, &err.to_string())
|
||||
self.sess().emit_fatal(Spanned { span, node: err })
|
||||
} else {
|
||||
span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
|
||||
}
|
||||
|
|
@ -965,7 +971,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
|
|||
fn_abi_request: FnAbiRequest<'tcx>,
|
||||
) -> ! {
|
||||
if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
|
||||
self.sess().span_fatal(span, &err.to_string())
|
||||
self.sess().emit_fatal(Spanned { span, node: err })
|
||||
} else {
|
||||
match fn_abi_request {
|
||||
FnAbiRequest::OfFnPtr { sig, extra_args } => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::common::CodegenCx;
|
||||
use crate::coverageinfo;
|
||||
use crate::errors::InstrumentCoverageRequiresLLVM12;
|
||||
use crate::llvm;
|
||||
|
||||
use llvm::coverageinfo::CounterMappingRegion;
|
||||
|
|
@ -37,7 +38,7 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
|
|||
// LLVM 12.
|
||||
let version = coverageinfo::mapping_version();
|
||||
if version < 4 {
|
||||
tcx.sess.fatal("rustc option `-C instrument-coverage` requires LLVM 12 or higher.");
|
||||
tcx.sess.emit_fatal(InstrumentCoverageRequiresLLVM12);
|
||||
}
|
||||
|
||||
debug!("Generating coverage map for CodegenUnit: `{}`", cx.codegen_unit.name());
|
||||
|
|
|
|||
139
compiler/rustc_codegen_llvm/src/errors.rs
Normal file
139
compiler/rustc_codegen_llvm/src/errors.rs
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use rustc_errors::fluent;
|
||||
use rustc_errors::DiagnosticBuilder;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_errors::Handler;
|
||||
use rustc_errors::IntoDiagnostic;
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::Span;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_unknown_ctarget_feature_prefix)]
|
||||
#[note]
|
||||
pub(crate) struct UnknownCTargetFeaturePrefix<'a> {
|
||||
pub feature: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_unknown_ctarget_feature)]
|
||||
#[note]
|
||||
pub(crate) struct UnknownCTargetFeature<'a> {
|
||||
pub feature: &'a str,
|
||||
#[subdiagnostic]
|
||||
pub rust_feature: PossibleFeature<'a>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum PossibleFeature<'a> {
|
||||
#[help(possible_feature)]
|
||||
Some { rust_feature: &'a str },
|
||||
#[help(consider_filing_feature_request)]
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_error_creating_import_library)]
|
||||
pub(crate) struct ErrorCreatingImportLibrary<'a> {
|
||||
pub lib_name: &'a str,
|
||||
pub error: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_instrument_coverage_requires_llvm_12)]
|
||||
pub(crate) struct InstrumentCoverageRequiresLLVM12;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_symbol_already_defined)]
|
||||
pub(crate) struct SymbolAlreadyDefined<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub symbol_name: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_branch_protection_requires_aarch64)]
|
||||
pub(crate) struct BranchProtectionRequiresAArch64;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_invalid_minimum_alignment)]
|
||||
pub(crate) struct InvalidMinimumAlignment {
|
||||
pub err: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_linkage_const_or_mut_type)]
|
||||
pub(crate) struct LinkageConstOrMutType {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_sanitizer_memtag_requires_mte)]
|
||||
pub(crate) struct SanitizerMemtagRequiresMte;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_archive_build_failure)]
|
||||
pub(crate) struct ArchiveBuildFailure {
|
||||
pub error: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_error_writing_def_file)]
|
||||
pub(crate) struct ErrorWritingDEFFile {
|
||||
pub error: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_error_calling_dlltool)]
|
||||
pub(crate) struct ErrorCallingDllTool {
|
||||
pub error: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_dlltool_fail_import_library)]
|
||||
pub(crate) struct DlltoolFailImportLibrary<'a> {
|
||||
pub stdout: Cow<'a, str>,
|
||||
pub stderr: Cow<'a, str>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_unknown_archive_kind)]
|
||||
pub(crate) struct UnknownArchiveKind<'a> {
|
||||
pub kind: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_dynamic_linking_with_lto)]
|
||||
#[note]
|
||||
pub(crate) struct DynamicLinkingWithLTO;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_fail_parsing_target_machine_config_to_target_machine)]
|
||||
pub(crate) struct FailParsingTargetMachineConfigToTargetMachine {
|
||||
pub error: String,
|
||||
}
|
||||
|
||||
pub(crate) struct TargetFeatureDisableOrEnable<'a> {
|
||||
pub features: &'a [&'a str],
|
||||
pub span: Option<Span>,
|
||||
pub missing_features: Option<MissingFeatures>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[help(codegen_llvm_missing_features)]
|
||||
pub(crate) struct MissingFeatures;
|
||||
|
||||
impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> {
|
||||
fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
||||
let mut diag = sess.struct_err(fluent::codegen_llvm_target_feature_disable_or_enable);
|
||||
if let Some(span) = self.span {
|
||||
diag.set_span(span);
|
||||
};
|
||||
if let Some(missing_features) = self.missing_features {
|
||||
diag.subdiagnostic(missing_features);
|
||||
}
|
||||
diag.set_arg("features", self.features.join(", "));
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,8 @@
|
|||
#![feature(iter_intersperse)]
|
||||
#![recursion_limit = "256"]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate rustc_macros;
|
||||
|
|
@ -20,6 +22,7 @@ extern crate tracing;
|
|||
|
||||
use back::write::{create_informational_target_machine, create_target_machine};
|
||||
|
||||
use errors::FailParsingTargetMachineConfigToTargetMachine;
|
||||
pub use llvm_util::target_features;
|
||||
use rustc_ast::expand::allocator::AllocatorKind;
|
||||
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
|
||||
|
|
@ -62,6 +65,7 @@ mod context;
|
|||
mod coverageinfo;
|
||||
mod debuginfo;
|
||||
mod declare;
|
||||
mod errors;
|
||||
mod intrinsic;
|
||||
|
||||
// The following is a work around that replaces `pub mod llvm;` and that fixes issue 53912.
|
||||
|
|
@ -412,7 +416,7 @@ impl ModuleLlvm {
|
|||
let tm = match (cgcx.tm_factory)(tm_factory_config) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
handler.struct_err(&e).emit();
|
||||
handler.emit_err(FailParsingTargetMachineConfigToTargetMachine { error: e });
|
||||
return Err(FatalError);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
use crate::back::write::create_informational_target_machine;
|
||||
use crate::errors::{
|
||||
PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature,
|
||||
UnknownCTargetFeaturePrefix,
|
||||
};
|
||||
use crate::llvm;
|
||||
use libc::c_int;
|
||||
use rustc_codegen_ssa::target_features::{
|
||||
|
|
@ -434,12 +438,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
|
|||
Some(c @ '+' | c @ '-') => c,
|
||||
Some(_) => {
|
||||
if diagnostics {
|
||||
let mut diag = sess.struct_warn(&format!(
|
||||
"unknown feature specified for `-Ctarget-feature`: `{}`",
|
||||
s
|
||||
));
|
||||
diag.note("features must begin with a `+` to enable or `-` to disable it");
|
||||
diag.emit();
|
||||
sess.emit_warning(UnknownCTargetFeaturePrefix { feature: s });
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
|
@ -456,17 +455,15 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
|
|||
None
|
||||
}
|
||||
});
|
||||
let mut diag = sess.struct_warn(&format!(
|
||||
"unknown feature specified for `-Ctarget-feature`: `{}`",
|
||||
feature
|
||||
));
|
||||
diag.note("it is still passed through to the codegen backend");
|
||||
if let Some(rust_feature) = rust_feature {
|
||||
diag.help(&format!("you might have meant: `{}`", rust_feature));
|
||||
let unknown_feature = if let Some(rust_feature) = rust_feature {
|
||||
UnknownCTargetFeature {
|
||||
feature,
|
||||
rust_feature: PossibleFeature::Some { rust_feature },
|
||||
}
|
||||
} else {
|
||||
diag.note("consider filing a feature request");
|
||||
}
|
||||
diag.emit();
|
||||
UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
|
||||
};
|
||||
sess.emit_warning(unknown_feature);
|
||||
}
|
||||
|
||||
if diagnostics {
|
||||
|
|
@ -492,10 +489,11 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
|
|||
features.extend(feats);
|
||||
|
||||
if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) {
|
||||
sess.err(&format!(
|
||||
"target features {} must all be enabled or disabled together",
|
||||
f.join(", ")
|
||||
));
|
||||
sess.emit_err(TargetFeatureDisableOrEnable {
|
||||
features: f,
|
||||
span: None,
|
||||
missing_features: None,
|
||||
});
|
||||
}
|
||||
|
||||
features
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::attributes;
|
||||
use crate::base;
|
||||
use crate::context::CodegenCx;
|
||||
use crate::errors::SymbolAlreadyDefined;
|
||||
use crate::llvm;
|
||||
use crate::type_of::LayoutLlvmExt;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
|
|
@ -25,10 +26,8 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> {
|
|||
let llty = self.layout_of(ty).llvm_type(self);
|
||||
|
||||
let g = self.define_global(symbol_name, llty).unwrap_or_else(|| {
|
||||
self.sess().span_fatal(
|
||||
self.tcx.def_span(def_id),
|
||||
&format!("symbol `{}` is already defined", symbol_name),
|
||||
)
|
||||
self.sess()
|
||||
.emit_fatal(SymbolAlreadyDefined { span: self.tcx.def_span(def_id), symbol_name })
|
||||
});
|
||||
|
||||
unsafe {
|
||||
|
|
|
|||
|
|
@ -127,10 +127,6 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
pub(crate) fn type_variadic_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
|
||||
unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, True) }
|
||||
}
|
||||
|
||||
pub(crate) fn type_array(&self, ty: &'ll Type, len: u64) -> &'ll Type {
|
||||
unsafe { llvm::LLVMRustArrayType(ty, len) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
|
|
@ -231,6 +227,10 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
fn val_ty(&self, v: &'ll Value) -> &'ll Type {
|
||||
common::val_ty(v)
|
||||
}
|
||||
|
||||
fn type_array(&self, ty: &'ll Type, len: u64) -> &'ll Type {
|
||||
unsafe { llvm::LLVMRustArrayType(ty, len) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Type {
|
||||
|
|
|
|||
|
|
@ -15,10 +15,8 @@ use rustc_data_structures::profiling::TimingGuard;
|
|||
use rustc_data_structures::profiling::VerboseTimingGuard;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::emitter::Emitter;
|
||||
use rustc_errors::{
|
||||
translation::{to_fluent_args, Translate},
|
||||
DiagnosticId, FatalError, Handler, Level,
|
||||
};
|
||||
use rustc_errors::{translation::Translate, DiagnosticId, FatalError, Handler, Level};
|
||||
use rustc_errors::{DiagnosticMessage, Style};
|
||||
use rustc_fs_util::link_or_copy;
|
||||
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||
use rustc_incremental::{
|
||||
|
|
@ -38,6 +36,7 @@ use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span};
|
|||
use rustc_target::spec::{MergeFunctions, SanitizerSet};
|
||||
|
||||
use std::any::Any;
|
||||
use std::borrow::Cow;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::marker::PhantomData;
|
||||
|
|
@ -969,8 +968,11 @@ pub enum Message<B: WriteBackendMethods> {
|
|||
CodegenAborted,
|
||||
}
|
||||
|
||||
type DiagnosticArgName<'source> = Cow<'source, str>;
|
||||
|
||||
struct Diagnostic {
|
||||
msg: String,
|
||||
msg: Vec<(DiagnosticMessage, Style)>,
|
||||
args: FxHashMap<DiagnosticArgName<'static>, rustc_errors::DiagnosticArgValue<'static>>,
|
||||
code: Option<DiagnosticId>,
|
||||
lvl: Level,
|
||||
}
|
||||
|
|
@ -1743,15 +1745,18 @@ impl Translate for SharedEmitter {
|
|||
|
||||
impl Emitter for SharedEmitter {
|
||||
fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) {
|
||||
let fluent_args = to_fluent_args(diag.args());
|
||||
let args: FxHashMap<Cow<'_, str>, rustc_errors::DiagnosticArgValue<'_>> =
|
||||
diag.args().map(|(name, arg)| (name.clone(), arg.clone())).collect();
|
||||
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
|
||||
msg: self.translate_messages(&diag.message, &fluent_args).to_string(),
|
||||
msg: diag.message.clone(),
|
||||
args: args.clone(),
|
||||
code: diag.code.clone(),
|
||||
lvl: diag.level(),
|
||||
})));
|
||||
for child in &diag.children {
|
||||
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
|
||||
msg: self.translate_messages(&child.message, &fluent_args).to_string(),
|
||||
msg: child.message.clone(),
|
||||
args: args.clone(),
|
||||
code: None,
|
||||
lvl: child.level,
|
||||
})));
|
||||
|
|
@ -1782,10 +1787,11 @@ impl SharedEmitterMain {
|
|||
match message {
|
||||
Ok(SharedEmitterMessage::Diagnostic(diag)) => {
|
||||
let handler = sess.diagnostic();
|
||||
let mut d = rustc_errors::Diagnostic::new(diag.lvl, &diag.msg);
|
||||
let mut d = rustc_errors::Diagnostic::new_with_messages(diag.lvl, diag.msg);
|
||||
if let Some(code) = diag.code {
|
||||
d.code(code);
|
||||
}
|
||||
d.replace_args(diag.args);
|
||||
handler.emit_diagnostic(&mut d);
|
||||
}
|
||||
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
|
||||
|
|
|
|||
|
|
@ -59,7 +59,13 @@ fn push_debuginfo_type_name<'tcx>(
|
|||
match *t.kind() {
|
||||
ty::Bool => output.push_str("bool"),
|
||||
ty::Char => output.push_str("char"),
|
||||
ty::Str => output.push_str("str"),
|
||||
ty::Str => {
|
||||
if cpp_like_debuginfo {
|
||||
output.push_str("str$")
|
||||
} else {
|
||||
output.push_str("str")
|
||||
}
|
||||
}
|
||||
ty::Never => {
|
||||
if cpp_like_debuginfo {
|
||||
output.push_str("never$");
|
||||
|
|
@ -152,25 +158,19 @@ fn push_debuginfo_type_name<'tcx>(
|
|||
}
|
||||
}
|
||||
ty::Ref(_, inner_type, mutbl) => {
|
||||
// Slices and `&str` are treated like C++ pointers when computing debug
|
||||
// info for MSVC debugger. However, wrapping these types' names in a synthetic type
|
||||
// causes the .natvis engine for WinDbg to fail to display their data, so we opt these
|
||||
// types out to aid debugging in MSVC.
|
||||
let is_slice_or_str = matches!(*inner_type.kind(), ty::Slice(_) | ty::Str);
|
||||
|
||||
if !cpp_like_debuginfo {
|
||||
output.push('&');
|
||||
output.push_str(mutbl.prefix_str());
|
||||
} else if !is_slice_or_str {
|
||||
if cpp_like_debuginfo {
|
||||
match mutbl {
|
||||
Mutability::Not => output.push_str("ref$<"),
|
||||
Mutability::Mut => output.push_str("ref_mut$<"),
|
||||
}
|
||||
} else {
|
||||
output.push('&');
|
||||
output.push_str(mutbl.prefix_str());
|
||||
}
|
||||
|
||||
push_debuginfo_type_name(tcx, inner_type, qualified, output, visited);
|
||||
|
||||
if cpp_like_debuginfo && !is_slice_or_str {
|
||||
if cpp_like_debuginfo {
|
||||
push_close_angle_bracket(cpp_like_debuginfo, output);
|
||||
}
|
||||
}
|
||||
|
|
@ -195,7 +195,7 @@ fn push_debuginfo_type_name<'tcx>(
|
|||
}
|
||||
ty::Slice(inner_type) => {
|
||||
if cpp_like_debuginfo {
|
||||
output.push_str("slice$<");
|
||||
output.push_str("slice2$<");
|
||||
} else {
|
||||
output.push('[');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
|
|||
fn type_f32(&self) -> Self::Type;
|
||||
fn type_f64(&self) -> Self::Type;
|
||||
|
||||
fn type_array(&self, ty: Self::Type, len: u64) -> Self::Type;
|
||||
fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type;
|
||||
fn type_struct(&self, els: &[Self::Type], packed: bool) -> Self::Type;
|
||||
fn type_kind(&self, ty: Self::Type) -> TypeKind;
|
||||
|
|
|
|||
|
|
@ -765,7 +765,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -831,7 +831,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
obligation.clone(),
|
||||
&obligation,
|
||||
&e,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ impl Qualif for NeedsNonConstDrop {
|
|||
qualifs.needs_non_const_drop
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(cx), ret)]
|
||||
fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
// Avoid selecting for simple cases, such as builtin types.
|
||||
if ty::util::is_trivially_const_drop(ty) {
|
||||
|
|
@ -174,6 +175,8 @@ impl Qualif for NeedsNonConstDrop {
|
|||
return true;
|
||||
};
|
||||
|
||||
trace!(?impl_src);
|
||||
|
||||
if !matches!(
|
||||
impl_src,
|
||||
ImplSource::ConstDestruct(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ rustc_macros = { path = "../rustc_macros" }
|
|||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
smallvec = { version = "1.8.1", features = ["const_generics", "union", "may_dangle"] }
|
||||
stable_deref_trait = "1.0.0"
|
||||
stacker = "0.1.14"
|
||||
stacker = "0.1.15"
|
||||
tempfile = "3.2"
|
||||
thin-vec = "0.2.9"
|
||||
tracing = "0.1"
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![feature(once_cell)]
|
||||
#![feature(decl_macro)]
|
||||
#![recursion_limit = "256"]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
|
|
@ -736,26 +737,58 @@ fn print_crate_info(
|
|||
// Any output here interferes with Cargo's parsing of other printed output
|
||||
NativeStaticLibs => {}
|
||||
LinkArgs => {}
|
||||
SplitDebuginfo => {
|
||||
use rustc_target::spec::SplitDebuginfo::{Off, Packed, Unpacked};
|
||||
|
||||
for split in &[Off, Packed, Unpacked] {
|
||||
let stable = sess.target.options.supported_split_debuginfo.contains(split);
|
||||
let unstable_ok = sess.unstable_options();
|
||||
if stable || unstable_ok {
|
||||
println!("{}", split);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Compilation::Stop
|
||||
}
|
||||
|
||||
/// Prints version information
|
||||
pub fn version(binary: &str, matches: &getopts::Matches) {
|
||||
///
|
||||
/// NOTE: this is a macro to support drivers built at a different time than the main `rustc_driver` crate.
|
||||
pub macro version($binary: literal, $matches: expr) {
|
||||
fn unw(x: Option<&str>) -> &str {
|
||||
x.unwrap_or("unknown")
|
||||
}
|
||||
$crate::version_at_macro_invocation(
|
||||
$binary,
|
||||
$matches,
|
||||
unw(option_env!("CFG_VERSION")),
|
||||
unw(option_env!("CFG_VER_HASH")),
|
||||
unw(option_env!("CFG_VER_DATE")),
|
||||
unw(option_env!("CFG_RELEASE")),
|
||||
)
|
||||
}
|
||||
|
||||
#[doc(hidden)] // use the macro instead
|
||||
pub fn version_at_macro_invocation(
|
||||
binary: &str,
|
||||
matches: &getopts::Matches,
|
||||
version: &str,
|
||||
commit_hash: &str,
|
||||
commit_date: &str,
|
||||
release: &str,
|
||||
) {
|
||||
let verbose = matches.opt_present("verbose");
|
||||
|
||||
println!("{} {}", binary, util::version_str().unwrap_or("unknown version"));
|
||||
println!("{} {}", binary, version);
|
||||
|
||||
if verbose {
|
||||
fn unw(x: Option<&str>) -> &str {
|
||||
x.unwrap_or("unknown")
|
||||
}
|
||||
println!("binary: {}", binary);
|
||||
println!("commit-hash: {}", unw(util::commit_hash_str()));
|
||||
println!("commit-date: {}", unw(util::commit_date_str()));
|
||||
println!("commit-hash: {}", commit_hash);
|
||||
println!("commit-date: {}", commit_date);
|
||||
println!("host: {}", config::host_triple());
|
||||
println!("release: {}", unw(util::release_str()));
|
||||
println!("release: {}", release);
|
||||
|
||||
let debug_flags = matches.opt_strs("Z");
|
||||
let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
|
||||
|
|
@ -1071,7 +1104,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
|
|||
}
|
||||
|
||||
if matches.opt_present("version") {
|
||||
version("rustc", &matches);
|
||||
version!("rustc", &matches);
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
@ -1216,7 +1249,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
|
|||
format!("we would appreciate a bug report: {}", bug_report_url).into(),
|
||||
format!(
|
||||
"rustc {} running on {}",
|
||||
util::version_str().unwrap_or("unknown_version"),
|
||||
util::version_str!().unwrap_or("unknown_version"),
|
||||
config::host_triple()
|
||||
)
|
||||
.into(),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
A type parameter that is specified for `impl` is not constrained.
|
||||
A type, const or lifetime parameter that is specified for `impl` is not
|
||||
constrained.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
|
|
@ -14,8 +15,8 @@ impl<T: Default> Foo {
|
|||
}
|
||||
```
|
||||
|
||||
Any type parameter of an `impl` must meet at least one of
|
||||
the following criteria:
|
||||
Any type or const parameter of an `impl` must meet at least one of the
|
||||
following criteria:
|
||||
|
||||
- it appears in the _implementing type_ of the impl, e.g. `impl<T> Foo<T>`
|
||||
- for a trait impl, it appears in the _implemented trait_, e.g.
|
||||
|
|
@ -23,6 +24,9 @@ the following criteria:
|
|||
- it is bound as an associated type, e.g. `impl<T, U> SomeTrait for T
|
||||
where T: AnotherTrait<AssocType=U>`
|
||||
|
||||
Any unconstrained lifetime parameter of an `impl` is not supported if the
|
||||
lifetime parameter is used by an associated type.
|
||||
|
||||
### Error example 1
|
||||
|
||||
Suppose we have a struct `Foo` and we would like to define some methods for it.
|
||||
|
|
@ -32,7 +36,6 @@ The problem is that the parameter `T` does not appear in the implementing type
|
|||
(`Foo`) of the impl. In this case, we can fix the error by moving the type
|
||||
parameter from the `impl` to the method `get`:
|
||||
|
||||
|
||||
```
|
||||
struct Foo;
|
||||
|
||||
|
|
@ -128,6 +131,70 @@ impl<T: Default> Maker<Foo<T>> for FooMaker {
|
|||
}
|
||||
```
|
||||
|
||||
### Error example 3
|
||||
|
||||
Suppose we have a struct `Foo` and we would like to define some methods for it.
|
||||
The following code example has a definition which leads to a compiler error:
|
||||
|
||||
```compile_fail,E0207
|
||||
struct Foo;
|
||||
|
||||
impl<const T: i32> Foo {
|
||||
// error: the const parameter `T` is not constrained by the impl trait, self
|
||||
// type, or predicates [E0207]
|
||||
fn get(&self) -> i32 {
|
||||
i32::default()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The problem is that the const parameter `T` does not appear in the implementing
|
||||
type (`Foo`) of the impl. In this case, we can fix the error by moving the type
|
||||
parameter from the `impl` to the method `get`:
|
||||
|
||||
|
||||
```
|
||||
struct Foo;
|
||||
|
||||
// Move the const parameter from the impl to the method
|
||||
impl Foo {
|
||||
fn get<const T: i32>(&self) -> i32 {
|
||||
i32::default()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Error example 4
|
||||
|
||||
Suppose we have a struct `Foo` and a struct `Bar` that uses lifetime `'a`. We
|
||||
would like to implement trait `Contains` for `Foo`. The trait `Contains` have
|
||||
the associated type `B`. The following code example has a definition which
|
||||
leads to a compiler error:
|
||||
|
||||
```compile_fail,E0207
|
||||
struct Foo;
|
||||
struct Bar<'a>;
|
||||
|
||||
trait Contains {
|
||||
type B;
|
||||
|
||||
fn get(&self) -> i32;
|
||||
}
|
||||
|
||||
impl<'a> Contains for Foo {
|
||||
type B = Bar<'a>;
|
||||
|
||||
// error: the lifetime parameter `'a` is not constrained by the impl trait,
|
||||
// self type, or predicates [E0207]
|
||||
fn get(&self) -> i32 {
|
||||
i32::default()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Please note that unconstrained lifetime parameters are not supported if they are
|
||||
being used by an associated type.
|
||||
|
||||
### Additional information
|
||||
|
||||
For more information, please see [RFC 447].
|
||||
|
|
|
|||
|
|
@ -58,3 +58,15 @@ borrowck_returned_lifetime_short =
|
|||
|
||||
borrowck_used_impl_require_static =
|
||||
the used `impl` has a `'static` requirement
|
||||
|
||||
borrowck_capture_kind_label =
|
||||
capture is {$kind_desc} because of use here
|
||||
|
||||
borrowck_var_borrow_by_use_place_in_generator =
|
||||
borrow occurs due to use of {$place} in closure in generator
|
||||
|
||||
borrowck_var_borrow_by_use_place_in_closure =
|
||||
borrow occurs due to use of {$place} in closure
|
||||
|
||||
borrowck_var_borrow_by_use_place =
|
||||
borrow occurs due to use of {$place}
|
||||
|
|
|
|||
58
compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl
Normal file
58
compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
codegen_llvm_unknown_ctarget_feature =
|
||||
unknown feature specified for `-Ctarget-feature`: `{$feature}`
|
||||
.note = it is still passed through to the codegen backend
|
||||
.possible_feature = you might have meant: `{$rust_feature}`
|
||||
.consider_filing_feature_request = consider filing a feature request
|
||||
|
||||
codegen_llvm_unknown_ctarget_feature_prefix =
|
||||
unknown feature specified for `-Ctarget-feature`: `{$feature}`
|
||||
.note = features must begin with a `+` to enable or `-` to disable it
|
||||
|
||||
codegen_llvm_error_creating_import_library =
|
||||
Error creating import library for {$lib_name}: {$error}
|
||||
|
||||
codegen_llvm_instrument_coverage_requires_llvm_12 =
|
||||
rustc option `-C instrument-coverage` requires LLVM 12 or higher.
|
||||
|
||||
codegen_llvm_symbol_already_defined =
|
||||
symbol `{$symbol_name}` is already defined
|
||||
|
||||
codegen_llvm_branch_protection_requires_aarch64 =
|
||||
-Zbranch-protection is only supported on aarch64
|
||||
|
||||
codegen_llvm_invalid_minimum_alignment =
|
||||
invalid minimum global alignment: {$err}
|
||||
|
||||
codegen_llvm_linkage_const_or_mut_type =
|
||||
must have type `*const T` or `*mut T` due to `#[linkage]` attribute
|
||||
|
||||
codegen_llvm_sanitizer_memtag_requires_mte =
|
||||
`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`
|
||||
|
||||
codegen_llvm_archive_build_failure =
|
||||
failed to build archive: {$error}
|
||||
|
||||
codegen_llvm_error_writing_def_file =
|
||||
Error writing .DEF file: {$error}
|
||||
|
||||
codegen_llvm_error_calling_dlltool =
|
||||
Error calling dlltool: {$error}
|
||||
|
||||
codegen_llvm_dlltool_fail_import_library =
|
||||
Dlltool could not create import library: {$stdout}\n{$stderr}
|
||||
|
||||
codegen_llvm_unknown_archive_kind =
|
||||
Don't know how to build archive of type: {$kind}
|
||||
|
||||
codegen_llvm_target_feature_disable_or_enable =
|
||||
the target features {$features} must all be either enabled or disabled together
|
||||
|
||||
codegen_llvm_missing_features =
|
||||
add the missing features in a `target_feature` attribute
|
||||
|
||||
codegen_llvm_dynamic_linking_with_lto =
|
||||
cannot prefer dynamic linking when performing LTO
|
||||
.note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
|
||||
|
||||
codegen_llvm_fail_parsing_target_machine_config_to_target_machine =
|
||||
failed to parse target machine config to target machine: {$error}
|
||||
|
|
@ -171,3 +171,4 @@ infer_msl_introduces_static = introduces a `'static` lifetime requirement
|
|||
infer_msl_unmet_req = because this has an unmet lifetime requirement
|
||||
infer_msl_trait_note = this has an implicit `'static` lifetime requirement
|
||||
infer_msl_trait_sugg = consider relaxing the implicit `'static` requirement
|
||||
infer_suggest_add_let_for_letchains = consider adding `let`
|
||||
|
|
|
|||
|
|
@ -112,6 +112,9 @@ parser_missing_semicolon_before_array = expected `;`, found `[`
|
|||
parser_invalid_block_macro_segment = cannot use a `block` macro fragment here
|
||||
.label = the `block` fragment is within this context
|
||||
|
||||
parser_expect_dotdot_not_dotdotdot = expected `..`, found `...`
|
||||
.suggestion = use `..` to fill in the rest of the fields
|
||||
|
||||
parser_if_expression_missing_then_block = this `if` expression is missing a block after the condition
|
||||
.add_then_block = add a block here
|
||||
.condition_possibly_unfinished = this binary operation is possibly unfinished
|
||||
|
|
@ -122,6 +125,9 @@ parser_if_expression_missing_condition = missing condition for `if` expression
|
|||
|
||||
parser_expected_expression_found_let = expected expression, found `let` statement
|
||||
|
||||
parser_expect_eq_instead_of_eqeq = expected `=`, found `==`
|
||||
.suggestion = consider using `=` here
|
||||
|
||||
parser_expected_else_block = expected `{"{"}`, found {$first_tok}
|
||||
.label = expected an `if` or a block after this `else`
|
||||
.suggestion = add an `if` if this is the condition of a chained `else if` statement
|
||||
|
|
|
|||
|
|
@ -47,7 +47,10 @@ passes_no_coverage_not_coverable =
|
|||
|
||||
passes_should_be_applied_to_fn =
|
||||
attribute should be applied to a function definition
|
||||
.label = not a function definition
|
||||
.label = {$on_crate ->
|
||||
[true] cannot be applied to crates
|
||||
*[false] not a function definition
|
||||
}
|
||||
|
||||
passes_naked_tracked_caller =
|
||||
cannot use `#[track_caller]` with `#[naked]`
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ fluent_messages! {
|
|||
borrowck => "../locales/en-US/borrowck.ftl",
|
||||
builtin_macros => "../locales/en-US/builtin_macros.ftl",
|
||||
codegen_gcc => "../locales/en-US/codegen_gcc.ftl",
|
||||
codegen_llvm => "../locales/en-US/codegen_llvm.ftl",
|
||||
codegen_ssa => "../locales/en-US/codegen_ssa.ftl",
|
||||
compiletest => "../locales/en-US/compiletest.ftl",
|
||||
const_eval => "../locales/en-US/const_eval.ftl",
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ impl Emitter for AnnotateSnippetEmitterWriter {
|
|||
let (mut primary_span, suggestions) = self.primary_span_formatted(&diag, &fluent_args);
|
||||
|
||||
self.fix_multispans_in_extern_macros_and_render_macro_backtrace(
|
||||
&self.source_map,
|
||||
&mut primary_span,
|
||||
&mut children,
|
||||
&diag.level,
|
||||
|
|
|
|||
|
|
@ -44,6 +44,15 @@ pub trait IntoDiagnosticArg {
|
|||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static>;
|
||||
}
|
||||
|
||||
impl<'source> IntoDiagnosticArg for DiagnosticArgValue<'source> {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
match self {
|
||||
DiagnosticArgValue::Str(s) => DiagnosticArgValue::Str(Cow::Owned(s.into_owned())),
|
||||
DiagnosticArgValue::Number(n) => DiagnosticArgValue::Number(n),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'source> Into<FluentValue<'source>> for DiagnosticArgValue<'source> {
|
||||
fn into(self) -> FluentValue<'source> {
|
||||
match self {
|
||||
|
|
@ -204,6 +213,22 @@ impl Diagnostic {
|
|||
Diagnostic::new_with_code(level, None, message)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn new_with_messages(level: Level, messages: Vec<(DiagnosticMessage, Style)>) -> Self {
|
||||
Diagnostic {
|
||||
level,
|
||||
message: messages,
|
||||
code: None,
|
||||
span: MultiSpan::new(),
|
||||
children: vec![],
|
||||
suggestions: Ok(vec![]),
|
||||
args: Default::default(),
|
||||
sort_span: DUMMY_SP,
|
||||
is_lint: false,
|
||||
emitted_at: DiagnosticLocation::caller(),
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn new_with_code<M: Into<DiagnosticMessage>>(
|
||||
level: Level,
|
||||
|
|
@ -931,6 +956,13 @@ impl Diagnostic {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn replace_args(
|
||||
&mut self,
|
||||
args: FxHashMap<DiagnosticArgName<'static>, DiagnosticArgValue<'static>>,
|
||||
) {
|
||||
self.args = args;
|
||||
}
|
||||
|
||||
pub fn styled_message(&self) -> &[(DiagnosticMessage, Style)] {
|
||||
&self.message
|
||||
}
|
||||
|
|
|
|||
|
|
@ -482,9 +482,9 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
|||
/// In the meantime, though, callsites are required to deal with the "bug"
|
||||
/// locally in whichever way makes the most sense.
|
||||
#[track_caller]
|
||||
pub fn delay_as_bug(&mut self) {
|
||||
pub fn delay_as_bug(&mut self) -> G {
|
||||
self.downgrade_to_delayed_bug();
|
||||
self.emit();
|
||||
self.emit()
|
||||
}
|
||||
|
||||
forward!(
|
||||
|
|
|
|||
|
|
@ -107,6 +107,12 @@ impl IntoDiagnosticArg for String {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoDiagnosticArg for Cow<'a, str> {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self.into_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoDiagnosticArg for &'a Path {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self.display().to_string()))
|
||||
|
|
|
|||
|
|
@ -314,7 +314,6 @@ pub trait Emitter: Translate {
|
|||
|
||||
fn fix_multispans_in_extern_macros_and_render_macro_backtrace(
|
||||
&self,
|
||||
source_map: &Option<Lrc<SourceMap>>,
|
||||
span: &mut MultiSpan,
|
||||
children: &mut Vec<SubDiagnostic>,
|
||||
level: &Level,
|
||||
|
|
@ -340,7 +339,7 @@ pub trait Emitter: Translate {
|
|||
.collect();
|
||||
|
||||
if !backtrace {
|
||||
self.fix_multispans_in_extern_macros(source_map, span, children);
|
||||
self.fix_multispans_in_extern_macros(span, children);
|
||||
}
|
||||
|
||||
self.render_multispans_macro_backtrace(span, children, backtrace);
|
||||
|
|
@ -480,15 +479,13 @@ pub trait Emitter: Translate {
|
|||
// this will change the span to point at the use site.
|
||||
fn fix_multispans_in_extern_macros(
|
||||
&self,
|
||||
source_map: &Option<Lrc<SourceMap>>,
|
||||
span: &mut MultiSpan,
|
||||
children: &mut Vec<SubDiagnostic>,
|
||||
) {
|
||||
let Some(source_map) = source_map else { return };
|
||||
debug!("fix_multispans_in_extern_macros: before: span={:?} children={:?}", span, children);
|
||||
self.fix_multispan_in_extern_macros(source_map, span);
|
||||
self.fix_multispan_in_extern_macros(span);
|
||||
for child in children.iter_mut() {
|
||||
self.fix_multispan_in_extern_macros(source_map, &mut child.span);
|
||||
self.fix_multispan_in_extern_macros(&mut child.span);
|
||||
}
|
||||
debug!("fix_multispans_in_extern_macros: after: span={:?} children={:?}", span, children);
|
||||
}
|
||||
|
|
@ -496,7 +493,8 @@ pub trait Emitter: Translate {
|
|||
// This "fixes" MultiSpans that contain `Span`s pointing to locations inside of external macros.
|
||||
// Since these locations are often difficult to read,
|
||||
// we move these spans from the external macros to their corresponding use site.
|
||||
fn fix_multispan_in_extern_macros(&self, source_map: &Lrc<SourceMap>, span: &mut MultiSpan) {
|
||||
fn fix_multispan_in_extern_macros(&self, span: &mut MultiSpan) {
|
||||
let Some(source_map) = self.source_map() else { return };
|
||||
// First, find all the spans in external macros and point instead at their use site.
|
||||
let replacements: Vec<(Span, Span)> = span
|
||||
.primary_spans()
|
||||
|
|
@ -544,7 +542,6 @@ impl Emitter for EmitterWriter {
|
|||
debug!("emit_diagnostic: suggestions={:?}", suggestions);
|
||||
|
||||
self.fix_multispans_in_extern_macros_and_render_macro_backtrace(
|
||||
&self.sm,
|
||||
&mut primary_span,
|
||||
&mut children,
|
||||
&diag.level,
|
||||
|
|
@ -2213,22 +2210,45 @@ impl FileWithAnnotatedLines {
|
|||
|
||||
if let Some(ref sm) = emitter.source_map() {
|
||||
for span_label in msp.span_labels() {
|
||||
let fixup_lo_hi = |span: Span| {
|
||||
let lo = sm.lookup_char_pos(span.lo());
|
||||
let mut hi = sm.lookup_char_pos(span.hi());
|
||||
|
||||
// Watch out for "empty spans". If we get a span like 6..6, we
|
||||
// want to just display a `^` at 6, so convert that to
|
||||
// 6..7. This is degenerate input, but it's best to degrade
|
||||
// gracefully -- and the parser likes to supply a span like
|
||||
// that for EOF, in particular.
|
||||
|
||||
if lo.col_display == hi.col_display && lo.line == hi.line {
|
||||
hi.col_display += 1;
|
||||
}
|
||||
(lo, hi)
|
||||
};
|
||||
|
||||
if span_label.span.is_dummy() {
|
||||
if let Some(span) = msp.primary_span() {
|
||||
// if we don't know where to render the annotation, emit it as a note
|
||||
// on the primary span.
|
||||
|
||||
let (lo, hi) = fixup_lo_hi(span);
|
||||
|
||||
let ann = Annotation {
|
||||
start_col: lo.col_display,
|
||||
end_col: hi.col_display,
|
||||
is_primary: span_label.is_primary,
|
||||
label: span_label
|
||||
.label
|
||||
.as_ref()
|
||||
.map(|m| emitter.translate_message(m, args).to_string()),
|
||||
annotation_type: AnnotationType::Singleline,
|
||||
};
|
||||
add_annotation_to_file(&mut output, lo.file, lo.line, ann);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
let lo = sm.lookup_char_pos(span_label.span.lo());
|
||||
let mut hi = sm.lookup_char_pos(span_label.span.hi());
|
||||
|
||||
// Watch out for "empty spans". If we get a span like 6..6, we
|
||||
// want to just display a `^` at 6, so convert that to
|
||||
// 6..7. This is degenerate input, but it's best to degrade
|
||||
// gracefully -- and the parser likes to supply a span like
|
||||
// that for EOF, in particular.
|
||||
|
||||
if lo.col_display == hi.col_display && lo.line == hi.line {
|
||||
hi.col_display += 1;
|
||||
}
|
||||
let (lo, hi) = fixup_lo_hi(span_label.span);
|
||||
|
||||
if lo.line != hi.line {
|
||||
let ml = MultilineAnnotation {
|
||||
|
|
|
|||
|
|
@ -191,6 +191,8 @@ declare_features! (
|
|||
(accepted, infer_outlives_requirements, "1.30.0", Some(44493), None),
|
||||
/// Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086).
|
||||
(accepted, irrefutable_let_patterns, "1.33.0", Some(44495), None),
|
||||
/// Allows `#[instruction_set(_)]` attribute.
|
||||
(accepted, isa_attribute, "CURRENT_RUSTC_VERSION", Some(74727), None),
|
||||
/// Allows some increased flexibility in the name resolution rules,
|
||||
/// especially around globs and shadowing (RFC 1560).
|
||||
(accepted, item_like_imports, "1.15.0", Some(35120), None),
|
||||
|
|
|
|||
|
|
@ -152,6 +152,8 @@ declare_features! (
|
|||
(active, anonymous_lifetime_in_impl_trait, "1.63.0", None, None),
|
||||
/// Allows identifying the `compiler_builtins` crate.
|
||||
(active, compiler_builtins, "1.13.0", None, None),
|
||||
/// Allows writing custom MIR
|
||||
(active, custom_mir, "1.65.0", None, None),
|
||||
/// Outputs useful `assert!` messages
|
||||
(active, generic_assert, "1.63.0", None, None),
|
||||
/// Allows using the `rust-intrinsic`'s "ABI".
|
||||
|
|
@ -427,8 +429,6 @@ declare_features! (
|
|||
(incomplete, inline_const_pat, "1.58.0", Some(76001), None),
|
||||
/// Allows using `pointer` and `reference` in intra-doc links
|
||||
(active, intra_doc_pointers, "1.51.0", Some(80896), None),
|
||||
/// Allows `#[instruction_set(_)]` attribute
|
||||
(active, isa_attribute, "1.48.0", Some(74727), None),
|
||||
// Allows setting the threshold for the `large_assignments` lint.
|
||||
(active, large_assignments, "1.52.0", Some(83518), None),
|
||||
/// Allows `if/while p && let q = r && ...` chains.
|
||||
|
|
|
|||
|
|
@ -391,6 +391,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
DuplicatesOk, @only_local: true,
|
||||
),
|
||||
ungated!(track_caller, Normal, template!(Word), WarnFollowing),
|
||||
ungated!(instruction_set, Normal, template!(List: "set"), ErrorPreceding),
|
||||
gated!(
|
||||
no_sanitize, Normal,
|
||||
template!(List: "address, memory, thread"), DuplicatesOk,
|
||||
|
|
@ -452,11 +453,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
optimize, Normal, template!(List: "size|speed"), ErrorPreceding, optimize_attribute,
|
||||
experimental!(optimize),
|
||||
),
|
||||
// RFC 2867
|
||||
gated!(
|
||||
instruction_set, Normal, template!(List: "set"), ErrorPreceding,
|
||||
isa_attribute, experimental!(instruction_set)
|
||||
),
|
||||
|
||||
gated!(
|
||||
ffi_returns_twice, Normal, template!(Word), WarnFollowing, experimental!(ffi_returns_twice)
|
||||
|
|
@ -814,6 +810,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
rustc_attr!(TEST, rustc_polymorphize_error, Normal, template!(Word), WarnFollowing),
|
||||
rustc_attr!(TEST, rustc_def_path, Normal, template!(Word), WarnFollowing),
|
||||
rustc_attr!(TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ..."), DuplicatesOk),
|
||||
gated!(
|
||||
custom_mir, Normal, template!(List: r#"dialect = "...", phase = "...""#),
|
||||
ErrorFollowing, "the `#[custom_mir]` attribute is just used for the Rust test suite",
|
||||
),
|
||||
rustc_attr!(TEST, rustc_dump_program_clauses, Normal, template!(Word), WarnFollowing),
|
||||
rustc_attr!(TEST, rustc_dump_env_program_clauses, Normal, template!(Word), WarnFollowing),
|
||||
rustc_attr!(TEST, rustc_object_lifetime_default, Normal, template!(Word), WarnFollowing),
|
||||
|
|
|
|||
|
|
@ -388,6 +388,8 @@ impl<'hir> GenericArgs<'hir> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
/// This function returns the number of type and const generic params.
|
||||
/// It should only be used for diagnostics.
|
||||
pub fn num_generic_params(&self) -> usize {
|
||||
self.args.iter().filter(|arg| !matches!(arg, GenericArg::Lifetime(_))).count()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
item_segment.args(),
|
||||
item_segment.infer_args,
|
||||
None,
|
||||
None,
|
||||
ty::BoundConstness::NotConst,
|
||||
);
|
||||
if let Some(b) = item_segment.args().bindings.first() {
|
||||
Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
|
||||
|
|
@ -324,7 +324,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
generic_args: &'a hir::GenericArgs<'_>,
|
||||
infer_args: bool,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
constness: Option<ty::BoundConstness>,
|
||||
constness: ty::BoundConstness,
|
||||
) -> (SubstsRef<'tcx>, GenericArgCountResult) {
|
||||
// If the type is parameterized by this region, then replace this
|
||||
// region with the current anon region binding (in other words,
|
||||
|
|
@ -538,7 +538,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
&mut substs_ctx,
|
||||
);
|
||||
|
||||
if let Some(ty::BoundConstness::ConstIfConst) = constness
|
||||
if let ty::BoundConstness::ConstIfConst = constness
|
||||
&& generics.has_self && !tcx.has_attr(def_id, sym::const_trait)
|
||||
{
|
||||
tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span } );
|
||||
|
|
@ -611,7 +611,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
item_segment.args(),
|
||||
item_segment.infer_args,
|
||||
None,
|
||||
None,
|
||||
ty::BoundConstness::NotConst,
|
||||
);
|
||||
|
||||
if let Some(b) = item_segment.args().bindings.first() {
|
||||
|
|
@ -641,7 +641,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
self_ty,
|
||||
trait_ref.path.segments.last().unwrap(),
|
||||
true,
|
||||
Some(constness),
|
||||
constness,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -668,7 +668,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
args,
|
||||
infer_args,
|
||||
Some(self_ty),
|
||||
Some(constness),
|
||||
constness,
|
||||
);
|
||||
|
||||
let tcx = self.tcx();
|
||||
|
|
@ -798,7 +798,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
self_ty: Ty<'tcx>,
|
||||
trait_segment: &hir::PathSegment<'_>,
|
||||
is_impl: bool,
|
||||
constness: Option<ty::BoundConstness>,
|
||||
constness: ty::BoundConstness,
|
||||
) -> ty::TraitRef<'tcx> {
|
||||
let (substs, _) = self.create_substs_for_ast_trait_ref(
|
||||
span,
|
||||
|
|
@ -822,7 +822,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
self_ty: Ty<'tcx>,
|
||||
trait_segment: &'a hir::PathSegment<'a>,
|
||||
is_impl: bool,
|
||||
constness: Option<ty::BoundConstness>,
|
||||
constness: ty::BoundConstness,
|
||||
) -> (SubstsRef<'tcx>, GenericArgCountResult) {
|
||||
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl);
|
||||
|
||||
|
|
@ -1201,7 +1201,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
(_, _) => {
|
||||
let got = if let Some(_) = term.ty() { "type" } else { "constant" };
|
||||
let expected = def_kind.descr(assoc_item_def_id);
|
||||
tcx.sess
|
||||
let reported = tcx
|
||||
.sess
|
||||
.struct_span_err(
|
||||
binding.span,
|
||||
&format!("expected {expected} bound, found {got}"),
|
||||
|
|
@ -1212,11 +1213,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
)
|
||||
.emit();
|
||||
term = match def_kind {
|
||||
hir::def::DefKind::AssocTy => tcx.ty_error().into(),
|
||||
hir::def::DefKind::AssocTy => {
|
||||
tcx.ty_error_with_guaranteed(reported).into()
|
||||
}
|
||||
hir::def::DefKind::AssocConst => tcx
|
||||
.const_error(
|
||||
.const_error_with_guaranteed(
|
||||
tcx.bound_type_of(assoc_item_def_id)
|
||||
.subst(tcx, projection_ty.skip_binder().substs),
|
||||
reported,
|
||||
)
|
||||
.into(),
|
||||
_ => unreachable!(),
|
||||
|
|
@ -1334,8 +1338,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
.map(|&(trait_ref, _, _)| trait_ref.def_id())
|
||||
.find(|&trait_ref| tcx.is_trait_alias(trait_ref))
|
||||
.map(|trait_ref| tcx.def_span(trait_ref));
|
||||
tcx.sess.emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span });
|
||||
return tcx.ty_error();
|
||||
let reported =
|
||||
tcx.sess.emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span });
|
||||
return tcx.ty_error_with_guaranteed(reported);
|
||||
}
|
||||
|
||||
// Check that there are no gross object safety violations;
|
||||
|
|
@ -1345,14 +1350,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
let object_safety_violations =
|
||||
astconv_object_safety_violations(tcx, item.trait_ref().def_id());
|
||||
if !object_safety_violations.is_empty() {
|
||||
report_object_safety_error(
|
||||
let reported = report_object_safety_error(
|
||||
tcx,
|
||||
span,
|
||||
item.trait_ref().def_id(),
|
||||
&object_safety_violations,
|
||||
)
|
||||
.emit();
|
||||
return tcx.ty_error();
|
||||
return tcx.ty_error_with_guaranteed(reported);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2112,13 +2117,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
"Type"
|
||||
};
|
||||
|
||||
self.report_ambiguous_associated_type(
|
||||
let reported = self.report_ambiguous_associated_type(
|
||||
span,
|
||||
type_name,
|
||||
&path_str,
|
||||
item_segment.ident.name,
|
||||
);
|
||||
return tcx.ty_error();
|
||||
return tcx.ty_error_with_guaranteed(reported)
|
||||
};
|
||||
|
||||
debug!("qpath_to_ty: self_type={:?}", self_ty);
|
||||
|
|
@ -2129,7 +2134,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
self_ty,
|
||||
trait_segment,
|
||||
false,
|
||||
Some(constness),
|
||||
constness,
|
||||
);
|
||||
|
||||
let item_substs = self.create_substs_for_associated_item(
|
||||
|
|
@ -2560,8 +2565,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
{
|
||||
err.span_note(impl_.self_ty.span, "not a concrete type");
|
||||
}
|
||||
err.emit();
|
||||
tcx.ty_error()
|
||||
tcx.ty_error_with_guaranteed(err.emit())
|
||||
} else {
|
||||
self.normalize_ty(span, ty)
|
||||
}
|
||||
|
|
@ -2700,7 +2704,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
&GenericArgs::none(),
|
||||
true,
|
||||
None,
|
||||
None,
|
||||
ty::BoundConstness::NotConst,
|
||||
);
|
||||
EarlyBinder(self.normalize_ty(span, tcx.at(span).type_of(def_id)))
|
||||
.subst(tcx, substs)
|
||||
|
|
@ -2976,7 +2980,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),
|
||||
|
|
@ -2984,7 +2988,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
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVE
|
|||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{self, Span};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedDirective;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
|
||||
use rustc_trait_selection::traits::{self, ObligationCtxt};
|
||||
|
||||
|
|
@ -471,7 +472,7 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||
// version.
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||
}
|
||||
match origin {
|
||||
// Checked when type checking the function containing them.
|
||||
|
|
@ -655,7 +656,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
|
|||
|
||||
pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
|
||||
// an error would be reported if this fails.
|
||||
let _ = traits::OnUnimplementedDirective::of_item(tcx, item.owner_id.to_def_id());
|
||||
let _ = OnUnimplementedDirective::of_item(tcx, item.owner_id.to_def_id());
|
||||
}
|
||||
|
||||
pub(super) fn check_specialization_validity<'tcx>(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use super::potentially_plural_count;
|
||||
use crate::errors::LifetimesOrBoundsMismatchOnTrait;
|
||||
use hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
|
||||
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
|
|
@ -256,7 +256,7 @@ fn compare_predicate_entailment<'tcx>(
|
|||
// Compute placeholder form of impl and trait method tys.
|
||||
let tcx = infcx.tcx;
|
||||
|
||||
let mut wf_tys = FxHashSet::default();
|
||||
let mut wf_tys = FxIndexSet::default();
|
||||
|
||||
let impl_sig = infcx.replace_bound_vars_with_fresh_vars(
|
||||
impl_m_span,
|
||||
|
|
@ -405,7 +405,7 @@ fn compare_predicate_entailment<'tcx>(
|
|||
// version.
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||
return Err(reported);
|
||||
}
|
||||
|
||||
|
|
@ -479,7 +479,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
|
|||
let trait_sig = ocx.normalize(norm_cause.clone(), param_env, unnormalized_trait_sig);
|
||||
let trait_return_ty = trait_sig.output();
|
||||
|
||||
let wf_tys = FxHashSet::from_iter(
|
||||
let wf_tys = FxIndexSet::from_iter(
|
||||
unnormalized_trait_sig.inputs_and_output.iter().chain(trait_sig.inputs_and_output.iter()),
|
||||
);
|
||||
|
||||
|
|
@ -538,7 +538,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
|
|||
// RPITs.
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||
return Err(reported);
|
||||
}
|
||||
|
||||
|
|
@ -611,11 +611,11 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
|
|||
collected_tys.insert(def_id, ty);
|
||||
}
|
||||
Err(err) => {
|
||||
tcx.sess.delay_span_bug(
|
||||
let reported = tcx.sess.delay_span_bug(
|
||||
return_span,
|
||||
format!("could not fully resolve: {ty} => {err:?}"),
|
||||
);
|
||||
collected_tys.insert(def_id, tcx.ty_error());
|
||||
collected_tys.insert(def_id, tcx.ty_error_with_guaranteed(reported));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1431,7 +1431,7 @@ pub(crate) fn raw_compare_const_impl<'tcx>(
|
|||
// version.
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
return Err(infcx.err_ctxt().report_fulfillment_errors(&errors, None, false));
|
||||
return Err(infcx.err_ctxt().report_fulfillment_errors(&errors, None));
|
||||
}
|
||||
|
||||
// FIXME return `ErrorReported` if region obligations error?
|
||||
|
|
@ -1549,7 +1549,7 @@ fn compare_type_predicate_entailment<'tcx>(
|
|||
// version.
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||
return Err(reported);
|
||||
}
|
||||
|
||||
|
|
@ -1769,7 +1769,7 @@ pub fn check_type_bounds<'tcx>(
|
|||
// version.
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||
return Err(reported);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -134,15 +134,18 @@ 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(0)), ty::BoundVariableKind::Region(ty::BrEnv)]
|
||||
.iter()
|
||||
.copied(),
|
||||
[
|
||||
ty::BoundVariableKind::Region(ty::BrAnon(0, None)),
|
||||
ty::BoundVariableKind::Region(ty::BrEnv),
|
||||
]
|
||||
.iter()
|
||||
.copied(),
|
||||
);
|
||||
let mk_va_list_ty = |mutbl| {
|
||||
tcx.lang_items().va_list().map(|did| {
|
||||
let region = tcx.mk_region(ty::ReLateBound(
|
||||
ty::INNERMOST,
|
||||
ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) },
|
||||
ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) },
|
||||
));
|
||||
let env_region = tcx.mk_region(ty::ReLateBound(
|
||||
ty::INNERMOST,
|
||||
|
|
@ -364,7 +367,8 @@ 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(0) };
|
||||
let br =
|
||||
ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) };
|
||||
(
|
||||
1,
|
||||
vec![
|
||||
|
|
@ -418,7 +422,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
|||
sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
|
||||
|
||||
sym::raw_eq => {
|
||||
let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) };
|
||||
let br =
|
||||
ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) };
|
||||
let param_ty =
|
||||
tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0));
|
||||
(1, vec![param_ty; 2], tcx.types.bool)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
|
||||
use hir::def::DefKind;
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
|
||||
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
|
|
@ -21,6 +21,7 @@ use rustc_middle::ty::{GenericArgKind, InternalSubsts};
|
|||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_trait_selection::autoderef::Autoderef;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
|
||||
|
|
@ -104,7 +105,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
|
|||
f(&mut wfcx);
|
||||
let errors = wfcx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -411,7 +412,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
|
|||
.iter()
|
||||
.copied()
|
||||
.collect::<Vec<_>>(),
|
||||
&FxHashSet::default(),
|
||||
&FxIndexSet::default(),
|
||||
gat_def_id.def_id,
|
||||
gat_generics,
|
||||
)
|
||||
|
|
@ -461,10 +462,10 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
|
|||
.into_iter()
|
||||
.filter(|clause| match clause.kind().skip_binder() {
|
||||
ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => {
|
||||
!region_known_to_outlive(tcx, gat_hir, param_env, &FxHashSet::default(), a, b)
|
||||
!region_known_to_outlive(tcx, gat_hir, param_env, &FxIndexSet::default(), a, b)
|
||||
}
|
||||
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
|
||||
!ty_known_to_outlive(tcx, gat_hir, param_env, &FxHashSet::default(), a, b)
|
||||
!ty_known_to_outlive(tcx, gat_hir, param_env, &FxIndexSet::default(), a, b)
|
||||
}
|
||||
_ => bug!("Unexpected PredicateKind"),
|
||||
})
|
||||
|
|
@ -546,7 +547,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<'tcx>>(
|
|||
param_env: ty::ParamEnv<'tcx>,
|
||||
item_hir: hir::HirId,
|
||||
to_check: T,
|
||||
wf_tys: &FxHashSet<Ty<'tcx>>,
|
||||
wf_tys: &FxIndexSet<Ty<'tcx>>,
|
||||
gat_def_id: LocalDefId,
|
||||
gat_generics: &'tcx ty::Generics,
|
||||
) -> Option<FxHashSet<ty::Predicate<'tcx>>> {
|
||||
|
|
@ -653,7 +654,7 @@ fn ty_known_to_outlive<'tcx>(
|
|||
tcx: TyCtxt<'tcx>,
|
||||
id: hir::HirId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
wf_tys: &FxHashSet<Ty<'tcx>>,
|
||||
wf_tys: &FxIndexSet<Ty<'tcx>>,
|
||||
ty: Ty<'tcx>,
|
||||
region: ty::Region<'tcx>,
|
||||
) -> bool {
|
||||
|
|
@ -670,7 +671,7 @@ fn region_known_to_outlive<'tcx>(
|
|||
tcx: TyCtxt<'tcx>,
|
||||
id: hir::HirId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
wf_tys: &FxHashSet<Ty<'tcx>>,
|
||||
wf_tys: &FxIndexSet<Ty<'tcx>>,
|
||||
region_a: ty::Region<'tcx>,
|
||||
region_b: ty::Region<'tcx>,
|
||||
) -> bool {
|
||||
|
|
@ -694,7 +695,7 @@ fn resolve_regions_with_wf_tys<'tcx>(
|
|||
tcx: TyCtxt<'tcx>,
|
||||
id: hir::HirId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
wf_tys: &FxHashSet<Ty<'tcx>>,
|
||||
wf_tys: &FxIndexSet<Ty<'tcx>>,
|
||||
add_constraints: impl for<'a> FnOnce(&'a InferCtxt<'tcx>, &'a RegionBoundPairs<'tcx>),
|
||||
) -> bool {
|
||||
// Unfortunately, we have to use a new `InferCtxt` each call, because
|
||||
|
|
@ -1542,6 +1543,33 @@ fn check_fn_or_method<'tcx>(
|
|||
sig.output(),
|
||||
hir_decl.output.span(),
|
||||
);
|
||||
|
||||
if sig.abi == Abi::RustCall {
|
||||
let span = tcx.def_span(def_id);
|
||||
let has_implicit_self = hir_decl.implicit_self != hir::ImplicitSelfKind::None;
|
||||
let mut inputs = sig.inputs().iter().skip(if has_implicit_self { 1 } else { 0 });
|
||||
// Check that the argument is a tuple
|
||||
if let Some(ty) = inputs.next() {
|
||||
wfcx.register_bound(
|
||||
ObligationCause::new(span, wfcx.body_id, ObligationCauseCode::RustCall),
|
||||
wfcx.param_env,
|
||||
*ty,
|
||||
tcx.require_lang_item(hir::LangItem::Tuple, Some(span)),
|
||||
);
|
||||
} else {
|
||||
tcx.sess.span_err(
|
||||
hir_decl.inputs.last().map_or(span, |input| input.span),
|
||||
"functions with the \"rust-call\" ABI must take a single non-self tuple argument",
|
||||
);
|
||||
}
|
||||
// No more inputs other than the `self` type and the tuple type
|
||||
if inputs.next().is_some() {
|
||||
tcx.sess.span_err(
|
||||
hir_decl.inputs.last().map_or(span, |input| input.span),
|
||||
"functions with the \"rust-call\" ABI must take a single non-self tuple argument",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Basically `check_associated_type_bounds`, but separated for now and should be
|
||||
|
|
@ -1680,8 +1708,7 @@ fn receiver_is_valid<'tcx>(
|
|||
return true;
|
||||
}
|
||||
|
||||
let mut autoderef =
|
||||
Autoderef::new(infcx, wfcx.param_env, wfcx.body_id, span, receiver_ty, span);
|
||||
let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_id, span, receiver_ty);
|
||||
|
||||
// The `arbitrary_self_types` feature allows raw pointer receivers like `self: *const Self`.
|
||||
if arbitrary_self_types_enabled {
|
||||
|
|
|
|||
|
|
@ -321,7 +321,7 @@ fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, impl_did:
|
|||
}),
|
||||
);
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||
}
|
||||
|
||||
// Finally, resolve all regions.
|
||||
|
|
@ -561,7 +561,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
|
|||
predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, source, &[target.into()]);
|
||||
let errors = traits::fully_solve_obligation(&infcx, predicate);
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||
}
|
||||
|
||||
// Finally, resolve all regions.
|
||||
|
|
|
|||
|
|
@ -512,8 +512,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
|
|||
}
|
||||
_ => {}
|
||||
}
|
||||
err.emit();
|
||||
self.tcx().ty_error()
|
||||
self.tcx().ty_error_with_guaranteed(err.emit())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ use rustc_middle::bug;
|
|||
use rustc_middle::hir::map::Map;
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::middle::resolve_lifetime::*;
|
||||
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
|
||||
use rustc_middle::ty::{self, DefIdTree, TyCtxt, TypeSuperVisitable, TypeVisitor};
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::Span;
|
||||
|
|
@ -1781,7 +1781,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
|
|||
|
||||
let mut late_bound = FxIndexSet::default();
|
||||
|
||||
let mut constrained_by_input = ConstrainedCollector::default();
|
||||
let mut constrained_by_input = ConstrainedCollector { regions: Default::default(), tcx };
|
||||
for arg_ty in decl.inputs {
|
||||
constrained_by_input.visit_ty(arg_ty);
|
||||
}
|
||||
|
|
@ -1834,12 +1834,65 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
|
|||
debug!(?late_bound);
|
||||
return Some(tcx.arena.alloc(late_bound));
|
||||
|
||||
#[derive(Default)]
|
||||
struct ConstrainedCollector {
|
||||
/// Visits a `ty::Ty` collecting information about what generic parameters are constrained.
|
||||
///
|
||||
/// The visitor does not operate on `hir::Ty` so that it can be called on the rhs of a `type Alias<...> = ...;`
|
||||
/// which may live in a separate crate so there would not be any hir available. Instead we use the `type_of`
|
||||
/// query to obtain a `ty::Ty` which will be present even in cross crate scenarios. It also naturally
|
||||
/// handles cycle detection as we go through the query system.
|
||||
///
|
||||
/// This is necessary in the first place for the following case:
|
||||
/// ```
|
||||
/// type Alias<'a, T> = <T as Trait<'a>>::Assoc;
|
||||
/// fn foo<'a>(_: Alias<'a, ()>) -> Alias<'a, ()> { ... }
|
||||
/// ```
|
||||
///
|
||||
/// If we conservatively considered `'a` unconstrained then we could break users who had written code before
|
||||
/// we started correctly handling aliases. If we considered `'a` constrained then it would become late bound
|
||||
/// causing an error during astconv as the `'a` is not constrained by the input type `<() as Trait<'a>>::Assoc`
|
||||
/// but appears in the output type `<() as Trait<'a>>::Assoc`.
|
||||
///
|
||||
/// We must therefore "look into" the `Alias` to see whether we should consider `'a` constrained or not.
|
||||
///
|
||||
/// See #100508 #85533 #47511 for additional context
|
||||
struct ConstrainedCollectorPostAstConv {
|
||||
arg_is_constrained: Box<[bool]>,
|
||||
}
|
||||
|
||||
use std::ops::ControlFlow;
|
||||
use ty::Ty;
|
||||
impl<'tcx> TypeVisitor<'tcx> for ConstrainedCollectorPostAstConv {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
|
||||
match t.kind() {
|
||||
ty::Param(param_ty) => {
|
||||
self.arg_is_constrained[param_ty.index as usize] = true;
|
||||
}
|
||||
ty::Projection(_) => return ControlFlow::Continue(()),
|
||||
_ => (),
|
||||
}
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, _: ty::Const<'tcx>) -> ControlFlow<!> {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<!> {
|
||||
debug!("r={:?}", r.kind());
|
||||
if let ty::RegionKind::ReEarlyBound(region) = r.kind() {
|
||||
self.arg_is_constrained[region.index as usize] = true;
|
||||
}
|
||||
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
|
||||
struct ConstrainedCollector<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
regions: FxHashSet<LocalDefId>,
|
||||
}
|
||||
|
||||
impl<'v> Visitor<'v> for ConstrainedCollector {
|
||||
impl<'v> Visitor<'v> for ConstrainedCollector<'_> {
|
||||
fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
|
||||
match ty.kind {
|
||||
hir::TyKind::Path(
|
||||
|
|
@ -1850,6 +1903,47 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
|
|||
// (defined above)
|
||||
}
|
||||
|
||||
hir::TyKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span },
|
||||
)) => {
|
||||
// See comments on `ConstrainedCollectorPostAstConv` for why this arm does not just consider
|
||||
// substs to be unconstrained.
|
||||
let generics = self.tcx.generics_of(alias_def);
|
||||
let mut walker = ConstrainedCollectorPostAstConv {
|
||||
arg_is_constrained: vec![false; generics.params.len()].into_boxed_slice(),
|
||||
};
|
||||
walker.visit_ty(self.tcx.type_of(alias_def));
|
||||
|
||||
match segments.last() {
|
||||
Some(hir::PathSegment { args: Some(args), .. }) => {
|
||||
let tcx = self.tcx;
|
||||
for constrained_arg in
|
||||
args.args.iter().enumerate().flat_map(|(n, arg)| {
|
||||
match walker.arg_is_constrained.get(n) {
|
||||
Some(true) => Some(arg),
|
||||
Some(false) => None,
|
||||
None => {
|
||||
tcx.sess.delay_span_bug(
|
||||
*span,
|
||||
format!(
|
||||
"Incorrect generic arg count for alias {:?}",
|
||||
alias_def
|
||||
),
|
||||
);
|
||||
None
|
||||
}
|
||||
}
|
||||
})
|
||||
{
|
||||
self.visit_generic_arg(constrained_arg);
|
||||
}
|
||||
}
|
||||
Some(_) => (),
|
||||
None => bug!("Path with no segments or self type"),
|
||||
}
|
||||
}
|
||||
|
||||
hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
|
||||
// consider only the lifetimes on the final
|
||||
// segment; I am not sure it's even currently
|
||||
|
|
|
|||
|
|
@ -698,7 +698,7 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
|
|||
}
|
||||
|
||||
let Some(hidden) = locator.found else {
|
||||
tcx.sess.emit_err(UnconstrainedOpaqueType {
|
||||
let reported = tcx.sess.emit_err(UnconstrainedOpaqueType {
|
||||
span: tcx.def_span(def_id),
|
||||
name: tcx.item_name(tcx.local_parent(def_id).to_def_id()),
|
||||
what: match tcx.hir().get(scope) {
|
||||
|
|
@ -708,7 +708,7 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
|
|||
_ => "item",
|
||||
},
|
||||
});
|
||||
return tcx.ty_error();
|
||||
return tcx.ty_error_with_guaranteed(reported);
|
||||
};
|
||||
|
||||
// Only check against typeck if we didn't already error
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ fn get_impl_substs<'tcx>(
|
|||
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
ocx.infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
||||
ocx.infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ fn require_same_types<'tcx>(
|
|||
match &errors[..] {
|
||||
[] => true,
|
||||
errors => {
|
||||
infcx.err_ctxt().report_fulfillment_errors(errors, None, false);
|
||||
infcx.err_ctxt().report_fulfillment_errors(errors, None);
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
@ -336,7 +336,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
|
|||
ocx.register_bound(cause, param_env, norm_return_ty, term_did);
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||
error = true;
|
||||
}
|
||||
// now we can take the return type of the given main function
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::coercion::{AsCoercionSite, CoerceMany};
|
||||
use crate::{Diverges, Expectation, FnCtxt, Needs};
|
||||
use rustc_errors::{Applicability, MultiSpan};
|
||||
use rustc_errors::{Applicability, Diagnostic, MultiSpan};
|
||||
use rustc_hir::{self as hir, ExprKind};
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::traits::Obligation;
|
||||
|
|
@ -137,55 +137,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Some(&arm.body),
|
||||
arm_ty,
|
||||
Some(&mut |err| {
|
||||
let Some(ret) = self
|
||||
.tcx
|
||||
.hir()
|
||||
.find_by_def_id(self.body_id.owner.def_id)
|
||||
.and_then(|owner| owner.fn_decl())
|
||||
.map(|decl| decl.output.span())
|
||||
else { return; };
|
||||
let Expectation::IsLast(stmt) = orig_expected else {
|
||||
return
|
||||
};
|
||||
let can_coerce_to_return_ty = match self.ret_coercion.as_ref() {
|
||||
Some(ret_coercion) if self.in_tail_expr => {
|
||||
let ret_ty = ret_coercion.borrow().expected_ty();
|
||||
let ret_ty = self.inh.infcx.shallow_resolve(ret_ty);
|
||||
self.can_coerce(arm_ty, ret_ty)
|
||||
&& prior_arm.map_or(true, |(_, t, _)| self.can_coerce(t, ret_ty))
|
||||
// The match arms need to unify for the case of `impl Trait`.
|
||||
&& !matches!(ret_ty.kind(), ty::Opaque(..))
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
if !can_coerce_to_return_ty {
|
||||
return;
|
||||
}
|
||||
|
||||
let semi_span = expr.span.shrink_to_hi().with_hi(stmt.hi());
|
||||
let mut ret_span: MultiSpan = semi_span.into();
|
||||
ret_span.push_span_label(
|
||||
expr.span,
|
||||
"this could be implicitly returned but it is a statement, not a \
|
||||
tail expression",
|
||||
);
|
||||
ret_span
|
||||
.push_span_label(ret, "the `match` arms can conform to this return type");
|
||||
ret_span.push_span_label(
|
||||
semi_span,
|
||||
"the `match` is a statement because of this semicolon, consider \
|
||||
removing it",
|
||||
);
|
||||
err.span_note(
|
||||
ret_span,
|
||||
"you might have meant to return the `match` expression",
|
||||
);
|
||||
err.tool_only_span_suggestion(
|
||||
semi_span,
|
||||
"remove this semicolon",
|
||||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
self.suggest_removing_semicolon_for_coerce(
|
||||
err,
|
||||
expr,
|
||||
orig_expected,
|
||||
arm_ty,
|
||||
prior_arm,
|
||||
)
|
||||
}),
|
||||
false,
|
||||
);
|
||||
|
|
@ -219,6 +177,71 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
coercion.complete(self)
|
||||
}
|
||||
|
||||
fn suggest_removing_semicolon_for_coerce(
|
||||
&self,
|
||||
diag: &mut Diagnostic,
|
||||
expr: &hir::Expr<'tcx>,
|
||||
expectation: Expectation<'tcx>,
|
||||
arm_ty: Ty<'tcx>,
|
||||
prior_arm: Option<(Option<hir::HirId>, Ty<'tcx>, Span)>,
|
||||
) {
|
||||
let hir = self.tcx.hir();
|
||||
|
||||
// First, check that we're actually in the tail of a function.
|
||||
let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Block(block, _), .. }) =
|
||||
hir.get(self.body_id) else { return; };
|
||||
let Some(hir::Stmt { kind: hir::StmtKind::Semi(last_expr), .. })
|
||||
= block.innermost_block().stmts.last() else { return; };
|
||||
if last_expr.hir_id != expr.hir_id {
|
||||
return;
|
||||
}
|
||||
|
||||
// Next, make sure that we have no type expectation.
|
||||
let Some(ret) = hir
|
||||
.find_by_def_id(self.body_id.owner.def_id)
|
||||
.and_then(|owner| owner.fn_decl())
|
||||
.map(|decl| decl.output.span()) else { return; };
|
||||
let Expectation::IsLast(stmt) = expectation else {
|
||||
return;
|
||||
};
|
||||
|
||||
let can_coerce_to_return_ty = match self.ret_coercion.as_ref() {
|
||||
Some(ret_coercion) => {
|
||||
let ret_ty = ret_coercion.borrow().expected_ty();
|
||||
let ret_ty = self.inh.infcx.shallow_resolve(ret_ty);
|
||||
self.can_coerce(arm_ty, ret_ty)
|
||||
&& prior_arm.map_or(true, |(_, ty, _)| self.can_coerce(ty, ret_ty))
|
||||
// The match arms need to unify for the case of `impl Trait`.
|
||||
&& !matches!(ret_ty.kind(), ty::Opaque(..))
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
if !can_coerce_to_return_ty {
|
||||
return;
|
||||
}
|
||||
|
||||
let semi_span = expr.span.shrink_to_hi().with_hi(stmt.hi());
|
||||
let mut ret_span: MultiSpan = semi_span.into();
|
||||
ret_span.push_span_label(
|
||||
expr.span,
|
||||
"this could be implicitly returned but it is a statement, not a \
|
||||
tail expression",
|
||||
);
|
||||
ret_span.push_span_label(ret, "the `match` arms can conform to this return type");
|
||||
ret_span.push_span_label(
|
||||
semi_span,
|
||||
"the `match` is a statement because of this semicolon, consider \
|
||||
removing it",
|
||||
);
|
||||
diag.span_note(ret_span, "you might have meant to return the `match` expression");
|
||||
diag.tool_only_span_suggestion(
|
||||
semi_span,
|
||||
"remove this semicolon",
|
||||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
|
||||
/// When the previously checked expression (the scrutinee) diverges,
|
||||
/// warn the user about the match arms being unreachable.
|
||||
fn warn_arms_when_scrutinee_diverges(&self, arms: &'tcx [hir::Arm<'tcx>]) {
|
||||
|
|
|
|||
|
|
@ -12,18 +12,7 @@ use std::iter;
|
|||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> {
|
||||
Autoderef::new(self, self.param_env, self.body_id, span, base_ty, span)
|
||||
}
|
||||
|
||||
/// Like `autoderef`, but provides a custom `Span` to use for calls to
|
||||
/// an overloaded `Deref` operator
|
||||
pub fn autoderef_overloaded_span(
|
||||
&'a self,
|
||||
span: Span,
|
||||
base_ty: Ty<'tcx>,
|
||||
overloaded_span: Span,
|
||||
) -> Autoderef<'a, 'tcx> {
|
||||
Autoderef::new(self, self.param_env, self.body_id, span, base_ty, overloaded_span)
|
||||
Autoderef::new(self, self.param_env, self.body_id, span, base_ty)
|
||||
}
|
||||
|
||||
pub fn try_overloaded_deref(
|
||||
|
|
@ -55,11 +44,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|InferOk { value: method, obligations: o }| {
|
||||
obligations.extend(o);
|
||||
if let ty::Ref(region, _, mutbl) = *method.sig.output().kind() {
|
||||
Some(OverloadedDeref {
|
||||
region,
|
||||
mutbl,
|
||||
span: autoderef.overloaded_span(),
|
||||
})
|
||||
Some(OverloadedDeref { region, mutbl, span: autoderef.span() })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
output
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, call_expr, callee_expr, arg_exprs, autoderef), ret)]
|
||||
fn try_overloaded_call_step(
|
||||
&self,
|
||||
call_expr: &'tcx hir::Expr<'tcx>,
|
||||
|
|
@ -138,10 +139,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
) -> Option<CallStep<'tcx>> {
|
||||
let adjusted_ty =
|
||||
self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
|
||||
debug!(
|
||||
"try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?})",
|
||||
call_expr, adjusted_ty
|
||||
);
|
||||
|
||||
// If the callee is a bare function or a closure, then we're all set.
|
||||
match *adjusted_ty.kind() {
|
||||
|
|
@ -471,6 +468,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
def_id,
|
||||
);
|
||||
|
||||
if fn_sig.abi == abi::Abi::RustCall {
|
||||
let sp = arg_exprs.last().map_or(call_expr.span, |expr| expr.span);
|
||||
if let Some(ty) = fn_sig.inputs().last().copied() {
|
||||
self.register_bound(
|
||||
ty,
|
||||
self.tcx.require_lang_item(hir::LangItem::Tuple, Some(sp)),
|
||||
traits::ObligationCause::new(sp, self.body_id, traits::RustCall),
|
||||
);
|
||||
} else {
|
||||
self.tcx.sess.span_err(
|
||||
sp,
|
||||
"functions with the \"rust-call\" ABI must take a single non-self tuple argument",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn_sig.output()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,13 +6,11 @@ use rustc_hir as hir;
|
|||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{ImplicitSelfKind, ItemKind, Node};
|
||||
use rustc_hir_analysis::check::fn_maybe_err;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::RegionVariableOrigin;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_trait_selection::traits;
|
||||
use std::cell::RefCell;
|
||||
|
||||
|
|
@ -56,41 +54,6 @@ pub(super) fn check_fn<'a, 'tcx>(
|
|||
|
||||
fn_maybe_err(tcx, span, fn_sig.abi);
|
||||
|
||||
if fn_sig.abi == Abi::RustCall {
|
||||
let expected_args = if let ImplicitSelfKind::None = decl.implicit_self { 1 } else { 2 };
|
||||
|
||||
let err = || {
|
||||
let item = match tcx.hir().get(fn_id) {
|
||||
Node::Item(hir::Item { kind: ItemKind::Fn(header, ..), .. }) => Some(header),
|
||||
Node::ImplItem(hir::ImplItem {
|
||||
kind: hir::ImplItemKind::Fn(header, ..), ..
|
||||
}) => Some(header),
|
||||
Node::TraitItem(hir::TraitItem {
|
||||
kind: hir::TraitItemKind::Fn(header, ..),
|
||||
..
|
||||
}) => Some(header),
|
||||
// Closures are RustCall, but they tuple their arguments, so shouldn't be checked
|
||||
Node::Expr(hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => None,
|
||||
node => bug!("Item being checked wasn't a function/closure: {:?}", node),
|
||||
};
|
||||
|
||||
if let Some(header) = item {
|
||||
tcx.sess.span_err(header.span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple");
|
||||
}
|
||||
};
|
||||
|
||||
if fn_sig.inputs().len() != expected_args {
|
||||
err()
|
||||
} else {
|
||||
// FIXME(CraftSpider) Add a check on parameter expansion, so we don't just make the ICE happen later on
|
||||
// This will probably require wide-scale changes to support a TupleKind obligation
|
||||
// We can't resolve this without knowing the type of the param
|
||||
if !matches!(fn_sig.inputs()[expected_args - 1].kind(), ty::Tuple(_) | ty::Param(_)) {
|
||||
err()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if body.generator_kind.is_some() && can_be_generator.is_some() {
|
||||
let yield_ty = fcx
|
||||
.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
|
||||
|
|
@ -137,7 +100,6 @@ pub(super) fn check_fn<'a, 'tcx>(
|
|||
|
||||
inherited.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig);
|
||||
|
||||
fcx.in_tail_expr = true;
|
||||
if let ty::Dynamic(..) = declared_ret_ty.kind() {
|
||||
// FIXME: We need to verify that the return type is `Sized` after the return expression has
|
||||
// been evaluated so that we have types available for all the nodes being returned, but that
|
||||
|
|
@ -156,7 +118,6 @@ pub(super) fn check_fn<'a, 'tcx>(
|
|||
fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
|
||||
fcx.check_return_expr(&body.value, false);
|
||||
}
|
||||
fcx.in_tail_expr = false;
|
||||
|
||||
// We insert the deferred_generator_interiors entry after visiting the body.
|
||||
// This ensures that all nested generators appear before the entry of this generator.
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use rustc_hir_analysis::astconv::AstConv;
|
|||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::LateBoundRegionConversionTime;
|
||||
use rustc_infer::infer::{InferOk, InferResult};
|
||||
use rustc_macros::{TypeFoldable, TypeVisitable};
|
||||
use rustc_middle::ty::subst::InternalSubsts;
|
||||
use rustc_middle::ty::visit::TypeVisitable;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
|
|
@ -22,7 +23,7 @@ use std::cmp;
|
|||
use std::iter;
|
||||
|
||||
/// What signature do we *expect* the closure to have from context?
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone, TypeFoldable, TypeVisitable)]
|
||||
struct ExpectedSig<'tcx> {
|
||||
/// Span that gave us this expectation, if we know that.
|
||||
cause_span: Option<Span>,
|
||||
|
|
@ -241,9 +242,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if expected_sig.is_none()
|
||||
&& let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder()
|
||||
{
|
||||
expected_sig = self.deduce_sig_from_projection(
|
||||
expected_sig = self.normalize_associated_types_in(
|
||||
obligation.cause.span,
|
||||
self.deduce_sig_from_projection(
|
||||
Some(obligation.cause.span),
|
||||
bound_predicate.rebind(proj_predicate),
|
||||
bound_predicate.rebind(proj_predicate),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -705,12 +705,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||
|
||||
// Object safety violations or miscellaneous.
|
||||
Err(err) => {
|
||||
self.err_ctxt().report_selection_error(
|
||||
obligation.clone(),
|
||||
&obligation,
|
||||
&err,
|
||||
false,
|
||||
);
|
||||
self.err_ctxt().report_selection_error(obligation.clone(), &obligation, &err);
|
||||
// Treat this like an obligation and follow through
|
||||
// with the unsizing - the lack of a coercion should
|
||||
// be silent, as it causes a type mismatch later.
|
||||
|
|
@ -1644,9 +1639,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
|||
if visitor.ret_exprs.len() > 0 && let Some(expr) = expression {
|
||||
self.note_unreachable_loop_return(&mut err, &expr, &visitor.ret_exprs);
|
||||
}
|
||||
err.emit_unless(unsized_return);
|
||||
let reported = err.emit_unless(unsized_return);
|
||||
|
||||
self.final_ty = Some(fcx.tcx.ty_error());
|
||||
self.final_ty = Some(fcx.tcx.ty_error_with_guaranteed(reported));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,14 +80,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// coercions from ! to `expected`.
|
||||
if ty.is_never() {
|
||||
if let Some(adjustments) = self.typeck_results.borrow().adjustments().get(expr.hir_id) {
|
||||
self.tcx().sess.delay_span_bug(
|
||||
let reported = self.tcx().sess.delay_span_bug(
|
||||
expr.span,
|
||||
"expression with never type wound up being adjusted",
|
||||
);
|
||||
return if let [Adjustment { kind: Adjust::NeverToAny, target }] = &adjustments[..] {
|
||||
target.to_owned()
|
||||
} else {
|
||||
self.tcx().ty_error()
|
||||
self.tcx().ty_error_with_guaranteed(reported)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -396,8 +396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
{
|
||||
err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
|
||||
}
|
||||
err.emit();
|
||||
oprnd_t = tcx.ty_error();
|
||||
oprnd_t = tcx.ty_error_with_guaranteed(err.emit());
|
||||
}
|
||||
}
|
||||
hir::UnOp::Not => {
|
||||
|
|
@ -843,7 +842,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
{
|
||||
// Point any obligations that were registered due to opaque type
|
||||
// inference at the return expression.
|
||||
self.select_obligations_where_possible(false, |errors| {
|
||||
self.select_obligations_where_possible(|errors| {
|
||||
self.point_at_return_for_opaque_ty_error(errors, span, return_expr_ty);
|
||||
});
|
||||
}
|
||||
|
|
@ -1097,12 +1096,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// If the assignment expression itself is ill-formed, don't
|
||||
// bother emitting another error
|
||||
if lhs_ty.references_error() || rhs_ty.references_error() {
|
||||
err.delay_as_bug()
|
||||
} else {
|
||||
err.emit();
|
||||
}
|
||||
return self.tcx.ty_error();
|
||||
let reported = err.emit_unless(lhs_ty.references_error() || rhs_ty.references_error());
|
||||
return self.tcx.ty_error_with_guaranteed(reported);
|
||||
}
|
||||
|
||||
let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
|
||||
|
|
@ -2738,7 +2733,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Some((index_ty, element_ty)) => {
|
||||
// two-phase not needed because index_ty is never mutable
|
||||
self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No);
|
||||
self.select_obligations_where_possible(false, |errors| {
|
||||
self.select_obligations_where_possible(|errors| {
|
||||
self.point_at_index_if_possible(errors, idx.span)
|
||||
});
|
||||
element_ty
|
||||
|
|
@ -2777,8 +2772,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
self.tcx.ty_error()
|
||||
let reported = err.emit();
|
||||
self.tcx.ty_error_with_guaranteed(reported)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,16 +7,16 @@ use rustc_data_structures::{
|
|||
use rustc_middle::ty::{self, Ty};
|
||||
|
||||
impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||
/// Performs type inference fallback, returning true if any fallback
|
||||
/// occurs.
|
||||
pub(super) fn type_inference_fallback(&self) -> bool {
|
||||
/// Performs type inference fallback, setting `FnCtxt::fallback_has_occurred`
|
||||
/// if fallback has occurred.
|
||||
pub(super) fn type_inference_fallback(&self) {
|
||||
debug!(
|
||||
"type-inference-fallback start obligations: {:#?}",
|
||||
self.fulfillment_cx.borrow_mut().pending_obligations()
|
||||
);
|
||||
|
||||
// All type checking constraints were added, try to fallback unsolved variables.
|
||||
self.select_obligations_where_possible(false, |_| {});
|
||||
self.select_obligations_where_possible(|_| {});
|
||||
|
||||
debug!(
|
||||
"type-inference-fallback post selection obligations: {:#?}",
|
||||
|
|
@ -26,18 +26,17 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
|||
// Check if we have any unsolved variables. If not, no need for fallback.
|
||||
let unsolved_variables = self.unsolved_variables();
|
||||
if unsolved_variables.is_empty() {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
let diverging_fallback = self.calculate_diverging_fallback(&unsolved_variables);
|
||||
|
||||
let mut fallback_has_occurred = false;
|
||||
// We do fallback in two passes, to try to generate
|
||||
// better error messages.
|
||||
// The first time, we do *not* replace opaque types.
|
||||
for ty in unsolved_variables {
|
||||
debug!("unsolved_variable = {:?}", ty);
|
||||
fallback_has_occurred |= self.fallback_if_possible(ty, &diverging_fallback);
|
||||
self.fallback_if_possible(ty, &diverging_fallback);
|
||||
}
|
||||
|
||||
// We now see if we can make progress. This might cause us to
|
||||
|
|
@ -63,9 +62,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
|||
// If we had tried to fallback the opaque inference variable to `MyType`,
|
||||
// we will generate a confusing type-check error that does not explicitly
|
||||
// refer to opaque types.
|
||||
self.select_obligations_where_possible(fallback_has_occurred, |_| {});
|
||||
|
||||
fallback_has_occurred
|
||||
self.select_obligations_where_possible(|_| {});
|
||||
}
|
||||
|
||||
// Tries to apply a fallback to `ty` if it is an unsolved variable.
|
||||
|
|
@ -81,12 +78,13 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
|||
// Fallback becomes very dubious if we have encountered
|
||||
// type-checking errors. In that case, fallback to Error.
|
||||
//
|
||||
// The return value indicates whether fallback has occurred.
|
||||
// Sets `FnCtxt::fallback_has_occurred` if fallback is performed
|
||||
// during this call.
|
||||
fn fallback_if_possible(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
diverging_fallback: &FxHashMap<Ty<'tcx>, Ty<'tcx>>,
|
||||
) -> bool {
|
||||
) {
|
||||
// Careful: we do NOT shallow-resolve `ty`. We know that `ty`
|
||||
// is an unsolved variable, and we determine its fallback
|
||||
// based solely on how it was created, not what other type
|
||||
|
|
@ -111,7 +109,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
|||
ty::Infer(ty::FloatVar(_)) => self.tcx.types.f64,
|
||||
_ => match diverging_fallback.get(&ty) {
|
||||
Some(&fallback_ty) => fallback_ty,
|
||||
None => return false,
|
||||
None => return,
|
||||
},
|
||||
};
|
||||
debug!("fallback_if_possible(ty={:?}): defaulting to `{:?}`", ty, fallback);
|
||||
|
|
@ -122,7 +120,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
|||
.map(|origin| origin.span)
|
||||
.unwrap_or(rustc_span::DUMMY_SP);
|
||||
self.demand_eqtype(span, ty, fallback);
|
||||
true
|
||||
self.fallback_has_occurred.set(true);
|
||||
}
|
||||
|
||||
/// The "diverging fallback" system is rather complicated. This is
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// possible. This can help substantially when there are
|
||||
// indirect dependencies that don't seem worth tracking
|
||||
// precisely.
|
||||
self.select_obligations_where_possible(false, mutate_fulfillment_errors);
|
||||
self.select_obligations_where_possible(mutate_fulfillment_errors);
|
||||
self.resolve_vars_if_possible(ty)
|
||||
}
|
||||
|
||||
|
|
@ -600,7 +600,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
pub(in super::super) fn resolve_generator_interiors(&self, def_id: DefId) {
|
||||
let mut generators = self.deferred_generator_interiors.borrow_mut();
|
||||
for (body_id, interior, kind) in generators.drain(..) {
|
||||
self.select_obligations_where_possible(false, |_| {});
|
||||
self.select_obligations_where_possible(|_| {});
|
||||
crate::generator_interior::resolve_interior(self, def_id, body_id, interior, kind);
|
||||
}
|
||||
}
|
||||
|
|
@ -611,25 +611,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
if !errors.is_empty() {
|
||||
self.adjust_fulfillment_errors_for_expr_obligation(&mut errors);
|
||||
self.err_ctxt().report_fulfillment_errors(&errors, self.inh.body_id, false);
|
||||
self.err_ctxt().report_fulfillment_errors(&errors, self.inh.body_id);
|
||||
}
|
||||
}
|
||||
|
||||
/// Select as many obligations as we can at present.
|
||||
pub(in super::super) fn select_obligations_where_possible(
|
||||
&self,
|
||||
fallback_has_occurred: bool,
|
||||
mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
|
||||
) {
|
||||
let mut result = self.fulfillment_cx.borrow_mut().select_where_possible(self);
|
||||
if !result.is_empty() {
|
||||
mutate_fulfillment_errors(&mut result);
|
||||
self.adjust_fulfillment_errors_for_expr_obligation(&mut result);
|
||||
self.err_ctxt().report_fulfillment_errors(
|
||||
&result,
|
||||
self.inh.body_id,
|
||||
fallback_has_occurred,
|
||||
);
|
||||
self.err_ctxt().report_fulfillment_errors(&result, self.inh.body_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1217,9 +1212,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
|
||||
return (tcx.ty_error(), res);
|
||||
let reported = err.emit();
|
||||
return (tcx.ty_error_with_guaranteed(reported), res);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
tuple_arguments,
|
||||
Some(method.def_id),
|
||||
);
|
||||
|
||||
method.sig.output()
|
||||
}
|
||||
|
||||
|
|
@ -214,7 +215,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
"cannot use call notation; the first type parameter \
|
||||
for the function trait is neither a tuple nor unit"
|
||||
)
|
||||
.emit();
|
||||
.delay_as_bug();
|
||||
(self.err_args(provided_args.len()), None)
|
||||
}
|
||||
}
|
||||
|
|
@ -344,7 +345,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// an "opportunistic" trait resolution of any trait bounds on
|
||||
// the call. This helps coercions.
|
||||
if check_closures {
|
||||
self.select_obligations_where_possible(false, |_| {})
|
||||
self.select_obligations_where_possible(|_| {})
|
||||
}
|
||||
|
||||
// Check each argument, to satisfy the input it was provided for
|
||||
|
|
|
|||
|
|
@ -68,10 +68,6 @@ pub struct FnCtxt<'a, 'tcx> {
|
|||
/// any).
|
||||
pub(super) ret_coercion: Option<RefCell<DynamicCoerceMany<'tcx>>>,
|
||||
|
||||
/// Used exclusively to reduce cost of advanced evaluation used for
|
||||
/// more helpful diagnostics.
|
||||
pub(super) in_tail_expr: bool,
|
||||
|
||||
/// First span of a return site that we find. Used in error messages.
|
||||
pub(super) ret_coercion_span: Cell<Option<Span>>,
|
||||
|
||||
|
|
@ -115,6 +111,8 @@ pub struct FnCtxt<'a, 'tcx> {
|
|||
pub(super) enclosing_breakables: RefCell<EnclosingBreakables<'tcx>>,
|
||||
|
||||
pub(super) inh: &'a Inherited<'tcx>,
|
||||
|
||||
pub(super) fallback_has_occurred: Cell<bool>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
|
@ -128,7 +126,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
param_env,
|
||||
err_count_on_creation: inh.tcx.sess.err_count(),
|
||||
ret_coercion: None,
|
||||
in_tail_expr: false,
|
||||
ret_coercion_span: Cell::new(None),
|
||||
resume_yield_tys: None,
|
||||
ps: Cell::new(UnsafetyState::function(hir::Unsafety::Normal, hir::CRATE_HIR_ID)),
|
||||
|
|
@ -138,6 +135,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
by_id: Default::default(),
|
||||
}),
|
||||
inh,
|
||||
fallback_has_occurred: Cell::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -159,7 +157,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
///
|
||||
/// [`InferCtxt::err_ctxt`]: infer::InferCtxt::err_ctxt
|
||||
pub fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> {
|
||||
TypeErrCtxt { infcx: &self.infcx, typeck_results: Some(self.typeck_results.borrow()) }
|
||||
TypeErrCtxt {
|
||||
infcx: &self.infcx,
|
||||
typeck_results: Some(self.typeck_results.borrow()),
|
||||
fallback_has_occurred: self.fallback_has_occurred.get(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn errors_reported_since_creation(&self) -> bool {
|
||||
|
|
|
|||
|
|
@ -13,10 +13,13 @@ use rustc_hir::def_id::DefId;
|
|||
use rustc_hir::hir_id::HirIdSet;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind};
|
||||
use rustc_infer::infer::RegionVariableOrigin;
|
||||
use rustc_middle::middle::region::{self, Scope, ScopeData, YieldData};
|
||||
use rustc_middle::ty::{self, RvalueScopes, Ty, TyCtxt, TypeVisitable};
|
||||
use rustc_middle::ty::fold::FnMutDelegate;
|
||||
use rustc_middle::ty::{self, BoundVariableKind, RvalueScopes, Ty, TyCtxt, TypeVisitable};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
mod drop_ranges;
|
||||
|
||||
|
|
@ -211,31 +214,57 @@ pub fn resolve_interior<'a, 'tcx>(
|
|||
|
||||
debug!("types in generator {:?}, span = {:?}", types, body.value.span);
|
||||
|
||||
let mut counter = 0;
|
||||
// We want to deduplicate if the lifetimes are the same modulo some non-informative counter.
|
||||
// So, we need to actually do two passes: first by type to anonymize (preserving information
|
||||
// required for diagnostics), then a second pass over all captured types to reassign disjoint
|
||||
// region indices.
|
||||
let mut captured_tys = FxHashSet::default();
|
||||
let type_causes: Vec<_> = types
|
||||
.into_iter()
|
||||
.filter_map(|mut cause| {
|
||||
// Erase regions and canonicalize late-bound regions to deduplicate as many types as we
|
||||
// can.
|
||||
let ty = fcx.normalize_associated_types_in(cause.span, cause.ty);
|
||||
let erased = fcx.tcx.erase_regions(ty);
|
||||
if captured_tys.insert(erased) {
|
||||
// Replace all regions inside the generator interior with late bound regions.
|
||||
// Note that each region slot in the types gets a new fresh late bound region,
|
||||
// which means that none of the regions inside relate to any other, even if
|
||||
// typeck had previously found constraints that would cause them to be related.
|
||||
let folded = fcx.tcx.fold_regions(erased, |_, current_depth| {
|
||||
let br = ty::BoundRegion {
|
||||
var: ty::BoundVar::from_u32(counter),
|
||||
kind: ty::BrAnon(counter),
|
||||
};
|
||||
let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br));
|
||||
counter += 1;
|
||||
r
|
||||
});
|
||||
// Replace all regions inside the generator interior with late bound regions.
|
||||
// Note that each region slot in the types gets a new fresh late bound region,
|
||||
// which means that none of the regions inside relate to any other, even if
|
||||
// typeck had previously found constraints that would cause them to be related.
|
||||
|
||||
cause.ty = folded;
|
||||
let mut counter = 0;
|
||||
let mut mk_bound_region = |span| {
|
||||
let kind = ty::BrAnon(counter, span);
|
||||
let var = ty::BoundVar::from_u32(counter);
|
||||
counter += 1;
|
||||
ty::BoundRegion { var, kind }
|
||||
};
|
||||
let ty = fcx.normalize_associated_types_in(cause.span, cause.ty);
|
||||
let ty = fcx.tcx.fold_regions(ty, |region, current_depth| {
|
||||
let br = match region.kind() {
|
||||
ty::ReVar(vid) => {
|
||||
let origin = fcx.region_var_origin(vid);
|
||||
match origin {
|
||||
RegionVariableOrigin::EarlyBoundRegion(span, _) => {
|
||||
mk_bound_region(Some(span))
|
||||
}
|
||||
_ => mk_bound_region(None),
|
||||
}
|
||||
}
|
||||
// FIXME: these should use `BrNamed`
|
||||
ty::ReEarlyBound(region) => {
|
||||
mk_bound_region(Some(fcx.tcx.def_span(region.def_id)))
|
||||
}
|
||||
ty::ReLateBound(_, ty::BoundRegion { kind, .. })
|
||||
| ty::ReFree(ty::FreeRegion { bound_region: kind, .. }) => match kind {
|
||||
ty::BoundRegionKind::BrAnon(_, span) => mk_bound_region(span),
|
||||
ty::BoundRegionKind::BrNamed(def_id, _) => {
|
||||
mk_bound_region(Some(fcx.tcx.def_span(def_id)))
|
||||
}
|
||||
ty::BoundRegionKind::BrEnv => mk_bound_region(None),
|
||||
},
|
||||
_ => mk_bound_region(None),
|
||||
};
|
||||
let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br));
|
||||
r
|
||||
});
|
||||
if captured_tys.insert(ty) {
|
||||
cause.ty = ty;
|
||||
Some(cause)
|
||||
} else {
|
||||
None
|
||||
|
|
@ -243,11 +272,38 @@ pub fn resolve_interior<'a, 'tcx>(
|
|||
})
|
||||
.collect();
|
||||
|
||||
let mut bound_vars: SmallVec<[BoundVariableKind; 4]> = smallvec![];
|
||||
let mut counter = 0;
|
||||
// Optimization: If there is only one captured type, then we don't actually
|
||||
// need to fold and reindex (since the first type doesn't change).
|
||||
let type_causes = if captured_tys.len() > 0 {
|
||||
// Optimization: Use `replace_escaping_bound_vars_uncached` instead of
|
||||
// `fold_regions`, since we only have late bound regions, and it skips
|
||||
// types without bound regions.
|
||||
fcx.tcx.replace_escaping_bound_vars_uncached(
|
||||
type_causes,
|
||||
FnMutDelegate {
|
||||
regions: &mut |br| {
|
||||
let kind = match br.kind {
|
||||
ty::BrAnon(_, span) => ty::BrAnon(counter, span),
|
||||
_ => br.kind,
|
||||
};
|
||||
let var = ty::BoundVar::from_usize(bound_vars.len());
|
||||
bound_vars.push(ty::BoundVariableKind::Region(kind));
|
||||
counter += 1;
|
||||
fcx.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var, kind }))
|
||||
},
|
||||
types: &mut |b| bug!("unexpected bound ty in binder: {b:?}"),
|
||||
consts: &mut |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}"),
|
||||
},
|
||||
)
|
||||
} else {
|
||||
type_causes
|
||||
};
|
||||
|
||||
// Extract type components to build the witness type.
|
||||
let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty));
|
||||
let bound_vars = fcx.tcx.mk_bound_variable_kinds(
|
||||
(0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))),
|
||||
);
|
||||
let bound_vars = fcx.tcx.mk_bound_variable_kinds(bound_vars.iter());
|
||||
let witness =
|
||||
fcx.tcx.mk_generator_witness(ty::Binder::bind_with_vars(type_list, bound_vars.clone()));
|
||||
|
||||
|
|
|
|||
|
|
@ -209,6 +209,7 @@ fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::T
|
|||
typeck_with_fallback(tcx, def_id, fallback)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(tcx, fallback), ret)]
|
||||
fn typeck_with_fallback<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
|
|
@ -316,12 +317,12 @@ fn typeck_with_fallback<'tcx>(
|
|||
fcx
|
||||
};
|
||||
|
||||
let fallback_has_occurred = fcx.type_inference_fallback();
|
||||
fcx.type_inference_fallback();
|
||||
|
||||
// Even though coercion casts provide type hints, we check casts after fallback for
|
||||
// backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
|
||||
fcx.check_casts();
|
||||
fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
|
||||
fcx.select_obligations_where_possible(|_| {});
|
||||
|
||||
// Closure and generator analysis may run after fallback
|
||||
// because they don't constrain other type variables.
|
||||
|
|
@ -458,7 +459,7 @@ fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, qpath: &hir::QPath<'
|
|||
/// # fn f(x: (isize, isize)) {}
|
||||
/// f((1, 2));
|
||||
/// ```
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
enum TupleArgumentsFlag {
|
||||
DontTupleArguments,
|
||||
TupleArguments,
|
||||
|
|
|
|||
|
|
@ -151,8 +151,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||
) -> Ty<'tcx> {
|
||||
// Commit the autoderefs by calling `autoderef` again, but this
|
||||
// time writing the results into the various typeck results.
|
||||
let mut autoderef =
|
||||
self.autoderef_overloaded_span(self.span, unadjusted_self_ty, self.call_expr.span);
|
||||
let mut autoderef = self.autoderef(self.call_expr.span, unadjusted_self_ty);
|
||||
let Some((ty, n)) = autoderef.nth(pick.autoderefs) else {
|
||||
return self.tcx.ty_error_with_message(
|
||||
rustc_span::DUMMY_SP,
|
||||
|
|
|
|||
|
|
@ -475,10 +475,9 @@ fn method_autoderef_steps<'tcx>(
|
|||
let (ref infcx, goal, inference_vars) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &goal);
|
||||
let ParamEnvAnd { param_env, value: self_ty } = goal;
|
||||
|
||||
let mut autoderef =
|
||||
Autoderef::new(infcx, param_env, hir::CRATE_HIR_ID, DUMMY_SP, self_ty, DUMMY_SP)
|
||||
.include_raw_pointers()
|
||||
.silence_errors();
|
||||
let mut autoderef = Autoderef::new(infcx, param_env, hir::CRATE_HIR_ID, DUMMY_SP, self_ty)
|
||||
.include_raw_pointers()
|
||||
.silence_errors();
|
||||
let mut reached_raw_pointer = false;
|
||||
let mut steps: Vec<_> = autoderef
|
||||
.by_ref()
|
||||
|
|
|
|||
|
|
@ -14,19 +14,26 @@ use rustc_hir::def::DefKind;
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{ExprKind, Node, QPath};
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::{
|
||||
type_variable::{TypeVariableOrigin, TypeVariableOriginKind},
|
||||
RegionVariableOrigin,
|
||||
};
|
||||
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
||||
use rustc_middle::traits::util::supertraits;
|
||||
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
|
||||
use rustc_middle::ty::print::with_crate_prefix;
|
||||
use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeVisitable};
|
||||
use rustc_middle::ty::{
|
||||
self, DefIdTree, GenericArg, GenericArgKind, ToPredicate, Ty, TyCtxt, TypeVisitable,
|
||||
};
|
||||
use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::Symbol;
|
||||
use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span};
|
||||
use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote;
|
||||
use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::{
|
||||
FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedNote,
|
||||
FulfillmentError, Obligation, ObligationCause, ObligationCauseCode,
|
||||
};
|
||||
|
||||
use std::cmp::Ordering;
|
||||
|
|
@ -279,7 +286,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
) {
|
||||
return None;
|
||||
}
|
||||
|
||||
span = item_name.span;
|
||||
|
||||
// Don't show generic arguments when the method can't be found in any implementation (#81576).
|
||||
|
|
@ -392,28 +398,118 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
custom_span_label = true;
|
||||
}
|
||||
if static_candidates.len() == 1 {
|
||||
let ty_str =
|
||||
if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) {
|
||||
// When the "method" is resolved through dereferencing, we really want the
|
||||
// original type that has the associated function for accurate suggestions.
|
||||
// (#61411)
|
||||
let ty = tcx.at(span).type_of(*impl_did);
|
||||
match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
|
||||
(ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
|
||||
// Use `actual` as it will have more `substs` filled in.
|
||||
self.ty_to_value_string(actual.peel_refs())
|
||||
let mut has_unsuggestable_args = false;
|
||||
let ty_str = if let Some(CandidateSource::Impl(impl_did)) =
|
||||
static_candidates.get(0)
|
||||
{
|
||||
// When the "method" is resolved through dereferencing, we really want the
|
||||
// original type that has the associated function for accurate suggestions.
|
||||
// (#61411)
|
||||
let ty = tcx.at(span).type_of(*impl_did);
|
||||
match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
|
||||
(ty::Adt(def, _), ty::Adt(def_actual, substs)) if def == def_actual => {
|
||||
// If there are any inferred arguments, (`{integer}`), we should replace
|
||||
// them with underscores to allow the compiler to infer them
|
||||
let infer_substs: Vec<GenericArg<'_>> = substs
|
||||
.into_iter()
|
||||
.map(|arg| {
|
||||
if !arg.is_suggestable(tcx, true) {
|
||||
has_unsuggestable_args = true;
|
||||
match arg.unpack() {
|
||||
GenericArgKind::Lifetime(_) => self
|
||||
.next_region_var(RegionVariableOrigin::MiscVariable(
|
||||
rustc_span::DUMMY_SP,
|
||||
))
|
||||
.into(),
|
||||
GenericArgKind::Type(_) => self
|
||||
.next_ty_var(TypeVariableOrigin {
|
||||
span: rustc_span::DUMMY_SP,
|
||||
kind: TypeVariableOriginKind::MiscVariable,
|
||||
})
|
||||
.into(),
|
||||
GenericArgKind::Const(arg) => self
|
||||
.next_const_var(
|
||||
arg.ty(),
|
||||
ConstVariableOrigin {
|
||||
span: rustc_span::DUMMY_SP,
|
||||
kind: ConstVariableOriginKind::MiscVariable,
|
||||
},
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
} else {
|
||||
arg
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
tcx.value_path_str_with_substs(
|
||||
def_actual.did(),
|
||||
tcx.intern_substs(&infer_substs),
|
||||
)
|
||||
}
|
||||
_ => self.ty_to_value_string(ty.peel_refs()),
|
||||
}
|
||||
} else {
|
||||
self.ty_to_value_string(actual.peel_refs())
|
||||
};
|
||||
if let SelfSource::MethodCall(_) = source {
|
||||
let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) &&
|
||||
let Some(assoc) = self.associated_value(*impl_did, item_name) {
|
||||
let sig = self.tcx.fn_sig(assoc.def_id);
|
||||
if let Some(first) = sig.inputs().skip_binder().get(0) {
|
||||
if first.peel_refs() == rcvr_ty.peel_refs() {
|
||||
None
|
||||
} else {
|
||||
Some(if first.is_region_ptr() {
|
||||
if first.is_mutable_ptr() { "&mut " } else { "&" }
|
||||
} else {
|
||||
""
|
||||
})
|
||||
}
|
||||
_ => self.ty_to_value_string(ty.peel_refs()),
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
self.ty_to_value_string(actual.peel_refs())
|
||||
None
|
||||
};
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let args = if let Some((receiver, args)) = args {
|
||||
// The first arg is the same kind as the receiver
|
||||
let explicit_args = if first_arg.is_some() {
|
||||
std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
|
||||
} else {
|
||||
// There is no `Self` kind to infer the arguments from
|
||||
if has_unsuggestable_args {
|
||||
applicability = Applicability::HasPlaceholders;
|
||||
}
|
||||
args.iter().collect()
|
||||
};
|
||||
format!(
|
||||
"({}{})",
|
||||
first_arg.unwrap_or(""),
|
||||
explicit_args
|
||||
.iter()
|
||||
.map(|arg| tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_to_snippet(arg.span)
|
||||
.unwrap_or_else(|_| {
|
||||
applicability = Applicability::HasPlaceholders;
|
||||
"_".to_owned()
|
||||
}))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
)
|
||||
} else {
|
||||
applicability = Applicability::HasPlaceholders;
|
||||
"(...)".to_owned()
|
||||
};
|
||||
if let SelfSource::MethodCall(expr) = source {
|
||||
err.span_suggestion(
|
||||
expr.span.to(span),
|
||||
sugg_span,
|
||||
"use associated function syntax instead",
|
||||
format!("{}::{}", ty_str, item_name),
|
||||
Applicability::MachineApplicable,
|
||||
format!("{}::{}{}", ty_str, item_name, args),
|
||||
applicability,
|
||||
);
|
||||
} else {
|
||||
err.help(&format!("try with `{}::{}`", ty_str, item_name,));
|
||||
|
|
@ -1826,7 +1922,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
/// Print out the type for use in value namespace.
|
||||
fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
|
||||
match ty.kind() {
|
||||
ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did(), substs)),
|
||||
ty::Adt(def, substs) => self.tcx.def_path_str_with_substs(def.did(), substs),
|
||||
_ => self.ty_to_string(ty),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -529,8 +529,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
self.tcx.ty_error()
|
||||
let reported = err.emit();
|
||||
self.tcx.ty_error_with_guaranteed(reported)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -772,7 +772,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
match (method, trait_did) {
|
||||
(Some(ok), _) => {
|
||||
let method = self.register_infer_ok_obligations(ok);
|
||||
self.select_obligations_where_possible(false, |_| {});
|
||||
self.select_obligations_where_possible(|_| {});
|
||||
Ok(method)
|
||||
}
|
||||
(None, None) => Err(vec![]),
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ use rustc_span::lev_distance::find_best_match_for_name;
|
|||
use rustc_span::source_map::{Span, Spanned};
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::{BytePos, DUMMY_SP};
|
||||
use rustc_trait_selection::autoderef::Autoderef;
|
||||
use rustc_trait_selection::traits::{ObligationCause, Pattern};
|
||||
use ty::VariantDef;
|
||||
|
||||
|
|
@ -1278,12 +1277,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let element_tys = tcx.mk_type_list(element_tys_iter);
|
||||
let pat_ty = tcx.mk_ty(ty::Tuple(element_tys));
|
||||
if let Some(mut err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, ti) {
|
||||
err.emit();
|
||||
let reported = err.emit();
|
||||
// Walk subpatterns with an expected type of `err` in this case to silence
|
||||
// further errors being emitted when using the bindings. #50333
|
||||
let element_tys_iter = (0..max_len).map(|_| tcx.ty_error());
|
||||
let element_tys_iter = (0..max_len).map(|_| tcx.ty_error_with_guaranteed(reported));
|
||||
for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
|
||||
self.check_pat(elem, tcx.ty_error(), def_bm, ti);
|
||||
self.check_pat(elem, tcx.ty_error_with_guaranteed(reported), def_bm, ti);
|
||||
}
|
||||
tcx.mk_tup(element_tys_iter)
|
||||
} else {
|
||||
|
|
@ -2132,7 +2131,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
&& let ty::Array(..) | ty::Slice(..) = ty.kind()
|
||||
{
|
||||
err.help("the semantics of slice patterns changed recently; see issue #62254");
|
||||
} else if Autoderef::new(&self.infcx, self.param_env, self.body_id, span, expected_ty, span)
|
||||
} else if self.autoderef(span, expected_ty)
|
||||
.any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
|
||||
&& let (Some(span), true) = (ti.span, ti.origin_expr)
|
||||
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
|
||||
|
|
|
|||
|
|
@ -90,8 +90,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
err.emit();
|
||||
Some((self.tcx.ty_error(), self.tcx.ty_error()))
|
||||
let reported = err.emit();
|
||||
Some((
|
||||
self.tcx.ty_error_with_guaranteed(reported),
|
||||
self.tcx.ty_error_with_guaranteed(reported),
|
||||
))
|
||||
}
|
||||
|
||||
/// To type-check `base_expr[index_expr]`, we progressively autoderef
|
||||
|
|
|
|||
|
|
@ -180,6 +180,18 @@ pub enum SourceKindMultiSuggestion<'a> {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[suggestion(
|
||||
infer_suggest_add_let_for_letchains,
|
||||
style = "verbose",
|
||||
applicability = "machine-applicable",
|
||||
code = "let "
|
||||
)]
|
||||
pub(crate) struct SuggAddLetForLetChains {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'a> SourceKindMultiSuggestion<'a> {
|
||||
pub fn new_fully_qualified(
|
||||
span: Span,
|
||||
|
|
|
|||
|
|
@ -89,10 +89,13 @@ impl<'a> DescriptionCtx<'a> {
|
|||
};
|
||||
me.span = Some(sp);
|
||||
}
|
||||
ty::BrAnon(idx) => {
|
||||
ty::BrAnon(idx, span) => {
|
||||
me.kind = "anon_num_here";
|
||||
me.num_arg = idx+1;
|
||||
me.span = Some(tcx.def_span(scope));
|
||||
me.span = match span {
|
||||
Some(_) => span,
|
||||
None => Some(tcx.def_span(scope)),
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
me.kind = "defined_here_reg";
|
||||
|
|
|
|||
|
|
@ -495,7 +495,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
|
|||
}
|
||||
ty::ConstKind::Bound(debruijn, _) => {
|
||||
if debruijn >= self.binder_index {
|
||||
bug!("escaping bound type during canonicalization")
|
||||
bug!("escaping bound const during canonicalization")
|
||||
} else {
|
||||
return ct;
|
||||
}
|
||||
|
|
@ -738,7 +738,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(var.as_u32()) };
|
||||
let br = ty::BoundRegion { var, kind: ty::BrAnon(var.as_u32(), None) };
|
||||
let region = ty::ReLateBound(self.binder_index, br);
|
||||
self.tcx().mk_region(region)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
// ignore-tidy-filelength
|
||||
//! Error Reporting Code for the inference engine
|
||||
//!
|
||||
//! Because of the way inference, and in particular region inference,
|
||||
|
|
@ -58,12 +59,15 @@ use crate::traits::{
|
|||
StatementAsExpression,
|
||||
};
|
||||
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use crate::errors::SuggAddLetForLetChains;
|
||||
use hir::intravisit::{walk_expr, walk_stmt};
|
||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnosticArg};
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::Node;
|
||||
use rustc_middle::dep_graph::DepContext;
|
||||
|
|
@ -91,6 +95,7 @@ pub mod nice_region_error;
|
|||
pub struct TypeErrCtxt<'a, 'tcx> {
|
||||
pub infcx: &'a InferCtxt<'tcx>,
|
||||
pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
|
||||
pub fallback_has_occurred: bool,
|
||||
}
|
||||
|
||||
impl TypeErrCtxt<'_, '_> {
|
||||
|
|
@ -206,9 +211,12 @@ fn msg_span_from_early_bound_and_free_regions<'tcx>(
|
|||
};
|
||||
(text, sp)
|
||||
}
|
||||
ty::BrAnon(idx) => (
|
||||
ty::BrAnon(idx, span) => (
|
||||
format!("the anonymous lifetime #{} defined here", idx + 1),
|
||||
tcx.def_span(scope)
|
||||
match span {
|
||||
Some(span) => span,
|
||||
None => tcx.def_span(scope)
|
||||
}
|
||||
),
|
||||
_ => (
|
||||
format!("the lifetime `{}` as defined here", region),
|
||||
|
|
@ -1498,9 +1506,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
values = None;
|
||||
}
|
||||
struct OpaqueTypesVisitor<'tcx> {
|
||||
types: FxHashMap<TyCategory, FxHashSet<Span>>,
|
||||
expected: FxHashMap<TyCategory, FxHashSet<Span>>,
|
||||
found: FxHashMap<TyCategory, FxHashSet<Span>>,
|
||||
types: FxIndexMap<TyCategory, FxIndexSet<Span>>,
|
||||
expected: FxIndexMap<TyCategory, FxIndexSet<Span>>,
|
||||
found: FxIndexMap<TyCategory, FxIndexSet<Span>>,
|
||||
ignore_span: Span,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
}
|
||||
|
|
@ -1538,7 +1546,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
&self,
|
||||
err: &mut Diagnostic,
|
||||
target: &str,
|
||||
types: &FxHashMap<TyCategory, FxHashSet<Span>>,
|
||||
types: &FxIndexMap<TyCategory, FxIndexSet<Span>>,
|
||||
) {
|
||||
for (key, values) in types.iter() {
|
||||
let count = values.len();
|
||||
|
|
@ -2332,6 +2340,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
// For code `if Some(..) = expr `, the type mismatch may be expected `bool` but found `()`,
|
||||
// we try to suggest to add the missing `let` for `if let Some(..) = expr`
|
||||
(ty::Bool, ty::Tuple(list)) => if list.len() == 0 {
|
||||
self.suggest_let_for_letchains(&mut err, &trace.cause, span);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -2356,6 +2369,67 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
diag
|
||||
}
|
||||
|
||||
/// Try to find code with pattern `if Some(..) = expr`
|
||||
/// use a `visitor` to mark the `if` which its span contains given error span,
|
||||
/// and then try to find a assignment in the `cond` part, which span is equal with error span
|
||||
fn suggest_let_for_letchains(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
cause: &ObligationCause<'_>,
|
||||
span: Span,
|
||||
) {
|
||||
let hir = self.tcx.hir();
|
||||
let fn_hir_id = hir.get_parent_node(cause.body_id);
|
||||
if let Some(node) = self.tcx.hir().find(fn_hir_id) &&
|
||||
let hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Fn(_sig, _, body_id), ..
|
||||
}) = node {
|
||||
let body = hir.body(*body_id);
|
||||
|
||||
/// Find the if expression with given span
|
||||
struct IfVisitor {
|
||||
pub result: bool,
|
||||
pub found_if: bool,
|
||||
pub err_span: Span,
|
||||
}
|
||||
|
||||
impl<'v> Visitor<'v> for IfVisitor {
|
||||
fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
|
||||
if self.result { return; }
|
||||
match ex.kind {
|
||||
hir::ExprKind::If(cond, _, _) => {
|
||||
self.found_if = true;
|
||||
walk_expr(self, cond);
|
||||
self.found_if = false;
|
||||
}
|
||||
_ => walk_expr(self, ex),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
|
||||
if let hir::StmtKind::Local(hir::Local {
|
||||
span, pat: hir::Pat{..}, ty: None, init: Some(_), ..
|
||||
}) = &ex.kind
|
||||
&& self.found_if
|
||||
&& span.eq(&self.err_span) {
|
||||
self.result = true;
|
||||
}
|
||||
walk_stmt(self, ex);
|
||||
}
|
||||
|
||||
fn visit_body(&mut self, body: &'v hir::Body<'v>) {
|
||||
hir::intravisit::walk_body(self, body);
|
||||
}
|
||||
}
|
||||
|
||||
let mut visitor = IfVisitor { err_span: span, found_if: false, result: false };
|
||||
visitor.visit_body(&body);
|
||||
if visitor.result {
|
||||
err.subdiagnostic(SuggAddLetForLetChains{span: span.shrink_to_lo()});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_tuple_wrap_err(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
|
|
@ -3254,7 +3328,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
if blk.expr.is_some() {
|
||||
return false;
|
||||
}
|
||||
let mut shadowed = FxHashSet::default();
|
||||
let mut shadowed = FxIndexSet::default();
|
||||
let mut candidate_idents = vec![];
|
||||
let mut find_compatible_candidates = |pat: &hir::Pat<'_>| {
|
||||
if let hir::PatKind::Binding(_, hir_id, ident, _) = &pat.kind
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
|||
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
||||
use crate::infer::{SubregionOrigin, TypeTrace};
|
||||
use crate::traits::ObligationCauseCode;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_errors::{ErrorGuaranteed, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
|
|
@ -73,7 +73,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
|
||||
// Next, let's figure out the set of trait objects with implicit static bounds
|
||||
let ty = self.tcx().type_of(*impl_def_id);
|
||||
let mut v = super::static_impl_trait::TraitObjectVisitor(FxHashSet::default());
|
||||
let mut v = super::static_impl_trait::TraitObjectVisitor(FxIndexSet::default());
|
||||
v.visit_ty(ty);
|
||||
let mut traits = vec![];
|
||||
for matching_def_id in v.0 {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ pub mod find_anon_type;
|
|||
mod mismatched_static_lifetime;
|
||||
mod named_anon_conflict;
|
||||
mod placeholder_error;
|
||||
mod placeholder_relation;
|
||||
mod static_impl_trait;
|
||||
mod trait_impl_difference;
|
||||
mod util;
|
||||
|
|
@ -52,7 +53,9 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
|
|||
pub fn try_report_from_nll(&self) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
// Due to the improved diagnostics returned by the MIR borrow checker, only a subset of
|
||||
// the nice region errors are required when running under the MIR borrow checker.
|
||||
self.try_report_named_anon_conflict().or_else(|| self.try_report_placeholder_conflict())
|
||||
self.try_report_named_anon_conflict()
|
||||
.or_else(|| self.try_report_placeholder_conflict())
|
||||
.or_else(|| self.try_report_placeholder_relation())
|
||||
}
|
||||
|
||||
pub fn try_report(&self) -> Option<ErrorGuaranteed> {
|
||||
|
|
|
|||
|
|
@ -68,7 +68,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");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
use crate::infer::{
|
||||
error_reporting::nice_region_error::NiceRegionError, RegionResolutionError, SubregionOrigin,
|
||||
};
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_middle::ty::{self, RePlaceholder, Region};
|
||||
|
||||
impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||
/// Emitted wwhen given a `ConcreteFailure` when relating two placeholders.
|
||||
pub(super) fn try_report_placeholder_relation(
|
||||
&self,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
match &self.error {
|
||||
Some(RegionResolutionError::ConcreteFailure(
|
||||
SubregionOrigin::RelateRegionParamBound(span),
|
||||
Region(Interned(RePlaceholder(ty::Placeholder { name: sub_name, .. }), _)),
|
||||
Region(Interned(RePlaceholder(ty::Placeholder { name: sup_name, .. }), _)),
|
||||
)) => {
|
||||
let msg = "lifetime bound not satisfied";
|
||||
let mut err = self.tcx().sess.struct_span_err(*span, msg);
|
||||
let (sub_span, sub_symbol) = match sub_name {
|
||||
ty::BrNamed(def_id, symbol) => {
|
||||
(Some(self.tcx().def_span(def_id)), Some(symbol))
|
||||
}
|
||||
ty::BrAnon(_, span) => (*span, None),
|
||||
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),
|
||||
};
|
||||
match (sub_span, sup_span, sub_symbol, sup_symbol) {
|
||||
(Some(sub_span), Some(sup_span), Some(sub_symbol), Some(sup_symbol)) => {
|
||||
err.span_note(
|
||||
sub_span,
|
||||
format!("the lifetime `{sub_symbol}` defined here..."),
|
||||
);
|
||||
err.span_note(
|
||||
sup_span,
|
||||
format!("...must outlive the lifetime `{sup_symbol}` defined here"),
|
||||
);
|
||||
}
|
||||
(Some(sub_span), Some(sup_span), _, Some(sup_symbol)) => {
|
||||
err.span_note(sub_span, format!("the lifetime defined here..."));
|
||||
err.span_note(
|
||||
sup_span,
|
||||
format!("...must outlive the lifetime `{sup_symbol}` defined here"),
|
||||
);
|
||||
}
|
||||
(Some(sub_span), Some(sup_span), Some(sub_symbol), _) => {
|
||||
err.span_note(
|
||||
sub_span,
|
||||
format!("the lifetime `{sub_symbol}` defined here..."),
|
||||
);
|
||||
err.span_note(
|
||||
sup_span,
|
||||
format!("...must outlive the lifetime defined here"),
|
||||
);
|
||||
}
|
||||
(Some(sub_span), Some(sup_span), _, _) => {
|
||||
err.span_note(sub_span, format!("the lifetime defined here..."));
|
||||
err.span_note(
|
||||
sup_span,
|
||||
format!("...must outlive the lifetime defined here"),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
err.note("this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)");
|
||||
Some(err)
|
||||
}
|
||||
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
|||
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
||||
use crate::infer::{SubregionOrigin, TypeTrace};
|
||||
use crate::traits::{ObligationCauseCode, UnifyReceiverContext};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::{walk_ty, Visitor};
|
||||
|
|
@ -236,7 +236,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
// Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static`
|
||||
// lifetime as above, but called using a fully-qualified path to the method:
|
||||
// `Foo::qux(bar)`.
|
||||
let mut v = TraitObjectVisitor(FxHashSet::default());
|
||||
let mut v = TraitObjectVisitor(FxIndexSet::default());
|
||||
v.visit_ty(param.param_ty);
|
||||
if let Some((ident, self_ty)) =
|
||||
self.get_impl_ident_and_self_ty_from_trait(item_def_id, &v.0)
|
||||
|
|
@ -408,7 +408,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
fn get_impl_ident_and_self_ty_from_trait(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
trait_objects: &FxHashSet<DefId>,
|
||||
trait_objects: &FxIndexSet<DefId>,
|
||||
) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> {
|
||||
let tcx = self.tcx();
|
||||
match tcx.hir().get_if_local(def_id) {
|
||||
|
|
@ -490,7 +490,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
return false;
|
||||
};
|
||||
|
||||
let mut v = TraitObjectVisitor(FxHashSet::default());
|
||||
let mut v = TraitObjectVisitor(FxIndexSet::default());
|
||||
v.visit_ty(ty);
|
||||
|
||||
// Get the `Ident` of the method being called and the corresponding `impl` (to point at
|
||||
|
|
@ -506,7 +506,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
fn suggest_constrain_dyn_trait_in_impl(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
found_dids: &FxHashSet<DefId>,
|
||||
found_dids: &FxIndexSet<DefId>,
|
||||
ident: Ident,
|
||||
self_ty: &hir::Ty<'_>,
|
||||
) -> bool {
|
||||
|
|
@ -538,7 +538,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
}
|
||||
|
||||
/// Collect all the trait objects in a type that could have received an implicit `'static` lifetime.
|
||||
pub struct TraitObjectVisitor(pub FxHashSet<DefId>);
|
||||
pub struct TraitObjectVisitor(pub FxIndexSet<DefId>);
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
|
|
|
|||
|
|
@ -149,6 +149,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
region: ty::BoundRegionKind,
|
||||
) -> bool {
|
||||
let late_bound_regions = self.tcx().collect_referenced_late_bound_regions(&ty);
|
||||
// We are only checking is any region meets the condition so order doesn't matter
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
late_bound_regions.iter().any(|r| *r == region)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -842,6 +842,9 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
|||
// are placeholders as upper bounds, but the universe of the
|
||||
// variable `'a`, or some variable that `'a` has to outlive, doesn't
|
||||
// permit those placeholders.
|
||||
//
|
||||
// We only iterate to find the min, which means it doesn't cause reproducibility issues
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
let min_universe = lower_vid_bounds
|
||||
.into_iter()
|
||||
.map(|vid| self.var_infos[vid].universe)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog};
|
|||
|
||||
use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine, TraitEngineExt};
|
||||
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::undo_log::Rollback;
|
||||
|
|
@ -294,7 +295,7 @@ pub struct InferCtxt<'tcx> {
|
|||
|
||||
/// the set of predicates on which errors have been reported, to
|
||||
/// avoid reporting the same error twice.
|
||||
pub reported_trait_errors: RefCell<FxHashMap<Span, Vec<ty::Predicate<'tcx>>>>,
|
||||
pub reported_trait_errors: RefCell<FxIndexMap<Span, Vec<ty::Predicate<'tcx>>>>,
|
||||
|
||||
pub reported_closure_mismatch: RefCell<FxHashSet<(Span, Option<Span>)>>,
|
||||
|
||||
|
|
@ -677,9 +678,9 @@ pub struct CombinedSnapshot<'tcx> {
|
|||
|
||||
impl<'tcx> InferCtxt<'tcx> {
|
||||
/// Creates a `TypeErrCtxt` for emitting various inference errors.
|
||||
/// During typeck, use `FnCtxt::infer_err` instead.
|
||||
/// During typeck, use `FnCtxt::err_ctxt` instead.
|
||||
pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {
|
||||
TypeErrCtxt { infcx: self, typeck_results: None }
|
||||
TypeErrCtxt { infcx: self, typeck_results: None, fallback_has_occurred: false }
|
||||
}
|
||||
|
||||
/// calls `tcx.try_unify_abstract_consts` after
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use super::*;
|
||||
use crate::infer::CombinedSnapshot;
|
||||
use rustc_data_structures::{
|
||||
fx::FxIndexMap,
|
||||
graph::{scc::Sccs, vec_graph::VecGraph},
|
||||
undo_log::UndoLogs,
|
||||
};
|
||||
|
|
@ -371,7 +372,7 @@ rustc_index::newtype_index! {
|
|||
/// an edge `R1 -> R2` in the graph.
|
||||
struct MiniGraph<'tcx> {
|
||||
/// Map from a region to the index of the node in the graph.
|
||||
nodes: FxHashMap<ty::Region<'tcx>, LeakCheckNode>,
|
||||
nodes: FxIndexMap<ty::Region<'tcx>, LeakCheckNode>,
|
||||
|
||||
/// Map from node index to SCC, and stores the successors of each SCC. All
|
||||
/// the regions in the same SCC are equal to one another, and if `S1 -> S2`,
|
||||
|
|
@ -388,7 +389,7 @@ impl<'tcx> MiniGraph<'tcx> {
|
|||
where
|
||||
'tcx: 'a,
|
||||
{
|
||||
let mut nodes = FxHashMap::default();
|
||||
let mut nodes = FxIndexMap::default();
|
||||
let mut edges = Vec::new();
|
||||
|
||||
// Note that if `R2: R1`, we get a callback `r1, r2`, so `target` is first parameter.
|
||||
|
|
@ -438,7 +439,7 @@ impl<'tcx> MiniGraph<'tcx> {
|
|||
}
|
||||
|
||||
fn add_node(
|
||||
nodes: &mut FxHashMap<ty::Region<'tcx>, LeakCheckNode>,
|
||||
nodes: &mut FxIndexMap<ty::Region<'tcx>, LeakCheckNode>,
|
||||
r: ty::Region<'tcx>,
|
||||
) -> LeakCheckNode {
|
||||
let l = nodes.len();
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use super::{
|
|||
InferCtxtUndoLogs, MiscVariable, RegionVariableOrigin, Rollback, Snapshot, SubregionOrigin,
|
||||
};
|
||||
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::undo_log::UndoLogs;
|
||||
|
|
@ -125,7 +125,7 @@ pub struct RegionConstraintData<'tcx> {
|
|||
/// we record the fact that `'a <= 'b` is implied by the fn
|
||||
/// signature, and then ignore the constraint when solving
|
||||
/// equations. This is a bit of a hack but seems to work.
|
||||
pub givens: FxHashSet<(Region<'tcx>, ty::RegionVid)>,
|
||||
pub givens: FxIndexSet<(Region<'tcx>, ty::RegionVid)>,
|
||||
}
|
||||
|
||||
/// Represents a constraint that influences the inference process.
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
//!
|
||||
//! This API is completely unstable and subject to change.
|
||||
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(control_flow_enum)]
|
||||
|
|
|
|||
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