Merge from rustc
This commit is contained in:
commit
af5f4be160
520 changed files with 5024 additions and 5651 deletions
44
Cargo.lock
44
Cargo.lock
|
|
@ -8,7 +8,7 @@ version = "0.24.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
"gimli 0.31.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1483,6 +1483,17 @@ dependencies = [
|
|||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93563d740bc9ef04104f9ed6f86f1e3275c2cdafb95664e26584b9ca807a8ffe"
|
||||
dependencies = [
|
||||
"fallible-iterator",
|
||||
"indexmap",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.2"
|
||||
|
|
@ -2568,7 +2579,7 @@ dependencies = [
|
|||
"hashbrown",
|
||||
"indexmap",
|
||||
"memchr",
|
||||
"ruzstd",
|
||||
"ruzstd 0.7.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2578,9 +2589,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "03fd943161069e1768b4b3d050890ba48730e590f57e56d4aa04e7e090e61b4a"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"flate2",
|
||||
"hashbrown",
|
||||
"indexmap",
|
||||
"memchr",
|
||||
"ruzstd 0.8.1",
|
||||
"wasmparser 0.234.0",
|
||||
]
|
||||
|
||||
|
|
@ -3194,9 +3207,9 @@ version = "0.2.0"
|
|||
dependencies = [
|
||||
"bstr",
|
||||
"build_helper",
|
||||
"gimli",
|
||||
"gimli 0.32.0",
|
||||
"libc",
|
||||
"object 0.36.7",
|
||||
"object 0.37.1",
|
||||
"regex",
|
||||
"serde_json",
|
||||
"similar",
|
||||
|
|
@ -3498,7 +3511,7 @@ name = "rustc_codegen_llvm"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"gimli",
|
||||
"gimli 0.31.1",
|
||||
"itertools",
|
||||
"libc",
|
||||
"measureme",
|
||||
|
|
@ -4473,7 +4486,7 @@ dependencies = [
|
|||
"rustc_target",
|
||||
"rustc_trait_selection",
|
||||
"tracing",
|
||||
"twox-hash",
|
||||
"twox-hash 1.6.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4857,7 +4870,16 @@ version = "0.7.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fad02996bfc73da3e301efe90b1837be9ed8f4a462b6ed410aa35d00381de89f"
|
||||
dependencies = [
|
||||
"twox-hash",
|
||||
"twox-hash 1.6.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruzstd"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3640bec8aad418d7d03c72ea2de10d5c646a598f9883c7babc160d91e3c1b26c"
|
||||
dependencies = [
|
||||
"twox-hash 2.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -5338,7 +5360,7 @@ version = "0.9.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e9c1e705f82a260173f3eec93f2ff6d7807f23ad5a8cc2e7316a891733ea7a1"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
"gimli 0.31.1",
|
||||
"hashbrown",
|
||||
"object 0.36.7",
|
||||
"tracing",
|
||||
|
|
@ -5580,6 +5602,12 @@ dependencies = [
|
|||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "twox-hash"
|
||||
version = "2.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b907da542cbced5261bd3256de1b3a1bf340a3d37f93425a07362a1d687de56"
|
||||
|
||||
[[package]]
|
||||
name = "type-map"
|
||||
version = "0.5.1"
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
//! - [`UnOp`], [`BinOp`], and [`BinOpKind`]: Unary and binary operators.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::sync::Arc;
|
||||
use std::{cmp, fmt};
|
||||
|
||||
pub use GenericArgs::*;
|
||||
|
|
@ -32,7 +31,7 @@ use rustc_data_structures::tagged_ptr::Tag;
|
|||
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
|
||||
pub use rustc_span::AttrId;
|
||||
use rustc_span::source_map::{Spanned, respan};
|
||||
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
|
||||
use rustc_span::{ByteSymbol, DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
|
||||
pub use crate::format::*;
|
||||
|
|
@ -1805,10 +1804,17 @@ pub enum ExprKind {
|
|||
Become(P<Expr>),
|
||||
|
||||
/// Bytes included via `include_bytes!`
|
||||
///
|
||||
/// Added for optimization purposes to avoid the need to escape
|
||||
/// large binary blobs - should always behave like [`ExprKind::Lit`]
|
||||
/// with a `ByteStr` literal.
|
||||
IncludedBytes(Arc<[u8]>),
|
||||
///
|
||||
/// The value is stored as a `ByteSymbol`. It's unfortunate that we need to
|
||||
/// intern (hash) the bytes because they're likely to be large and unique.
|
||||
/// But it's necessary because this will eventually be lowered to
|
||||
/// `LitKind::ByteStr`, which needs a `ByteSymbol` to impl `Copy` and avoid
|
||||
/// arena allocation.
|
||||
IncludedBytes(ByteSymbol),
|
||||
|
||||
/// A `format_args!()` expression.
|
||||
FormatArgs(P<FormatArgs>),
|
||||
|
|
@ -2066,7 +2072,7 @@ impl YieldKind {
|
|||
}
|
||||
|
||||
/// A literal in a meta item.
|
||||
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
#[derive(Clone, Copy, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
pub struct MetaItemLit {
|
||||
/// The original literal as written in the source code.
|
||||
pub symbol: Symbol,
|
||||
|
|
@ -2129,16 +2135,18 @@ pub enum LitFloatType {
|
|||
/// deciding the `LitKind`. This means that float literals like `1f32` are
|
||||
/// classified by this type as `Float`. This is different to `token::LitKind`
|
||||
/// which does *not* consider the suffix.
|
||||
#[derive(Clone, Encodable, Decodable, Debug, Hash, Eq, PartialEq, HashStable_Generic)]
|
||||
#[derive(Clone, Copy, Encodable, Decodable, Debug, Hash, Eq, PartialEq, HashStable_Generic)]
|
||||
pub enum LitKind {
|
||||
/// A string literal (`"foo"`). The symbol is unescaped, and so may differ
|
||||
/// from the original token's symbol.
|
||||
Str(Symbol, StrStyle),
|
||||
/// A byte string (`b"foo"`). Not stored as a symbol because it might be
|
||||
/// non-utf8, and symbols only allow utf8 strings.
|
||||
ByteStr(Arc<[u8]>, StrStyle),
|
||||
/// A C String (`c"foo"`). Guaranteed to only have `\0` at the end.
|
||||
CStr(Arc<[u8]>, StrStyle),
|
||||
/// A byte string (`b"foo"`). The symbol is unescaped, and so may differ
|
||||
/// from the original token's symbol.
|
||||
ByteStr(ByteSymbol, StrStyle),
|
||||
/// A C String (`c"foo"`). Guaranteed to only have `\0` at the end. The
|
||||
/// symbol is unescaped, and so may differ from the original token's
|
||||
/// symbol.
|
||||
CStr(ByteSymbol, StrStyle),
|
||||
/// A byte char (`b'f'`).
|
||||
Byte(u8),
|
||||
/// A character literal (`'a'`).
|
||||
|
|
@ -2577,8 +2585,7 @@ pub enum TyPatKind {
|
|||
pub enum TraitObjectSyntax {
|
||||
// SAFETY: When adding new variants make sure to update the `Tag` impl.
|
||||
Dyn = 0,
|
||||
DynStar = 1,
|
||||
None = 2,
|
||||
None = 1,
|
||||
}
|
||||
|
||||
/// SAFETY: `TraitObjectSyntax` only has 3 data-less variants which means
|
||||
|
|
@ -2594,8 +2601,7 @@ unsafe impl Tag for TraitObjectSyntax {
|
|||
unsafe fn from_usize(tag: usize) -> Self {
|
||||
match tag {
|
||||
0 => TraitObjectSyntax::Dyn,
|
||||
1 => TraitObjectSyntax::DynStar,
|
||||
2 => TraitObjectSyntax::None,
|
||||
1 => TraitObjectSyntax::None,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use std::{ascii, fmt, str};
|
|||
use rustc_literal_escaper::{
|
||||
MixedUnit, unescape_byte, unescape_byte_str, unescape_c_str, unescape_char, unescape_str,
|
||||
};
|
||||
use rustc_span::{Span, Symbol, kw, sym};
|
||||
use rustc_span::{ByteSymbol, Span, Symbol, kw, sym};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::ast::{self, LitKind, MetaItemLit, StrStyle};
|
||||
|
|
@ -116,13 +116,12 @@ impl LitKind {
|
|||
assert!(!err.is_fatal(), "failed to unescape string literal")
|
||||
}
|
||||
});
|
||||
LitKind::ByteStr(buf.into(), StrStyle::Cooked)
|
||||
LitKind::ByteStr(ByteSymbol::intern(&buf), StrStyle::Cooked)
|
||||
}
|
||||
token::ByteStrRaw(n) => {
|
||||
// Raw strings have no escapes so we can convert the symbol
|
||||
// directly to a `Arc<u8>`.
|
||||
// Raw byte strings have no escapes so no work is needed here.
|
||||
let buf = symbol.as_str().to_owned().into_bytes();
|
||||
LitKind::ByteStr(buf.into(), StrStyle::Raw(n))
|
||||
LitKind::ByteStr(ByteSymbol::intern(&buf), StrStyle::Raw(n))
|
||||
}
|
||||
token::CStr => {
|
||||
let s = symbol.as_str();
|
||||
|
|
@ -137,7 +136,7 @@ impl LitKind {
|
|||
}
|
||||
});
|
||||
buf.push(0);
|
||||
LitKind::CStr(buf.into(), StrStyle::Cooked)
|
||||
LitKind::CStr(ByteSymbol::intern(&buf), StrStyle::Cooked)
|
||||
}
|
||||
token::CStrRaw(n) => {
|
||||
// Raw strings have no escapes so we can convert the symbol
|
||||
|
|
@ -145,7 +144,7 @@ impl LitKind {
|
|||
// char.
|
||||
let mut buf = symbol.as_str().to_owned().into_bytes();
|
||||
buf.push(0);
|
||||
LitKind::CStr(buf.into(), StrStyle::Raw(n))
|
||||
LitKind::CStr(ByteSymbol::intern(&buf), StrStyle::Raw(n))
|
||||
}
|
||||
token::Err(guar) => LitKind::Err(guar),
|
||||
})
|
||||
|
|
@ -167,12 +166,12 @@ impl fmt::Display for LitKind {
|
|||
delim = "#".repeat(n as usize),
|
||||
string = sym
|
||||
)?,
|
||||
LitKind::ByteStr(ref bytes, StrStyle::Cooked) => {
|
||||
write!(f, "b\"{}\"", escape_byte_str_symbol(bytes))?
|
||||
LitKind::ByteStr(ref byte_sym, StrStyle::Cooked) => {
|
||||
write!(f, "b\"{}\"", escape_byte_str_symbol(byte_sym.as_byte_str()))?
|
||||
}
|
||||
LitKind::ByteStr(ref bytes, StrStyle::Raw(n)) => {
|
||||
LitKind::ByteStr(ref byte_sym, StrStyle::Raw(n)) => {
|
||||
// Unwrap because raw byte string literals can only contain ASCII.
|
||||
let symbol = str::from_utf8(bytes).unwrap();
|
||||
let symbol = str::from_utf8(byte_sym.as_byte_str()).unwrap();
|
||||
write!(
|
||||
f,
|
||||
"br{delim}\"{string}\"{delim}",
|
||||
|
|
@ -181,11 +180,11 @@ impl fmt::Display for LitKind {
|
|||
)?;
|
||||
}
|
||||
LitKind::CStr(ref bytes, StrStyle::Cooked) => {
|
||||
write!(f, "c\"{}\"", escape_byte_str_symbol(bytes))?
|
||||
write!(f, "c\"{}\"", escape_byte_str_symbol(bytes.as_byte_str()))?
|
||||
}
|
||||
LitKind::CStr(ref bytes, StrStyle::Raw(n)) => {
|
||||
// This can only be valid UTF-8.
|
||||
let symbol = str::from_utf8(bytes).unwrap();
|
||||
let symbol = str::from_utf8(bytes.as_byte_str()).unwrap();
|
||||
write!(f, "cr{delim}\"{symbol}\"{delim}", delim = "#".repeat(n as usize),)?;
|
||||
}
|
||||
LitKind::Int(n, ty) => {
|
||||
|
|
|
|||
|
|
@ -144,11 +144,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
hir::ExprKind::Unary(op, ohs)
|
||||
}
|
||||
ExprKind::Lit(token_lit) => hir::ExprKind::Lit(self.lower_lit(token_lit, e.span)),
|
||||
ExprKind::IncludedBytes(bytes) => {
|
||||
let lit = self.arena.alloc(respan(
|
||||
ExprKind::IncludedBytes(byte_sym) => {
|
||||
let lit = respan(
|
||||
self.lower_span(e.span),
|
||||
LitKind::ByteStr(Arc::clone(bytes), StrStyle::Cooked),
|
||||
));
|
||||
LitKind::ByteStr(*byte_sym, StrStyle::Cooked),
|
||||
);
|
||||
hir::ExprKind::Lit(lit)
|
||||
}
|
||||
ExprKind::Cast(expr, ty) => {
|
||||
|
|
@ -421,11 +421,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn lower_lit(
|
||||
&mut self,
|
||||
token_lit: &token::Lit,
|
||||
span: Span,
|
||||
) -> &'hir Spanned<LitKind> {
|
||||
pub(crate) fn lower_lit(&mut self, token_lit: &token::Lit, span: Span) -> hir::Lit {
|
||||
let lit_kind = match LitKind::from_token_lit(*token_lit) {
|
||||
Ok(lit_kind) => lit_kind,
|
||||
Err(err) => {
|
||||
|
|
@ -433,7 +429,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
LitKind::Err(guar)
|
||||
}
|
||||
};
|
||||
self.arena.alloc(respan(self.lower_span(span), lit_kind))
|
||||
respan(self.lower_span(span), lit_kind)
|
||||
}
|
||||
|
||||
fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {
|
||||
|
|
@ -2141,10 +2137,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
|
||||
fn expr_uint(&mut self, sp: Span, ty: ast::UintTy, value: u128) -> hir::Expr<'hir> {
|
||||
let lit = self.arena.alloc(hir::Lit {
|
||||
let lit = hir::Lit {
|
||||
span: sp,
|
||||
node: ast::LitKind::Int(value.into(), ast::LitIntType::Unsigned(ty)),
|
||||
});
|
||||
};
|
||||
self.expr(sp, hir::ExprKind::Lit(lit))
|
||||
}
|
||||
|
||||
|
|
@ -2161,9 +2157,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
|
||||
pub(super) fn expr_str(&mut self, sp: Span, value: Symbol) -> hir::Expr<'hir> {
|
||||
let lit = self
|
||||
.arena
|
||||
.alloc(hir::Lit { span: sp, node: ast::LitKind::Str(value, ast::StrStyle::Cooked) });
|
||||
let lit = hir::Lit { span: sp, node: ast::LitKind::Str(value, ast::StrStyle::Cooked) };
|
||||
self.expr(sp, hir::ExprKind::Lit(lit))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -390,19 +390,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
allow_paths: bool,
|
||||
) -> &'hir hir::PatExpr<'hir> {
|
||||
let span = self.lower_span(expr.span);
|
||||
let err = |guar| hir::PatExprKind::Lit {
|
||||
lit: self.arena.alloc(respan(span, LitKind::Err(guar))),
|
||||
negated: false,
|
||||
};
|
||||
let err =
|
||||
|guar| hir::PatExprKind::Lit { lit: respan(span, LitKind::Err(guar)), negated: false };
|
||||
let kind = match &expr.kind {
|
||||
ExprKind::Lit(lit) => {
|
||||
hir::PatExprKind::Lit { lit: self.lower_lit(lit, span), negated: false }
|
||||
}
|
||||
ExprKind::ConstBlock(c) => hir::PatExprKind::ConstBlock(self.lower_const_block(c)),
|
||||
ExprKind::IncludedBytes(bytes) => hir::PatExprKind::Lit {
|
||||
lit: self
|
||||
.arena
|
||||
.alloc(respan(span, LitKind::ByteStr(Arc::clone(bytes), StrStyle::Cooked))),
|
||||
ExprKind::IncludedBytes(byte_sym) => hir::PatExprKind::Lit {
|
||||
lit: respan(span, LitKind::ByteStr(*byte_sym, StrStyle::Cooked)),
|
||||
negated: false,
|
||||
},
|
||||
ExprKind::Err(guar) => err(*guar),
|
||||
|
|
|
|||
|
|
@ -504,7 +504,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
);
|
||||
gate_all!(associated_const_equality, "associated const equality is incomplete");
|
||||
gate_all!(yeet_expr, "`do yeet` expression is experimental");
|
||||
gate_all!(dyn_star, "`dyn*` trait objects are experimental");
|
||||
gate_all!(const_closures, "const closures are experimental");
|
||||
gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
|
||||
gate_all!(ergonomic_clones, "ergonomic clones are experimental");
|
||||
|
|
|
|||
|
|
@ -1303,7 +1303,6 @@ impl<'a> State<'a> {
|
|||
ast::TyKind::TraitObject(bounds, syntax) => {
|
||||
match syntax {
|
||||
ast::TraitObjectSyntax::Dyn => self.word_nbsp("dyn"),
|
||||
ast::TraitObjectSyntax::DynStar => self.word_nbsp("dyn*"),
|
||||
ast::TraitObjectSyntax::None => {}
|
||||
}
|
||||
self.print_type_bounds(bounds);
|
||||
|
|
|
|||
|
|
@ -469,8 +469,12 @@ impl<'a> State<'a> {
|
|||
ast::ExprKind::Lit(token_lit) => {
|
||||
self.print_token_literal(*token_lit, expr.span);
|
||||
}
|
||||
ast::ExprKind::IncludedBytes(bytes) => {
|
||||
let lit = token::Lit::new(token::ByteStr, escape_byte_str_symbol(bytes), None);
|
||||
ast::ExprKind::IncludedBytes(byte_sym) => {
|
||||
let lit = token::Lit::new(
|
||||
token::ByteStr,
|
||||
escape_byte_str_symbol(byte_sym.as_byte_str()),
|
||||
None,
|
||||
);
|
||||
self.print_token_literal(lit, expr.span)
|
||||
}
|
||||
ast::ExprKind::Cast(expr, ty) => {
|
||||
|
|
|
|||
|
|
@ -290,6 +290,15 @@ pub enum AttributeKind {
|
|||
/// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
|
||||
Repr(ThinVec<(ReprAttr, Span)>),
|
||||
|
||||
/// Represents `#[rustc_layout_scalar_valid_range_end]`.
|
||||
RustcLayoutScalarValidRangeEnd(Box<u128>, Span),
|
||||
|
||||
/// Represents `#[rustc_layout_scalar_valid_range_start]`.
|
||||
RustcLayoutScalarValidRangeStart(Box<u128>, Span),
|
||||
|
||||
/// Represents `#[rustc_object_lifetime_default]`.
|
||||
RustcObjectLifetimeDefault,
|
||||
|
||||
/// Represents `#[rustc_skip_during_method_dispatch]`.
|
||||
SkipDuringMethodDispatch { array: bool, boxed_slice: bool, span: Span },
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@ impl AttributeKind {
|
|||
NoMangle(..) => No,
|
||||
Optimize(..) => No,
|
||||
PubTransparent(..) => Yes,
|
||||
RustcLayoutScalarValidRangeEnd(..) => Yes,
|
||||
RustcLayoutScalarValidRangeStart(..) => Yes,
|
||||
RustcObjectLifetimeDefault => No,
|
||||
SkipDuringMethodDispatch { .. } => No,
|
||||
TrackCaller(..) => Yes,
|
||||
Used { .. } => No,
|
||||
|
|
|
|||
|
|
@ -49,6 +49,16 @@ pub trait PrintAttribute {
|
|||
fn print_attribute(&self, p: &mut Printer);
|
||||
}
|
||||
|
||||
impl PrintAttribute for u128 {
|
||||
fn should_render(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn print_attribute(&self, p: &mut Printer) {
|
||||
p.word(self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PrintAttribute> PrintAttribute for &T {
|
||||
fn should_render(&self) -> bool {
|
||||
T::should_render(self)
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ pub(crate) mod lint_helpers;
|
|||
pub(crate) mod loop_match;
|
||||
pub(crate) mod must_use;
|
||||
pub(crate) mod repr;
|
||||
pub(crate) mod rustc_internal;
|
||||
pub(crate) mod semantics;
|
||||
pub(crate) mod stability;
|
||||
pub(crate) mod traits;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,16 @@ impl<S: Stage> SingleAttributeParser<S> for MustUseParser {
|
|||
span: cx.attr_span,
|
||||
reason: match args {
|
||||
ArgParser::NoArgs => None,
|
||||
ArgParser::NameValue(name_value) => name_value.value_as_str(),
|
||||
ArgParser::NameValue(name_value) => {
|
||||
let Some(value_str) = name_value.value_as_str() else {
|
||||
cx.expected_string_literal(
|
||||
name_value.value_span,
|
||||
Some(&name_value.value_as_lit()),
|
||||
);
|
||||
return None;
|
||||
};
|
||||
Some(value_str)
|
||||
}
|
||||
ArgParser::List(_) => {
|
||||
let suggestions =
|
||||
<Self as SingleAttributeParser<S>>::TEMPLATE.suggestions(false, "must_use");
|
||||
|
|
|
|||
77
compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs
Normal file
77
compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
use rustc_ast::LitKind;
|
||||
use rustc_attr_data_structures::AttributeKind;
|
||||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_span::{Symbol, sym};
|
||||
|
||||
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
|
||||
use crate::context::{AcceptContext, Stage};
|
||||
use crate::parser::ArgParser;
|
||||
|
||||
pub(crate) struct RustcLayoutScalarValidRangeStart;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeStart {
|
||||
const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_start];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate = template!(List: "start");
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
parse_rustc_layout_scalar_valid_range(cx, args)
|
||||
.map(|n| AttributeKind::RustcLayoutScalarValidRangeStart(n, cx.attr_span))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RustcLayoutScalarValidRangeEnd;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeEnd {
|
||||
const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_end];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate = template!(List: "end");
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
parse_rustc_layout_scalar_valid_range(cx, args)
|
||||
.map(|n| AttributeKind::RustcLayoutScalarValidRangeEnd(n, cx.attr_span))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_rustc_layout_scalar_valid_range<S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
args: &ArgParser<'_>,
|
||||
) -> Option<Box<u128>> {
|
||||
let Some(list) = args.list() else {
|
||||
cx.expected_list(cx.attr_span);
|
||||
return None;
|
||||
};
|
||||
let Some(single) = list.single() else {
|
||||
cx.expected_single_argument(list.span);
|
||||
return None;
|
||||
};
|
||||
let Some(lit) = single.lit() else {
|
||||
cx.expected_integer_literal(single.span());
|
||||
return None;
|
||||
};
|
||||
let LitKind::Int(num, _ty) = lit.kind else {
|
||||
cx.expected_integer_literal(single.span());
|
||||
return None;
|
||||
};
|
||||
Some(Box::new(num.0))
|
||||
}
|
||||
|
||||
pub(crate) struct RustcObjectLifetimeDefaultParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcObjectLifetimeDefaultParser {
|
||||
const PATH: &[rustc_span::Symbol] = &[sym::rustc_object_lifetime_default];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
if let Err(span) = args.no_args() {
|
||||
cx.expected_no_args(span);
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(AttributeKind::RustcObjectLifetimeDefault)
|
||||
}
|
||||
}
|
||||
|
|
@ -27,6 +27,10 @@ use crate::attributes::lint_helpers::{AsPtrParser, PubTransparentParser};
|
|||
use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
|
||||
use crate::attributes::must_use::MustUseParser;
|
||||
use crate::attributes::repr::{AlignParser, ReprParser};
|
||||
use crate::attributes::rustc_internal::{
|
||||
RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
|
||||
RustcObjectLifetimeDefaultParser,
|
||||
};
|
||||
use crate::attributes::semantics::MayDangleParser;
|
||||
use crate::attributes::stability::{
|
||||
BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
|
||||
|
|
@ -131,6 +135,9 @@ attribute_parsers!(
|
|||
Single<OptimizeParser>,
|
||||
Single<PubTransparentParser>,
|
||||
Single<RustcForceInlineParser>,
|
||||
Single<RustcLayoutScalarValidRangeEnd>,
|
||||
Single<RustcLayoutScalarValidRangeStart>,
|
||||
Single<RustcObjectLifetimeDefaultParser>,
|
||||
Single<SkipDuringMethodDispatchParser>,
|
||||
Single<TrackCallerParser>,
|
||||
Single<TransparencyParser>,
|
||||
|
|
@ -274,6 +281,16 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn expected_integer_literal(&self, span: Span) -> ErrorGuaranteed {
|
||||
self.emit_err(AttributeParseError {
|
||||
span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
reason: AttributeParseErrorReason::ExpectedIntegerLiteral,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn expected_list(&self, span: Span) -> ErrorGuaranteed {
|
||||
self.emit_err(AttributeParseError {
|
||||
span,
|
||||
|
|
|
|||
|
|
@ -510,6 +510,7 @@ pub(crate) struct NakedFunctionIncompatibleAttribute {
|
|||
pub(crate) enum AttributeParseErrorReason {
|
||||
ExpectedNoArgs,
|
||||
ExpectedStringLiteral { byte_string: Option<Span> },
|
||||
ExpectedIntegerLiteral,
|
||||
ExpectedAtLeastOneArgument,
|
||||
ExpectedSingleArgument,
|
||||
ExpectedList,
|
||||
|
|
@ -550,6 +551,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
|
|||
diag.span_label(self.span, "expected a string literal here");
|
||||
}
|
||||
}
|
||||
AttributeParseErrorReason::ExpectedIntegerLiteral => {
|
||||
diag.span_label(self.span, "expected an integer literal here");
|
||||
}
|
||||
AttributeParseErrorReason::ExpectedSingleArgument => {
|
||||
diag.span_label(self.span, "expected a single argument here");
|
||||
diag.code(E0805);
|
||||
|
|
@ -573,10 +577,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
|
|||
diag.code(E0565);
|
||||
}
|
||||
AttributeParseErrorReason::ExpectedNameValue(None) => {
|
||||
diag.span_label(
|
||||
self.span,
|
||||
format!("expected this to be of the form `{name} = \"...\"`"),
|
||||
);
|
||||
// The suggestion we add below this match already contains enough information
|
||||
}
|
||||
AttributeParseErrorReason::ExpectedNameValue(Some(name)) => {
|
||||
diag.span_label(
|
||||
|
|
|
|||
|
|
@ -1168,6 +1168,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
_,
|
||||
mir::Rvalue::Use(mir::Operand::Copy(place)),
|
||||
)),
|
||||
..
|
||||
}) = self.body[location.block].statements.get(location.statement_index)
|
||||
{
|
||||
self.body.local_decls[place.local].source_info.span
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@ use rustc_middle::traits::query::NoSolution;
|
|||
use rustc_middle::ty::adjustment::PointerCoercion;
|
||||
use rustc_middle::ty::cast::CastTy;
|
||||
use rustc_middle::ty::{
|
||||
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt,
|
||||
Dynamic, GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt,
|
||||
TypeVisitableExt, UserArgs, UserTypeAnnotationIndex, fold_regions,
|
||||
self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt,
|
||||
GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, TypeVisitableExt,
|
||||
UserArgs, UserTypeAnnotationIndex, fold_regions,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_mir_dataflow::move_paths::MoveData;
|
||||
|
|
@ -1233,38 +1233,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
CastKind::PointerCoercion(PointerCoercion::DynStar, coercion_source) => {
|
||||
// get the constraints from the target type (`dyn* Clone`)
|
||||
//
|
||||
// apply them to prove that the source type `Foo` implements `Clone` etc
|
||||
let (existential_predicates, region) = match ty.kind() {
|
||||
Dynamic(predicates, region, ty::DynStar) => (predicates, region),
|
||||
_ => panic!("Invalid dyn* cast_ty"),
|
||||
};
|
||||
|
||||
let self_ty = op.ty(self.body, tcx);
|
||||
|
||||
let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
|
||||
self.prove_predicates(
|
||||
existential_predicates
|
||||
.iter()
|
||||
.map(|predicate| predicate.with_self_ty(tcx, self_ty)),
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
|
||||
);
|
||||
|
||||
let outlives_predicate = tcx.mk_predicate(Binder::dummy(
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
|
||||
ty::OutlivesPredicate(self_ty, *region),
|
||||
)),
|
||||
));
|
||||
self.prove_predicate(
|
||||
outlives_predicate,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
|
||||
);
|
||||
}
|
||||
|
||||
CastKind::PointerCoercion(
|
||||
PointerCoercion::MutToConstPointer,
|
||||
coercion_source,
|
||||
|
|
|
|||
|
|
@ -177,15 +177,15 @@ pub(crate) fn expand_concat_bytes(
|
|||
Ok(LitKind::Byte(val)) => {
|
||||
accumulator.push(val);
|
||||
}
|
||||
Ok(LitKind::ByteStr(ref bytes, _)) => {
|
||||
accumulator.extend_from_slice(bytes);
|
||||
Ok(LitKind::ByteStr(ref byte_sym, _)) => {
|
||||
accumulator.extend_from_slice(byte_sym.as_byte_str());
|
||||
}
|
||||
_ => {
|
||||
guar.get_or_insert_with(|| invalid_type_err(cx, token_lit, e.span, false));
|
||||
}
|
||||
},
|
||||
ExprKind::IncludedBytes(bytes) => {
|
||||
accumulator.extend_from_slice(bytes);
|
||||
ExprKind::IncludedBytes(byte_sym) => {
|
||||
accumulator.extend_from_slice(byte_sym.as_byte_str());
|
||||
}
|
||||
ExprKind::Err(guarantee) => {
|
||||
guar = Some(*guarantee);
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@
|
|||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![cfg_attr(not(bootstrap), feature(autodiff))]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(autodiff)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(if_let_guard)]
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use rustc_parse::parser::{ForceCollect, Parser};
|
|||
use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal, utf8_error};
|
||||
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::{Pos, Span, Symbol};
|
||||
use rustc_span::{ByteSymbol, Pos, Span, Symbol};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::errors;
|
||||
|
|
@ -237,7 +237,7 @@ pub(crate) fn expand_include_bytes(
|
|||
Ok((bytes, _bsp)) => {
|
||||
// Don't care about getting the span for the raw bytes,
|
||||
// because the console can't really show them anyway.
|
||||
let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(bytes));
|
||||
let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(ByteSymbol::intern(&bytes)));
|
||||
MacEager::expr(expr)
|
||||
}
|
||||
Err(dummy) => dummy,
|
||||
|
|
|
|||
|
|
@ -753,51 +753,6 @@ pub(crate) fn codegen_drop<'tcx>(
|
|||
fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]);
|
||||
fx.bcx.ins().jump(ret_block, &[]);
|
||||
}
|
||||
ty::Dynamic(_, _, ty::DynStar) => {
|
||||
// IN THIS ARM, WE HAVE:
|
||||
// ty = *mut (dyn* Trait)
|
||||
// which is: *mut exists<T: sizeof(T) == sizeof(usize)> (T, Vtable<T: Trait>)
|
||||
//
|
||||
// args = [ * ]
|
||||
// |
|
||||
// v
|
||||
// ( Data, Vtable )
|
||||
// |
|
||||
// v
|
||||
// /-------\
|
||||
// | ... |
|
||||
// \-------/
|
||||
//
|
||||
//
|
||||
// WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING
|
||||
//
|
||||
// data = &(*args[0]).0 // gives a pointer to Data above (really the same pointer)
|
||||
// vtable = (*args[0]).1 // loads the vtable out
|
||||
// (data, vtable) // an equivalent Rust `*mut dyn Trait`
|
||||
//
|
||||
// SO THEN WE CAN USE THE ABOVE CODE.
|
||||
let (data, vtable) = drop_place.to_cvalue(fx).dyn_star_force_data_on_stack(fx);
|
||||
let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable);
|
||||
|
||||
let is_null = fx.bcx.ins().icmp_imm(IntCC::Equal, drop_fn, 0);
|
||||
let target_block = fx.get_block(target);
|
||||
let continued = fx.bcx.create_block();
|
||||
fx.bcx.ins().brif(is_null, target_block, &[], continued, &[]);
|
||||
fx.bcx.switch_to_block(continued);
|
||||
|
||||
let virtual_drop = Instance {
|
||||
def: ty::InstanceKind::Virtual(drop_instance.def_id(), 0),
|
||||
args: drop_instance.args,
|
||||
};
|
||||
let fn_abi = FullyMonomorphizedLayoutCx(fx.tcx)
|
||||
.fn_abi_of_instance(virtual_drop, ty::List::empty());
|
||||
|
||||
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
|
||||
let sig = fx.bcx.import_signature(sig);
|
||||
fx.bcx.ins().call_indirect(sig, drop_fn, &[data]);
|
||||
// FIXME implement cleanup on exceptions
|
||||
fx.bcx.ins().jump(ret_block, &[]);
|
||||
}
|
||||
_ => {
|
||||
assert!(!matches!(drop_instance.def, InstanceKind::Virtual(_, _)));
|
||||
|
||||
|
|
|
|||
|
|
@ -790,14 +790,6 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
|
|||
let operand = codegen_operand(fx, operand);
|
||||
crate::unsize::coerce_unsized_into(fx, operand, lval);
|
||||
}
|
||||
Rvalue::Cast(
|
||||
CastKind::PointerCoercion(PointerCoercion::DynStar, _),
|
||||
ref operand,
|
||||
_,
|
||||
) => {
|
||||
let operand = codegen_operand(fx, operand);
|
||||
crate::unsize::coerce_dyn_star(fx, operand, lval);
|
||||
}
|
||||
Rvalue::Cast(CastKind::Transmute, ref operand, _to_ty) => {
|
||||
let operand = codegen_operand(fx, operand);
|
||||
lval.write_cvalue_transmute(fx, operand);
|
||||
|
|
|
|||
|
|
@ -112,21 +112,6 @@ fn unsize_ptr<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
/// Coerces `src` to `dst_ty` which is guaranteed to be a `dyn*` type.
|
||||
pub(crate) fn cast_to_dyn_star<'tcx>(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
src: Value,
|
||||
src_ty_and_layout: TyAndLayout<'tcx>,
|
||||
dst_ty: Ty<'tcx>,
|
||||
old_info: Option<Value>,
|
||||
) -> (Value, Value) {
|
||||
assert!(
|
||||
matches!(dst_ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
|
||||
"destination type must be a dyn*"
|
||||
);
|
||||
(src, unsized_info(fx, src_ty_and_layout.ty, dst_ty, old_info))
|
||||
}
|
||||
|
||||
/// Coerce `src`, which is a reference to a value of type `src_ty`,
|
||||
/// to a value of type `dst_ty` and store the result in `dst`
|
||||
pub(crate) fn coerce_unsized_into<'tcx>(
|
||||
|
|
@ -174,24 +159,6 @@ pub(crate) fn coerce_unsized_into<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn coerce_dyn_star<'tcx>(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
src: CValue<'tcx>,
|
||||
dst: CPlace<'tcx>,
|
||||
) {
|
||||
let (data, extra) = if let ty::Dynamic(_, _, ty::DynStar) = src.layout().ty.kind() {
|
||||
let (data, vtable) = src.load_scalar_pair(fx);
|
||||
(data, Some(vtable))
|
||||
} else {
|
||||
let data = src.load_scalar(fx);
|
||||
(data, None)
|
||||
};
|
||||
|
||||
let (data, vtable) = cast_to_dyn_star(fx, data, src.layout(), dst.layout().ty, extra);
|
||||
|
||||
dst.write_cvalue(fx, CValue::by_val_pair(data, vtable, dst.layout()));
|
||||
}
|
||||
|
||||
// Adapted from https://github.com/rust-lang/rust/blob/2a663555ddf36f6b041445894a8c175cd1bc718c/src/librustc_codegen_ssa/glue.rs
|
||||
|
||||
pub(crate) fn size_and_align_of<'tcx>(
|
||||
|
|
|
|||
|
|
@ -121,43 +121,6 @@ impl<'tcx> CValue<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME remove
|
||||
/// Forces the data value of a dyn* value to the stack and returns a pointer to it as well as the
|
||||
/// vtable pointer.
|
||||
pub(crate) fn dyn_star_force_data_on_stack(
|
||||
self,
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
) -> (Value, Value) {
|
||||
assert!(self.1.ty.is_dyn_star());
|
||||
|
||||
match self.0 {
|
||||
CValueInner::ByRef(ptr, None) => {
|
||||
let (a_scalar, b_scalar) = match self.1.backend_repr {
|
||||
BackendRepr::ScalarPair(a, b) => (a, b),
|
||||
_ => unreachable!("dyn_star_force_data_on_stack({:?})", self),
|
||||
};
|
||||
let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
|
||||
let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar);
|
||||
let mut flags = MemFlags::new();
|
||||
flags.set_notrap();
|
||||
let vtable = ptr.offset(fx, b_offset).load(fx, clif_ty2, flags);
|
||||
(ptr.get_addr(fx), vtable)
|
||||
}
|
||||
CValueInner::ByValPair(data, vtable) => {
|
||||
let data_ptr = fx.create_stack_slot(
|
||||
u32::try_from(fx.target_config.pointer_type().bytes()).unwrap(),
|
||||
u32::try_from(fx.target_config.pointer_type().bytes()).unwrap(),
|
||||
);
|
||||
data_ptr.store(fx, data, MemFlags::trusted());
|
||||
|
||||
(data_ptr.get_addr(fx), vtable)
|
||||
}
|
||||
CValueInner::ByRef(_, Some(_)) | CValueInner::ByVal(_) => {
|
||||
unreachable!("dyn_star_force_data_on_stack({:?})", self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn try_to_ptr(self) -> Option<(Pointer, Option<Value>)> {
|
||||
match self.0 {
|
||||
CValueInner::ByRef(ptr, meta) => Some((ptr, meta)),
|
||||
|
|
|
|||
|
|
@ -46,34 +46,22 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
|
|||
mut arg: CValue<'tcx>,
|
||||
idx: usize,
|
||||
) -> (Pointer, Value) {
|
||||
let (ptr, vtable) = 'block: {
|
||||
if let BackendRepr::Scalar(_) = arg.layout().backend_repr {
|
||||
while !arg.layout().ty.is_raw_ptr() && !arg.layout().ty.is_ref() {
|
||||
let (idx, _) = arg
|
||||
.layout()
|
||||
.non_1zst_field(fx)
|
||||
.expect("not exactly one non-1-ZST field in a `DispatchFromDyn` type");
|
||||
arg = arg.value_field(fx, idx);
|
||||
}
|
||||
if let BackendRepr::Scalar(_) = arg.layout().backend_repr {
|
||||
while !arg.layout().ty.is_raw_ptr() && !arg.layout().ty.is_ref() {
|
||||
let (idx, _) = arg
|
||||
.layout()
|
||||
.non_1zst_field(fx)
|
||||
.expect("not exactly one non-1-ZST field in a `DispatchFromDyn` type");
|
||||
arg = arg.value_field(fx, idx);
|
||||
}
|
||||
}
|
||||
|
||||
if let ty::Ref(_, ty, _) = arg.layout().ty.kind() {
|
||||
if ty.is_dyn_star() {
|
||||
let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap());
|
||||
let dyn_star = CPlace::for_ptr(Pointer::new(arg.load_scalar(fx)), inner_layout);
|
||||
let ptr = dyn_star.place_field(fx, FieldIdx::ZERO).to_ptr();
|
||||
let vtable = dyn_star.place_field(fx, FieldIdx::ONE).to_cvalue(fx).load_scalar(fx);
|
||||
break 'block (ptr, vtable);
|
||||
}
|
||||
}
|
||||
|
||||
if let BackendRepr::ScalarPair(_, _) = arg.layout().backend_repr {
|
||||
let (ptr, vtable) = arg.load_scalar_pair(fx);
|
||||
(Pointer::new(ptr), vtable)
|
||||
} else {
|
||||
let (ptr, vtable) = arg.try_to_ptr().unwrap();
|
||||
(ptr, vtable.unwrap())
|
||||
}
|
||||
let (ptr, vtable) = if let BackendRepr::ScalarPair(_, _) = arg.layout().backend_repr {
|
||||
let (ptr, vtable) = arg.load_scalar_pair(fx);
|
||||
(Pointer::new(ptr), vtable)
|
||||
} else {
|
||||
let (ptr, vtable) = arg.try_to_ptr().unwrap();
|
||||
(ptr, vtable.unwrap())
|
||||
};
|
||||
|
||||
let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes();
|
||||
|
|
|
|||
|
|
@ -370,10 +370,18 @@ fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) {
|
|||
let target_env = sess.target.options.env.as_ref();
|
||||
let target_abi = sess.target.options.abi.as_ref();
|
||||
let target_pointer_width = sess.target.pointer_width;
|
||||
let version = get_version();
|
||||
|
||||
cfg.has_reliable_f16 = match (target_arch, target_os) {
|
||||
// Selection failure <https://github.com/llvm/llvm-project/issues/50374>
|
||||
("s390x", _) => false,
|
||||
// LLVM crash without neon <https://github.com/llvm/llvm-project/issues/129394> (now fixed)
|
||||
("aarch64", _)
|
||||
if !cfg.target_features.iter().any(|f| f.as_str() == "neon")
|
||||
&& version < (20, 1, 1) =>
|
||||
{
|
||||
false
|
||||
}
|
||||
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
|
||||
("arm64ec", _) => false,
|
||||
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
|
||||
|
|
|
|||
|
|
@ -1794,7 +1794,10 @@ fn for_each_exported_symbols_include_dep<'tcx>(
|
|||
for (cnum, dep_format) in deps.iter_enumerated() {
|
||||
// For each dependency that we are linking to statically ...
|
||||
if *dep_format == Linkage::Static {
|
||||
for &(symbol, info) in tcx.exported_symbols(cnum).iter() {
|
||||
for &(symbol, info) in tcx.exported_non_generic_symbols(cnum).iter() {
|
||||
callback(symbol, info, cnum);
|
||||
}
|
||||
for &(symbol, info) in tcx.exported_generic_symbols(cnum).iter() {
|
||||
callback(symbol, info, cnum);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ fn is_reachable_non_generic_provider_extern(tcx: TyCtxt<'_>, def_id: DefId) -> b
|
|||
tcx.reachable_non_generics(def_id.krate).contains_key(&def_id)
|
||||
}
|
||||
|
||||
fn exported_symbols_provider_local<'tcx>(
|
||||
fn exported_non_generic_symbols_provider_local<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
_: LocalCrate,
|
||||
) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
|
||||
|
|
@ -306,6 +306,22 @@ fn exported_symbols_provider_local<'tcx>(
|
|||
));
|
||||
}
|
||||
|
||||
// Sort so we get a stable incr. comp. hash.
|
||||
symbols.sort_by_cached_key(|s| s.0.symbol_name_for_local_instance(tcx));
|
||||
|
||||
tcx.arena.alloc_from_iter(symbols)
|
||||
}
|
||||
|
||||
fn exported_generic_symbols_provider_local<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
_: LocalCrate,
|
||||
) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
|
||||
if !tcx.sess.opts.output_types.should_codegen() && !tcx.is_sdylib_interface_build() {
|
||||
return &[];
|
||||
}
|
||||
|
||||
let mut symbols: Vec<_> = vec![];
|
||||
|
||||
if tcx.local_crate_exports_generics() {
|
||||
use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility};
|
||||
use rustc_middle::ty::InstanceKind;
|
||||
|
|
@ -474,7 +490,7 @@ fn upstream_monomorphizations_provider(
|
|||
let async_drop_in_place_fn_def_id = tcx.lang_items().async_drop_in_place_fn();
|
||||
|
||||
for &cnum in cnums.iter() {
|
||||
for (exported_symbol, _) in tcx.exported_symbols(cnum).iter() {
|
||||
for (exported_symbol, _) in tcx.exported_generic_symbols(cnum).iter() {
|
||||
let (def_id, args) = match *exported_symbol {
|
||||
ExportedSymbol::Generic(def_id, args) => (def_id, args),
|
||||
ExportedSymbol::DropGlue(ty) => {
|
||||
|
|
@ -496,10 +512,7 @@ fn upstream_monomorphizations_provider(
|
|||
ExportedSymbol::AsyncDropGlue(def_id, ty) => (def_id, tcx.mk_args(&[ty.into()])),
|
||||
ExportedSymbol::NonGeneric(..)
|
||||
| ExportedSymbol::ThreadLocalShim(..)
|
||||
| ExportedSymbol::NoDefId(..) => {
|
||||
// These are no monomorphizations
|
||||
continue;
|
||||
}
|
||||
| ExportedSymbol::NoDefId(..) => unreachable!("{exported_symbol:?}"),
|
||||
};
|
||||
|
||||
let args_map = instances.entry(def_id).or_default();
|
||||
|
|
@ -554,7 +567,8 @@ fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: LocalDefId)
|
|||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
providers.reachable_non_generics = reachable_non_generics_provider;
|
||||
providers.is_reachable_non_generic = is_reachable_non_generic_provider_local;
|
||||
providers.exported_symbols = exported_symbols_provider_local;
|
||||
providers.exported_non_generic_symbols = exported_non_generic_symbols_provider_local;
|
||||
providers.exported_generic_symbols = exported_generic_symbols_provider_local;
|
||||
providers.upstream_monomorphizations = upstream_monomorphizations_provider;
|
||||
providers.is_unreachable_local_definition = is_unreachable_local_definition_provider;
|
||||
providers.upstream_drop_glue_for = upstream_drop_glue_for_provider;
|
||||
|
|
|
|||
|
|
@ -1124,8 +1124,9 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
|
||||
let copy_symbols = |cnum| {
|
||||
let symbols = tcx
|
||||
.exported_symbols(cnum)
|
||||
.exported_non_generic_symbols(cnum)
|
||||
.iter()
|
||||
.chain(tcx.exported_generic_symbols(cnum))
|
||||
.map(|&(s, lvl)| (symbol_name_for_instance_in_crate(tcx, s, cnum), lvl))
|
||||
.collect();
|
||||
Arc::new(symbols)
|
||||
|
|
|
|||
|
|
@ -262,28 +262,6 @@ pub(crate) fn unsize_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
}
|
||||
}
|
||||
|
||||
/// Coerces `src` to `dst_ty` which is guaranteed to be a `dyn*` type.
|
||||
pub(crate) fn cast_to_dyn_star<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
bx: &mut Bx,
|
||||
src: Bx::Value,
|
||||
src_ty_and_layout: TyAndLayout<'tcx>,
|
||||
dst_ty: Ty<'tcx>,
|
||||
old_info: Option<Bx::Value>,
|
||||
) -> (Bx::Value, Bx::Value) {
|
||||
debug!("cast_to_dyn_star: {:?} => {:?}", src_ty_and_layout.ty, dst_ty);
|
||||
assert!(
|
||||
matches!(dst_ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
|
||||
"destination type must be a dyn*"
|
||||
);
|
||||
let src = match bx.cx().type_kind(bx.cx().backend_type(src_ty_and_layout)) {
|
||||
TypeKind::Pointer => src,
|
||||
TypeKind::Integer => bx.inttoptr(src, bx.type_ptr()),
|
||||
// FIXME(dyn-star): We probably have to do a bitcast first, then inttoptr.
|
||||
kind => bug!("unexpected TypeKind for left-hand side of `dyn*` cast: {kind:?}"),
|
||||
};
|
||||
(src, unsized_info(bx, src_ty_and_layout.ty, dst_ty, old_info))
|
||||
}
|
||||
|
||||
/// Coerces `src`, which is a reference to a value of type `src_ty`,
|
||||
/// to a value of type `dst_ty`, and stores the result in `dst`.
|
||||
pub(crate) fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_abi::{Align, ExternAbi};
|
||||
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode};
|
||||
use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr};
|
||||
use rustc_attr_data_structures::{
|
||||
|
|
@ -395,6 +395,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
codegen_fn_attrs.alignment =
|
||||
Ord::max(codegen_fn_attrs.alignment, tcx.sess.opts.unstable_opts.min_function_alignment);
|
||||
|
||||
// On trait methods, inherit the `#[align]` of the trait's method prototype.
|
||||
codegen_fn_attrs.alignment = Ord::max(codegen_fn_attrs.alignment, tcx.inherited_align(did));
|
||||
|
||||
let inline_span;
|
||||
(codegen_fn_attrs.inline, inline_span) = if let Some((inline_attr, span)) =
|
||||
find_attr!(attrs, AttributeKind::Inline(i, span) => (*i, *span))
|
||||
|
|
@ -549,17 +552,26 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
codegen_fn_attrs
|
||||
}
|
||||
|
||||
/// If the provided DefId is a method in a trait impl, return the DefId of the method prototype.
|
||||
fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
|
||||
let impl_item = tcx.opt_associated_item(def_id)?;
|
||||
match impl_item.container {
|
||||
ty::AssocItemContainer::Impl => impl_item.trait_item_def_id,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
|
||||
/// applied to the method prototype.
|
||||
fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||
if let Some(impl_item) = tcx.opt_associated_item(def_id)
|
||||
&& let ty::AssocItemContainer::Impl = impl_item.container
|
||||
&& let Some(trait_item) = impl_item.trait_item_def_id
|
||||
{
|
||||
return tcx.codegen_fn_attrs(trait_item).flags.intersects(CodegenFnAttrFlags::TRACK_CALLER);
|
||||
}
|
||||
let Some(trait_item) = opt_trait_item(tcx, def_id) else { return false };
|
||||
tcx.codegen_fn_attrs(trait_item).flags.intersects(CodegenFnAttrFlags::TRACK_CALLER)
|
||||
}
|
||||
|
||||
false
|
||||
/// If the provided DefId is a method in a trait impl, return the value of the `#[align]`
|
||||
/// attribute on the method prototype (if any).
|
||||
fn inherited_align<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<Align> {
|
||||
tcx.codegen_fn_attrs(opt_trait_item(tcx, def_id)?).alignment
|
||||
}
|
||||
|
||||
fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &hir::Attribute) -> Option<u16> {
|
||||
|
|
@ -727,5 +739,6 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
|
|||
}
|
||||
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
*providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers };
|
||||
*providers =
|
||||
Providers { codegen_fn_attrs, should_inherit_track_caller, inherited_align, ..*providers };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -628,50 +628,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
virtual_drop,
|
||||
)
|
||||
}
|
||||
ty::Dynamic(_, _, ty::DynStar) => {
|
||||
// IN THIS ARM, WE HAVE:
|
||||
// ty = *mut (dyn* Trait)
|
||||
// which is: *mut exists<T: sizeof(T) == sizeof(usize)> (T, Vtable<T: Trait>)
|
||||
//
|
||||
// args = [ * ]
|
||||
// |
|
||||
// v
|
||||
// ( Data, Vtable )
|
||||
// |
|
||||
// v
|
||||
// /-------\
|
||||
// | ... |
|
||||
// \-------/
|
||||
//
|
||||
//
|
||||
// WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING
|
||||
//
|
||||
// data = &(*args[0]).0 // gives a pointer to Data above (really the same pointer)
|
||||
// vtable = (*args[0]).1 // loads the vtable out
|
||||
// (data, vtable) // an equivalent Rust `*mut dyn Trait`
|
||||
//
|
||||
// SO THEN WE CAN USE THE ABOVE CODE.
|
||||
let virtual_drop = Instance {
|
||||
def: ty::InstanceKind::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function
|
||||
args: drop_fn.args,
|
||||
};
|
||||
debug!("ty = {:?}", ty);
|
||||
debug!("drop_fn = {:?}", drop_fn);
|
||||
debug!("args = {:?}", args);
|
||||
let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty());
|
||||
let meta_ptr = place.project_field(bx, 1);
|
||||
let meta = bx.load_operand(meta_ptr);
|
||||
// Truncate vtable off of args list
|
||||
args = &args[..1];
|
||||
debug!("args' = {:?}", args);
|
||||
(
|
||||
true,
|
||||
meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
|
||||
.get_optional_fn(bx, meta.immediate(), ty, fn_abi),
|
||||
fn_abi,
|
||||
virtual_drop,
|
||||
)
|
||||
}
|
||||
_ => (
|
||||
false,
|
||||
bx.get_fn_addr(drop_fn),
|
||||
|
|
@ -1108,33 +1064,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
llargs.push(data_ptr);
|
||||
continue;
|
||||
}
|
||||
Immediate(_) => {
|
||||
// See comment above explaining why we peel these newtypes
|
||||
while !op.layout.ty.is_raw_ptr() && !op.layout.ty.is_ref() {
|
||||
let (idx, _) = op.layout.non_1zst_field(bx).expect(
|
||||
"not exactly one non-1-ZST field in a `DispatchFromDyn` type",
|
||||
);
|
||||
op = op.extract_field(self, bx, idx.as_usize());
|
||||
}
|
||||
|
||||
// Make sure that we've actually unwrapped the rcvr down
|
||||
// to a pointer or ref to `dyn* Trait`.
|
||||
if !op.layout.ty.builtin_deref(true).unwrap().is_dyn_star() {
|
||||
span_bug!(fn_span, "can't codegen a virtual call on {:#?}", op);
|
||||
}
|
||||
let place = op.deref(bx.cx());
|
||||
let data_place = place.project_field(bx, 0);
|
||||
let meta_place = place.project_field(bx, 1);
|
||||
let meta = bx.load_operand(meta_place);
|
||||
llfn = Some(meth::VirtualIndex::from_index(idx).get_fn(
|
||||
bx,
|
||||
meta.immediate(),
|
||||
op.layout.ty,
|
||||
fn_abi,
|
||||
));
|
||||
llargs.push(data_place.val.llval);
|
||||
continue;
|
||||
}
|
||||
_ => {
|
||||
span_bug!(fn_span, "can't codegen a virtual call on {:#?}", op);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -468,12 +468,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
bug!("unexpected non-pair operand");
|
||||
}
|
||||
}
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::DynStar, _) => {
|
||||
let (lldata, llextra) = operand.val.pointer_parts();
|
||||
let (lldata, llextra) =
|
||||
base::cast_to_dyn_star(bx, lldata, operand.layout, cast.ty, llextra);
|
||||
OperandValue::Pair(lldata, llextra)
|
||||
}
|
||||
| mir::CastKind::IntToInt
|
||||
| mir::CastKind::FloatToInt
|
||||
| mir::CastKind::FloatToFloat
|
||||
|
|
|
|||
|
|
@ -638,14 +638,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
// These are all okay; they only change the type, not the data.
|
||||
}
|
||||
|
||||
Rvalue::Cast(
|
||||
CastKind::PointerCoercion(PointerCoercion::Unsize | PointerCoercion::DynStar, _),
|
||||
_,
|
||||
_,
|
||||
) => {
|
||||
// Unsizing and `dyn*` coercions are implemented for CTFE.
|
||||
}
|
||||
|
||||
Rvalue::Cast(CastKind::PointerExposeProvenance, _, _) => {
|
||||
self.check_op(ops::RawPtrToIntCast);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -643,13 +643,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
break self.ref_to_mplace(&val)?;
|
||||
}
|
||||
ty::Dynamic(.., ty::Dyn) => break receiver.assert_mem_place(), // no immediate unsized values
|
||||
ty::Dynamic(.., ty::DynStar) => {
|
||||
// Not clear how to handle this, so far we assume the receiver is always a pointer.
|
||||
span_bug!(
|
||||
self.cur_span(),
|
||||
"by-value calls on a `dyn*`... are those a thing?"
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
// Not there yet, search for the only non-ZST field.
|
||||
// (The rules for `DispatchFromDyn` ensure there's exactly one such field.)
|
||||
|
|
@ -662,39 +655,23 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
};
|
||||
|
||||
// Obtain the underlying trait we are working on, and the adjusted receiver argument.
|
||||
let (trait_, dyn_ty, adjusted_recv) = if let ty::Dynamic(data, _, ty::DynStar) =
|
||||
receiver_place.layout.ty.kind()
|
||||
{
|
||||
let recv = self.unpack_dyn_star(&receiver_place, data)?;
|
||||
|
||||
(data.principal(), recv.layout.ty, recv.ptr())
|
||||
} else {
|
||||
// Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`.
|
||||
// (For that reason we also cannot use `unpack_dyn_trait`.)
|
||||
let receiver_tail =
|
||||
self.tcx.struct_tail_for_codegen(receiver_place.layout.ty, self.typing_env);
|
||||
let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else {
|
||||
span_bug!(
|
||||
self.cur_span(),
|
||||
"dynamic call on non-`dyn` type {}",
|
||||
receiver_tail
|
||||
)
|
||||
};
|
||||
assert!(receiver_place.layout.is_unsized());
|
||||
|
||||
// Get the required information from the vtable.
|
||||
let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?;
|
||||
let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?;
|
||||
|
||||
// It might be surprising that we use a pointer as the receiver even if this
|
||||
// is a by-val case; this works because by-val passing of an unsized `dyn
|
||||
// Trait` to a function is actually desugared to a pointer.
|
||||
(receiver_trait.principal(), dyn_ty, receiver_place.ptr())
|
||||
// Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`.
|
||||
// (For that reason we also cannot use `unpack_dyn_trait`.)
|
||||
let receiver_tail =
|
||||
self.tcx.struct_tail_for_codegen(receiver_place.layout.ty, self.typing_env);
|
||||
let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else {
|
||||
span_bug!(self.cur_span(), "dynamic call on non-`dyn` type {}", receiver_tail)
|
||||
};
|
||||
assert!(receiver_place.layout.is_unsized());
|
||||
|
||||
// Get the required information from the vtable.
|
||||
let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?;
|
||||
let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?;
|
||||
let adjusted_recv = receiver_place.ptr();
|
||||
|
||||
// Now determine the actual method to call. Usually we use the easy way of just
|
||||
// looking up the method at index `idx`.
|
||||
let vtable_entries = self.vtable_entries(trait_, dyn_ty);
|
||||
let vtable_entries = self.vtable_entries(receiver_trait.principal(), dyn_ty);
|
||||
let Some(ty::VtblEntry::Method(fn_inst)) = vtable_entries.get(idx).copied() else {
|
||||
// FIXME(fee1-dead) these could be variants of the UB info enum instead of this
|
||||
throw_ub_custom!(fluent::const_eval_dyn_call_not_a_method);
|
||||
|
|
@ -830,10 +807,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
// Dropping a trait object. Need to find actual drop fn.
|
||||
self.unpack_dyn_trait(&place, data)?
|
||||
}
|
||||
ty::Dynamic(data, _, ty::DynStar) => {
|
||||
// Dropping a `dyn*`. Need to find actual drop fn.
|
||||
self.unpack_dyn_star(&place, data)?
|
||||
}
|
||||
_ => {
|
||||
debug_assert_eq!(
|
||||
instance,
|
||||
|
|
|
|||
|
|
@ -126,20 +126,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
}
|
||||
}
|
||||
|
||||
CastKind::PointerCoercion(PointerCoercion::DynStar, _) => {
|
||||
if let ty::Dynamic(data, _, ty::DynStar) = cast_ty.kind() {
|
||||
// Initial cast from sized to dyn trait
|
||||
let vtable = self.get_vtable_ptr(src.layout.ty, data)?;
|
||||
let vtable = Scalar::from_maybe_pointer(vtable, self);
|
||||
let data = self.read_immediate(src)?.to_scalar();
|
||||
let _assert_pointer_like = data.to_pointer(self)?;
|
||||
let val = Immediate::ScalarPair(data, vtable);
|
||||
self.write_immediate(val, dest)?;
|
||||
} else {
|
||||
bug!()
|
||||
}
|
||||
}
|
||||
|
||||
CastKind::Transmute => {
|
||||
assert!(src.layout.is_sized());
|
||||
assert!(dest.layout.is_sized());
|
||||
|
|
|
|||
|
|
@ -499,8 +499,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
| ty::Closure(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
| ty::Never
|
||||
| ty::Error(_)
|
||||
| ty::Dynamic(_, _, ty::DynStar) => true,
|
||||
| ty::Error(_) => true,
|
||||
|
||||
ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => false,
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use rustc_abi::{Align, FieldIdx, Size};
|
||||
use rustc_abi::{Align, Size};
|
||||
use rustc_middle::mir::interpret::{InterpResult, Pointer};
|
||||
use rustc_middle::ty::{self, ExistentialPredicateStableCmpExt, Ty, TyCtxt, VtblEntry};
|
||||
use tracing::trace;
|
||||
|
|
@ -125,24 +125,4 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
)?;
|
||||
interp_ok(mplace)
|
||||
}
|
||||
|
||||
/// Turn a `dyn* Trait` type into an value with the actual dynamic type.
|
||||
pub(super) fn unpack_dyn_star<P: Projectable<'tcx, M::Provenance>>(
|
||||
&self,
|
||||
val: &P,
|
||||
expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
) -> InterpResult<'tcx, P> {
|
||||
assert!(
|
||||
matches!(val.layout().ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
|
||||
"`unpack_dyn_star` only makes sense on `dyn*` types"
|
||||
);
|
||||
let data = self.project_field(val, FieldIdx::ZERO)?;
|
||||
let vtable = self.project_field(val, FieldIdx::ONE)?;
|
||||
let vtable = self.read_pointer(&vtable.to_op(self)?)?;
|
||||
let ty = self.get_ptr_vtable_ty(vtable, Some(expected_trait))?;
|
||||
// `data` is already the right thing but has the wrong type. So we transmute it.
|
||||
let layout = self.layout_of(ty)?;
|
||||
let data = data.transmute(layout, self)?;
|
||||
interp_ok(data)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -358,9 +358,6 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
|
|||
// arrays/slices
|
||||
ty::Array(..) | ty::Slice(..) => PathElem::ArrayElem(field),
|
||||
|
||||
// dyn* vtables
|
||||
ty::Dynamic(_, _, ty::DynKind::DynStar) if field == 1 => PathElem::Vtable,
|
||||
|
||||
// dyn traits
|
||||
ty::Dynamic(..) => {
|
||||
assert_eq!(field, 0);
|
||||
|
|
|
|||
|
|
@ -101,26 +101,6 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
|
|||
// recurse with the inner type
|
||||
return self.visit_field(v, 0, &inner_mplace.into());
|
||||
}
|
||||
ty::Dynamic(data, _, ty::DynStar) => {
|
||||
// DynStar types. Very different from a dyn type (but strangely part of the
|
||||
// same variant in `TyKind`): These are pairs where the 2nd component is the
|
||||
// vtable, and the first component is the data (which must be ptr-sized).
|
||||
|
||||
// First make sure the vtable can be read at its type.
|
||||
// The type of this vtable is fake, it claims to be a reference to some actual memory but that isn't true.
|
||||
// So we transmute it to a raw pointer.
|
||||
let raw_ptr_ty = Ty::new_mut_ptr(*self.ecx().tcx, self.ecx().tcx.types.unit);
|
||||
let raw_ptr_ty = self.ecx().layout_of(raw_ptr_ty)?;
|
||||
let vtable_field = self
|
||||
.ecx()
|
||||
.project_field(v, FieldIdx::ONE)?
|
||||
.transmute(raw_ptr_ty, self.ecx())?;
|
||||
self.visit_field(v, 1, &vtable_field)?;
|
||||
|
||||
// Then unpack the first field, and continue.
|
||||
let data = self.ecx().unpack_dyn_star(v, data)?;
|
||||
return self.visit_field(v, 0, &data);
|
||||
}
|
||||
// Slices do not need special handling here: they have `Array` field
|
||||
// placement with length 0, so we enter the `Array` case below which
|
||||
// indirectly uses the metadata to determine the actual length.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use std::marker::PointeeSized;
|
||||
use std::ptr::Alignment;
|
||||
|
||||
use rustc_serialize::PointeeSized;
|
||||
|
||||
/// Returns the ABI-required minimum alignment of a type in bytes.
|
||||
///
|
||||
/// This is equivalent to [`align_of`], but also works for some unsized
|
||||
|
|
|
|||
|
|
@ -4,18 +4,7 @@
|
|||
//! green/native threading. This is just a bare-bones enough solution for
|
||||
//! librustdoc, it is not production quality at all.
|
||||
|
||||
// cfg(bootstrap)
|
||||
macro_rules! cfg_select_dispatch {
|
||||
($($tokens:tt)*) => {
|
||||
#[cfg(bootstrap)]
|
||||
cfg_match! { $($tokens)* }
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
cfg_select! { $($tokens)* }
|
||||
};
|
||||
}
|
||||
|
||||
cfg_select_dispatch! {
|
||||
cfg_select! {
|
||||
target_os = "linux" => {
|
||||
mod linux;
|
||||
use linux as imp;
|
||||
|
|
|
|||
|
|
@ -10,9 +10,6 @@
|
|||
#![allow(internal_features)]
|
||||
#![allow(rustc::default_hash_types)]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![cfg_attr(bootstrap, feature(cfg_match))]
|
||||
#![cfg_attr(not(bootstrap), feature(cfg_select))]
|
||||
#![cfg_attr(not(bootstrap), feature(sized_hierarchy))]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
|
|
@ -22,6 +19,7 @@
|
|||
#![feature(ascii_char_variants)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(auto_traits)]
|
||||
#![feature(cfg_select)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(dropck_eyepatch)]
|
||||
#![feature(extend_one)]
|
||||
|
|
@ -33,6 +31,7 @@
|
|||
#![feature(ptr_alignment_type)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(sized_hierarchy)]
|
||||
#![feature(test)]
|
||||
#![feature(thread_id_value)]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
|
@ -44,9 +43,6 @@ use std::fmt;
|
|||
pub use atomic_ref::AtomicRef;
|
||||
pub use ena::{snapshot_vec, undo_log, unify};
|
||||
pub use rustc_index::static_assert_size;
|
||||
// re-exported for `rustc_smir`
|
||||
// FIXME(sized_hierarchy): remove with `cfg(bootstrap)`, see `rustc_serialize/src/lib.rs`
|
||||
pub use rustc_serialize::PointeeSized;
|
||||
|
||||
pub mod aligned;
|
||||
pub mod base_n;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use std::alloc::Allocator;
|
||||
|
||||
use rustc_serialize::PointeeSized;
|
||||
use std::marker::PointeeSized;
|
||||
|
||||
#[diagnostic::on_unimplemented(message = "`{Self}` doesn't implement `DynSend`. \
|
||||
Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Send`")]
|
||||
|
|
|
|||
|
|
@ -859,19 +859,8 @@ fn get_thread_id() -> u32 {
|
|||
std::thread::current().id().as_u64().get() as u32
|
||||
}
|
||||
|
||||
// cfg(bootstrap)
|
||||
macro_rules! cfg_select_dispatch {
|
||||
($($tokens:tt)*) => {
|
||||
#[cfg(bootstrap)]
|
||||
cfg_match! { $($tokens)* }
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
cfg_select! { $($tokens)* }
|
||||
};
|
||||
}
|
||||
|
||||
// Memory reporting
|
||||
cfg_select_dispatch! {
|
||||
cfg_select! {
|
||||
windows => {
|
||||
pub fn get_resident_set_size() -> Option<usize> {
|
||||
use windows::{
|
||||
|
|
|
|||
|
|
@ -1005,7 +1005,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
/// * may look like "to do xyz, use" or "to do xyz, use abc"
|
||||
/// * may contain a name of a function, variable, or type, but not whole expressions
|
||||
///
|
||||
/// See `CodeSuggestion` for more information.
|
||||
/// See [`CodeSuggestion`] for more information.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_suggestion(
|
||||
&mut self,
|
||||
|
|
@ -1166,7 +1166,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
/// Prints out a message with a suggested edit of the code. If the suggestion is presented
|
||||
/// inline, it will only show the message and not the suggestion.
|
||||
///
|
||||
/// See `CodeSuggestion` for more information.
|
||||
/// See [`CodeSuggestion`] for more information.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_suggestion_short(
|
||||
&mut self,
|
||||
|
|
|
|||
|
|
@ -2078,7 +2078,9 @@ impl HumanEmitter {
|
|||
// file name, saving in verbosity, but if it *isn't* we do need it, otherwise we're
|
||||
// telling users to make a change but not clarifying *where*.
|
||||
let loc = sm.lookup_char_pos(parts[0].span.lo());
|
||||
if loc.file.name != sm.span_to_filename(span) && loc.file.name.is_real() {
|
||||
if (span.is_dummy() || loc.file.name != sm.span_to_filename(span))
|
||||
&& loc.file.name.is_real()
|
||||
{
|
||||
// --> file.rs:line:col
|
||||
// |
|
||||
let arrow = self.file_start();
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
#![allow(incomplete_features)]
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::direct_use_of_rustc_type_ir)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![cfg_attr(not(bootstrap), allow(rustc::direct_use_of_rustc_type_ir))]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(array_windows)]
|
||||
|
|
|
|||
|
|
@ -109,9 +109,6 @@ expand_malformed_feature_attribute =
|
|||
|
||||
expand_meta_var_dif_seq_matchers = {$msg}
|
||||
|
||||
expand_meta_var_expr_unrecognized_var =
|
||||
variable `{$key}` is not recognized in meta-variable expression
|
||||
|
||||
expand_missing_fragment_specifier = missing fragment specifier
|
||||
.note = fragment specifiers must be provided
|
||||
.suggestion_add_fragspec = try adding a specifier here
|
||||
|
|
@ -136,6 +133,9 @@ expand_module_multiple_candidates =
|
|||
expand_must_repeat_once =
|
||||
this must repeat at least once
|
||||
|
||||
expand_mve_unrecognized_var =
|
||||
variable `{$key}` is not recognized in meta-variable expression
|
||||
|
||||
expand_non_inline_modules_in_proc_macro_input_are_unstable =
|
||||
non-inline modules in proc macro input are unstable
|
||||
|
||||
|
|
|
|||
|
|
@ -27,14 +27,6 @@ pub(crate) struct CountRepetitionMisplaced {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(expand_meta_var_expr_unrecognized_var)]
|
||||
pub(crate) struct MetaVarExprUnrecognizedVar {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub key: MacroRulesNormalizedIdent,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(expand_var_still_repeating)]
|
||||
pub(crate) struct VarStillRepeating {
|
||||
|
|
@ -499,3 +491,16 @@ pub(crate) struct ProcMacroBackCompat {
|
|||
pub crate_name: String,
|
||||
pub fixed_version: String,
|
||||
}
|
||||
|
||||
pub(crate) use metavar_exprs::*;
|
||||
mod metavar_exprs {
|
||||
use super::*;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(expand_mve_unrecognized_var)]
|
||||
pub(crate) struct MveUnrecognizedVar {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub key: MacroRulesNormalizedIdent,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,46 +47,7 @@ impl MetaVarExpr {
|
|||
check_trailing_token(&mut iter, psess)?;
|
||||
let mut iter = args.iter();
|
||||
let rslt = match ident.as_str() {
|
||||
"concat" => {
|
||||
let mut result = Vec::new();
|
||||
loop {
|
||||
let is_var = try_eat_dollar(&mut iter);
|
||||
let token = parse_token(&mut iter, psess, outer_span)?;
|
||||
let element = if is_var {
|
||||
MetaVarExprConcatElem::Var(parse_ident_from_token(psess, token)?)
|
||||
} else if let TokenKind::Literal(Lit {
|
||||
kind: token::LitKind::Str,
|
||||
symbol,
|
||||
suffix: None,
|
||||
}) = token.kind
|
||||
{
|
||||
MetaVarExprConcatElem::Literal(symbol)
|
||||
} else {
|
||||
match parse_ident_from_token(psess, token) {
|
||||
Err(err) => {
|
||||
err.cancel();
|
||||
return Err(psess
|
||||
.dcx()
|
||||
.struct_span_err(token.span, UNSUPPORTED_CONCAT_ELEM_ERR));
|
||||
}
|
||||
Ok(elem) => MetaVarExprConcatElem::Ident(elem),
|
||||
}
|
||||
};
|
||||
result.push(element);
|
||||
if iter.peek().is_none() {
|
||||
break;
|
||||
}
|
||||
if !try_eat_comma(&mut iter) {
|
||||
return Err(psess.dcx().struct_span_err(outer_span, "expected comma"));
|
||||
}
|
||||
}
|
||||
if result.len() < 2 {
|
||||
return Err(psess
|
||||
.dcx()
|
||||
.struct_span_err(ident.span, "`concat` must have at least two elements"));
|
||||
}
|
||||
MetaVarExpr::Concat(result.into())
|
||||
}
|
||||
"concat" => parse_concat(&mut iter, psess, outer_span, ident.span)?,
|
||||
"count" => parse_count(&mut iter, psess, ident.span)?,
|
||||
"ignore" => {
|
||||
eat_dollar(&mut iter, psess, ident.span)?;
|
||||
|
|
@ -126,20 +87,6 @@ impl MetaVarExpr {
|
|||
}
|
||||
}
|
||||
|
||||
/// Indicates what is placed in a `concat` parameter. For example, literals
|
||||
/// (`${concat("foo", "bar")}`) or adhoc identifiers (`${concat(foo, bar)}`).
|
||||
#[derive(Debug, Decodable, Encodable, PartialEq)]
|
||||
pub(crate) enum MetaVarExprConcatElem {
|
||||
/// Identifier WITHOUT a preceding dollar sign, which means that this identifier should be
|
||||
/// interpreted as a literal.
|
||||
Ident(Ident),
|
||||
/// For example, a number or a string.
|
||||
Literal(Symbol),
|
||||
/// Identifier WITH a preceding dollar sign, which means that this identifier should be
|
||||
/// expanded and interpreted as a variable.
|
||||
Var(Ident),
|
||||
}
|
||||
|
||||
// Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}`
|
||||
fn check_trailing_token<'psess>(
|
||||
iter: &mut TokenStreamIter<'_>,
|
||||
|
|
@ -156,6 +103,64 @@ fn check_trailing_token<'psess>(
|
|||
}
|
||||
}
|
||||
|
||||
/// Indicates what is placed in a `concat` parameter. For example, literals
|
||||
/// (`${concat("foo", "bar")}`) or adhoc identifiers (`${concat(foo, bar)}`).
|
||||
#[derive(Debug, Decodable, Encodable, PartialEq)]
|
||||
pub(crate) enum MetaVarExprConcatElem {
|
||||
/// Identifier WITHOUT a preceding dollar sign, which means that this identifier should be
|
||||
/// interpreted as a literal.
|
||||
Ident(Ident),
|
||||
/// For example, a number or a string.
|
||||
Literal(Symbol),
|
||||
/// Identifier WITH a preceding dollar sign, which means that this identifier should be
|
||||
/// expanded and interpreted as a variable.
|
||||
Var(Ident),
|
||||
}
|
||||
|
||||
/// Parse a meta-variable `concat` expression: `concat($metavar, ident, ...)`.
|
||||
fn parse_concat<'psess>(
|
||||
iter: &mut TokenStreamIter<'_>,
|
||||
psess: &'psess ParseSess,
|
||||
outer_span: Span,
|
||||
expr_ident_span: Span,
|
||||
) -> PResult<'psess, MetaVarExpr> {
|
||||
let mut result = Vec::new();
|
||||
loop {
|
||||
let is_var = try_eat_dollar(iter);
|
||||
let token = parse_token(iter, psess, outer_span)?;
|
||||
let element = if is_var {
|
||||
MetaVarExprConcatElem::Var(parse_ident_from_token(psess, token)?)
|
||||
} else if let TokenKind::Literal(Lit { kind: token::LitKind::Str, symbol, suffix: None }) =
|
||||
token.kind
|
||||
{
|
||||
MetaVarExprConcatElem::Literal(symbol)
|
||||
} else {
|
||||
match parse_ident_from_token(psess, token) {
|
||||
Err(err) => {
|
||||
err.cancel();
|
||||
return Err(psess
|
||||
.dcx()
|
||||
.struct_span_err(token.span, UNSUPPORTED_CONCAT_ELEM_ERR));
|
||||
}
|
||||
Ok(elem) => MetaVarExprConcatElem::Ident(elem),
|
||||
}
|
||||
};
|
||||
result.push(element);
|
||||
if iter.peek().is_none() {
|
||||
break;
|
||||
}
|
||||
if !try_eat_comma(iter) {
|
||||
return Err(psess.dcx().struct_span_err(outer_span, "expected comma"));
|
||||
}
|
||||
}
|
||||
if result.len() < 2 {
|
||||
return Err(psess
|
||||
.dcx()
|
||||
.struct_span_err(expr_ident_span, "`concat` must have at least two elements"));
|
||||
}
|
||||
Ok(MetaVarExpr::Concat(result.into()))
|
||||
}
|
||||
|
||||
/// Parse a meta-variable `count` expression: `count(ident[, depth])`
|
||||
fn parse_count<'psess>(
|
||||
iter: &mut TokenStreamIter<'_>,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use rustc_span::{
|
|||
use smallvec::{SmallVec, smallvec};
|
||||
|
||||
use crate::errors::{
|
||||
CountRepetitionMisplaced, MetaVarExprUnrecognizedVar, MetaVarsDifSeqMatchers, MustRepeatOnce,
|
||||
CountRepetitionMisplaced, MetaVarsDifSeqMatchers, MustRepeatOnce, MveUnrecognizedVar,
|
||||
NoSyntaxVarsExprRepeat, VarStillRepeating,
|
||||
};
|
||||
use crate::mbe::macro_parser::NamedMatch;
|
||||
|
|
@ -879,7 +879,7 @@ where
|
|||
{
|
||||
let span = ident.span;
|
||||
let key = MacroRulesNormalizedIdent::new(ident);
|
||||
interp.get(&key).ok_or_else(|| dcx.create_err(MetaVarExprUnrecognizedVar { span, key }))
|
||||
interp.get(&key).ok_or_else(|| dcx.create_err(MveUnrecognizedVar { span, key }))
|
||||
}
|
||||
|
||||
/// Used by meta-variable expressions when an user input is out of the actual declared bounds. For
|
||||
|
|
|
|||
|
|
@ -599,8 +599,12 @@ impl server::TokenStream for Rustc<'_, '_> {
|
|||
ast::ExprKind::Lit(token_lit) => {
|
||||
Ok(tokenstream::TokenStream::token_alone(token::Literal(*token_lit), expr.span))
|
||||
}
|
||||
ast::ExprKind::IncludedBytes(bytes) => {
|
||||
let lit = token::Lit::new(token::ByteStr, escape_byte_str_symbol(bytes), None);
|
||||
ast::ExprKind::IncludedBytes(byte_sym) => {
|
||||
let lit = token::Lit::new(
|
||||
token::ByteStr,
|
||||
escape_byte_str_symbol(byte_sym.as_byte_str()),
|
||||
None,
|
||||
);
|
||||
Ok(tokenstream::TokenStream::token_alone(token::TokenKind::Literal(lit), expr.span))
|
||||
}
|
||||
ast::ExprKind::Unary(ast::UnOp::Neg, e) => match &e.kind {
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ declare_features! (
|
|||
/// Allows overloading augmented assignment operations like `a += b`.
|
||||
(accepted, augmented_assignments, "1.8.0", Some(28235)),
|
||||
/// Allows using `avx512*` target features.
|
||||
(accepted, avx512_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)),
|
||||
(accepted, avx512_target_feature, "1.89.0", Some(44839)),
|
||||
/// Allows mixing bind-by-move in patterns and references to those identifiers in guards.
|
||||
(accepted, bind_by_move_pattern_guards, "1.39.0", Some(15287)),
|
||||
/// Allows bindings in the subpattern of a binding pattern.
|
||||
|
|
@ -221,7 +221,7 @@ declare_features! (
|
|||
/// Allows capturing variables in scope using format_args!
|
||||
(accepted, format_args_capture, "1.58.0", Some(67984)),
|
||||
/// Infer generic args for both consts and types.
|
||||
(accepted, generic_arg_infer, "CURRENT_RUSTC_VERSION", Some(85077)),
|
||||
(accepted, generic_arg_infer, "1.89.0", Some(85077)),
|
||||
/// Allows associated types to be generic, e.g., `type Foo<T>;` (RFC 1598).
|
||||
(accepted, generic_associated_types, "1.65.0", Some(44265)),
|
||||
/// Allows attributes on lifetime/type formal parameters in generics (RFC 1327).
|
||||
|
|
@ -262,7 +262,7 @@ declare_features! (
|
|||
/// especially around globs and shadowing (RFC 1560).
|
||||
(accepted, item_like_imports, "1.15.0", Some(35120)),
|
||||
// Allows using the `kl` and `widekl` target features and the associated intrinsics
|
||||
(accepted, keylocker_x86, "CURRENT_RUSTC_VERSION", Some(134813)),
|
||||
(accepted, keylocker_x86, "1.89.0", Some(134813)),
|
||||
/// Allows `'a: { break 'a; }`.
|
||||
(accepted, label_break_value, "1.65.0", Some(48594)),
|
||||
/// Allows `if/while p && let q = r && ...` chains.
|
||||
|
|
@ -367,7 +367,7 @@ declare_features! (
|
|||
/// Lessens the requirements for structs to implement `Unsize`.
|
||||
(accepted, relaxed_struct_unsize, "1.58.0", Some(81793)),
|
||||
/// Allows the `#[repr(i128)]` attribute for enums.
|
||||
(accepted, repr128, "CURRENT_RUSTC_VERSION", Some(56071)),
|
||||
(accepted, repr128, "1.89.0", Some(56071)),
|
||||
/// Allows `repr(align(16))` struct attribute (RFC 1358).
|
||||
(accepted, repr_align, "1.25.0", Some(33626)),
|
||||
/// Allows using `#[repr(align(X))]` on enums with equivalent semantics
|
||||
|
|
@ -389,7 +389,7 @@ declare_features! (
|
|||
/// Allows `Self` struct constructor (RFC 2302).
|
||||
(accepted, self_struct_ctor, "1.32.0", Some(51994)),
|
||||
/// Allows use of x86 SHA512, SM3 and SM4 target-features and intrinsics
|
||||
(accepted, sha512_sm_x86, "CURRENT_RUSTC_VERSION", Some(126624)),
|
||||
(accepted, sha512_sm_x86, "1.89.0", Some(126624)),
|
||||
/// Shorten the tail expression lifetime
|
||||
(accepted, shorter_tail_lifetimes, "1.84.0", Some(123739)),
|
||||
/// Allows using subslice patterns, `[a, .., b]` and `[a, xs @ .., b]`.
|
||||
|
|
|
|||
|
|
@ -123,6 +123,9 @@ declare_features! (
|
|||
/// [^1]: Formerly known as "object safe".
|
||||
(removed, dyn_compatible_for_dispatch, "1.87.0", Some(43561),
|
||||
Some("removed, not used heavily and represented additional complexity in dyn compatibility"), 136522),
|
||||
/// Allows `dyn* Trait` objects.
|
||||
(removed, dyn_star, "1.65.0", Some(102425),
|
||||
Some("removed as it was no longer necessary for AFIDT (async fn in dyn trait) support")),
|
||||
/// Uses generic effect parameters for [const] bounds
|
||||
(removed, effects, "1.84.0", Some(102090),
|
||||
Some("removed, redundant with `#![feature(const_trait_impl)]`"), 132479),
|
||||
|
|
@ -222,7 +225,7 @@ declare_features! (
|
|||
/// Allows exhaustive integer pattern matching with `usize::MAX`/`isize::MIN`/`isize::MAX`.
|
||||
(removed, precise_pointer_size_matching, "1.76.0", Some(56354),
|
||||
Some("removed in favor of half-open ranges"), 118598),
|
||||
(removed, pref_align_of, "CURRENT_RUSTC_VERSION", Some(91971),
|
||||
(removed, pref_align_of, "1.89.0", Some(91971),
|
||||
Some("removed due to marginal use and inducing compiler complications")),
|
||||
(removed, proc_macro_expr, "1.27.0", Some(54727),
|
||||
Some("subsumed by `#![feature(proc_macro_hygiene)]`"), 52121),
|
||||
|
|
@ -265,7 +268,7 @@ declare_features! (
|
|||
(removed, unnamed_fields, "1.83.0", Some(49804), Some("feature needs redesign"), 131045),
|
||||
(removed, unsafe_no_drop_flag, "1.0.0", None, None),
|
||||
/// Allows unsized rvalues at arguments and parameters.
|
||||
(removed, unsized_locals, "CURRENT_RUSTC_VERSION", Some(48055), Some("removed due to implementation concerns; see https://github.com/rust-lang/rust/issues/111942")),
|
||||
(removed, unsized_locals, "1.89.0", Some(48055), Some("removed due to implementation concerns; see https://github.com/rust-lang/rust/issues/111942")),
|
||||
(removed, unsized_tuple_coercion, "1.87.0", Some(42877),
|
||||
Some("The feature restricts possible layouts for tuples, and this restriction is not worth it."), 137728),
|
||||
/// Allows `union` fields that don't implement `Copy` as long as they don't have any drop glue.
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ declare_features! (
|
|||
/// Allows using `rustc_*` attributes (RFC 572).
|
||||
(internal, rustc_attrs, "1.0.0", None),
|
||||
/// Introduces a hierarchy of `Sized` traits (RFC 3729).
|
||||
(unstable, sized_hierarchy, "CURRENT_RUSTC_VERSION", None),
|
||||
(unstable, sized_hierarchy, "1.89.0", None),
|
||||
/// Allows using the `#[stable]` and `#[unstable]` attributes.
|
||||
(internal, staged_api, "1.0.0", None),
|
||||
/// Added for testing unstable lints; perma-unstable.
|
||||
|
|
@ -356,7 +356,7 @@ declare_features! (
|
|||
/// Allows `extern "cmse-nonsecure-call" fn()`.
|
||||
(unstable, abi_cmse_nonsecure_call, "CURRENT_RUSTC_VERSION", Some(81391)),
|
||||
/// Allows `extern "custom" fn()`.
|
||||
(unstable, abi_custom, "CURRENT_RUSTC_VERSION", Some(140829)),
|
||||
(unstable, abi_custom, "1.89.0", Some(140829)),
|
||||
/// Allows `extern "gpu-kernel" fn()`.
|
||||
(unstable, abi_gpu_kernel, "1.86.0", Some(135467)),
|
||||
/// Allows `extern "msp430-interrupt" fn()`.
|
||||
|
|
@ -376,7 +376,7 @@ declare_features! (
|
|||
/// Allows inherent and trait methods with arbitrary self types that are raw pointers.
|
||||
(unstable, arbitrary_self_types_pointers, "1.83.0", Some(44874)),
|
||||
/// Allows #[cfg(...)] on inline assembly templates and operands.
|
||||
(unstable, asm_cfg, "CURRENT_RUSTC_VERSION", Some(140364)),
|
||||
(unstable, asm_cfg, "1.89.0", Some(140364)),
|
||||
/// Enables experimental inline assembly support for additional architectures.
|
||||
(unstable, asm_experimental_arch, "1.58.0", Some(93335)),
|
||||
/// Enables experimental register support in inline assembly.
|
||||
|
|
@ -481,8 +481,6 @@ declare_features! (
|
|||
(unstable, doc_cfg_hide, "1.57.0", Some(43781)),
|
||||
/// Allows `#[doc(masked)]`.
|
||||
(unstable, doc_masked, "1.21.0", Some(44027)),
|
||||
/// Allows `dyn* Trait` objects.
|
||||
(incomplete, dyn_star, "1.65.0", Some(102425)),
|
||||
/// Allows the .use postfix syntax `x.use` and use closures `use |x| { ... }`
|
||||
(incomplete, ergonomic_clones, "1.87.0", Some(132290)),
|
||||
/// Allows exhaustive pattern matching on types that contain uninhabited types.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ macro_rules! arena_types {
|
|||
[] asm_template: rustc_ast::InlineAsmTemplatePiece,
|
||||
[] attribute: rustc_hir::Attribute,
|
||||
[] owner_info: rustc_hir::OwnerInfo<'tcx>,
|
||||
[] lit: rustc_hir::Lit,
|
||||
[] macro_def: rustc_ast::MacroDef,
|
||||
]);
|
||||
)
|
||||
|
|
|
|||
|
|
@ -956,7 +956,7 @@ impl<'hir> Generics<'hir> {
|
|||
&& let Some(ret_ty) = segment.args().paren_sugar_output()
|
||||
&& let ret_ty = ret_ty.peel_refs()
|
||||
&& let TyKind::TraitObject(_, tagged_ptr) = ret_ty.kind
|
||||
&& let TraitObjectSyntax::Dyn | TraitObjectSyntax::DynStar = tagged_ptr.tag()
|
||||
&& let TraitObjectSyntax::Dyn = tagged_ptr.tag()
|
||||
&& ret_ty.span.can_be_used_for_suggestions()
|
||||
{
|
||||
Some(ret_ty.span)
|
||||
|
|
@ -1807,7 +1807,7 @@ pub struct PatExpr<'hir> {
|
|||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub enum PatExprKind<'hir> {
|
||||
Lit {
|
||||
lit: &'hir Lit,
|
||||
lit: Lit,
|
||||
// FIXME: move this into `Lit` and handle negated literal expressions
|
||||
// once instead of matching on unop neg expressions everywhere.
|
||||
negated: bool,
|
||||
|
|
@ -2734,7 +2734,7 @@ pub enum ExprKind<'hir> {
|
|||
/// A unary operation (e.g., `!x`, `*x`).
|
||||
Unary(UnOp, &'hir Expr<'hir>),
|
||||
/// A literal (e.g., `1`, `"foo"`).
|
||||
Lit(&'hir Lit),
|
||||
Lit(Lit),
|
||||
/// A cast (e.g., `foo as f64`).
|
||||
Cast(&'hir Expr<'hir>, &'hir Ty<'hir>),
|
||||
/// A type ascription (e.g., `x: Foo`). See RFC 3307.
|
||||
|
|
@ -3141,15 +3141,6 @@ pub enum TraitItemKind<'hir> {
|
|||
/// type.
|
||||
Type(GenericBounds<'hir>, Option<&'hir Ty<'hir>>),
|
||||
}
|
||||
impl TraitItemKind<'_> {
|
||||
pub fn descr(&self) -> &'static str {
|
||||
match self {
|
||||
TraitItemKind::Const(..) => "associated constant",
|
||||
TraitItemKind::Fn(..) => "function",
|
||||
TraitItemKind::Type(..) => "associated type",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The bodies for items are stored "out of line", in a separate
|
||||
// hashmap in the `Crate`. Here we just record the hir-id of the item
|
||||
|
|
@ -3211,15 +3202,6 @@ pub enum ImplItemKind<'hir> {
|
|||
/// An associated type.
|
||||
Type(&'hir Ty<'hir>),
|
||||
}
|
||||
impl ImplItemKind<'_> {
|
||||
pub fn descr(&self) -> &'static str {
|
||||
match self {
|
||||
ImplItemKind::Const(..) => "associated constant",
|
||||
ImplItemKind::Fn(..) => "function",
|
||||
ImplItemKind::Type(..) => "associated type",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A constraint on an associated item.
|
||||
///
|
||||
|
|
@ -4418,27 +4400,6 @@ impl ItemKind<'_> {
|
|||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn descr(&self) -> &'static str {
|
||||
match self {
|
||||
ItemKind::ExternCrate(..) => "extern crate",
|
||||
ItemKind::Use(..) => "`use` import",
|
||||
ItemKind::Static(..) => "static item",
|
||||
ItemKind::Const(..) => "constant item",
|
||||
ItemKind::Fn { .. } => "function",
|
||||
ItemKind::Macro(..) => "macro",
|
||||
ItemKind::Mod(..) => "module",
|
||||
ItemKind::ForeignMod { .. } => "extern block",
|
||||
ItemKind::GlobalAsm { .. } => "global asm item",
|
||||
ItemKind::TyAlias(..) => "type alias",
|
||||
ItemKind::Enum(..) => "enum",
|
||||
ItemKind::Struct(..) => "struct",
|
||||
ItemKind::Union(..) => "union",
|
||||
ItemKind::Trait(..) => "trait",
|
||||
ItemKind::TraitAlias(..) => "trait alias",
|
||||
ItemKind::Impl(..) => "implementation",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A reference from an trait to one of its associated items. This
|
||||
|
|
@ -4545,16 +4506,6 @@ pub enum ForeignItemKind<'hir> {
|
|||
Type,
|
||||
}
|
||||
|
||||
impl ForeignItemKind<'_> {
|
||||
pub fn descr(&self) -> &'static str {
|
||||
match self {
|
||||
ForeignItemKind::Fn(..) => "function",
|
||||
ForeignItemKind::Static(..) => "static variable",
|
||||
ForeignItemKind::Type => "type",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A variable captured by a closure.
|
||||
#[derive(Debug, Copy, Clone, HashStable_Generic)]
|
||||
pub struct Upvar {
|
||||
|
|
@ -4862,6 +4813,10 @@ impl<'hir> Node<'hir> {
|
|||
ImplItemKind::Type(ty) => Some(ty),
|
||||
_ => None,
|
||||
},
|
||||
Node::ForeignItem(it) => match it.kind {
|
||||
ForeignItemKind::Static(ty, ..) => Some(ty),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ define_tests! {
|
|||
#[test]
|
||||
fn trait_object_roundtrips() {
|
||||
trait_object_roundtrips_impl(TraitObjectSyntax::Dyn);
|
||||
trait_object_roundtrips_impl(TraitObjectSyntax::DynStar);
|
||||
trait_object_roundtrips_impl(TraitObjectSyntax::None);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -347,7 +347,7 @@ pub trait Visitor<'v>: Sized {
|
|||
fn visit_pat_expr(&mut self, expr: &'v PatExpr<'v>) -> Self::Result {
|
||||
walk_pat_expr(self, expr)
|
||||
}
|
||||
fn visit_lit(&mut self, _hir_id: HirId, _lit: &'v Lit, _negated: bool) -> Self::Result {
|
||||
fn visit_lit(&mut self, _hir_id: HirId, _lit: Lit, _negated: bool) -> Self::Result {
|
||||
Self::Result::output()
|
||||
}
|
||||
fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
|
||||
|
|
@ -786,7 +786,7 @@ pub fn walk_pat_expr<'v, V: Visitor<'v>>(visitor: &mut V, expr: &'v PatExpr<'v>)
|
|||
let PatExpr { hir_id, span, kind } = expr;
|
||||
try_visit!(visitor.visit_id(*hir_id));
|
||||
match kind {
|
||||
PatExprKind::Lit { lit, negated } => visitor.visit_lit(*hir_id, lit, *negated),
|
||||
PatExprKind::Lit { lit, negated } => visitor.visit_lit(*hir_id, *lit, *negated),
|
||||
PatExprKind::ConstBlock(c) => visitor.visit_inline_const(c),
|
||||
PatExprKind::Path(qpath) => visitor.visit_qpath(qpath, *hir_id, *span),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use rustc_errors::{EmissionGuarantee, MultiSpan};
|
|||
use rustc_hir::def::{CtorKind, DefKind};
|
||||
use rustc_hir::{LangItem, Node, intravisit};
|
||||
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
|
||||
use rustc_infer::traits::{Obligation, ObligationCauseCode};
|
||||
use rustc_infer::traits::{Obligation, ObligationCauseCode, WellFormedLoc};
|
||||
use rustc_lint_defs::builtin::{
|
||||
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_CALLING_CONVENTIONS,
|
||||
};
|
||||
|
|
@ -36,6 +36,10 @@ use {rustc_attr_data_structures as attrs, rustc_hir as hir};
|
|||
|
||||
use super::compare_impl_item::check_type_bounds;
|
||||
use super::*;
|
||||
use crate::check::wfcheck::{
|
||||
check_associated_item, check_trait_item, check_variances_for_type_defn, check_where_clauses,
|
||||
enter_wf_checking_ctxt,
|
||||
};
|
||||
|
||||
fn add_abi_diag_help<T: EmissionGuarantee>(abi: ExternAbi, diag: &mut Diag<'_, T>) {
|
||||
if let ExternAbi::Cdecl { unwind } = abi {
|
||||
|
|
@ -729,7 +733,8 @@ fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
|
||||
let mut res = Ok(());
|
||||
let generics = tcx.generics_of(def_id);
|
||||
|
||||
for param in &generics.own_params {
|
||||
|
|
@ -754,15 +759,39 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
}
|
||||
|
||||
match tcx.def_kind(def_id) {
|
||||
DefKind::Static { .. } => {
|
||||
check_static_inhabited(tcx, def_id);
|
||||
check_static_linkage(tcx, def_id);
|
||||
def_kind @ (DefKind::Static { .. } | DefKind::Const) => {
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
match def_kind {
|
||||
DefKind::Static { .. } => {
|
||||
check_static_inhabited(tcx, def_id);
|
||||
check_static_linkage(tcx, def_id);
|
||||
res = res.and(wfcheck::check_static_item(tcx, def_id));
|
||||
|
||||
// Only `Node::Item` and `Node::ForeignItem` still have HIR based
|
||||
// checks. Returning early here does not miss any checks and
|
||||
// avoids this query from having a direct dependency edge on the HIR
|
||||
return res;
|
||||
}
|
||||
DefKind::Const => {}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
DefKind::Const => {}
|
||||
DefKind::Enum => {
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
crate::collect::lower_enum_variant_types(tcx, def_id.to_def_id());
|
||||
check_enum(tcx, def_id);
|
||||
check_variances_for_type_defn(tcx, def_id);
|
||||
}
|
||||
DefKind::Fn => {
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
tcx.ensure_ok().fn_sig(def_id);
|
||||
tcx.ensure_ok().codegen_fn_attrs(def_id);
|
||||
if let Some(i) = tcx.intrinsic(def_id) {
|
||||
intrinsic::check_intrinsic_type(
|
||||
tcx,
|
||||
|
|
@ -773,17 +802,31 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
}
|
||||
}
|
||||
DefKind::Impl { of_trait } => {
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().impl_trait_header(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
tcx.ensure_ok().associated_items(def_id);
|
||||
if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) {
|
||||
if tcx
|
||||
.ensure_ok()
|
||||
.coherent_trait(impl_trait_header.trait_ref.instantiate_identity().def_id)
|
||||
.is_ok()
|
||||
{
|
||||
res = res.and(
|
||||
tcx.ensure_ok()
|
||||
.coherent_trait(impl_trait_header.trait_ref.instantiate_identity().def_id),
|
||||
);
|
||||
|
||||
if res.is_ok() {
|
||||
// Checking this only makes sense if the all trait impls satisfy basic
|
||||
// requirements (see `coherent_trait` query), otherwise
|
||||
// we run into infinite recursions a lot.
|
||||
check_impl_items_against_trait(tcx, def_id, impl_trait_header);
|
||||
}
|
||||
}
|
||||
}
|
||||
DefKind::Trait => {
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().trait_def(def_id);
|
||||
tcx.ensure_ok().explicit_super_predicates_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
tcx.ensure_ok().associated_items(def_id);
|
||||
let assoc_items = tcx.associated_items(def_id);
|
||||
check_on_unimplemented(tcx, def_id);
|
||||
|
||||
|
|
@ -802,11 +845,33 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
}
|
||||
}
|
||||
}
|
||||
DefKind::Struct => {
|
||||
check_struct(tcx, def_id);
|
||||
DefKind::TraitAlias => {
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().explicit_implied_predicates_of(def_id);
|
||||
tcx.ensure_ok().explicit_super_predicates_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
}
|
||||
DefKind::Union => {
|
||||
check_union(tcx, def_id);
|
||||
def_kind @ (DefKind::Struct | DefKind::Union) => {
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
|
||||
let adt = tcx.adt_def(def_id).non_enum_variant();
|
||||
for f in adt.fields.iter() {
|
||||
tcx.ensure_ok().generics_of(f.did);
|
||||
tcx.ensure_ok().type_of(f.did);
|
||||
tcx.ensure_ok().predicates_of(f.did);
|
||||
}
|
||||
|
||||
if let Some((_, ctor_def_id)) = adt.ctor {
|
||||
crate::collect::lower_variant_ctor(tcx, ctor_def_id.expect_local());
|
||||
}
|
||||
match def_kind {
|
||||
DefKind::Struct => check_struct(tcx, def_id),
|
||||
DefKind::Union => check_union(tcx, def_id),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
check_variances_for_type_defn(tcx, def_id);
|
||||
}
|
||||
DefKind::OpaqueTy => {
|
||||
check_opaque_precise_captures(tcx, def_id);
|
||||
|
|
@ -831,14 +896,37 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
tcx.ensure_ok().explicit_implied_const_bounds(def_id);
|
||||
tcx.ensure_ok().const_conditions(def_id);
|
||||
}
|
||||
|
||||
// Only `Node::Item` and `Node::ForeignItem` still have HIR based
|
||||
// checks. Returning early here does not miss any checks and
|
||||
// avoids this query from having a direct dependency edge on the HIR
|
||||
return res;
|
||||
}
|
||||
DefKind::TyAlias => {
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
check_type_alias_type_params_are_used(tcx, def_id);
|
||||
if tcx.type_alias_is_lazy(def_id) {
|
||||
res = res.and(enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
|
||||
let ty = tcx.type_of(def_id).instantiate_identity();
|
||||
let span = tcx.def_span(def_id);
|
||||
let item_ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), ty);
|
||||
wfcx.register_wf_obligation(
|
||||
span,
|
||||
Some(WellFormedLoc::Ty(def_id)),
|
||||
item_ty.into(),
|
||||
);
|
||||
check_where_clauses(wfcx, def_id);
|
||||
Ok(())
|
||||
}));
|
||||
check_variances_for_type_defn(tcx, def_id);
|
||||
}
|
||||
}
|
||||
DefKind::ForeignMod => {
|
||||
let it = tcx.hir_expect_item(def_id);
|
||||
let hir::ItemKind::ForeignMod { abi, items } = it.kind else {
|
||||
return;
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
check_abi(tcx, it.hir_id(), it.span, abi);
|
||||
|
|
@ -877,15 +965,23 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
}
|
||||
|
||||
let item = tcx.hir_foreign_item(item.id);
|
||||
match &item.kind {
|
||||
hir::ForeignItemKind::Fn(sig, _, _) => {
|
||||
tcx.ensure_ok().generics_of(item.owner_id);
|
||||
tcx.ensure_ok().type_of(item.owner_id);
|
||||
tcx.ensure_ok().predicates_of(item.owner_id);
|
||||
if tcx.is_conditionally_const(def_id) {
|
||||
tcx.ensure_ok().explicit_implied_const_bounds(def_id);
|
||||
tcx.ensure_ok().const_conditions(def_id);
|
||||
}
|
||||
match item.kind {
|
||||
hir::ForeignItemKind::Fn(sig, ..) => {
|
||||
tcx.ensure_ok().codegen_fn_attrs(item.owner_id);
|
||||
tcx.ensure_ok().fn_sig(item.owner_id);
|
||||
require_c_abi_if_c_variadic(tcx, sig.decl, abi, item.span);
|
||||
}
|
||||
hir::ForeignItemKind::Static(..) => {
|
||||
check_static_inhabited(tcx, def_id);
|
||||
check_static_linkage(tcx, def_id);
|
||||
tcx.ensure_ok().codegen_fn_attrs(item.owner_id);
|
||||
}
|
||||
_ => {}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -897,9 +993,85 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
// We do not call `type_of` for closures here as that
|
||||
// depends on typecheck and would therefore hide
|
||||
// any further errors in case one typeck fails.
|
||||
|
||||
// Only `Node::Item` and `Node::ForeignItem` still have HIR based
|
||||
// checks. Returning early here does not miss any checks and
|
||||
// avoids this query from having a direct dependency edge on the HIR
|
||||
return res;
|
||||
}
|
||||
DefKind::AssocFn => {
|
||||
tcx.ensure_ok().codegen_fn_attrs(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().fn_sig(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
res = res.and(check_associated_item(tcx, def_id));
|
||||
let assoc_item = tcx.associated_item(def_id);
|
||||
match assoc_item.container {
|
||||
ty::AssocItemContainer::Impl => {}
|
||||
ty::AssocItemContainer::Trait => {
|
||||
res = res.and(check_trait_item(tcx, def_id));
|
||||
}
|
||||
}
|
||||
|
||||
// Only `Node::Item` and `Node::ForeignItem` still have HIR based
|
||||
// checks. Returning early here does not miss any checks and
|
||||
// avoids this query from having a direct dependency edge on the HIR
|
||||
return res;
|
||||
}
|
||||
DefKind::AssocConst => {
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
res = res.and(check_associated_item(tcx, def_id));
|
||||
let assoc_item = tcx.associated_item(def_id);
|
||||
match assoc_item.container {
|
||||
ty::AssocItemContainer::Impl => {}
|
||||
ty::AssocItemContainer::Trait => {
|
||||
res = res.and(check_trait_item(tcx, def_id));
|
||||
}
|
||||
}
|
||||
|
||||
// Only `Node::Item` and `Node::ForeignItem` still have HIR based
|
||||
// checks. Returning early here does not miss any checks and
|
||||
// avoids this query from having a direct dependency edge on the HIR
|
||||
return res;
|
||||
}
|
||||
DefKind::AssocTy => {
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
res = res.and(check_associated_item(tcx, def_id));
|
||||
|
||||
let assoc_item = tcx.associated_item(def_id);
|
||||
let has_type = match assoc_item.container {
|
||||
ty::AssocItemContainer::Impl => true,
|
||||
ty::AssocItemContainer::Trait => {
|
||||
tcx.ensure_ok().item_bounds(def_id);
|
||||
tcx.ensure_ok().item_self_bounds(def_id);
|
||||
res = res.and(check_trait_item(tcx, def_id));
|
||||
assoc_item.defaultness(tcx).has_value()
|
||||
}
|
||||
};
|
||||
if has_type {
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
}
|
||||
|
||||
// Only `Node::Item` and `Node::ForeignItem` still have HIR based
|
||||
// checks. Returning early here does not miss any checks and
|
||||
// avoids this query from having a direct dependency edge on the HIR
|
||||
return res;
|
||||
}
|
||||
|
||||
// Only `Node::Item` and `Node::ForeignItem` still have HIR based
|
||||
// checks. Returning early here does not miss any checks and
|
||||
// avoids this query from having a direct dependency edge on the HIR
|
||||
DefKind::AnonConst | DefKind::InlineConst => return res,
|
||||
_ => {}
|
||||
}
|
||||
let node = tcx.hir_node_by_def_id(def_id);
|
||||
res.and(match node {
|
||||
hir::Node::Crate(_) => bug!("check_well_formed cannot be applied to the crate root"),
|
||||
hir::Node::Item(item) => wfcheck::check_item(tcx, item),
|
||||
hir::Node::ForeignItem(item) => wfcheck::check_foreign_item(tcx, item),
|
||||
_ => unreachable!("{node:?}"),
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ use rustc_middle::ty::{
|
|||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::{DUMMY_SP, Ident, Span, sym};
|
||||
use rustc_span::{DUMMY_SP, Span, sym};
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::regions::{InferCtxtRegionExt, OutlivesEnvironmentBuildExt};
|
||||
use rustc_trait_selection::traits::misc::{
|
||||
|
|
@ -46,7 +46,6 @@ use crate::{errors, fluent_generated as fluent};
|
|||
|
||||
pub(super) struct WfCheckingCtxt<'a, 'tcx> {
|
||||
pub(super) ocx: ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>>,
|
||||
span: Span,
|
||||
body_def_id: LocalDefId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
}
|
||||
|
|
@ -84,7 +83,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
|
|||
/// signature types for implied bounds when checking regions.
|
||||
// FIXME(-Znext-solver): This should be removed when we compute implied outlives
|
||||
// bounds using the unnormalized signature of the function we're checking.
|
||||
fn deeply_normalize<T>(&self, span: Span, loc: Option<WellFormedLoc>, value: T) -> T
|
||||
pub(super) fn deeply_normalize<T>(&self, span: Span, loc: Option<WellFormedLoc>, value: T) -> T
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
|
|
@ -105,7 +104,12 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn register_wf_obligation(&self, span: Span, loc: Option<WellFormedLoc>, term: ty::Term<'tcx>) {
|
||||
pub(super) fn register_wf_obligation(
|
||||
&self,
|
||||
span: Span,
|
||||
loc: Option<WellFormedLoc>,
|
||||
term: ty::Term<'tcx>,
|
||||
) {
|
||||
let cause = traits::ObligationCause::new(
|
||||
span,
|
||||
self.body_def_id,
|
||||
|
|
@ -122,7 +126,6 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
|
|||
|
||||
pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
span: Span,
|
||||
body_def_id: LocalDefId,
|
||||
f: F,
|
||||
) -> Result<(), ErrorGuaranteed>
|
||||
|
|
@ -133,7 +136,7 @@ where
|
|||
let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
|
||||
|
||||
let mut wfcx = WfCheckingCtxt { ocx, span, body_def_id, param_env };
|
||||
let mut wfcx = WfCheckingCtxt { ocx, body_def_id, param_env };
|
||||
|
||||
if !tcx.features().trivial_bounds() {
|
||||
wfcx.check_false_global_bounds()
|
||||
|
|
@ -187,23 +190,10 @@ where
|
|||
}
|
||||
|
||||
fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
|
||||
let node = tcx.hir_node_by_def_id(def_id);
|
||||
let mut res = match node {
|
||||
hir::Node::Crate(_) => bug!("check_well_formed cannot be applied to the crate root"),
|
||||
hir::Node::Item(item) => check_item(tcx, item),
|
||||
hir::Node::TraitItem(item) => check_trait_item(tcx, item),
|
||||
hir::Node::ImplItem(item) => check_impl_item(tcx, item),
|
||||
hir::Node::ForeignItem(item) => check_foreign_item(tcx, item),
|
||||
hir::Node::ConstBlock(_) | hir::Node::Expr(_) | hir::Node::OpaqueTy(_) => {
|
||||
Ok(crate::check::check::check_item_type(tcx, def_id))
|
||||
}
|
||||
_ => unreachable!("{node:?}"),
|
||||
};
|
||||
let mut res = crate::check::check::check_item_type(tcx, def_id);
|
||||
|
||||
if let Some(generics) = node.generics() {
|
||||
for param in generics.params {
|
||||
res = res.and(check_param_wf(tcx, param));
|
||||
}
|
||||
for param in &tcx.generics_of(def_id).own_params {
|
||||
res = res.and(check_param_wf(tcx, param));
|
||||
}
|
||||
|
||||
res
|
||||
|
|
@ -223,16 +213,18 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGua
|
|||
/// not included it frequently leads to confusing errors in fn bodies. So it's better to check
|
||||
/// the types first.
|
||||
#[instrument(skip(tcx), level = "debug")]
|
||||
fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<(), ErrorGuaranteed> {
|
||||
pub(super) fn check_item<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
item: &'tcx hir::Item<'tcx>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let def_id = item.owner_id.def_id;
|
||||
|
||||
debug!(
|
||||
?item.owner_id,
|
||||
item.name = ? tcx.def_path_str(def_id)
|
||||
);
|
||||
crate::collect::lower_item(tcx, item.item_id());
|
||||
|
||||
let res = match item.kind {
|
||||
match item.kind {
|
||||
// Right now we check that every default trait implementation
|
||||
// has an implementation of itself. Basically, a case like:
|
||||
//
|
||||
|
|
@ -295,57 +287,18 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
|
|||
}
|
||||
res
|
||||
}
|
||||
hir::ItemKind::Fn { ident, sig, .. } => {
|
||||
check_item_fn(tcx, def_id, ident, item.span, sig.decl)
|
||||
}
|
||||
hir::ItemKind::Static(_, _, ty, _) => {
|
||||
check_static_item(tcx, def_id, ty.span, UnsizedHandling::Forbid)
|
||||
}
|
||||
hir::ItemKind::Const(_, _, ty, _) => check_const_item(tcx, def_id, ty.span, item.span),
|
||||
hir::ItemKind::Struct(_, generics, _) => {
|
||||
let res = check_type_defn(tcx, item, false);
|
||||
check_variances_for_type_defn(tcx, item, generics);
|
||||
res
|
||||
}
|
||||
hir::ItemKind::Union(_, generics, _) => {
|
||||
let res = check_type_defn(tcx, item, true);
|
||||
check_variances_for_type_defn(tcx, item, generics);
|
||||
res
|
||||
}
|
||||
hir::ItemKind::Enum(_, generics, _) => {
|
||||
let res = check_type_defn(tcx, item, true);
|
||||
check_variances_for_type_defn(tcx, item, generics);
|
||||
res
|
||||
}
|
||||
hir::ItemKind::Fn { sig, .. } => check_item_fn(tcx, def_id, sig.decl),
|
||||
hir::ItemKind::Const(_, _, ty, _) => check_const_item(tcx, def_id, ty.span),
|
||||
hir::ItemKind::Struct(..) => check_type_defn(tcx, item, false),
|
||||
hir::ItemKind::Union(..) => check_type_defn(tcx, item, true),
|
||||
hir::ItemKind::Enum(..) => check_type_defn(tcx, item, true),
|
||||
hir::ItemKind::Trait(..) => check_trait(tcx, item),
|
||||
hir::ItemKind::TraitAlias(..) => check_trait(tcx, item),
|
||||
// `ForeignItem`s are handled separately.
|
||||
hir::ItemKind::ForeignMod { .. } => Ok(()),
|
||||
hir::ItemKind::TyAlias(_, generics, hir_ty) if tcx.type_alias_is_lazy(item.owner_id) => {
|
||||
let res = enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| {
|
||||
let ty = tcx.type_of(def_id).instantiate_identity();
|
||||
let item_ty =
|
||||
wfcx.deeply_normalize(hir_ty.span, Some(WellFormedLoc::Ty(def_id)), ty);
|
||||
wfcx.register_wf_obligation(
|
||||
hir_ty.span,
|
||||
Some(WellFormedLoc::Ty(def_id)),
|
||||
item_ty.into(),
|
||||
);
|
||||
check_where_clauses(wfcx, item.span, def_id);
|
||||
Ok(())
|
||||
});
|
||||
check_variances_for_type_defn(tcx, item, generics);
|
||||
res
|
||||
}
|
||||
_ => Ok(()),
|
||||
};
|
||||
|
||||
crate::check::check::check_item_type(tcx, def_id);
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
fn check_foreign_item<'tcx>(
|
||||
pub(super) fn check_foreign_item<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
item: &'tcx hir::ForeignItem<'tcx>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
|
|
@ -357,43 +310,23 @@ fn check_foreign_item<'tcx>(
|
|||
);
|
||||
|
||||
match item.kind {
|
||||
hir::ForeignItemKind::Fn(sig, ..) => {
|
||||
check_item_fn(tcx, def_id, item.ident, item.span, sig.decl)
|
||||
}
|
||||
hir::ForeignItemKind::Static(ty, ..) => {
|
||||
check_static_item(tcx, def_id, ty.span, UnsizedHandling::AllowIfForeignTail)
|
||||
}
|
||||
hir::ForeignItemKind::Type => Ok(()),
|
||||
hir::ForeignItemKind::Fn(sig, ..) => check_item_fn(tcx, def_id, sig.decl),
|
||||
hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
fn check_trait_item<'tcx>(
|
||||
pub(crate) fn check_trait_item<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_item: &'tcx hir::TraitItem<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let def_id = trait_item.owner_id.def_id;
|
||||
|
||||
crate::collect::lower_trait_item(tcx, trait_item.trait_item_id());
|
||||
|
||||
let (method_sig, span) = match trait_item.kind {
|
||||
hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span),
|
||||
hir::TraitItemKind::Type(_bounds, Some(ty)) => (None, ty.span),
|
||||
_ => (None, trait_item.span),
|
||||
};
|
||||
|
||||
// Check that an item definition in a subtrait is shadowing a supertrait item.
|
||||
lint_item_shadowing_supertrait_item(tcx, def_id);
|
||||
|
||||
let mut res = check_associated_item(tcx, def_id, span, method_sig);
|
||||
let mut res = Ok(());
|
||||
|
||||
if matches!(trait_item.kind, hir::TraitItemKind::Fn(..)) {
|
||||
if matches!(tcx.def_kind(def_id), DefKind::AssocFn) {
|
||||
for &assoc_ty_def_id in tcx.associated_types_for_impl_traits_in_associated_fn(def_id) {
|
||||
res = res.and(check_associated_item(
|
||||
tcx,
|
||||
assoc_ty_def_id.expect_local(),
|
||||
tcx.def_span(assoc_ty_def_id),
|
||||
None,
|
||||
));
|
||||
res = res.and(check_associated_item(tcx, assoc_ty_def_id.expect_local()));
|
||||
}
|
||||
}
|
||||
res
|
||||
|
|
@ -872,67 +805,54 @@ fn lint_item_shadowing_supertrait_item<'tcx>(tcx: TyCtxt<'tcx>, trait_item_def_i
|
|||
}
|
||||
}
|
||||
|
||||
fn check_impl_item<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
impl_item: &'tcx hir::ImplItem<'tcx>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
crate::collect::lower_impl_item(tcx, impl_item.impl_item_id());
|
||||
|
||||
let (method_sig, span) = match impl_item.kind {
|
||||
hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span),
|
||||
// Constrain binding and overflow error spans to `<Ty>` in `type foo = <Ty>`.
|
||||
hir::ImplItemKind::Type(ty) if ty.span != DUMMY_SP => (None, ty.span),
|
||||
_ => (None, impl_item.span),
|
||||
};
|
||||
check_associated_item(tcx, impl_item.owner_id.def_id, span, method_sig)
|
||||
}
|
||||
|
||||
fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(), ErrorGuaranteed> {
|
||||
fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), ErrorGuaranteed> {
|
||||
match param.kind {
|
||||
// We currently only check wf of const params here.
|
||||
hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => Ok(()),
|
||||
ty::GenericParamDefKind::Lifetime | ty::GenericParamDefKind::Type { .. } => Ok(()),
|
||||
|
||||
// Const parameters are well formed if their type is structural match.
|
||||
hir::GenericParamKind::Const { ty: hir_ty, default: _, synthetic: _ } => {
|
||||
ty::GenericParamDefKind::Const { .. } => {
|
||||
let ty = tcx.type_of(param.def_id).instantiate_identity();
|
||||
let span = tcx.def_span(param.def_id);
|
||||
let def_id = param.def_id.expect_local();
|
||||
|
||||
if tcx.features().unsized_const_params() {
|
||||
enter_wf_checking_ctxt(tcx, hir_ty.span, tcx.local_parent(param.def_id), |wfcx| {
|
||||
enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {
|
||||
wfcx.register_bound(
|
||||
ObligationCause::new(
|
||||
hir_ty.span,
|
||||
param.def_id,
|
||||
ObligationCauseCode::ConstParam(ty),
|
||||
),
|
||||
ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(ty)),
|
||||
wfcx.param_env,
|
||||
ty,
|
||||
tcx.require_lang_item(LangItem::UnsizedConstParamTy, hir_ty.span),
|
||||
tcx.require_lang_item(LangItem::UnsizedConstParamTy, span),
|
||||
);
|
||||
Ok(())
|
||||
})
|
||||
} else if tcx.features().adt_const_params() {
|
||||
enter_wf_checking_ctxt(tcx, hir_ty.span, tcx.local_parent(param.def_id), |wfcx| {
|
||||
enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {
|
||||
wfcx.register_bound(
|
||||
ObligationCause::new(
|
||||
hir_ty.span,
|
||||
param.def_id,
|
||||
ObligationCauseCode::ConstParam(ty),
|
||||
),
|
||||
ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(ty)),
|
||||
wfcx.param_env,
|
||||
ty,
|
||||
tcx.require_lang_item(LangItem::ConstParamTy, hir_ty.span),
|
||||
tcx.require_lang_item(LangItem::ConstParamTy, span),
|
||||
);
|
||||
Ok(())
|
||||
})
|
||||
} else {
|
||||
let span = || {
|
||||
let hir::GenericParamKind::Const { ty: &hir::Ty { span, .. }, .. } =
|
||||
tcx.hir_node_by_def_id(def_id).expect_generic_param().kind
|
||||
else {
|
||||
bug!()
|
||||
};
|
||||
span
|
||||
};
|
||||
let mut diag = match ty.kind() {
|
||||
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => return Ok(()),
|
||||
ty::FnPtr(..) => tcx.dcx().struct_span_err(
|
||||
hir_ty.span,
|
||||
span(),
|
||||
"using function pointers as const generic parameters is forbidden",
|
||||
),
|
||||
ty::RawPtr(_, _) => tcx.dcx().struct_span_err(
|
||||
hir_ty.span,
|
||||
span(),
|
||||
"using raw pointers as const generic parameters is forbidden",
|
||||
),
|
||||
_ => {
|
||||
|
|
@ -940,7 +860,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
|
|||
ty.error_reported()?;
|
||||
|
||||
tcx.dcx().struct_span_err(
|
||||
hir_ty.span,
|
||||
span(),
|
||||
format!(
|
||||
"`{ty}` is forbidden as the type of a const generic parameter",
|
||||
),
|
||||
|
|
@ -950,7 +870,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
|
|||
|
||||
diag.note("the only supported types are integers, `bool`, and `char`");
|
||||
|
||||
let cause = ObligationCause::misc(hir_ty.span, param.def_id);
|
||||
let cause = ObligationCause::misc(span(), def_id);
|
||||
let adt_const_params_feature_string =
|
||||
" more complex and user defined types".to_string();
|
||||
let may_suggest_feature = match type_allowed_to_implement_const_param_ty(
|
||||
|
|
@ -1010,15 +930,13 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(tcx, span, sig_if_method))]
|
||||
fn check_associated_item(
|
||||
#[instrument(level = "debug", skip(tcx))]
|
||||
pub(crate) fn check_associated_item(
|
||||
tcx: TyCtxt<'_>,
|
||||
item_id: LocalDefId,
|
||||
span: Span,
|
||||
sig_if_method: Option<&hir::FnSig<'_>>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let loc = Some(WellFormedLoc::Ty(item_id));
|
||||
enter_wf_checking_ctxt(tcx, span, item_id, |wfcx| {
|
||||
enter_wf_checking_ctxt(tcx, item_id, |wfcx| {
|
||||
let item = tcx.associated_item(item_id);
|
||||
|
||||
// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
|
||||
|
|
@ -1033,6 +951,8 @@ fn check_associated_item(
|
|||
}
|
||||
};
|
||||
|
||||
let span = tcx.def_span(item_id);
|
||||
|
||||
match item.kind {
|
||||
ty::AssocKind::Const { .. } => {
|
||||
let ty = tcx.type_of(item.def_id).instantiate_identity();
|
||||
|
|
@ -1049,14 +969,9 @@ fn check_associated_item(
|
|||
}
|
||||
ty::AssocKind::Fn { .. } => {
|
||||
let sig = tcx.fn_sig(item.def_id).instantiate_identity();
|
||||
let hir_sig = sig_if_method.expect("bad signature for method");
|
||||
check_fn_or_method(
|
||||
wfcx,
|
||||
item.ident(tcx).span,
|
||||
sig,
|
||||
hir_sig.decl,
|
||||
item.def_id.expect_local(),
|
||||
);
|
||||
let hir_sig =
|
||||
tcx.hir_node_by_def_id(item_id).fn_sig().expect("bad signature for method");
|
||||
check_fn_or_method(wfcx, sig, hir_sig.decl, item_id);
|
||||
check_method_receiver(wfcx, hir_sig, item, self_ty)
|
||||
}
|
||||
ty::AssocKind::Type { .. } => {
|
||||
|
|
@ -1083,7 +998,7 @@ fn check_type_defn<'tcx>(
|
|||
let _ = tcx.representability(item.owner_id.def_id);
|
||||
let adt_def = tcx.adt_def(item.owner_id);
|
||||
|
||||
enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| {
|
||||
enter_wf_checking_ctxt(tcx, item.owner_id.def_id, |wfcx| {
|
||||
let variants = adt_def.variants();
|
||||
let packed = adt_def.repr().packed();
|
||||
|
||||
|
|
@ -1185,7 +1100,7 @@ fn check_type_defn<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
check_where_clauses(wfcx, item.span, item.owner_id.def_id);
|
||||
check_where_clauses(wfcx, item.owner_id.def_id);
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
|
@ -1215,8 +1130,8 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) -> Result<(), ErrorGuarant
|
|||
}
|
||||
}
|
||||
|
||||
let res = enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| {
|
||||
check_where_clauses(wfcx, item.span, def_id);
|
||||
let res = enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
|
||||
check_where_clauses(wfcx, def_id);
|
||||
Ok(())
|
||||
});
|
||||
|
||||
|
|
@ -1252,72 +1167,63 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt
|
|||
fn check_item_fn(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: LocalDefId,
|
||||
ident: Ident,
|
||||
span: Span,
|
||||
decl: &hir::FnDecl<'_>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
enter_wf_checking_ctxt(tcx, span, def_id, |wfcx| {
|
||||
enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
|
||||
let sig = tcx.fn_sig(def_id).instantiate_identity();
|
||||
check_fn_or_method(wfcx, ident.span, sig, decl, def_id);
|
||||
check_fn_or_method(wfcx, sig, decl, def_id);
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
enum UnsizedHandling {
|
||||
Forbid,
|
||||
AllowIfForeignTail,
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(tcx, ty_span, unsized_handling))]
|
||||
fn check_static_item(
|
||||
#[instrument(level = "debug", skip(tcx))]
|
||||
pub(super) fn check_static_item(
|
||||
tcx: TyCtxt<'_>,
|
||||
item_id: LocalDefId,
|
||||
ty_span: Span,
|
||||
unsized_handling: UnsizedHandling,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| {
|
||||
enter_wf_checking_ctxt(tcx, item_id, |wfcx| {
|
||||
let ty = tcx.type_of(item_id).instantiate_identity();
|
||||
let item_ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);
|
||||
let item_ty = wfcx.deeply_normalize(DUMMY_SP, Some(WellFormedLoc::Ty(item_id)), ty);
|
||||
|
||||
let forbid_unsized = match unsized_handling {
|
||||
UnsizedHandling::Forbid => true,
|
||||
UnsizedHandling::AllowIfForeignTail => {
|
||||
let tail =
|
||||
tcx.struct_tail_for_codegen(item_ty, wfcx.infcx.typing_env(wfcx.param_env));
|
||||
!matches!(tail.kind(), ty::Foreign(_))
|
||||
}
|
||||
let is_foreign_item = tcx.is_foreign_item(item_id);
|
||||
|
||||
let forbid_unsized = !is_foreign_item || {
|
||||
let tail = tcx.struct_tail_for_codegen(item_ty, wfcx.infcx.typing_env(wfcx.param_env));
|
||||
!matches!(tail.kind(), ty::Foreign(_))
|
||||
};
|
||||
|
||||
wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(item_id)), item_ty.into());
|
||||
wfcx.register_wf_obligation(DUMMY_SP, Some(WellFormedLoc::Ty(item_id)), item_ty.into());
|
||||
if forbid_unsized {
|
||||
let span = tcx.def_span(item_id);
|
||||
wfcx.register_bound(
|
||||
traits::ObligationCause::new(
|
||||
ty_span,
|
||||
span,
|
||||
wfcx.body_def_id,
|
||||
ObligationCauseCode::SizedConstOrStatic,
|
||||
),
|
||||
wfcx.param_env,
|
||||
item_ty,
|
||||
tcx.require_lang_item(LangItem::Sized, ty_span),
|
||||
tcx.require_lang_item(LangItem::Sized, span),
|
||||
);
|
||||
}
|
||||
|
||||
// Ensure that the end result is `Sync` in a non-thread local `static`.
|
||||
let should_check_for_sync = tcx.static_mutability(item_id.to_def_id())
|
||||
== Some(hir::Mutability::Not)
|
||||
&& !tcx.is_foreign_item(item_id.to_def_id())
|
||||
&& !is_foreign_item
|
||||
&& !tcx.is_thread_local_static(item_id.to_def_id());
|
||||
|
||||
if should_check_for_sync {
|
||||
let span = tcx.def_span(item_id);
|
||||
wfcx.register_bound(
|
||||
traits::ObligationCause::new(
|
||||
ty_span,
|
||||
span,
|
||||
wfcx.body_def_id,
|
||||
ObligationCauseCode::SharedStatic,
|
||||
),
|
||||
wfcx.param_env,
|
||||
item_ty,
|
||||
tcx.require_lang_item(LangItem::Sync, ty_span),
|
||||
tcx.require_lang_item(LangItem::Sync, span),
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -1328,9 +1234,8 @@ fn check_const_item(
|
|||
tcx: TyCtxt<'_>,
|
||||
def_id: LocalDefId,
|
||||
ty_span: Span,
|
||||
item_span: Span,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
enter_wf_checking_ctxt(tcx, ty_span, def_id, |wfcx| {
|
||||
enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
|
||||
let ty = tcx.type_of(def_id).instantiate_identity();
|
||||
let ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(def_id)), ty);
|
||||
|
||||
|
|
@ -1346,7 +1251,7 @@ fn check_const_item(
|
|||
tcx.require_lang_item(LangItem::Sized, ty_span),
|
||||
);
|
||||
|
||||
check_where_clauses(wfcx, item_span, def_id);
|
||||
check_where_clauses(wfcx, def_id);
|
||||
|
||||
Ok(())
|
||||
})
|
||||
|
|
@ -1359,7 +1264,7 @@ fn check_impl<'tcx>(
|
|||
hir_self_ty: &hir::Ty<'_>,
|
||||
hir_trait_ref: &Option<hir::TraitRef<'_>>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| {
|
||||
enter_wf_checking_ctxt(tcx, item.owner_id.def_id, |wfcx| {
|
||||
match hir_trait_ref {
|
||||
Some(hir_trait_ref) => {
|
||||
// `#[rustc_reservation_impl]` impls are not real impls and
|
||||
|
|
@ -1443,14 +1348,14 @@ fn check_impl<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
check_where_clauses(wfcx, item.span, item.owner_id.def_id);
|
||||
check_where_clauses(wfcx, item.owner_id.def_id);
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Checks where-clauses and inline bounds that are declared on `def_id`.
|
||||
#[instrument(level = "debug", skip(wfcx))]
|
||||
fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id: LocalDefId) {
|
||||
pub(super) fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, def_id: LocalDefId) {
|
||||
let infcx = wfcx.infcx;
|
||||
let tcx = wfcx.tcx();
|
||||
|
||||
|
|
@ -1605,21 +1510,18 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
|||
|
||||
let predicates = predicates.instantiate_identity(tcx);
|
||||
|
||||
let predicates = wfcx.normalize(span, None, predicates);
|
||||
|
||||
debug!(?predicates.predicates);
|
||||
assert_eq!(predicates.predicates.len(), predicates.spans.len());
|
||||
let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| {
|
||||
let p = wfcx.normalize(sp, None, p);
|
||||
traits::wf::clause_obligations(infcx, wfcx.param_env, wfcx.body_def_id, p, sp)
|
||||
});
|
||||
let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect();
|
||||
wfcx.register_obligations(obligations);
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(wfcx, span, hir_decl))]
|
||||
#[instrument(level = "debug", skip(wfcx, hir_decl))]
|
||||
fn check_fn_or_method<'tcx>(
|
||||
wfcx: &WfCheckingCtxt<'_, 'tcx>,
|
||||
span: Span,
|
||||
sig: ty::PolyFnSig<'tcx>,
|
||||
hir_decl: &hir::FnDecl<'_>,
|
||||
def_id: LocalDefId,
|
||||
|
|
@ -1657,7 +1559,7 @@ fn check_fn_or_method<'tcx>(
|
|||
);
|
||||
}
|
||||
|
||||
check_where_clauses(wfcx, span, def_id);
|
||||
check_where_clauses(wfcx, def_id);
|
||||
|
||||
if sig.abi == ExternAbi::RustCall {
|
||||
let span = tcx.def_span(def_id);
|
||||
|
|
@ -1746,17 +1648,18 @@ fn check_method_receiver<'tcx>(
|
|||
}
|
||||
|
||||
let span = fn_sig.decl.inputs[0].span;
|
||||
let loc = Some(WellFormedLoc::Param { function: method.def_id.expect_local(), param_idx: 0 });
|
||||
|
||||
let sig = tcx.fn_sig(method.def_id).instantiate_identity();
|
||||
let sig = tcx.liberate_late_bound_regions(method.def_id, sig);
|
||||
let sig = wfcx.normalize(span, None, sig);
|
||||
let sig = wfcx.normalize(DUMMY_SP, loc, sig);
|
||||
|
||||
debug!("check_method_receiver: sig={:?}", sig);
|
||||
|
||||
let self_ty = wfcx.normalize(span, None, self_ty);
|
||||
let self_ty = wfcx.normalize(DUMMY_SP, loc, self_ty);
|
||||
|
||||
let receiver_ty = sig.inputs()[0];
|
||||
let receiver_ty = wfcx.normalize(span, None, receiver_ty);
|
||||
let receiver_ty = wfcx.normalize(DUMMY_SP, loc, receiver_ty);
|
||||
|
||||
// If the receiver already has errors reported, consider it valid to avoid
|
||||
// unnecessary errors (#58712).
|
||||
|
|
@ -2004,27 +1907,23 @@ fn legacy_receiver_is_implemented<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
fn check_variances_for_type_defn<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
item: &'tcx hir::Item<'tcx>,
|
||||
hir_generics: &hir::Generics<'tcx>,
|
||||
) {
|
||||
match item.kind {
|
||||
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
|
||||
pub(super) fn check_variances_for_type_defn<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
|
||||
match tcx.def_kind(def_id) {
|
||||
DefKind::Enum | DefKind::Struct | DefKind::Union => {
|
||||
// Ok
|
||||
}
|
||||
ItemKind::TyAlias(..) => {
|
||||
DefKind::TyAlias => {
|
||||
assert!(
|
||||
tcx.type_alias_is_lazy(item.owner_id),
|
||||
tcx.type_alias_is_lazy(def_id),
|
||||
"should not be computing variance of non-free type alias"
|
||||
);
|
||||
}
|
||||
kind => span_bug!(item.span, "cannot compute the variances of {kind:?}"),
|
||||
kind => span_bug!(tcx.def_span(def_id), "cannot compute the variances of {kind:?}"),
|
||||
}
|
||||
|
||||
let ty_predicates = tcx.predicates_of(item.owner_id);
|
||||
let ty_predicates = tcx.predicates_of(def_id);
|
||||
assert_eq!(ty_predicates.parent, None);
|
||||
let variances = tcx.variances_of(item.owner_id);
|
||||
let variances = tcx.variances_of(def_id);
|
||||
|
||||
let mut constrained_parameters: FxHashSet<_> = variances
|
||||
.iter()
|
||||
|
|
@ -2037,8 +1936,10 @@ fn check_variances_for_type_defn<'tcx>(
|
|||
|
||||
// Lazily calculated because it is only needed in case of an error.
|
||||
let explicitly_bounded_params = LazyCell::new(|| {
|
||||
let icx = crate::collect::ItemCtxt::new(tcx, item.owner_id.def_id);
|
||||
hir_generics
|
||||
let icx = crate::collect::ItemCtxt::new(tcx, def_id);
|
||||
tcx.hir_node_by_def_id(def_id)
|
||||
.generics()
|
||||
.unwrap()
|
||||
.predicates
|
||||
.iter()
|
||||
.filter_map(|predicate| match predicate.kind {
|
||||
|
|
@ -2053,8 +1954,6 @@ fn check_variances_for_type_defn<'tcx>(
|
|||
.collect::<FxHashSet<_>>()
|
||||
});
|
||||
|
||||
let ty_generics = tcx.generics_of(item.owner_id);
|
||||
|
||||
for (index, _) in variances.iter().enumerate() {
|
||||
let parameter = Parameter(index as u32);
|
||||
|
||||
|
|
@ -2062,9 +1961,13 @@ fn check_variances_for_type_defn<'tcx>(
|
|||
continue;
|
||||
}
|
||||
|
||||
let ty_param = &ty_generics.own_params[index];
|
||||
let node = tcx.hir_node_by_def_id(def_id);
|
||||
let item = node.expect_item();
|
||||
let hir_generics = node.generics().unwrap();
|
||||
let hir_param = &hir_generics.params[index];
|
||||
|
||||
let ty_param = &tcx.generics_of(item.owner_id).own_params[index];
|
||||
|
||||
if ty_param.def_id != hir_param.def_id.into() {
|
||||
// Valid programs always have lifetimes before types in the generic parameter list.
|
||||
// ty_generics are normalized to be in this required order, and variances are built
|
||||
|
|
@ -2082,7 +1985,7 @@ fn check_variances_for_type_defn<'tcx>(
|
|||
|
||||
// Look for `ErrorGuaranteed` deeply within this type.
|
||||
if let ControlFlow::Break(ErrorGuaranteed { .. }) = tcx
|
||||
.type_of(item.owner_id)
|
||||
.type_of(def_id)
|
||||
.instantiate_identity()
|
||||
.visit_with(&mut HasErrorDeep { tcx, seen: Default::default() })
|
||||
{
|
||||
|
|
@ -2301,7 +2204,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
|
|||
#[instrument(level = "debug", skip(self))]
|
||||
fn check_false_global_bounds(&mut self) {
|
||||
let tcx = self.ocx.infcx.tcx;
|
||||
let mut span = self.span;
|
||||
let mut span = tcx.def_span(self.body_def_id);
|
||||
let empty_env = ty::ParamEnv::empty();
|
||||
|
||||
let predicates_with_span = tcx.predicates_of(self.body_def_id).predicates.iter().copied();
|
||||
|
|
|
|||
|
|
@ -277,17 +277,7 @@ impl<'tcx> ItemCtxt<'tcx> {
|
|||
}
|
||||
_ => self.item_def_id,
|
||||
};
|
||||
// FIXME: just invoke `tcx.def_descr` instead of going through the HIR
|
||||
// Can also remove most `descr` methods then.
|
||||
let kind = match self.tcx.hir_node_by_def_id(kind_id) {
|
||||
Node::Item(it) => it.kind.descr(),
|
||||
Node::ImplItem(it) => it.kind.descr(),
|
||||
Node::TraitItem(it) => it.kind.descr(),
|
||||
Node::ForeignItem(it) => it.kind.descr(),
|
||||
Node::OpaqueTy(_) => "opaque type",
|
||||
Node::Synthetic => self.tcx.def_descr(kind_id.into()),
|
||||
node => todo!("{node:#?}"),
|
||||
};
|
||||
let kind = self.tcx.def_descr(kind_id.into());
|
||||
let mut diag = placeholder_type_error_diag(
|
||||
self,
|
||||
generics,
|
||||
|
|
@ -615,159 +605,13 @@ fn get_new_lifetime_name<'tcx>(
|
|||
(1..).flat_map(a_to_z_repeat_n).find(|lt| !existing_lifetimes.contains(lt.as_str())).unwrap()
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
pub(super) fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
||||
let it = tcx.hir_item(item_id);
|
||||
debug!(item = ?it.kind.ident(), id = %it.hir_id());
|
||||
let def_id = item_id.owner_id.def_id;
|
||||
|
||||
match &it.kind {
|
||||
// These don't define types.
|
||||
hir::ItemKind::ExternCrate(..)
|
||||
| hir::ItemKind::Use(..)
|
||||
| hir::ItemKind::Macro(..)
|
||||
| hir::ItemKind::Mod(..)
|
||||
| hir::ItemKind::GlobalAsm { .. } => {}
|
||||
hir::ItemKind::ForeignMod { items, .. } => {
|
||||
for item in *items {
|
||||
let item = tcx.hir_foreign_item(item.id);
|
||||
tcx.ensure_ok().generics_of(item.owner_id);
|
||||
tcx.ensure_ok().type_of(item.owner_id);
|
||||
tcx.ensure_ok().predicates_of(item.owner_id);
|
||||
if tcx.is_conditionally_const(def_id) {
|
||||
tcx.ensure_ok().explicit_implied_const_bounds(def_id);
|
||||
tcx.ensure_ok().const_conditions(def_id);
|
||||
}
|
||||
match item.kind {
|
||||
hir::ForeignItemKind::Fn(..) => {
|
||||
tcx.ensure_ok().codegen_fn_attrs(item.owner_id);
|
||||
tcx.ensure_ok().fn_sig(item.owner_id)
|
||||
}
|
||||
hir::ForeignItemKind::Static(..) => {
|
||||
tcx.ensure_ok().codegen_fn_attrs(item.owner_id);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
hir::ItemKind::Enum(..) => {
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
lower_enum_variant_types(tcx, def_id.to_def_id());
|
||||
}
|
||||
hir::ItemKind::Impl { .. } => {
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().impl_trait_header(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
tcx.ensure_ok().associated_items(def_id);
|
||||
}
|
||||
hir::ItemKind::Trait(..) => {
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().trait_def(def_id);
|
||||
tcx.at(it.span).explicit_super_predicates_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
tcx.ensure_ok().associated_items(def_id);
|
||||
}
|
||||
hir::ItemKind::TraitAlias(..) => {
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.at(it.span).explicit_implied_predicates_of(def_id);
|
||||
tcx.at(it.span).explicit_super_predicates_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
}
|
||||
hir::ItemKind::Struct(_, _, struct_def) | hir::ItemKind::Union(_, _, struct_def) => {
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
|
||||
for f in struct_def.fields() {
|
||||
tcx.ensure_ok().generics_of(f.def_id);
|
||||
tcx.ensure_ok().type_of(f.def_id);
|
||||
tcx.ensure_ok().predicates_of(f.def_id);
|
||||
}
|
||||
|
||||
if let Some(ctor_def_id) = struct_def.ctor_def_id() {
|
||||
lower_variant_ctor(tcx, ctor_def_id);
|
||||
}
|
||||
}
|
||||
|
||||
hir::ItemKind::TyAlias(..) => {
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
}
|
||||
|
||||
hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => {
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
}
|
||||
|
||||
hir::ItemKind::Fn { .. } => {
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
tcx.ensure_ok().fn_sig(def_id);
|
||||
tcx.ensure_ok().codegen_fn_attrs(def_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
|
||||
let trait_item = tcx.hir_trait_item(trait_item_id);
|
||||
let def_id = trait_item_id.owner_id;
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
|
||||
match trait_item.kind {
|
||||
hir::TraitItemKind::Fn(..) => {
|
||||
tcx.ensure_ok().codegen_fn_attrs(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().fn_sig(def_id);
|
||||
}
|
||||
|
||||
hir::TraitItemKind::Const(..) => {
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
}
|
||||
|
||||
hir::TraitItemKind::Type(_, Some(_)) => {
|
||||
tcx.ensure_ok().item_bounds(def_id);
|
||||
tcx.ensure_ok().item_self_bounds(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
}
|
||||
|
||||
hir::TraitItemKind::Type(_, None) => {
|
||||
tcx.ensure_ok().item_bounds(def_id);
|
||||
tcx.ensure_ok().item_self_bounds(def_id);
|
||||
}
|
||||
};
|
||||
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
}
|
||||
|
||||
pub(super) fn lower_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
|
||||
let def_id = impl_item_id.owner_id;
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
let impl_item = tcx.hir_impl_item(impl_item_id);
|
||||
match impl_item.kind {
|
||||
hir::ImplItemKind::Fn(..) => {
|
||||
tcx.ensure_ok().codegen_fn_attrs(def_id);
|
||||
tcx.ensure_ok().fn_sig(def_id);
|
||||
}
|
||||
hir::ImplItemKind::Type(_) => {}
|
||||
hir::ImplItemKind::Const(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
pub(super) fn lower_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
}
|
||||
|
||||
fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
|
||||
pub(super) fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
|
||||
let def = tcx.adt_def(def_id);
|
||||
let repr_type = def.repr().discr_type();
|
||||
let initial = repr_type.initial_discriminant(tcx);
|
||||
|
|
|
|||
|
|
@ -2364,9 +2364,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
};
|
||||
|
||||
let lit_input = match expr.kind {
|
||||
hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
|
||||
hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: lit.node, ty, neg: false }),
|
||||
hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind {
|
||||
hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }),
|
||||
hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: lit.node, ty, neg: true }),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
|
|
@ -2433,7 +2433,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
} else {
|
||||
let repr = match repr {
|
||||
TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn,
|
||||
TraitObjectSyntax::DynStar => ty::DynStar,
|
||||
};
|
||||
self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -420,7 +420,6 @@ impl<'a> State<'a> {
|
|||
let syntax = lifetime.tag();
|
||||
match syntax {
|
||||
ast::TraitObjectSyntax::Dyn => self.word_nbsp("dyn"),
|
||||
ast::TraitObjectSyntax::DynStar => self.word_nbsp("dyn*"),
|
||||
ast::TraitObjectSyntax::None => {}
|
||||
}
|
||||
let mut first = true;
|
||||
|
|
@ -1480,7 +1479,7 @@ impl<'a> State<'a> {
|
|||
self.print_expr_addr_of(k, m, expr);
|
||||
}
|
||||
hir::ExprKind::Lit(lit) => {
|
||||
self.print_literal(lit);
|
||||
self.print_literal(&lit);
|
||||
}
|
||||
hir::ExprKind::Cast(expr, ty) => {
|
||||
self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Cast);
|
||||
|
|
|
|||
|
|
@ -143,7 +143,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
| ty::Coroutine(..)
|
||||
| ty::Adt(..)
|
||||
| ty::Never
|
||||
| ty::Dynamic(_, _, ty::DynStar)
|
||||
| ty::Error(_) => {
|
||||
let guar = self
|
||||
.dcx()
|
||||
|
|
@ -734,14 +733,6 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
use rustc_middle::ty::cast::CastTy::*;
|
||||
use rustc_middle::ty::cast::IntTy::*;
|
||||
|
||||
if self.cast_ty.is_dyn_star() {
|
||||
// This coercion will fail if the feature is not enabled, OR
|
||||
// if the coercion is (currently) illegal (e.g. `dyn* Foo + Send`
|
||||
// to `dyn* Foo`). Report "casting is invalid" rather than
|
||||
// "non-primitive cast".
|
||||
return Err(CastError::IllegalCast);
|
||||
}
|
||||
|
||||
let (t_from, t_cast) = match (CastTy::from_ty(self.expr_ty), CastTy::from_ty(self.cast_ty))
|
||||
{
|
||||
(Some(t_from), Some(t_cast)) => (t_from, t_cast),
|
||||
|
|
|
|||
|
|
@ -231,9 +231,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||
ty::Ref(r_b, _, mutbl_b) => {
|
||||
return self.coerce_borrowed_pointer(a, b, r_b, mutbl_b);
|
||||
}
|
||||
ty::Dynamic(predicates, region, ty::DynStar) if self.tcx.features().dyn_star() => {
|
||||
return self.coerce_dyn_star(a, b, predicates, region);
|
||||
}
|
||||
ty::Adt(pin, _)
|
||||
if self.tcx.features().pin_ergonomics()
|
||||
&& self.tcx.is_lang_item(pin.did(), hir::LangItem::Pin) =>
|
||||
|
|
@ -773,71 +770,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||
Ok(coercion)
|
||||
}
|
||||
|
||||
fn coerce_dyn_star(
|
||||
&self,
|
||||
a: Ty<'tcx>,
|
||||
b: Ty<'tcx>,
|
||||
predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
b_region: ty::Region<'tcx>,
|
||||
) -> CoerceResult<'tcx> {
|
||||
if !self.tcx.features().dyn_star() {
|
||||
return Err(TypeError::Mismatch);
|
||||
}
|
||||
|
||||
// FIXME(dyn_star): We should probably allow things like casting from
|
||||
// `dyn* Foo + Send` to `dyn* Foo`.
|
||||
if let ty::Dynamic(a_data, _, ty::DynStar) = a.kind()
|
||||
&& let ty::Dynamic(b_data, _, ty::DynStar) = b.kind()
|
||||
&& a_data.principal_def_id() == b_data.principal_def_id()
|
||||
{
|
||||
return self.unify(a, b);
|
||||
}
|
||||
|
||||
// Check the obligations of the cast -- for example, when casting
|
||||
// `usize` to `dyn* Clone + 'static`:
|
||||
let obligations = predicates
|
||||
.iter()
|
||||
.map(|predicate| {
|
||||
// For each existential predicate (e.g., `?Self: Clone`) instantiate
|
||||
// the type of the expression (e.g., `usize` in our example above)
|
||||
// and then require that the resulting predicate (e.g., `usize: Clone`)
|
||||
// holds (it does).
|
||||
let predicate = predicate.with_self_ty(self.tcx, a);
|
||||
Obligation::new(self.tcx, self.cause.clone(), self.param_env, predicate)
|
||||
})
|
||||
.chain([
|
||||
// Enforce the region bound (e.g., `usize: 'static`, in our example).
|
||||
Obligation::new(
|
||||
self.tcx,
|
||||
self.cause.clone(),
|
||||
self.param_env,
|
||||
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
|
||||
ty::OutlivesPredicate(a, b_region),
|
||||
))),
|
||||
),
|
||||
// Enforce that the type is `usize`/pointer-sized.
|
||||
Obligation::new(
|
||||
self.tcx,
|
||||
self.cause.clone(),
|
||||
self.param_env,
|
||||
ty::TraitRef::new(
|
||||
self.tcx,
|
||||
self.tcx.require_lang_item(hir::LangItem::PointerLike, self.cause.span),
|
||||
[a],
|
||||
),
|
||||
),
|
||||
])
|
||||
.collect();
|
||||
|
||||
Ok(InferOk {
|
||||
value: (
|
||||
vec![Adjustment { kind: Adjust::Pointer(PointerCoercion::DynStar), target: b }],
|
||||
b,
|
||||
),
|
||||
obligations,
|
||||
})
|
||||
}
|
||||
|
||||
/// Applies reborrowing for `Pin`
|
||||
///
|
||||
/// We currently only support reborrowing `Pin<&mut T>` as `Pin<&mut T>`. This is accomplished
|
||||
|
|
|
|||
|
|
@ -1637,7 +1637,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
ast::LitKind::ByteStr(ref v, _) => Ty::new_imm_ref(
|
||||
tcx,
|
||||
tcx.lifetimes.re_static,
|
||||
Ty::new_array(tcx, tcx.types.u8, v.len() as u64),
|
||||
Ty::new_array(tcx, tcx.types.u8, v.as_byte_str().len() as u64),
|
||||
),
|
||||
ast::LitKind::Byte(_) => tcx.types.u8,
|
||||
ast::LitKind::Char(_) => tcx.types.char,
|
||||
|
|
|
|||
|
|
@ -1624,7 +1624,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
node: rustc_ast::LitKind::Int(lit, rustc_ast::LitIntType::Unsuffixed),
|
||||
span,
|
||||
}) => {
|
||||
let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(*span) else {
|
||||
let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) else {
|
||||
return false;
|
||||
};
|
||||
if !(snippet.starts_with("0x") || snippet.starts_with("0X")) {
|
||||
|
|
@ -1683,7 +1683,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// We have satisfied all requirements to provide a suggestion. Emit it.
|
||||
err.span_suggestion(
|
||||
*span,
|
||||
span,
|
||||
format!("if you meant to create a null pointer, use `{null_path_str}()`"),
|
||||
null_path_str + "()",
|
||||
Applicability::MachineApplicable,
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@
|
|||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::direct_use_of_rustc_type_ir)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![cfg_attr(not(bootstrap), allow(rustc::direct_use_of_rustc_type_ir))]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(assert_matches)]
|
||||
|
|
|
|||
|
|
@ -108,8 +108,8 @@ impl<'tcx> LateLintPass<'tcx> for InvalidFromUtf8 {
|
|||
}
|
||||
match init.kind {
|
||||
ExprKind::Lit(Spanned { node: lit, .. }) => {
|
||||
if let LitKind::ByteStr(bytes, _) = &lit
|
||||
&& let Err(utf8_error) = std::str::from_utf8(bytes)
|
||||
if let LitKind::ByteStr(byte_sym, _) = &lit
|
||||
&& let Err(utf8_error) = std::str::from_utf8(byte_sym.as_byte_str())
|
||||
{
|
||||
lint(init.span, utf8_error);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
|
|||
hir_visit::walk_pat(self, p);
|
||||
}
|
||||
|
||||
fn visit_lit(&mut self, hir_id: HirId, lit: &'tcx hir::Lit, negated: bool) {
|
||||
fn visit_lit(&mut self, hir_id: HirId, lit: hir::Lit, negated: bool) {
|
||||
lint_callback!(self, check_lit, hir_id, lit, negated);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ macro_rules! late_lint_methods {
|
|||
fn check_stmt(a: &'tcx rustc_hir::Stmt<'tcx>);
|
||||
fn check_arm(a: &'tcx rustc_hir::Arm<'tcx>);
|
||||
fn check_pat(a: &'tcx rustc_hir::Pat<'tcx>);
|
||||
fn check_lit(hir_id: rustc_hir::HirId, a: &'tcx rustc_hir::Lit, negated: bool);
|
||||
fn check_lit(hir_id: rustc_hir::HirId, a: rustc_hir::Lit, negated: bool);
|
||||
fn check_expr(a: &'tcx rustc_hir::Expr<'tcx>);
|
||||
fn check_expr_post(a: &'tcx rustc_hir::Expr<'tcx>);
|
||||
fn check_ty(a: &'tcx rustc_hir::Ty<'tcx, rustc_hir::AmbigArg>);
|
||||
|
|
|
|||
|
|
@ -547,18 +547,12 @@ fn lint_fn_pointer<'tcx>(
|
|||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for TypeLimits {
|
||||
fn check_lit(
|
||||
&mut self,
|
||||
cx: &LateContext<'tcx>,
|
||||
hir_id: HirId,
|
||||
lit: &'tcx hir::Lit,
|
||||
negated: bool,
|
||||
) {
|
||||
fn check_lit(&mut self, cx: &LateContext<'tcx>, hir_id: HirId, lit: hir::Lit, negated: bool) {
|
||||
if negated {
|
||||
self.negated_expr_id = Some(hir_id);
|
||||
self.negated_expr_span = Some(lit.span);
|
||||
}
|
||||
lint_literal(cx, self, hir_id, lit.span, lit, negated);
|
||||
lint_literal(cx, self, hir_id, lit.span, &lit, negated);
|
||||
}
|
||||
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>) {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,9 @@ use rustc_session::Session;
|
|||
use rustc_session::config::TargetModifier;
|
||||
use rustc_session::cstore::{CrateSource, ExternCrate};
|
||||
use rustc_span::hygiene::HygieneDecodeContext;
|
||||
use rustc_span::{BytePos, DUMMY_SP, Pos, SpanData, SpanDecoder, SyntaxContext, kw};
|
||||
use rustc_span::{
|
||||
BytePos, ByteSymbol, DUMMY_SP, Pos, SpanData, SpanDecoder, Symbol, SyntaxContext, kw,
|
||||
};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::creader::CStore;
|
||||
|
|
@ -384,6 +386,28 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
|
|||
fn read_raw_bytes(&mut self, len: usize) -> &[u8] {
|
||||
self.opaque.read_raw_bytes(len)
|
||||
}
|
||||
|
||||
fn decode_symbol_or_byte_symbol<S>(
|
||||
&mut self,
|
||||
new_from_index: impl Fn(u32) -> S,
|
||||
read_and_intern_str_or_byte_str_this: impl Fn(&mut Self) -> S,
|
||||
read_and_intern_str_or_byte_str_opaque: impl Fn(&mut MemDecoder<'a>) -> S,
|
||||
) -> S {
|
||||
let tag = self.read_u8();
|
||||
|
||||
match tag {
|
||||
SYMBOL_STR => read_and_intern_str_or_byte_str_this(self),
|
||||
SYMBOL_OFFSET => {
|
||||
// read str offset
|
||||
let pos = self.read_usize();
|
||||
|
||||
// move to str offset and read
|
||||
self.opaque.with_position(pos, |d| read_and_intern_str_or_byte_str_opaque(d))
|
||||
}
|
||||
SYMBOL_PREDEFINED => new_from_index(self.read_u32()),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> {
|
||||
|
|
@ -545,29 +569,19 @@ impl<'a, 'tcx> SpanDecoder for DecodeContext<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn decode_symbol(&mut self) -> Symbol {
|
||||
let tag = self.read_u8();
|
||||
self.decode_symbol_or_byte_symbol(
|
||||
Symbol::new,
|
||||
|this| Symbol::intern(this.read_str()),
|
||||
|opaque| Symbol::intern(opaque.read_str()),
|
||||
)
|
||||
}
|
||||
|
||||
match tag {
|
||||
SYMBOL_STR => {
|
||||
let s = self.read_str();
|
||||
Symbol::intern(s)
|
||||
}
|
||||
SYMBOL_OFFSET => {
|
||||
// read str offset
|
||||
let pos = self.read_usize();
|
||||
|
||||
// move to str offset and read
|
||||
self.opaque.with_position(pos, |d| {
|
||||
let s = d.read_str();
|
||||
Symbol::intern(s)
|
||||
})
|
||||
}
|
||||
SYMBOL_PREDEFINED => {
|
||||
let symbol_index = self.read_u32();
|
||||
Symbol::new(symbol_index)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
fn decode_byte_symbol(&mut self) -> ByteSymbol {
|
||||
self.decode_symbol_or_byte_symbol(
|
||||
ByteSymbol::new,
|
||||
|this| ByteSymbol::intern(this.read_byte_str()),
|
||||
|opaque| ByteSymbol::intern(opaque.read_byte_str()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1496,11 +1510,18 @@ impl<'a> CrateMetadataRef<'a> {
|
|||
.map(move |v| (self.local_def_id(v.0), v.1))
|
||||
}
|
||||
|
||||
fn exported_symbols<'tcx>(
|
||||
fn exported_non_generic_symbols<'tcx>(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
|
||||
tcx.arena.alloc_from_iter(self.root.exported_symbols.decode((self, tcx)))
|
||||
tcx.arena.alloc_from_iter(self.root.exported_non_generic_symbols.decode((self, tcx)))
|
||||
}
|
||||
|
||||
fn exported_generic_symbols<'tcx>(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
|
||||
tcx.arena.alloc_from_iter(self.root.exported_generic_symbols.decode((self, tcx)))
|
||||
}
|
||||
|
||||
fn get_macro(self, id: DefIndex, sess: &Session) -> ast::MacroDef {
|
||||
|
|
|
|||
|
|
@ -358,7 +358,7 @@ provide! { tcx, def_id, other, cdata,
|
|||
specialization_enabled_in => { cdata.root.specialization_enabled_in }
|
||||
reachable_non_generics => {
|
||||
let reachable_non_generics = tcx
|
||||
.exported_symbols(cdata.cnum)
|
||||
.exported_non_generic_symbols(cdata.cnum)
|
||||
.iter()
|
||||
.filter_map(|&(exported_symbol, export_info)| {
|
||||
if let ExportedSymbol::NonGeneric(def_id) = exported_symbol {
|
||||
|
|
@ -408,15 +408,8 @@ provide! { tcx, def_id, other, cdata,
|
|||
|
||||
exportable_items => { tcx.arena.alloc_from_iter(cdata.get_exportable_items()) }
|
||||
stable_order_of_exportable_impls => { tcx.arena.alloc(cdata.get_stable_order_of_exportable_impls().collect()) }
|
||||
exported_symbols => {
|
||||
let syms = cdata.exported_symbols(tcx);
|
||||
|
||||
// FIXME rust-lang/rust#64319, rust-lang/rust#64872: We want
|
||||
// to block export of generics from dylibs, but we must fix
|
||||
// rust-lang/rust#65890 before we can do that robustly.
|
||||
|
||||
syms
|
||||
}
|
||||
exported_non_generic_symbols => { cdata.exported_non_generic_symbols(tcx) }
|
||||
exported_generic_symbols => { cdata.exported_generic_symbols(tcx) }
|
||||
|
||||
crate_extern_paths => { cdata.source().paths().cloned().collect() }
|
||||
expn_that_defined => { cdata.get_expn_that_defined(def_id.index, tcx.sess) }
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque};
|
|||
use rustc_session::config::{CrateType, OptLevel, TargetModifier};
|
||||
use rustc_span::hygiene::HygieneEncodeContext;
|
||||
use rustc_span::{
|
||||
ExternalSource, FileName, SourceFile, SpanData, SpanEncoder, StableSourceFileId, SyntaxContext,
|
||||
sym,
|
||||
ByteSymbol, ExternalSource, FileName, SourceFile, SpanData, SpanEncoder, StableSourceFileId,
|
||||
Symbol, SyntaxContext, sym,
|
||||
};
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
|
|
@ -63,7 +63,8 @@ pub(super) struct EncodeContext<'a, 'tcx> {
|
|||
required_source_files: Option<FxIndexSet<usize>>,
|
||||
is_proc_macro: bool,
|
||||
hygiene_ctxt: &'a HygieneEncodeContext,
|
||||
symbol_table: FxHashMap<Symbol, usize>,
|
||||
// Used for both `Symbol`s and `ByteSymbol`s.
|
||||
symbol_index_table: FxHashMap<u32, usize>,
|
||||
}
|
||||
|
||||
/// If the current crate is a proc-macro, returns early with `LazyArray::default()`.
|
||||
|
|
@ -200,27 +201,14 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn encode_symbol(&mut self, symbol: Symbol) {
|
||||
// if symbol predefined, emit tag and symbol index
|
||||
if symbol.is_predefined() {
|
||||
self.opaque.emit_u8(SYMBOL_PREDEFINED);
|
||||
self.opaque.emit_u32(symbol.as_u32());
|
||||
} else {
|
||||
// otherwise write it as string or as offset to it
|
||||
match self.symbol_table.entry(symbol) {
|
||||
Entry::Vacant(o) => {
|
||||
self.opaque.emit_u8(SYMBOL_STR);
|
||||
let pos = self.opaque.position();
|
||||
o.insert(pos);
|
||||
self.emit_str(symbol.as_str());
|
||||
}
|
||||
Entry::Occupied(o) => {
|
||||
let x = *o.get();
|
||||
self.emit_u8(SYMBOL_OFFSET);
|
||||
self.emit_usize(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
fn encode_symbol(&mut self, sym: Symbol) {
|
||||
self.encode_symbol_or_byte_symbol(sym.as_u32(), |this| this.emit_str(sym.as_str()));
|
||||
}
|
||||
|
||||
fn encode_byte_symbol(&mut self, byte_sym: ByteSymbol) {
|
||||
self.encode_symbol_or_byte_symbol(byte_sym.as_u32(), |this| {
|
||||
this.emit_byte_str(byte_sym.as_byte_str())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -492,6 +480,33 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
LazyArray::from_position_and_num_elems(pos, len)
|
||||
}
|
||||
|
||||
fn encode_symbol_or_byte_symbol(
|
||||
&mut self,
|
||||
index: u32,
|
||||
emit_str_or_byte_str: impl Fn(&mut Self),
|
||||
) {
|
||||
// if symbol/byte symbol is predefined, emit tag and symbol index
|
||||
if Symbol::is_predefined(index) {
|
||||
self.opaque.emit_u8(SYMBOL_PREDEFINED);
|
||||
self.opaque.emit_u32(index);
|
||||
} else {
|
||||
// otherwise write it as string or as offset to it
|
||||
match self.symbol_index_table.entry(index) {
|
||||
Entry::Vacant(o) => {
|
||||
self.opaque.emit_u8(SYMBOL_STR);
|
||||
let pos = self.opaque.position();
|
||||
o.insert(pos);
|
||||
emit_str_or_byte_str(self);
|
||||
}
|
||||
Entry::Occupied(o) => {
|
||||
let x = *o.get();
|
||||
self.emit_u8(SYMBOL_OFFSET);
|
||||
self.emit_usize(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_def_path_table(&mut self) {
|
||||
let table = self.tcx.def_path_table();
|
||||
if self.is_proc_macro {
|
||||
|
|
@ -677,9 +692,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
stat!("exportable-items", || self.encode_stable_order_of_exportable_impls());
|
||||
|
||||
// Encode exported symbols info. This is prefetched in `encode_metadata`.
|
||||
let exported_symbols = stat!("exported-symbols", || {
|
||||
self.encode_exported_symbols(tcx.exported_symbols(LOCAL_CRATE))
|
||||
});
|
||||
let (exported_non_generic_symbols, exported_generic_symbols) =
|
||||
stat!("exported-symbols", || {
|
||||
(
|
||||
self.encode_exported_symbols(tcx.exported_non_generic_symbols(LOCAL_CRATE)),
|
||||
self.encode_exported_symbols(tcx.exported_generic_symbols(LOCAL_CRATE)),
|
||||
)
|
||||
});
|
||||
|
||||
// Encode the hygiene data.
|
||||
// IMPORTANT: this *must* be the last thing that we encode (other than `SourceMap`). The
|
||||
|
|
@ -745,7 +764,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
incoherent_impls,
|
||||
exportable_items,
|
||||
stable_order_of_exportable_impls,
|
||||
exported_symbols,
|
||||
exported_non_generic_symbols,
|
||||
exported_generic_symbols,
|
||||
interpret_alloc_index,
|
||||
tables,
|
||||
syntax_contexts,
|
||||
|
|
@ -2360,7 +2380,13 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) {
|
|||
// Prefetch some queries used by metadata encoding.
|
||||
// This is not necessary for correctness, but is only done for performance reasons.
|
||||
// It can be removed if it turns out to cause trouble or be detrimental to performance.
|
||||
join(|| prefetch_mir(tcx), || tcx.exported_symbols(LOCAL_CRATE));
|
||||
join(
|
||||
|| prefetch_mir(tcx),
|
||||
|| {
|
||||
let _ = tcx.exported_non_generic_symbols(LOCAL_CRATE);
|
||||
let _ = tcx.exported_generic_symbols(LOCAL_CRATE);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
with_encode_metadata_header(tcx, path, |ecx| {
|
||||
|
|
@ -2427,7 +2453,7 @@ fn with_encode_metadata_header(
|
|||
required_source_files,
|
||||
is_proc_macro: tcx.crate_types().contains(&CrateType::ProcMacro),
|
||||
hygiene_ctxt: &hygiene_ctxt,
|
||||
symbol_table: Default::default(),
|
||||
symbol_index_table: Default::default(),
|
||||
};
|
||||
|
||||
// Encode the rustc version string in a predictable location.
|
||||
|
|
|
|||
|
|
@ -282,7 +282,8 @@ pub(crate) struct CrateRoot {
|
|||
|
||||
exportable_items: LazyArray<DefIndex>,
|
||||
stable_order_of_exportable_impls: LazyArray<(DefIndex, usize)>,
|
||||
exported_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>,
|
||||
exported_non_generic_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>,
|
||||
exported_generic_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>,
|
||||
|
||||
syntax_contexts: SyntaxContextTable,
|
||||
expn_data: ExpnDataTable,
|
||||
|
|
|
|||
|
|
@ -27,9 +27,8 @@
|
|||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::direct_use_of_rustc_type_ir)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![cfg_attr(not(bootstrap), allow(rustc::direct_use_of_rustc_type_ir))]
|
||||
#![cfg_attr(not(bootstrap), feature(sized_hierarchy))]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(allocator_api)]
|
||||
|
|
@ -55,6 +54,7 @@
|
|||
#![feature(round_char_boundary)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(sized_hierarchy)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(try_trait_v2)]
|
||||
#![feature(try_trait_v2_yeet)]
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ impl<'tcx> GlobalId<'tcx> {
|
|||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, HashStable)]
|
||||
pub struct LitToConstInput<'tcx> {
|
||||
/// The absolute value of the resultant constant.
|
||||
pub lit: &'tcx LitKind,
|
||||
pub lit: LitKind,
|
||||
/// The type of the constant.
|
||||
pub ty: Ty<'tcx>,
|
||||
/// If the constant is negative.
|
||||
|
|
|
|||
|
|
@ -1336,6 +1336,7 @@ impl BasicBlock {
|
|||
///
|
||||
/// See [`BasicBlock`] for documentation on what basic blocks are at a high level.
|
||||
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
|
||||
#[non_exhaustive]
|
||||
pub struct BasicBlockData<'tcx> {
|
||||
/// List of statements in this block.
|
||||
pub statements: Vec<Statement<'tcx>>,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use crate::ty::CoroutineArgsExt;
|
|||
|
||||
/// A statement in a basic block, including information about its source code.
|
||||
#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
|
||||
#[non_exhaustive]
|
||||
pub struct Statement<'tcx> {
|
||||
pub source_info: SourceInfo,
|
||||
pub kind: StatementKind<'tcx>,
|
||||
|
|
|
|||
|
|
@ -266,6 +266,7 @@ trivial! {
|
|||
Option<rustc_target::spec::PanicStrategy>,
|
||||
Option<usize>,
|
||||
Option<rustc_middle::ty::IntrinsicDef>,
|
||||
Option<rustc_abi::Align>,
|
||||
Result<(), rustc_errors::ErrorGuaranteed>,
|
||||
Result<(), rustc_middle::traits::query::NoSolution>,
|
||||
Result<rustc_middle::traits::EvaluationResult, rustc_middle::traits::OverflowError>,
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ use std::mem;
|
|||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_abi::Align;
|
||||
use rustc_arena::TypedArena;
|
||||
use rustc_ast::expand::StrippedCfgItem;
|
||||
use rustc_ast::expand::allocator::AllocatorKind;
|
||||
|
|
@ -1481,6 +1482,10 @@ rustc_queries! {
|
|||
desc { |tcx| "computing should_inherit_track_caller of `{}`", tcx.def_path_str(def_id) }
|
||||
}
|
||||
|
||||
query inherited_align(def_id: DefId) -> Option<Align> {
|
||||
desc { |tcx| "computing inherited_align of `{}`", tcx.def_path_str(def_id) }
|
||||
}
|
||||
|
||||
query lookup_deprecation_entry(def_id: DefId) -> Option<DeprecationEntry> {
|
||||
desc { |tcx| "checking whether `{}` is deprecated", tcx.def_path_str(def_id) }
|
||||
cache_on_disk_if { def_id.is_local() }
|
||||
|
|
@ -2312,13 +2317,32 @@ rustc_queries! {
|
|||
separate_provide_extern
|
||||
}
|
||||
|
||||
/// The list of symbols exported from the given crate.
|
||||
/// The list of non-generic symbols exported from the given crate.
|
||||
///
|
||||
/// - All names contained in `exported_symbols(cnum)` are guaranteed to
|
||||
/// correspond to a publicly visible symbol in `cnum` machine code.
|
||||
/// - The `exported_symbols` sets of different crates do not intersect.
|
||||
query exported_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
|
||||
desc { "collecting exported symbols for crate `{}`", cnum}
|
||||
/// This is separate from exported_generic_symbols to avoid having
|
||||
/// to deserialize all non-generic symbols too for upstream crates
|
||||
/// in the upstream_monomorphizations query.
|
||||
///
|
||||
/// - All names contained in `exported_non_generic_symbols(cnum)` are
|
||||
/// guaranteed to correspond to a publicly visible symbol in `cnum`
|
||||
/// machine code.
|
||||
/// - The `exported_non_generic_symbols` and `exported_generic_symbols`
|
||||
/// sets of different crates do not intersect.
|
||||
query exported_non_generic_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
|
||||
desc { "collecting exported non-generic symbols for crate `{}`", cnum}
|
||||
cache_on_disk_if { *cnum == LOCAL_CRATE }
|
||||
separate_provide_extern
|
||||
}
|
||||
|
||||
/// The list of generic symbols exported from the given crate.
|
||||
///
|
||||
/// - All names contained in `exported_generic_symbols(cnum)` are
|
||||
/// guaranteed to correspond to a publicly visible symbol in `cnum`
|
||||
/// machine code.
|
||||
/// - The `exported_non_generic_symbols` and `exported_generic_symbols`
|
||||
/// sets of different crates do not intersect.
|
||||
query exported_generic_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
|
||||
desc { "collecting exported generic symbols for crate `{}`", cnum}
|
||||
cache_on_disk_if { *cnum == LOCAL_CRATE }
|
||||
separate_provide_extern
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ use rustc_span::hygiene::{
|
|||
};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{
|
||||
BytePos, CachingSourceMapView, ExpnData, ExpnHash, Pos, RelativeBytePos, SourceFile, Span,
|
||||
SpanDecoder, SpanEncoder, StableSourceFileId, Symbol,
|
||||
BytePos, ByteSymbol, CachingSourceMapView, ExpnData, ExpnHash, Pos, RelativeBytePos,
|
||||
SourceFile, Span, SpanDecoder, SpanEncoder, StableSourceFileId, Symbol,
|
||||
};
|
||||
|
||||
use crate::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
|
||||
|
|
@ -42,7 +42,7 @@ const TAG_RELATIVE_SPAN: u8 = 2;
|
|||
const TAG_SYNTAX_CONTEXT: u8 = 0;
|
||||
const TAG_EXPN_DATA: u8 = 1;
|
||||
|
||||
// Tags for encoding Symbol's
|
||||
// Tags for encoding Symbols and ByteSymbols
|
||||
const SYMBOL_STR: u8 = 0;
|
||||
const SYMBOL_OFFSET: u8 = 1;
|
||||
const SYMBOL_PREDEFINED: u8 = 2;
|
||||
|
|
@ -253,7 +253,7 @@ impl OnDiskCache {
|
|||
source_map: CachingSourceMapView::new(tcx.sess.source_map()),
|
||||
file_to_file_index,
|
||||
hygiene_context: &hygiene_encode_context,
|
||||
symbol_table: Default::default(),
|
||||
symbol_index_table: Default::default(),
|
||||
};
|
||||
|
||||
// Encode query results.
|
||||
|
|
@ -479,6 +479,30 @@ impl<'a, 'tcx> CacheDecoder<'a, 'tcx> {
|
|||
.expect("failed to lookup `SourceFile` in new context")
|
||||
}))
|
||||
}
|
||||
|
||||
// copy&paste impl from rustc_metadata
|
||||
#[inline]
|
||||
fn decode_symbol_or_byte_symbol<S>(
|
||||
&mut self,
|
||||
new_from_index: impl Fn(u32) -> S,
|
||||
read_and_intern_str_or_byte_str_this: impl Fn(&mut Self) -> S,
|
||||
read_and_intern_str_or_byte_str_opaque: impl Fn(&mut MemDecoder<'a>) -> S,
|
||||
) -> S {
|
||||
let tag = self.read_u8();
|
||||
|
||||
match tag {
|
||||
SYMBOL_STR => read_and_intern_str_or_byte_str_this(self),
|
||||
SYMBOL_OFFSET => {
|
||||
// read str offset
|
||||
let pos = self.read_usize();
|
||||
|
||||
// move to str offset and read
|
||||
self.opaque.with_position(pos, |d| read_and_intern_str_or_byte_str_opaque(d))
|
||||
}
|
||||
SYMBOL_PREDEFINED => new_from_index(self.read_u32()),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decodes something that was encoded with `encode_tagged()` and verify that the
|
||||
|
|
@ -653,32 +677,20 @@ impl<'a, 'tcx> SpanDecoder for CacheDecoder<'a, 'tcx> {
|
|||
Span::new(lo, hi, ctxt, parent)
|
||||
}
|
||||
|
||||
// copy&paste impl from rustc_metadata
|
||||
#[inline]
|
||||
fn decode_symbol(&mut self) -> Symbol {
|
||||
let tag = self.read_u8();
|
||||
self.decode_symbol_or_byte_symbol(
|
||||
Symbol::new,
|
||||
|this| Symbol::intern(this.read_str()),
|
||||
|opaque| Symbol::intern(opaque.read_str()),
|
||||
)
|
||||
}
|
||||
|
||||
match tag {
|
||||
SYMBOL_STR => {
|
||||
let s = self.read_str();
|
||||
Symbol::intern(s)
|
||||
}
|
||||
SYMBOL_OFFSET => {
|
||||
// read str offset
|
||||
let pos = self.read_usize();
|
||||
|
||||
// move to str offset and read
|
||||
self.opaque.with_position(pos, |d| {
|
||||
let s = d.read_str();
|
||||
Symbol::intern(s)
|
||||
})
|
||||
}
|
||||
SYMBOL_PREDEFINED => {
|
||||
let symbol_index = self.read_u32();
|
||||
Symbol::new(symbol_index)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
fn decode_byte_symbol(&mut self) -> ByteSymbol {
|
||||
self.decode_symbol_or_byte_symbol(
|
||||
ByteSymbol::new,
|
||||
|this| ByteSymbol::intern(this.read_byte_str()),
|
||||
|opaque| ByteSymbol::intern(opaque.read_byte_str()),
|
||||
)
|
||||
}
|
||||
|
||||
fn decode_crate_num(&mut self) -> CrateNum {
|
||||
|
|
@ -807,7 +819,8 @@ pub struct CacheEncoder<'a, 'tcx> {
|
|||
source_map: CachingSourceMapView<'tcx>,
|
||||
file_to_file_index: FxHashMap<*const SourceFile, SourceFileIndex>,
|
||||
hygiene_context: &'a HygieneEncodeContext,
|
||||
symbol_table: FxHashMap<Symbol, usize>,
|
||||
// Used for both `Symbol`s and `ByteSymbol`s.
|
||||
symbol_index_table: FxHashMap<u32, usize>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> CacheEncoder<'a, 'tcx> {
|
||||
|
|
@ -831,6 +844,34 @@ impl<'a, 'tcx> CacheEncoder<'a, 'tcx> {
|
|||
((end_pos - start_pos) as u64).encode(self);
|
||||
}
|
||||
|
||||
// copy&paste impl from rustc_metadata
|
||||
fn encode_symbol_or_byte_symbol(
|
||||
&mut self,
|
||||
index: u32,
|
||||
emit_str_or_byte_str: impl Fn(&mut Self),
|
||||
) {
|
||||
// if symbol/byte symbol is predefined, emit tag and symbol index
|
||||
if Symbol::is_predefined(index) {
|
||||
self.encoder.emit_u8(SYMBOL_PREDEFINED);
|
||||
self.encoder.emit_u32(index);
|
||||
} else {
|
||||
// otherwise write it as string or as offset to it
|
||||
match self.symbol_index_table.entry(index) {
|
||||
Entry::Vacant(o) => {
|
||||
self.encoder.emit_u8(SYMBOL_STR);
|
||||
let pos = self.encoder.position();
|
||||
o.insert(pos);
|
||||
emit_str_or_byte_str(self);
|
||||
}
|
||||
Entry::Occupied(o) => {
|
||||
let x = *o.get();
|
||||
self.emit_u8(SYMBOL_OFFSET);
|
||||
self.emit_usize(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn finish(mut self) -> FileEncodeResult {
|
||||
self.encoder.finish()
|
||||
|
|
@ -889,28 +930,14 @@ impl<'a, 'tcx> SpanEncoder for CacheEncoder<'a, 'tcx> {
|
|||
len.encode(self);
|
||||
}
|
||||
|
||||
// copy&paste impl from rustc_metadata
|
||||
fn encode_symbol(&mut self, symbol: Symbol) {
|
||||
// if symbol predefined, emit tag and symbol index
|
||||
if symbol.is_predefined() {
|
||||
self.encoder.emit_u8(SYMBOL_PREDEFINED);
|
||||
self.encoder.emit_u32(symbol.as_u32());
|
||||
} else {
|
||||
// otherwise write it as string or as offset to it
|
||||
match self.symbol_table.entry(symbol) {
|
||||
Entry::Vacant(o) => {
|
||||
self.encoder.emit_u8(SYMBOL_STR);
|
||||
let pos = self.encoder.position();
|
||||
o.insert(pos);
|
||||
self.emit_str(symbol.as_str());
|
||||
}
|
||||
Entry::Occupied(o) => {
|
||||
let x = *o.get();
|
||||
self.emit_u8(SYMBOL_OFFSET);
|
||||
self.emit_usize(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
fn encode_symbol(&mut self, sym: Symbol) {
|
||||
self.encode_symbol_or_byte_symbol(sym.as_u32(), |this| this.emit_str(sym.as_str()));
|
||||
}
|
||||
|
||||
fn encode_byte_symbol(&mut self, byte_sym: ByteSymbol) {
|
||||
self.encode_symbol_or_byte_symbol(byte_sym.as_u32(), |this| {
|
||||
this.emit_byte_str(byte_sym.as_byte_str())
|
||||
});
|
||||
}
|
||||
|
||||
fn encode_crate_num(&mut self, crate_num: CrateNum) {
|
||||
|
|
|
|||
|
|
@ -526,7 +526,7 @@ pub enum ExprKind<'tcx> {
|
|||
Closure(Box<ClosureExpr<'tcx>>),
|
||||
/// A literal.
|
||||
Literal {
|
||||
lit: &'tcx hir::Lit,
|
||||
lit: hir::Lit,
|
||||
neg: bool,
|
||||
},
|
||||
/// For literals that don't correspond to anything in the HIR
|
||||
|
|
|
|||
|
|
@ -36,9 +36,6 @@ pub enum PointerCoercion {
|
|||
/// type. Codegen backends and miri figure out what has to be done
|
||||
/// based on the precise source/target type at hand.
|
||||
Unsize,
|
||||
|
||||
/// Go from a pointer-like type to a `dyn*` object.
|
||||
DynStar,
|
||||
}
|
||||
|
||||
/// Represents coercing a value to a different type of value.
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@
|
|||
|
||||
use std::hash::Hash;
|
||||
use std::intrinsics;
|
||||
use std::marker::DiscriminantKind;
|
||||
use std::marker::{DiscriminantKind, PointeeSized};
|
||||
|
||||
use rustc_abi::{FieldIdx, VariantIdx};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_serialize::{Decodable, Encodable, PointeeSized};
|
||||
use rustc_serialize::{Decodable, Encodable};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{Span, SpanDecoder, SpanEncoder};
|
||||
|
||||
|
|
|
|||
|
|
@ -10,13 +10,14 @@ use std::cmp::Ordering;
|
|||
use std::env::VarError;
|
||||
use std::ffi::OsStr;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::marker::PhantomData;
|
||||
use std::marker::{PhantomData, PointeeSized};
|
||||
use std::ops::{Bound, Deref};
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use std::{fmt, iter, mem};
|
||||
|
||||
use rustc_abi::{ExternAbi, FieldIdx, Layout, LayoutData, TargetDataLayout, VariantIdx};
|
||||
use rustc_ast as ast;
|
||||
use rustc_attr_data_structures::{AttributeKind, find_attr};
|
||||
use rustc_data_structures::defer;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
|
@ -43,7 +44,6 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable};
|
|||
use rustc_query_system::cache::WithDepNode;
|
||||
use rustc_query_system::dep_graph::DepNodeIndex;
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
use rustc_serialize::PointeeSized;
|
||||
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
|
||||
use rustc_session::config::CrateType;
|
||||
use rustc_session::cstore::{CrateStoreDyn, Untracked};
|
||||
|
|
@ -1648,32 +1648,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// `rustc_layout_scalar_valid_range` attribute.
|
||||
// FIXME(eddyb) this is an awkward spot for this method, maybe move it?
|
||||
pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound<u128>, Bound<u128>) {
|
||||
let get = |name| {
|
||||
let Some(attr) = self.get_attr(def_id, name) else {
|
||||
return Bound::Unbounded;
|
||||
};
|
||||
debug!("layout_scalar_valid_range: attr={:?}", attr);
|
||||
if let Some(
|
||||
&[
|
||||
ast::MetaItemInner::Lit(ast::MetaItemLit {
|
||||
kind: ast::LitKind::Int(a, _), ..
|
||||
}),
|
||||
],
|
||||
) = attr.meta_item_list().as_deref()
|
||||
{
|
||||
Bound::Included(a.get())
|
||||
} else {
|
||||
self.dcx().span_delayed_bug(
|
||||
attr.span(),
|
||||
"invalid rustc_layout_scalar_valid_range attribute",
|
||||
);
|
||||
Bound::Unbounded
|
||||
}
|
||||
};
|
||||
(
|
||||
get(sym::rustc_layout_scalar_valid_range_start),
|
||||
get(sym::rustc_layout_scalar_valid_range_end),
|
||||
)
|
||||
let start = find_attr!(self.get_all_attrs(def_id), AttributeKind::RustcLayoutScalarValidRangeStart(n, _) => Bound::Included(**n)).unwrap_or(Bound::Unbounded);
|
||||
let end = find_attr!(self.get_all_attrs(def_id), AttributeKind::RustcLayoutScalarValidRangeEnd(n, _) => Bound::Included(**n)).unwrap_or(Bound::Unbounded);
|
||||
(start, end)
|
||||
}
|
||||
|
||||
pub fn lift<T: Lift<TyCtxt<'tcx>>>(self, value: T) -> Option<T::Lifted> {
|
||||
|
|
|
|||
|
|
@ -946,21 +946,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
ty::Dynamic(_, _, ty::DynStar) => {
|
||||
if i == 0 {
|
||||
TyMaybeWithLayout::Ty(Ty::new_mut_ptr(tcx, tcx.types.unit))
|
||||
} else if i == 1 {
|
||||
// FIXME(dyn-star) same FIXME as above applies here too
|
||||
TyMaybeWithLayout::Ty(Ty::new_imm_ref(
|
||||
tcx,
|
||||
tcx.lifetimes.re_static,
|
||||
Ty::new_array(tcx, tcx.types.usize, 3),
|
||||
))
|
||||
} else {
|
||||
bug!("no field {i} on dyn*")
|
||||
}
|
||||
}
|
||||
|
||||
ty::Alias(..)
|
||||
| ty::Bound(..)
|
||||
| ty::Placeholder(..)
|
||||
|
|
|
|||
|
|
@ -810,7 +810,6 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
}
|
||||
match repr {
|
||||
ty::Dyn => p!("dyn "),
|
||||
ty::DynStar => p!("dyn* "),
|
||||
}
|
||||
p!(print(data));
|
||||
if print_r {
|
||||
|
|
|
|||
|
|
@ -1321,11 +1321,6 @@ impl<'tcx> Ty<'tcx> {
|
|||
matches!(self.kind(), Dynamic(_, _, ty::Dyn))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_dyn_star(self) -> bool {
|
||||
matches!(self.kind(), Dynamic(_, _, ty::DynStar))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_enum(self) -> bool {
|
||||
matches!(self.kind(), Adt(adt_def, _) if adt_def.is_enum())
|
||||
|
|
@ -1629,8 +1624,6 @@ impl<'tcx> Ty<'tcx> {
|
|||
| ty::Error(_)
|
||||
// Extern types have metadata = ().
|
||||
| ty::Foreign(..)
|
||||
// `dyn*` has metadata = ().
|
||||
| ty::Dynamic(_, _, ty::DynStar)
|
||||
// If returned by `struct_tail_raw` this is a unit struct
|
||||
// without any fields, or not a struct, and therefore is Sized.
|
||||
| ty::Adt(..)
|
||||
|
|
@ -1820,8 +1813,7 @@ impl<'tcx> Ty<'tcx> {
|
|||
| ty::Closure(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
| ty::Never
|
||||
| ty::Error(_)
|
||||
| ty::Dynamic(_, _, ty::DynStar) => true,
|
||||
| ty::Error(_) => true,
|
||||
|
||||
ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) => match sizedness {
|
||||
SizedTraitKind::Sized => false,
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ pub(crate) fn as_constant_inner<'tcx>(
|
|||
let Expr { ty, temp_lifetime: _, span, ref kind } = *expr;
|
||||
match *kind {
|
||||
ExprKind::Literal { lit, neg } => {
|
||||
let const_ = lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg });
|
||||
let const_ = lit_to_mir_constant(tcx, LitToConstInput { lit: lit.node, ty, neg });
|
||||
|
||||
ConstOperand { span, user_ty: None, const_ }
|
||||
}
|
||||
|
|
@ -128,34 +128,35 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>
|
|||
(ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _))
|
||||
if matches!(inner_ty.kind(), ty::Slice(_)) =>
|
||||
{
|
||||
let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8], ());
|
||||
let allocation = Allocation::from_bytes_byte_aligned_immutable(data.as_byte_str(), ());
|
||||
let allocation = tcx.mk_const_alloc(allocation);
|
||||
ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() }
|
||||
}
|
||||
(ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
|
||||
let id = tcx.allocate_bytes_dedup(data, CTFE_ALLOC_SALT);
|
||||
(ast::LitKind::ByteStr(byte_sym, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
|
||||
let id = tcx.allocate_bytes_dedup(byte_sym.as_byte_str(), CTFE_ALLOC_SALT);
|
||||
ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
|
||||
}
|
||||
(ast::LitKind::CStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) =>
|
||||
(ast::LitKind::CStr(byte_sym, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) =>
|
||||
{
|
||||
let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8], ());
|
||||
let allocation =
|
||||
Allocation::from_bytes_byte_aligned_immutable(byte_sym.as_byte_str(), ());
|
||||
let allocation = tcx.mk_const_alloc(allocation);
|
||||
ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() }
|
||||
}
|
||||
(ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
|
||||
ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))
|
||||
ConstValue::Scalar(Scalar::from_uint(n, Size::from_bytes(1)))
|
||||
}
|
||||
(ast::LitKind::Int(n, _), ty::Uint(_)) if !neg => trunc(n.get()),
|
||||
(ast::LitKind::Int(n, _), ty::Int(_)) => {
|
||||
trunc(if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() })
|
||||
}
|
||||
(ast::LitKind::Float(n, _), ty::Float(fty)) => {
|
||||
parse_float_into_constval(*n, *fty, neg).unwrap()
|
||||
parse_float_into_constval(n, *fty, neg).unwrap()
|
||||
}
|
||||
(ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)),
|
||||
(ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
|
||||
(ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(b)),
|
||||
(ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(c)),
|
||||
(ast::LitKind::Err(guar), _) => {
|
||||
return Const::Ty(Ty::new_error(tcx, *guar), ty::Const::new_error(tcx, *guar));
|
||||
return Const::Ty(Ty::new_error(tcx, guar), ty::Const::new_error(tcx, guar));
|
||||
}
|
||||
_ => bug!("invalid lit/ty combination in `lit_to_mir_constant`: {lit:?}: {ty:?}"),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -43,27 +43,23 @@ pub(crate) fn lit_to_const<'tcx>(
|
|||
let str_bytes = s.as_str().as_bytes();
|
||||
ty::ValTree::from_raw_bytes(tcx, str_bytes)
|
||||
}
|
||||
(ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _))
|
||||
(ast::LitKind::ByteStr(byte_sym, _), ty::Ref(_, inner_ty, _))
|
||||
if matches!(inner_ty.kind(), ty::Slice(_) | ty::Array(..)) =>
|
||||
{
|
||||
let bytes = data as &[u8];
|
||||
ty::ValTree::from_raw_bytes(tcx, bytes)
|
||||
ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str())
|
||||
}
|
||||
(ast::LitKind::ByteStr(data, _), ty::Slice(_) | ty::Array(..))
|
||||
(ast::LitKind::ByteStr(byte_sym, _), ty::Slice(_) | ty::Array(..))
|
||||
if tcx.features().deref_patterns() =>
|
||||
{
|
||||
// Byte string literal patterns may have type `[u8]` or `[u8; N]` if `deref_patterns` is
|
||||
// enabled, in order to allow, e.g., `deref!(b"..."): Vec<u8>`.
|
||||
let bytes = data as &[u8];
|
||||
ty::ValTree::from_raw_bytes(tcx, bytes)
|
||||
ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str())
|
||||
}
|
||||
(ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
|
||||
ty::ValTree::from_scalar_int(tcx, (*n).into())
|
||||
ty::ValTree::from_scalar_int(tcx, n.into())
|
||||
}
|
||||
(ast::LitKind::CStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) =>
|
||||
{
|
||||
let bytes = data as &[u8];
|
||||
ty::ValTree::from_raw_bytes(tcx, bytes)
|
||||
(ast::LitKind::CStr(byte_sym, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) => {
|
||||
ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str())
|
||||
}
|
||||
(ast::LitKind::Int(n, _), ty::Uint(ui)) if !neg => {
|
||||
let scalar_int = trunc(n.get(), *ui);
|
||||
|
|
@ -76,15 +72,15 @@ pub(crate) fn lit_to_const<'tcx>(
|
|||
);
|
||||
ty::ValTree::from_scalar_int(tcx, scalar_int)
|
||||
}
|
||||
(ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int(tcx, (*b).into()),
|
||||
(ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int(tcx, b.into()),
|
||||
(ast::LitKind::Float(n, _), ty::Float(fty)) => {
|
||||
let bits = parse_float_into_scalar(*n, *fty, neg).unwrap_or_else(|| {
|
||||
let bits = parse_float_into_scalar(n, *fty, neg).unwrap_or_else(|| {
|
||||
tcx.dcx().bug(format!("couldn't parse float literal: {:?}", lit_input.lit))
|
||||
});
|
||||
ty::ValTree::from_scalar_int(tcx, bits)
|
||||
}
|
||||
(ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int(tcx, (*c).into()),
|
||||
(ast::LitKind::Err(guar), _) => return ty::Const::new_error(tcx, *guar),
|
||||
(ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int(tcx, c.into()),
|
||||
(ast::LitKind::Err(guar), _) => return ty::Const::new_error(tcx, guar),
|
||||
_ => return ty::Const::new_misc_error(tcx),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -680,7 +680,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
Some(pat_ty) => pat_ty,
|
||||
None => self.typeck_results.node_type(expr.hir_id),
|
||||
};
|
||||
let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg: *negated };
|
||||
let lit_input = LitToConstInput { lit: lit.node, ty: ct_ty, neg: *negated };
|
||||
let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
|
||||
self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind
|
||||
}
|
||||
|
|
|
|||
|
|
@ -230,11 +230,11 @@ fn split_block(
|
|||
let block_data = &mut basic_blocks[location.block];
|
||||
|
||||
// Drain every statement after this one and move the current terminator to a new basic block.
|
||||
let new_block = BasicBlockData {
|
||||
statements: block_data.statements.split_off(location.statement_index),
|
||||
terminator: block_data.terminator.take(),
|
||||
is_cleanup: block_data.is_cleanup,
|
||||
};
|
||||
let new_block = BasicBlockData::new_stmts(
|
||||
block_data.statements.split_off(location.statement_index),
|
||||
block_data.terminator.take(),
|
||||
block_data.is_cleanup,
|
||||
);
|
||||
|
||||
basic_blocks.push(new_block)
|
||||
}
|
||||
|
|
@ -270,10 +270,9 @@ fn insert_discr_cast_to_u128<'tcx>(
|
|||
let mu_array =
|
||||
local_decls.push(LocalDecl::with_source_info(mu_array_ty, source_info)).into();
|
||||
let rvalue = Rvalue::Cast(CastKind::Transmute, source_op, mu_array_ty);
|
||||
block_data.statements.push(Statement {
|
||||
source_info,
|
||||
kind: StatementKind::Assign(Box::new((mu_array, rvalue))),
|
||||
});
|
||||
block_data
|
||||
.statements
|
||||
.push(Statement::new(source_info, StatementKind::Assign(Box::new((mu_array, rvalue)))));
|
||||
|
||||
// Index into the array of MaybeUninit to get something that is actually
|
||||
// as wide as the discriminant.
|
||||
|
|
@ -294,10 +293,10 @@ fn insert_discr_cast_to_u128<'tcx>(
|
|||
let op_as_int =
|
||||
local_decls.push(LocalDecl::with_source_info(operand_int_ty, source_info)).into();
|
||||
let rvalue = Rvalue::Cast(CastKind::Transmute, source_op, operand_int_ty);
|
||||
block_data.statements.push(Statement {
|
||||
block_data.statements.push(Statement::new(
|
||||
source_info,
|
||||
kind: StatementKind::Assign(Box::new((op_as_int, rvalue))),
|
||||
});
|
||||
StatementKind::Assign(Box::new((op_as_int, rvalue))),
|
||||
));
|
||||
|
||||
(CastKind::IntToInt, Operand::Copy(op_as_int))
|
||||
};
|
||||
|
|
@ -306,10 +305,10 @@ fn insert_discr_cast_to_u128<'tcx>(
|
|||
let rvalue = Rvalue::Cast(cast_kind, discr_ty_bits, discr.ty);
|
||||
let discr_in_discr_ty =
|
||||
local_decls.push(LocalDecl::with_source_info(discr.ty, source_info)).into();
|
||||
block_data.statements.push(Statement {
|
||||
block_data.statements.push(Statement::new(
|
||||
source_info,
|
||||
kind: StatementKind::Assign(Box::new((discr_in_discr_ty, rvalue))),
|
||||
});
|
||||
StatementKind::Assign(Box::new((discr_in_discr_ty, rvalue))),
|
||||
));
|
||||
|
||||
// Cast the discriminant to a u128 (base for comparisions of enum discriminants).
|
||||
let const_u128 = Ty::new_uint(tcx, ty::UintTy::U128);
|
||||
|
|
@ -317,7 +316,7 @@ fn insert_discr_cast_to_u128<'tcx>(
|
|||
let discr = local_decls.push(LocalDecl::with_source_info(const_u128, source_info)).into();
|
||||
block_data
|
||||
.statements
|
||||
.push(Statement { source_info, kind: StatementKind::Assign(Box::new((discr, rvalue))) });
|
||||
.push(Statement::new(source_info, StatementKind::Assign(Box::new((discr, rvalue)))));
|
||||
|
||||
discr
|
||||
}
|
||||
|
|
@ -390,9 +389,9 @@ fn insert_uninhabited_enum_check<'tcx>(
|
|||
) {
|
||||
let is_ok: Place<'_> =
|
||||
local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into();
|
||||
block_data.statements.push(Statement {
|
||||
block_data.statements.push(Statement::new(
|
||||
source_info,
|
||||
kind: StatementKind::Assign(Box::new((
|
||||
StatementKind::Assign(Box::new((
|
||||
is_ok,
|
||||
Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
|
||||
span: source_info.span,
|
||||
|
|
@ -400,7 +399,7 @@ fn insert_uninhabited_enum_check<'tcx>(
|
|||
const_: Const::Val(ConstValue::from_bool(false), tcx.types.bool),
|
||||
}))),
|
||||
))),
|
||||
});
|
||||
));
|
||||
|
||||
block_data.terminator = Some(Terminator {
|
||||
source_info,
|
||||
|
|
@ -463,19 +462,19 @@ fn insert_niche_check<'tcx>(
|
|||
|
||||
let discr_diff: Place<'_> =
|
||||
local_decls.push(LocalDecl::with_source_info(tcx.types.u128, source_info)).into();
|
||||
block_data.statements.push(Statement {
|
||||
block_data.statements.push(Statement::new(
|
||||
source_info,
|
||||
kind: StatementKind::Assign(Box::new((
|
||||
StatementKind::Assign(Box::new((
|
||||
discr_diff,
|
||||
Rvalue::BinaryOp(BinOp::Sub, Box::new((Operand::Copy(discr), start_const))),
|
||||
))),
|
||||
});
|
||||
));
|
||||
|
||||
let is_ok: Place<'_> =
|
||||
local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into();
|
||||
block_data.statements.push(Statement {
|
||||
block_data.statements.push(Statement::new(
|
||||
source_info,
|
||||
kind: StatementKind::Assign(Box::new((
|
||||
StatementKind::Assign(Box::new((
|
||||
is_ok,
|
||||
Rvalue::BinaryOp(
|
||||
// This is a `WrappingRange`, so make sure to get the wrapping right.
|
||||
|
|
@ -483,7 +482,7 @@ fn insert_niche_check<'tcx>(
|
|||
Box::new((Operand::Copy(discr_diff), end_start_diff_const)),
|
||||
),
|
||||
))),
|
||||
});
|
||||
));
|
||||
|
||||
block_data.terminator = Some(Terminator {
|
||||
source_info,
|
||||
|
|
|
|||
|
|
@ -74,8 +74,7 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> {
|
|||
match *rvalue {
|
||||
// We need to detect unsizing casts that required vtables.
|
||||
mir::Rvalue::Cast(
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _)
|
||||
| mir::CastKind::PointerCoercion(PointerCoercion::DynStar, _),
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _),
|
||||
ref operand,
|
||||
target_ty,
|
||||
) => {
|
||||
|
|
|
|||
|
|
@ -1260,9 +1260,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
self.fail(location, format!("Unsize coercion, but `{op_ty}` isn't coercible to `{target_type}`"));
|
||||
}
|
||||
}
|
||||
CastKind::PointerCoercion(PointerCoercion::DynStar, _) => {
|
||||
// FIXME(dyn-star): make sure nothing needs to be done here.
|
||||
}
|
||||
CastKind::IntToInt | CastKind::IntToFloat => {
|
||||
let input_valid = op_ty.is_integral() || op_ty.is_char() || op_ty.is_bool();
|
||||
let target_valid = target_type.is_numeric() || target_type.is_char();
|
||||
|
|
|
|||
|
|
@ -694,8 +694,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
|
|||
// have to instantiate all methods of the trait being cast to, so we
|
||||
// can build the appropriate vtable.
|
||||
mir::Rvalue::Cast(
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _)
|
||||
| mir::CastKind::PointerCoercion(PointerCoercion::DynStar, _),
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _),
|
||||
ref operand,
|
||||
target_ty,
|
||||
) => {
|
||||
|
|
@ -710,9 +709,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
|
|||
// This could also be a different Unsize instruction, like
|
||||
// from a fixed sized array to a slice. But we are only
|
||||
// interested in things that produce a vtable.
|
||||
if (target_ty.is_trait() && !source_ty.is_trait())
|
||||
|| (target_ty.is_dyn_star() && !source_ty.is_dyn_star())
|
||||
{
|
||||
if target_ty.is_trait() && !source_ty.is_trait() {
|
||||
create_mono_items_for_vtable_methods(
|
||||
self.tcx,
|
||||
target_ty,
|
||||
|
|
@ -1109,14 +1106,6 @@ fn find_tails_for_unsizing<'tcx>(
|
|||
find_tails_for_unsizing(tcx, source_field, target_field)
|
||||
}
|
||||
|
||||
// `T` as `dyn* Trait` unsizes *directly*.
|
||||
//
|
||||
// FIXME(dyn_star): This case is a bit awkward, b/c we're not really computing
|
||||
// a tail here. We probably should handle this separately in the *caller* of
|
||||
// this function, rather than returning something that is semantically different
|
||||
// than what we return above.
|
||||
(_, &ty::Dynamic(_, _, ty::DynStar)) => (source_ty, target_ty),
|
||||
|
||||
_ => bug!(
|
||||
"find_vtable_types_for_unsizing: invalid coercion {:?} -> {:?}",
|
||||
source_ty,
|
||||
|
|
@ -1344,9 +1333,7 @@ fn visit_mentioned_item<'tcx>(
|
|||
// This could also be a different Unsize instruction, like
|
||||
// from a fixed sized array to a slice. But we are only
|
||||
// interested in things that produce a vtable.
|
||||
if (target_ty.is_trait() && !source_ty.is_trait())
|
||||
|| (target_ty.is_dyn_star() && !source_ty.is_dyn_star())
|
||||
{
|
||||
if target_ty.is_trait() && !source_ty.is_trait() {
|
||||
create_mono_items_for_vtable_methods(tcx, target_ty, source_ty, span, output);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
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