Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion compiler/rustc_const_eval/src/const_eval/type_info.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use rustc_abi::FieldIdx;
use rustc_ast::Mutability;
use rustc_hir::LangItem;
use rustc_middle::mir::interpret::{CtfeProvenance, Scalar};
use rustc_middle::span_bug;
Expand Down Expand Up @@ -103,12 +104,19 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
let (variant, _variant_place) = downcast(sym::Str)?;
variant
}
ty::Ref(_, ty, mutability) => {
let (variant, variant_place) = downcast(sym::Reference)?;
let reference_place =
self.project_field(&variant_place, FieldIdx::ZERO)?;
self.write_reference_type_info(reference_place, *ty, *mutability)?;

variant
}
ty::Adt(_, _)
| ty::Foreign(_)
| ty::Pat(_, _)
| ty::Slice(_)
| ty::RawPtr(..)
| ty::Ref(..)
| ty::FnDef(..)
| ty::FnPtr(..)
| ty::UnsafeBinder(..)
Expand Down Expand Up @@ -279,4 +287,29 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
}
interp_ok(())
}

pub(crate) fn write_reference_type_info(
&mut self,
place: impl Writeable<'tcx, CtfeProvenance>,
ty: Ty<'tcx>,
mutability: Mutability,
) -> InterpResult<'tcx> {
// Iterate over all fields of `type_info::Reference`.
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 {
// Write the `TypeId` of the reference's inner type to the `ty` field.
sym::pointee => self.write_type_id(ty, &field_place)?,
// Write the boolean representing the reference's mutability to the `mutable` field.
sym::mutable => {
self.write_scalar(Scalar::from_bool(mutability.is_mut()), &field_place)?
}
other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"),
}
}
interp_ok(())
}
}
2 changes: 2 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ symbols! {
RefCell,
RefCellRef,
RefCellRefMut,
Reference,
Relaxed,
Release,
Result,
Expand Down Expand Up @@ -1521,6 +1522,7 @@ symbols! {
must_use,
mut_preserve_binding_mode_2024,
mut_ref,
mutable,
naked,
naked_asm,
naked_functions,
Expand Down
13 changes: 13 additions & 0 deletions library/core/src/mem/type_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ pub enum TypeKind {
Float(Float),
/// String slice type.
Str(Str),
/// References.
Reference(Reference),
/// FIXME(#146922): add all the common types
Other,
}
Expand Down Expand Up @@ -133,3 +135,14 @@ pub struct Float {
pub struct Str {
// No additional information to provide for now.
}

/// Compile-time type information about references.
#[derive(Debug)]
#[non_exhaustive]
#[unstable(feature = "type_info", issue = "146922")]
pub struct Reference {
/// The type of the value being referred to.
pub pointee: TypeId,
/// Whether this reference is mutable or not.
pub mutable: bool,
}
32 changes: 31 additions & 1 deletion library/coretests/tests/mem/type_info.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::any::TypeId;
use std::any::{Any, TypeId};
use std::mem::type_info::{Type, TypeKind};

#[test]
Expand Down Expand Up @@ -95,3 +95,33 @@ fn test_primitives() {
let Type { kind: Str(_ty), size, .. } = (const { Type::of::<str>() }) else { panic!() };
assert_eq!(size, None);
}

#[test]
fn test_references() {
// Immutable reference.
match const { Type::of::<&u8>() }.kind {
TypeKind::Reference(reference) => {
assert_eq!(reference.pointee, TypeId::of::<u8>());
assert!(!reference.mutable);
}
_ => unreachable!(),
}

// Mutable pointer.
match const { Type::of::<&mut u64>() }.kind {
TypeKind::Reference(reference) => {
assert_eq!(reference.pointee, TypeId::of::<u64>());
assert!(reference.mutable);
}
_ => unreachable!(),
}

// Wide pointer.
match const { Type::of::<&dyn Any>() }.kind {
TypeKind::Reference(reference) => {
assert_eq!(reference.pointee, TypeId::of::<dyn Any>());
assert!(!reference.mutable);
}
_ => unreachable!(),
}
}
7 changes: 7 additions & 0 deletions src/bootstrap/src/core/build_steps/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,13 @@ impl Step for Rustc {
// see https://github.com/rust-lang/rust/pull/122066#issuecomment-1983049222
// If there is any bug, please comment out the next line.
cargo.rustdocflag("--generate-link-to-definition");
// FIXME: Currently, `--generate-macro-expansion` option is buggy in `beta` rustdoc. To
// allow CI to pass, we only enable the option in stage 2 and higher.
// cfg(bootstrap)
// ^ Adding this so it's not forgotten when the new release is done.
if builder.top_stage > 1 {
cargo.rustdocflag("--generate-macro-expansion");
}

compile::rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
cargo.arg("-Zskip-rustdoc-fingerprint");
Expand Down
32 changes: 25 additions & 7 deletions src/librustdoc/passes/collect_intra_doc_links.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use std::fmt::Display;
use std::mem;
use std::ops::Range;

use rustc_ast::attr::AttributeExt;
use rustc_ast::util::comments::may_have_doc_links;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::intern::Interned;
Expand Down Expand Up @@ -1062,20 +1061,21 @@ fn preprocessed_markdown_links(s: &str) -> Vec<PreprocessedMarkdownLink> {
impl LinkCollector<'_, '_> {
#[instrument(level = "debug", skip_all)]
fn resolve_links(&mut self, item: &Item) {
let tcx = self.cx.tcx;
if !self.cx.document_private()
&& let Some(def_id) = item.item_id.as_def_id()
&& let Some(def_id) = def_id.as_local()
&& !self.cx.tcx.effective_visibilities(()).is_exported(def_id)
&& !tcx.effective_visibilities(()).is_exported(def_id)
&& !has_primitive_or_keyword_or_attribute_docs(&item.attrs.other_attrs)
{
// Skip link resolution for non-exported items.
return;
}

let mut insert_links = |item_id, doc: &str| {
let module_id = match self.cx.tcx.def_kind(item_id) {
DefKind::Mod if item.inner_docs(self.cx.tcx) => item_id,
_ => find_nearest_parent_module(self.cx.tcx, item_id).unwrap(),
let module_id = match tcx.def_kind(item_id) {
DefKind::Mod if item.inner_docs(tcx) => item_id,
_ => find_nearest_parent_module(tcx, item_id).unwrap(),
};
for md_link in preprocessed_markdown_links(&doc) {
let link = self.resolve_link(&doc, item, item_id, module_id, &md_link);
Expand Down Expand Up @@ -1108,15 +1108,33 @@ impl LinkCollector<'_, '_> {

// Also resolve links in the note text of `#[deprecated]`.
for attr in &item.attrs.other_attrs {
let Some(note_sym) = attr.deprecation_note() else { continue };
let rustc_hir::Attribute::Parsed(rustc_hir::attrs::AttributeKind::Deprecation {
span,
deprecation,
}) = attr
else {
continue;
};
let Some(note_sym) = deprecation.note else { continue };
let note = note_sym.as_str();

if !may_have_doc_links(note) {
continue;
}

debug!("deprecated_note={note}");
insert_links(item.item_id.expect_def_id(), note)
// When resolving an intra-doc link inside a deprecation note that is on an inlined
// `use` statement, we need to use the `def_id` of the `use` statement, not the
// inlined item.
// <https://github.com/rust-lang/rust/pull/151120>
let item_id = if let Some(inline_stmt_id) = item.inline_stmt_id
&& item.span(tcx).is_none_or(|item_span| !item_span.inner().contains(*span))
{
inline_stmt_id.to_def_id()
} else {
item.item_id.expect_def_id()
};
insert_links(item_id, note)
}
}

Expand Down
7 changes: 4 additions & 3 deletions tests/mir-opt/unreachable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,11 @@ fn as_match() {
// CHECK: bb1: {
// CHECK: [[eq:_.*]] = Ne({{.*}}, const 1_isize);
// CHECK-NEXT: assume(move [[eq]]);
// CHECK-NEXT: goto -> bb2;
// CHECK: bb2: {
// CHECK-NEXT: goto -> [[return:bb.*]];
// CHECK: [[return]]: {
// CHECK-NOT: {{bb.*}}: {
// CHECK: return;
// CHECK: bb3: {
// CHECK: {{bb.*}}: {
// CHECK-NEXT: unreachable;
match empty() {
Some(_x) => match _x {},
Expand Down
8 changes: 4 additions & 4 deletions tests/mir-opt/unreachable_enum_branching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ struct Plop {
fn simple() {
// CHECK-LABEL: fn simple(
// CHECK: [[discr:_.*]] = discriminant(
// CHECK: switchInt(move [[discr]]) -> [0: [[unreachable:bb.*]], 1: [[unreachable]], 2: bb1, otherwise: [[unreachable]]];
// CHECK: switchInt(move [[discr]]) -> [0: [[unreachable:bb.*]], 1: [[unreachable]], 2: {{bb.*}}, otherwise: [[unreachable]]];
// CHECK: [[unreachable]]: {
// CHECK-NEXT: unreachable;
match Test1::C {
Expand All @@ -63,7 +63,7 @@ fn simple() {
fn custom_discriminant() {
// CHECK-LABEL: fn custom_discriminant(
// CHECK: [[discr:_.*]] = discriminant(
// CHECK: switchInt(move [[discr]]) -> [4: bb3, 5: bb2, otherwise: [[unreachable:bb.*]]];
// CHECK: switchInt(move [[discr]]) -> [4: {{bb.*}}, 5: {{bb.*}}, otherwise: [[unreachable:bb.*]]];
// CHECK: [[unreachable]]: {
// CHECK-NEXT: unreachable;
match Test2::D {
Expand All @@ -76,7 +76,7 @@ fn custom_discriminant() {
fn otherwise_t1() {
// CHECK-LABEL: fn otherwise_t1(
// CHECK: [[discr:_.*]] = discriminant(
// CHECK: switchInt(move [[discr]]) -> [0: bb5, 1: bb5, 2: bb1, otherwise: [[unreachable:bb.*]]];
// CHECK: switchInt(move [[discr]]) -> [0: {{bb.*}}, 1: {{bb.*}}, 2: {{bb.*}}, otherwise: [[unreachable:bb.*]]];
// CHECK: [[unreachable]]: {
// CHECK-NEXT: unreachable;
match Test1::C {
Expand All @@ -90,7 +90,7 @@ fn otherwise_t1() {
fn otherwise_t2() {
// CHECK-LABEL: fn otherwise_t2(
// CHECK: [[discr:_.*]] = discriminant(
// CHECK: switchInt(move [[discr]]) -> [4: bb2, 5: bb1, otherwise: [[unreachable:bb.*]]];
// CHECK: switchInt(move [[discr]]) -> [4: {{bb.*}}, 5: {{bb.*}}, otherwise: [[unreachable:bb.*]]];
// CHECK: [[unreachable]]: {
// CHECK-NEXT: unreachable;
match Test2::D {
Expand Down
11 changes: 11 additions & 0 deletions tests/rustdoc-html/intra-doc/ice-deprecated-note-on-reexport.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// This test ensures that the intra-doc link in `deprecated` note is resolved at the correct
// location (ie in the current crate and not in the reexported item's location/crate) and
// therefore doesn't crash.
//
// This is a regression test for <https://github.com/rust-lang/rust/issues/151028>.

#![crate_name = "foo"]

#[deprecated(note = "use [`std::mem::forget`]")]
#[doc(inline)]
pub use std::mem::drop;
7 changes: 1 addition & 6 deletions tests/ui/closures/2229_closure_analysis/capture-enums.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//@ edition:2021

#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]

enum Info {
Point(i32, i32, String),
Expand All @@ -14,9 +15,6 @@ fn multi_variant_enum() {
let meta = Info::Meta("meta".into(), vec);

let c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
//~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|| {
//~^ ERROR First Pass analysis includes:
//~| ERROR Min Capture analysis includes:
Expand Down Expand Up @@ -48,9 +46,6 @@ fn single_variant_enum() {
let point = SingleVariant::Point(10, -10, "1".into());

let c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
//~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|| {
//~^ ERROR First Pass analysis includes:
//~| ERROR Min Capture analysis includes:
Expand Down
Loading
Loading