about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/errors.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs31
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs4
-rw-r--r--compiler/rustc_session/src/config.rs14
-rw-r--r--compiler/rustc_session/src/options.rs2
-rw-r--r--compiler/rustc_session/src/session.rs9
-rw-r--r--src/librustdoc/clean/mod.rs26
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css1
-rw-r--r--src/librustdoc/visit_ast.rs29
-rw-r--r--src/test/rustdoc/local-reexport-doc.rs16
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-99705.rs33
-rw-r--r--src/test/ui/consts/issue-103790.rs10
-rw-r--r--src/test/ui/consts/issue-103790.stderr65
15 files changed, 213 insertions, 50 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index a9152bdc597..e6465d641f1 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -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();
 
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 39b178f5976..9dd9bf05540 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -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 {
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 46db0f74d4d..25faacadf3d 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -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(
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 2e84e1d0160..5d1ca1cbd23 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -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);
             }
         }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 0c600daf445..c36c01e1b46 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -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(
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index bd1f85a9d06..b8ad18c64dc 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -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,
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index e93c4138e61..f9ee202466f 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -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],
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 6d3cda684a6..ec0a5b9d0d8 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -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;
         }
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 1ce0d1e4ffd..ad4ad4104e1 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -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)]
+        }
     })
 }
 
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 360b6b9832a..d6f2b02afd8 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -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;
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 7ee7eb25e0d..c788b9f4093 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -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));
                 }
             }
         }
diff --git a/src/test/rustdoc/local-reexport-doc.rs b/src/test/rustdoc/local-reexport-doc.rs
new file mode 100644
index 00000000000..1c8468008dd
--- /dev/null
+++ b/src/test/rustdoc/local-reexport-doc.rs
@@ -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;
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-99705.rs b/src/test/ui/const-generics/generic_const_exprs/issue-99705.rs
new file mode 100644
index 00000000000..75b57b621bb
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-99705.rs
@@ -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}>{}
+}
diff --git a/src/test/ui/consts/issue-103790.rs b/src/test/ui/consts/issue-103790.rs
new file mode 100644
index 00000000000..ea3cac605b1
--- /dev/null
+++ b/src/test/ui/consts/issue-103790.rs
@@ -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() {}
diff --git a/src/test/ui/consts/issue-103790.stderr b/src/test/ui/consts/issue-103790.stderr
new file mode 100644
index 00000000000..41b0816dc32
--- /dev/null
+++ b/src/test/ui/consts/issue-103790.stderr
@@ -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`.