Auto merge of #103903 - matthiaskrgr:rollup-r5xcvrp, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #99801 (fix(generic_const_exprs): Fix predicate inheritance for children of opaque types) - #103610 (Allow use of `-Clto=thin` with `-Ccodegen-units=1` in general) - #103870 (Fix `inferred_kind` ICE) - #103875 (Simplify astconv item def id handling) - #103886 (rustdoc: Fix merge of attributes for reexports of local items) - #103890 (rustdoc: remove unused mobile CSS `.rustdoc { padding-top: 0 }`) Failed merges: - #103884 (Add visit_fn_ret_ty to hir intravisit) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
96787c45ac
@ -177,11 +177,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
.all_traits()
|
||||
.filter(|trait_def_id| {
|
||||
let viz = self.tcx().visibility(*trait_def_id);
|
||||
if let Some(def_id) = self.item_def_id() {
|
||||
viz.is_accessible_from(def_id, self.tcx())
|
||||
} else {
|
||||
viz.is_visible_locally()
|
||||
}
|
||||
let def_id = self.item_def_id();
|
||||
viz.is_accessible_from(def_id, self.tcx())
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -54,7 +54,7 @@ pub struct PathSeg(pub DefId, pub usize);
|
||||
pub trait AstConv<'tcx> {
|
||||
fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
|
||||
|
||||
fn item_def_id(&self) -> Option<DefId>;
|
||||
fn item_def_id(&self) -> DefId;
|
||||
|
||||
/// Returns predicates in scope of the form `X: Foo<T>`, where `X`
|
||||
/// is a type parameter `X` with the given id `def_id` and T
|
||||
@ -500,6 +500,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
}
|
||||
GenericParamDefKind::Const { has_default } => {
|
||||
let ty = tcx.at(self.span).type_of(param.def_id);
|
||||
if ty.references_error() {
|
||||
return tcx.const_error(ty).into();
|
||||
}
|
||||
if !infer_args && has_default {
|
||||
tcx.bound_const_param_default(param.def_id)
|
||||
.subst(tcx, substs.unwrap())
|
||||
@ -2079,17 +2082,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
|
||||
debug!("qpath_to_ty: self.item_def_id()={:?}", def_id);
|
||||
|
||||
let parent_def_id = def_id
|
||||
.and_then(|def_id| {
|
||||
def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
|
||||
})
|
||||
let parent_def_id = def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
|
||||
.map(|hir_id| tcx.hir().get_parent_item(hir_id).to_def_id());
|
||||
|
||||
debug!("qpath_to_ty: parent_def_id={:?}", parent_def_id);
|
||||
|
||||
// If the trait in segment is the same as the trait defining the item,
|
||||
// use the `<Self as ..>` syntax in the error.
|
||||
let is_part_of_self_trait_constraints = def_id == Some(trait_def_id);
|
||||
let is_part_of_self_trait_constraints = def_id == trait_def_id;
|
||||
let is_part_of_fn_in_self_trait = parent_def_id == Some(trait_def_id);
|
||||
|
||||
let type_name = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
|
||||
|
@ -379,8 +379,8 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn item_def_id(&self) -> Option<DefId> {
|
||||
Some(self.item_def_id)
|
||||
fn item_def_id(&self) -> DefId {
|
||||
self.item_def_id
|
||||
}
|
||||
|
||||
fn get_type_parameter_bounds(
|
||||
|
@ -427,6 +427,8 @@ pub(super) fn explicit_predicates_of<'tcx>(
|
||||
} else {
|
||||
if matches!(def_kind, DefKind::AnonConst) && tcx.lazy_normalization() {
|
||||
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
|
||||
let parent_def_id = tcx.hir().get_parent_item(hir_id);
|
||||
|
||||
if tcx.hir().opt_const_param_default_param_hir_id(hir_id).is_some() {
|
||||
// In `generics_of` we set the generics' parent to be our parent's parent which means that
|
||||
// we lose out on the predicates of our actual parent if we dont return those predicates here.
|
||||
@ -439,8 +441,33 @@ pub(super) fn explicit_predicates_of<'tcx>(
|
||||
// parent of generics returned by `generics_of`
|
||||
//
|
||||
// In the above code we want the anon const to have predicates in its param env for `T: Trait`
|
||||
let item_def_id = tcx.hir().get_parent_item(hir_id);
|
||||
// In the above code example we would be calling `explicit_predicates_of(Foo)` here
|
||||
// and we would be calling `explicit_predicates_of(Foo)` here
|
||||
return tcx.explicit_predicates_of(parent_def_id);
|
||||
}
|
||||
|
||||
let parent_def_kind = tcx.def_kind(parent_def_id);
|
||||
if matches!(parent_def_kind, DefKind::OpaqueTy) {
|
||||
// In `instantiate_identity` we inherit the predicates of our parent.
|
||||
// However, opaque types do not have a parent (see `gather_explicit_predicates_of`), which means
|
||||
// that we lose out on the predicates of our actual parent if we dont return those predicates here.
|
||||
//
|
||||
//
|
||||
// fn foo<T: Trait>() -> impl Iterator<Output = Another<{ <T as Trait>::ASSOC }> > { todo!() }
|
||||
// ^^^^^^^^^^^^^^^^^^^ the def id we are calling
|
||||
// explicit_predicates_of on
|
||||
//
|
||||
// In the above code we want the anon const to have predicates in its param env for `T: Trait`.
|
||||
// However, the anon const cannot inherit predicates from its parent since it's opaque.
|
||||
//
|
||||
// To fix this, we call `explicit_predicates_of` directly on `foo`, the parent's parent.
|
||||
|
||||
// In the above example this is `foo::{opaque#0}` or `impl Iterator`
|
||||
let parent_hir_id = tcx.hir().local_def_id_to_hir_id(parent_def_id.def_id);
|
||||
|
||||
// In the above example this is the function `foo`
|
||||
let item_def_id = tcx.hir().get_parent_item(parent_hir_id);
|
||||
|
||||
// In the above code example we would be calling `explicit_predicates_of(foo)` here
|
||||
return tcx.explicit_predicates_of(item_def_id);
|
||||
}
|
||||
}
|
||||
|
@ -194,8 +194,8 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn item_def_id(&self) -> Option<DefId> {
|
||||
None
|
||||
fn item_def_id(&self) -> DefId {
|
||||
self.body_id.owner.to_def_id()
|
||||
}
|
||||
|
||||
fn get_type_parameter_bounds(
|
||||
|
@ -738,7 +738,7 @@ impl Default for Options {
|
||||
actually_rustdoc: false,
|
||||
trimmed_def_paths: TrimmedDefPaths::default(),
|
||||
cli_forced_codegen_units: None,
|
||||
cli_forced_thinlto_off: false,
|
||||
cli_forced_local_thinlto_off: false,
|
||||
remap_path_prefix: Vec::new(),
|
||||
real_rust_source_base_dir: None,
|
||||
edition: DEFAULT_EDITION,
|
||||
@ -1721,7 +1721,7 @@ fn should_override_cgus_and_disable_thinlto(
|
||||
error_format: ErrorOutputType,
|
||||
mut codegen_units: Option<usize>,
|
||||
) -> (bool, Option<usize>) {
|
||||
let mut disable_thinlto = false;
|
||||
let mut disable_local_thinlto = false;
|
||||
// Issue #30063: if user requests LLVM-related output to one
|
||||
// particular path, disable codegen-units.
|
||||
let incompatible: Vec<_> = output_types
|
||||
@ -1746,12 +1746,12 @@ fn should_override_cgus_and_disable_thinlto(
|
||||
}
|
||||
early_warn(error_format, "resetting to default -C codegen-units=1");
|
||||
codegen_units = Some(1);
|
||||
disable_thinlto = true;
|
||||
disable_local_thinlto = true;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
codegen_units = Some(1);
|
||||
disable_thinlto = true;
|
||||
disable_local_thinlto = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1760,7 +1760,7 @@ fn should_override_cgus_and_disable_thinlto(
|
||||
early_error(error_format, "value for codegen units must be a positive non-zero integer");
|
||||
}
|
||||
|
||||
(disable_thinlto, codegen_units)
|
||||
(disable_local_thinlto, codegen_units)
|
||||
}
|
||||
|
||||
fn check_thread_count(unstable_opts: &UnstableOptions, error_format: ErrorOutputType) {
|
||||
@ -2265,7 +2265,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
||||
let output_types = parse_output_types(&unstable_opts, matches, error_format);
|
||||
|
||||
let mut cg = CodegenOptions::build(matches, error_format);
|
||||
let (disable_thinlto, mut codegen_units) = should_override_cgus_and_disable_thinlto(
|
||||
let (disable_local_thinlto, mut codegen_units) = should_override_cgus_and_disable_thinlto(
|
||||
&output_types,
|
||||
matches,
|
||||
error_format,
|
||||
@ -2508,7 +2508,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
||||
actually_rustdoc: false,
|
||||
trimmed_def_paths: TrimmedDefPaths::default(),
|
||||
cli_forced_codegen_units: codegen_units,
|
||||
cli_forced_thinlto_off: disable_thinlto,
|
||||
cli_forced_local_thinlto_off: disable_local_thinlto,
|
||||
remap_path_prefix,
|
||||
real_rust_source_base_dir,
|
||||
edition,
|
||||
|
@ -181,7 +181,7 @@ top_level_options!(
|
||||
#[rustc_lint_opt_deny_field_access("use `Session::codegen_units` instead of this field")]
|
||||
cli_forced_codegen_units: Option<usize> [UNTRACKED],
|
||||
#[rustc_lint_opt_deny_field_access("use `Session::lto` instead of this field")]
|
||||
cli_forced_thinlto_off: bool [UNTRACKED],
|
||||
cli_forced_local_thinlto_off: bool [UNTRACKED],
|
||||
|
||||
/// Remap source path prefixes in all output (messages, object files, debug, etc.).
|
||||
remap_path_prefix: Vec<(PathBuf, PathBuf)> [TRACKED_NO_CRATE_HASH],
|
||||
|
@ -1018,11 +1018,8 @@ impl Session {
|
||||
return config::Lto::Fat;
|
||||
}
|
||||
config::LtoCli::Thin => {
|
||||
return if self.opts.cli_forced_thinlto_off {
|
||||
config::Lto::Fat
|
||||
} else {
|
||||
config::Lto::Thin
|
||||
};
|
||||
// The user explicitly asked for ThinLTO
|
||||
return config::Lto::Thin;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1034,7 +1031,7 @@ impl Session {
|
||||
|
||||
// If processing command line options determined that we're incompatible
|
||||
// with ThinLTO (e.g., `-C lto --emit llvm-ir`) then return that option.
|
||||
if self.opts.cli_forced_thinlto_off {
|
||||
if self.opts.cli_forced_local_thinlto_off {
|
||||
return config::Lto::No;
|
||||
}
|
||||
|
||||
|
@ -74,12 +74,12 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
|
||||
// This covers the case where somebody does an import which should pull in an item,
|
||||
// but there's already an item with the same namespace and same name. Rust gives
|
||||
// priority to the not-imported one, so we should, too.
|
||||
items.extend(doc.items.iter().flat_map(|(item, renamed)| {
|
||||
items.extend(doc.items.iter().flat_map(|(item, renamed, import_id)| {
|
||||
// First, lower everything other than imports.
|
||||
if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
|
||||
return Vec::new();
|
||||
}
|
||||
let v = clean_maybe_renamed_item(cx, item, *renamed);
|
||||
let v = clean_maybe_renamed_item(cx, item, *renamed, *import_id);
|
||||
for item in &v {
|
||||
if let Some(name) = item.name && !item.attrs.lists(sym::doc).has_word(sym::hidden) {
|
||||
inserted.insert((item.type_(), name));
|
||||
@ -87,7 +87,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
|
||||
}
|
||||
v
|
||||
}));
|
||||
items.extend(doc.items.iter().flat_map(|(item, renamed)| {
|
||||
items.extend(doc.items.iter().flat_map(|(item, renamed, _)| {
|
||||
// Now we actually lower the imports, skipping everything else.
|
||||
if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind {
|
||||
let name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id()));
|
||||
@ -1911,6 +1911,7 @@ fn clean_maybe_renamed_item<'tcx>(
|
||||
cx: &mut DocContext<'tcx>,
|
||||
item: &hir::Item<'tcx>,
|
||||
renamed: Option<Symbol>,
|
||||
import_id: Option<hir::HirId>,
|
||||
) -> Vec<Item> {
|
||||
use hir::ItemKind;
|
||||
|
||||
@ -1987,8 +1988,23 @@ fn clean_maybe_renamed_item<'tcx>(
|
||||
}
|
||||
_ => unreachable!("not yet converted"),
|
||||
};
|
||||
|
||||
vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)]
|
||||
if let Some(import_id) = import_id {
|
||||
let (attrs, cfg) = inline::merge_attrs(
|
||||
cx,
|
||||
Some(cx.tcx.parent_module(import_id).to_def_id()),
|
||||
inline::load_attrs(cx, def_id),
|
||||
Some(inline::load_attrs(cx, cx.tcx.hir().local_def_id(import_id).to_def_id())),
|
||||
);
|
||||
vec![Item::from_def_id_and_attrs_and_parts(
|
||||
def_id,
|
||||
Some(name),
|
||||
kind,
|
||||
Box::new(attrs),
|
||||
cfg,
|
||||
)]
|
||||
} else {
|
||||
vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1677,7 +1677,6 @@ in storage.js
|
||||
}
|
||||
|
||||
.rustdoc {
|
||||
padding-top: 0px;
|
||||
/* Sidebar should overlay main content, rather than pushing main content to the right.
|
||||
Turn off `display: flex` on the body element. */
|
||||
display: block;
|
||||
|
@ -25,8 +25,8 @@ pub(crate) struct Module<'hir> {
|
||||
pub(crate) where_inner: Span,
|
||||
pub(crate) mods: Vec<Module<'hir>>,
|
||||
pub(crate) id: hir::HirId,
|
||||
// (item, renamed)
|
||||
pub(crate) items: Vec<(&'hir hir::Item<'hir>, Option<Symbol>)>,
|
||||
// (item, renamed, import_id)
|
||||
pub(crate) items: Vec<(&'hir hir::Item<'hir>, Option<Symbol>, Option<hir::HirId>)>,
|
||||
pub(crate) foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option<Symbol>)>,
|
||||
}
|
||||
|
||||
@ -93,6 +93,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
hir::CRATE_HIR_ID,
|
||||
self.cx.tcx.hir().root_module(),
|
||||
self.cx.tcx.crate_name(LOCAL_CRATE),
|
||||
None,
|
||||
);
|
||||
|
||||
// `#[macro_export] macro_rules!` items are reexported at the top level of the
|
||||
@ -113,7 +114,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
if self.cx.tcx.has_attr(def_id, sym::macro_export) {
|
||||
if inserted.insert(def_id) {
|
||||
let item = self.cx.tcx.hir().expect_item(local_def_id);
|
||||
top_level_module.items.push((item, None));
|
||||
top_level_module.items.push((item, None, None));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -155,6 +156,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
id: hir::HirId,
|
||||
m: &'tcx hir::Mod<'tcx>,
|
||||
name: Symbol,
|
||||
parent_id: Option<hir::HirId>,
|
||||
) -> Module<'tcx> {
|
||||
let mut om = Module::new(name, id, m.spans.inner_span);
|
||||
let def_id = self.cx.tcx.hir().local_def_id(id).to_def_id();
|
||||
@ -166,7 +168,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
|
||||
continue;
|
||||
}
|
||||
self.visit_item(item, None, &mut om);
|
||||
self.visit_item(item, None, &mut om, parent_id);
|
||||
}
|
||||
for &i in m.item_ids {
|
||||
let item = self.cx.tcx.hir().item(i);
|
||||
@ -174,7 +176,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
// 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.visit_item(item, None, &mut om, parent_id);
|
||||
}
|
||||
}
|
||||
self.inside_public_path = orig_inside_public_path;
|
||||
@ -247,14 +249,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
let prev = mem::replace(&mut self.inlining, true);
|
||||
for &i in m.item_ids {
|
||||
let i = self.cx.tcx.hir().item(i);
|
||||
self.visit_item(i, None, om);
|
||||
self.visit_item(i, None, om, Some(id));
|
||||
}
|
||||
self.inlining = prev;
|
||||
true
|
||||
}
|
||||
Node::Item(it) if !glob => {
|
||||
let prev = mem::replace(&mut self.inlining, true);
|
||||
self.visit_item(it, renamed, om);
|
||||
self.visit_item(it, renamed, om, Some(id));
|
||||
self.inlining = prev;
|
||||
true
|
||||
}
|
||||
@ -275,6 +277,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
item: &'tcx hir::Item<'_>,
|
||||
renamed: Option<Symbol>,
|
||||
om: &mut Module<'tcx>,
|
||||
parent_id: Option<hir::HirId>,
|
||||
) {
|
||||
debug!("visiting item {:?}", item);
|
||||
let name = renamed.unwrap_or(item.ident.name);
|
||||
@ -330,7 +333,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
om.items.push((item, renamed))
|
||||
om.items.push((item, renamed, parent_id))
|
||||
}
|
||||
hir::ItemKind::Macro(ref macro_def, _) => {
|
||||
// `#[macro_export] macro_rules!` items are handled separately in `visit()`,
|
||||
@ -349,11 +352,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
let nonexported = !self.cx.tcx.has_attr(def_id, sym::macro_export);
|
||||
|
||||
if is_macro_2_0 || nonexported || self.inlining {
|
||||
om.items.push((item, renamed));
|
||||
om.items.push((item, renamed, None));
|
||||
}
|
||||
}
|
||||
hir::ItemKind::Mod(ref m) => {
|
||||
om.mods.push(self.visit_mod_contents(item.hir_id(), m, name));
|
||||
om.mods.push(self.visit_mod_contents(item.hir_id(), m, name, parent_id));
|
||||
}
|
||||
hir::ItemKind::Fn(..)
|
||||
| hir::ItemKind::ExternCrate(..)
|
||||
@ -364,19 +367,19 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
| hir::ItemKind::OpaqueTy(..)
|
||||
| hir::ItemKind::Static(..)
|
||||
| hir::ItemKind::Trait(..)
|
||||
| hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed)),
|
||||
| hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed, parent_id)),
|
||||
hir::ItemKind::Const(..) => {
|
||||
// Underscore constants do not correspond to a nameable item and
|
||||
// so are never useful in documentation.
|
||||
if name != kw::Underscore {
|
||||
om.items.push((item, renamed));
|
||||
om.items.push((item, renamed, parent_id));
|
||||
}
|
||||
}
|
||||
hir::ItemKind::Impl(impl_) => {
|
||||
// Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
|
||||
// them up regardless of where they're located.
|
||||
if !self.inlining && impl_.of_trait.is_none() {
|
||||
om.items.push((item, None));
|
||||
om.items.push((item, None, None));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
16
src/test/rustdoc/local-reexport-doc.rs
Normal file
16
src/test/rustdoc/local-reexport-doc.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// This test ensures that the reexports of local items also get the doc from
|
||||
// the reexport.
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
// @has 'foo/fn.g.html'
|
||||
// @has - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]' \
|
||||
// 'outer module inner module'
|
||||
|
||||
mod inner_mod {
|
||||
/// inner module
|
||||
pub fn g() {}
|
||||
}
|
||||
|
||||
/// outer module
|
||||
pub use inner_mod::g;
|
@ -0,0 +1,33 @@
|
||||
// check-pass
|
||||
#![crate_type = "lib"]
|
||||
#![feature(generic_const_exprs)]
|
||||
#![allow(incomplete_features)]
|
||||
pub trait MyIterator {
|
||||
type Output;
|
||||
}
|
||||
|
||||
pub trait Foo {
|
||||
const ABC: usize;
|
||||
}
|
||||
|
||||
pub struct IteratorStruct<const N: usize>{
|
||||
|
||||
}
|
||||
|
||||
pub struct Bar<const N: usize> {
|
||||
pub data: [usize; N]
|
||||
}
|
||||
|
||||
impl<const N: usize> MyIterator for IteratorStruct<N> {
|
||||
type Output = Bar<N>;
|
||||
}
|
||||
|
||||
pub fn test1<T: Foo>() -> impl MyIterator<Output = Bar<{T::ABC}>> where [(); T::ABC]: Sized {
|
||||
IteratorStruct::<{T::ABC}>{}
|
||||
}
|
||||
|
||||
pub trait Baz<const N: usize>{}
|
||||
impl<const N: usize> Baz<N> for Bar<N> {}
|
||||
pub fn test2<T: Foo>() -> impl MyIterator<Output = impl Baz<{ T::ABC }>> where [(); T::ABC]: Sized {
|
||||
IteratorStruct::<{T::ABC}>{}
|
||||
}
|
10
src/test/ui/consts/issue-103790.rs
Normal file
10
src/test/ui/consts/issue-103790.rs
Normal file
@ -0,0 +1,10 @@
|
||||
#![feature(generic_const_exprs)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
struct S<const S: (), const S: S = { S }>;
|
||||
//~^ ERROR the name `S` is already used for a generic parameter in this item's generic parameters
|
||||
//~| ERROR missing generics for struct `S`
|
||||
//~| ERROR cycle detected when computing type of `S::S`
|
||||
//~| ERROR cycle detected when computing type of `S`
|
||||
|
||||
fn main() {}
|
65
src/test/ui/consts/issue-103790.stderr
Normal file
65
src/test/ui/consts/issue-103790.stderr
Normal file
@ -0,0 +1,65 @@
|
||||
error[E0403]: the name `S` is already used for a generic parameter in this item's generic parameters
|
||||
--> $DIR/issue-103790.rs:4:29
|
||||
|
|
||||
LL | struct S<const S: (), const S: S = { S }>;
|
||||
| - ^ already used
|
||||
| |
|
||||
| first use of `S`
|
||||
|
||||
error[E0107]: missing generics for struct `S`
|
||||
--> $DIR/issue-103790.rs:4:32
|
||||
|
|
||||
LL | struct S<const S: (), const S: S = { S }>;
|
||||
| ^ expected at least 1 generic argument
|
||||
|
|
||||
note: struct defined here, with at least 1 generic parameter: `S`
|
||||
--> $DIR/issue-103790.rs:4:8
|
||||
|
|
||||
LL | struct S<const S: (), const S: S = { S }>;
|
||||
| ^ -----------
|
||||
help: add missing generic argument
|
||||
|
|
||||
LL | struct S<const S: (), const S: S<S> = { S }>;
|
||||
| ~~~~
|
||||
|
||||
error[E0391]: cycle detected when computing type of `S::S`
|
||||
--> $DIR/issue-103790.rs:4:32
|
||||
|
|
||||
LL | struct S<const S: (), const S: S = { S }>;
|
||||
| ^
|
||||
|
|
||||
= note: ...which immediately requires computing type of `S::S` again
|
||||
note: cycle used when computing type of `S`
|
||||
--> $DIR/issue-103790.rs:4:1
|
||||
|
|
||||
LL | struct S<const S: (), const S: S = { S }>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0391]: cycle detected when computing type of `S`
|
||||
--> $DIR/issue-103790.rs:4:1
|
||||
|
|
||||
LL | struct S<const S: (), const S: S = { S }>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires computing type of `S::S`...
|
||||
--> $DIR/issue-103790.rs:4:32
|
||||
|
|
||||
LL | struct S<const S: (), const S: S = { S }>;
|
||||
| ^
|
||||
= note: ...which again requires computing type of `S`, completing the cycle
|
||||
note: cycle used when collecting item types in top-level module
|
||||
--> $DIR/issue-103790.rs:1:1
|
||||
|
|
||||
LL | / #![feature(generic_const_exprs)]
|
||||
LL | | #![allow(incomplete_features)]
|
||||
LL | |
|
||||
LL | | struct S<const S: (), const S: S = { S }>;
|
||||
... |
|
||||
LL | |
|
||||
LL | | fn main() {}
|
||||
| |____________^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0107, E0391, E0403.
|
||||
For more information about an error, try `rustc --explain E0107`.
|
Loading…
x
Reference in New Issue
Block a user