mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-30 04:56:25 +03:00
Auto merge of #156736 - GuillaumeGomez:primitive-assoc-methods, r=fmease
Fix jump to def link generation on primitive type associated methods Fixes rust-lang/rust#156707. Interestingly enough, the inference fails on primitive type, so instead I go around a bit by generating a `PrimitiveType` and then tweak a bit the `href` generation. r? @fmease
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
use rustc_metadata::rendered_const;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::fast_reject::SimplifiedType;
|
||||
use rustc_middle::ty::{self, TyCtxt, Visibility};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, Visibility};
|
||||
use rustc_resolve::rustdoc::{
|
||||
DocFragment, add_doc_fragment, attrs_to_doc_fragments, inner_docs, span_of_fragments,
|
||||
};
|
||||
@@ -1758,6 +1758,40 @@ pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_ty(ty: Ty<'_>) -> Option<Self> {
|
||||
match ty.kind() {
|
||||
ty::Array(..) => Some(Self::Array),
|
||||
ty::Bool => Some(Self::Bool),
|
||||
ty::Char => Some(Self::Char),
|
||||
ty::FnDef(..) | ty::FnPtr(..) => Some(Self::Fn),
|
||||
ty::Int(int) => Some(Self::from(*int)),
|
||||
ty::Uint(uint) => Some(Self::from(*uint)),
|
||||
ty::Float(float) => Some(Self::from(*float)),
|
||||
ty::Never => Some(Self::Never),
|
||||
ty::Pat(..) => Some(Self::Pat),
|
||||
ty::RawPtr(..) => Some(Self::RawPointer),
|
||||
ty::Ref(..) => Some(Self::Reference),
|
||||
ty::Slice(..) => Some(Self::Slice),
|
||||
ty::Str => Some(Self::Str),
|
||||
ty::Tuple(elems) if elems.is_empty() => Some(Self::Unit),
|
||||
ty::Tuple(_) => Some(Self::Tuple),
|
||||
ty::Adt(..)
|
||||
| ty::Alias(..)
|
||||
| ty::Bound(..)
|
||||
| ty::Closure(..)
|
||||
| ty::Coroutine(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
| ty::CoroutineWitness(..)
|
||||
| ty::Dynamic(..)
|
||||
| ty::Error(..)
|
||||
| ty::Foreign(..)
|
||||
| ty::Infer(..)
|
||||
| ty::Param(..)
|
||||
| ty::Placeholder(..)
|
||||
| ty::UnsafeBinder(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
|
||||
use PrimitiveType::*;
|
||||
use ty::{FloatTy, IntTy, UintTy};
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::{self, Display, Write};
|
||||
use std::iter::{self, once};
|
||||
use std::slice;
|
||||
use std::{iter, slice};
|
||||
|
||||
use itertools::{Either, Itertools};
|
||||
use rustc_abi::ExternAbi;
|
||||
@@ -434,27 +433,33 @@ fn generate_item_def_id_path(
|
||||
|
||||
let tcx = cx.tcx();
|
||||
let crate_name = tcx.crate_name(def_id.krate);
|
||||
let mut prim = None;
|
||||
|
||||
// No need to try to infer the actual parent item if it's not an associated item from the `impl`
|
||||
// block.
|
||||
if def_id != original_def_id && matches!(tcx.def_kind(def_id), DefKind::Impl { .. }) {
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
def_id = infcx
|
||||
let ty = tcx.type_of(def_id);
|
||||
let ty = infcx
|
||||
.at(&ObligationCause::dummy(), tcx.param_env(def_id))
|
||||
.query_normalize(ty::Binder::dummy(
|
||||
tcx.type_of(def_id).instantiate_identity().skip_norm_wip(),
|
||||
))
|
||||
.map(|resolved| infcx.resolve_vars_if_possible(resolved.value))
|
||||
.ok()
|
||||
.and_then(|normalized| normalized.skip_binder().ty_adt_def())
|
||||
.map(|adt| adt.did())
|
||||
.unwrap_or(def_id);
|
||||
.query_normalize(ty::Binder::dummy(ty.instantiate_identity().skip_norm_wip()))
|
||||
.map(|resolved| infcx.resolve_vars_if_possible(resolved.value).skip_binder())
|
||||
.unwrap_or(ty.skip_binder());
|
||||
if let Some(new_def_id) = ty.ty_adt_def().map(|adt| adt.did()) {
|
||||
def_id = new_def_id;
|
||||
} else {
|
||||
prim = PrimitiveType::from_ty(ty);
|
||||
}
|
||||
}
|
||||
|
||||
let relative = clean::inline::item_relative_path(tcx, def_id);
|
||||
let fqp: Vec<Symbol> = once(crate_name).chain(relative).collect();
|
||||
|
||||
let shortty = ItemType::from_def_id(def_id, tcx);
|
||||
let mut fqp = vec![crate_name];
|
||||
let shortty = if let Some(prim) = prim {
|
||||
fqp.push(prim.as_sym());
|
||||
ItemType::Primitive
|
||||
} else {
|
||||
fqp.append(&mut clean::inline::item_relative_path(tcx, def_id));
|
||||
ItemType::from_def_id(def_id, tcx)
|
||||
};
|
||||
let module_fqp = to_module_fqp(shortty, &fqp);
|
||||
|
||||
let (parts, is_absolute) = url_parts(cx.cache(), def_id, module_fqp, &cx.current)?;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// Checks that links to primitive types methods work.
|
||||
// Regression test for <https://github.com/rust-lang/rust/issues/156707>.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
//@ compile-flags: -Zunstable-options --generate-link-to-definition
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
//@ has 'src/foo/prim-method.rs.html'
|
||||
|
||||
fn scope() {
|
||||
//@ has - '//a[@href="{{channel}}/core/primitive.usize.html#method.saturating_add"]' 'saturating_add'
|
||||
let _ = 0usize.saturating_add(1);
|
||||
//@ has - '//a[@href="{{channel}}/core/primitive.bool.html#method.then_some"]' 'then_some'
|
||||
let _ = false.then_some(());
|
||||
}
|
||||
Reference in New Issue
Block a user