Auto merge of #152506 - Urgau:rollup-MlGAszj, r=Urgau
Rollup of 7 pull requests Successful merges: - rust-lang/rust#152505 (Sync relnotes for stable 1.93.1) - rust-lang/rust#137487 (Stabilize `assert_matches`) - rust-lang/rust#152281 (borrowck: suggest `&mut *x` for pattern reborrows) - rust-lang/rust#151142 (Support ADT types in type info reflection) - rust-lang/rust#152477 (rustc-dev-guide subtree update) - rust-lang/rust#152488 (allow `deprecated(since = "CURRENT_RUSTC_VERSION")`) - rust-lang/rust#152491 (Remove unused `fluent-syntax` dependency from tidy)
This commit is contained in:
commit
605f49b274
122 changed files with 1178 additions and 875 deletions
|
|
@ -5564,7 +5564,6 @@ dependencies = [
|
||||||
"build_helper",
|
"build_helper",
|
||||||
"cargo_metadata 0.21.0",
|
"cargo_metadata 0.21.0",
|
||||||
"clap",
|
"clap",
|
||||||
"fluent-syntax",
|
|
||||||
"globset",
|
"globset",
|
||||||
"ignore",
|
"ignore",
|
||||||
"miropt-test-tools",
|
"miropt-test-tools",
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,12 @@
|
||||||
|
Version 1.93.1 (2026-02-12)
|
||||||
|
===========================
|
||||||
|
|
||||||
|
<a id="1.93.1"></a>
|
||||||
|
|
||||||
|
- [Don't try to recover keyword as non-keyword identifier](https://github.com/rust-lang/rust/pull/150590), fixing an ICE that especially [affected rustfmt](https://github.com/rust-lang/rustfmt/issues/6739).
|
||||||
|
- [Fix `clippy::panicking_unwrap` false-positive on field access with implicit deref](https://github.com/rust-lang/rust-clippy/pull/16196).
|
||||||
|
- [Revert "Update wasm-related dependencies in CI"](https://github.com/rust-lang/rust/pull/152259), fixing file descriptor leaks on the `wasm32-wasip2` target.
|
||||||
|
|
||||||
Version 1.93.0 (2026-01-22)
|
Version 1.93.0 (2026-01-22)
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
|
#![cfg_attr(all(feature = "nightly", bootstrap), feature(assert_matches))]
|
||||||
#![cfg_attr(feature = "nightly", allow(internal_features))]
|
#![cfg_attr(feature = "nightly", allow(internal_features))]
|
||||||
#![cfg_attr(feature = "nightly", feature(assert_matches))]
|
|
||||||
#![cfg_attr(feature = "nightly", feature(rustc_attrs))]
|
#![cfg_attr(feature = "nightly", feature(rustc_attrs))]
|
||||||
#![cfg_attr(feature = "nightly", feature(step_trait))]
|
#![cfg_attr(feature = "nightly", feature(step_trait))]
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use rustc_hir::attrs::{DeprecatedSince, Deprecation};
|
use rustc_hir::attrs::{DeprecatedSince, Deprecation};
|
||||||
|
use rustc_hir::{RustcVersion, VERSION_PLACEHOLDER};
|
||||||
|
|
||||||
use super::prelude::*;
|
use super::prelude::*;
|
||||||
use super::util::parse_version;
|
use super::util::parse_version;
|
||||||
|
|
@ -143,6 +144,8 @@ impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {
|
||||||
DeprecatedSince::Future
|
DeprecatedSince::Future
|
||||||
} else if !is_rustc {
|
} else if !is_rustc {
|
||||||
DeprecatedSince::NonStandard(since)
|
DeprecatedSince::NonStandard(since)
|
||||||
|
} else if since.as_str() == VERSION_PLACEHOLDER {
|
||||||
|
DeprecatedSince::RustcVersion(RustcVersion::CURRENT)
|
||||||
} else if let Some(version) = parse_version(since) {
|
} else if let Some(version) = parse_version(since) {
|
||||||
DeprecatedSince::RustcVersion(version)
|
DeprecatedSince::RustcVersion(version)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -354,14 +354,71 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||||
self.infcx.tcx.sess.source_map().span_to_snippet(source_info.span)
|
self.infcx.tcx.sess.source_map().span_to_snippet(source_info.span)
|
||||||
{
|
{
|
||||||
if snippet.starts_with("&mut ") {
|
if snippet.starts_with("&mut ") {
|
||||||
// We don't have access to the HIR to get accurate spans, but we can
|
// In calls, `&mut &mut T` may be deref-coerced to `&mut T`, and
|
||||||
// give a best effort structured suggestion.
|
// removing the extra `&mut` is the most direct suggestion. But for
|
||||||
|
// pattern-matching expressions (`match`, `if let`, `while let`), that
|
||||||
|
// can easily turn into a move, so prefer suggesting an explicit
|
||||||
|
// reborrow via `&mut *x` instead.
|
||||||
|
let mut in_pat_scrutinee = false;
|
||||||
|
let mut is_deref_coerced = false;
|
||||||
|
if let Some(expr) = self.find_expr(source_info.span) {
|
||||||
|
let tcx = self.infcx.tcx;
|
||||||
|
let span = expr.span.source_callsite();
|
||||||
|
for (_, node) in tcx.hir_parent_iter(expr.hir_id) {
|
||||||
|
if let Node::Expr(parent_expr) = node {
|
||||||
|
match parent_expr.kind {
|
||||||
|
ExprKind::Match(scrutinee, ..)
|
||||||
|
if scrutinee
|
||||||
|
.span
|
||||||
|
.source_callsite()
|
||||||
|
.contains(span) =>
|
||||||
|
{
|
||||||
|
in_pat_scrutinee = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ExprKind::Let(let_expr)
|
||||||
|
if let_expr
|
||||||
|
.init
|
||||||
|
.span
|
||||||
|
.source_callsite()
|
||||||
|
.contains(span) =>
|
||||||
|
{
|
||||||
|
in_pat_scrutinee = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let typeck = tcx.typeck(expr.hir_id.owner.def_id);
|
||||||
|
is_deref_coerced =
|
||||||
|
typeck.expr_adjustments(expr).iter().any(|adj| {
|
||||||
|
matches!(adj.kind, ty::adjustment::Adjust::Deref(_))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if in_pat_scrutinee {
|
||||||
|
// Best-effort structured suggestion: insert `*` after `&mut `.
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
source_info
|
||||||
|
.span
|
||||||
|
.with_lo(source_info.span.lo() + BytePos(5))
|
||||||
|
.shrink_to_lo(),
|
||||||
|
"to reborrow the mutable reference, add `*`",
|
||||||
|
"*",
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
} else if is_deref_coerced {
|
||||||
|
// We don't have access to the HIR to get accurate spans, but we
|
||||||
|
// can give a best effort structured suggestion.
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
source_info.span.with_hi(source_info.span.lo() + BytePos(5)),
|
source_info.span.with_hi(source_info.span.lo() + BytePos(5)),
|
||||||
"if there is only one mutable reborrow, remove the `&mut`",
|
"if there is only one mutable reborrow, remove the `&mut`",
|
||||||
"",
|
"",
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// This can occur with things like `(&mut self).foo()`.
|
// This can occur with things like `(&mut self).foo()`.
|
||||||
err.span_help(source_info.span, "try removing `&mut` here");
|
err.span_help(source_info.span, "try removing `&mut` here");
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
#![feature(assert_matches)]
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(default_field_values)]
|
#![feature(default_field_values)]
|
||||||
#![feature(file_buffered)]
|
#![feature(file_buffered)]
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
#![feature(assert_matches)]
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(decl_macro)]
|
#![feature(decl_macro)]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
//! This API is completely unstable and subject to change.
|
//! This API is completely unstable and subject to change.
|
||||||
|
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![feature(assert_matches)]
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![feature(extern_types)]
|
#![feature(extern_types)]
|
||||||
#![feature(file_buffered)]
|
#![feature(file_buffered)]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![feature(assert_matches)]
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(file_buffered)]
|
#![feature(file_buffered)]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
use rustc_abi::FieldIdx;
|
mod adt;
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
use rustc_abi::{FieldIdx, VariantIdx};
|
||||||
use rustc_ast::Mutability;
|
use rustc_ast::Mutability;
|
||||||
use rustc_hir::LangItem;
|
use rustc_hir::LangItem;
|
||||||
use rustc_middle::span_bug;
|
use rustc_middle::span_bug;
|
||||||
|
|
@ -8,11 +12,58 @@ use rustc_span::{Symbol, sym};
|
||||||
|
|
||||||
use crate::const_eval::CompileTimeMachine;
|
use crate::const_eval::CompileTimeMachine;
|
||||||
use crate::interpret::{
|
use crate::interpret::{
|
||||||
CtfeProvenance, Immediate, InterpCx, InterpResult, MPlaceTy, MemoryKind, Scalar, Writeable,
|
CtfeProvenance, Immediate, InterpCx, InterpResult, MPlaceTy, MemoryKind, Projectable, Scalar,
|
||||||
interp_ok,
|
Writeable, interp_ok,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
||||||
|
/// Equivalent to `project_downcast`, but identifies the variant by name instead of index.
|
||||||
|
fn downcast<'a>(
|
||||||
|
&self,
|
||||||
|
place: &(impl Writeable<'tcx, CtfeProvenance> + 'a),
|
||||||
|
name: Symbol,
|
||||||
|
) -> InterpResult<'tcx, (VariantIdx, impl Writeable<'tcx, CtfeProvenance> + 'a)> {
|
||||||
|
let variants = place.layout().ty.ty_adt_def().unwrap().variants();
|
||||||
|
let variant_idx = variants
|
||||||
|
.iter_enumerated()
|
||||||
|
.find(|(_idx, var)| var.name == name)
|
||||||
|
.unwrap_or_else(|| panic!("got {name} but expected one of {variants:#?}"))
|
||||||
|
.0;
|
||||||
|
|
||||||
|
interp_ok((variant_idx, self.project_downcast(place, variant_idx)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
// A general method to write an array to a static slice place.
|
||||||
|
fn allocate_fill_and_write_slice_ptr(
|
||||||
|
&mut self,
|
||||||
|
slice_place: impl Writeable<'tcx, CtfeProvenance>,
|
||||||
|
len: u64,
|
||||||
|
writer: impl Fn(&mut Self, /* index */ u64, MPlaceTy<'tcx>) -> InterpResult<'tcx>,
|
||||||
|
) -> InterpResult<'tcx> {
|
||||||
|
// Array element type
|
||||||
|
let field_ty = slice_place
|
||||||
|
.layout()
|
||||||
|
.ty
|
||||||
|
.builtin_deref(false)
|
||||||
|
.unwrap()
|
||||||
|
.sequence_element_type(self.tcx.tcx);
|
||||||
|
|
||||||
|
// Allocate an array
|
||||||
|
let array_layout = self.layout_of(Ty::new_array(self.tcx.tcx, field_ty, len))?;
|
||||||
|
let array_place = self.allocate(array_layout, MemoryKind::Stack)?;
|
||||||
|
|
||||||
|
// Fill the array fields
|
||||||
|
let mut field_places = self.project_array_fields(&array_place)?;
|
||||||
|
while let Some((i, place)) = field_places.next(self)? {
|
||||||
|
writer(self, i, place)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the slice pointing to the array
|
||||||
|
let array_place = array_place.map_provenance(CtfeProvenance::as_immutable);
|
||||||
|
let ptr = Immediate::new_slice(array_place.ptr(), len, self);
|
||||||
|
self.write_immediate(ptr, &slice_place)
|
||||||
|
}
|
||||||
|
|
||||||
/// Writes a `core::mem::type_info::TypeInfo` for a given type, `ty` to the given place.
|
/// Writes a `core::mem::type_info::TypeInfo` for a given type, `ty` to the given place.
|
||||||
pub(crate) fn write_type_info(
|
pub(crate) fn write_type_info(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
@ -26,22 +77,13 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
||||||
// Fill all fields of the `TypeInfo` struct.
|
// Fill all fields of the `TypeInfo` struct.
|
||||||
for (idx, field) in ty_struct.fields.iter_enumerated() {
|
for (idx, field) in ty_struct.fields.iter_enumerated() {
|
||||||
let field_dest = self.project_field(dest, idx)?;
|
let field_dest = self.project_field(dest, idx)?;
|
||||||
let downcast = |name: Symbol| {
|
|
||||||
let variants = field_dest.layout().ty.ty_adt_def().unwrap().variants();
|
|
||||||
let variant_id = variants
|
|
||||||
.iter_enumerated()
|
|
||||||
.find(|(_idx, var)| var.name == name)
|
|
||||||
.unwrap_or_else(|| panic!("got {name} but expected one of {variants:#?}"))
|
|
||||||
.0;
|
|
||||||
|
|
||||||
interp_ok((variant_id, self.project_downcast(&field_dest, variant_id)?))
|
|
||||||
};
|
|
||||||
let ptr_bit_width = || self.tcx.data_layout.pointer_size().bits();
|
let ptr_bit_width = || self.tcx.data_layout.pointer_size().bits();
|
||||||
match field.name {
|
match field.name {
|
||||||
sym::kind => {
|
sym::kind => {
|
||||||
let variant_index = match ty.kind() {
|
let variant_index = match ty.kind() {
|
||||||
ty::Tuple(fields) => {
|
ty::Tuple(fields) => {
|
||||||
let (variant, variant_place) = downcast(sym::Tuple)?;
|
let (variant, variant_place) =
|
||||||
|
self.downcast(&field_dest, sym::Tuple)?;
|
||||||
// project to the single tuple variant field of `type_info::Tuple` struct type
|
// project to the single tuple variant field of `type_info::Tuple` struct type
|
||||||
let tuple_place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
let tuple_place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
@ -55,11 +97,12 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
||||||
.fields
|
.fields
|
||||||
.len()
|
.len()
|
||||||
);
|
);
|
||||||
self.write_tuple_fields(tuple_place, fields, ty)?;
|
self.write_tuple_type_info(tuple_place, fields, ty)?;
|
||||||
variant
|
variant
|
||||||
}
|
}
|
||||||
ty::Array(ty, len) => {
|
ty::Array(ty, len) => {
|
||||||
let (variant, variant_place) = downcast(sym::Array)?;
|
let (variant, variant_place) =
|
||||||
|
self.downcast(&field_dest, sym::Array)?;
|
||||||
let array_place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
let array_place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||||
|
|
||||||
self.write_array_type_info(array_place, *ty, *len)?;
|
self.write_array_type_info(array_place, *ty, *len)?;
|
||||||
|
|
@ -67,23 +110,29 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
||||||
variant
|
variant
|
||||||
}
|
}
|
||||||
ty::Slice(ty) => {
|
ty::Slice(ty) => {
|
||||||
let (variant, variant_place) = downcast(sym::Slice)?;
|
let (variant, variant_place) =
|
||||||
|
self.downcast(&field_dest, sym::Slice)?;
|
||||||
let slice_place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
let slice_place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||||
|
|
||||||
self.write_slice_type_info(slice_place, *ty)?;
|
self.write_slice_type_info(slice_place, *ty)?;
|
||||||
|
|
||||||
variant
|
variant
|
||||||
}
|
}
|
||||||
|
ty::Adt(adt_def, generics) => {
|
||||||
|
self.write_adt_type_info(&field_dest, (ty, *adt_def), generics)?
|
||||||
|
}
|
||||||
ty::Bool => {
|
ty::Bool => {
|
||||||
let (variant, _variant_place) = downcast(sym::Bool)?;
|
let (variant, _variant_place) =
|
||||||
|
self.downcast(&field_dest, sym::Bool)?;
|
||||||
variant
|
variant
|
||||||
}
|
}
|
||||||
ty::Char => {
|
ty::Char => {
|
||||||
let (variant, _variant_place) = downcast(sym::Char)?;
|
let (variant, _variant_place) =
|
||||||
|
self.downcast(&field_dest, sym::Char)?;
|
||||||
variant
|
variant
|
||||||
}
|
}
|
||||||
ty::Int(int_ty) => {
|
ty::Int(int_ty) => {
|
||||||
let (variant, variant_place) = downcast(sym::Int)?;
|
let (variant, variant_place) = self.downcast(&field_dest, sym::Int)?;
|
||||||
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||||
self.write_int_type_info(
|
self.write_int_type_info(
|
||||||
place,
|
place,
|
||||||
|
|
@ -93,7 +142,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
||||||
variant
|
variant
|
||||||
}
|
}
|
||||||
ty::Uint(uint_ty) => {
|
ty::Uint(uint_ty) => {
|
||||||
let (variant, variant_place) = downcast(sym::Int)?;
|
let (variant, variant_place) = self.downcast(&field_dest, sym::Int)?;
|
||||||
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||||
self.write_int_type_info(
|
self.write_int_type_info(
|
||||||
place,
|
place,
|
||||||
|
|
@ -103,17 +152,19 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
||||||
variant
|
variant
|
||||||
}
|
}
|
||||||
ty::Float(float_ty) => {
|
ty::Float(float_ty) => {
|
||||||
let (variant, variant_place) = downcast(sym::Float)?;
|
let (variant, variant_place) =
|
||||||
|
self.downcast(&field_dest, sym::Float)?;
|
||||||
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||||
self.write_float_type_info(place, float_ty.bit_width())?;
|
self.write_float_type_info(place, float_ty.bit_width())?;
|
||||||
variant
|
variant
|
||||||
}
|
}
|
||||||
ty::Str => {
|
ty::Str => {
|
||||||
let (variant, _variant_place) = downcast(sym::Str)?;
|
let (variant, _variant_place) = self.downcast(&field_dest, sym::Str)?;
|
||||||
variant
|
variant
|
||||||
}
|
}
|
||||||
ty::Ref(_, ty, mutability) => {
|
ty::Ref(_, ty, mutability) => {
|
||||||
let (variant, variant_place) = downcast(sym::Reference)?;
|
let (variant, variant_place) =
|
||||||
|
self.downcast(&field_dest, sym::Reference)?;
|
||||||
let reference_place =
|
let reference_place =
|
||||||
self.project_field(&variant_place, FieldIdx::ZERO)?;
|
self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||||
self.write_reference_type_info(reference_place, *ty, *mutability)?;
|
self.write_reference_type_info(reference_place, *ty, *mutability)?;
|
||||||
|
|
@ -121,7 +172,8 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
||||||
variant
|
variant
|
||||||
}
|
}
|
||||||
ty::RawPtr(ty, mutability) => {
|
ty::RawPtr(ty, mutability) => {
|
||||||
let (variant, variant_place) = downcast(sym::Pointer)?;
|
let (variant, variant_place) =
|
||||||
|
self.downcast(&field_dest, sym::Pointer)?;
|
||||||
let pointer_place =
|
let pointer_place =
|
||||||
self.project_field(&variant_place, FieldIdx::ZERO)?;
|
self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||||
|
|
||||||
|
|
@ -130,13 +182,13 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
||||||
variant
|
variant
|
||||||
}
|
}
|
||||||
ty::Dynamic(predicates, region) => {
|
ty::Dynamic(predicates, region) => {
|
||||||
let (variant, variant_place) = downcast(sym::DynTrait)?;
|
let (variant, variant_place) =
|
||||||
|
self.downcast(&field_dest, sym::DynTrait)?;
|
||||||
let dyn_place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
let dyn_place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||||
self.write_dyn_trait_type_info(dyn_place, *predicates, *region)?;
|
self.write_dyn_trait_type_info(dyn_place, *predicates, *region)?;
|
||||||
variant
|
variant
|
||||||
}
|
}
|
||||||
ty::Adt(_, _)
|
ty::Foreign(_)
|
||||||
| ty::Foreign(_)
|
|
||||||
| ty::Pat(_, _)
|
| ty::Pat(_, _)
|
||||||
| ty::FnDef(..)
|
| ty::FnDef(..)
|
||||||
| ty::FnPtr(..)
|
| ty::FnPtr(..)
|
||||||
|
|
@ -151,14 +203,14 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
||||||
| ty::Bound(..)
|
| ty::Bound(..)
|
||||||
| ty::Placeholder(_)
|
| ty::Placeholder(_)
|
||||||
| ty::Infer(..)
|
| ty::Infer(..)
|
||||||
| ty::Error(_) => downcast(sym::Other)?.0,
|
| ty::Error(_) => self.downcast(&field_dest, sym::Other)?.0,
|
||||||
};
|
};
|
||||||
self.write_discriminant(variant_index, &field_dest)?
|
self.write_discriminant(variant_index, &field_dest)?
|
||||||
}
|
}
|
||||||
sym::size => {
|
sym::size => {
|
||||||
let layout = self.layout_of(ty)?;
|
let layout = self.layout_of(ty)?;
|
||||||
let variant_index = if layout.is_sized() {
|
let variant_index = if layout.is_sized() {
|
||||||
let (variant, variant_place) = downcast(sym::Some)?;
|
let (variant, variant_place) = self.downcast(&field_dest, sym::Some)?;
|
||||||
let size_field_place =
|
let size_field_place =
|
||||||
self.project_field(&variant_place, FieldIdx::ZERO)?;
|
self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||||
self.write_scalar(
|
self.write_scalar(
|
||||||
|
|
@ -168,7 +220,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
||||||
)?;
|
)?;
|
||||||
variant
|
variant
|
||||||
} else {
|
} else {
|
||||||
downcast(sym::None)?.0
|
self.downcast(&field_dest, sym::None)?.0
|
||||||
};
|
};
|
||||||
self.write_discriminant(variant_index, &field_dest)?;
|
self.write_discriminant(variant_index, &field_dest)?;
|
||||||
}
|
}
|
||||||
|
|
@ -179,46 +231,12 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
||||||
interp_ok(())
|
interp_ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn write_tuple_fields(
|
|
||||||
&mut self,
|
|
||||||
tuple_place: impl Writeable<'tcx, CtfeProvenance>,
|
|
||||||
fields: &[Ty<'tcx>],
|
|
||||||
tuple_ty: Ty<'tcx>,
|
|
||||||
) -> InterpResult<'tcx> {
|
|
||||||
// project into the `type_info::Tuple::fields` field
|
|
||||||
let fields_slice_place = self.project_field(&tuple_place, FieldIdx::ZERO)?;
|
|
||||||
// get the `type_info::Field` type from `fields: &[Field]`
|
|
||||||
let field_type = fields_slice_place
|
|
||||||
.layout()
|
|
||||||
.ty
|
|
||||||
.builtin_deref(false)
|
|
||||||
.unwrap()
|
|
||||||
.sequence_element_type(self.tcx.tcx);
|
|
||||||
// Create an array with as many elements as the number of fields in the inspected tuple
|
|
||||||
let fields_layout =
|
|
||||||
self.layout_of(Ty::new_array(self.tcx.tcx, field_type, fields.len() as u64))?;
|
|
||||||
let fields_place = self.allocate(fields_layout, MemoryKind::Stack)?;
|
|
||||||
let mut fields_places = self.project_array_fields(&fields_place)?;
|
|
||||||
|
|
||||||
let tuple_layout = self.layout_of(tuple_ty)?;
|
|
||||||
|
|
||||||
while let Some((i, place)) = fields_places.next(self)? {
|
|
||||||
let field_ty = fields[i as usize];
|
|
||||||
self.write_field(field_ty, place, tuple_layout, i)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let fields_place = fields_place.map_provenance(CtfeProvenance::as_immutable);
|
|
||||||
|
|
||||||
let ptr = Immediate::new_slice(fields_place.ptr(), fields.len() as u64, self);
|
|
||||||
|
|
||||||
self.write_immediate(ptr, &fields_slice_place)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_field(
|
fn write_field(
|
||||||
&mut self,
|
&mut self,
|
||||||
field_ty: Ty<'tcx>,
|
field_ty: Ty<'tcx>,
|
||||||
place: MPlaceTy<'tcx>,
|
place: MPlaceTy<'tcx>,
|
||||||
layout: TyAndLayout<'tcx>,
|
layout: TyAndLayout<'tcx>,
|
||||||
|
name: Option<Symbol>,
|
||||||
idx: u64,
|
idx: u64,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
for (field_idx, field_ty_field) in
|
for (field_idx, field_ty_field) in
|
||||||
|
|
@ -226,7 +244,19 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
||||||
{
|
{
|
||||||
let field_place = self.project_field(&place, field_idx)?;
|
let field_place = self.project_field(&place, field_idx)?;
|
||||||
match field_ty_field.name {
|
match field_ty_field.name {
|
||||||
sym::ty => self.write_type_id(field_ty, &field_place)?,
|
sym::name => {
|
||||||
|
let name = match name.as_ref() {
|
||||||
|
Some(name) => Cow::Borrowed(name.as_str()),
|
||||||
|
None => Cow::Owned(idx.to_string()), // For tuples
|
||||||
|
};
|
||||||
|
let name_place = self.allocate_str_dedup(&name)?;
|
||||||
|
let ptr = self.mplace_to_ref(&name_place)?;
|
||||||
|
self.write_immediate(*ptr, &field_place)?
|
||||||
|
}
|
||||||
|
sym::ty => {
|
||||||
|
let field_ty = self.tcx.erase_and_anonymize_regions(field_ty);
|
||||||
|
self.write_type_id(field_ty, &field_place)?
|
||||||
|
}
|
||||||
sym::offset => {
|
sym::offset => {
|
||||||
let offset = layout.fields.offset(idx as usize);
|
let offset = layout.fields.offset(idx as usize);
|
||||||
self.write_scalar(
|
self.write_scalar(
|
||||||
|
|
@ -242,6 +272,24 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
||||||
interp_ok(())
|
interp_ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn write_tuple_type_info(
|
||||||
|
&mut self,
|
||||||
|
tuple_place: impl Writeable<'tcx, CtfeProvenance>,
|
||||||
|
fields: &[Ty<'tcx>],
|
||||||
|
tuple_ty: Ty<'tcx>,
|
||||||
|
) -> InterpResult<'tcx> {
|
||||||
|
let tuple_layout = self.layout_of(tuple_ty)?;
|
||||||
|
let fields_slice_place = self.project_field(&tuple_place, FieldIdx::ZERO)?;
|
||||||
|
self.allocate_fill_and_write_slice_ptr(
|
||||||
|
fields_slice_place,
|
||||||
|
fields.len() as u64,
|
||||||
|
|this, i, place| {
|
||||||
|
let field_ty = fields[i as usize];
|
||||||
|
this.write_field(field_ty, place, tuple_layout, None, i)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn write_array_type_info(
|
pub(crate) fn write_array_type_info(
|
||||||
&mut self,
|
&mut self,
|
||||||
place: impl Writeable<'tcx, CtfeProvenance>,
|
place: impl Writeable<'tcx, CtfeProvenance>,
|
||||||
|
|
|
||||||
276
compiler/rustc_const_eval/src/const_eval/type_info/adt.rs
Normal file
276
compiler/rustc_const_eval/src/const_eval/type_info/adt.rs
Normal file
|
|
@ -0,0 +1,276 @@
|
||||||
|
use rustc_abi::{FieldIdx, VariantIdx};
|
||||||
|
use rustc_middle::ty::layout::TyAndLayout;
|
||||||
|
use rustc_middle::ty::{
|
||||||
|
AdtDef, AdtKind, Const, ConstKind, GenericArgKind, GenericArgs, Region, Ty, VariantDef,
|
||||||
|
};
|
||||||
|
use rustc_middle::{bug, span_bug};
|
||||||
|
use rustc_span::sym;
|
||||||
|
|
||||||
|
use crate::const_eval::CompileTimeMachine;
|
||||||
|
use crate::interpret::{
|
||||||
|
CtfeProvenance, InterpCx, InterpResult, MPlaceTy, Projectable, Scalar, Writeable, interp_ok,
|
||||||
|
};
|
||||||
|
|
||||||
|
impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
||||||
|
// FIXME(type_info): No semver considerations for now
|
||||||
|
pub(crate) fn write_adt_type_info(
|
||||||
|
&mut self,
|
||||||
|
place: &impl Writeable<'tcx, CtfeProvenance>,
|
||||||
|
adt: (Ty<'tcx>, AdtDef<'tcx>),
|
||||||
|
generics: &'tcx GenericArgs<'tcx>,
|
||||||
|
) -> InterpResult<'tcx, VariantIdx> {
|
||||||
|
let (adt_ty, adt_def) = adt;
|
||||||
|
let variant_idx = match adt_def.adt_kind() {
|
||||||
|
AdtKind::Struct => {
|
||||||
|
let (variant, variant_place) = self.downcast(place, sym::Struct)?;
|
||||||
|
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||||
|
self.write_struct_type_info(
|
||||||
|
place,
|
||||||
|
(adt_ty, adt_def.variant(VariantIdx::ZERO)),
|
||||||
|
generics,
|
||||||
|
)?;
|
||||||
|
variant
|
||||||
|
}
|
||||||
|
AdtKind::Union => {
|
||||||
|
let (variant, variant_place) = self.downcast(place, sym::Union)?;
|
||||||
|
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||||
|
self.write_union_type_info(
|
||||||
|
place,
|
||||||
|
(adt_ty, adt_def.variant(VariantIdx::ZERO)),
|
||||||
|
generics,
|
||||||
|
)?;
|
||||||
|
variant
|
||||||
|
}
|
||||||
|
AdtKind::Enum => {
|
||||||
|
let (variant, variant_place) = self.downcast(place, sym::Enum)?;
|
||||||
|
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||||
|
self.write_enum_type_info(place, adt, generics)?;
|
||||||
|
variant
|
||||||
|
}
|
||||||
|
};
|
||||||
|
interp_ok(variant_idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn write_struct_type_info(
|
||||||
|
&mut self,
|
||||||
|
place: impl Writeable<'tcx, CtfeProvenance>,
|
||||||
|
struct_: (Ty<'tcx>, &'tcx VariantDef),
|
||||||
|
generics: &'tcx GenericArgs<'tcx>,
|
||||||
|
) -> InterpResult<'tcx> {
|
||||||
|
let (struct_ty, struct_def) = struct_;
|
||||||
|
let struct_layout = self.layout_of(struct_ty)?;
|
||||||
|
|
||||||
|
for (field_idx, field) in
|
||||||
|
place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated()
|
||||||
|
{
|
||||||
|
let field_place = self.project_field(&place, field_idx)?;
|
||||||
|
|
||||||
|
match field.name {
|
||||||
|
sym::generics => self.write_generics(field_place, generics)?,
|
||||||
|
sym::fields => {
|
||||||
|
self.write_variant_fields(field_place, struct_def, struct_layout, generics)?
|
||||||
|
}
|
||||||
|
sym::non_exhaustive => {
|
||||||
|
let is_non_exhaustive = struct_def.is_field_list_non_exhaustive();
|
||||||
|
self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)?
|
||||||
|
}
|
||||||
|
other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interp_ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn write_union_type_info(
|
||||||
|
&mut self,
|
||||||
|
place: impl Writeable<'tcx, CtfeProvenance>,
|
||||||
|
union_: (Ty<'tcx>, &'tcx VariantDef),
|
||||||
|
generics: &'tcx GenericArgs<'tcx>,
|
||||||
|
) -> InterpResult<'tcx> {
|
||||||
|
let (union_ty, union_def) = union_;
|
||||||
|
let union_layout = self.layout_of(union_ty)?;
|
||||||
|
|
||||||
|
for (field_idx, field) in
|
||||||
|
place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated()
|
||||||
|
{
|
||||||
|
let field_place = self.project_field(&place, field_idx)?;
|
||||||
|
|
||||||
|
match field.name {
|
||||||
|
sym::generics => self.write_generics(field_place, generics)?,
|
||||||
|
sym::fields => {
|
||||||
|
self.write_variant_fields(field_place, union_def, union_layout, generics)?
|
||||||
|
}
|
||||||
|
sym::non_exhaustive => {
|
||||||
|
let is_non_exhaustive = union_def.is_field_list_non_exhaustive();
|
||||||
|
self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)?
|
||||||
|
}
|
||||||
|
other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interp_ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn write_enum_type_info(
|
||||||
|
&mut self,
|
||||||
|
place: impl Writeable<'tcx, CtfeProvenance>,
|
||||||
|
enum_: (Ty<'tcx>, AdtDef<'tcx>),
|
||||||
|
generics: &'tcx GenericArgs<'tcx>,
|
||||||
|
) -> InterpResult<'tcx> {
|
||||||
|
let (enum_ty, enum_def) = enum_;
|
||||||
|
let enum_layout = self.layout_of(enum_ty)?;
|
||||||
|
|
||||||
|
for (field_idx, field) in
|
||||||
|
place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated()
|
||||||
|
{
|
||||||
|
let field_place = self.project_field(&place, field_idx)?;
|
||||||
|
|
||||||
|
match field.name {
|
||||||
|
sym::generics => self.write_generics(field_place, generics)?,
|
||||||
|
sym::variants => {
|
||||||
|
self.allocate_fill_and_write_slice_ptr(
|
||||||
|
field_place,
|
||||||
|
enum_def.variants().len() as u64,
|
||||||
|
|this, i, place| {
|
||||||
|
let variant_idx = VariantIdx::from_usize(i as usize);
|
||||||
|
let variant_def = &enum_def.variants()[variant_idx];
|
||||||
|
let variant_layout = enum_layout.for_variant(this, variant_idx);
|
||||||
|
this.write_enum_variant(place, (variant_layout, &variant_def), generics)
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
sym::non_exhaustive => {
|
||||||
|
let is_non_exhaustive = enum_def.is_variant_list_non_exhaustive();
|
||||||
|
self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)?
|
||||||
|
}
|
||||||
|
other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interp_ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_enum_variant(
|
||||||
|
&mut self,
|
||||||
|
place: impl Writeable<'tcx, CtfeProvenance>,
|
||||||
|
variant: (TyAndLayout<'tcx>, &'tcx VariantDef),
|
||||||
|
generics: &'tcx GenericArgs<'tcx>,
|
||||||
|
) -> InterpResult<'tcx> {
|
||||||
|
let (variant_layout, variant_def) = variant;
|
||||||
|
|
||||||
|
for (field_idx, field_def) in
|
||||||
|
place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated()
|
||||||
|
{
|
||||||
|
let field_place = self.project_field(&place, field_idx)?;
|
||||||
|
match field_def.name {
|
||||||
|
sym::name => {
|
||||||
|
let name_place = self.allocate_str_dedup(variant_def.name.as_str())?;
|
||||||
|
let ptr = self.mplace_to_ref(&name_place)?;
|
||||||
|
self.write_immediate(*ptr, &field_place)?
|
||||||
|
}
|
||||||
|
sym::fields => {
|
||||||
|
self.write_variant_fields(field_place, &variant_def, variant_layout, generics)?
|
||||||
|
}
|
||||||
|
sym::non_exhaustive => {
|
||||||
|
let is_non_exhaustive = variant_def.is_field_list_non_exhaustive();
|
||||||
|
self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)?
|
||||||
|
}
|
||||||
|
other => span_bug!(self.tcx.def_span(field_def.did), "unimplemented field {other}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
interp_ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write fields for struct, enum variants
|
||||||
|
fn write_variant_fields(
|
||||||
|
&mut self,
|
||||||
|
place: impl Writeable<'tcx, CtfeProvenance>,
|
||||||
|
variant_def: &'tcx VariantDef,
|
||||||
|
variant_layout: TyAndLayout<'tcx>,
|
||||||
|
generics: &'tcx GenericArgs<'tcx>,
|
||||||
|
) -> InterpResult<'tcx> {
|
||||||
|
self.allocate_fill_and_write_slice_ptr(
|
||||||
|
place,
|
||||||
|
variant_def.fields.len() as u64,
|
||||||
|
|this, i, place| {
|
||||||
|
let field_def = &variant_def.fields[FieldIdx::from_usize(i as usize)];
|
||||||
|
let field_ty = field_def.ty(*this.tcx, generics);
|
||||||
|
this.write_field(field_ty, place, variant_layout, Some(field_def.name), i)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_generics(
|
||||||
|
&mut self,
|
||||||
|
place: impl Writeable<'tcx, CtfeProvenance>,
|
||||||
|
generics: &'tcx GenericArgs<'tcx>,
|
||||||
|
) -> InterpResult<'tcx> {
|
||||||
|
self.allocate_fill_and_write_slice_ptr(place, generics.len() as u64, |this, i, place| {
|
||||||
|
match generics[i as usize].kind() {
|
||||||
|
GenericArgKind::Lifetime(region) => this.write_generic_lifetime(region, place),
|
||||||
|
GenericArgKind::Type(ty) => this.write_generic_type(ty, place),
|
||||||
|
GenericArgKind::Const(c) => this.write_generic_const(c, place),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_generic_lifetime(
|
||||||
|
&mut self,
|
||||||
|
_region: Region<'tcx>,
|
||||||
|
place: MPlaceTy<'tcx>,
|
||||||
|
) -> InterpResult<'tcx> {
|
||||||
|
let (variant_idx, _) = self.downcast(&place, sym::Lifetime)?;
|
||||||
|
self.write_discriminant(variant_idx, &place)?;
|
||||||
|
interp_ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_generic_type(&mut self, ty: Ty<'tcx>, place: MPlaceTy<'tcx>) -> InterpResult<'tcx> {
|
||||||
|
let (variant_idx, variant_place) = self.downcast(&place, sym::Type)?;
|
||||||
|
let generic_type_place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||||
|
|
||||||
|
for (field_idx, field_def) in generic_type_place
|
||||||
|
.layout()
|
||||||
|
.ty
|
||||||
|
.ty_adt_def()
|
||||||
|
.unwrap()
|
||||||
|
.non_enum_variant()
|
||||||
|
.fields
|
||||||
|
.iter_enumerated()
|
||||||
|
{
|
||||||
|
let field_place = self.project_field(&generic_type_place, field_idx)?;
|
||||||
|
match field_def.name {
|
||||||
|
sym::ty => self.write_type_id(ty, &field_place)?,
|
||||||
|
other => span_bug!(self.tcx.def_span(field_def.did), "unimplemented field {other}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.write_discriminant(variant_idx, &place)?;
|
||||||
|
interp_ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_generic_const(&mut self, c: Const<'tcx>, place: MPlaceTy<'tcx>) -> InterpResult<'tcx> {
|
||||||
|
let ConstKind::Value(c) = c.kind() else { bug!("expected a computed const, got {c:?}") };
|
||||||
|
|
||||||
|
let (variant_idx, variant_place) = self.downcast(&place, sym::Const)?;
|
||||||
|
let const_place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||||
|
|
||||||
|
for (field_idx, field_def) in const_place
|
||||||
|
.layout()
|
||||||
|
.ty
|
||||||
|
.ty_adt_def()
|
||||||
|
.unwrap()
|
||||||
|
.non_enum_variant()
|
||||||
|
.fields
|
||||||
|
.iter_enumerated()
|
||||||
|
{
|
||||||
|
let field_place = self.project_field(&const_place, field_idx)?;
|
||||||
|
match field_def.name {
|
||||||
|
sym::ty => self.write_type_id(c.ty, &field_place)?,
|
||||||
|
other => span_bug!(self.tcx.def_span(field_def.did), "unimplemented field {other}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.write_discriminant(variant_idx, &place)?;
|
||||||
|
interp_ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,7 +13,7 @@ use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, read_target_uint, write_target_uint};
|
use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, read_target_uint, write_target_uint};
|
||||||
use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic};
|
use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic};
|
||||||
use rustc_middle::ty::layout::TyAndLayout;
|
use rustc_middle::ty::layout::TyAndLayout;
|
||||||
use rustc_middle::ty::{FloatTy, PolyExistentialPredicate, Ty, TyCtxt};
|
use rustc_middle::ty::{FloatTy, PolyExistentialPredicate, Ty, TyCtxt, TypeVisitableExt};
|
||||||
use rustc_middle::{bug, span_bug, ty};
|
use rustc_middle::{bug, span_bug, ty};
|
||||||
use rustc_span::{Symbol, sym};
|
use rustc_span::{Symbol, sym};
|
||||||
use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt};
|
use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt};
|
||||||
|
|
@ -73,6 +73,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
dest: &impl Writeable<'tcx, M::Provenance>,
|
dest: &impl Writeable<'tcx, M::Provenance>,
|
||||||
) -> InterpResult<'tcx, ()> {
|
) -> InterpResult<'tcx, ()> {
|
||||||
|
debug_assert!(
|
||||||
|
!ty.has_erasable_regions(),
|
||||||
|
"type {ty:?} has regions that need erasing before writing a TypeId",
|
||||||
|
);
|
||||||
|
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let type_id_hash = tcx.type_id_hash(ty).as_u128();
|
let type_id_hash = tcx.type_id_hash(ty).as_u128();
|
||||||
let op = self.const_val_to_op(
|
let op = self.const_val_to_op(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![feature(array_try_map)]
|
#![feature(array_try_map)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(decl_macro)]
|
#![feature(decl_macro)]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,12 @@
|
||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
#![allow(rustc::default_hash_types)]
|
#![allow(rustc::default_hash_types)]
|
||||||
#![allow(rustc::potential_query_instability)]
|
#![allow(rustc::potential_query_instability)]
|
||||||
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![cfg_attr(bootstrap, feature(cold_path))]
|
#![cfg_attr(bootstrap, feature(cold_path))]
|
||||||
#![deny(unsafe_op_in_unsafe_fn)]
|
#![deny(unsafe_op_in_unsafe_fn)]
|
||||||
#![feature(allocator_api)]
|
#![feature(allocator_api)]
|
||||||
#![feature(ascii_char)]
|
#![feature(ascii_char)]
|
||||||
#![feature(ascii_char_variants)]
|
#![feature(ascii_char_variants)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
#![feature(auto_traits)]
|
#![feature(auto_traits)]
|
||||||
#![feature(cfg_select)]
|
#![feature(cfg_select)]
|
||||||
#![feature(const_default)]
|
#![feature(const_default)]
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
#![allow(rustc::direct_use_of_rustc_type_ir)]
|
#![allow(rustc::direct_use_of_rustc_type_ir)]
|
||||||
#![feature(assert_matches)]
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![feature(associated_type_defaults)]
|
#![feature(associated_type_defaults)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(default_field_values)]
|
#![feature(default_field_values)]
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ This API is completely unstable and subject to change.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![feature(assert_matches)]
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![feature(default_field_values)]
|
#![feature(default_field_values)]
|
||||||
#![feature(gen_blocks)]
|
#![feature(gen_blocks)]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![feature(assert_matches)]
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
#![feature(iter_intersperse)]
|
#![feature(iter_intersperse)]
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![allow(rustc::direct_use_of_rustc_type_ir)]
|
#![allow(rustc::direct_use_of_rustc_type_ir)]
|
||||||
#![feature(assert_matches)]
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![feature(extend_one)]
|
#![feature(extend_one)]
|
||||||
#![recursion_limit = "512"] // For rustdoc
|
#![recursion_limit = "512"] // For rustdoc
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
#![feature(assert_matches)]
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
#![feature(iter_order_by)]
|
#![feature(iter_order_by)]
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
#![allow(rustc::direct_use_of_rustc_type_ir)]
|
#![allow(rustc::direct_use_of_rustc_type_ir)]
|
||||||
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![feature(allocator_api)]
|
#![feature(allocator_api)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
#![feature(associated_type_defaults)]
|
#![feature(associated_type_defaults)]
|
||||||
#![feature(box_as_ptr)]
|
#![feature(box_as_ptr)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
//! Construction of MIR from HIR.
|
//! Construction of MIR from HIR.
|
||||||
|
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![feature(assert_matches)]
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
#![feature(try_blocks)]
|
#![feature(try_blocks)]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![feature(assert_matches)]
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![feature(associated_type_defaults)]
|
#![feature(associated_type_defaults)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(exact_size_is_empty)]
|
#![feature(exact_size_is_empty)]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![feature(assert_matches)]
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(const_type_name)]
|
#![feature(const_type_name)]
|
||||||
#![feature(cow_is_borrowed)]
|
#![feature(cow_is_borrowed)]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
//! The main parser interface.
|
//! The main parser interface.
|
||||||
|
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![feature(assert_matches)]
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(debug_closure_helpers)]
|
#![feature(debug_closure_helpers)]
|
||||||
#![feature(default_field_values)]
|
#![feature(default_field_values)]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
#![feature(assert_matches)]
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(trait_alias)]
|
#![feature(trait_alias)]
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,9 @@
|
||||||
|
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![cfg_attr(bootstrap, feature(ptr_as_ref_unchecked))]
|
#![cfg_attr(bootstrap, feature(ptr_as_ref_unchecked))]
|
||||||
#![feature(arbitrary_self_types)]
|
#![feature(arbitrary_self_types)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(const_default)]
|
#![feature(const_default)]
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
|
|
|
||||||
|
|
@ -211,6 +211,7 @@ symbols! {
|
||||||
CoercePointeeValidated,
|
CoercePointeeValidated,
|
||||||
CoerceUnsized,
|
CoerceUnsized,
|
||||||
Command,
|
Command,
|
||||||
|
Const,
|
||||||
ConstParamTy,
|
ConstParamTy,
|
||||||
ConstParamTy_,
|
ConstParamTy_,
|
||||||
Context,
|
Context,
|
||||||
|
|
@ -234,6 +235,7 @@ symbols! {
|
||||||
DynTrait,
|
DynTrait,
|
||||||
Encodable,
|
Encodable,
|
||||||
Encoder,
|
Encoder,
|
||||||
|
Enum,
|
||||||
Enumerate,
|
Enumerate,
|
||||||
Eq,
|
Eq,
|
||||||
Equal,
|
Equal,
|
||||||
|
|
@ -292,6 +294,7 @@ symbols! {
|
||||||
IteratorMap,
|
IteratorMap,
|
||||||
Layout,
|
Layout,
|
||||||
Left,
|
Left,
|
||||||
|
Lifetime,
|
||||||
LinkedList,
|
LinkedList,
|
||||||
LintDiagnostic,
|
LintDiagnostic,
|
||||||
LintPass,
|
LintPass,
|
||||||
|
|
@ -372,6 +375,7 @@ symbols! {
|
||||||
Stdin,
|
Stdin,
|
||||||
Str,
|
Str,
|
||||||
String,
|
String,
|
||||||
|
Struct,
|
||||||
StructuralPartialEq,
|
StructuralPartialEq,
|
||||||
Subdiagnostic,
|
Subdiagnostic,
|
||||||
SymbolIntern,
|
SymbolIntern,
|
||||||
|
|
@ -394,6 +398,8 @@ symbols! {
|
||||||
Ty,
|
Ty,
|
||||||
TyCtxt,
|
TyCtxt,
|
||||||
TyKind,
|
TyKind,
|
||||||
|
Type,
|
||||||
|
Union,
|
||||||
Unknown,
|
Unknown,
|
||||||
Unsize,
|
Unsize,
|
||||||
UnsizedConstParamTy,
|
UnsizedConstParamTy,
|
||||||
|
|
@ -1085,6 +1091,7 @@ symbols! {
|
||||||
ffi_returns_twice,
|
ffi_returns_twice,
|
||||||
field,
|
field,
|
||||||
field_init_shorthand,
|
field_init_shorthand,
|
||||||
|
fields,
|
||||||
file,
|
file,
|
||||||
file_options,
|
file_options,
|
||||||
flags,
|
flags,
|
||||||
|
|
@ -1173,6 +1180,7 @@ symbols! {
|
||||||
generic_const_parameter_types,
|
generic_const_parameter_types,
|
||||||
generic_param_attrs,
|
generic_param_attrs,
|
||||||
generic_pattern_types,
|
generic_pattern_types,
|
||||||
|
generics,
|
||||||
get_context,
|
get_context,
|
||||||
global_alloc_ty,
|
global_alloc_ty,
|
||||||
global_allocator,
|
global_allocator,
|
||||||
|
|
@ -2473,6 +2481,7 @@ symbols! {
|
||||||
values,
|
values,
|
||||||
var,
|
var,
|
||||||
variant_count,
|
variant_count,
|
||||||
|
variants,
|
||||||
vec,
|
vec,
|
||||||
vec_as_mut_slice,
|
vec_as_mut_slice,
|
||||||
vec_as_slice,
|
vec_as_slice,
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@
|
||||||
//! DefPaths which are much more robust in the face of changes to the code base.
|
//! DefPaths which are much more robust in the face of changes to the code base.
|
||||||
|
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![feature(assert_matches)]
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
|
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
//! This API is completely unstable and subject to change.
|
//! This API is completely unstable and subject to change.
|
||||||
|
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![feature(assert_matches)]
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![feature(associated_type_defaults)]
|
#![feature(associated_type_defaults)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(default_field_values)]
|
#![feature(default_field_values)]
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
//! This API is completely unstable and subject to change.
|
//! This API is completely unstable and subject to change.
|
||||||
|
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![feature(assert_matches)]
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![feature(associated_type_defaults)]
|
#![feature(associated_type_defaults)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,6 @@
|
||||||
#![feature(allocator_api)]
|
#![feature(allocator_api)]
|
||||||
#![feature(array_into_iter_constructors)]
|
#![feature(array_into_iter_constructors)]
|
||||||
#![feature(ascii_char)]
|
#![feature(ascii_char)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
#![feature(async_fn_traits)]
|
#![feature(async_fn_traits)]
|
||||||
#![feature(async_iterator)]
|
#![feature(async_iterator)]
|
||||||
#![feature(box_vec_non_null)]
|
#![feature(box_vec_non_null)]
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![feature(allocator_api)]
|
#![feature(allocator_api)]
|
||||||
#![feature(array_into_iter_constructors)]
|
#![feature(array_into_iter_constructors)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
#![feature(box_vec_non_null)]
|
#![feature(box_vec_non_null)]
|
||||||
#![feature(char_internals)]
|
#![feature(char_internals)]
|
||||||
#![feature(const_alloc_error)]
|
#![feature(const_alloc_error)]
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
#![feature(const_heap)]
|
#![feature(const_heap)]
|
||||||
#![feature(deque_extend_front)]
|
#![feature(deque_extend_front)]
|
||||||
#![feature(iter_array_chunks)]
|
#![feature(iter_array_chunks)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
#![feature(wtf8_internals)]
|
#![feature(wtf8_internals)]
|
||||||
#![feature(cow_is_borrowed)]
|
#![feature(cow_is_borrowed)]
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
|
|
|
||||||
|
|
@ -225,7 +225,7 @@ use prelude::rust_2024::*;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
#[unstable(feature = "assert_matches", issue = "82775")]
|
#[stable(feature = "assert_matches", since = "CURRENT_RUSTC_VERSION")]
|
||||||
pub use crate::macros::{assert_matches, debug_assert_matches};
|
pub use crate::macros::{assert_matches, debug_assert_matches};
|
||||||
|
|
||||||
#[unstable(feature = "derive_from", issue = "144889")]
|
#[unstable(feature = "derive_from", issue = "144889")]
|
||||||
|
|
|
||||||
|
|
@ -147,8 +147,6 @@ macro_rules! assert_ne {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(assert_matches)]
|
|
||||||
///
|
|
||||||
/// use std::assert_matches;
|
/// use std::assert_matches;
|
||||||
///
|
///
|
||||||
/// let a = Some(345);
|
/// let a = Some(345);
|
||||||
|
|
@ -166,7 +164,7 @@ macro_rules! assert_ne {
|
||||||
/// assert_matches!(a, Some(x) if x > 100);
|
/// assert_matches!(a, Some(x) if x > 100);
|
||||||
/// // assert_matches!(a, Some(x) if x < 100); // panics
|
/// // assert_matches!(a, Some(x) if x < 100); // panics
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "assert_matches", issue = "82775")]
|
#[stable(feature = "assert_matches", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[allow_internal_unstable(panic_internals)]
|
#[allow_internal_unstable(panic_internals)]
|
||||||
#[rustc_macro_transparency = "semiopaque"]
|
#[rustc_macro_transparency = "semiopaque"]
|
||||||
pub macro assert_matches {
|
pub macro assert_matches {
|
||||||
|
|
@ -380,8 +378,6 @@ macro_rules! debug_assert_ne {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(assert_matches)]
|
|
||||||
///
|
|
||||||
/// use std::debug_assert_matches;
|
/// use std::debug_assert_matches;
|
||||||
///
|
///
|
||||||
/// let a = Some(345);
|
/// let a = Some(345);
|
||||||
|
|
@ -399,7 +395,7 @@ macro_rules! debug_assert_ne {
|
||||||
/// debug_assert_matches!(a, Some(x) if x > 100);
|
/// debug_assert_matches!(a, Some(x) if x > 100);
|
||||||
/// // debug_assert_matches!(a, Some(x) if x < 100); // panics
|
/// // debug_assert_matches!(a, Some(x) if x < 100); // panics
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "assert_matches", issue = "82775")]
|
#[stable(feature = "assert_matches", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[allow_internal_unstable(assert_matches)]
|
#[allow_internal_unstable(assert_matches)]
|
||||||
#[rustc_macro_transparency = "semiopaque"]
|
#[rustc_macro_transparency = "semiopaque"]
|
||||||
pub macro debug_assert_matches($($arg:tt)*) {
|
pub macro debug_assert_matches($($arg:tt)*) {
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,12 @@ pub enum TypeKind {
|
||||||
Slice(Slice),
|
Slice(Slice),
|
||||||
/// Dynamic Traits.
|
/// Dynamic Traits.
|
||||||
DynTrait(DynTrait),
|
DynTrait(DynTrait),
|
||||||
|
/// Structs.
|
||||||
|
Struct(Struct),
|
||||||
|
/// Enums.
|
||||||
|
Enum(Enum),
|
||||||
|
/// Unions.
|
||||||
|
Union(Union),
|
||||||
/// Primitive boolean type.
|
/// Primitive boolean type.
|
||||||
Bool(Bool),
|
Bool(Bool),
|
||||||
/// Primitive character type.
|
/// Primitive character type.
|
||||||
|
|
@ -81,6 +87,8 @@ pub struct Tuple {
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[unstable(feature = "type_info", issue = "146922")]
|
#[unstable(feature = "type_info", issue = "146922")]
|
||||||
pub struct Field {
|
pub struct Field {
|
||||||
|
/// The name of the field.
|
||||||
|
pub name: &'static str,
|
||||||
/// The field's type.
|
/// The field's type.
|
||||||
pub ty: TypeId,
|
pub ty: TypeId,
|
||||||
/// Offset in bytes from the parent type
|
/// Offset in bytes from the parent type
|
||||||
|
|
@ -137,6 +145,95 @@ pub struct Trait {
|
||||||
pub is_auto: bool,
|
pub is_auto: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Compile-time type information about arrays.
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[unstable(feature = "type_info", issue = "146922")]
|
||||||
|
pub struct Struct {
|
||||||
|
/// Instantiated generics of the struct.
|
||||||
|
pub generics: &'static [Generic],
|
||||||
|
/// All fields of the struct.
|
||||||
|
pub fields: &'static [Field],
|
||||||
|
/// Whether the struct field list is non-exhaustive.
|
||||||
|
pub non_exhaustive: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compile-time type information about unions.
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[unstable(feature = "type_info", issue = "146922")]
|
||||||
|
pub struct Union {
|
||||||
|
/// Instantiated generics of the union.
|
||||||
|
pub generics: &'static [Generic],
|
||||||
|
/// All fields of the union.
|
||||||
|
pub fields: &'static [Field],
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compile-time type information about enums.
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[unstable(feature = "type_info", issue = "146922")]
|
||||||
|
pub struct Enum {
|
||||||
|
/// Instantiated generics of the enum.
|
||||||
|
pub generics: &'static [Generic],
|
||||||
|
/// All variants of the enum.
|
||||||
|
pub variants: &'static [Variant],
|
||||||
|
/// Whether the enum variant list is non-exhaustive.
|
||||||
|
pub non_exhaustive: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compile-time type information about variants of enums.
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[unstable(feature = "type_info", issue = "146922")]
|
||||||
|
pub struct Variant {
|
||||||
|
/// The name of the variant.
|
||||||
|
pub name: &'static str,
|
||||||
|
/// All fields of the variant.
|
||||||
|
pub fields: &'static [Field],
|
||||||
|
/// Whether the enum variant fields is non-exhaustive.
|
||||||
|
pub non_exhaustive: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compile-time type information about instantiated generics of structs, enum and union variants.
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[unstable(feature = "type_info", issue = "146922")]
|
||||||
|
pub enum Generic {
|
||||||
|
/// Lifetimes.
|
||||||
|
Lifetime(Lifetime),
|
||||||
|
/// Types.
|
||||||
|
Type(GenericType),
|
||||||
|
/// Const parameters.
|
||||||
|
Const(Const),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compile-time type information about generic lifetimes.
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[unstable(feature = "type_info", issue = "146922")]
|
||||||
|
pub struct Lifetime {
|
||||||
|
// No additional information to provide for now.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compile-time type information about instantiated generic types.
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[unstable(feature = "type_info", issue = "146922")]
|
||||||
|
pub struct GenericType {
|
||||||
|
/// The type itself.
|
||||||
|
pub ty: TypeId,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compile-time type information about generic const parameters.
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[unstable(feature = "type_info", issue = "146922")]
|
||||||
|
pub struct Const {
|
||||||
|
/// The const's type.
|
||||||
|
pub ty: TypeId,
|
||||||
|
}
|
||||||
|
|
||||||
/// Compile-time type information about `bool`.
|
/// Compile-time type information about `bool`.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::any::{Any, TypeId};
|
use std::any::{Any, TypeId};
|
||||||
use std::mem::type_info::{Type, TypeKind};
|
use std::mem::offset_of;
|
||||||
|
use std::mem::type_info::{Const, Generic, GenericType, Type, TypeKind};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_arrays() {
|
fn test_arrays() {
|
||||||
|
|
@ -66,6 +69,155 @@ fn test_tuples() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_structs() {
|
||||||
|
use TypeKind::*;
|
||||||
|
|
||||||
|
const {
|
||||||
|
struct TestStruct {
|
||||||
|
first: u8,
|
||||||
|
second: u16,
|
||||||
|
reference: &'static u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
let Type { kind: Struct(ty), size, .. } = Type::of::<TestStruct>() else { panic!() };
|
||||||
|
assert!(size == Some(size_of::<TestStruct>()));
|
||||||
|
assert!(!ty.non_exhaustive);
|
||||||
|
assert!(ty.fields.len() == 3);
|
||||||
|
assert!(ty.fields[0].name == "first");
|
||||||
|
assert!(ty.fields[0].ty == TypeId::of::<u8>());
|
||||||
|
assert!(ty.fields[0].offset == offset_of!(TestStruct, first));
|
||||||
|
assert!(ty.fields[1].name == "second");
|
||||||
|
assert!(ty.fields[1].ty == TypeId::of::<u16>());
|
||||||
|
assert!(ty.fields[1].offset == offset_of!(TestStruct, second));
|
||||||
|
assert!(ty.fields[2].name == "reference");
|
||||||
|
assert!(ty.fields[2].ty == TypeId::of::<&'static u16>());
|
||||||
|
assert!(ty.fields[2].offset == offset_of!(TestStruct, reference));
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
#[non_exhaustive]
|
||||||
|
struct NonExhaustive {
|
||||||
|
a: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
let Type { kind: Struct(ty), .. } = Type::of::<NonExhaustive>() else { panic!() };
|
||||||
|
assert!(ty.non_exhaustive);
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
struct TupleStruct(u8, u16);
|
||||||
|
|
||||||
|
let Type { kind: Struct(ty), .. } = Type::of::<TupleStruct>() else { panic!() };
|
||||||
|
assert!(ty.fields.len() == 2);
|
||||||
|
assert!(ty.fields[0].name == "0");
|
||||||
|
assert!(ty.fields[0].ty == TypeId::of::<u8>());
|
||||||
|
assert!(ty.fields[1].name == "1");
|
||||||
|
assert!(ty.fields[1].ty == TypeId::of::<u16>());
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
struct Generics<'a, T, const C: u64> {
|
||||||
|
a: &'a T,
|
||||||
|
}
|
||||||
|
|
||||||
|
let Type { kind: Struct(ty), .. } = Type::of::<Generics<'static, i32, 1_u64>>() else {
|
||||||
|
panic!()
|
||||||
|
};
|
||||||
|
assert!(ty.fields.len() == 1);
|
||||||
|
assert!(ty.generics.len() == 3);
|
||||||
|
|
||||||
|
let Generic::Lifetime(_) = ty.generics[0] else { panic!() };
|
||||||
|
let Generic::Type(GenericType { ty: generic_ty, .. }) = ty.generics[1] else { panic!() };
|
||||||
|
assert!(generic_ty == TypeId::of::<i32>());
|
||||||
|
let Generic::Const(Const { ty: const_ty, .. }) = ty.generics[2] else { panic!() };
|
||||||
|
assert!(const_ty == TypeId::of::<u64>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_unions() {
|
||||||
|
use TypeKind::*;
|
||||||
|
|
||||||
|
const {
|
||||||
|
union TestUnion {
|
||||||
|
first: i16,
|
||||||
|
second: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
let Type { kind: Union(ty), size, .. } = Type::of::<TestUnion>() else { panic!() };
|
||||||
|
assert!(size == Some(size_of::<TestUnion>()));
|
||||||
|
assert!(ty.fields.len() == 2);
|
||||||
|
assert!(ty.fields[0].name == "first");
|
||||||
|
assert!(ty.fields[0].offset == offset_of!(TestUnion, first));
|
||||||
|
assert!(ty.fields[1].name == "second");
|
||||||
|
assert!(ty.fields[1].offset == offset_of!(TestUnion, second));
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
union Generics<'a, T: Copy, const C: u64> {
|
||||||
|
a: T,
|
||||||
|
z: &'a (),
|
||||||
|
}
|
||||||
|
|
||||||
|
let Type { kind: Union(ty), .. } = Type::of::<Generics<'static, i32, 1_u64>>() else {
|
||||||
|
panic!()
|
||||||
|
};
|
||||||
|
assert!(ty.fields.len() == 2);
|
||||||
|
assert!(ty.fields[0].offset == offset_of!(Generics<'static, i32, 1_u64>, a));
|
||||||
|
assert!(ty.fields[1].offset == offset_of!(Generics<'static, i32, 1_u64>, z));
|
||||||
|
|
||||||
|
assert!(ty.generics.len() == 3);
|
||||||
|
let Generic::Lifetime(_) = ty.generics[0] else { panic!() };
|
||||||
|
let Generic::Type(GenericType { ty: generic_ty, .. }) = ty.generics[1] else { panic!() };
|
||||||
|
assert!(generic_ty == TypeId::of::<i32>());
|
||||||
|
let Generic::Const(Const { ty: const_ty, .. }) = ty.generics[2] else { panic!() };
|
||||||
|
assert!(const_ty == TypeId::of::<u64>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_enums() {
|
||||||
|
use TypeKind::*;
|
||||||
|
|
||||||
|
const {
|
||||||
|
enum E {
|
||||||
|
Some(u32),
|
||||||
|
None,
|
||||||
|
#[non_exhaustive]
|
||||||
|
Foomp {
|
||||||
|
a: (),
|
||||||
|
b: &'static str,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
let Type { kind: Enum(ty), size, .. } = Type::of::<E>() else { panic!() };
|
||||||
|
assert!(size == Some(size_of::<E>()));
|
||||||
|
assert!(ty.variants.len() == 3);
|
||||||
|
|
||||||
|
assert!(ty.variants[0].name == "Some");
|
||||||
|
assert!(!ty.variants[0].non_exhaustive);
|
||||||
|
assert!(ty.variants[0].fields.len() == 1);
|
||||||
|
|
||||||
|
assert!(ty.variants[1].name == "None");
|
||||||
|
assert!(!ty.variants[1].non_exhaustive);
|
||||||
|
assert!(ty.variants[1].fields.len() == 0);
|
||||||
|
|
||||||
|
assert!(ty.variants[2].name == "Foomp");
|
||||||
|
assert!(ty.variants[2].non_exhaustive);
|
||||||
|
assert!(ty.variants[2].fields.len() == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
let Type { kind: Enum(ty), size, .. } = Type::of::<Option<i32>>() else { panic!() };
|
||||||
|
assert!(size == Some(size_of::<Option<i32>>()));
|
||||||
|
assert!(ty.variants.len() == 2);
|
||||||
|
assert!(ty.generics.len() == 1);
|
||||||
|
let Generic::Type(GenericType { ty: generic_ty, .. }) = ty.generics[0] else { panic!() };
|
||||||
|
assert!(generic_ty == TypeId::of::<i32>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_primitives() {
|
fn test_primitives() {
|
||||||
use TypeKind::*;
|
use TypeKind::*;
|
||||||
|
|
|
||||||
|
|
@ -394,7 +394,6 @@
|
||||||
//
|
//
|
||||||
// Only for re-exporting:
|
// Only for re-exporting:
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![feature(assert_matches)]
|
|
||||||
#![feature(async_iterator)]
|
#![feature(async_iterator)]
|
||||||
#![feature(c_variadic)]
|
#![feature(c_variadic)]
|
||||||
#![feature(cfg_accessible)]
|
#![feature(cfg_accessible)]
|
||||||
|
|
@ -726,7 +725,7 @@ pub use core::{
|
||||||
assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, r#try, unimplemented,
|
assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, r#try, unimplemented,
|
||||||
unreachable, write, writeln,
|
unreachable, write, writeln,
|
||||||
};
|
};
|
||||||
#[unstable(feature = "assert_matches", issue = "82775")]
|
#[stable(feature = "assert_matches", since = "CURRENT_RUSTC_VERSION")]
|
||||||
pub use core::{assert_matches, debug_assert_matches};
|
pub use core::{assert_matches, debug_assert_matches};
|
||||||
|
|
||||||
// Re-export unstable derive macro defined through core.
|
// Re-export unstable derive macro defined through core.
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,9 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println!();
|
println!();
|
||||||
|
|
||||||
|
println!("@rustbot label +C-date-reference-triage +E-easy +E-help-wanted");
|
||||||
|
println!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@ fn main() {
|
||||||
output_dir: None, // Option<PathBuf>
|
output_dir: None, // Option<PathBuf>
|
||||||
output_file: None, // Option<PathBuf>
|
output_file: None, // Option<PathBuf>
|
||||||
file_loader: None, // Option<Box<dyn FileLoader + Send + Sync>>
|
file_loader: None, // Option<Box<dyn FileLoader + Send + Sync>>
|
||||||
locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES.to_owned(),
|
|
||||||
lint_caps: FxHashMap::default(), // FxHashMap<lint::LintId, lint::Level>
|
lint_caps: FxHashMap::default(), // FxHashMap<lint::LintId, lint::Level>
|
||||||
// This is a callback from the driver that is called when [`ParseSess`] is created.
|
// This is a callback from the driver that is called when [`ParseSess`] is created.
|
||||||
psess_created: None, //Option<Box<dyn FnOnce(&mut ParseSess) + Send>>
|
psess_created: None, //Option<Box<dyn FnOnce(&mut ParseSess) + Send>>
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,6 @@ fn main() {
|
||||||
output_dir: None,
|
output_dir: None,
|
||||||
output_file: None,
|
output_file: None,
|
||||||
file_loader: None,
|
file_loader: None,
|
||||||
locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES.to_owned(),
|
|
||||||
lint_caps: rustc_hash::FxHashMap::default(),
|
lint_caps: rustc_hash::FxHashMap::default(),
|
||||||
psess_created: Some(Box::new(|parse_sess| {
|
psess_created: Some(Box::new(|parse_sess| {
|
||||||
parse_sess.dcx().set_emitter(Box::new(DebugEmitter {
|
parse_sess.dcx().set_emitter(Box::new(DebugEmitter {
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@
|
||||||
- [`#[test]` implementation](./test-implementation.md)
|
- [`#[test]` implementation](./test-implementation.md)
|
||||||
- [Panic implementation](./panic-implementation.md)
|
- [Panic implementation](./panic-implementation.md)
|
||||||
- [AST validation](./ast-validation.md)
|
- [AST validation](./ast-validation.md)
|
||||||
- [Feature gate checking](./feature-gate-ck.md)
|
- [Feature gate checking](./feature-gate-check.md)
|
||||||
- [Lang Items](./lang-items.md)
|
- [Lang Items](./lang-items.md)
|
||||||
- [The HIR (High-level IR)](./hir.md)
|
- [The HIR (High-level IR)](./hir.md)
|
||||||
- [Lowering AST to HIR](./hir/lowering.md)
|
- [Lowering AST to HIR](./hir/lowering.md)
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ There are several parts to this guide:
|
||||||
about building, debugging, profiling, etc.
|
about building, debugging, profiling, etc.
|
||||||
1. [Contributing to Rust][p2]:
|
1. [Contributing to Rust][p2]:
|
||||||
Contains information that should be useful no matter how you are contributing,
|
Contains information that should be useful no matter how you are contributing,
|
||||||
about procedures for contribution, using git and Github, stabilizing features, etc.
|
about procedures for contribution, using git and GitHub, stabilizing features, etc.
|
||||||
1. [Bootstrapping][p3]:
|
1. [Bootstrapping][p3]:
|
||||||
Describes how the Rust compiler builds itself using previous versions, including
|
Describes how the Rust compiler builds itself using previous versions, including
|
||||||
an introduction to the bootstrap process and debugging methods.
|
an introduction to the bootstrap process and debugging methods.
|
||||||
|
|
|
||||||
|
|
@ -243,7 +243,7 @@ This is also where `--keep-stage 1 library/std` comes into play. Since most
|
||||||
changes to the compiler don't actually change the ABI, once you've produced a
|
changes to the compiler don't actually change the ABI, once you've produced a
|
||||||
`std` in `stage1`, you can probably just reuse it with a different compiler. If
|
`std` in `stage1`, you can probably just reuse it with a different compiler. If
|
||||||
the ABI hasn't changed, you're good to go, no need to spend time recompiling
|
the ABI hasn't changed, you're good to go, no need to spend time recompiling
|
||||||
that `std`. The flag `--keep-stage` simply instructs the build script to assumes
|
that `std`. The flag `--keep-stage` simply instructs the build script to assume
|
||||||
the previous compile is fine and copies those artifacts into the appropriate
|
the previous compile is fine and copies those artifacts into the appropriate
|
||||||
place, skipping the `cargo` invocation.
|
place, skipping the `cargo` invocation.
|
||||||
|
|
||||||
|
|
@ -342,7 +342,7 @@ This flag has the following effects:
|
||||||
|
|
||||||
Code which does not use `-Z force-unstable-if-unmarked` should include the
|
Code which does not use `-Z force-unstable-if-unmarked` should include the
|
||||||
`#![feature(rustc_private)]` crate attribute to access these forced-unstable
|
`#![feature(rustc_private)]` crate attribute to access these forced-unstable
|
||||||
crates. This is needed for things which link `rustc` its self, such as `MIRI` or
|
crates. This is needed for things which link `rustc` itself, such as `Miri` or
|
||||||
`clippy`.
|
`clippy`.
|
||||||
|
|
||||||
You can find more discussion about sysroots in:
|
You can find more discussion about sysroots in:
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ You can also include extensions within extensions recursively.
|
||||||
**Note:** In the `include` field, the overriding logic follows a right-to-left order.
|
**Note:** In the `include` field, the overriding logic follows a right-to-left order.
|
||||||
For example,
|
For example,
|
||||||
in `include = ["a.toml", "b.toml"]`, extension `b.toml` overrides `a.toml`.
|
in `include = ["a.toml", "b.toml"]`, extension `b.toml` overrides `a.toml`.
|
||||||
Also, parent extensions always overrides the inner ones.
|
Also, parent extensions always override the inner ones.
|
||||||
|
|
||||||
## Configuring `rust-analyzer` for `rustc`
|
## Configuring `rust-analyzer` for `rustc`
|
||||||
|
|
||||||
|
|
@ -426,7 +426,7 @@ You can then use that rust2 folder as a separate workspace for modifying and bui
|
||||||
|
|
||||||
Several nix configurations are defined in `src/tools/nix-dev-shell`.
|
Several nix configurations are defined in `src/tools/nix-dev-shell`.
|
||||||
|
|
||||||
If you're using direnv, you can create a symbol link to `src/tools/nix-dev-shell/envrc-flake` or `src/tools/nix-dev-shell/envrc-shell`
|
If you're using direnv, you can create a symbolic link to `src/tools/nix-dev-shell/envrc-flake` or `src/tools/nix-dev-shell/envrc-shell`
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ln -s ./src/tools/nix-dev-shell/envrc-flake ./.envrc # Use flake
|
ln -s ./src/tools/nix-dev-shell/envrc-flake ./.envrc # Use flake
|
||||||
|
|
@ -436,6 +436,12 @@ or
|
||||||
ln -s ./src/tools/nix-dev-shell/envrc-shell ./.envrc # Use nix-shell
|
ln -s ./src/tools/nix-dev-shell/envrc-shell ./.envrc # Use nix-shell
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you're using the flake, make sure to also update it with the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
nix flake update --flake ./src/tools/nix-dev-shell
|
||||||
|
```
|
||||||
|
|
||||||
### Note
|
### Note
|
||||||
|
|
||||||
Note that when using nix on a not-NixOS distribution, it may be necessary to set
|
Note that when using nix on a not-NixOS distribution, it may be necessary to set
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ In some sense the desugarings from the previous examples are to:
|
||||||
struct Foo<const N: usize>;
|
struct Foo<const N: usize>;
|
||||||
type Alias = [u8; 1 + 1];
|
type Alias = [u8; 1 + 1];
|
||||||
|
|
||||||
// sort-of desugars to psuedo-rust:
|
// sort-of desugars to pseudo-rust:
|
||||||
struct Foo<const N: usize>;
|
struct Foo<const N: usize>;
|
||||||
|
|
||||||
const ANON = 1 + 1;
|
const ANON = 1 + 1;
|
||||||
|
|
@ -178,7 +178,7 @@ To check this we have [`ClauseKind::ConstArgHasType(ty::Const, Ty)`][const_arg_h
|
||||||
```rust
|
```rust
|
||||||
fn foo<const N: usize>() {}
|
fn foo<const N: usize>() {}
|
||||||
|
|
||||||
// desugars to in psuedo-rust
|
// desugars to in pseudo-rust
|
||||||
|
|
||||||
fn foo<const N>()
|
fn foo<const N>()
|
||||||
where
|
where
|
||||||
|
|
|
||||||
|
|
@ -324,7 +324,7 @@ When you resolve them, you should use `@rustbot` to mark it as `S-waiting-on-rev
|
||||||
GitHub allows [closing issues using keywords][closing-keywords].
|
GitHub allows [closing issues using keywords][closing-keywords].
|
||||||
This feature should be used to keep the issue tracker tidy.
|
This feature should be used to keep the issue tracker tidy.
|
||||||
However, it is generally preferred
|
However, it is generally preferred
|
||||||
to put the "closes #123" text in the PR description rather than the issue commit;
|
to put the "closes #123" text in the PR description rather than the commit message;
|
||||||
particularly during rebasing, citing the issue number in the commit can "spam"
|
particularly during rebasing, citing the issue number in the commit can "spam"
|
||||||
the issue in question.
|
the issue in question.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,13 @@
|
||||||
# crates.io dependencies
|
# crates.io dependencies
|
||||||
|
|
||||||
The Rust compiler supports building with some dependencies from `crates.io`.
|
The Rust compiler supports building with some dependencies from `crates.io`.
|
||||||
Examples are `log` and `env_logger`.
|
|
||||||
|
|
||||||
In general,
|
Rust Forge has [official policy for vetting new dependencies].
|
||||||
you should avoid adding dependencies to the compiler for several reasons:
|
|
||||||
|
|
||||||
- The dependency may not be of high quality or well-maintained.
|
|
||||||
- The dependency may not be using a compatible license.
|
|
||||||
- The dependency may have transitive dependencies that have one of the above
|
|
||||||
problems.
|
|
||||||
|
|
||||||
<!-- date-check: Aug 2025 -->
|
|
||||||
Note that there is no official policy for vetting new dependencies to the compiler.
|
|
||||||
Decisions are made on a case-by-case basis, during code review.
|
|
||||||
|
|
||||||
## Permitted dependencies
|
## Permitted dependencies
|
||||||
|
|
||||||
The `tidy` tool has [a list of crates that are allowed]. To add a
|
The `tidy` tool has [a list of crates that are allowed].
|
||||||
dependency that is not already in the compiler, you will need to add it to the list.
|
To add a dependency that is not already in the compiler, you will need to add it to the list.
|
||||||
|
|
||||||
[a list of crates that are allowed]: https://github.com/rust-lang/rust/blob/9d1b2106e23b1abd32fce1f17267604a5102f57a/src/tools/tidy/src/deps.rs#L73
|
[a list of crates that are allowed]: https://github.com/rust-lang/rust/blob/9d1b2106e23b1abd32fce1f17267604a5102f57a/src/tools/tidy/src/deps.rs#L73
|
||||||
|
[official policy for vetting new dependencies]: https://forge.rust-lang.org/compiler/third-party-out-of-tree#third-party-crates
|
||||||
|
|
|
||||||
|
|
@ -216,7 +216,7 @@ trait for a type would be one of these interfaces (`DW_tag_interface` type). Als
|
||||||
which it is implemented would describe all the interfaces this type implements. This requires a
|
which it is implemented would describe all the interfaces this type implements. This requires a
|
||||||
DWARF extension.
|
DWARF extension.
|
||||||
|
|
||||||
Issue on Github: [https://github.com/rust-lang/rust/issues/33014]
|
Issue on GitHub: [https://github.com/rust-lang/rust/issues/33014]
|
||||||
|
|
||||||
## Typical process for a Debug Info change (LLVM)
|
## Typical process for a Debug Info change (LLVM)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -228,7 +228,7 @@ Guidelines for different diagnostic levels:
|
||||||
The error or warning portion should *not* suggest how to fix the problem,
|
The error or warning portion should *not* suggest how to fix the problem,
|
||||||
only the "help" sub-diagnostic should.
|
only the "help" sub-diagnostic should.
|
||||||
|
|
||||||
- `note`: emitted to given more context and identify additional circumstances
|
- `note`: emitted to give more context and identify additional circumstances
|
||||||
and parts of the code that caused the warning or error. For example, the
|
and parts of the code that caused the warning or error. For example, the
|
||||||
borrow checker will note any previous conflicting borrows.
|
borrow checker will note any previous conflicting borrows.
|
||||||
|
|
||||||
|
|
@ -788,7 +788,7 @@ add_lint_group!(sess,
|
||||||
```
|
```
|
||||||
|
|
||||||
This defines the `nonstandard_style` group which turns on the listed lints. A
|
This defines the `nonstandard_style` group which turns on the listed lints. A
|
||||||
user can turn on these lints with a `!#[warn(nonstandard_style)]` attribute in
|
user can turn on these lints with a `#![warn(nonstandard_style)]` attribute in
|
||||||
the source code, or by passing `-W nonstandard-style` on the command line.
|
the source code, or by passing `-W nonstandard-style` on the command line.
|
||||||
|
|
||||||
Some lint groups are created automatically in `LintStore::register_lints`. For instance,
|
Some lint groups are created automatically in `LintStore::register_lints`. For instance,
|
||||||
|
|
@ -944,7 +944,7 @@ You can filter on the following boolean flags:
|
||||||
- `crate_local`: whether the code causing the trait bound to not be
|
- `crate_local`: whether the code causing the trait bound to not be
|
||||||
fulfilled is part of the user's crate. This is used to avoid suggesting
|
fulfilled is part of the user's crate. This is used to avoid suggesting
|
||||||
code changes that would require modifying a dependency.
|
code changes that would require modifying a dependency.
|
||||||
- `direct`: whether this is an user-specified rather than derived obligation.
|
- `direct`: whether this is a user-specified rather than derived obligation.
|
||||||
- `from_desugaring`: whether we are in some kind of desugaring, like `?`
|
- `from_desugaring`: whether we are in some kind of desugaring, like `?`
|
||||||
or a `try` block for example. This flag can also be matched on, see below.
|
or a `try` block for example. This flag can also be matched on, see below.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ customizing the rendering logic, or selecting messages at runtime, you will need
|
||||||
the corresponding trait (`Diagnostic`, `LintDiagnostic`, or `Subdiagnostic`).
|
the corresponding trait (`Diagnostic`, `LintDiagnostic`, or `Subdiagnostic`).
|
||||||
This approach provides greater flexibility and is recommended for diagnostics that go beyond simple, static structures.
|
This approach provides greater flexibility and is recommended for diagnostics that go beyond simple, static structures.
|
||||||
|
|
||||||
Diagnostic can be translated into different languages and each has a slug that uniquely identifies the diagnostic.
|
Diagnostic can be translated into different languages.
|
||||||
|
|
||||||
## `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]`
|
## `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]`
|
||||||
|
|
||||||
|
|
@ -21,13 +21,13 @@ shown below:
|
||||||
|
|
||||||
```rust,ignore
|
```rust,ignore
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(hir_analysis_field_already_declared, code = E0124)]
|
#[diag("field `{$field_name}` is already declared", code = E0124)]
|
||||||
pub struct FieldAlreadyDeclared {
|
pub struct FieldAlreadyDeclared {
|
||||||
pub field_name: Ident,
|
pub field_name: Ident,
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label]
|
#[label("field already declared")]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
#[label(previous_decl_label)]
|
#[label("`{$field_name}` first declared here")]
|
||||||
pub prev_span: Span,
|
pub prev_span: Span,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
@ -42,25 +42,10 @@ the `code` sub-attribute. Specifying a `code` isn't mandatory, but if you are
|
||||||
porting a diagnostic that uses `Diag` to use `Diagnostic`
|
porting a diagnostic that uses `Diag` to use `Diagnostic`
|
||||||
then you should keep the code if there was one.
|
then you should keep the code if there was one.
|
||||||
|
|
||||||
`#[diag(..)]` must provide a slug as the first positional argument (a path to an
|
`#[diag(..)]` must provide a message as the first positional argument.
|
||||||
item in `rustc_errors::fluent::*`). A slug uniquely identifies the diagnostic
|
The message is written in English, but might be translated to the locale requested by the user. See
|
||||||
and is also how the compiler knows what error message to emit (in the default
|
|
||||||
locale of the compiler, or in the locale requested by the user). See
|
|
||||||
[translation documentation](./translation.md) to learn more about how
|
[translation documentation](./translation.md) to learn more about how
|
||||||
translatable error messages are written and how slug items are generated.
|
translatable error messages are written and how they are generated.
|
||||||
|
|
||||||
In our example, the Fluent message for the "field already declared" diagnostic
|
|
||||||
looks like this:
|
|
||||||
|
|
||||||
```fluent
|
|
||||||
hir_analysis_field_already_declared =
|
|
||||||
field `{$field_name}` is already declared
|
|
||||||
.label = field already declared
|
|
||||||
.previous_decl_label = `{$field_name}` first declared here
|
|
||||||
```
|
|
||||||
|
|
||||||
`hir_analysis_field_already_declared` is the slug from our example and is followed
|
|
||||||
by the diagnostic message.
|
|
||||||
|
|
||||||
Every field of the `Diagnostic` which does not have an annotation is
|
Every field of the `Diagnostic` which does not have an annotation is
|
||||||
available in Fluent messages as a variable, like `field_name` in the example
|
available in Fluent messages as a variable, like `field_name` in the example
|
||||||
|
|
@ -76,13 +61,7 @@ specified on a `Diagnostic`.
|
||||||
|
|
||||||
`#[label]`, `#[help]`, `#[warning]` and `#[note]` can all be applied to fields which have the
|
`#[label]`, `#[help]`, `#[warning]` and `#[note]` can all be applied to fields which have the
|
||||||
type `Span`. Applying any of these attributes will create the corresponding
|
type `Span`. Applying any of these attributes will create the corresponding
|
||||||
subdiagnostic with that `Span`. These attributes will look for their
|
subdiagnostic with that `Span`. These attributes take a diagnostic message as an argument.
|
||||||
diagnostic message in a Fluent attribute attached to the primary Fluent
|
|
||||||
message. In our example, `#[label]` will look for
|
|
||||||
`hir_analysis_field_already_declared.label` (which has the message "field already
|
|
||||||
declared"). If there is more than one subdiagnostic of the same type, then
|
|
||||||
these attributes can also take a value that is the attribute name to look for
|
|
||||||
(e.g. `previous_decl_label` in our example).
|
|
||||||
|
|
||||||
Other types have special behavior when used in a `Diagnostic` derive:
|
Other types have special behavior when used in a `Diagnostic` derive:
|
||||||
|
|
||||||
|
|
@ -99,17 +78,17 @@ represent optional `#[note]`/`#[help]`/`#[warning]` subdiagnostics.
|
||||||
|
|
||||||
Suggestions can be emitted using one of four field attributes:
|
Suggestions can be emitted using one of four field attributes:
|
||||||
|
|
||||||
- `#[suggestion(slug, code = "...", applicability = "...")]`
|
- `#[suggestion("message", code = "...", applicability = "...")]`
|
||||||
- `#[suggestion_hidden(slug, code = "...", applicability = "...")]`
|
- `#[suggestion_hidden("message", code = "...", applicability = "...")]`
|
||||||
- `#[suggestion_short(slug, code = "...", applicability = "...")]`
|
- `#[suggestion_short("message", code = "...", applicability = "...")]`
|
||||||
- `#[suggestion_verbose(slug, code = "...", applicability = "...")]`
|
- `#[suggestion_verbose("message", code = "...", applicability = "...")]`
|
||||||
|
|
||||||
Suggestions must be applied on either a `Span` field or a `(Span,
|
Suggestions must be applied on either a `Span` field or a `(Span,
|
||||||
MachineApplicability)` field. Similarly to other field attributes, the slug
|
MachineApplicability)` field. Similarly to other field attributes, a message
|
||||||
specifies the Fluent attribute with the message and defaults to the equivalent
|
needs to be provided which will be shown to the user.
|
||||||
of `.suggestion`. `code` specifies the code that should be suggested as a
|
`code` specifies the code that should be suggested as a
|
||||||
replacement and is a format string (e.g. `{field_name}` would be replaced by
|
replacement and is a format string (e.g. `{field_name}` would be replaced by
|
||||||
the value of the `field_name` field of the struct), not a Fluent identifier.
|
the value of the `field_name` field of the struct).
|
||||||
`applicability` can be used to specify the applicability in the attribute, it
|
`applicability` can be used to specify the applicability in the attribute, it
|
||||||
cannot be used when the field's type contains an `Applicability`.
|
cannot be used when the field's type contains an `Applicability`.
|
||||||
|
|
||||||
|
|
@ -119,15 +98,15 @@ In the end, the `Diagnostic` derive will generate an implementation of
|
||||||
```rust,ignore
|
```rust,ignore
|
||||||
impl<'a, G: EmissionGuarantee> Diagnostic<'a> for FieldAlreadyDeclared {
|
impl<'a, G: EmissionGuarantee> Diagnostic<'a> for FieldAlreadyDeclared {
|
||||||
fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
|
fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
|
||||||
let mut diag = Diag::new(dcx, level, fluent::hir_analysis_field_already_declared);
|
let mut diag = Diag::new(dcx, level, "field `{$field_name}` is already declared");
|
||||||
diag.set_span(self.span);
|
diag.set_span(self.span);
|
||||||
diag.span_label(
|
diag.span_label(
|
||||||
self.span,
|
self.span,
|
||||||
fluent::hir_analysis_label
|
"field already declared"
|
||||||
);
|
);
|
||||||
diag.span_label(
|
diag.span_label(
|
||||||
self.prev_span,
|
self.prev_span,
|
||||||
fluent::hir_analysis_previous_decl_label
|
"`{$field_name}` first declared here"
|
||||||
);
|
);
|
||||||
diag
|
diag
|
||||||
}
|
}
|
||||||
|
|
@ -150,60 +129,40 @@ tcx.dcx().emit_err(FieldAlreadyDeclared {
|
||||||
`#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]` support the
|
`#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]` support the
|
||||||
following attributes:
|
following attributes:
|
||||||
|
|
||||||
- `#[diag(slug, code = "...")]`
|
- `#[diag("message", code = "...")]`
|
||||||
- _Applied to struct or enum variant._
|
- _Applied to struct or enum variant._
|
||||||
- _Mandatory_
|
- _Mandatory_
|
||||||
- Defines the text and error code to be associated with the diagnostic.
|
- Defines the text and error code to be associated with the diagnostic.
|
||||||
- Slug (_Mandatory_)
|
- Message (_Mandatory_)
|
||||||
- Uniquely identifies the diagnostic and corresponds to its Fluent message,
|
- The diagnostic message which will be shown to the user.
|
||||||
mandatory.
|
|
||||||
- A path to an item in `rustc_errors::fluent`, e.g.
|
|
||||||
`rustc_errors::fluent::hir_analysis_field_already_declared`
|
|
||||||
(`rustc_errors::fluent` is implicit in the attribute, so just
|
|
||||||
`hir_analysis_field_already_declared`).
|
|
||||||
- See [translation documentation](./translation.md).
|
- See [translation documentation](./translation.md).
|
||||||
- `code = "..."` (_Optional_)
|
- `code = "..."` (_Optional_)
|
||||||
- Specifies the error code.
|
- Specifies the error code.
|
||||||
- `#[note]` or `#[note(slug)]` (_Optional_)
|
- `#[note("message")]` (_Optional_)
|
||||||
- _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._
|
- _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._
|
||||||
- Adds a note subdiagnostic.
|
- Adds a note subdiagnostic.
|
||||||
- Value is a path to an item in `rustc_errors::fluent` for the note's
|
- Value is the note's message.
|
||||||
message.
|
|
||||||
- Defaults to equivalent of `.note`.
|
|
||||||
- If applied to a `Span` field, creates a spanned note.
|
- If applied to a `Span` field, creates a spanned note.
|
||||||
- `#[help]` or `#[help(slug)]` (_Optional_)
|
- `#[help("message")]` (_Optional_)
|
||||||
- _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._
|
- _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._
|
||||||
- Adds a help subdiagnostic.
|
- Adds a help subdiagnostic.
|
||||||
- Value is a path to an item in `rustc_errors::fluent` for the note's
|
- Value is the help message.
|
||||||
message.
|
|
||||||
- Defaults to equivalent of `.help`.
|
|
||||||
- If applied to a `Span` field, creates a spanned help.
|
- If applied to a `Span` field, creates a spanned help.
|
||||||
- `#[label]` or `#[label(slug)]` (_Optional_)
|
- `#[label("message")]` (_Optional_)
|
||||||
- _Applied to `Span` fields._
|
- _Applied to `Span` fields._
|
||||||
- Adds a label subdiagnostic.
|
- Adds a label subdiagnostic.
|
||||||
- Value is a path to an item in `rustc_errors::fluent` for the note's
|
- Value is the label's message.
|
||||||
message.
|
- `#[warning("message")]` (_Optional_)
|
||||||
- Defaults to equivalent of `.label`.
|
|
||||||
- `#[warning]` or `#[warning(slug)]` (_Optional_)
|
|
||||||
- _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._
|
- _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._
|
||||||
- Adds a warning subdiagnostic.
|
- Adds a warning subdiagnostic.
|
||||||
- Value is a path to an item in `rustc_errors::fluent` for the note's
|
- Value is the warning's message.
|
||||||
message.
|
- `#[suggestion{,_hidden,_short,_verbose}("message", code = "...", applicability = "...")]`
|
||||||
- Defaults to equivalent of `.warn`.
|
|
||||||
- `#[suggestion{,_hidden,_short,_verbose}(slug, code = "...", applicability = "...")]`
|
|
||||||
(_Optional_)
|
(_Optional_)
|
||||||
- _Applied to `(Span, MachineApplicability)` or `Span` fields._
|
- _Applied to `(Span, MachineApplicability)` or `Span` fields._
|
||||||
- Adds a suggestion subdiagnostic.
|
- Adds a suggestion subdiagnostic.
|
||||||
- Slug (_Mandatory_)
|
- Message (_Mandatory_)
|
||||||
- A path to an item in `rustc_errors::fluent`, e.g.
|
- Value is the suggestion message that will be shown to the user.
|
||||||
`rustc_errors::fluent::hir_analysis_field_already_declared`
|
|
||||||
(`rustc_errors::fluent` is implicit in the attribute, so just
|
|
||||||
`hir_analysis_field_already_declared`). Fluent attributes for all messages
|
|
||||||
exist as top-level items in that module (so `hir_analysis_message.attr` is just
|
|
||||||
`attr`).
|
|
||||||
- See [translation documentation](./translation.md).
|
- See [translation documentation](./translation.md).
|
||||||
- Defaults to `rustc_errors::fluent::_subdiag::suggestion` (or
|
|
||||||
- `.suggestion` in Fluent).
|
|
||||||
- `code = "..."`/`code("...", ...)` (_Mandatory_)
|
- `code = "..."`/`code("...", ...)` (_Mandatory_)
|
||||||
- One or multiple format strings indicating the code to be suggested as a
|
- One or multiple format strings indicating the code to be suggested as a
|
||||||
replacement. Multiple values signify multiple possible replacements.
|
replacement. Multiple values signify multiple possible replacements.
|
||||||
|
|
@ -235,12 +194,12 @@ shown below:
|
||||||
```rust
|
```rust
|
||||||
#[derive(Subdiagnostic)]
|
#[derive(Subdiagnostic)]
|
||||||
pub enum ExpectedReturnTypeLabel<'tcx> {
|
pub enum ExpectedReturnTypeLabel<'tcx> {
|
||||||
#[label(hir_analysis_expected_default_return_type)]
|
#[label("expected `()` because of default return type")]
|
||||||
Unit {
|
Unit {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
span: Span,
|
span: Span,
|
||||||
},
|
},
|
||||||
#[label(hir_analysis_expected_return_type)]
|
#[label("expected `{$expected}` because of return type")]
|
||||||
Other {
|
Other {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
span: Span,
|
span: Span,
|
||||||
|
|
@ -260,21 +219,9 @@ attribute applied to the struct or each variant, one of:
|
||||||
- `#[warning(..)]` for defining a warning
|
- `#[warning(..)]` for defining a warning
|
||||||
- `#[suggestion{,_hidden,_short,_verbose}(..)]` for defining a suggestion
|
- `#[suggestion{,_hidden,_short,_verbose}(..)]` for defining a suggestion
|
||||||
|
|
||||||
All of the above must provide a slug as the first positional argument (a path
|
All of the above must provide a diagnostic message as the first positional argument.
|
||||||
to an item in `rustc_errors::fluent::*`). A slug uniquely identifies the
|
|
||||||
diagnostic and is also how the compiler knows what error message to emit (in
|
|
||||||
the default locale of the compiler, or in the locale requested by the user).
|
|
||||||
See [translation documentation](./translation.md) to learn more about how
|
See [translation documentation](./translation.md) to learn more about how
|
||||||
translatable error messages are written and how slug items are generated.
|
translatable error messages are generated.
|
||||||
|
|
||||||
In our example, the Fluent message for the "expected return type" label
|
|
||||||
looks like this:
|
|
||||||
|
|
||||||
```fluent
|
|
||||||
hir_analysis_expected_default_return_type = expected `()` because of default return type
|
|
||||||
|
|
||||||
hir_analysis_expected_return_type = expected `{$expected}` because of return type
|
|
||||||
```
|
|
||||||
|
|
||||||
Using the `#[primary_span]` attribute on a field (with type `Span`) will denote
|
Using the `#[primary_span]` attribute on a field (with type `Span`) will denote
|
||||||
the primary span of the subdiagnostic. A primary span is only necessary for a
|
the primary span of the subdiagnostic. A primary span is only necessary for a
|
||||||
|
|
@ -289,17 +236,15 @@ Like `Diagnostic`, `Subdiagnostic` supports `Option<T>` and
|
||||||
|
|
||||||
Suggestions can be emitted using one of four attributes on the type/variant:
|
Suggestions can be emitted using one of four attributes on the type/variant:
|
||||||
|
|
||||||
- `#[suggestion(..., code = "...", applicability = "...")]`
|
- `#[suggestion("...", code = "...", applicability = "...")]`
|
||||||
- `#[suggestion_hidden(..., code = "...", applicability = "...")]`
|
- `#[suggestion_hidden("...", code = "...", applicability = "...")]`
|
||||||
- `#[suggestion_short(..., code = "...", applicability = "...")]`
|
- `#[suggestion_short("...", code = "...", applicability = "...")]`
|
||||||
- `#[suggestion_verbose(..., code = "...", applicability = "...")]`
|
- `#[suggestion_verbose("...", code = "...", applicability = "...")]`
|
||||||
|
|
||||||
Suggestions require `#[primary_span]` be set on a field and can have the
|
Suggestions require `#[primary_span]` be set on a field and can have the
|
||||||
following sub-attributes:
|
following sub-attributes:
|
||||||
|
|
||||||
- The first positional argument specifies the path to a item in
|
- The first positional argument specifies the message which will be shown to the user.
|
||||||
`rustc_errors::fluent` corresponding to the Fluent attribute with the message
|
|
||||||
and defaults to the equivalent of `.suggestion`.
|
|
||||||
- `code` specifies the code that should be suggested as a replacement and is a
|
- `code` specifies the code that should be suggested as a replacement and is a
|
||||||
format string (e.g. `{field_name}` would be replaced by the value of the
|
format string (e.g. `{field_name}` would be replaced by the value of the
|
||||||
`field_name` field of the struct), not a Fluent identifier.
|
`field_name` field of the struct), not a Fluent identifier.
|
||||||
|
|
@ -318,11 +263,11 @@ impl<'tcx> Subdiagnostic for ExpectedReturnTypeLabel<'tcx> {
|
||||||
use rustc_errors::{Applicability, IntoDiagArg};
|
use rustc_errors::{Applicability, IntoDiagArg};
|
||||||
match self {
|
match self {
|
||||||
ExpectedReturnTypeLabel::Unit { span } => {
|
ExpectedReturnTypeLabel::Unit { span } => {
|
||||||
diag.span_label(span, rustc_errors::fluent::hir_analysis_expected_default_return_type)
|
diag.span_label(span, "expected `()` because of default return type")
|
||||||
}
|
}
|
||||||
ExpectedReturnTypeLabel::Other { span, expected } => {
|
ExpectedReturnTypeLabel::Other { span, expected } => {
|
||||||
diag.set_arg("expected", expected);
|
diag.set_arg("expected", expected);
|
||||||
diag.span_label(span, rustc_errors::fluent::hir_analysis_expected_return_type)
|
diag.span_label(span, "expected `{$expected}` because of return type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -354,7 +299,7 @@ If a subdiagnostic sets a argument with the same name as a arguments already in
|
||||||
it will report an error at runtime unless both have exactly the same value.
|
it will report an error at runtime unless both have exactly the same value.
|
||||||
It has two benefits:
|
It has two benefits:
|
||||||
- preserves the flexibility that arguments in the main diagnostic are allowed to appear in the attributes of the subdiagnostic.
|
- preserves the flexibility that arguments in the main diagnostic are allowed to appear in the attributes of the subdiagnostic.
|
||||||
For example, There is an attribute `#[suggestion(code = "{new_vis}")]` in the subdiagnostic, but `new_vis` is the field in the main diagnostic struct.
|
For example, There is an attribute `#[suggestion("...", code = "{new_vis}")]` in the subdiagnostic, but `new_vis` is the field in the main diagnostic struct.
|
||||||
- prevents accidental overwriting or deletion of arguments required by the main diagnostic or other subdiagnostics.
|
- prevents accidental overwriting or deletion of arguments required by the main diagnostic or other subdiagnostics.
|
||||||
|
|
||||||
These rules guarantee that arguments injected by subdiagnostics are strictly scoped to their own rendering.
|
These rules guarantee that arguments injected by subdiagnostics are strictly scoped to their own rendering.
|
||||||
|
|
@ -364,32 +309,20 @@ Additionally, subdiagnostics can access arguments from the main diagnostic with
|
||||||
### Reference for `#[derive(Subdiagnostic)]`
|
### Reference for `#[derive(Subdiagnostic)]`
|
||||||
`#[derive(Subdiagnostic)]` supports the following attributes:
|
`#[derive(Subdiagnostic)]` supports the following attributes:
|
||||||
|
|
||||||
- `#[label(slug)]`, `#[help(slug)]`, `#[warning(slug)]` or `#[note(slug)]`
|
- `#[label("message")]`, `#[help("message")]`, `#[warning("message")]` or `#[note("message")]`
|
||||||
- _Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes._
|
- _Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes._
|
||||||
- _Mandatory_
|
- _Mandatory_
|
||||||
- Defines the type to be representing a label, help or note.
|
- Defines the type to be representing a label, help or note.
|
||||||
- Slug (_Mandatory_)
|
- Message (_Mandatory_)
|
||||||
- Uniquely identifies the diagnostic and corresponds to its Fluent message,
|
- The diagnostic message that will be shown to the user.
|
||||||
mandatory.
|
|
||||||
- A path to an item in `rustc_errors::fluent`, e.g.
|
|
||||||
`rustc_errors::fluent::hir_analysis_field_already_declared`
|
|
||||||
(`rustc_errors::fluent` is implicit in the attribute, so just
|
|
||||||
`hir_analysis_field_already_declared`).
|
|
||||||
- See [translation documentation](./translation.md).
|
- See [translation documentation](./translation.md).
|
||||||
- `#[suggestion{,_hidden,_short,_verbose}(slug, code = "...", applicability = "...")]`
|
- `#[suggestion{,_hidden,_short,_verbose}("message", code = "...", applicability = "...")]`
|
||||||
- _Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes._
|
- _Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes._
|
||||||
- _Mandatory_
|
- _Mandatory_
|
||||||
- Defines the type to be representing a suggestion.
|
- Defines the type to be representing a suggestion.
|
||||||
- Slug (_Mandatory_)
|
- Message (_Mandatory_)
|
||||||
- A path to an item in `rustc_errors::fluent`, e.g.
|
- The diagnostic message that will be shown to the user.
|
||||||
`rustc_errors::fluent::hir_analysis_field_already_declared`
|
|
||||||
(`rustc_errors::fluent` is implicit in the attribute, so just
|
|
||||||
`hir_analysis::field_already_declared`). Fluent attributes for all messages
|
|
||||||
exist as top-level items in that module (so `hir_analysis_message.attr` is just
|
|
||||||
`hir_analysis::attr`).
|
|
||||||
- See [translation documentation](./translation.md).
|
- See [translation documentation](./translation.md).
|
||||||
- Defaults to `rustc_errors::fluent::_subdiag::suggestion` (or
|
|
||||||
- `.suggestion` in Fluent).
|
|
||||||
- `code = "..."`/`code("...", ...)` (_Mandatory_)
|
- `code = "..."`/`code("...", ...)` (_Mandatory_)
|
||||||
- One or multiple format strings indicating the code to be suggested as a
|
- One or multiple format strings indicating the code to be suggested as a
|
||||||
replacement. Multiple values signify multiple possible replacements.
|
replacement. Multiple values signify multiple possible replacements.
|
||||||
|
|
@ -401,11 +334,11 @@ Additionally, subdiagnostics can access arguments from the main diagnostic with
|
||||||
- `maybe-incorrect`
|
- `maybe-incorrect`
|
||||||
- `has-placeholders`
|
- `has-placeholders`
|
||||||
- `unspecified`
|
- `unspecified`
|
||||||
- `#[multipart_suggestion{,_hidden,_short,_verbose}(slug, applicability = "...")]`
|
- `#[multipart_suggestion{,_hidden,_short,_verbose}("message", applicability = "...")]`
|
||||||
- _Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes._
|
- _Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes._
|
||||||
- _Mandatory_
|
- _Mandatory_
|
||||||
- Defines the type to be representing a multipart suggestion.
|
- Defines the type to be representing a multipart suggestion.
|
||||||
- Slug (_Mandatory_): see `#[suggestion]`
|
- Message (_Mandatory_): see `#[suggestion]`
|
||||||
- `applicability = "..."` (_Optional_): see `#[suggestion]`
|
- `applicability = "..."` (_Optional_): see `#[suggestion]`
|
||||||
- `#[primary_span]` (_Mandatory_ for labels and suggestions; _optional_ otherwise; not applicable
|
- `#[primary_span]` (_Mandatory_ for labels and suggestions; _optional_ otherwise; not applicable
|
||||||
to multipart suggestions)
|
to multipart suggestions)
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,7 @@ active redesign proposals (as of
|
||||||
Please see the tracking issue <https://github.com/rust-lang/rust/issues/132181>
|
Please see the tracking issue <https://github.com/rust-lang/rust/issues/132181>
|
||||||
for status updates.
|
for status updates.
|
||||||
|
|
||||||
We have downgraded the internal lints `untranslatable_diagnostic` and
|
The translation infra is waiting for a yet-to-be-proposed redesign and thus rework, we are not
|
||||||
`diagnostic_outside_of_impl`. Those internal lints previously required new code
|
|
||||||
to use the current translation infrastructure. However, because the translation
|
|
||||||
infra is waiting for a yet-to-be-proposed redesign and thus rework, we are not
|
|
||||||
mandating usage of current translation infra. Use the infra if you *want to* or
|
mandating usage of current translation infra. Use the infra if you *want to* or
|
||||||
otherwise makes the code cleaner, but otherwise sidestep the translation infra
|
otherwise makes the code cleaner, but otherwise sidestep the translation infra
|
||||||
if you need more flexibility.
|
if you need more flexibility.
|
||||||
|
|
@ -40,11 +37,6 @@ There are two ways of writing translatable diagnostics:
|
||||||
When adding or changing a translatable diagnostic,
|
When adding or changing a translatable diagnostic,
|
||||||
you don't need to worry about the translations.
|
you don't need to worry about the translations.
|
||||||
Only updating the original English message is required.
|
Only updating the original English message is required.
|
||||||
Currently,
|
|
||||||
each crate which defines translatable diagnostics has its own Fluent resource,
|
|
||||||
which is a file named `messages.ftl`,
|
|
||||||
located in the root of the crate
|
|
||||||
(such as`compiler/rustc_expand/messages.ftl`).
|
|
||||||
|
|
||||||
## Fluent
|
## Fluent
|
||||||
|
|
||||||
|
|
@ -118,11 +110,8 @@ information that needs to be provided by the code to do so.
|
||||||
|
|
||||||
### Compile-time validation and typed identifiers
|
### Compile-time validation and typed identifiers
|
||||||
|
|
||||||
rustc's `fluent_messages` macro performs compile-time validation of Fluent
|
rustc's `#[derive(Diagnostic)]` macro performs compile-time validation of Fluent
|
||||||
resources and generates code to make it easier to refer to Fluent messages in
|
messages. Compile-time validation of Fluent resources will emit any parsing errors
|
||||||
diagnostics.
|
|
||||||
|
|
||||||
Compile-time validation of Fluent resources will emit any parsing errors
|
|
||||||
from Fluent resources while building the compiler, preventing invalid Fluent
|
from Fluent resources while building the compiler, preventing invalid Fluent
|
||||||
resources from causing panics in the compiler. Compile-time validation also
|
resources from causing panics in the compiler. Compile-time validation also
|
||||||
emits an error if multiple Fluent messages have the same identifier.
|
emits an error if multiple Fluent messages have the same identifier.
|
||||||
|
|
|
||||||
144
src/doc/rustc-dev-guide/src/feature-gate-check.md
Normal file
144
src/doc/rustc-dev-guide/src/feature-gate-check.md
Normal file
|
|
@ -0,0 +1,144 @@
|
||||||
|
# Feature Gate Checking
|
||||||
|
|
||||||
|
For the how-to steps to add, remove, rename, or stabilize feature gates,
|
||||||
|
see [Feature gates][feature-gates].
|
||||||
|
|
||||||
|
Feature gates prevent usage of unstable language and library features without a
|
||||||
|
nightly-only `#![feature(...)]` opt-in. This chapter documents the implementation
|
||||||
|
of feature gating: where gates are defined, how they are enabled, and how usage
|
||||||
|
is verified.
|
||||||
|
|
||||||
|
<!-- data-check: Feb 2026 -->
|
||||||
|
|
||||||
|
## Feature Definitions
|
||||||
|
|
||||||
|
All feature gate definitions are located in the `rustc_feature` crate:
|
||||||
|
|
||||||
|
- **Unstable features** are declared in [`rustc_feature/src/unstable.rs`] via
|
||||||
|
the `declare_features!` macro. This associates features with issue numbers and
|
||||||
|
tracking metadata.
|
||||||
|
- **Accepted features** (stabilized) are listed in [`rustc_feature/src/accepted.rs`].
|
||||||
|
- **Removed features** (explicitly disallowed) are listed in [`rustc_feature/src/removed.rs`].
|
||||||
|
- **Gated built-in attributes and cfgs** are declared in [`rustc_feature/src/builtin_attrs.rs`].
|
||||||
|
|
||||||
|
The [`rustc_feature::Features`] type represents the **active feature set** for a
|
||||||
|
crate. Helpers like `enabled`, `incomplete`, and `internal` are used during
|
||||||
|
compilation to check status.
|
||||||
|
|
||||||
|
## Collecting Features
|
||||||
|
|
||||||
|
Before AST validation or expansion, `rustc` collects crate-level
|
||||||
|
`#![feature(...)]` attributes to build the active `Features` set.
|
||||||
|
|
||||||
|
- The collection happens in [`rustc_expand/src/config.rs`] in [`features`].
|
||||||
|
- Each `#![feature]` entry is classified against the `unstable`, `accepted`, and
|
||||||
|
`removed` tables:
|
||||||
|
- **Removed** features cause an immediate error.
|
||||||
|
- **Accepted** features are recorded but do not require nightly. On
|
||||||
|
stable/beta, `maybe_stage_features` in
|
||||||
|
[`rustc_ast_passes/src/feature_gate.rs`] emits the non-nightly
|
||||||
|
diagnostic and lists stable features, which is where the "already
|
||||||
|
stabilized" messaging comes from.
|
||||||
|
- **Unstable** features are recorded as enabled.
|
||||||
|
- Unknown features are treated as **library features** and validated later.
|
||||||
|
- With `-Z allow-features=...`, any **unstable** or **unknown** feature
|
||||||
|
not in the allowlist is rejected.
|
||||||
|
- [`RUSTC_BOOTSTRAP`] feeds into `UnstableFeatures::from_environment`. This
|
||||||
|
variable controls whether the compiler is treated as "nightly", allowing
|
||||||
|
feature gates to be bypassed during bootstrapping or explicitly disabled (`-1`).
|
||||||
|
|
||||||
|
## Parser Gating
|
||||||
|
|
||||||
|
Some syntax is detected and gated during parsing. The parser records spans for
|
||||||
|
later checking to keep diagnostics consistent and deferred until after parsing.
|
||||||
|
|
||||||
|
- [`rustc_session/src/parse.rs`] defines [`GatedSpans`] and the `gate` method.
|
||||||
|
- The parser uses it in [`rustc_parse/src/parser/*`] when it encounters
|
||||||
|
syntax that requires a gate (e.g., `async for`, `yield`, experimental patterns).
|
||||||
|
|
||||||
|
## Checking Pass
|
||||||
|
|
||||||
|
The central logic lives in [`rustc_ast_passes/src/feature_gate.rs`], primarily
|
||||||
|
in `check_crate` and its AST visitor.
|
||||||
|
|
||||||
|
### `check_crate`
|
||||||
|
|
||||||
|
`check_crate` performs high-level validation:
|
||||||
|
|
||||||
|
- `maybe_stage_features`: Rejects `#![feature]` on stable/beta.
|
||||||
|
- `check_incompatible_features`: Ensures incompatible feature combinations
|
||||||
|
(declared in `rustc_feature::INCOMPATIBLE_FEATURES`) are not used together.
|
||||||
|
- `check_new_solver_banned_features`: Bans features incompatible with
|
||||||
|
compiler mode for the next trait solver.
|
||||||
|
- **Parser-gated spans**: Processes the `GatedSpans` recorded during parsing
|
||||||
|
(see [Checking `GatedSpans`](#checking-gatedspans)).
|
||||||
|
|
||||||
|
### Checking `GatedSpans`
|
||||||
|
|
||||||
|
`check_crate` iterates over `sess.psess.gated_spans`:
|
||||||
|
|
||||||
|
- The `gate_all!` macro emits diagnostics for each gated span if the feature is
|
||||||
|
not enabled.
|
||||||
|
- Some gates have extra logic (e.g., `yield` can be allowed by `coroutines` or
|
||||||
|
`gen_blocks`).
|
||||||
|
- Legacy gates (e.g., `box_patterns`, `try_blocks`) may use a separate path that
|
||||||
|
emits future-incompatibility warnings instead of hard errors.
|
||||||
|
|
||||||
|
### AST Visitor
|
||||||
|
|
||||||
|
A `PostExpansionVisitor` walks the expanded AST to check constructs that are
|
||||||
|
easier to validate after expansion.
|
||||||
|
|
||||||
|
- The visitor uses helper macros (`gate!`, `gate_alt!`, `gate_multi!`) to check:
|
||||||
|
1. Is the feature enabled?
|
||||||
|
2. Does `span.allows_unstable` permit it (for internal compiler macros)?
|
||||||
|
- Examples include `trait_alias`, `decl_macro`, `extern types`, and various
|
||||||
|
`impl Trait` forms.
|
||||||
|
|
||||||
|
## Attributes and `cfg`
|
||||||
|
|
||||||
|
Beyond syntax, rustc also gates attributes and `cfg` options.
|
||||||
|
|
||||||
|
### Built-in attributes
|
||||||
|
|
||||||
|
- [`rustc_ast_passes::check_attribute`] inspects attributes against
|
||||||
|
`BUILTIN_ATTRIBUTE_MAP`.
|
||||||
|
- If the attribute is `AttributeGate::Gated` and the feature isn’t enabled,
|
||||||
|
`feature_err` is emitted.
|
||||||
|
|
||||||
|
### `cfg` options
|
||||||
|
|
||||||
|
- [`rustc_attr_parsing/src/attributes/cfg.rs`] defines `gate_cfg` and uses
|
||||||
|
[`rustc_feature::find_gated_cfg`] to reject gated `cfg`s.
|
||||||
|
- `gate_cfg` respects `Span::allows_unstable`, allowing internal compiler
|
||||||
|
macros to bypass `cfg` gates when marked with `#[allow_internal_unstable]`.
|
||||||
|
- The gated cfg list is defined in [`rustc_feature/src/builtin_attrs.rs`].
|
||||||
|
|
||||||
|
## Diagnostics
|
||||||
|
|
||||||
|
Diagnostic helpers are located in [`rustc_session/src/parse.rs`].
|
||||||
|
|
||||||
|
- `feature_err` and `feature_warn` emit standardized diagnostics, attaching the
|
||||||
|
tracking issue number where possible.
|
||||||
|
- `Span::allows_unstable` in [`rustc_span/src/lib.rs`] checks if a span originates
|
||||||
|
from a macro marked with `#[allow_internal_unstable]`. This allows internal
|
||||||
|
macros to use unstable features on stable channels while enforcing gates for
|
||||||
|
user code.
|
||||||
|
|
||||||
|
[`rustc_feature/src/unstable.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_feature/src/unstable.rs
|
||||||
|
[`rustc_feature/src/removed.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_feature/src/removed.rs
|
||||||
|
[`rustc_feature/src/accepted.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_feature/src/accepted.rs
|
||||||
|
[`rustc_feature/src/builtin_attrs.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_feature/src/builtin_attrs.rs
|
||||||
|
[`rustc_feature::Features`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_feature/struct.Features.html
|
||||||
|
[`rustc_expand/src/config.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_expand/src/config.rs
|
||||||
|
[`features`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/config/fn.features.html
|
||||||
|
[`RUSTC_BOOTSTRAP`]: https://doc.rust-lang.org/beta/unstable-book/compiler-environment-variables/RUSTC_BOOTSTRAP.html
|
||||||
|
[`rustc_session/src/parse.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_session/src/parse.rs
|
||||||
|
[`GatedSpans`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/parse/struct.GatedSpans.html
|
||||||
|
[`rustc_ast_passes/src/feature_gate.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_ast_passes/src/feature_gate.rs
|
||||||
|
[`rustc_parse/src/parser/*`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/index.html
|
||||||
|
[`rustc_ast_passes::check_attribute`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast_passes/feature_gate/fn.check_attribute.html
|
||||||
|
[`rustc_attr_parsing/src/attributes/cfg.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_attr_parsing/src/attributes/cfg.rs
|
||||||
|
[`rustc_feature::find_gated_cfg`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_feature/fn.find_gated_cfg.html
|
||||||
|
[`rustc_span/src/lib.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_span/src/lib.rs
|
||||||
|
[feature-gates]: ./feature-gates.md
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
# Feature Gate Checking
|
|
||||||
|
|
||||||
**TODO**: this chapter [#1158](https://github.com/rust-lang/rustc-dev-guide/issues/1158)
|
|
||||||
|
|
@ -3,9 +3,13 @@
|
||||||
This chapter is intended to provide basic help for adding, removing, and
|
This chapter is intended to provide basic help for adding, removing, and
|
||||||
modifying feature gates.
|
modifying feature gates.
|
||||||
|
|
||||||
|
For how rustc enforces and checks feature gates in the compiler pipeline,
|
||||||
|
see [Feature Gate Checking][feature-gate-check].
|
||||||
|
|
||||||
Note that this is specific to *language* feature gates; *library* feature gates use [a different
|
Note that this is specific to *language* feature gates; *library* feature gates use [a different
|
||||||
mechanism][libs-gate].
|
mechanism][libs-gate].
|
||||||
|
|
||||||
|
[feature-gate-check]: ./feature-gate-check.md
|
||||||
[libs-gate]: ./stability.md
|
[libs-gate]: ./stability.md
|
||||||
|
|
||||||
## Adding a feature gate
|
## Adding a feature gate
|
||||||
|
|
|
||||||
|
|
@ -372,7 +372,7 @@ to ensure that Git doesn't create merge commits when `git pull`ing, without
|
||||||
needing to pass `--ff-only` or `--rebase` every time.
|
needing to pass `--ff-only` or `--rebase` every time.
|
||||||
|
|
||||||
You can also `git push --force-with-lease` from main to double-check that your
|
You can also `git push --force-with-lease` from main to double-check that your
|
||||||
feature branches are in sync with their state on the Github side.
|
feature branches are in sync with their state on the GitHub side.
|
||||||
|
|
||||||
## Advanced Rebasing
|
## Advanced Rebasing
|
||||||
|
|
||||||
|
|
@ -494,7 +494,7 @@ to follow and understand.
|
||||||
|
|
||||||
### Hiding whitespace
|
### Hiding whitespace
|
||||||
|
|
||||||
Github has a button for disabling whitespace changes that may be useful.
|
GitHub has a button for disabling whitespace changes that may be useful.
|
||||||
You can also use `git diff -w origin/main` to view changes locally.
|
You can also use `git diff -w origin/main` to view changes locally.
|
||||||
|
|
||||||

|

|
||||||
|
|
@ -505,7 +505,7 @@ To checkout PRs locally, you can use `git fetch upstream pull/NNNNN/head && git
|
||||||
FETCH_HEAD`.
|
FETCH_HEAD`.
|
||||||
|
|
||||||
You can also use github's cli tool.
|
You can also use github's cli tool.
|
||||||
Github shows a button on PRs where you can copy-paste the command to check it out locally.
|
GitHub shows a button on PRs where you can copy-paste the command to check it out locally.
|
||||||
See <https://cli.github.com/> for more info.
|
See <https://cli.github.com/> for more info.
|
||||||
|
|
||||||

|

|
||||||
|
|
@ -521,7 +521,7 @@ for more details.
|
||||||
|
|
||||||
### Moving large sections of code
|
### Moving large sections of code
|
||||||
|
|
||||||
Git and Github's default diff view for large moves *within* a file is quite poor; it will show each
|
Git and GitHub's default diff view for large moves *within* a file is quite poor; it will show each
|
||||||
line as deleted and each line as added, forcing you to compare each line yourself.
|
line as deleted and each line as added, forcing you to compare each line yourself.
|
||||||
Git has an option to show moved lines in a different color:
|
Git has an option to show moved lines in a different color:
|
||||||
|
|
||||||
|
|
@ -562,7 +562,7 @@ Rust projects from within the `rust` repo.
|
||||||
Examples include Rust's fork of
|
Examples include Rust's fork of
|
||||||
`llvm-project`, `cargo`, and libraries like `stdarch` and `backtrace`.
|
`llvm-project`, `cargo`, and libraries like `stdarch` and `backtrace`.
|
||||||
|
|
||||||
Those projects are developed and maintained in an separate Git (and GitHub)
|
Those projects are developed and maintained in a separate Git (and GitHub)
|
||||||
repository, and they have their own Git history/commits, issue tracker and PRs.
|
repository, and they have their own Git history/commits, issue tracker and PRs.
|
||||||
Submodules allow us to create some sort of embedded sub-repository inside the
|
Submodules allow us to create some sort of embedded sub-repository inside the
|
||||||
`rust` repository and use them like they were directories in the `rust` repository.
|
`rust` repository and use them like they were directories in the `rust` repository.
|
||||||
|
|
|
||||||
|
|
@ -468,7 +468,7 @@ Here `$mvar` is called a _metavariable_. Unlike normal variables, rather than
|
||||||
binding to a value _at runtime_, a metavariable binds _at compile time_ to a
|
binding to a value _at runtime_, a metavariable binds _at compile time_ to a
|
||||||
tree of _tokens_. A _token_ is a single "unit" of the grammar, such as an
|
tree of _tokens_. A _token_ is a single "unit" of the grammar, such as an
|
||||||
identifier (e.g. `foo`) or punctuation (e.g. `=>`). There are also other
|
identifier (e.g. `foo`) or punctuation (e.g. `=>`). There are also other
|
||||||
special tokens, such as `EOF`, which its self indicates that there are no more
|
special tokens, such as `EOF`, which itself indicates that there are no more
|
||||||
tokens. There are token trees resulting from the paired parentheses-like
|
tokens. There are token trees resulting from the paired parentheses-like
|
||||||
characters (`(`...`)`, `[`...`]`, and `{`...`}`) – they include the open and
|
characters (`(`...`)`, `[`...`]`, and `{`...`}`) – they include the open and
|
||||||
close and all the tokens in between (Rust requires that parentheses-like
|
close and all the tokens in between (Rust requires that parentheses-like
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ that fits the notification group's criteria. If you are interested, you
|
||||||
can then [claim the issue] and start working on it.
|
can then [claim the issue] and start working on it.
|
||||||
|
|
||||||
Of course, you don't have to wait for new issues to be tagged! If you
|
Of course, you don't have to wait for new issues to be tagged! If you
|
||||||
prefer, you can use the Github label for a notification group to
|
prefer, you can use the GitHub label for a notification group to
|
||||||
search for existing issues that haven't been claimed yet.
|
search for existing issues that haven't been claimed yet.
|
||||||
|
|
||||||
[claim the issue]: https://forge.rust-lang.org/triagebot/issue-assignment.html
|
[claim the issue]: https://forge.rust-lang.org/triagebot/issue-assignment.html
|
||||||
|
|
@ -47,7 +47,7 @@ particularly those of **middle priority**:
|
||||||
## Joining a notification group
|
## Joining a notification group
|
||||||
|
|
||||||
To join a notification group, you just have to open a PR adding your
|
To join a notification group, you just have to open a PR adding your
|
||||||
Github username to the appropriate file in the Rust team repository.
|
GitHub username to the appropriate file in the Rust team repository.
|
||||||
See the "example PRs" below to get a precise idea and to identify the
|
See the "example PRs" below to get a precise idea and to identify the
|
||||||
file to edit.
|
file to edit.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Apple notification group
|
# Apple notification group
|
||||||
|
|
||||||
**Github Labels:** [O-macos], [O-ios], [O-tvos], [O-watchos] and [O-visionos] <br>
|
**GitHub Labels:** [O-macos], [O-ios], [O-tvos], [O-watchos] and [O-visionos] <br>
|
||||||
**Ping command:** `@rustbot ping apple`
|
**Ping command:** `@rustbot ping apple`
|
||||||
|
|
||||||
This list will be used to ask for help both in diagnosing and testing
|
This list will be used to ask for help both in diagnosing and testing
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# ARM notification group
|
# ARM notification group
|
||||||
|
|
||||||
**Github Label:** [O-ARM] <br>
|
**GitHub Label:** [O-ARM] <br>
|
||||||
**Ping command:** `@rustbot ping arm`
|
**Ping command:** `@rustbot ping arm`
|
||||||
|
|
||||||
[O-ARM]: https://github.com/rust-lang/rust/labels/O-ARM
|
[O-ARM]: https://github.com/rust-lang/rust/labels/O-ARM
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Emscripten notification group
|
# Emscripten notification group
|
||||||
|
|
||||||
**Github Label:** [O-emscripten] <br>
|
**GitHub Label:** [O-emscripten] <br>
|
||||||
**Ping command:** `@rustbot ping emscripten`
|
**Ping command:** `@rustbot ping emscripten`
|
||||||
|
|
||||||
[O-emscripten]: https://github.com/rust-lang/rust/labels/O-emscripten
|
[O-emscripten]: https://github.com/rust-lang/rust/labels/O-emscripten
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Fuchsia notification group
|
# Fuchsia notification group
|
||||||
|
|
||||||
**Github Label:** [O-fuchsia] <br>
|
**GitHub Label:** [O-fuchsia] <br>
|
||||||
**Ping command:** `@rustbot ping fuchsia`
|
**Ping command:** `@rustbot ping fuchsia`
|
||||||
|
|
||||||
[O-fuchsia]: https://github.com/rust-lang/rust/labels/O-fuchsia
|
[O-fuchsia]: https://github.com/rust-lang/rust/labels/O-fuchsia
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# LoongArch notification group
|
# LoongArch notification group
|
||||||
|
|
||||||
**Github Label:** [O-loongarch] <br>
|
**GitHub Label:** [O-loongarch] <br>
|
||||||
**Ping command:** `@rustbot ping loongarch`
|
**Ping command:** `@rustbot ping loongarch`
|
||||||
|
|
||||||
[O-loongarch]: https://github.com/rust-lang/rust/labels/O-loongarch
|
[O-loongarch]: https://github.com/rust-lang/rust/labels/O-loongarch
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# RISC-V notification group
|
# RISC-V notification group
|
||||||
|
|
||||||
**Github Label:** [O-riscv] <br>
|
**GitHub Label:** [O-riscv] <br>
|
||||||
**Ping command:** `@rustbot ping risc-v`
|
**Ping command:** `@rustbot ping risc-v`
|
||||||
|
|
||||||
[O-riscv]: https://github.com/rust-lang/rust/labels/O-riscv
|
[O-riscv]: https://github.com/rust-lang/rust/labels/O-riscv
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Rust for Linux notification group
|
# Rust for Linux notification group
|
||||||
|
|
||||||
**Github Label:** [A-rust-for-linux] <br>
|
**GitHub Label:** [A-rust-for-linux] <br>
|
||||||
**Ping command:** `@rustbot ping rfl`
|
**Ping command:** `@rustbot ping rfl`
|
||||||
|
|
||||||
[A-rust-for-linux]: https://github.com/rust-lang/rust/labels/A-rust-for-linux
|
[A-rust-for-linux]: https://github.com/rust-lang/rust/labels/A-rust-for-linux
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# WASI notification group
|
# WASI notification group
|
||||||
|
|
||||||
**Github Label:** [O-wasi] <br>
|
**GitHub Label:** [O-wasi] <br>
|
||||||
**Ping command:** `@rustbot ping wasi`
|
**Ping command:** `@rustbot ping wasi`
|
||||||
|
|
||||||
[O-wasi]: https://github.com/rust-lang/rust/labels/O-wasi
|
[O-wasi]: https://github.com/rust-lang/rust/labels/O-wasi
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# WebAssembly (WASM) notification group
|
# WebAssembly (WASM) notification group
|
||||||
|
|
||||||
**Github Label:** [O-wasm] <br>
|
**GitHub Label:** [O-wasm] <br>
|
||||||
**Ping command:** `@rustbot ping wasm`
|
**Ping command:** `@rustbot ping wasm`
|
||||||
|
|
||||||
[O-wasm]: https://github.com/rust-lang/rust/labels/O-wasm
|
[O-wasm]: https://github.com/rust-lang/rust/labels/O-wasm
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Windows notification group
|
# Windows notification group
|
||||||
|
|
||||||
**Github Label:** [O-Windows] <br>
|
**GitHub Label:** [O-Windows] <br>
|
||||||
**Ping command:** `@rustbot ping windows`
|
**Ping command:** `@rustbot ping windows`
|
||||||
|
|
||||||
[O-Windows]: https://github.com/rust-lang/rust/labels/O-Windows
|
[O-Windows]: https://github.com/rust-lang/rust/labels/O-Windows
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,15 @@ also offer more advanced, possibly unsafe, interfaces which allow a higher degre
|
||||||
The implementation is based on LLVM's "offload" project, which is already used by OpenMP to run Fortran or C++ code on GPUs.
|
The implementation is based on LLVM's "offload" project, which is already used by OpenMP to run Fortran or C++ code on GPUs.
|
||||||
While the project is under development, users will need to call other compilers like clang to finish the compilation process.
|
While the project is under development, users will need to call other compilers like clang to finish the compilation process.
|
||||||
|
|
||||||
## High-level design:
|
## High-level compilation design:
|
||||||
We use a single-source, two-pass compilation approach.
|
We use a single-source, two-pass compilation approach.
|
||||||
|
|
||||||
First we compile all functions that should be offloaded for the device (e.g nvptx64, amdgcn-amd-amdhsa, intel in the future). Currently we require cumbersome `#cfg(target_os="")` annotations, but we intend to recognize those in the future based on our offload intrinsic.
|
First we compile all functions that should be offloaded for the device (e.g nvptx64, amdgcn-amd-amdhsa, intel in the future). Currently we require cumbersome `#cfg(target_os="")` annotations, but we intend to recognize those in the future based on our offload intrinsic.
|
||||||
|
This first compilation currently does not leverage rustc's internal Query system, so it will always recompile your kernels at the moment. This should be easy to fix, but we prioritize features and runtime performance improvements at the moment. Please reach out if you want to implement it, though!
|
||||||
|
|
||||||
We then compile the code for the host (e.g. x86-64), where most of the offloading logic happens. On the host side, we generate calls to the openmp offload runtime, to inform it about the layout of the types (a simplified version of the autodiff TypeTrees). We also use the type system to figure out whether kernel arguments have to be moved only to the device (e.g. `&[f32;1024]`), from the device, or both (e.g. `&mut [f64]`). We then launch the kernel, after which we inform the runtime to end this environment and move data back (as far as needed).
|
We then compile the code for the host (e.g. x86-64), where most of the offloading logic happens. On the host side, we generate calls to the openmp offload runtime, to inform it about the layout of the types (a simplified version of the autodiff TypeTrees). We also use the type system to figure out whether kernel arguments have to be moved only to the device (e.g. `&[f32;1024]`), from the device, or both (e.g. `&mut [f64]`). We then launch the kernel, after which we inform the runtime to end this environment and move data back (as far as needed).
|
||||||
|
|
||||||
|
The second pass for the host will load the kernel artifacts from the previous compilation. rustc in general may not "guess" or hardcode the build directory layout, and as such it must be told the path to the kernel artifacts in the second invocation. The logic for this could be integrated into cargo, but it also only requires a trivial cargo wrapper, which we could trivially provide via crates.io till we see larger adoption.
|
||||||
|
|
||||||
|
It might seem tempting to think about a single-source, single pass compilation approach. However, a lot of the rustc frontend (e.g. AST) will drop any dead code (e.g. code behind an inactive `cfg`). Getting the frontend to expand and lower code for two targets naively will result in multiple definitions of the same symbol (and other issues). Trying to teach the whole rustc middle and backend to be aware that any symbol now might contain two implementations is a large undertaking, and it is questionable why we should make the whole compiler more complex, if the alternative is a ~5 line cargo wrapper. We still control the full compilation pipeline and have both host and device code available, therefore there shouldn't be a runtime performance difference between the two approaches.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,7 @@ satisfy/optimize for. For example,
|
||||||
the input programs says they do, and should continue to do so despite the
|
the input programs says they do, and should continue to do so despite the
|
||||||
tremendous amount of change constantly going on.
|
tremendous amount of change constantly going on.
|
||||||
- Integration: a number of other tools need to use the compiler in
|
- Integration: a number of other tools need to use the compiler in
|
||||||
various ways (e.g. `cargo`, `clippy`, `MIRI`) that must be supported.
|
various ways (e.g. `cargo`, `clippy`, `Miri`) that must be supported.
|
||||||
- Compiler stability: the compiler should not crash or fail ungracefully on the
|
- Compiler stability: the compiler should not crash or fail ungracefully on the
|
||||||
stable channel.
|
stable channel.
|
||||||
- Rust stability: the compiler must respect Rust's stability guarantees by not
|
- Rust stability: the compiler must respect Rust's stability guarantees by not
|
||||||
|
|
@ -245,7 +245,7 @@ for different purposes:
|
||||||
values). `MIR` is used for borrow checking and other
|
values). `MIR` is used for borrow checking and other
|
||||||
important dataflow-based checks, such as checking for uninitialized values.
|
important dataflow-based checks, such as checking for uninitialized values.
|
||||||
It is also used for a series of optimizations and for constant evaluation (via
|
It is also used for a series of optimizations and for constant evaluation (via
|
||||||
`MIRI`). Because `MIR` is still generic, we can do a lot of analyses here more
|
`Miri`). Because `MIR` is still generic, we can do a lot of analyses here more
|
||||||
efficiently than after monomorphization.
|
efficiently than after monomorphization.
|
||||||
- `LLVM-IR`: This is the standard form of all input to the LLVM compiler. `LLVM-IR`
|
- `LLVM-IR`: This is the standard form of all input to the LLVM compiler. `LLVM-IR`
|
||||||
is a sort of typed assembly language with lots of annotations. It's
|
is a sort of typed assembly language with lots of annotations. It's
|
||||||
|
|
@ -395,7 +395,7 @@ For more details on bootstrapping, see
|
||||||
- Lexical Analysis: Lex the user program to a stream of tokens
|
- Lexical Analysis: Lex the user program to a stream of tokens
|
||||||
- Guide: [Lexing and Parsing](the-parser.md)
|
- Guide: [Lexing and Parsing](the-parser.md)
|
||||||
- Lexer definition: [`rustc_lexer`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lexer/index.html)
|
- Lexer definition: [`rustc_lexer`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lexer/index.html)
|
||||||
- Main entry point: [`rustc_lexer::cursor::Cursor::advance_token`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lexer/cursor/struct.Cursor.html#method.advance_token)
|
- Main entry point: [`rustc_lexer::Cursor::advance_token`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lexer/struct.Cursor.html#method.advance_token)
|
||||||
- Parsing: Parse the stream of tokens to an Abstract Syntax Tree (AST)
|
- Parsing: Parse the stream of tokens to an Abstract Syntax Tree (AST)
|
||||||
- Guide: [Lexing and Parsing](the-parser.md)
|
- Guide: [Lexing and Parsing](the-parser.md)
|
||||||
- Guide: [Macro Expansion](macro-expansion.md)
|
- Guide: [Macro Expansion](macro-expansion.md)
|
||||||
|
|
|
||||||
|
|
@ -254,8 +254,8 @@ You will typically need to:
|
||||||
An example of introducing such a cross-crate query can be found in commit [`996a185`](https://github.com/rust-lang/rust/commit/996a185) in the `rust-lang/rust` repository.
|
An example of introducing such a cross-crate query can be found in commit [`996a185`](https://github.com/rust-lang/rust/commit/996a185) in the `rust-lang/rust` repository.
|
||||||
|
|
||||||
[rustc_metadata]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/index.html
|
[rustc_metadata]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/index.html
|
||||||
[providers_struct]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/query/struct.Providers.html
|
[providers_struct]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/queries/struct.Providers.html
|
||||||
[extern_providers_struct]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/query/struct.ExternProviders.html
|
[extern_providers_struct]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/queries/struct.ExternProviders.html
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ And parsing requires macro expansion, which in turn may require parsing the outp
|
||||||
|
|
||||||
[AST]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/index.html
|
[AST]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/index.html
|
||||||
[macro expansion]: ./macro-expansion.md
|
[macro expansion]: ./macro-expansion.md
|
||||||
[feature-gate checking]: ./feature-gate-ck.md
|
[feature-gate checking]: ./feature-gate-check.md
|
||||||
[lexing, parsing]: ./the-parser.md
|
[lexing, parsing]: ./the-parser.md
|
||||||
[name resolution]: ./name-resolution.md
|
[name resolution]: ./name-resolution.md
|
||||||
[validation]: ./ast-validation.md
|
[validation]: ./ast-validation.md
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ Most platforms only run the build steps, some run a restricted set of tests;
|
||||||
only a subset run the full suite of tests (see Rust's [platform tiers]).
|
only a subset run the full suite of tests (see Rust's [platform tiers]).
|
||||||
|
|
||||||
Auto jobs are defined in the `auto` section of [`jobs.yml`].
|
Auto jobs are defined in the `auto` section of [`jobs.yml`].
|
||||||
They are executed on the `auto` branch under the `rust-lang/rust` repository,
|
They are executed on the [`automation/bors/auto`][auto] branch under the `rust-lang/rust` repository,
|
||||||
and the final result will be reported via a comment made by bors on the corresponding PR.
|
and the final result will be reported via a comment made by bors on the corresponding PR.
|
||||||
The live results can be seen on [the GitHub Actions workflows page].
|
The live results can be seen on [the GitHub Actions workflows page].
|
||||||
|
|
||||||
|
|
@ -110,6 +110,7 @@ At any given time, at most a single `auto` build is being executed.
|
||||||
Find out more in [Merging PRs serially with bors](#merging-prs-serially-with-bors).
|
Find out more in [Merging PRs serially with bors](#merging-prs-serially-with-bors).
|
||||||
|
|
||||||
[platform tiers]: https://forge.rust-lang.org/release/platform-support.html#rust-platform-support
|
[platform tiers]: https://forge.rust-lang.org/release/platform-support.html#rust-platform-support
|
||||||
|
[auto]: https://github.com/rust-lang/rust/tree/automation/bors/auto
|
||||||
|
|
||||||
### Try builds
|
### Try builds
|
||||||
|
|
||||||
|
|
@ -204,7 +205,7 @@ to help make the perf comparison as fair as possible.
|
||||||
> However, it can be less flexible because you cannot adjust the set of tests
|
> However, it can be less flexible because you cannot adjust the set of tests
|
||||||
> that are exercised this way.
|
> that are exercised this way.
|
||||||
|
|
||||||
Try builds are executed on the `try` branch under the `rust-lang/rust` repository and
|
Try builds are executed on the [`automation/bors/try`][try] branch under the `rust-lang/rust` repository and
|
||||||
their results can be seen on [the GitHub Actions workflows page],
|
their results can be seen on [the GitHub Actions workflows page],
|
||||||
although usually you will be notified of the result by a comment made by bors on
|
although usually you will be notified of the result by a comment made by bors on
|
||||||
the corresponding PR.
|
the corresponding PR.
|
||||||
|
|
@ -213,6 +214,7 @@ Multiple try builds can execute concurrently across different PRs, but there can
|
||||||
a single try build running on a single PR at any given time.
|
a single try build running on a single PR at any given time.
|
||||||
|
|
||||||
[rustc-perf]: https://github.com/rust-lang/rustc-perf
|
[rustc-perf]: https://github.com/rust-lang/rustc-perf
|
||||||
|
[try]: https://github.com/rust-lang/rust/tree/automation/bors/try
|
||||||
|
|
||||||
### Modifying CI jobs
|
### Modifying CI jobs
|
||||||
|
|
||||||
|
|
@ -284,8 +286,8 @@ If all the builders are green, the PR is merged, otherwise the failure is
|
||||||
recorded and the PR will have to be re-approved again.
|
recorded and the PR will have to be re-approved again.
|
||||||
|
|
||||||
Bors doesn’t interact with CI services directly, but it works by pushing the
|
Bors doesn’t interact with CI services directly, but it works by pushing the
|
||||||
merge commit it wants to test to specific branches (like `auto` or `try`), which
|
merge commit it wants to test to specific branches (like `automation/bors/auto` or `automation/bors/try`),
|
||||||
are configured to execute CI checks.
|
which are configured to execute CI checks.
|
||||||
Bors then detects the outcome of the build by listening for either Commit Statuses or Check Runs.
|
Bors then detects the outcome of the build by listening for either Commit Statuses or Check Runs.
|
||||||
Since the merge commit is
|
Since the merge commit is
|
||||||
based on the latest `main` and only one can be tested at the same time, when
|
based on the latest `main` and only one can be tested at the same time, when
|
||||||
|
|
@ -447,8 +449,8 @@ If you want to determine which `bootstrap.toml` settings are used in CI for a
|
||||||
particular job, it is probably easiest to just look at the build log.
|
particular job, it is probably easiest to just look at the build log.
|
||||||
To do this:
|
To do this:
|
||||||
|
|
||||||
1. Go to <https://github.com/rust-lang/rust/actions?query=branch%3Aauto+is%3Asuccess>
|
1. Go to [the Rust CI successful workflow runs page][workflow runs]
|
||||||
to find the most recently successful build, and click on it.
|
and click on the most recent one.
|
||||||
2. Choose the job you are interested in on the left-hand side.
|
2. Choose the job you are interested in on the left-hand side.
|
||||||
3. Click on the gear icon and choose "View raw logs"
|
3. Click on the gear icon and choose "View raw logs"
|
||||||
4. Search for the string "Configure the build"
|
4. Search for the string "Configure the build"
|
||||||
|
|
@ -462,3 +464,4 @@ To do this:
|
||||||
[merge queue]: https://bors.rust-lang.org/queue/rust
|
[merge queue]: https://bors.rust-lang.org/queue/rust
|
||||||
[dist-x86_64-linux]: https://github.com/rust-lang/rust/blob/HEAD/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
|
[dist-x86_64-linux]: https://github.com/rust-lang/rust/blob/HEAD/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
|
||||||
[the GitHub Actions workflows page]: https://github.com/rust-lang/rust/actions
|
[the GitHub Actions workflows page]: https://github.com/rust-lang/rust/actions
|
||||||
|
[workflow runs]: https://github.com/rust-lang/rust/actions?query=branch%3Aautomation%2Fbors%2Fauto+is%3Asuccess
|
||||||
|
|
|
||||||
|
|
@ -48,5 +48,5 @@ This would cause all kinds of issues as the region `'^1_0` refers to a binder at
|
||||||
|
|
||||||
[`Binder`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Binder.html
|
[`Binder`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Binder.html
|
||||||
[`BoundVar`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.BoundVar.html
|
[`BoundVar`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.BoundVar.html
|
||||||
[`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundRegionKind.html
|
[`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.BoundRegionKind.html
|
||||||
[`BoundTyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundTyKind.html
|
[`BoundTyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.BoundTyKind.html
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ As a concrete example, accessing the signature of a function we are type checkin
|
||||||
|
|
||||||
[`liberate_late_bound_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.liberate_late_bound_regions
|
[`liberate_late_bound_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.liberate_late_bound_regions
|
||||||
[representing-types]: param-ty-const-regions.md
|
[representing-types]: param-ty-const-regions.md
|
||||||
[`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundRegionKind.html
|
[`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.BoundRegionKind.html
|
||||||
[`enter_forall`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/struct.InferCtxt.html#method.enter_forall
|
[`enter_forall`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/struct.InferCtxt.html#method.enter_forall
|
||||||
[ch_placeholders_universes]: ../borrow-check/region-inference/placeholders-and-universes.md
|
[ch_placeholders_universes]: ../borrow-check/region-inference/placeholders-and-universes.md
|
||||||
[`instantiate_binder_with_fresh_vars`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/struct.InferCtxt.html#method.instantiate_binder_with_fresh_vars
|
[`instantiate_binder_with_fresh_vars`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/struct.InferCtxt.html#method.instantiate_binder_with_fresh_vars
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ fn foo<'a, 'b, T: 'a>(one: T, two: &'a &'b u32) -> &'b u32 {
|
||||||
[ch_early_late_bound]: ../early-late-parameters.md
|
[ch_early_late_bound]: ../early-late-parameters.md
|
||||||
[ch_binders]: ./binders.md
|
[ch_binders]: ./binders.md
|
||||||
[ch_instantiating_binders]: ./instantiating-binders.md
|
[ch_instantiating_binders]: ./instantiating-binders.md
|
||||||
[`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundRegionKind.html
|
[`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.BoundRegionKind.html
|
||||||
[`RegionKind::EarlyParam`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.RegionKind.html#variant.ReEarlyParam
|
[`RegionKind::EarlyParam`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.RegionKind.html#variant.ReEarlyParam
|
||||||
[`RegionKind::LateParam`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.RegionKind.html#variant.ReLateParam
|
[`RegionKind::LateParam`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.RegionKind.html#variant.ReLateParam
|
||||||
[`ConstKind::Param`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.ConstKind.html#variant.Param
|
[`ConstKind::Param`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.ConstKind.html#variant.Param
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
new_issue = true
|
new_issue = true
|
||||||
exclude_labels = [
|
exclude_labels = [
|
||||||
"A-diagnostics",
|
"A-diagnostics",
|
||||||
|
"C-date-reference-triage",
|
||||||
"C-tracking-issue",
|
"C-tracking-issue",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -84,6 +85,7 @@ does not need reviews. You can request a review using `r? rustc-dev-guide` or \
|
||||||
rustc-dev-guide = [
|
rustc-dev-guide = [
|
||||||
"@BoxyUwU",
|
"@BoxyUwU",
|
||||||
"@jyn514",
|
"@jyn514",
|
||||||
|
"@reddevilmidzy",
|
||||||
"@tshepang",
|
"@tshepang",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![doc(
|
#![doc(
|
||||||
html_root_url = "https://doc.rust-lang.org/nightly/",
|
html_root_url = "https://doc.rust-lang.org/nightly/",
|
||||||
html_playground_url = "https://play.rust-lang.org/"
|
html_playground_url = "https://play.rust-lang.org/"
|
||||||
)]
|
)]
|
||||||
#![feature(ascii_char)]
|
#![feature(ascii_char)]
|
||||||
#![feature(ascii_char_variants)]
|
#![feature(ascii_char_variants)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
#![feature(box_into_inner)]
|
#![feature(box_into_inner)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(file_buffered)]
|
#![feature(file_buffered)]
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
#![feature(macro_metavar_expr)]
|
#![feature(macro_metavar_expr)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||||
#![feature(unwrap_infallible)]
|
#![feature(unwrap_infallible)]
|
||||||
#![recursion_limit = "512"]
|
#![recursion_limit = "512"]
|
||||||
#![allow(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)]
|
#![allow(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)]
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ semver = "1.0"
|
||||||
serde = { version = "1.0.125", features = ["derive"], optional = true }
|
serde = { version = "1.0.125", features = ["derive"], optional = true }
|
||||||
termcolor = "1.1.3"
|
termcolor = "1.1.3"
|
||||||
rustc-hash = "2.0.0"
|
rustc-hash = "2.0.0"
|
||||||
fluent-syntax = "0.12"
|
|
||||||
similar = "2.5.0"
|
similar = "2.5.0"
|
||||||
toml = "0.7.8"
|
toml = "0.7.8"
|
||||||
tempfile = "3.15.0"
|
tempfile = "3.15.0"
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@
|
||||||
//@ ignore-remote
|
//@ ignore-remote
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
#![feature(ascii_char, ascii_char_variants)]
|
#![feature(ascii_char, ascii_char_variants)]
|
||||||
|
|
||||||
extern crate rustc_driver;
|
extern crate rustc_driver;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
#![feature(ascii_char, ascii_char_variants)]
|
#![feature(ascii_char, ascii_char_variants)]
|
||||||
|
|
||||||
extern crate rustc_hir;
|
extern crate rustc_hir;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
|
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
//@ edition: 2024
|
//@ edition: 2024
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
|
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@
|
||||||
//@ ignore-remote
|
//@ ignore-remote
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
|
|
||||||
extern crate rustc_hir;
|
extern crate rustc_hir;
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
|
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
|
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
|
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
|
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
//@ ignore-remote
|
//@ ignore-remote
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
|
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
extern crate rustc_hir;
|
extern crate rustc_hir;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
|
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
|
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@
|
||||||
//@ ignore-remote
|
//@ ignore-remote
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
#![feature(ascii_char, ascii_char_variants)]
|
#![feature(ascii_char, ascii_char_variants)]
|
||||||
|
|
||||||
extern crate rustc_hir;
|
extern crate rustc_hir;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
|
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
||||||
//@ edition: 2024
|
//@ edition: 2024
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
|
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
|
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
|
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
|
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
|
|
||||||
extern crate rustc_hir;
|
extern crate rustc_hir;
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(assert_matches)]
|
|
||||||
|
|
||||||
extern crate rustc_hir;
|
extern crate rustc_hir;
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue