diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 66c3904af963b..5743f086f89b4 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -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() { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index a34ee1a99a178..ca46cf29919f8 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -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> 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> { diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index 0c4b4bc3f6265..5e4b66018e42e 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -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); diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 9b3249e58e8db..1c66fb257ebb5 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -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 diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 2c50b766d21f6..f1af0073e4da9 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -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>, + fn_def_id: DefId, + bound_vars: &'tcx ty::List, + seen: FxHashSet, +} + +impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow { + 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 diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index cd027a4abb7fa..56f96734bbbc7 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -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 diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index 2b613ad50ee48..a027139df2397 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -29,6 +29,7 @@ pub enum Profile { static SETTINGS_HASHES: &[&str] = &[ "ea67e259dedf60d4429b6c349a564ffcd1563cf41c920a856d1f5b16b4701ac8", "56e7bf011c71c5d81e0bf42e84938111847a810eee69d906bba494ea90b51922", + "af1b5efe196aed007577899db9dae15d6dbc923d6fa42fa0934e68617ba9bbe0", ]; static VSCODE_SETTINGS: &str = include_str!("../etc/vscode_settings.json"); diff --git a/src/etc/vscode_settings.json b/src/etc/vscode_settings.json index 04c34ce91c0b7..dd01bfaa7252d 100644 --- a/src/etc/vscode_settings.json +++ b/src/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" } diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index bd95ec18650b3..d5e9010eb4ed9 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -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 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) -> Id { - struct DisplayDefId<'a>(DefId, TyCtxt<'a>, Option); +/// 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, + extra: Option<&Id>, +) -> Id { + struct DisplayDefId<'a, 'b>(DefId, TyCtxt<'a>, Option<&'b Id>, Option); - 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 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 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, tcx: TyCtxt<'_>) -> Vec 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> { 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() } diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index e3788fe57d013..08bceb59cfde6 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -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(), diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index d2c6e7ab02499..920a3b22f25a2 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -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) { diff --git a/tests/rustdoc-json/reexport/same_name_different_types.rs b/tests/rustdoc-json/reexport/same_name_different_types.rs new file mode 100644 index 0000000000000..2314a4eb90940 --- /dev/null +++ b/tests/rustdoc-json/reexport/same_name_different_types.rs @@ -0,0 +1,25 @@ +// Regression test for . + +#![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; diff --git a/tests/rustdoc/issue-107995.rs b/tests/rustdoc/issue-107995.rs new file mode 100644 index 0000000000000..1273e4fdd12eb --- /dev/null +++ b/tests/rustdoc/issue-107995.rs @@ -0,0 +1,28 @@ +// Regression test for . + +#![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; diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs new file mode 100644 index 0000000000000..0fd1a2703db99 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs @@ -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, + } + } +} diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.stderr b/tests/ui/async-await/in-trait/async-default-fn-overridden.stderr new file mode 100644 index 0000000000000..61a826258d09f --- /dev/null +++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.stderr @@ -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 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted +