mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Auto merge of #101652 - Dylan-DPC:rollup-f4atky0, r=Dylan-DPC
Rollup of 6 pull requests Successful merges: - #101578 (remove bound var hack in `resolve`) - #101606 (doc: fix minor typo) - #101614 (Equate fn outputs when inferring RPITIT hidden types) - #101631 (rustdoc: avoid cleaning modules with duplicate names) - #101635 (Move `Queries::new` out of the macro) - #101641 (Update browser-ui-test version to 0.9.8) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
1463688700
@ -48,7 +48,7 @@ cfg_if! {
|
||||
/// the native atomic types.
|
||||
/// You should use this type through the `AtomicU64`, `AtomicUsize`, etc, type aliases
|
||||
/// as it's not intended to be used separately.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Atomic<T: Copy>(Cell<T>);
|
||||
|
||||
impl<T: Copy> Atomic<T> {
|
||||
|
@ -1202,14 +1202,11 @@ rustc_queries! {
|
||||
}
|
||||
}
|
||||
|
||||
query codegen_fulfill_obligation(
|
||||
query codegen_select_candidate(
|
||||
key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)
|
||||
) -> Result<&'tcx ImplSource<'tcx, ()>, traits::CodegenObligationError> {
|
||||
cache_on_disk_if { true }
|
||||
desc { |tcx|
|
||||
"checking if `{}` fulfills its obligations",
|
||||
tcx.def_path_str(key.1.def_id())
|
||||
}
|
||||
desc { |tcx| "computing candidate for `{}`", key.1 }
|
||||
}
|
||||
|
||||
/// Return all `impl` blocks in the current crate.
|
||||
|
@ -1024,7 +1024,7 @@ pub enum MethodViolationCode {
|
||||
UndispatchableReceiver(Option<Span>),
|
||||
}
|
||||
|
||||
/// These are the error cases for `codegen_fulfill_obligation`.
|
||||
/// These are the error cases for `codegen_select_candidate`.
|
||||
#[derive(Copy, Clone, Debug, Hash, HashStable, Encodable, Decodable)]
|
||||
pub enum CodegenObligationError {
|
||||
/// Ambiguity can happen when monomorphizing during trans
|
||||
|
@ -35,7 +35,7 @@ fn custom_coerce_unsize_info<'tcx>(
|
||||
substs: tcx.mk_substs_trait(source_ty, &[target_ty.into()]),
|
||||
});
|
||||
|
||||
match tcx.codegen_fulfill_obligation((ty::ParamEnv::reveal_all(), trait_ref)) {
|
||||
match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), trait_ref)) {
|
||||
Ok(traits::ImplSource::UserDefined(traits::ImplSourceUserDefinedData {
|
||||
impl_def_id,
|
||||
..
|
||||
|
@ -5,7 +5,7 @@
|
||||
use crate::keys::Key;
|
||||
use crate::{on_disk_cache, Queries};
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::sync::Lock;
|
||||
use rustc_data_structures::sync::{AtomicU64, Lock};
|
||||
use rustc_errors::{Diagnostic, Handler};
|
||||
use rustc_middle::dep_graph::{
|
||||
self, DepKind, DepKindStruct, DepNode, DepNodeIndex, SerializedDepNodeIndex,
|
||||
@ -499,9 +499,28 @@ macro_rules! define_queries {
|
||||
}
|
||||
}
|
||||
|
||||
use crate::{ExternProviders, OnDiskCache, Providers};
|
||||
|
||||
impl<'tcx> Queries<'tcx> {
|
||||
pub fn new(
|
||||
local_providers: Providers,
|
||||
extern_providers: ExternProviders,
|
||||
on_disk_cache: Option<OnDiskCache<'tcx>>,
|
||||
) -> Self {
|
||||
Queries {
|
||||
local_providers: Box::new(local_providers),
|
||||
extern_providers: Box::new(extern_providers),
|
||||
on_disk_cache,
|
||||
jobs: AtomicU64::new(1),
|
||||
..Queries::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! define_queries_struct {
|
||||
(
|
||||
input: ($(([$($modifiers:tt)*] [$($attr:tt)*] [$name:ident]))*)) => {
|
||||
#[derive(Default)]
|
||||
pub struct Queries<'tcx> {
|
||||
local_providers: Box<Providers>,
|
||||
extern_providers: Box<ExternProviders>,
|
||||
@ -514,20 +533,6 @@ macro_rules! define_queries_struct {
|
||||
}
|
||||
|
||||
impl<'tcx> Queries<'tcx> {
|
||||
pub fn new(
|
||||
local_providers: Providers,
|
||||
extern_providers: ExternProviders,
|
||||
on_disk_cache: Option<OnDiskCache<'tcx>>,
|
||||
) -> Self {
|
||||
Queries {
|
||||
local_providers: Box::new(local_providers),
|
||||
extern_providers: Box::new(extern_providers),
|
||||
on_disk_cache,
|
||||
jobs: AtomicU64::new(1),
|
||||
$($name: Default::default()),*
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn try_collect_active_jobs(
|
||||
&'tcx self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
|
@ -18,7 +18,7 @@ use rustc_middle::ty::{self, TyCtxt};
|
||||
/// obligations *could be* resolved if we wanted to.
|
||||
///
|
||||
/// This also expects that `trait_ref` is fully normalized.
|
||||
pub fn codegen_fulfill_obligation<'tcx>(
|
||||
pub fn codegen_select_candidate<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
(param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>),
|
||||
) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> {
|
||||
|
@ -971,7 +971,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
|
||||
*providers = ty::query::Providers {
|
||||
specialization_graph_of: specialize::specialization_graph_provider,
|
||||
specializes: specialize::specializes,
|
||||
codegen_fulfill_obligation: codegen::codegen_fulfill_obligation,
|
||||
codegen_select_candidate: codegen::codegen_select_candidate,
|
||||
own_existential_vtable_entries,
|
||||
vtable_entries,
|
||||
vtable_trait_upcasting_coercion_new_vptr_slot,
|
||||
|
@ -3,113 +3,11 @@ use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::traits::CodegenObligationError;
|
||||
use rustc_middle::ty::subst::SubstsRef;
|
||||
use rustc_middle::ty::{
|
||||
self, Binder, Instance, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
|
||||
};
|
||||
use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitable};
|
||||
use rustc_span::{sym, DUMMY_SP};
|
||||
use rustc_trait_selection::traits;
|
||||
use traits::{translate_substs, Reveal};
|
||||
|
||||
use rustc_data_structures::sso::SsoHashSet;
|
||||
use std::collections::btree_map::Entry;
|
||||
use std::collections::BTreeMap;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
// FIXME(#86795): `BoundVarsCollector` here should **NOT** be used
|
||||
// outside of `resolve_associated_item`. It's just to address #64494,
|
||||
// #83765, and #85848 which are creating bound types/regions that lose
|
||||
// their `Binder` *unintentionally*.
|
||||
// It's ideal to remove `BoundVarsCollector` and just use
|
||||
// `ty::Binder::*` methods but we use this stopgap until we figure out
|
||||
// the "real" fix.
|
||||
struct BoundVarsCollector<'tcx> {
|
||||
binder_index: ty::DebruijnIndex,
|
||||
vars: BTreeMap<u32, ty::BoundVariableKind>,
|
||||
// We may encounter the same variable at different levels of binding, so
|
||||
// this can't just be `Ty`
|
||||
visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>,
|
||||
}
|
||||
|
||||
impl<'tcx> BoundVarsCollector<'tcx> {
|
||||
fn new() -> Self {
|
||||
BoundVarsCollector {
|
||||
binder_index: ty::INNERMOST,
|
||||
vars: BTreeMap::new(),
|
||||
visited: SsoHashSet::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn into_vars(self, tcx: TyCtxt<'tcx>) -> &'tcx ty::List<ty::BoundVariableKind> {
|
||||
let max = self.vars.iter().map(|(k, _)| *k).max().unwrap_or(0);
|
||||
for i in 0..max {
|
||||
if let None = self.vars.get(&i) {
|
||||
panic!("Unknown variable: {:?}", i);
|
||||
}
|
||||
}
|
||||
|
||||
tcx.mk_bound_variable_kinds(self.vars.into_iter().map(|(_, v)| v))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
|
||||
type BreakTy = ();
|
||||
|
||||
fn visit_binder<T: TypeVisitable<'tcx>>(
|
||||
&mut self,
|
||||
t: &Binder<'tcx, T>,
|
||||
) -> ControlFlow<Self::BreakTy> {
|
||||
self.binder_index.shift_in(1);
|
||||
let result = t.super_visit_with(self);
|
||||
self.binder_index.shift_out(1);
|
||||
result
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if t.outer_exclusive_binder() < self.binder_index
|
||||
|| !self.visited.insert((self.binder_index, t))
|
||||
{
|
||||
return ControlFlow::CONTINUE;
|
||||
}
|
||||
match *t.kind() {
|
||||
ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
|
||||
match self.vars.entry(bound_ty.var.as_u32()) {
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(ty::BoundVariableKind::Ty(bound_ty.kind));
|
||||
}
|
||||
Entry::Occupied(entry) => match entry.get() {
|
||||
ty::BoundVariableKind::Ty(_) => {}
|
||||
_ => bug!("Conflicting bound vars"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
_ => (),
|
||||
};
|
||||
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match *r {
|
||||
ty::ReLateBound(index, br) if index == self.binder_index => {
|
||||
match self.vars.entry(br.var.as_u32()) {
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(ty::BoundVariableKind::Region(br.kind));
|
||||
}
|
||||
Entry::Occupied(entry) => match entry.get() {
|
||||
ty::BoundVariableKind::Region(_) => {}
|
||||
_ => bug!("Conflicting bound vars"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
_ => (),
|
||||
};
|
||||
|
||||
r.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_instance<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>,
|
||||
@ -201,19 +99,14 @@ fn resolve_associated_item<'tcx>(
|
||||
|
||||
let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
|
||||
|
||||
// See FIXME on `BoundVarsCollector`.
|
||||
let mut bound_vars_collector = BoundVarsCollector::new();
|
||||
trait_ref.visit_with(&mut bound_vars_collector);
|
||||
let trait_binder = ty::Binder::bind_with_vars(trait_ref, bound_vars_collector.into_vars(tcx));
|
||||
let vtbl = match tcx.codegen_fulfill_obligation((param_env, trait_binder)) {
|
||||
let vtbl = match tcx.codegen_select_candidate((param_env, ty::Binder::dummy(trait_ref))) {
|
||||
Ok(vtbl) => vtbl,
|
||||
Err(CodegenObligationError::Ambiguity) => {
|
||||
let reported = tcx.sess.delay_span_bug(
|
||||
tcx.def_span(trait_item_id),
|
||||
&format!(
|
||||
"encountered ambiguity selecting `{:?}` during codegen, presuming due to \
|
||||
"encountered ambiguity selecting `{trait_ref:?}` during codegen, presuming due to \
|
||||
overflow or prior type error",
|
||||
trait_binder
|
||||
),
|
||||
);
|
||||
return Err(reported);
|
||||
|
@ -295,12 +295,26 @@ pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>(
|
||||
// type would be more appropriate. In other places we have a `Vec<Span>`
|
||||
// corresponding to their `Vec<Predicate>`, but we don't have that here.
|
||||
// Fixing this would improve the output of test `issue-83765.rs`.
|
||||
let sub_result = infcx
|
||||
let mut result = infcx
|
||||
.at(&cause, param_env)
|
||||
.sup(trait_fty, impl_fty)
|
||||
.map(|infer_ok| ocx.register_infer_ok_obligations(infer_ok));
|
||||
|
||||
if let Err(terr) = sub_result {
|
||||
// HACK(RPITIT): #101614. When we are trying to infer the hidden types for
|
||||
// RPITITs, we need to equate the output tys instead of just subtyping. If
|
||||
// we just use `sup` above, we'll end up `&'static str <: _#1t`, which causes
|
||||
// us to infer `_#1t = #'_#2r str`, where `'_#2r` is unconstrained, which gets
|
||||
// fixed up to `ReEmpty`, and which is certainly not what we want.
|
||||
if trait_fty.has_infer_types() {
|
||||
result = result.and_then(|()| {
|
||||
infcx
|
||||
.at(&cause, param_env)
|
||||
.eq(trait_sig.output(), impl_sig.output())
|
||||
.map(|infer_ok| ocx.register_infer_ok_obligations(infer_ok))
|
||||
});
|
||||
}
|
||||
|
||||
if let Err(terr) = result {
|
||||
debug!("sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty);
|
||||
|
||||
let (impl_err_span, trait_err_span) =
|
||||
@ -445,6 +459,7 @@ pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>(
|
||||
region
|
||||
}
|
||||
});
|
||||
debug!(%ty);
|
||||
collected_tys.insert(def_id, ty);
|
||||
}
|
||||
Err(err) => {
|
||||
|
@ -116,7 +116,7 @@
|
||||
//! Threads are able to have associated names for identification purposes. By default, spawned
|
||||
//! threads are unnamed. To specify a name for a thread, build the thread with [`Builder`] and pass
|
||||
//! the desired thread name to [`Builder::name`]. To retrieve the thread name from within the
|
||||
//! thread, use [`Thread::name`]. A couple examples of where the name of a thread gets used:
|
||||
//! thread, use [`Thread::name`]. A couple of examples where the name of a thread gets used:
|
||||
//!
|
||||
//! * If a panic occurs in a named thread, the thread name will be printed in the panic message.
|
||||
//! * The thread name is provided to the OS where applicable (e.g., `pthread_setname_np` in
|
||||
|
@ -1 +1 @@
|
||||
0.9.7
|
||||
0.9.8
|
@ -50,14 +50,23 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
|
||||
let mut inserted = FxHashSet::default();
|
||||
items.extend(doc.foreigns.iter().map(|(item, renamed)| {
|
||||
let item = clean_maybe_renamed_foreign_item(cx, item, *renamed);
|
||||
if let Some(name) = item.name {
|
||||
if let Some(name) = item.name && !item.attrs.lists(sym::doc).has_word(sym::hidden) {
|
||||
inserted.insert((item.type_(), name));
|
||||
}
|
||||
item
|
||||
}));
|
||||
items.extend(doc.mods.iter().map(|x| {
|
||||
inserted.insert((ItemType::Module, x.name));
|
||||
clean_doc_module(x, cx)
|
||||
items.extend(doc.mods.iter().filter_map(|x| {
|
||||
if !inserted.insert((ItemType::Module, x.name)) {
|
||||
return None;
|
||||
}
|
||||
let item = clean_doc_module(x, cx);
|
||||
if item.attrs.lists(sym::doc).has_word(sym::hidden) {
|
||||
// Hidden modules are stripped at a later stage.
|
||||
// If a hidden module has the same name as a visible one, we want
|
||||
// to keep both of them around.
|
||||
inserted.remove(&(ItemType::Module, x.name));
|
||||
}
|
||||
Some(item)
|
||||
}));
|
||||
|
||||
// Split up imports from all other items.
|
||||
@ -72,7 +81,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
|
||||
}
|
||||
let v = clean_maybe_renamed_item(cx, item, *renamed);
|
||||
for item in &v {
|
||||
if let Some(name) = item.name {
|
||||
if let Some(name) = item.name && !item.attrs.lists(sym::doc).has_word(sym::hidden) {
|
||||
inserted.insert((item.type_(), name));
|
||||
}
|
||||
}
|
||||
|
@ -164,8 +164,20 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
self.inside_public_path &= self.cx.tcx.visibility(def_id).is_public();
|
||||
for &i in m.item_ids {
|
||||
let item = self.cx.tcx.hir().item(i);
|
||||
if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
|
||||
continue;
|
||||
}
|
||||
self.visit_item(item, None, &mut om);
|
||||
}
|
||||
for &i in m.item_ids {
|
||||
let item = self.cx.tcx.hir().item(i);
|
||||
// To match the way import precedence works, visit glob imports last.
|
||||
// Later passes in rustdoc will de-duplicate by name and kind, so if glob-
|
||||
// imported items appear last, then they'll be the ones that get discarded.
|
||||
if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
|
||||
self.visit_item(item, None, &mut om);
|
||||
}
|
||||
}
|
||||
self.inside_public_path = orig_inside_public_path;
|
||||
om
|
||||
}
|
||||
|
20
src/test/rustdoc/glob-shadowing-const.rs
Normal file
20
src/test/rustdoc/glob-shadowing-const.rs
Normal file
@ -0,0 +1,20 @@
|
||||
// https://github.com/rust-lang/rust/pull/83872#issuecomment-820101008
|
||||
#![crate_name="foo"]
|
||||
|
||||
mod sub4 {
|
||||
/// 0
|
||||
pub const X: usize = 0;
|
||||
pub mod inner {
|
||||
pub use super::*;
|
||||
/// 1
|
||||
pub const X: usize = 1;
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(inline)]
|
||||
pub use sub4::inner::*;
|
||||
|
||||
// @has 'foo/index.html'
|
||||
// @has - '//div[@class="item-right docblock-short"]' '1'
|
||||
// @!has - '//div[@class="item-right docblock-short"]' '0'
|
||||
fn main() { assert_eq!(X, 1); }
|
86
src/test/rustdoc/glob-shadowing.rs
Normal file
86
src/test/rustdoc/glob-shadowing.rs
Normal file
@ -0,0 +1,86 @@
|
||||
// @has 'glob_shadowing/index.html'
|
||||
// @count - '//div[@class="item-left module-item"]' 6
|
||||
// @!has - '//div[@class="item-right docblock-short"]' 'sub1::describe'
|
||||
// @has - '//div[@class="item-right docblock-short"]' 'sub2::describe'
|
||||
|
||||
// @!has - '//div[@class="item-right docblock-short"]' 'sub1::describe2'
|
||||
|
||||
// @!has - '//div[@class="item-right docblock-short"]' 'sub1::prelude'
|
||||
// @has - '//div[@class="item-right docblock-short"]' 'mod::prelude'
|
||||
|
||||
// @has - '//div[@class="item-right docblock-short"]' 'sub1::Foo (struct)'
|
||||
// @has - '//div[@class="item-right docblock-short"]' 'mod::Foo (function)'
|
||||
|
||||
// @has - '//div[@class="item-right docblock-short"]' 'sub4::inner::X'
|
||||
|
||||
// @has 'glob_shadowing/fn.describe.html'
|
||||
// @has - '//div[@class="docblock"]' 'sub2::describe'
|
||||
|
||||
mod sub1 {
|
||||
// this should be shadowed by sub2::describe
|
||||
/// sub1::describe
|
||||
pub fn describe() -> &'static str {
|
||||
"sub1::describe"
|
||||
}
|
||||
|
||||
// this should be shadowed by mod::prelude
|
||||
/// sub1::prelude
|
||||
pub mod prelude {
|
||||
}
|
||||
|
||||
// this should *not* be shadowed, because sub1::Foo and mod::Foo are in different namespaces
|
||||
/// sub1::Foo (struct)
|
||||
pub struct Foo;
|
||||
|
||||
// this should be shadowed,
|
||||
// because both sub1::describe2 and sub3::describe2 are from glob reexport
|
||||
/// sub1::describe2
|
||||
pub fn describe2() -> &'static str {
|
||||
"sub1::describe2"
|
||||
}
|
||||
}
|
||||
|
||||
mod sub2 {
|
||||
/// sub2::describe
|
||||
pub fn describe() -> &'static str {
|
||||
"sub2::describe"
|
||||
}
|
||||
}
|
||||
|
||||
mod sub3 {
|
||||
// this should be shadowed
|
||||
// because both sub1::describe2 and sub3::describe2 are from glob reexport
|
||||
/// sub3::describe2
|
||||
pub fn describe2() -> &'static str {
|
||||
"sub3::describe2"
|
||||
}
|
||||
}
|
||||
|
||||
mod sub4 {
|
||||
// this should be shadowed by sub4::inner::X
|
||||
/// sub4::X
|
||||
pub const X: usize = 0;
|
||||
pub mod inner {
|
||||
pub use super::*;
|
||||
/// sub4::inner::X
|
||||
pub const X: usize = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// mod::Foo (function)
|
||||
pub fn Foo() {}
|
||||
|
||||
#[doc(inline)]
|
||||
pub use sub2::describe;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use sub1::*;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use sub3::*;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use sub4::inner::*;
|
||||
|
||||
/// mod::prelude
|
||||
pub mod prelude {}
|
@ -0,0 +1,16 @@
|
||||
#![crate_name = "foo"]
|
||||
|
||||
pub mod sub {
|
||||
pub struct Item;
|
||||
|
||||
pub mod prelude {
|
||||
pub use super::Item;
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(inline)]
|
||||
pub use sub::*;
|
||||
|
||||
// @count foo/index.html '//a[@class="mod"][@title="foo::prelude mod"]' 1
|
||||
// @count foo/prelude/index.html '//div[@class="item-row"]' 0
|
||||
pub mod prelude {}
|
@ -0,0 +1,16 @@
|
||||
#![crate_name = "foo"]
|
||||
|
||||
pub mod sub {
|
||||
pub struct Item;
|
||||
|
||||
pub mod prelude {
|
||||
pub use super::Item;
|
||||
}
|
||||
}
|
||||
|
||||
// @count foo/index.html '//a[@class="mod"][@title="foo::prelude mod"]' 1
|
||||
// @count foo/prelude/index.html '//div[@class="item-row"]' 0
|
||||
pub mod prelude {}
|
||||
|
||||
#[doc(inline)]
|
||||
pub use sub::*;
|
@ -4,13 +4,13 @@ error[E0391]: cycle detected when resolving instance `<LazyUpdim<T, { T::DIM },
|
||||
LL | const DIM: usize;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires checking if `TensorDimension` fulfills its obligations...
|
||||
note: ...which requires computing candidate for `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>`...
|
||||
--> $DIR/issue-83765.rs:4:1
|
||||
|
|
||||
LL | trait TensorDimension {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: ...which again requires resolving instance `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>::DIM`, completing the cycle
|
||||
note: cycle used when checking if `TensorDimension` fulfills its obligations
|
||||
note: cycle used when computing candidate for `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>`
|
||||
--> $DIR/issue-83765.rs:4:1
|
||||
|
|
||||
LL | trait TensorDimension {
|
||||
|
Loading…
Reference in New Issue
Block a user