Merge from rustc

This commit is contained in:
The Miri Cronjob Bot 2025-07-02 05:05:02 +00:00
commit af5f4be160
520 changed files with 5024 additions and 5651 deletions

View file

@ -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"

View file

@ -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!(),
}
}

View file

@ -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) => {

View file

@ -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))
}

View file

@ -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),

View file

@ -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");

View file

@ -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);

View file

@ -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) => {

View file

@ -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 },

View file

@ -38,6 +38,9 @@ impl AttributeKind {
NoMangle(..) => No,
Optimize(..) => No,
PubTransparent(..) => Yes,
RustcLayoutScalarValidRangeEnd(..) => Yes,
RustcLayoutScalarValidRangeStart(..) => Yes,
RustcObjectLifetimeDefault => No,
SkipDuringMethodDispatch { .. } => No,
TrackCaller(..) => Yes,
Used { .. } => No,

View file

@ -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)

View file

@ -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;

View file

@ -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");

View 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)
}
}

View file

@ -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,

View file

@ -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(

View file

@ -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

View file

@ -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,

View file

@ -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);

View file

@ -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)]

View file

@ -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,

View file

@ -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(_, _)));

View file

@ -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);

View file

@ -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>(

View file

@ -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)),

View file

@ -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();

View file

@ -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>

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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)

View file

@ -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>>(

View file

@ -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 };
}

View file

@ -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);
}

View file

@ -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

View file

@ -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);
}

View file

@ -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,

View file

@ -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());

View file

@ -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,

View file

@ -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)
}
}

View file

@ -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);

View file

@ -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.

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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`")]

View file

@ -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::{

View file

@ -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,

View file

@ -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();

View file

@ -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)]

View file

@ -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

View file

@ -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,
}
}

View file

@ -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<'_>,

View file

@ -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

View file

@ -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 {

View file

@ -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]`.

View file

@ -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.

View file

@ -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.

View file

@ -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,
]);
)

View file

@ -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,
}
}

View file

@ -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);
}

View file

@ -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),
}

View file

@ -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) {

View file

@ -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();

View file

@ -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);

View file

@ -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)
}

View file

@ -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);

View file

@ -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),

View file

@ -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

View file

@ -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,

View file

@ -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,

View file

@ -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)]

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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>);

View file

@ -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>) {

View file

@ -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 {

View file

@ -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) }

View file

@ -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.

View file

@ -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,

View file

@ -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)]

View file

@ -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.

View file

@ -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>>,

View file

@ -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>,

View file

@ -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>,

View file

@ -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
}

View file

@ -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) {

View file

@ -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

View file

@ -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.

View file

@ -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};

View file

@ -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> {

View file

@ -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(..)

View file

@ -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 {

View file

@ -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,

View file

@ -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:?}"),
};

View file

@ -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),
};

View file

@ -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
}

View file

@ -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,

View file

@ -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,
) => {

View file

@ -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();

View file

@ -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