diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index a9152bdc59787..e6465d641f1e6 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 39b178f5976b8..9dd9bf05540fb 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; + fn item_def_id(&self) -> DefId; /// Returns predicates in scope of the form `X: Foo`, 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 `` 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 46db0f74d4d5f..25faacadf3d0c 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 { - 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 2e84e1d016007..5d1ca1cbd2389 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() -> impl Iterator::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 0c600daf4459e..c36c01e1b46d0 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 { - 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 bd1f85a9d0693..b8ad18c64dcf6 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, ) -> (bool, Option) { - 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 e93c4138e61b0..f9ee202466f67 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 [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 6d3cda684a62a..ec0a5b9d0d84f 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 1ce0d1e4ffd02..ad4ad4104e104 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, + import_id: Option, ) -> Vec { 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 360b6b9832a55..d6f2b02afd8f8 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 7ee7eb25e0d90..c788b9f4093fe 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>, pub(crate) id: hir::HirId, - // (item, renamed) - pub(crate) items: Vec<(&'hir hir::Item<'hir>, Option)>, + // (item, renamed, import_id) + pub(crate) items: Vec<(&'hir hir::Item<'hir>, Option, Option)>, pub(crate) foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option)>, } @@ -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, ) -> 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, om: &mut Module<'tcx>, + parent_id: Option, ) { 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 0000000000000..1c8468008dd0a --- /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 0000000000000..75b57b621bb57 --- /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{ + +} + +pub struct Bar { + pub data: [usize; N] +} + +impl MyIterator for IteratorStruct { + type Output = Bar; +} + +pub fn test1() -> impl MyIterator> where [(); T::ABC]: Sized { + IteratorStruct::<{T::ABC}>{} +} + +pub trait Baz{} +impl Baz for Bar {} +pub fn test2() -> impl MyIterator> 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 0000000000000..ea3cac605b156 --- /dev/null +++ b/src/test/ui/consts/issue-103790.rs @@ -0,0 +1,10 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct 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 0000000000000..41b0816dc32af --- /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; + | - ^ already used + | | + | first use of `S` + +error[E0107]: missing generics for struct `S` + --> $DIR/issue-103790.rs:4:32 + | +LL | struct 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; + | ^ ----------- +help: add missing generic argument + | +LL | struct S = { S }>; + | ~~~~ + +error[E0391]: cycle detected when computing type of `S::S` + --> $DIR/issue-103790.rs:4:32 + | +LL | struct 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; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0391]: cycle detected when computing type of `S` + --> $DIR/issue-103790.rs:4:1 + | +LL | struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires computing type of `S::S`... + --> $DIR/issue-103790.rs:4:32 + | +LL | struct 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; +... | +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`.