Skip to content

Commit a1dba63

Browse files
Fix jump to def link generation on primitive type associated methods
1 parent 1ea1171 commit a1dba63

5 files changed

Lines changed: 80 additions & 9 deletions

File tree

compiler/rustc_codegen_gcc/src/intrinsic/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1352,7 +1352,9 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>(
13521352
dest: PlaceRef<'tcx, RValue<'gcc>>,
13531353
) {
13541354
if !bx.sess().panic_strategy().unwinds() {
1355-
bx.call(bx.type_void(), None, None, try_func, &[data], None, None);
1355+
let param_type = bx.u8_type.make_pointer();
1356+
let fn_type = bx.context.new_function_pointer_type(None, bx.type_void(), &[param_type], false);
1357+
bx.call(fn_type, None, None, try_func, &[data], None, None);
13561358
// Return 0 unconditionally from the intrinsic call;
13571359
// we can never unwind.
13581360
OperandValue::Immediate(bx.const_i32(0)).store(bx, dest);

src/librustdoc/clean/types.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc_index::IndexVec;
2020
use rustc_metadata::rendered_const;
2121
use rustc_middle::span_bug;
2222
use rustc_middle::ty::fast_reject::SimplifiedType;
23-
use rustc_middle::ty::{self, TyCtxt, Visibility};
23+
use rustc_middle::ty::{self, Ty, TyCtxt, Visibility};
2424
use rustc_resolve::rustdoc::{
2525
DocFragment, add_doc_fragment, attrs_to_doc_fragments, inner_docs, span_of_fragments,
2626
};
@@ -1758,6 +1758,40 @@ impl PrimitiveType {
17581758
}
17591759
}
17601760

1761+
pub(crate) fn from_ty(ty: Ty<'_>) -> Option<Self> {
1762+
match ty.kind() {
1763+
ty::Array(..) => Some(Self::Array),
1764+
ty::Bool => Some(Self::Bool),
1765+
ty::Char => Some(Self::Char),
1766+
ty::FnDef(..) | ty::FnPtr(..) => Some(Self::Fn),
1767+
ty::Int(int) => Some(Self::from(*int)),
1768+
ty::Uint(uint) => Some(Self::from(*uint)),
1769+
ty::Float(float) => Some(Self::from(*float)),
1770+
ty::Never => Some(Self::Never),
1771+
ty::Pat(..) => Some(Self::Pat),
1772+
ty::RawPtr(..) => Some(Self::RawPointer),
1773+
ty::Ref(..) => Some(Self::Reference),
1774+
ty::Slice(..) => Some(Self::Slice),
1775+
ty::Str => Some(Self::Str),
1776+
ty::Tuple(elems) if elems.is_empty() => Some(Self::Unit),
1777+
ty::Tuple(_) => Some(Self::Tuple),
1778+
ty::Adt(..)
1779+
| ty::Alias(..)
1780+
| ty::Bound(..)
1781+
| ty::Closure(..)
1782+
| ty::Coroutine(..)
1783+
| ty::CoroutineClosure(..)
1784+
| ty::CoroutineWitness(..)
1785+
| ty::Dynamic(..)
1786+
| ty::Error(..)
1787+
| ty::Foreign(..)
1788+
| ty::Infer(..)
1789+
| ty::Param(..)
1790+
| ty::Placeholder(..)
1791+
| ty::UnsafeBinder(..) => None,
1792+
}
1793+
}
1794+
17611795
pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
17621796
use PrimitiveType::*;
17631797
use ty::{FloatTy, IntTy, UintTy};

src/librustdoc/html/format.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -434,27 +434,38 @@ fn generate_item_def_id_path(
434434

435435
let tcx = cx.tcx();
436436
let crate_name = tcx.crate_name(def_id.krate);
437+
let mut prim = None;
437438

438439
// No need to try to infer the actual parent item if it's not an associated item from the `impl`
439440
// block.
440441
if def_id != original_def_id && matches!(tcx.def_kind(def_id), DefKind::Impl { .. }) {
441442
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
442-
def_id = infcx
443+
let ty = tcx.type_of(def_id);
444+
if let Some(new_def_id) = infcx
443445
.at(&ObligationCause::dummy(), tcx.param_env(def_id))
444446
.query_normalize(ty::Binder::dummy(
445-
tcx.type_of(def_id).instantiate_identity().skip_norm_wip(),
447+
ty.instantiate_identity().skip_norm_wip(),
446448
))
447449
.map(|resolved| infcx.resolve_vars_if_possible(resolved.value))
448450
.ok()
449451
.and_then(|normalized| normalized.skip_binder().ty_adt_def())
450452
.map(|adt| adt.did())
451-
.unwrap_or(def_id);
453+
{
454+
def_id = new_def_id;
455+
} else {
456+
// If the parent is an impl of a primitive type, it'll fail because primitives aren't
457+
// ADT, so instead we use `type_of` to get the actual primitive type.
458+
prim = PrimitiveType::from_ty(ty.skip_binder());
459+
}
452460
}
453461

454-
let relative = clean::inline::item_relative_path(tcx, def_id);
455-
let fqp: Vec<Symbol> = once(crate_name).chain(relative).collect();
456-
457-
let shortty = ItemType::from_def_id(def_id, tcx);
462+
let (fqp, shortty): (Vec<Symbol>, ItemType) = match prim {
463+
Some(prim) => (vec![crate_name, prim.as_sym()], ItemType::Primitive),
464+
None => {
465+
let relative = clean::inline::item_relative_path(tcx, def_id);
466+
(once(crate_name).chain(relative).collect(), ItemType::from_def_id(def_id, tcx))
467+
}
468+
};
458469
let module_fqp = to_module_fqp(shortty, &fqp);
459470

460471
let (parts, is_absolute) = url_parts(cx.cache(), def_id, module_fqp, &cx.current)?;

src/librustdoc/html/span_map.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,14 @@ impl<'tcx> SpanMapVisitor<'tcx> {
127127
fn link_for_def(&self, def_id: DefId) -> LinkFromSrc {
128128
if def_id.is_local() {
129129
LinkFromSrc::Local(rustc_span(def_id, self.tcx))
130+
// // If this is the `DefId` of a function...
131+
// } else if self.tcx.type_of(def_id).skip_binder().is_fn()
132+
// // coming from an impl block...
133+
// && let Some(parent_def_id) = self.tcx.opt_parent(def_id)
134+
// // implemented on a primitive, then it's not an external item but a primitive.
135+
// && self.tcx.type_of(parent_def_id).skip_binder().is_primitive()
136+
// {
137+
// LinkFromSrc::Primitive(def_id)
130138
} else {
131139
LinkFromSrc::External(def_id)
132140
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Checks that links to primitive types methods work.
2+
// Regression test for <https://github.com/rust-lang/rust/issues/156707>.
3+
4+
// ignore-tidy-linelength
5+
//@ compile-flags: -Zunstable-options --generate-link-to-definition
6+
7+
#![crate_name = "foo"]
8+
9+
//@ has 'src/foo/prim-method.rs.html'
10+
11+
fn scope() {
12+
//@ has - '//a[@href="{{channel}}/core/primitive.usize.html#method.saturating_add"]' 'saturating_add'
13+
let _ = 0usize.saturating_add(1);
14+
//@ has - '//a[@href="{{channel}}/core/primitive.bool.html#method.then_some"]' 'then_some'
15+
let _ = false.then_some(());
16+
}

0 commit comments

Comments
 (0)