Auto merge of #108237 - GuillaumeGomez:rollup-olxq5dt, r=GuillaumeGomez
Rollup of 5 pull requests Successful merges: - #107766 (Fix json reexports of different items with same name) - #108129 (Correctly handle links starting with whitespace) - #108188 (Change src/etc/vscode_settings.json to always treat ./library as the sysroot source) - #108203 (Fix RPITITs in default trait methods (by assuming projection predicates in param-env)) - #108212 (Download rustfmt regardless of rustc being set in config.toml) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
dc89a803d6
15 changed files with 294 additions and 91 deletions
|
@ -1599,7 +1599,7 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
|
|||
{
|
||||
for arg in fn_output.walk() {
|
||||
if let ty::GenericArgKind::Type(ty) = arg.unpack()
|
||||
&& let ty::Alias(ty::Projection, proj) = ty.kind()
|
||||
&& let ty::Alias(ty::Opaque, proj) = ty.kind()
|
||||
&& tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
|
||||
&& tcx.impl_trait_in_trait_parent(proj.def_id) == fn_def_id.to_def_id()
|
||||
{
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
|||
use crate::mir;
|
||||
use crate::ty::layout::IntegerExt;
|
||||
use crate::ty::{
|
||||
self, ir::TypeFolder, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable,
|
||||
self, ir::TypeFolder, DefIdTree, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable,
|
||||
TypeSuperFoldable,
|
||||
};
|
||||
use crate::ty::{GenericArgKind, SubstsRef};
|
||||
|
@ -865,6 +865,26 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
|
|||
}
|
||||
t
|
||||
}
|
||||
|
||||
fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
|
||||
if let ty::PredicateKind::Clause(clause) = p.kind().skip_binder()
|
||||
&& let ty::Clause::Projection(projection_pred) = clause
|
||||
{
|
||||
p.kind()
|
||||
.rebind(ty::ProjectionPredicate {
|
||||
projection_ty: projection_pred.projection_ty.fold_with(self),
|
||||
// Don't fold the term on the RHS of the projection predicate.
|
||||
// This is because for default trait methods with RPITITs, we
|
||||
// install a `NormalizesTo(Projection(RPITIT) -> Opaque(RPITIT))`
|
||||
// predicate, which would trivially cause a cycle when we do
|
||||
// anything that requires `ParamEnv::with_reveal_all_normalized`.
|
||||
term: projection_pred.term,
|
||||
})
|
||||
.to_predicate(self.tcx)
|
||||
} else {
|
||||
p.super_fold_with(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Ty<'tcx> {
|
||||
|
|
|
@ -339,6 +339,7 @@ pub fn inner_docs(attrs: &[ast::Attribute]) -> bool {
|
|||
fn preprocess_link(link: &str) -> String {
|
||||
let link = link.replace('`', "");
|
||||
let link = link.split('#').next().unwrap();
|
||||
let link = link.trim();
|
||||
let link = link.rsplit('@').next().unwrap();
|
||||
let link = link.strip_suffix("()").unwrap_or(link);
|
||||
let link = link.strip_suffix("{}").unwrap_or(link);
|
||||
|
|
|
@ -90,15 +90,7 @@ enum ProjectionCandidate<'tcx> {
|
|||
/// From an "impl" (or a "pseudo-impl" returned by select)
|
||||
Select(Selection<'tcx>),
|
||||
|
||||
ImplTraitInTrait(ImplTraitInTraitCandidate<'tcx>),
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
enum ImplTraitInTraitCandidate<'tcx> {
|
||||
// The `impl Trait` from a trait function's default body
|
||||
Trait,
|
||||
// A concrete type provided from a trait's `impl Trait` from an impl
|
||||
Impl(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>),
|
||||
ImplTraitInTrait(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>),
|
||||
}
|
||||
|
||||
enum ProjectionCandidateSet<'tcx> {
|
||||
|
@ -1292,17 +1284,6 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
|
|||
let tcx = selcx.tcx();
|
||||
if tcx.def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
|
||||
let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
|
||||
// If we are trying to project an RPITIT with trait's default `Self` parameter,
|
||||
// then we must be within a default trait body.
|
||||
if obligation.predicate.self_ty()
|
||||
== ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.def_id).type_at(0)
|
||||
&& tcx.associated_item(trait_fn_def_id).defaultness(tcx).has_value()
|
||||
{
|
||||
candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
|
||||
ImplTraitInTraitCandidate::Trait,
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
let trait_def_id = tcx.parent(trait_fn_def_id);
|
||||
let trait_substs =
|
||||
|
@ -1313,9 +1294,7 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
|
|||
let _ = selcx.infcx.commit_if_ok(|_| {
|
||||
match selcx.select(&obligation.with(tcx, trait_predicate)) {
|
||||
Ok(Some(super::ImplSource::UserDefined(data))) => {
|
||||
candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
|
||||
ImplTraitInTraitCandidate::Impl(data),
|
||||
));
|
||||
candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data));
|
||||
Ok(())
|
||||
}
|
||||
Ok(None) => {
|
||||
|
@ -1777,18 +1756,9 @@ fn confirm_candidate<'cx, 'tcx>(
|
|||
ProjectionCandidate::Select(impl_source) => {
|
||||
confirm_select_candidate(selcx, obligation, impl_source)
|
||||
}
|
||||
ProjectionCandidate::ImplTraitInTrait(ImplTraitInTraitCandidate::Impl(data)) => {
|
||||
ProjectionCandidate::ImplTraitInTrait(data) => {
|
||||
confirm_impl_trait_in_trait_candidate(selcx, obligation, data)
|
||||
}
|
||||
// If we're projecting an RPITIT for a default trait body, that's just
|
||||
// the same def-id, but as an opaque type (with regular RPIT semantics).
|
||||
ProjectionCandidate::ImplTraitInTrait(ImplTraitInTraitCandidate::Trait) => Progress {
|
||||
term: selcx
|
||||
.tcx()
|
||||
.mk_opaque(obligation.predicate.def_id, obligation.predicate.substs)
|
||||
.into(),
|
||||
obligations: vec![],
|
||||
},
|
||||
};
|
||||
|
||||
// When checking for cycle during evaluation, we compare predicates with
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
#[cfg(not(bootstrap))]
|
||||
use rustc_middle::ty::ir::TypeVisitable;
|
||||
use rustc_middle::ty::{
|
||||
self, Binder, EarlyBinder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt,
|
||||
self, ir::TypeVisitor, Binder, EarlyBinder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt,
|
||||
TypeSuperVisitable,
|
||||
};
|
||||
use rustc_session::config::TraitSolver;
|
||||
use rustc_span::def_id::{DefId, CRATE_DEF_ID};
|
||||
|
@ -136,6 +140,19 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
|
|||
predicates.extend(environment);
|
||||
}
|
||||
|
||||
if tcx.def_kind(def_id) == DefKind::AssocFn
|
||||
&& tcx.associated_item(def_id).container == ty::AssocItemContainer::TraitContainer
|
||||
{
|
||||
let sig = tcx.fn_sig(def_id).subst_identity();
|
||||
sig.visit_with(&mut ImplTraitInTraitFinder {
|
||||
tcx,
|
||||
fn_def_id: def_id,
|
||||
bound_vars: sig.bound_vars(),
|
||||
predicates: &mut predicates,
|
||||
seen: FxHashSet::default(),
|
||||
});
|
||||
}
|
||||
|
||||
let local_did = def_id.as_local();
|
||||
let hir_id = local_did.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id));
|
||||
|
||||
|
@ -222,6 +239,46 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
|
|||
traits::normalize_param_env_or_error(tcx, unnormalized_env, cause)
|
||||
}
|
||||
|
||||
/// Walk through a function type, gathering all RPITITs and installing a
|
||||
/// `NormalizesTo(Projection(RPITIT) -> Opaque(RPITIT))` predicate into the
|
||||
/// predicates list. This allows us to observe that an RPITIT projects to
|
||||
/// its corresponding opaque within the body of a default-body trait method.
|
||||
struct ImplTraitInTraitFinder<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
predicates: &'a mut Vec<Predicate<'tcx>>,
|
||||
fn_def_id: DefId,
|
||||
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
|
||||
seen: FxHashSet<DefId>,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
|
||||
if let ty::Alias(ty::Projection, alias_ty) = *ty.kind()
|
||||
&& self.tcx.def_kind(alias_ty.def_id) == DefKind::ImplTraitPlaceholder
|
||||
&& self.tcx.impl_trait_in_trait_parent(alias_ty.def_id) == self.fn_def_id
|
||||
&& self.seen.insert(alias_ty.def_id)
|
||||
{
|
||||
self.predicates.push(
|
||||
ty::Binder::bind_with_vars(
|
||||
ty::ProjectionPredicate {
|
||||
projection_ty: alias_ty,
|
||||
term: self.tcx.mk_alias(ty::Opaque, alias_ty).into(),
|
||||
},
|
||||
self.bound_vars,
|
||||
)
|
||||
.to_predicate(self.tcx),
|
||||
);
|
||||
|
||||
for bound in self.tcx.item_bounds(alias_ty.def_id).subst_iter(self.tcx, alias_ty.substs)
|
||||
{
|
||||
bound.visit_with(self);
|
||||
}
|
||||
}
|
||||
|
||||
ty.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Elaborate the environment.
|
||||
///
|
||||
/// Collect a list of `Predicate`'s used for building the `ParamEnv`. Adds `TypeWellFormedFromEnv`'s
|
||||
|
|
|
@ -1315,15 +1315,6 @@ impl Config {
|
|||
} else {
|
||||
RustfmtState::Unavailable
|
||||
};
|
||||
} else {
|
||||
// If using a system toolchain for bootstrapping, see if that has rustfmt available.
|
||||
let host = config.build;
|
||||
let rustfmt_path = config.initial_rustc.with_file_name(exe("rustfmt", host));
|
||||
let bin_root = config.out.join(host.triple).join("stage0");
|
||||
if !rustfmt_path.starts_with(&bin_root) {
|
||||
// Using a system-provided toolchain; we shouldn't download rustfmt.
|
||||
*config.initial_rustfmt.borrow_mut() = RustfmtState::SystemToolchain(rustfmt_path);
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we've reached the end of our configuration, infer the
|
||||
|
|
|
@ -29,6 +29,7 @@ pub enum Profile {
|
|||
static SETTINGS_HASHES: &[&str] = &[
|
||||
"ea67e259dedf60d4429b6c349a564ffcd1563cf41c920a856d1f5b16b4701ac8",
|
||||
"56e7bf011c71c5d81e0bf42e84938111847a810eee69d906bba494ea90b51922",
|
||||
"af1b5efe196aed007577899db9dae15d6dbc923d6fa42fa0934e68617ba9bbe0",
|
||||
];
|
||||
static VSCODE_SETTINGS: &str = include_str!("../etc/vscode_settings.json");
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"rust-analyzer.check.invocationLocation": "root",
|
||||
"rust-analyzer.check.invocationStrategy": "once",
|
||||
"rust-analyzer.checkOnSave.overrideCommand": [
|
||||
"rust-analyzer.check.overrideCommand": [
|
||||
"python3",
|
||||
"x.py",
|
||||
"check",
|
||||
|
@ -23,6 +23,6 @@
|
|||
"check",
|
||||
"--json-output"
|
||||
],
|
||||
"rust-analyzer.cargo.sysroot": "./build/host/stage0-sysroot",
|
||||
"rust-analyzer.cargo.sysrootSrc": "./library",
|
||||
"rust-analyzer.rustc.source": "./Cargo.toml"
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ impl JsonRenderer<'_> {
|
|||
Some(UrlFragment::UserWritten(_)) | None => *page_id,
|
||||
};
|
||||
|
||||
(link.clone(), from_item_id(id.into(), self.tcx))
|
||||
(link.clone(), id_from_item_default(id.into(), self.tcx))
|
||||
})
|
||||
.collect();
|
||||
let docs = item.attrs.collapsed_doc_value();
|
||||
|
@ -50,7 +50,8 @@ impl JsonRenderer<'_> {
|
|||
.collect();
|
||||
let span = item.span(self.tcx);
|
||||
let visibility = item.visibility(self.tcx);
|
||||
let clean::Item { name, attrs: _, kind: _, item_id, cfg: _, .. } = item;
|
||||
let clean::Item { name, item_id, .. } = item;
|
||||
let id = id_from_item(&item, self.tcx);
|
||||
let inner = match *item.kind {
|
||||
clean::KeywordItem => return None,
|
||||
clean::StrippedItem(ref inner) => {
|
||||
|
@ -69,7 +70,7 @@ impl JsonRenderer<'_> {
|
|||
_ => from_clean_item(item, self.tcx),
|
||||
};
|
||||
Some(Item {
|
||||
id: from_item_id_with_name(item_id, self.tcx, name),
|
||||
id,
|
||||
crate_id: item_id.krate().as_u32(),
|
||||
name: name.map(|sym| sym.to_string()),
|
||||
span: span.and_then(|span| self.convert_span(span)),
|
||||
|
@ -107,7 +108,7 @@ impl JsonRenderer<'_> {
|
|||
Some(ty::Visibility::Public) => Visibility::Public,
|
||||
Some(ty::Visibility::Restricted(did)) if did.is_crate_root() => Visibility::Crate,
|
||||
Some(ty::Visibility::Restricted(did)) => Visibility::Restricted {
|
||||
parent: from_item_id(did.into(), self.tcx),
|
||||
parent: id_from_item_default(did.into(), self.tcx),
|
||||
path: self.tcx.def_path(did).to_string_no_crate_verbose(),
|
||||
},
|
||||
}
|
||||
|
@ -204,21 +205,42 @@ impl FromWithTcx<clean::TypeBindingKind> for TypeBindingKind {
|
|||
}
|
||||
}
|
||||
|
||||
/// It generates an ID as follows:
|
||||
///
|
||||
/// `CRATE_ID:ITEM_ID[:NAME_ID]` (if there is no name, NAME_ID is not generated).
|
||||
pub(crate) fn from_item_id(item_id: ItemId, tcx: TyCtxt<'_>) -> Id {
|
||||
from_item_id_with_name(item_id, tcx, None)
|
||||
#[inline]
|
||||
pub(crate) fn id_from_item_default(item_id: ItemId, tcx: TyCtxt<'_>) -> Id {
|
||||
id_from_item_inner(item_id, tcx, None, None)
|
||||
}
|
||||
|
||||
// FIXME: this function (and appending the name at the end of the ID) should be removed when
|
||||
// reexports are not inlined anymore for json format. It should be done in #93518.
|
||||
pub(crate) fn from_item_id_with_name(item_id: ItemId, tcx: TyCtxt<'_>, name: Option<Symbol>) -> Id {
|
||||
struct DisplayDefId<'a>(DefId, TyCtxt<'a>, Option<Symbol>);
|
||||
/// It generates an ID as follows:
|
||||
///
|
||||
/// `CRATE_ID:ITEM_ID[:NAME_ID][-EXTRA]`:
|
||||
/// * If there is no `name`, `NAME_ID` is not generated.
|
||||
/// * If there is no `extra`, `EXTRA` is not generated.
|
||||
///
|
||||
/// * `name` is the item's name if available (it's not for impl blocks for example).
|
||||
/// * `extra` is used for reexports: it contains the ID of the reexported item. It is used to allow
|
||||
/// to have items with the same name but different types to both appear in the generated JSON.
|
||||
pub(crate) fn id_from_item_inner(
|
||||
item_id: ItemId,
|
||||
tcx: TyCtxt<'_>,
|
||||
name: Option<Symbol>,
|
||||
extra: Option<&Id>,
|
||||
) -> Id {
|
||||
struct DisplayDefId<'a, 'b>(DefId, TyCtxt<'a>, Option<&'b Id>, Option<Symbol>);
|
||||
|
||||
impl<'a> fmt::Display for DisplayDefId<'a> {
|
||||
impl<'a, 'b> fmt::Display for DisplayDefId<'a, 'b> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let DisplayDefId(def_id, tcx, name) = self;
|
||||
let DisplayDefId(def_id, tcx, extra, name) = self;
|
||||
// We need this workaround because primitive types' DefId actually refers to
|
||||
// their parent module, which isn't present in the output JSON items. So
|
||||
// instead, we directly get the primitive symbol and convert it to u32 to
|
||||
// generate the ID.
|
||||
let s;
|
||||
let extra = if let Some(e) = extra {
|
||||
s = format!("-{}", e.0);
|
||||
&s
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let name = match name {
|
||||
Some(name) => format!(":{}", name.as_u32()),
|
||||
None => {
|
||||
|
@ -240,18 +262,33 @@ pub(crate) fn from_item_id_with_name(item_id: ItemId, tcx: TyCtxt<'_>, name: Opt
|
|||
}
|
||||
}
|
||||
};
|
||||
write!(f, "{}:{}{}", self.0.krate.as_u32(), u32::from(self.0.index), name)
|
||||
write!(f, "{}:{}{name}{extra}", def_id.krate.as_u32(), u32::from(def_id.index))
|
||||
}
|
||||
}
|
||||
|
||||
match item_id {
|
||||
ItemId::DefId(did) => Id(format!("{}", DisplayDefId(did, tcx, name))),
|
||||
ItemId::Blanket { for_, impl_id } => {
|
||||
Id(format!("b:{}-{}", DisplayDefId(impl_id, tcx, None), DisplayDefId(for_, tcx, name)))
|
||||
}
|
||||
ItemId::Auto { for_, trait_ } => {
|
||||
Id(format!("a:{}-{}", DisplayDefId(trait_, tcx, None), DisplayDefId(for_, tcx, name)))
|
||||
ItemId::DefId(did) => Id(format!("{}", DisplayDefId(did, tcx, extra, name))),
|
||||
ItemId::Blanket { for_, impl_id } => Id(format!(
|
||||
"b:{}-{}",
|
||||
DisplayDefId(impl_id, tcx, None, None),
|
||||
DisplayDefId(for_, tcx, extra, name)
|
||||
)),
|
||||
ItemId::Auto { for_, trait_ } => Id(format!(
|
||||
"a:{}-{}",
|
||||
DisplayDefId(trait_, tcx, None, None),
|
||||
DisplayDefId(for_, tcx, extra, name)
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn id_from_item(item: &clean::Item, tcx: TyCtxt<'_>) -> Id {
|
||||
match *item.kind {
|
||||
clean::ItemKind::ImportItem(ref import) => {
|
||||
let extra =
|
||||
import.source.did.map(ItemId::from).map(|i| id_from_item_inner(i, tcx, None, None));
|
||||
id_from_item_inner(item.item_id, tcx, item.name, extra.as_ref())
|
||||
}
|
||||
_ => id_from_item_inner(item.item_id, tcx, item.name, None),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -525,7 +562,7 @@ impl FromWithTcx<clean::Path> for Path {
|
|||
fn from_tcx(path: clean::Path, tcx: TyCtxt<'_>) -> Path {
|
||||
Path {
|
||||
name: path.whole_name(),
|
||||
id: from_item_id(path.def_id().into(), tcx),
|
||||
id: id_from_item_default(path.def_id().into(), tcx),
|
||||
args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))),
|
||||
}
|
||||
}
|
||||
|
@ -702,7 +739,7 @@ impl FromWithTcx<clean::Import> for Import {
|
|||
Import {
|
||||
source: import.source.path.whole_name(),
|
||||
name,
|
||||
id: import.source.did.map(ItemId::from).map(|i| from_item_id(i, tcx)),
|
||||
id: import.source.did.map(ItemId::from).map(|i| id_from_item_default(i, tcx)),
|
||||
glob,
|
||||
}
|
||||
}
|
||||
|
@ -791,7 +828,7 @@ fn ids(items: impl IntoIterator<Item = clean::Item>, tcx: TyCtxt<'_>) -> Vec<Id>
|
|||
items
|
||||
.into_iter()
|
||||
.filter(|x| !x.is_stripped() && !x.is_keyword())
|
||||
.map(|i| from_item_id_with_name(i.item_id, tcx, i.name))
|
||||
.map(|i| id_from_item(&i, tcx))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
@ -801,12 +838,10 @@ fn ids_keeping_stripped(
|
|||
) -> Vec<Option<Id>> {
|
||||
items
|
||||
.into_iter()
|
||||
.map(|i| {
|
||||
if !i.is_stripped() && !i.is_keyword() {
|
||||
Some(from_item_id_with_name(i.item_id, tcx, i.name))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.map(
|
||||
|i| {
|
||||
if !i.is_stripped() && !i.is_keyword() { Some(id_from_item(&i, tcx)) } else { None }
|
||||
},
|
||||
)
|
||||
.collect()
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ use crate::docfs::PathError;
|
|||
use crate::error::Error;
|
||||
use crate::formats::cache::Cache;
|
||||
use crate::formats::FormatRenderer;
|
||||
use crate::json::conversions::{from_item_id, from_item_id_with_name, IntoWithTcx};
|
||||
use crate::json::conversions::{id_from_item, id_from_item_default, IntoWithTcx};
|
||||
use crate::{clean, try_err};
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -58,7 +58,7 @@ impl<'tcx> JsonRenderer<'tcx> {
|
|||
.map(|i| {
|
||||
let item = &i.impl_item;
|
||||
self.item(item.clone()).unwrap();
|
||||
from_item_id_with_name(item.item_id, self.tcx, item.name)
|
||||
id_from_item(&item, self.tcx)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
|
@ -89,7 +89,7 @@ impl<'tcx> JsonRenderer<'tcx> {
|
|||
|
||||
if item.item_id.is_local() || is_primitive_impl {
|
||||
self.item(item.clone()).unwrap();
|
||||
Some(from_item_id_with_name(item.item_id, self.tcx, item.name))
|
||||
Some(id_from_item(&item, self.tcx))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -150,7 +150,6 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
|
|||
// Flatten items that recursively store other items
|
||||
item.kind.inner_items().for_each(|i| self.item(i.clone()).unwrap());
|
||||
|
||||
let name = item.name;
|
||||
let item_id = item.item_id;
|
||||
if let Some(mut new_item) = self.convert_item(item) {
|
||||
let can_be_ignored = match new_item.inner {
|
||||
|
@ -193,10 +192,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
|
|||
| types::ItemEnum::Macro(_)
|
||||
| types::ItemEnum::ProcMacro(_) => false,
|
||||
};
|
||||
let removed = self
|
||||
.index
|
||||
.borrow_mut()
|
||||
.insert(from_item_id_with_name(item_id, self.tcx, name), new_item.clone());
|
||||
let removed = self.index.borrow_mut().insert(new_item.id.clone(), new_item.clone());
|
||||
|
||||
// FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check
|
||||
// to make sure the items are unique. The main place this happens is when an item, is
|
||||
|
@ -207,6 +203,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
|
|||
if !can_be_ignored {
|
||||
assert_eq!(old_item, new_item);
|
||||
}
|
||||
trace!("replaced {:?}\nwith {:?}", old_item, new_item);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,7 +243,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
|
|||
.chain(&self.cache.external_paths)
|
||||
.map(|(&k, &(ref path, kind))| {
|
||||
(
|
||||
from_item_id(k.into(), self.tcx),
|
||||
id_from_item_default(k.into(), self.tcx),
|
||||
types::ItemSummary {
|
||||
crate_id: k.krate.as_u32(),
|
||||
path: path.iter().map(|s| s.to_string()).collect(),
|
||||
|
|
|
@ -884,7 +884,8 @@ fn preprocess_link(
|
|||
let mut parts = stripped.split('#');
|
||||
|
||||
let link = parts.next().unwrap();
|
||||
if link.trim().is_empty() {
|
||||
let link = link.trim();
|
||||
if link.is_empty() {
|
||||
// This is an anchor to an element of the current page, nothing to do in here!
|
||||
return None;
|
||||
}
|
||||
|
@ -897,7 +898,7 @@ fn preprocess_link(
|
|||
// Parse and strip the disambiguator from the link, if present.
|
||||
let (disambiguator, path_str, link_text) = match Disambiguator::from_str(link) {
|
||||
Ok(Some((d, path, link_text))) => (Some(d), path.trim(), link_text.trim()),
|
||||
Ok(None) => (None, link.trim(), link.trim()),
|
||||
Ok(None) => (None, link, link),
|
||||
Err((err_msg, relative_range)) => {
|
||||
// Only report error if we would not have ignored this link. See issue #83859.
|
||||
if !should_ignore_link_with_disambiguators(link) {
|
||||
|
|
25
tests/rustdoc-json/reexport/same_name_different_types.rs
Normal file
25
tests/rustdoc-json/reexport/same_name_different_types.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
// Regression test for <https://github.com/rust-lang/rust/issues/107677>.
|
||||
|
||||
#![feature(no_core)]
|
||||
#![no_core]
|
||||
|
||||
pub mod nested {
|
||||
// @set foo_struct = "$.index[*][?(@.docs == 'Foo the struct')].id"
|
||||
|
||||
/// Foo the struct
|
||||
pub struct Foo {}
|
||||
|
||||
// @set foo_fn = "$.index[*][?(@.docs == 'Foo the function')].id"
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
/// Foo the function
|
||||
pub fn Foo() {}
|
||||
}
|
||||
|
||||
// @ismany "$.index[*][?(@.inner.name == 'Foo' && @.kind == 'import')].inner.id" $foo_fn $foo_struct
|
||||
// @ismany "$.index[*][?(@.inner.name == 'Bar' && @.kind == 'import')].inner.id" $foo_fn $foo_struct
|
||||
|
||||
// @count "$.index[*][?(@.inner.name == 'Foo' && @.kind == 'import')]" 2
|
||||
pub use nested::Foo;
|
||||
// @count "$.index[*][?(@.inner.name == 'Bar' && @.kind == 'import')]" 2
|
||||
pub use Foo as Bar;
|
28
tests/rustdoc/issue-107995.rs
Normal file
28
tests/rustdoc/issue-107995.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
// Regression test for <https://github.com/rust-lang/rust/issues/107995>.
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
// @has 'foo/fn.foo.html'
|
||||
// @has - '//*[@class="docblock"]//a[@href="fn.bar.html"]' 'bar`'
|
||||
/// A foo, see also [ bar`]
|
||||
pub fn foo() {}
|
||||
|
||||
// @has 'foo/fn.bar.html'
|
||||
// @has - '//*[@class="docblock"]' 'line Path line'
|
||||
// @has - '//*[@class="docblock"]//a[@href="struct.Path.html"]' 'Path'
|
||||
#[doc = "line ["]
|
||||
#[doc = "Path"]
|
||||
#[doc = "] line"]
|
||||
pub fn bar() {}
|
||||
|
||||
// @has 'foo/fn.another.html'
|
||||
// @has - '//*[@class="docblock"]//a[@href="struct.Path.html"]' 'Path'
|
||||
/// [ `Path`]
|
||||
pub fn another() {}
|
||||
|
||||
// @has 'foo/fn.last.html'
|
||||
// @has - '//*[@class="docblock"]//a[@href="struct.Path.html"]' 'Path'
|
||||
/// [ Path`]
|
||||
pub fn last() {}
|
||||
|
||||
pub struct Path;
|
66
tests/ui/async-await/in-trait/async-default-fn-overridden.rs
Normal file
66
tests/ui/async-await/in-trait/async-default-fn-overridden.rs
Normal file
|
@ -0,0 +1,66 @@
|
|||
// run-pass
|
||||
// edition:2021
|
||||
|
||||
#![feature(async_fn_in_trait)]
|
||||
//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
trait AsyncTrait {
|
||||
async fn default_impl() {
|
||||
assert!(false);
|
||||
}
|
||||
|
||||
async fn call_default_impl() {
|
||||
Self::default_impl().await
|
||||
}
|
||||
}
|
||||
|
||||
struct AsyncType;
|
||||
|
||||
impl AsyncTrait for AsyncType {
|
||||
async fn default_impl() {
|
||||
// :)
|
||||
}
|
||||
}
|
||||
|
||||
async fn async_main() {
|
||||
// Should not assert false
|
||||
AsyncType::call_default_impl().await;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
// Implementation Details Below...
|
||||
|
||||
use std::pin::Pin;
|
||||
use std::task::*;
|
||||
|
||||
pub fn noop_waker() -> Waker {
|
||||
let raw = RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE);
|
||||
|
||||
// SAFETY: the contracts for RawWaker and RawWakerVTable are upheld
|
||||
unsafe { Waker::from_raw(raw) }
|
||||
}
|
||||
|
||||
const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop);
|
||||
|
||||
unsafe fn noop_clone(_p: *const ()) -> RawWaker {
|
||||
RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE)
|
||||
}
|
||||
|
||||
unsafe fn noop(_p: *const ()) {}
|
||||
|
||||
fn main() {
|
||||
let mut fut = async_main();
|
||||
|
||||
// Poll loop, just to test the future...
|
||||
let waker = noop_waker();
|
||||
let ctx = &mut Context::from_waker(&waker);
|
||||
|
||||
loop {
|
||||
match unsafe { Pin::new_unchecked(&mut fut).poll(ctx) } {
|
||||
Poll::Pending => {}
|
||||
Poll::Ready(()) => break,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/async-default-fn-overridden.rs:4:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
Loading…
Add table
Reference in a new issue