From b5d5682ac30615b35bd2f011c24a3c927420c87f Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 31 Jul 2022 19:14:03 -0500 Subject: [PATCH 001/171] Make `core::mem::copy` const --- library/core/src/mem/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index d2dd2941d590..ee29a233efe1 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1005,7 +1005,7 @@ pub fn drop(_x: T) {} /// ``` #[inline] #[unstable(feature = "mem_copy_fn", issue = "98262")] -pub fn copy(x: &T) -> T { +pub const fn copy(x: &T) -> T { *x } From f310d4cbb4ac792ecfe2bb680c869bb732e9e7af Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 27 Sep 2022 18:22:06 +0200 Subject: [PATCH 002/171] Don't auto-publish lib crates --- .github/workflows/publish.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index a4497f49e3c2..73e62ab32c6c 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -2,8 +2,8 @@ name: publish on: workflow_dispatch: # We can add version input when 1.0 is released and scheduled releases are removed -# schedule: -# - cron: "0 0 * * *" # midnight UTC + # schedule: + # - cron: "0 0 * * *" # midnight UTC push: branches: @@ -50,5 +50,7 @@ jobs: cargo workspaces rename --from test-utils test_utils cargo workspaces rename --from text-edit text_edit cargo workspaces rename ra_ap_%n + # Remove library crates from the workspaces so we don't auto-publish them as well + sed -i 's/ "lib\/\*",//' ./Cargo.toml find crates/rust-analyzer -type f -name '*.rs' -exec sed -i 's/rust_analyzer/ra_ap_rust_analyzer/g' {} + cargo workspaces publish --yes --force '*' --exact --no-git-commit --allow-dirty --skip-published custom 0.0.$PATCH From afe29e48bc4d57c1bb73228ba8d70dc8f42436fc Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 5 Oct 2022 11:23:57 +0200 Subject: [PATCH 003/171] split steps for generating the standalone docs and the shared assets Before this commit, the step to generate the standalone docs (which included the index page and other HTML files at the root of the documentation) was bundled with the code copying files needed by multiple pieces of documentation. This means it wasn't possible to avoid generating the standalone docs. This commit splits the step into two, allowing the standalone docs generation to be excluded while still building the rest of the docs. --- src/bootstrap/doc.rs | 61 ++++++++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 819af6587484..b286c79a3030 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -227,7 +227,7 @@ impl Step for TheBook { } // build the version info page and CSS - builder.ensure(Standalone { compiler, target }); + let shared_assets = builder.ensure(SharedAssets { target }); // build the redirect pages builder.info(&format!("Documenting book redirect pages ({})", target)); @@ -236,7 +236,7 @@ impl Step for TheBook { let path = file.path(); let path = path.to_str().unwrap(); - invoke_rustdoc(builder, compiler, target, path); + invoke_rustdoc(builder, compiler, &shared_assets, target, path); } if builder.was_invoked_explicitly::(Kind::Doc) { @@ -250,6 +250,7 @@ impl Step for TheBook { fn invoke_rustdoc( builder: &Builder<'_>, compiler: Compiler, + shared_assets: &SharedAssetsPaths, target: TargetSelection, markdown: &str, ) { @@ -259,7 +260,6 @@ fn invoke_rustdoc( let header = builder.src.join("src/doc/redirect.inc"); let footer = builder.src.join("src/doc/footer.inc"); - let version_info = out.join("version_info.html"); let mut cmd = builder.rustdoc_cmd(compiler); @@ -268,7 +268,7 @@ fn invoke_rustdoc( cmd.arg("--html-after-content") .arg(&footer) .arg("--html-before-content") - .arg(&version_info) + .arg(&shared_assets.version_info) .arg("--html-in-header") .arg(&header) .arg("--markdown-no-toc") @@ -324,21 +324,11 @@ impl Step for Standalone { let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); + let version_info = builder.ensure(SharedAssets { target: self.target }).version_info; + let favicon = builder.src.join("src/doc/favicon.inc"); let footer = builder.src.join("src/doc/footer.inc"); let full_toc = builder.src.join("src/doc/full-toc.inc"); - t!(fs::copy(builder.src.join("src/doc/rust.css"), out.join("rust.css"))); - - let version_input = builder.src.join("src/doc/version_info.html.template"); - let version_info = out.join("version_info.html"); - - if !builder.config.dry_run && !up_to_date(&version_input, &version_info) { - let info = t!(fs::read_to_string(&version_input)) - .replace("VERSION", &builder.rust_release()) - .replace("SHORT_HASH", builder.rust_info.sha_short().unwrap_or("")) - .replace("STAMP", builder.rust_info.sha().unwrap_or("")); - t!(fs::write(&version_info, &info)); - } for file in t!(fs::read_dir(builder.src.join("src/doc"))) { let file = t!(file); @@ -400,6 +390,45 @@ impl Step for Standalone { } } +#[derive(Debug, Clone)] +pub struct SharedAssetsPaths { + pub version_info: PathBuf, +} + +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct SharedAssets { + target: TargetSelection, +} + +impl Step for SharedAssets { + type Output = SharedAssetsPaths; + const DEFAULT: bool = false; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + // Other tasks depend on this, no need to execute it on its own + run.never() + } + + // Generate shared resources used by other pieces of documentation. + fn run(self, builder: &Builder<'_>) -> Self::Output { + let out = builder.doc_out(self.target); + + let version_input = builder.src.join("src").join("doc").join("version_info.html.template"); + let version_info = out.join("version_info.html"); + if !builder.config.dry_run && !up_to_date(&version_input, &version_info) { + let info = t!(fs::read_to_string(&version_input)) + .replace("VERSION", &builder.rust_release()) + .replace("SHORT_HASH", builder.rust_info.sha_short().unwrap_or("")) + .replace("STAMP", builder.rust_info.sha().unwrap_or("")); + t!(fs::write(&version_info, &info)); + } + + builder.copy(&builder.src.join("src").join("doc").join("rust.css"), &out.join("rust.css")); + + SharedAssetsPaths { version_info } + } +} + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Std { pub stage: u32, From 004b8b98d626a89b5d4cdc630ff337c0f4ea919f Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 5 Oct 2022 12:45:52 +0200 Subject: [PATCH 004/171] add a "standalone" path for doc::Standalone to be able to exclude it Before this commit, the path for the doc::Standalone step was "src/doc", which is accurate as the standalone docs source files live at the root of the "src/doc" directory tree. Unfortunately, that caused bad interactions when trying to exclude it with `--exclude src/doc`. When an exclusion is passed to bootstrap, it will exclude all steps whose path *ends with* the exclusion, which results in the Cargo book (src/tools/cargo/src/doc) to also be excluded. To work around this problem, this commit adds the "standalone" path as an alternate path for doc::Standalone, allowing `--exclude standalone` to work without side effects. --- src/bootstrap/doc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index b286c79a3030..a8524fea1b2a 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -299,7 +299,7 @@ impl Step for Standalone { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.path("src/doc").default_condition(builder.config.docs) + run.path("src/doc").path("standalone").default_condition(builder.config.docs) } fn make_run(run: RunConfig<'_>) { From 17d78c4ef922f81e752feb077d66fbce80630c6c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 6 Oct 2022 13:36:07 +0200 Subject: [PATCH 005/171] poll_fn and Unpin: fix pinning --- library/core/src/future/poll_fn.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/library/core/src/future/poll_fn.rs b/library/core/src/future/poll_fn.rs index db2a523323b7..90cb797391a0 100644 --- a/library/core/src/future/poll_fn.rs +++ b/library/core/src/future/poll_fn.rs @@ -5,7 +5,9 @@ use crate::task::{Context, Poll}; /// Creates a future that wraps a function returning [`Poll`]. /// -/// Polling the future delegates to the wrapped function. +/// Polling the future delegates to the wrapped function. If the returned future is pinned, then the +/// captured environment of the wrapped function is also pinned in-place, so as long as the closure +/// does not move out of its captures it can soundly create pinned references to them. /// /// # Examples /// @@ -41,7 +43,7 @@ pub struct PollFn { } #[stable(feature = "future_poll_fn", since = "1.64.0")] -impl Unpin for PollFn {} +impl Unpin for PollFn {} #[stable(feature = "future_poll_fn", since = "1.64.0")] impl fmt::Debug for PollFn { @@ -57,7 +59,8 @@ where { type Output = T; - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - (&mut self.f)(cx) + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + // SAFETY: We are not moving out of the pinned field. + (unsafe { &mut self.get_unchecked_mut().f })(cx) } } From d7fb8d51d6269c2119254a886d883ac7e051938e Mon Sep 17 00:00:00 2001 From: DropDemBits Date: Mon, 10 Oct 2022 14:22:01 -0400 Subject: [PATCH 006/171] Migrate assists to format args captures, part 2 --- .../src/handlers/generate_constant.rs | 12 ++-- .../generate_default_from_enum_variant.rs | 5 +- .../src/handlers/generate_default_from_new.rs | 61 ++++++++++--------- .../src/handlers/generate_delegate_methods.rs | 12 ++-- .../src/handlers/generate_deref.rs | 12 ++-- .../generate_documentation_template.rs | 52 +++++++++------- .../src/handlers/generate_enum_is_method.rs | 16 ++--- .../generate_enum_projection_method.rs | 37 +++++------ .../handlers/generate_from_impl_for_enum.rs | 19 +++--- .../src/handlers/generate_function.rs | 32 +++++----- .../src/handlers/generate_getter.rs | 18 +++--- .../ide-assists/src/handlers/generate_impl.rs | 2 +- .../ide-assists/src/handlers/generate_new.rs | 13 ++-- .../src/handlers/generate_setter.rs | 16 ++--- 14 files changed, 150 insertions(+), 157 deletions(-) diff --git a/crates/ide-assists/src/handlers/generate_constant.rs b/crates/ide-assists/src/handlers/generate_constant.rs index eaa6de73eb35..ccdfcb0d9e4f 100644 --- a/crates/ide-assists/src/handlers/generate_constant.rs +++ b/crates/ide-assists/src/handlers/generate_constant.rs @@ -77,7 +77,7 @@ pub(crate) fn generate_constant(acc: &mut Assists, ctx: &AssistContext<'_>) -> O target_data_for_generate_constant(ctx, current_module, constant_module).unwrap_or_else( || { let indent = IndentLevel::from_node(statement.syntax()); - (statement.syntax().text_range().start(), indent, None, format!("\n{}", indent)) + (statement.syntax().text_range().start(), indent, None, format!("\n{indent}")) }, ); @@ -90,7 +90,7 @@ pub(crate) fn generate_constant(acc: &mut Assists, ctx: &AssistContext<'_>) -> O if let Some(file_id) = file_id { builder.edit_file(file_id); } - builder.insert(offset, format!("{}{}", text, post_string)); + builder.insert(offset, format!("{text}{post_string}")); }, ) } @@ -103,13 +103,13 @@ fn get_text_for_generate_constant( ) -> Option { let constant_token = not_exist_name_ref.pop()?; let vis = if not_exist_name_ref.len() == 0 && !outer_exists { "" } else { "\npub " }; - let mut text = format!("{}const {}: {} = $0;", vis, constant_token, type_name); + let mut text = format!("{vis}const {constant_token}: {type_name} = $0;"); while let Some(name_ref) = not_exist_name_ref.pop() { let vis = if not_exist_name_ref.len() == 0 && !outer_exists { "" } else { "\npub " }; text = text.replace("\n", "\n "); - text = format!("{}mod {} {{{}\n}}", vis, name_ref.to_string(), text); + text = format!("{vis}mod {name_ref} {{{text}\n}}"); } - Some(text.replace("\n", &format!("\n{}", indent))) + Some(text.replace("\n", &format!("\n{indent}"))) } fn target_data_for_generate_constant( @@ -134,7 +134,7 @@ fn target_data_for_generate_constant( .find(|it| it.kind() == SyntaxKind::WHITESPACE && it.to_string().contains("\n")) .is_some(); let post_string = - if siblings_has_newline { format!("{}", indent) } else { format!("\n{}", indent) }; + if siblings_has_newline { format!("{indent}") } else { format!("\n{indent}") }; Some((offset, indent + 1, Some(file_id), post_string)) } _ => Some((TextSize::from(0), 0.into(), Some(file_id), "\n".into())), diff --git a/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs b/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs index 5e9995a98664..a6e3d49e0d1a 100644 --- a/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs +++ b/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs @@ -55,12 +55,11 @@ pub(crate) fn generate_default_from_enum_variant( let buf = format!( r#" -impl Default for {0} {{ +impl Default for {enum_name} {{ fn default() -> Self {{ - Self::{1} + Self::{variant_name} }} }}"#, - enum_name, variant_name ); edit.insert(start_offset, buf); }, diff --git a/crates/ide-assists/src/handlers/generate_default_from_new.rs b/crates/ide-assists/src/handlers/generate_default_from_new.rs index cbd33de19eda..49d9fd707ffc 100644 --- a/crates/ide-assists/src/handlers/generate_default_from_new.rs +++ b/crates/ide-assists/src/handlers/generate_default_from_new.rs @@ -1,8 +1,7 @@ use ide_db::famous_defs::FamousDefs; -use itertools::Itertools; use stdx::format_to; use syntax::{ - ast::{self, HasGenericParams, HasName, HasTypeBounds, Impl}, + ast::{self, make, HasGenericParams, HasName, Impl}, AstNode, }; @@ -77,45 +76,47 @@ pub(crate) fn generate_default_from_new(acc: &mut Assists, ctx: &AssistContext<' ) } +// FIXME: based on from utils::generate_impl_text_inner fn generate_trait_impl_text_from_impl(impl_: &ast::Impl, trait_text: &str, code: &str) -> String { - let generic_params = impl_.generic_param_list(); + let impl_ty = impl_.self_ty().unwrap(); + let generic_params = impl_.generic_param_list().map(|generic_params| { + let lifetime_params = + generic_params.lifetime_params().map(ast::GenericParam::LifetimeParam); + let ty_or_const_params = generic_params.type_or_const_params().filter_map(|param| { + // remove defaults since they can't be specified in impls + match param { + ast::TypeOrConstParam::Type(param) => { + let param = param.clone_for_update(); + param.remove_default(); + Some(ast::GenericParam::TypeParam(param)) + } + ast::TypeOrConstParam::Const(param) => { + let param = param.clone_for_update(); + param.remove_default(); + Some(ast::GenericParam::ConstParam(param)) + } + } + }); + + make::generic_param_list(itertools::chain(lifetime_params, ty_or_const_params)) + }); + let mut buf = String::with_capacity(code.len()); buf.push_str("\n\n"); + + // `impl{generic_params} {trait_text} for {impl_.self_ty()}` buf.push_str("impl"); - if let Some(generic_params) = &generic_params { - let lifetimes = generic_params.lifetime_params().map(|lt| format!("{}", lt.syntax())); - let toc_params = generic_params.type_or_const_params().map(|toc_param| match toc_param { - ast::TypeOrConstParam::Type(type_param) => { - let mut buf = String::new(); - if let Some(it) = type_param.name() { - format_to!(buf, "{}", it.syntax()); - } - if let Some(it) = type_param.colon_token() { - format_to!(buf, "{} ", it); - } - if let Some(it) = type_param.type_bound_list() { - format_to!(buf, "{}", it.syntax()); - } - buf - } - ast::TypeOrConstParam::Const(const_param) => const_param.syntax().to_string(), - }); - let generics = lifetimes.chain(toc_params).format(", "); - format_to!(buf, "<{}>", generics); + format_to!(buf, "{generic_params}") } - - buf.push(' '); - buf.push_str(trait_text); - buf.push_str(" for "); - buf.push_str(&impl_.self_ty().unwrap().syntax().text().to_string()); + format_to!(buf, " {trait_text} for {impl_ty}"); match impl_.where_clause() { Some(where_clause) => { - format_to!(buf, "\n{}\n{{\n{}\n}}", where_clause, code); + format_to!(buf, "\n{where_clause}\n{{\n{code}\n}}"); } None => { - format_to!(buf, " {{\n{}\n}}", code); + format_to!(buf, " {{\n{code}\n}}"); } } diff --git a/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/crates/ide-assists/src/handlers/generate_delegate_methods.rs index 85b193663a05..e5df3cbdaa96 100644 --- a/crates/ide-assists/src/handlers/generate_delegate_methods.rs +++ b/crates/ide-assists/src/handlers/generate_delegate_methods.rs @@ -51,14 +51,14 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' Some(field) => { let field_name = field.name()?; let field_ty = field.ty()?; - (format!("{}", field_name), field_ty, field.syntax().text_range()) + (format!("{field_name}"), field_ty, field.syntax().text_range()) } None => { let field = ctx.find_node_at_offset::()?; let field_list = ctx.find_node_at_offset::()?; let field_list_index = field_list.fields().position(|it| it == field)?; let field_ty = field.ty()?; - (format!("{}", field_list_index), field_ty, field.syntax().text_range()) + (format!("{field_list_index}"), field_ty, field.syntax().text_range()) } }; @@ -78,10 +78,12 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' let adt = ast::Adt::Struct(strukt.clone()); let name = method.name(ctx.db()).to_string(); let impl_def = find_struct_impl(ctx, &adt, &name).flatten(); + let method_name = method.name(ctx.db()); + acc.add_group( &GroupLabel("Generate delegate methods…".to_owned()), AssistId("generate_delegate_methods", AssistKind::Generate), - format!("Generate delegate for `{}.{}()`", field_name, method.name(ctx.db())), + format!("Generate delegate for `{field_name}.{method_name}()`"), target, |builder| { // Create the function @@ -151,12 +153,12 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' Some(cap) => { let offset = strukt.syntax().text_range().end(); let snippet = render_snippet(cap, impl_def.syntax(), cursor); - let snippet = format!("\n\n{}", snippet); + let snippet = format!("\n\n{snippet}"); builder.insert_snippet(cap, offset, snippet); } None => { let offset = strukt.syntax().text_range().end(); - let snippet = format!("\n\n{}", impl_def.syntax()); + let snippet = format!("\n\n{impl_def}"); builder.insert(offset, snippet); } } diff --git a/crates/ide-assists/src/handlers/generate_deref.rs b/crates/ide-assists/src/handlers/generate_deref.rs index 8f4405a8c869..55b7afb3d3b0 100644 --- a/crates/ide-assists/src/handlers/generate_deref.rs +++ b/crates/ide-assists/src/handlers/generate_deref.rs @@ -66,7 +66,7 @@ fn generate_record_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( let target = field.syntax().text_range(); acc.add( AssistId("generate_deref", AssistKind::Generate), - format!("Generate `{:?}` impl using `{}`", deref_type_to_generate, field_name), + format!("Generate `{deref_type_to_generate:?}` impl using `{field_name}`"), target, |edit| { generate_edit( @@ -106,7 +106,7 @@ fn generate_tuple_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<() let target = field.syntax().text_range(); acc.add( AssistId("generate_deref", AssistKind::Generate), - format!("Generate `{:?}` impl using `{}`", deref_type_to_generate, field.syntax()), + format!("Generate `{deref_type_to_generate:?}` impl using `{field}`"), target, |edit| { generate_edit( @@ -132,18 +132,16 @@ fn generate_edit( let start_offset = strukt.syntax().text_range().end(); let impl_code = match deref_type { DerefType::Deref => format!( - r#" type Target = {0}; + r#" type Target = {field_type_syntax}; fn deref(&self) -> &Self::Target {{ - &self.{1} + &self.{field_name} }}"#, - field_type_syntax, field_name ), DerefType::DerefMut => format!( r#" fn deref_mut(&mut self) -> &mut Self::Target {{ - &mut self.{} + &mut self.{field_name} }}"#, - field_name ), }; let strukt_adt = ast::Adt::Struct(strukt); diff --git a/crates/ide-assists/src/handlers/generate_documentation_template.rs b/crates/ide-assists/src/handlers/generate_documentation_template.rs index c91141f8eb50..b8415c72a2a3 100644 --- a/crates/ide-assists/src/handlers/generate_documentation_template.rs +++ b/crates/ide-assists/src/handlers/generate_documentation_template.rs @@ -139,40 +139,44 @@ fn make_example_for_fn(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> Option) -> Option) -> Option None, }; @@ -228,7 +235,9 @@ fn introduction_builder(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> Option String { // instance `TuplePat`) could be managed later. Some(ast::Pat::IdentPat(ident_pat)) => match ident_pat.name() { Some(name) => match is_a_ref_mut_param(¶m) { - true => format!("&mut {}", name), + true => format!("&mut {name}"), false => name.to_string(), }, None => "_".to_string(), @@ -424,14 +433,15 @@ fn function_call( let name = ast_func.name()?; let arguments = arguments_from_params(param_list); let function_call = if param_list.self_param().is_some() { - format!("{}.{}({})", self_name?, name, arguments) + let self_ = self_name?; + format!("{self_}.{name}({arguments})") } else if let Some(implementation) = self_partial_type(ast_func) { - format!("{}::{}({})", implementation, name, arguments) + format!("{implementation}::{name}({arguments})") } else { - format!("{}({})", name, arguments) + format!("{name}({arguments})") }; match is_unsafe { - true => Some(format!("unsafe {{ {} }}", function_call)), + true => Some(format!("unsafe {{ {function_call} }}")), false => Some(function_call), } } @@ -469,8 +479,8 @@ fn build_path(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> Option { .unwrap_or_else(|| "*".into()); let module_def: ModuleDef = ctx.sema.to_def(ast_func)?.module(ctx.db()).into(); match module_def.canonical_path(ctx.db()) { - Some(path) => Some(format!("{}::{}::{}", crate_name, path, leaf)), - None => Some(format!("{}::{}", crate_name, leaf)), + Some(path) => Some(format!("{crate_name}::{path}::{leaf}")), + None => Some(format!("{crate_name}::{leaf}")), } } diff --git a/crates/ide-assists/src/handlers/generate_enum_is_method.rs b/crates/ide-assists/src/handlers/generate_enum_is_method.rs index 52d27d8a7d63..dba98f7a04e4 100644 --- a/crates/ide-assists/src/handlers/generate_enum_is_method.rs +++ b/crates/ide-assists/src/handlers/generate_enum_is_method.rs @@ -61,21 +61,15 @@ pub(crate) fn generate_enum_is_method(acc: &mut Assists, ctx: &AssistContext<'_> "Generate an `is_` method for this enum variant", target, |builder| { - let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{} ", v)); + let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{v} ")); let method = format!( - " /// Returns `true` if the {} is [`{variant}`]. + " /// Returns `true` if the {enum_lowercase_name} is [`{variant_name}`]. /// - /// [`{variant}`]: {}::{variant} + /// [`{variant_name}`]: {enum_name}::{variant_name} #[must_use] - {}fn {}(&self) -> bool {{ - matches!(self, Self::{variant}{}) + {vis}fn {fn_name}(&self) -> bool {{ + matches!(self, Self::{variant_name}{pattern_suffix}) }}", - enum_lowercase_name, - enum_name, - vis, - fn_name, - pattern_suffix, - variant = variant_name ); add_method_to_adt(builder, &parent_enum, impl_def, &method); diff --git a/crates/ide-assists/src/handlers/generate_enum_projection_method.rs b/crates/ide-assists/src/handlers/generate_enum_projection_method.rs index b19aa0f652aa..402ab1ee79d3 100644 --- a/crates/ide-assists/src/handlers/generate_enum_projection_method.rs +++ b/crates/ide-assists/src/handlers/generate_enum_projection_method.rs @@ -116,6 +116,14 @@ fn generate_enum_projection_method( assist_description: &str, props: ProjectionProps, ) -> Option<()> { + let ProjectionProps { + fn_name_prefix, + self_param, + return_prefix, + return_suffix, + happy_case, + sad_case, + } = props; let variant = ctx.find_node_at_offset::()?; let variant_name = variant.name()?; let parent_enum = ast::Adt::Enum(variant.parent_enum()); @@ -125,7 +133,7 @@ fn generate_enum_projection_method( let (field,) = record.fields().collect_tuple()?; let name = field.name()?.to_string(); let ty = field.ty()?; - let pattern_suffix = format!(" {{ {} }}", name); + let pattern_suffix = format!(" {{ {name} }}"); (pattern_suffix, ty, name) } ast::StructKind::Tuple(tuple) => { @@ -136,8 +144,7 @@ fn generate_enum_projection_method( ast::StructKind::Unit => return None, }; - let fn_name = - format!("{}_{}", props.fn_name_prefix, &to_lower_snake_case(&variant_name.text())); + let fn_name = format!("{}_{}", fn_name_prefix, &to_lower_snake_case(&variant_name.text())); // Return early if we've found an existing new fn let impl_def = find_struct_impl(ctx, &parent_enum, &fn_name)?; @@ -149,27 +156,15 @@ fn generate_enum_projection_method( assist_description, target, |builder| { - let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{} ", v)); + let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{v} ")); let method = format!( - " {0}fn {1}({2}) -> {3}{4}{5} {{ - if let Self::{6}{7} = self {{ - {8}({9}) + " {vis}fn {fn_name}({self_param}) -> {return_prefix}{field_type}{return_suffix} {{ + if let Self::{variant_name}{pattern_suffix} = self {{ + {happy_case}({bound_name}) }} else {{ - {10} + {sad_case} }} - }}", - vis, - fn_name, - props.self_param, - props.return_prefix, - field_type.syntax(), - props.return_suffix, - variant_name, - pattern_suffix, - props.happy_case, - bound_name, - props.sad_case, - ); + }}"); add_method_to_adt(builder, &parent_enum, impl_def, &method); }, diff --git a/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs b/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs index 507ea012babf..7c81d2c6a6cc 100644 --- a/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs +++ b/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs @@ -56,23 +56,18 @@ pub(crate) fn generate_from_impl_for_enum( target, |edit| { let start_offset = variant.parent_enum().syntax().text_range().end(); - let from_trait = format!("From<{}>", field_type.syntax()); + let from_trait = format!("From<{field_type}>"); let impl_code = if let Some(name) = field_name { format!( - r#" fn from({0}: {1}) -> Self {{ - Self::{2} {{ {0} }} - }}"#, - name.text(), - field_type.syntax(), - variant_name, + r#" fn from({name}: {field_type}) -> Self {{ + Self::{variant_name} {{ {name} }} + }}"# ) } else { format!( - r#" fn from(v: {}) -> Self {{ - Self::{}(v) - }}"#, - field_type.syntax(), - variant_name, + r#" fn from(v: {field_type}) -> Self {{ + Self::{variant_name}(v) + }}"# ) }; let from_impl = generate_trait_impl_text(&enum_, &from_trait, &impl_code); diff --git a/crates/ide-assists/src/handlers/generate_function.rs b/crates/ide-assists/src/handlers/generate_function.rs index 8b67982f9158..e6cc8cacedd9 100644 --- a/crates/ide-assists/src/handlers/generate_function.rs +++ b/crates/ide-assists/src/handlers/generate_function.rs @@ -179,7 +179,7 @@ fn add_func_to_accumulator( let function_template = function_builder.render(adt_name.is_some()); let mut func = function_template.to_string(ctx.config.snippet_cap); if let Some(name) = adt_name { - func = format!("\n{}impl {} {{\n{}\n{}}}", indent, name, func, indent); + func = format!("\n{indent}impl {name} {{\n{func}\n{indent}}}"); } builder.edit_file(file); match ctx.config.snippet_cap { @@ -212,23 +212,26 @@ struct FunctionTemplate { impl FunctionTemplate { fn to_string(&self, cap: Option) -> String { + let Self { leading_ws, fn_def, ret_type, should_focus_return_type, trailing_ws, tail_expr } = + self; + let f = match cap { Some(cap) => { - let cursor = if self.should_focus_return_type { + let cursor = if *should_focus_return_type { // Focus the return type if there is one - match self.ret_type { - Some(ref ret_type) => ret_type.syntax(), - None => self.tail_expr.syntax(), + match ret_type { + Some(ret_type) => ret_type.syntax(), + None => tail_expr.syntax(), } } else { - self.tail_expr.syntax() + tail_expr.syntax() }; - render_snippet(cap, self.fn_def.syntax(), Cursor::Replace(cursor)) + render_snippet(cap, fn_def.syntax(), Cursor::Replace(cursor)) } - None => self.fn_def.to_string(), + None => fn_def.to_string(), }; - format!("{}{}{}", self.leading_ws, f, self.trailing_ws) + format!("{leading_ws}{f}{trailing_ws}") } } @@ -330,9 +333,9 @@ impl FunctionBuilder { let mut indent = IndentLevel::from_node(&it); if is_method { indent = indent + 1; - leading_ws = format!("{}", indent); + leading_ws = format!("{indent}"); } else { - leading_ws = format!("\n\n{}", indent); + leading_ws = format!("\n\n{indent}"); } fn_def = fn_def.indent(indent); @@ -340,9 +343,10 @@ impl FunctionBuilder { } GeneratedFunctionTarget::InEmptyItemList(it) => { let indent = IndentLevel::from_node(&it); - leading_ws = format!("\n{}", indent + 1); - fn_def = fn_def.indent(indent + 1); - trailing_ws = format!("\n{}", indent); + let leading_indent = indent + 1; + leading_ws = format!("\n{leading_indent}"); + fn_def = fn_def.indent(leading_indent); + trailing_ws = format!("\n{indent}"); } }; diff --git a/crates/ide-assists/src/handlers/generate_getter.rs b/crates/ide-assists/src/handlers/generate_getter.rs index 76fcef0cad95..09eedb11fbc1 100644 --- a/crates/ide-assists/src/handlers/generate_getter.rs +++ b/crates/ide-assists/src/handlers/generate_getter.rs @@ -108,9 +108,9 @@ pub(crate) fn generate_getter_impl( buf.push('\n'); } - let vis = strukt.visibility().map_or(String::new(), |v| format!("{} ", v)); + let vis = strukt.visibility().map_or(String::new(), |v| format!("{v} ")); let (ty, body) = if mutable { - (format!("&mut {}", field_ty), format!("&mut self.{}", field_name)) + (format!("&mut {field_ty}"), format!("&mut self.{field_name}")) } else { (|| { let krate = ctx.sema.scope(field_ty.syntax())?.krate(); @@ -126,19 +126,15 @@ pub(crate) fn generate_getter_impl( ) }) })() - .unwrap_or_else(|| (format!("&{}", field_ty), format!("&self.{}", field_name))) + .unwrap_or_else(|| (format!("&{field_ty}"), format!("&self.{field_name}"))) }; + let mut_ = mutable.then(|| "mut ").unwrap_or_default(); format_to!( buf, - " {}fn {}(&{}self) -> {} {{ - {} - }}", - vis, - fn_name, - mutable.then(|| "mut ").unwrap_or_default(), - ty, - body, + " {vis}fn {fn_name}(&{mut_}self) -> {ty} {{ + {body} + }}" ); let start_offset = impl_def diff --git a/crates/ide-assists/src/handlers/generate_impl.rs b/crates/ide-assists/src/handlers/generate_impl.rs index 307cea3d0a4f..9af26c04eb45 100644 --- a/crates/ide-assists/src/handlers/generate_impl.rs +++ b/crates/ide-assists/src/handlers/generate_impl.rs @@ -28,7 +28,7 @@ pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio acc.add( AssistId("generate_impl", AssistKind::Generate), - format!("Generate impl for `{}`", name), + format!("Generate impl for `{name}`"), target, |edit| { let start_offset = nominal.syntax().text_range().end(); diff --git a/crates/ide-assists/src/handlers/generate_new.rs b/crates/ide-assists/src/handlers/generate_new.rs index 9cda74d9e0d3..c441a2dc48e4 100644 --- a/crates/ide-assists/src/handlers/generate_new.rs +++ b/crates/ide-assists/src/handlers/generate_new.rs @@ -51,11 +51,13 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option buf.push('\n'); } - let vis = strukt.visibility().map_or(String::new(), |v| format!("{} ", v)); + let vis = strukt.visibility().map_or(String::new(), |v| format!("{v} ")); let trivial_constructors = field_list .fields() .map(|f| { + let name = f.name()?; + let ty = ctx.sema.resolve_type(&f.ty()?)?; let item_in_ns = hir::ItemInNs::from(hir::ModuleDef::from(ty.as_adt()?)); @@ -72,7 +74,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option &ty, )?; - Some(format!("{}: {}", f.name()?.syntax(), expr)) + Some(format!("{name}: {expr}")) }) .collect::>(); @@ -81,7 +83,10 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option .enumerate() .filter_map(|(i, f)| { if trivial_constructors[i].is_none() { - Some(format!("{}: {}", f.name()?.syntax(), f.ty()?.syntax())) + let name = f.name()?; + let ty = f.ty()?; + + Some(format!("{name}: {ty}")) } else { None } @@ -101,7 +106,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option }) .format(", "); - format_to!(buf, " {}fn new({}) -> Self {{ Self {{ {} }} }}", vis, params, fields); + format_to!(buf, " {vis}fn new({params}) -> Self {{ Self {{ {fields} }} }}"); let start_offset = impl_def .and_then(|impl_def| find_impl_block_start(impl_def, &mut buf)) diff --git a/crates/ide-assists/src/handlers/generate_setter.rs b/crates/ide-assists/src/handlers/generate_setter.rs index 2a7ad6ce3681..e139bcb1a1b0 100644 --- a/crates/ide-assists/src/handlers/generate_setter.rs +++ b/crates/ide-assists/src/handlers/generate_setter.rs @@ -39,7 +39,7 @@ pub(crate) fn generate_setter(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt let impl_def = find_struct_impl( ctx, &ast::Adt::Struct(strukt.clone()), - format!("set_{}", fn_name).as_str(), + format!("set_{fn_name}").as_str(), )?; let target = field.syntax().text_range(); @@ -55,18 +55,12 @@ pub(crate) fn generate_setter(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt buf.push('\n'); } - let vis = strukt.visibility().map_or(String::new(), |v| format!("{} ", v)); + let vis = strukt.visibility().map_or(String::new(), |v| format!("{v} ")); format_to!( buf, - " {}fn set_{}(&mut self, {}: {}) {{ - self.{} = {}; - }}", - vis, - fn_name, - fn_name, - field_ty, - fn_name, - fn_name, + " {vis}fn set_{fn_name}(&mut self, {fn_name}: {field_ty}) {{ + self.{fn_name} = {fn_name}; + }}" ); let start_offset = impl_def From 328f81713cc80861fb79c629e4887de1a8b7bf05 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 12 Oct 2022 12:57:16 +0200 Subject: [PATCH 007/171] Make `CStr::from_ptr` `const`. --- library/core/src/ffi/c_str.rs | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 55e58c4e0baa..ae15be793414 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -240,7 +240,9 @@ impl CStr { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr { + #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")] + #[rustc_allow_const_fn_unstable(const_eval_select)] + pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr { // SAFETY: The caller has provided a pointer that points to a valid C // string with a NUL terminator of size less than `isize::MAX`, whose // content remain valid and doesn't change for the lifetime of the @@ -252,13 +254,29 @@ impl CStr { // // The cast from c_char to u8 is ok because a c_char is always one byte. unsafe { - extern "C" { - /// Provided by libc or compiler_builtins. - fn strlen(s: *const c_char) -> usize; + const fn strlen_ct(s: *const c_char) -> usize { + let mut len = 0; + + // SAFETY: Outer caller has provided a pointer to a valid C string. + while unsafe { *s.add(len) } != 0 { + len += 1; + } + + len } - let len = strlen(ptr); - let ptr = ptr as *const u8; - CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1)) + + fn strlen_rt(s: *const c_char) -> usize { + extern "C" { + /// Provided by libc or compiler_builtins. + fn strlen(s: *const c_char) -> usize; + } + + // SAFETY: Outer caller has provided a pointer to a valid C string. + unsafe { strlen(s) } + } + + let len = intrinsics::const_eval_select((ptr,), strlen_ct, strlen_rt); + Self::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr.cast(), len + 1)) } } From 36dbb07dafe59c4d1491c2fbff6971d653f2ff77 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 12 Oct 2022 13:12:27 +0200 Subject: [PATCH 008/171] Update docs for `CStr::from_ptr`. --- library/core/src/ffi/c_str.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index ae15be793414..9f7c960d88fe 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -221,9 +221,7 @@ impl CStr { /// # Examples /// /// ```ignore (extern-declaration) - /// # fn main() { - /// use std::ffi::CStr; - /// use std::os::raw::c_char; + /// use std::ffi::{c_char, CStr}; /// /// extern "C" { /// fn my_string() -> *const c_char; @@ -233,7 +231,18 @@ impl CStr { /// let slice = CStr::from_ptr(my_string()); /// println!("string returned: {}", slice.to_str().unwrap()); /// } - /// # } + /// ``` + /// + /// ``` + /// #![feature(const_cstr_methods)] + /// + /// use std::ffi::{c_char, CStr}; + /// + /// const HELLO_PTR: *const c_char = { + /// const BYTES: &[u8] = b"Hello, world!\0"; + /// BYTES.as_ptr().cast() + /// }; + /// const HELLO: &CStr = unsafe { CStr::from_ptr(HELLO_PTR) }; /// ``` /// /// [valid]: core::ptr#safety From 9363a1401e2d0061c810504c7be169badd5a910b Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Fri, 14 Oct 2022 14:09:30 -0400 Subject: [PATCH 009/171] Add test case for MIR inlining debuginfo line numbers --- src/test/codegen/mir-inlined-line-numbers.rs | 25 ++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/test/codegen/mir-inlined-line-numbers.rs diff --git a/src/test/codegen/mir-inlined-line-numbers.rs b/src/test/codegen/mir-inlined-line-numbers.rs new file mode 100644 index 000000000000..53efe0f5be5b --- /dev/null +++ b/src/test/codegen/mir-inlined-line-numbers.rs @@ -0,0 +1,25 @@ +// compile-flags: -O -g + +#![crate_type = "lib"] + +#[inline(always)] +fn foo() { + bar(); +} + +#[inline(never)] +#[no_mangle] +fn bar() { + panic!(); +} + +#[no_mangle] +pub fn example() { + foo(); +} + +// CHECK-LABEL: @example +// CHECK: tail call void @bar(), !dbg [[DBG_ID:![0-9]+]] +// CHECK: [[DBG_ID]] = !DILocation(line: 18, +// CHECK-SAME: inlinedAt: [[INLINE_ID:![0-9]+]]) +// CHECK: [[INLINE_ID]] = !DILocation(line: 18, From 34d90a46dac95d6f09cd8851b71b43350eecda4d Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Fri, 14 Oct 2022 18:44:30 -0400 Subject: [PATCH 010/171] Fix line numbers for MIR inlined code `should_collapse_debuginfo` detects if the specified span is part of a macro expansion however it does this by checking if the span is anything other than a normal (non-expanded) kind, then the span sequence is walked backwards to the root span. This doesn't work when the MIR inliner inlines code as it creates spans with expansion information set to `ExprKind::Inlined` and results in the line number being attributed to the inline callsite rather than the normal line number of the inlined code. --- compiler/rustc_middle/src/ty/mod.rs | 4 +++- compiler/rustc_span/src/lib.rs | 8 +++++++- src/test/codegen/mir-inlined-line-numbers.rs | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 0d7d4054bb3c..34938ab05cb9 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2522,7 +2522,9 @@ impl<'tcx> TyCtxt<'tcx> { && if self.features().collapse_debuginfo { span.in_macro_expansion_with_collapse_debuginfo() } else { - span.from_expansion() + // Inlined spans should not be collapsed as that leads to all of the + // inlined code being attributed to the inline callsite. + span.from_expansion() && !span.is_inlined() } } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 91eef647713d..ec5491116e87 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -558,7 +558,7 @@ impl Span { self.data_untracked().is_dummy() } - /// Returns `true` if this span comes from a macro or desugaring. + /// Returns `true` if this span comes from any kind of macro, desugaring or inlining. #[inline] pub fn from_expansion(self) -> bool { self.ctxt() != SyntaxContext::root() @@ -571,6 +571,12 @@ impl Span { matches!(outer_expn.kind, ExpnKind::Macro(..)) && outer_expn.collapse_debuginfo } + /// Returns `true` if this span comes from MIR inlining. + pub fn is_inlined(self) -> bool { + let outer_expn = self.ctxt().outer_expn_data(); + matches!(outer_expn.kind, ExpnKind::Inlined) + } + /// Returns `true` if `span` originates in a derive-macro's expansion. pub fn in_derive_expansion(self) -> bool { matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _)) diff --git a/src/test/codegen/mir-inlined-line-numbers.rs b/src/test/codegen/mir-inlined-line-numbers.rs index 53efe0f5be5b..19d83f0eee7c 100644 --- a/src/test/codegen/mir-inlined-line-numbers.rs +++ b/src/test/codegen/mir-inlined-line-numbers.rs @@ -20,6 +20,6 @@ pub fn example() { // CHECK-LABEL: @example // CHECK: tail call void @bar(), !dbg [[DBG_ID:![0-9]+]] -// CHECK: [[DBG_ID]] = !DILocation(line: 18, +// CHECK: [[DBG_ID]] = !DILocation(line: 7, // CHECK-SAME: inlinedAt: [[INLINE_ID:![0-9]+]]) // CHECK: [[INLINE_ID]] = !DILocation(line: 18, From 73d655e9c2106566f328de28aeff6fd3a8ee8e21 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 16 Oct 2022 10:38:48 +0200 Subject: [PATCH 011/171] remove redundant Send impls for references also move them next to the trait they are implementing --- library/core/src/marker.rs | 13 ++++++------- src/test/ui/async-await/async-fn-nonsend.stderr | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index d5ed52124e2c..bb10caee6e2d 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -44,6 +44,12 @@ impl !Send for *const T {} #[stable(feature = "rust1", since = "1.0.0")] impl !Send for *mut T {} +// Most instances arise automatically, but this instance is needed to link up `T: Sync` with +// `&T: Send` (and it also removes the unsound default instance `T Send` -> `&T: Send` that would +// otherwise exist). +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for &T {} + /// Types with a constant size known at compile time. /// /// All type parameters have an implicit bound of `Sized`. The special syntax @@ -680,13 +686,6 @@ pub struct PhantomData; impls! { PhantomData } -mod impls { - #[stable(feature = "rust1", since = "1.0.0")] - unsafe impl Send for &T {} - #[stable(feature = "rust1", since = "1.0.0")] - unsafe impl Send for &mut T {} -} - /// Compiler-internal trait used to indicate the type of enum discriminants. /// /// This trait is automatically implemented for every type and does not add any diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr index 40ad46b48620..a7b872fe4444 100644 --- a/src/test/ui/async-await/async-fn-nonsend.stderr +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -27,7 +27,7 @@ error: future cannot be sent between threads safely LL | assert_send(non_sync_with_method_call()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` | - = help: the trait `Send` is not implemented for `dyn std::fmt::Write` + = help: within `impl Future`, the trait `Send` is not implemented for `dyn std::fmt::Write` note: future is not `Send` as this value is used across an await --> $DIR/async-fn-nonsend.rs:46:14 | From d5f467aa4a6b28ffa6acb7673bfea472fdcd64c8 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 16 Oct 2022 17:11:24 +0200 Subject: [PATCH 012/171] Substitute some VSCode variables in the VSCode client --- editors/code/src/client.ts | 26 ++++++++++-- editors/code/src/config.ts | 85 +++++++++++++++++++++++++------------- 2 files changed, 79 insertions(+), 32 deletions(-) diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts index 05d4d08f70b6..45a7970b2171 100644 --- a/editors/code/src/client.ts +++ b/editors/code/src/client.ts @@ -5,7 +5,7 @@ import * as Is from "vscode-languageclient/lib/common/utils/is"; import { assert } from "./util"; import { WorkspaceEdit } from "vscode"; import { Workspace } from "./ctx"; -import { substituteVariablesInEnv } from "./config"; +import { substituteVariablesInEnv, substituteVSCodeVariables } from "./config"; import { outputChannel, traceOutputChannel } from "./main"; import { randomUUID } from "crypto"; @@ -83,15 +83,17 @@ export async function createClient( debug: run, }; - let initializationOptions = vscode.workspace.getConfiguration("rust-analyzer"); + let rawInitializationOptions = vscode.workspace.getConfiguration("rust-analyzer"); if (workspace.kind === "Detached Files") { - initializationOptions = { + rawInitializationOptions = { detachedFiles: workspace.files.map((file) => file.uri.fsPath), - ...initializationOptions, + ...rawInitializationOptions, }; } + const initializationOptions = substituteVSCodeVariables(rawInitializationOptions); + const clientOptions: lc.LanguageClientOptions = { documentSelector: [{ scheme: "file", language: "rust" }], initializationOptions, @@ -99,6 +101,22 @@ export async function createClient( traceOutputChannel: traceOutputChannel(), outputChannel: outputChannel(), middleware: { + workspace: { + async configuration( + params: lc.ConfigurationParams, + token: vscode.CancellationToken, + next: lc.ConfigurationRequest.HandlerSignature + ) { + const resp = await next(params, token); + if (resp && Array.isArray(resp)) { + return resp.map((val) => { + return substituteVSCodeVariables(val); + }); + } else { + return resp; + } + }, + }, async provideHover( document: vscode.TextDocument, position: vscode.Position, diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 15846a5e8645..199db6e30fc5 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -1,4 +1,5 @@ -import path = require("path"); +import * as path from "path"; +import * as os from "os"; import * as vscode from "vscode"; import { Env } from "./client"; import { log } from "./util"; @@ -187,6 +188,37 @@ export class Config { } } +const VarRegex = new RegExp(/\$\{(.+?)\}/g); + +export function substituteVSCodeVariableInString(val: string): string { + return val.replaceAll(VarRegex, (substring: string, varName) => { + if (typeof varName === "string") { + return computeVscodeVar(varName) || substring; + } else { + return substring; + } + }); +} + +export function substituteVSCodeVariables(resp: any): any { + if (typeof resp === "string") { + return substituteVSCodeVariableInString(resp); + } else if (resp && Array.isArray(resp)) { + return resp.map((val) => { + return substituteVSCodeVariables(val); + }); + } else if (resp && typeof resp === "object") { + const res: { [key: string]: any } = {}; + for (const key in resp) { + const val = resp[key]; + res[key] = substituteVSCodeVariables(val); + } + return res; + } else if (typeof resp === "function") { + return null; + } + return resp; +} export function substituteVariablesInEnv(env: Env): Env { const missingDeps = new Set(); // vscode uses `env:ENV_NAME` for env vars resolution, and it's easier @@ -233,7 +265,7 @@ export function substituteVariablesInEnv(env: Env): Env { } } else { envWithDeps[dep] = { - value: computeVscodeVar(dep), + value: computeVscodeVar(dep) || "${" + dep + "}", deps: [], }; } @@ -264,37 +296,34 @@ export function substituteVariablesInEnv(env: Env): Env { return resolvedEnv; } -function computeVscodeVar(varName: string): string { +function computeVscodeVar(varName: string): string | null { + const workspaceFolder = () => { + const folders = vscode.workspace.workspaceFolders ?? []; + if (folders.length === 1) { + // TODO: support for remote workspaces? + return folders[0].uri.fsPath; + } else if (folders.length > 1) { + // could use currently opened document to detect the correct + // workspace. However, that would be determined by the document + // user has opened on Editor startup. Could lead to + // unpredictable workspace selection in practice. + // It's better to pick the first one + return folders[0].uri.fsPath; + } else { + // no workspace opened + return ""; + } + }; // https://code.visualstudio.com/docs/editor/variables-reference const supportedVariables: { [k: string]: () => string } = { - workspaceFolder: () => { - const folders = vscode.workspace.workspaceFolders ?? []; - if (folders.length === 1) { - // TODO: support for remote workspaces? - return folders[0].uri.fsPath; - } else if (folders.length > 1) { - // could use currently opened document to detect the correct - // workspace. However, that would be determined by the document - // user has opened on Editor startup. Could lead to - // unpredictable workspace selection in practice. - // It's better to pick the first one - return folders[0].uri.fsPath; - } else { - // no workspace opened - return ""; - } - }, + workspaceFolder, workspaceFolderBasename: () => { - const workspaceFolder = computeVscodeVar("workspaceFolder"); - if (workspaceFolder) { - return path.basename(workspaceFolder); - } else { - return ""; - } + return path.basename(workspaceFolder()); }, cwd: () => process.cwd(), + userHome: () => os.homedir(), // see // https://github.com/microsoft/vscode/blob/08ac1bb67ca2459496b272d8f4a908757f24f56f/src/vs/workbench/api/common/extHostVariableResolverService.ts#L81 @@ -308,7 +337,7 @@ function computeVscodeVar(varName: string): string { if (varName in supportedVariables) { return supportedVariables[varName](); } else { - // can't resolve, keep the expression as is - return "${" + varName + "}"; + // return "${" + varName + "}"; + return null; } } From 3e904197950d273b7d87fe05bf7e3ec23db9794a Mon Sep 17 00:00:00 2001 From: bogon-right Date: Mon, 17 Oct 2022 04:03:23 +0800 Subject: [PATCH 013/171] Add tests for autoderef on block tail --- .../ui/coercion/coerce-block-tail-26978.rs | 11 ++++++ .../coercion/coerce-block-tail-26978.stderr | 16 +++++++++ .../ui/coercion/coerce-block-tail-57749.rs | 35 +++++++++++++++++++ .../coercion/coerce-block-tail-57749.stderr | 14 ++++++++ .../ui/coercion/coerce-block-tail-83783.rs | 13 +++++++ .../coercion/coerce-block-tail-83783.stderr | 12 +++++++ .../ui/coercion/coerce-block-tail-83850.rs | 7 ++++ .../coercion/coerce-block-tail-83850.stderr | 19 ++++++++++ src/test/ui/coercion/coerce-block-tail.rs | 6 ++++ src/test/ui/coercion/coerce-block-tail.stderr | 16 +++++++++ 10 files changed, 149 insertions(+) create mode 100644 src/test/ui/coercion/coerce-block-tail-26978.rs create mode 100644 src/test/ui/coercion/coerce-block-tail-26978.stderr create mode 100644 src/test/ui/coercion/coerce-block-tail-57749.rs create mode 100644 src/test/ui/coercion/coerce-block-tail-57749.stderr create mode 100644 src/test/ui/coercion/coerce-block-tail-83783.rs create mode 100644 src/test/ui/coercion/coerce-block-tail-83783.stderr create mode 100644 src/test/ui/coercion/coerce-block-tail-83850.rs create mode 100644 src/test/ui/coercion/coerce-block-tail-83850.stderr create mode 100644 src/test/ui/coercion/coerce-block-tail.rs create mode 100644 src/test/ui/coercion/coerce-block-tail.stderr diff --git a/src/test/ui/coercion/coerce-block-tail-26978.rs b/src/test/ui/coercion/coerce-block-tail-26978.rs new file mode 100644 index 000000000000..01c8ab5a839f --- /dev/null +++ b/src/test/ui/coercion/coerce-block-tail-26978.rs @@ -0,0 +1,11 @@ +// check-fail +fn f(_: &i32) {} + +fn main() { + let x = Box::new(1i32); + + f(&x); + f(&(x)); + f(&{x}); + //~^ ERROR mismatched types +} diff --git a/src/test/ui/coercion/coerce-block-tail-26978.stderr b/src/test/ui/coercion/coerce-block-tail-26978.stderr new file mode 100644 index 000000000000..384debd487c5 --- /dev/null +++ b/src/test/ui/coercion/coerce-block-tail-26978.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/coerce-block-tail-26978.rs:9:9 + | +LL | f(&{x}); + | ^ expected `i32`, found struct `Box` + | + = note: expected type `i32` + found struct `Box` +help: consider unboxing the value + | +LL | f(&{*x}); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/coercion/coerce-block-tail-57749.rs b/src/test/ui/coercion/coerce-block-tail-57749.rs new file mode 100644 index 000000000000..79b5b33233b3 --- /dev/null +++ b/src/test/ui/coercion/coerce-block-tail-57749.rs @@ -0,0 +1,35 @@ +// check-fail +use std::ops::Deref; + +fn main() { + fn save(who: &str) { + println!("I'll save you, {}!", who); + } + + struct Madoka; + + impl Deref for Madoka { + type Target = str; + fn deref(&self) -> &Self::Target { + "Madoka" + } + } + + save(&{ Madoka }); + + fn reset(how: &u32) { + println!("Reset {} times", how); + } + + struct Homura; + + impl Deref for Homura { + type Target = u32; + fn deref(&self) -> &Self::Target { + &42 + } + } + + reset(&{ Homura }); + //~^ ERROR mismatched types +} diff --git a/src/test/ui/coercion/coerce-block-tail-57749.stderr b/src/test/ui/coercion/coerce-block-tail-57749.stderr new file mode 100644 index 000000000000..d5660c81dbd3 --- /dev/null +++ b/src/test/ui/coercion/coerce-block-tail-57749.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/coerce-block-tail-57749.rs:33:14 + | +LL | reset(&{ Homura }); + | ^^^^^^ expected `u32`, found struct `Homura` + | +help: consider dereferencing the type + | +LL | reset(&{ *Homura }); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/coercion/coerce-block-tail-83783.rs b/src/test/ui/coercion/coerce-block-tail-83783.rs new file mode 100644 index 000000000000..18c8ae3bbbad --- /dev/null +++ b/src/test/ui/coercion/coerce-block-tail-83783.rs @@ -0,0 +1,13 @@ +// check-fail +// edition:2018 +fn _consume_reference(_: &T) {} + +async fn _foo() { + _consume_reference::(&Box::new(7_i32)); + _consume_reference::(&async { Box::new(7_i32) }.await); + //~^ ERROR mismatched types + _consume_reference::<[i32]>(&vec![7_i32]); + _consume_reference::<[i32]>(&async { vec![7_i32] }.await); +} + +fn main() { } diff --git a/src/test/ui/coercion/coerce-block-tail-83783.stderr b/src/test/ui/coercion/coerce-block-tail-83783.stderr new file mode 100644 index 000000000000..5f53606ce222 --- /dev/null +++ b/src/test/ui/coercion/coerce-block-tail-83783.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/coerce-block-tail-83783.rs:7:32 + | +LL | _consume_reference::(&async { Box::new(7_i32) }.await); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `Box` + | + = note: expected type `i32` + found struct `Box` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/coercion/coerce-block-tail-83850.rs b/src/test/ui/coercion/coerce-block-tail-83850.rs new file mode 100644 index 000000000000..77fdf9998333 --- /dev/null +++ b/src/test/ui/coercion/coerce-block-tail-83850.rs @@ -0,0 +1,7 @@ +// check-fail +fn f(_: &[i32]) {} + +fn main() { + f(&Box::new([1, 2])); + //~^ ERROR mismatched types +} diff --git a/src/test/ui/coercion/coerce-block-tail-83850.stderr b/src/test/ui/coercion/coerce-block-tail-83850.stderr new file mode 100644 index 000000000000..bbf607543704 --- /dev/null +++ b/src/test/ui/coercion/coerce-block-tail-83850.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/coerce-block-tail-83850.rs:5:7 + | +LL | f(&Box::new([1, 2])); + | - ^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found struct `Box` + | | + | arguments to this function are incorrect + | + = note: expected reference `&[i32]` + found reference `&Box<[{integer}; 2]>` +note: function defined here + --> $DIR/coerce-block-tail-83850.rs:2:4 + | +LL | fn f(_: &[i32]) {} + | ^ --------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/coercion/coerce-block-tail.rs b/src/test/ui/coercion/coerce-block-tail.rs new file mode 100644 index 000000000000..dcbcd3762862 --- /dev/null +++ b/src/test/ui/coercion/coerce-block-tail.rs @@ -0,0 +1,6 @@ +// check-fail +fn main() { + let _: &str = & { String::from("hahah")}; + let _: &i32 = & { Box::new(1i32) }; + //~^ ERROR mismatched types +} diff --git a/src/test/ui/coercion/coerce-block-tail.stderr b/src/test/ui/coercion/coerce-block-tail.stderr new file mode 100644 index 000000000000..318cf75867b4 --- /dev/null +++ b/src/test/ui/coercion/coerce-block-tail.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/coerce-block-tail.rs:4:23 + | +LL | let _: &i32 = & { Box::new(1i32) }; + | ^^^^^^^^^^^^^^ expected `i32`, found struct `Box` + | + = note: expected type `i32` + found struct `Box` +help: consider unboxing the value + | +LL | let _: &i32 = & { *Box::new(1i32) }; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 6f435977df34e722b45d787d7eadac23cf5b040e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 17 Oct 2022 14:20:14 +0200 Subject: [PATCH 014/171] Refactor language client handling --- editors/code/package-lock.json | 78 ++++---- editors/code/package.json | 4 +- editors/code/src/ast_inspector.ts | 8 +- editors/code/src/bootstrap.ts | 148 +++++++++++++++ editors/code/src/client.ts | 43 +---- editors/code/src/commands.ts | 183 +++++++++---------- editors/code/src/ctx.ts | 135 +++++++++++--- editors/code/src/main.ts | 294 ++++++------------------------ 8 files changed, 456 insertions(+), 437 deletions(-) create mode 100644 editors/code/src/bootstrap.ts diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index 3ff4b6897a16..192d8fabc317 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json @@ -11,11 +11,11 @@ "dependencies": { "d3": "^7.6.1", "d3-graphviz": "^4.1.1", - "vscode-languageclient": "^8.0.0-next.14" + "vscode-languageclient": "^8.0.2" }, "devDependencies": { "@types/node": "~16.11.7", - "@types/vscode": "~1.66.0", + "@types/vscode": "~1.72.0", "@typescript-eslint/eslint-plugin": "^5.30.5", "@typescript-eslint/parser": "^5.30.5", "@vscode/test-electron": "^2.1.5", @@ -141,9 +141,9 @@ "dev": true }, "node_modules/@types/vscode": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.66.0.tgz", - "integrity": "sha512-ZfJck4M7nrGasfs4A4YbUoxis3Vu24cETw3DERsNYtDZmYSYtk6ljKexKFKhImO/ZmY6ZMsmegu2FPkXoUFImA==", + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.72.0.tgz", + "integrity": "sha512-WvHluhUo+lQvE3I4wUagRpnkHuysB4qSyOQUyIAS9n9PYMJjepzTUD8Jyks0YeXoPD0UGctjqp2u84/b3v6Ydw==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { @@ -3791,39 +3791,39 @@ } }, "node_modules/vscode-jsonrpc": { - "version": "8.0.0-next.7", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.0-next.7.tgz", - "integrity": "sha512-JX/F31LEsims0dAlOTKFE4E+AJMiJvdRSRViifFJSqSN7EzeYyWlfuDchF7g91oRNPZOIWfibTkDf3/UMsQGzQ==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.2.tgz", + "integrity": "sha512-RY7HwI/ydoC1Wwg4gJ3y6LpU9FJRZAUnTYMXthqhFXXu77ErDd/xkREpGuk4MyYkk4a+XDWAMqe0S3KkelYQEQ==", "engines": { "node": ">=14.0.0" } }, "node_modules/vscode-languageclient": { - "version": "8.0.0-next.14", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.0.0-next.14.tgz", - "integrity": "sha512-NqjkOuDTMu8uo+PhoMsV72VO9Gd3wBi/ZpOrkRUOrWKQo7yUdiIw183g8wjH8BImgbK9ZP51HM7TI0ZhCnI1Mw==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.0.2.tgz", + "integrity": "sha512-lHlthJtphG9gibGb/y72CKqQUxwPsMXijJVpHEC2bvbFqxmkj9LwQ3aGU9dwjBLqsX1S4KjShYppLvg1UJDF/Q==", "dependencies": { "minimatch": "^3.0.4", "semver": "^7.3.5", - "vscode-languageserver-protocol": "3.17.0-next.16" + "vscode-languageserver-protocol": "3.17.2" }, "engines": { - "vscode": "^1.66.0" + "vscode": "^1.67.0" } }, "node_modules/vscode-languageserver-protocol": { - "version": "3.17.0-next.16", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.0-next.16.tgz", - "integrity": "sha512-tx4DnXw9u3N7vw+bx6n2NKp6FoxoNwiP/biH83AS30I2AnTGyLd7afSeH6Oewn2E8jvB7K15bs12sMppkKOVeQ==", + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.2.tgz", + "integrity": "sha512-8kYisQ3z/SQ2kyjlNeQxbkkTNmVFoQCqkmGrzLH6A9ecPlgTbp3wDTnUNqaUxYr4vlAcloxx8zwy7G5WdguYNg==", "dependencies": { - "vscode-jsonrpc": "8.0.0-next.7", - "vscode-languageserver-types": "3.17.0-next.9" + "vscode-jsonrpc": "8.0.2", + "vscode-languageserver-types": "3.17.2" } }, "node_modules/vscode-languageserver-types": { - "version": "3.17.0-next.9", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.0-next.9.tgz", - "integrity": "sha512-9/PeDNPYduaoXRUzYpqmu4ZV9L01HGo0wH9FUt+sSHR7IXwA7xoXBfNUlv8gB9H0D2WwEmMomSy1NmhjKQyn3A==" + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz", + "integrity": "sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==" }, "node_modules/which": { "version": "2.0.2", @@ -4039,9 +4039,9 @@ "dev": true }, "@types/vscode": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.66.0.tgz", - "integrity": "sha512-ZfJck4M7nrGasfs4A4YbUoxis3Vu24cETw3DERsNYtDZmYSYtk6ljKexKFKhImO/ZmY6ZMsmegu2FPkXoUFImA==", + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.72.0.tgz", + "integrity": "sha512-WvHluhUo+lQvE3I4wUagRpnkHuysB4qSyOQUyIAS9n9PYMJjepzTUD8Jyks0YeXoPD0UGctjqp2u84/b3v6Ydw==", "dev": true }, "@typescript-eslint/eslint-plugin": { @@ -6634,33 +6634,33 @@ } }, "vscode-jsonrpc": { - "version": "8.0.0-next.7", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.0-next.7.tgz", - "integrity": "sha512-JX/F31LEsims0dAlOTKFE4E+AJMiJvdRSRViifFJSqSN7EzeYyWlfuDchF7g91oRNPZOIWfibTkDf3/UMsQGzQ==" + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.2.tgz", + "integrity": "sha512-RY7HwI/ydoC1Wwg4gJ3y6LpU9FJRZAUnTYMXthqhFXXu77ErDd/xkREpGuk4MyYkk4a+XDWAMqe0S3KkelYQEQ==" }, "vscode-languageclient": { - "version": "8.0.0-next.14", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.0.0-next.14.tgz", - "integrity": "sha512-NqjkOuDTMu8uo+PhoMsV72VO9Gd3wBi/ZpOrkRUOrWKQo7yUdiIw183g8wjH8BImgbK9ZP51HM7TI0ZhCnI1Mw==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.0.2.tgz", + "integrity": "sha512-lHlthJtphG9gibGb/y72CKqQUxwPsMXijJVpHEC2bvbFqxmkj9LwQ3aGU9dwjBLqsX1S4KjShYppLvg1UJDF/Q==", "requires": { "minimatch": "^3.0.4", "semver": "^7.3.5", - "vscode-languageserver-protocol": "3.17.0-next.16" + "vscode-languageserver-protocol": "3.17.2" } }, "vscode-languageserver-protocol": { - "version": "3.17.0-next.16", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.0-next.16.tgz", - "integrity": "sha512-tx4DnXw9u3N7vw+bx6n2NKp6FoxoNwiP/biH83AS30I2AnTGyLd7afSeH6Oewn2E8jvB7K15bs12sMppkKOVeQ==", + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.2.tgz", + "integrity": "sha512-8kYisQ3z/SQ2kyjlNeQxbkkTNmVFoQCqkmGrzLH6A9ecPlgTbp3wDTnUNqaUxYr4vlAcloxx8zwy7G5WdguYNg==", "requires": { - "vscode-jsonrpc": "8.0.0-next.7", - "vscode-languageserver-types": "3.17.0-next.9" + "vscode-jsonrpc": "8.0.2", + "vscode-languageserver-types": "3.17.2" } }, "vscode-languageserver-types": { - "version": "3.17.0-next.9", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.0-next.9.tgz", - "integrity": "sha512-9/PeDNPYduaoXRUzYpqmu4ZV9L01HGo0wH9FUt+sSHR7IXwA7xoXBfNUlv8gB9H0D2WwEmMomSy1NmhjKQyn3A==" + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz", + "integrity": "sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==" }, "which": { "version": "2.0.2", diff --git a/editors/code/package.json b/editors/code/package.json index f1dd3aa79ff0..da4bac5ad844 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -37,11 +37,11 @@ "dependencies": { "d3": "^7.6.1", "d3-graphviz": "^4.1.1", - "vscode-languageclient": "^8.0.0-next.14" + "vscode-languageclient": "^8.0.2" }, "devDependencies": { "@types/node": "~16.11.7", - "@types/vscode": "~1.66.0", + "@types/vscode": "~1.72.0", "@typescript-eslint/eslint-plugin": "^5.30.5", "@typescript-eslint/parser": "^5.30.5", "@vscode/test-electron": "^2.1.5", diff --git a/editors/code/src/ast_inspector.ts b/editors/code/src/ast_inspector.ts index e57fb20e2cf8..2a2c9326b6a0 100644 --- a/editors/code/src/ast_inspector.ts +++ b/editors/code/src/ast_inspector.ts @@ -35,8 +35,10 @@ export class AstInspector implements vscode.HoverProvider, vscode.DefinitionProv }); constructor(ctx: Ctx) { - ctx.pushCleanup(vscode.languages.registerHoverProvider({ scheme: "rust-analyzer" }, this)); - ctx.pushCleanup(vscode.languages.registerDefinitionProvider({ language: "rust" }, this)); + ctx.pushExtCleanup( + vscode.languages.registerHoverProvider({ scheme: "rust-analyzer" }, this) + ); + ctx.pushExtCleanup(vscode.languages.registerDefinitionProvider({ language: "rust" }, this)); vscode.workspace.onDidCloseTextDocument( this.onDidCloseTextDocument, this, @@ -53,7 +55,7 @@ export class AstInspector implements vscode.HoverProvider, vscode.DefinitionProv ctx.subscriptions ); - ctx.pushCleanup(this); + ctx.pushExtCleanup(this); } dispose() { this.setRustEditor(undefined); diff --git a/editors/code/src/bootstrap.ts b/editors/code/src/bootstrap.ts new file mode 100644 index 000000000000..374c3b8144c3 --- /dev/null +++ b/editors/code/src/bootstrap.ts @@ -0,0 +1,148 @@ +import * as vscode from "vscode"; +import * as os from "os"; +import { Config } from "./config"; +import { log, isValidExecutable } from "./util"; +import { PersistentState } from "./persistent_state"; +import { exec } from "child_process"; + +export async function bootstrap( + context: vscode.ExtensionContext, + config: Config, + state: PersistentState +): Promise { + const path = await getServer(context, config, state); + if (!path) { + throw new Error( + "Rust Analyzer Language Server is not available. " + + "Please, ensure its [proper installation](https://rust-analyzer.github.io/manual.html#installation)." + ); + } + + log.info("Using server binary at", path); + + if (!isValidExecutable(path)) { + if (config.serverPath) { + throw new Error(`Failed to execute ${path} --version. \`config.server.path\` or \`config.serverPath\` has been set explicitly.\ + Consider removing this config or making a valid server binary available at that path.`); + } else { + throw new Error(`Failed to execute ${path} --version`); + } + } + + return path; +} + +async function patchelf(dest: vscode.Uri): Promise { + await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: "Patching rust-analyzer for NixOS", + }, + async (progress, _) => { + const expression = ` + {srcStr, pkgs ? import {}}: + pkgs.stdenv.mkDerivation { + name = "rust-analyzer"; + src = /. + srcStr; + phases = [ "installPhase" "fixupPhase" ]; + installPhase = "cp $src $out"; + fixupPhase = '' + chmod 755 $out + patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" $out + ''; + } + `; + const origFile = vscode.Uri.file(dest.fsPath + "-orig"); + await vscode.workspace.fs.rename(dest, origFile, { overwrite: true }); + try { + progress.report({ message: "Patching executable", increment: 20 }); + await new Promise((resolve, reject) => { + const handle = exec( + `nix-build -E - --argstr srcStr '${origFile.fsPath}' -o '${dest.fsPath}'`, + (err, stdout, stderr) => { + if (err != null) { + reject(Error(stderr)); + } else { + resolve(stdout); + } + } + ); + handle.stdin?.write(expression); + handle.stdin?.end(); + }); + } finally { + await vscode.workspace.fs.delete(origFile); + } + } + ); +} + +async function getServer( + context: vscode.ExtensionContext, + config: Config, + state: PersistentState +): Promise { + const explicitPath = serverPath(config); + if (explicitPath) { + if (explicitPath.startsWith("~/")) { + return os.homedir() + explicitPath.slice("~".length); + } + return explicitPath; + } + if (config.package.releaseTag === null) return "rust-analyzer"; + + const ext = process.platform === "win32" ? ".exe" : ""; + const bundled = vscode.Uri.joinPath(context.extensionUri, "server", `rust-analyzer${ext}`); + const bundledExists = await vscode.workspace.fs.stat(bundled).then( + () => true, + () => false + ); + if (bundledExists) { + let server = bundled; + if (await isNixOs()) { + await vscode.workspace.fs.createDirectory(config.globalStorageUri).then(); + const dest = vscode.Uri.joinPath(config.globalStorageUri, `rust-analyzer${ext}`); + let exists = await vscode.workspace.fs.stat(dest).then( + () => true, + () => false + ); + if (exists && config.package.version !== state.serverVersion) { + await vscode.workspace.fs.delete(dest); + exists = false; + } + if (!exists) { + await vscode.workspace.fs.copy(bundled, dest); + await patchelf(dest); + } + server = dest; + } + await state.updateServerVersion(config.package.version); + return server.fsPath; + } + + await state.updateServerVersion(undefined); + await vscode.window.showErrorMessage( + "Unfortunately we don't ship binaries for your platform yet. " + + "You need to manually clone the rust-analyzer repository and " + + "run `cargo xtask install --server` to build the language server from sources. " + + "If you feel that your platform should be supported, please create an issue " + + "about that [here](https://github.com/rust-lang/rust-analyzer/issues) and we " + + "will consider it." + ); + return undefined; +} +function serverPath(config: Config): string | null { + return process.env.__RA_LSP_SERVER_DEBUG ?? config.serverPath; +} + +async function isNixOs(): Promise { + try { + const contents = ( + await vscode.workspace.fs.readFile(vscode.Uri.file("/etc/os-release")) + ).toString(); + const idString = contents.split("\n").find((a) => a.startsWith("ID=")) || "ID=linux"; + return idString.indexOf("nixos") !== -1; + } catch { + return false; + } +} diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts index 45a7970b2171..3408a2ee84ee 100644 --- a/editors/code/src/client.ts +++ b/editors/code/src/client.ts @@ -4,9 +4,7 @@ import * as ra from "../src/lsp_ext"; import * as Is from "vscode-languageclient/lib/common/utils/is"; import { assert } from "./util"; import { WorkspaceEdit } from "vscode"; -import { Workspace } from "./ctx"; -import { substituteVariablesInEnv, substituteVSCodeVariables } from "./config"; -import { outputChannel, traceOutputChannel } from "./main"; +import { substituteVSCodeVariables } from "./config"; import { randomUUID } from "crypto"; export interface Env { @@ -65,41 +63,17 @@ function renderHoverActions(actions: ra.CommandLinkGroup[]): vscode.MarkdownStri } export async function createClient( - serverPath: string, - workspace: Workspace, - extraEnv: Env + traceOutputChannel: vscode.OutputChannel, + outputChannel: vscode.OutputChannel, + initializationOptions: vscode.WorkspaceConfiguration, + serverOptions: lc.ServerOptions ): Promise { - // '.' Is the fallback if no folder is open - // TODO?: Workspace folders support Uri's (eg: file://test.txt). - // It might be a good idea to test if the uri points to a file. - - const newEnv = substituteVariablesInEnv(Object.assign({}, process.env, extraEnv)); - const run: lc.Executable = { - command: serverPath, - options: { env: newEnv }, - }; - const serverOptions: lc.ServerOptions = { - run, - debug: run, - }; - - let rawInitializationOptions = vscode.workspace.getConfiguration("rust-analyzer"); - - if (workspace.kind === "Detached Files") { - rawInitializationOptions = { - detachedFiles: workspace.files.map((file) => file.uri.fsPath), - ...rawInitializationOptions, - }; - } - - const initializationOptions = substituteVSCodeVariables(rawInitializationOptions); - const clientOptions: lc.LanguageClientOptions = { documentSelector: [{ scheme: "file", language: "rust" }], initializationOptions, diagnosticCollectionName: "rustc", - traceOutputChannel: traceOutputChannel(), - outputChannel: outputChannel(), + traceOutputChannel, + outputChannel, middleware: { workspace: { async configuration( @@ -273,6 +247,9 @@ export async function createClient( } class ExperimentalFeatures implements lc.StaticFeature { + getState(): lc.FeatureState { + return { kind: "static" }; + } fillClientCapabilities(capabilities: lc.ClientCapabilities): void { const caps: any = capabilities.experimental ?? {}; caps.snippetTextEdit = true; diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts index b9ad525e361f..cbdeb28c99fe 100644 --- a/editors/code/src/commands.ts +++ b/editors/code/src/commands.ts @@ -21,16 +21,16 @@ export function analyzerStatus(ctx: Ctx): Cmd { readonly uri = vscode.Uri.parse("rust-analyzer-status://status"); readonly eventEmitter = new vscode.EventEmitter(); - provideTextDocumentContent(_uri: vscode.Uri): vscode.ProviderResult { + async provideTextDocumentContent(_uri: vscode.Uri): Promise { if (!vscode.window.activeTextEditor) return ""; + const client = await ctx.getClient(); const params: ra.AnalyzerStatusParams = {}; const doc = ctx.activeRustEditor?.document; if (doc != null) { - params.textDocument = - ctx.client.code2ProtocolConverter.asTextDocumentIdentifier(doc); + params.textDocument = client.code2ProtocolConverter.asTextDocumentIdentifier(doc); } - return ctx.client.sendRequest(ra.analyzerStatus, params); + return await client.sendRequest(ra.analyzerStatus, params); } get onDidChange(): vscode.Event { @@ -38,7 +38,7 @@ export function analyzerStatus(ctx: Ctx): Cmd { } })(); - ctx.pushCleanup( + ctx.pushExtCleanup( vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-status", tdcp) ); @@ -60,9 +60,14 @@ export function memoryUsage(ctx: Ctx): Cmd { provideTextDocumentContent(_uri: vscode.Uri): vscode.ProviderResult { if (!vscode.window.activeTextEditor) return ""; - return ctx.client.sendRequest(ra.memoryUsage).then((mem: any) => { - return "Per-query memory usage:\n" + mem + "\n(note: database has been cleared)"; - }); + return ctx + .getClient() + .then((it) => it.sendRequest(ra.memoryUsage)) + .then((mem: any) => { + return ( + "Per-query memory usage:\n" + mem + "\n(note: database has been cleared)" + ); + }); } get onDidChange(): vscode.Event { @@ -70,7 +75,7 @@ export function memoryUsage(ctx: Ctx): Cmd { } })(); - ctx.pushCleanup( + ctx.pushExtCleanup( vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-memory", tdcp) ); @@ -83,23 +88,19 @@ export function memoryUsage(ctx: Ctx): Cmd { export function shuffleCrateGraph(ctx: Ctx): Cmd { return async () => { - const client = ctx.client; - if (!client) return; - - await client.sendRequest(ra.shuffleCrateGraph); + return ctx.getClient().then((it) => it.sendRequest(ra.shuffleCrateGraph)); }; } export function matchingBrace(ctx: Ctx): Cmd { return async () => { const editor = ctx.activeRustEditor; - const client = ctx.client; - if (!editor || !client) return; + if (!editor) return; + + const client = await ctx.getClient(); const response = await client.sendRequest(ra.matchingBrace, { - textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier( - editor.document - ), + textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document), positions: editor.selections.map((s) => client.code2ProtocolConverter.asPosition(s.active) ), @@ -116,14 +117,13 @@ export function matchingBrace(ctx: Ctx): Cmd { export function joinLines(ctx: Ctx): Cmd { return async () => { const editor = ctx.activeRustEditor; - const client = ctx.client; - if (!editor || !client) return; + if (!editor) return; + + const client = await ctx.getClient(); const items: lc.TextEdit[] = await client.sendRequest(ra.joinLines, { ranges: editor.selections.map((it) => client.code2ProtocolConverter.asRange(it)), - textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier( - editor.document - ), + textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document), }); const textEdits = await client.protocol2CodeConverter.asTextEdits(items); await editor.edit((builder) => { @@ -145,14 +145,12 @@ export function moveItemDown(ctx: Ctx): Cmd { export function moveItem(ctx: Ctx, direction: ra.Direction): Cmd { return async () => { const editor = ctx.activeRustEditor; - const client = ctx.client; - if (!editor || !client) return; + if (!editor) return; + const client = await ctx.getClient(); const lcEdits = await client.sendRequest(ra.moveItem, { range: client.code2ProtocolConverter.asRange(editor.selection), - textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier( - editor.document - ), + textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document), direction, }); @@ -166,13 +164,13 @@ export function moveItem(ctx: Ctx, direction: ra.Direction): Cmd { export function onEnter(ctx: Ctx): Cmd { async function handleKeypress() { const editor = ctx.activeRustEditor; - const client = ctx.client; - if (!editor || !client) return false; + if (!editor) return false; + const client = await ctx.getClient(); const lcEdits = await client .sendRequest(ra.onEnter, { - textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier( + textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier( editor.document ), position: client.code2ProtocolConverter.asPosition(editor.selection.active), @@ -198,14 +196,13 @@ export function onEnter(ctx: Ctx): Cmd { export function parentModule(ctx: Ctx): Cmd { return async () => { const editor = vscode.window.activeTextEditor; - const client = ctx.client; - if (!editor || !client) return; + if (!editor) return; if (!(isRustDocument(editor.document) || isCargoTomlDocument(editor.document))) return; + const client = await ctx.getClient(); + const locations = await client.sendRequest(ra.parentModule, { - textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier( - editor.document - ), + textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document), position: client.code2ProtocolConverter.asPosition(editor.selection.active), }); if (!locations) return; @@ -236,13 +233,11 @@ export function parentModule(ctx: Ctx): Cmd { export function openCargoToml(ctx: Ctx): Cmd { return async () => { const editor = ctx.activeRustEditor; - const client = ctx.client; - if (!editor || !client) return; + if (!editor) return; + const client = await ctx.getClient(); const response = await client.sendRequest(ra.openCargoToml, { - textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier( - editor.document - ), + textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document), }); if (!response) return; @@ -259,12 +254,13 @@ export function openCargoToml(ctx: Ctx): Cmd { export function ssr(ctx: Ctx): Cmd { return async () => { const editor = vscode.window.activeTextEditor; - const client = ctx.client; - if (!editor || !client) return; + if (!editor) return; + + const client = await ctx.getClient(); const position = editor.selection.active; const selections = editor.selections; - const textDocument = ctx.client.code2ProtocolConverter.asTextDocumentIdentifier( + const textDocument = client.code2ProtocolConverter.asTextDocumentIdentifier( editor.document ); @@ -354,21 +350,22 @@ export function syntaxTree(ctx: Ctx): Cmd { } } - provideTextDocumentContent( + async provideTextDocumentContent( uri: vscode.Uri, ct: vscode.CancellationToken - ): vscode.ProviderResult { + ): Promise { const rustEditor = ctx.activeRustEditor; if (!rustEditor) return ""; + const client = await ctx.getClient(); // When the range based query is enabled we take the range of the selection const range = uri.query === "range=true" && !rustEditor.selection.isEmpty - ? ctx.client.code2ProtocolConverter.asRange(rustEditor.selection) + ? client.code2ProtocolConverter.asRange(rustEditor.selection) : null; const params = { textDocument: { uri: rustEditor.document.uri.toString() }, range }; - return ctx.client.sendRequest(ra.syntaxTree, params, ct); + return client.sendRequest(ra.syntaxTree, params, ct); } get onDidChange(): vscode.Event { @@ -378,10 +375,10 @@ export function syntaxTree(ctx: Ctx): Cmd { void new AstInspector(ctx); - ctx.pushCleanup( + ctx.pushExtCleanup( vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-syntax-tree", tdcp) ); - ctx.pushCleanup( + ctx.pushExtCleanup( vscode.languages.setLanguageConfiguration("ra_syntax_tree", { brackets: [["[", ")"]], }) @@ -437,14 +434,14 @@ export function viewHir(ctx: Ctx): Cmd { } } - provideTextDocumentContent( + async provideTextDocumentContent( _uri: vscode.Uri, ct: vscode.CancellationToken - ): vscode.ProviderResult { + ): Promise { const rustEditor = ctx.activeRustEditor; - const client = ctx.client; - if (!rustEditor || !client) return ""; + if (!rustEditor) return ""; + const client = await ctx.getClient(); const params = { textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier( rustEditor.document @@ -459,7 +456,7 @@ export function viewHir(ctx: Ctx): Cmd { } })(); - ctx.pushCleanup( + ctx.pushExtCleanup( vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-hir", tdcp) ); @@ -503,13 +500,13 @@ export function viewFileText(ctx: Ctx): Cmd { } } - provideTextDocumentContent( + async provideTextDocumentContent( _uri: vscode.Uri, ct: vscode.CancellationToken - ): vscode.ProviderResult { + ): Promise { const rustEditor = ctx.activeRustEditor; - const client = ctx.client; - if (!rustEditor || !client) return ""; + if (!rustEditor) return ""; + const client = await ctx.getClient(); const params = client.code2ProtocolConverter.asTextDocumentIdentifier( rustEditor.document @@ -522,7 +519,7 @@ export function viewFileText(ctx: Ctx): Cmd { } })(); - ctx.pushCleanup( + ctx.pushExtCleanup( vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-file-text", tdcp) ); @@ -566,13 +563,13 @@ export function viewItemTree(ctx: Ctx): Cmd { } } - provideTextDocumentContent( + async provideTextDocumentContent( _uri: vscode.Uri, ct: vscode.CancellationToken - ): vscode.ProviderResult { + ): Promise { const rustEditor = ctx.activeRustEditor; - const client = ctx.client; - if (!rustEditor || !client) return ""; + if (!rustEditor) return ""; + const client = await ctx.getClient(); const params = { textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier( @@ -587,7 +584,7 @@ export function viewItemTree(ctx: Ctx): Cmd { } })(); - ctx.pushCleanup( + ctx.pushExtCleanup( vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-item-tree", tdcp) ); @@ -618,8 +615,8 @@ function crateGraph(ctx: Ctx, full: boolean): Cmd { const params = { full: full, }; - - const dot = await ctx.client.sendRequest(ra.viewCrateGraph, params); + const client = await ctx.getClient(); + const dot = await client.sendRequest(ra.viewCrateGraph, params); const uri = panel.webview.asWebviewUri(nodeModulesPath); const html = ` @@ -690,13 +687,13 @@ export function expandMacro(ctx: Ctx): Cmd { eventEmitter = new vscode.EventEmitter(); async provideTextDocumentContent(_uri: vscode.Uri): Promise { const editor = vscode.window.activeTextEditor; - const client = ctx.client; - if (!editor || !client) return ""; + if (!editor) return ""; + const client = await ctx.getClient(); const position = editor.selection.active; const expanded = await client.sendRequest(ra.expandMacro, { - textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier( + textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier( editor.document ), position, @@ -712,7 +709,7 @@ export function expandMacro(ctx: Ctx): Cmd { } })(); - ctx.pushCleanup( + ctx.pushExtCleanup( vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-expand-macro", tdcp) ); @@ -724,11 +721,11 @@ export function expandMacro(ctx: Ctx): Cmd { } export function reloadWorkspace(ctx: Ctx): Cmd { - return async () => ctx.client.sendRequest(ra.reloadWorkspace); + return async () => (await ctx.getClient()).sendRequest(ra.reloadWorkspace); } async function showReferencesImpl( - client: LanguageClient, + client: LanguageClient | undefined, uri: string, position: lc.Position, locations: lc.Location[] @@ -745,7 +742,7 @@ async function showReferencesImpl( export function showReferences(ctx: Ctx): Cmd { return async (uri: string, position: lc.Position, locations: lc.Location[]) => { - await showReferencesImpl(ctx.client, uri, position, locations); + await showReferencesImpl(await ctx.getClient(), uri, position, locations); }; } @@ -762,25 +759,23 @@ export function applyActionGroup(_ctx: Ctx): Cmd { export function gotoLocation(ctx: Ctx): Cmd { return async (locationLink: lc.LocationLink) => { - const client = ctx.client; - if (client) { - const uri = client.protocol2CodeConverter.asUri(locationLink.targetUri); - let range = client.protocol2CodeConverter.asRange(locationLink.targetSelectionRange); - // collapse the range to a cursor position - range = range.with({ end: range.start }); + const client = await ctx.getClient(); + const uri = client.protocol2CodeConverter.asUri(locationLink.targetUri); + let range = client.protocol2CodeConverter.asRange(locationLink.targetSelectionRange); + // collapse the range to a cursor position + range = range.with({ end: range.start }); - await vscode.window.showTextDocument(uri, { selection: range }); - } + await vscode.window.showTextDocument(uri, { selection: range }); }; } export function openDocs(ctx: Ctx): Cmd { return async () => { - const client = ctx.client; const editor = vscode.window.activeTextEditor; - if (!editor || !client) { + if (!editor) { return; } + const client = await ctx.getClient(); const position = editor.selection.active; const textDocument = { uri: editor.document.uri.toString() }; @@ -795,20 +790,21 @@ export function openDocs(ctx: Ctx): Cmd { export function cancelFlycheck(ctx: Ctx): Cmd { return async () => { - await ctx.client.sendRequest(ra.cancelFlycheck); + const client = await ctx.getClient(); + await client.sendRequest(ra.cancelFlycheck); }; } export function resolveCodeAction(ctx: Ctx): Cmd { - const client = ctx.client; return async (params: lc.CodeAction) => { + const client = await ctx.getClient(); params.command = undefined; - const item = await client.sendRequest(lc.CodeActionResolveRequest.type, params); - if (!item.edit) { + const item = await client?.sendRequest(lc.CodeActionResolveRequest.type, params); + if (!item?.edit) { return; } const itemEdit = item.edit; - const edit = await client.protocol2CodeConverter.asWorkspaceEdit(itemEdit); + const edit = await client?.protocol2CodeConverter.asWorkspaceEdit(itemEdit); // filter out all text edits and recreate the WorkspaceEdit without them so we can apply // snippet edits on our own const lcFileSystemEdit = { @@ -847,11 +843,10 @@ export function run(ctx: Ctx): Cmd { } export function peekTests(ctx: Ctx): Cmd { - const client = ctx.client; - return async () => { const editor = ctx.activeRustEditor; - if (!editor || !client) return; + if (!editor) return; + const client = await ctx.getClient(); await vscode.window.withProgress( { @@ -937,10 +932,10 @@ export function newDebugConfig(ctx: Ctx): Cmd { }; } -export function linkToCommand(ctx: Ctx): Cmd { +export function linkToCommand(_: Ctx): Cmd { return async (commandId: string) => { const link = LINKED_COMMANDS.get(commandId); - if (ctx.client && link) { + if (link) { const { command, arguments: args = [] } = link; await vscode.commands.executeCommand(command, ...args); } diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index 26510011d439..d4f5ab3c88c9 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -2,9 +2,9 @@ import * as vscode from "vscode"; import * as lc from "vscode-languageclient/node"; import * as ra from "./lsp_ext"; -import { Config } from "./config"; +import { Config, substituteVariablesInEnv, substituteVSCodeVariables } from "./config"; import { createClient } from "./client"; -import { isRustEditor, RustEditor } from "./util"; +import { isRustEditor, log, RustEditor } from "./util"; import { ServerStatusParams } from "./lsp_ext"; export type Workspace = @@ -17,35 +17,118 @@ export type Workspace = }; export class Ctx { - private constructor( - readonly config: Config, - private readonly extCtx: vscode.ExtensionContext, - readonly client: lc.LanguageClient, - readonly serverPath: string, - readonly statusBar: vscode.StatusBarItem - ) {} + private client: lc.LanguageClient | undefined; + readonly config: Config; + serverPath: string; + readonly statusBar: vscode.StatusBarItem; - static async create( + traceOutputChannel: vscode.OutputChannel | undefined; + outputChannel: vscode.OutputChannel | undefined; + + serverOptions: + | { + run: lc.Executable; + debug: lc.Executable; + } + | undefined; + workspace: Workspace; + + constructor( + readonly extCtx: vscode.ExtensionContext, config: Config, - extCtx: vscode.ExtensionContext, serverPath: string, workspace: Workspace - ): Promise { - const client = await createClient(serverPath, workspace, config.serverExtraEnv); + ) { + this.statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); + extCtx.subscriptions.push(this.statusBar); + extCtx.subscriptions.push({ + dispose() { + this.dispose(); + }, + }); + this.statusBar.text = "rust-analyzer"; + this.statusBar.tooltip = "ready"; + this.statusBar.command = "rust-analyzer.analyzerStatus"; + this.statusBar.show(); + this.serverPath = serverPath; + this.config = config; + this.workspace = workspace; + } - const statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); - extCtx.subscriptions.push(statusBar); - statusBar.text = "rust-analyzer"; - statusBar.tooltip = "ready"; - statusBar.command = "rust-analyzer.analyzerStatus"; - statusBar.show(); + clientFetcher() { + return { + get client(): lc.LanguageClient | undefined { + return this.client; + }, + }; + } - const res = new Ctx(config, extCtx, client, serverPath, statusBar); + async getClient() { + if (!this.traceOutputChannel) { + this.traceOutputChannel = vscode.window.createOutputChannel( + "Rust Analyzer Language Server Trace" + ); + } + if (!this.outputChannel) { + this.outputChannel = vscode.window.createOutputChannel("Rust Analyzer Language Server"); + } + if (!this.serverOptions) { + log.info("Creating server options client"); + const newEnv = substituteVariablesInEnv( + Object.assign({}, process.env, this.config.serverExtraEnv) + ); + const run: lc.Executable = { + command: this.serverPath, + options: { env: newEnv }, + }; + this.serverOptions = { + run, + debug: run, + }; + } else { + this.serverOptions.run.command = this.serverPath; + this.serverOptions.debug.command = this.serverPath; + } + if (!this.client) { + log.info("Creating language client"); + let rawInitializationOptions = vscode.workspace.getConfiguration("rust-analyzer"); - res.pushCleanup(client.start()); - await client.onReady(); - client.onNotification(ra.serverStatus, (params) => res.setServerStatus(params)); - return res; + if (this.workspace.kind === "Detached Files") { + rawInitializationOptions = { + detachedFiles: this.workspace.files.map((file) => file.uri.fsPath), + ...rawInitializationOptions, + }; + } + + const initializationOptions = substituteVSCodeVariables(rawInitializationOptions); + + this.client = await createClient( + this.traceOutputChannel, + this.outputChannel, + initializationOptions, + this.serverOptions + ); + this.client.onNotification(ra.serverStatus, (params) => this.setServerStatus(params)); + } + return this.client; + } + + async activate() { + log.info("Activating language client"); + const client = await this.getClient(); + await client.start(); + return client; + } + + async deactivate() { + log.info("Deactivating language client"); + await this.client?.stop(); + } + + async disposeClient() { + log.info("Deactivating language client"); + await this.client?.dispose(); + this.client = undefined; } get activeRustEditor(): RustEditor | undefined { @@ -61,7 +144,7 @@ export class Ctx { const fullName = `rust-analyzer.${name}`; const cmd = factory(this); const d = vscode.commands.registerCommand(fullName, cmd); - this.pushCleanup(d); + this.pushExtCleanup(d); } get extensionPath(): string { @@ -111,7 +194,7 @@ export class Ctx { statusBar.text = `${icon}rust-analyzer`; } - pushCleanup(d: Disposable) { + pushExtCleanup(d: Disposable) { this.extCtx.subscriptions.push(d); } } diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 41bde4195e07..4ff27e0b5518 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -1,53 +1,36 @@ import * as vscode from "vscode"; import * as lc from "vscode-languageclient/node"; -import * as os from "os"; import * as commands from "./commands"; -import { Ctx } from "./ctx"; -import { Config } from "./config"; -import { log, isValidExecutable, isRustDocument } from "./util"; +import { Ctx, Workspace } from "./ctx"; +import { log, isRustDocument } from "./util"; import { PersistentState } from "./persistent_state"; import { activateTaskProvider } from "./tasks"; import { setContextValue } from "./util"; -import { exec } from "child_process"; - -let ctx: Ctx | undefined; +import { bootstrap } from "./bootstrap"; +import { Config } from "./config"; const RUST_PROJECT_CONTEXT_NAME = "inRustProject"; -let TRACE_OUTPUT_CHANNEL: vscode.OutputChannel | null = null; -export function traceOutputChannel() { - if (!TRACE_OUTPUT_CHANNEL) { - TRACE_OUTPUT_CHANNEL = vscode.window.createOutputChannel( - "Rust Analyzer Language Server Trace" - ); - } - return TRACE_OUTPUT_CHANNEL; -} -let OUTPUT_CHANNEL: vscode.OutputChannel | null = null; -export function outputChannel() { - if (!OUTPUT_CHANNEL) { - OUTPUT_CHANNEL = vscode.window.createOutputChannel("Rust Analyzer Language Server"); - } - return OUTPUT_CHANNEL; -} - export interface RustAnalyzerExtensionApi { - client?: lc.LanguageClient; + // FIXME: this should be non-optional + readonly client?: lc.LanguageClient; } export async function activate( context: vscode.ExtensionContext ): Promise { - // VS Code doesn't show a notification when an extension fails to activate - // so we do it ourselves. - return await tryActivate(context).catch((err) => { - void vscode.window.showErrorMessage(`Cannot activate rust-analyzer: ${err.message}`); - throw err; - }); -} + if (vscode.extensions.getExtension("rust-lang.rust")) { + vscode.window + .showWarningMessage( + `You have both the rust-analyzer (rust-lang.rust-analyzer) and Rust (rust-lang.rust) ` + + "plugins enabled. These are known to conflict and cause various functions of " + + "both plugins to not work correctly. You should disable one of them.", + "Got it" + ) + .then(() => {}, console.error); + } -async function tryActivate(context: vscode.ExtensionContext): Promise { // We only support local folders, not eg. Live Share (`vlsl:` scheme), so don't activate if // only those are in use. // (r-a still somewhat works with Live Share, because commands are tunneled to the host) @@ -65,8 +48,17 @@ async function tryActivate(context: vscode.ExtensionContext): Promise { let message = "bootstrap error. "; @@ -77,42 +69,43 @@ async function tryActivate(context: vscode.ExtensionContext): Promise { + void vscode.window.showErrorMessage(`Cannot activate rust-analyzer: ${err.message}`); + throw err; + }); +} + +async function activateServer(ctx: Ctx): Promise { + if (ctx.workspace.kind === "Workspace Folder") { + ctx.pushExtCleanup(activateTaskProvider(ctx.config)); } - await initCommonContext(context, ctx); - warnAboutExtensionConflicts(); + await ctx.activate(); + await initCommonContext(ctx); - if (config.typingContinueCommentsOnNewline) { - ctx.pushCleanup(configureLanguage()); + if (ctx.config.typingContinueCommentsOnNewline) { + ctx.pushExtCleanup(configureLanguage()); } vscode.workspace.onDidChangeConfiguration( (_) => - ctx?.client - ?.sendNotification("workspace/didChangeConfiguration", { settings: "" }) + ctx + .getClient() + .then((it) => + it.sendNotification("workspace/didChangeConfiguration", { settings: "" }) + ) .catch(log.error), null, ctx.subscriptions ); - return { - client: ctx.client, - }; + return ctx.clientFetcher(); } -async function initCommonContext(context: vscode.ExtensionContext, ctx: Ctx) { +async function initCommonContext(ctx: Ctx) { // Register a "dumb" onEnter command for the case where server fails to // start. // @@ -130,24 +123,15 @@ async function initCommonContext(context: vscode.ExtensionContext, ctx: Ctx) { const defaultOnEnter = vscode.commands.registerCommand("rust-analyzer.onEnter", () => vscode.commands.executeCommand("default:type", { text: "\n" }) ); - context.subscriptions.push(defaultOnEnter); + ctx.pushExtCleanup(defaultOnEnter); await setContextValue(RUST_PROJECT_CONTEXT_NAME, true); // Commands which invokes manually via command palette, shortcut, etc. - - // Reloading is inspired by @DanTup maneuver: https://github.com/microsoft/vscode/issues/45774#issuecomment-373423895 ctx.registerCommand("reload", (_) => async () => { void vscode.window.showInformationMessage("Reloading rust-analyzer..."); - await doDeactivate(); - while (context.subscriptions.length > 0) { - try { - context.subscriptions.pop()!.dispose(); - } catch (err) { - log.error("Dispose error:", err); - } - } - await activate(context).catch(log.error); + await ctx.disposeClient(); + await ctx.activate(); }); ctx.registerCommand("analyzerStatus", commands.analyzerStatus); @@ -175,9 +159,6 @@ async function initCommonContext(context: vscode.ExtensionContext, ctx: Ctx) { ctx.registerCommand("moveItemDown", commands.moveItemDown); ctx.registerCommand("cancelFlycheck", commands.cancelFlycheck); - defaultOnEnter.dispose(); - ctx.registerCommand("onEnter", commands.onEnter); - ctx.registerCommand("ssr", commands.ssr); ctx.registerCommand("serverVersion", commands.serverVersion); @@ -191,176 +172,9 @@ async function initCommonContext(context: vscode.ExtensionContext, ctx: Ctx) { ctx.registerCommand("gotoLocation", commands.gotoLocation); ctx.registerCommand("linkToCommand", commands.linkToCommand); -} -export async function deactivate() { - TRACE_OUTPUT_CHANNEL?.dispose(); - TRACE_OUTPUT_CHANNEL = null; - OUTPUT_CHANNEL?.dispose(); - OUTPUT_CHANNEL = null; - await doDeactivate(); -} - -async function doDeactivate() { - await setContextValue(RUST_PROJECT_CONTEXT_NAME, undefined); - await ctx?.client.stop(); - ctx = undefined; -} - -async function bootstrap( - context: vscode.ExtensionContext, - config: Config, - state: PersistentState -): Promise { - const path = await getServer(context, config, state); - if (!path) { - throw new Error( - "Rust Analyzer Language Server is not available. " + - "Please, ensure its [proper installation](https://rust-analyzer.github.io/manual.html#installation)." - ); - } - - log.info("Using server binary at", path); - - if (!isValidExecutable(path)) { - if (config.serverPath) { - throw new Error(`Failed to execute ${path} --version. \`config.server.path\` or \`config.serverPath\` has been set explicitly.\ - Consider removing this config or making a valid server binary available at that path.`); - } else { - throw new Error(`Failed to execute ${path} --version`); - } - } - - return path; -} - -async function patchelf(dest: vscode.Uri): Promise { - await vscode.window.withProgress( - { - location: vscode.ProgressLocation.Notification, - title: "Patching rust-analyzer for NixOS", - }, - async (progress, _) => { - const expression = ` - {srcStr, pkgs ? import {}}: - pkgs.stdenv.mkDerivation { - name = "rust-analyzer"; - src = /. + srcStr; - phases = [ "installPhase" "fixupPhase" ]; - installPhase = "cp $src $out"; - fixupPhase = '' - chmod 755 $out - patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" $out - ''; - } - `; - const origFile = vscode.Uri.file(dest.fsPath + "-orig"); - await vscode.workspace.fs.rename(dest, origFile, { overwrite: true }); - try { - progress.report({ message: "Patching executable", increment: 20 }); - await new Promise((resolve, reject) => { - const handle = exec( - `nix-build -E - --argstr srcStr '${origFile.fsPath}' -o '${dest.fsPath}'`, - (err, stdout, stderr) => { - if (err != null) { - reject(Error(stderr)); - } else { - resolve(stdout); - } - } - ); - handle.stdin?.write(expression); - handle.stdin?.end(); - }); - } finally { - await vscode.workspace.fs.delete(origFile); - } - } - ); -} - -async function getServer( - context: vscode.ExtensionContext, - config: Config, - state: PersistentState -): Promise { - const explicitPath = serverPath(config); - if (explicitPath) { - if (explicitPath.startsWith("~/")) { - return os.homedir() + explicitPath.slice("~".length); - } - return explicitPath; - } - if (config.package.releaseTag === null) return "rust-analyzer"; - - const ext = process.platform === "win32" ? ".exe" : ""; - const bundled = vscode.Uri.joinPath(context.extensionUri, "server", `rust-analyzer${ext}`); - const bundledExists = await vscode.workspace.fs.stat(bundled).then( - () => true, - () => false - ); - if (bundledExists) { - let server = bundled; - if (await isNixOs()) { - await vscode.workspace.fs.createDirectory(config.globalStorageUri).then(); - const dest = vscode.Uri.joinPath(config.globalStorageUri, `rust-analyzer${ext}`); - let exists = await vscode.workspace.fs.stat(dest).then( - () => true, - () => false - ); - if (exists && config.package.version !== state.serverVersion) { - await vscode.workspace.fs.delete(dest); - exists = false; - } - if (!exists) { - await vscode.workspace.fs.copy(bundled, dest); - await patchelf(dest); - } - server = dest; - } - await state.updateServerVersion(config.package.version); - return server.fsPath; - } - - await state.updateServerVersion(undefined); - await vscode.window.showErrorMessage( - "Unfortunately we don't ship binaries for your platform yet. " + - "You need to manually clone the rust-analyzer repository and " + - "run `cargo xtask install --server` to build the language server from sources. " + - "If you feel that your platform should be supported, please create an issue " + - "about that [here](https://github.com/rust-lang/rust-analyzer/issues) and we " + - "will consider it." - ); - return undefined; -} - -function serverPath(config: Config): string | null { - return process.env.__RA_LSP_SERVER_DEBUG ?? config.serverPath; -} - -async function isNixOs(): Promise { - try { - const contents = ( - await vscode.workspace.fs.readFile(vscode.Uri.file("/etc/os-release")) - ).toString(); - const idString = contents.split("\n").find((a) => a.startsWith("ID=")) || "ID=linux"; - return idString.indexOf("nixos") !== -1; - } catch { - return false; - } -} - -function warnAboutExtensionConflicts() { - if (vscode.extensions.getExtension("rust-lang.rust")) { - vscode.window - .showWarningMessage( - `You have both the rust-analyzer (rust-lang.rust-analyzer) and Rust (rust-lang.rust) ` + - "plugins enabled. These are known to conflict and cause various functions of " + - "both plugins to not work correctly. You should disable one of them.", - "Got it" - ) - .then(() => {}, console.error); - } + defaultOnEnter.dispose(); + ctx.registerCommand("onEnter", commands.onEnter); } /** From 8aaafddee8ad709438a663084e6eec8f458bfd50 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 17 Oct 2022 14:53:46 +0200 Subject: [PATCH 015/171] Properly reload changed configs for server start --- editors/code/src/commands.ts | 4 +++ editors/code/src/config.ts | 4 +-- editors/code/src/ctx.ts | 58 +++++++++++++++++++----------------- editors/code/src/main.ts | 42 ++++++++++---------------- 4 files changed, 51 insertions(+), 57 deletions(-) diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts index cbdeb28c99fe..cb088fc6c682 100644 --- a/editors/code/src/commands.ts +++ b/editors/code/src/commands.ts @@ -310,6 +310,10 @@ export function ssr(ctx: Ctx): Cmd { export function serverVersion(ctx: Ctx): Cmd { return async () => { + if (!ctx.serverPath) { + void vscode.window.showWarningMessage(`rust-analyzer server is not running`); + return; + } const { stdout } = spawnSync(ctx.serverPath, ["--version"], { encoding: "utf8" }); const versionString = stdout.slice(`rust-analyzer `.length).trim(); diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 199db6e30fc5..10e243dc896c 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -14,8 +14,6 @@ export class Config { readonly rootSection = "rust-analyzer"; private readonly requiresWorkspaceReloadOpts = [ - "serverPath", - "server", // FIXME: This shouldn't be here, changing this setting should reload // `continueCommentsOnNewline` behavior without restart "typing", @@ -23,6 +21,8 @@ export class Config { private readonly requiresReloadOpts = [ "cargo", "procMacro", + "serverPath", + "server", "files", "lens", // works as lens.* ] diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index d4f5ab3c88c9..f62ccd1a6529 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -6,6 +6,8 @@ import { Config, substituteVariablesInEnv, substituteVSCodeVariables } from "./c import { createClient } from "./client"; import { isRustEditor, log, RustEditor } from "./util"; import { ServerStatusParams } from "./lsp_ext"; +import { PersistentState } from "./persistent_state"; +import { bootstrap } from "./bootstrap"; export type Workspace = | { @@ -17,28 +19,18 @@ export type Workspace = }; export class Ctx { - private client: lc.LanguageClient | undefined; - readonly config: Config; - serverPath: string; readonly statusBar: vscode.StatusBarItem; + readonly config: Config; + + private client: lc.LanguageClient | undefined; traceOutputChannel: vscode.OutputChannel | undefined; outputChannel: vscode.OutputChannel | undefined; - - serverOptions: - | { - run: lc.Executable; - debug: lc.Executable; - } - | undefined; workspace: Workspace; + state: PersistentState; + serverPath: string | undefined; - constructor( - readonly extCtx: vscode.ExtensionContext, - config: Config, - serverPath: string, - workspace: Workspace - ) { + constructor(readonly extCtx: vscode.ExtensionContext, workspace: Workspace) { this.statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); extCtx.subscriptions.push(this.statusBar); extCtx.subscriptions.push({ @@ -50,9 +42,10 @@ export class Ctx { this.statusBar.tooltip = "ready"; this.statusBar.command = "rust-analyzer.analyzerStatus"; this.statusBar.show(); - this.serverPath = serverPath; - this.config = config; this.workspace = workspace; + + this.state = new PersistentState(extCtx.globalState); + this.config = new Config(extCtx); } clientFetcher() { @@ -64,6 +57,7 @@ export class Ctx { } async getClient() { + // if server path changes -> dispose if (!this.traceOutputChannel) { this.traceOutputChannel = vscode.window.createOutputChannel( "Rust Analyzer Language Server Trace" @@ -72,8 +66,20 @@ export class Ctx { if (!this.outputChannel) { this.outputChannel = vscode.window.createOutputChannel("Rust Analyzer Language Server"); } - if (!this.serverOptions) { - log.info("Creating server options client"); + + if (!this.client) { + log.info("Creating language client"); + + this.serverPath = await bootstrap(this.extCtx, this.config, this.state).catch((err) => { + let message = "bootstrap error. "; + + message += + 'See the logs in "OUTPUT > Rust Analyzer Client" (should open automatically). '; + message += 'To enable verbose logs use { "rust-analyzer.trace.extension": true }'; + + log.error("Bootstrap error", err); + throw new Error(message); + }); const newEnv = substituteVariablesInEnv( Object.assign({}, process.env, this.config.serverExtraEnv) ); @@ -81,16 +87,11 @@ export class Ctx { command: this.serverPath, options: { env: newEnv }, }; - this.serverOptions = { + const serverOptions = { run, debug: run, }; - } else { - this.serverOptions.run.command = this.serverPath; - this.serverOptions.debug.command = this.serverPath; - } - if (!this.client) { - log.info("Creating language client"); + let rawInitializationOptions = vscode.workspace.getConfiguration("rust-analyzer"); if (this.workspace.kind === "Detached Files") { @@ -106,7 +107,7 @@ export class Ctx { this.traceOutputChannel, this.outputChannel, initializationOptions, - this.serverOptions + serverOptions ); this.client.onNotification(ra.serverStatus, (params) => this.setServerStatus(params)); } @@ -128,6 +129,7 @@ export class Ctx { async disposeClient() { log.info("Deactivating language client"); await this.client?.dispose(); + this.serverPath = undefined; this.client = undefined; } diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 4ff27e0b5518..84f0a5810f9a 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -3,12 +3,9 @@ import * as lc from "vscode-languageclient/node"; import * as commands from "./commands"; import { Ctx, Workspace } from "./ctx"; -import { log, isRustDocument } from "./util"; -import { PersistentState } from "./persistent_state"; +import { isRustDocument } from "./util"; import { activateTaskProvider } from "./tasks"; import { setContextValue } from "./util"; -import { bootstrap } from "./bootstrap"; -import { Config } from "./config"; const RUST_PROJECT_CONTEXT_NAME = "inRustProject"; @@ -56,24 +53,13 @@ export async function activate( } : { kind: "Workspace Folder" }; - const state = new PersistentState(context.globalState); - const config = new Config(context); - - const serverPath = await bootstrap(context, config, state).catch((err) => { - let message = "bootstrap error. "; - - message += 'See the logs in "OUTPUT > Rust Analyzer Client" (should open automatically). '; - message += 'To enable verbose logs use { "rust-analyzer.trace.extension": true }'; - - log.error("Bootstrap error", err); - throw new Error(message); - }); - - const ctx = new Ctx(context, config, serverPath, workspace); + const ctx = new Ctx(context, workspace); // VS Code doesn't show a notification when an extension fails to activate // so we do it ourselves. return await activateServer(ctx).catch((err) => { - void vscode.window.showErrorMessage(`Cannot activate rust-analyzer: ${err.message}`); + void vscode.window.showErrorMessage( + `Cannot activate rust-analyzer extension: ${err.message}` + ); throw err; }); } @@ -83,7 +69,6 @@ async function activateServer(ctx: Ctx): Promise { ctx.pushExtCleanup(activateTaskProvider(ctx.config)); } - await ctx.activate(); await initCommonContext(ctx); if (ctx.config.typingContinueCommentsOnNewline) { @@ -91,17 +76,19 @@ async function activateServer(ctx: Ctx): Promise { } vscode.workspace.onDidChangeConfiguration( - (_) => - ctx - .getClient() - .then((it) => - it.sendNotification("workspace/didChangeConfiguration", { settings: "" }) - ) - .catch(log.error), + async (_) => { + await ctx + .clientFetcher() + .client?.sendNotification("workspace/didChangeConfiguration", { settings: "" }); + }, null, ctx.subscriptions ); + await ctx.activate().catch((err) => { + void vscode.window.showErrorMessage(`Cannot activate rust-analyzer server: ${err.message}`); + }); + return ctx.clientFetcher(); } @@ -130,6 +117,7 @@ async function initCommonContext(ctx: Ctx) { // Commands which invokes manually via command palette, shortcut, etc. ctx.registerCommand("reload", (_) => async () => { void vscode.window.showInformationMessage("Reloading rust-analyzer..."); + // FIXME: We should re-use the client, that is ctx.deactivate() if none of the configs have changed await ctx.disposeClient(); await ctx.activate(); }); From d68616a140b35dd9bc4e2982e0993257ab0942e0 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 17 Oct 2022 15:05:20 +0200 Subject: [PATCH 016/171] Make more things private --- editors/code/src/ast_inspector.ts | 2 -- editors/code/src/commands.ts | 3 +-- editors/code/src/ctx.ts | 35 ++++++++++++++++++------------- editors/code/src/main.ts | 10 ++++++--- editors/code/src/run.ts | 4 ++-- 5 files changed, 31 insertions(+), 23 deletions(-) diff --git a/editors/code/src/ast_inspector.ts b/editors/code/src/ast_inspector.ts index 2a2c9326b6a0..176040120f41 100644 --- a/editors/code/src/ast_inspector.ts +++ b/editors/code/src/ast_inspector.ts @@ -54,8 +54,6 @@ export class AstInspector implements vscode.HoverProvider, vscode.DefinitionProv this, ctx.subscriptions ); - - ctx.pushExtCleanup(this); } dispose() { this.setRustEditor(undefined); diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts index cb088fc6c682..12ceb4f2df8e 100644 --- a/editors/code/src/commands.ts +++ b/editors/code/src/commands.ts @@ -377,8 +377,7 @@ export function syntaxTree(ctx: Ctx): Cmd { } })(); - void new AstInspector(ctx); - + ctx.pushExtCleanup(new AstInspector(ctx)); ctx.pushExtCleanup( vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-syntax-tree", tdcp) ); diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index f62ccd1a6529..6b12d9ca1ecf 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -23,12 +23,12 @@ export class Ctx { readonly config: Config; private client: lc.LanguageClient | undefined; + private _serverPath: string | undefined; + private traceOutputChannel: vscode.OutputChannel | undefined; + private outputChannel: vscode.OutputChannel | undefined; + private state: PersistentState; - traceOutputChannel: vscode.OutputChannel | undefined; - outputChannel: vscode.OutputChannel | undefined; workspace: Workspace; - state: PersistentState; - serverPath: string | undefined; constructor(readonly extCtx: vscode.ExtensionContext, workspace: Workspace) { this.statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); @@ -70,21 +70,24 @@ export class Ctx { if (!this.client) { log.info("Creating language client"); - this.serverPath = await bootstrap(this.extCtx, this.config, this.state).catch((err) => { - let message = "bootstrap error. "; + this._serverPath = await bootstrap(this.extCtx, this.config, this.state).catch( + (err) => { + let message = "bootstrap error. "; - message += - 'See the logs in "OUTPUT > Rust Analyzer Client" (should open automatically). '; - message += 'To enable verbose logs use { "rust-analyzer.trace.extension": true }'; + message += + 'See the logs in "OUTPUT > Rust Analyzer Client" (should open automatically). '; + message += + 'To enable verbose logs use { "rust-analyzer.trace.extension": true }'; - log.error("Bootstrap error", err); - throw new Error(message); - }); + log.error("Bootstrap error", err); + throw new Error(message); + } + ); const newEnv = substituteVariablesInEnv( Object.assign({}, process.env, this.config.serverExtraEnv) ); const run: lc.Executable = { - command: this.serverPath, + command: this._serverPath, options: { env: newEnv }, }; const serverOptions = { @@ -129,7 +132,7 @@ export class Ctx { async disposeClient() { log.info("Deactivating language client"); await this.client?.dispose(); - this.serverPath = undefined; + this._serverPath = undefined; this.client = undefined; } @@ -161,6 +164,10 @@ export class Ctx { return this.extCtx.subscriptions; } + get serverPath(): string | undefined { + return this._serverPath; + } + setServerStatus(status: ServerStatusParams) { let icon = ""; const statusBar = this.statusBar; diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 84f0a5810f9a..97ec41dce3a5 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -14,6 +14,10 @@ export interface RustAnalyzerExtensionApi { readonly client?: lc.LanguageClient; } +export async function deactivate() { + await setContextValue(RUST_PROJECT_CONTEXT_NAME, undefined); +} + export async function activate( context: vscode.ExtensionContext ): Promise { @@ -56,12 +60,14 @@ export async function activate( const ctx = new Ctx(context, workspace); // VS Code doesn't show a notification when an extension fails to activate // so we do it ourselves. - return await activateServer(ctx).catch((err) => { + const api = await activateServer(ctx).catch((err) => { void vscode.window.showErrorMessage( `Cannot activate rust-analyzer extension: ${err.message}` ); throw err; }); + await setContextValue(RUST_PROJECT_CONTEXT_NAME, true); + return api; } async function activateServer(ctx: Ctx): Promise { @@ -112,8 +118,6 @@ async function initCommonContext(ctx: Ctx) { ); ctx.pushExtCleanup(defaultOnEnter); - await setContextValue(RUST_PROJECT_CONTEXT_NAME, true); - // Commands which invokes manually via command palette, shortcut, etc. ctx.registerCommand("reload", (_) => async () => { void vscode.window.showInformationMessage("Reloading rust-analyzer..."); diff --git a/editors/code/src/run.ts b/editors/code/src/run.ts index 22e5eda6827d..dadaa41b1d16 100644 --- a/editors/code/src/run.ts +++ b/editors/code/src/run.ts @@ -18,9 +18,9 @@ export async function selectRunnable( showButtons: boolean = true ): Promise { const editor = ctx.activeRustEditor; - const client = ctx.client; - if (!editor || !client) return; + if (!editor) return; + const client = await ctx.getClient(); const textDocument: lc.TextDocumentIdentifier = { uri: editor.document.uri.toString(), }; From 0421756b4256b8edf739b5889e754d7bc733ed38 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 17 Oct 2022 15:43:15 +0200 Subject: [PATCH 017/171] Implement stop and start server commands --- editors/code/package.json | 11 +++++++++++ editors/code/src/client.ts | 8 ++++++++ editors/code/src/ctx.ts | 2 -- editors/code/src/main.ts | 7 +++++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/editors/code/package.json b/editors/code/package.json index da4bac5ad844..10558e8c018a 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -60,6 +60,7 @@ "onCommand:rust-analyzer.analyzerStatus", "onCommand:rust-analyzer.memoryUsage", "onCommand:rust-analyzer.reloadWorkspace", + "onCommand:rust-analyzer.startServer", "workspaceContains:*/Cargo.toml", "workspaceContains:*/rust-project.json" ], @@ -191,6 +192,16 @@ "title": "Restart server", "category": "rust-analyzer" }, + { + "command": "rust-analyzer.startServer", + "title": "Start server", + "category": "rust-analyzer" + }, + { + "command": "rust-analyzer.stopServer", + "title": "Stop server", + "category": "rust-analyzer" + }, { "command": "rust-analyzer.onEnter", "title": "Enhanced enter key", diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts index 3408a2ee84ee..fb667619c86b 100644 --- a/editors/code/src/client.ts +++ b/editors/code/src/client.ts @@ -76,6 +76,14 @@ export async function createClient( outputChannel, middleware: { workspace: { + // HACK: This is a workaround, when the client has been disposed, VSCode + // continues to emit events to the client and the default one for this event + // attempt to restart the client for no reason + async didChangeWatchedFile(event, next) { + if (client.isRunning()) { + await next(event); + } + }, async configuration( params: lc.ConfigurationParams, token: vscode.CancellationToken, diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index 6b12d9ca1ecf..2080db7a2c12 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -68,8 +68,6 @@ export class Ctx { } if (!this.client) { - log.info("Creating language client"); - this._serverPath = await bootstrap(this.extCtx, this.config, this.state).catch( (err) => { let message = "bootstrap error. "; diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 97ec41dce3a5..f65620aebc69 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -126,6 +126,13 @@ async function initCommonContext(ctx: Ctx) { await ctx.activate(); }); + ctx.registerCommand("startServer", (_) => async () => { + await ctx.activate(); + }); + ctx.registerCommand("stopServer", (_) => async () => { + // FIXME: We should re-use the client, that is ctx.deactivate() if none of the configs have changed + await ctx.disposeClient(); + }); ctx.registerCommand("analyzerStatus", commands.analyzerStatus); ctx.registerCommand("memoryUsage", commands.memoryUsage); ctx.registerCommand("shuffleCrateGraph", commands.shuffleCrateGraph); From 7b5c943129ca285ec2c386b8608f1410ee258f07 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 17 Oct 2022 15:48:36 +0200 Subject: [PATCH 018/171] Downgrade vscode types dependency --- editors/code/package-lock.json | 14 +++++++------- editors/code/package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index 192d8fabc317..a72865d4fe44 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json @@ -15,7 +15,7 @@ }, "devDependencies": { "@types/node": "~16.11.7", - "@types/vscode": "~1.72.0", + "@types/vscode": "~1.66.0", "@typescript-eslint/eslint-plugin": "^5.30.5", "@typescript-eslint/parser": "^5.30.5", "@vscode/test-electron": "^2.1.5", @@ -141,9 +141,9 @@ "dev": true }, "node_modules/@types/vscode": { - "version": "1.72.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.72.0.tgz", - "integrity": "sha512-WvHluhUo+lQvE3I4wUagRpnkHuysB4qSyOQUyIAS9n9PYMJjepzTUD8Jyks0YeXoPD0UGctjqp2u84/b3v6Ydw==", + "version": "1.66.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.66.0.tgz", + "integrity": "sha512-ZfJck4M7nrGasfs4A4YbUoxis3Vu24cETw3DERsNYtDZmYSYtk6ljKexKFKhImO/ZmY6ZMsmegu2FPkXoUFImA==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { @@ -4039,9 +4039,9 @@ "dev": true }, "@types/vscode": { - "version": "1.72.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.72.0.tgz", - "integrity": "sha512-WvHluhUo+lQvE3I4wUagRpnkHuysB4qSyOQUyIAS9n9PYMJjepzTUD8Jyks0YeXoPD0UGctjqp2u84/b3v6Ydw==", + "version": "1.66.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.66.0.tgz", + "integrity": "sha512-ZfJck4M7nrGasfs4A4YbUoxis3Vu24cETw3DERsNYtDZmYSYtk6ljKexKFKhImO/ZmY6ZMsmegu2FPkXoUFImA==", "dev": true }, "@typescript-eslint/eslint-plugin": { diff --git a/editors/code/package.json b/editors/code/package.json index 10558e8c018a..1afe2087c71a 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -41,7 +41,7 @@ }, "devDependencies": { "@types/node": "~16.11.7", - "@types/vscode": "~1.72.0", + "@types/vscode": "~1.66.0", "@typescript-eslint/eslint-plugin": "^5.30.5", "@typescript-eslint/parser": "^5.30.5", "@vscode/test-electron": "^2.1.5", From d63c44e650f9a6ce2fc5f713b4688f3e9e2d9a8d Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 17 Oct 2022 16:01:39 +0200 Subject: [PATCH 019/171] Cleanup output channels --- editors/code/src/ctx.ts | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index 2080db7a2c12..e94d4365c376 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -62,9 +62,11 @@ export class Ctx { this.traceOutputChannel = vscode.window.createOutputChannel( "Rust Analyzer Language Server Trace" ); + this.pushExtCleanup(this.traceOutputChannel); } if (!this.outputChannel) { this.outputChannel = vscode.window.createOutputChannel("Rust Analyzer Language Server"); + this.pushExtCleanup(this.outputChannel); } if (!this.client) { @@ -139,25 +141,10 @@ export class Ctx { return editor && isRustEditor(editor) ? editor : undefined; } - get visibleRustEditors(): RustEditor[] { - return vscode.window.visibleTextEditors.filter(isRustEditor); - } - - registerCommand(name: string, factory: (ctx: Ctx) => Cmd) { - const fullName = `rust-analyzer.${name}`; - const cmd = factory(this); - const d = vscode.commands.registerCommand(fullName, cmd); - this.pushExtCleanup(d); - } - get extensionPath(): string { return this.extCtx.extensionPath; } - get globalState(): vscode.Memento { - return this.extCtx.globalState; - } - get subscriptions(): Disposable[] { return this.extCtx.subscriptions; } @@ -201,6 +188,13 @@ export class Ctx { statusBar.text = `${icon}rust-analyzer`; } + registerCommand(name: string, factory: (ctx: Ctx) => Cmd) { + const fullName = `rust-analyzer.${name}`; + const cmd = factory(this); + const d = vscode.commands.registerCommand(fullName, cmd); + this.pushExtCleanup(d); + } + pushExtCleanup(d: Disposable) { this.extCtx.subscriptions.push(d); } From e41023ce46b36d57fd920a4520555d1067170e30 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 17 Oct 2022 16:32:47 +0200 Subject: [PATCH 020/171] Make flycheck workdone progress reports cancellable --- crates/rust-analyzer/src/lsp_utils.rs | 10 +++++++--- crates/rust-analyzer/src/main_loop.rs | 26 +++++++++++++++++++++----- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/crates/rust-analyzer/src/lsp_utils.rs b/crates/rust-analyzer/src/lsp_utils.rs index 5a37cbe2e334..b3cea64d4175 100644 --- a/crates/rust-analyzer/src/lsp_utils.rs +++ b/crates/rust-analyzer/src/lsp_utils.rs @@ -87,6 +87,7 @@ impl GlobalState { state: Progress, message: Option, fraction: Option, + cancel_token: Option, ) { if !self.config.work_done_progress() { return; @@ -95,7 +96,10 @@ impl GlobalState { assert!((0.0..=1.0).contains(&f)); (f * 100.0) as u32 }); - let token = lsp_types::ProgressToken::String(format!("rustAnalyzer/{}", title)); + let cancellable = Some(cancel_token.is_some()); + let token = lsp_types::ProgressToken::String( + cancel_token.unwrap_or_else(|| format!("rustAnalyzer/{}", title)), + ); let work_done_progress = match state { Progress::Begin => { self.send_request::( @@ -105,14 +109,14 @@ impl GlobalState { lsp_types::WorkDoneProgress::Begin(lsp_types::WorkDoneProgressBegin { title: title.into(), - cancellable: None, + cancellable, message, percentage, }) } Progress::Report => { lsp_types::WorkDoneProgress::Report(lsp_types::WorkDoneProgressReport { - cancellable: None, + cancellable, message, percentage, }) diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 15922dac651c..3a379993ad65 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -257,7 +257,7 @@ impl GlobalState { } }; - self.report_progress("Indexing", state, message, Some(fraction)); + self.report_progress("Indexing", state, message, Some(fraction), None); } } Event::Vfs(message) => { @@ -465,7 +465,7 @@ impl GlobalState { } }; - self.report_progress("Fetching", state, msg, None); + self.report_progress("Fetching", state, msg, None, None); } Task::FetchBuildData(progress) => { let (state, msg) = match progress { @@ -481,7 +481,7 @@ impl GlobalState { }; if let Some(state) = state { - self.report_progress("Loading", state, msg, None); + self.report_progress("Loading", state, msg, None, None); } } } @@ -518,6 +518,7 @@ impl GlobalState { state, Some(format!("{}/{}", n_done, n_total)), Some(Progress::fraction(n_done, n_total)), + None, ) } } @@ -584,7 +585,13 @@ impl GlobalState { } else { format!("cargo check (#{})", id + 1) }; - self.report_progress(&title, state, message, None); + self.report_progress( + &title, + state, + message, + None, + Some(format!("rust-analyzer/checkOnSave/{}", id)), + ); } } } @@ -698,7 +705,16 @@ impl GlobalState { this.cancel(id); Ok(()) })? - .on::(|_this, _params| { + .on::(|this, params| { + if let lsp_types::NumberOrString::String(s) = ¶ms.token { + if let Some(id) = s.strip_prefix("rust-analyzer/checkOnSave/") { + if let Ok(id) = u32::from_str_radix(id, 10) { + if let Some(flycheck) = this.flycheck.get(id as usize) { + flycheck.cancel(); + } + } + } + } // Just ignore this. It is OK to continue sending progress // notifications for this token, as the client can't know when // we accepted notification. From a762baca028e2a6f5efeb7d7804de08d035ba0c5 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 17 Oct 2022 17:53:50 +0200 Subject: [PATCH 021/171] fix: Fix formatting requests hanging when r-a is still starting The reason for that was that we were calculating the crate defmaps of the file we are saving by accident causing us to get stuck waiting on their expensive computation, while we only need the relevant crate id. --- crates/ide/src/lib.rs | 4 ++-- crates/ide/src/parent_module.rs | 12 +++++------- crates/ide/src/status.rs | 2 +- crates/rust-analyzer/src/cargo_target_spec.rs | 6 +----- crates/rust-analyzer/src/dispatch.rs | 4 ++-- crates/rust-analyzer/src/global_state.rs | 7 +++---- crates/rust-analyzer/src/handlers.rs | 4 ++-- crates/rust-analyzer/src/main_loop.rs | 2 +- 8 files changed, 17 insertions(+), 24 deletions(-) diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 77fe0dbf5565..09a5cb03ecdc 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -482,8 +482,8 @@ impl Analysis { } /// Returns crates this file belongs too. - pub fn crate_for(&self, file_id: FileId) -> Cancellable> { - self.with_db(|db| parent_module::crate_for(db, file_id)) + pub fn crates_for(&self, file_id: FileId) -> Cancellable> { + self.with_db(|db| parent_module::crates_for(db, file_id)) } /// Returns the edition of the given crate. diff --git a/crates/ide/src/parent_module.rs b/crates/ide/src/parent_module.rs index 8f3cc86873f5..9d425954e390 100644 --- a/crates/ide/src/parent_module.rs +++ b/crates/ide/src/parent_module.rs @@ -1,9 +1,8 @@ use hir::Semantics; use ide_db::{ - base_db::{CrateId, FileId, FilePosition}, + base_db::{CrateId, FileId, FileLoader, FilePosition}, RootDatabase, }; -use itertools::Itertools; use syntax::{ algo::find_node_at_offset, ast::{self, AstNode}, @@ -55,9 +54,8 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec Vec { - let sema = Semantics::new(db); - sema.to_module_defs(file_id).map(|module| module.krate().into()).unique().collect() +pub(crate) fn crates_for(db: &RootDatabase, file_id: FileId) -> Vec { + db.relevant_crates(file_id).iter().copied().collect() } #[cfg(test)] @@ -147,7 +145,7 @@ $0 mod foo; "#, ); - assert_eq!(analysis.crate_for(file_id).unwrap().len(), 1); + assert_eq!(analysis.crates_for(file_id).unwrap().len(), 1); } #[test] @@ -162,6 +160,6 @@ mod baz; mod baz; "#, ); - assert_eq!(analysis.crate_for(file_id).unwrap().len(), 2); + assert_eq!(analysis.crates_for(file_id).unwrap().len(), 2); } } diff --git a/crates/ide/src/status.rs b/crates/ide/src/status.rs index f4d0387440d4..20810c25b3e8 100644 --- a/crates/ide/src/status.rs +++ b/crates/ide/src/status.rs @@ -45,7 +45,7 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option) -> String { if let Some(file_id) = file_id { format_to!(buf, "\nFile info:\n"); - let crates = crate::parent_module::crate_for(db, file_id); + let crates = crate::parent_module::crates_for(db, file_id); if crates.is_empty() { format_to!(buf, "Does not belong to any crate"); } diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs index e1675a030c0f..cbde73547619 100644 --- a/crates/rust-analyzer/src/cargo_target_spec.rs +++ b/crates/rust-analyzer/src/cargo_target_spec.rs @@ -118,11 +118,7 @@ impl CargoTargetSpec { global_state_snapshot: &GlobalStateSnapshot, file_id: FileId, ) -> Result> { - let crate_id = match &*global_state_snapshot.analysis.crate_for(file_id)? { - &[crate_id, ..] => crate_id, - _ => return Ok(None), - }; - let (cargo_ws, target) = match global_state_snapshot.cargo_target_for_crate_root(crate_id) { + let (cargo_ws, target) = match global_state_snapshot.cargo_target_for_file_id(file_id) { Some(it) => it, None => return Ok(None), }; diff --git a/crates/rust-analyzer/src/dispatch.rs b/crates/rust-analyzer/src/dispatch.rs index f16559148e65..57899b599146 100644 --- a/crates/rust-analyzer/src/dispatch.rs +++ b/crates/rust-analyzer/src/dispatch.rs @@ -52,7 +52,7 @@ impl<'a> RequestDispatcher<'a> { let _pctx = stdx::panic_context::enter(panic_context); f(self.global_state, params) }; - if let Ok(response) = result_to_response::(req.id.clone(), result) { + if let Ok(response) = result_to_response::(req.id, result) { self.global_state.respond(response); } @@ -80,7 +80,7 @@ impl<'a> RequestDispatcher<'a> { f(global_state_snapshot, params) }); - if let Ok(response) = thread_result_to_response::(req.id.clone(), result) { + if let Ok(response) = thread_result_to_response::(req.id, result) { self.global_state.respond(response); } diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 000ff88e458f..4cddb12083a1 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -8,7 +8,7 @@ use std::{sync::Arc, time::Instant}; use crossbeam_channel::{unbounded, Receiver, Sender}; use flycheck::FlycheckHandle; use ide::{Analysis, AnalysisHost, Cancellable, Change, FileId}; -use ide_db::base_db::{CrateId, FileLoader, SourceDatabase}; +use ide_db::base_db::{FileLoader, SourceDatabase}; use lsp_types::{SemanticTokens, Url}; use parking_lot::{Mutex, RwLock}; use proc_macro_api::ProcMacroServer; @@ -398,11 +398,10 @@ impl GlobalStateSnapshot { url_from_abs_path(path) } - pub(crate) fn cargo_target_for_crate_root( + pub(crate) fn cargo_target_for_file_id( &self, - crate_id: CrateId, + file_id: FileId, ) -> Option<(&CargoWorkspace, Target)> { - let file_id = self.analysis.crate_root(crate_id).ok()?; let path = self.vfs.read().0.file_path(file_id); let path = path.as_path()?; self.workspaces.iter().find_map(|ws| match ws { diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 8c3ea77d0611..701a009ea8bd 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs @@ -658,7 +658,7 @@ pub(crate) fn handle_parent_module( // check if invoked at the crate root let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; - let crate_id = match snap.analysis.crate_for(file_id)?.first() { + let crate_id = match snap.analysis.crates_for(file_id)?.first() { Some(&crate_id) => crate_id, None => return Ok(None), }; @@ -1782,7 +1782,7 @@ fn run_rustfmt( ) -> Result>> { let file_id = from_proto::file_id(snap, &text_document.uri)?; let file = snap.analysis.file_text(file_id)?; - let crate_ids = snap.analysis.crate_for(file_id)?; + let crate_ids = snap.analysis.crates_for(file_id)?; let line_index = snap.file_line_index(file_id)?; diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 15922dac651c..7cd7d0024814 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -767,7 +767,7 @@ impl GlobalState { let analysis = this.analysis_host.analysis(); // Crates containing or depending on the saved file let crate_ids: Vec<_> = analysis - .crate_for(file_id)? + .crates_for(file_id)? .into_iter() .flat_map(|id| { this.analysis_host From 8047512dcab33780276771d398ddaee20ec8e933 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 18 Oct 2022 14:18:59 +0200 Subject: [PATCH 022/171] Revert "feat: Diagnose some incorrect usages of the question mark operator" --- crates/hir-expand/src/mod_path.rs | 1 - crates/hir-expand/src/name.rs | 2 - crates/hir-ty/src/infer.rs | 13 ++- crates/hir-ty/src/infer/expr.rs | 99 ++----------------- crates/hir-ty/src/method_resolution.rs | 18 ---- crates/hir-ty/src/tests/traits.rs | 92 ++++++++++++++++- crates/hir/src/diagnostics.rs | 14 +-- crates/hir/src/lib.rs | 38 +++---- .../src/handlers/incorrect_try_expr.rs | 37 ------- .../src/handlers/not_implemented.rs | 35 ------- crates/ide-diagnostics/src/lib.rs | 4 - crates/ide/src/hover/tests.rs | 22 +---- crates/test-utils/src/minicore.rs | 39 +------- 13 files changed, 125 insertions(+), 289 deletions(-) delete mode 100644 crates/ide-diagnostics/src/handlers/incorrect_try_expr.rs delete mode 100644 crates/ide-diagnostics/src/handlers/not_implemented.rs diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs index 68413df420c7..d7586d129b76 100644 --- a/crates/hir-expand/src/mod_path.rs +++ b/crates/hir-expand/src/mod_path.rs @@ -259,7 +259,6 @@ macro_rules! __known_path { (core::future::Future) => {}; (core::future::IntoFuture) => {}; (core::ops::Try) => {}; - (core::ops::FromResidual) => {}; ($path:path) => { compile_error!("Please register your known path in the path module") }; diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs index 8a735b965ab8..2679a1c36026 100644 --- a/crates/hir-expand/src/name.rs +++ b/crates/hir-expand/src/name.rs @@ -279,8 +279,6 @@ pub mod known { RangeToInclusive, RangeTo, Range, - Residual, - FromResidual, Neg, Not, None, diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 4315ccab6c11..31e56dec6259 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -190,9 +190,7 @@ pub(crate) type InferResult = Result, TypeError>; pub enum InferenceDiagnostic { NoSuchField { expr: ExprId }, BreakOutsideOfLoop { expr: ExprId, is_break: bool }, - IncorrectTryTarget { expr: ExprId }, MismatchedArgCount { call_expr: ExprId, expected: usize, found: usize }, - DoesNotImplement { expr: ExprId, trait_: TraitId, ty: Ty }, } /// A mismatch between an expected and an inferred type. @@ -907,6 +905,17 @@ impl<'a> InferenceContext<'a> { self.db.trait_data(trait_).associated_type_by_name(&name![Item]) } + fn resolve_ops_try_ok(&self) -> Option { + // FIXME resolve via lang_item once try v2 is stable + let path = path![core::ops::Try]; + let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?; + let trait_data = self.db.trait_data(trait_); + trait_data + // FIXME remove once try v2 is stable + .associated_type_by_name(&name![Ok]) + .or_else(|| trait_data.associated_type_by_name(&name![Output])) + } + fn resolve_ops_neg_output(&self) -> Option { let trait_ = self.resolve_lang_item(name![neg])?.as_trait()?; self.db.trait_data(trait_).associated_type_by_name(&name![Output]) diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 59ab50d0717b..f56108b26c45 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -19,24 +19,24 @@ use hir_def::{ resolver::resolver_for_expr, ConstParamId, FieldId, ItemContainerId, Lookup, }; -use hir_expand::{name, name::Name}; +use hir_expand::name::Name; use stdx::always; use syntax::ast::RangeOp; use crate::{ autoderef::{self, Autoderef}, consteval, - infer::{coerce::CoerceMany, find_continuable, path, BreakableKind}, + infer::{coerce::CoerceMany, find_continuable, BreakableKind}, lower::{ const_or_path_to_chalk, generic_arg_to_chalk, lower_to_chalk_mutability, ParamLoweringMode, }, mapping::{from_chalk, ToChalk}, method_resolution::{self, lang_names_for_bin_op, VisibleFromModule}, primitive::{self, UintTy}, - static_lifetime, to_assoc_type_id, to_chalk_trait_id, + static_lifetime, to_chalk_trait_id, utils::{generics, Generics}, - AdtId, AliasEq, AliasTy, Binders, CallableDefId, FnPointer, FnSig, FnSubst, Interner, - ProjectionTy, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind, + AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, Interner, Rawness, Scalar, + Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind, }; use super::{ @@ -564,29 +564,9 @@ impl<'a> InferenceContext<'a> { let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); self.resolve_associated_type(inner_ty, self.resolve_future_future_output()) } - &Expr::Try { expr } => { - let inner_ty = self.infer_expr_inner(expr, &Expectation::none()); - match self.resolve_try_impl_for(inner_ty.clone()) { - Some((_, Some((output, residual)))) => { - if let Some((_trait, false)) = - self.implements_from_residual(self.return_ty.clone(), residual) - { - self.push_diagnostic(InferenceDiagnostic::IncorrectTryTarget { - expr: tgt_expr, - }); - } - output - } - Some((trait_, None)) => { - self.push_diagnostic(InferenceDiagnostic::DoesNotImplement { - expr, - trait_, - ty: inner_ty, - }); - self.err_ty() - } - None => self.err_ty(), - } + Expr::Try { expr } => { + let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); + self.resolve_associated_type(inner_ty, self.resolve_ops_try_ok()) } Expr::Cast { expr, type_ref } => { // FIXME: propagate the "castable to" expectation (and find a test case that shows this is necessary) @@ -1550,67 +1530,4 @@ impl<'a> InferenceContext<'a> { let ctx = self.breakables.pop().expect("breakable stack broken"); (ctx.may_break.then(|| ctx.coerce.complete()), res) } - - /// Check whether `ty` implements `FromResidual` - fn implements_from_residual(&mut self, ty: Ty, r: Ty) -> Option<(hir_def::TraitId, bool)> { - let from_residual_trait = self - .resolver - .resolve_known_trait(self.db.upcast(), &(super::path![core::ops::FromResidual]))?; - let r = GenericArgData::Ty(r).intern(Interner); - let b = TyBuilder::trait_ref(self.db, from_residual_trait); - if b.remaining() != 2 { - return Some((from_residual_trait, false)); - } - let trait_ref = b.push(ty).push(r).build(); - Some((from_residual_trait, self.table.try_obligation(trait_ref.cast(Interner)).is_some())) - } - - fn resolve_try_impl_for(&mut self, ty: Ty) -> Option<(hir_def::TraitId, Option<(Ty, Ty)>)> { - let path = path![core::ops::Try]; - let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?; - - let trait_ref = TyBuilder::trait_ref(self.db, trait_).push(ty).build(); - let substitution = trait_ref.substitution.clone(); - self.push_obligation(trait_ref.clone().cast(Interner)); - - let trait_data = self.db.trait_data(trait_); - let output = trait_data.associated_type_by_name(&name![Output]); - let residual = trait_data.associated_type_by_name(&name![Residual]); - - let output_ty = match output { - Some(output) => { - let output_ty = self.table.new_type_var(); - let alias_eq = AliasEq { - alias: AliasTy::Projection(ProjectionTy { - associated_ty_id: to_assoc_type_id(output), - substitution: substitution.clone(), - }), - ty: output_ty.clone(), - }; - self.push_obligation(alias_eq.cast(Interner)); - output_ty - } - None => self.err_ty(), - }; - let residual_ty = match residual { - Some(residual) => { - let residual_ty = self.table.new_type_var(); - let alias_eq = AliasEq { - alias: AliasTy::Projection(ProjectionTy { - associated_ty_id: to_assoc_type_id(residual), - substitution, - }), - ty: residual_ty.clone(), - }; - self.push_obligation(alias_eq.cast(Interner)); - residual_ty - } - None => self.err_ty(), - }; - // FIXME: We are doing the work twice here I think? - Some(( - trait_, - self.table.try_obligation(trait_ref.cast(Interner)).map(|_| (output_ty, residual_ty)), - )) - } } diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs index 224dc21e94e5..5998680dcd39 100644 --- a/crates/hir-ty/src/method_resolution.rs +++ b/crates/hir-ty/src/method_resolution.rs @@ -1111,24 +1111,6 @@ pub fn resolve_indexing_op( } None } -/// Returns the receiver type for the try branch trait call. -pub fn resolve_branch_op( - db: &dyn HirDatabase, - env: Arc, - ty: Canonical, - try_trait: TraitId, -) -> Option { - let mut table = InferenceTable::new(db, env.clone()); - let ty = table.instantiate_canonical(ty); - let (deref_chain, adj) = autoderef_method_receiver(&mut table, ty); - for (ty, adj) in deref_chain.into_iter().zip(adj) { - let goal = generic_implements_goal(db, env.clone(), try_trait, &ty); - if db.trait_solve(env.krate, goal.cast(Interner)).is_some() { - return Some(adj); - } - } - None -} macro_rules! check_that { ($cond:expr) => { diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs index b91172e33422..555b6972fb71 100644 --- a/crates/hir-ty/src/tests/traits.rs +++ b/crates/hir-ty/src/tests/traits.rs @@ -162,16 +162,98 @@ fn test() { ); } +#[test] +fn infer_try() { + check_types( + r#" +//- /main.rs crate:main deps:core +fn test() { + let r: Result = Result::Ok(1); + let v = r?; + v; +} //^ i32 + +//- /core.rs crate:core +pub mod ops { + pub trait Try { + type Ok; + type Error; + } +} + +pub mod result { + pub enum Result { + Ok(O), + Err(E) + } + + impl crate::ops::Try for Result { + type Ok = O; + type Error = E; + } +} + +pub mod prelude { + pub mod rust_2018 { + pub use crate::{result::*, ops::*}; + } +} +"#, + ); +} + #[test] fn infer_try_trait_v2() { check_types( r#" -//- minicore: try -fn test() -> core::ops::ControlFlow { - let r: core::ops::ControlFlow = core::ops::ControlFlow::Continue(1.0); +//- /main.rs crate:main deps:core +fn test() { + let r: Result = Result::Ok(1); let v = r?; - //^ f32 - r + v; +} //^ i32 + +//- /core.rs crate:core +mod ops { + mod try_trait { + pub trait Try: FromResidual { + type Output; + type Residual; + } + pub trait FromResidual::Residual> {} + } + + pub use self::try_trait::FromResidual; + pub use self::try_trait::Try; +} + +mod convert { + pub trait From {} + impl From for T {} +} + +pub mod result { + use crate::convert::From; + use crate::ops::{Try, FromResidual}; + + pub enum Infallible {} + pub enum Result { + Ok(O), + Err(E) + } + + impl Try for Result { + type Output = O; + type Error = Result; + } + + impl> FromResidual> for Result {} +} + +pub mod prelude { + pub mod rust_2018 { + pub use crate::result::*; + } } "#, ); diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index 6c8b3088adc0..c5dc60f1ec5f 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs @@ -6,7 +6,7 @@ use base_db::CrateId; use cfg::{CfgExpr, CfgOptions}; use either::Either; -use hir_def::{path::ModPath, TraitId}; +use hir_def::path::ModPath; use hir_expand::{name::Name, HirFileId, InFile}; use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange}; @@ -33,7 +33,6 @@ diagnostics![ BreakOutsideOfLoop, InactiveCode, IncorrectCase, - IncorrectTryExpr, InvalidDeriveTarget, MacroError, MalformedDerive, @@ -41,7 +40,6 @@ diagnostics![ MissingFields, MissingMatchArms, MissingUnsafe, - NotImplemented, NoSuchField, ReplaceFilterMapNextWithFindMap, TypeMismatch, @@ -155,16 +153,6 @@ pub struct MismatchedArgCount { pub expected: usize, pub found: usize, } -#[derive(Debug)] -pub struct IncorrectTryExpr { - pub expr: InFile>, -} -#[derive(Debug)] -pub struct NotImplemented { - pub expr: InFile>, - pub trait_: TraitId, - pub ty: Type, -} #[derive(Debug)] pub struct MissingMatchArms { diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index e6c5c6b58339..f5324208c9a4 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -81,12 +81,11 @@ use crate::db::{DefDatabase, HirDatabase}; pub use crate::{ attrs::{HasAttrs, Namespace}, diagnostics::{ - AnyDiagnostic, BreakOutsideOfLoop, InactiveCode, IncorrectCase, IncorrectTryExpr, - InvalidDeriveTarget, MacroError, MalformedDerive, MismatchedArgCount, MissingFields, - MissingMatchArms, MissingUnsafe, NoSuchField, NotImplemented, - ReplaceFilterMapNextWithFindMap, TypeMismatch, UnimplementedBuiltinMacro, - UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall, UnresolvedModule, - UnresolvedProcMacro, + AnyDiagnostic, BreakOutsideOfLoop, InactiveCode, IncorrectCase, InvalidDeriveTarget, + MacroError, MalformedDerive, MismatchedArgCount, MissingFields, MissingMatchArms, + MissingUnsafe, NoSuchField, ReplaceFilterMapNextWithFindMap, TypeMismatch, + UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall, + UnresolvedModule, UnresolvedProcMacro, }, has_source::HasSource, semantics::{PathResolution, Semantics, SemanticsScope, TypeInfo, VisibleTraits}, @@ -1283,45 +1282,30 @@ impl DefWithBody { let infer = db.infer(self.into()); let source_map = Lazy::new(|| db.body_with_source_map(self.into()).1); for d in &infer.diagnostics { - match *d { + match d { hir_ty::InferenceDiagnostic::NoSuchField { expr } => { - let field = source_map.field_syntax(expr); + let field = source_map.field_syntax(*expr); acc.push(NoSuchField { field }.into()) } - hir_ty::InferenceDiagnostic::BreakOutsideOfLoop { expr, is_break } => { + &hir_ty::InferenceDiagnostic::BreakOutsideOfLoop { expr, is_break } => { let expr = source_map .expr_syntax(expr) .expect("break outside of loop in synthetic syntax"); acc.push(BreakOutsideOfLoop { expr, is_break }.into()) } hir_ty::InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => { - match source_map.expr_syntax(call_expr) { + match source_map.expr_syntax(*call_expr) { Ok(source_ptr) => acc.push( MismatchedArgCount { call_expr: source_ptr, - expected: expected, - found: found, + expected: *expected, + found: *found, } .into(), ), Err(SyntheticSyntax) => (), } } - hir_ty::InferenceDiagnostic::IncorrectTryTarget { expr } => { - let expr = source_map.expr_syntax(expr).expect("try in synthetic syntax"); - acc.push(IncorrectTryExpr { expr }.into()) - } - hir_ty::InferenceDiagnostic::DoesNotImplement { expr, trait_, ref ty } => { - let expr = source_map.expr_syntax(expr).expect("try in synthetic syntax"); - acc.push( - NotImplemented { - expr, - trait_, - ty: Type::new(db, DefWithBodyId::from(self), ty.clone()), - } - .into(), - ) - } } } for (expr, mismatch) in infer.expr_type_mismatches() { diff --git a/crates/ide-diagnostics/src/handlers/incorrect_try_expr.rs b/crates/ide-diagnostics/src/handlers/incorrect_try_expr.rs deleted file mode 100644 index 085d8d32598a..000000000000 --- a/crates/ide-diagnostics/src/handlers/incorrect_try_expr.rs +++ /dev/null @@ -1,37 +0,0 @@ -use hir::InFile; - -use crate::{Diagnostic, DiagnosticsContext}; - -// Diagnostic: incorrect-try-target -// -// This diagnostic is triggered if a question mark operator was used in a context where it is not applicable. -pub(crate) fn incorrect_try_expr( - ctx: &DiagnosticsContext<'_>, - d: &hir::IncorrectTryExpr, -) -> Diagnostic { - Diagnostic::new( - "incorrect-try-target", - format!("the return type of the containing function does not implement `FromResidual`"), - ctx.sema - .diagnostics_display_range(InFile::new(d.expr.file_id, d.expr.value.clone().into())) - .range, - ) -} - -#[cfg(test)] -mod tests { - use crate::tests::check_diagnostics; - - #[test] - fn try_ops_diag() { - check_diagnostics( - r#" -//- minicore: try -fn test() { - core::ops::ControlFlow::::Continue(1.0)?; - // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the return type of the containing function does not implement `FromResidual` -} -"#, - ); - } -} diff --git a/crates/ide-diagnostics/src/handlers/not_implemented.rs b/crates/ide-diagnostics/src/handlers/not_implemented.rs deleted file mode 100644 index 3bf6a4232298..000000000000 --- a/crates/ide-diagnostics/src/handlers/not_implemented.rs +++ /dev/null @@ -1,35 +0,0 @@ -use hir::{db::DefDatabase, HirDisplay}; - -use crate::{Diagnostic, DiagnosticsContext}; - -// Diagnostic: not-implemented -// -// This diagnostic is triggered if a type doesn't implement a necessary trait. -pub(crate) fn not_implemented(ctx: &DiagnosticsContext<'_>, d: &hir::NotImplemented) -> Diagnostic { - Diagnostic::new( - "not-implemented", - format!( - "the trait `{}` is not implemented for `{}`", - ctx.sema.db.trait_data(d.trait_).name, - d.ty.display(ctx.sema.db) - ), - ctx.sema.diagnostics_display_range(d.expr.clone().map(|it| it.into())).range, - ) -} - -#[cfg(test)] -mod tests { - use crate::tests::check_diagnostics; - - #[test] - fn missing_try_impl() { - check_diagnostics( - r#" -//- minicore: try -fn main() { - ()?; -} //^^ error: the trait `Try` is not implemented for `()` -"#, - ) - } -} diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs index 4577072149a7..ae299f058414 100644 --- a/crates/ide-diagnostics/src/lib.rs +++ b/crates/ide-diagnostics/src/lib.rs @@ -29,7 +29,6 @@ mod handlers { pub(crate) mod break_outside_of_loop; pub(crate) mod inactive_code; pub(crate) mod incorrect_case; - pub(crate) mod incorrect_try_expr; pub(crate) mod invalid_derive_target; pub(crate) mod macro_error; pub(crate) mod malformed_derive; @@ -37,7 +36,6 @@ mod handlers { pub(crate) mod missing_fields; pub(crate) mod missing_match_arms; pub(crate) mod missing_unsafe; - pub(crate) mod not_implemented; pub(crate) mod no_such_field; pub(crate) mod replace_filter_map_next_with_find_map; pub(crate) mod type_mismatch; @@ -227,14 +225,12 @@ pub fn diagnostics( let d = match diag { AnyDiagnostic::BreakOutsideOfLoop(d) => handlers::break_outside_of_loop::break_outside_of_loop(&ctx, &d), AnyDiagnostic::IncorrectCase(d) => handlers::incorrect_case::incorrect_case(&ctx, &d), - AnyDiagnostic::IncorrectTryExpr(d) => handlers::incorrect_try_expr::incorrect_try_expr(&ctx, &d), AnyDiagnostic::MacroError(d) => handlers::macro_error::macro_error(&ctx, &d), AnyDiagnostic::MalformedDerive(d) => handlers::malformed_derive::malformed_derive(&ctx, &d), AnyDiagnostic::MismatchedArgCount(d) => handlers::mismatched_arg_count::mismatched_arg_count(&ctx, &d), AnyDiagnostic::MissingFields(d) => handlers::missing_fields::missing_fields(&ctx, &d), AnyDiagnostic::MissingMatchArms(d) => handlers::missing_match_arms::missing_match_arms(&ctx, &d), AnyDiagnostic::MissingUnsafe(d) => handlers::missing_unsafe::missing_unsafe(&ctx, &d), - AnyDiagnostic::NotImplemented(d) => handlers::not_implemented::not_implemented(&ctx, &d), AnyDiagnostic::NoSuchField(d) => handlers::no_such_field::no_such_field(&ctx, &d), AnyDiagnostic::ReplaceFilterMapNextWithFindMap(d) => handlers::replace_filter_map_next_with_find_map::replace_filter_map_next_with_find_map(&ctx, &d), AnyDiagnostic::TypeMismatch(d) => handlers::type_mismatch::type_mismatch(&ctx, &d), diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 5cab017a58db..eb997e6fef83 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -4913,22 +4913,6 @@ fn foo() -> NotResult<(), Short> { ``` "#]], ); - check_hover_range( - r#" -//- minicore: try -use core::ops::ControlFlow; -fn foo() -> ControlFlow<()> { - $0ControlFlow::Break(())?$0; - ControlFlow::Continue(()) -} -"#, - expect![[r#" - ```text - Try Target Type: ControlFlow<(), {unknown}> - Propagated as: ControlFlow<(), ()> - ``` - "#]], - ); } #[test] @@ -4944,9 +4928,9 @@ fn foo() -> Option<()> { } "#, expect![[r#" - ```rust - i32 - ```"#]], + ```rust + as Try>::Output + ```"#]], ); } diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs index 59b1c147d7f1..69d2e62b2567 100644 --- a/crates/test-utils/src/minicore.rs +++ b/crates/test-utils/src/minicore.rs @@ -27,7 +27,6 @@ //! generator: pin //! hash: //! index: sized -//! infallible: //! iterator: option //! iterators: iterator, fn //! option: @@ -37,7 +36,7 @@ //! result: //! sized: //! slice: -//! try: infallible +//! try: //! unsize: sized pub mod marker { @@ -151,9 +150,6 @@ pub mod convert { fn as_ref(&self) -> &T; } // endregion:as_ref - // region:infallible - pub enum Infallible {} - // endregion:infallible } pub mod ops { @@ -330,7 +326,7 @@ pub mod ops { Continue(C), Break(B), } - pub trait FromResidual::Residual> { + pub trait FromResidual { #[lang = "from_residual"] fn from_residual(residual: R) -> Self; } @@ -346,13 +342,13 @@ pub mod ops { impl Try for ControlFlow { type Output = C; - type Residual = ControlFlow; + type Residual = ControlFlow; fn from_output(output: Self::Output) -> Self {} fn branch(self) -> ControlFlow {} } impl FromResidual for ControlFlow { - fn from_residual(residual: ControlFlow) -> Self {} + fn from_residual(residual: ControlFlow) -> Self {} } } pub use self::try_::{ControlFlow, FromResidual, Try}; @@ -473,33 +469,6 @@ pub mod option { } } } - // region:try - impl crate::ops::Try for Option { - type Output = T; - type Residual = Option; - - #[inline] - fn from_output(output: Self::Output) -> Self { - Some(output) - } - - #[inline] - fn branch(self) -> crate::ops::ControlFlow { - match self { - Some(v) => crate::ops::ControlFlow::Continue(v), - None => crate::ops::ControlFlow::Break(None), - } - } - } - impl crate::ops::FromResidual for Option { - #[inline] - fn from_residual(residual: Option) -> Self { - match residual { - None => None, - } - } - } - // endregion:try } // endregion:option From f134370b916b107cc2c07a563430e99d3c102188 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 18 Oct 2022 16:47:35 +0200 Subject: [PATCH 023/171] apply joshua's suggestion Co-authored-by: Joshua Nelson --- src/bootstrap/doc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index a8524fea1b2a..939e169ec00e 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -299,7 +299,7 @@ impl Step for Standalone { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.path("src/doc").path("standalone").default_condition(builder.config.docs) + run.path("src/doc").alias("standalone").default_condition(builder.config.docs) } fn make_run(run: RunConfig<'_>) { From c3a1ca6be72dc676e585657983c48b8cd3048b0c Mon Sep 17 00:00:00 2001 From: CastilloDel Date: Tue, 4 Oct 2022 21:18:15 +0200 Subject: [PATCH 024/171] Remove allow(rustc::potential_query_instability) in rustc_const_eval The use of FxHashMap has been replaced with FxIndexMap. For more information see https://github.com/rust-lang/rust/issues/84447 --- .../rustc_const_eval/src/const_eval/machine.rs | 16 ++++++++-------- .../rustc_const_eval/src/interpret/intern.rs | 10 +++++----- .../rustc_const_eval/src/interpret/machine.rs | 2 +- compiler/rustc_const_eval/src/lib.rs | 1 - 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index e5acacd91888..35d58d2f638b 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -2,10 +2,10 @@ use rustc_hir::def::DefKind; use rustc_middle::mir; use rustc_middle::ty::{self, Ty, TyCtxt}; use std::borrow::Borrow; -use std::collections::hash_map::Entry; use std::hash::Hash; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::fx::IndexEntry; use std::fmt; use rustc_ast::Mutability; @@ -107,18 +107,18 @@ impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> { } } -impl interpret::AllocMap for FxHashMap { +impl interpret::AllocMap for FxIndexMap { #[inline(always)] fn contains_key(&mut self, k: &Q) -> bool where K: Borrow, { - FxHashMap::contains_key(self, k) + FxIndexMap::contains_key(self, k) } #[inline(always)] fn insert(&mut self, k: K, v: V) -> Option { - FxHashMap::insert(self, k, v) + FxIndexMap::insert(self, k, v) } #[inline(always)] @@ -126,7 +126,7 @@ impl interpret::AllocMap for FxHashMap { where K: Borrow, { - FxHashMap::remove(self, k) + FxIndexMap::remove(self, k) } #[inline(always)] @@ -148,8 +148,8 @@ impl interpret::AllocMap for FxHashMap { #[inline(always)] fn get_mut_or(&mut self, k: K, vacant: impl FnOnce() -> Result) -> Result<&mut V, E> { match self.entry(k) { - Entry::Occupied(e) => Ok(e.into_mut()), - Entry::Vacant(e) => { + IndexEntry::Occupied(e) => Ok(e.into_mut()), + IndexEntry::Vacant(e) => { let v = vacant()?; Ok(e.insert(v)) } diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index f72ae7413e30..fda2a1490968 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -15,7 +15,7 @@ //! that contains allocations whose mutability we cannot identify.) use super::validity::RefTracking; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_middle::mir::interpret::InterpResult; @@ -37,7 +37,7 @@ pub trait CompileTimeMachine<'mir, 'tcx, T> = Machine< ExtraFnVal = !, FrameExtra = (), AllocExtra = (), - MemoryMap = FxHashMap, Allocation)>, + MemoryMap = FxIndexMap, Allocation)>, >; struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>> { @@ -47,7 +47,7 @@ struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_ev ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, InternMode)>, /// A list of all encountered allocations. After type-based interning, we traverse this list to /// also intern allocations that are only referenced by a raw pointer or inside a union. - leftover_allocations: &'rt mut FxHashSet, + leftover_allocations: &'rt mut FxIndexSet, /// The root kind of the value that we're looking at. This field is never mutated for a /// particular allocation. It is primarily used to make as many allocations as possible /// read-only so LLVM can place them in const memory. @@ -79,7 +79,7 @@ struct IsStaticOrFn; /// to account for (e.g. for vtables). fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>>( ecx: &'rt mut InterpCx<'mir, 'tcx, M>, - leftover_allocations: &'rt mut FxHashSet, + leftover_allocations: &'rt mut FxIndexSet, alloc_id: AllocId, mode: InternMode, ty: Option>, @@ -355,7 +355,7 @@ pub fn intern_const_alloc_recursive< // `leftover_allocations` collects *all* allocations we see, because some might not // be available in a typed way. They get interned at the end. let mut ref_tracking = RefTracking::empty(); - let leftover_allocations = &mut FxHashSet::default(); + let leftover_allocations = &mut FxIndexSet::default(); // start with the outermost allocation intern_shallow( diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 530e252b7c07..351152eba01f 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -426,7 +426,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { type ExtraFnVal = !; type MemoryMap = - rustc_data_structures::fx::FxHashMap, Allocation)>; + rustc_data_structures::fx::FxIndexMap, Allocation)>; const GLOBAL_KIND: Option = None; // no copying of globals from `tcx` to machine memory type AllocExtra = (); diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 230f841cf4d5..443c01fdb90c 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -22,7 +22,6 @@ Rust MIR: a lowered representation of Rust. #![feature(yeet_expr)] #![feature(is_some_and)] #![recursion_limit = "256"] -#![allow(rustc::potential_query_instability)] #[macro_use] extern crate tracing; From 8de7a4f21ca1816845f4880d10885d5d354312b0 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 19 Oct 2022 08:43:21 -0700 Subject: [PATCH 025/171] rustdoc: add test case for masked blanket impl --- src/test/rustdoc/auxiliary/masked.rs | 4 ++++ src/test/rustdoc/masked.rs | 1 + 2 files changed, 5 insertions(+) diff --git a/src/test/rustdoc/auxiliary/masked.rs b/src/test/rustdoc/auxiliary/masked.rs index f289359e52ac..3d722d5e0c2e 100644 --- a/src/test/rustdoc/auxiliary/masked.rs +++ b/src/test/rustdoc/auxiliary/masked.rs @@ -8,3 +8,7 @@ pub trait MaskedTrait { impl MaskedTrait for String { fn masked_method() {} } + +pub trait MaskedBlanketTrait {} + +impl MaskedBlanketTrait for T {} diff --git a/src/test/rustdoc/masked.rs b/src/test/rustdoc/masked.rs index 80d5b99c0b03..875c026fd058 100644 --- a/src/test/rustdoc/masked.rs +++ b/src/test/rustdoc/masked.rs @@ -10,6 +10,7 @@ extern crate masked; // @!hasraw 'search-index.js' 'masked_method' // @!hasraw 'foo/struct.String.html' 'MaskedTrait' +// @!hasraw 'foo/struct.String.html' 'MaskedBlanketTrait' // @!hasraw 'foo/struct.String.html' 'masked_method' pub use std::string::String; From 47703d3f3daaa84b0d8e2c66ddd3835402da0884 Mon Sep 17 00:00:00 2001 From: Andrew Pollack Date: Mon, 3 Oct 2022 19:36:27 +0000 Subject: [PATCH 026/171] compiletest: refactor rustcflags to Vec --- src/bootstrap/test.rs | 10 +++++--- src/tools/compiletest/src/common.rs | 8 +++---- src/tools/compiletest/src/main.rs | 8 +++---- src/tools/compiletest/src/runtest.rs | 35 ++++++---------------------- 4 files changed, 22 insertions(+), 39 deletions(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 01f4cacd771f..0346f652ae27 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1386,7 +1386,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the } let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] }; flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests)); - flags.push(builder.config.cmd.rustc_args().join(" ")); + flags.extend(builder.config.cmd.rustc_args().iter().map(|s| s.to_string())); if let Some(linker) = builder.linker(target) { cmd.arg("--linker").arg(linker); @@ -1395,12 +1395,16 @@ note: if you're sure you want to do this, please open an issue as to why. In the let mut hostflags = flags.clone(); hostflags.push(format!("-Lnative={}", builder.test_helpers_out(compiler.host).display())); hostflags.extend(builder.lld_flags(compiler.host)); - cmd.arg("--host-rustcflags").arg(hostflags.join(" ")); + for flag in hostflags { + cmd.arg("--host-rustcflags").arg(flag); + } let mut targetflags = flags; targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display())); targetflags.extend(builder.lld_flags(target)); - cmd.arg("--target-rustcflags").arg(targetflags.join(" ")); + for flag in targetflags { + cmd.arg("--target-rustcflags").arg(flag); + } cmd.arg("--python").arg(builder.python()); diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index b9ac6c9f3641..0260f6848386 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -269,10 +269,10 @@ pub struct Config { pub runtool: Option, /// Flags to pass to the compiler when building for the host - pub host_rustcflags: Option, + pub host_rustcflags: Vec, /// Flags to pass to the compiler when building for the target - pub target_rustcflags: Option, + pub target_rustcflags: Vec, /// Whether tests should be optimized by default. Individual test-suites and test files may /// override this setting. @@ -457,12 +457,12 @@ pub enum Endian { } impl TargetCfg { - fn new(rustc_path: &Path, target: &str, target_rustcflags: &Option) -> TargetCfg { + fn new(rustc_path: &Path, target: &str, target_rustcflags: &Vec) -> TargetCfg { let output = match Command::new(rustc_path) .arg("--print=cfg") .arg("--target") .arg(target) - .args(target_rustcflags.into_iter().map(|s| s.split_whitespace()).flatten()) + .args(target_rustcflags) .output() { Ok(output) => output, diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index dccfd4e0d980..f2d80d7f5325 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -252,8 +252,8 @@ pub fn parse_config(args: Vec) -> Config { }), logfile: matches.opt_str("logfile").map(|s| PathBuf::from(&s)), runtool: matches.opt_str("runtool"), - host_rustcflags: Some(matches.opt_strs("host-rustcflags").join(" ")), - target_rustcflags: Some(matches.opt_strs("target-rustcflags").join(" ")), + host_rustcflags: matches.opt_strs("host-rustcflags"), + target_rustcflags: matches.opt_strs("target-rustcflags"), optimize_tests: matches.opt_present("optimize-tests"), target, host: opt_str2(matches.opt_str("host")), @@ -320,8 +320,8 @@ pub fn log_config(config: &Config) { format!("force_pass_mode: {}", opt_str(&config.force_pass_mode.map(|m| format!("{}", m))),), ); logv(c, format!("runtool: {}", opt_str(&config.runtool))); - logv(c, format!("host-rustcflags: {}", opt_str(&config.host_rustcflags))); - logv(c, format!("target-rustcflags: {}", opt_str(&config.target_rustcflags))); + logv(c, format!("host-rustcflags: {:?}", config.host_rustcflags)); + logv(c, format!("target-rustcflags: {:?}", config.target_rustcflags)); logv(c, format!("target: {}", config.target)); logv(c, format!("host: {}", config.host)); logv(c, format!("android-cross-path: {:?}", config.android_cross_path.display())); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 8f289876f730..3068f3c5b0b0 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -558,10 +558,7 @@ impl<'test> TestCx<'test> { .arg(&aux_dir) .args(&self.props.compile_flags) .envs(self.props.rustc_env.clone()); - self.maybe_add_external_args( - &mut rustc, - self.split_maybe_args(&self.config.target_rustcflags), - ); + self.maybe_add_external_args(&mut rustc, &self.config.target_rustcflags); let src = match read_from { ReadFrom::Stdin(src) => Some(src), @@ -629,10 +626,7 @@ impl<'test> TestCx<'test> { .arg("-L") .arg(aux_dir); self.set_revision_flags(&mut rustc); - self.maybe_add_external_args( - &mut rustc, - self.split_maybe_args(&self.config.target_rustcflags), - ); + self.maybe_add_external_args(&mut rustc, &self.config.target_rustcflags); rustc.args(&self.props.compile_flags); self.compose_and_run_compiler(rustc, Some(src)) @@ -1186,23 +1180,14 @@ impl<'test> TestCx<'test> { ProcRes { status, stdout: out, stderr: err, cmdline: format!("{:?}", cmd) } } - fn cleanup_debug_info_options(&self, options: &Option) -> Option { - if options.is_none() { - return None; - } - + fn cleanup_debug_info_options(&self, options: &Vec) -> Vec { // Remove options that are either unwanted (-O) or may lead to duplicates due to RUSTFLAGS. let options_to_remove = ["-O".to_owned(), "-g".to_owned(), "--debuginfo".to_owned()]; - let new_options = self - .split_maybe_args(options) - .into_iter() - .filter(|x| !options_to_remove.contains(x)) - .collect::>(); - Some(new_options.join(" ")) + options.to_vec().into_iter().filter(|x| !options_to_remove.contains(x)).collect() } - fn maybe_add_external_args(&self, cmd: &mut Command, args: Vec) { + fn maybe_add_external_args(&self, cmd: &mut Command, args: &Vec) { // Filter out the arguments that should not be added by runtest here. // // Notable use-cases are: do not add our optimisation flag if @@ -2035,15 +2020,9 @@ impl<'test> TestCx<'test> { } if self.props.force_host { - self.maybe_add_external_args( - &mut rustc, - self.split_maybe_args(&self.config.host_rustcflags), - ); + self.maybe_add_external_args(&mut rustc, &self.config.host_rustcflags); } else { - self.maybe_add_external_args( - &mut rustc, - self.split_maybe_args(&self.config.target_rustcflags), - ); + self.maybe_add_external_args(&mut rustc, &self.config.target_rustcflags); if !is_rustdoc { if let Some(ref linker) = self.config.linker { rustc.arg(format!("-Clinker={}", linker)); From 9d3e616f82aecd4ba81ee632483f26169aca1aa3 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 19 Oct 2022 21:17:11 +0200 Subject: [PATCH 027/171] Simplify --- crates/project-model/Cargo.toml | 4 +- crates/project-model/src/cargo_workspace.rs | 46 +++++++++++---------- crates/project-model/src/lib.rs | 4 +- crates/project-model/src/sysroot.rs | 1 + crates/syntax/src/ast/edit_in_place.rs | 5 +-- crates/syntax/src/lib.rs | 2 +- 6 files changed, 33 insertions(+), 29 deletions(-) diff --git a/crates/project-model/Cargo.toml b/crates/project-model/Cargo.toml index 6fd7c3166f82..cf9868740cb0 100644 --- a/crates/project-model/Cargo.toml +++ b/crates/project-model/Cargo.toml @@ -17,7 +17,6 @@ semver = "1.0.14" serde = { version = "1.0.137", features = ["derive"] } serde_json = "1.0.86" anyhow = "1.0.62" -expect-test = "1.4.0" la-arena = { version = "0.3.0", path = "../../lib/la-arena" } cfg = { path = "../cfg", version = "0.0.0" } @@ -26,3 +25,6 @@ toolchain = { path = "../toolchain", version = "0.0.0" } paths = { path = "../paths", version = "0.0.0" } stdx = { path = "../stdx", version = "0.0.0" } profile = { path = "../profile", version = "0.0.0" } + +[dev-dependencies] +expect-test = "1.4.0" diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs index 8e690f1125a0..8d011f22e621 100644 --- a/crates/project-model/src/cargo_workspace.rs +++ b/crates/project-model/src/cargo_workspace.rs @@ -283,8 +283,6 @@ impl CargoWorkspace { } CargoFeatures::Selected { features, no_default_features } => { if *no_default_features { - // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures` - // https://github.com/oli-obk/cargo_metadata/issues/79 meta.features(CargoOpt::NoDefaultFeatures); } if !features.is_empty() { @@ -329,18 +327,21 @@ impl CargoWorkspace { let ws_members = &meta.workspace_members; meta.packages.sort_by(|a, b| a.id.cmp(&b.id)); - for meta_pkg in &meta.packages { + for meta_pkg in meta.packages { let cargo_metadata::Package { - id, - edition, name, - manifest_path, version, - metadata, + id, + source, + targets: meta_targets, + features, + manifest_path, repository, + edition, + metadata, .. } = meta_pkg; - let meta = from_value::(metadata.clone()).unwrap_or_default(); + let meta = from_value::(metadata).unwrap_or_default(); let edition = match edition { cargo_metadata::Edition::E2015 => Edition::Edition2015, cargo_metadata::Edition::E2018 => Edition::Edition2018, @@ -352,35 +353,36 @@ impl CargoWorkspace { }; // We treat packages without source as "local" packages. That includes all members of // the current workspace, as well as any path dependency outside the workspace. - let is_local = meta_pkg.source.is_none(); - let is_member = ws_members.contains(id); + let is_local = source.is_none(); + let is_member = ws_members.contains(&id); let pkg = packages.alloc(PackageData { id: id.repr.clone(), - name: name.clone(), - version: version.clone(), - manifest: AbsPathBuf::assert(PathBuf::from(&manifest_path)).try_into().unwrap(), + name, + version, + manifest: AbsPathBuf::assert(manifest_path.into()).try_into().unwrap(), targets: Vec::new(), is_local, is_member, edition, - repository: repository.clone(), + repository, dependencies: Vec::new(), - features: meta_pkg.features.clone().into_iter().collect(), + features: features.into_iter().collect(), active_features: Vec::new(), metadata: meta.rust_analyzer.unwrap_or_default(), }); let pkg_data = &mut packages[pkg]; pkg_by_id.insert(id, pkg); - for meta_tgt in &meta_pkg.targets { - let is_proc_macro = meta_tgt.kind.as_slice() == ["proc-macro"]; + for meta_tgt in meta_targets { + let cargo_metadata::Target { name, kind, required_features, src_path, .. } = + meta_tgt; let tgt = targets.alloc(TargetData { package: pkg, - name: meta_tgt.name.clone(), - root: AbsPathBuf::assert(PathBuf::from(&meta_tgt.src_path)), - kind: TargetKind::new(meta_tgt.kind.as_slice()), - is_proc_macro, - required_features: meta_tgt.required_features.clone(), + name, + root: AbsPathBuf::assert(src_path.into()), + kind: TargetKind::new(&kind), + is_proc_macro: &*kind == ["proc-macro"], + required_features, }); pkg_data.targets.push(tgt); } diff --git a/crates/project-model/src/lib.rs b/crates/project-model/src/lib.rs index ce78ce85697a..28e9379c1ae8 100644 --- a/crates/project-model/src/lib.rs +++ b/crates/project-model/src/lib.rs @@ -67,7 +67,7 @@ impl ProjectManifest { if path.file_name().unwrap_or_default() == "Cargo.toml" { return Ok(ProjectManifest::CargoToml(path)); } - bail!("project root must point to Cargo.toml or rust-project.json: {}", path.display()) + bail!("project root must point to Cargo.toml or rust-project.json: {}", path.display()); } pub fn discover_single(path: &AbsPath) -> Result { @@ -78,7 +78,7 @@ impl ProjectManifest { }; if !candidates.is_empty() { - bail!("more than one project") + bail!("more than one project"); } Ok(res) } diff --git a/crates/project-model/src/sysroot.rs b/crates/project-model/src/sysroot.rs index bc37e3d132a6..d4f6940d7ed2 100644 --- a/crates/project-model/src/sysroot.rs +++ b/crates/project-model/src/sysroot.rs @@ -189,6 +189,7 @@ fn discover_sysroot_src_dir(sysroot_path: &AbsPathBuf) -> Option { get_rust_src(sysroot_path) } + fn discover_sysroot_src_dir_or_add_component( sysroot_path: &AbsPathBuf, current_dir: &AbsPath, diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs index 229e7419b736..660c057e99c5 100644 --- a/crates/syntax/src/ast/edit_in_place.rs +++ b/crates/syntax/src/ast/edit_in_place.rs @@ -645,7 +645,7 @@ impl ast::RecordPatFieldList { } fn get_or_insert_comma_after(syntax: &SyntaxNode) -> SyntaxToken { - let comma = match syntax + match syntax .siblings_with_tokens(Direction::Next) .filter_map(|it| it.into_token()) .find(|it| it.kind() == T![,]) @@ -656,8 +656,7 @@ fn get_or_insert_comma_after(syntax: &SyntaxNode) -> SyntaxToken { ted::insert(Position::after(syntax), &comma); comma } - }; - comma + } } impl ast::StmtList { diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs index 4f5e273a520a..84c66b27e69f 100644 --- a/crates/syntax/src/lib.rs +++ b/crates/syntax/src/lib.rs @@ -92,7 +92,7 @@ impl Parse { SyntaxNode::new_root(self.green.clone()) } pub fn errors(&self) -> &[SyntaxError] { - &*self.errors + &self.errors } } From 653dafa7b176174aead7d8f975e4041f82d7d53c Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 19 Oct 2022 22:25:57 +0200 Subject: [PATCH 028/171] Add some sysroot logging --- crates/project-model/src/sysroot.rs | 17 +++++++++-------- crates/project-model/src/workspace.rs | 9 +++++++++ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/crates/project-model/src/sysroot.rs b/crates/project-model/src/sysroot.rs index d4f6940d7ed2..fa8d76f3f452 100644 --- a/crates/project-model/src/sysroot.rs +++ b/crates/project-model/src/sysroot.rs @@ -64,14 +64,15 @@ impl Sysroot { self.by_name("proc_macro") } - pub fn crates<'a>(&'a self) -> impl Iterator + ExactSizeIterator + 'a { + pub fn crates(&self) -> impl Iterator + ExactSizeIterator + '_ { self.crates.iter().map(|(id, _data)| id) } } impl Sysroot { + /// Attempts to discover the toolchain's sysroot from the given `dir`. pub fn discover(dir: &AbsPath, extra_env: &FxHashMap) -> Result { - tracing::debug!("Discovering sysroot for {}", dir.display()); + tracing::debug!("discovering sysroot for {}", dir.display()); let sysroot_dir = discover_sysroot_dir(dir, extra_env)?; let sysroot_src_dir = discover_sysroot_src_dir_or_add_component(&sysroot_dir, dir, extra_env)?; @@ -83,11 +84,10 @@ impl Sysroot { cargo_toml: &ManifestPath, extra_env: &FxHashMap, ) -> Option { - tracing::debug!("Discovering rustc source for {}", cargo_toml.display()); + tracing::debug!("discovering rustc source for {}", cargo_toml.display()); let current_dir = cargo_toml.parent(); - discover_sysroot_dir(current_dir, extra_env) - .ok() - .and_then(|sysroot_dir| get_rustc_src(&sysroot_dir)) + let sysroot_dir = discover_sysroot_dir(current_dir, extra_env).ok()?; + get_rustc_src(&sysroot_dir) } pub fn with_sysroot_dir(sysroot_dir: AbsPathBuf) -> Result { @@ -200,6 +200,7 @@ fn discover_sysroot_src_dir_or_add_component( let mut rustup = Command::new(toolchain::rustup()); rustup.envs(extra_env); rustup.current_dir(current_dir).args(&["component", "add", "rust-src"]); + tracing::info!("adding rust-src component by {:?}", rustup); utf8_stdout(rustup).ok()?; get_rust_src(sysroot_path) }) @@ -218,7 +219,7 @@ try installing the Rust source the same way you installed rustc", fn get_rustc_src(sysroot_path: &AbsPath) -> Option { let rustc_src = sysroot_path.join("lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml"); let rustc_src = ManifestPath::try_from(rustc_src).ok()?; - tracing::debug!("Checking for rustc source code: {}", rustc_src.display()); + tracing::debug!("checking for rustc source code: {}", rustc_src.display()); if fs::metadata(&rustc_src).is_ok() { Some(rustc_src) } else { @@ -228,7 +229,7 @@ fn get_rustc_src(sysroot_path: &AbsPath) -> Option { fn get_rust_src(sysroot_path: &AbsPath) -> Option { let rust_src = sysroot_path.join("lib/rustlib/src/rust/library"); - tracing::debug!("Checking sysroot: {}", rust_src.display()); + tracing::debug!("checking sysroot library: {}", rust_src.display()); if fs::metadata(&rust_src).is_ok() { Some(rust_src) } else { diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index 72ddf809288a..9b0a2617036b 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -209,6 +209,9 @@ impl ProjectWorkspace { ), None => None, }; + if let Some(sysroot) = &sysroot { + tracing::info!(src_root = %sysroot.src_root().display(), root = %sysroot.root().display(), "Using sysroot"); + } let rustc_dir = match &config.rustc_source { Some(RustcSource::Path(path)) => ManifestPath::try_from(path.clone()).ok(), @@ -217,6 +220,9 @@ impl ProjectWorkspace { } None => None, }; + if let Some(rustc_dir) = &rustc_dir { + tracing::info!(rustc_dir = %rustc_dir.display(), "Using rustc source"); + } let rustc = match rustc_dir { Some(rustc_dir) => Some({ @@ -277,6 +283,9 @@ impl ProjectWorkspace { } (None, None) => None, }; + if let Some(sysroot) = &sysroot { + tracing::info!(src_root = %sysroot.src_root().display(), root = %sysroot.root().display(), "Using sysroot"); + } let rustc_cfg = rustc_cfg::get(None, target, extra_env); Ok(ProjectWorkspace::Json { project: project_json, sysroot, rustc_cfg }) From 7e2c41dbd68014acbf91c2657a975c5a4b486da9 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 27 Aug 2022 18:28:09 +0200 Subject: [PATCH 029/171] Implement invocation strategy config for build scripts --- crates/project-model/src/build_scripts.rs | 400 ++++++++++++-------- crates/project-model/src/cargo_workspace.rs | 3 +- crates/project-model/src/lib.rs | 8 + crates/project-model/src/workspace.rs | 60 ++- crates/rust-analyzer/src/config.rs | 32 ++ crates/rust-analyzer/src/reload.rs | 6 +- docs/user/generated_config.adoc | 11 + editors/code/package.json | 15 + 8 files changed, 373 insertions(+), 162 deletions(-) diff --git a/crates/project-model/src/build_scripts.rs b/crates/project-model/src/build_scripts.rs index d9f09c034956..6e6654e74e1a 100644 --- a/crates/project-model/src/build_scripts.rs +++ b/crates/project-model/src/build_scripts.rs @@ -6,7 +6,12 @@ //! This module implements this second part. We use "build script" terminology //! here, but it covers procedural macros as well. -use std::{cell::RefCell, io, path::PathBuf, process::Command}; +use std::{ + cell::RefCell, + io, mem, + path::{self, PathBuf}, + process::Command, +}; use cargo_metadata::{camino::Utf8Path, Message}; use la_arena::ArenaMap; @@ -15,11 +20,13 @@ use rustc_hash::FxHashMap; use semver::Version; use serde::Deserialize; -use crate::{cfg_flag::CfgFlag, CargoConfig, CargoFeatures, CargoWorkspace, Package}; +use crate::{ + cfg_flag::CfgFlag, CargoConfig, CargoFeatures, CargoWorkspace, InvocationStrategy, Package, +}; #[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct WorkspaceBuildScripts { - outputs: ArenaMap>, + outputs: ArenaMap, error: Option, } @@ -38,76 +45,55 @@ pub(crate) struct BuildScriptOutput { pub(crate) proc_macro_dylib_path: Option, } +impl BuildScriptOutput { + fn is_unchanged(&self) -> bool { + self.cfgs.is_empty() + && self.envs.is_empty() + && self.out_dir.is_none() + && self.proc_macro_dylib_path.is_none() + } +} + impl WorkspaceBuildScripts { - fn build_command(config: &CargoConfig) -> Command { - if let Some([program, args @ ..]) = config.run_build_script_command.as_deref() { - let mut cmd = Command::new(program); - cmd.args(args); - cmd.envs(&config.extra_env); - return cmd; - } + fn build_command(config: &CargoConfig) -> io::Result { + let mut cmd = match config.run_build_script_command.as_deref() { + Some([program, args @ ..]) => { + let mut cmd = Command::new(program); + cmd.args(args); + cmd + } + _ => { + let mut cmd = Command::new(toolchain::cargo()); - let mut cmd = Command::new(toolchain::cargo()); + cmd.args(&["check", "--quiet", "--workspace", "--message-format=json"]); + + // --all-targets includes tests, benches and examples in addition to the + // default lib and bins. This is an independent concept from the --targets + // flag below. + cmd.arg("--all-targets"); + + if let Some(target) = &config.target { + cmd.args(&["--target", target]); + } + + match &config.features { + CargoFeatures::All => { + cmd.arg("--all-features"); + } + CargoFeatures::Selected { features, no_default_features } => { + if *no_default_features { + cmd.arg("--no-default-features"); + } + if !features.is_empty() { + cmd.arg("--features"); + cmd.arg(features.join(" ")); + } + } + } + cmd + } + }; cmd.envs(&config.extra_env); - cmd.args(&["check", "--quiet", "--workspace", "--message-format=json"]); - - // --all-targets includes tests, benches and examples in addition to the - // default lib and bins. This is an independent concept from the --targets - // flag below. - cmd.arg("--all-targets"); - - if let Some(target) = &config.target { - cmd.args(&["--target", target]); - } - - match &config.features { - CargoFeatures::All => { - cmd.arg("--all-features"); - } - CargoFeatures::Selected { features, no_default_features } => { - if *no_default_features { - cmd.arg("--no-default-features"); - } - if !features.is_empty() { - cmd.arg("--features"); - cmd.arg(features.join(" ")); - } - } - } - - cmd - } - - pub(crate) fn run( - config: &CargoConfig, - workspace: &CargoWorkspace, - progress: &dyn Fn(String), - toolchain: &Option, - ) -> io::Result { - const RUST_1_62: Version = Version::new(1, 62, 0); - - match Self::run_(Self::build_command(config), config, workspace, progress) { - Ok(WorkspaceBuildScripts { error: Some(error), .. }) - if toolchain.as_ref().map_or(false, |it| *it >= RUST_1_62) => - { - // building build scripts failed, attempt to build with --keep-going so - // that we potentially get more build data - let mut cmd = Self::build_command(config); - cmd.args(&["-Z", "unstable-options", "--keep-going"]).env("RUSTC_BOOTSTRAP", "1"); - let mut res = Self::run_(cmd, config, workspace, progress)?; - res.error = Some(error); - Ok(res) - } - res => res, - } - } - - fn run_( - mut cmd: Command, - config: &CargoConfig, - workspace: &CargoWorkspace, - progress: &dyn Fn(String), - ) -> io::Result { if config.wrap_rustc_in_build_scripts { // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use // that to compile only proc macros and build scripts during the initial @@ -117,7 +103,107 @@ impl WorkspaceBuildScripts { cmd.env("RA_RUSTC_WRAPPER", "1"); } - cmd.current_dir(workspace.workspace_root()); + Ok(cmd) + } + + /// Runs the build scripts for the given workspace + pub(crate) fn run_for_workspace( + config: &CargoConfig, + workspace: &CargoWorkspace, + progress: &dyn Fn(String), + toolchain: &Option, + ) -> io::Result { + const RUST_1_62: Version = Version::new(1, 62, 0); + + match Self::run_per_ws(Self::build_command(config)?, config, workspace, progress) { + Ok(WorkspaceBuildScripts { error: Some(error), .. }) + if toolchain.as_ref().map_or(false, |it| *it >= RUST_1_62) => + { + // building build scripts failed, attempt to build with --keep-going so + // that we potentially get more build data + let mut cmd = Self::build_command(config)?; + cmd.args(&["-Z", "unstable-options", "--keep-going"]).env("RUSTC_BOOTSTRAP", "1"); + let mut res = Self::run_per_ws(cmd, config, workspace, progress)?; + res.error = Some(error); + Ok(res) + } + res => res, + } + } + + /// Runs the build scripts by invoking the configured command *once*. + /// This populates the outputs for all passed in workspaces. + pub(crate) fn run_once( + config: &CargoConfig, + workspaces: &[&CargoWorkspace], + progress: &dyn Fn(String), + ) -> io::Result> { + assert_eq!(config.invocation_strategy, InvocationStrategy::OnceInRoot); + let cmd = Self::build_command(config)?; + // NB: Cargo.toml could have been modified between `cargo metadata` and + // `cargo check`. We shouldn't assume that package ids we see here are + // exactly those from `config`. + let mut by_id = FxHashMap::default(); + let mut res: Vec<_> = workspaces + .iter() + .enumerate() + .map(|(idx, workspace)| { + let mut res = WorkspaceBuildScripts::default(); + for package in workspace.packages() { + res.outputs.insert(package, BuildScriptOutput::default()); + by_id.insert(workspace[package].id.clone(), (package, idx)); + } + res + }) + .collect(); + + let errors = Self::run_command( + cmd, + |package, cb| { + if let Some(&(package, workspace)) = by_id.get(package) { + cb(&workspaces[workspace][package].name, &mut res[workspace].outputs[package]); + } + }, + progress, + )?; + res.iter_mut().for_each(|it| it.error = errors.clone()); + + if tracing::enabled!(tracing::Level::INFO) { + for (idx, workspace) in workspaces.iter().enumerate() { + for package in workspace.packages() { + let package_build_data = &mut res[idx].outputs[package]; + if !package_build_data.is_unchanged() { + tracing::info!( + "{}: {:?}", + workspace[package].manifest.parent().display(), + package_build_data, + ); + } + } + } + } + + Ok(res) + } + + fn run_per_ws( + mut cmd: Command, + config: &CargoConfig, + workspace: &CargoWorkspace, + progress: &dyn Fn(String), + ) -> io::Result { + let workspace_root: &path::Path = &workspace.workspace_root().as_ref(); + + match config.invocation_strategy { + InvocationStrategy::OnceInRoot => (), + InvocationStrategy::PerWorkspaceWithManifestPath => { + cmd.arg("--manifest-path"); + cmd.arg(workspace_root.join("Cargo.toml")); + } + InvocationStrategy::PerWorkspace => { + cmd.current_dir(workspace_root); + } + } let mut res = WorkspaceBuildScripts::default(); let outputs = &mut res.outputs; @@ -126,10 +212,44 @@ impl WorkspaceBuildScripts { // exactly those from `config`. let mut by_id: FxHashMap = FxHashMap::default(); for package in workspace.packages() { - outputs.insert(package, None); + outputs.insert(package, BuildScriptOutput::default()); by_id.insert(workspace[package].id.clone(), package); } + res.error = Self::run_command( + cmd, + |package, cb| { + if let Some(&package) = by_id.get(package) { + cb(&workspace[package].name, &mut outputs[package]); + } + }, + progress, + )?; + + if tracing::enabled!(tracing::Level::INFO) { + for package in workspace.packages() { + let package_build_data = &mut outputs[package]; + if !package_build_data.is_unchanged() { + tracing::info!( + "{}: {:?}", + workspace[package].manifest.parent().display(), + package_build_data, + ); + } + } + } + + Ok(res) + } + + fn run_command( + cmd: Command, + // ideally this would be something like: + // with_output_for: impl FnMut(&str, dyn FnOnce(&mut BuildScriptOutput)), + // but owned trait objects aren't a thing + mut with_output_for: impl FnMut(&str, &mut dyn FnMut(&str, &mut BuildScriptOutput)), + progress: &dyn Fn(String), + ) -> io::Result> { let errors = RefCell::new(String::new()); let push_err = |err: &str| { let mut e = errors.borrow_mut(); @@ -149,61 +269,58 @@ impl WorkspaceBuildScripts { .unwrap_or_else(|_| Message::TextLine(line.to_string())); match message { - Message::BuildScriptExecuted(message) => { - let package = match by_id.get(&message.package_id.repr) { - Some(&it) => it, - None => return, - }; - progress(format!("running build-script: {}", workspace[package].name)); - - let cfgs = { - let mut acc = Vec::new(); - for cfg in message.cfgs { - match cfg.parse::() { - Ok(it) => acc.push(it), - Err(err) => { - push_err(&format!( - "invalid cfg from cargo-metadata: {}", - err - )); - return; - } - }; + Message::BuildScriptExecuted(mut message) => { + with_output_for(&message.package_id.repr, &mut |name, data| { + progress(format!("running build-script: {}", name)); + let cfgs = { + let mut acc = Vec::new(); + for cfg in &message.cfgs { + match cfg.parse::() { + Ok(it) => acc.push(it), + Err(err) => { + push_err(&format!( + "invalid cfg from cargo-metadata: {}", + err + )); + return; + } + }; + } + acc + }; + if !message.env.is_empty() { + data.envs = mem::take(&mut message.env); } - acc - }; - // cargo_metadata crate returns default (empty) path for - // older cargos, which is not absolute, so work around that. - let out_dir = message.out_dir.into_os_string(); - if !out_dir.is_empty() { - let data = outputs[package].get_or_insert_with(Default::default); - data.out_dir = Some(AbsPathBuf::assert(PathBuf::from(out_dir))); - data.cfgs = cfgs; - } - if !message.env.is_empty() { - outputs[package].get_or_insert_with(Default::default).envs = - message.env; - } + // cargo_metadata crate returns default (empty) path for + // older cargos, which is not absolute, so work around that. + let out_dir = mem::take(&mut message.out_dir).into_os_string(); + if !out_dir.is_empty() { + let out_dir = AbsPathBuf::assert(PathBuf::from(out_dir)); + // inject_cargo_env(package, package_build_data); + // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!() + if let Some(out_dir) = + out_dir.as_os_str().to_str().map(|s| s.to_owned()) + { + data.envs.push(("OUT_DIR".to_string(), out_dir)); + } + data.out_dir = Some(out_dir); + data.cfgs = cfgs; + } + }); } Message::CompilerArtifact(message) => { - let package = match by_id.get(&message.package_id.repr) { - Some(it) => *it, - None => return, - }; - - progress(format!("building proc-macros: {}", message.target.name)); - - if message.target.kind.iter().any(|k| k == "proc-macro") { - // Skip rmeta file - if let Some(filename) = - message.filenames.iter().find(|name| is_dylib(name)) - { - let filename = AbsPathBuf::assert(PathBuf::from(&filename)); - outputs[package] - .get_or_insert_with(Default::default) - .proc_macro_dylib_path = Some(filename); + with_output_for(&message.package_id.repr, &mut |name, data| { + progress(format!("building proc-macros: {}", name)); + if message.target.kind.iter().any(|k| k == "proc-macro") { + // Skip rmeta file + if let Some(filename) = + message.filenames.iter().find(|name| is_dylib(name)) + { + let filename = AbsPathBuf::assert(PathBuf::from(&filename)); + data.proc_macro_dylib_path = Some(filename); + } } - } + }); } Message::CompilerMessage(message) => { progress(message.target.name); @@ -222,32 +339,13 @@ impl WorkspaceBuildScripts { }, )?; - for package in workspace.packages() { - if let Some(package_build_data) = &mut outputs[package] { - tracing::info!( - "{}: {:?}", - workspace[package].manifest.parent().display(), - package_build_data, - ); - // inject_cargo_env(package, package_build_data); - if let Some(out_dir) = &package_build_data.out_dir { - // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!() - if let Some(out_dir) = out_dir.as_os_str().to_str().map(|s| s.to_owned()) { - package_build_data.envs.push(("OUT_DIR".to_string(), out_dir)); - } - } - } - } - - let mut errors = errors.into_inner(); - if !output.status.success() { - if errors.is_empty() { - errors = "cargo check failed".to_string(); - } - res.error = Some(errors); - } - - Ok(res) + let errors = if !output.status.success() { + let errors = errors.into_inner(); + Some(if errors.is_empty() { "cargo check failed".to_string() } else { errors }) + } else { + None + }; + Ok(errors) } pub fn error(&self) -> Option<&str> { @@ -255,11 +353,11 @@ impl WorkspaceBuildScripts { } pub(crate) fn get_output(&self, idx: Package) -> Option<&BuildScriptOutput> { - self.outputs.get(idx)?.as_ref() + self.outputs.get(idx) } } -// FIXME: File a better way to know if it is a dylib. +// FIXME: Find a better way to know if it is a dylib. fn is_dylib(path: &Utf8Path) -> bool { match path.extension().map(|e| e.to_string().to_lowercase()) { None => false, diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs index 8e690f1125a0..79b56815c021 100644 --- a/crates/project-model/src/cargo_workspace.rs +++ b/crates/project-model/src/cargo_workspace.rs @@ -14,8 +14,8 @@ use rustc_hash::FxHashMap; use serde::Deserialize; use serde_json::from_value; -use crate::CfgOverrides; use crate::{utf8_stdout, ManifestPath}; +use crate::{CfgOverrides, InvocationStrategy}; /// [`CargoWorkspace`] represents the logical structure of, well, a Cargo /// workspace. It pretty closely mirrors `cargo metadata` output. @@ -106,6 +106,7 @@ pub struct CargoConfig { pub run_build_script_command: Option>, /// Extra env vars to set when invoking the cargo command pub extra_env: FxHashMap, + pub invocation_strategy: InvocationStrategy, } impl CargoConfig { diff --git a/crates/project-model/src/lib.rs b/crates/project-model/src/lib.rs index ce78ce85697a..13a86901f71c 100644 --- a/crates/project-model/src/lib.rs +++ b/crates/project-model/src/lib.rs @@ -157,3 +157,11 @@ fn utf8_stdout(mut cmd: Command) -> Result { let stdout = String::from_utf8(output.stdout)?; Ok(stdout.trim().to_string()) } + +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub enum InvocationStrategy { + OnceInRoot, + PerWorkspaceWithManifestPath, + #[default] + PerWorkspace, +} diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index 72ddf809288a..01f5157093ad 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -2,7 +2,7 @@ //! metadata` or `rust-project.json`) into representation stored in the salsa //! database -- `CrateGraph`. -use std::{collections::VecDeque, fmt, fs, process::Command}; +use std::{collections::VecDeque, fmt, fs, process::Command, sync::Arc}; use anyhow::{format_err, Context, Result}; use base_db::{ @@ -21,8 +21,8 @@ use crate::{ cfg_flag::CfgFlag, rustc_cfg, sysroot::SysrootCrate, - utf8_stdout, CargoConfig, CargoWorkspace, ManifestPath, Package, ProjectJson, ProjectManifest, - Sysroot, TargetKind, WorkspaceBuildScripts, + utf8_stdout, CargoConfig, CargoWorkspace, InvocationStrategy, ManifestPath, Package, + ProjectJson, ProjectManifest, Sysroot, TargetKind, WorkspaceBuildScripts, }; /// A set of cfg-overrides per crate. @@ -294,6 +294,7 @@ impl ProjectWorkspace { Ok(ProjectWorkspace::DetachedFiles { files: detached_files, sysroot, rustc_cfg }) } + /// Runs the build scripts for this [`ProjectWorkspace`]. pub fn run_build_scripts( &self, config: &CargoConfig, @@ -301,9 +302,13 @@ impl ProjectWorkspace { ) -> Result { match self { ProjectWorkspace::Cargo { cargo, toolchain, .. } => { - WorkspaceBuildScripts::run(config, cargo, progress, toolchain).with_context(|| { - format!("Failed to run build scripts for {}", &cargo.workspace_root().display()) - }) + WorkspaceBuildScripts::run_for_workspace(config, cargo, progress, toolchain) + .with_context(|| { + format!( + "Failed to run build scripts for {}", + &cargo.workspace_root().display() + ) + }) } ProjectWorkspace::Json { .. } | ProjectWorkspace::DetachedFiles { .. } => { Ok(WorkspaceBuildScripts::default()) @@ -311,6 +316,49 @@ impl ProjectWorkspace { } } + /// Runs the build scripts for the given [`ProjectWorkspace`]s. Depending on the invocation + /// strategy this may run a single build process for all project workspaces. + pub fn run_all_build_scripts( + workspaces: &[ProjectWorkspace], + config: &CargoConfig, + progress: &dyn Fn(String), + ) -> Vec> { + if let InvocationStrategy::PerWorkspaceWithManifestPath | InvocationStrategy::PerWorkspace = + config.invocation_strategy + { + return workspaces.iter().map(|it| it.run_build_scripts(config, progress)).collect(); + } + + let cargo_ws: Vec<_> = workspaces + .iter() + .filter_map(|it| match it { + ProjectWorkspace::Cargo { cargo, .. } => Some(cargo), + _ => None, + }) + .collect(); + let ref mut outputs = match WorkspaceBuildScripts::run_once(config, &cargo_ws, progress) { + Ok(it) => Ok(it.into_iter()), + // io::Error is not Clone? + Err(e) => Err(Arc::new(e)), + }; + + workspaces + .iter() + .map(|it| match it { + ProjectWorkspace::Cargo { cargo, .. } => match outputs { + Ok(outputs) => Ok(outputs.next().unwrap()), + Err(e) => Err(e.clone()).with_context(|| { + format!( + "Failed to run build scripts for {}", + &cargo.workspace_root().display() + ) + }), + }, + _ => Ok(WorkspaceBuildScripts::default()), + }) + .collect() + } + pub fn set_build_scripts(&mut self, bs: WorkspaceBuildScripts) { match self { ProjectWorkspace::Cargo { build_scripts, .. } => *build_scripts = bs, diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 577a8640a4c0..79f6ded4899e 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -69,6 +69,14 @@ config_data! { cargo_autoreload: bool = "true", /// Run build scripts (`build.rs`) for more precise code analysis. cargo_buildScripts_enable: bool = "true", + /// Specifies the invocation strategy to use when running the build scripts command. + /// If `per_workspace_with_manifest_path` is set, the command will be executed for each + /// workspace, `--manifest-path {workspace-dir}` will be passed to the invoked command and + /// the command will be executed from the project root. + /// If `per_workspace` is set, the command will be executed for each workspace and the + /// command will be executed from the corresponding workspace root. + /// If `once_in_root` is set, the command will be executed once in the project root. + cargo_buildScripts_invocationStrategy: InvocationStrategy = "\"per_workspace\"", /// Override the command rust-analyzer uses to run build scripts and /// build procedural macros. The command is required to output json /// and should therefore include `--message-format=json` or a similar @@ -1056,6 +1064,13 @@ impl Config { rustc_source, unset_test_crates: UnsetTestCrates::Only(self.data.cargo_unsetTest.clone()), wrap_rustc_in_build_scripts: self.data.cargo_buildScripts_useRustcWrapper, + invocation_strategy: match self.data.cargo_buildScripts_invocationStrategy { + InvocationStrategy::OnceInRoot => project_model::InvocationStrategy::OnceInRoot, + InvocationStrategy::PerWorkspaceWithManifestPath => { + project_model::InvocationStrategy::PerWorkspaceWithManifestPath + } + InvocationStrategy::PerWorkspace => project_model::InvocationStrategy::PerWorkspace, + }, run_build_script_command: self.data.cargo_buildScripts_overrideCommand.clone(), extra_env: self.data.cargo_extraEnv.clone(), } @@ -1587,6 +1602,14 @@ enum CargoFeaturesDef { Selected(Vec), } +#[derive(Deserialize, Debug, Clone)] +#[serde(rename_all = "snake_case")] +enum InvocationStrategy { + OnceInRoot, + PerWorkspaceWithManifestPath, + PerWorkspace, +} + #[derive(Deserialize, Debug, Clone)] #[serde(untagged)] enum LifetimeElisionDef { @@ -2001,6 +2024,15 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json "Render annotations above the whole item, including documentation comments and attributes." ], }, + "InvocationStrategy" => set! { + "type": "string", + "enum": ["per_workspace", "per_workspace_with_manifest_path", "once_in_root"], + "enumDescriptions": [ + "The command will be executed for each workspace, `--manifest-path {workspace-dir}` will be passed to the invoked command and the command will be executed from the project root.", + "The command will be executed for each workspace and the command will be executed from the corresponding workspace root.", + "The command will be executed once in the project root." + ], + }, _ => panic!("missing entry for {}: {}", ty, default), } diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index f87348939446..bd5741f61590 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -175,10 +175,8 @@ impl GlobalState { sender.send(Task::FetchBuildData(BuildDataProgress::Report(msg))).unwrap() } }; - let mut res = Vec::new(); - for ws in workspaces.iter() { - res.push(ws.run_build_scripts(&config, &progress)); - } + let res = ProjectWorkspace::run_all_build_scripts(&workspaces, &config, &progress); + sender.send(Task::FetchBuildData(BuildDataProgress::End((workspaces, res)))).unwrap(); }); } diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index acf0aaea859a..a5307b631512 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -24,6 +24,17 @@ Automatically refresh project info via `cargo metadata` on -- Run build scripts (`build.rs`) for more precise code analysis. -- +[[rust-analyzer.cargo.buildScripts.invocationStrategy]]rust-analyzer.cargo.buildScripts.invocationStrategy (default: `"per_workspace"`):: ++ +-- +Specifies the invocation strategy to use when running the build scripts command. +If `per_workspace_with_manifest_path` is set, the command will be executed for each +workspace, `--manifest-path {workspace-dir}` will be passed to the invoked command and +the command will be executed from the project root. +If `per_workspace` is set, the command will be executed for each workspace and the +command will be executed from the corresponding workspace root. +If `once_in_root` is set, the command will be executed once in the project root. +-- [[rust-analyzer.cargo.buildScripts.overrideCommand]]rust-analyzer.cargo.buildScripts.overrideCommand (default: `null`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index f1dd3aa79ff0..b1b565106a37 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -421,6 +421,21 @@ "default": true, "type": "boolean" }, + "rust-analyzer.cargo.buildScripts.invocationStrategy": { + "markdownDescription": "Specifies the invocation strategy to use when running the build scripts command.\nIf `per_workspace_with_manifest_path` is set, the command will be executed for each\nworkspace, `--manifest-path {workspace-dir}` will be passed to the invoked command and\nthe command will be executed from the project root.\nIf `per_workspace` is set, the command will be executed for each workspace and the\ncommand will be executed from the corresponding workspace root.\nIf `once_in_root` is set, the command will be executed once in the project root.", + "default": "per_workspace", + "type": "string", + "enum": [ + "per_workspace", + "per_workspace_with_manifest_path", + "once_in_root" + ], + "enumDescriptions": [ + "The command will be executed for each workspace, `--manifest-path {workspace-dir}` will be passed to the invoked command and the command will be executed from the project root.", + "The command will be executed for each workspace and the command will be executed from the corresponding workspace root.", + "The command will be executed once in the project root." + ] + }, "rust-analyzer.cargo.buildScripts.overrideCommand": { "markdownDescription": "Override the command rust-analyzer uses to run build scripts and\nbuild procedural macros. The command is required to output json\nand should therefore include `--message-format=json` or a similar\noption.\n\nBy default, a cargo invocation will be constructed for the configured\ntargets and features, with the following base command line:\n\n```bash\ncargo check --quiet --workspace --message-format=json --all-targets\n```\n.", "default": null, From 4a287d25258aac0873863584e6f3d075dfb69033 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 15 Sep 2022 13:28:09 +0200 Subject: [PATCH 030/171] Implement invocation strategy config for checkOnSave Note that due to how cargo works, none of the modes currently work for r-a --- crates/flycheck/src/lib.rs | 53 ++++++++++++++++++++---- crates/rust-analyzer/src/config.rs | 17 ++++++++ crates/rust-analyzer/src/reload.rs | 65 ++++++++++++++++++------------ docs/user/generated_config.adoc | 11 +++++ editors/code/package.json | 15 +++++++ 5 files changed, 127 insertions(+), 34 deletions(-) diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index e8c63d410aa7..c3976e6b7a86 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs @@ -6,6 +6,7 @@ use std::{ fmt, io, + path::Path, process::{ChildStderr, ChildStdout, Command, Stdio}, time::Duration, }; @@ -21,6 +22,14 @@ pub use cargo_metadata::diagnostic::{ DiagnosticSpanMacroExpansion, }; +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub enum InvocationStrategy { + OnceInRoot, + PerWorkspaceWithManifestPath, + #[default] + PerWorkspace, +} + #[derive(Clone, Debug, PartialEq, Eq)] pub enum FlycheckConfig { CargoCommand { @@ -32,11 +41,13 @@ pub enum FlycheckConfig { features: Vec, extra_args: Vec, extra_env: FxHashMap, + invocation_strategy: InvocationStrategy, }, CustomCommand { command: String, args: Vec, extra_env: FxHashMap, + invocation_strategy: InvocationStrategy, }, } @@ -136,7 +147,9 @@ enum Restart { No, } +/// A [`FlycheckActor`] is a single check instance of a workspace. struct FlycheckActor { + /// The workspace id of this flycheck instance. id: usize, sender: Box, config: FlycheckConfig, @@ -164,9 +177,11 @@ impl FlycheckActor { tracing::info!(%id, ?workspace_root, "Spawning flycheck"); FlycheckActor { id, sender, config, workspace_root, cargo_handle: None } } - fn progress(&self, progress: Progress) { + + fn report_progress(&self, progress: Progress) { self.send(Message::Progress { id: self.id, progress }); } + fn next_event(&self, inbox: &Receiver) -> Option { let check_chan = self.cargo_handle.as_ref().map(|cargo| &cargo.receiver); if let Ok(msg) = inbox.try_recv() { @@ -178,6 +193,7 @@ impl FlycheckActor { recv(check_chan.unwrap_or(&never())) -> msg => Some(Event::CheckEvent(msg.ok())), } } + fn run(mut self, inbox: Receiver) { 'event: while let Some(event) = self.next_event(&inbox) { match event { @@ -194,7 +210,20 @@ impl FlycheckActor { } } - let command = self.check_command(); + let mut command = self.check_command(); + let invocation_strategy = self.invocation_strategy(); + match invocation_strategy { + InvocationStrategy::OnceInRoot => (), + InvocationStrategy::PerWorkspaceWithManifestPath => { + command.arg("--manifest-path"); + command.arg(<_ as AsRef>::as_ref( + &self.workspace_root.join("Cargo.toml"), + )); + } + InvocationStrategy::PerWorkspace => { + command.current_dir(&self.workspace_root); + } + } tracing::debug!(?command, "will restart flycheck"); match CargoHandle::spawn(command) { Ok(cargo_handle) => { @@ -203,10 +232,10 @@ impl FlycheckActor { "did restart flycheck" ); self.cargo_handle = Some(cargo_handle); - self.progress(Progress::DidStart); + self.report_progress(Progress::DidStart); } Err(error) => { - self.progress(Progress::DidFailToRestart(format!( + self.report_progress(Progress::DidFailToRestart(format!( "Failed to run the following command: {:?} error={}", self.check_command(), error @@ -226,11 +255,11 @@ impl FlycheckActor { self.check_command() ); } - self.progress(Progress::DidFinish(res)); + self.report_progress(Progress::DidFinish(res)); } Event::CheckEvent(Some(message)) => match message { CargoMessage::CompilerArtifact(msg) => { - self.progress(Progress::DidCheckCrate(msg.target.name)); + self.report_progress(Progress::DidCheckCrate(msg.target.name)); } CargoMessage::Diagnostic(msg) => { @@ -254,7 +283,14 @@ impl FlycheckActor { "did cancel flycheck" ); cargo_handle.cancel(); - self.progress(Progress::DidCancel); + self.report_progress(Progress::DidCancel); + } + } + + fn invocation_strategy(&self) -> InvocationStrategy { + match self.config { + FlycheckConfig::CargoCommand { invocation_strategy, .. } + | FlycheckConfig::CustomCommand { invocation_strategy, .. } => invocation_strategy, } } @@ -269,6 +305,7 @@ impl FlycheckActor { extra_args, features, extra_env, + invocation_strategy: _, } => { let mut cmd = Command::new(toolchain::cargo()); cmd.arg(command); @@ -297,7 +334,7 @@ impl FlycheckActor { cmd.envs(extra_env); cmd } - FlycheckConfig::CustomCommand { command, args, extra_env } => { + FlycheckConfig::CustomCommand { command, args, extra_env, invocation_strategy: _ } => { let mut cmd = Command::new(command); cmd.args(args); cmd.envs(extra_env); diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 79f6ded4899e..a61e38706e50 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -130,6 +130,14 @@ config_data! { /// /// Set to `"all"` to pass `--all-features` to Cargo. checkOnSave_features: Option = "null", + /// Specifies the invocation strategy to use when running the checkOnSave command. + /// If `per_workspace_with_manifest_path` is set, the command will be executed for each + /// workspace, `--manifest-path {workspace-dir}` will be passed to the invoked command and + /// the command will be executed from the project root. + /// If `per_workspace` is set, the command will be executed for each workspace and the + /// command will be executed from the corresponding workspace root. + /// If `once_in_root` is set, the command will be executed once in the project root. + checkOnSave_invocationStrategy: InvocationStrategy = "\"per_workspace\"", /// Whether to pass `--no-default-features` to Cargo. Defaults to /// `#rust-analyzer.cargo.noDefaultFeatures#`. checkOnSave_noDefaultFeatures: Option = "null", @@ -1094,6 +1102,13 @@ impl Config { if !self.data.checkOnSave_enable { return None; } + let invocation_strategy = match self.data.cargo_buildScripts_invocationStrategy { + InvocationStrategy::OnceInRoot => flycheck::InvocationStrategy::OnceInRoot, + InvocationStrategy::PerWorkspaceWithManifestPath => { + flycheck::InvocationStrategy::PerWorkspaceWithManifestPath + } + InvocationStrategy::PerWorkspace => flycheck::InvocationStrategy::PerWorkspace, + }; let flycheck_config = match &self.data.checkOnSave_overrideCommand { Some(args) if !args.is_empty() => { let mut args = args.clone(); @@ -1102,6 +1117,7 @@ impl Config { command, args, extra_env: self.check_on_save_extra_env(), + invocation_strategy, } } Some(_) | None => FlycheckConfig::CargoCommand { @@ -1131,6 +1147,7 @@ impl Config { }, extra_args: self.data.checkOnSave_extraArgs.clone(), extra_env: self.check_on_save_extra_env(), + invocation_strategy, }, }; Some(flycheck_config) diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index bd5741f61590..5382790f6e74 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -473,32 +473,45 @@ impl GlobalState { }; let sender = self.flycheck_sender.clone(); - self.flycheck = self - .workspaces - .iter() - .enumerate() - .filter_map(|(id, w)| match w { - ProjectWorkspace::Cargo { cargo, .. } => Some((id, cargo.workspace_root())), - ProjectWorkspace::Json { project, .. } => { - // Enable flychecks for json projects if a custom flycheck command was supplied - // in the workspace configuration. - match config { - FlycheckConfig::CustomCommand { .. } => Some((id, project.path())), - _ => None, - } - } - ProjectWorkspace::DetachedFiles { .. } => None, - }) - .map(|(id, root)| { - let sender = sender.clone(); - FlycheckHandle::spawn( - id, - Box::new(move |msg| sender.send(msg).unwrap()), - config.clone(), - root.to_path_buf(), - ) - }) - .collect(); + let (FlycheckConfig::CargoCommand { invocation_strategy, .. } + | FlycheckConfig::CustomCommand { invocation_strategy, .. }) = config; + + self.flycheck = match invocation_strategy { + flycheck::InvocationStrategy::OnceInRoot => vec![FlycheckHandle::spawn( + 0, + Box::new(move |msg| sender.send(msg).unwrap()), + config.clone(), + self.config.root_path().clone(), + )], + flycheck::InvocationStrategy::PerWorkspaceWithManifestPath + | flycheck::InvocationStrategy::PerWorkspace => { + self.workspaces + .iter() + .enumerate() + .filter_map(|(id, w)| match w { + ProjectWorkspace::Cargo { cargo, .. } => Some((id, cargo.workspace_root())), + ProjectWorkspace::Json { project, .. } => { + // Enable flychecks for json projects if a custom flycheck command was supplied + // in the workspace configuration. + match config { + FlycheckConfig::CustomCommand { .. } => Some((id, project.path())), + _ => None, + } + } + ProjectWorkspace::DetachedFiles { .. } => None, + }) + .map(|(id, root)| { + let sender = sender.clone(); + FlycheckHandle::spawn( + id, + Box::new(move |msg| sender.send(msg).unwrap()), + config.clone(), + root.to_path_buf(), + ) + }) + .collect() + } + }; } } diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index a5307b631512..3ced42ef72e3 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -129,6 +129,17 @@ List of features to activate. Defaults to Set to `"all"` to pass `--all-features` to Cargo. -- +[[rust-analyzer.checkOnSave.invocationStrategy]]rust-analyzer.checkOnSave.invocationStrategy (default: `"per_workspace"`):: ++ +-- +Specifies the invocation strategy to use when running the checkOnSave command. +If `per_workspace_with_manifest_path` is set, the command will be executed for each +workspace, `--manifest-path {workspace-dir}` will be passed to the invoked command and +the command will be executed from the project root. +If `per_workspace` is set, the command will be executed for each workspace and the +command will be executed from the corresponding workspace root. +If `once_in_root` is set, the command will be executed once in the project root. +-- [[rust-analyzer.checkOnSave.noDefaultFeatures]]rust-analyzer.checkOnSave.noDefaultFeatures (default: `null`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index b1b565106a37..3af32685fdae 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -561,6 +561,21 @@ } ] }, + "rust-analyzer.checkOnSave.invocationStrategy": { + "markdownDescription": "Specifies the invocation strategy to use when running the checkOnSave command.\nIf `per_workspace_with_manifest_path` is set, the command will be executed for each\nworkspace, `--manifest-path {workspace-dir}` will be passed to the invoked command and\nthe command will be executed from the project root.\nIf `per_workspace` is set, the command will be executed for each workspace and the\ncommand will be executed from the corresponding workspace root.\nIf `once_in_root` is set, the command will be executed once in the project root.", + "default": "per_workspace", + "type": "string", + "enum": [ + "per_workspace", + "per_workspace_with_manifest_path", + "once_in_root" + ], + "enumDescriptions": [ + "The command will be executed for each workspace, `--manifest-path {workspace-dir}` will be passed to the invoked command and the command will be executed from the project root.", + "The command will be executed for each workspace and the command will be executed from the corresponding workspace root.", + "The command will be executed once in the project root." + ] + }, "rust-analyzer.checkOnSave.noDefaultFeatures": { "markdownDescription": "Whether to pass `--no-default-features` to Cargo. Defaults to\n`#rust-analyzer.cargo.noDefaultFeatures#`.", "default": null, From 5174b65ed8ada51977b5621bc070fe5bf9137dc4 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 15 Sep 2022 13:35:46 +0200 Subject: [PATCH 031/171] Use correct invocation strategy config for checkOnSave --- crates/rust-analyzer/src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index a61e38706e50..9f022d6add14 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -1102,7 +1102,7 @@ impl Config { if !self.data.checkOnSave_enable { return None; } - let invocation_strategy = match self.data.cargo_buildScripts_invocationStrategy { + let invocation_strategy = match self.data.checkOnSave_invocationStrategy { InvocationStrategy::OnceInRoot => flycheck::InvocationStrategy::OnceInRoot, InvocationStrategy::PerWorkspaceWithManifestPath => { flycheck::InvocationStrategy::PerWorkspaceWithManifestPath From 7db50294a3e458b7dd00ee646eee75a7ec933e3b Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 26 Sep 2022 15:58:55 +0200 Subject: [PATCH 032/171] {manifest-path} interpolation --- crates/flycheck/src/lib.rs | 69 +++++++++++------------ crates/project-model/src/build_scripts.rs | 66 +++++++++++++++------- crates/project-model/src/lib.rs | 3 +- crates/project-model/src/workspace.rs | 4 +- crates/rust-analyzer/src/config.rs | 38 ++++++------- crates/rust-analyzer/src/reload.rs | 3 +- docs/user/generated_config.adoc | 26 +++++---- editors/code/package.json | 12 ++-- 8 files changed, 118 insertions(+), 103 deletions(-) diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index c3976e6b7a86..cdb3c2969c85 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs @@ -6,7 +6,6 @@ use std::{ fmt, io, - path::Path, process::{ChildStderr, ChildStdout, Command, Stdio}, time::Duration, }; @@ -25,7 +24,6 @@ pub use cargo_metadata::diagnostic::{ #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] pub enum InvocationStrategy { OnceInRoot, - PerWorkspaceWithManifestPath, #[default] PerWorkspace, } @@ -153,7 +151,9 @@ struct FlycheckActor { id: usize, sender: Box, config: FlycheckConfig, - workspace_root: AbsPathBuf, + /// Either the workspace root of the workspace we are flychecking, + /// or the project root of the project. + root: AbsPathBuf, /// CargoHandle exists to wrap around the communication needed to be able to /// run `cargo check` without blocking. Currently the Rust standard library /// doesn't provide a way to read sub-process output without blocking, so we @@ -175,7 +175,7 @@ impl FlycheckActor { workspace_root: AbsPathBuf, ) -> FlycheckActor { tracing::info!(%id, ?workspace_root, "Spawning flycheck"); - FlycheckActor { id, sender, config, workspace_root, cargo_handle: None } + FlycheckActor { id, sender, config, root: workspace_root, cargo_handle: None } } fn report_progress(&self, progress: Progress) { @@ -210,20 +210,7 @@ impl FlycheckActor { } } - let mut command = self.check_command(); - let invocation_strategy = self.invocation_strategy(); - match invocation_strategy { - InvocationStrategy::OnceInRoot => (), - InvocationStrategy::PerWorkspaceWithManifestPath => { - command.arg("--manifest-path"); - command.arg(<_ as AsRef>::as_ref( - &self.workspace_root.join("Cargo.toml"), - )); - } - InvocationStrategy::PerWorkspace => { - command.current_dir(&self.workspace_root); - } - } + let command = self.check_command(); tracing::debug!(?command, "will restart flycheck"); match CargoHandle::spawn(command) { Ok(cargo_handle) => { @@ -265,7 +252,7 @@ impl FlycheckActor { CargoMessage::Diagnostic(msg) => { self.send(Message::AddDiagnostic { id: self.id, - workspace_root: self.workspace_root.clone(), + workspace_root: self.root.clone(), diagnostic: msg, }); } @@ -287,15 +274,8 @@ impl FlycheckActor { } } - fn invocation_strategy(&self) -> InvocationStrategy { - match self.config { - FlycheckConfig::CargoCommand { invocation_strategy, .. } - | FlycheckConfig::CustomCommand { invocation_strategy, .. } => invocation_strategy, - } - } - fn check_command(&self) -> Command { - let mut cmd = match &self.config { + let (mut cmd, args, invocation_strategy) = match &self.config { FlycheckConfig::CargoCommand { command, target_triple, @@ -305,13 +285,11 @@ impl FlycheckActor { extra_args, features, extra_env, - invocation_strategy: _, + invocation_strategy, } => { let mut cmd = Command::new(toolchain::cargo()); cmd.arg(command); - cmd.current_dir(&self.workspace_root); - cmd.args(&["--workspace", "--message-format=json", "--manifest-path"]) - .arg(self.workspace_root.join("Cargo.toml").as_os_str()); + cmd.args(&["--workspace", "--message-format=json"]); if let Some(target) = target_triple { cmd.args(&["--target", target.as_str()]); @@ -330,18 +308,35 @@ impl FlycheckActor { cmd.arg(features.join(" ")); } } - cmd.args(extra_args); cmd.envs(extra_env); - cmd + (cmd, extra_args, invocation_strategy) } - FlycheckConfig::CustomCommand { command, args, extra_env, invocation_strategy: _ } => { + FlycheckConfig::CustomCommand { command, args, extra_env, invocation_strategy } => { let mut cmd = Command::new(command); - cmd.args(args); cmd.envs(extra_env); - cmd + (cmd, args, invocation_strategy) } }; - cmd.current_dir(&self.workspace_root); + if let InvocationStrategy::PerWorkspace = invocation_strategy { + let mut with_manifest_path = false; + for arg in args { + if let Some(_) = arg.find("$manifest_path") { + with_manifest_path = true; + cmd.arg(arg.replace( + "$manifest_path", + &self.root.join("Cargo.toml").display().to_string(), + )); + } else { + cmd.arg(arg); + } + } + + if !with_manifest_path { + cmd.current_dir(&self.root); + } + } else { + cmd.args(args); + } cmd } diff --git a/crates/project-model/src/build_scripts.rs b/crates/project-model/src/build_scripts.rs index 6e6654e74e1a..12be67d9a0cb 100644 --- a/crates/project-model/src/build_scripts.rs +++ b/crates/project-model/src/build_scripts.rs @@ -55,11 +55,37 @@ impl BuildScriptOutput { } impl WorkspaceBuildScripts { - fn build_command(config: &CargoConfig) -> io::Result { + fn build_command( + config: &CargoConfig, + workspace_root: Option<&path::Path>, + ) -> io::Result { let mut cmd = match config.run_build_script_command.as_deref() { Some([program, args @ ..]) => { let mut cmd = Command::new(program); - cmd.args(args); + + // FIXME: strategy and workspace root are coupled, express that in code + if let (InvocationStrategy::PerWorkspace, Some(workspace_root)) = + (config.invocation_strategy, workspace_root) + { + let mut with_manifest_path = false; + for arg in args { + if let Some(_) = arg.find("$manifest_path") { + with_manifest_path = true; + cmd.arg(arg.replace( + "$manifest_path", + &workspace_root.join("Cargo.toml").display().to_string(), + )); + } else { + cmd.arg(arg); + } + } + + if !with_manifest_path { + cmd.current_dir(workspace_root); + } + } else { + cmd.args(args); + } cmd } _ => { @@ -90,9 +116,15 @@ impl WorkspaceBuildScripts { } } } + + if let Some(workspace_root) = workspace_root { + cmd.current_dir(workspace_root); + } + cmd } }; + cmd.envs(&config.extra_env); if config.wrap_rustc_in_build_scripts { // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use @@ -115,15 +147,21 @@ impl WorkspaceBuildScripts { ) -> io::Result { const RUST_1_62: Version = Version::new(1, 62, 0); - match Self::run_per_ws(Self::build_command(config)?, config, workspace, progress) { + let workspace_root: &path::Path = &workspace.workspace_root().as_ref(); + + match Self::run_per_ws( + Self::build_command(config, Some(workspace_root))?, + workspace, + progress, + ) { Ok(WorkspaceBuildScripts { error: Some(error), .. }) if toolchain.as_ref().map_or(false, |it| *it >= RUST_1_62) => { // building build scripts failed, attempt to build with --keep-going so // that we potentially get more build data - let mut cmd = Self::build_command(config)?; + let mut cmd = Self::build_command(config, Some(workspace_root))?; cmd.args(&["-Z", "unstable-options", "--keep-going"]).env("RUSTC_BOOTSTRAP", "1"); - let mut res = Self::run_per_ws(cmd, config, workspace, progress)?; + let mut res = Self::run_per_ws(cmd, workspace, progress)?; res.error = Some(error); Ok(res) } @@ -139,7 +177,7 @@ impl WorkspaceBuildScripts { progress: &dyn Fn(String), ) -> io::Result> { assert_eq!(config.invocation_strategy, InvocationStrategy::OnceInRoot); - let cmd = Self::build_command(config)?; + let cmd = Self::build_command(config, None)?; // NB: Cargo.toml could have been modified between `cargo metadata` and // `cargo check`. We shouldn't assume that package ids we see here are // exactly those from `config`. @@ -187,24 +225,10 @@ impl WorkspaceBuildScripts { } fn run_per_ws( - mut cmd: Command, - config: &CargoConfig, + cmd: Command, workspace: &CargoWorkspace, progress: &dyn Fn(String), ) -> io::Result { - let workspace_root: &path::Path = &workspace.workspace_root().as_ref(); - - match config.invocation_strategy { - InvocationStrategy::OnceInRoot => (), - InvocationStrategy::PerWorkspaceWithManifestPath => { - cmd.arg("--manifest-path"); - cmd.arg(workspace_root.join("Cargo.toml")); - } - InvocationStrategy::PerWorkspace => { - cmd.current_dir(workspace_root); - } - } - let mut res = WorkspaceBuildScripts::default(); let outputs = &mut res.outputs; // NB: Cargo.toml could have been modified between `cargo metadata` and diff --git a/crates/project-model/src/lib.rs b/crates/project-model/src/lib.rs index 13a86901f71c..956c872ccc62 100644 --- a/crates/project-model/src/lib.rs +++ b/crates/project-model/src/lib.rs @@ -158,10 +158,9 @@ fn utf8_stdout(mut cmd: Command) -> Result { Ok(stdout.trim().to_string()) } -#[derive(Clone, Debug, Default, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] pub enum InvocationStrategy { OnceInRoot, - PerWorkspaceWithManifestPath, #[default] PerWorkspace, } diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index 01f5157093ad..561bad3a6abb 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -323,9 +323,7 @@ impl ProjectWorkspace { config: &CargoConfig, progress: &dyn Fn(String), ) -> Vec> { - if let InvocationStrategy::PerWorkspaceWithManifestPath | InvocationStrategy::PerWorkspace = - config.invocation_strategy - { + if let InvocationStrategy::PerWorkspace = config.invocation_strategy { return workspaces.iter().map(|it| it.run_build_scripts(config, progress)).collect(); } diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 9f022d6add14..3bf28cb7b472 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -70,12 +70,15 @@ config_data! { /// Run build scripts (`build.rs`) for more precise code analysis. cargo_buildScripts_enable: bool = "true", /// Specifies the invocation strategy to use when running the build scripts command. - /// If `per_workspace_with_manifest_path` is set, the command will be executed for each - /// workspace, `--manifest-path {workspace-dir}` will be passed to the invoked command and - /// the command will be executed from the project root. - /// If `per_workspace` is set, the command will be executed for each workspace and the - /// command will be executed from the corresponding workspace root. + /// If `per_workspace` is set, the command will be executed for each workspace and all + /// occurrences of `$manifest_path` in the command will be replaced by the corresponding + /// manifest path of the workspace that the command is being invoked for. If interpolation + /// for the manifest path happens at least once, the commands will be executed from the + /// project root, otherwise the commands will be executed from the corresponding workspace + /// root. /// If `once_in_root` is set, the command will be executed once in the project root. + /// This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#` + /// is set. cargo_buildScripts_invocationStrategy: InvocationStrategy = "\"per_workspace\"", /// Override the command rust-analyzer uses to run build scripts and /// build procedural macros. The command is required to output json @@ -131,12 +134,15 @@ config_data! { /// Set to `"all"` to pass `--all-features` to Cargo. checkOnSave_features: Option = "null", /// Specifies the invocation strategy to use when running the checkOnSave command. - /// If `per_workspace_with_manifest_path` is set, the command will be executed for each - /// workspace, `--manifest-path {workspace-dir}` will be passed to the invoked command and - /// the command will be executed from the project root. - /// If `per_workspace` is set, the command will be executed for each workspace and the - /// command will be executed from the corresponding workspace root. + /// If `per_workspace` is set, the command will be executed for each workspace and all + /// occurrences of `$manifest_path` in the command will be replaced by the corresponding + /// manifest path of the workspace that the command is being invoked for. If interpolation + /// for the manifest path happens at least once, the commands will be executed from the + /// project root, otherwise the commands will be executed from the corresponding workspace + /// root. /// If `once_in_root` is set, the command will be executed once in the project root. + /// This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#` + /// is set. checkOnSave_invocationStrategy: InvocationStrategy = "\"per_workspace\"", /// Whether to pass `--no-default-features` to Cargo. Defaults to /// `#rust-analyzer.cargo.noDefaultFeatures#`. @@ -1074,9 +1080,6 @@ impl Config { wrap_rustc_in_build_scripts: self.data.cargo_buildScripts_useRustcWrapper, invocation_strategy: match self.data.cargo_buildScripts_invocationStrategy { InvocationStrategy::OnceInRoot => project_model::InvocationStrategy::OnceInRoot, - InvocationStrategy::PerWorkspaceWithManifestPath => { - project_model::InvocationStrategy::PerWorkspaceWithManifestPath - } InvocationStrategy::PerWorkspace => project_model::InvocationStrategy::PerWorkspace, }, run_build_script_command: self.data.cargo_buildScripts_overrideCommand.clone(), @@ -1104,9 +1107,6 @@ impl Config { } let invocation_strategy = match self.data.checkOnSave_invocationStrategy { InvocationStrategy::OnceInRoot => flycheck::InvocationStrategy::OnceInRoot, - InvocationStrategy::PerWorkspaceWithManifestPath => { - flycheck::InvocationStrategy::PerWorkspaceWithManifestPath - } InvocationStrategy::PerWorkspace => flycheck::InvocationStrategy::PerWorkspace, }; let flycheck_config = match &self.data.checkOnSave_overrideCommand { @@ -1623,7 +1623,6 @@ enum CargoFeaturesDef { #[serde(rename_all = "snake_case")] enum InvocationStrategy { OnceInRoot, - PerWorkspaceWithManifestPath, PerWorkspace, } @@ -2043,10 +2042,9 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json }, "InvocationStrategy" => set! { "type": "string", - "enum": ["per_workspace", "per_workspace_with_manifest_path", "once_in_root"], + "enum": ["per_workspace", "once_in_root"], "enumDescriptions": [ - "The command will be executed for each workspace, `--manifest-path {workspace-dir}` will be passed to the invoked command and the command will be executed from the project root.", - "The command will be executed for each workspace and the command will be executed from the corresponding workspace root.", + "The command will be executed for each workspace and `{manifest-path}` usages will be interpolated with the corresponding workspace manifests. If `{manifest-path}` is used, the commands will be executed in the project root, otherwise in the corresponding workspace roots.", "The command will be executed once in the project root." ], }, diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index 5382790f6e74..af7a51a68ef5 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -483,8 +483,7 @@ impl GlobalState { config.clone(), self.config.root_path().clone(), )], - flycheck::InvocationStrategy::PerWorkspaceWithManifestPath - | flycheck::InvocationStrategy::PerWorkspace => { + flycheck::InvocationStrategy::PerWorkspace => { self.workspaces .iter() .enumerate() diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 3ced42ef72e3..3948d8f7e72e 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -28,12 +28,15 @@ Run build scripts (`build.rs`) for more precise code analysis. + -- Specifies the invocation strategy to use when running the build scripts command. -If `per_workspace_with_manifest_path` is set, the command will be executed for each -workspace, `--manifest-path {workspace-dir}` will be passed to the invoked command and -the command will be executed from the project root. -If `per_workspace` is set, the command will be executed for each workspace and the -command will be executed from the corresponding workspace root. +If `per_workspace` is set, the command will be executed for each workspace and all +occurrences of `$manifest_path` in the command will be replaced by the corresponding +manifest path of the workspace that the command is being invoked for. If interpolation +for the manifest path happens at least once, the commands will be executed from the +project root, otherwise the commands will be executed from the corresponding workspace +root. If `once_in_root` is set, the command will be executed once in the project root. +This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#` +is set. -- [[rust-analyzer.cargo.buildScripts.overrideCommand]]rust-analyzer.cargo.buildScripts.overrideCommand (default: `null`):: + @@ -133,12 +136,15 @@ Set to `"all"` to pass `--all-features` to Cargo. + -- Specifies the invocation strategy to use when running the checkOnSave command. -If `per_workspace_with_manifest_path` is set, the command will be executed for each -workspace, `--manifest-path {workspace-dir}` will be passed to the invoked command and -the command will be executed from the project root. -If `per_workspace` is set, the command will be executed for each workspace and the -command will be executed from the corresponding workspace root. +If `per_workspace` is set, the command will be executed for each workspace and all +occurrences of `$manifest_path` in the command will be replaced by the corresponding +manifest path of the workspace that the command is being invoked for. If interpolation +for the manifest path happens at least once, the commands will be executed from the +project root, otherwise the commands will be executed from the corresponding workspace +root. If `once_in_root` is set, the command will be executed once in the project root. +This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#` +is set. -- [[rust-analyzer.checkOnSave.noDefaultFeatures]]rust-analyzer.checkOnSave.noDefaultFeatures (default: `null`):: + diff --git a/editors/code/package.json b/editors/code/package.json index 3af32685fdae..8c40a3878f5b 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -422,17 +422,15 @@ "type": "boolean" }, "rust-analyzer.cargo.buildScripts.invocationStrategy": { - "markdownDescription": "Specifies the invocation strategy to use when running the build scripts command.\nIf `per_workspace_with_manifest_path` is set, the command will be executed for each\nworkspace, `--manifest-path {workspace-dir}` will be passed to the invoked command and\nthe command will be executed from the project root.\nIf `per_workspace` is set, the command will be executed for each workspace and the\ncommand will be executed from the corresponding workspace root.\nIf `once_in_root` is set, the command will be executed once in the project root.", + "markdownDescription": "Specifies the invocation strategy to use when running the build scripts command.\nIf `per_workspace` is set, the command will be executed for each workspace and all\noccurrences of `$manifest_path` in the command will be replaced by the corresponding\nmanifest path of the workspace that the command is being invoked for. If interpolation\nfor the manifest path happens at least once, the commands will be executed from the\nproject root, otherwise the commands will be executed from the corresponding workspace\nroot.\nIf `once_in_root` is set, the command will be executed once in the project root.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.", "default": "per_workspace", "type": "string", "enum": [ "per_workspace", - "per_workspace_with_manifest_path", "once_in_root" ], "enumDescriptions": [ - "The command will be executed for each workspace, `--manifest-path {workspace-dir}` will be passed to the invoked command and the command will be executed from the project root.", - "The command will be executed for each workspace and the command will be executed from the corresponding workspace root.", + "The command will be executed for each workspace and `{manifest-path}` usages will be interpolated with the corresponding workspace manifests. If `{manifest-path}` is used, the commands will be executed in the project root, otherwise in the corresponding workspace roots.", "The command will be executed once in the project root." ] }, @@ -562,17 +560,15 @@ ] }, "rust-analyzer.checkOnSave.invocationStrategy": { - "markdownDescription": "Specifies the invocation strategy to use when running the checkOnSave command.\nIf `per_workspace_with_manifest_path` is set, the command will be executed for each\nworkspace, `--manifest-path {workspace-dir}` will be passed to the invoked command and\nthe command will be executed from the project root.\nIf `per_workspace` is set, the command will be executed for each workspace and the\ncommand will be executed from the corresponding workspace root.\nIf `once_in_root` is set, the command will be executed once in the project root.", + "markdownDescription": "Specifies the invocation strategy to use when running the checkOnSave command.\nIf `per_workspace` is set, the command will be executed for each workspace and all\noccurrences of `$manifest_path` in the command will be replaced by the corresponding\nmanifest path of the workspace that the command is being invoked for. If interpolation\nfor the manifest path happens at least once, the commands will be executed from the\nproject root, otherwise the commands will be executed from the corresponding workspace\nroot.\nIf `once_in_root` is set, the command will be executed once in the project root.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.", "default": "per_workspace", "type": "string", "enum": [ "per_workspace", - "per_workspace_with_manifest_path", "once_in_root" ], "enumDescriptions": [ - "The command will be executed for each workspace, `--manifest-path {workspace-dir}` will be passed to the invoked command and the command will be executed from the project root.", - "The command will be executed for each workspace and the command will be executed from the corresponding workspace root.", + "The command will be executed for each workspace and `{manifest-path}` usages will be interpolated with the corresponding workspace manifests. If `{manifest-path}` is used, the commands will be executed in the project root, otherwise in the corresponding workspace roots.", "The command will be executed once in the project root." ] }, From 46732369f4b8246e6dc764ef1aa01d03ab5f52b7 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 19 Oct 2022 23:34:36 +0200 Subject: [PATCH 033/171] Remove simplistic interpolation for manifest-path --- crates/flycheck/src/lib.rs | 26 ++++---------------- crates/project-model/src/build_scripts.rs | 27 ++------------------ crates/project-model/src/lib.rs | 2 +- crates/rust-analyzer/src/config.rs | 30 +++++++++-------------- crates/rust-analyzer/src/reload.rs | 2 +- docs/user/generated_config.adoc | 20 +++++---------- editors/code/package.json | 12 ++++----- 7 files changed, 32 insertions(+), 87 deletions(-) diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index cdb3c2969c85..0debf3270f61 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs @@ -23,7 +23,7 @@ pub use cargo_metadata::diagnostic::{ #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] pub enum InvocationStrategy { - OnceInRoot, + Once, #[default] PerWorkspace, } @@ -317,26 +317,10 @@ impl FlycheckActor { (cmd, args, invocation_strategy) } }; - if let InvocationStrategy::PerWorkspace = invocation_strategy { - let mut with_manifest_path = false; - for arg in args { - if let Some(_) = arg.find("$manifest_path") { - with_manifest_path = true; - cmd.arg(arg.replace( - "$manifest_path", - &self.root.join("Cargo.toml").display().to_string(), - )); - } else { - cmd.arg(arg); - } - } - - if !with_manifest_path { - cmd.current_dir(&self.root); - } - } else { - cmd.args(args); - } + match invocation_strategy { + InvocationStrategy::PerWorkspace => cmd.current_dir(&self.root), + InvocationStrategy::Once => cmd.args(args), + }; cmd } diff --git a/crates/project-model/src/build_scripts.rs b/crates/project-model/src/build_scripts.rs index 12be67d9a0cb..0bb9bd65dccf 100644 --- a/crates/project-model/src/build_scripts.rs +++ b/crates/project-model/src/build_scripts.rs @@ -62,30 +62,7 @@ impl WorkspaceBuildScripts { let mut cmd = match config.run_build_script_command.as_deref() { Some([program, args @ ..]) => { let mut cmd = Command::new(program); - - // FIXME: strategy and workspace root are coupled, express that in code - if let (InvocationStrategy::PerWorkspace, Some(workspace_root)) = - (config.invocation_strategy, workspace_root) - { - let mut with_manifest_path = false; - for arg in args { - if let Some(_) = arg.find("$manifest_path") { - with_manifest_path = true; - cmd.arg(arg.replace( - "$manifest_path", - &workspace_root.join("Cargo.toml").display().to_string(), - )); - } else { - cmd.arg(arg); - } - } - - if !with_manifest_path { - cmd.current_dir(workspace_root); - } - } else { - cmd.args(args); - } + cmd.args(args); cmd } _ => { @@ -176,7 +153,7 @@ impl WorkspaceBuildScripts { workspaces: &[&CargoWorkspace], progress: &dyn Fn(String), ) -> io::Result> { - assert_eq!(config.invocation_strategy, InvocationStrategy::OnceInRoot); + assert_eq!(config.invocation_strategy, InvocationStrategy::Once); let cmd = Self::build_command(config, None)?; // NB: Cargo.toml could have been modified between `cargo metadata` and // `cargo check`. We shouldn't assume that package ids we see here are diff --git a/crates/project-model/src/lib.rs b/crates/project-model/src/lib.rs index 956c872ccc62..2cc0a60bca00 100644 --- a/crates/project-model/src/lib.rs +++ b/crates/project-model/src/lib.rs @@ -160,7 +160,7 @@ fn utf8_stdout(mut cmd: Command) -> Result { #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] pub enum InvocationStrategy { - OnceInRoot, + Once, #[default] PerWorkspace, } diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 3bf28cb7b472..3669fda926a7 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -70,13 +70,9 @@ config_data! { /// Run build scripts (`build.rs`) for more precise code analysis. cargo_buildScripts_enable: bool = "true", /// Specifies the invocation strategy to use when running the build scripts command. - /// If `per_workspace` is set, the command will be executed for each workspace and all - /// occurrences of `$manifest_path` in the command will be replaced by the corresponding - /// manifest path of the workspace that the command is being invoked for. If interpolation - /// for the manifest path happens at least once, the commands will be executed from the - /// project root, otherwise the commands will be executed from the corresponding workspace - /// root. - /// If `once_in_root` is set, the command will be executed once in the project root. + /// If `per_workspace` is set, the command will be executed for each workspace from the + /// corresponding workspace root. + /// If `once` is set, the command will be executed once in the project root. /// This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#` /// is set. cargo_buildScripts_invocationStrategy: InvocationStrategy = "\"per_workspace\"", @@ -134,13 +130,9 @@ config_data! { /// Set to `"all"` to pass `--all-features` to Cargo. checkOnSave_features: Option = "null", /// Specifies the invocation strategy to use when running the checkOnSave command. - /// If `per_workspace` is set, the command will be executed for each workspace and all - /// occurrences of `$manifest_path` in the command will be replaced by the corresponding - /// manifest path of the workspace that the command is being invoked for. If interpolation - /// for the manifest path happens at least once, the commands will be executed from the - /// project root, otherwise the commands will be executed from the corresponding workspace - /// root. - /// If `once_in_root` is set, the command will be executed once in the project root. + /// If `per_workspace` is set, the command will be executed for each workspace from the + /// corresponding workspace root. + /// If `once` is set, the command will be executed once in the project root. /// This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#` /// is set. checkOnSave_invocationStrategy: InvocationStrategy = "\"per_workspace\"", @@ -1079,7 +1071,7 @@ impl Config { unset_test_crates: UnsetTestCrates::Only(self.data.cargo_unsetTest.clone()), wrap_rustc_in_build_scripts: self.data.cargo_buildScripts_useRustcWrapper, invocation_strategy: match self.data.cargo_buildScripts_invocationStrategy { - InvocationStrategy::OnceInRoot => project_model::InvocationStrategy::OnceInRoot, + InvocationStrategy::Once => project_model::InvocationStrategy::Once, InvocationStrategy::PerWorkspace => project_model::InvocationStrategy::PerWorkspace, }, run_build_script_command: self.data.cargo_buildScripts_overrideCommand.clone(), @@ -1106,7 +1098,7 @@ impl Config { return None; } let invocation_strategy = match self.data.checkOnSave_invocationStrategy { - InvocationStrategy::OnceInRoot => flycheck::InvocationStrategy::OnceInRoot, + InvocationStrategy::Once => flycheck::InvocationStrategy::Once, InvocationStrategy::PerWorkspace => flycheck::InvocationStrategy::PerWorkspace, }; let flycheck_config = match &self.data.checkOnSave_overrideCommand { @@ -1622,7 +1614,7 @@ enum CargoFeaturesDef { #[derive(Deserialize, Debug, Clone)] #[serde(rename_all = "snake_case")] enum InvocationStrategy { - OnceInRoot, + Once, PerWorkspace, } @@ -2042,9 +2034,9 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json }, "InvocationStrategy" => set! { "type": "string", - "enum": ["per_workspace", "once_in_root"], + "enum": ["per_workspace", "once"], "enumDescriptions": [ - "The command will be executed for each workspace and `{manifest-path}` usages will be interpolated with the corresponding workspace manifests. If `{manifest-path}` is used, the commands will be executed in the project root, otherwise in the corresponding workspace roots.", + "The command will be executed for each workspace from the corresponding workspace root.", "The command will be executed once in the project root." ], }, diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index af7a51a68ef5..f7db62baf2c1 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -477,7 +477,7 @@ impl GlobalState { | FlycheckConfig::CustomCommand { invocation_strategy, .. }) = config; self.flycheck = match invocation_strategy { - flycheck::InvocationStrategy::OnceInRoot => vec![FlycheckHandle::spawn( + flycheck::InvocationStrategy::Once => vec![FlycheckHandle::spawn( 0, Box::new(move |msg| sender.send(msg).unwrap()), config.clone(), diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 3948d8f7e72e..e5d4395c345c 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -28,13 +28,9 @@ Run build scripts (`build.rs`) for more precise code analysis. + -- Specifies the invocation strategy to use when running the build scripts command. -If `per_workspace` is set, the command will be executed for each workspace and all -occurrences of `$manifest_path` in the command will be replaced by the corresponding -manifest path of the workspace that the command is being invoked for. If interpolation -for the manifest path happens at least once, the commands will be executed from the -project root, otherwise the commands will be executed from the corresponding workspace -root. -If `once_in_root` is set, the command will be executed once in the project root. +If `per_workspace` is set, the command will be executed for each workspace from the +corresponding workspace root. +If `once` is set, the command will be executed once in the project root. This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#` is set. -- @@ -136,13 +132,9 @@ Set to `"all"` to pass `--all-features` to Cargo. + -- Specifies the invocation strategy to use when running the checkOnSave command. -If `per_workspace` is set, the command will be executed for each workspace and all -occurrences of `$manifest_path` in the command will be replaced by the corresponding -manifest path of the workspace that the command is being invoked for. If interpolation -for the manifest path happens at least once, the commands will be executed from the -project root, otherwise the commands will be executed from the corresponding workspace -root. -If `once_in_root` is set, the command will be executed once in the project root. +If `per_workspace` is set, the command will be executed for each workspace from the +corresponding workspace root. +If `once` is set, the command will be executed once in the project root. This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#` is set. -- diff --git a/editors/code/package.json b/editors/code/package.json index 8c40a3878f5b..d685d634109a 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -422,15 +422,15 @@ "type": "boolean" }, "rust-analyzer.cargo.buildScripts.invocationStrategy": { - "markdownDescription": "Specifies the invocation strategy to use when running the build scripts command.\nIf `per_workspace` is set, the command will be executed for each workspace and all\noccurrences of `$manifest_path` in the command will be replaced by the corresponding\nmanifest path of the workspace that the command is being invoked for. If interpolation\nfor the manifest path happens at least once, the commands will be executed from the\nproject root, otherwise the commands will be executed from the corresponding workspace\nroot.\nIf `once_in_root` is set, the command will be executed once in the project root.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.", + "markdownDescription": "Specifies the invocation strategy to use when running the build scripts command.\nIf `per_workspace` is set, the command will be executed for each workspace from the\ncorresponding workspace root.\nIf `once` is set, the command will be executed once in the project root.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.", "default": "per_workspace", "type": "string", "enum": [ "per_workspace", - "once_in_root" + "once" ], "enumDescriptions": [ - "The command will be executed for each workspace and `{manifest-path}` usages will be interpolated with the corresponding workspace manifests. If `{manifest-path}` is used, the commands will be executed in the project root, otherwise in the corresponding workspace roots.", + "The command will be executed for each workspace from the corresponding workspace root.", "The command will be executed once in the project root." ] }, @@ -560,15 +560,15 @@ ] }, "rust-analyzer.checkOnSave.invocationStrategy": { - "markdownDescription": "Specifies the invocation strategy to use when running the checkOnSave command.\nIf `per_workspace` is set, the command will be executed for each workspace and all\noccurrences of `$manifest_path` in the command will be replaced by the corresponding\nmanifest path of the workspace that the command is being invoked for. If interpolation\nfor the manifest path happens at least once, the commands will be executed from the\nproject root, otherwise the commands will be executed from the corresponding workspace\nroot.\nIf `once_in_root` is set, the command will be executed once in the project root.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.", + "markdownDescription": "Specifies the invocation strategy to use when running the checkOnSave command.\nIf `per_workspace` is set, the command will be executed for each workspace from the\ncorresponding workspace root.\nIf `once` is set, the command will be executed once in the project root.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.", "default": "per_workspace", "type": "string", "enum": [ "per_workspace", - "once_in_root" + "once" ], "enumDescriptions": [ - "The command will be executed for each workspace and `{manifest-path}` usages will be interpolated with the corresponding workspace manifests. If `{manifest-path}` is used, the commands will be executed in the project root, otherwise in the corresponding workspace roots.", + "The command will be executed for each workspace from the corresponding workspace root.", "The command will be executed once in the project root." ] }, From ab36a2fe16006a34c7d19baa6ef8e23f6ec079cc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 19 Oct 2022 18:34:01 +0000 Subject: [PATCH 034/171] Revert "Unify tcx.constness and param env constness checks" This reverts commit bef8681a1837790f2745c1f6a7f8214af2fd7f5d. This reverts commit c646c4d403d8c88cd3450f859fbdc34ec26d5bb5. --- .../src/const_eval/fn_queries.rs | 72 +++++-------------- compiler/rustc_metadata/src/rmeta/encoder.rs | 56 ++++----------- compiler/rustc_ty_utils/src/ty.rs | 69 +++++++++++++++++- 3 files changed, 99 insertions(+), 98 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index cdcebb61c2e8..f1674d04f8d1 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -25,10 +25,12 @@ pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { /// report whether said intrinsic has a `rustc_const_{un,}stable` attribute. Otherwise, return /// `Constness::NotConst`. fn constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - match tcx.hir().get(hir_id) { - hir::Node::Ctor(_) => hir::Constness::Const, + let def_id = def_id.expect_local(); + let node = tcx.hir().get_by_def_id(def_id); + match node { + hir::Node::Ctor(_) => hir::Constness::Const, + hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness, hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) => { // Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other // foreign items cannot be evaluated at compile-time. @@ -39,62 +41,20 @@ fn constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness { }; if is_const { hir::Constness::Const } else { hir::Constness::NotConst } } + _ => { + if let Some(fn_kind) = node.fn_kind() { + if fn_kind.constness() == hir::Constness::Const { + return hir::Constness::Const; + } - hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) - if tcx.is_const_default_method(def_id) => - { - hir::Constness::Const - } - - hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(..), .. }) - | hir::Node::Item(hir::Item { kind: hir::ItemKind::Static(..), .. }) - | hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Const(..), .. }) - | hir::Node::AnonConst(_) - | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) - | hir::Node::ImplItem(hir::ImplItem { - kind: - hir::ImplItemKind::Fn( - hir::FnSig { - header: hir::FnHeader { constness: hir::Constness::Const, .. }, - .. - }, - .., - ), - .. - }) => hir::Constness::Const, - - hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Type(..) | hir::ImplItemKind::Fn(..), - .. - }) => { - let parent_hir_id = tcx.hir().get_parent_node(hir_id); - match tcx.hir().get(parent_hir_id) { - hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), - .. - }) => *constness, - _ => span_bug!( - tcx.def_span(parent_hir_id.owner), - "impl item's parent node is not an impl", - ), + // If the function itself is not annotated with `const`, it may still be a `const fn` + // if it resides in a const trait impl. + let is_const = is_parent_const_impl_raw(tcx, def_id); + if is_const { hir::Constness::Const } else { hir::Constness::NotConst } + } else { + hir::Constness::NotConst } } - - hir::Node::Item(hir::Item { - kind: hir::ItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..), - .. - }) - | hir::Node::TraitItem(hir::TraitItem { - kind: - hir::TraitItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..), - .. - }) - | hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), - .. - }) => *constness, - - _ => hir::Constness::NotConst, } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 68119598285c..3fc10197b912 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1059,43 +1059,6 @@ fn should_encode_const(def_kind: DefKind) -> bool { } } -fn should_encode_constness(def_kind: DefKind) -> bool { - match def_kind { - DefKind::Struct - | DefKind::Union - | DefKind::Enum - | DefKind::Trait - | DefKind::AssocTy - | DefKind::Fn - | DefKind::Const - | DefKind::Static(..) - | DefKind::Ctor(..) - | DefKind::AssocFn - | DefKind::AssocConst - | DefKind::AnonConst - | DefKind::InlineConst - | DefKind::OpaqueTy - | DefKind::ImplTraitPlaceholder - | DefKind::Impl - | DefKind::Closure - | DefKind::Generator - | DefKind::TyAlias => true, - DefKind::Variant - | DefKind::TraitAlias - | DefKind::ForeignTy - | DefKind::Field - | DefKind::TyParam - | DefKind::Mod - | DefKind::ForeignMod - | DefKind::ConstParam - | DefKind::Macro(..) - | DefKind::Use - | DefKind::LifetimeParam - | DefKind::GlobalAsm - | DefKind::ExternCrate => false, - } -} - fn should_encode_trait_impl_trait_tys<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { if tcx.def_kind(def_id) != DefKind::AssocFn { return false; @@ -1202,9 +1165,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { { record!(self.tables.trait_impl_trait_tys[def_id] <- table); } - if should_encode_constness(def_kind) { - self.tables.constness.set(def_id.index, tcx.constness(def_id)); - } } let inherent_impls = tcx.crate_inherent_impls(()); for (def_id, implementations) in inherent_impls.inherent_impls.iter() { @@ -1232,6 +1192,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }; record!(self.tables.variant_data[def_id] <- data); + self.tables.constness.set(def_id.index, hir::Constness::Const); record_array!(self.tables.children[def_id] <- variant.fields.iter().map(|f| { assert!(f.did.is_local()); f.did.index @@ -1259,6 +1220,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }; record!(self.tables.variant_data[def_id] <- data); + self.tables.constness.set(def_id.index, hir::Constness::Const); if variant.ctor_kind == CtorKind::Fn { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); } @@ -1322,6 +1284,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.repr_options[def_id] <- adt_def.repr()); record!(self.tables.variant_data[def_id] <- data); + self.tables.constness.set(def_id.index, hir::Constness::Const); if variant.ctor_kind == CtorKind::Fn { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); } @@ -1357,6 +1320,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } }; self.tables.asyncness.set(def_id.index, m_sig.header.asyncness); + self.tables.constness.set(def_id.index, hir::Constness::NotConst); } ty::AssocKind::Type => { self.encode_explicit_item_bounds(def_id); @@ -1381,6 +1345,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind else { bug!() }; self.tables.asyncness.set(def_id.index, sig.header.asyncness); record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body)); + // Can be inside `impl const Trait`, so using sig.header.constness is not reliable + let constness = if self.tcx.is_const_fn_raw(def_id) { + hir::Constness::Const + } else { + hir::Constness::NotConst + }; + self.tables.constness.set(def_id.index, constness); } ty::AssocKind::Const | ty::AssocKind::Type => {} } @@ -1503,6 +1474,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hir::ItemKind::Fn(ref sig, .., body) => { self.tables.asyncness.set(def_id.index, sig.header.asyncness); record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body)); + self.tables.constness.set(def_id.index, sig.header.constness); } hir::ItemKind::Macro(ref macro_def, _) => { if macro_def.macro_rules { @@ -1523,6 +1495,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hir::ItemKind::Struct(ref struct_def, _) => { let adt_def = self.tcx.adt_def(def_id); record!(self.tables.repr_options[def_id] <- adt_def.repr()); + self.tables.constness.set(def_id.index, hir::Constness::Const); // Encode def_ids for each field and method // for methods, write all the stuff get_trait_method @@ -1551,8 +1524,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { is_non_exhaustive: variant.is_field_list_non_exhaustive(), }); } - hir::ItemKind::Impl(hir::Impl { defaultness, .. }) => { + hir::ItemKind::Impl(hir::Impl { defaultness, constness, .. }) => { self.tables.impl_defaultness.set(def_id.index, *defaultness); + self.tables.constness.set(def_id.index, *constness); let trait_ref = self.tcx.impl_trait_ref(def_id); if let Some(trait_ref) = trait_ref { diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 196d70614e7c..cd9d22964057 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -137,10 +137,77 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { 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)); + let constness = match hir_id { + Some(hir_id) => match tcx.hir().get(hir_id) { + hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) + if tcx.is_const_default_method(def_id) => + { + hir::Constness::Const + } + + hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(..), .. }) + | hir::Node::Item(hir::Item { kind: hir::ItemKind::Static(..), .. }) + | hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Const(..), .. + }) + | hir::Node::AnonConst(_) + | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) + | hir::Node::ImplItem(hir::ImplItem { + kind: + hir::ImplItemKind::Fn( + hir::FnSig { + header: hir::FnHeader { constness: hir::Constness::Const, .. }, + .. + }, + .., + ), + .. + }) => hir::Constness::Const, + + hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Type(..) | hir::ImplItemKind::Fn(..), + .. + }) => { + let parent_hir_id = tcx.hir().get_parent_node(hir_id); + match tcx.hir().get(parent_hir_id) { + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), + .. + }) => *constness, + _ => span_bug!( + tcx.def_span(parent_hir_id.owner), + "impl item's parent node is not an impl", + ), + } + } + + hir::Node::Item(hir::Item { + kind: + hir::ItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..), + .. + }) + | hir::Node::TraitItem(hir::TraitItem { + kind: + hir::TraitItemKind::Fn( + hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, + .., + ), + .. + }) + | hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), + .. + }) => *constness, + + _ => hir::Constness::NotConst, + }, + None => hir::Constness::NotConst, + }; + let unnormalized_env = ty::ParamEnv::new( tcx.intern_predicates(&predicates), traits::Reveal::UserFacing, - tcx.constness(def_id), + constness, ); let body_id = From 43f2c37f9350b2bed0b81bf858e7478869d8c306 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 19 Oct 2022 19:05:15 +0000 Subject: [PATCH 035/171] Note discrepancies in constness calculation --- compiler/rustc_ty_utils/src/ty.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index cd9d22964057..3eebb4ace477 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -137,6 +137,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { 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)); + // FIXME(consts): This is not exactly in line with the constness query. let constness = match hir_id { Some(hir_id) => match tcx.hir().get(hir_id) { hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) @@ -201,6 +202,10 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { _ => hir::Constness::NotConst, }, + // FIXME(consts): It's suspicious that a param-env for a foreign item + // will always have NotConst param-env, though we don't typically use + // that param-env for anything meaningful right now, so it's likely + // not an issue. None => hir::Constness::NotConst, }; From 751ac6ce5168b8bbefd83040fb262204072fc4df Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 20 Oct 2022 04:19:54 +0000 Subject: [PATCH 036/171] Bless test --- .../rfc-2632-const-trait-impl/issue-102985.rs | 3 ++- .../issue-102985.stderr | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-102985.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-102985.rs index e0df72003844..07d3f51edce5 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/issue-102985.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/issue-102985.rs @@ -4,7 +4,8 @@ struct Bug { inner: [(); match || 1 { n => n(), //~^ ERROR the trait bound - //~| ERROR cannot call non-const fn `Bug::inner::{constant#0}::{closure#0}` in constants + //~| ERROR the trait bound + //~| ERROR cannot call non-const closure in constants }], } diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-102985.stderr b/src/test/ui/rfc-2632-const-trait-impl/issue-102985.stderr index 14d87e7cdc64..b98ccbe5d03e 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/issue-102985.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/issue-102985.stderr @@ -12,15 +12,30 @@ LL | n => n(), | ^^^ = note: wrap the `[closure@$DIR/issue-102985.rs:4:23: 4:25]` in a closure with no arguments: `|| { /* code */ }` -error[E0015]: cannot call non-const fn `Bug::inner::{constant#0}::{closure#0}` in constants +error[E0277]: the trait bound `[closure@$DIR/issue-102985.rs:4:23: 4:25]: ~const Fn<()>` is not satisfied + --> $DIR/issue-102985.rs:5:14 + | +LL | n => n(), + | ^^^ expected an `Fn<()>` closure, found `[closure@$DIR/issue-102985.rs:4:23: 4:25]` + | + = help: the trait `~const Fn<()>` is not implemented for closure `[closure@$DIR/issue-102985.rs:4:23: 4:25]` +note: the trait `Fn<()>` is implemented for `[closure@$DIR/issue-102985.rs:4:23: 4:25]`, but that implementation is not `const` + --> $DIR/issue-102985.rs:5:14 + | +LL | n => n(), + | ^^^ + = note: wrap the `[closure@$DIR/issue-102985.rs:4:23: 4:25]` in a closure with no arguments: `|| { /* code */ }` + +error[E0015]: cannot call non-const closure in constants --> $DIR/issue-102985.rs:5:14 | LL | n => n(), | ^^^ | + = note: closures need an RFC before allowed to be called in constants = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0015, E0277. For more information about an error, try `rustc --explain E0015`. From cfcb0a2135da6d4bdbf5f28806dea0cc70c5b6c5 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 20 Oct 2022 00:30:00 -0400 Subject: [PATCH 037/171] Use a faster allocation size check in slice::from_raw_parts --- library/core/src/intrinsics.rs | 10 ++++++++++ library/core/src/lib.rs | 1 + library/core/src/slice/raw.rs | 10 +++++----- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 2399262c05b4..3a7a179c98be 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2229,6 +2229,16 @@ pub(crate) fn is_aligned_and_not_null(ptr: *const T) -> bool { !ptr.is_null() && ptr.is_aligned() } +/// Checks whether an allocation of `len` instances of `T` exceeds +/// the maximum allowed allocation size. +pub(crate) fn is_valid_allocation_size(len: usize) -> bool { + let max_len = const { + let size = crate::mem::size_of::(); + if size == 0 { usize::MAX } else { isize::MAX as usize / size } + }; + len <= max_len +} + /// Checks whether the regions of memory starting at `src` and `dst` of size /// `count * size_of::()` do *not* overlap. pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) -> bool { diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 2fd8180f8b2a..aa197c990b20 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -191,6 +191,7 @@ #![feature(extern_types)] #![feature(fundamental)] #![feature(if_let_guard)] +#![feature(inline_const)] #![feature(intra_doc_pointers)] #![feature(intrinsics)] #![feature(lang_items)] diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 3c5abd215a4b..dace748fed45 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -1,7 +1,9 @@ //! Free functions to create `&[T]` and `&mut [T]`. use crate::array; -use crate::intrinsics::{assert_unsafe_precondition, is_aligned_and_not_null}; +use crate::intrinsics::{ + assert_unsafe_precondition, is_aligned_and_not_null, is_valid_allocation_size, +}; use crate::ops::Range; use crate::ptr; @@ -91,8 +93,7 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] // SAFETY: the caller must uphold the safety contract for `from_raw_parts`. unsafe { assert_unsafe_precondition!([T](data: *const T, len: usize) => - is_aligned_and_not_null(data) - && crate::mem::size_of::().saturating_mul(len) <= isize::MAX as usize + is_aligned_and_not_null(data) && is_valid_allocation_size::(len) ); &*ptr::slice_from_raw_parts(data, len) } @@ -135,8 +136,7 @@ pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a m // SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`. unsafe { assert_unsafe_precondition!([T](data: *mut T, len: usize) => - is_aligned_and_not_null(data) - && crate::mem::size_of::().saturating_mul(len) <= isize::MAX as usize + is_aligned_and_not_null(data) && is_valid_allocation_size::(len) ); &mut *ptr::slice_from_raw_parts_mut(data, len) } From 16104474ad9472481ac7e3da67a35e1d3ad0b2ad Mon Sep 17 00:00:00 2001 From: Pointerbender Date: Thu, 20 Oct 2022 08:37:47 +0200 Subject: [PATCH 038/171] clarify documentation about the memory layout of `UnsafeCell` --- library/core/src/cell.rs | 59 +++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 3451a25504e3..12c6f2117259 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1825,35 +1825,44 @@ impl fmt::Display for RefMut<'_, T> { /// Therefore this is not a valid conversion, despite `NonNull` and `UnsafeCell>>` /// having the same memory layout. This is because `UnsafeCell` disables niche optimizations in /// order to avoid its interior mutability property from spreading from `T` into the `Outer` type, -/// thus this can cause distortions in the type size in these cases. Furthermore, it is only valid -/// to obtain a `*mut T` pointer to the contents of a _shared_ `UnsafeCell` through [`.get()`] -/// or [`.raw_get()`]. A `&mut T` reference can be obtained by either dereferencing this pointer or -/// by calling [`.get_mut()`] on an _exclusive_ `UnsafeCell`, e.g.: +/// thus this can cause distortions in the type size in these cases. +/// +/// Note that it is still only valid to obtain a `*mut T` pointer to the contents of a +/// _shared_ `UnsafeCell` through [`.get()`] or [`.raw_get()`]. A `&mut T` reference +/// can be obtained by either dereferencing this pointer or by calling [`.get_mut()`] +/// on an _exclusive_ `UnsafeCell`. Even though `T` and `UnsafeCell` have the +/// same memory layout, the following is not allowed and undefined behavior: +/// +/// ```rust,no_run +/// # use std::cell::UnsafeCell; +/// unsafe fn not_allowed(ptr: &UnsafeCell) -> &mut T { +/// let t = ptr as *const UnsafeCell as *mut T; +/// // This is undefined behavior, because the `*mut T` pointer +/// // was not obtained through `.get()` nor `.raw_get()`: +/// unsafe { &mut *t } +/// } +/// ``` +/// +/// Instead, do this: /// /// ```rust -/// use std::cell::UnsafeCell; +/// # use std::cell::UnsafeCell; +/// // Safety: the caller must ensure that there are no references that +/// // point to the *contents* of the `UnsafeCell`. +/// unsafe fn get_mut(ptr: &UnsafeCell) -> &mut T { +/// unsafe { &mut *ptr.get() } +/// } +/// ``` /// -/// let mut x: UnsafeCell = UnsafeCell::new(5); -/// let shared: &UnsafeCell = &x; -/// // using `.get()` is okay: -/// unsafe { -/// // SAFETY: there exist no other references to the contents of `x` -/// let exclusive: &mut u32 = &mut *shared.get(); -/// }; -/// // using `.raw_get()` is also okay: -/// unsafe { -/// // SAFETY: there exist no other references to the contents of `x` in this scope -/// let exclusive: &mut u32 = &mut *UnsafeCell::raw_get(shared as *const _); -/// }; -/// // using `.get_mut()` is always safe: -/// let exclusive: &mut u32 = x.get_mut(); +/// Coverting in the other direction from a `&mut T` +/// to an `&UnsafeCell` is allowed: /// -/// // when we have exclusive access, we can convert it to a shared `&UnsafeCell`: -/// unsafe { -/// // SAFETY: `u32` has no niche, therefore it has the same layout as `UnsafeCell` -/// let shared: &UnsafeCell = &*(exclusive as *mut _ as *const UnsafeCell); -/// // SAFETY: there exist no other *active* references to the contents of `x` in this scope -/// let exclusive: &mut u32 = &mut *shared.get(); +/// ```rust +/// # use std::cell::UnsafeCell; +/// fn get_shared(ptr: &mut T) -> &UnsafeCell { +/// let t = ptr as *mut T as *const UnsafeCell; +/// // SAFETY: `T` and `UnsafeCell` have the same memory layout +/// unsafe { &*t } /// } /// ``` /// From 69b845674c44cc14793a9d3727ff687c0141cf72 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 20 Oct 2022 11:32:02 +0200 Subject: [PATCH 039/171] Don't catch the server activation error --- editors/code/src/main.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index f65620aebc69..c47680fbac51 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -91,10 +91,7 @@ async function activateServer(ctx: Ctx): Promise { ctx.subscriptions ); - await ctx.activate().catch((err) => { - void vscode.window.showErrorMessage(`Cannot activate rust-analyzer server: ${err.message}`); - }); - + await ctx.activate(); return ctx.clientFetcher(); } From 5bff6c55deaf4ae75dc463bb83a39ce2ce8cdc7f Mon Sep 17 00:00:00 2001 From: feniljain Date: Sat, 8 Oct 2022 00:54:57 +0530 Subject: [PATCH 040/171] feat: add multiple getters mode in `generate_getter` This commit adds two modes to generate_getter action. First, the plain old working on single fields. Second, working on a selected range of fields. --- .../src/handlers/generate_delegate_methods.rs | 12 +- .../src/handlers/generate_enum_is_method.rs | 2 +- .../generate_enum_projection_method.rs | 2 +- .../src/handlers/generate_function.rs | 2 +- .../src/handlers/generate_getter.rs | 317 +++++++++++++++--- .../ide-assists/src/handlers/generate_new.rs | 3 +- .../src/handlers/generate_setter.rs | 7 +- crates/ide-assists/src/utils.rs | 12 +- 8 files changed, 290 insertions(+), 67 deletions(-) diff --git a/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/crates/ide-assists/src/handlers/generate_delegate_methods.rs index e5df3cbdaa96..ceae80755037 100644 --- a/crates/ide-assists/src/handlers/generate_delegate_methods.rs +++ b/crates/ide-assists/src/handlers/generate_delegate_methods.rs @@ -51,14 +51,14 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' Some(field) => { let field_name = field.name()?; let field_ty = field.ty()?; - (format!("{field_name}"), field_ty, field.syntax().text_range()) + (field_name.to_string(), field_ty, field.syntax().text_range()) } None => { let field = ctx.find_node_at_offset::()?; let field_list = ctx.find_node_at_offset::()?; let field_list_index = field_list.fields().position(|it| it == field)?; let field_ty = field.ty()?; - (format!("{field_list_index}"), field_ty, field.syntax().text_range()) + (field_list_index.to_string(), field_ty, field.syntax().text_range()) } }; @@ -77,13 +77,11 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' for method in methods { let adt = ast::Adt::Struct(strukt.clone()); let name = method.name(ctx.db()).to_string(); - let impl_def = find_struct_impl(ctx, &adt, &name).flatten(); - let method_name = method.name(ctx.db()); - + let impl_def = find_struct_impl(ctx, &adt, &[name]).flatten(); acc.add_group( &GroupLabel("Generate delegate methods…".to_owned()), AssistId("generate_delegate_methods", AssistKind::Generate), - format!("Generate delegate for `{field_name}.{method_name}()`"), + format!("Generate delegate for `{}.{}()`", field_name, method.name(ctx.db())), target, |builder| { // Create the function @@ -158,7 +156,7 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' } None => { let offset = strukt.syntax().text_range().end(); - let snippet = format!("\n\n{impl_def}"); + let snippet = format!("\n\n{}", impl_def.syntax()); builder.insert(offset, snippet); } } diff --git a/crates/ide-assists/src/handlers/generate_enum_is_method.rs b/crates/ide-assists/src/handlers/generate_enum_is_method.rs index dba98f7a04e4..63e91b835f1f 100644 --- a/crates/ide-assists/src/handlers/generate_enum_is_method.rs +++ b/crates/ide-assists/src/handlers/generate_enum_is_method.rs @@ -52,7 +52,7 @@ pub(crate) fn generate_enum_is_method(acc: &mut Assists, ctx: &AssistContext<'_> let fn_name = format!("is_{}", &to_lower_snake_case(&variant_name.text())); // Return early if we've found an existing new fn - let impl_def = find_struct_impl(ctx, &parent_enum, &fn_name)?; + let impl_def = find_struct_impl(ctx, &parent_enum, &[fn_name.clone()])?; let target = variant.syntax().text_range(); acc.add_group( diff --git a/crates/ide-assists/src/handlers/generate_enum_projection_method.rs b/crates/ide-assists/src/handlers/generate_enum_projection_method.rs index 402ab1ee79d3..bdd3cf4f06c2 100644 --- a/crates/ide-assists/src/handlers/generate_enum_projection_method.rs +++ b/crates/ide-assists/src/handlers/generate_enum_projection_method.rs @@ -147,7 +147,7 @@ fn generate_enum_projection_method( let fn_name = format!("{}_{}", fn_name_prefix, &to_lower_snake_case(&variant_name.text())); // Return early if we've found an existing new fn - let impl_def = find_struct_impl(ctx, &parent_enum, &fn_name)?; + let impl_def = find_struct_impl(ctx, &parent_enum, &[fn_name.clone()])?; let target = variant.syntax().text_range(); acc.add_group( diff --git a/crates/ide-assists/src/handlers/generate_function.rs b/crates/ide-assists/src/handlers/generate_function.rs index e6cc8cacedd9..c229127e48ff 100644 --- a/crates/ide-assists/src/handlers/generate_function.rs +++ b/crates/ide-assists/src/handlers/generate_function.rs @@ -198,7 +198,7 @@ fn get_adt_source( let file = ctx.sema.parse(range.file_id); let adt_source = ctx.sema.find_node_at_offset_with_macros(file.syntax(), range.range.start())?; - find_struct_impl(ctx, &adt_source, fn_name).map(|impl_| (impl_, range.file_id)) + find_struct_impl(ctx, &adt_source, &[fn_name.to_string()]).map(|impl_| (impl_, range.file_id)) } struct FunctionTemplate { diff --git a/crates/ide-assists/src/handlers/generate_getter.rs b/crates/ide-assists/src/handlers/generate_getter.rs index 09eedb11fbc1..5e7191428349 100644 --- a/crates/ide-assists/src/handlers/generate_getter.rs +++ b/crates/ide-assists/src/handlers/generate_getter.rs @@ -1,6 +1,9 @@ use ide_db::famous_defs::FamousDefs; use stdx::{format_to, to_lower_snake_case}; -use syntax::ast::{self, AstNode, HasName, HasVisibility}; +use syntax::{ + ast::{self, AstNode, HasName, HasVisibility}, + TextRange, +}; use crate::{ utils::{convert_reference_type, find_impl_block_end, find_struct_impl, generate_impl_text}, @@ -72,88 +75,259 @@ pub(crate) fn generate_getter_mut(acc: &mut Assists, ctx: &AssistContext<'_>) -> generate_getter_impl(acc, ctx, true) } +#[derive(Clone, Debug)] +struct RecordFieldInfo { + field_name: syntax::ast::Name, + field_ty: syntax::ast::Type, + fn_name: String, + target: TextRange, +} + +struct GetterInfo { + impl_def: Option, + strukt: ast::Struct, + mutable: bool, +} + pub(crate) fn generate_getter_impl( acc: &mut Assists, ctx: &AssistContext<'_>, mutable: bool, ) -> Option<()> { - let strukt = ctx.find_node_at_offset::()?; - let field = ctx.find_node_at_offset::()?; + // This if condition denotes two modes this assist can work in: + // - First is acting upon selection of record fields + // - Next is acting upon a single record field + // + // This is the only part where implementation diverges a bit, + // subsequent code is generic for both of these modes - let field_name = field.name()?; - let field_ty = field.ty()?; + let (strukt, info_of_record_fields, fn_names) = if !ctx.has_empty_selection() { + // Selection Mode + let node = ctx.covering_element(); - // Return early if we've found an existing fn - let mut fn_name = to_lower_snake_case(&field_name.to_string()); - if mutable { - format_to!(fn_name, "_mut"); + let node = match node { + syntax::NodeOrToken::Node(n) => n, + syntax::NodeOrToken::Token(t) => t.parent()?, + }; + + let parent_struct = node.ancestors().find_map(ast::Struct::cast)?; + + let (info_of_record_fields, field_names) = + extract_and_parse_record_fields(&parent_struct, ctx.selection_trimmed(), mutable)?; + + (parent_struct, info_of_record_fields, field_names) + } else { + // Single Record Field mode + let strukt = ctx.find_node_at_offset::()?; + let field = ctx.find_node_at_offset::()?; + + let record_field_info = parse_record_field(field, mutable)?; + + let fn_name = record_field_info.fn_name.clone(); + + (strukt, vec![record_field_info], vec![fn_name]) + }; + + // No record fields to do work on :( + if info_of_record_fields.len() == 0 { + return None; } - let impl_def = find_struct_impl(ctx, &ast::Adt::Struct(strukt.clone()), fn_name.as_str())?; + + let impl_def = find_struct_impl(ctx, &ast::Adt::Struct(strukt.clone()), &fn_names)?; let (id, label) = if mutable { ("generate_getter_mut", "Generate a mut getter method") } else { ("generate_getter", "Generate a getter method") }; - let target = field.syntax().text_range(); + + // Computing collective text range of all record fields in selected region + let target: TextRange = info_of_record_fields + .iter() + .map(|record_field_info| record_field_info.target) + .reduce(|acc, target| acc.cover(target))?; + + let getter_info = GetterInfo { impl_def, strukt, mutable }; + acc.add_group( &GroupLabel("Generate getter/setter".to_owned()), AssistId(id, AssistKind::Generate), label, target, |builder| { + let record_fields_count = info_of_record_fields.len(); + let mut buf = String::with_capacity(512); - if impl_def.is_some() { - buf.push('\n'); + // Check if an impl exists + if let Some(impl_def) = &getter_info.impl_def { + // Check if impl is empty + if let Some(assoc_item_list) = impl_def.assoc_item_list() { + if assoc_item_list.assoc_items().next().is_some() { + // If not empty then only insert a new line + buf.push('\n'); + } + } } - let vis = strukt.visibility().map_or(String::new(), |v| format!("{v} ")); - let (ty, body) = if mutable { - (format!("&mut {field_ty}"), format!("&mut self.{field_name}")) - } else { - (|| { - let krate = ctx.sema.scope(field_ty.syntax())?.krate(); - let famous_defs = &FamousDefs(&ctx.sema, krate); - ctx.sema - .resolve_type(&field_ty) - .and_then(|ty| convert_reference_type(ty, ctx.db(), famous_defs)) - .map(|conversion| { - cov_mark::hit!(convert_reference_type); - ( - conversion.convert_type(ctx.db()), - conversion.getter(field_name.to_string()), - ) - }) - })() - .unwrap_or_else(|| (format!("&{field_ty}"), format!("&self.{field_name}"))) - }; + for (i, record_field_info) in info_of_record_fields.iter().enumerate() { + // this buf inserts a newline at the end of a getter + // automatically, if one wants to add one more newline + // for separating it from other assoc items, that needs + // to be handled spearately + let mut getter_buf = + generate_getter_from_info(ctx, &getter_info, &record_field_info); - let mut_ = mutable.then(|| "mut ").unwrap_or_default(); - format_to!( - buf, - " {vis}fn {fn_name}(&{mut_}self) -> {ty} {{ - {body} - }}" - ); + // Insert `$0` only for last getter we generate + if i == record_fields_count - 1 { + getter_buf = getter_buf.replacen("fn ", "fn $0", 1); + } - let start_offset = impl_def - .and_then(|impl_def| find_impl_block_end(impl_def, &mut buf)) + // For first element we do not merge with '\n', as + // that can be inserted by impl_def check defined + // above, for other cases which are: + // + // - impl exists but it empty, here we would ideally + // not want to keep newline between impl { + // and fn () { line + // + // - next if impl itself does not exist, in this + // case we ourselves generate a new impl and that + // again ends up with the same reasoning as above + // for not keeping newline + if i == 0 { + buf = buf + &getter_buf; + } else { + buf = buf + "\n" + &getter_buf; + } + + // We don't insert a new line at the end of + // last getter as it will end up in the end + // of an impl where we would not like to keep + // getter and end of impl ( i.e. `}` ) with an + // extra line for no reason + if i < record_fields_count - 1 { + buf = buf + "\n"; + } + } + + let start_offset = getter_info + .impl_def + .as_ref() + .and_then(|impl_def| find_impl_block_end(impl_def.to_owned(), &mut buf)) .unwrap_or_else(|| { - buf = generate_impl_text(&ast::Adt::Struct(strukt.clone()), &buf); - strukt.syntax().text_range().end() + buf = generate_impl_text(&ast::Adt::Struct(getter_info.strukt.clone()), &buf); + getter_info.strukt.syntax().text_range().end() }); match ctx.config.snippet_cap { - Some(cap) => { - builder.insert_snippet(cap, start_offset, buf.replacen("fn ", "fn $0", 1)) - } + Some(cap) => builder.insert_snippet(cap, start_offset, buf), None => builder.insert(start_offset, buf), } }, ) } +fn generate_getter_from_info( + ctx: &AssistContext<'_>, + info: &GetterInfo, + record_field_info: &RecordFieldInfo, +) -> String { + let mut buf = String::with_capacity(512); + + let vis = info.strukt.visibility().map_or(String::new(), |v| format!("{} ", v)); + let (ty, body) = if info.mutable { + ( + format!("&mut {}", record_field_info.field_ty), + format!("&mut self.{}", record_field_info.field_name), + ) + } else { + (|| { + let krate = ctx.sema.scope(record_field_info.field_ty.syntax())?.krate(); + let famous_defs = &FamousDefs(&ctx.sema, krate); + ctx.sema + .resolve_type(&record_field_info.field_ty) + .and_then(|ty| convert_reference_type(ty, ctx.db(), famous_defs)) + .map(|conversion| { + cov_mark::hit!(convert_reference_type); + ( + conversion.convert_type(ctx.db()), + conversion.getter(record_field_info.field_name.to_string()), + ) + }) + })() + .unwrap_or_else(|| { + ( + format!("&{}", record_field_info.field_ty), + format!("&self.{}", record_field_info.field_name), + ) + }) + }; + + format_to!( + buf, + " {}fn {}(&{}self) -> {} {{ + {} + }}", + vis, + record_field_info.fn_name, + info.mutable.then(|| "mut ").unwrap_or_default(), + ty, + body, + ); + + buf +} + +fn extract_and_parse_record_fields( + node: &ast::Struct, + selection_range: TextRange, + mutable: bool, +) -> Option<(Vec, Vec)> { + let mut field_names: Vec = vec![]; + let field_list = node.field_list()?; + + match field_list { + ast::FieldList::RecordFieldList(ele) => { + let info_of_record_fields_in_selection = ele + .fields() + .filter_map(|record_field| { + if selection_range.contains_range(record_field.syntax().text_range()) { + let record_field_info = parse_record_field(record_field, mutable)?; + field_names.push(record_field_info.fn_name.clone()); + return Some(record_field_info); + } + + None + }) + .collect::>(); + + if info_of_record_fields_in_selection.len() == 0 { + return None; + } + + Some((info_of_record_fields_in_selection, field_names)) + } + ast::FieldList::TupleFieldList(_) => { + return None; + } + } +} + +fn parse_record_field(record_field: ast::RecordField, mutable: bool) -> Option { + let field_name = record_field.name()?; + let field_ty = record_field.ty()?; + + let mut fn_name = to_lower_snake_case(&field_name.to_string()); + if mutable { + format_to!(fn_name, "_mut"); + } + + let target = record_field.syntax().text_range(); + + Some(RecordFieldInfo { field_name, field_ty, fn_name, target }) +} + #[cfg(test)] mod tests { use crate::tests::{check_assist, check_assist_not_applicable}; @@ -485,4 +659,53 @@ impl Context { "#, ); } + + #[test] + fn test_generate_multiple_getters_from_selection() { + check_assist( + generate_getter, + r#" +struct Context { + $0data: Data, + count: usize,$0 +} + "#, + r#" +struct Context { + data: Data, + count: usize, +} + +impl Context { + fn data(&self) -> &Data { + &self.data + } + + fn $0count(&self) -> &usize { + &self.count + } +} + "#, + ); + } + + #[test] + fn test_generate_multiple_getters_from_selection_one_already_exists() { + // As impl for one of the fields already exist, skip it + check_assist_not_applicable( + generate_getter, + r#" +struct Context { + $0data: Data, + count: usize,$0 +} + +impl Context { + fn data(&self) -> &Data { + &self.data + } +} + "#, + ); + } } diff --git a/crates/ide-assists/src/handlers/generate_new.rs b/crates/ide-assists/src/handlers/generate_new.rs index c441a2dc48e4..17fadea0eaf1 100644 --- a/crates/ide-assists/src/handlers/generate_new.rs +++ b/crates/ide-assists/src/handlers/generate_new.rs @@ -39,7 +39,8 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option }; // Return early if we've found an existing new fn - let impl_def = find_struct_impl(ctx, &ast::Adt::Struct(strukt.clone()), "new")?; + let impl_def = + find_struct_impl(ctx, &ast::Adt::Struct(strukt.clone()), &[String::from("new")])?; let current_module = ctx.sema.scope(strukt.syntax())?.module(); diff --git a/crates/ide-assists/src/handlers/generate_setter.rs b/crates/ide-assists/src/handlers/generate_setter.rs index e139bcb1a1b0..62f72df1c9d6 100644 --- a/crates/ide-assists/src/handlers/generate_setter.rs +++ b/crates/ide-assists/src/handlers/generate_setter.rs @@ -36,11 +36,8 @@ pub(crate) fn generate_setter(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt // Return early if we've found an existing fn let fn_name = to_lower_snake_case(&field_name.to_string()); - let impl_def = find_struct_impl( - ctx, - &ast::Adt::Struct(strukt.clone()), - format!("set_{fn_name}").as_str(), - )?; + let impl_def = + find_struct_impl(ctx, &ast::Adt::Struct(strukt.clone()), &[format!("set_{fn_name}")])?; let target = field.syntax().text_range(); acc.add_group( diff --git a/crates/ide-assists/src/utils.rs b/crates/ide-assists/src/utils.rs index 38396cd7d7ba..db32e7182c44 100644 --- a/crates/ide-assists/src/utils.rs +++ b/crates/ide-assists/src/utils.rs @@ -331,10 +331,14 @@ fn calc_depth(pat: &ast::Pat, depth: usize) -> usize { // FIXME: change the new fn checking to a more semantic approach when that's more // viable (e.g. we process proc macros, etc) // FIXME: this partially overlaps with `find_impl_block_*` + +/// `find_struct_impl` looks for impl of a struct, but this also has additional feature +/// where it takes a list of function names and check if they exist inside impl_, if +/// even one match is found, it returns None pub(crate) fn find_struct_impl( ctx: &AssistContext<'_>, adt: &ast::Adt, - name: &str, + names: &[String], ) -> Option> { let db = ctx.db(); let module = adt.syntax().parent()?; @@ -362,7 +366,7 @@ pub(crate) fn find_struct_impl( }); if let Some(ref impl_blk) = block { - if has_fn(impl_blk, name) { + if has_any_fn(impl_blk, names) { return None; } } @@ -370,12 +374,12 @@ pub(crate) fn find_struct_impl( Some(block) } -fn has_fn(imp: &ast::Impl, rhs_name: &str) -> bool { +fn has_any_fn(imp: &ast::Impl, names: &[String]) -> bool { if let Some(il) = imp.assoc_item_list() { for item in il.assoc_items() { if let ast::AssocItem::Fn(f) = item { if let Some(name) = f.name() { - if name.text().eq_ignore_ascii_case(rhs_name) { + if names.iter().any(|n| n.eq_ignore_ascii_case(&name.text())) { return true; } } From de195ff97cda417c61c8760bb332167b2c377078 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 20 Oct 2022 19:28:28 +0200 Subject: [PATCH 041/171] fix: Fix DidSaveDocument requests blocking the server on startup --- crates/ide/src/lib.rs | 10 ++ crates/ide/src/parent_module.rs | 10 +- crates/rust-analyzer/src/cargo_target_spec.rs | 6 +- crates/rust-analyzer/src/global_state.rs | 17 +- crates/rust-analyzer/src/handlers.rs | 14 +- crates/rust-analyzer/src/main_loop.rs | 153 ++++++++++-------- crates/rust-analyzer/src/reload.rs | 5 +- 7 files changed, 132 insertions(+), 83 deletions(-) diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 09a5cb03ecdc..416817ca0b42 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -486,6 +486,16 @@ impl Analysis { self.with_db(|db| parent_module::crates_for(db, file_id)) } + /// Returns crates this file belongs too. + pub fn transitive_rev_deps(&self, crate_id: CrateId) -> Cancellable> { + self.with_db(|db| db.crate_graph().transitive_rev_deps(crate_id).collect()) + } + + /// Returns crates this file *might* belong too. + pub fn relevant_crates_for(&self, file_id: FileId) -> Cancellable> { + self.with_db(|db| db.relevant_crates(file_id).iter().copied().collect()) + } + /// Returns the edition of the given crate. pub fn crate_edition(&self, crate_id: CrateId) -> Cancellable { self.with_db(|db| db.crate_graph()[crate_id].edition) diff --git a/crates/ide/src/parent_module.rs b/crates/ide/src/parent_module.rs index 9d425954e390..506f9452cf19 100644 --- a/crates/ide/src/parent_module.rs +++ b/crates/ide/src/parent_module.rs @@ -1,8 +1,9 @@ -use hir::Semantics; +use hir::{db::DefDatabase, Semantics}; use ide_db::{ base_db::{CrateId, FileId, FileLoader, FilePosition}, RootDatabase, }; +use itertools::Itertools; use syntax::{ algo::find_node_at_offset, ast::{self, AstNode}, @@ -55,7 +56,12 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec Vec { - db.relevant_crates(file_id).iter().copied().collect() + db.relevant_crates(file_id) + .iter() + .copied() + .filter(|&crate_id| db.crate_def_map(crate_id).modules_for_file(file_id).next().is_some()) + .sorted() + .collect() } #[cfg(test)] diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs index cbde73547619..6ede194babc2 100644 --- a/crates/rust-analyzer/src/cargo_target_spec.rs +++ b/crates/rust-analyzer/src/cargo_target_spec.rs @@ -118,7 +118,11 @@ impl CargoTargetSpec { global_state_snapshot: &GlobalStateSnapshot, file_id: FileId, ) -> Result> { - let (cargo_ws, target) = match global_state_snapshot.cargo_target_for_file_id(file_id) { + let crate_id = match &*global_state_snapshot.analysis.crates_for(file_id)? { + &[crate_id, ..] => crate_id, + _ => return Ok(None), + }; + let (cargo_ws, target) = match global_state_snapshot.cargo_target_for_crate_root(crate_id) { Some(it) => it, None => return Ok(None), }; diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 4cddb12083a1..3fb06c31f7ca 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -8,7 +8,7 @@ use std::{sync::Arc, time::Instant}; use crossbeam_channel::{unbounded, Receiver, Sender}; use flycheck::FlycheckHandle; use ide::{Analysis, AnalysisHost, Cancellable, Change, FileId}; -use ide_db::base_db::{FileLoader, SourceDatabase}; +use ide_db::base_db::{CrateId, FileLoader, SourceDatabase}; use lsp_types::{SemanticTokens, Url}; use parking_lot::{Mutex, RwLock}; use proc_macro_api::ProcMacroServer; @@ -64,7 +64,7 @@ pub(crate) struct GlobalState { pub(crate) source_root_config: SourceRootConfig, pub(crate) proc_macro_clients: Vec>, - pub(crate) flycheck: Vec, + pub(crate) flycheck: Arc<[FlycheckHandle]>, pub(crate) flycheck_sender: Sender, pub(crate) flycheck_receiver: Receiver, @@ -117,6 +117,7 @@ pub(crate) struct GlobalStateSnapshot { vfs: Arc)>>, pub(crate) workspaces: Arc>, pub(crate) proc_macros_loaded: bool, + pub(crate) flycheck: Arc<[FlycheckHandle]>, } impl std::panic::UnwindSafe for GlobalStateSnapshot {} @@ -155,7 +156,7 @@ impl GlobalState { source_root_config: SourceRootConfig::default(), proc_macro_clients: vec![], - flycheck: Vec::new(), + flycheck: Arc::new([]), flycheck_sender, flycheck_receiver, @@ -295,6 +296,7 @@ impl GlobalState { mem_docs: self.mem_docs.clone(), semantic_tokens_cache: Arc::clone(&self.semantic_tokens_cache), proc_macros_loaded: !self.fetch_build_data_queue.last_op_result().0.is_empty(), + flycheck: self.flycheck.clone(), } } @@ -398,10 +400,15 @@ impl GlobalStateSnapshot { url_from_abs_path(path) } - pub(crate) fn cargo_target_for_file_id( + pub(crate) fn file_id_to_file_path(&self, file_id: FileId) -> vfs::VfsPath { + self.vfs.read().0.file_path(file_id) + } + + pub(crate) fn cargo_target_for_crate_root( &self, - file_id: FileId, + crate_id: CrateId, ) -> Option<(&CargoWorkspace, Target)> { + let file_id = self.analysis.crate_root(crate_id).ok()?; let path = self.vfs.read().0.file_path(file_id); let path = path.as_path()?; self.workspaces.iter().find_map(|ws| match ws { diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 701a009ea8bd..34795a8eb40a 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs @@ -1782,7 +1782,15 @@ fn run_rustfmt( ) -> Result>> { let file_id = from_proto::file_id(snap, &text_document.uri)?; let file = snap.analysis.file_text(file_id)?; - let crate_ids = snap.analysis.crates_for(file_id)?; + + // find the edition of the package the file belongs to + // (if it belongs to multiple we'll just pick the first one and pray) + let edition = snap + .analysis + .relevant_crates_for(file_id)? + .into_iter() + .find_map(|crate_id| snap.cargo_target_for_crate_root(crate_id)) + .map(|(ws, target)| ws[ws[target].package].edition); let line_index = snap.file_line_index(file_id)?; @@ -1808,9 +1816,7 @@ fn run_rustfmt( ); } } - if let Some(&crate_id) = crate_ids.first() { - // Assume all crates are in the same edition - let edition = snap.analysis.crate_edition(crate_id)?; + if let Some(edition) = edition { cmd.arg("--edition"); cmd.arg(edition.to_string()); } diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 89189cef1499..319b86c58b5c 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -10,7 +10,7 @@ use std::{ use always_assert::always; use crossbeam_channel::{select, Receiver}; use flycheck::FlycheckHandle; -use ide_db::base_db::{SourceDatabase, SourceDatabaseExt, VfsPath}; +use ide_db::base_db::{SourceDatabaseExt, VfsPath}; use itertools::Itertools; use lsp_server::{Connection, Notification, Request}; use lsp_types::notification::Notification as _; @@ -191,7 +191,7 @@ impl GlobalState { // NOTE: don't count blocking select! call as a loop-turn time let _p = profile::span("GlobalState::handle_event"); - tracing::debug!("handle_event({:?})", event); + tracing::debug!("{:?} handle_event({:?})", loop_start, event); let task_queue_len = self.task_pool.handle.len(); if task_queue_len > 0 { tracing::info!("task queue len: {}", task_queue_len); @@ -727,7 +727,7 @@ impl GlobalState { .insert(path.clone(), DocumentData::new(params.text_document.version)) .is_err(); if already_exists { - tracing::error!("duplicate DidOpenTextDocument: {}", path) + tracing::error!("duplicate DidOpenTextDocument: {}", path); } this.vfs .write() @@ -774,69 +774,7 @@ impl GlobalState { Ok(()) })? .on::(|this, params| { - let mut updated = false; if let Ok(vfs_path) = from_proto::vfs_path(¶ms.text_document.uri) { - let (vfs, _) = &*this.vfs.read(); - - // Trigger flychecks for all workspaces that depend on the saved file - if let Some(file_id) = vfs.file_id(&vfs_path) { - let analysis = this.analysis_host.analysis(); - // Crates containing or depending on the saved file - let crate_ids: Vec<_> = analysis - .crates_for(file_id)? - .into_iter() - .flat_map(|id| { - this.analysis_host - .raw_database() - .crate_graph() - .transitive_rev_deps(id) - }) - .sorted() - .unique() - .collect(); - - let crate_root_paths: Vec<_> = crate_ids - .iter() - .filter_map(|&crate_id| { - analysis - .crate_root(crate_id) - .map(|file_id| { - vfs.file_path(file_id).as_path().map(ToOwned::to_owned) - }) - .transpose() - }) - .collect::>()?; - let crate_root_paths: Vec<_> = - crate_root_paths.iter().map(Deref::deref).collect(); - - // Find all workspaces that have at least one target containing the saved file - let workspace_ids = - this.workspaces.iter().enumerate().filter(|(_, ws)| match ws { - project_model::ProjectWorkspace::Cargo { cargo, .. } => { - cargo.packages().any(|pkg| { - cargo[pkg].targets.iter().any(|&it| { - crate_root_paths.contains(&cargo[it].root.as_path()) - }) - }) - } - project_model::ProjectWorkspace::Json { project, .. } => project - .crates() - .any(|(c, _)| crate_ids.iter().any(|&crate_id| crate_id == c)), - project_model::ProjectWorkspace::DetachedFiles { .. } => false, - }); - - // Find and trigger corresponding flychecks - for flycheck in &this.flycheck { - for (id, _) in workspace_ids.clone() { - if id == flycheck.id() { - updated = true; - flycheck.restart(); - continue; - } - } - } - } - // Re-fetch workspaces if a workspace related file has changed if let Some(abs_path) = vfs_path.as_path() { if reload::should_refresh_for_change(&abs_path, ChangeKind::Modify) { @@ -844,13 +782,90 @@ impl GlobalState { .request_op(format!("DidSaveTextDocument {}", abs_path.display())); } } + + let file_id = this.vfs.read().0.file_id(&vfs_path); + if let Some(file_id) = file_id { + let world = this.snapshot(); + let mut updated = false; + let task = move || -> std::result::Result<(), ide::Cancelled> { + // Trigger flychecks for all workspaces that depend on the saved file + // Crates containing or depending on the saved file + let crate_ids: Vec<_> = world + .analysis + .crates_for(file_id)? + .into_iter() + .flat_map(|id| world.analysis.transitive_rev_deps(id)) + .flatten() + .sorted() + .unique() + .collect(); + + let crate_root_paths: Vec<_> = crate_ids + .iter() + .filter_map(|&crate_id| { + world + .analysis + .crate_root(crate_id) + .map(|file_id| { + world + .file_id_to_file_path(file_id) + .as_path() + .map(ToOwned::to_owned) + }) + .transpose() + }) + .collect::>()?; + let crate_root_paths: Vec<_> = + crate_root_paths.iter().map(Deref::deref).collect(); + + // Find all workspaces that have at least one target containing the saved file + let workspace_ids = + world.workspaces.iter().enumerate().filter(|(_, ws)| match ws { + project_model::ProjectWorkspace::Cargo { cargo, .. } => { + cargo.packages().any(|pkg| { + cargo[pkg].targets.iter().any(|&it| { + crate_root_paths.contains(&cargo[it].root.as_path()) + }) + }) + } + project_model::ProjectWorkspace::Json { project, .. } => { + project.crates().any(|(c, _)| { + crate_ids.iter().any(|&crate_id| crate_id == c) + }) + } + project_model::ProjectWorkspace::DetachedFiles { .. } => false, + }); + + // Find and trigger corresponding flychecks + for flycheck in world.flycheck.iter() { + for (id, _) in workspace_ids.clone() { + if id == flycheck.id() { + updated = true; + flycheck.restart(); + continue; + } + } + } + // No specific flycheck was triggered, so let's trigger all of them. + if !updated { + for flycheck in world.flycheck.iter() { + flycheck.restart(); + } + } + Ok(()) + }; + this.task_pool.handle.spawn_with_sender(move |_| { + if let Err(e) = std::panic::catch_unwind(task) { + tracing::error!("DidSaveTextDocument flycheck task panicked: {e:?}") + } + }); + return Ok(()); + } } // No specific flycheck was triggered, so let's trigger all of them. - if !updated { - for flycheck in &this.flycheck { - flycheck.restart(); - } + for flycheck in this.flycheck.iter() { + flycheck.restart(); } Ok(()) })? diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index f7db62baf2c1..cc7600a2fa98 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -466,7 +466,7 @@ impl GlobalState { let config = match self.config.flycheck() { Some(it) => it, None => { - self.flycheck = Vec::new(); + self.flycheck = Arc::new([]); self.diagnostics.clear_check_all(); return; } @@ -510,7 +510,8 @@ impl GlobalState { }) .collect() } - }; + } + .into(); } } From e05df93b8ee0936c37df8e368817dc201e07fb75 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Thu, 20 Oct 2022 17:56:51 +0000 Subject: [PATCH 042/171] Workaround the python vscode extension's polyfill --- editors/code/src/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 10e243dc896c..0aa998db6250 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -191,7 +191,7 @@ export class Config { const VarRegex = new RegExp(/\$\{(.+?)\}/g); export function substituteVSCodeVariableInString(val: string): string { - return val.replaceAll(VarRegex, (substring: string, varName) => { + return val.replace(VarRegex, (substring: string, varName) => { if (typeof varName === "string") { return computeVscodeVar(varName) || substring; } else { From a8e0a20ce4396d3c77adf3b5deb48edfd27d6af2 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 20 Oct 2022 21:12:58 +0200 Subject: [PATCH 043/171] internal: Properly handle language configuration config changes --- editors/code/src/config.ts | 100 ++++++++++++++++++++++++++++--------- editors/code/src/ctx.ts | 8 ++- editors/code/src/main.ts | 60 ++-------------------- 3 files changed, 88 insertions(+), 80 deletions(-) diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 10e243dc896c..61125d7a83eb 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -11,13 +11,9 @@ export type RunnableEnvCfg = export class Config { readonly extensionId = "rust-lang.rust-analyzer"; + configureLang: vscode.Disposable | undefined; readonly rootSection = "rust-analyzer"; - private readonly requiresWorkspaceReloadOpts = [ - // FIXME: This shouldn't be here, changing this setting should reload - // `continueCommentsOnNewline` behavior without restart - "typing", - ].map((opt) => `${this.rootSection}.${opt}`); private readonly requiresReloadOpts = [ "cargo", "procMacro", @@ -25,9 +21,7 @@ export class Config { "server", "files", "lens", // works as lens.* - ] - .map((opt) => `${this.rootSection}.${opt}`) - .concat(this.requiresWorkspaceReloadOpts); + ].map((opt) => `${this.rootSection}.${opt}`); readonly package: { version: string; @@ -45,6 +39,11 @@ export class Config { ctx.subscriptions ); this.refreshLogging(); + this.configureLanguage(); + } + + dispose() { + this.configureLang?.dispose(); } private refreshLogging() { @@ -58,33 +57,86 @@ export class Config { private async onDidChangeConfiguration(event: vscode.ConfigurationChangeEvent) { this.refreshLogging(); + this.configureLanguage(); + const requiresReloadOpt = this.requiresReloadOpts.find((opt) => event.affectsConfiguration(opt) ); if (!requiresReloadOpt) return; - const requiresWorkspaceReloadOpt = this.requiresWorkspaceReloadOpts.find((opt) => - event.affectsConfiguration(opt) - ); - - if (!requiresWorkspaceReloadOpt && this.restartServerOnConfigChange) { + if (this.restartServerOnConfigChange) { await vscode.commands.executeCommand("rust-analyzer.reload"); return; } - const message = requiresWorkspaceReloadOpt - ? `Changing "${requiresWorkspaceReloadOpt}" requires a window reload` - : `Changing "${requiresReloadOpt}" requires a reload`; - const userResponse = await vscode.window.showInformationMessage(message, "Reload now"); + const message = `Changing "${requiresReloadOpt}" requires a server restart`; + const userResponse = await vscode.window.showInformationMessage(message, "Restart now"); - if (userResponse === "Reload now") { - const command = requiresWorkspaceReloadOpt - ? "workbench.action.reloadWindow" - : "rust-analyzer.reload"; - if (userResponse === "Reload now") { - await vscode.commands.executeCommand(command); - } + if (userResponse) { + const command = "rust-analyzer.reload"; + await vscode.commands.executeCommand(command); + } + } + + /** + * Sets up additional language configuration that's impossible to do via a + * separate language-configuration.json file. See [1] for more information. + * + * [1]: https://github.com/Microsoft/vscode/issues/11514#issuecomment-244707076 + */ + private configureLanguage() { + if (this.typingContinueCommentsOnNewline && !this.configureLang) { + const indentAction = vscode.IndentAction.None; + + this.configureLang = vscode.languages.setLanguageConfiguration("rust", { + onEnterRules: [ + { + // Doc single-line comment + // e.g. ///| + beforeText: /^\s*\/{3}.*$/, + action: { indentAction, appendText: "/// " }, + }, + { + // Parent doc single-line comment + // e.g. //!| + beforeText: /^\s*\/{2}\!.*$/, + action: { indentAction, appendText: "//! " }, + }, + { + // Begins an auto-closed multi-line comment (standard or parent doc) + // e.g. /** | */ or /*! | */ + beforeText: /^\s*\/\*(\*|\!)(?!\/)([^\*]|\*(?!\/))*$/, + afterText: /^\s*\*\/$/, + action: { + indentAction: vscode.IndentAction.IndentOutdent, + appendText: " * ", + }, + }, + { + // Begins a multi-line comment (standard or parent doc) + // e.g. /** ...| or /*! ...| + beforeText: /^\s*\/\*(\*|\!)(?!\/)([^\*]|\*(?!\/))*$/, + action: { indentAction, appendText: " * " }, + }, + { + // Continues a multi-line comment + // e.g. * ...| + beforeText: /^(\ \ )*\ \*(\ ([^\*]|\*(?!\/))*)?$/, + action: { indentAction, appendText: "* " }, + }, + { + // Dedents after closing a multi-line comment + // e.g. */| + beforeText: /^(\ \ )*\ \*\/\s*$/, + action: { indentAction, removeText: 1 }, + }, + ], + }); + } + if (!this.typingContinueCommentsOnNewline && this.configureLang) { + this.configureLang.dispose(); + this.configureLang = undefined; } } diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index e94d4365c376..75c6d4698c17 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -38,6 +38,7 @@ export class Ctx { this.dispose(); }, }); + extCtx.subscriptions.push(this); this.statusBar.text = "rust-analyzer"; this.statusBar.tooltip = "ready"; this.statusBar.command = "rust-analyzer.analyzerStatus"; @@ -48,10 +49,15 @@ export class Ctx { this.config = new Config(extCtx); } + dispose() { + this.config.dispose(); + } + clientFetcher() { + const self = this; return { get client(): lc.LanguageClient | undefined { - return this.client; + return self.client; }, }; } diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index c47680fbac51..fa7dc6fe304e 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -77,10 +77,6 @@ async function activateServer(ctx: Ctx): Promise { await initCommonContext(ctx); - if (ctx.config.typingContinueCommentsOnNewline) { - ctx.pushExtCleanup(configureLanguage()); - } - vscode.workspace.onDidChangeConfiguration( async (_) => { await ctx @@ -129,6 +125,11 @@ async function initCommonContext(ctx: Ctx) { ctx.registerCommand("stopServer", (_) => async () => { // FIXME: We should re-use the client, that is ctx.deactivate() if none of the configs have changed await ctx.disposeClient(); + ctx.setServerStatus({ + health: "ok", + quiescent: true, + message: "server is not running", + }); }); ctx.registerCommand("analyzerStatus", commands.analyzerStatus); ctx.registerCommand("memoryUsage", commands.memoryUsage); @@ -172,54 +173,3 @@ async function initCommonContext(ctx: Ctx) { defaultOnEnter.dispose(); ctx.registerCommand("onEnter", commands.onEnter); } - -/** - * Sets up additional language configuration that's impossible to do via a - * separate language-configuration.json file. See [1] for more information. - * - * [1]: https://github.com/Microsoft/vscode/issues/11514#issuecomment-244707076 - */ -function configureLanguage(): vscode.Disposable { - const indentAction = vscode.IndentAction.None; - return vscode.languages.setLanguageConfiguration("rust", { - onEnterRules: [ - { - // Doc single-line comment - // e.g. ///| - beforeText: /^\s*\/{3}.*$/, - action: { indentAction, appendText: "/// " }, - }, - { - // Parent doc single-line comment - // e.g. //!| - beforeText: /^\s*\/{2}\!.*$/, - action: { indentAction, appendText: "//! " }, - }, - { - // Begins an auto-closed multi-line comment (standard or parent doc) - // e.g. /** | */ or /*! | */ - beforeText: /^\s*\/\*(\*|\!)(?!\/)([^\*]|\*(?!\/))*$/, - afterText: /^\s*\*\/$/, - action: { indentAction: vscode.IndentAction.IndentOutdent, appendText: " * " }, - }, - { - // Begins a multi-line comment (standard or parent doc) - // e.g. /** ...| or /*! ...| - beforeText: /^\s*\/\*(\*|\!)(?!\/)([^\*]|\*(?!\/))*$/, - action: { indentAction, appendText: " * " }, - }, - { - // Continues a multi-line comment - // e.g. * ...| - beforeText: /^(\ \ )*\ \*(\ ([^\*]|\*(?!\/))*)?$/, - action: { indentAction, appendText: "* " }, - }, - { - // Dedents after closing a multi-line comment - // e.g. */| - beforeText: /^(\ \ )*\ \*\/\s*$/, - action: { indentAction, removeText: 1 }, - }, - ], - }); -} From 770538ef9b9a93038983ee5d82e07754c279df06 Mon Sep 17 00:00:00 2001 From: Nicolas Barrios Date: Wed, 19 Oct 2022 22:06:50 -0400 Subject: [PATCH 044/171] Add fix suggestions for E0199, E0200, and E0569 --- .../src/coherence/unsafety.rs | 30 +++++++++++++++++++ .../coherence-default-trait-impl.stderr | 12 ++++++++ ...dropck-eyepatch-implies-unsafe-impl.stderr | 12 ++++++++ src/test/ui/error-codes/E0199.stderr | 6 ++++ src/test/ui/error-codes/E0200.stderr | 6 ++++ .../ui/traits/safety-trait-impl-cc.stderr | 6 ++++ src/test/ui/traits/safety-trait-impl.stderr | 12 ++++++++ 7 files changed, 84 insertions(+) diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index e45fb5fe41c0..25b2ed76adf2 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -26,6 +26,12 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { "implementing the trait `{}` is not unsafe", trait_ref.print_only_trait_path() ) + .span_suggestion_verbose( + item.span.with_hi(item.span.lo() + rustc_span::BytePos(7)), + "remove `unsafe` from this trait implementation", + "", + rustc_errors::Applicability::MachineApplicable, + ) .emit(); } @@ -37,6 +43,18 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { "the trait `{}` requires an `unsafe impl` declaration", trait_ref.print_only_trait_path() ) + .note(format!( + "the trait `{}` enforces invariants that the compiler can't check. \ + Review the trait documentation and make sure this implementation \ + upholds those invariants before adding the `unsafe` keyword", + trait_ref.print_only_trait_path() + )) + .span_suggestion_verbose( + item.span.shrink_to_lo(), + "add `unsafe` to this trait implementation", + "unsafe ", + rustc_errors::Applicability::MaybeIncorrect, + ) .emit(); } @@ -48,6 +66,18 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { "requires an `unsafe impl` declaration due to `#[{}]` attribute", attr_name ) + .note(format!( + "the trait `{}` enforces invariants that the compiler can't check. \ + Review the trait documentation and make sure this implementation \ + upholds those invariants before adding the `unsafe` keyword", + trait_ref.print_only_trait_path() + )) + .span_suggestion_verbose( + item.span.shrink_to_lo(), + "add `unsafe` to this trait implementation", + "unsafe ", + rustc_errors::Applicability::MaybeIncorrect, + ) .emit(); } diff --git a/src/test/ui/coherence/coherence-default-trait-impl.stderr b/src/test/ui/coherence/coherence-default-trait-impl.stderr index b08ccb087d91..632018782725 100644 --- a/src/test/ui/coherence/coherence-default-trait-impl.stderr +++ b/src/test/ui/coherence/coherence-default-trait-impl.stderr @@ -3,12 +3,24 @@ error[E0199]: implementing the trait `MySafeTrait` is not unsafe | LL | unsafe impl MySafeTrait for Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove `unsafe` from this trait implementation + | +LL - unsafe impl MySafeTrait for Foo {} +LL + impl MySafeTrait for Foo {} + | error[E0200]: the trait `MyUnsafeTrait` requires an `unsafe impl` declaration --> $DIR/coherence-default-trait-impl.rs:13:1 | LL | impl MyUnsafeTrait for Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the trait `MyUnsafeTrait` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword +help: add `unsafe` to this trait implementation + | +LL | unsafe impl MyUnsafeTrait for Foo {} + | ++++++ error: aborting due to 2 previous errors diff --git a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr index 49e55be1b49e..82169ee01bed 100644 --- a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr +++ b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr @@ -8,6 +8,12 @@ LL | | // (unsafe to access self.1 due to #[may_dangle] on A) LL | | fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); } LL | | } | |_^ + | + = note: the trait `Drop` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword +help: add `unsafe` to this trait implementation + | +LL | unsafe impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt { + | ++++++ error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:27:1 @@ -19,6 +25,12 @@ LL | | // (unsafe to access self.1 due to #[may_dangle] on 'a) LL | | fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); } LL | | } | |_^ + | + = note: the trait `Drop` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword +help: add `unsafe` to this trait implementation + | +LL | unsafe impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> { + | ++++++ error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0199.stderr b/src/test/ui/error-codes/E0199.stderr index 3632d26cd32e..99d808c0d4b1 100644 --- a/src/test/ui/error-codes/E0199.stderr +++ b/src/test/ui/error-codes/E0199.stderr @@ -3,6 +3,12 @@ error[E0199]: implementing the trait `Bar` is not unsafe | LL | unsafe impl Bar for Foo { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove `unsafe` from this trait implementation + | +LL - unsafe impl Bar for Foo { } +LL + impl Bar for Foo { } + | error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0200.stderr b/src/test/ui/error-codes/E0200.stderr index 677271aad445..1fd86aecee17 100644 --- a/src/test/ui/error-codes/E0200.stderr +++ b/src/test/ui/error-codes/E0200.stderr @@ -3,6 +3,12 @@ error[E0200]: the trait `Bar` requires an `unsafe impl` declaration | LL | impl Bar for Foo { } | ^^^^^^^^^^^^^^^^^^^^ + | + = note: the trait `Bar` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword +help: add `unsafe` to this trait implementation + | +LL | unsafe impl Bar for Foo { } + | ++++++ error: aborting due to previous error diff --git a/src/test/ui/traits/safety-trait-impl-cc.stderr b/src/test/ui/traits/safety-trait-impl-cc.stderr index 5a0f8d3b8cac..0b1fb30478ff 100644 --- a/src/test/ui/traits/safety-trait-impl-cc.stderr +++ b/src/test/ui/traits/safety-trait-impl-cc.stderr @@ -7,6 +7,12 @@ LL | | panic!(); LL | | } LL | | } | |_^ + | + = note: the trait `Foo` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword +help: add `unsafe` to this trait implementation + | +LL | unsafe impl lib::Foo for Bar { + | ++++++ error: aborting due to previous error diff --git a/src/test/ui/traits/safety-trait-impl.stderr b/src/test/ui/traits/safety-trait-impl.stderr index fc0f6c693089..721e2b48b954 100644 --- a/src/test/ui/traits/safety-trait-impl.stderr +++ b/src/test/ui/traits/safety-trait-impl.stderr @@ -3,12 +3,24 @@ error[E0200]: the trait `UnsafeTrait` requires an `unsafe impl` declaration | LL | impl UnsafeTrait for u16 { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the trait `UnsafeTrait` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword +help: add `unsafe` to this trait implementation + | +LL | unsafe impl UnsafeTrait for u16 { } + | ++++++ error[E0199]: implementing the trait `SafeTrait` is not unsafe --> $DIR/safety-trait-impl.rs:16:1 | LL | unsafe impl SafeTrait for u32 { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove `unsafe` from this trait implementation + | +LL - unsafe impl SafeTrait for u32 { } +LL + impl SafeTrait for u32 { } + | error: aborting due to 2 previous errors From 1cb46079e493af318a2dc6f97c93c2e0ac7ecd0e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 21 Oct 2022 16:00:43 +0200 Subject: [PATCH 045/171] internal: Properly handle commands in the VSCode client when the server is stopped --- editors/code/src/ctx.ts | 80 +++++++++++++++----- editors/code/src/main.ts | 159 ++++++++++++++++++--------------------- 2 files changed, 136 insertions(+), 103 deletions(-) diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index 75c6d4698c17..044a9470aa94 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -18,6 +18,11 @@ export type Workspace = files: vscode.TextDocument[]; }; +export type CommandFactory = { + enabled: (ctx: Ctx) => Cmd; + disabled?: (ctx: Ctx) => Cmd; +}; + export class Ctx { readonly statusBar: vscode.StatusBarItem; readonly config: Config; @@ -26,31 +31,40 @@ export class Ctx { private _serverPath: string | undefined; private traceOutputChannel: vscode.OutputChannel | undefined; private outputChannel: vscode.OutputChannel | undefined; + private clientSubscriptions: Disposable[]; private state: PersistentState; + private commandFactories: Record; + private commandDisposables: Disposable[]; workspace: Workspace; - constructor(readonly extCtx: vscode.ExtensionContext, workspace: Workspace) { - this.statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); - extCtx.subscriptions.push(this.statusBar); - extCtx.subscriptions.push({ - dispose() { - this.dispose(); - }, - }); + constructor( + readonly extCtx: vscode.ExtensionContext, + workspace: Workspace, + commandFactories: Record + ) { extCtx.subscriptions.push(this); + this.statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); this.statusBar.text = "rust-analyzer"; this.statusBar.tooltip = "ready"; this.statusBar.command = "rust-analyzer.analyzerStatus"; this.statusBar.show(); this.workspace = workspace; + this.clientSubscriptions = []; + this.commandDisposables = []; + this.commandFactories = commandFactories; this.state = new PersistentState(extCtx.globalState); this.config = new Config(extCtx); + + this.updateCommands(); } dispose() { this.config.dispose(); + this.statusBar.dispose(); + void this.disposeClient(); + this.commandDisposables.forEach((disposable) => disposable.dispose()); } clientFetcher() { @@ -63,7 +77,6 @@ export class Ctx { } async getClient() { - // if server path changes -> dispose if (!this.traceOutputChannel) { this.traceOutputChannel = vscode.window.createOutputChannel( "Rust Analyzer Language Server Trace" @@ -118,7 +131,11 @@ export class Ctx { initializationOptions, serverOptions ); - this.client.onNotification(ra.serverStatus, (params) => this.setServerStatus(params)); + this.pushClientCleanup( + this.client.onNotification(ra.serverStatus, (params) => + this.setServerStatus(params) + ) + ); } return this.client; } @@ -127,16 +144,25 @@ export class Ctx { log.info("Activating language client"); const client = await this.getClient(); await client.start(); + this.updateCommands(); return client; } async deactivate() { log.info("Deactivating language client"); await this.client?.stop(); + this.updateCommands(); } - async disposeClient() { - log.info("Deactivating language client"); + async stop() { + log.info("Stopping language client"); + await this.disposeClient(); + this.updateCommands(); + } + + private async disposeClient() { + this.clientSubscriptions?.forEach((disposable) => disposable.dispose()); + this.clientSubscriptions = []; await this.client?.dispose(); this._serverPath = undefined; this.client = undefined; @@ -159,6 +185,25 @@ export class Ctx { return this._serverPath; } + private updateCommands() { + this.commandDisposables.forEach((disposable) => disposable.dispose()); + this.commandDisposables = []; + const fetchFactory = (factory: CommandFactory, fullName: string) => { + return this.client && this.client.isRunning() + ? factory.enabled + : factory.disabled || + ((_) => () => + vscode.window.showErrorMessage( + `command ${fullName} failed: rust-analyzer server is not running` + )); + }; + for (const [name, factory] of Object.entries(this.commandFactories)) { + const fullName = `rust-analyzer.${name}`; + const callback = fetchFactory(factory, fullName)(this); + this.commandDisposables.push(vscode.commands.registerCommand(fullName, callback)); + } + } + setServerStatus(status: ServerStatusParams) { let icon = ""; const statusBar = this.statusBar; @@ -194,16 +239,13 @@ export class Ctx { statusBar.text = `${icon}rust-analyzer`; } - registerCommand(name: string, factory: (ctx: Ctx) => Cmd) { - const fullName = `rust-analyzer.${name}`; - const cmd = factory(this); - const d = vscode.commands.registerCommand(fullName, cmd); - this.pushExtCleanup(d); - } - pushExtCleanup(d: Disposable) { this.extCtx.subscriptions.push(d); } + + private pushClientCleanup(d: Disposable) { + this.clientSubscriptions.push(d); + } } export interface Disposable { diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index fa7dc6fe304e..8c3a676ffb05 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -2,7 +2,7 @@ import * as vscode from "vscode"; import * as lc from "vscode-languageclient/node"; import * as commands from "./commands"; -import { Ctx, Workspace } from "./ctx"; +import { CommandFactory, Ctx, Workspace } from "./ctx"; import { isRustDocument } from "./util"; import { activateTaskProvider } from "./tasks"; import { setContextValue } from "./util"; @@ -57,7 +57,7 @@ export async function activate( } : { kind: "Workspace Folder" }; - const ctx = new Ctx(context, workspace); + const ctx = new Ctx(context, workspace, createCommands()); // VS Code doesn't show a notification when an extension fails to activate // so we do it ourselves. const api = await activateServer(ctx).catch((err) => { @@ -75,8 +75,6 @@ async function activateServer(ctx: Ctx): Promise { ctx.pushExtCleanup(activateTaskProvider(ctx.config)); } - await initCommonContext(ctx); - vscode.workspace.onDidChangeConfiguration( async (_) => { await ctx @@ -91,85 +89,78 @@ async function activateServer(ctx: Ctx): Promise { return ctx.clientFetcher(); } -async function initCommonContext(ctx: Ctx) { - // Register a "dumb" onEnter command for the case where server fails to - // start. - // - // FIXME: refactor command registration code such that commands are - // **always** registered, even if the server does not start. Use API like - // this perhaps? - // - // ```TypeScript - // registerCommand( - // factory: (Ctx) => ((Ctx) => any), - // fallback: () => any = () => vscode.window.showErrorMessage( - // "rust-analyzer is not available" - // ), - // ) - const defaultOnEnter = vscode.commands.registerCommand("rust-analyzer.onEnter", () => - vscode.commands.executeCommand("default:type", { text: "\n" }) - ); - ctx.pushExtCleanup(defaultOnEnter); +function createCommands(): Record { + return { + onEnter: { + enabled: commands.onEnter, + disabled: (_) => () => vscode.commands.executeCommand("default:type", { text: "\n" }), + }, + reload: { + enabled: (ctx) => async () => { + void vscode.window.showInformationMessage("Reloading rust-analyzer..."); + // FIXME: We should re-use the client, that is ctx.deactivate() if none of the configs have changed + await ctx.stop(); + await ctx.activate(); + }, + disabled: (ctx) => async () => { + void vscode.window.showInformationMessage("Reloading rust-analyzer..."); + await ctx.activate(); + }, + }, + startServer: { + enabled: (ctx) => async () => { + await ctx.activate(); + }, + disabled: (ctx) => async () => { + await ctx.activate(); + }, + }, + stopServer: { + enabled: (ctx) => async () => { + // FIXME: We should re-use the client, that is ctx.deactivate() if none of the configs have changed + await ctx.stop(); + ctx.setServerStatus({ + health: "ok", + quiescent: true, + message: "server is not running", + }); + }, + }, - // Commands which invokes manually via command palette, shortcut, etc. - ctx.registerCommand("reload", (_) => async () => { - void vscode.window.showInformationMessage("Reloading rust-analyzer..."); - // FIXME: We should re-use the client, that is ctx.deactivate() if none of the configs have changed - await ctx.disposeClient(); - await ctx.activate(); - }); - - ctx.registerCommand("startServer", (_) => async () => { - await ctx.activate(); - }); - ctx.registerCommand("stopServer", (_) => async () => { - // FIXME: We should re-use the client, that is ctx.deactivate() if none of the configs have changed - await ctx.disposeClient(); - ctx.setServerStatus({ - health: "ok", - quiescent: true, - message: "server is not running", - }); - }); - ctx.registerCommand("analyzerStatus", commands.analyzerStatus); - ctx.registerCommand("memoryUsage", commands.memoryUsage); - ctx.registerCommand("shuffleCrateGraph", commands.shuffleCrateGraph); - ctx.registerCommand("reloadWorkspace", commands.reloadWorkspace); - ctx.registerCommand("matchingBrace", commands.matchingBrace); - ctx.registerCommand("joinLines", commands.joinLines); - ctx.registerCommand("parentModule", commands.parentModule); - ctx.registerCommand("syntaxTree", commands.syntaxTree); - ctx.registerCommand("viewHir", commands.viewHir); - ctx.registerCommand("viewFileText", commands.viewFileText); - ctx.registerCommand("viewItemTree", commands.viewItemTree); - ctx.registerCommand("viewCrateGraph", commands.viewCrateGraph); - ctx.registerCommand("viewFullCrateGraph", commands.viewFullCrateGraph); - ctx.registerCommand("expandMacro", commands.expandMacro); - ctx.registerCommand("run", commands.run); - ctx.registerCommand("copyRunCommandLine", commands.copyRunCommandLine); - ctx.registerCommand("debug", commands.debug); - ctx.registerCommand("newDebugConfig", commands.newDebugConfig); - ctx.registerCommand("openDocs", commands.openDocs); - ctx.registerCommand("openCargoToml", commands.openCargoToml); - ctx.registerCommand("peekTests", commands.peekTests); - ctx.registerCommand("moveItemUp", commands.moveItemUp); - ctx.registerCommand("moveItemDown", commands.moveItemDown); - ctx.registerCommand("cancelFlycheck", commands.cancelFlycheck); - - ctx.registerCommand("ssr", commands.ssr); - ctx.registerCommand("serverVersion", commands.serverVersion); - - // Internal commands which are invoked by the server. - ctx.registerCommand("runSingle", commands.runSingle); - ctx.registerCommand("debugSingle", commands.debugSingle); - ctx.registerCommand("showReferences", commands.showReferences); - ctx.registerCommand("applySnippetWorkspaceEdit", commands.applySnippetWorkspaceEditCommand); - ctx.registerCommand("resolveCodeAction", commands.resolveCodeAction); - ctx.registerCommand("applyActionGroup", commands.applyActionGroup); - ctx.registerCommand("gotoLocation", commands.gotoLocation); - - ctx.registerCommand("linkToCommand", commands.linkToCommand); - - defaultOnEnter.dispose(); - ctx.registerCommand("onEnter", commands.onEnter); + analyzerStatus: { enabled: commands.analyzerStatus }, + memoryUsage: { enabled: commands.memoryUsage }, + shuffleCrateGraph: { enabled: commands.shuffleCrateGraph }, + reloadWorkspace: { enabled: commands.reloadWorkspace }, + matchingBrace: { enabled: commands.matchingBrace }, + joinLines: { enabled: commands.joinLines }, + parentModule: { enabled: commands.parentModule }, + syntaxTree: { enabled: commands.syntaxTree }, + viewHir: { enabled: commands.viewHir }, + viewFileText: { enabled: commands.viewFileText }, + viewItemTree: { enabled: commands.viewItemTree }, + viewCrateGraph: { enabled: commands.viewCrateGraph }, + viewFullCrateGraph: { enabled: commands.viewFullCrateGraph }, + expandMacro: { enabled: commands.expandMacro }, + run: { enabled: commands.run }, + copyRunCommandLine: { enabled: commands.copyRunCommandLine }, + debug: { enabled: commands.debug }, + newDebugConfig: { enabled: commands.newDebugConfig }, + openDocs: { enabled: commands.openDocs }, + openCargoToml: { enabled: commands.openCargoToml }, + peekTests: { enabled: commands.peekTests }, + moveItemUp: { enabled: commands.moveItemUp }, + moveItemDown: { enabled: commands.moveItemDown }, + cancelFlycheck: { enabled: commands.cancelFlycheck }, + ssr: { enabled: commands.ssr }, + serverVersion: { enabled: commands.serverVersion }, + // Internal commands which are invoked by the server. + applyActionGroup: { enabled: commands.applyActionGroup }, + applySnippetWorkspaceEdit: { enabled: commands.applySnippetWorkspaceEditCommand }, + debugSingle: { enabled: commands.debugSingle }, + gotoLocation: { enabled: commands.gotoLocation }, + linkToCommand: { enabled: commands.linkToCommand }, + resolveCodeAction: { enabled: commands.resolveCodeAction }, + runSingle: { enabled: commands.runSingle }, + showReferences: { enabled: commands.showReferences }, + }; } From 4accf838f6d847c0c93f4c25540446dad0309519 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 22 Oct 2022 03:09:49 +0000 Subject: [PATCH 046/171] Note scope of TAIT more accurately --- .../rustc_error_messages/locales/en-US/hir_analysis.ftl | 2 +- compiler/rustc_hir_analysis/src/collect/type_of.rs | 6 ++++++ compiler/rustc_hir_analysis/src/errors.rs | 1 + src/test/ui/generic-associated-types/issue-87258_a.stderr | 2 +- src/test/ui/lint/inline-trait-and-foreign-items.stderr | 2 +- src/test/ui/lint/no-coverage.stderr | 2 +- src/test/ui/save-analysis/issue-68621.stderr | 2 +- 7 files changed, 12 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl index 357c6900a70e..a5bbd1f7fc24 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl @@ -93,7 +93,7 @@ hir_analysis_expected_default_return_type = expected `()` because of default ret hir_analysis_expected_return_type = expected `{$expected}` because of return type hir_analysis_unconstrained_opaque_type = unconstrained opaque type - .note = `{$name}` must be used in combination with a concrete type within the same module + .note = `{$name}` must be used in combination with a concrete type within the same {$what} hir_analysis_missing_type_params = the type {$parameterCount -> diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 32f359a81581..05ada7879224 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -693,6 +693,12 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T tcx.sess.emit_err(UnconstrainedOpaqueType { span: tcx.def_span(def_id), name: tcx.item_name(tcx.local_parent(def_id).to_def_id()), + what: match tcx.hir().get(scope) { + _ if scope == hir::CRATE_HIR_ID => "module", + Node::Item(hir::Item { kind: hir::ItemKind::Mod(_), .. }) => "module", + Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) => "impl", + _ => "item", + }, }); return tcx.ty_error(); }; diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index aaebbe6398a1..5b41a64dcd8e 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -143,6 +143,7 @@ pub struct UnconstrainedOpaqueType { #[primary_span] pub span: Span, pub name: Symbol, + pub what: &'static str, } pub struct MissingTypeParams { diff --git a/src/test/ui/generic-associated-types/issue-87258_a.stderr b/src/test/ui/generic-associated-types/issue-87258_a.stderr index fa0748a280b6..eae9bd9b16f2 100644 --- a/src/test/ui/generic-associated-types/issue-87258_a.stderr +++ b/src/test/ui/generic-associated-types/issue-87258_a.stderr @@ -4,7 +4,7 @@ error: unconstrained opaque type LL | type FooFuture<'a> = impl Trait1; | ^^^^^^^^^^^ | - = note: `FooFuture` must be used in combination with a concrete type within the same module + = note: `FooFuture` must be used in combination with a concrete type within the same impl error: aborting due to previous error diff --git a/src/test/ui/lint/inline-trait-and-foreign-items.stderr b/src/test/ui/lint/inline-trait-and-foreign-items.stderr index 27399746bed6..2f1fb4c46c08 100644 --- a/src/test/ui/lint/inline-trait-and-foreign-items.stderr +++ b/src/test/ui/lint/inline-trait-and-foreign-items.stderr @@ -67,7 +67,7 @@ error: unconstrained opaque type LL | type U = impl Trait; | ^^^^^^^^^^ | - = note: `U` must be used in combination with a concrete type within the same module + = note: `U` must be used in combination with a concrete type within the same impl error: aborting due to 6 previous errors; 2 warnings emitted diff --git a/src/test/ui/lint/no-coverage.stderr b/src/test/ui/lint/no-coverage.stderr index 8452ccc7a03c..404efbeac1e1 100644 --- a/src/test/ui/lint/no-coverage.stderr +++ b/src/test/ui/lint/no-coverage.stderr @@ -94,7 +94,7 @@ error: unconstrained opaque type LL | type U = impl Trait; | ^^^^^^^^^^ | - = note: `U` must be used in combination with a concrete type within the same module + = note: `U` must be used in combination with a concrete type within the same impl error: aborting due to 7 previous errors; 6 warnings emitted diff --git a/src/test/ui/save-analysis/issue-68621.stderr b/src/test/ui/save-analysis/issue-68621.stderr index 4a4bf9a6996b..4452ee7915ba 100644 --- a/src/test/ui/save-analysis/issue-68621.stderr +++ b/src/test/ui/save-analysis/issue-68621.stderr @@ -4,7 +4,7 @@ error: unconstrained opaque type LL | type Future = impl Trait; | ^^^^^^^^^^ | - = note: `Future` must be used in combination with a concrete type within the same module + = note: `Future` must be used in combination with a concrete type within the same impl error: aborting due to previous error From 988e75bb65f688d76f4f80e0fb72ef21e831d0b0 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 6 Apr 2022 11:21:10 +1000 Subject: [PATCH 047/171] Stabilize arbitrary_enum_discriminant, take 2 --- compiler/rustc_ast_passes/src/feature_gate.rs | 62 +------------------ .../src/error_codes/E0732.md | 4 -- compiler/rustc_feature/src/accepted.rs | 2 + compiler/rustc_feature/src/active.rs | 2 - .../rustc_hir_analysis/src/check/check.rs | 2 +- .../arbitrary-enum-discriminant.md | 37 ----------- src/test/ui/cast/issue-88621.rs | 2 - .../arbitrary_enum_discriminant-no-repr.rs | 1 - .../arbitrary_enum_discriminant.rs | 2 +- .../enum-discriminant/discriminant_value.rs | 2 +- ...eature-gate-arbitrary_enum_discriminant.rs | 10 --- ...re-gate-arbitrary_enum_discriminant.stderr | 36 ----------- .../issue-70453-generics-in-discr-ice-2.rs | 2 +- .../issue-70453-polymorphic-ctfe.rs | 2 +- .../issue-70509-partial_eq.rs | 2 +- .../issue-70509-partial_eq.stderr | 2 +- .../intrinsics/panic-uninitialized-zeroed.rs | 2 +- src/test/ui/macros/macros-nonfatal-errors.rs | 2 +- src/test/ui/parser/issues/issue-17383.rs | 7 --- src/test/ui/parser/issues/issue-17383.stderr | 15 ----- .../ui/parser/tag-variant-disr-non-nullary.rs | 12 ---- .../tag-variant-disr-non-nullary.stderr | 25 -------- 22 files changed, 12 insertions(+), 221 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md delete mode 100644 src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs delete mode 100644 src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr delete mode 100644 src/test/ui/parser/issues/issue-17383.rs delete mode 100644 src/test/ui/parser/issues/issue-17383.stderr delete mode 100644 src/test/ui/parser/tag-variant-disr-non-nullary.rs delete mode 100644 src/test/ui/parser/tag-variant-disr-non-nullary.stderr diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 0f11c1766528..546010135a72 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -1,7 +1,7 @@ use rustc_ast as ast; use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::{AssocConstraint, AssocConstraintKind, NodeId}; -use rustc_ast::{PatKind, RangeEnd, VariantData}; +use rustc_ast::{PatKind, RangeEnd}; use rustc_errors::{struct_span_err, Applicability, StashKey}; use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP}; use rustc_session::parse::{feature_err, feature_err_issue, feature_warn}; @@ -116,46 +116,6 @@ impl<'a> PostExpansionVisitor<'a> { } } - fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) { - let has_fields = variants.iter().any(|variant| match variant.data { - VariantData::Tuple(..) | VariantData::Struct(..) => true, - VariantData::Unit(..) => false, - }); - - let discriminant_spans = variants - .iter() - .filter(|variant| match variant.data { - VariantData::Tuple(..) | VariantData::Struct(..) => false, - VariantData::Unit(..) => true, - }) - .filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span)) - .collect::>(); - - if !discriminant_spans.is_empty() && has_fields { - let mut err = feature_err( - &self.sess.parse_sess, - sym::arbitrary_enum_discriminant, - discriminant_spans.clone(), - "custom discriminant values are not allowed in enums with tuple or struct variants", - ); - for sp in discriminant_spans { - err.span_label(sp, "disallowed custom discriminant"); - } - for variant in variants.iter() { - match &variant.data { - VariantData::Struct(..) => { - err.span_label(variant.span, "struct variant defined here"); - } - VariantData::Tuple(..) => { - err.span_label(variant.span, "tuple variant defined here"); - } - VariantData::Unit(..) => {} - } - } - err.emit(); - } - } - /// Feature gate `impl Trait` inside `type Alias = $type_expr;`. fn check_impl_trait(&self, ty: &ast::Ty) { struct ImplTraitVisitor<'a> { @@ -273,26 +233,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } - ast::ItemKind::Enum(ast::EnumDef { ref variants, .. }, ..) => { - for variant in variants { - match (&variant.data, &variant.disr_expr) { - (ast::VariantData::Unit(..), _) => {} - (_, Some(disr_expr)) => gate_feature_post!( - &self, - arbitrary_enum_discriminant, - disr_expr.value.span, - "discriminants on non-unit variants are experimental" - ), - _ => {} - } - } - - let has_feature = self.features.arbitrary_enum_discriminant; - if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) { - self.maybe_report_invalid_custom_discriminants(&variants); - } - } - ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, ref of_trait, .. }) => { if let ast::ImplPolarity::Negative(span) = polarity { gate_feature_post!( diff --git a/compiler/rustc_error_codes/src/error_codes/E0732.md b/compiler/rustc_error_codes/src/error_codes/E0732.md index 7347e6654c5b..9536fdbf0df8 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0732.md +++ b/compiler/rustc_error_codes/src/error_codes/E0732.md @@ -3,8 +3,6 @@ An `enum` with a discriminant must specify a `#[repr(inttype)]`. Erroneous code example: ```compile_fail,E0732 -#![feature(arbitrary_enum_discriminant)] - enum Enum { // error! Unit = 1, Tuple() = 2, @@ -20,8 +18,6 @@ is a well-defined way to extract a variant's discriminant from a value; for instance: ``` -#![feature(arbitrary_enum_discriminant)] - #[repr(u8)] enum Enum { Unit = 3, diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 54bf5a2c34b8..db289a64046a 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -53,6 +53,8 @@ declare_features! ( (accepted, abi_sysv64, "1.24.0", Some(36167), None), /// Allows using ADX intrinsics from `core::arch::{x86, x86_64}`. (accepted, adx_target_feature, "1.61.0", Some(44839), None), + /// Allows explicit discriminants on non-unit enum variants. + (accepted, arbitrary_enum_discriminant, "CURRENT_RUSTC_VERSION", Some(60553), None), /// Allows using `sym` operands in inline assembly. (accepted, asm_sym, "CURRENT_RUSTC_VERSION", Some(93333), None), /// Allows the definition of associated constants in `trait` or `impl` blocks. diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 1b8d683b1336..4facb6140a30 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -292,8 +292,6 @@ declare_features! ( (incomplete, adt_const_params, "1.56.0", Some(95174), None), /// Allows defining an `#[alloc_error_handler]`. (active, alloc_error_handler, "1.29.0", Some(51540), None), - /// Allows explicit discriminants on non-unit enum variants. - (active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None), /// Allows trait methods with arbitrary self types. (active, arbitrary_self_types, "1.23.0", Some(44874), None), /// Allows using `const` operands in inline assembly. diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index a1faf8025195..b302cee4816f 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1180,7 +1180,7 @@ fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, vs: &'tcx [hir::Variant<'tcx>], def_id: L } } - if tcx.adt_def(def_id).repr().int.is_none() && tcx.features().arbitrary_enum_discriminant { + if tcx.adt_def(def_id).repr().int.is_none() { let is_unit = |var: &hir::Variant<'_>| matches!(var.data, hir::VariantData::Unit(..)); let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some(); diff --git a/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md b/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md deleted file mode 100644 index e0bb782270e2..000000000000 --- a/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md +++ /dev/null @@ -1,37 +0,0 @@ -# `arbitrary_enum_discriminant` - -The tracking issue for this feature is: [#60553] - -[#60553]: https://github.com/rust-lang/rust/issues/60553 - ------------------------- - -The `arbitrary_enum_discriminant` feature permits tuple-like and -struct-like enum variants with `#[repr()]` to have explicit discriminants. - -## Examples - -```rust -#![feature(arbitrary_enum_discriminant)] - -#[allow(dead_code)] -#[repr(u8)] -enum Enum { - Unit = 3, - Tuple(u16) = 2, - Struct { - a: u8, - b: u16, - } = 1, -} - -impl Enum { - fn tag(&self) -> u8 { - unsafe { *(self as *const Self as *const u8) } - } -} - -assert_eq!(3, Enum::Unit.tag()); -assert_eq!(2, Enum::Tuple(5).tag()); -assert_eq!(1, Enum::Struct{a: 7, b: 11}.tag()); -``` diff --git a/src/test/ui/cast/issue-88621.rs b/src/test/ui/cast/issue-88621.rs index 9242b80e2293..1679793ee683 100644 --- a/src/test/ui/cast/issue-88621.rs +++ b/src/test/ui/cast/issue-88621.rs @@ -1,5 +1,3 @@ -#![feature(arbitrary_enum_discriminant)] - #[repr(u8)] enum Kind2 { Foo() = 1, diff --git a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs index 4da7b5ab24b2..a6e5f70fdefa 100644 --- a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs +++ b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs @@ -1,5 +1,4 @@ #![crate_type="lib"] -#![feature(arbitrary_enum_discriminant)] enum Enum { //~^ ERROR `#[repr(inttype)]` must be specified diff --git a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs index ccc423e4a194..83e74a6e685a 100644 --- a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs +++ b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs @@ -1,5 +1,5 @@ // run-pass -#![feature(arbitrary_enum_discriminant, test)] +#![feature(test)] extern crate test; diff --git a/src/test/ui/enum-discriminant/discriminant_value.rs b/src/test/ui/enum-discriminant/discriminant_value.rs index 65ab411dbcbe..f3dfac298ad7 100644 --- a/src/test/ui/enum-discriminant/discriminant_value.rs +++ b/src/test/ui/enum-discriminant/discriminant_value.rs @@ -1,6 +1,6 @@ // run-pass #![allow(stable_features)] -#![feature(arbitrary_enum_discriminant, core, core_intrinsics)] +#![feature(core, core_intrinsics)] extern crate core; use core::intrinsics::discriminant_value; diff --git a/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs b/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs deleted file mode 100644 index 3e90af4d36af..000000000000 --- a/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![crate_type="lib"] - -enum Enum { - Unit = 1, - //~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants - Tuple() = 2, - //~^ ERROR discriminants on non-unit variants are experimental - Struct{} = 3, - //~^ ERROR discriminants on non-unit variants are experimental -} diff --git a/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr b/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr deleted file mode 100644 index b5f61e6e991d..000000000000 --- a/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr +++ /dev/null @@ -1,36 +0,0 @@ -error[E0658]: discriminants on non-unit variants are experimental - --> $DIR/feature-gate-arbitrary_enum_discriminant.rs:6:13 - | -LL | Tuple() = 2, - | ^ - | - = note: see issue #60553 for more information - = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable - -error[E0658]: discriminants on non-unit variants are experimental - --> $DIR/feature-gate-arbitrary_enum_discriminant.rs:8:14 - | -LL | Struct{} = 3, - | ^ - | - = note: see issue #60553 for more information - = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable - -error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants - --> $DIR/feature-gate-arbitrary_enum_discriminant.rs:4:10 - | -LL | Unit = 1, - | ^ disallowed custom discriminant -LL | -LL | Tuple() = 2, - | ----------- tuple variant defined here -LL | -LL | Struct{} = 3, - | ------------ struct variant defined here - | - = note: see issue #60553 for more information - = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs index f927dd189038..ad9fcc25b412 100644 --- a/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs +++ b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs @@ -1,4 +1,4 @@ -#![feature(arbitrary_enum_discriminant, core_intrinsics)] +#![feature(core_intrinsics)] extern crate core; use core::intrinsics::discriminant_value; diff --git a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs index e62582fb5161..42a062239d34 100644 --- a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs +++ b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs @@ -1,4 +1,4 @@ -#![feature(arbitrary_enum_discriminant, core_intrinsics)] +#![feature(core_intrinsics)] extern crate core; use core::intrinsics::discriminant_value; diff --git a/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs b/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs index ae389e114664..3adac7b72621 100644 --- a/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs +++ b/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs @@ -1,5 +1,5 @@ // run-pass -#![feature(repr128, arbitrary_enum_discriminant)] +#![feature(repr128)] //~^ WARN the feature `repr128` is incomplete #[derive(PartialEq, Debug)] diff --git a/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr b/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr index ac93badf2156..2eef930c3943 100644 --- a/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr +++ b/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr @@ -1,7 +1,7 @@ warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-70509-partial_eq.rs:2:12 | -LL | #![feature(repr128, arbitrary_enum_discriminant)] +LL | #![feature(repr128)] | ^^^^^^^ | = note: see issue #56071 for more information diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs index ae44ffd29bd5..ec3860a322fc 100644 --- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs +++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs @@ -7,7 +7,7 @@ // This test checks panic emitted from `mem::{uninitialized,zeroed}`. -#![feature(never_type, arbitrary_enum_discriminant)] +#![feature(never_type)] #![allow(deprecated, invalid_value)] use std::{ diff --git a/src/test/ui/macros/macros-nonfatal-errors.rs b/src/test/ui/macros/macros-nonfatal-errors.rs index 140cc5b0fd80..ab14c35893d0 100644 --- a/src/test/ui/macros/macros-nonfatal-errors.rs +++ b/src/test/ui/macros/macros-nonfatal-errors.rs @@ -4,7 +4,7 @@ // immediately, so that we get more errors listed at a time. #![feature(trace_macros, concat_idents)] -#![feature(stmt_expr_attributes, arbitrary_enum_discriminant)] +#![feature(stmt_expr_attributes)] use std::arch::asm; diff --git a/src/test/ui/parser/issues/issue-17383.rs b/src/test/ui/parser/issues/issue-17383.rs deleted file mode 100644 index 7bf0e64f2c0a..000000000000 --- a/src/test/ui/parser/issues/issue-17383.rs +++ /dev/null @@ -1,7 +0,0 @@ -enum X { - A = 3, - //~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants - B(usize) -} - -fn main() {} diff --git a/src/test/ui/parser/issues/issue-17383.stderr b/src/test/ui/parser/issues/issue-17383.stderr deleted file mode 100644 index 265d6e148661..000000000000 --- a/src/test/ui/parser/issues/issue-17383.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants - --> $DIR/issue-17383.rs:2:9 - | -LL | A = 3, - | ^ disallowed custom discriminant -LL | -LL | B(usize) - | -------- tuple variant defined here - | - = note: see issue #60553 for more information - = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/parser/tag-variant-disr-non-nullary.rs b/src/test/ui/parser/tag-variant-disr-non-nullary.rs deleted file mode 100644 index a9cfdd549c75..000000000000 --- a/src/test/ui/parser/tag-variant-disr-non-nullary.rs +++ /dev/null @@ -1,12 +0,0 @@ -enum Color { - Red = 0xff0000, - //~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants - Green = 0x00ff00, - Blue = 0x0000ff, - Black = 0x000000, - White = 0xffffff, - Other(usize), - Other2(usize, usize), -} - -fn main() {} diff --git a/src/test/ui/parser/tag-variant-disr-non-nullary.stderr b/src/test/ui/parser/tag-variant-disr-non-nullary.stderr deleted file mode 100644 index 79f044a0675b..000000000000 --- a/src/test/ui/parser/tag-variant-disr-non-nullary.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants - --> $DIR/tag-variant-disr-non-nullary.rs:2:11 - | -LL | Red = 0xff0000, - | ^^^^^^^^ disallowed custom discriminant -LL | -LL | Green = 0x00ff00, - | ^^^^^^^^ disallowed custom discriminant -LL | Blue = 0x0000ff, - | ^^^^^^^^ disallowed custom discriminant -LL | Black = 0x000000, - | ^^^^^^^^ disallowed custom discriminant -LL | White = 0xffffff, - | ^^^^^^^^ disallowed custom discriminant -LL | Other(usize), - | ------------ tuple variant defined here -LL | Other2(usize, usize), - | -------------------- tuple variant defined here - | - = note: see issue #60553 for more information - = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. From b614b0e64c2990c60207aa748957728d644a5a8d Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 6 Apr 2022 13:45:30 +1000 Subject: [PATCH 048/171] Bless tests --- src/test/ui/cast/issue-88621.stderr | 2 +- .../arbitrary_enum_discriminant-no-repr.stderr | 2 +- src/test/ui/transmutability/enums/should_order_correctly.rs | 1 - .../ui/transmutability/enums/should_respect_endianness.rs | 1 - .../ui/transmutability/enums/should_respect_endianness.stderr | 4 ++-- 5 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/test/ui/cast/issue-88621.stderr b/src/test/ui/cast/issue-88621.stderr index e96d86651523..886145c1bafe 100644 --- a/src/test/ui/cast/issue-88621.stderr +++ b/src/test/ui/cast/issue-88621.stderr @@ -1,5 +1,5 @@ error[E0605]: non-primitive cast: `Kind2` as `u8` - --> $DIR/issue-88621.rs:11:13 + --> $DIR/issue-88621.rs:9:13 | LL | let _ = Kind2::Foo() as u8; | ^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object diff --git a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr index 803bb06fcc21..8cee74696295 100644 --- a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr +++ b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr @@ -1,5 +1,5 @@ error[E0732]: `#[repr(inttype)]` must be specified - --> $DIR/arbitrary_enum_discriminant-no-repr.rs:4:1 + --> $DIR/arbitrary_enum_discriminant-no-repr.rs:3:1 | LL | enum Enum { | ^^^^^^^^^ diff --git a/src/test/ui/transmutability/enums/should_order_correctly.rs b/src/test/ui/transmutability/enums/should_order_correctly.rs index b753cf0e62d5..1335cc9d2b17 100644 --- a/src/test/ui/transmutability/enums/should_order_correctly.rs +++ b/src/test/ui/transmutability/enums/should_order_correctly.rs @@ -2,7 +2,6 @@ //! The payloads of an enum variant should be ordered after its tag. #![crate_type = "lib"] -#![feature(arbitrary_enum_discriminant)] #![feature(transmutability)] #![allow(dead_code)] diff --git a/src/test/ui/transmutability/enums/should_respect_endianness.rs b/src/test/ui/transmutability/enums/should_respect_endianness.rs index 19ff69005003..f3567b405f40 100644 --- a/src/test/ui/transmutability/enums/should_respect_endianness.rs +++ b/src/test/ui/transmutability/enums/should_respect_endianness.rs @@ -2,7 +2,6 @@ //! an enum with a multi-byte tag. #![crate_type = "lib"] -#![feature(arbitrary_enum_discriminant)] #![feature(transmutability)] #![allow(dead_code)] diff --git a/src/test/ui/transmutability/enums/should_respect_endianness.stderr b/src/test/ui/transmutability/enums/should_respect_endianness.stderr index fcb70813bd96..0845a5edf32e 100644 --- a/src/test/ui/transmutability/enums/should_respect_endianness.stderr +++ b/src/test/ui/transmutability/enums/should_respect_endianness.stderr @@ -1,12 +1,12 @@ error[E0277]: `Src` cannot be safely transmuted into `Unexpected` in the defining scope of `assert::Context`. - --> $DIR/should_respect_endianness.rs:37:36 + --> $DIR/should_respect_endianness.rs:36:36 | LL | assert::is_transmutable::(); | ^^^^^^^^^^ `Src` cannot be safely transmuted into `Unexpected` in the defining scope of `assert::Context`. | = help: the trait `BikeshedIntrinsicFrom` is not implemented for `Unexpected` note: required by a bound in `is_transmutable` - --> $DIR/should_respect_endianness.rs:15:14 + --> $DIR/should_respect_endianness.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this From 7ee72256eba49faa53b6885460b5769279893885 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 22 Oct 2022 13:50:02 +0200 Subject: [PATCH 049/171] scip: minor clean-ups Avoids a couple redundant hash map lookups and so. --- crates/rust-analyzer/src/cli/scip.rs | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/crates/rust-analyzer/src/cli/scip.rs b/crates/rust-analyzer/src/cli/scip.rs index 2c29b3ee3a6f..d70bc3f195f3 100644 --- a/crates/rust-analyzer/src/cli/scip.rs +++ b/crates/rust-analyzer/src/cli/scip.rs @@ -75,7 +75,7 @@ impl flags::Scip { let mut symbols_emitted: HashSet = HashSet::default(); let mut tokens_to_symbol: HashMap = HashMap::new(); - for file in si.files { + for StaticIndexedFile { file_id, tokens, .. } in si.files { let mut local_count = 0; let mut new_local_symbol = || { let new_symbol = scip::types::Symbol::new_local(local_count); @@ -84,7 +84,6 @@ impl flags::Scip { new_symbol }; - let StaticIndexedFile { file_id, tokens, .. } = file; let relative_path = match get_relative_filepath(&vfs, &rootpath, file_id) { Some(relative_path) => relative_path, None => continue, @@ -107,28 +106,23 @@ impl flags::Scip { let mut occurrence = scip_types::Occurrence::default(); occurrence.range = text_range_to_scip_range(&line_index, range); - occurrence.symbol = match tokens_to_symbol.get(&id) { - Some(symbol) => symbol.clone(), - None => { + occurrence.symbol = tokens_to_symbol + .entry(id) + .or_insert_with(|| { let symbol = match &token.moniker { Some(moniker) => moniker_to_symbol(&moniker), None => new_local_symbol(), }; - - let symbol = scip::symbol::format_symbol(symbol); - tokens_to_symbol.insert(id, symbol.clone()); - symbol - } - }; + scip::symbol::format_symbol(symbol) + }) + .clone(); if let Some(def) = token.definition { if def.range == range { occurrence.symbol_roles |= scip_types::SymbolRole::Definition as i32; } - if !symbols_emitted.contains(&id) { - symbols_emitted.insert(id); - + if symbols_emitted.insert(id) { let mut symbol_info = scip_types::SymbolInformation::default(); symbol_info.symbol = occurrence.symbol.clone(); if let Some(hover) = &token.hover { From bd49d019063478f2f159165734600ee7c6e72ae7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 22 Oct 2022 14:04:47 +0200 Subject: [PATCH 050/171] ide: Remove unnecessary continue. --- crates/ide/src/static_index.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index 9e5eb909508f..27ad1a948d13 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -210,9 +210,7 @@ fn get_definition(sema: &Semantics<'_, RootDatabase>, token: SyntaxToken) -> Opt let def = IdentClass::classify_token(sema, &token).map(IdentClass::definitions_no_ops); if let Some(&[x]) = def.as_deref() { return Some(x); - } else { - continue; - }; + } } None } From ec6d72baa104fd5428af2d5b6c09ed5546a8af40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Fri, 21 Oct 2022 22:04:43 +0200 Subject: [PATCH 051/171] scip: Rewrite tests to be closer to what we actually do. It's also less code. --- crates/rust-analyzer/src/cli/scip.rs | 85 ++++++++++------------------ 1 file changed, 30 insertions(+), 55 deletions(-) diff --git a/crates/rust-analyzer/src/cli/scip.rs b/crates/rust-analyzer/src/cli/scip.rs index d70bc3f195f3..8b77ccde0ee4 100644 --- a/crates/rust-analyzer/src/cli/scip.rs +++ b/crates/rust-analyzer/src/cli/scip.rs @@ -8,8 +8,8 @@ use std::{ use crate::line_index::{LineEndings, LineIndex, OffsetEncoding}; use hir::Name; use ide::{ - LineCol, MonikerDescriptorKind, MonikerResult, StaticIndex, StaticIndexedFile, TextRange, - TokenId, + LineCol, MonikerDescriptorKind, StaticIndex, StaticIndexedFile, TextRange, TokenId, + TokenStaticData, }; use ide_db::LineIndexDatabase; use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace}; @@ -109,10 +109,7 @@ impl flags::Scip { occurrence.symbol = tokens_to_symbol .entry(id) .or_insert_with(|| { - let symbol = match &token.moniker { - Some(moniker) => moniker_to_symbol(&moniker), - None => new_local_symbol(), - }; + let symbol = token_to_symbol(&token).unwrap_or_else(&mut new_local_symbol); scip::symbol::format_symbol(symbol) }) .clone(); @@ -201,9 +198,11 @@ fn new_descriptor(name: Name, suffix: scip_types::descriptor::Suffix) -> scip_ty /// /// Only returns a Symbol when it's a non-local symbol. /// So if the visibility isn't outside of a document, then it will return None -fn moniker_to_symbol(moniker: &MonikerResult) -> scip_types::Symbol { +fn token_to_symbol(token: &TokenStaticData) -> Option { use scip_types::descriptor::Suffix::*; + let moniker = token.moniker.as_ref()?; + let package_name = moniker.package_information.name.clone(); let version = moniker.package_information.version.clone(); let descriptors = moniker @@ -227,7 +226,7 @@ fn moniker_to_symbol(moniker: &MonikerResult) -> scip_types::Symbol { }) .collect(); - scip_types::Symbol { + Some(scip_types::Symbol { scheme: "rust-analyzer".into(), package: Some(scip_types::Package { manager: "cargo".to_string(), @@ -238,19 +237,15 @@ fn moniker_to_symbol(moniker: &MonikerResult) -> scip_types::Symbol { .into(), descriptors, ..Default::default() - } + }) } #[cfg(test)] mod test { use super::*; - use hir::Semantics; - use ide::{AnalysisHost, FilePosition}; - use ide_db::defs::IdentClass; - use ide_db::{base_db::fixture::ChangeFixture, helpers::pick_best_token}; + use ide::{AnalysisHost, FilePosition, StaticIndex, TextSize}; + use ide_db::base_db::fixture::ChangeFixture; use scip::symbol::format_symbol; - use syntax::SyntaxKind::*; - use syntax::{AstNode, T}; fn position(ra_fixture: &str) -> (AnalysisHost, FilePosition) { let mut host = AnalysisHost::default(); @@ -267,53 +262,33 @@ mod test { fn check_symbol(ra_fixture: &str, expected: &str) { let (host, position) = position(ra_fixture); + let analysis = host.analysis(); + let si = StaticIndex::compute(&analysis); + let FilePosition { file_id, offset } = position; - let db = host.raw_database(); - let sema = &Semantics::new(db); - let file = sema.parse(file_id).syntax().clone(); - let original_token = pick_best_token(file.token_at_offset(offset), |kind| match kind { - IDENT - | INT_NUMBER - | LIFETIME_IDENT - | T![self] - | T![super] - | T![crate] - | T![Self] - | COMMENT => 2, - kind if kind.is_trivia() => 0, - _ => 1, - }) - .expect("OK OK"); - - let navs = sema - .descend_into_macros(original_token.clone()) - .into_iter() - .filter_map(|token| { - IdentClass::classify_token(sema, &token).map(IdentClass::definitions).map(|it| { - it.into_iter().flat_map(|def| { - let module = def.module(db).unwrap(); - let current_crate = module.krate(); - - match MonikerResult::from_def(sema.db, def, current_crate) { - Some(moniker_result) => Some(moniker_to_symbol(&moniker_result)), - None => None, - } - }) - }) - }) - .flatten() - .collect::>(); + let mut found_symbol = None; + for file in &si.files { + if file.file_id != file_id { + continue; + } + for &(range, id) in &file.tokens { + if range.contains(offset - TextSize::from(1)) { + let token = si.tokens.get(id).unwrap(); + found_symbol = token_to_symbol(token); + break; + } + } + } if expected == "" { - assert_eq!(0, navs.len(), "must have no symbols {:?}", navs); + assert!(found_symbol.is_none(), "must have no symbols {:?}", found_symbol); return; } - assert_eq!(1, navs.len(), "must have one symbol {:?}", navs); - - let res = navs.get(0).unwrap(); - let formatted = format_symbol(res.clone()); + assert!(found_symbol.is_some(), "must have one symbol {:?}", found_symbol); + let res = found_symbol.unwrap(); + let formatted = format_symbol(res); assert_eq!(formatted, expected); } From 6459d7f817ddb91fa2bdc4de8ff61e7905177686 Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Sat, 22 Oct 2022 17:49:38 +0900 Subject: [PATCH 052/171] Support const generics for builtin derive macro --- .../builtin_derive_macro.rs | 36 +++++--- crates/hir-expand/src/builtin_derive_macro.rs | 86 ++++++++----------- 2 files changed, 62 insertions(+), 60 deletions(-) diff --git a/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs b/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs index 6819e9114a02..fafcde25ae70 100644 --- a/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs +++ b/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs @@ -12,11 +12,11 @@ fn test_copy_expand_simple() { #[derive(Copy)] struct Foo; "#, - expect![[r##" + expect![[r#" #[derive(Copy)] struct Foo; -impl < > core::marker::Copy for Foo< > {}"##]], +impl < > core::marker::Copy for Foo< > {}"#]], ); } @@ -33,7 +33,7 @@ macro Copy {} #[derive(Copy)] struct Foo; "#, - expect![[r##" + expect![[r#" #[rustc_builtin_macro] macro derive {} #[rustc_builtin_macro] @@ -41,7 +41,7 @@ macro Copy {} #[derive(Copy)] struct Foo; -impl < > crate ::marker::Copy for Foo< > {}"##]], +impl < > crate ::marker::Copy for Foo< > {}"#]], ); } @@ -53,11 +53,11 @@ fn test_copy_expand_with_type_params() { #[derive(Copy)] struct Foo; "#, - expect![[r##" + expect![[r#" #[derive(Copy)] struct Foo; -impl core::marker::Copy for Foo {}"##]], +impl core::marker::Copy for Foo {}"#]], ); } @@ -70,11 +70,11 @@ fn test_copy_expand_with_lifetimes() { #[derive(Copy)] struct Foo; "#, - expect![[r##" + expect![[r#" #[derive(Copy)] struct Foo; -impl core::marker::Copy for Foo {}"##]], +impl core::marker::Copy for Foo {}"#]], ); } @@ -86,10 +86,26 @@ fn test_clone_expand() { #[derive(Clone)] struct Foo; "#, - expect![[r##" + expect![[r#" #[derive(Clone)] struct Foo; -impl core::clone::Clone for Foo {}"##]], +impl core::clone::Clone for Foo {}"#]], + ); +} + +#[test] +fn test_clone_expand_with_const_generics() { + check( + r#" +//- minicore: derive, clone +#[derive(Clone)] +struct Foo(u32); +"#, + expect![[r#" +#[derive(Clone)] +struct Foo(u32); + +impl core::clone::Clone for Foo {}"#]], ); } diff --git a/crates/hir-expand/src/builtin_derive_macro.rs b/crates/hir-expand/src/builtin_derive_macro.rs index 79989bc2e38b..8966047c9b25 100644 --- a/crates/hir-expand/src/builtin_derive_macro.rs +++ b/crates/hir-expand/src/builtin_derive_macro.rs @@ -60,7 +60,8 @@ pub fn find_builtin_derive(ident: &name::Name) -> Option struct BasicAdtInfo { name: tt::Ident, - type_or_const_params: usize, + /// `Some(ty)` if it's a const param of type `ty`, `None` if it's a type param. + param_types: Vec>, } fn parse_adt(tt: &tt::Subtree) -> Result { @@ -92,50 +93,22 @@ fn parse_adt(tt: &tt::Subtree) -> Result { let name_token_id = token_map.token_by_range(name.syntax().text_range()).unwrap_or_else(TokenId::unspecified); let name_token = tt::Ident { id: name_token_id, text: name.text().into() }; - let type_or_const_params = - params.map_or(0, |type_param_list| type_param_list.type_or_const_params().count()); - Ok(BasicAdtInfo { name: name_token, type_or_const_params }) -} - -fn make_type_args(n: usize, bound: Vec) -> Vec { - let mut result = Vec::::with_capacity(n * 2); - result.push( - tt::Leaf::Punct(tt::Punct { - char: '<', - spacing: tt::Spacing::Alone, - id: tt::TokenId::unspecified(), + let param_types = params + .into_iter() + .flat_map(|param_list| param_list.type_or_const_params()) + .map(|param| { + if let ast::TypeOrConstParam::Const(param) = param { + let ty = param + .ty() + .map(|ty| mbe::syntax_node_to_token_tree(ty.syntax()).0) + .unwrap_or_default(); + Some(ty) + } else { + None + } }) - .into(), - ); - for i in 0..n { - if i > 0 { - result.push( - tt::Leaf::Punct(tt::Punct { - char: ',', - spacing: tt::Spacing::Alone, - id: tt::TokenId::unspecified(), - }) - .into(), - ); - } - result.push( - tt::Leaf::Ident(tt::Ident { - id: tt::TokenId::unspecified(), - text: format!("T{}", i).into(), - }) - .into(), - ); - result.extend(bound.iter().cloned()); - } - result.push( - tt::Leaf::Punct(tt::Punct { - char: '>', - spacing: tt::Spacing::Alone, - id: tt::TokenId::unspecified(), - }) - .into(), - ); - result + .collect(); + Ok(BasicAdtInfo { name: name_token, param_types }) } fn expand_simple_derive(tt: &tt::Subtree, trait_path: tt::Subtree) -> ExpandResult { @@ -143,14 +116,27 @@ fn expand_simple_derive(tt: &tt::Subtree, trait_path: tt::Subtree) -> ExpandResu Ok(info) => info, Err(e) => return ExpandResult::only_err(e), }; + let (params, args): (Vec<_>, Vec<_>) = info + .param_types + .into_iter() + .enumerate() + .map(|(idx, param_ty)| { + let ident = tt::Leaf::Ident(tt::Ident { + id: tt::TokenId::unspecified(), + text: format!("T{idx}").into(), + }); + let ident_ = ident.clone(); + if let Some(ty) = param_ty { + (quote! { const #ident : #ty , }, quote! { #ident_ , }) + } else { + let bound = trait_path.clone(); + (quote! { #ident : #bound , }, quote! { #ident_ , }) + } + }) + .unzip(); let name = info.name; - let trait_path_clone = trait_path.token_trees.clone(); - let bound = (quote! { : ##trait_path_clone }).token_trees; - let type_params = make_type_args(info.type_or_const_params, bound); - let type_args = make_type_args(info.type_or_const_params, Vec::new()); - let trait_path = trait_path.token_trees; let expanded = quote! { - impl ##type_params ##trait_path for #name ##type_args {} + impl < ##params > #trait_path for #name < ##args > {} }; ExpandResult::ok(expanded) } From def755edab084e971394e9d9ba929e205e9a1baa Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 22 Oct 2022 17:48:31 +0000 Subject: [PATCH 053/171] Clean middle RPITITs correctly in rustdoc --- src/librustdoc/clean/mod.rs | 122 ++++++++++-------- src/test/rustdoc/async-trait.rs | 16 +++ src/test/rustdoc/auxiliary/async-trait-dep.rs | 9 ++ 3 files changed, 94 insertions(+), 53 deletions(-) create mode 100644 src/test/rustdoc/async-trait.rs create mode 100644 src/test/rustdoc/auxiliary/async-trait-dep.rs diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 13d63ffa0ee3..6947e8e8e25a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -415,6 +415,16 @@ fn clean_projection<'tcx>( cx: &mut DocContext<'tcx>, def_id: Option, ) -> Type { + if cx.tcx.def_kind(ty.item_def_id) == DefKind::ImplTraitPlaceholder { + let bounds = cx + .tcx + .explicit_item_bounds(ty.item_def_id) + .iter() + .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.substs)) + .collect::>(); + return clean_middle_opaque_bounds(cx, bounds); + } + let trait_ = clean_trait_ref_with_bindings(cx, ty.trait_ref(cx.tcx), ThinVec::new()); let self_type = clean_middle_ty(ty.self_ty(), cx, None); let self_def_id = if let Some(def_id) = def_id { @@ -1715,59 +1725,7 @@ pub(crate) fn clean_middle_ty<'tcx>( .iter() .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, substs)) .collect::>(); - let mut regions = vec![]; - let mut has_sized = false; - let mut bounds = bounds - .iter() - .filter_map(|bound| { - let bound_predicate = bound.kind(); - let trait_ref = match bound_predicate.skip_binder() { - ty::PredicateKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref), - ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => { - if let Some(r) = clean_middle_region(reg) { - regions.push(GenericBound::Outlives(r)); - } - return None; - } - _ => return None, - }; - - if let Some(sized) = cx.tcx.lang_items().sized_trait() { - if trait_ref.def_id() == sized { - has_sized = true; - return None; - } - } - - let bindings: ThinVec<_> = bounds - .iter() - .filter_map(|bound| { - if let ty::PredicateKind::Projection(proj) = bound.kind().skip_binder() - { - if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() { - Some(TypeBinding { - assoc: projection_to_path_segment(proj.projection_ty, cx), - kind: TypeBindingKind::Equality { - term: clean_middle_term(proj.term, cx), - }, - }) - } else { - None - } - } else { - None - } - }) - .collect(); - - Some(clean_poly_trait_ref_with_bindings(cx, trait_ref, bindings)) - }) - .collect::>(); - bounds.extend(regions); - if !has_sized && !bounds.is_empty() { - bounds.insert(0, GenericBound::maybe_sized(cx)); - } - ImplTrait(bounds) + clean_middle_opaque_bounds(cx, bounds) } ty::Closure(..) => panic!("Closure"), @@ -1780,6 +1738,64 @@ pub(crate) fn clean_middle_ty<'tcx>( } } +fn clean_middle_opaque_bounds<'tcx>( + cx: &mut DocContext<'tcx>, + bounds: Vec>, +) -> Type { + let mut regions = vec![]; + let mut has_sized = false; + let mut bounds = bounds + .iter() + .filter_map(|bound| { + let bound_predicate = bound.kind(); + let trait_ref = match bound_predicate.skip_binder() { + ty::PredicateKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref), + ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => { + if let Some(r) = clean_middle_region(reg) { + regions.push(GenericBound::Outlives(r)); + } + return None; + } + _ => return None, + }; + + if let Some(sized) = cx.tcx.lang_items().sized_trait() { + if trait_ref.def_id() == sized { + has_sized = true; + return None; + } + } + + let bindings: ThinVec<_> = bounds + .iter() + .filter_map(|bound| { + if let ty::PredicateKind::Projection(proj) = bound.kind().skip_binder() { + if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() { + Some(TypeBinding { + assoc: projection_to_path_segment(proj.projection_ty, cx), + kind: TypeBindingKind::Equality { + term: clean_middle_term(proj.term, cx), + }, + }) + } else { + None + } + } else { + None + } + }) + .collect(); + + Some(clean_poly_trait_ref_with_bindings(cx, trait_ref, bindings)) + }) + .collect::>(); + bounds.extend(regions); + if !has_sized && !bounds.is_empty() { + bounds.insert(0, GenericBound::maybe_sized(cx)); + } + ImplTrait(bounds) +} + pub(crate) fn clean_field<'tcx>(field: &hir::FieldDef<'tcx>, cx: &mut DocContext<'tcx>) -> Item { let def_id = cx.tcx.hir().local_def_id(field.hir_id).to_def_id(); clean_field_with_def_id(def_id, field.ident.name, clean_ty(field.ty, cx), cx) diff --git a/src/test/rustdoc/async-trait.rs b/src/test/rustdoc/async-trait.rs new file mode 100644 index 000000000000..a473e467473e --- /dev/null +++ b/src/test/rustdoc/async-trait.rs @@ -0,0 +1,16 @@ +// aux-build:async-trait-dep.rs +// edition:2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +extern crate async_trait_dep; + +pub struct Oink {} + +// @has 'async_trait/struct.Oink.html' '//h4[@class="code-header"]' "async fn woof()" +impl async_trait_dep::Meow for Oink { + async fn woof() { + todo!() + } +} diff --git a/src/test/rustdoc/auxiliary/async-trait-dep.rs b/src/test/rustdoc/auxiliary/async-trait-dep.rs new file mode 100644 index 000000000000..10a55dd0260e --- /dev/null +++ b/src/test/rustdoc/auxiliary/async-trait-dep.rs @@ -0,0 +1,9 @@ +// edition:2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +pub trait Meow { + /// Who's a good dog? + async fn woof(); +} From 4216caed31b56d1980812960b740af5d93de36b9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 22 Oct 2022 20:34:37 +0000 Subject: [PATCH 054/171] filter candidates in pick probe for diagnostics --- compiler/rustc_hir_typeck/src/demand.rs | 41 +++++++++++-------- compiler/rustc_hir_typeck/src/method/probe.rs | 13 ++++-- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 2974ac97f236..7c74ac6f1703 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -530,24 +530,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { checked_ty: Ty<'tcx>, hir_id: hir::HirId, ) -> Vec { - let mut methods = - self.probe_for_return_type(span, probe::Mode::MethodCall, expected, checked_ty, hir_id); - methods.retain(|m| { - self.has_only_self_parameter(m) - && self - .tcx - // This special internal attribute is used to permit - // "identity-like" conversion methods to be suggested here. - // - // FIXME (#46459 and #46460): ideally - // `std::convert::Into::into` and `std::borrow:ToOwned` would - // also be `#[rustc_conversion_suggestion]`, if not for - // method-probing false-positives and -negatives (respectively). - // - // FIXME? Other potential candidate methods: `as_ref` and - // `as_mut`? - .has_attr(m.def_id, sym::rustc_conversion_suggestion) - }); + let methods = self.probe_for_return_type( + span, + probe::Mode::MethodCall, + expected, + checked_ty, + hir_id, + |m| { + self.has_only_self_parameter(m) + && self + .tcx + // This special internal attribute is used to permit + // "identity-like" conversion methods to be suggested here. + // + // FIXME (#46459 and #46460): ideally + // `std::convert::Into::into` and `std::borrow:ToOwned` would + // also be `#[rustc_conversion_suggestion]`, if not for + // method-probing false-positives and -negatives (respectively). + // + // FIXME? Other potential candidate methods: `as_ref` and + // `as_mut`? + .has_attr(m.def_id, sym::rustc_conversion_suggestion) + }, + ); methods } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 74cf2ac32aab..28aa2302f882 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -252,7 +252,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// would result in an error (basically, the same criteria we /// would use to decide if a method is a plausible fit for /// ambiguity purposes). - #[instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self, candidate_filter))] pub fn probe_for_return_type( &self, span: Span, @@ -260,6 +260,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return_type: Ty<'tcx>, self_ty: Ty<'tcx>, scope_expr_id: hir::HirId, + candidate_filter: impl Fn(&ty::AssocItem) -> bool, ) -> Vec { let method_names = self .probe_op( @@ -271,7 +272,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self_ty, scope_expr_id, ProbeScope::AllTraits, - |probe_cx| Ok(probe_cx.candidate_method_names()), + |probe_cx| Ok(probe_cx.candidate_method_names(candidate_filter)), ) .unwrap_or_default(); method_names @@ -966,12 +967,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } - fn candidate_method_names(&self) -> Vec { + fn candidate_method_names( + &self, + candidate_filter: impl Fn(&ty::AssocItem) -> bool, + ) -> Vec { let mut set = FxHashSet::default(); let mut names: Vec<_> = self .inherent_candidates .iter() .chain(&self.extension_candidates) + .filter(|candidate| candidate_filter(&candidate.item)) .filter(|candidate| { if let Some(return_ty) = self.return_type { self.matches_return_type(&candidate.item, None, return_ty) @@ -1689,7 +1694,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { pcx.allow_similar_names = true; pcx.assemble_inherent_candidates(); - let method_names = pcx.candidate_method_names(); + let method_names = pcx.candidate_method_names(|_| true); pcx.allow_similar_names = false; let applicable_close_candidates: Vec = method_names .iter() From 0f8904ec9cc0d26fda0164bc4a61f8e8ceb4d4ee Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 22 Oct 2022 23:02:59 +0200 Subject: [PATCH 055/171] Implement invocation location config --- crates/flycheck/src/lib.rs | 48 ++++++++++++--- crates/project-model/src/build_scripts.rs | 41 +++++++------ crates/project-model/src/cargo_workspace.rs | 3 +- crates/project-model/src/lib.rs | 7 +++ crates/project-model/src/workspace.rs | 4 +- crates/rust-analyzer/src/config.rs | 68 ++++++++++++++++----- crates/rust-analyzer/src/reload.rs | 6 +- docs/user/generated_config.adoc | 30 +++++++-- editors/code/package.json | 38 ++++++++++-- 9 files changed, 188 insertions(+), 57 deletions(-) diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index 0debf3270f61..73c3a48b4c5a 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs @@ -28,6 +28,13 @@ pub enum InvocationStrategy { PerWorkspace, } +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub enum InvocationLocation { + Root(AbsPathBuf), + #[default] + Workspace, +} + #[derive(Clone, Debug, PartialEq, Eq)] pub enum FlycheckConfig { CargoCommand { @@ -39,13 +46,13 @@ pub enum FlycheckConfig { features: Vec, extra_args: Vec, extra_env: FxHashMap, - invocation_strategy: InvocationStrategy, }, CustomCommand { command: String, args: Vec, extra_env: FxHashMap, invocation_strategy: InvocationStrategy, + invocation_location: InvocationLocation, }, } @@ -275,7 +282,7 @@ impl FlycheckActor { } fn check_command(&self) -> Command { - let (mut cmd, args, invocation_strategy) = match &self.config { + let (mut cmd, args) = match &self.config { FlycheckConfig::CargoCommand { command, target_triple, @@ -285,7 +292,6 @@ impl FlycheckActor { extra_args, features, extra_env, - invocation_strategy, } => { let mut cmd = Command::new(toolchain::cargo()); cmd.arg(command); @@ -309,18 +315,40 @@ impl FlycheckActor { } } cmd.envs(extra_env); - (cmd, extra_args, invocation_strategy) + (cmd, extra_args) } - FlycheckConfig::CustomCommand { command, args, extra_env, invocation_strategy } => { + FlycheckConfig::CustomCommand { + command, + args, + extra_env, + invocation_strategy, + invocation_location, + } => { let mut cmd = Command::new(command); cmd.envs(extra_env); - (cmd, args, invocation_strategy) + + match invocation_location { + InvocationLocation::Workspace => { + match invocation_strategy { + InvocationStrategy::Once => { + cmd.current_dir(&self.root); + } + InvocationStrategy::PerWorkspace => { + // FIXME: cmd.current_dir(&affected_workspace); + cmd.current_dir(&self.root); + } + } + } + InvocationLocation::Root(root) => { + cmd.current_dir(root); + } + } + + (cmd, args) } }; - match invocation_strategy { - InvocationStrategy::PerWorkspace => cmd.current_dir(&self.root), - InvocationStrategy::Once => cmd.args(args), - }; + + cmd.args(args); cmd } diff --git a/crates/project-model/src/build_scripts.rs b/crates/project-model/src/build_scripts.rs index 0bb9bd65dccf..b5f837d3c6b5 100644 --- a/crates/project-model/src/build_scripts.rs +++ b/crates/project-model/src/build_scripts.rs @@ -21,7 +21,8 @@ use semver::Version; use serde::Deserialize; use crate::{ - cfg_flag::CfgFlag, CargoConfig, CargoFeatures, CargoWorkspace, InvocationStrategy, Package, + cfg_flag::CfgFlag, CargoConfig, CargoFeatures, CargoWorkspace, InvocationLocation, + InvocationStrategy, Package, }; #[derive(Debug, Default, Clone, PartialEq, Eq)] @@ -55,10 +56,7 @@ impl BuildScriptOutput { } impl WorkspaceBuildScripts { - fn build_command( - config: &CargoConfig, - workspace_root: Option<&path::Path>, - ) -> io::Result { + fn build_command(config: &CargoConfig, current_dir: &path::Path) -> io::Result { let mut cmd = match config.run_build_script_command.as_deref() { Some([program, args @ ..]) => { let mut cmd = Command::new(program); @@ -94,14 +92,11 @@ impl WorkspaceBuildScripts { } } - if let Some(workspace_root) = workspace_root { - cmd.current_dir(workspace_root); - } - cmd } }; + cmd.current_dir(current_dir); cmd.envs(&config.extra_env); if config.wrap_rustc_in_build_scripts { // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use @@ -124,19 +119,21 @@ impl WorkspaceBuildScripts { ) -> io::Result { const RUST_1_62: Version = Version::new(1, 62, 0); - let workspace_root: &path::Path = &workspace.workspace_root().as_ref(); + let current_dir = match &config.invocation_location { + InvocationLocation::Root(root) if config.run_build_script_command.is_some() => { + root.as_path() + } + _ => &workspace.workspace_root(), + } + .as_ref(); - match Self::run_per_ws( - Self::build_command(config, Some(workspace_root))?, - workspace, - progress, - ) { + match Self::run_per_ws(Self::build_command(config, current_dir)?, workspace, progress) { Ok(WorkspaceBuildScripts { error: Some(error), .. }) if toolchain.as_ref().map_or(false, |it| *it >= RUST_1_62) => { // building build scripts failed, attempt to build with --keep-going so // that we potentially get more build data - let mut cmd = Self::build_command(config, Some(workspace_root))?; + let mut cmd = Self::build_command(config, current_dir)?; cmd.args(&["-Z", "unstable-options", "--keep-going"]).env("RUSTC_BOOTSTRAP", "1"); let mut res = Self::run_per_ws(cmd, workspace, progress)?; res.error = Some(error); @@ -154,7 +151,17 @@ impl WorkspaceBuildScripts { progress: &dyn Fn(String), ) -> io::Result> { assert_eq!(config.invocation_strategy, InvocationStrategy::Once); - let cmd = Self::build_command(config, None)?; + + let current_dir = match &config.invocation_location { + InvocationLocation::Root(root) => root, + InvocationLocation::Workspace => { + return Err(io::Error::new( + io::ErrorKind::Other, + "Cannot run build scripts from workspace with invocation strategy `once`", + )) + } + }; + let cmd = Self::build_command(config, current_dir.as_path().as_ref())?; // NB: Cargo.toml could have been modified between `cargo metadata` and // `cargo check`. We shouldn't assume that package ids we see here are // exactly those from `config`. diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs index d8f6d62349eb..b4c2ba436772 100644 --- a/crates/project-model/src/cargo_workspace.rs +++ b/crates/project-model/src/cargo_workspace.rs @@ -14,7 +14,7 @@ use rustc_hash::FxHashMap; use serde::Deserialize; use serde_json::from_value; -use crate::{utf8_stdout, ManifestPath}; +use crate::{utf8_stdout, InvocationLocation, ManifestPath}; use crate::{CfgOverrides, InvocationStrategy}; /// [`CargoWorkspace`] represents the logical structure of, well, a Cargo @@ -107,6 +107,7 @@ pub struct CargoConfig { /// Extra env vars to set when invoking the cargo command pub extra_env: FxHashMap, pub invocation_strategy: InvocationStrategy, + pub invocation_location: InvocationLocation, } impl CargoConfig { diff --git a/crates/project-model/src/lib.rs b/crates/project-model/src/lib.rs index d116ff3c0104..575581fa543a 100644 --- a/crates/project-model/src/lib.rs +++ b/crates/project-model/src/lib.rs @@ -164,3 +164,10 @@ pub enum InvocationStrategy { #[default] PerWorkspace, } + +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub enum InvocationLocation { + Root(AbsPathBuf), + #[default] + Workspace, +} diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index 01180fcf4c3e..0ec5320997ca 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -332,7 +332,9 @@ impl ProjectWorkspace { config: &CargoConfig, progress: &dyn Fn(String), ) -> Vec> { - if let InvocationStrategy::PerWorkspace = config.invocation_strategy { + if matches!(config.invocation_strategy, InvocationStrategy::PerWorkspace) + || config.run_build_script_command.is_some() + { return workspaces.iter().map(|it| it.run_build_scripts(config, progress)).collect(); } diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 3669fda926a7..85322f12a834 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -69,10 +69,16 @@ config_data! { cargo_autoreload: bool = "true", /// Run build scripts (`build.rs`) for more precise code analysis. cargo_buildScripts_enable: bool = "true", + /// Specifies the working directory for running build scripts. + /// - "workspace": run build scripts for a workspace in the workspace's root directory. + /// This is incompatible with `#rust-analyzer.cargo.buildScripts.invocationStrategy#` set to `once`. + /// - "root": run build scripts in the project's root directory. + /// This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#` + /// is set. + cargo_buildScripts_invocationLocation: InvocationLocation = "\"workspace\"", /// Specifies the invocation strategy to use when running the build scripts command. - /// If `per_workspace` is set, the command will be executed for each workspace from the - /// corresponding workspace root. - /// If `once` is set, the command will be executed once in the project root. + /// If `per_workspace` is set, the command will be executed for each workspace. + /// If `once` is set, the command will be executed once. /// This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#` /// is set. cargo_buildScripts_invocationStrategy: InvocationStrategy = "\"per_workspace\"", @@ -129,10 +135,17 @@ config_data! { /// /// Set to `"all"` to pass `--all-features` to Cargo. checkOnSave_features: Option = "null", + /// Specifies the working directory for running checks. + /// - "workspace": run checks for workspaces in the corresponding workspaces' root directories. + // FIXME: Ideally we would support this in some way + /// This falls back to "root" if `#rust-analyzer.cargo.checkOnSave.invocationStrategy#` is set to `once`. + /// - "root": run checks in the project's root directory. + /// This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#` + /// is set. + checkOnSave_invocationLocation: InvocationLocation = "\"workspace\"", /// Specifies the invocation strategy to use when running the checkOnSave command. - /// If `per_workspace` is set, the command will be executed for each workspace from the - /// corresponding workspace root. - /// If `once` is set, the command will be executed once in the project root. + /// If `per_workspace` is set, the command will be executed for each workspace. + /// If `once` is set, the command will be executed once. /// This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#` /// is set. checkOnSave_invocationStrategy: InvocationStrategy = "\"per_workspace\"", @@ -1074,6 +1087,12 @@ impl Config { InvocationStrategy::Once => project_model::InvocationStrategy::Once, InvocationStrategy::PerWorkspace => project_model::InvocationStrategy::PerWorkspace, }, + invocation_location: match self.data.cargo_buildScripts_invocationLocation { + InvocationLocation::Root => { + project_model::InvocationLocation::Root(self.root_path.clone()) + } + InvocationLocation::Workspace => project_model::InvocationLocation::Workspace, + }, run_build_script_command: self.data.cargo_buildScripts_overrideCommand.clone(), extra_env: self.data.cargo_extraEnv.clone(), } @@ -1097,10 +1116,6 @@ impl Config { if !self.data.checkOnSave_enable { return None; } - let invocation_strategy = match self.data.checkOnSave_invocationStrategy { - InvocationStrategy::Once => flycheck::InvocationStrategy::Once, - InvocationStrategy::PerWorkspace => flycheck::InvocationStrategy::PerWorkspace, - }; let flycheck_config = match &self.data.checkOnSave_overrideCommand { Some(args) if !args.is_empty() => { let mut args = args.clone(); @@ -1109,7 +1124,18 @@ impl Config { command, args, extra_env: self.check_on_save_extra_env(), - invocation_strategy, + invocation_strategy: match self.data.checkOnSave_invocationStrategy { + InvocationStrategy::Once => flycheck::InvocationStrategy::Once, + InvocationStrategy::PerWorkspace => { + flycheck::InvocationStrategy::PerWorkspace + } + }, + invocation_location: match self.data.checkOnSave_invocationLocation { + InvocationLocation::Root => { + flycheck::InvocationLocation::Root(self.root_path.clone()) + } + InvocationLocation::Workspace => flycheck::InvocationLocation::Workspace, + }, } } Some(_) | None => FlycheckConfig::CargoCommand { @@ -1139,7 +1165,6 @@ impl Config { }, extra_args: self.data.checkOnSave_extraArgs.clone(), extra_env: self.check_on_save_extra_env(), - invocation_strategy, }, }; Some(flycheck_config) @@ -1618,6 +1643,13 @@ enum InvocationStrategy { PerWorkspace, } +#[derive(Deserialize, Debug, Clone)] +#[serde(rename_all = "snake_case")] +enum InvocationLocation { + Root, + Workspace, +} + #[derive(Deserialize, Debug, Clone)] #[serde(untagged)] enum LifetimeElisionDef { @@ -2036,8 +2068,16 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json "type": "string", "enum": ["per_workspace", "once"], "enumDescriptions": [ - "The command will be executed for each workspace from the corresponding workspace root.", - "The command will be executed once in the project root." + "The command will be executed for each workspace.", + "The command will be executed once." + ], + }, + "InvocationLocation" => set! { + "type": "string", + "enum": ["workspace", "root"], + "enumDescriptions": [ + "The command will be executed in the corresponding workspace root.", + "The command will be executed in the project root." ], }, _ => panic!("missing entry for {}: {}", ty, default), diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index cc7600a2fa98..e1f651786dee 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -473,8 +473,10 @@ impl GlobalState { }; let sender = self.flycheck_sender.clone(); - let (FlycheckConfig::CargoCommand { invocation_strategy, .. } - | FlycheckConfig::CustomCommand { invocation_strategy, .. }) = config; + let invocation_strategy = match config { + FlycheckConfig::CargoCommand { .. } => flycheck::InvocationStrategy::PerWorkspace, + FlycheckConfig::CustomCommand { invocation_strategy, .. } => invocation_strategy, + }; self.flycheck = match invocation_strategy { flycheck::InvocationStrategy::Once => vec![FlycheckHandle::spawn( diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index e5d4395c345c..502833de72c1 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -24,13 +24,22 @@ Automatically refresh project info via `cargo metadata` on -- Run build scripts (`build.rs`) for more precise code analysis. -- +[[rust-analyzer.cargo.buildScripts.invocationLocation]]rust-analyzer.cargo.buildScripts.invocationLocation (default: `"workspace"`):: ++ +-- +Specifies the working directory for running build scripts. +- "workspace": run build scripts for a workspace in the workspace's root directory. + This is incompatible with `#rust-analyzer.cargo.buildScripts.invocationStrategy#` set to `once`. +- "root": run build scripts in the project's root directory. +This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#` +is set. +-- [[rust-analyzer.cargo.buildScripts.invocationStrategy]]rust-analyzer.cargo.buildScripts.invocationStrategy (default: `"per_workspace"`):: + -- Specifies the invocation strategy to use when running the build scripts command. -If `per_workspace` is set, the command will be executed for each workspace from the -corresponding workspace root. -If `once` is set, the command will be executed once in the project root. +If `per_workspace` is set, the command will be executed for each workspace. +If `once` is set, the command will be executed once. This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#` is set. -- @@ -128,13 +137,22 @@ List of features to activate. Defaults to Set to `"all"` to pass `--all-features` to Cargo. -- +[[rust-analyzer.checkOnSave.invocationLocation]]rust-analyzer.checkOnSave.invocationLocation (default: `"workspace"`):: ++ +-- +Specifies the working directory for running checks. +- "workspace": run checks for workspaces in the corresponding workspaces' root directories. + This falls back to "root" if `#rust-analyzer.cargo.checkOnSave.invocationStrategy#` is set to `once`. +- "root": run checks in the project's root directory. +This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#` +is set. +-- [[rust-analyzer.checkOnSave.invocationStrategy]]rust-analyzer.checkOnSave.invocationStrategy (default: `"per_workspace"`):: + -- Specifies the invocation strategy to use when running the checkOnSave command. -If `per_workspace` is set, the command will be executed for each workspace from the -corresponding workspace root. -If `once` is set, the command will be executed once in the project root. +If `per_workspace` is set, the command will be executed for each workspace. +If `once` is set, the command will be executed once. This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#` is set. -- diff --git a/editors/code/package.json b/editors/code/package.json index 62ac1e60b00a..6771cad28a79 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -432,8 +432,21 @@ "default": true, "type": "boolean" }, + "rust-analyzer.cargo.buildScripts.invocationLocation": { + "markdownDescription": "Specifies the working directory for running build scripts.\n- \"workspace\": run build scripts for a workspace in the workspace's root directory.\n This is incompatible with `#rust-analyzer.cargo.buildScripts.invocationStrategy#` set to `once`.\n- \"root\": run build scripts in the project's root directory.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.", + "default": "workspace", + "type": "string", + "enum": [ + "workspace", + "root" + ], + "enumDescriptions": [ + "The command will be executed in the corresponding workspace root.", + "The command will be executed in the project root." + ] + }, "rust-analyzer.cargo.buildScripts.invocationStrategy": { - "markdownDescription": "Specifies the invocation strategy to use when running the build scripts command.\nIf `per_workspace` is set, the command will be executed for each workspace from the\ncorresponding workspace root.\nIf `once` is set, the command will be executed once in the project root.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.", + "markdownDescription": "Specifies the invocation strategy to use when running the build scripts command.\nIf `per_workspace` is set, the command will be executed for each workspace.\nIf `once` is set, the command will be executed once.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.", "default": "per_workspace", "type": "string", "enum": [ @@ -441,8 +454,8 @@ "once" ], "enumDescriptions": [ - "The command will be executed for each workspace from the corresponding workspace root.", - "The command will be executed once in the project root." + "The command will be executed for each workspace.", + "The command will be executed once." ] }, "rust-analyzer.cargo.buildScripts.overrideCommand": { @@ -570,8 +583,21 @@ } ] }, + "rust-analyzer.checkOnSave.invocationLocation": { + "markdownDescription": "Specifies the working directory for running checks.\n- \"workspace\": run checks for workspaces in the corresponding workspaces' root directories.\n This falls back to \"root\" if `#rust-analyzer.cargo.checkOnSave.invocationStrategy#` is set to `once`.\n- \"root\": run checks in the project's root directory.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.", + "default": "workspace", + "type": "string", + "enum": [ + "workspace", + "root" + ], + "enumDescriptions": [ + "The command will be executed in the corresponding workspace root.", + "The command will be executed in the project root." + ] + }, "rust-analyzer.checkOnSave.invocationStrategy": { - "markdownDescription": "Specifies the invocation strategy to use when running the checkOnSave command.\nIf `per_workspace` is set, the command will be executed for each workspace from the\ncorresponding workspace root.\nIf `once` is set, the command will be executed once in the project root.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.", + "markdownDescription": "Specifies the invocation strategy to use when running the checkOnSave command.\nIf `per_workspace` is set, the command will be executed for each workspace.\nIf `once` is set, the command will be executed once.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.", "default": "per_workspace", "type": "string", "enum": [ @@ -579,8 +605,8 @@ "once" ], "enumDescriptions": [ - "The command will be executed for each workspace from the corresponding workspace root.", - "The command will be executed once in the project root." + "The command will be executed for each workspace.", + "The command will be executed once." ] }, "rust-analyzer.checkOnSave.noDefaultFeatures": { From 74d4eefc1346a8b9242e072df16de4f664b0873c Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 23 Oct 2022 09:22:19 +0000 Subject: [PATCH 056/171] Workaround unstable stmt_expr_attributes for method receiver expressions. --- compiler/rustc_ast/src/mut_visit.rs | 14 ++++- compiler/rustc_ast/src/visit.rs | 5 ++ compiler/rustc_builtin_macros/src/cfg_eval.rs | 9 ++- compiler/rustc_expand/src/config.rs | 10 ++- compiler/rustc_expand/src/expand.rs | 63 +++++++++++++++++++ compiler/rustc_expand/src/placeholders.rs | 8 +++ src/test/ui/cfg/cfg-method-receiver-ok.rs | 14 +++++ src/test/ui/cfg/cfg-method-receiver.rs | 3 +- src/test/ui/cfg/cfg-method-receiver.stderr | 14 +---- 9 files changed, 121 insertions(+), 19 deletions(-) create mode 100644 src/test/ui/cfg/cfg-method-receiver-ok.rs diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 25022a02f4bb..b970e57e0173 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -152,6 +152,12 @@ pub trait MutVisitor: Sized { noop_visit_expr(e, self); } + /// This method is a hack to workaround unstable of `stmt_expr_attributes`. + /// It can be removed once that feature is stabilized. + fn visit_method_receiver_expr(&mut self, ex: &mut P) { + self.visit_expr(ex) + } + fn filter_map_expr(&mut self, e: P) -> Option> { noop_filter_map_expr(e, self) } @@ -1301,7 +1307,7 @@ pub fn noop_visit_expr( vis.visit_ident(ident); vis.visit_id(id); visit_opt(args, |args| vis.visit_generic_args(args)); - vis.visit_expr(receiver); + vis.visit_method_receiver_expr(receiver); visit_exprs(exprs, vis); vis.visit_span(span); } @@ -1589,3 +1595,9 @@ impl DummyAstNode for Crate { } } } + +impl DummyAstNode for crate::ast_traits::AstNodeWrapper { + fn dummy() -> Self { + crate::ast_traits::AstNodeWrapper::new(N::dummy(), T::dummy()) + } +} diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index e752cc7dc2dc..6f56c1ef0e8d 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -140,6 +140,11 @@ pub trait Visitor<'ast>: Sized { fn visit_expr(&mut self, ex: &'ast Expr) { walk_expr(self, ex) } + /// This method is a hack to workaround unstable of `stmt_expr_attributes`. + /// It can be removed once that feature is stabilized. + fn visit_method_receiver_expr(&mut self, ex: &'ast Expr) { + self.visit_expr(ex) + } fn visit_expr_post(&mut self, _ex: &'ast Expr) {} fn visit_ty(&mut self, t: &'ast Ty) { walk_ty(self, t) diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index 009f3c783d4c..750f1fe121f6 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -210,8 +210,15 @@ impl CfgEval<'_, '_> { } impl MutVisitor for CfgEval<'_, '_> { + #[instrument(level = "trace", skip(self))] fn visit_expr(&mut self, expr: &mut P) { - self.cfg.configure_expr(expr); + self.cfg.configure_expr(expr, false); + mut_visit::noop_visit_expr(expr, self); + } + + #[instrument(level = "trace", skip(self))] + fn visit_method_receiver_expr(&mut self, expr: &mut P) { + self.cfg.configure_expr(expr, true); mut_visit::noop_visit_expr(expr, self); } diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 8d4e36407486..1d2b1298a68f 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -469,6 +469,7 @@ impl<'a> StripUnconfigured<'a> { } /// If attributes are not allowed on expressions, emit an error for `attr` + #[instrument(level = "trace", skip(self))] pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) { if !self.features.map_or(true, |features| features.stmt_expr_attributes) { let mut err = feature_err( @@ -486,9 +487,12 @@ impl<'a> StripUnconfigured<'a> { } } - pub fn configure_expr(&self, expr: &mut P) { - for attr in expr.attrs.iter() { - self.maybe_emit_expr_attr_err(attr); + #[instrument(level = "trace", skip(self))] + pub fn configure_expr(&self, expr: &mut P, method_receiver: bool) { + if !method_receiver { + for attr in expr.attrs.iter() { + self.maybe_emit_expr_attr_err(attr); + } } // If an expr is valid to cfg away it will have been removed by the diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 15e9a8db3c60..57713fb3cd61 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -50,6 +50,7 @@ macro_rules! ast_fragments { /// Can also serve as an input and intermediate result for macro expansion operations. pub enum AstFragment { OptExpr(Option>), + MethodReceiverExpr(P), $($Kind($AstTy),)* } @@ -57,6 +58,7 @@ macro_rules! ast_fragments { #[derive(Copy, Clone, PartialEq, Eq)] pub enum AstFragmentKind { OptExpr, + MethodReceiverExpr, $($Kind,)* } @@ -64,6 +66,7 @@ macro_rules! ast_fragments { pub fn name(self) -> &'static str { match self { AstFragmentKind::OptExpr => "expression", + AstFragmentKind::MethodReceiverExpr => "expression", $(AstFragmentKind::$Kind => $kind_name,)* } } @@ -72,6 +75,8 @@ macro_rules! ast_fragments { match self { AstFragmentKind::OptExpr => result.make_expr().map(Some).map(AstFragment::OptExpr), + AstFragmentKind::MethodReceiverExpr => + result.make_expr().map(AstFragment::MethodReceiverExpr), $(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)* } } @@ -98,6 +103,13 @@ macro_rules! ast_fragments { } } + pub fn make_method_receiver_expr(self) -> P { + match self { + AstFragment::MethodReceiverExpr(expr) => expr, + _ => panic!("AstFragment::make_* called on the wrong kind of fragment"), + } + } + $(pub fn $make_ast(self) -> $AstTy { match self { AstFragment::$Kind(ast) => ast, @@ -120,6 +132,7 @@ macro_rules! ast_fragments { } }); } + AstFragment::MethodReceiverExpr(expr) => vis.visit_method_receiver_expr(expr), $($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)* $($(AstFragment::$Kind(ast) => ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast)),)?)* @@ -130,6 +143,7 @@ macro_rules! ast_fragments { match *self { AstFragment::OptExpr(Some(ref expr)) => visitor.visit_expr(expr), AstFragment::OptExpr(None) => {} + AstFragment::MethodReceiverExpr(ref expr) => visitor.visit_method_receiver_expr(expr), $($(AstFragment::$Kind(ref ast) => visitor.$visit_ast(ast),)?)* $($(AstFragment::$Kind(ref ast) => for ast_elt in &ast[..] { visitor.$visit_ast_elt(ast_elt, $($args)*); @@ -222,6 +236,7 @@ impl AstFragmentKind { match self { AstFragmentKind::OptExpr | AstFragmentKind::Expr + | AstFragmentKind::MethodReceiverExpr | AstFragmentKind::Stmts | AstFragmentKind::Ty | AstFragmentKind::Pat => SupportsMacroExpansion::Yes { supports_inner_attrs: false }, @@ -285,6 +300,9 @@ impl AstFragmentKind { AstFragmentKind::Expr => AstFragment::Expr( items.next().expect("expected exactly one expression").expect_expr(), ), + AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr( + items.next().expect("expected exactly one expression").expect_expr(), + ), AstFragmentKind::OptExpr => { AstFragment::OptExpr(items.next().map(Annotatable::expect_expr)) } @@ -893,6 +911,7 @@ pub fn parse_ast_fragment<'a>( AstFragment::Stmts(stmts) } AstFragmentKind::Expr => AstFragment::Expr(this.parse_expr()?), + AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(this.parse_expr()?), AstFragmentKind::OptExpr => { if this.token != token::Eof { AstFragment::OptExpr(Some(this.parse_expr()?)) @@ -1477,6 +1496,42 @@ impl InvocationCollectorNode for AstNodeWrapper, OptExprTag> { } } +/// This struct is a hack to workaround unstable of `stmt_expr_attributes`. +/// It can be removed once that feature is stabilized. +struct MethodReceiverTag; +impl DummyAstNode for MethodReceiverTag { + fn dummy() -> MethodReceiverTag { + MethodReceiverTag + } +} +impl InvocationCollectorNode for AstNodeWrapper, MethodReceiverTag> { + type OutputTy = Self; + type AttrsTy = ast::AttrVec; + const KIND: AstFragmentKind = AstFragmentKind::MethodReceiverExpr; + fn descr() -> &'static str { + "an expression" + } + fn to_annotatable(self) -> Annotatable { + Annotatable::Expr(self.wrapped) + } + fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { + AstNodeWrapper::new(fragment.make_method_receiver_expr(), MethodReceiverTag) + } + fn noop_visit(&mut self, visitor: &mut V) { + noop_visit_expr(&mut self.wrapped, visitor) + } + fn is_mac_call(&self) -> bool { + matches!(self.wrapped.kind, ast::ExprKind::MacCall(..)) + } + fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) { + let node = self.wrapped.into_inner(); + match node.kind { + ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No), + _ => unreachable!(), + } + } +} + struct InvocationCollector<'a, 'b> { cx: &'a mut ExtCtxt<'b>, invocations: Vec<(Invocation, Option>)>, @@ -1840,6 +1895,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { self.visit_node(node) } + fn visit_method_receiver_expr(&mut self, node: &mut P) { + visit_clobber(node, |node| { + let mut wrapper = AstNodeWrapper::new(node, MethodReceiverTag); + self.visit_node(&mut wrapper); + wrapper.wrapped + }) + } + fn filter_map_expr(&mut self, node: P) -> Option> { self.flat_map_node(AstNodeWrapper::new(node, OptExprTag)) } diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 3b0d5ddb97b4..faaf3b3fea58 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -55,6 +55,7 @@ pub fn placeholder( }), AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()), AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())), + AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(expr_placeholder()), AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item { id, span, @@ -296,6 +297,13 @@ impl MutVisitor for PlaceholderExpander { } } + fn visit_method_receiver_expr(&mut self, expr: &mut P) { + match expr.kind { + ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_method_receiver_expr(), + _ => noop_visit_expr(expr, self), + } + } + fn filter_map_expr(&mut self, expr: P) -> Option> { match expr.kind { ast::ExprKind::MacCall(_) => self.remove(expr.id).make_opt_expr(), diff --git a/src/test/ui/cfg/cfg-method-receiver-ok.rs b/src/test/ui/cfg/cfg-method-receiver-ok.rs new file mode 100644 index 000000000000..61ad3b8c17ab --- /dev/null +++ b/src/test/ui/cfg/cfg-method-receiver-ok.rs @@ -0,0 +1,14 @@ +// check-pass + +macro_rules! foo { + () => { + #[allow(unreachable_patterns)] + { + 123i32 + } + }; +} + +fn main() { + let _ = foo!().abs(); +} diff --git a/src/test/ui/cfg/cfg-method-receiver.rs b/src/test/ui/cfg/cfg-method-receiver.rs index 78a072f503fa..71134ff17b52 100644 --- a/src/test/ui/cfg/cfg-method-receiver.rs +++ b/src/test/ui/cfg/cfg-method-receiver.rs @@ -7,6 +7,5 @@ macro_rules! cbor_map { fn main() { cbor_map! { #[cfg(test)] 4}; - //~^ ERROR attributes on expressions are experimental - //~| ERROR removing an expression is not supported in this position + //~^ ERROR removing an expression is not supported in this position } diff --git a/src/test/ui/cfg/cfg-method-receiver.stderr b/src/test/ui/cfg/cfg-method-receiver.stderr index 517fc8168e72..5767a7c1b4b1 100644 --- a/src/test/ui/cfg/cfg-method-receiver.stderr +++ b/src/test/ui/cfg/cfg-method-receiver.stderr @@ -1,12 +1,3 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/cfg-method-receiver.rs:9:17 - | -LL | cbor_map! { #[cfg(test)] 4}; - | ^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable - error: removing an expression is not supported in this position --> $DIR/cfg-method-receiver.rs:9:17 | @@ -28,7 +19,6 @@ help: you must specify a concrete type for this numeric value, like `i32` LL | cbor_map! { #[cfg(test)] 4_i32}; | ~~~~~ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0658, E0689. -For more information about an error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0689`. From 859f5594acced1ebd9ca3b0f4705c94a326f84e9 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 23 Oct 2022 18:01:35 +0200 Subject: [PATCH 057/171] Handle multiple projects sharing dependency correctly in `once` strategy --- crates/project-model/src/build_scripts.rs | 34 +++++++++++++++++------ crates/project-model/src/workspace.rs | 2 +- crates/rust-analyzer/src/main_loop.rs | 5 +++- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/crates/project-model/src/build_scripts.rs b/crates/project-model/src/build_scripts.rs index b5f837d3c6b5..a26a7c57acfc 100644 --- a/crates/project-model/src/build_scripts.rs +++ b/crates/project-model/src/build_scripts.rs @@ -56,7 +56,7 @@ impl BuildScriptOutput { } impl WorkspaceBuildScripts { - fn build_command(config: &CargoConfig, current_dir: &path::Path) -> io::Result { + fn build_command(config: &CargoConfig) -> io::Result { let mut cmd = match config.run_build_script_command.as_deref() { Some([program, args @ ..]) => { let mut cmd = Command::new(program); @@ -96,7 +96,6 @@ impl WorkspaceBuildScripts { } }; - cmd.current_dir(current_dir); cmd.envs(&config.extra_env); if config.wrap_rustc_in_build_scripts { // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use @@ -127,15 +126,15 @@ impl WorkspaceBuildScripts { } .as_ref(); - match Self::run_per_ws(Self::build_command(config, current_dir)?, workspace, progress) { + match Self::run_per_ws(Self::build_command(config)?, workspace, current_dir, progress) { Ok(WorkspaceBuildScripts { error: Some(error), .. }) if toolchain.as_ref().map_or(false, |it| *it >= RUST_1_62) => { // building build scripts failed, attempt to build with --keep-going so // that we potentially get more build data - let mut cmd = Self::build_command(config, current_dir)?; + let mut cmd = Self::build_command(config)?; cmd.args(&["-Z", "unstable-options", "--keep-going"]).env("RUSTC_BOOTSTRAP", "1"); - let mut res = Self::run_per_ws(cmd, workspace, progress)?; + let mut res = Self::run_per_ws(cmd, workspace, current_dir, progress)?; res.error = Some(error); Ok(res) } @@ -161,11 +160,14 @@ impl WorkspaceBuildScripts { )) } }; - let cmd = Self::build_command(config, current_dir.as_path().as_ref())?; + let cmd = Self::build_command(config)?; // NB: Cargo.toml could have been modified between `cargo metadata` and // `cargo check`. We shouldn't assume that package ids we see here are // exactly those from `config`. let mut by_id = FxHashMap::default(); + // some workspaces might depend on the same crates, so we need to duplicate the outputs + // to those collisions + let mut collisions = Vec::new(); let mut res: Vec<_> = workspaces .iter() .enumerate() @@ -173,7 +175,11 @@ impl WorkspaceBuildScripts { let mut res = WorkspaceBuildScripts::default(); for package in workspace.packages() { res.outputs.insert(package, BuildScriptOutput::default()); - by_id.insert(workspace[package].id.clone(), (package, idx)); + if by_id.contains_key(&workspace[package].id) { + collisions.push((&workspace[package].id, idx, package)); + } else { + by_id.insert(workspace[package].id.clone(), (package, idx)); + } } res }) @@ -181,6 +187,7 @@ impl WorkspaceBuildScripts { let errors = Self::run_command( cmd, + current_dir.as_path().as_ref(), |package, cb| { if let Some(&(package, workspace)) = by_id.get(package) { cb(&workspaces[workspace][package].name, &mut res[workspace].outputs[package]); @@ -189,6 +196,11 @@ impl WorkspaceBuildScripts { progress, )?; res.iter_mut().for_each(|it| it.error = errors.clone()); + collisions.into_iter().for_each(|(id, workspace, package)| { + if let Some(&(p, w)) = by_id.get(id) { + res[workspace].outputs[package] = res[w].outputs[p].clone(); + } + }); if tracing::enabled!(tracing::Level::INFO) { for (idx, workspace) in workspaces.iter().enumerate() { @@ -211,6 +223,7 @@ impl WorkspaceBuildScripts { fn run_per_ws( cmd: Command, workspace: &CargoWorkspace, + current_dir: &path::Path, progress: &dyn Fn(String), ) -> io::Result { let mut res = WorkspaceBuildScripts::default(); @@ -226,6 +239,7 @@ impl WorkspaceBuildScripts { res.error = Self::run_command( cmd, + current_dir, |package, cb| { if let Some(&package) = by_id.get(package) { cb(&workspace[package].name, &mut outputs[package]); @@ -251,7 +265,8 @@ impl WorkspaceBuildScripts { } fn run_command( - cmd: Command, + mut cmd: Command, + current_dir: &path::Path, // ideally this would be something like: // with_output_for: impl FnMut(&str, dyn FnOnce(&mut BuildScriptOutput)), // but owned trait objects aren't a thing @@ -265,7 +280,8 @@ impl WorkspaceBuildScripts { e.push('\n'); }; - tracing::info!("Running build scripts: {:?}", cmd); + tracing::info!("Running build scripts in {}: {:?}", current_dir.display(), cmd); + cmd.current_dir(current_dir); let output = stdx::process::spawn_with_streaming_output( cmd, &mut |line| { diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index 0ec5320997ca..2780c62ed118 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -333,7 +333,7 @@ impl ProjectWorkspace { progress: &dyn Fn(String), ) -> Vec> { if matches!(config.invocation_strategy, InvocationStrategy::PerWorkspace) - || config.run_build_script_command.is_some() + || config.run_build_script_command.is_none() { return workspaces.iter().map(|it| it.run_build_scripts(config, progress)).collect(); } diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 319b86c58b5c..2c928a580405 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -543,7 +543,10 @@ impl GlobalState { diag.fix, ), Err(err) => { - tracing::error!("File with cargo diagnostic not found in VFS: {}", err); + tracing::error!( + "flycheck {id}: File with cargo diagnostic not found in VFS: {}", + err + ); } }; } From 8bc43f99e91a94868fe08bb72b7ce66d7656d0b5 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Mon, 17 Oct 2022 19:41:49 +0200 Subject: [PATCH 058/171] Allow specifying multiple alternative suggestions This allows porting uses of span_suggestions() to diagnostic structs. Doesn't work for multipart_suggestions() because the rank would be reversed - the struct would specify multiple spans, each of which has multiple possible replacements, while multipart_suggestions() creates multiple possible replacements, each with multiple spans. --- compiler/rustc_errors/src/diagnostic.rs | 26 ++++- .../src/diagnostics/diagnostic_builder.rs | 2 +- .../src/diagnostics/subdiagnostic.rs | 21 ++-- .../rustc_macros/src/diagnostics/utils.rs | 105 ++++++++++++++++-- .../session-diagnostic/diagnostic-derive.rs | 38 +++++++ .../diagnostic-derive.stderr | 20 +++- .../subdiagnostic-derive.rs | 45 ++++++++ .../subdiagnostic-derive.stderr | 32 +++++- 8 files changed, 263 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index a63fc0ca285d..23f29a24fe79 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -690,6 +690,24 @@ impl Diagnostic { msg: impl Into, suggestions: impl Iterator, applicability: Applicability, + ) -> &mut Self { + self.span_suggestions_with_style( + sp, + msg, + suggestions, + applicability, + SuggestionStyle::ShowCode, + ) + } + + /// [`Diagnostic::span_suggestions()`] but you can set the [`SuggestionStyle`]. + pub fn span_suggestions_with_style( + &mut self, + sp: Span, + msg: impl Into, + suggestions: impl Iterator, + applicability: Applicability, + style: SuggestionStyle, ) -> &mut Self { let mut suggestions: Vec<_> = suggestions.collect(); suggestions.sort(); @@ -706,14 +724,15 @@ impl Diagnostic { self.push_suggestion(CodeSuggestion { substitutions, msg: self.subdiagnostic_message_to_diagnostic_message(msg), - style: SuggestionStyle::ShowCode, + style, applicability, }); self } - /// Prints out a message with multiple suggested edits of the code. - /// See also [`Diagnostic::span_suggestion()`]. + /// Prints out a message with multiple suggested edits of the code, where each edit consists of + /// multiple parts. + /// See also [`Diagnostic::multipart_suggestion()`]. pub fn multipart_suggestions( &mut self, msg: impl Into, @@ -745,6 +764,7 @@ impl Diagnostic { }); self } + /// Prints out a message with a suggested edit of the code. If the suggestion is presented /// inline, it will only show the message and not the suggestion. /// diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 9f7d2661a3e8..3ea83fd09c79 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -454,7 +454,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { self.formatting_init.extend(code_init); Ok(quote! { - #diag.span_suggestion_with_style( + #diag.span_suggestions_with_style( #span_field, rustc_errors::fluent::#slug, #code_field, diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index d1acb7138422..fa0ca5a52423 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -11,9 +11,11 @@ use crate::diagnostics::utils::{ }; use proc_macro2::TokenStream; use quote::{format_ident, quote}; -use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path}; +use syn::{spanned::Spanned, Attribute, Meta, MetaList, NestedMeta, Path}; use synstructure::{BindingInfo, Structure, VariantInfo}; +use super::utils::{build_suggestion_code, AllowMultipleAlternatives}; + /// The central struct for constructing the `add_to_diagnostic` method from an annotated struct. pub(crate) struct SubdiagnosticDeriveBuilder { diag: syn::Ident, @@ -414,15 +416,16 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let nested_name = meta.path().segments.last().unwrap().ident.to_string(); let nested_name = nested_name.as_str(); - let Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) = meta else { - throw_invalid_nested_attr!(attr, &nested_attr); - }; - match nested_name { "code" => { - let formatted_str = self.build_format(&value.value(), value.span()); let code_field = new_code_ident(); - code.set_once((code_field, formatted_str), span); + let formatting_init = build_suggestion_code( + &code_field, + meta, + self, + AllowMultipleAlternatives::No, + ); + code.set_once((code_field, formatting_init), span); } _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { diag.help("`code` is the only valid nested attribute") @@ -430,14 +433,14 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { } } - let Some((code_field, formatted_str)) = code.value() else { + let Some((code_field, formatting_init)) = code.value() else { span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`") .emit(); return Ok(quote! {}); }; let binding = info.binding; - self.formatting_init.extend(quote! { let #code_field = #formatted_str; }); + self.formatting_init.extend(formatting_init); let code_field = if clone_suggestion_code { quote! { #code_field.clone() } } else { diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 61d5007fc30f..374c795d0a63 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -2,7 +2,7 @@ use crate::diagnostics::error::{ span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, DiagnosticDeriveError, }; use proc_macro::Span; -use proc_macro2::TokenStream; +use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote, ToTokens}; use std::cell::RefCell; use std::collections::{BTreeSet, HashMap}; @@ -395,6 +395,82 @@ pub(super) fn build_field_mapping<'v>(variant: &VariantInfo<'v>) -> HashMap TokenStream { + let values = match meta { + // `code = "foo"` + Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => vec![s], + // `code("foo", "bar")` + Meta::List(MetaList { nested, .. }) => { + if let AllowMultipleAlternatives::No = allow_multiple { + span_err( + meta.span().unwrap(), + "expected exactly one string literal for `code = ...`", + ) + .emit(); + vec![] + } else if nested.is_empty() { + span_err( + meta.span().unwrap(), + "expected at least one string literal for `code(...)`", + ) + .emit(); + vec![] + } else { + nested + .into_iter() + .filter_map(|item| { + if let NestedMeta::Lit(syn::Lit::Str(s)) = item { + Some(s) + } else { + span_err( + item.span().unwrap(), + "`code(...)` must contain only string literals", + ) + .emit(); + None + } + }) + .collect() + } + } + _ => { + span_err( + meta.span().unwrap(), + r#"`code = "..."`/`code(...)` must contain only string literals"#, + ) + .emit(); + vec![] + } + }; + + if let AllowMultipleAlternatives::Yes = allow_multiple { + let formatted_strings: Vec<_> = values + .into_iter() + .map(|value| fields.build_format(&value.value(), value.span())) + .collect(); + quote! { let #code_field = [#(#formatted_strings),*].into_iter(); } + } else if let [value] = values.as_slice() { + let formatted_str = fields.build_format(&value.value(), value.span()); + quote! { let #code_field = #formatted_str; } + } else { + // error handled previously + quote! { let #code_field = String::new(); } + } +} + /// Possible styles for suggestion subdiagnostics. #[derive(Clone, Copy)] pub(super) enum SuggestionKind { @@ -571,21 +647,23 @@ impl SubdiagnosticKind { let nested_name = meta.path().segments.last().unwrap().ident.to_string(); let nested_name = nested_name.as_str(); - let value = match meta { - Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => value, + let string_value = match meta { + Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => Some(value), + Meta::Path(_) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { diag.help("a diagnostic slug must be the first argument to the attribute") }), - _ => { - invalid_nested_attr(attr, &nested_attr).emit(); - continue; - } + _ => None, }; match (nested_name, &mut kind) { ("code", SubdiagnosticKind::Suggestion { code_field, .. }) => { - let formatted_str = fields.build_format(&value.value(), value.span()); - let code_init = quote! { let #code_field = #formatted_str; }; + let code_init = build_suggestion_code( + code_field, + meta, + fields, + AllowMultipleAlternatives::Yes, + ); code.set_once(code_init, span); } ( @@ -593,6 +671,11 @@ impl SubdiagnosticKind { SubdiagnosticKind::Suggestion { ref mut applicability, .. } | SubdiagnosticKind::MultipartSuggestion { ref mut applicability, .. }, ) => { + let Some(value) = string_value else { + invalid_nested_attr(attr, &nested_attr).emit(); + continue; + }; + let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| { span_err(span, "invalid applicability").emit(); Applicability::Unspecified @@ -623,7 +706,7 @@ impl SubdiagnosticKind { init } else { span_err(span, "suggestion without `code = \"...\"`").emit(); - quote! { let #code_field: String = unreachable!(); } + quote! { let #code_field = std::iter::empty(); } }; } SubdiagnosticKind::Label @@ -644,7 +727,7 @@ impl quote::IdentFragment for SubdiagnosticKind { SubdiagnosticKind::Note => write!(f, "note"), SubdiagnosticKind::Help => write!(f, "help"), SubdiagnosticKind::Warn => write!(f, "warn"), - SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestion_with_style"), + SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestions_with_style"), SubdiagnosticKind::MultipartSuggestion { .. } => { write!(f, "multipart_suggestion_with_style") } diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index 46164d573b0b..ca77e483d6ff 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -758,3 +758,41 @@ struct WithDocComment { #[primary_span] span: Span, } + +#[derive(Diagnostic)] +#[diag(compiletest_example)] +struct SuggestionsGood { + #[suggestion(code("foo", "bar"))] + sub: Span, +} + +#[derive(Diagnostic)] +#[diag(compiletest_example)] +struct SuggestionsSingleItem { + #[suggestion(code("foo"))] + sub: Span, +} + +#[derive(Diagnostic)] +#[diag(compiletest_example)] +struct SuggestionsNoItem { + #[suggestion(code())] + //~^ ERROR expected at least one string literal for `code(...)` + sub: Span, +} + +#[derive(Diagnostic)] +#[diag(compiletest_example)] +struct SuggestionsInvalidItem { + #[suggestion(code(foo))] + //~^ ERROR `code(...)` must contain only string literals + sub: Span, +} + +#[derive(Diagnostic)] +#[diag(compiletest_example)] +struct SuggestionsInvalidLiteral { + #[suggestion(code = 3)] + //~^ ERROR `code = "..."`/`code(...)` must contain only string literals + sub: Span, +} diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 0a1c4bddb06a..859c272b6ba9 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -573,6 +573,24 @@ LL | #[subdiagnostic(eager)] | = help: eager subdiagnostics are not supported on lints +error: expected at least one string literal for `code(...)` + --> $DIR/diagnostic-derive.rs:779:18 + | +LL | #[suggestion(code())] + | ^^^^^^ + +error: `code(...)` must contain only string literals + --> $DIR/diagnostic-derive.rs:787:23 + | +LL | #[suggestion(code(foo))] + | ^^^ + +error: `code = "..."`/`code(...)` must contain only string literals + --> $DIR/diagnostic-derive.rs:795:18 + | +LL | #[suggestion(code = 3)] + | ^^^^^^^^ + error: cannot find attribute `nonsense` in this scope --> $DIR/diagnostic-derive.rs:55:3 | @@ -647,7 +665,7 @@ LL | arg: impl IntoDiagnosticArg, | ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg` = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 80 previous errors +error: aborting due to 83 previous errors Some errors have detailed explanations: E0277, E0425. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index 9088ca6ce462..efec85eb52c2 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -661,3 +661,48 @@ enum BL { span: Span, } } + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser_add_paren)] +struct BM { + #[suggestion_part(code("foo"))] + //~^ ERROR expected exactly one string literal for `code = ...` + span: Span, + r#type: String, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser_add_paren)] +struct BN { + #[suggestion_part(code("foo", "bar"))] + //~^ ERROR expected exactly one string literal for `code = ...` + span: Span, + r#type: String, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser_add_paren)] +struct BO { + #[suggestion_part(code(3))] + //~^ ERROR expected exactly one string literal for `code = ...` + span: Span, + r#type: String, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser_add_paren)] +struct BP { + #[suggestion_part(code())] + //~^ ERROR expected exactly one string literal for `code = ...` + span: Span, + r#type: String, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser_add_paren)] +struct BQ { + #[suggestion_part(code = 3)] + //~^ ERROR `code = "..."`/`code(...)` must contain only string literals + span: Span, + r#type: String, +} diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr index b21f9cc94a98..a85a8711eaca 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr @@ -415,6 +415,36 @@ error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_sugg LL | #[applicability] | ^^^^^^^^^^^^^^^^ +error: expected exactly one string literal for `code = ...` + --> $DIR/subdiagnostic-derive.rs:668:23 + | +LL | #[suggestion_part(code("foo"))] + | ^^^^^^^^^^^ + +error: expected exactly one string literal for `code = ...` + --> $DIR/subdiagnostic-derive.rs:677:23 + | +LL | #[suggestion_part(code("foo", "bar"))] + | ^^^^^^^^^^^^^^^^^^ + +error: expected exactly one string literal for `code = ...` + --> $DIR/subdiagnostic-derive.rs:686:23 + | +LL | #[suggestion_part(code(3))] + | ^^^^^^^ + +error: expected exactly one string literal for `code = ...` + --> $DIR/subdiagnostic-derive.rs:695:23 + | +LL | #[suggestion_part(code())] + | ^^^^^^ + +error: `code = "..."`/`code(...)` must contain only string literals + --> $DIR/subdiagnostic-derive.rs:704:23 + | +LL | #[suggestion_part(code = 3)] + | ^^^^^^^^ + error: cannot find attribute `foo` in this scope --> $DIR/subdiagnostic-derive.rs:63:3 | @@ -475,6 +505,6 @@ error[E0425]: cannot find value `slug` in module `rustc_errors::fluent` LL | #[label(slug)] | ^^^^ not found in `rustc_errors::fluent` -error: aborting due to 67 previous errors +error: aborting due to 72 previous errors For more information about this error, try `rustc --explain E0425`. From dd51b36fb261513a0886d98c16be7fcc43c66272 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 20 Oct 2022 01:52:23 +0000 Subject: [PATCH 059/171] Add normalize hack back --- compiler/rustc_middle/src/ty/relate.rs | 15 ++++++++-- src/test/ui/consts/unnormalized-param-env.rs | 31 ++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/consts/unnormalized-param-env.rs diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index cdb618e030af..b25b4bd4fe36 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -574,8 +574,8 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( /// it. pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( relation: &mut R, - a: ty::Const<'tcx>, - b: ty::Const<'tcx>, + mut a: ty::Const<'tcx>, + mut b: ty::Const<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b); let tcx = relation.tcx(); @@ -596,6 +596,17 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( ); } + // HACK(const_generics): We still need to eagerly evaluate consts when + // relating them because during `normalize_param_env_or_error`, + // we may relate an evaluated constant in a obligation against + // an unnormalized (i.e. unevaluated) const in the param-env. + // FIXME(generic_const_exprs): Once we always lazily unify unevaluated constants + // these `eval` calls can be removed. + if !relation.tcx().features().generic_const_exprs { + a = a.eval(tcx, relation.param_env()); + b = b.eval(tcx, relation.param_env()); + } + // Currently, the values that can be unified are primitive types, // and those that derive both `PartialEq` and `Eq`, corresponding // to structural-match types. diff --git a/src/test/ui/consts/unnormalized-param-env.rs b/src/test/ui/consts/unnormalized-param-env.rs new file mode 100644 index 000000000000..a7bbe4db9929 --- /dev/null +++ b/src/test/ui/consts/unnormalized-param-env.rs @@ -0,0 +1,31 @@ +// check-pass + +pub trait CSpace { + type Traj; +} + +pub struct Const; + +pub trait Obstacle { + fn trajectory_free(&self, t: &FT) + where + CS::Traj: Sized, + CS: CSpace; +} + +// ----- + +const N: usize = 4; + +struct ObstacleSpace2df32; + +impl Obstacle for ObstacleSpace2df32 { + fn trajectory_free(&self, t: &TF) + where + CS::Traj: Sized, + CS: CSpace, + { + } +} + +fn main() {} From 6e6fe30d0f7e3dcbbf3988650311cee179992e5d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 20 Oct 2022 17:53:29 +0000 Subject: [PATCH 060/171] Comment why normalization is needed for debug assertions --- compiler/rustc_const_eval/src/interpret/operand.rs | 9 ++++++++- compiler/rustc_mir_build/src/thir/pattern/mod.rs | 7 ++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 719588a936ce..0c212cf59e17 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -554,6 +554,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { val: &mir::ConstantKind<'tcx>, layout: Option>, ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { + // FIXME(const_prop): normalization needed b/c const prop lint in + // `mir_drops_elaborated_and_const_checked`, which happens before + // optimized MIR. Only after optimizing the MIR can we guarantee + // that the `RevealAll` pass has happened and that the body's consts + // are normalized, so any call to resolve before that needs to be + // manually normalized. + let val = self.tcx.normalize_erasing_regions(self.param_env, *val); match val { mir::ConstantKind::Ty(ct) => { match ct.kind() { @@ -585,7 +592,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } } - mir::ConstantKind::Val(val, ty) => self.const_val_to_op(*val, *ty, layout), + mir::ConstantKind::Val(val, ty) => self.const_val_to_op(val, ty, layout), mir::ConstantKind::Unevaluated(uv, _) => { let instance = self.resolve(uv.def, uv.substs)?; Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into()) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 895af80bd7f3..2526522a25c8 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -483,7 +483,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // Use `Reveal::All` here because patterns are always monomorphic even if their function // isn't. let param_env_reveal_all = self.param_env.with_reveal_all_normalized(self.tcx); - let substs = self.typeck_results.node_substs(id); + // N.B. There is no guarantee that substs collected in typeck results are fully normalized, + // so they need to be normalized in order to pass to `Instance::resolve`, which will ICE + // if given unnormalized types. + let substs = self + .tcx + .normalize_erasing_regions(param_env_reveal_all, self.typeck_results.node_substs(id)); let instance = match ty::Instance::resolve(self.tcx, param_env_reveal_all, def_id, substs) { Ok(Some(i)) => i, Ok(None) => { From e521a8d46b4437f94ba1bb85826bb7d00ba13436 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 5 Oct 2022 19:59:45 +0100 Subject: [PATCH 061/171] Prevent foreign Rust exceptions from being caught --- library/panic_unwind/src/gcc.rs | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs index 261404e8795f..777ae41fab12 100644 --- a/library/panic_unwind/src/gcc.rs +++ b/library/panic_unwind/src/gcc.rs @@ -38,12 +38,23 @@ use alloc::boxed::Box; use core::any::Any; +use core::ptr; use unwind as uw; +// In case where multiple copies of std is compiled into a single binary, +// we use address of this static variable to distinguish an exception raised by +// this copy and some other copy (which needs to be treated as foreign exception). +static CANARY: u8 = 0; + +// NOTE(nbdd0121) +// Once `c_unwind` feature is stabilized, there will be ABI stability requirement +// on this struct. The first two field must be `_Unwind_Exception` and `canary`, +// as it may be accessed by a different version of the std with a different compiler. #[repr(C)] struct Exception { _uwe: uw::_Unwind_Exception, + canary: *const u8, cause: Box, } @@ -54,6 +65,7 @@ pub unsafe fn panic(data: Box) -> u32 { exception_cleanup, private: [0; uw::unwinder_private_data_size], }, + canary: &CANARY, cause: data, }); let exception_param = Box::into_raw(exception) as *mut uw::_Unwind_Exception; @@ -75,10 +87,22 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box { if (*exception).exception_class != rust_exception_class() { uw::_Unwind_DeleteException(exception); super::__rust_foreign_exception(); - } else { - let exception = Box::from_raw(exception as *mut Exception); - exception.cause } + + let exception = exception.cast::(); + // Just access the canary field, avoid accessing the entire `Exception` as + // it can be a foreign Rust exception. + let canary = ptr::addr_of!((*exception).canary).read(); + if !ptr::eq(canary, &CANARY) { + // A foreign Rust exception, treat it slightly differently from other + // foreign exceptions, because call into `_Unwind_DeleteException` will + // call into `__rust_drop_panic` which produces a confusing + // "Rust panic must be rethrown" message. + super::__rust_foreign_exception(); + } + + let exception = Box::from_raw(exception as *mut Exception); + exception.cause } // Rust's exception class identifier. This is used by personality routines to From 86c65d2c1ce5aba2c1c74298c3e42696cff1d41a Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 5 Oct 2022 22:40:07 +0100 Subject: [PATCH 062/171] Implement Rust foreign exception protection for EMCC and SEH --- library/panic_unwind/src/emcc.rs | 37 +++++++++++++++++++++++--------- library/panic_unwind/src/seh.rs | 20 ++++++++++++----- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/library/panic_unwind/src/emcc.rs b/library/panic_unwind/src/emcc.rs index 7c233c7c3a1c..57e817ce6ad5 100644 --- a/library/panic_unwind/src/emcc.rs +++ b/library/panic_unwind/src/emcc.rs @@ -47,7 +47,12 @@ static EXCEPTION_TYPE_INFO: TypeInfo = TypeInfo { name: b"rust_panic\0".as_ptr(), }; +// NOTE(nbdd0121): The `canary` field will be part of stable ABI after `c_unwind` stabilization. +#[repr(C)] struct Exception { + // See `gcc.rs` on why this is present. We already have a static here so just use it. + canary: *const TypeInfo, + // This is necessary because C++ code can capture our exception with // std::exception_ptr and rethrow it multiple times, possibly even in // another thread. @@ -70,16 +75,21 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box { let catch_data = &*(ptr as *mut CatchData); let adjusted_ptr = __cxa_begin_catch(catch_data.ptr as *mut libc::c_void) as *mut Exception; - let out = if catch_data.is_rust_panic { - let was_caught = (*adjusted_ptr).caught.swap(true, Ordering::SeqCst); - if was_caught { - // Since cleanup() isn't allowed to panic, we just abort instead. - intrinsics::abort(); - } - (*adjusted_ptr).data.take().unwrap() - } else { + if !catch_data.is_rust_panic { super::__rust_foreign_exception(); - }; + } + + let canary = ptr::addr_of!((*adjusted_ptr).canary).read(); + if !ptr::eq(canary, &EXCEPTION_TYPE_INFO) { + super::__rust_foreign_exception(); + } + + let was_caught = (*adjusted_ptr).caught.swap(true, Ordering::SeqCst); + if was_caught { + // Since cleanup() isn't allowed to panic, we just abort instead. + intrinsics::abort(); + } + let out = (*adjusted_ptr).data.take().unwrap(); __cxa_end_catch(); out } @@ -90,7 +100,14 @@ pub unsafe fn panic(data: Box) -> u32 { if exception.is_null() { return uw::_URC_FATAL_PHASE1_ERROR as u32; } - ptr::write(exception, Exception { caught: AtomicBool::new(false), data: Some(data) }); + ptr::write( + exception, + Exception { + canary: &EXCEPTION_TYPE_INFO, + caught: AtomicBool::new(false), + data: Some(data), + }, + ); __cxa_throw(exception as *mut _, &EXCEPTION_TYPE_INFO, exception_cleanup); } diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs index 6b8d06568611..651115a8248a 100644 --- a/library/panic_unwind/src/seh.rs +++ b/library/panic_unwind/src/seh.rs @@ -49,9 +49,15 @@ use alloc::boxed::Box; use core::any::Any; use core::mem::{self, ManuallyDrop}; +use core::ptr; use libc::{c_int, c_uint, c_void}; +// NOTE(nbdd0121): The `canary` field will be part of stable ABI after `c_unwind` stabilization. +#[repr(C)] struct Exception { + // See `gcc.rs` on why this is present. We already have a static here so just use it. + canary: *const _TypeDescriptor, + // This needs to be an Option because we catch the exception by reference // and its destructor is executed by the C++ runtime. When we take the Box // out of the exception, we need to leave the exception in a valid state @@ -235,7 +241,7 @@ static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor { macro_rules! define_cleanup { ($abi:tt $abi2:tt) => { unsafe extern $abi fn exception_cleanup(e: *mut Exception) { - if let Exception { data: Some(b) } = e.read() { + if let Exception { data: Some(b), .. } = e.read() { drop(b); super::__rust_drop_panic(); } @@ -265,7 +271,7 @@ pub unsafe fn panic(data: Box) -> u32 { // The ManuallyDrop is needed here since we don't want Exception to be // dropped when unwinding. Instead it will be dropped by exception_cleanup // which is invoked by the C++ runtime. - let mut exception = ManuallyDrop::new(Exception { data: Some(data) }); + let mut exception = ManuallyDrop::new(Exception { canary: &TYPE_DESCRIPTOR, data: Some(data) }); let throw_ptr = &mut exception as *mut _ as *mut _; // This... may seems surprising, and justifiably so. On 32-bit MSVC the @@ -321,8 +327,12 @@ pub unsafe fn cleanup(payload: *mut u8) -> Box { // __rust_try. This happens when a non-Rust foreign exception is caught. if payload.is_null() { super::__rust_foreign_exception(); - } else { - let exception = &mut *(payload as *mut Exception); - exception.data.take().unwrap() } + let exception = payload as *mut Exception; + let canary = ptr::addr_of!((*exception).canary).read(); + if !ptr::eq(canary, &TYPE_DESCRIPTOR) { + // A foreign Rust exception. + super::__rust_foreign_exception(); + } + (*exception).data.take().unwrap() } From daf3063056d6c3dbd402d5b940f0b28aac0e1dff Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 5 Oct 2022 23:58:35 +0100 Subject: [PATCH 063/171] Add test case for foreign Rust exceptions --- .../foreign-rust-exceptions/Makefile | 6 ++++++ .../run-make-fulldeps/foreign-rust-exceptions/bar.rs | 7 +++++++ .../run-make-fulldeps/foreign-rust-exceptions/foo.rs | 12 ++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile create mode 100644 src/test/run-make-fulldeps/foreign-rust-exceptions/bar.rs create mode 100644 src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs diff --git a/src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile b/src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile new file mode 100644 index 000000000000..24d9742aef0b --- /dev/null +++ b/src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile @@ -0,0 +1,6 @@ +include ../tools.mk + +all: + $(RUSTC) bar.rs --crate-type=cdylib + $(RUSTC) foo.rs + $(call RUN,foo) 2>&1 | $(CGREP) "Rust cannot catch foreign exceptions" diff --git a/src/test/run-make-fulldeps/foreign-rust-exceptions/bar.rs b/src/test/run-make-fulldeps/foreign-rust-exceptions/bar.rs new file mode 100644 index 000000000000..5f9efe323609 --- /dev/null +++ b/src/test/run-make-fulldeps/foreign-rust-exceptions/bar.rs @@ -0,0 +1,7 @@ +#![crate_type = "cdylib"] +#![feature(c_unwind)] + +#[no_mangle] +extern "C-unwind" fn panic() { + panic!(); +} diff --git a/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs b/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs new file mode 100644 index 000000000000..d6a6d94a1949 --- /dev/null +++ b/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs @@ -0,0 +1,12 @@ +#![feature(c_unwind)] + +#[link(name = "bar")] +extern "C-unwind" { + fn panic(); +} + +fn main() { + let _ = std::panic::catch_unwind(|| { + unsafe { panic() }; + }); +} From 979d1a2c78a3fd45807eb28ccff5aeea37128e0f Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 11 Oct 2022 18:02:07 +0100 Subject: [PATCH 064/171] Apply suggestion Co-authored-by: Amanieu d'Antras --- library/panic_unwind/src/gcc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs index 777ae41fab12..0b7a873a691c 100644 --- a/library/panic_unwind/src/gcc.rs +++ b/library/panic_unwind/src/gcc.rs @@ -42,7 +42,7 @@ use core::ptr; use unwind as uw; -// In case where multiple copies of std is compiled into a single binary, +// In case where multiple copies of std exist in a single process, // we use address of this static variable to distinguish an exception raised by // this copy and some other copy (which needs to be treated as foreign exception). static CANARY: u8 = 0; From 4e6d60c837e178950b844bd1235c67ebbb6a5899 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 12 Oct 2022 12:24:59 +0100 Subject: [PATCH 065/171] Fix alloc size --- library/panic_unwind/src/emcc.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/panic_unwind/src/emcc.rs b/library/panic_unwind/src/emcc.rs index 57e817ce6ad5..c6d42308596c 100644 --- a/library/panic_unwind/src/emcc.rs +++ b/library/panic_unwind/src/emcc.rs @@ -95,8 +95,7 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box { } pub unsafe fn panic(data: Box) -> u32 { - let sz = mem::size_of_val(&data); - let exception = __cxa_allocate_exception(sz) as *mut Exception; + let exception = __cxa_allocate_exception(mem::size_of::()) as *mut Exception; if exception.is_null() { return uw::_URC_FATAL_PHASE1_ERROR as u32; } From 47704bbcc063c2a8f3e88b06cf2f54f6b64b5ae7 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 23 Oct 2022 19:35:47 +0000 Subject: [PATCH 066/171] Do not consider repeated lifetime params for elision. --- compiler/rustc_resolve/src/late.rs | 10 +++++----- ...ision-return-type-requires-explicit-lifetime.rs | 3 +++ ...n-return-type-requires-explicit-lifetime.stderr | 14 +++++++++++++- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index ba3d8f64bbc7..40e71d4fc751 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -565,7 +565,7 @@ struct LateResolutionVisitor<'a, 'b, 'ast> { /// They will be used to determine the correct lifetime for the fn return type. /// The `LifetimeElisionCandidate` is used for diagnostics, to suggest introducing named /// lifetimes. - lifetime_elision_candidates: Option>, + lifetime_elision_candidates: Option>, /// The trait that the current context can refer to. current_trait_ref: Option<(Module<'a>, TraitRef)>, @@ -1799,7 +1799,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { match res { LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static => { if let Some(ref mut candidates) = self.lifetime_elision_candidates { - candidates.insert(res, candidate); + candidates.push((res, candidate)); } } LifetimeRes::Infer | LifetimeRes::Error | LifetimeRes::ElidedAnchor { .. } => {} @@ -1910,8 +1910,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // We do not have a `self` candidate, look at the full list. let all_candidates = all_candidates.unwrap(); - if all_candidates.len() == 1 { - Ok(*all_candidates.first().unwrap().0) + if let [(res, _)] = &all_candidates[..] { + Ok(*res) } else { let all_candidates = all_candidates .into_iter() @@ -2391,7 +2391,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // Do not account for the parameters we just bound for function lifetime elision. if let Some(ref mut candidates) = self.lifetime_elision_candidates { for (_, res) in function_lifetime_rib.bindings.values() { - candidates.remove(res); + candidates.retain(|(r, _)| r != res); } } diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs index 7a2eba518fef..ba769a4bcc0a 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs @@ -42,4 +42,7 @@ fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &isize { panic!() } +fn l<'a>(_: &'a str, _: &'a str) -> &str { "" } +//~^ ERROR missing lifetime specifier + fn main() {} diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr index d07754879559..5eee953ef189 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -70,6 +70,18 @@ help: consider using the `'a` lifetime LL | fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &'a isize { | ++ -error: aborting due to 6 previous errors +error[E0106]: missing lifetime specifier + --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:45:37 + | +LL | fn l<'a>(_: &'a str, _: &'a str) -> &str { "" } + | ------- ------- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments +help: consider using the `'a` lifetime + | +LL | fn l<'a>(_: &'a str, _: &'a str) -> &'a str { "" } + | ++ + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0106`. From c9cca33e85352c6ffd0c29a22c7302ca5f761ba3 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sun, 23 Oct 2022 21:30:37 +0100 Subject: [PATCH 067/171] Fix windows compilation --- src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs b/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs index d6a6d94a1949..266987c5b6d6 100644 --- a/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs +++ b/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs @@ -1,6 +1,7 @@ #![feature(c_unwind)] -#[link(name = "bar")] +#[cfg_attr(not(windows), link(name = "bar"))] +#[cfg_attr(windows, link(name = "bar.dll"))] extern "C-unwind" { fn panic(); } From be2401b8bfc824026b477f11b876b5611cb204c0 Mon Sep 17 00:00:00 2001 From: Jakob Degen Date: Mon, 26 Sep 2022 18:43:35 -0700 Subject: [PATCH 068/171] Split phase change from `MirPass` --- .../src/transform/promote_consts.rs | 4 - compiler/rustc_middle/src/mir/mod.rs | 39 ++++++-- compiler/rustc_mir_transform/src/lib.rs | 21 ++--- compiler/rustc_mir_transform/src/marker.rs | 20 ----- .../rustc_mir_transform/src/pass_manager.rs | 89 ++++++++++++------- compiler/rustc_mir_transform/src/shim.rs | 4 +- 6 files changed, 101 insertions(+), 76 deletions(-) delete mode 100644 compiler/rustc_mir_transform/src/marker.rs diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 4b219300739c..f3ae16da43bd 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -41,10 +41,6 @@ pub struct PromoteTemps<'tcx> { } impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { - fn phase_change(&self) -> Option { - Some(MirPhase::Analysis(AnalysisPhase::Initial)) - } - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // There's not really any point in promoting errorful MIR. // diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index e0e823e2090e..3b80af184be4 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -116,11 +116,6 @@ pub trait MirPass<'tcx> { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>); - /// If this pass causes the MIR to enter a new phase, return that phase. - fn phase_change(&self) -> Option { - None - } - fn is_mir_dump_enabled(&self) -> bool { true } @@ -145,6 +140,35 @@ impl MirPhase { } } +impl Display for MirPhase { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + MirPhase::Built => write!(f, "built"), + MirPhase::Analysis(p) => write!(f, "analysis-{}", p), + MirPhase::Runtime(p) => write!(f, "runtime-{}", p), + } + } +} + +impl Display for AnalysisPhase { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + AnalysisPhase::Initial => write!(f, "initial"), + AnalysisPhase::PostCleanup => write!(f, "post_cleanup"), + } + } +} + +impl Display for RuntimePhase { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + RuntimePhase::Initial => write!(f, "initial"), + RuntimePhase::PostCleanup => write!(f, "post_cleanup"), + RuntimePhase::Optimized => write!(f, "optimized"), + } + } +} + /// Where a specific `mir::Body` comes from. #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] @@ -207,6 +231,9 @@ pub struct Body<'tcx> { /// us to see the difference and forego optimization on the inlined promoted items. pub phase: MirPhase, + /// How many passses we have executed since starting the current phase. Used for debug output. + pub pass_count: usize, + pub source: MirSource<'tcx>, /// A list of source scopes; these are referenced by statements @@ -292,6 +319,7 @@ impl<'tcx> Body<'tcx> { let mut body = Body { phase: MirPhase::Built, + pass_count: 1, source, basic_blocks: BasicBlocks::new(basic_blocks), source_scopes, @@ -325,6 +353,7 @@ impl<'tcx> Body<'tcx> { pub fn new_cfg_only(basic_blocks: IndexVec>) -> Self { let mut body = Body { phase: MirPhase::Built, + pass_count: 1, source: MirSource::item(CRATE_DEF_ID.to_def_id()), basic_blocks: BasicBlocks::new(basic_blocks), source_scopes: IndexVec::new(), diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 5c411fa56578..5be2232547bd 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -71,7 +71,6 @@ mod inline; mod instcombine; mod lower_intrinsics; mod lower_slice_len; -mod marker; mod match_branches; mod multiple_return_terminators; mod normalize_array_len; @@ -303,6 +302,7 @@ fn mir_const<'tcx>( &simplify::SimplifyCfg::new("initial"), &rustc_peek::SanityCheck, // Just a lint ], + None, ); tcx.alloc_steal_mir(body) } @@ -342,6 +342,7 @@ fn mir_promoted<'tcx>( &simplify::SimplifyCfg::new("promote-consts"), &coverage::InstrumentCoverage, ], + Some(MirPhase::Analysis(AnalysisPhase::Initial)), ); let promoted = promote_pass.promoted_fragments.into_inner(); @@ -409,10 +410,8 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) - pm::run_passes( tcx, &mut body, - &[ - &const_prop::ConstProp, - &marker::PhaseChange(MirPhase::Runtime(RuntimePhase::Optimized)), - ], + &[&const_prop::ConstProp], + Some(MirPhase::Runtime(RuntimePhase::Optimized)), ); } } @@ -474,6 +473,7 @@ fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx> &remove_uninit_drops::RemoveUninitDrops, &simplify::SimplifyCfg::new("remove-false-edges"), ], + None, ); check_consts::post_drop_elaboration::check_live_drops(tcx, &body); // FIXME: make this a MIR lint } @@ -498,10 +498,9 @@ fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &cleanup_post_borrowck::CleanupNonCodegenStatements, &simplify::SimplifyCfg::new("early-opt"), &deref_separator::Derefer, - &marker::PhaseChange(MirPhase::Analysis(AnalysisPhase::PostCleanup)), ]; - pm::run_passes(tcx, body, passes); + pm::run_passes(tcx, body, passes, Some(MirPhase::Analysis(AnalysisPhase::PostCleanup))); } /// Returns the sequence of passes that lowers analysis to runtime MIR. @@ -526,9 +525,8 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // CTFE support for aggregates. &deaggregator::Deaggregator, &Lint(const_prop_lint::ConstProp), - &marker::PhaseChange(MirPhase::Runtime(RuntimePhase::Initial)), ]; - pm::run_passes_no_validate(tcx, body, passes); + pm::run_passes_no_validate(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::Initial))); } /// Returns the sequence of passes that do the initial cleanup of runtime MIR. @@ -537,10 +535,9 @@ fn run_runtime_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &elaborate_box_derefs::ElaborateBoxDerefs, &lower_intrinsics::LowerIntrinsics, &simplify::SimplifyCfg::new("elaborate-drops"), - &marker::PhaseChange(MirPhase::Runtime(RuntimePhase::PostCleanup)), ]; - pm::run_passes(tcx, body, passes); + pm::run_passes(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::PostCleanup))); } fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -591,10 +588,10 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &deduplicate_blocks::DeduplicateBlocks, // Some cleanup necessary at least for LLVM and potentially other codegen backends. &add_call_guards::CriticalCallEdges, - &marker::PhaseChange(MirPhase::Runtime(RuntimePhase::Optimized)), // Dump the end result for testing and debugging purposes. &dump_mir::Marker("PreCodegen"), ], + Some(MirPhase::Runtime(RuntimePhase::Optimized)), ); } diff --git a/compiler/rustc_mir_transform/src/marker.rs b/compiler/rustc_mir_transform/src/marker.rs deleted file mode 100644 index 06819fc1d37d..000000000000 --- a/compiler/rustc_mir_transform/src/marker.rs +++ /dev/null @@ -1,20 +0,0 @@ -use std::borrow::Cow; - -use crate::MirPass; -use rustc_middle::mir::{Body, MirPhase}; -use rustc_middle::ty::TyCtxt; - -/// Changes the MIR phase without changing the MIR itself. -pub struct PhaseChange(pub MirPhase); - -impl<'tcx> MirPass<'tcx> for PhaseChange { - fn phase_change(&self) -> Option { - Some(self.0) - } - - fn name(&self) -> Cow<'_, str> { - Cow::from(format!("PhaseChange-{:?}", self.0)) - } - - fn run_pass(&self, _: TyCtxt<'tcx>, _body: &mut Body<'tcx>) {} -} diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 67dae71468f9..230c6a7cb4b0 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -66,10 +66,6 @@ where fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { self.1.run_pass(tcx, body) } - - fn phase_change(&self) -> Option { - self.1.phase_change() - } } /// Run the sequence of passes without validating the MIR after each pass. The MIR is still @@ -78,23 +74,28 @@ pub fn run_passes_no_validate<'tcx>( tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, passes: &[&dyn MirPass<'tcx>], + phase_change: Option, ) { - run_passes_inner(tcx, body, passes, false); + run_passes_inner(tcx, body, passes, phase_change, false); } -pub fn run_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, passes: &[&dyn MirPass<'tcx>]) { - run_passes_inner(tcx, body, passes, true); +/// The optional `phase_change` is applied after executing all the passes, if present +pub fn run_passes<'tcx>( + tcx: TyCtxt<'tcx>, + body: &mut Body<'tcx>, + passes: &[&dyn MirPass<'tcx>], + phase_change: Option, +) { + run_passes_inner(tcx, body, passes, phase_change, true); } fn run_passes_inner<'tcx>( tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, passes: &[&dyn MirPass<'tcx>], + phase_change: Option, validate_each: bool, ) { - let start_phase = body.phase; - let mut cnt = 0; - let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir; let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes; trace!(?overridden_passes); @@ -102,7 +103,6 @@ fn run_passes_inner<'tcx>( for pass in passes { let name = pass.name(); - // Gather information about what we should be doing for this pass let overridden = overridden_passes.iter().rev().find(|(s, _)| s == &*name).map(|(_name, polarity)| { trace!( @@ -112,32 +112,44 @@ fn run_passes_inner<'tcx>( ); *polarity }); - let is_enabled = overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)); - let new_phase = pass.phase_change(); - let dump_enabled = (is_enabled && pass.is_mir_dump_enabled()) || new_phase.is_some(); - let validate = (validate && is_enabled) - || new_phase == Some(MirPhase::Runtime(RuntimePhase::Optimized)); + if !overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)) { + continue; + } + + let dump_enabled = pass.is_mir_dump_enabled(); if dump_enabled { - dump_mir(tcx, body, start_phase, &name, cnt, false); + dump_mir_for_pass(tcx, body, &name, false); } - if is_enabled { - pass.run_pass(tcx, body); + if validate { + validate_body(tcx, body, format!("before pass {}", name)); } - if dump_enabled { - dump_mir(tcx, body, start_phase, &name, cnt, true); - cnt += 1; - } - if let Some(new_phase) = pass.phase_change() { - if body.phase >= new_phase { - panic!("Invalid MIR phase transition from {:?} to {:?}", body.phase, new_phase); - } - body.phase = new_phase; + pass.run_pass(tcx, body); + + if dump_enabled { + dump_mir_for_pass(tcx, body, &name, true); } if validate { validate_body(tcx, body, format!("after pass {}", name)); } + + body.pass_count += 1; + } + + if let Some(new_phase) = phase_change { + if body.phase >= new_phase { + panic!("Invalid MIR phase transition from {:?} to {:?}", body.phase, new_phase); + } + + body.phase = new_phase; + + dump_mir_for_phase_change(tcx, body); + if validate || new_phase == MirPhase::Runtime(RuntimePhase::Optimized) { + validate_body(tcx, body, format!("after phase change to {}", new_phase)); + } + + body.pass_count = 1; } } @@ -145,22 +157,33 @@ pub fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: Strin validate::Validator { when, mir_phase: body.phase }.run_pass(tcx, body); } -pub fn dump_mir<'tcx>( +pub fn dump_mir_for_pass<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, - phase: MirPhase, pass_name: &str, - cnt: usize, is_after: bool, ) { - let phase_index = phase.phase_index(); + let phase_index = body.phase.phase_index(); mir::dump_mir( tcx, - Some(&format_args!("{:03}-{:03}", phase_index, cnt)), + Some(&format_args!("{:03}-{:03}", phase_index, body.pass_count)), pass_name, if is_after { &"after" } else { &"before" }, body, |_, _| Ok(()), ); } + +pub fn dump_mir_for_phase_change<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { + let phase_index = body.phase.phase_index(); + + mir::dump_mir( + tcx, + Some(&format_args!("{:03}-000", phase_index)), + &format!("{}", body.phase), + &"after", + body, + |_, _| Ok(()), + ) +} diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 6ca58ee458c5..c19380ef89cc 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -17,7 +17,7 @@ use std::iter; use crate::util::expand_aggregate; use crate::{ - abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, deref_separator, marker, + abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, deref_separator, pass_manager as pm, remove_noop_landing_pads, simplify, }; use rustc_middle::mir::patch::MirPatch; @@ -97,8 +97,8 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' &simplify::SimplifyCfg::new("make_shim"), &add_call_guards::CriticalCallEdges, &abort_unwinding_calls::AbortUnwindingCalls, - &marker::PhaseChange(MirPhase::Runtime(RuntimePhase::Optimized)), ], + Some(MirPhase::Runtime(RuntimePhase::Optimized)), ); debug!("make_shim({:?}) = {:?}", instance, result); From f54c336c8019432803dd9a67b575053ffc03c372 Mon Sep 17 00:00:00 2001 From: yukang Date: Sat, 22 Oct 2022 07:56:26 +0800 Subject: [PATCH 069/171] fix #103425, remove extra type error after missing semicolon error --- compiler/rustc_parse/src/parser/stmt.rs | 63 ++++++++++++++----------- src/test/ui/parser/issue-103425.rs | 15 ++++++ src/test/ui/parser/issue-103425.stderr | 29 ++++++++++++ 3 files changed, 79 insertions(+), 28 deletions(-) create mode 100644 src/test/ui/parser/issue-103425.rs create mode 100644 src/test/ui/parser/issue-103425.stderr diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index a61e77b7c3bf..12753c6785c9 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -553,39 +553,46 @@ impl<'a> Parser<'a> { match stmt.kind { // Expression without semicolon. StmtKind::Expr(ref mut expr) - if self.token != token::Eof && classify::expr_requires_semi_to_be_stmt(expr) => - { + if self.token != token::Eof && classify::expr_requires_semi_to_be_stmt(expr) => { // Just check for errors and recover; do not eat semicolon yet. - if let Err(mut e) = - self.expect_one_of(&[], &[token::Semi, token::CloseDelim(Delimiter::Brace)]) - { - if let TokenKind::DocComment(..) = self.token.kind { - if let Ok(snippet) = self.span_to_snippet(self.token.span) { - let sp = self.token.span; - let marker = &snippet[..3]; - let (comment_marker, doc_comment_marker) = marker.split_at(2); + // `expect_one_of` returns PResult<'a, bool /* recovered */> + let replace_with_err = + match self.expect_one_of(&[], &[token::Semi, token::CloseDelim(Delimiter::Brace)]) { + // Recover from parser, skip type error to avoid extra errors. + Ok(true) => true, + Err(mut e) => { + if let TokenKind::DocComment(..) = self.token.kind && + let Ok(snippet) = self.span_to_snippet(self.token.span) { + let sp = self.token.span; + let marker = &snippet[..3]; + let (comment_marker, doc_comment_marker) = marker.split_at(2); - e.span_suggestion( - sp.with_hi(sp.lo() + BytePos(marker.len() as u32)), - &format!( - "add a space before `{}` to use a regular comment", - doc_comment_marker, - ), - format!("{} {}", comment_marker, doc_comment_marker), - Applicability::MaybeIncorrect, - ); + e.span_suggestion( + sp.with_hi(sp.lo() + BytePos(marker.len() as u32)), + &format!( + "add a space before `{}` to use a regular comment", + doc_comment_marker, + ), + format!("{} {}", comment_marker, doc_comment_marker), + Applicability::MaybeIncorrect, + ); } - } - if let Err(mut e) = - self.check_mistyped_turbofish_with_multiple_type_params(e, expr) - { - if recover.no() { - return Err(e); + + if let Err(mut e) = + self.check_mistyped_turbofish_with_multiple_type_params(e, expr) + { + if recover.no() { + return Err(e); + } + e.emit(); + self.recover_stmt(); } - e.emit(); - self.recover_stmt(); + true } - // Don't complain about type errors in body tail after parse error (#57383). + _ => false + }; + if replace_with_err { + // We already emitted an error, so don't emit another type error let sp = expr.span.to(self.prev_token.span); *expr = self.mk_expr_err(sp); } diff --git a/src/test/ui/parser/issue-103425.rs b/src/test/ui/parser/issue-103425.rs new file mode 100644 index 000000000000..c2f8123ca4e6 --- /dev/null +++ b/src/test/ui/parser/issue-103425.rs @@ -0,0 +1,15 @@ +fn f() -> f32 { + 3 + //~^ ERROR expected `;` + 5.0 +} + +fn k() -> f32 { + 2_u32 + //~^ ERROR expected `;` + 3_i8 + //~^ ERROR expected `;` + 5.0 +} + +fn main() {} diff --git a/src/test/ui/parser/issue-103425.stderr b/src/test/ui/parser/issue-103425.stderr new file mode 100644 index 000000000000..0efe3e3ca711 --- /dev/null +++ b/src/test/ui/parser/issue-103425.stderr @@ -0,0 +1,29 @@ +error: expected `;`, found `5.0` + --> $DIR/issue-103425.rs:2:6 + | +LL | 3 + | ^ help: add `;` here +LL | +LL | 5.0 + | --- unexpected token + +error: expected `;`, found `3_i8` + --> $DIR/issue-103425.rs:8:10 + | +LL | 2_u32 + | ^ help: add `;` here +LL | +LL | 3_i8 + | ---- unexpected token + +error: expected `;`, found `5.0` + --> $DIR/issue-103425.rs:10:9 + | +LL | 3_i8 + | ^ help: add `;` here +LL | +LL | 5.0 + | --- unexpected token + +error: aborting due to 3 previous errors + From 56735361536773aee70f44b76438d1a07b7062e3 Mon Sep 17 00:00:00 2001 From: Pointerbender <81013316+Pointerbender@users.noreply.github.com> Date: Mon, 24 Oct 2022 04:27:37 +0200 Subject: [PATCH 070/171] fix typos Co-authored-by: Ralf Jung --- library/core/src/cell.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 12c6f2117259..fe5dd7be8f6b 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1827,8 +1827,8 @@ impl fmt::Display for RefMut<'_, T> { /// order to avoid its interior mutability property from spreading from `T` into the `Outer` type, /// thus this can cause distortions in the type size in these cases. /// -/// Note that it is still only valid to obtain a `*mut T` pointer to the contents of a -/// _shared_ `UnsafeCell` through [`.get()`] or [`.raw_get()`]. A `&mut T` reference +/// Note that the only valid way to obtain a `*mut T` pointer to the contents of a +/// _shared_ `UnsafeCell` is through [`.get()`] or [`.raw_get()`]. A `&mut T` reference /// can be obtained by either dereferencing this pointer or by calling [`.get_mut()`] /// on an _exclusive_ `UnsafeCell`. Even though `T` and `UnsafeCell` have the /// same memory layout, the following is not allowed and undefined behavior: From 63d1a721f187faf007e8540e4d5b6b2e494231eb Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Sun, 23 Oct 2022 02:47:20 -0700 Subject: [PATCH 071/171] rustdoc: don't mark Box as Iterator, Read, etc Because Box has pass-through implementations, rustdoc was giving it the "Notable Traits" treatment for Iterator, Read, Write, and Future, even when the type of T was unspecified. Pin had the same problem, but just for Future. --- src/librustdoc/html/render/mod.rs | 9 +++++ ...oc-notable_trait_box_is_not_an_iterator.rs | 38 +++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 src/test/rustdoc/doc-notable_trait_box_is_not_an_iterator.rs diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index cd56d73e7d47..b2fac7228272 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1276,6 +1276,15 @@ fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String { if let Some((did, ty)) = decl.output.as_return().and_then(|t| Some((t.def_id(cx.cache())?, t))) { + // Box has pass-through impls for Read, Write, Iterator, and Future when the + // boxed type implements one of those. We don't want to treat every Box return + // as being notably an Iterator (etc), though, so we exempt it. Pin has the same + // issue, with a pass-through impl for Future. + if Some(did) == cx.tcx().lang_items().owned_box() + || Some(did) == cx.tcx().lang_items().pin_type() + { + return "".to_string(); + } if let Some(impls) = cx.cache().impls.get(&did) { for i in impls { let impl_ = i.inner_impl(); diff --git a/src/test/rustdoc/doc-notable_trait_box_is_not_an_iterator.rs b/src/test/rustdoc/doc-notable_trait_box_is_not_an_iterator.rs new file mode 100644 index 000000000000..3fb00c7db841 --- /dev/null +++ b/src/test/rustdoc/doc-notable_trait_box_is_not_an_iterator.rs @@ -0,0 +1,38 @@ +#![feature(doc_notable_trait)] +#![feature(lang_items)] +#![feature(no_core)] +#![no_core] +#[lang = "owned_box"] +pub struct Box; + +impl Box { + pub fn new(x: T) -> Box { + Box + } +} + +#[doc(notable_trait)] +pub trait FakeIterator {} + +impl FakeIterator for Box {} + +#[lang = "pin"] +pub struct Pin; + +impl Pin { + pub fn new(x: T) -> Pin { + Pin + } +} + +impl FakeIterator for Pin {} + +// @!has doc_notable_trait_box_is_not_an_iterator/fn.foo.html '//*' 'Notable' +pub fn foo(x: T) -> Box { + Box::new(x) +} + +// @!has doc_notable_trait_box_is_not_an_iterator/fn.bar.html '//*' 'Notable' +pub fn bar(x: T) -> Pin { + Pin::new(x) +} From 0fca075ce8a2247b6d59cd8eaf2fd1d6b89855d8 Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Wed, 12 Oct 2022 17:07:30 +0800 Subject: [PATCH 072/171] suggest type annotation for local statement initialed by ref expression --- compiler/rustc_hir_typeck/src/demand.rs | 19 ++++++- .../src/fn_ctxt/suggestions.rs | 47 ++++++++++++++- src/test/ui/suggestions/format-borrow.stderr | 16 ++++++ src/test/ui/suggestions/issue-102892.rs | 25 ++++++++ src/test/ui/suggestions/issue-102892.stderr | 57 +++++++++++++++++++ 5 files changed, 160 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/suggestions/issue-102892.rs create mode 100644 src/test/ui/suggestions/issue-102892.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 2974ac97f236..be14234afe28 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -714,7 +714,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &hir::Expr<'tcx>, checked_ty: Ty<'tcx>, expected: Ty<'tcx>, - ) -> Option<(Span, String, String, Applicability, bool /* verbose */)> { + ) -> Option<( + Span, + String, + String, + Applicability, + bool, /* verbose */ + bool, /* suggest `&` or `&mut` type annotation */ + )> { let sess = self.sess(); let sp = expr.span; @@ -746,6 +753,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { String::new(), Applicability::MachineApplicable, true, + false, )); } } @@ -760,6 +768,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "b".to_string(), Applicability::MachineApplicable, true, + false, )); } } @@ -817,6 +826,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sugg.2, Applicability::MachineApplicable, false, + false, )); } @@ -844,6 +854,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("{prefix}&mut {sugg_expr}"), Applicability::MachineApplicable, false, + false, ), hir::Mutability::Not => ( sp, @@ -851,6 +862,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("{prefix}&{sugg_expr}"), Applicability::MachineApplicable, false, + false, ), }); } @@ -880,6 +892,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { String::new(), Applicability::MachineApplicable, true, + true )); } return None; @@ -893,6 +906,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { String::new(), Applicability::MachineApplicable, true, + true, )); } } @@ -959,6 +973,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { src, applicability, true, + false, )); } } @@ -999,6 +1014,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable }, true, + false, )); } @@ -1050,6 +1066,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { suggestion, Applicability::MachineApplicable, true, + false, )); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index cd2e41aff0f1..4db9c56f98fe 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -327,7 +327,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, ) -> bool { let expr = expr.peel_blocks(); - if let Some((sp, msg, suggestion, applicability, verbose)) = + if let Some((sp, msg, suggestion, applicability, verbose, annotation)) = self.check_ref(expr, found, expected) { if verbose { @@ -335,9 +335,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { err.span_suggestion(sp, &msg, suggestion, applicability); } + if annotation { + let suggest_annotation = match expr.peel_drop_temps().kind { + hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, _) => "&", + hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, _) => "&mut ", + _ => return true, + }; + let mut tuple_indexes = Vec::new(); + let mut expr_id = expr.hir_id; + for (parent_id, node) in self.tcx.hir().parent_iter(expr.hir_id) { + match node { + Node::Expr(&Expr { kind: ExprKind::Tup(subs), .. }) => { + tuple_indexes.push( + subs.iter() + .enumerate() + .find(|(_, sub_expr)| sub_expr.hir_id == expr_id) + .unwrap() + .0, + ); + expr_id = parent_id; + } + Node::Local(local) => { + if let Some(mut ty) = local.ty { + while let Some(index) = tuple_indexes.pop() { + match ty.kind { + TyKind::Tup(tys) => ty = &tys[index], + _ => return true, + } + } + let annotation_span = ty.span; + err.span_suggestion( + annotation_span.with_hi(annotation_span.lo()), + format!("alternatively, consider changing the type annotation"), + suggest_annotation, + Applicability::MaybeIncorrect, + ); + } + break; + } + _ => break, + } + } + } return true; - } else if self.suggest_else_fn_with_closure(err, expr, found, expected) - { + } else if self.suggest_else_fn_with_closure(err, expr, found, expected) { return true; } else if self.suggest_fn_call(err, expr, found, |output| self.can_coerce(output, expected)) && let ty::FnDef(def_id, ..) = &found.kind() diff --git a/src/test/ui/suggestions/format-borrow.stderr b/src/test/ui/suggestions/format-borrow.stderr index fac6a5a5f48c..8ed2b9c9a633 100644 --- a/src/test/ui/suggestions/format-borrow.stderr +++ b/src/test/ui/suggestions/format-borrow.stderr @@ -11,6 +11,10 @@ help: consider removing the borrow LL - let a: String = &String::from("a"); LL + let a: String = String::from("a"); | +help: alternatively, consider changing the type annotation + | +LL | let a: &String = &String::from("a"); + | + error[E0308]: mismatched types --> $DIR/format-borrow.rs:4:21 @@ -25,6 +29,10 @@ help: consider removing the borrow LL - let b: String = &format!("b"); LL + let b: String = format!("b"); | +help: alternatively, consider changing the type annotation + | +LL | let b: &String = &format!("b"); + | + error[E0308]: mismatched types --> $DIR/format-borrow.rs:6:21 @@ -39,6 +47,10 @@ help: consider removing the borrow LL - let c: String = &mut format!("c"); LL + let c: String = format!("c"); | +help: alternatively, consider changing the type annotation + | +LL | let c: &mut String = &mut format!("c"); + | ++++ error[E0308]: mismatched types --> $DIR/format-borrow.rs:8:21 @@ -53,6 +65,10 @@ help: consider removing the borrow LL - let d: String = &mut (format!("d")); LL + let d: String = format!("d")); | +help: alternatively, consider changing the type annotation + | +LL | let d: &mut String = &mut (format!("d")); + | ++++ error: aborting due to 4 previous errors diff --git a/src/test/ui/suggestions/issue-102892.rs b/src/test/ui/suggestions/issue-102892.rs new file mode 100644 index 000000000000..c1a791d8d857 --- /dev/null +++ b/src/test/ui/suggestions/issue-102892.rs @@ -0,0 +1,25 @@ +#![allow(dead_code, unused_variables)] + +use std::sync::Arc; + +#[derive(Debug)] +struct A; +#[derive(Debug)] +struct B; + +fn process_without_annot(arc: &Arc<(A, B)>) { + let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed! +} + +fn process_with_annot(arc: &Arc<(A, B)>) { + let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too + //~^ ERROR mismatched types +} + +fn process_with_tuple_annot(mutation: &mut (A, B), arc: &Arc<(A, B)>) { + let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too + //~^ ERROR mismatched types + //~| ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-102892.stderr b/src/test/ui/suggestions/issue-102892.stderr new file mode 100644 index 000000000000..a3dbc7cb861f --- /dev/null +++ b/src/test/ui/suggestions/issue-102892.stderr @@ -0,0 +1,57 @@ +error[E0308]: mismatched types + --> $DIR/issue-102892.rs:15:26 + | +LL | let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too + | ------ ^^^^^^ expected tuple, found `&(A, B)` + | | + | expected due to this + | + = note: expected tuple `(A, B)` + found reference `&(A, B)` +help: consider removing the borrow + | +LL - let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too +LL + let (a, b): (A, B) = **arc; // suggests putting `&**arc` here too + | +help: alternatively, consider changing the type annotation + | +LL | let (a, b): &(A, B) = &**arc; // suggests putting `&**arc` here too + | + + +error[E0308]: mismatched types + --> $DIR/issue-102892.rs:20:32 + | +LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too + | ^^^^^^^^^^^^^^ expected tuple, found `&mut (A, B)` + | + = note: expected tuple `(A, B)` + found mutable reference `&mut (A, B)` +help: consider removing the borrow + | +LL - let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too +LL + let (a, b): ((A, B), A) = (*mutation, &(**arc).0); // suggests putting `&**arc` here too + | +help: alternatively, consider changing the type annotation + | +LL | let (a, b): (&mut (A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too + | ++++ + +error[E0308]: mismatched types + --> $DIR/issue-102892.rs:20:48 + | +LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too + | ^^^^^^^^^^ expected struct `A`, found `&A` + | +help: consider removing the borrow + | +LL - let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too +LL + let (a, b): ((A, B), A) = (&mut *mutation, (**arc).0); // suggests putting `&**arc` here too + | +help: alternatively, consider changing the type annotation + | +LL | let (a, b): ((A, B), &A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too + | + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. From 91c09d44f60c22e0874bcef393e2fa67e1875c01 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 24 Oct 2022 13:01:07 +0200 Subject: [PATCH 073/171] use the shared assets step for building std too --- src/bootstrap/doc.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 939e169ec00e..5c624bd4eb44 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -457,7 +457,8 @@ impl Step for Std { let target = self.target; let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); - t!(fs::copy(builder.src.join("src/doc/rust.css"), out.join("rust.css"))); + + builder.ensure(SharedAssets { target: self.target }); let index_page = builder.src.join("src/doc/index.md").into_os_string(); let mut extra_args = vec![ From b6824ba52adda195f6279cd84e248936788188b9 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 24 Oct 2022 11:58:45 +0000 Subject: [PATCH 074/171] Make param index generation a bit more robust --- .../src/collect/generics_of.rs | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 707fd6c75278..c7777a946893 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -249,6 +249,11 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { // Now create the real type and const parameters. let type_start = own_start - has_self as u32 + params.len() as u32; let mut i = 0; + let mut next_index = || { + let prev = i; + i += 1; + prev as u32 + type_start + }; const TYPE_DEFAULT_NOT_ALLOWED: &'static str = "defaults for type parameters are only allowed in \ `struct`, `enum`, `type`, or `trait` definitions"; @@ -278,15 +283,13 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { let kind = ty::GenericParamDefKind::Type { has_default: default.is_some(), synthetic }; - let param_def = ty::GenericParamDef { - index: type_start + i as u32, + Some(ty::GenericParamDef { + index: next_index(), name: param.name.ident().name, def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(), pure_wrt_drop: param.pure_wrt_drop, kind, - }; - i += 1; - Some(param_def) + }) } GenericParamKind::Const { default, .. } => { if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() { @@ -297,15 +300,13 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { ); } - let param_def = ty::GenericParamDef { - index: type_start + i as u32, + Some(ty::GenericParamDef { + index: next_index(), name: param.name.ident().name, def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(), pure_wrt_drop: param.pure_wrt_drop, kind: ty::GenericParamDefKind::Const { has_default: default.is_some() }, - }; - i += 1; - Some(param_def) + }) } })); @@ -323,8 +324,8 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { &["", "", ""][..] }; - params.extend(dummy_args.iter().enumerate().map(|(i, &arg)| ty::GenericParamDef { - index: type_start + i as u32, + params.extend(dummy_args.iter().map(|&arg| ty::GenericParamDef { + index: next_index(), name: Symbol::intern(arg), def_id, pure_wrt_drop: false, @@ -337,7 +338,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id)); if let Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) = parent_node { params.push(ty::GenericParamDef { - index: type_start, + index: next_index(), name: Symbol::intern(""), def_id, pure_wrt_drop: false, From f01608cbc41783710dd1909707d74d720c2b6cf8 Mon Sep 17 00:00:00 2001 From: Andrew Pollack Date: Mon, 24 Oct 2022 08:48:13 -0700 Subject: [PATCH 075/171] Update src/tools/compiletest/src/runtest.rs Co-authored-by: Mark Rousskov --- src/tools/compiletest/src/runtest.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 3068f3c5b0b0..8af5f1da694b 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1184,7 +1184,7 @@ impl<'test> TestCx<'test> { // Remove options that are either unwanted (-O) or may lead to duplicates due to RUSTFLAGS. let options_to_remove = ["-O".to_owned(), "-g".to_owned(), "--debuginfo".to_owned()]; - options.to_vec().into_iter().filter(|x| !options_to_remove.contains(x)).collect() + options.iter().filter(|x| !options_to_remove.contains(x)).map(|x| x.clone()).collect() } fn maybe_add_external_args(&self, cmd: &mut Command, args: &Vec) { From 1727c00f1a810cae447e12bb564110527450219c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 10 Oct 2022 22:39:41 +0000 Subject: [PATCH 076/171] Assert if inference vars are leaking from fully_resolve --- compiler/rustc_infer/src/infer/mod.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 2732c92ecd38..7e2ea6c0e269 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1469,7 +1469,12 @@ impl<'tcx> InferCtxt<'tcx> { * except during the writeback phase. */ - resolve::fully_resolve(self, value) + let value = resolve::fully_resolve(self, value); + assert!( + value.as_ref().map_or(true, |value| !value.needs_infer()), + "`{value:?}` is not fully resolved" + ); + value } pub fn replace_bound_vars_with_fresh_vars( From eaa1b8b10e50ae618904314e0fd2ce266ed3590d Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 24 Oct 2022 09:16:45 -0700 Subject: [PATCH 077/171] Migrate from highfive to triagebot --- triagebot.toml | 159 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 157 insertions(+), 2 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 04c2a0507acc..fb6287c5526c 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -20,8 +20,6 @@ allow-unauthenticated = [ "AsyncAwait-OnDeck", ] -[assign] - [glacier] [ping.icebreakers-llvm] @@ -246,6 +244,9 @@ trigger_files = [ "src/version" ] +[autolabel."S-waiting-on-review"] +new_pr = true + [notify-zulip."I-prioritize"] zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts topic = "#{number} {title}" @@ -420,3 +421,157 @@ cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"] [mentions."compiler/rustc_macros/src/diagnostics"] message = "`rustc_macros::diagnostics` was changed" cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"] + +[assign] +warn_non_default_branch = true +contributing_url = "https://rustc-dev-guide.rust-lang.org/contributing.html" + +[assign.adhoc_groups] +compiler-team = [ + "@cjgillot", + "@estebank", + "@petrochenkov", + "@davidtwco", + "@oli-obk", + "@lcnr", + "@nagisa", + "@wesleywiser", +] +compiler-team-contributors = [ + "@compiler-errors", + "@eholk", + "@jackh726", + "@fee1-dead", + "@TaKO8Ki", +] +compiler = [ + "compiler-team", + "compiler-team-contributors", +] +libs = [ + "@joshtriplett", + "@Mark-Simulacrum", + "@m-ou-se", + "@thomcc", +] +bootstrap = [ + "@Mark-Simulacrum", + "@jyn514", +] +infra-ci = [ + "@Mark-Simulacrum", + "@pietroalbini", + "@jyn514", +] +rustdoc = [ + "@jsha", + "@GuillaumeGomez", + "@CraftSpider", + "@notriddle", +] +docs = [ + "@ehuss", + "@GuillaumeGomez", + "@JohnTitor", +] +query-system = [ + "@cjgillot", +] +incremental = [ + "@michaelwoerister", + "@wesleywiser", +] +diagnostics = [ + "@compiler-errors", + "@davidtwco", + "@estebank", + "@oli-obk", + "@TaKO8Ki", +] +parser = [ + "@davidtwco", + "@estebank", + "@nnethercote", + "@petrochenkov", +] +lexer = [ + "@nnethercote", + "@petrochenkov", +] +mir = [ + "@davidtwco", + "@oli-obk", +] +mir-opt = [ + "@nagisa", + "@oli-obk", + "@wesleywiser", +] +types = [ + "@compiler-errors", + "@jackh726", + "@lcnr", + "@oli-obk", + "@spastorino", +] +borrowck = [ + "@davidtwco", + "@pnkfelix", +] +ast_lowering = [ + "@spastorino", +] +fallback = [ + "@Mark-Simulacrum" +] + +[assign.owners] +"/.github/workflows" = ["infra-ci"] +"/Cargo.lock" = ["@Mark-Simulacrum"] +"/Cargo.toml" = ["@Mark-Simulacrum"] +"/compiler" = ["compiler"] +"/compiler/rustc_apfloat" = ["@eddyb"] +"/compiler/rustc_ast" = ["compiler", "parser"] +"/compiler/rustc_ast_lowering" = ["compiler", "ast_lowering"] +"/compiler/rustc_hir_analysis" = ["compiler", "types"] +"/compiler/rustc_lexer" = ["compiler", "lexer"] +"/compiler/rustc_llvm" = ["@cuviper"] +"/compiler/rustc_middle/src/mir" = ["compiler", "mir"] +"/compiler/rustc_middle/src/traits" = ["compiler", "types"] +"/compiler/rustc_const_eval/src/interpret" = ["compiler", "mir"] +"/compiler/rustc_const_eval/src/transform" = ["compiler", "mir-opt"] +"/compiler/rustc_mir_build/src/build" = ["compiler", "mir"] +"/compiler/rustc_parse" = ["compiler", "parser"] +"/compiler/rustc_parse/src/lexer" = ["compiler", "lexer"] +"/compiler/rustc_query_impl" = ["compiler", "query-system"] +"/compiler/rustc_query_system" = ["compiler", "query-system"] +"/compiler/rustc_trait_selection" = ["compiler", "types"] +"/compiler/rustc_traits" = ["compiler", "types"] +"/compiler/rustc_type_ir" = ["compiler", "types"] +"/library/alloc" = ["libs"] +"/library/core" = ["libs", "@scottmcm"] +"/library/panic_abort" = ["libs"] +"/library/panic_unwind" = ["libs"] +"/library/proc_macro" = ["@petrochenkov"] +"/library/std" = ["libs"] +"/library/std/src/sys/windows" = ["@ChrisDenton", "@thomcc"] +"/library/stdarch" = ["libs"] +"/library/test" = ["libs"] +"/src/bootstrap" = ["bootstrap"] +"/src/ci" = ["infra-ci"] +"/src/doc" = ["docs"] +"/src/doc/rustdoc" = ["rustdoc"] +"/src/etc" = ["@Mark-Simulacrum"] +"/src/librustdoc" = ["rustdoc"] +"/src/llvm-project" = ["@cuviper"] +"/src/rustdoc-json-types" = ["rustdoc"] +"/src/stage0.json" = ["bootstrap"] +"/src/tools/cargo" = ["@ehuss", "@joshtriplett"] +"/src/tools/compiletest" = ["bootstrap"] +"/src/tools/linkchecker" = ["@ehuss"] +"/src/tools/rust-installer" = ["bootstrap"] +"/src/tools/rustbook" = ["@ehuss"] +"/src/tools/rustdoc" = ["rustdoc"] +"/src/tools/rustdoc-js" = ["rustdoc"] +"/src/tools/rustdoc-themes" = ["rustdoc"] +"/src/tools/tidy" = ["bootstrap"] From f9cace081d27469d4f8c4f50218cd5b7c0fbf419 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 24 Oct 2022 17:46:23 -0700 Subject: [PATCH 078/171] rustdoc: parse self-closing tags and attributes in `invalid_html_tags` Fixes #103460 --- src/librustdoc/passes/html_tags.rs | 55 ++++++++++++- .../invalid-html-self-closing-tag.rs | 70 ++++++++++++++++ .../invalid-html-self-closing-tag.stderr | 80 +++++++++++++++++++ 3 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 src/test/rustdoc-ui/invalid-html-self-closing-tag.rs create mode 100644 src/test/rustdoc-ui/invalid-html-self-closing-tag.stderr diff --git a/src/librustdoc/passes/html_tags.rs b/src/librustdoc/passes/html_tags.rs index 67fc71665ccf..a89ed7c7ed45 100644 --- a/src/librustdoc/passes/html_tags.rs +++ b/src/librustdoc/passes/html_tags.rs @@ -184,7 +184,60 @@ fn extract_html_tag( } drop_tag(tags, tag_name, r, f); } else { - tags.push((tag_name, r)); + let mut is_self_closing = false; + let mut quote_pos = None; + if c != '>' { + let mut quote = None; + let mut after_eq = false; + for (i, c) in text[pos..].char_indices() { + if !c.is_whitespace() { + if let Some(q) = quote { + if c == q { + quote = None; + quote_pos = None; + after_eq = false; + } + } else if c == '>' { + break; + } else if c == '/' && !after_eq { + is_self_closing = true; + } else { + if is_self_closing { + is_self_closing = false; + } + if (c == '"' || c == '\'') && after_eq { + quote = Some(c); + quote_pos = Some(pos + i); + } else if c == '=' { + after_eq = true; + } + } + } else if quote.is_none() { + after_eq = false; + } + } + } + if let Some(quote_pos) = quote_pos { + let qr = Range { start: quote_pos, end: quote_pos }; + f( + &format!("unclosed quoted HTML attribute on tag `{}`", tag_name), + &qr, + false, + ); + } + if is_self_closing { + // https://html.spec.whatwg.org/#parse-error-non-void-html-element-start-tag-with-trailing-solidus + let valid = ALLOWED_UNCLOSED.contains(&&tag_name[..]) + || tags.iter().take(pos + 1).any(|(at, _)| { + let at = at.to_lowercase(); + at == "svg" || at == "math" + }); + if !valid { + f(&format!("invalid self-closing HTML tag `{}`", tag_name), &r, false); + } + } else { + tags.push((tag_name, r)); + } } } break; diff --git a/src/test/rustdoc-ui/invalid-html-self-closing-tag.rs b/src/test/rustdoc-ui/invalid-html-self-closing-tag.rs new file mode 100644 index 000000000000..d973a53cbc7c --- /dev/null +++ b/src/test/rustdoc-ui/invalid-html-self-closing-tag.rs @@ -0,0 +1,70 @@ +#![deny(rustdoc::invalid_html_tags)] + +///

+//~^ ERROR invalid self-closing HTML tag `p` +pub struct A; + +///

+//~^ ERROR invalid self-closing HTML tag `p` +pub struct B; + +///

+//~^ ERROR invalid self-closing HTML tag `p` +pub struct C; + +///

+//~^ ERROR invalid self-closing HTML tag `p` +pub struct D; + +///

+pub struct G; + +///

+//~^ ERROR invalid self-closing HTML tag `p` +pub struct H; + +///

+//~^ ERROR invalid self-closing HTML tag `p` +pub struct I; + +///
+pub struct J; + +/// +pub struct K; + +/// +pub struct L; + +/// +//~^ ERROR invalid self-closing HTML tag `a` +pub struct M; + +/// +//~^ ERROR invalid self-closing HTML tag `a` +pub struct N; + +/// +//~^ ERROR invalid self-closing HTML tag `a` +pub struct O; + +/// +pub struct P; + +/// +pub struct Q; + +/// +//~^ ERROR unclosed HTML tag `rect` +pub struct R; + +/// +pub struct S; diff --git a/src/test/rustdoc-ui/invalid-html-self-closing-tag.stderr b/src/test/rustdoc-ui/invalid-html-self-closing-tag.stderr new file mode 100644 index 000000000000..e45edfb43ff8 --- /dev/null +++ b/src/test/rustdoc-ui/invalid-html-self-closing-tag.stderr @@ -0,0 +1,80 @@ +error: invalid self-closing HTML tag `p` + --> $DIR/invalid-html-self-closing-tag.rs:3:5 + | +LL | ///

+ | ^^ + | +note: the lint level is defined here + --> $DIR/invalid-html-self-closing-tag.rs:1:9 + | +LL | #![deny(rustdoc::invalid_html_tags)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: invalid self-closing HTML tag `p` + --> $DIR/invalid-html-self-closing-tag.rs:7:5 + | +LL | ///

+ | ^^ + +error: invalid self-closing HTML tag `p` + --> $DIR/invalid-html-self-closing-tag.rs:11:5 + | +LL | ///

+ | ^^ + +error: invalid self-closing HTML tag `p` + --> $DIR/invalid-html-self-closing-tag.rs:15:5 + | +LL | ///

+ | ^^ + +error: unclosed quoted HTML attribute on tag `p` + --> $DIR/invalid-html-self-closing-tag.rs:19:14 + | +LL | ///

+ | ^^ + +error: invalid self-closing HTML tag `p` + --> $DIR/invalid-html-self-closing-tag.rs:34:5 + | +LL | ///

+ | ^^ + +error: invalid self-closing HTML tag `a` + --> $DIR/invalid-html-self-closing-tag.rs:47:5 + | +LL | /// + | ^^ + +error: invalid self-closing HTML tag `a` + --> $DIR/invalid-html-self-closing-tag.rs:51:5 + | +LL | /// + | ^^ + +error: invalid self-closing HTML tag `a` + --> $DIR/invalid-html-self-closing-tag.rs:55:5 + | +LL | /// + | ^^ + +error: unclosed HTML tag `rect` + --> $DIR/invalid-html-self-closing-tag.rs:65:10 + | +LL | /// + | ^^^^^ + +error: aborting due to 12 previous errors + From 5e46d8675cd924e981aac9fd6ca146d627e9d4ab Mon Sep 17 00:00:00 2001 From: Sarthak Singh Date: Sun, 23 Oct 2022 12:29:59 +0530 Subject: [PATCH 079/171] Added helper to prevent verbose printing from the `PrettyPrinter` when printing constants --- .../src/interpret/intrinsics/type_name.rs | 6 ++++-- compiler/rustc_middle/src/ty/print/pretty.rs | 10 +++++++--- src/test/ui/type/issue-94187-verbose-type-name.rs | 13 +++++++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/type/issue-94187-verbose-type-name.rs diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs index 7e4c5fcb031b..ffdb8de5b6c8 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs @@ -4,7 +4,7 @@ use rustc_hir::definitions::DisambiguatedDefPathData; use rustc_middle::mir::interpret::{Allocation, ConstAllocation}; use rustc_middle::ty::{ self, - print::{PrettyPrinter, Print, Printer}, + print::{with_no_verbose_constants, PrettyPrinter, Print, Printer}, subst::{GenericArg, GenericArgKind}, Ty, TyCtxt, }; @@ -190,7 +190,9 @@ impl Write for AbsolutePathPrinter<'_> { /// Directly returns an `Allocation` containing an absolute path representation of the given type. pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> { - let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path; + let path = with_no_verbose_constants!( + AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path + ); let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes()); tcx.intern_const_alloc(alloc) } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index b8ee2b994b1e..c1c2e162f283 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -63,6 +63,7 @@ thread_local! { static NO_TRIMMED_PATH: Cell = const { Cell::new(false) }; static NO_QUERIES: Cell = const { Cell::new(false) }; static NO_VISIBLE_PATH: Cell = const { Cell::new(false) }; + static NO_VERBOSE_CONSTANTS: Cell = const { Cell::new(false) }; } macro_rules! define_helper { @@ -117,6 +118,9 @@ define_helper!( /// Prevent selection of visible paths. `Display` impl of DefId will prefer /// visible (public) reexports of types as paths. fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH); + /// Prevent verbose printing of constants. Verbose printing of constants is + /// never desirable in some contexts like `std::any::type_name`. + fn with_no_verbose_constants(NoVerboseConstantsGuard, NO_VERBOSE_CONSTANTS); ); /// The "region highlights" are used to control region printing during @@ -759,7 +763,7 @@ pub trait PrettyPrinter<'tcx>: } ty::Array(ty, sz) => { p!("[", print(ty), "; "); - if self.tcx().sess.verbose() { + if !NO_VERBOSE_CONSTANTS.with(|flag| flag.get()) && self.tcx().sess.verbose() { p!(write("{:?}", sz)); } else if let ty::ConstKind::Unevaluated(..) = sz.kind() { // Do not try to evaluate unevaluated constants. If we are const evaluating an @@ -1181,7 +1185,7 @@ pub trait PrettyPrinter<'tcx>: ) -> Result { define_scoped_cx!(self); - if self.tcx().sess.verbose() { + if !NO_VERBOSE_CONSTANTS.with(|flag| flag.get()) && self.tcx().sess.verbose() { p!(write("Const({:?}: {:?})", ct.kind(), ct.ty())); return Ok(self); } @@ -1416,7 +1420,7 @@ pub trait PrettyPrinter<'tcx>: ) -> Result { define_scoped_cx!(self); - if self.tcx().sess.verbose() { + if !NO_VERBOSE_CONSTANTS.with(|flag| flag.get()) && self.tcx().sess.verbose() { p!(write("ValTree({:?}: ", valtree), print(ty), ")"); return Ok(self); } diff --git a/src/test/ui/type/issue-94187-verbose-type-name.rs b/src/test/ui/type/issue-94187-verbose-type-name.rs new file mode 100644 index 000000000000..902ef5ade2b0 --- /dev/null +++ b/src/test/ui/type/issue-94187-verbose-type-name.rs @@ -0,0 +1,13 @@ +// Check to insure that the output of `std::any::type_name` does not change based on -Zverbose +// when printing constants +// run-pass +// edition: 2018 +// revisions: normal verbose +// [verbose]compile-flags:-Zverbose + +struct Wrapper; + +fn main() { + assert_eq!(std::any::type_name::<[u32; 0]>(), "[u32; 0]"); + assert_eq!(std::any::type_name::>(), "issue_94187_verbose_type_name::Wrapper<0>"); +} From 919673ea03e2c376931161a9301a9d6f089f8984 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 25 Oct 2022 14:45:02 +0400 Subject: [PATCH 080/171] rustc_middle: Rearrange resolver outputs structures slightly --- compiler/rustc_interface/src/passes.rs | 14 ++------- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 41 +++++++++++++------------ compiler/rustc_middle/src/ty/mod.rs | 11 ++++++- compiler/rustc_resolve/src/lib.rs | 27 ++++++++-------- 5 files changed, 48 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index a47c3e3253ec..9d2325e8265e 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -16,7 +16,6 @@ use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; use rustc_errors::{ErrorGuaranteed, PResult}; use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand}; use rustc_hir::def_id::StableCrateId; -use rustc_hir::definitions::Definitions; use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore}; use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; @@ -30,7 +29,7 @@ use rustc_plugin_impl as plugin; use rustc_query_impl::{OnDiskCache, Queries as TcxQueries}; use rustc_resolve::{Resolver, ResolverArenas}; use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType}; -use rustc_session::cstore::{CrateStoreDyn, MetadataLoader, MetadataLoaderDyn}; +use rustc_session::cstore::{MetadataLoader, MetadataLoaderDyn}; use rustc_session::output::filename_for_input; use rustc_session::search_paths::PathKind; use rustc_session::{Limit, Session}; @@ -135,10 +134,7 @@ mod boxed_resolver { f((&mut *resolver).as_mut().unwrap()) } - pub fn to_resolver_outputs( - resolver: Rc>, - ) -> (Definitions, Box, ty::ResolverOutputs, ty::ResolverAstLowering) - { + pub fn to_resolver_outputs(resolver: Rc>) -> ty::ResolverOutputs { match Rc::try_unwrap(resolver) { Ok(resolver) => { let mut resolver = resolver.into_inner(); @@ -788,8 +784,7 @@ pub fn create_global_ctxt<'tcx>( // incr. comp. yet. dep_graph.assert_ignored(); - let (definitions, cstore, resolver_outputs, resolver_for_lowering) = - BoxedResolver::to_resolver_outputs(resolver); + let resolver_outputs = BoxedResolver::to_resolver_outputs(resolver); let sess = &compiler.session(); let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess); @@ -816,10 +811,7 @@ pub fn create_global_ctxt<'tcx>( lint_store, arena, hir_arena, - definitions, - cstore, resolver_outputs, - resolver_for_lowering, krate, dep_graph, queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn), diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 2ab3b0d27c88..67c85ef0d3b5 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -23,7 +23,7 @@ rustc_queries! { desc { "triggering a delay span bug" } } - query resolutions(_: ()) -> &'tcx ty::ResolverOutputs { + query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt { eval_always no_hash desc { "getting the resolver outputs" } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 0816a5cb8f16..94e3f3b63c81 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -79,7 +79,7 @@ use std::mem; use std::ops::{Bound, Deref}; use std::sync::Arc; -use super::{ImplPolarity, RvalueScopes}; +use super::{ImplPolarity, ResolverOutputs, RvalueScopes}; pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync { /// Creates a new `OnDiskCache` instance from the serialized data in `data`. @@ -1067,10 +1067,9 @@ pub struct GlobalCtxt<'tcx> { pub consts: CommonConsts<'tcx>, definitions: RwLock, - cstore: Box, /// Output of the resolver. - pub(crate) untracked_resolutions: ty::ResolverOutputs, + pub(crate) untracked_resolutions: ty::ResolverGlobalCtxt, untracked_resolver_for_lowering: Steal, /// The entire crate as AST. This field serves as the input for the hir_crate query, /// which lowers it from AST to HIR. It must not be read or used by anything else. @@ -1233,10 +1232,7 @@ impl<'tcx> TyCtxt<'tcx> { lint_store: Lrc, arena: &'tcx WorkerLocal>, hir_arena: &'tcx WorkerLocal>, - definitions: Definitions, - cstore: Box, - untracked_resolutions: ty::ResolverOutputs, - untracked_resolver_for_lowering: ty::ResolverAstLowering, + resolver_outputs: ResolverOutputs, krate: Lrc, dep_graph: DepGraph, on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>, @@ -1245,6 +1241,11 @@ impl<'tcx> TyCtxt<'tcx> { crate_name: &str, output_filenames: OutputFilenames, ) -> GlobalCtxt<'tcx> { + let ResolverOutputs { + definitions, + global_ctxt: untracked_resolutions, + ast_lowering: untracked_resolver_for_lowering, + } = resolver_outputs; let data_layout = TargetDataLayout::parse(&s.target).unwrap_or_else(|err| { s.emit_fatal(err); }); @@ -1253,7 +1254,7 @@ impl<'tcx> TyCtxt<'tcx> { &interners, s, &definitions, - &*cstore, + &*untracked_resolutions.cstore, // This is only used to create a stable hashing context. &untracked_resolutions.source_span, ); @@ -1268,7 +1269,6 @@ impl<'tcx> TyCtxt<'tcx> { interners, dep_graph, definitions: RwLock::new(definitions), - cstore, prof: s.prof.clone(), types: common_types, lifetimes: common_lifetimes, @@ -1369,7 +1369,7 @@ impl<'tcx> TyCtxt<'tcx> { if let Some(id) = id.as_local() { self.definitions_untracked().def_key(id) } else { - self.cstore.def_key(id) + self.untracked_resolutions.cstore.def_key(id) } } @@ -1383,7 +1383,7 @@ impl<'tcx> TyCtxt<'tcx> { if let Some(id) = id.as_local() { self.definitions_untracked().def_path(id) } else { - self.cstore.def_path(id) + self.untracked_resolutions.cstore.def_path(id) } } @@ -1393,7 +1393,7 @@ impl<'tcx> TyCtxt<'tcx> { if let Some(def_id) = def_id.as_local() { self.definitions_untracked().def_path_hash(def_id) } else { - self.cstore.def_path_hash(def_id) + self.untracked_resolutions.cstore.def_path_hash(def_id) } } @@ -1402,7 +1402,7 @@ impl<'tcx> TyCtxt<'tcx> { if crate_num == LOCAL_CRATE { self.sess.local_stable_crate_id() } else { - self.cstore.stable_crate_id(crate_num) + self.untracked_resolutions.cstore.stable_crate_id(crate_num) } } @@ -1413,7 +1413,7 @@ impl<'tcx> TyCtxt<'tcx> { if stable_crate_id == self.sess.local_stable_crate_id() { LOCAL_CRATE } else { - self.cstore.stable_crate_id_to_crate_num(stable_crate_id) + self.untracked_resolutions.cstore.stable_crate_id_to_crate_num(stable_crate_id) } } @@ -1432,8 +1432,9 @@ impl<'tcx> TyCtxt<'tcx> { } else { // If this is a DefPathHash from an upstream crate, let the CrateStore map // it to a DefId. - let cnum = self.cstore.stable_crate_id_to_crate_num(stable_crate_id); - self.cstore.def_path_hash_to_def_id(cnum, hash) + let cstore = &*self.untracked_resolutions.cstore; + let cnum = cstore.stable_crate_id_to_crate_num(stable_crate_id); + cstore.def_path_hash_to_def_id(cnum, hash) } } @@ -1445,7 +1446,7 @@ impl<'tcx> TyCtxt<'tcx> { let (crate_name, stable_crate_id) = if def_id.is_local() { (self.crate_name, self.sess.local_stable_crate_id()) } else { - let cstore = &self.cstore; + let cstore = &*self.untracked_resolutions.cstore; (cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate)) }; @@ -1520,7 +1521,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Note that this is *untracked* and should only be used within the query /// system if the result is otherwise tracked through queries pub fn cstore_untracked(self) -> &'tcx CrateStoreDyn { - &*self.cstore + &*self.untracked_resolutions.cstore } /// Note that this is *untracked* and should only be used within the query @@ -1546,7 +1547,7 @@ impl<'tcx> TyCtxt<'tcx> { let hcx = StableHashingContext::new( self.sess, &*definitions, - &*self.cstore, + &*self.untracked_resolutions.cstore, &self.untracked_resolutions.source_span, ); f(hcx) @@ -2364,7 +2365,7 @@ impl<'tcx> TyCtxt<'tcx> { st, self.sess, &self.definitions.read(), - &*self.cstore, + &*self.untracked_resolutions.cstore, // This is only used to create a stable hashing context. &self.untracked_resolutions.source_span, ) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c2aef8178e2c..9671d3a32f94 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -38,11 +38,13 @@ use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, LifetimeRes, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap}; +use rustc_hir::definitions::Definitions; use rustc_hir::Node; use rustc_index::vec::IndexVec; use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; use rustc_serialize::{Decodable, Encodable}; +use rustc_session::cstore::CrateStoreDyn; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{ExpnId, Span}; @@ -142,8 +144,15 @@ mod sty; pub type RegisteredTools = FxHashSet; -#[derive(Debug)] pub struct ResolverOutputs { + pub definitions: Definitions, + pub global_ctxt: ResolverGlobalCtxt, + pub ast_lowering: ResolverAstLowering, +} + +#[derive(Debug)] +pub struct ResolverGlobalCtxt { + pub cstore: Box, pub visibilities: FxHashMap, /// This field is used to decide whether we should make `PRIVATE_IN_PUBLIC` a hard error. pub has_pub_restricted: bool, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 1c1976af5054..c2213e8d1e2e 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -42,9 +42,10 @@ use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_middle::metadata::ModChild; use rustc_middle::middle::privacy::AccessLevels; use rustc_middle::span_bug; -use rustc_middle::ty::{self, DefIdTree, MainDefinition, RegisteredTools, ResolverOutputs}; +use rustc_middle::ty::{self, DefIdTree, MainDefinition, RegisteredTools}; +use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs}; use rustc_query_system::ich::StableHashingContext; -use rustc_session::cstore::{CrateStore, CrateStoreDyn, MetadataLoaderDyn}; +use rustc_session::cstore::{CrateStore, MetadataLoaderDyn}; use rustc_session::lint::LintBuffer; use rustc_session::Session; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; @@ -1376,9 +1377,7 @@ impl<'a> Resolver<'a> { Default::default() } - pub fn into_outputs( - self, - ) -> (Definitions, Box, ResolverOutputs, ty::ResolverAstLowering) { + pub fn into_outputs(self) -> ResolverOutputs { let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect(); let definitions = self.definitions; let cstore = Box::new(self.crate_loader.into_cstore()); @@ -1394,7 +1393,8 @@ impl<'a> Resolver<'a> { let main_def = self.main_def; let confused_type_with_std_module = self.confused_type_with_std_module; let access_levels = self.access_levels; - let resolutions = ResolverOutputs { + let global_ctxt = ResolverGlobalCtxt { + cstore, source_span, expn_that_defined, visibilities, @@ -1416,7 +1416,7 @@ impl<'a> Resolver<'a> { confused_type_with_std_module, registered_tools: self.registered_tools, }; - let resolutions_lowering = ty::ResolverAstLowering { + let ast_lowering = ty::ResolverAstLowering { legacy_const_generic_args: self.legacy_const_generic_args, partial_res_map: self.partial_res_map, import_res_map: self.import_res_map, @@ -1429,16 +1429,15 @@ impl<'a> Resolver<'a> { trait_map: self.trait_map, builtin_macro_kinds: self.builtin_macro_kinds, }; - (definitions, cstore, resolutions, resolutions_lowering) + ResolverOutputs { definitions, global_ctxt, ast_lowering } } - pub fn clone_outputs( - &self, - ) -> (Definitions, Box, ResolverOutputs, ty::ResolverAstLowering) { + pub fn clone_outputs(&self) -> ResolverOutputs { let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect(); let definitions = self.definitions.clone(); let cstore = Box::new(self.cstore().clone()); - let resolutions = ResolverOutputs { + let global_ctxt = ResolverGlobalCtxt { + cstore, source_span: self.source_span.clone(), expn_that_defined: self.expn_that_defined.clone(), visibilities: self.visibilities.clone(), @@ -1460,7 +1459,7 @@ impl<'a> Resolver<'a> { registered_tools: self.registered_tools.clone(), access_levels: self.access_levels.clone(), }; - let resolutions_lowering = ty::ResolverAstLowering { + let ast_lowering = ty::ResolverAstLowering { legacy_const_generic_args: self.legacy_const_generic_args.clone(), partial_res_map: self.partial_res_map.clone(), import_res_map: self.import_res_map.clone(), @@ -1473,7 +1472,7 @@ impl<'a> Resolver<'a> { trait_map: self.trait_map.clone(), builtin_macro_kinds: self.builtin_macro_kinds.clone(), }; - (definitions, cstore, resolutions, resolutions_lowering) + ResolverOutputs { definitions, global_ctxt, ast_lowering } } fn create_stable_hashing_context(&self) -> StableHashingContext<'_> { From a9447bb9d00f480d0b7f18218b632eda4d9b4f5d Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Mon, 17 Oct 2022 20:09:03 +0300 Subject: [PATCH 081/171] Perf improvements for effective visibility calculating --- compiler/rustc_middle/src/middle/privacy.rs | 68 +++++++++++---------- compiler/rustc_privacy/src/lib.rs | 8 ++- compiler/rustc_resolve/src/access_levels.rs | 22 +++---- src/test/ui/privacy/access_levels.rs | 8 +-- src/test/ui/privacy/access_levels.stderr | 4 +- 5 files changed, 57 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index 556bd24d00f9..5687e5bdc434 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -69,21 +69,7 @@ impl EffectiveVisibility { self.get(tag).is_public() } - fn update(&mut self, vis: Visibility, tag: AccessLevel, tree: impl DefIdTree) -> bool { - let mut changed = false; - for level in AccessLevel::all_levels() { - if level <= tag { - let current_effective_vis = self.get_mut(level); - if *current_effective_vis != vis && vis.is_at_least(*current_effective_vis, tree) { - changed = true; - *current_effective_vis = vis; - } - } - } - changed - } - - fn from_vis(vis: Visibility) -> EffectiveVisibility { + pub fn from_vis(vis: Visibility) -> EffectiveVisibility { EffectiveVisibility { public: vis, exported: vis, @@ -173,33 +159,49 @@ impl> AccessLevels { parent_id: Id, tag: AccessLevel, tree: impl DefIdTree, - ) -> Result { + ) -> bool { let mut changed = false; - let mut current_effective_vis = self - .get_effective_vis(id) - .copied() - .unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis())); + let mut current_effective_vis = self.get_effective_vis(id).copied().unwrap_or_else(|| { + if id.into().is_crate_root() { + EffectiveVisibility::from_vis(Visibility::Public) + } else { + EffectiveVisibility::from_vis(default_vis()) + } + }); if let Some(inherited_effective_vis) = self.get_effective_vis(parent_id) { + let mut inherited_effective_vis_at_prev_level = *inherited_effective_vis.get(tag); + let mut calculated_effective_vis = inherited_effective_vis_at_prev_level; for level in AccessLevel::all_levels() { if tag >= level { let inherited_effective_vis_at_level = *inherited_effective_vis.get(level); - let calculated_effective_vis = - if nominal_vis.is_at_least(inherited_effective_vis_at_level, tree) { - inherited_effective_vis_at_level - } else { - nominal_vis - }; - changed |= current_effective_vis.update(calculated_effective_vis, level, tree); + let current_effective_vis_at_level = current_effective_vis.get_mut(level); + // effective visibility for id shouldn't be recalculated if + // inherited from parent_id effective visibility isn't changed at next level + if !(inherited_effective_vis_at_prev_level == inherited_effective_vis_at_level + && tag != level) + { + calculated_effective_vis = + if nominal_vis.is_at_least(inherited_effective_vis_at_level, tree) { + inherited_effective_vis_at_level + } else { + nominal_vis + }; + } + // effective visibility can't be decreased at next update call for the + // same id + if *current_effective_vis_at_level != calculated_effective_vis + && calculated_effective_vis + .is_at_least(*current_effective_vis_at_level, tree) + { + changed = true; + *current_effective_vis_at_level = calculated_effective_vis; + } + inherited_effective_vis_at_prev_level = inherited_effective_vis_at_level; } } - } else { - if !id.into().is_crate_root() { - return Err(()); - } - changed |= current_effective_vis.update(Visibility::Public, AccessLevel::Public, tree); } self.map.insert(id, current_effective_vis); - Ok(changed) + changed } } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 2636db6dbe1a..4db58d92bd5e 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -922,9 +922,9 @@ pub struct TestReachabilityVisitor<'tcx, 'a> { impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> { fn access_level_diagnostic(&mut self, def_id: LocalDefId) { if self.tcx.has_attr(def_id.to_def_id(), sym::rustc_effective_visibility) { + let mut error_msg = String::new(); + let span = self.tcx.def_span(def_id.to_def_id()); if let Some(effective_vis) = self.access_levels.get_effective_vis(def_id) { - let mut error_msg = String::new(); - let span = self.tcx.def_span(def_id.to_def_id()); for level in AccessLevel::all_levels() { let vis_str = match effective_vis.get(level) { ty::Visibility::Restricted(restricted_id) => { @@ -943,8 +943,10 @@ impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> { } error_msg.push_str(&format!("{:?}: {}", level, vis_str)); } - self.tcx.sess.emit_err(ReportEffectiveVisibility { span, descr: error_msg }); + } else { + error_msg.push_str("not in the table"); } + self.tcx.sess.emit_err(ReportEffectiveVisibility { span, descr: error_msg }); } } } diff --git a/compiler/rustc_resolve/src/access_levels.rs b/compiler/rustc_resolve/src/access_levels.rs index 257784341e3f..c27b5b0c4200 100644 --- a/compiler/rustc_resolve/src/access_levels.rs +++ b/compiler/rustc_resolve/src/access_levels.rs @@ -96,10 +96,18 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { parent_id: LocalDefId, tag: AccessLevel, ) { + let module_id = self + .r + .get_nearest_non_block_module(def_id.to_def_id()) + .nearest_parent_mod() + .expect_local(); + if nominal_vis == Visibility::Restricted(module_id) + || self.r.visibilities[&parent_id] == Visibility::Restricted(module_id) + { + return; + } let mut access_levels = std::mem::take(&mut self.r.access_levels); - let module_id = - self.r.get_nearest_non_block_module(def_id.to_def_id()).def_id().expect_local(); - let res = access_levels.update( + self.changed |= access_levels.update( def_id, nominal_vis, || Visibility::Restricted(module_id), @@ -107,14 +115,6 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { tag, &*self.r, ); - if let Ok(changed) = res { - self.changed |= changed; - } else { - self.r.session.delay_span_bug( - self.r.opt_span(def_id.to_def_id()).unwrap(), - "Can't update effective visibility", - ); - } self.r.access_levels = access_levels; } } diff --git a/src/test/ui/privacy/access_levels.rs b/src/test/ui/privacy/access_levels.rs index 42c9975bedb7..6bca71618868 100644 --- a/src/test/ui/privacy/access_levels.rs +++ b/src/test/ui/privacy/access_levels.rs @@ -17,12 +17,12 @@ mod outer { //~ ERROR Public: pub(crate), Exported: pub(crate), Reachable: pub(c } #[rustc_effective_visibility] - struct PrivStruct; //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) + struct PrivStruct; //~ ERROR not in the table #[rustc_effective_visibility] pub union PubUnion { //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub #[rustc_effective_visibility] - a: u8, //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) + a: u8, //~ ERROR not in the table #[rustc_effective_visibility] pub b: u8, //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub } @@ -38,13 +38,13 @@ mod outer { //~ ERROR Public: pub(crate), Exported: pub(crate), Reachable: pub(c } #[rustc_effective_visibility] - macro_rules! none_macro { //~ Public: pub(crate), Exported: pub(crate), Reachable: pub(crate), ReachableFromImplTrait: pub(crate) + macro_rules! none_macro { //~ ERROR Public: pub(crate), Exported: pub(crate), Reachable: pub(crate), ReachableFromImplTrait: pub(crate) () => {}; } #[macro_export] #[rustc_effective_visibility] - macro_rules! public_macro { //~ Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + macro_rules! public_macro { //~ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub () => {}; } diff --git a/src/test/ui/privacy/access_levels.stderr b/src/test/ui/privacy/access_levels.stderr index 111e02bc329c..07c4d436ff00 100644 --- a/src/test/ui/privacy/access_levels.stderr +++ b/src/test/ui/privacy/access_levels.stderr @@ -22,7 +22,7 @@ error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait LL | pub trait PubTrait { | ^^^^^^^^^^^^^^^^^^ -error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) +error: not in the table --> $DIR/access_levels.rs:20:9 | LL | struct PrivStruct; @@ -34,7 +34,7 @@ error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait LL | pub union PubUnion { | ^^^^^^^^^^^^^^^^^^ -error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) +error: not in the table --> $DIR/access_levels.rs:25:13 | LL | a: u8, From 14caf7396d1875ff96268f48ea0d203fb989d77a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 7 Oct 2022 09:29:51 +0000 Subject: [PATCH 082/171] Pull opaque type handling out of the type relating delegate --- .../src/type_check/relate_tys.rs | 19 ++++--------------- .../src/infer/canonical/query_response.rs | 16 +++++----------- .../rustc_infer/src/infer/nll_relate/mod.rs | 15 ++++++++++----- 3 files changed, 19 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index b53360ea61bb..ca249938d040 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -1,6 +1,6 @@ use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; use rustc_infer::infer::NllRegionVariableOrigin; -use rustc_infer::traits::ObligationCause; +use rustc_infer::traits::PredicateObligations; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::TypeRelation; @@ -155,27 +155,16 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> true } - fn register_opaque_type( + fn register_opaque_type_obligations( &mut self, - a: Ty<'tcx>, - b: Ty<'tcx>, - a_is_expected: bool, + obligations: PredicateObligations<'tcx>, ) -> Result<(), TypeError<'tcx>> { - let param_env = self.param_env(); - let span = self.span(); - let def_id = self.type_checker.body.source.def_id().expect_local(); - let body_id = self.type_checker.tcx().hir().local_def_id_to_hir_id(def_id); - let cause = ObligationCause::misc(span, body_id); self.type_checker .fully_perform_op( self.locations, self.category, InstantiateOpaqueType { - obligations: self - .type_checker - .infcx - .handle_opaque_type(a, b, a_is_expected, &cause, param_env)? - .obligations, + obligations, // These fields are filled in during execution of the operation base_universe: None, region_constraints: None, diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 608b5cc8756a..4d287988e336 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -16,8 +16,8 @@ use crate::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelating use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::{InferCtxt, InferOk, InferResult, NllRegionVariableOrigin}; use crate::traits::query::{Fallible, NoSolution}; -use crate::traits::TraitEngine; use crate::traits::{Obligation, ObligationCause, PredicateObligation}; +use crate::traits::{PredicateObligations, TraitEngine}; use rustc_data_structures::captures::Captures; use rustc_index::vec::Idx; use rustc_index::vec::IndexVec; @@ -509,7 +509,7 @@ impl<'tcx> InferCtxt<'tcx> { for &(a, b) in &query_response.value.opaque_types { let a = substitute_value(self.tcx, &result_subst, a); let b = substitute_value(self.tcx, &result_subst, b); - obligations.extend(self.handle_opaque_type(a, b, true, cause, param_env)?.obligations); + obligations.extend(self.at(cause, param_env).eq(a, b)?.obligations); } Ok(InferOk { value: result_subst, obligations }) @@ -741,17 +741,11 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> { true } - fn register_opaque_type( + fn register_opaque_type_obligations( &mut self, - a: Ty<'tcx>, - b: Ty<'tcx>, - a_is_expected: bool, + obligations: PredicateObligations<'tcx>, ) -> Result<(), TypeError<'tcx>> { - self.obligations.extend( - self.infcx - .handle_opaque_type(a, b, a_is_expected, &self.cause, self.param_env)? - .obligations, - ); + self.obligations.extend(obligations); Ok(()) } } diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 7c186ae94706..529c72d266ae 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -25,7 +25,9 @@ use crate::infer::combine::ConstEquateRelation; use crate::infer::InferCtxt; use crate::infer::{ConstVarValue, ConstVariableValue}; use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind}; +use crate::traits::PredicateObligation; use rustc_data_structures::fx::FxHashMap; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; @@ -91,11 +93,9 @@ pub trait TypeRelatingDelegate<'tcx> { ); fn const_equate(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>); - fn register_opaque_type( + fn register_opaque_type_obligations( &mut self, - a: Ty<'tcx>, - b: Ty<'tcx>, - a_is_expected: bool, + obligations: Vec>, ) -> Result<(), TypeError<'tcx>>; /// Creates a new universe index. Used when instantiating placeholders. @@ -414,7 +414,12 @@ where (_, &ty::Opaque(..)) => (generalize(a, true)?, b), _ => unreachable!(), }; - self.delegate.register_opaque_type(a, b, true)?; + let cause = ObligationCause::dummy_with_span(self.delegate.span()); + let obligations = self + .infcx + .handle_opaque_type(a, b, true, &cause, self.delegate.param_env())? + .obligations; + self.delegate.register_opaque_type_obligations(obligations)?; trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated"); Ok(a) } From 196a429a671209531422a3895140fc16745ac4ea Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 7 Oct 2022 09:33:22 +0000 Subject: [PATCH 083/171] Use the general type API instead of directly accessing register_hidden_type --- .../src/region_infer/opaque_types.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 11a57ef26217..465f353aaa37 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -263,13 +263,11 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { // Require that the hidden type actually fulfills all the bounds of the opaque type, even without // the bounds that the function supplies. - match infcx.register_hidden_type( - OpaqueTypeKey { def_id, substs: id_substs }, - ObligationCause::misc(instantiated_ty.span, body_id), - param_env, - definition_ty, - origin, - ) { + let opaque_ty = self.tcx.mk_opaque(def_id.to_def_id(), id_substs); + match infcx + .at(&ObligationCause::misc(instantiated_ty.span, body_id), param_env) + .eq(opaque_ty, definition_ty) + { Ok(infer_ok) => { for obligation in infer_ok.obligations { fulfillment_cx.register_predicate_obligation(&infcx, obligation); @@ -280,7 +278,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { .err_ctxt() .report_mismatched_types( &ObligationCause::misc(instantiated_ty.span, body_id), - self.tcx.mk_opaque(def_id.to_def_id(), id_substs), + opaque_ty, definition_ty, err, ) From f3bd222ad9e30245aef89d41defd378eefed70f4 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 7 Oct 2022 09:56:42 +0000 Subject: [PATCH 084/171] Bubble the opaque type ordering int opaque type handling --- compiler/rustc_infer/src/infer/opaque_types.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 0a4ecc4c033e..a982f11f7187 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -103,7 +103,7 @@ impl<'tcx> InferCtxt<'tcx> { return Ok(InferOk { value: (), obligations: vec![] }); } let (a, b) = if a_is_expected { (a, b) } else { (b, a) }; - let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() { + let process = |a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected| match *a.kind() { ty::Opaque(def_id, substs) if def_id.is_local() => { let def_id = def_id.expect_local(); let origin = match self.defining_use_anchor { @@ -169,13 +169,14 @@ impl<'tcx> InferCtxt<'tcx> { param_env, b, origin, + a_is_expected, )) } _ => None, }; - if let Some(res) = process(a, b) { + if let Some(res) = process(a, b, true) { res - } else if let Some(res) = process(b, a) { + } else if let Some(res) = process(b, a, false) { res } else { let (a, b) = self.resolve_vars_if_possible((a, b)); @@ -514,13 +515,14 @@ impl UseKind { impl<'tcx> InferCtxt<'tcx> { #[instrument(skip(self), level = "debug")] - pub fn register_hidden_type( + fn register_hidden_type( &self, opaque_type_key: OpaqueTypeKey<'tcx>, cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, hidden_ty: Ty<'tcx>, origin: hir::OpaqueTyOrigin, + a_is_expected: bool, ) -> InferResult<'tcx, ()> { let tcx = self.tcx; let OpaqueTypeKey { def_id, substs } = opaque_type_key; @@ -539,7 +541,8 @@ impl<'tcx> InferCtxt<'tcx> { origin, ); if let Some(prev) = prev { - obligations = self.at(&cause, param_env).eq(prev, hidden_ty)?.obligations; + obligations = + self.at(&cause, param_env).eq_exp(a_is_expected, prev, hidden_ty)?.obligations; } let item_bounds = tcx.bound_explicit_item_bounds(def_id.to_def_id()); From 2283a5e65bf7efd63e9456f9fa336bfc69f7b277 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 25 Oct 2022 16:13:02 +0400 Subject: [PATCH 085/171] rustc_metadata: Add constructors to module children at encoding time instead of decoding time. --- compiler/rustc_metadata/src/rmeta/decoder.rs | 79 +++++++++----------- compiler/rustc_metadata/src/rmeta/encoder.rs | 24 ++++-- 2 files changed, 53 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 830417eea1a0..691e3d0f8f90 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -773,7 +773,15 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn opt_item_name(self, item_index: DefIndex) -> Option { - self.def_key(item_index).disambiguated_data.data.get_opt_name() + let def_key = self.def_key(item_index); + def_key.disambiguated_data.data.get_opt_name().or_else(|| { + if def_key.disambiguated_data.data == DefPathData::Ctor { + let parent_index = def_key.parent.expect("no parent for a constructor"); + self.def_key(parent_index).disambiguated_data.data.get_opt_name() + } else { + None + } + }) } fn item_name(self, item_index: DefIndex) -> Symbol { @@ -905,7 +913,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .get(self, item_id) .unwrap_or_else(LazyArray::empty) .decode(self) - .map(|index| self.get_variant(&self.def_kind(index), index, did)) + .filter_map(|index| { + let kind = self.def_kind(index); + match kind { + DefKind::Ctor(..) => None, + _ => Some(self.get_variant(&kind, index, did)), + } + }) .collect() } else { std::iter::once(self.get_variant(&kind, item_id, did)).collect() @@ -1029,50 +1043,27 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { callback(ModChild { ident, res, vis, span, macro_rules }); - // For non-re-export structs and variants add their constructors to children. - // Re-export lists automatically contain constructors when necessary. - match kind { - DefKind::Struct => { - if let Some((ctor_def_id, ctor_kind)) = - self.get_ctor_def_id_and_kind(child_index) - { - let ctor_res = - Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id); - let vis = self.get_visibility(ctor_def_id.index); - callback(ModChild { - ident, - res: ctor_res, - vis, - span, - macro_rules: false, - }); + // For non-reexport variants add their fictive constructors to children. + // Braced variants, unlike structs, generate unusable names in value namespace, + // they are reserved for possible future use. It's ok to use the variant's id as + // a ctor id since an error will be reported on any use of such resolution anyway. + // Reexport lists automatically contain such constructors when necessary. + if kind == DefKind::Variant && self.get_ctor_def_id_and_kind(child_index).is_none() + { + let ctor_res = + Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fictive), def_id); + let mut vis = vis; + if vis.is_public() { + // For non-exhaustive variants lower the constructor visibility to + // within the crate. We only need this for fictive constructors, + // for other constructors correct visibilities + // were already encoded in metadata. + let mut attrs = self.get_item_attrs(def_id.index, sess); + if attrs.any(|item| item.has_name(sym::non_exhaustive)) { + vis = ty::Visibility::Restricted(self.local_def_id(CRATE_DEF_INDEX)); } } - DefKind::Variant => { - // Braced variants, unlike structs, generate unusable names in - // value namespace, they are reserved for possible future use. - // It's ok to use the variant's id as a ctor id since an - // error will be reported on any use of such resolution anyway. - let (ctor_def_id, ctor_kind) = self - .get_ctor_def_id_and_kind(child_index) - .unwrap_or((def_id, CtorKind::Fictive)); - let ctor_res = - Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id); - let mut vis = self.get_visibility(ctor_def_id.index); - if ctor_def_id == def_id && vis.is_public() { - // For non-exhaustive variants lower the constructor visibility to - // within the crate. We only need this for fictive constructors, - // for other constructors correct visibilities - // were already encoded in metadata. - let mut attrs = self.get_item_attrs(def_id.index, sess); - if attrs.any(|item| item.has_name(sym::non_exhaustive)) { - let crate_def_id = self.local_def_id(CRATE_DEF_INDEX); - vis = ty::Visibility::Restricted(crate_def_id); - } - } - callback(ModChild { ident, res: ctor_res, vis, span, macro_rules: false }); - } - _ => {} + callback(ModChild { ident, res: ctor_res, vis, span, macro_rules: false }); } } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index c019211a948e..61e84a5a01dd 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1335,6 +1335,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Only encode named non-reexport children, reexports are encoded // separately and unnamed items are not used by name resolution. hir::ItemKind::ExternCrate(..) => continue, + hir::ItemKind::Struct(ref vdata, _) => { + yield item_id.def_id.def_id.local_def_index; + // Encode constructors which take a separate slot in value namespace. + if let Some(ctor_hir_id) = vdata.ctor_hir_id() { + yield tcx.hir().local_def_id(ctor_hir_id).local_def_index; + } + } _ if tcx.def_key(item_id.def_id.to_def_id()).get_opt_name().is_some() => { yield item_id.def_id.def_id.local_def_index; } @@ -1646,12 +1653,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }; // FIXME(eddyb) there should be a nicer way to do this. match item.kind { - hir::ItemKind::Enum(..) => record_array!(self.tables.children[def_id] <- - self.tcx.adt_def(def_id).variants().iter().map(|v| { - assert!(v.def_id.is_local()); - v.def_id.index - }) - ), + hir::ItemKind::Enum(..) => { + record_array!(self.tables.children[def_id] <- iter::from_generator(|| + for variant in tcx.adt_def(def_id).variants() { + yield variant.def_id.index; + // Encode constructors which take a separate slot in value namespace. + if let Some(ctor_def_id) = variant.ctor_def_id { + yield ctor_def_id.index; + } + } + )) + } hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { record_array!(self.tables.children[def_id] <- self.tcx.adt_def(def_id).non_enum_variant().fields.iter().map(|f| { From 8286ea5a4977a5bca5d75ce25f30e1afbbb95e31 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 20 Oct 2022 09:39:09 +0000 Subject: [PATCH 086/171] Move a wf-check into the site where the value is instantiated --- .../rustc_hir_analysis/src/astconv/mod.rs | 71 ++++++++++++++----- compiler/rustc_hir_analysis/src/collect.rs | 33 ++++++++- .../rustc_trait_selection/src/traits/wf.rs | 26 ------- .../super-traits-fail-2.nn.stderr | 4 +- .../super-traits-fail-2.ny.stderr | 4 +- .../super-traits-fail-3.nn.stderr | 8 +-- .../super-traits-fail-3.ny.stderr | 4 +- .../super-traits-fail-3.yn.stderr | 4 +- 8 files changed, 95 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index a0350c26d827..a4ebe38b02ec 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -36,7 +36,7 @@ use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECT use rustc_span::edition::Edition; use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::symbol::{kw, Ident, Symbol}; -use rustc_span::Span; +use rustc_span::{sym, Span}; use rustc_target::spec::abi; use rustc_trait_selection::traits; use rustc_trait_selection::traits::astconv_object_safety_violations; @@ -275,6 +275,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_segment.args(), item_segment.infer_args, None, + None, ); if let Some(b) = item_segment.args().bindings.first() { Self::prohibit_assoc_ty_binding(self.tcx(), b.span); @@ -324,6 +325,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { generic_args: &'a hir::GenericArgs<'_>, infer_args: bool, self_ty: Option>, + constness: Option, ) -> (SubstsRef<'tcx>, GenericArgCountResult) { // If the type is parameterized by this region, then replace this // region with the current anon region binding (in other words, @@ -534,6 +536,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &mut substs_ctx, ); + if let Some(ty::BoundConstness::ConstIfConst) = constness + && generics.has_self && !tcx.has_attr(def_id, sym::const_trait) + { + tcx.sess.span_err( + span, + "~const can only be applied to `#[const_trait]` traits", + ); + } + (substs, arg_count) } @@ -601,6 +612,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_segment.args(), item_segment.infer_args, None, + None, ); if let Some(b) = item_segment.args().bindings.first() { @@ -620,6 +632,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, trait_ref: &hir::TraitRef<'_>, self_ty: Ty<'tcx>, + constness: ty::BoundConstness, ) -> ty::TraitRef<'tcx> { self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {}); @@ -629,6 +642,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty, trait_ref.path.segments.last().unwrap(), true, + Some(constness), ) } @@ -655,6 +669,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { args, infer_args, Some(self_ty), + Some(constness), ); let tcx = self.tcx(); @@ -680,6 +695,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { speculative, &mut dup_bindings, binding_span.unwrap_or(binding.span), + constness, ); // Okay to ignore `Err` because of `ErrorGuaranteed` (see above). } @@ -783,6 +799,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Ty<'tcx>, trait_segment: &hir::PathSegment<'_>, is_impl: bool, + constness: Option, ) -> ty::TraitRef<'tcx> { let (substs, _) = self.create_substs_for_ast_trait_ref( span, @@ -790,6 +807,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty, trait_segment, is_impl, + constness, ); if let Some(b) = trait_segment.args().bindings.first() { Self::prohibit_assoc_ty_binding(self.tcx(), b.span); @@ -805,6 +823,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Ty<'tcx>, trait_segment: &'a hir::PathSegment<'a>, is_impl: bool, + constness: Option, ) -> (SubstsRef<'tcx>, GenericArgCountResult) { self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl); @@ -816,6 +835,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { trait_segment.args(), trait_segment.infer_args, Some(self_ty), + constness, ) } @@ -1027,6 +1047,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { speculative: bool, dup_bindings: &mut FxHashMap, path_span: Span, + constness: ty::BoundConstness, ) -> Result<(), ErrorGuaranteed> { // Given something like `U: SomeTrait`, we want to produce a // predicate like `::T = X`. This is somewhat @@ -1122,10 +1143,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { trait_ref.substs, ); - debug!( - "add_predicates_for_ast_type_binding: substs for trait-ref and assoc_item: {:?}", - substs_trait_ref_and_assoc_item - ); + debug!(?substs_trait_ref_and_assoc_item); ty::ProjectionTy { item_def_id: assoc_item.def_id, @@ -1146,8 +1164,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx.collect_constrained_late_bound_regions(&projection_ty); let late_bound_in_ty = tcx.collect_referenced_late_bound_regions(&trait_ref.rebind(ty)); - debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref); - debug!("late_bound_in_ty = {:?}", late_bound_in_ty); + debug!(?late_bound_in_trait_ref); + debug!(?late_bound_in_ty); // FIXME: point at the type params that don't have appropriate lifetimes: // struct S1 Fn(&i32, &i32) -> &'a i32>(F); @@ -1648,6 +1666,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Checks that `bounds` contains exactly one element and reports appropriate // errors otherwise. + #[instrument(level = "debug", skip(self, all_candidates, ty_param_name, is_equality), ret)] fn one_bound_for_assoc_type( &self, all_candidates: impl Fn() -> I, @@ -1677,10 +1696,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { return Err(reported); } }; - debug!("one_bound_for_assoc_type: bound = {:?}", bound); + debug!(?bound); if let Some(bound2) = next_cand { - debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2); + debug!(?bound2); let is_equality = is_equality(); let bounds = IntoIterator::into_iter([bound, bound2]).chain(matching_candidates); @@ -1776,6 +1795,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // parameter or `Self`. // NOTE: When this function starts resolving `Trait::AssocTy` successfully // it should also start reporting the `BARE_TRAIT_OBJECTS` lint. + #[instrument(level = "debug", skip(self, hir_ref_id, span, qself, assoc_segment), fields(assoc_ident=?assoc_segment.ident), ret)] pub fn associated_path_to_ty( &self, hir_ref_id: hir::HirId, @@ -1793,8 +1813,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Res::Err }; - debug!("associated_path_to_ty: {:?}::{}", qself_ty, assoc_ident); - // Check if we have an enum variant. let mut variant_resolution = None; if let ty::Adt(adt_def, _) = qself_ty.kind() { @@ -2050,6 +2068,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_def_id: DefId, trait_segment: &hir::PathSegment<'_>, item_segment: &hir::PathSegment<'_>, + constness: ty::BoundConstness, ) -> Ty<'tcx> { let tcx = self.tcx(); @@ -2094,8 +2113,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!("qpath_to_ty: self_type={:?}", self_ty); - let trait_ref = - self.ast_path_to_mono_trait_ref(span, trait_def_id, self_ty, trait_segment, false); + let trait_ref = self.ast_path_to_mono_trait_ref( + span, + trait_def_id, + self_ty, + trait_segment, + false, + Some(constness), + ); let item_substs = self.create_substs_for_associated_item( span, @@ -2534,12 +2559,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Res::Def(DefKind::AssocTy, def_id) => { debug_assert!(path.segments.len() >= 2); self.prohibit_generics(path.segments[..path.segments.len() - 2].iter(), |_| {}); + // HACK: until we support ``, assume all of them are. + let constness = if tcx.has_attr(tcx.parent(def_id), sym::const_trait) { + ty::BoundConstness::ConstIfConst + } else { + ty::BoundConstness::NotConst + }; self.qpath_to_ty( span, opt_self_ty, def_id, &path.segments[path.segments.len() - 2], path.segments.last().unwrap(), + constness, ) } Res::PrimTy(prim_ty) => { @@ -2658,6 +2690,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &GenericArgs::none(), true, None, + None, ); EarlyBinder(self.normalize_ty(span, tcx.at(span).type_of(def_id))) .subst(tcx, substs) @@ -2766,6 +2799,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } + #[instrument(level = "debug", skip(self, hir_id, unsafety, abi, decl, generics, hir_ty), ret)] pub fn ty_of_fn( &self, hir_id: hir::HirId, @@ -2775,8 +2809,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { generics: Option<&hir::Generics<'_>>, hir_ty: Option<&hir::Ty<'_>>, ) -> ty::PolyFnSig<'tcx> { - debug!("ty_of_fn"); - let tcx = self.tcx(); let bound_vars = tcx.late_bound_vars(hir_id); debug!(?bound_vars); @@ -2826,7 +2858,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir::FnRetTy::DefaultReturn(..) => tcx.mk_unit(), }; - debug!("ty_of_fn: output_ty={:?}", output_ty); + debug!(?output_ty); let fn_ty = tcx.mk_fn_sig(input_tys.into_iter(), output_ty, decl.c_variadic, unsafety, abi); let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars); @@ -2903,8 +2935,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(i), .. }) = hir.get(hir.get_parent_node(fn_hir_id)) else { bug!("ImplItem should have Impl parent") }; - let trait_ref = - self.instantiate_mono_trait_ref(i.of_trait.as_ref()?, self.ast_ty_to_ty(i.self_ty)); + let trait_ref = self.instantiate_mono_trait_ref( + i.of_trait.as_ref()?, + self.ast_ty_to_ty(i.self_ty), + ty::BoundConstness::NotConst, + ); let assoc = tcx.associated_items(trait_ref.def_id).find_by_name_and_kind( tcx, diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 66ca7d7aa08f..0698ec7c4d02 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1143,7 +1143,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { } ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => { - // Do not try to inference the return type for a impl method coming from a trait + // Do not try to infer the return type for a impl method coming from a trait if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) = tcx.hir().get(tcx.hir().get_parent_node(hir_id)) && i.of_trait.is_some() @@ -1286,10 +1286,37 @@ fn infer_return_ty_for_fn_sig<'tcx>( fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { let icx = ItemCtxt::new(tcx, def_id); - match tcx.hir().expect_item(def_id.expect_local()).kind { + let item = tcx.hir().expect_item(def_id.expect_local()); + match item.kind { hir::ItemKind::Impl(ref impl_) => impl_.of_trait.as_ref().map(|ast_trait_ref| { let selfty = tcx.type_of(def_id); - >::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty) + >::instantiate_mono_trait_ref( + &icx, + ast_trait_ref, + selfty, + match impl_.constness { + hir::Constness::Const => { + if let Some(trait_def_id) = ast_trait_ref.trait_def_id() && !tcx.has_attr(trait_def_id, sym::const_trait) { + let trait_name = tcx.item_name(trait_def_id); + let mut err = tcx.sess.struct_span_err( + ast_trait_ref.path.span, + &format!("const `impl` for trait `{trait_name}` which is not marked with `#[const_trait]`"), + ); + if trait_def_id.is_local() { + let sp = tcx.def_span(trait_def_id).shrink_to_lo(); + err.span_suggestion(sp, &format!("mark `{trait_name}` as const"), "#[const_trait]", rustc_errors::Applicability::MachineApplicable); + } + err.note("marking a trait with `#[const_trait]` ensures all default method bodies are `const`"); + err.note("adding a non-const method body in the future would be a breaking change"); + err.emit(); + ty::BoundConstness::NotConst + } else { + ty::BoundConstness::ConstIfConst + } + }, + hir::Constness::NotConst => ty::BoundConstness::NotConst, + }, + ) }), _ => bug!(), } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 0870833cc35a..30feabe1a095 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -303,32 +303,6 @@ impl<'tcx> WfPredicates<'tcx> { let obligations = if trait_pred.constness == ty::BoundConstness::NotConst { self.nominal_obligations_without_const(trait_ref.def_id, trait_ref.substs) } else { - if !tcx.has_attr(trait_ref.def_id, rustc_span::sym::const_trait) { - if let Some(item) = self.item && - let hir::ItemKind::Impl(impl_) = item.kind && - let Some(trait_) = &impl_.of_trait && - let Some(def_id) = trait_.trait_def_id() && - def_id == trait_ref.def_id - { - let trait_name = tcx.item_name(def_id); - let mut err = tcx.sess.struct_span_err( - self.span, - &format!("const `impl` for trait `{trait_name}` which is not marked with `#[const_trait]`"), - ); - if def_id.is_local() { - let sp = tcx.def_span(def_id).shrink_to_lo(); - err.span_suggestion(sp, &format!("mark `{trait_name}` as const"), "#[const_trait]", rustc_errors::Applicability::MachineApplicable); - } - err.note("marking a trait with `#[const_trait]` ensures all default method bodies are `const`"); - err.note("adding a non-const method body in the future would be a breaking change"); - err.emit(); - } else { - tcx.sess.span_err( - self.span, - "~const can only be applied to `#[const_trait]` traits", - ); - } - } self.nominal_obligations(trait_ref.def_id, trait_ref.substs) }; diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr index b86acb2cc9ab..d4f42b787e4d 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr @@ -1,8 +1,8 @@ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-2.rs:11:12 + --> $DIR/super-traits-fail-2.rs:11:19 | LL | trait Bar: ~const Foo {} - | ^^^^^^^^^^ + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr index b86acb2cc9ab..d4f42b787e4d 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr @@ -1,8 +1,8 @@ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-2.rs:11:12 + --> $DIR/super-traits-fail-2.rs:11:19 | LL | trait Bar: ~const Foo {} - | ^^^^^^^^^^ + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr index 191edca1761c..d433e1cfa698 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr @@ -1,14 +1,14 @@ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:12:12 + --> $DIR/super-traits-fail-3.rs:12:19 | LL | trait Bar: ~const Foo {} - | ^^^^^^^^^^ + | ^^^ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:15:17 + --> $DIR/super-traits-fail-3.rs:15:24 | LL | const fn foo(x: &T) { - | ^^^^^^^^^^ + | ^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr index a3b4c302a57f..2a7e8e00bc78 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr @@ -1,8 +1,8 @@ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:12:12 + --> $DIR/super-traits-fail-3.rs:12:19 | LL | trait Bar: ~const Foo {} - | ^^^^^^^^^^ + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr index 9d6116654659..e5978c12a098 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr @@ -1,8 +1,8 @@ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:15:17 + --> $DIR/super-traits-fail-3.rs:15:24 | LL | const fn foo(x: &T) { - | ^^^^^^^^^^ + | ^^^ error: aborting due to previous error From c246a3ddd4ab4e3b43f85c8e04231243a00bc1ee Mon Sep 17 00:00:00 2001 From: Rageking8 Date: Tue, 25 Oct 2022 22:51:47 +0800 Subject: [PATCH 087/171] more dupe typos again --- library/std/src/sync/mpsc/stream.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sync/mpsc/stream.rs b/library/std/src/sync/mpsc/stream.rs index 4c3812c79f61..4592e9141600 100644 --- a/library/std/src/sync/mpsc/stream.rs +++ b/library/std/src/sync/mpsc/stream.rs @@ -114,7 +114,7 @@ impl Packet { match self.queue.producer_addition().cnt.fetch_add(1, Ordering::SeqCst) { // As described in the mod's doc comment, -1 == wakeup -1 => UpWoke(self.take_to_wake()), - // As as described before, SPSC queues must be >= -2 + // As described before, SPSC queues must be >= -2 -2 => UpSuccess, // Be sure to preserve the disconnected state, and the return value From 5378c82d808f01bbb0d1c03ea03b2865f10db8cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Tue, 25 Oct 2022 18:31:11 +0200 Subject: [PATCH 088/171] Use &self instead of &mut self for cast methods --- compiler/rustc_const_eval/src/interpret/cast.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index f980e606b932..cb33c4d4c465 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -139,7 +139,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } pub fn int_to_int_or_float( - &mut self, + &self, src: &ImmTy<'tcx, M::Provenance>, cast_ty: Ty<'tcx>, ) -> InterpResult<'tcx, Immediate> { @@ -154,7 +154,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } pub fn float_to_float_or_int( - &mut self, + &self, src: &ImmTy<'tcx, M::Provenance>, cast_ty: Ty<'tcx>, ) -> InterpResult<'tcx, Immediate> { @@ -176,7 +176,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Handles 'FnPtrToPtr' and 'PtrToPtr' casts. pub fn ptr_to_ptr( - &mut self, + &self, src: &ImmTy<'tcx, M::Provenance>, cast_ty: Ty<'tcx>, ) -> InterpResult<'tcx, Immediate> { @@ -226,7 +226,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } pub fn pointer_from_exposed_address_cast( - &mut self, + &self, src: &ImmTy<'tcx, M::Provenance>, cast_ty: Ty<'tcx>, ) -> InterpResult<'tcx, Immediate> { From 726bf18d2d97eec43196e8ba48be5f28892b6729 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 22 Oct 2022 21:38:05 +0000 Subject: [PATCH 089/171] Name impl trait in region bound suggestion --- .../nice_region_error/static_impl_trait.rs | 21 +++++++++---------- .../ret-impl-trait-one.stderr | 2 +- .../ui/impl-trait/hidden-lifetimes.stderr | 4 ++-- .../ordinary-bounds-unrelated.stderr | 2 +- .../ordinary-bounds-unsuited.stderr | 2 +- .../must_outlive_least_region_or_bound.stderr | 14 ++++++------- .../impl-trait/region-escape-via-bound.stderr | 2 +- .../static-return-lifetime-infered.stderr | 8 +++---- .../ty-outlives/impl-trait-captures.stderr | 2 +- ...types_pin_lifetime_impl_trait-async.stderr | 2 +- ..._self_types_pin_lifetime_impl_trait.stderr | 2 +- .../missing-lifetimes-in-signature.stderr | 2 +- .../trait-object-nested-in-impl-trait.stderr | 4 ++-- 13 files changed, 33 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 6bb736687d6e..a74c172fa0c1 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -286,8 +286,8 @@ pub fn suggest_new_region_bound( ) { debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns); // FIXME: account for the need of parens in `&(dyn Trait + '_)` - let consider = "consider changing the"; - let declare = "to declare that the"; + let consider = "consider changing"; + let declare = "to declare that"; let explicit = format!("you can add an explicit `{}` lifetime bound", lifetime_name); let explicit_static = arg.map(|arg| format!("explicit `'static` bound to the lifetime of {}", arg)); @@ -305,6 +305,10 @@ pub fn suggest_new_region_bound( return; }; + // Get the identity type for this RPIT + let did = item_id.def_id.to_def_id(); + let ty = tcx.mk_opaque(did, ty::InternalSubsts::identity_for_item(tcx, did)); + if let Some(span) = opaque .bounds .iter() @@ -321,7 +325,7 @@ pub fn suggest_new_region_bound( if let Some(explicit_static) = &explicit_static { err.span_suggestion_verbose( span, - &format!("{} `impl Trait`'s {}", consider, explicit_static), + &format!("{consider} `{ty}`'s {explicit_static}"), &lifetime_name, Applicability::MaybeIncorrect, ); @@ -351,12 +355,7 @@ pub fn suggest_new_region_bound( } else { err.span_suggestion_verbose( fn_return.span.shrink_to_hi(), - &format!( - "{declare} `impl Trait` {captures}, {explicit}", - declare = declare, - captures = captures, - explicit = explicit, - ), + &format!("{declare} `{ty}` {captures}, {explicit}",), &plus_lt, Applicability::MaybeIncorrect, ); @@ -367,7 +366,7 @@ pub fn suggest_new_region_bound( err.span_suggestion_verbose( fn_return.span.shrink_to_hi(), &format!( - "{declare} trait object {captures}, {explicit}", + "{declare} the trait object {captures}, {explicit}", declare = declare, captures = captures, explicit = explicit, @@ -384,7 +383,7 @@ pub fn suggest_new_region_bound( if let Some(explicit_static) = &explicit_static { err.span_suggestion_verbose( lt.span, - &format!("{} trait object's {}", consider, explicit_static), + &format!("{} the trait object's {}", consider, explicit_static), &lifetime_name, Applicability::MaybeIncorrect, ); diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr index 3128b4df4e2d..ae4d0d5853ca 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr @@ -25,7 +25,7 @@ LL | | (a, b) LL | | } | |_^ | -help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound +help: to declare that `impl Trait<'a>` captures `'b`, you can add an explicit `'b` lifetime bound | LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b { | ++++ diff --git a/src/test/ui/impl-trait/hidden-lifetimes.stderr b/src/test/ui/impl-trait/hidden-lifetimes.stderr index de06ded7acdb..3cc47e1e89da 100644 --- a/src/test/ui/impl-trait/hidden-lifetimes.stderr +++ b/src/test/ui/impl-trait/hidden-lifetimes.stderr @@ -6,7 +6,7 @@ LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { LL | x | ^ | -help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound +help: to declare that `impl Swap + 'a` captures `'b`, you can add an explicit `'b` lifetime bound | LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a + 'b { | ++++ @@ -19,7 +19,7 @@ LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl S LL | x | ^ | -help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound +help: to declare that `impl Swap + 'a` captures `'b`, you can add an explicit `'b` lifetime bound | LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a + 'b { | ++++ diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr index cb1dc0b7d50a..ec49a61795a0 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr @@ -7,7 +7,7 @@ LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> im LL | if condition() { a } else { b } | ^ | -help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound +help: to declare that `impl Trait<'d, 'e>` captures `'b`, you can add an explicit `'b` lifetime bound | LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b | ++++ diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr index 4388e6601a6c..c36f9bc6957c 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr @@ -7,7 +7,7 @@ LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, LL | if condition() { a } else { b } | ^ | -help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound +help: to declare that `impl Trait<'a, 'b>` captures `'b`, you can add an explicit `'b` lifetime bound | LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b | ++++ diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 16767abd7224..9c81791fbcba 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -6,7 +6,7 @@ LL | fn elided(x: &i32) -> impl Copy { x } | | | hidden type `&i32` captures the anonymous lifetime defined here | -help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound +help: to declare that `impl Copy` captures `'_`, you can add an explicit `'_` lifetime bound | LL | fn elided(x: &i32) -> impl Copy + '_ { x } | ++++ @@ -19,7 +19,7 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | | | hidden type `&'a i32` captures the lifetime `'a` as defined here | -help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound +help: to declare that `impl Copy` captures `'a`, you can add an explicit `'a` lifetime bound | LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ++++ @@ -32,7 +32,7 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | | | let's call the lifetime of this reference `'1` | -help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x` +help: consider changing `impl Copy + 'static`'s explicit `'static` bound to the lifetime of argument `x` | LL | fn elided2(x: &i32) -> impl Copy + '_ { x } | ~~ @@ -47,7 +47,7 @@ error: lifetime may not live long enough LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` | -help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x` +help: consider changing `impl Copy + 'static`'s explicit `'static` bound to the lifetime of argument `x` | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x } | ~~ @@ -76,7 +76,7 @@ help: to declare that the trait object captures data from argument `x`, you can | LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } | ++++ -help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound +help: to declare that `impl Debug` captures data from argument `x`, you can add an explicit `'_` lifetime bound | LL | fn elided5(x: &i32) -> (Box, impl Debug + '_) { (Box::new(x), x) } | ++++ @@ -87,7 +87,7 @@ error: lifetime may not live long enough LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` | -help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x` +help: consider changing `impl LifetimeTrait<'a> + 'static`'s explicit `'static` bound to the lifetime of argument `x` | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x } | ~~ @@ -104,7 +104,7 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32 LL | move |_| println!("{}", y) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound +help: to declare that `impl Fn(&'a u32)` captures `'b`, you can add an explicit `'b` lifetime bound | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) + 'b { | ++++ diff --git a/src/test/ui/impl-trait/region-escape-via-bound.stderr b/src/test/ui/impl-trait/region-escape-via-bound.stderr index fdb2fe022b4d..44a790cb1a43 100644 --- a/src/test/ui/impl-trait/region-escape-via-bound.stderr +++ b/src/test/ui/impl-trait/region-escape-via-bound.stderr @@ -7,7 +7,7 @@ LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> LL | x | ^ | -help: to declare that the `impl Trait` captures `'x`, you can add an explicit `'x` lifetime bound +help: to declare that `impl Trait<'y>` captures `'x`, you can add an explicit `'x` lifetime bound | LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> + 'x | ++++ diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index b86815231550..b365bd884548 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -6,7 +6,7 @@ LL | fn iter_values_anon(&self) -> impl Iterator { LL | self.x.iter().map(|a| a.0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound +help: to declare that `impl Iterator` captures `'_`, you can add an explicit `'_` lifetime bound | LL | fn iter_values_anon(&self) -> impl Iterator + '_ { | ++++ @@ -19,7 +19,7 @@ LL | fn iter_values_anon(&self) -> impl Iterator { LL | self.x.iter().map(|a| a.0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound +help: to declare that `impl Iterator` captures `'_`, you can add an explicit `'_` lifetime bound | LL | fn iter_values_anon(&self) -> impl Iterator + '_ { | ++++ @@ -32,7 +32,7 @@ LL | fn iter_values<'a>(&'a self) -> impl Iterator { LL | self.x.iter().map(|a| a.0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound +help: to declare that `impl Iterator` captures `'a`, you can add an explicit `'a` lifetime bound | LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { | ++++ @@ -45,7 +45,7 @@ LL | fn iter_values<'a>(&'a self) -> impl Iterator { LL | self.x.iter().map(|a| a.0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound +help: to declare that `impl Iterator` captures `'a`, you can add an explicit `'a` lifetime bound | LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { | ++++ diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr index 6a8a1ad1caad..737cb35841cf 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -6,7 +6,7 @@ LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { LL | x | ^ | -help: to declare that the `impl Trait` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))` lifetime bound +help: to declare that `Opaque(DefId(0:13 ~ impl_trait_captures[1afc]::foo::{opaque#0}), [ReEarlyBound(0, 'a), T, ReEarlyBound(2, 'a)])` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))` lifetime bound | LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_)) { | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 7e7d60d0ff90..eb3d3e4a67a9 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -6,7 +6,7 @@ LL | async fn f(self: Pin<&Self>) -> impl Clone { self } | | | hidden type `Pin<&Foo>` captures the anonymous lifetime defined here | -help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound +help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound | LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } | ++++ diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index 30d2250c0c81..2c0b2a0d9193 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -6,7 +6,7 @@ LL | fn f(self: Pin<&Self>) -> impl Clone { self } | | | hidden type `Pin<&Foo>` captures the anonymous lifetime defined here | -help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound +help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound | LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } | ++++ diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 171f4b333db4..fa758bf05df5 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -18,7 +18,7 @@ LL | | *dest = g.get(); LL | | } | |_____^ | -help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound +help: to declare that `impl FnOnce()` captures `'_`, you can add an explicit `'_` lifetime bound | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + '_ | ++++ diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr index f49876bcd3f1..c77ef79e7ed1 100644 --- a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr +++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr @@ -10,7 +10,7 @@ LL | | remaining: self.0.iter(), LL | | } | |_________^ returning this value requires that `'1` must outlive `'static` | -help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound +help: to declare that `impl Iterator>` captures data from argument `self`, you can add an explicit `'_` lifetime bound | LL | fn iter(&self) -> impl Iterator> + '_ { | ++++ @@ -65,7 +65,7 @@ LL | | remaining: self.0.iter(), LL | | } | |_________^ returning this value requires that `'a` must outlive `'static` | -help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'a` lifetime bound +help: to declare that `impl Iterator>` captures data from argument `self`, you can add an explicit `'a` lifetime bound | LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { | ++++ From 43e17454e2d8f650142cb671e13ca70fcbe42fcc Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Mon, 24 Oct 2022 20:59:22 +0200 Subject: [PATCH 090/171] Remove `rustc_driver::set_sigpipe_handler()` Its usage was removed in 5e624bf4ba and 093b075d32, so we do not need to keep it around any longer. According to [preliminary input](https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/Find.20.60rustc_driver.60.20dependent.20projects.3F/near/304490764), we do not need to worry about any deprecation cycle for this API and can just straight up remove it. Migration instructions for remaining clients -------------------------------------------- Change from ```rust extern crate rustc_driver; fn main() { rustc_driver::set_sigpipe_handler(); // ... ``` to ```rust fn main() { // ... ``` --- compiler/rustc_driver/src/lib.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 7edbb6f757ce..cfa734c7df39 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -427,18 +427,6 @@ fn run_compiler( }) } -#[cfg(unix)] -pub fn set_sigpipe_handler() { - unsafe { - // Set the SIGPIPE signal handler, so that an EPIPE - // will cause rustc to terminate, as expected. - assert_ne!(libc::signal(libc::SIGPIPE, libc::SIG_DFL), libc::SIG_ERR); - } -} - -#[cfg(windows)] -pub fn set_sigpipe_handler() {} - // Extract output directory and file from matches. fn make_output(matches: &getopts::Matches) -> (Option, Option) { let odir = matches.opt_str("out-dir").map(|o| PathBuf::from(&o)); From 626d7fc6133d5b3f24689114c0f605e8986e66ba Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 25 Oct 2022 10:43:08 -0700 Subject: [PATCH 091/171] rustdoc: combine shared CSS between `.*-line-numbers` --- src/librustdoc/html/static/css/rustdoc.css | 53 ++++++++-------------- 1 file changed, 20 insertions(+), 33 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 173553ed4774..75b22f682a5f 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -549,47 +549,38 @@ ul.block, .block li { margin-bottom: 0px; } -pre.example-line-numbers { - overflow: initial; - border: 1px solid; - padding: 13px 8px; - text-align: right; - border-top-left-radius: 5px; - border-bottom-left-radius: 5px; -} - -.src-line-numbers { - text-align: right; -} -.rustdoc:not(.source) .example-wrap > pre:not(.example-line-numbers) { - width: 100%; +.rustdoc .example-wrap > pre { + margin: 0; + flex-grow: 1; overflow-x: auto; } -.rustdoc:not(.source) .example-wrap > pre.src-line-numbers { - width: auto; - overflow-x: visible; -} - -.rustdoc .example-wrap > pre { - margin: 0; -} - -.search-loading { - text-align: center; -} - -.content > .example-wrap pre.src-line-numbers { - position: relative; +.rustdoc .example-wrap > pre.example-line-numbers, +.rustdoc .example-wrap > pre.src-line-numbers { + flex-grow: 0; + overflow: initial; + text-align: right; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } + +.example-line-numbers { + border: 1px solid; + padding: 13px 8px; + border-top-left-radius: 5px; + border-bottom-left-radius: 5px; +} + .src-line-numbers span { cursor: pointer; } +.search-loading { + text-align: center; +} + .docblock-short { overflow-wrap: break-word; overflow-wrap: anywhere; @@ -2024,10 +2015,6 @@ in storage.js padding-bottom: 0; } -.scraped-example:not(.expanded) .code-wrapper pre.src-line-numbers { - overflow-x: hidden; -} - .scraped-example .code-wrapper .prev { position: absolute; top: 0.25em; From 1c26a278f30a173a47606695211b586451396fbf Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 25 Oct 2022 18:28:04 +0000 Subject: [PATCH 092/171] Split diagnostic details out into a separate function and fluent files --- .../locales/en-US/hir_analysis.ftl | 9 ++++ .../rustc_hir_analysis/src/astconv/mod.rs | 5 +- compiler/rustc_hir_analysis/src/collect.rs | 48 ++++++++++--------- compiler/rustc_hir_analysis/src/errors.rs | 21 ++++++++ 4 files changed, 57 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl index 357c6900a70e..7ac44312695d 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl @@ -137,3 +137,12 @@ hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(l hir_analysis_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}` hir_analysis_add_missing_parentheses_in_range = you must surround the range in parentheses to call its `{$func_name}` function + +hir_analysis_const_impl_for_non_const_trait = + const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]` + .suggestion = mark `{$trait_name}` as const + .note = marking a trait with `#[const_trait]` ensures all default method bodies are `const` + .adding = adding a non-const method body in the future would be a breaking change + +hir_analysis_const_bound_for_non_const_trait = + ~const can only be applied to `#[const_trait]` traits diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index a4ebe38b02ec..6baf98449775 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -539,10 +539,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if let Some(ty::BoundConstness::ConstIfConst) = constness && generics.has_self && !tcx.has_attr(def_id, sym::const_trait) { - tcx.sess.span_err( - span, - "~const can only be applied to `#[const_trait]` traits", - ); + tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span } ); } (substs, arg_count) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 0698ec7c4d02..e261bb07f954 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1294,34 +1294,38 @@ fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { &icx, ast_trait_ref, selfty, - match impl_.constness { - hir::Constness::Const => { - if let Some(trait_def_id) = ast_trait_ref.trait_def_id() && !tcx.has_attr(trait_def_id, sym::const_trait) { - let trait_name = tcx.item_name(trait_def_id); - let mut err = tcx.sess.struct_span_err( - ast_trait_ref.path.span, - &format!("const `impl` for trait `{trait_name}` which is not marked with `#[const_trait]`"), - ); - if trait_def_id.is_local() { - let sp = tcx.def_span(trait_def_id).shrink_to_lo(); - err.span_suggestion(sp, &format!("mark `{trait_name}` as const"), "#[const_trait]", rustc_errors::Applicability::MachineApplicable); - } - err.note("marking a trait with `#[const_trait]` ensures all default method bodies are `const`"); - err.note("adding a non-const method body in the future would be a breaking change"); - err.emit(); - ty::BoundConstness::NotConst - } else { - ty::BoundConstness::ConstIfConst - } - }, - hir::Constness::NotConst => ty::BoundConstness::NotConst, - }, + check_impl_constness(tcx, impl_.constness, ast_trait_ref), ) }), _ => bug!(), } } +fn check_impl_constness( + tcx: TyCtxt<'_>, + constness: hir::Constness, + ast_trait_ref: &hir::TraitRef<'_>, +) -> ty::BoundConstness { + match constness { + hir::Constness::Const => { + if let Some(trait_def_id) = ast_trait_ref.trait_def_id() && !tcx.has_attr(trait_def_id, sym::const_trait) { + let trait_name = tcx.item_name(trait_def_id).to_string(); + tcx.sess.emit_err(errors::ConstImplForNonConstTrait { + trait_ref_span: ast_trait_ref.path.span, + trait_name, + local_trait_span: trait_def_id.as_local().map(|_| tcx.def_span(trait_def_id).shrink_to_lo()), + marking: (), + adding: (), + }); + ty::BoundConstness::NotConst + } else { + ty::BoundConstness::ConstIfConst + } + }, + hir::Constness::NotConst => ty::BoundConstness::NotConst, + } +} + fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity { let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl); let item = tcx.hir().expect_item(def_id.expect_local()); diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 9457da32ce65..bd0c1f5dd109 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -249,3 +249,24 @@ pub struct ExpectedUsedSymbol { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_const_impl_for_non_const_trait)] +pub struct ConstImplForNonConstTrait { + #[primary_span] + pub trait_ref_span: Span, + pub trait_name: String, + #[suggestion(applicability = "machine-applicable", code = "#[const_trait]")] + pub local_trait_span: Option, + #[note] + pub marking: (), + #[note(adding)] + pub adding: (), +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_const_bound_for_non_const_trait)] +pub struct ConstBoundForNonConstTrait { + #[primary_span] + pub span: Span, +} From 5064648624c94008d54a2f1d754168d1a0d1df26 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Tue, 25 Oct 2022 12:16:25 -0700 Subject: [PATCH 093/171] Pinning tests for some macro_rules things discussed in the lang meeting --- .../ui/macros/macro_rules-unmatchable-literals.rs | 14 ++++++++++++++ .../macros/macro_rules-unmatchable-literals.stderr | 14 ++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/test/ui/macros/macro_rules-unmatchable-literals.rs create mode 100644 src/test/ui/macros/macro_rules-unmatchable-literals.stderr diff --git a/src/test/ui/macros/macro_rules-unmatchable-literals.rs b/src/test/ui/macros/macro_rules-unmatchable-literals.rs new file mode 100644 index 000000000000..bde0fe1a0157 --- /dev/null +++ b/src/test/ui/macros/macro_rules-unmatchable-literals.rs @@ -0,0 +1,14 @@ +// Pinning tests for things that don't work to make sure we notice if that changes + +#![crate_type = "lib"] + +macro_rules! octal_with_bad_digit { + ( 0o1238 ) => {}; //~ ERROR invalid digit +} + +macro_rules! binary_with_bad_digit { + ( 0b012 ) => {}; //~ ERROR invalid digit +} + +// This can't happen for Hex and Decimal as things like `123A` and `0xFFG` +// get treated as unknown *suffixes*, rather than digits. diff --git a/src/test/ui/macros/macro_rules-unmatchable-literals.stderr b/src/test/ui/macros/macro_rules-unmatchable-literals.stderr new file mode 100644 index 000000000000..956a669791d0 --- /dev/null +++ b/src/test/ui/macros/macro_rules-unmatchable-literals.stderr @@ -0,0 +1,14 @@ +error: invalid digit for a base 8 literal + --> $DIR/macro_rules-unmatchable-literals.rs:6:12 + | +LL | ( 0o1238 ) => {}; + | ^ + +error: invalid digit for a base 2 literal + --> $DIR/macro_rules-unmatchable-literals.rs:10:11 + | +LL | ( 0b012 ) => {}; + | ^ + +error: aborting due to 2 previous errors + From ed142028641079918b95b539f0570e92469687fe Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Tue, 25 Oct 2022 21:24:01 +0200 Subject: [PATCH 094/171] Add flag to forbid recovery in the parser --- compiler/rustc_expand/src/mbe/macro_rules.rs | 1 + compiler/rustc_parse/src/parser/expr.rs | 2 ++ compiler/rustc_parse/src/parser/mod.rs | 23 ++++++++++++++++++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 1e268542bcd9..f6fe38174f7c 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -250,6 +250,7 @@ fn expand_macro<'cx>( // hacky, but speeds up the `html5ever` benchmark significantly. (Issue // 68836 suggests a more comprehensive but more complex change to deal with // this situation.) + // FIXME(Nilstrieb): Stop recovery from happening on this parser and retry later with recovery if the macro failed to match. let parser = parser_from_cx(sess, arg.clone()); // Try each arm's matchers. diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index ca216b1cd100..a781748efc52 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2112,6 +2112,8 @@ impl<'a> Parser<'a> { // HACK: This is needed so we can detect whether we're inside a macro, // where regular assumptions about what tokens can follow other tokens // don't necessarily apply. + && self.may_recover() + // FIXME(Nilstrieb): Remove this check once `may_recover` actually stops recovery && self.subparser_name.is_none() { // It is likely that the closure body is a block but where the diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 89c24920f857..89f7ab930b1a 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -115,6 +115,12 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath { }; } +#[derive(Clone, Copy)] +pub enum Recovery { + Allowed, + Forbidden, +} + #[derive(Clone)] pub struct Parser<'a> { pub sess: &'a ParseSess, @@ -152,12 +158,15 @@ pub struct Parser<'a> { /// This allows us to recover when the user forget to add braces around /// multiple statements in the closure body. pub current_closure: Option, + /// Whether the parser is allowed to recover and parse invalid code successfully (and emit a diagnostic as a side effect). + /// This is disabled when parsing macro arguments, see #103534 + pub recovery: Recovery, } -// This type is used a lot, e.g. it's cloned when matching many declarative macro rules. Make sure +// This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. Make sure // it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Parser<'_>, 328); +rustc_data_structures::static_assert_size!(Parser<'_>, 336); /// Stores span information about a closure. #[derive(Clone)] @@ -483,6 +492,7 @@ impl<'a> Parser<'a> { inner_attr_ranges: Default::default(), }, current_closure: None, + recovery: Recovery::Allowed, }; // Make parser point to the first token. @@ -491,6 +501,15 @@ impl<'a> Parser<'a> { parser } + pub fn forbid_recovery(mut self) -> Self { + self.recovery = Recovery::Forbidden; + self + } + + fn may_recover(&self) -> bool { + matches!(self.recovery, Recovery::Allowed) + } + pub fn unexpected(&mut self) -> PResult<'a, T> { match self.expect_one_of(&[], &[]) { Err(e) => Err(e), From 52fda858ddb5f4a6ce2826f7305ac83973a0ad43 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 25 Oct 2022 22:09:35 +0200 Subject: [PATCH 095/171] interpret: a bit of cast cleanup --- .../rustc_const_eval/src/interpret/cast.rs | 61 +++++++++---------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index f980e606b932..9742dca01deb 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -138,21 +138,19 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(()) } + /// Handles 'IntToInt' and 'IntToFloat' casts. pub fn int_to_int_or_float( &mut self, src: &ImmTy<'tcx, M::Provenance>, cast_ty: Ty<'tcx>, ) -> InterpResult<'tcx, Immediate> { - if (src.layout.ty.is_integral() || src.layout.ty.is_char() || src.layout.ty.is_bool()) - && (cast_ty.is_floating_point() || cast_ty.is_integral() || cast_ty.is_char()) - { - let scalar = src.to_scalar(); - Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into()) - } else { - bug!("Unexpected cast from type {:?}", src.layout.ty) - } + assert!(src.layout.ty.is_integral() || src.layout.ty.is_char() || src.layout.ty.is_bool()); + assert!(cast_ty.is_floating_point() || cast_ty.is_integral() || cast_ty.is_char()); + + Ok(self.cast_from_int_like(src.to_scalar(), src.layout, cast_ty)?.into()) } + /// Handles 'FloatToFloat' and 'FloatToInt' casts. pub fn float_to_float_or_int( &mut self, src: &ImmTy<'tcx, M::Provenance>, @@ -180,31 +178,29 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { src: &ImmTy<'tcx, M::Provenance>, cast_ty: Ty<'tcx>, ) -> InterpResult<'tcx, Immediate> { + assert!(src.layout.ty.is_any_ptr()); + assert!(cast_ty.is_unsafe_ptr()); // Handle casting any ptr to raw ptr (might be a fat ptr). - if src.layout.ty.is_any_ptr() && cast_ty.is_unsafe_ptr() { - let dest_layout = self.layout_of(cast_ty)?; - if dest_layout.size == src.layout.size { - // Thin or fat pointer that just hast the ptr kind of target type changed. - return Ok(**src); - } else { - // Casting the metadata away from a fat ptr. - assert_eq!(src.layout.size, 2 * self.pointer_size()); - assert_eq!(dest_layout.size, self.pointer_size()); - assert!(src.layout.ty.is_unsafe_ptr()); - return match **src { - Immediate::ScalarPair(data, _) => Ok(data.into()), - Immediate::Scalar(..) => span_bug!( - self.cur_span(), - "{:?} input to a fat-to-thin cast ({:?} -> {:?})", - *src, - src.layout.ty, - cast_ty - ), - Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)), - }; - } + let dest_layout = self.layout_of(cast_ty)?; + if dest_layout.size == src.layout.size { + // Thin or fat pointer that just hast the ptr kind of target type changed. + return Ok(**src); } else { - bug!("Can't cast 'Ptr' or 'FnPtr' into {:?}", cast_ty); + // Casting the metadata away from a fat ptr. + assert_eq!(src.layout.size, 2 * self.pointer_size()); + assert_eq!(dest_layout.size, self.pointer_size()); + assert!(src.layout.ty.is_unsafe_ptr()); + return match **src { + Immediate::ScalarPair(data, _) => Ok(data.into()), + Immediate::Scalar(..) => span_bug!( + self.cur_span(), + "{:?} input to a fat-to-thin cast ({:?} -> {:?})", + *src, + src.layout.ty, + cast_ty + ), + Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)), + }; } } @@ -243,6 +239,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(Scalar::from_maybe_pointer(ptr, self).into()) } + /// Low-level cast helper function. This works directly on scalars and can take 'int-like' input + /// type (basically everything with a scalar layout) to int/float/char types. pub fn cast_from_int_like( &self, scalar: Scalar, // input value (there is no ScalarTy so we separate data+layout) @@ -282,6 +280,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }) } + /// Low-level cast helper function. Converts an apfloat `f` into int or float types. fn cast_from_float(&self, f: F, dest_ty: Ty<'tcx>) -> Scalar where F: Float + Into> + FloatConvert + FloatConvert, From 641bf083969ce1bd519d8270c1985c9a86f3a0af Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 25 Oct 2022 16:27:21 +0200 Subject: [PATCH 096/171] Don't merge inline doc comments for impl blocks --- src/librustdoc/clean/inline.rs | 43 +++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 432d318907fa..88592494493b 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -55,12 +55,39 @@ pub(crate) fn try_inline( let mut ret = Vec::new(); debug!("attrs={:?}", attrs); - let attrs_clone = attrs; + + let attrs_without_docs = attrs.map(|attrs| { + attrs.into_iter().filter(|a| a.doc_str().is_none()).cloned().collect::>() + }); + // We need this ugly code because: + // + // ``` + // attrs_without_docs.map(|a| a.as_slice()) + // ``` + // + // will fail because it returns a temporary slice and: + // + // ``` + // attrs_without_docs.map(|s| { + // vec = s.as_slice(); + // vec + // }) + // ``` + // + // will fail because we're moving an uninitialized variable into a closure. + let vec; + let attrs_without_docs = match attrs_without_docs { + Some(s) => { + vec = s; + Some(vec.as_slice()) + } + None => None, + }; let kind = match res { Res::Def(DefKind::Trait, did) => { record_extern_fqn(cx, did, ItemType::Trait); - build_impls(cx, Some(parent_module), did, attrs, &mut ret); + build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret); clean::TraitItem(Box::new(build_external_trait(cx, did))) } Res::Def(DefKind::Fn, did) => { @@ -69,27 +96,27 @@ pub(crate) fn try_inline( } Res::Def(DefKind::Struct, did) => { record_extern_fqn(cx, did, ItemType::Struct); - build_impls(cx, Some(parent_module), did, attrs, &mut ret); + build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret); clean::StructItem(build_struct(cx, did)) } Res::Def(DefKind::Union, did) => { record_extern_fqn(cx, did, ItemType::Union); - build_impls(cx, Some(parent_module), did, attrs, &mut ret); + build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret); clean::UnionItem(build_union(cx, did)) } Res::Def(DefKind::TyAlias, did) => { record_extern_fqn(cx, did, ItemType::Typedef); - build_impls(cx, Some(parent_module), did, attrs, &mut ret); + build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret); clean::TypedefItem(build_type_alias(cx, did)) } Res::Def(DefKind::Enum, did) => { record_extern_fqn(cx, did, ItemType::Enum); - build_impls(cx, Some(parent_module), did, attrs, &mut ret); + build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret); clean::EnumItem(build_enum(cx, did)) } Res::Def(DefKind::ForeignTy, did) => { record_extern_fqn(cx, did, ItemType::ForeignType); - build_impls(cx, Some(parent_module), did, attrs, &mut ret); + build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret); clean::ForeignTypeItem } // Never inline enum variants but leave them shown as re-exports. @@ -123,7 +150,7 @@ pub(crate) fn try_inline( _ => return None, }; - let (attrs, cfg) = merge_attrs(cx, Some(parent_module), load_attrs(cx, did), attrs_clone); + let (attrs, cfg) = merge_attrs(cx, Some(parent_module), load_attrs(cx, did), attrs); cx.inlined.insert(did.into()); let mut item = clean::Item::from_def_id_and_attrs_and_parts( did, From a4279a1d1f9fd8bde6dfc46ac9d53d72fd32a41d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 25 Oct 2022 16:28:27 +0200 Subject: [PATCH 097/171] Add regression test for inlined doc comment on impl block --- src/test/rustdoc/auxiliary/reexport-doc-aux.rs | 5 +++++ src/test/rustdoc/reexport-doc.rs | 8 ++++++++ 2 files changed, 13 insertions(+) create mode 100644 src/test/rustdoc/auxiliary/reexport-doc-aux.rs create mode 100644 src/test/rustdoc/reexport-doc.rs diff --git a/src/test/rustdoc/auxiliary/reexport-doc-aux.rs b/src/test/rustdoc/auxiliary/reexport-doc-aux.rs new file mode 100644 index 000000000000..3400717eba1e --- /dev/null +++ b/src/test/rustdoc/auxiliary/reexport-doc-aux.rs @@ -0,0 +1,5 @@ +pub struct Foo; + +impl Foo { + pub fn foo() {} +} diff --git a/src/test/rustdoc/reexport-doc.rs b/src/test/rustdoc/reexport-doc.rs new file mode 100644 index 000000000000..df2c889b4d57 --- /dev/null +++ b/src/test/rustdoc/reexport-doc.rs @@ -0,0 +1,8 @@ +// aux-build:reexport-doc-aux.rs + +extern crate reexport_doc_aux as dep; + +// @has 'reexport_doc/struct.Foo.html' +// @count - '//p' 'These are the docs for Foo.' 1 +/// These are the docs for Foo. +pub use dep::Foo; From b205a5a67c3ababf7e7d6f47fe667f4dd5f12e58 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 25 Oct 2022 14:46:14 -0700 Subject: [PATCH 098/171] diagnostics: do not suggest static candidates as traits to import If it's a static candidate, then it's already implemented. Do not suggest it a second time for implementing. --- .../rustc_hir_typeck/src/method/suggest.rs | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index f4351bfa84ae..6c21ed902d00 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -106,7 +106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let report_candidates = |span: Span, err: &mut Diagnostic, - mut sources: Vec, + sources: &mut Vec, sugg_span: Span| { sources.sort(); sources.dedup(); @@ -248,7 +248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match error { MethodError::NoMatch(NoMatchData { - static_candidates: static_sources, + static_candidates: mut static_sources, unsatisfied_predicates, out_of_scope_traits, lev_candidate, @@ -422,9 +422,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.help(&format!("try with `{}::{}`", ty_str, item_name,)); } - report_candidates(span, &mut err, static_sources, sugg_span); + report_candidates(span, &mut err, &mut static_sources, sugg_span); } else if static_sources.len() > 1 { - report_candidates(span, &mut err, static_sources, sugg_span); + report_candidates(span, &mut err, &mut static_sources, sugg_span); } let mut bound_spans = vec![]; @@ -1007,6 +1007,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { source, out_of_scope_traits, &unsatisfied_predicates, + &static_sources, unsatisfied_bounds, ); } @@ -1079,7 +1080,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return Some(err); } - MethodError::Ambiguity(sources) => { + MethodError::Ambiguity(mut sources) => { let mut err = struct_span_err!( self.sess(), item_name.span, @@ -1088,7 +1089,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); err.span_label(item_name.span, format!("multiple `{}` found", item_name)); - report_candidates(span, &mut err, sources, sugg_span); + report_candidates(span, &mut err, &mut sources, sugg_span); err.emit(); } @@ -2015,6 +2016,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Option>, Option>, )], + static_candidates: &[CandidateSource], unsatisfied_bounds: bool, ) { let mut alt_rcvr_sugg = false; @@ -2128,6 +2130,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(attr) => attr.level.is_stable(), None => true, }) + .filter(|info| { + // Static candidates are already implemented, and known not to work + // Do not suggest them again + static_candidates.iter().all(|sc| match *sc { + CandidateSource::Trait(def_id) => def_id != info.def_id, + CandidateSource::Impl(def_id) => { + self.tcx.trait_id_of_impl(def_id) != Some(info.def_id) + } + }) + }) .filter(|info| { // We approximate the coherence rules to only suggest // traits that are legal to implement by requiring that From 0c3ae7d97ca36a86a8122429bdc274356c43baa6 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 16 Oct 2022 01:03:52 -0400 Subject: [PATCH 099/171] Try to say that memory outside the AM is always exposed Co-authored-by: Ralf Jung --- library/core/src/ptr/mod.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index cfffe351a87d..2c19c27681f3 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -581,12 +581,20 @@ pub const fn invalid_mut(addr: usize) -> *mut T { /// Convert an address back to a pointer, picking up a previously 'exposed' provenance. /// /// This is equivalent to `addr as *const T`. The provenance of the returned pointer is that of *any* -/// pointer that was previously passed to [`expose_addr`][pointer::expose_addr] or a `ptr as usize` -/// cast. If there is no previously 'exposed' provenance that justifies the way this pointer will be -/// used, the program has undefined behavior. Note that there is no algorithm that decides which -/// provenance will be used. You can think of this as "guessing" the right provenance, and the guess -/// will be "maximally in your favor", in the sense that if there is any way to avoid undefined -/// behavior, then that is the guess that will be taken. +/// pointer that was previously exposed by passing it to [`expose_addr`][pointer::expose_addr], +/// or a `ptr as usize` cast. In addition, memory which is outside the control of the Rust abstract +/// machine (MMIO registers, for example) is always considered to be exposed, so long as this memory +/// is disjoint from memory that will be used by the abstract machine such as the stack, heap, +/// and statics. +/// +/// If there is no 'exposed' provenance that justifies the way this pointer will be used, +/// the program has undefined behavior. In particular, the aliasing rules still apply: pointers +/// and references that have been invalidated due to aliasing accesses cannot be used any more, +/// even if they have been exposed! +/// Note that there is no algorithm that decides which provenance will be used. You can think of this +/// as "guessing" the right provenance, and the guess will be "maximally in your favor", in the sense +/// that if there is any way to avoid undefined behavior (while upholding all aliasing requirements), +/// then that is the guess that will be taken. /// /// On platforms with multiple address spaces, it is your responsibility to ensure that the /// address makes sense in the address space that this pointer will be used with. From 6ea75aea56ab66069b72a29335831f8395e6ee2b Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Tue, 25 Oct 2022 15:03:21 -0700 Subject: [PATCH 100/171] llvm-16: Don't initialize removed legacy passes LLVM removed initialization for legacy passes: https://reviews.llvm.org/D136615 --- compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 879a3b660b4b..18d37d95a835 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -69,7 +69,9 @@ extern "C" void LLVMInitializePasses() { initializeAnalysis(Registry); initializeTransformUtils(Registry); initializeInstCombine(Registry); +#if LLVM_VERSION_LT(16, 0) initializeInstrumentation(Registry); +#endif initializeTarget(Registry); } From 952585c1eb43ae456c1413d6c609d5a9d31fb5a5 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 25 Oct 2022 12:34:05 -0700 Subject: [PATCH 101/171] Update books --- src/doc/book | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/book b/src/doc/book index f1e5ad844d0c..aa5ee485bd6b 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit f1e5ad844d0c61738006cdef26227beeb136948e +Subproject commit aa5ee485bd6bd80d205da7c82fcdd776f92fdd51 diff --git a/src/doc/reference b/src/doc/reference index f6ed74f582bd..4ea7c5def38a 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit f6ed74f582bddcec73f753eafaab3749c4f7df61 +Subproject commit 4ea7c5def38ac81df33a9e48e5637a82a5ac404d diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 5e7b296d6c34..03491f33375c 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 5e7b296d6c345addbd748f242aae28c42555c015 +Subproject commit 03491f33375c5a2a1661c7fa4be671fe95ce1249 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 7518c3445dc0..51a37ad19a15 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 7518c3445dc02df0d196f5f84e568d633c5141fb +Subproject commit 51a37ad19a15709d0601afbac6581f5aea6a45da From 8cf9ad634b049af8b9f442e5b31bc6a85c3a3392 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 25 Oct 2022 15:28:02 -0700 Subject: [PATCH 102/171] diagnostics: add test case for issue 102354 --- src/test/ui/suggestions/issue-102354.rs | 10 +++++++++ src/test/ui/suggestions/issue-102354.stderr | 24 +++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 src/test/ui/suggestions/issue-102354.rs create mode 100644 src/test/ui/suggestions/issue-102354.stderr diff --git a/src/test/ui/suggestions/issue-102354.rs b/src/test/ui/suggestions/issue-102354.rs new file mode 100644 index 000000000000..f881feb0060a --- /dev/null +++ b/src/test/ui/suggestions/issue-102354.rs @@ -0,0 +1,10 @@ +trait Trait { + fn func() {} +} + +impl Trait for i32 {} + +fn main() { + let x: i32 = 123; + x.func(); //~ERROR no method +} diff --git a/src/test/ui/suggestions/issue-102354.stderr b/src/test/ui/suggestions/issue-102354.stderr new file mode 100644 index 000000000000..4f76c5f2e75b --- /dev/null +++ b/src/test/ui/suggestions/issue-102354.stderr @@ -0,0 +1,24 @@ +error[E0599]: no method named `func` found for type `i32` in the current scope + --> $DIR/issue-102354.rs:9:7 + | +LL | x.func(); + | ^^^^ this is an associated function, not a method + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in the trait `Trait` + --> $DIR/issue-102354.rs:2:5 + | +LL | fn func() {} + | ^^^^^^^^^ +help: use associated function syntax instead + | +LL | i32::func(); + | ~~~~~~~~~ +help: disambiguate the associated function for the candidate + | +LL | ::func(x); + | ~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. From 60b5f6dc9190c1fa10c2ca22d472d32f9689253e Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 25 Oct 2022 16:52:50 -0700 Subject: [PATCH 103/171] rustdoc: add visible focus outline to rustdoc-toggle The change in opacity is inconsistent with most of rustdoc, which uses default browser styles for the focus outline. Unfortunately, just using the default focus outline here won't work, because it gets applied to the summary itself instead of the pseudo-element "real button." --- src/librustdoc/html/static/css/rustdoc.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 173553ed4774..84a1fa2e28ec 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1585,6 +1585,14 @@ details.rustdoc-toggle > summary:hover::before { opacity: 1; } +details.rustdoc-toggle > summary:focus-visible::before { + /* The SVG is black, and gets turned white using a filter. + Do the same with the outline. + */ + outline: 1px dotted #000; + outline-offset: 1px; +} + details.rustdoc-toggle.top-doc > summary, details.rustdoc-toggle.top-doc > summary::before, details.rustdoc-toggle.non-exhaustive > summary, From 67c4c1fc8fa92fe823e8fb2d8531153de3762f2d Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Wed, 26 Oct 2022 09:20:22 +0800 Subject: [PATCH 104/171] Update cargo 5 commits in 071eeaf210708219a5a1b2c4728ca2f97df7f2ae..9210810d1fd7b51ae0439a0a363cc50e36963455 2022-10-22 01:17:55 +0000 to 2022-10-25 22:31:50 +0000 - Fix 410 gone response handling (rust-lang/cargo#11286) - Fix inequality in "stale mtime" log messages (rust-lang/cargo#11281) - doc(cargo-tree): mention it considering feature unification (rust-lang/cargo#11282) - Improve the error message if `publish` is `false` or empty list (rust-lang/cargo#11280) - Add test for deleted index entry (rust-lang/cargo#11278) --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 071eeaf21070..9210810d1fd7 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 071eeaf210708219a5a1b2c4728ca2f97df7f2ae +Subproject commit 9210810d1fd7b51ae0439a0a363cc50e36963455 From 20ab57e582edc0a562a20f37700d0af90adcb10b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 26 Oct 2022 09:48:47 +0200 Subject: [PATCH 105/171] library: allow some unused things in Miri --- library/std/src/sys/unix/fs.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index e22b2f3340af..37a49f2d78ac 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1,3 +1,6 @@ +// miri has some special hacks here that make things unused. +#![cfg_attr(miri, allow(unused))] + use crate::os::unix::prelude::*; use crate::ffi::{CStr, OsStr, OsString}; @@ -850,7 +853,6 @@ impl DirEntry { target_os = "fuchsia", target_os = "redox" )))] - #[cfg_attr(miri, allow(unused))] fn name_cstr(&self) -> &CStr { unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()) } } @@ -862,7 +864,6 @@ impl DirEntry { target_os = "fuchsia", target_os = "redox" ))] - #[cfg_attr(miri, allow(unused))] fn name_cstr(&self) -> &CStr { &self.name } From 99a74afa5fdc2318e7245e6657a3f21695526356 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 26 Oct 2022 11:15:14 +0200 Subject: [PATCH 106/171] ptr::eq: clarify that comparing dyn Trait is fragile --- library/alloc/src/rc.rs | 10 +++++----- library/alloc/src/sync.rs | 10 +++++----- library/core/src/ptr/mod.rs | 40 +++++-------------------------------- 3 files changed, 15 insertions(+), 45 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 9c229665c7e9..006d813e5f9f 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1110,8 +1110,8 @@ impl Rc { #[inline] #[stable(feature = "ptr_eq", since = "1.17.0")] - /// Returns `true` if the two `Rc`s point to the same allocation - /// (in a vein similar to [`ptr::eq`]). + /// Returns `true` if the two `Rc`s point to the same allocation in a vein similar to + /// [`ptr::eq`]. See [that function][`ptr::eq`] for caveats when comparing `dyn Trait` pointers. /// /// # Examples /// @@ -2419,9 +2419,9 @@ impl Weak { } } - /// Returns `true` if the two `Weak`s point to the same allocation (similar to - /// [`ptr::eq`]), or if both don't point to any allocation - /// (because they were created with `Weak::new()`). + /// Returns `true` if the two `Weak`s point to the same allocation similar to [`ptr::eq`], or if + /// both don't point to any allocation (because they were created with `Weak::new()`). See [that + /// function][`ptr::eq`] for caveats when comparing `dyn Trait` pointers. /// /// # Notes /// diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index e8d9de4fb3ce..81cd77074885 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1117,8 +1117,8 @@ impl Arc { drop(Weak { ptr: self.ptr }); } - /// Returns `true` if the two `Arc`s point to the same allocation - /// (in a vein similar to [`ptr::eq`]). + /// Returns `true` if the two `Arc`s point to the same allocation in a vein similar to + /// [`ptr::eq`]. See [that function][`ptr::eq`] for caveats when comparing `dyn Trait` pointers. /// /// # Examples /// @@ -2069,9 +2069,9 @@ impl Weak { } } - /// Returns `true` if the two `Weak`s point to the same allocation (similar to - /// [`ptr::eq`]), or if both don't point to any allocation - /// (because they were created with `Weak::new()`). + /// Returns `true` if the two `Weak`s point to the same allocation similar to [`ptr::eq`], or if + /// both don't point to any allocation (because they were created with `Weak::new()`). See [that + /// function][`ptr::eq`] for caveats when comparing `dyn Trait` pointers. /// /// # Notes /// diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index cfffe351a87d..a4b89fc62f2c 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1733,6 +1733,11 @@ pub(crate) unsafe fn align_offset(p: *const T, a: usize) -> usize { /// by their address rather than comparing the values they point to /// (which is what the `PartialEq for &T` implementation does). /// +/// However, note that comparing trait object pointers (`*const dyn Trait`) is unrealiable: pointers +/// to values of the same underlying type can compare inequal (because vtables are duplicated in +/// multiple codegen units), and pointers to values of *different* underlying type can compare equal +/// (since identical vtables can be deduplicated within a codegen unit). +/// /// # Examples /// /// ``` @@ -1759,41 +1764,6 @@ pub(crate) unsafe fn align_offset(p: *const T, a: usize) -> usize { /// assert!(!std::ptr::eq(&a[..2], &a[..3])); /// assert!(!std::ptr::eq(&a[0..2], &a[1..3])); /// ``` -/// -/// Traits are also compared by their implementation: -/// -/// ``` -/// #[repr(transparent)] -/// struct Wrapper { member: i32 } -/// -/// trait Trait {} -/// impl Trait for Wrapper {} -/// impl Trait for i32 {} -/// -/// let wrapper = Wrapper { member: 10 }; -/// -/// // Pointers have equal addresses. -/// assert!(std::ptr::eq( -/// &wrapper as *const Wrapper as *const u8, -/// &wrapper.member as *const i32 as *const u8 -/// )); -/// -/// // Objects have equal addresses, but `Trait` has different implementations. -/// assert!(!std::ptr::eq( -/// &wrapper as &dyn Trait, -/// &wrapper.member as &dyn Trait, -/// )); -/// assert!(!std::ptr::eq( -/// &wrapper as &dyn Trait as *const dyn Trait, -/// &wrapper.member as &dyn Trait as *const dyn Trait, -/// )); -/// -/// // Converting the reference to a `*const u8` compares by address. -/// assert!(std::ptr::eq( -/// &wrapper as &dyn Trait as *const dyn Trait as *const u8, -/// &wrapper.member as &dyn Trait as *const dyn Trait as *const u8, -/// )); -/// ``` #[stable(feature = "ptr_eq", since = "1.17.0")] #[inline] pub fn eq(a: *const T, b: *const T) -> bool { From b857138d3bad1372618cb925963a9e1fb512fd8e Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 26 Oct 2022 02:41:34 -0700 Subject: [PATCH 107/171] Update src/librustdoc/html/static/css/rustdoc.css Co-authored-by: Jacob Hoffman-Andrews --- src/librustdoc/html/static/css/rustdoc.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 84a1fa2e28ec..8424b2c4e293 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1586,8 +1586,9 @@ details.rustdoc-toggle > summary:hover::before { } details.rustdoc-toggle > summary:focus-visible::before { - /* The SVG is black, and gets turned white using a filter. + /* The SVG is black, and gets turned white using a filter in the dark themes. Do the same with the outline. + The dotted 1px style is copied from Firefox's focus ring style. */ outline: 1px dotted #000; outline-offset: 1px; From 1946a1842e3e12be48d1e9e6f874c3924d58b8fc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 26 Oct 2022 14:20:31 +0200 Subject: [PATCH 108/171] explicitly mention that both components of wide prts are compared --- library/core/src/ptr/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index a4b89fc62f2c..3a70981d2e13 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1733,6 +1733,7 @@ pub(crate) unsafe fn align_offset(p: *const T, a: usize) -> usize { /// by their address rather than comparing the values they point to /// (which is what the `PartialEq for &T` implementation does). /// +/// When comparing wide pointers, both the address and the metadata are tested for equality. /// However, note that comparing trait object pointers (`*const dyn Trait`) is unrealiable: pointers /// to values of the same underlying type can compare inequal (because vtables are duplicated in /// multiple codegen units), and pointers to values of *different* underlying type can compare equal From 34eb73c72d7e40d61ca2efa0dd1fedc89e21f0b8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 22 Sep 2022 16:19:53 +0300 Subject: [PATCH 109/171] privacy: Rename "accessibility levels" to "effective visibilities" And a couple of other naming tweaks Related to https://github.com/rust-lang/rust/issues/48054 --- compiler/rustc_interface/src/passes.rs | 2 +- compiler/rustc_lint/src/builtin.rs | 9 +- compiler/rustc_lint/src/context.rs | 4 +- compiler/rustc_lint/src/late.rs | 8 +- compiler/rustc_lint/src/lib.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 5 +- compiler/rustc_middle/src/arena.rs | 2 +- compiler/rustc_middle/src/middle/privacy.rs | 159 +++++++++--------- compiler/rustc_middle/src/query/mod.rs | 6 +- compiler/rustc_middle/src/ty/mod.rs | 4 +- compiler/rustc_middle/src/ty/query.rs | 2 +- compiler/rustc_passes/src/dead.rs | 8 +- compiler/rustc_passes/src/reachable.rs | 14 +- compiler/rustc_passes/src/stability.rs | 15 +- compiler/rustc_privacy/src/lib.rs | 132 +++++++-------- ...ss_levels.rs => effective_visibilities.rs} | 61 ++++--- compiler/rustc_resolve/src/lib.rs | 21 +-- .../rustc_save_analysis/src/dump_visitor.rs | 2 +- compiler/rustc_save_analysis/src/lib.rs | 14 +- src/librustdoc/clean/blanket_impl.rs | 2 +- src/librustdoc/clean/inline.rs | 4 +- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/core.rs | 4 +- src/librustdoc/formats/cache.rs | 18 +- src/librustdoc/html/format.rs | 2 +- .../passes/check_doc_test_visibility.rs | 4 +- .../passes/collect_intra_doc_links.rs | 4 +- src/librustdoc/passes/strip_private.rs | 2 +- src/librustdoc/passes/stripper.rs | 14 +- src/librustdoc/visit_ast.rs | 8 +- src/librustdoc/visit_lib.rs | 24 +-- src/test/ui/privacy/access_levels.rs | 75 --------- src/test/ui/privacy/access_levels.stderr | 134 --------------- src/test/ui/privacy/effective_visibilities.rs | 75 +++++++++ .../ui/privacy/effective_visibilities.stderr | 134 +++++++++++++++ src/tools/clippy/clippy_lints/src/doc.rs | 2 +- .../clippy/clippy_lints/src/enum_variants.rs | 2 +- .../clippy_lints/src/exhaustive_items.rs | 2 +- .../clippy_lints/src/functions/must_use.rs | 8 +- .../src/functions/not_unsafe_ptr_arg_deref.rs | 2 +- .../clippy_lints/src/functions/result.rs | 6 +- .../clippy_lints/src/implicit_hasher.rs | 2 +- src/tools/clippy/clippy_lints/src/len_zero.rs | 6 +- .../clippy/clippy_lints/src/methods/mod.rs | 4 +- .../clippy/clippy_lints/src/missing_inline.rs | 6 +- .../clippy_lints/src/new_without_default.rs | 2 +- .../clippy_lints/src/pass_by_ref_or_value.rs | 2 +- .../clippy_lints/src/redundant_pub_crate.rs | 4 +- .../src/return_self_not_must_use.rs | 2 +- .../clippy/clippy_lints/src/types/mod.rs | 8 +- .../clippy_lints/src/unnecessary_wraps.rs | 2 +- .../clippy/clippy_lints/src/unused_self.rs | 2 +- .../clippy_lints/src/upper_case_acronyms.rs | 2 +- 53 files changed, 524 insertions(+), 516 deletions(-) rename compiler/rustc_resolve/src/{access_levels.rs => effective_visibilities.rs} (76%) delete mode 100644 src/test/ui/privacy/access_levels.rs delete mode 100644 src/test/ui/privacy/access_levels.stderr create mode 100644 src/test/ui/privacy/effective_visibilities.rs create mode 100644 src/test/ui/privacy/effective_visibilities.stderr diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 9d2325e8265e..7f1d21bf1d8b 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -927,7 +927,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { sess.time("misc_checking_3", || { parallel!( { - tcx.ensure().privacy_access_levels(()); + tcx.ensure().effective_visibilities(()); parallel!( { diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 53c491051342..fa20e34f9ca2 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -563,7 +563,7 @@ impl MissingDoc { // It's an option so the crate root can also use this function (it doesn't // have a `NodeId`). if def_id != CRATE_DEF_ID { - if !cx.access_levels.is_exported(def_id) { + if !cx.effective_visibilities.is_exported(def_id) { return; } } @@ -721,7 +721,7 @@ declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS]) impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - if !cx.access_levels.is_reachable(item.def_id.def_id) { + if !cx.effective_visibilities.is_reachable(item.def_id.def_id) { return; } let (def, ty) = match item.kind { @@ -814,7 +814,7 @@ impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]); impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - if !cx.access_levels.is_reachable(item.def_id.def_id) { + if !cx.effective_visibilities.is_reachable(item.def_id.def_id) { return; } @@ -1385,7 +1385,8 @@ impl UnreachablePub { exportable: bool, ) { let mut applicability = Applicability::MachineApplicable; - if cx.tcx.visibility(def_id).is_public() && !cx.access_levels.is_reachable(def_id) { + if cx.tcx.visibility(def_id).is_public() && !cx.effective_visibilities.is_reachable(def_id) + { if vis_span.from_expansion() { applicability = Applicability::MaybeIncorrect; } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 63a11877333e..cec0003ffea7 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -31,7 +31,7 @@ use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; -use rustc_middle::middle::privacy::AccessLevels; +use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::middle::stability; use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -542,7 +542,7 @@ pub struct LateContext<'tcx> { pub param_env: ty::ParamEnv<'tcx>, /// Items accessible from the crate being checked. - pub access_levels: &'tcx AccessLevels, + pub effective_visibilities: &'tcx EffectiveVisibilities, /// The store of registered lints and the lint levels. pub lint_store: &'tcx LintStore, diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index d4e19ef6b223..303fcb1a1d15 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -338,14 +338,14 @@ fn late_lint_mod_pass<'tcx, T: LateLintPass<'tcx>>( module_def_id: LocalDefId, pass: T, ) { - let access_levels = &tcx.privacy_access_levels(()); + let effective_visibilities = &tcx.effective_visibilities(()); let context = LateContext { tcx, enclosing_body: None, cached_typeck_results: Cell::new(None), param_env: ty::ParamEnv::empty(), - access_levels, + effective_visibilities, lint_store: unerased_lint_store(tcx), last_node_with_lint_attrs: tcx.hir().local_def_id_to_hir_id(module_def_id), generics: None, @@ -386,14 +386,14 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx>>( } fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T) { - let access_levels = &tcx.privacy_access_levels(()); + let effective_visibilities = &tcx.effective_visibilities(()); let context = LateContext { tcx, enclosing_body: None, cached_typeck_results: Cell::new(None), param_env: ty::ParamEnv::empty(), - access_levels, + effective_visibilities, lint_store: unerased_lint_store(tcx), last_node_with_lint_attrs: hir::CRATE_HIR_ID, generics: None, diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index fee6e080c4fc..5288fc542d79 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -212,7 +212,7 @@ macro_rules! late_lint_mod_passes { TypeLimits: TypeLimits::new(), NonSnakeCase: NonSnakeCase, InvalidNoMangleItems: InvalidNoMangleItems, - // Depends on access levels + // Depends on effective visibilities UnreachablePub: UnreachablePub, ExplicitOutlivesRequirements: ExplicitOutlivesRequirements, InvalidValue: InvalidValue, diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index c019211a948e..97c55bf19c7b 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -787,9 +787,8 @@ fn should_encode_attr( } else if attr.doc_str().is_some() { // We keep all public doc comments because they might be "imported" into downstream crates // if they use `#[doc(inline)]` to copy an item's documentation into their own. - *is_def_id_public.get_or_insert_with(|| { - tcx.privacy_access_levels(()).get_effective_vis(def_id).is_some() - }) + *is_def_id_public + .get_or_insert_with(|| tcx.effective_visibilities(()).effective_vis(def_id).is_some()) } else if attr.has_name(sym::doc) { // If this is a `doc` attribute, and it's marked `inline` (as in `#[doc(inline)]`), we can // remove it. It won't be inlinable in downstream crates. diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index d2847e4bc12a..321cdf873c1f 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -77,7 +77,7 @@ macro_rules! arena_types { rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Ty<'tcx>> >, [] all_traits: Vec, - [] privacy_access_levels: rustc_middle::middle::privacy::AccessLevels, + [] effective_visibilities: rustc_middle::middle::privacy::EffectiveVisibilities, [] foreign_module: rustc_session::cstore::ForeignModule, [] foreign_modules: Vec, [] upvars_mentioned: rustc_data_structures::fx::FxIndexMap, diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index 5687e5bdc434..9c68c7504754 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -9,106 +9,101 @@ use rustc_query_system::ich::StableHashingContext; use rustc_span::def_id::{DefId, LocalDefId}; use std::hash::Hash; -/// Represents the levels of accessibility an item can have. +/// Represents the levels of effective visibility an item can have. /// -/// The variants are sorted in ascending order of accessibility. +/// The variants are sorted in ascending order of directness. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, HashStable)] -pub enum AccessLevel { - /// Superset of `AccessLevel::Reachable` used to mark impl Trait items. - ReachableFromImplTrait, - /// Exported items + items participating in various kinds of public interfaces, - /// but not directly nameable. For example, if function `fn f() -> T {...}` is - /// public, then type `T` is reachable. Its values can be obtained by other crates - /// even if the type itself is not nameable. +pub enum Level { + /// Superset of `Reachable` including items leaked through return position `impl Trait`. + ReachableThroughImplTrait, + /// Item is either reexported, or leaked through any kind of interface. + /// For example, if function `fn f() -> T {...}` is directly public, then type `T` is publicly + /// reachable and its values can be obtained by other crates even if the type itself is not + /// nameable. Reachable, - /// Public items + items accessible to other crates with the help of `pub use` re-exports. - Exported, - /// Items accessible to other crates directly, without the help of re-exports. - Public, + /// Item is accessible either directly, or with help of `use` reexports. + Reexported, + /// Item is directly accessible, without help of reexports. + Direct, } -impl AccessLevel { - pub fn all_levels() -> [AccessLevel; 4] { - [ - AccessLevel::Public, - AccessLevel::Exported, - AccessLevel::Reachable, - AccessLevel::ReachableFromImplTrait, - ] +impl Level { + pub fn all_levels() -> [Level; 4] { + [Level::Direct, Level::Reexported, Level::Reachable, Level::ReachableThroughImplTrait] } } #[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)] pub struct EffectiveVisibility { - public: Visibility, - exported: Visibility, + direct: Visibility, + reexported: Visibility, reachable: Visibility, - reachable_from_impl_trait: Visibility, + reachable_through_impl_trait: Visibility, } impl EffectiveVisibility { - pub fn get(&self, tag: AccessLevel) -> &Visibility { - match tag { - AccessLevel::Public => &self.public, - AccessLevel::Exported => &self.exported, - AccessLevel::Reachable => &self.reachable, - AccessLevel::ReachableFromImplTrait => &self.reachable_from_impl_trait, + pub fn at_level(&self, level: Level) -> &Visibility { + match level { + Level::Direct => &self.direct, + Level::Reexported => &self.reexported, + Level::Reachable => &self.reachable, + Level::ReachableThroughImplTrait => &self.reachable_through_impl_trait, } } - fn get_mut(&mut self, tag: AccessLevel) -> &mut Visibility { - match tag { - AccessLevel::Public => &mut self.public, - AccessLevel::Exported => &mut self.exported, - AccessLevel::Reachable => &mut self.reachable, - AccessLevel::ReachableFromImplTrait => &mut self.reachable_from_impl_trait, + fn at_level_mut(&mut self, level: Level) -> &mut Visibility { + match level { + Level::Direct => &mut self.direct, + Level::Reexported => &mut self.reexported, + Level::Reachable => &mut self.reachable, + Level::ReachableThroughImplTrait => &mut self.reachable_through_impl_trait, } } - pub fn is_public_at_level(&self, tag: AccessLevel) -> bool { - self.get(tag).is_public() + pub fn is_public_at_level(&self, level: Level) -> bool { + self.at_level(level).is_public() } pub fn from_vis(vis: Visibility) -> EffectiveVisibility { EffectiveVisibility { - public: vis, - exported: vis, + direct: vis, + reexported: vis, reachable: vis, - reachable_from_impl_trait: vis, + reachable_through_impl_trait: vis, } } } -/// Holds a map of accessibility levels for reachable HIR nodes. +/// Holds a map of effective visibilities for reachable HIR nodes. #[derive(Debug, Clone)] -pub struct AccessLevels { +pub struct EffectiveVisibilities { map: FxHashMap, } -impl AccessLevels { - pub fn is_public_at_level(&self, id: Id, tag: AccessLevel) -> bool { - self.get_effective_vis(id) - .map_or(false, |effective_vis| effective_vis.is_public_at_level(tag)) +impl EffectiveVisibilities { + pub fn is_public_at_level(&self, id: Id, level: Level) -> bool { + self.effective_vis(id) + .map_or(false, |effective_vis| effective_vis.is_public_at_level(level)) } - /// See `AccessLevel::Reachable`. + /// See `Level::Reachable`. pub fn is_reachable(&self, id: Id) -> bool { - self.is_public_at_level(id, AccessLevel::Reachable) + self.is_public_at_level(id, Level::Reachable) } - /// See `AccessLevel::Exported`. + /// See `Level::Reexported`. pub fn is_exported(&self, id: Id) -> bool { - self.is_public_at_level(id, AccessLevel::Exported) + self.is_public_at_level(id, Level::Reexported) } - /// See `AccessLevel::Public`. - pub fn is_public(&self, id: Id) -> bool { - self.is_public_at_level(id, AccessLevel::Public) + /// See `Level::Direct`. + pub fn is_directly_public(&self, id: Id) -> bool { + self.is_public_at_level(id, Level::Direct) } - pub fn get_access_level(&self, id: Id) -> Option { - self.get_effective_vis(id).and_then(|effective_vis| { - for level in AccessLevel::all_levels() { + pub fn public_at_level(&self, id: Id) -> Option { + self.effective_vis(id).and_then(|effective_vis| { + for level in Level::all_levels() { if effective_vis.is_public_at_level(level) { return Some(level); } @@ -117,7 +112,7 @@ impl AccessLevels { }) } - pub fn get_effective_vis(&self, id: Id) -> Option<&EffectiveVisibility> { + pub fn effective_vis(&self, id: Id) -> Option<&EffectiveVisibility> { self.map.get(&id) } @@ -125,30 +120,33 @@ impl AccessLevels { self.map.iter() } - pub fn map_id(&self, f: impl Fn(Id) -> OutId) -> AccessLevels { - AccessLevels { map: self.map.iter().map(|(k, v)| (f(*k), *v)).collect() } + pub fn map_id( + &self, + f: impl Fn(Id) -> OutId, + ) -> EffectiveVisibilities { + EffectiveVisibilities { map: self.map.iter().map(|(k, v)| (f(*k), *v)).collect() } } - pub fn set_access_level( + pub fn set_public_at_level( &mut self, id: Id, default_vis: impl FnOnce() -> Visibility, - tag: AccessLevel, + level: Level, ) { let mut effective_vis = self - .get_effective_vis(id) + .effective_vis(id) .copied() .unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis())); - for level in AccessLevel::all_levels() { - if level <= tag { - *effective_vis.get_mut(level) = Visibility::Public; + for l in Level::all_levels() { + if l <= level { + *effective_vis.at_level_mut(l) = Visibility::Public; } } self.map.insert(id, effective_vis); } } -impl> AccessLevels { +impl> EffectiveVisibilities { // `parent_id` is not necessarily a parent in source code tree, // it is the node from which the maximum effective visibility is inherited. pub fn update( @@ -157,28 +155,29 @@ impl> AccessLevels { nominal_vis: Visibility, default_vis: impl FnOnce() -> Visibility, parent_id: Id, - tag: AccessLevel, + level: Level, tree: impl DefIdTree, ) -> bool { let mut changed = false; - let mut current_effective_vis = self.get_effective_vis(id).copied().unwrap_or_else(|| { + let mut current_effective_vis = self.effective_vis(id).copied().unwrap_or_else(|| { if id.into().is_crate_root() { EffectiveVisibility::from_vis(Visibility::Public) } else { EffectiveVisibility::from_vis(default_vis()) } }); - if let Some(inherited_effective_vis) = self.get_effective_vis(parent_id) { - let mut inherited_effective_vis_at_prev_level = *inherited_effective_vis.get(tag); + if let Some(inherited_effective_vis) = self.effective_vis(parent_id) { + let mut inherited_effective_vis_at_prev_level = + *inherited_effective_vis.at_level(level); let mut calculated_effective_vis = inherited_effective_vis_at_prev_level; - for level in AccessLevel::all_levels() { - if tag >= level { - let inherited_effective_vis_at_level = *inherited_effective_vis.get(level); - let current_effective_vis_at_level = current_effective_vis.get_mut(level); + for l in Level::all_levels() { + if level >= l { + let inherited_effective_vis_at_level = *inherited_effective_vis.at_level(l); + let current_effective_vis_at_level = current_effective_vis.at_level_mut(l); // effective visibility for id shouldn't be recalculated if // inherited from parent_id effective visibility isn't changed at next level if !(inherited_effective_vis_at_prev_level == inherited_effective_vis_at_level - && tag != level) + && level != l) { calculated_effective_vis = if nominal_vis.is_at_least(inherited_effective_vis_at_level, tree) { @@ -205,15 +204,15 @@ impl> AccessLevels { } } -impl Default for AccessLevels { +impl Default for EffectiveVisibilities { fn default() -> Self { - AccessLevels { map: Default::default() } + EffectiveVisibilities { map: Default::default() } } } -impl<'a> HashStable> for AccessLevels { +impl<'a> HashStable> for EffectiveVisibilities { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let AccessLevels { ref map } = *self; + let EffectiveVisibilities { ref map } = *self; map.hash_stable(hcx, hasher); } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 67c85ef0d3b5..de2538f94d05 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1065,10 +1065,10 @@ rustc_queries! { cache_on_disk_if { key.is_local() } } - /// Performs part of the privacy check and computes "access levels". - query privacy_access_levels(_: ()) -> &'tcx AccessLevels { + /// Performs part of the privacy check and computes effective visibilities. + query effective_visibilities(_: ()) -> &'tcx EffectiveVisibilities { eval_always - desc { "checking privacy access levels" } + desc { "checking effective visibilities" } } query check_private_in_public(_: ()) -> () { eval_always diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9671d3a32f94..51da92acd89c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -17,7 +17,7 @@ pub use self::IntVarValue::*; pub use self::Variance::*; use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason}; use crate::metadata::ModChild; -use crate::middle::privacy::AccessLevels; +use crate::middle::privacy::EffectiveVisibilities; use crate::mir::{Body, GeneratorLayout}; use crate::traits::{self, Reveal}; use crate::ty; @@ -160,7 +160,7 @@ pub struct ResolverGlobalCtxt { pub expn_that_defined: FxHashMap, /// Reference span for definitions. pub source_span: IndexVec, - pub access_levels: AccessLevels, + pub effective_visibilities: EffectiveVisibilities, pub extern_crate_map: FxHashMap, pub maybe_unused_trait_imports: FxIndexSet, pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>, diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 9c97ce34f29e..3e2b4edf716c 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -5,7 +5,7 @@ use crate::metadata::ModChild; use crate::middle::codegen_fn_attrs::CodegenFnAttrs; use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use crate::middle::lib_features::LibFeatures; -use crate::middle::privacy::AccessLevels; +use crate::middle::privacy::EffectiveVisibilities; use crate::middle::resolve_lifetime::{ObjectLifetimeDefault, Region, ResolveLifetimes}; use crate::middle::stability::{self, DeprecationEntry}; use crate::mir; diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 6a97ad3fe86e..2fb46f47da27 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -11,7 +11,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Node, PatKind, TyKind}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::middle::privacy::AccessLevel; +use rustc_middle::middle::privacy::Level; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, DefIdTree, TyCtxt}; use rustc_session::lint; @@ -604,13 +604,13 @@ fn check_foreign_item<'tcx>( fn create_and_seed_worklist<'tcx>( tcx: TyCtxt<'tcx>, ) -> (Vec, FxHashMap) { - let access_levels = &tcx.privacy_access_levels(()); + let effective_visibilities = &tcx.effective_visibilities(()); // see `MarkSymbolVisitor::struct_constructors` let mut struct_constructors = Default::default(); - let mut worklist = access_levels + let mut worklist = effective_visibilities .iter() .filter_map(|(&id, effective_vis)| { - effective_vis.is_public_at_level(AccessLevel::Reachable).then_some(id) + effective_vis.is_public_at_level(Level::Reachable).then_some(id) }) // Seed entry point .chain(tcx.entry_fn(()).and_then(|(def_id, _)| def_id.as_local())) diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 0f2879c1eff2..273cab7922e3 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -12,7 +12,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::Node; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; -use rustc_middle::middle::privacy::{self, AccessLevel}; +use rustc_middle::middle::privacy::{self, Level}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, DefIdTree, TyCtxt}; use rustc_session::config::CrateType; @@ -303,7 +303,7 @@ fn check_item<'tcx>( tcx: TyCtxt<'tcx>, id: hir::ItemId, worklist: &mut Vec, - access_levels: &privacy::AccessLevels, + effective_visibilities: &privacy::EffectiveVisibilities, ) { if has_custom_linkage(tcx, id.def_id.def_id) { worklist.push(id.def_id.def_id); @@ -318,7 +318,7 @@ fn check_item<'tcx>( if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref trait_ref), ref items, .. }) = item.kind { - if !access_levels.is_reachable(item.def_id.def_id) { + if !effective_visibilities.is_reachable(item.def_id.def_id) { worklist.extend(items.iter().map(|ii_ref| ii_ref.id.def_id.def_id)); let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res else { @@ -354,7 +354,7 @@ fn has_custom_linkage<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { } fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet { - let access_levels = &tcx.privacy_access_levels(()); + let effective_visibilities = &tcx.effective_visibilities(()); let any_library = tcx.sess.crate_types().iter().any(|ty| { @@ -373,10 +373,10 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet { // If other crates link to us, they're going to expect to be able to // use the lang items, so we need to be sure to mark them as // exported. - reachable_context.worklist = access_levels + reachable_context.worklist = effective_visibilities .iter() .filter_map(|(&id, effective_vis)| { - effective_vis.is_public_at_level(AccessLevel::ReachableFromImplTrait).then_some(id) + effective_vis.is_public_at_level(Level::ReachableThroughImplTrait).then_some(id) }) .collect::>(); @@ -399,7 +399,7 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet { let crate_items = tcx.hir_crate_items(()); for id in crate_items.items() { - check_item(tcx, id, &mut reachable_context.worklist, access_levels); + check_item(tcx, id, &mut reachable_context.worklist, effective_visibilities); } for id in crate_items.impl_items() { diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 9591aeb881f3..d7655655d78c 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -20,7 +20,7 @@ use rustc_hir::hir_id::CRATE_HIR_ID; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant}; use rustc_middle::hir::nested_filter; -use rustc_middle::middle::privacy::AccessLevels; +use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::middle::stability::{AllowUnstable, DeprecationEntry, Index}; use rustc_middle::ty::{query::Providers, TyCtxt}; use rustc_session::lint; @@ -516,13 +516,16 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { struct MissingStabilityAnnotations<'tcx> { tcx: TyCtxt<'tcx>, - access_levels: &'tcx AccessLevels, + effective_visibilities: &'tcx EffectiveVisibilities, } impl<'tcx> MissingStabilityAnnotations<'tcx> { fn check_missing_stability(&self, def_id: LocalDefId, span: Span) { let stab = self.tcx.stability().local_stability(def_id); - if !self.tcx.sess.opts.test && stab.is_none() && self.access_levels.is_reachable(def_id) { + if !self.tcx.sess.opts.test + && stab.is_none() + && self.effective_visibilities.is_reachable(def_id) + { let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id()); self.tcx.sess.emit_err(MissingStabilityAttr { span, descr }); } @@ -540,7 +543,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { .lookup_stability(def_id) .map_or(false, |stability| stability.level.is_stable()); let missing_const_stability_attribute = self.tcx.lookup_const_stability(def_id).is_none(); - let is_reachable = self.access_levels.is_reachable(def_id); + let is_reachable = self.effective_visibilities.is_reachable(def_id); if is_const && is_stable && missing_const_stability_attribute && is_reachable { let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id()); @@ -919,8 +922,8 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { let is_staged_api = tcx.sess.opts.unstable_opts.force_unstable_if_unmarked || tcx.features().staged_api; if is_staged_api { - let access_levels = &tcx.privacy_access_levels(()); - let mut missing = MissingStabilityAnnotations { tcx, access_levels }; + let effective_visibilities = &tcx.effective_visibilities(()); + let mut missing = MissingStabilityAnnotations { tcx, effective_visibilities }; missing.check_missing_stability(CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID)); tcx.hir().walk_toplevel_module(&mut missing); tcx.hir().visit_all_item_likes_in_crate(&mut missing); diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 4db58d92bd5e..df8454ed4ee0 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -23,7 +23,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{AssocItemKind, HirIdSet, ItemId, Node, PatKind}; use rustc_middle::bug; use rustc_middle::hir::nested_filter; -use rustc_middle::middle::privacy::{AccessLevel, AccessLevels}; +use rustc_middle::middle::privacy::{EffectiveVisibilities, Level}; use rustc_middle::span_bug; use rustc_middle::ty::abstract_const::{walk_abstract_const, AbstractConst, Node as ACNode}; use rustc_middle::ty::query::Providers; @@ -310,7 +310,7 @@ fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visib struct FindMin<'a, 'tcx, VL: VisibilityLike> { tcx: TyCtxt<'tcx>, - access_levels: &'a AccessLevels, + effective_visibilities: &'a EffectiveVisibilities, min: VL, } @@ -344,8 +344,12 @@ trait VisibilityLike: Sized { // Returns an over-approximation (`skip_assoc_tys` = true) of visibility due to // associated types for which we can't determine visibility precisely. - fn of_impl(def_id: LocalDefId, tcx: TyCtxt<'_>, access_levels: &AccessLevels) -> Self { - let mut find = FindMin { tcx, access_levels, min: Self::MAX }; + fn of_impl( + def_id: LocalDefId, + tcx: TyCtxt<'_>, + effective_visibilities: &EffectiveVisibilities, + ) -> Self { + let mut find = FindMin { tcx, effective_visibilities, min: Self::MAX }; find.visit(tcx.type_of(def_id)); if let Some(trait_ref) = tcx.impl_trait_ref(def_id) { find.visit_trait(trait_ref); @@ -359,8 +363,8 @@ impl VisibilityLike for ty::Visibility { min(find.tcx.local_visibility(def_id), find.min, find.tcx) } } -impl VisibilityLike for Option { - const MAX: Self = Some(AccessLevel::Public); +impl VisibilityLike for Option { + const MAX: Self = Some(Level::Direct); // Type inference is very smart sometimes. // It can make an impl reachable even some components of its type or trait are unreachable. // E.g. methods of `impl ReachableTrait for ReachableTy { ... }` @@ -372,7 +376,7 @@ impl VisibilityLike for Option { // (which require reaching the `DefId`s in them). const SHALLOW: bool = true; fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self { - cmp::min(find.access_levels.get_access_level(def_id), find.min) + cmp::min(find.effective_visibilities.public_at_level(def_id), find.min) } } @@ -383,8 +387,8 @@ impl VisibilityLike for Option { struct EmbargoVisitor<'tcx> { tcx: TyCtxt<'tcx>, - /// Accessibility levels for reachable nodes. - access_levels: AccessLevels, + /// Effective visibilities for reachable nodes. + effective_visibilities: EffectiveVisibilities, /// A set of pairs corresponding to modules, where the first module is /// reachable via a macro that's defined in the second module. This cannot /// be represented as reachable because it can't handle the following case: @@ -398,38 +402,34 @@ struct EmbargoVisitor<'tcx> { /// n::p::f() /// } macro_reachable: FxHashSet<(LocalDefId, LocalDefId)>, - /// Previous accessibility level; `None` means unreachable. - prev_level: Option, + /// Previous visibility level; `None` means unreachable. + prev_level: Option, /// Has something changed in the level map? changed: bool, } struct ReachEverythingInTheInterfaceVisitor<'a, 'tcx> { - access_level: Option, + level: Option, item_def_id: LocalDefId, ev: &'a mut EmbargoVisitor<'tcx>, } impl<'tcx> EmbargoVisitor<'tcx> { - fn get(&self, def_id: LocalDefId) -> Option { - self.access_levels.get_access_level(def_id) + fn get(&self, def_id: LocalDefId) -> Option { + self.effective_visibilities.public_at_level(def_id) } - fn update_with_hir_id( - &mut self, - hir_id: hir::HirId, - level: Option, - ) -> Option { + fn update_with_hir_id(&mut self, hir_id: hir::HirId, level: Option) -> Option { let def_id = self.tcx.hir().local_def_id(hir_id); self.update(def_id, level) } /// Updates node level and returns the updated level. - fn update(&mut self, def_id: LocalDefId, level: Option) -> Option { + fn update(&mut self, def_id: LocalDefId, level: Option) -> Option { let old_level = self.get(def_id); - // Accessibility levels can only grow. + // Visibility levels can only grow. if level > old_level { - self.access_levels.set_access_level( + self.effective_visibilities.set_public_at_level( def_id, || ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id)), level.unwrap(), @@ -444,10 +444,10 @@ impl<'tcx> EmbargoVisitor<'tcx> { fn reach( &mut self, def_id: LocalDefId, - access_level: Option, + level: Option, ) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> { ReachEverythingInTheInterfaceVisitor { - access_level: cmp::min(access_level, Some(AccessLevel::Reachable)), + level: cmp::min(level, Some(Level::Reachable)), item_def_id: def_id, ev: self, } @@ -530,7 +530,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { vis: ty::Visibility, module: LocalDefId, ) { - let level = Some(AccessLevel::Reachable); + let level = Some(Level::Reachable); if vis.is_public() { self.update(def_id, level); } @@ -627,10 +627,10 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { let item_level = match item.kind { hir::ItemKind::Impl { .. } => { - let impl_level = Option::::of_impl( + let impl_level = Option::::of_impl( item.def_id.def_id, self.tcx, - &self.access_levels, + &self.effective_visibilities, ); self.update(item.def_id.def_id, impl_level) } @@ -705,7 +705,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { hir::ItemKind::Macro(..) | hir::ItemKind::ExternCrate(..) => {} // All nested items are checked by `visit_item`. hir::ItemKind::Mod(..) => {} - // Handled in the access level of in rustc_resolve + // Handled in `rustc_resolve`. hir::ItemKind::Use(..) => {} // The interface is empty. hir::ItemKind::GlobalAsm(..) => {} @@ -718,8 +718,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { // FIXME: This is some serious pessimization intended to workaround deficiencies // in the reachability pass (`middle/reachable.rs`). Types are marked as link-time // reachable if they are returned via `impl Trait`, even from private functions. - let exist_level = - cmp::max(item_level, Some(AccessLevel::ReachableFromImplTrait)); + let exist_level = cmp::max(item_level, Some(Level::ReachableThroughImplTrait)); self.reach(item.def_id.def_id, exist_level).generics().predicates().ty(); } } @@ -901,10 +900,10 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> _descr: &dyn fmt::Display, ) -> ControlFlow { if let Some(def_id) = def_id.as_local() { - if let (ty::Visibility::Public, _) | (_, Some(AccessLevel::ReachableFromImplTrait)) = - (self.tcx().visibility(def_id.to_def_id()), self.access_level) + if let (ty::Visibility::Public, _) | (_, Some(Level::ReachableThroughImplTrait)) = + (self.tcx().visibility(def_id.to_def_id()), self.level) { - self.ev.update(def_id, self.access_level); + self.ev.update(def_id, self.level); } } ControlFlow::CONTINUE @@ -912,21 +911,21 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> } //////////////////////////////////////////////////////////////////////////////// -/// Visitor, used for AccessLevels table checking +/// Visitor, used for EffectiveVisibilities table checking //////////////////////////////////////////////////////////////////////////////// pub struct TestReachabilityVisitor<'tcx, 'a> { tcx: TyCtxt<'tcx>, - access_levels: &'a AccessLevels, + effective_visibilities: &'a EffectiveVisibilities, } impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> { - fn access_level_diagnostic(&mut self, def_id: LocalDefId) { + fn effective_visibility_diagnostic(&mut self, def_id: LocalDefId) { if self.tcx.has_attr(def_id.to_def_id(), sym::rustc_effective_visibility) { let mut error_msg = String::new(); let span = self.tcx.def_span(def_id.to_def_id()); - if let Some(effective_vis) = self.access_levels.get_effective_vis(def_id) { - for level in AccessLevel::all_levels() { - let vis_str = match effective_vis.get(level) { + if let Some(effective_vis) = self.effective_visibilities.effective_vis(def_id) { + for level in Level::all_levels() { + let vis_str = match effective_vis.at_level(level) { ty::Visibility::Restricted(restricted_id) => { if restricted_id.is_top_level_module() { "pub(crate)".to_string() @@ -938,7 +937,7 @@ impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> { } ty::Visibility::Public => "pub".to_string(), }; - if level != AccessLevel::Public { + if level != Level::Direct { error_msg.push_str(", "); } error_msg.push_str(&format!("{:?}: {}", level, vis_str)); @@ -953,23 +952,23 @@ impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> { impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - self.access_level_diagnostic(item.def_id.def_id); + self.effective_visibility_diagnostic(item.def_id.def_id); match item.kind { hir::ItemKind::Enum(ref def, _) => { for variant in def.variants.iter() { let variant_id = self.tcx.hir().local_def_id(variant.id); - self.access_level_diagnostic(variant_id); + self.effective_visibility_diagnostic(variant_id); for field in variant.data.fields() { let def_id = self.tcx.hir().local_def_id(field.hir_id); - self.access_level_diagnostic(def_id); + self.effective_visibility_diagnostic(def_id); } } } hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => { for field in def.fields() { let def_id = self.tcx.hir().local_def_id(field.hir_id); - self.access_level_diagnostic(def_id); + self.effective_visibility_diagnostic(def_id); } } _ => {} @@ -977,13 +976,13 @@ impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> { } fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem<'tcx>) { - self.access_level_diagnostic(item.def_id.def_id); + self.effective_visibility_diagnostic(item.def_id.def_id); } fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem<'tcx>) { - self.access_level_diagnostic(item.def_id.def_id); + self.effective_visibility_diagnostic(item.def_id.def_id); } fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { - self.access_level_diagnostic(item.def_id.def_id); + self.effective_visibility_diagnostic(item.def_id.def_id); } } @@ -1054,7 +1053,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) { // Don't visit nested modules, since we run a separate visitor walk - // for each module in `privacy_access_levels` + // for each module in `effective_visibilities` } fn visit_nested_body(&mut self, body: hir::BodyId) { @@ -1179,7 +1178,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) { // Don't visit nested modules, since we run a separate visitor walk - // for each module in `privacy_access_levels` + // for each module in `effective_visibilities` } fn visit_nested_body(&mut self, body: hir::BodyId) { @@ -1404,7 +1403,7 @@ impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> { struct ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, - access_levels: &'a AccessLevels, + effective_visibilities: &'a EffectiveVisibilities, in_variant: bool, // Set of errors produced by this obsolete visitor. old_error_set: HirIdSet, @@ -1447,7 +1446,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { fn trait_is_public(&self, trait_id: LocalDefId) -> bool { // FIXME: this would preferably be using `exported_items`, but all // traits are exported currently (see `EmbargoVisitor.exported_trait`). - self.access_levels.is_public(trait_id) + self.effective_visibilities.is_directly_public(trait_id) } fn check_generic_bound(&mut self, bound: &hir::GenericBound<'_>) { @@ -1459,7 +1458,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } fn item_is_public(&self, def_id: LocalDefId) -> bool { - self.access_levels.is_reachable(def_id) || self.tcx.visibility(def_id).is_public() + self.effective_visibilities.is_reachable(def_id) || self.tcx.visibility(def_id).is_public() } } @@ -1573,9 +1572,9 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { || impl_.items.iter().any(|impl_item_ref| { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item.kind { - hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) => { - self.access_levels.is_reachable(impl_item_ref.id.def_id.def_id) - } + hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) => self + .effective_visibilities + .is_reachable(impl_item_ref.id.def_id.def_id), hir::ImplItemKind::Type(_) => false, } }); @@ -1635,7 +1634,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // methods will be visible as `Public::foo`. let mut found_pub_static = false; for impl_item_ref in impl_.items { - if self.access_levels.is_reachable(impl_item_ref.id.def_id.def_id) + if self.effective_visibilities.is_reachable(impl_item_ref.id.def_id.def_id) || self.tcx.visibility(impl_item_ref.id.def_id).is_public() { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); @@ -1695,7 +1694,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { - if self.access_levels.is_reachable(item.def_id.def_id) { + if self.effective_visibilities.is_reachable(item.def_id.def_id) { intravisit::walk_foreign_item(self, item) } } @@ -1710,7 +1709,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } fn visit_variant(&mut self, v: &'tcx hir::Variant<'tcx>) { - if self.access_levels.is_reachable(self.tcx.hir().local_def_id(v.id)) { + if self.effective_visibilities.is_reachable(self.tcx.hir().local_def_id(v.id)) { self.in_variant = true; intravisit::walk_variant(self, v); self.in_variant = false; @@ -2040,7 +2039,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { pub fn provide(providers: &mut Providers) { *providers = Providers { visibility, - privacy_access_levels, + effective_visibilities, check_private_in_public, check_mod_privacy, ..*providers @@ -2112,14 +2111,14 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { intravisit::walk_mod(&mut visitor, module, hir_id); } -fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels { +fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities { // Build up a set of all exported items in the AST. This is a set of all // items which are reachable from external crates based on visibility. let mut visitor = EmbargoVisitor { tcx, - access_levels: tcx.resolutions(()).access_levels.clone(), + effective_visibilities: tcx.resolutions(()).effective_visibilities.clone(), macro_reachable: Default::default(), - prev_level: Some(AccessLevel::Public), + prev_level: Some(Level::Direct), changed: false, }; @@ -2132,18 +2131,19 @@ fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels { } } - let mut check_visitor = TestReachabilityVisitor { tcx, access_levels: &visitor.access_levels }; + let mut check_visitor = + TestReachabilityVisitor { tcx, effective_visibilities: &visitor.effective_visibilities }; tcx.hir().visit_all_item_likes_in_crate(&mut check_visitor); - tcx.arena.alloc(visitor.access_levels) + tcx.arena.alloc(visitor.effective_visibilities) } fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) { - let access_levels = tcx.privacy_access_levels(()); + let effective_visibilities = tcx.effective_visibilities(()); let mut visitor = ObsoleteVisiblePrivateTypesVisitor { tcx, - access_levels, + effective_visibilities, in_variant: false, old_error_set: Default::default(), }; diff --git a/compiler/rustc_resolve/src/access_levels.rs b/compiler/rustc_resolve/src/effective_visibilities.rs similarity index 76% rename from compiler/rustc_resolve/src/access_levels.rs rename to compiler/rustc_resolve/src/effective_visibilities.rs index c27b5b0c4200..c40669ac95be 100644 --- a/compiler/rustc_resolve/src/access_levels.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -6,55 +6,54 @@ use rustc_ast::Crate; use rustc_ast::EnumDef; use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::CRATE_DEF_ID; -use rustc_middle::middle::privacy::AccessLevel; +use rustc_middle::middle::privacy::Level; use rustc_middle::ty::{DefIdTree, Visibility}; -pub struct AccessLevelsVisitor<'r, 'a> { +pub struct EffectiveVisibilitiesVisitor<'r, 'a> { r: &'r mut Resolver<'a>, changed: bool, } -impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { - /// Fills the `Resolver::access_levels` table with public & exported items +impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> { + /// Fills the `Resolver::effective_visibilities` table with public & exported items /// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we /// need access to a TyCtxt for that. - pub fn compute_access_levels<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) { - let mut visitor = AccessLevelsVisitor { r, changed: false }; + pub fn compute_effective_visibilities<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) { + let mut visitor = EffectiveVisibilitiesVisitor { r, changed: false }; - visitor.update(CRATE_DEF_ID, Visibility::Public, CRATE_DEF_ID, AccessLevel::Public); - visitor.set_bindings_access_level(CRATE_DEF_ID); + visitor.update(CRATE_DEF_ID, Visibility::Public, CRATE_DEF_ID, Level::Direct); + visitor.set_bindings_effective_visibilities(CRATE_DEF_ID); while visitor.changed { visitor.reset(); visit::walk_crate(&mut visitor, krate); } - info!("resolve::access_levels: {:#?}", r.access_levels); + info!("resolve::effective_visibilities: {:#?}", r.effective_visibilities); } fn reset(&mut self) { self.changed = false; } - /// Update the access level of the bindings in the given module accordingly. The module access - /// level has to be Exported or Public. - /// This will also follow `use` chains (see PrivacyVisitor::set_import_binding_access_level). - fn set_bindings_access_level(&mut self, module_id: LocalDefId) { + /// Update effective visibilities of bindings in the given module, + /// including their whole reexport chains. + fn set_bindings_effective_visibilities(&mut self, module_id: LocalDefId) { assert!(self.r.module_map.contains_key(&&module_id.to_def_id())); let module = self.r.get_module(module_id.to_def_id()).unwrap(); let resolutions = self.r.resolutions(module); for (_, name_resolution) in resolutions.borrow().iter() { if let Some(mut binding) = name_resolution.borrow().binding() && !binding.is_ambiguity() { - // Set the given binding access level to `AccessLevel::Public` and - // sets the rest of the `use` chain to `AccessLevel::Exported` until + // Set the given effective visibility level to `Level::Direct` and + // sets the rest of the `use` chain to `Level::Reexported` until // we hit the actual exported item. // FIXME: tag and is_public() condition should be removed, but assertions occur. - let tag = if binding.is_import() { AccessLevel::Exported } else { AccessLevel::Public }; + let tag = if binding.is_import() { Level::Reexported } else { Level::Direct }; if binding.vis.is_public() { let mut prev_parent_id = module_id; - let mut level = AccessLevel::Public; + let mut level = Level::Direct; while let NameBindingKind::Import { binding: nested_binding, import, .. } = binding.kind { @@ -76,7 +75,7 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { update(additional_ids.1); } - level = AccessLevel::Exported; + level = Level::Reexported; prev_parent_id = self.r.local_def_id(import.id); binding = nested_binding; } @@ -94,7 +93,7 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { def_id: LocalDefId, nominal_vis: Visibility, parent_id: LocalDefId, - tag: AccessLevel, + tag: Level, ) { let module_id = self .r @@ -106,8 +105,8 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { { return; } - let mut access_levels = std::mem::take(&mut self.r.access_levels); - self.changed |= access_levels.update( + let mut effective_visibilities = std::mem::take(&mut self.r.effective_visibilities); + self.changed |= effective_visibilities.update( def_id, nominal_vis, || Visibility::Restricted(module_id), @@ -115,14 +114,14 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { tag, &*self.r, ); - self.r.access_levels = access_levels; + self.r.effective_visibilities = effective_visibilities; } } -impl<'r, 'ast> Visitor<'ast> for AccessLevelsVisitor<'ast, 'r> { +impl<'r, 'ast> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r> { fn visit_item(&mut self, item: &'ast ast::Item) { let def_id = self.r.local_def_id(item.id); - // Set access level of nested items. + // Update effective visibilities of nested items. // If it's a mod, also make the visitor walk all of its items match item.kind { // Resolved in rustc_privacy when types are available @@ -136,29 +135,29 @@ impl<'r, 'ast> Visitor<'ast> for AccessLevelsVisitor<'ast, 'r> { // Foreign modules inherit level from parents. ast::ItemKind::ForeignMod(..) => { let parent_id = self.r.local_parent(def_id); - self.update(def_id, Visibility::Public, parent_id, AccessLevel::Public); + self.update(def_id, Visibility::Public, parent_id, Level::Direct); } // Only exported `macro_rules!` items are public, but they always are ast::ItemKind::MacroDef(ref macro_def) if macro_def.macro_rules => { let parent_id = self.r.local_parent(def_id); let vis = self.r.visibilities[&def_id]; - self.update(def_id, vis, parent_id, AccessLevel::Public); + self.update(def_id, vis, parent_id, Level::Direct); } ast::ItemKind::Mod(..) => { - self.set_bindings_access_level(def_id); + self.set_bindings_effective_visibilities(def_id); visit::walk_item(self, item); } ast::ItemKind::Enum(EnumDef { ref variants }, _) => { - self.set_bindings_access_level(def_id); + self.set_bindings_effective_visibilities(def_id); for variant in variants { let variant_def_id = self.r.local_def_id(variant.id); for field in variant.data.fields() { let field_def_id = self.r.local_def_id(field.id); let vis = self.r.visibilities[&field_def_id]; - self.update(field_def_id, vis, variant_def_id, AccessLevel::Public); + self.update(field_def_id, vis, variant_def_id, Level::Direct); } } } @@ -167,12 +166,12 @@ impl<'r, 'ast> Visitor<'ast> for AccessLevelsVisitor<'ast, 'r> { for field in def.fields() { let field_def_id = self.r.local_def_id(field.id); let vis = self.r.visibilities[&field_def_id]; - self.update(field_def_id, vis, def_id, AccessLevel::Public); + self.update(field_def_id, vis, def_id, Level::Direct); } } ast::ItemKind::Trait(..) => { - self.set_bindings_access_level(def_id); + self.set_bindings_effective_visibilities(def_id); } ast::ItemKind::ExternCrate(..) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index c2213e8d1e2e..11b70a38da58 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -7,6 +7,7 @@ //! Type-relative name resolution (methods, fields, associated items) happens in `rustc_hir_analysis`. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(drain_filter)] #![feature(if_let_guard)] @@ -40,7 +41,7 @@ use rustc_hir::TraitCandidate; use rustc_index::vec::IndexVec; use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_middle::metadata::ModChild; -use rustc_middle::middle::privacy::AccessLevels; +use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::span_bug; use rustc_middle::ty::{self, DefIdTree, MainDefinition, RegisteredTools}; use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs}; @@ -63,15 +64,15 @@ use imports::{Import, ImportKind, ImportResolver, NameResolution}; use late::{HasGenericParams, PathSource, PatternSource}; use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef}; -use crate::access_levels::AccessLevelsVisitor; +use crate::effective_visibilities::EffectiveVisibilitiesVisitor; type Res = def::Res; -mod access_levels; mod build_reduced_graph; mod check_unused; mod def_collector; mod diagnostics; +mod effective_visibilities; mod ident; mod imports; mod late; @@ -1030,7 +1031,7 @@ pub struct Resolver<'a> { proc_macros: Vec, confused_type_with_std_module: FxHashMap, - access_levels: AccessLevels, + effective_visibilities: EffectiveVisibilities, } /// Nothing really interesting here; it just provides memory for the rest of the crate. @@ -1334,7 +1335,7 @@ impl<'a> Resolver<'a> { trait_impls: Default::default(), proc_macros: Default::default(), confused_type_with_std_module: Default::default(), - access_levels: Default::default(), + effective_visibilities: Default::default(), }; let root_parent_scope = ParentScope::module(graph_root, &resolver); @@ -1392,14 +1393,14 @@ impl<'a> Resolver<'a> { let glob_map = self.glob_map; let main_def = self.main_def; let confused_type_with_std_module = self.confused_type_with_std_module; - let access_levels = self.access_levels; + let effective_visibilities = self.effective_visibilities; let global_ctxt = ResolverGlobalCtxt { cstore, source_span, expn_that_defined, visibilities, has_pub_restricted, - access_levels, + effective_visibilities, extern_crate_map, reexport_map, glob_map, @@ -1457,7 +1458,7 @@ impl<'a> Resolver<'a> { proc_macros, confused_type_with_std_module: self.confused_type_with_std_module.clone(), registered_tools: self.registered_tools.clone(), - access_levels: self.access_levels.clone(), + effective_visibilities: self.effective_visibilities.clone(), }; let ast_lowering = ty::ResolverAstLowering { legacy_const_generic_args: self.legacy_const_generic_args.clone(), @@ -1520,8 +1521,8 @@ impl<'a> Resolver<'a> { pub fn resolve_crate(&mut self, krate: &Crate) { self.session.time("resolve_crate", || { self.session.time("finalize_imports", || ImportResolver { r: self }.finalize_imports()); - self.session.time("resolve_access_levels", || { - AccessLevelsVisitor::compute_access_levels(self, krate) + self.session.time("compute_effective_visibilities", || { + EffectiveVisibilitiesVisitor::compute_effective_visibilities(self, krate) }); self.session.time("finalize_macro_resolutions", || self.finalize_macro_resolutions()); self.session.time("late_resolve_crate", || self.late_resolve_crate(krate)); diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 23d06d8e5163..d0752e5a20d0 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -57,7 +57,7 @@ macro_rules! access_from { ($save_ctxt:expr, $id:expr) => { Access { public: $save_ctxt.tcx.visibility($id).is_public(), - reachable: $save_ctxt.access_levels.is_reachable($id), + reachable: $save_ctxt.effective_visibilities.is_reachable($id), } }; } diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index aa000b7067bd..d1ed0e078d21 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -26,7 +26,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::Node; use rustc_hir_pretty::{enum_def_to_string, fn_to_string, ty_to_string}; use rustc_middle::hir::nested_filter; -use rustc_middle::middle::privacy::AccessLevels; +use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::ty::{self, print::with_no_trimmed_paths, DefIdTree, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::config::{CrateType, Input, OutputType}; @@ -54,7 +54,7 @@ use rls_data::{ pub struct SaveContext<'tcx> { tcx: TyCtxt<'tcx>, maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>, - access_levels: &'tcx AccessLevels, + effective_visibilities: &'tcx EffectiveVisibilities, span_utils: SpanUtils<'tcx>, config: Config, impl_counter: Cell, @@ -968,16 +968,16 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>( info!("Dumping crate {}", cratename); // Privacy checking must be done outside of type inference; use a - // fallback in case the access levels couldn't have been correctly computed. - let access_levels = match tcx.sess.compile_status() { - Ok(..) => tcx.privacy_access_levels(()), - Err(..) => tcx.arena.alloc(AccessLevels::default()), + // fallback in case effective visibilities couldn't have been correctly computed. + let effective_visibilities = match tcx.sess.compile_status() { + Ok(..) => tcx.effective_visibilities(()), + Err(..) => tcx.arena.alloc(EffectiveVisibilities::default()), }; let save_ctxt = SaveContext { tcx, maybe_typeck_results: None, - access_levels: &access_levels, + effective_visibilities: &effective_visibilities, span_utils: SpanUtils::new(&tcx.sess), config: find_config(config), impl_counter: Cell::new(0), diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 7c59e785752d..8b63c3db3c33 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -20,7 +20,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { trace!("get_blanket_impls({:?})", ty); let mut impls = Vec::new(); for trait_def_id in cx.tcx.all_traits() { - if !cx.cache.access_levels.is_public(trait_def_id) + if !cx.cache.effective_visibilities.is_directly_public(trait_def_id) || cx.generated_synthetics.get(&(ty.0, trait_def_id)).is_some() { continue; diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 432d318907fa..33d717a26b30 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -347,7 +347,7 @@ pub(crate) fn build_impl( if !did.is_local() { if let Some(traitref) = associated_trait { let did = traitref.def_id; - if !cx.cache.access_levels.is_public(did) { + if !cx.cache.effective_visibilities.is_directly_public(did) { return; } @@ -376,7 +376,7 @@ pub(crate) fn build_impl( // reachable in rustdoc generated documentation if !did.is_local() { if let Some(did) = for_.def_id(&cx.cache) { - if !cx.cache.access_levels.is_public(did) { + if !cx.cache.effective_visibilities.is_directly_public(did) { return; } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d86a26826416..93fc5455add8 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1421,7 +1421,7 @@ fn maybe_expand_private_type_alias<'tcx>( let Res::Def(DefKind::TyAlias, def_id) = path.res else { return None }; // Substitute private type aliases let def_id = def_id.as_local()?; - let alias = if !cx.cache.access_levels.is_exported(def_id.to_def_id()) { + let alias = if !cx.cache.effective_visibilities.is_exported(def_id.to_def_id()) { &cx.tcx.hir().expect_item(def_id).kind } else { return None; diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 8232353f915b..6fcf02dfc949 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -348,7 +348,7 @@ pub(crate) fn run_global_ctxt( let auto_traits = tcx.all_traits().filter(|&trait_def_id| tcx.trait_is_auto(trait_def_id)).collect(); - let access_levels = tcx.privacy_access_levels(()).map_id(Into::into); + let effective_visibilities = tcx.effective_visibilities(()).map_id(Into::into); let mut ctxt = DocContext { tcx, @@ -361,7 +361,7 @@ pub(crate) fn run_global_ctxt( impl_trait_bounds: Default::default(), generated_synthetics: Default::default(), auto_traits, - cache: Cache::new(access_levels, render_options.document_private), + cache: Cache::new(effective_visibilities, render_options.document_private), inlined: FxHashSet::default(), output_format, render_options, diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 2e428cfddcf0..afe2264e8bf8 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -2,7 +2,7 @@ use std::mem; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def_id::{CrateNum, DefId}; -use rustc_middle::middle::privacy::AccessLevels; +use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Symbol; @@ -77,8 +77,8 @@ pub(crate) struct Cache { // Note that external items for which `doc(hidden)` applies to are shown as // non-reachable while local items aren't. This is because we're reusing - // the access levels from the privacy check pass. - pub(crate) access_levels: AccessLevels, + // the effective visibilities from the privacy check pass. + pub(crate) effective_visibilities: EffectiveVisibilities, /// The version of the crate being documented, if given from the `--crate-version` flag. pub(crate) crate_version: Option, @@ -132,8 +132,11 @@ struct CacheBuilder<'a, 'tcx> { } impl Cache { - pub(crate) fn new(access_levels: AccessLevels, document_private: bool) -> Self { - Cache { access_levels, document_private, ..Cache::default() } + pub(crate) fn new( + effective_visibilities: EffectiveVisibilities, + document_private: bool, + ) -> Self { + Cache { effective_visibilities, document_private, ..Cache::default() } } /// Populates the `Cache` with more data. The returned `Crate` will be missing some data that was @@ -381,7 +384,10 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // paths map if there was already an entry present and we're // not a public item. if !self.cache.paths.contains_key(&item.item_id.expect_def_id()) - || self.cache.access_levels.is_public(item.item_id.expect_def_id()) + || self + .cache + .effective_visibilities + .is_directly_public(item.item_id.expect_def_id()) { self.cache.paths.insert( item.item_id.expect_def_id(), diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 7d00002d05be..92e7f2739afb 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -659,7 +659,7 @@ pub(crate) fn href_with_root_path( } if !did.is_local() - && !cache.access_levels.is_public(did) + && !cache.effective_visibilities.is_directly_public(did) && !cache.document_private && !cache.primitive_locations.values().any(|&id| id == did) { diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index 15982b40944e..7740c6d5bbbb 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -56,7 +56,7 @@ impl crate::doctest::Tester for Tests { } pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> bool { - if !cx.cache.access_levels.is_public(item.item_id.expect_def_id()) + if !cx.cache.effective_visibilities.is_directly_public(item.item_id.expect_def_id()) || matches!( *item.kind, clean::StructFieldItem(_) @@ -130,7 +130,7 @@ pub(crate) fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item ); } } else if tests.found_tests > 0 - && !cx.cache.access_levels.is_exported(item.item_id.expect_def_id()) + && !cx.cache.effective_visibilities.is_exported(item.item_id.expect_def_id()) { cx.tcx.struct_span_lint_hir( crate::lint::PRIVATE_DOC_TESTS, diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 3513c13d522f..8aa0abd369cd 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1202,8 +1202,8 @@ impl LinkCollector<'_, '_> { item.item_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id)) }) { - if self.cx.tcx.privacy_access_levels(()).is_exported(src_id) - && !self.cx.tcx.privacy_access_levels(()).is_exported(dst_id) + if self.cx.tcx.effective_visibilities(()).is_exported(src_id) + && !self.cx.tcx.effective_visibilities(()).is_exported(dst_id) { privacy_error(self.cx, diag_info, path_str); } diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs index f3aa3c7ce245..450f69e15d1a 100644 --- a/src/librustdoc/passes/strip_private.rs +++ b/src/librustdoc/passes/strip_private.rs @@ -23,7 +23,7 @@ pub(crate) fn strip_private(mut krate: clean::Crate, cx: &mut DocContext<'_>) -> { let mut stripper = Stripper { retained: &mut retained, - access_levels: &cx.cache.access_levels, + effective_visibilities: &cx.cache.effective_visibilities, update_retained: true, is_json_output, }; diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index a9d768f0149d..f293a6fcc6df 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -1,6 +1,6 @@ //! A collection of utility functions for the `strip_*` passes. use rustc_hir::def_id::DefId; -use rustc_middle::middle::privacy::AccessLevels; +use rustc_middle::middle::privacy::EffectiveVisibilities; use std::mem; use crate::clean::{self, Item, ItemId, ItemIdSet}; @@ -9,7 +9,7 @@ use crate::formats::cache::Cache; pub(crate) struct Stripper<'a> { pub(crate) retained: &'a mut ItemIdSet, - pub(crate) access_levels: &'a AccessLevels, + pub(crate) effective_visibilities: &'a EffectiveVisibilities, pub(crate) update_retained: bool, pub(crate) is_json_output: bool, } @@ -20,13 +20,13 @@ pub(crate) struct Stripper<'a> { #[inline] fn is_item_reachable( is_json_output: bool, - access_levels: &AccessLevels, + effective_visibilities: &EffectiveVisibilities, item_id: ItemId, ) -> bool { if is_json_output { - access_levels.is_reachable(item_id.expect_def_id()) + effective_visibilities.is_reachable(item_id.expect_def_id()) } else { - access_levels.is_exported(item_id.expect_def_id()) + effective_visibilities.is_exported(item_id.expect_def_id()) } } @@ -64,7 +64,7 @@ impl<'a> DocFolder for Stripper<'a> { | clean::ForeignTypeItem => { let item_id = i.item_id; if item_id.is_local() - && !is_item_reachable(self.is_json_output, self.access_levels, item_id) + && !is_item_reachable(self.is_json_output, self.effective_visibilities, item_id) { debug!("Stripper: stripping {:?} {:?}", i.type_(), i.name); return None; @@ -168,7 +168,7 @@ impl<'a> DocFolder for ImplStripper<'a> { item_id.is_local() && !is_item_reachable( self.is_json_output, - &self.cache.access_levels, + &self.cache.effective_visibilities, item_id, ) }) diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index b8522ea5d8fd..8023ec9fa9a2 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -7,7 +7,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::Node; use rustc_hir::CRATE_HIR_ID; -use rustc_middle::middle::privacy::AccessLevel; +use rustc_middle::middle::privacy::Level; use rustc_middle::ty::{TyCtxt, Visibility}; use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; use rustc_span::symbol::{kw, sym, Symbol}; @@ -230,10 +230,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } else { // All items need to be handled here in case someone wishes to link // to them with intra-doc links - self.cx.cache.access_levels.set_access_level( + self.cx.cache.effective_visibilities.set_public_at_level( did, || Visibility::Restricted(CRATE_DEF_ID), - AccessLevel::Public, + Level::Direct, ); } } @@ -246,7 +246,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { None => return false, }; - let is_private = !self.cx.cache.access_levels.is_public(res_did); + let is_private = !self.cx.cache.effective_visibilities.is_directly_public(res_did); let is_hidden = inherits_doc_hidden(self.cx.tcx, res_hir_id); // Only inline if requested or if the item would otherwise be stripped. diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 0511494668b1..70214e2adba4 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -1,7 +1,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_ID}; -use rustc_middle::middle::privacy::{AccessLevel, AccessLevels}; +use rustc_middle::middle::privacy::{EffectiveVisibilities, Level}; use rustc_middle::ty::{TyCtxt, Visibility}; // FIXME: this may not be exhaustive, but is sufficient for rustdocs current uses @@ -10,10 +10,10 @@ use rustc_middle::ty::{TyCtxt, Visibility}; /// specific rustdoc annotations into account (i.e., `doc(hidden)`) pub(crate) struct LibEmbargoVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, - // Accessibility levels for reachable nodes - access_levels: &'a mut AccessLevels, - // Previous accessibility level, None means unreachable - prev_level: Option, + // Effective visibilities for reachable nodes + effective_visibilities: &'a mut EffectiveVisibilities, + // Previous level, None means unreachable + prev_level: Option, // Keeps track of already visited modules, in case a module re-exports its parent visited_mods: FxHashSet, } @@ -22,26 +22,26 @@ impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> { pub(crate) fn new(cx: &'a mut crate::core::DocContext<'tcx>) -> LibEmbargoVisitor<'a, 'tcx> { LibEmbargoVisitor { tcx: cx.tcx, - access_levels: &mut cx.cache.access_levels, - prev_level: Some(AccessLevel::Public), + effective_visibilities: &mut cx.cache.effective_visibilities, + prev_level: Some(Level::Direct), visited_mods: FxHashSet::default(), } } pub(crate) fn visit_lib(&mut self, cnum: CrateNum) { let did = cnum.as_def_id(); - self.update(did, Some(AccessLevel::Public)); + self.update(did, Some(Level::Direct)); self.visit_mod(did); } // Updates node level and returns the updated level - fn update(&mut self, did: DefId, level: Option) -> Option { + fn update(&mut self, did: DefId, level: Option) -> Option { let is_hidden = self.tcx.is_doc_hidden(did); - let old_level = self.access_levels.get_access_level(did); - // Accessibility levels can only grow + let old_level = self.effective_visibilities.public_at_level(did); + // Visibility levels can only grow if level > old_level && !is_hidden { - self.access_levels.set_access_level( + self.effective_visibilities.set_public_at_level( did, || Visibility::Restricted(CRATE_DEF_ID), level.unwrap(), diff --git a/src/test/ui/privacy/access_levels.rs b/src/test/ui/privacy/access_levels.rs deleted file mode 100644 index 6bca71618868..000000000000 --- a/src/test/ui/privacy/access_levels.rs +++ /dev/null @@ -1,75 +0,0 @@ -#![feature(rustc_attrs)] - -#[rustc_effective_visibility] -mod outer { //~ ERROR Public: pub(crate), Exported: pub(crate), Reachable: pub(crate), ReachableFromImplTrait: pub(crate) - #[rustc_effective_visibility] - pub mod inner1 { //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - - #[rustc_effective_visibility] - extern "C" {} //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - - #[rustc_effective_visibility] - pub trait PubTrait { //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - #[rustc_effective_visibility] - const A: i32; //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - #[rustc_effective_visibility] - type B; //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - } - - #[rustc_effective_visibility] - struct PrivStruct; //~ ERROR not in the table - - #[rustc_effective_visibility] - pub union PubUnion { //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - #[rustc_effective_visibility] - a: u8, //~ ERROR not in the table - #[rustc_effective_visibility] - pub b: u8, //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - } - - #[rustc_effective_visibility] - pub enum Enum { //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - #[rustc_effective_visibility] - A( //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - #[rustc_effective_visibility] - PubUnion, //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - ), - } - } - - #[rustc_effective_visibility] - macro_rules! none_macro { //~ ERROR Public: pub(crate), Exported: pub(crate), Reachable: pub(crate), ReachableFromImplTrait: pub(crate) - () => {}; - } - - #[macro_export] - #[rustc_effective_visibility] - macro_rules! public_macro { //~ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - () => {}; - } - - #[rustc_effective_visibility] - pub struct ReachableStruct { //~ ERROR Public: pub(crate), Exported: pub(crate), Reachable: pub, ReachableFromImplTrait: pub - #[rustc_effective_visibility] - pub a: u8, //~ ERROR Public: pub(crate), Exported: pub(crate), Reachable: pub, ReachableFromImplTrait: pub - } -} - -#[rustc_effective_visibility] -pub use outer::inner1; //~ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - -pub fn foo() -> outer::ReachableStruct { outer::ReachableStruct {a: 0} } - -mod half_public_import { - #[rustc_effective_visibility] - pub type HalfPublicImport = u8; //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - #[rustc_effective_visibility] - #[allow(non_upper_case_globals)] - pub(crate) const HalfPublicImport: u8 = 0; //~ ERROR Public: pub(crate), Exported: pub(crate), Reachable: pub(crate), ReachableFromImplTrait: pub(crate) -} - -#[rustc_effective_visibility] -pub use half_public_import::HalfPublicImport; //~ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - //~^ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - -fn main() {} diff --git a/src/test/ui/privacy/access_levels.stderr b/src/test/ui/privacy/access_levels.stderr deleted file mode 100644 index 07c4d436ff00..000000000000 --- a/src/test/ui/privacy/access_levels.stderr +++ /dev/null @@ -1,134 +0,0 @@ -error: Public: pub(crate), Exported: pub(crate), Reachable: pub(crate), ReachableFromImplTrait: pub(crate) - --> $DIR/access_levels.rs:4:1 - | -LL | mod outer { - | ^^^^^^^^^ - -error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - --> $DIR/access_levels.rs:6:5 - | -LL | pub mod inner1 { - | ^^^^^^^^^^^^^^ - -error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - --> $DIR/access_levels.rs:9:9 - | -LL | extern "C" {} - | ^^^^^^^^^^^^^ - -error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - --> $DIR/access_levels.rs:12:9 - | -LL | pub trait PubTrait { - | ^^^^^^^^^^^^^^^^^^ - -error: not in the table - --> $DIR/access_levels.rs:20:9 - | -LL | struct PrivStruct; - | ^^^^^^^^^^^^^^^^^ - -error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - --> $DIR/access_levels.rs:23:9 - | -LL | pub union PubUnion { - | ^^^^^^^^^^^^^^^^^^ - -error: not in the table - --> $DIR/access_levels.rs:25:13 - | -LL | a: u8, - | ^^^^^ - -error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - --> $DIR/access_levels.rs:27:13 - | -LL | pub b: u8, - | ^^^^^^^^^ - -error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - --> $DIR/access_levels.rs:31:9 - | -LL | pub enum Enum { - | ^^^^^^^^^^^^^ - -error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - --> $DIR/access_levels.rs:33:13 - | -LL | A( - | ^ - -error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - --> $DIR/access_levels.rs:35:17 - | -LL | PubUnion, - | ^^^^^^^^ - -error: Public: pub(crate), Exported: pub(crate), Reachable: pub(crate), ReachableFromImplTrait: pub(crate) - --> $DIR/access_levels.rs:41:5 - | -LL | macro_rules! none_macro { - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - --> $DIR/access_levels.rs:47:5 - | -LL | macro_rules! public_macro { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: Public: pub(crate), Exported: pub(crate), Reachable: pub, ReachableFromImplTrait: pub - --> $DIR/access_levels.rs:52:5 - | -LL | pub struct ReachableStruct { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: Public: pub(crate), Exported: pub(crate), Reachable: pub, ReachableFromImplTrait: pub - --> $DIR/access_levels.rs:54:9 - | -LL | pub a: u8, - | ^^^^^^^^^ - -error: Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - --> $DIR/access_levels.rs:59:9 - | -LL | pub use outer::inner1; - | ^^^^^^^^^^^^^ - -error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - --> $DIR/access_levels.rs:65:5 - | -LL | pub type HalfPublicImport = u8; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: Public: pub(crate), Exported: pub(crate), Reachable: pub(crate), ReachableFromImplTrait: pub(crate) - --> $DIR/access_levels.rs:68:5 - | -LL | pub(crate) const HalfPublicImport: u8 = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - --> $DIR/access_levels.rs:72:9 - | -LL | pub use half_public_import::HalfPublicImport; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - --> $DIR/access_levels.rs:72:9 - | -LL | pub use half_public_import::HalfPublicImport; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - --> $DIR/access_levels.rs:14:13 - | -LL | const A: i32; - | ^^^^^^^^^^^^ - -error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - --> $DIR/access_levels.rs:16:13 - | -LL | type B; - | ^^^^^^ - -error: aborting due to 22 previous errors - diff --git a/src/test/ui/privacy/effective_visibilities.rs b/src/test/ui/privacy/effective_visibilities.rs new file mode 100644 index 000000000000..1d806a1d1d16 --- /dev/null +++ b/src/test/ui/privacy/effective_visibilities.rs @@ -0,0 +1,75 @@ +#![feature(rustc_attrs)] + +#[rustc_effective_visibility] +mod outer { //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) + #[rustc_effective_visibility] + pub mod inner1 { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + + #[rustc_effective_visibility] + extern "C" {} //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + + #[rustc_effective_visibility] + pub trait PubTrait { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + #[rustc_effective_visibility] + const A: i32; //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + #[rustc_effective_visibility] + type B; //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + } + + #[rustc_effective_visibility] + struct PrivStruct; //~ ERROR not in the table + + #[rustc_effective_visibility] + pub union PubUnion { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + #[rustc_effective_visibility] + a: u8, //~ ERROR not in the table + #[rustc_effective_visibility] + pub b: u8, //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + } + + #[rustc_effective_visibility] + pub enum Enum { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + #[rustc_effective_visibility] + A( //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + #[rustc_effective_visibility] + PubUnion, //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + ), + } + } + + #[rustc_effective_visibility] + macro_rules! none_macro { //~ Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) + () => {}; + } + + #[macro_export] + #[rustc_effective_visibility] + macro_rules! public_macro { //~ Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + () => {}; + } + + #[rustc_effective_visibility] + pub struct ReachableStruct { //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub, ReachableThroughImplTrait: pub + #[rustc_effective_visibility] + pub a: u8, //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub, ReachableThroughImplTrait: pub + } +} + +#[rustc_effective_visibility] +pub use outer::inner1; //~ ERROR Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + +pub fn foo() -> outer::ReachableStruct { outer::ReachableStruct {a: 0} } + +mod half_public_import { + #[rustc_effective_visibility] + pub type HalfPublicImport = u8; //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + #[rustc_effective_visibility] + #[allow(non_upper_case_globals)] + pub(crate) const HalfPublicImport: u8 = 0; //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) +} + +#[rustc_effective_visibility] +pub use half_public_import::HalfPublicImport; //~ ERROR Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + //~^ ERROR Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + +fn main() {} diff --git a/src/test/ui/privacy/effective_visibilities.stderr b/src/test/ui/privacy/effective_visibilities.stderr new file mode 100644 index 000000000000..1c6201600b63 --- /dev/null +++ b/src/test/ui/privacy/effective_visibilities.stderr @@ -0,0 +1,134 @@ +error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) + --> $DIR/effective_visibilities.rs:4:1 + | +LL | mod outer { + | ^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:6:5 + | +LL | pub mod inner1 { + | ^^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:9:9 + | +LL | extern "C" {} + | ^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:12:9 + | +LL | pub trait PubTrait { + | ^^^^^^^^^^^^^^^^^^ + +error: not in the table + --> $DIR/effective_visibilities.rs:20:9 + | +LL | struct PrivStruct; + | ^^^^^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:23:9 + | +LL | pub union PubUnion { + | ^^^^^^^^^^^^^^^^^^ + +error: not in the table + --> $DIR/effective_visibilities.rs:25:13 + | +LL | a: u8, + | ^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:27:13 + | +LL | pub b: u8, + | ^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:31:9 + | +LL | pub enum Enum { + | ^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:33:13 + | +LL | A( + | ^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:35:17 + | +LL | PubUnion, + | ^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) + --> $DIR/effective_visibilities.rs:41:5 + | +LL | macro_rules! none_macro { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:47:5 + | +LL | macro_rules! public_macro { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:52:5 + | +LL | pub struct ReachableStruct { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:54:9 + | +LL | pub a: u8, + | ^^^^^^^^^ + +error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:59:9 + | +LL | pub use outer::inner1; + | ^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:65:5 + | +LL | pub type HalfPublicImport = u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) + --> $DIR/effective_visibilities.rs:68:5 + | +LL | pub(crate) const HalfPublicImport: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:72:9 + | +LL | pub use half_public_import::HalfPublicImport; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:72:9 + | +LL | pub use half_public_import::HalfPublicImport; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:14:13 + | +LL | const A: i32; + | ^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:16:13 + | +LL | type B; + | ^^^^^^ + +error: aborting due to 22 previous errors + diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs index 36dc7e3396b8..b47fa6c7ecf5 100644 --- a/src/tools/clippy/clippy_lints/src/doc.rs +++ b/src/tools/clippy/clippy_lints/src/doc.rs @@ -345,7 +345,7 @@ fn lint_for_missing_headers<'tcx>( body_id: Option, panic_span: Option, ) { - if !cx.access_levels.is_exported(def_id) { + if !cx.effective_visibilities.is_exported(def_id) { return; // Private functions do not require doc comments } diff --git a/src/tools/clippy/clippy_lints/src/enum_variants.rs b/src/tools/clippy/clippy_lints/src/enum_variants.rs index b019d07d53d1..2c3487a6e10f 100644 --- a/src/tools/clippy/clippy_lints/src/enum_variants.rs +++ b/src/tools/clippy/clippy_lints/src/enum_variants.rs @@ -296,7 +296,7 @@ impl LateLintPass<'_> for EnumVariantNames { } } if let ItemKind::Enum(ref def, _) = item.kind { - if !(self.avoid_breaking_exported_api && cx.access_levels.is_exported(item.def_id.def_id)) { + if !(self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(item.def_id.def_id)) { check_variant(cx, self.threshold, def, item_name, item.span); } } diff --git a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs index be6242bd20b8..bb07b29b0763 100644 --- a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs +++ b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs @@ -73,7 +73,7 @@ impl LateLintPass<'_> for ExhaustiveItems { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { if_chain! { if let ItemKind::Enum(..) | ItemKind::Struct(..) = item.kind; - if cx.access_levels.is_exported(item.def_id.def_id); + if cx.effective_visibilities.is_exported(item.def_id.def_id); let attrs = cx.tcx.hir().attrs(item.hir_id()); if !attrs.iter().any(|a| a.has_name(sym::non_exhaustive)); then { diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index 3064b6c9d22f..32cba5e608ad 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -24,7 +24,7 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_> let attrs = cx.tcx.hir().attrs(item.hir_id()); let attr = cx.tcx.get_attr(item.def_id.to_def_id(), sym::must_use); if let hir::ItemKind::Fn(ref sig, _generics, ref body_id) = item.kind { - let is_public = cx.access_levels.is_exported(item.def_id.def_id); + let is_public = cx.effective_visibilities.is_exported(item.def_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); if let Some(attr) = attr { check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr); @@ -44,7 +44,7 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_> pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) { if let hir::ImplItemKind::Fn(ref sig, ref body_id) = item.kind { - let is_public = cx.access_levels.is_exported(item.def_id.def_id); + let is_public = cx.effective_visibilities.is_exported(item.def_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); let attrs = cx.tcx.hir().attrs(item.hir_id()); let attr = cx.tcx.get_attr(item.def_id.to_def_id(), sym::must_use); @@ -67,7 +67,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { if let hir::TraitItemKind::Fn(ref sig, ref eid) = item.kind { - let is_public = cx.access_levels.is_exported(item.def_id.def_id); + let is_public = cx.effective_visibilities.is_exported(item.def_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); let attrs = cx.tcx.hir().attrs(item.hir_id()); @@ -137,7 +137,7 @@ fn check_must_use_candidate<'tcx>( || mutates_static(cx, body) || in_external_macro(cx.sess(), item_span) || returns_unit(decl) - || !cx.access_levels.is_exported(item_id) + || !cx.effective_visibilities.is_exported(item_id) || is_must_use_ty(cx, return_ty(cx, cx.tcx.hir().local_def_id_to_hir_id(item_id))) { return; diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs index b7595d101e0f..0831b5cc38bd 100644 --- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs +++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs @@ -42,7 +42,7 @@ fn check_raw_ptr<'tcx>( body: &'tcx hir::Body<'tcx>, def_id: LocalDefId, ) { - if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(def_id) { + if unsafety == hir::Unsafety::Normal && cx.effective_visibilities.is_exported(def_id) { let raw_ptrs = iter_input_pats(decl, body) .filter_map(|arg| raw_ptr_arg(cx, arg)) .collect::(); diff --git a/src/tools/clippy/clippy_lints/src/functions/result.rs b/src/tools/clippy/clippy_lints/src/functions/result.rs index 113c4e9f5091..c5ce56dd2cef 100644 --- a/src/tools/clippy/clippy_lints/src/functions/result.rs +++ b/src/tools/clippy/clippy_lints/src/functions/result.rs @@ -36,7 +36,7 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, l if let hir::ItemKind::Fn(ref sig, _generics, _) = item.kind && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id.def_id, item.span) { - if cx.access_levels.is_exported(item.def_id.def_id) { + if cx.effective_visibilities.is_exported(item.def_id.def_id) { let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); check_result_unit_err(cx, err_ty, fn_header_span); } @@ -50,7 +50,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::ImplItem && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id.def_id, item.span) && trait_ref_of_method(cx, item.def_id.def_id).is_none() { - if cx.access_levels.is_exported(item.def_id.def_id) { + if cx.effective_visibilities.is_exported(item.def_id.def_id) { let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); check_result_unit_err(cx, err_ty, fn_header_span); } @@ -62,7 +62,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::TraitIt if let hir::TraitItemKind::Fn(ref sig, _) = item.kind { let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); if let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id.def_id, item.span) { - if cx.access_levels.is_exported(item.def_id.def_id) { + if cx.effective_visibilities.is_exported(item.def_id.def_id) { check_result_unit_err(cx, err_ty, fn_header_span); } check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold); diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs index 93efe957b1dc..6415f35ddd03 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs @@ -111,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { } } - if !cx.access_levels.is_exported(item.def_id.def_id) { + if !cx.effective_visibilities.is_exported(item.def_id.def_id) { return; } diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 3a563736fb07..6e31812d7053 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -134,7 +134,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { if item.ident.name == sym::len; if let ImplItemKind::Fn(sig, _) = &item.kind; if sig.decl.implicit_self.has_implicit_self(); - if cx.access_levels.is_exported(item.def_id.def_id); + if cx.effective_visibilities.is_exported(item.def_id.def_id); if matches!(sig.decl.output, FnRetTy::Return(_)); if let Some(imp) = get_parent_as_impl(cx.tcx, item.hir_id()); if imp.of_trait.is_none(); @@ -210,7 +210,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items } } - if cx.access_levels.is_exported(visited_trait.def_id.def_id) + if cx.effective_visibilities.is_exported(visited_trait.def_id.def_id) && trait_items.iter().any(|i| is_named_self(cx, i, sym::len)) { let mut current_and_super_traits = DefIdSet::default(); @@ -331,7 +331,7 @@ fn check_for_is_empty<'tcx>( None, None, ), - Some(is_empty) if !cx.access_levels.is_exported(is_empty.def_id.expect_local()) => ( + Some(is_empty) if !cx.effective_visibilities.is_exported(is_empty.def_id.expect_local()) => ( format!( "{item_kind} `{}` has a public `len` method, but a private `is_empty` method", item_name.as_str(), diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index fb92779be2a7..adfa7426607f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -3258,7 +3258,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { let method_sig = cx.tcx.erase_late_bound_regions(method_sig); let first_arg_ty_opt = method_sig.inputs().iter().next().copied(); // if this impl block implements a trait, lint in trait definition instead - if !implements_trait && cx.access_levels.is_exported(impl_item.def_id.def_id) { + if !implements_trait && cx.effective_visibilities.is_exported(impl_item.def_id.def_id) { // check missing trait implementations for method_config in &TRAIT_METHODS { if name == method_config.method_name @@ -3292,7 +3292,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if sig.decl.implicit_self.has_implicit_self() && !(self.avoid_breaking_exported_api - && cx.access_levels.is_exported(impl_item.def_id.def_id)) + && cx.effective_visibilities.is_exported(impl_item.def_id.def_id)) && let Some(first_arg) = iter_input_pats(sig.decl, cx.tcx.hir().body(id)).next() && let Some(first_arg_ty) = first_arg_ty_opt { diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index 01c87f058ade..ed9da2d92173 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { return; } - if !cx.access_levels.is_exported(it.def_id.def_id) { + if !cx.effective_visibilities.is_exported(it.def_id.def_id) { return; } match it.kind { @@ -142,7 +142,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { } // If the item being implemented is not exported, then we don't need #[inline] - if !cx.access_levels.is_exported(impl_item.def_id.def_id) { + if !cx.effective_visibilities.is_exported(impl_item.def_id.def_id) { return; } @@ -159,7 +159,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { }; if let Some(trait_def_id) = trait_def_id { - if trait_def_id.is_local() && !cx.access_levels.is_exported(impl_item.def_id.def_id) { + if trait_def_id.is_local() && !cx.effective_visibilities.is_exported(impl_item.def_id.def_id) { // If a trait is being implemented for an item, and the // trait is not exported, we don't need #[inline] return; diff --git a/src/tools/clippy/clippy_lints/src/new_without_default.rs b/src/tools/clippy/clippy_lints/src/new_without_default.rs index 6017117e1ecc..99166c68936c 100644 --- a/src/tools/clippy/clippy_lints/src/new_without_default.rs +++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs @@ -96,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { if_chain! { if sig.decl.inputs.is_empty(); if name == sym::new; - if cx.access_levels.is_reachable(impl_item.def_id.def_id); + if cx.effective_visibilities.is_reachable(impl_item.def_id.def_id); let self_def_id = cx.tcx.hir().get_parent_item(id); let self_ty = cx.tcx.type_of(self_def_id); if self_ty == return_ty(cx, id); diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index 45e98de10ace..c55985275db6 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -139,7 +139,7 @@ impl<'tcx> PassByRefOrValue { } fn check_poly_fn(&mut self, cx: &LateContext<'tcx>, def_id: LocalDefId, decl: &FnDecl<'_>, span: Option) { - if self.avoid_breaking_exported_api && cx.access_levels.is_exported(def_id) { + if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(def_id) { return; } diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs index 464f6827e1d5..bc73613a1502 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs @@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { if_chain! { if cx.tcx.visibility(item.def_id.def_id) == ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id()); - if !cx.access_levels.is_exported(item.def_id.def_id) && self.is_exported.last() == Some(&false); + if !cx.effective_visibilities.is_exported(item.def_id.def_id) && self.is_exported.last() == Some(&false); if is_not_macro_export(item); then { let span = item.span.with_hi(item.ident.span.hi()); @@ -70,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { } if let ItemKind::Mod { .. } = item.kind { - self.is_exported.push(cx.access_levels.is_exported(item.def_id.def_id)); + self.is_exported.push(cx.effective_visibilities.is_exported(item.def_id.def_id)); } } diff --git a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs index 16d702a3868d..7f34be5e7fd8 100644 --- a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs +++ b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs @@ -74,7 +74,7 @@ fn check_method(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_def: LocalDefId, spa if !in_external_macro(cx.sess(), span); if decl.implicit_self.has_implicit_self(); // We only show this warning for public exported methods. - if cx.access_levels.is_exported(fn_def); + if cx.effective_visibilities.is_exported(fn_def); // We don't want to emit this lint if the `#[must_use]` attribute is already there. if !cx.tcx.hir().attrs(hir_id).iter().any(|attr| attr.has_name(sym::must_use)); if cx.tcx.visibility(fn_def.to_def_id()).is_public(); diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index a06d1fffd8bd..40cdcc3865ba 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -319,7 +319,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { false }; - let is_exported = cx.access_levels.is_exported(cx.tcx.hir().local_def_id(id)); + let is_exported = cx.effective_visibilities.is_exported(cx.tcx.hir().local_def_id(id)); self.check_fn_decl( cx, @@ -333,7 +333,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - let is_exported = cx.access_levels.is_exported(item.def_id.def_id); + let is_exported = cx.effective_visibilities.is_exported(item.def_id.def_id); match item.kind { ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => self.check_ty( @@ -379,7 +379,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) { - let is_exported = cx.access_levels.is_exported(cx.tcx.hir().local_def_id(field.hir_id)); + let is_exported = cx.effective_visibilities.is_exported(cx.tcx.hir().local_def_id(field.hir_id)); self.check_ty( cx, @@ -392,7 +392,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'_>) { - let is_exported = cx.access_levels.is_exported(item.def_id.def_id); + let is_exported = cx.effective_visibilities.is_exported(item.def_id.def_id); let context = CheckTyContext { is_exported, diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs index 7211e6864f3a..60b46854b4ff 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs @@ -83,7 +83,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { match fn_kind { FnKind::ItemFn(..) | FnKind::Method(..) => { let def_id = cx.tcx.hir().local_def_id(hir_id); - if self.avoid_breaking_exported_api && cx.access_levels.is_exported(def_id) { + if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(def_id) { return; } }, diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs index 713fe06bad43..62ab927d2f5c 100644 --- a/src/tools/clippy/clippy_lints/src/unused_self.rs +++ b/src/tools/clippy/clippy_lints/src/unused_self.rs @@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf { if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind; if assoc_item.fn_has_self_parameter; if let ImplItemKind::Fn(.., body_id) = &impl_item.kind; - if !cx.access_levels.is_exported(impl_item.def_id.def_id) || !self.avoid_breaking_exported_api; + if !cx.effective_visibilities.is_exported(impl_item.def_id.def_id) || !self.avoid_breaking_exported_api; let body = cx.tcx.hir().body(*body_id); if let [self_param, ..] = body.params; if !is_local_used(cx, body, self_param.pat.hir_id); diff --git a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs index 654ea306793b..7a20148c70a5 100644 --- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs +++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs @@ -105,7 +105,7 @@ impl LateLintPass<'_> for UpperCaseAcronyms { fn check_item(&mut self, cx: &LateContext<'_>, it: &Item<'_>) { // do not lint public items or in macros if in_external_macro(cx.sess(), it.span) - || (self.avoid_breaking_exported_api && cx.access_levels.is_exported(it.def_id.def_id)) + || (self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(it.def_id.def_id)) { return; } From de5517c3ae3c9ec007b49958c56be67247fa2713 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 19 Oct 2022 15:49:08 +0000 Subject: [PATCH 110/171] Remove unneeded sub-comparison --- compiler/rustc_infer/src/infer/sub.rs | 39 ++++++--------------------- 1 file changed, 8 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index a4b55dfa691d..97354ba5d1bd 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -2,9 +2,7 @@ use super::combine::{CombineFields, RelationDir}; use super::SubregionOrigin; use crate::infer::combine::ConstEquateRelation; -use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::traits::Obligation; -use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::TyVar; @@ -130,39 +128,18 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) if self.fields.define_opaque_types && did.is_local() => { - let mut generalize = |ty, ty_is_expected| { - let var = infcx.next_ty_var_id_in_universe( - TypeVariableOrigin { - kind: TypeVariableOriginKind::MiscVariable, - span: self.fields.trace.cause.span, - }, - ty::UniverseIndex::ROOT, - ); - self.fields.instantiate(ty, RelationDir::SubtypeOf, var, ty_is_expected)?; - Ok(infcx.tcx.mk_ty_var(var)) - }; - let (a, b) = if self.a_is_expected { (a, b) } else { (b, a) }; - let (ga, gb) = match (a.kind(), b.kind()) { - (&ty::Opaque(..), _) => (a, generalize(b, true)?), - (_, &ty::Opaque(..)) => (generalize(a, false)?, b), - _ => unreachable!(), - }; self.fields.obligations.extend( infcx - .handle_opaque_type(ga, gb, true, &self.fields.trace.cause, self.param_env()) - // Don't leak any generalized type variables out of this - // subtyping relation in the case of a type error. - .map_err(|err| { - let (ga, gb) = self.fields.infcx.resolve_vars_if_possible((ga, gb)); - if let TypeError::Sorts(sorts) = err && sorts.expected == ga && sorts.found == gb { - TypeError::Sorts(ExpectedFound { expected: a, found: b }) - } else { - err - } - })? + .handle_opaque_type( + a, + b, + self.a_is_expected, + &self.fields.trace.cause, + self.param_env(), + )? .obligations, ); - Ok(ga) + Ok(a) } // Optimization of GeneratorWitness relation since we know that all // free regions are replaced with bound regions during construction. From bd947632b5da12ccb28a446a62898862f8f415ed Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 26 Oct 2022 07:14:20 -0700 Subject: [PATCH 111/171] Update library/core/src/ptr/mod.rs Co-authored-by: Ralf Jung --- library/core/src/ptr/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 2c19c27681f3..3fd617559033 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -591,6 +591,7 @@ pub const fn invalid_mut(addr: usize) -> *mut T { /// the program has undefined behavior. In particular, the aliasing rules still apply: pointers /// and references that have been invalidated due to aliasing accesses cannot be used any more, /// even if they have been exposed! +/// /// Note that there is no algorithm that decides which provenance will be used. You can think of this /// as "guessing" the right provenance, and the guess will be "maximally in your favor", in the sense /// that if there is any way to avoid undefined behavior (while upholding all aliasing requirements), From cce46e9ae2b7ead4594e3a009bcca90db1b0b0a6 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Wed, 26 Oct 2022 16:50:08 +0200 Subject: [PATCH 112/171] Fix typo in docs for `guaranteed_ne` --- library/core/src/ptr/const_ptr.rs | 2 +- library/core/src/ptr/mut_ptr.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 67e59460d74b..ed16c5f051f7 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -802,7 +802,7 @@ impl *const T { /// Returns whether two pointers are guaranteed to be inequal. /// - /// At runtime this function behaves like `Some(self == other)`. + /// At runtime this function behaves like `Some(self != other)`. /// However, in some contexts (e.g., compile-time evaluation), /// it is not always possible to determine inequality of two pointers, so this function may /// spuriously return `None` for pointers that later actually turn out to have its inequality known. diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index bbcc7c699e03..fd5065471eaa 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -726,7 +726,7 @@ impl *mut T { /// Returns whether two pointers are guaranteed to be inequal. /// - /// At runtime this function behaves like `Some(self == other)`. + /// At runtime this function behaves like `Some(self != other)`. /// However, in some contexts (e.g., compile-time evaluation), /// it is not always possible to determine inequality of two pointers, so this function may /// spuriously return `None` for pointers that later actually turn out to have its inequality known. From db3b01d2bf67e647487320467bde6f7023a8f154 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 26 Oct 2022 16:05:58 +0000 Subject: [PATCH 113/171] Process registered region obligation in resolve_regions_with_wf_tys --- .../rustc_hir_analysis/src/check/wfcheck.rs | 4 ++++ src/test/ui/wf/issue-103573.rs | 22 +++++++++++++++++++ src/test/ui/wf/issue-103573.stderr | 14 ++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 src/test/ui/wf/issue-103573.rs create mode 100644 src/test/ui/wf/issue-103573.stderr diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 33ed3b96aa81..70a171c02b26 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -713,6 +713,10 @@ fn resolve_regions_with_wf_tys<'tcx>( add_constraints(&infcx, region_bound_pairs); + infcx.process_registered_region_obligations( + outlives_environment.region_bound_pairs(), + param_env, + ); let errors = infcx.resolve_regions(&outlives_environment); debug!(?errors, "errors"); diff --git a/src/test/ui/wf/issue-103573.rs b/src/test/ui/wf/issue-103573.rs new file mode 100644 index 000000000000..bcbf4f941ecd --- /dev/null +++ b/src/test/ui/wf/issue-103573.rs @@ -0,0 +1,22 @@ +trait TraitA { + type TypeA; +} + +trait TraitD { + type TypeD; +} + +pub trait TraitB { + type TypeB: TraitD; + + fn f(_: &::TypeD); +} + +pub trait TraitC { + type TypeC<'a>: TraitB; + + fn g<'a>(_: &< as TraitB>::TypeB as TraitA>::TypeA); + //~^ ERROR the trait bound `<>::TypeC<'a> as TraitB>::TypeB: TraitA` is not satisfied +} + +fn main() {} diff --git a/src/test/ui/wf/issue-103573.stderr b/src/test/ui/wf/issue-103573.stderr new file mode 100644 index 000000000000..fcf3f15e4d3f --- /dev/null +++ b/src/test/ui/wf/issue-103573.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `<>::TypeC<'a> as TraitB>::TypeB: TraitA` is not satisfied + --> $DIR/issue-103573.rs:18:5 + | +LL | fn g<'a>(_: &< as TraitB>::TypeB as TraitA>::TypeA); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitA` is not implemented for `<>::TypeC<'a> as TraitB>::TypeB` + | +help: consider further restricting the associated type + | +LL | fn g<'a>(_: &< as TraitB>::TypeB as TraitA>::TypeA) where <>::TypeC<'a> as TraitB>::TypeB: TraitA; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 796114a5b0c66abbb2527257b8a38c4cda964a66 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Wed, 26 Oct 2022 21:09:28 +0200 Subject: [PATCH 114/171] Add documentation --- compiler/rustc_parse/src/parser/mod.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 89f7ab930b1a..4376e5832efb 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -158,7 +158,7 @@ pub struct Parser<'a> { /// This allows us to recover when the user forget to add braces around /// multiple statements in the closure body. pub current_closure: Option, - /// Whether the parser is allowed to recover and parse invalid code successfully (and emit a diagnostic as a side effect). + /// Whether the parser is allowed to do recovery. /// This is disabled when parsing macro arguments, see #103534 pub recovery: Recovery, } @@ -506,6 +506,13 @@ impl<'a> Parser<'a> { self } + /// Whether the parser is allowed to recover from broken code. + /// + /// If this returns false, recovering broken code into valid code (especially if this recovery does lookahead) + /// is not allowed. All recovery done by the parser must be gated behind this check. + /// + /// Technically, this only needs to restruct eager recovery by doing lookahead at more tokens. + /// But making the distinction is very subtle, and simply forbidding all recovery is a lot simpler to uphold. fn may_recover(&self) -> bool { matches!(self.recovery, Recovery::Allowed) } From 3dd7009f1fb7a30771925ae5e6cedd9656d57796 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 26 Oct 2022 12:15:58 -0700 Subject: [PATCH 115/171] rustdoc: remove redundant CSS selector `.notable-traits .notable` The margin was already being set to 0 only a few lines lower. --- src/librustdoc/html/static/css/rustdoc.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 8424b2c4e293..5c4b3bb4df75 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1302,7 +1302,7 @@ h3.variant { content: "\00a0\00a0\00a0"; } -.notable-traits .notable, .notable-traits .docblock { +.notable-traits .docblock { margin: 0; } From d380d0387de4c0c0fd9bed40d1aa6f01457b061d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 26 Oct 2022 19:19:37 +0000 Subject: [PATCH 116/171] remove unused parser fn --- compiler/rustc_ast/src/ast.rs | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 7112c2675771..4ef43735a62c 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1112,24 +1112,6 @@ pub struct Expr { } impl Expr { - /// Returns `true` if this expression would be valid somewhere that expects a value; - /// for example, an `if` condition. - pub fn returns(&self) -> bool { - if let ExprKind::Block(ref block, _) = self.kind { - match block.stmts.last().map(|last_stmt| &last_stmt.kind) { - // Implicit return - Some(StmtKind::Expr(_)) => true, - // Last statement is an explicit return? - Some(StmtKind::Semi(expr)) => matches!(expr.kind, ExprKind::Ret(_)), - // This is a block that doesn't end in either an implicit or explicit return. - _ => false, - } - } else { - // This is not a block, it is a value. - true - } - } - /// Is this expr either `N`, or `{ N }`. /// /// If this is not the case, name resolution does not resolve `N` when using From da407ed38f6bcb79683379d59d18e615d2b8dfaa Mon Sep 17 00:00:00 2001 From: nils <48135649+Nilstrieb@users.noreply.github.com> Date: Wed, 26 Oct 2022 22:06:35 +0200 Subject: [PATCH 117/171] Fix typo Co-authored-by: Esteban Kuber --- compiler/rustc_parse/src/parser/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 4376e5832efb..5fe29062b85b 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -511,7 +511,7 @@ impl<'a> Parser<'a> { /// If this returns false, recovering broken code into valid code (especially if this recovery does lookahead) /// is not allowed. All recovery done by the parser must be gated behind this check. /// - /// Technically, this only needs to restruct eager recovery by doing lookahead at more tokens. + /// Technically, this only needs to restrict eager recovery by doing lookahead at more tokens. /// But making the distinction is very subtle, and simply forbidding all recovery is a lot simpler to uphold. fn may_recover(&self) -> bool { matches!(self.recovery, Recovery::Allowed) From d1132fb805537bc43539e1fca7729dde1bc16048 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 26 Oct 2022 22:11:12 +0200 Subject: [PATCH 118/171] thread::set_name: debug-assert that things went well --- library/std/src/sys/unix/thread.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index 69cd2b500a1f..c1d30dd9d521 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -137,7 +137,9 @@ impl Thread { unsafe { // Available since glibc 2.12, musl 1.1.16, and uClibc 1.0.20. let name = truncate_cstr(name, TASK_COMM_LEN); - libc::pthread_setname_np(libc::pthread_self(), name.as_ptr()); + let res = libc::pthread_setname_np(libc::pthread_self(), name.as_ptr()); + // We have no good way of propagating errors here, but in debug-builds let's check that this actually worked. + debug_assert_eq!(res, 0); } } @@ -152,7 +154,9 @@ impl Thread { pub fn set_name(name: &CStr) { unsafe { let name = truncate_cstr(name, libc::MAXTHREADNAMESIZE); - libc::pthread_setname_np(name.as_ptr()); + let res = libc::pthread_setname_np(name.as_ptr()); + // We have no good way of propagating errors here, but in debug-builds let's check that this actually worked. + debug_assert_eq!(res, 0); } } @@ -160,11 +164,12 @@ impl Thread { pub fn set_name(name: &CStr) { unsafe { let cname = CStr::from_bytes_with_nul_unchecked(b"%s\0".as_slice()); - libc::pthread_setname_np( + let res = libc::pthread_setname_np( libc::pthread_self(), cname.as_ptr(), name.as_ptr() as *mut libc::c_void, ); + debug_assert_eq!(res, 0); } } @@ -177,9 +182,8 @@ impl Thread { } if let Some(f) = pthread_setname_np.get() { - unsafe { - f(libc::pthread_self(), name.as_ptr()); - } + let res = unsafe { f(libc::pthread_self(), name.as_ptr()) }; + debug_assert_eq!(res, 0); } } From b66f92197a3a08bd268d1ad3a5fcfb8ecdebaafb Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 26 Oct 2022 23:32:14 +0200 Subject: [PATCH 119/171] rustc_lexer::TokenKind improve docs --- compiler/rustc_lexer/src/lib.rs | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index c71e6ffe34d9..51515976e4ee 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -57,29 +57,42 @@ pub enum TokenKind { // Multi-char tokens: /// "// comment" LineComment { doc_style: Option }, + /// `/* block comment */` /// - /// Block comments can be recursive, so the sequence like `/* /* */` + /// Block comments can be recursive, so a sequence like `/* /* */` /// will not be considered terminated and will result in a parsing error. BlockComment { doc_style: Option, terminated: bool }, - /// Any whitespace characters sequence. + + /// Any whitespace character sequence. Whitespace, + /// "ident" or "continue" - /// At this step keywords are also considered identifiers. + /// + /// At this step, keywords are also considered identifiers. Ident, + /// Like the above, but containing invalid unicode codepoints. InvalidIdent, + /// "r#ident" RawIdent, - /// An unknown prefix like `foo#`, `foo'`, `foo"`. Note that only the + + /// An unknown prefix, like `foo#`, `foo'`, `foo"`. + /// + /// Note that only the /// prefix (`foo`) is included in the token, not the separator (which is /// lexed as its own distinct token). In Rust 2021 and later, reserved /// prefixes are reported as errors; in earlier editions, they result in a /// (allowed by default) lint, and are treated as regular identifier /// tokens. UnknownPrefix, - /// "12_u8", "1.0e-40", "b"123"". See `LiteralKind` for more details. + + /// Examples: `"12_u8"`, `"1.0e-40"`, `b"123`. + /// + /// See [LiteralKind] for more details. Literal { kind: LiteralKind, suffix_start: u32 }, + /// "'a" Lifetime { starts_with_number: bool }, From a7a0b360a8f7dc2e7b942cad2cbf8b9a145e20aa Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 26 Oct 2022 14:42:53 -0700 Subject: [PATCH 120/171] rustdoc: add test case for positioning of notable trait tooltip --- src/test/rustdoc-gui/notable-trait.goml | 39 ++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/test/rustdoc-gui/notable-trait.goml b/src/test/rustdoc-gui/notable-trait.goml index 997fb5cf0ade..efe0cb15f08a 100644 --- a/src/test/rustdoc-gui/notable-trait.goml +++ b/src/test/rustdoc-gui/notable-trait.goml @@ -24,7 +24,23 @@ assert-position: ( "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']", {"x": 951}, ) - +// The tooltip should be beside the `i` +click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']" +compare-elements-position-near: ( + "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']", + "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']", + {"y": 2} +) +compare-elements-position-false: ( + "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']", + "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']", + ("x") +) +// The docblock should be flush with the border. +assert-css: ( + "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']/*[@class='docblock']", + {"margin-left": "0px"} +) // Now only the `i` should be on the next line. size: (1055, 600) @@ -81,6 +97,27 @@ assert-position: ( "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']", {"x": 289}, ) +// The tooltip should be below `i` +compare-elements-position-near-false: ( + "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']", + "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']", + {"y": 2} +) +compare-elements-position-false: ( + "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']", + "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']", + ("x") +) +compare-elements-position-near: ( + "//*[@id='method.create_an_iterator_from_read']/parent::*", + "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']", + {"x": 5} +) +// The docblock should be flush with the border. +assert-css: ( + "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']/*[@class='docblock']", + {"margin-left": "0px"} +) // Checking on very small mobile. The `i` should be on its own line. size: (365, 600) From 901649eeb7a42d521b222ee42701cc06655e9cd8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 26 Oct 2022 22:09:48 +0000 Subject: [PATCH 121/171] No need to probe when relating opaques in nll_relate --- compiler/rustc_infer/src/infer/nll_relate/mod.rs | 2 +- src/test/ui/impl-trait/issue-103599.rs | 10 ++++++++++ src/test/ui/impl-trait/issue-103599.stderr | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/impl-trait/issue-103599.rs create mode 100644 src/test/ui/impl-trait/issue-103599.stderr diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 7c186ae94706..bd4a11550921 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -592,7 +592,7 @@ where (&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)), (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => { - infcx.commit_if_ok(|_| infcx.super_combine_tys(self, a, b)).or_else(|err| { + infcx.super_combine_tys(self, a, b).or_else(|err| { self.tcx().sess.delay_span_bug( self.delegate.span(), "failure to relate an opaque to itself should result in an error later on", diff --git a/src/test/ui/impl-trait/issue-103599.rs b/src/test/ui/impl-trait/issue-103599.rs new file mode 100644 index 000000000000..043ae67f2e15 --- /dev/null +++ b/src/test/ui/impl-trait/issue-103599.rs @@ -0,0 +1,10 @@ +// check-pass + +trait T {} + +fn wrap(x: impl T) -> impl T { + //~^ WARN function cannot return without recursing + wrap(wrap(x)) +} + +fn main() {} diff --git a/src/test/ui/impl-trait/issue-103599.stderr b/src/test/ui/impl-trait/issue-103599.stderr new file mode 100644 index 000000000000..82038c1dceb3 --- /dev/null +++ b/src/test/ui/impl-trait/issue-103599.stderr @@ -0,0 +1,14 @@ +warning: function cannot return without recursing + --> $DIR/issue-103599.rs:5:1 + | +LL | fn wrap(x: impl T) -> impl T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | +LL | wrap(wrap(x)) + | ------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +warning: 1 warning emitted + From 27a6280eca979fa28582ea79d3e4736a298b13bd Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 26 Oct 2022 16:45:24 -0700 Subject: [PATCH 122/171] Add Target Tier Policy notification. --- triagebot.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index fb6287c5526c..202f9cad57a4 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -422,6 +422,12 @@ cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"] message = "`rustc_macros::diagnostics` was changed" cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"] +[mentions."compiler/rustc_target/src/spec"] +message = """ +These commits modify **compiler targets**. +(See the [Target Tier Policy](https://doc.rust-lang.org/nightly/rustc/target-tier-policy.html).) +""" + [assign] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/contributing.html" From b1cc95da2338af399e65c7186540e2f412c8fbe0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 24 Oct 2022 03:33:42 +0000 Subject: [PATCH 123/171] Remap early bound lifetimes too --- .../src/check/compare_method.rs | 2 +- src/test/ui/impl-trait/in-trait/early.rs | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/impl-trait/in-trait/early.rs diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs index e72f18012ab3..32f66b06f835 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_method.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs @@ -597,7 +597,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>( let num_trait_substs = trait_to_impl_substs.len(); let num_impl_substs = tcx.generics_of(impl_m.container_id(tcx)).params.len(); let ty = tcx.fold_regions(ty, |region, _| { - let ty::ReFree(_) = region.kind() else { return region; }; + let (ty::ReFree(_) | ty::ReEarlyBound(_)) = region.kind() else { return region; }; let Some(ty::ReEarlyBound(e)) = map.get(®ion.into()).map(|r| r.expect_region().kind()) else { tcx diff --git a/src/test/ui/impl-trait/in-trait/early.rs b/src/test/ui/impl-trait/in-trait/early.rs new file mode 100644 index 000000000000..9c1c2b503390 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/early.rs @@ -0,0 +1,23 @@ +// check-pass +// edition:2021 + +#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +pub trait Foo { + async fn bar<'a: 'a>(&'a mut self); +} + +impl Foo for () { + async fn bar<'a: 'a>(&'a mut self) {} +} + +pub trait Foo2 { + fn bar<'a: 'a>(&'a mut self) -> impl Sized + 'a; +} + +impl Foo2 for () { + fn bar<'a: 'a>(&'a mut self) -> impl Sized + 'a {} +} + +fn main() {} From 458aaa5a2343a58d169c21e90101376b83fd9fdc Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 13 Oct 2022 23:01:58 -0400 Subject: [PATCH 124/171] Print the precondition we violated, and visible through output capture Co-authored-by: Ralf Jung --- library/core/src/hint.rs | 2 +- library/core/src/intrinsics.rs | 23 +++++++++++++----- library/core/src/num/nonzero.rs | 5 +++- library/core/src/ops/index_range.rs | 7 +++++- library/core/src/ptr/alignment.rs | 7 +++++- library/core/src/ptr/const_ptr.rs | 5 +++- library/core/src/ptr/mod.rs | 30 +++++++++++++++++++----- library/core/src/ptr/non_null.rs | 2 +- library/core/src/slice/index.rs | 36 +++++++++++++++++++++-------- library/core/src/slice/mod.rs | 20 ++++++++++++---- library/core/src/slice/raw.rs | 12 ++++++---- library/test/src/lib.rs | 25 ++++++++++++++++++++ 12 files changed, 138 insertions(+), 36 deletions(-) diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 80036bcc4def..3412d3730d01 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -101,7 +101,7 @@ pub const unsafe fn unreachable_unchecked() -> ! { // SAFETY: the safety contract for `intrinsics::unreachable` must // be upheld by the caller. unsafe { - intrinsics::assert_unsafe_precondition!(() => false); + intrinsics::assert_unsafe_precondition!("hint::unreachable_unchecked must never be reached", () => false); intrinsics::unreachable() } } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 29f796fad6d5..1dc79afe83fd 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2203,7 +2203,7 @@ extern "rust-intrinsic" { /// the occasional mistake, and this check should help them figure things out. #[allow_internal_unstable(const_eval_select)] // permit this to be called in stably-const fn macro_rules! assert_unsafe_precondition { - ($([$($tt:tt)*])?($($i:ident:$ty:ty),*$(,)?) => $e:expr) => { + ($name:expr, $([$($tt:tt)*])?($($i:ident:$ty:ty),*$(,)?) => $e:expr) => { if cfg!(debug_assertions) { // allow non_snake_case to allow capturing const generics #[allow(non_snake_case)] @@ -2211,7 +2211,9 @@ macro_rules! assert_unsafe_precondition { fn runtime$(<$($tt)*>)?($($i:$ty),*) { if !$e { // don't unwind to reduce impact on code size - ::core::panicking::panic_str_nounwind("unsafe precondition violated"); + ::core::panicking::panic_str_nounwind( + concat!("unsafe precondition(s) violated: ", $name) + ); } } #[allow(non_snake_case)] @@ -2350,7 +2352,10 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us // SAFETY: the safety contract for `copy_nonoverlapping` must be // upheld by the caller. unsafe { - assert_unsafe_precondition!([T](src: *const T, dst: *mut T, count: usize) => + assert_unsafe_precondition!( + "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \ + and the specified memory ranges do not overlap", + [T](src: *const T, dst: *mut T, count: usize) => is_aligned_and_not_null(src) && is_aligned_and_not_null(dst) && is_nonoverlapping(src, dst, count) @@ -2436,8 +2441,11 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { // SAFETY: the safety contract for `copy` must be upheld by the caller. unsafe { - assert_unsafe_precondition!([T](src: *const T, dst: *mut T) => - is_aligned_and_not_null(src) && is_aligned_and_not_null(dst)); + assert_unsafe_precondition!( + "ptr::copy requires that both pointer arguments are aligned aligned and non-null", + [T](src: *const T, dst: *mut T) => + is_aligned_and_not_null(src) && is_aligned_and_not_null(dst) + ); copy(src, dst, count) } } @@ -2505,7 +2513,10 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { // SAFETY: the safety contract for `write_bytes` must be upheld by the caller. unsafe { - assert_unsafe_precondition!([T](dst: *mut T) => is_aligned_and_not_null(dst)); + assert_unsafe_precondition!( + "ptr::write_bytes requires that the destination pointer is aligned and non-null", + [T](dst: *mut T) => is_aligned_and_not_null(dst) + ); write_bytes(dst, val, count) } } diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index da402d66502a..6b6f3417f8ad 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -56,7 +56,10 @@ macro_rules! nonzero_integers { pub const unsafe fn new_unchecked(n: $Int) -> Self { // SAFETY: this is guaranteed to be safe by the caller. unsafe { - core::intrinsics::assert_unsafe_precondition!((n: $Int) => n != 0); + core::intrinsics::assert_unsafe_precondition!( + concat!(stringify!($Ty), "::new_unchecked requires a non-zero argument"), + (n: $Int) => n != 0 + ); Self(n) } } diff --git a/library/core/src/ops/index_range.rs b/library/core/src/ops/index_range.rs index 41ffe11f610d..3e06776d2c6f 100644 --- a/library/core/src/ops/index_range.rs +++ b/library/core/src/ops/index_range.rs @@ -19,7 +19,12 @@ impl IndexRange { #[inline] pub const unsafe fn new_unchecked(start: usize, end: usize) -> Self { // SAFETY: comparisons on usize are pure - unsafe { assert_unsafe_precondition!((start: usize, end: usize) => start <= end) }; + unsafe { + assert_unsafe_precondition!( + "IndexRange::new_unchecked requires `start <= end`", + (start: usize, end: usize) => start <= end + ) + }; IndexRange { start, end } } diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 846efbc4ebf6..1390e09dd96a 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -76,7 +76,12 @@ impl Alignment { #[inline] pub const unsafe fn new_unchecked(align: usize) -> Self { // SAFETY: Precondition passed to the caller. - unsafe { assert_unsafe_precondition!((align: usize) => align.is_power_of_two()) }; + unsafe { + assert_unsafe_precondition!( + "Alignment::new_unchecked requires a power of two", + (align: usize) => align.is_power_of_two() + ) + }; // SAFETY: By precondition, this must be a power of two, and // our variants encompass all possible powers of two. diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 67e59460d74b..42206047aa23 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -761,7 +761,10 @@ impl *const T { // SAFETY: The comparison has no side-effects, and the intrinsic // does this check internally in the CTFE implementation. unsafe { - assert_unsafe_precondition!([T](this: *const T, origin: *const T) => this >= origin) + assert_unsafe_precondition!( + "ptr::sub_ptr requires `this >= origin`", + [T](this: *const T, origin: *const T) => this >= origin + ) }; let pointee_size = mem::size_of::(); diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index cfffe351a87d..e8b44a6e4ace 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -889,7 +889,10 @@ pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { // SAFETY: the caller must guarantee that `x` and `y` are // valid for writes and properly aligned. unsafe { - assert_unsafe_precondition!([T](x: *mut T, y: *mut T, count: usize) => + assert_unsafe_precondition!( + "ptr::swap_nonoverlapping requires that both pointer arguments are aligned and non-null \ + and the specified memory ranges do not overlap", + [T](x: *mut T, y: *mut T, count: usize) => is_aligned_and_not_null(x) && is_aligned_and_not_null(y) && is_nonoverlapping(x, y, count) @@ -986,7 +989,10 @@ pub const unsafe fn replace(dst: *mut T, mut src: T) -> T { // and cannot overlap `src` since `dst` must point to a distinct // allocated object. unsafe { - assert_unsafe_precondition!([T](dst: *mut T) => is_aligned_and_not_null(dst)); + assert_unsafe_precondition!( + "ptr::replace requires that the pointer argument is aligned and non-null", + [T](dst: *mut T) => is_aligned_and_not_null(dst) + ); mem::swap(&mut *dst, &mut src); // cannot overlap } src @@ -1117,7 +1123,10 @@ pub const unsafe fn read(src: *const T) -> T { // Also, since we just wrote a valid value into `tmp`, it is guaranteed // to be properly initialized. unsafe { - assert_unsafe_precondition!([T](src: *const T) => is_aligned_and_not_null(src)); + assert_unsafe_precondition!( + "ptr::read requires that the pointer argument is aligned and non-null", + [T](src: *const T) => is_aligned_and_not_null(src) + ); copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); tmp.assume_init() } @@ -1311,7 +1320,10 @@ pub const unsafe fn write(dst: *mut T, src: T) { // `dst` cannot overlap `src` because the caller has mutable access // to `dst` while `src` is owned by this function. unsafe { - assert_unsafe_precondition!([T](dst: *mut T) => is_aligned_and_not_null(dst)); + assert_unsafe_precondition!( + "ptr::write requires that the pointer argument is aligned and non-null", + [T](dst: *mut T) => is_aligned_and_not_null(dst) + ); copy_nonoverlapping(&src as *const T, dst, 1); intrinsics::forget(src); } @@ -1475,7 +1487,10 @@ pub const unsafe fn write_unaligned(dst: *mut T, src: T) { pub unsafe fn read_volatile(src: *const T) -> T { // SAFETY: the caller must uphold the safety contract for `volatile_load`. unsafe { - assert_unsafe_precondition!([T](src: *const T) => is_aligned_and_not_null(src)); + assert_unsafe_precondition!( + "ptr::read_volatile requires that the pointer argument is aligned and non-null", + [T](src: *const T) => is_aligned_and_not_null(src) + ); intrinsics::volatile_load(src) } } @@ -1546,7 +1561,10 @@ pub unsafe fn read_volatile(src: *const T) -> T { pub unsafe fn write_volatile(dst: *mut T, src: T) { // SAFETY: the caller must uphold the safety contract for `volatile_store`. unsafe { - assert_unsafe_precondition!([T](dst: *mut T) => is_aligned_and_not_null(dst)); + assert_unsafe_precondition!( + "ptr::write_volatile requires that the pointer argument is aligned and non-null", + [T](dst: *mut T) => is_aligned_and_not_null(dst) + ); intrinsics::volatile_store(dst, src); } } diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 7264d57ba6ae..c18264d13eba 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -197,7 +197,7 @@ impl NonNull { pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { // SAFETY: the caller must guarantee that `ptr` is non-null. unsafe { - assert_unsafe_precondition!([T: ?Sized](ptr: *mut T) => !ptr.is_null()); + assert_unsafe_precondition!("NonNull::new_unchecked requires that the pointer is non-null", [T: ?Sized](ptr: *mut T) => !ptr.is_null()); NonNull { pointer: ptr as _ } } } diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 916d0262dedb..6d2f7330d5db 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -232,7 +232,10 @@ unsafe impl const SliceIndex<[T]> for usize { // `self` is in bounds of `slice` so `self` cannot overflow an `isize`, // so the call to `add` is safe. unsafe { - assert_unsafe_precondition!([T](this: usize, slice: *const [T]) => this < slice.len()); + assert_unsafe_precondition!( + "slice::get_unchecked requires that the index is within the slice", + [T](this: usize, slice: *const [T]) => this < slice.len() + ); slice.as_ptr().add(self) } } @@ -242,7 +245,10 @@ unsafe impl const SliceIndex<[T]> for usize { let this = self; // SAFETY: see comments for `get_unchecked` above. unsafe { - assert_unsafe_precondition!([T](this: usize, slice: *mut [T]) => this < slice.len()); + assert_unsafe_precondition!( + "slice::get_unchecked_mut requires that the index is within the slice", + [T](this: usize, slice: *mut [T]) => this < slice.len() + ); slice.as_mut_ptr().add(self) } } @@ -295,8 +301,10 @@ unsafe impl const SliceIndex<[T]> for ops::IndexRange { // so the call to `add` is safe. unsafe { - assert_unsafe_precondition!([T](end: usize, slice: *const [T]) => - end <= slice.len()); + assert_unsafe_precondition!( + "slice::get_unchecked requires that the index is within the slice", + [T](end: usize, slice: *const [T]) => end <= slice.len() + ); ptr::slice_from_raw_parts(slice.as_ptr().add(self.start()), self.len()) } } @@ -306,8 +314,10 @@ unsafe impl const SliceIndex<[T]> for ops::IndexRange { let end = self.end(); // SAFETY: see comments for `get_unchecked` above. unsafe { - assert_unsafe_precondition!([T](end: usize, slice: *mut [T]) => - end <= slice.len()); + assert_unsafe_precondition!( + "slice::get_unchecked_mut requires that the index is within the slice", + [T](end: usize, slice: *mut [T]) => end <= slice.len() + ); ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start()), self.len()) } } @@ -367,8 +377,11 @@ unsafe impl const SliceIndex<[T]> for ops::Range { // so the call to `add` is safe. unsafe { - assert_unsafe_precondition!([T](this: ops::Range, slice: *const [T]) => - this.end >= this.start && this.end <= slice.len()); + assert_unsafe_precondition!( + "slice::get_unchecked requires that the range is within the slice", + [T](this: ops::Range, slice: *const [T]) => + this.end >= this.start && this.end <= slice.len() + ); ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), self.end - self.start) } } @@ -378,8 +391,11 @@ unsafe impl const SliceIndex<[T]> for ops::Range { let this = ops::Range { start: self.start, end: self.end }; // SAFETY: see comments for `get_unchecked` above. unsafe { - assert_unsafe_precondition!([T](this: ops::Range, slice: *mut [T]) => - this.end >= this.start && this.end <= slice.len()); + assert_unsafe_precondition!( + "slice::get_unchecked_mut requires that the range is within the slice", + [T](this: ops::Range, slice: *mut [T]) => + this.end >= this.start && this.end <= slice.len() + ); ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), self.end - self.start) } } diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 94ab13ed2e04..4f1bb17344b2 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -653,7 +653,10 @@ impl [T] { let ptr = this.as_mut_ptr(); // SAFETY: caller has to guarantee that `a < self.len()` and `b < self.len()` unsafe { - assert_unsafe_precondition!([T](a: usize, b: usize, this: &mut [T]) => a < this.len() && b < this.len()); + assert_unsafe_precondition!( + "slice::swap_unchecked requires that the indices are within the slice", + [T](a: usize, b: usize, this: &mut [T]) => a < this.len() && b < this.len() + ); ptr::swap(ptr.add(a), ptr.add(b)); } } @@ -969,7 +972,10 @@ impl [T] { let this = self; // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length let new_len = unsafe { - assert_unsafe_precondition!([T](this: &[T], N: usize) => N != 0 && this.len() % N == 0); + assert_unsafe_precondition!( + "slice::as_chunks_unchecked requires `N != 0` and the slice to split exactly into `N`-element chunks", + [T](this: &[T], N: usize) => N != 0 && this.len() % N == 0 + ); exact_div(self.len(), N) }; // SAFETY: We cast a slice of `new_len * N` elements into @@ -1109,7 +1115,10 @@ impl [T] { let this = &*self; // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length let new_len = unsafe { - assert_unsafe_precondition!([T](this: &[T], N: usize) => N != 0 && this.len() % N == 0); + assert_unsafe_precondition!( + "slice::as_chunks_unchecked_mut requires `N != 0` and the slice to split exactly into `N`-element chunks", + [T](this: &[T], N: usize) => N != 0 && this.len() % N == 0 + ); exact_div(this.len(), N) }; // SAFETY: We cast a slice of `new_len * N` elements into @@ -1685,7 +1694,10 @@ impl [T] { // `[ptr; mid]` and `[mid; len]` are not overlapping, so returning a mutable reference // is fine. unsafe { - assert_unsafe_precondition!((mid: usize, len: usize) => mid <= len); + assert_unsafe_precondition!( + "slice::split_at_mut_unchecked requires the index to be within the slice", + (mid: usize, len: usize) => mid <= len + ); (from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid)) } } diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index dace748fed45..052fd34d0b6b 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -92,8 +92,10 @@ use crate::ptr; pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { // SAFETY: the caller must uphold the safety contract for `from_raw_parts`. unsafe { - assert_unsafe_precondition!([T](data: *const T, len: usize) => - is_aligned_and_not_null(data) && is_valid_allocation_size::(len) + assert_unsafe_precondition!( + "slice::from_raw_parts requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`", + [T](data: *const T, len: usize) => is_aligned_and_not_null(data) + && is_valid_allocation_size::(len) ); &*ptr::slice_from_raw_parts(data, len) } @@ -135,8 +137,10 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { // SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`. unsafe { - assert_unsafe_precondition!([T](data: *mut T, len: usize) => - is_aligned_and_not_null(data) && is_valid_allocation_size::(len) + assert_unsafe_precondition!( + "slice::from_raw_parts_mut requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`", + [T](data: *mut T, len: usize) => is_aligned_and_not_null(data) + && is_valid_allocation_size::(len) ); &mut *ptr::slice_from_raw_parts_mut(data, len) } diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 4de694557982..141f16d17f02 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -20,6 +20,7 @@ #![feature(is_terminal)] #![feature(staged_api)] #![feature(process_exitcode_internals)] +#![feature(panic_can_unwind)] #![feature(test)] // Public reexports @@ -54,6 +55,7 @@ use std::{ collections::VecDeque, env, io, io::prelude::Write, + mem::ManuallyDrop, panic::{self, catch_unwind, AssertUnwindSafe, PanicInfo}, process::{self, Command, Termination}, sync::mpsc::{channel, Sender}, @@ -112,6 +114,29 @@ pub fn test_main(args: &[String], tests: Vec, options: Option| { + if !info.can_unwind() { + std::mem::forget(std::io::stderr().lock()); + let mut stdout = ManuallyDrop::new(std::io::stdout().lock()); + if let Some(captured) = io::set_output_capture(None) { + if let Ok(data) = captured.lock() { + let _ = stdout.write_all(&data); + let _ = stdout.flush(); + } + } + } + builtin_panic_hook(info); + } + }); + panic::set_hook(hook); + } match console::run_tests_console(&opts, tests) { Ok(true) => {} Ok(false) => process::exit(ERROR_EXIT_CODE), From 2f2a97ee16b76a98b0646ea0730d1befed0552d6 Mon Sep 17 00:00:00 2001 From: Rageking8 Date: Thu, 27 Oct 2022 10:11:49 +0800 Subject: [PATCH 125/171] add tests and slight formatting --- ...erlap-marker-trait-with-static-lifetime.rs | 10 ++++++ ...p-marker-trait-with-underscore-lifetime.rs | 9 ++++++ ...rker-trait-with-underscore-lifetime.stderr | 31 +++++++++++++++++++ .../marker_trait_attr/overlap-marker-trait.rs | 3 +- .../overlap-marker-trait.stderr | 4 +-- ...p-permitted-for-annotated-marker-traits.rs | 3 +- 6 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.rs create mode 100644 src/test/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.rs create mode 100644 src/test/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr diff --git a/src/test/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.rs b/src/test/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.rs new file mode 100644 index 000000000000..62aa22d41ed8 --- /dev/null +++ b/src/test/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.rs @@ -0,0 +1,10 @@ +// check-pass +#![feature(marker_trait_attr)] + +#[marker] +trait Marker {} + +impl Marker for &'static () {} +impl Marker for &'static () {} + +fn main() {} diff --git a/src/test/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.rs b/src/test/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.rs new file mode 100644 index 000000000000..eabce1aeff14 --- /dev/null +++ b/src/test/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.rs @@ -0,0 +1,9 @@ +#![feature(marker_trait_attr)] + +#[marker] +trait Marker {} + +impl Marker for &'_ () {} //~ ERROR type annotations needed +impl Marker for &'_ () {} //~ ERROR type annotations needed + +fn main() {} diff --git a/src/test/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr b/src/test/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr new file mode 100644 index 000000000000..235c89e200ae --- /dev/null +++ b/src/test/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr @@ -0,0 +1,31 @@ +error[E0283]: type annotations needed: cannot satisfy `&(): Marker` + --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:6:6 + | +LL | impl Marker for &'_ () {} + | ^^^^^^ + | +note: multiple `impl`s satisfying `&(): Marker` found + --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:6:1 + | +LL | impl Marker for &'_ () {} + | ^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Marker for &'_ () {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0283]: type annotations needed: cannot satisfy `&(): Marker` + --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:7:6 + | +LL | impl Marker for &'_ () {} + | ^^^^^^ + | +note: multiple `impl`s satisfying `&(): Marker` found + --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:6:1 + | +LL | impl Marker for &'_ () {} + | ^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Marker for &'_ () {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/marker_trait_attr/overlap-marker-trait.rs b/src/test/ui/marker_trait_attr/overlap-marker-trait.rs index 8794d42f4113..67e551797755 100644 --- a/src/test/ui/marker_trait_attr/overlap-marker-trait.rs +++ b/src/test/ui/marker_trait_attr/overlap-marker-trait.rs @@ -7,7 +7,8 @@ use std::fmt::{Debug, Display}; -#[marker] trait Marker {} +#[marker] +trait Marker {} impl Marker for T {} impl Marker for T {} diff --git a/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr b/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr index 1f3410597944..133bc0484ee0 100644 --- a/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr +++ b/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `NotDebugOrDisplay: Marker` is not satisfied - --> $DIR/overlap-marker-trait.rs:27:17 + --> $DIR/overlap-marker-trait.rs:28:17 | LL | is_marker::(); | ^^^^^^^^^^^^^^^^^ the trait `Marker` is not implemented for `NotDebugOrDisplay` | note: required by a bound in `is_marker` - --> $DIR/overlap-marker-trait.rs:15:17 + --> $DIR/overlap-marker-trait.rs:16:17 | LL | fn is_marker() { } | ^^^^^^ required by this bound in `is_marker` diff --git a/src/test/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs b/src/test/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs index 383313902379..f7654458feb0 100644 --- a/src/test/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs +++ b/src/test/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs @@ -7,7 +7,8 @@ use std::fmt::{Debug, Display}; -#[marker] trait MyMarker {} +#[marker] +trait MyMarker {} impl MyMarker for T {} impl MyMarker for T {} From 4d4b567bcc64921921521a3076d8b4b94c96e441 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 26 Oct 2022 21:13:20 -0700 Subject: [PATCH 126/171] rustdoc: remove CSS workaround for Firefox 29 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CSS variables, which rustdoc now relies on, are only supported in Firefox 31 and later: https://www.mozilla.org/en-US/firefox/31.0/releasenotes/ This means it’s fine to also rely on unprefixed box-sizing, which is supported in Firefox 29 and later: https://www.mozilla.org/en-US/firefox/29.0/releasenotes/ --- src/librustdoc/html/static/css/rustdoc.css | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index b60c77195639..9fb694124b70 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -857,9 +857,7 @@ so that we can apply CSS-filters to change the arrow color in themes */ causes rounded corners and no border on iOS Safari. */ -webkit-appearance: none; /* Override Normalize.css: we have margins and do - not want to overflow - the `moz` attribute is necessary - until Firefox 29, too early to drop at this point */ - -moz-box-sizing: border-box !important; + not want to overflow */ box-sizing: border-box !important; outline: none; border: 1px solid var(--border-color); From 166d8b8c2b282ba0d0cf4da277cf8829d30df94b Mon Sep 17 00:00:00 2001 From: Pointerbender Date: Thu, 27 Oct 2022 06:32:36 +0200 Subject: [PATCH 127/171] add "Memory layout" subsection to documentation of `UnsafeCell` for additional clarity --- library/core/src/cell.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index fe5dd7be8f6b..7bf32cb0d98f 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1816,6 +1816,8 @@ impl fmt::Display for RefMut<'_, T> { /// /// [`.get_mut()`]: `UnsafeCell::get_mut` /// +/// # Memory layout +/// /// `UnsafeCell` has the same in-memory representation as its inner type `T`. A consequence /// of this guarantee is that it is possible to convert between `T` and `UnsafeCell`. /// Special care has to be taken when converting a nested `T` inside of an `Outer` type From a17ccfa6211b978c502cdd6739bb1b58db0dbb03 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 27 Oct 2022 14:45:02 +0400 Subject: [PATCH 128/171] Accept `TyCtxt` instead of `TyCtxtAt` in `Ty::is_*` functions Functions in answer: - `Ty::is_freeze` - `Ty::is_sized` - `Ty::is_unpin` - `Ty::is_copy_modulo_regions` --- compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- .../rustc_codegen_ssa/src/traits/type_.rs | 7 +++---- .../src/const_eval/valtrees.rs | 4 ++-- .../src/interpret/eval_context.rs | 2 +- .../rustc_const_eval/src/interpret/intern.rs | 2 +- .../src/interpret/validity.rs | 3 +-- .../src/transform/check_consts/qualifs.rs | 3 +-- .../src/transform/check_consts/resolver.rs | 6 +----- .../src/transform/validate.rs | 3 +-- .../rustc_hir_analysis/src/check/check.rs | 2 +- .../src/check/intrinsicck.rs | 4 ++-- compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_lint/src/types.rs | 6 +++--- compiler/rustc_middle/src/ty/layout.rs | 4 ++-- compiler/rustc_middle/src/ty/util.rs | 21 +++++++------------ .../src/build/expr/as_operand.rs | 5 ++--- .../rustc_mir_build/src/check_unsafety.rs | 6 ++---- .../src/thir/pattern/check_match.rs | 8 +++---- .../src/thir/pattern/const_to_pat.rs | 4 ++-- .../rustc_mir_transform/src/check_unsafety.rs | 2 +- .../rustc_mir_transform/src/const_prop.rs | 2 +- .../src/const_prop_lint.rs | 2 +- .../src/deduce_param_attrs.rs | 3 +-- compiler/rustc_mir_transform/src/shim.rs | 2 +- compiler/rustc_monomorphize/src/collector.rs | 2 +- compiler/rustc_trait_selection/src/infer.rs | 2 +- compiler/rustc_ty_utils/src/instance.rs | 4 ++-- compiler/rustc_ty_utils/src/layout.rs | 5 ++--- compiler/rustc_ty_utils/src/needs_drop.rs | 2 +- 29 files changed, 51 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 00cacd515a1e..074aca9251c8 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1776,7 +1776,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // `Sized` bound in no way depends on precise regions, so this // shouldn't affect `is_sized`. let erased_ty = tcx.erase_regions(ty); - if !erased_ty.is_sized(tcx.at(span), self.param_env) { + if !erased_ty.is_sized(tcx, self.param_env) { // in current MIR construction, all non-control-flow rvalue // expressions evaluate through `as_temp` or `into` a return // slot or local, so to find all unsized rvalues it is enough diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index 8158e8dd0112..bdc6a91cf6ab 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -5,7 +5,6 @@ use crate::common::TypeKind; use crate::mir::place::PlaceRef; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, Ty}; -use rustc_span::DUMMY_SP; use rustc_target::abi::call::{ArgAbi, CastTarget, FnAbi, Reg}; use rustc_target::abi::{AddressSpace, Integer}; @@ -75,16 +74,16 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> { } fn type_is_sized(&self, ty: Ty<'tcx>) -> bool { - ty.is_sized(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all()) + ty.is_sized(self.tcx(), ty::ParamEnv::reveal_all()) } fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool { - ty.is_freeze(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all()) + ty.is_freeze(self.tcx(), ty::ParamEnv::reveal_all()) } fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool { let param_env = ty::ParamEnv::reveal_all(); - if ty.is_sized(self.tcx().at(DUMMY_SP), param_env) { + if ty.is_sized(self.tcx(), param_env) { return false; } diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index a964fe8465ee..f4da11883957 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -212,7 +212,7 @@ fn create_pointee_place<'tcx>( ) -> MPlaceTy<'tcx> { let tcx = ecx.tcx.tcx; - if !ty.is_sized(ecx.tcx, ty::ParamEnv::empty()) { + if !ty.is_sized(*ecx.tcx, ty::ParamEnv::empty()) { // We need to create `Allocation`s for custom DSTs let (unsized_inner_ty, num_elems) = get_info_on_unsized_field(ty, valtree, tcx); @@ -398,7 +398,7 @@ fn valtree_into_mplace<'tcx>( let mut place_inner = match ty.kind() { ty::Str | ty::Slice(_) => ecx.mplace_index(&place, i as u64).unwrap(), - _ if !ty.is_sized(ecx.tcx, ty::ParamEnv::empty()) + _ if !ty.is_sized(*ecx.tcx, ty::ParamEnv::empty()) && i == branches.len() - 1 => { // Note: For custom DSTs we need to manually process the last unsized field. diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index d2e0a0dd240e..a9063ad31cfe 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -468,7 +468,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { #[inline] pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool { - ty.is_freeze(self.tcx, self.param_env) + ty.is_freeze(*self.tcx, self.param_env) } pub fn load_mir( diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index f72ae7413e30..79f981797a89 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -114,7 +114,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval: if let InternMode::Static(mutability) = mode { // For this, we need to take into account `UnsafeCell`. When `ty` is `None`, we assume // no interior mutability. - let frozen = ty.map_or(true, |ty| ty.is_freeze(ecx.tcx, ecx.param_env)); + let frozen = ty.map_or(true, |ty| ty.is_freeze(*ecx.tcx, ecx.param_env)); // For statics, allocation mutability is the combination of place mutability and // type mutability. // The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere. diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index d4146c242410..8aa56c275d91 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -15,7 +15,6 @@ use rustc_middle::mir::interpret::InterpError; use rustc_middle::ty; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_span::symbol::{sym, Symbol}; -use rustc_span::DUMMY_SP; use rustc_target::abi::{Abi, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange}; use std::hash::Hash; @@ -726,7 +725,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> ) -> InterpResult<'tcx> { // Special check preventing `UnsafeCell` inside unions in the inner part of constants. if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { inner: true, .. })) { - if !op.layout.ty.is_freeze(self.ecx.tcx.at(DUMMY_SP), self.ecx.param_env) { + if !op.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.param_env) { throw_validation_failure!(self.path, { "`UnsafeCell` in a `const`" }); } } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index b77b213b51a5..335992342a64 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -8,7 +8,6 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir; use rustc_middle::mir::*; use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty}; -use rustc_span::DUMMY_SP; use rustc_trait_selection::traits::{ self, ImplSource, Obligation, ObligationCause, SelectionContext, }; @@ -92,7 +91,7 @@ impl Qualif for HasMutInterior { } fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { - !ty.is_freeze(cx.tcx.at(DUMMY_SP), cx.param_env) + !ty.is_freeze(cx.tcx, cx.param_env) } fn in_adt_inherently<'tcx>( diff --git a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs index 60c1e4950292..805e6096b35c 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs @@ -8,7 +8,6 @@ use rustc_middle::mir::{self, BasicBlock, Local, Location, Statement, StatementK use rustc_mir_dataflow::fmt::DebugWithContext; use rustc_mir_dataflow::JoinSemiLattice; use rustc_mir_dataflow::{Analysis, AnalysisDomain, CallReturnPlaces}; -use rustc_span::DUMMY_SP; use std::fmt; use std::marker::PhantomData; @@ -120,10 +119,7 @@ where /// /// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134 fn shared_borrow_allows_mutation(&self, place: mir::Place<'tcx>) -> bool { - !place - .ty(self.ccx.body, self.ccx.tcx) - .ty - .is_freeze(self.ccx.tcx.at(DUMMY_SP), self.ccx.param_env) + !place.ty(self.ccx.body, self.ccx.tcx).ty.is_freeze(self.ccx.tcx, self.ccx.param_env) } } diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 7f78d963e9f0..81b82a21fa1a 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -235,9 +235,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { // `Operand::Copy` is only supposed to be used with `Copy` types. if let Operand::Copy(place) = operand { let ty = place.ty(&self.body.local_decls, self.tcx).ty; - let span = self.body.source_info(location).span; - if !ty.is_copy_modulo_regions(self.tcx.at(span), self.param_env) { + if !ty.is_copy_modulo_regions(self.tcx, self.param_env) { self.fail(location, format!("`Operand::Copy` with non-`Copy` type {}", ty)); } } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index b302cee4816f..0bdd509e621f 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -114,7 +114,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b _ => { // Fallback case: allow `ManuallyDrop` and things that are `Copy`. ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop()) - || ty.is_copy_modulo_regions(tcx.at(span), param_env) + || ty.is_copy_modulo_regions(tcx, param_env) } } } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index a026f8033c8c..17c4d0d482f2 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -33,7 +33,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool { // Type still may have region variables, but `Sized` does not depend // on those, so just erase them before querying. - if ty.is_sized(self.tcx.at(DUMMY_SP), self.param_env) { + if ty.is_sized(self.tcx, self.param_env) { return true; } if let ty::Foreign(..) = ty.kind() { @@ -128,7 +128,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { // Check that the type implements Copy. The only case where this can // possibly fail is for SIMD types which don't #[derive(Copy)]. - if !ty.is_copy_modulo_regions(self.tcx.at(expr.span), self.param_env) { + if !ty.is_copy_modulo_regions(self.tcx, self.param_env) { let msg = "arguments for inline assembly must be copyable"; let mut err = self.tcx.sess.struct_span_err(expr.span, msg); err.note(&format!("`{ty}` does not implement the Copy trait")); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 53c491051342..2617b60ec309 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -752,7 +752,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { return; } let param_env = ty::ParamEnv::empty(); - if ty.is_copy_modulo_regions(cx.tcx.at(item.span), param_env) { + if ty.is_copy_modulo_regions(cx.tcx, param_env) { return; } if can_type_implement_copy( diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 7c99bb2790fd..05957b57408b 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -11,7 +11,7 @@ use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable}; use rustc_span::source_map; use rustc_span::symbol::sym; -use rustc_span::{Span, Symbol, DUMMY_SP}; +use rustc_span::{Span, Symbol}; use rustc_target::abi::{Abi, WrappingRange}; use rustc_target::abi::{Integer, TagEncoding, Variants}; use rustc_target::spec::abi::Abi as SpecAbi; @@ -931,7 +931,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { match *ty.kind() { ty::Adt(def, substs) => { if def.is_box() && matches!(self.mode, CItemKind::Definition) { - if ty.boxed_ty().is_sized(tcx.at(DUMMY_SP), self.cx.param_env) { + if ty.boxed_ty().is_sized(tcx, self.cx.param_env) { return FfiSafe; } else { return FfiUnsafe { @@ -1082,7 +1082,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _) if { matches!(self.mode, CItemKind::Definition) - && ty.is_sized(self.cx.tcx.at(DUMMY_SP), self.cx.param_env) + && ty.is_sized(self.cx.tcx, self.cx.param_env) } => { FfiSafe diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 0a109fd8f44f..3312f44c67b2 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -830,7 +830,7 @@ where } else { match mt { hir::Mutability::Not => { - if ty.is_freeze(tcx.at(DUMMY_SP), cx.param_env()) { + if ty.is_freeze(tcx, cx.param_env()) { PointerKind::Frozen } else { PointerKind::SharedMutable @@ -841,7 +841,7 @@ where // noalias, as another pointer to the structure can be obtained, that // is not based-on the original reference. We consider all !Unpin // types to be potentially self-referential here. - if ty.is_unpin(tcx.at(DUMMY_SP), cx.param_env()) { + if ty.is_unpin(tcx, cx.param_env()) { PointerKind::UniqueBorrowed } else { PointerKind::UniqueBorrowedPinned diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index f73d062ba30a..f72e236eda13 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -2,7 +2,6 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::ty::layout::IntegerExt; -use crate::ty::query::TyCtxtAt; use crate::ty::{ self, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, @@ -821,12 +820,8 @@ impl<'tcx> Ty<'tcx> { /// does copies even when the type actually doesn't satisfy the /// full requirements for the `Copy` trait (cc #29149) -- this /// winds up being reported as an error during NLL borrow check. - pub fn is_copy_modulo_regions( - self, - tcx_at: TyCtxtAt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ) -> bool { - self.is_trivially_pure_clone_copy() || tcx_at.is_copy_raw(param_env.and(self)) + pub fn is_copy_modulo_regions(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + self.is_trivially_pure_clone_copy() || tcx.is_copy_raw(param_env.and(self)) } /// Checks whether values of this type `T` have a size known at @@ -835,8 +830,8 @@ impl<'tcx> Ty<'tcx> { /// over-approximation in generic contexts, where one can have /// strange rules like `>::Bar: Sized` that /// actually carry lifetime requirements. - pub fn is_sized(self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { - self.is_trivially_sized(tcx_at.tcx) || tcx_at.is_sized_raw(param_env.and(self)) + pub fn is_sized(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + self.is_trivially_sized(tcx) || tcx.is_sized_raw(param_env.and(self)) } /// Checks whether values of this type `T` implement the `Freeze` @@ -846,8 +841,8 @@ impl<'tcx> Ty<'tcx> { /// optimization as well as the rules around static values. Note /// that the `Freeze` trait is not exposed to end users and is /// effectively an implementation detail. - pub fn is_freeze(self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { - self.is_trivially_freeze() || tcx_at.is_freeze_raw(param_env.and(self)) + pub fn is_freeze(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + self.is_trivially_freeze() || tcx.is_freeze_raw(param_env.and(self)) } /// Fast path helper for testing if a type is `Freeze`. @@ -886,8 +881,8 @@ impl<'tcx> Ty<'tcx> { } /// Checks whether values of this type `T` implement the `Unpin` trait. - pub fn is_unpin(self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { - self.is_trivially_unpin() || tcx_at.is_unpin_raw(param_env.and(self)) + pub fn is_unpin(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + self.is_trivially_unpin() || tcx.is_unpin_raw(param_env.and(self)) } /// Fast path helper for testing if a type is `Unpin`. diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs index e707c373f0dd..c8610af7038d 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs @@ -153,12 +153,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if tcx.features().unsized_fn_params { let ty = expr.ty; - let span = expr.span; let param_env = this.param_env; - if !ty.is_sized(tcx.at(span), param_env) { + if !ty.is_sized(tcx, param_env) { // !sized means !copy, so this is an unsized move - assert!(!ty.is_copy_modulo_regions(tcx.at(span), param_env)); + assert!(!ty.is_copy_modulo_regions(tcx, param_env)); // As described above, detect the case where we are passing a value of unsized // type, and that value is coming from the deref of a box. diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 5e8ce65daf0f..fb1ea9ed300a 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -260,7 +260,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { }; match borrow_kind { BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique => { - if !ty.is_freeze(self.tcx.at(pat.span), self.param_env) { + if !ty.is_freeze(self.tcx, self.param_env) { self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField); } } @@ -457,9 +457,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { if visitor.found { match borrow_kind { BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique - if !self.thir[arg] - .ty - .is_freeze(self.tcx.at(self.thir[arg].span), self.param_env) => + if !self.thir[arg].ty.is_freeze(self.tcx, self.param_env) => { self.requires_unsafe(expr.span, BorrowOfLayoutConstrainedField) } diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 5984c800d838..858129c742dc 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -1004,8 +1004,8 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>( } /// Check if a by-value binding is by-value. That is, check if the binding's type is not `Copy`. -fn is_binding_by_move(cx: &MatchVisitor<'_, '_, '_>, hir_id: HirId, span: Span) -> bool { - !cx.typeck_results.node_type(hir_id).is_copy_modulo_regions(cx.tcx.at(span), cx.param_env) +fn is_binding_by_move(cx: &MatchVisitor<'_, '_, '_>, hir_id: HirId) -> bool { + !cx.typeck_results.node_type(hir_id).is_copy_modulo_regions(cx.tcx, cx.param_env) } /// Check that there are no borrow or move conflicts in `binding @ subpat` patterns. @@ -1031,7 +1031,7 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa // Get the binding move, extract the mutability if by-ref. let mut_outer = match typeck_results.extract_binding_mode(sess, pat.hir_id, pat.span) { - Some(ty::BindByValue(_)) if is_binding_by_move(cx, pat.hir_id, pat.span) => { + Some(ty::BindByValue(_)) if is_binding_by_move(cx, pat.hir_id) => { // We have `x @ pat` where `x` is by-move. Reject all borrows in `pat`. let mut conflicts_ref = Vec::new(); sub.each_binding(|_, hir_id, span, _| { @@ -1070,7 +1070,7 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa (Mutability::Mut, Mutability::Mut) => conflicts_mut_mut.push((span, name)), // 2x `ref mut`. _ => conflicts_mut_ref.push((span, name)), // `ref` + `ref mut` in either direction. }, - Some(ty::BindByValue(_)) if is_binding_by_move(cx, hir_id, span) => { + Some(ty::BindByValue(_)) if is_binding_by_move(cx, hir_id) => { conflicts_move.push((span, name)) // `ref mut?` + by-move conflict. } Some(ty::BindByValue(_)) | None => {} // `ref mut?` + by-copy is fine. diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index cf8ae776be96..ad12e0116211 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -506,7 +506,7 @@ impl<'tcx> ConstToPat<'tcx> { // convert the dereferenced constant to a pattern that is the sub-pattern of the // deref pattern. _ => { - if !pointee_ty.is_sized(tcx.at(span), param_env) { + if !pointee_ty.is_sized(tcx, param_env) { // `tcx.deref_mir_constant()` below will ICE with an unsized type // (except slices, which are handled in a separate arm above). let msg = format!("cannot use unsized non-slice type `{}` in constant patterns", pointee_ty); @@ -534,7 +534,7 @@ impl<'tcx> ConstToPat<'tcx> { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => { PatKind::Constant { value: cv } } - ty::RawPtr(pointee) if pointee.ty.is_sized(tcx.at(span), param_env) => { + ty::RawPtr(pointee) if pointee.ty.is_sized(tcx, param_env) => { PatKind::Constant { value: cv } } // FIXME: these can have very surprising behaviour where optimization levels or other diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 4730be1244bd..f8f04214a2ca 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -312,7 +312,7 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> { } else if !place .ty(self.body, self.tcx) .ty - .is_freeze(self.tcx.at(self.source_info.span), self.param_env) + .is_freeze(self.tcx, self.param_env) { UnsafetyViolationDetails::BorrowOfLayoutConstrainedField } else { diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 4a9bd9df327f..4e4515888454 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -633,7 +633,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } if !rvalue .ty(&self.ecx.frame().body.local_decls, *self.ecx.tcx) - .is_sized(self.ecx.tcx, self.param_env) + .is_sized(*self.ecx.tcx, self.param_env) { // the interpreter doesn't support unsized locals (only unsized arguments), // but rustc does (in a kinda broken way), so we have to skip them here diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 6bddbdb8e6aa..479c4e577d4e 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -500,7 +500,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } if !rvalue .ty(&self.ecx.frame().body.local_decls, *self.ecx.tcx) - .is_sized(self.ecx.tcx, self.param_env) + .is_sized(*self.ecx.tcx, self.param_env) { // the interpreter doesn't support unsized locals (only unsized arguments), // but rustc does (in a kinda broken way), so we have to skip them here diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index 18352fbf675c..28b1c5a48099 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs @@ -11,7 +11,6 @@ use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{Body, Local, Location, Operand, Terminator, TerminatorKind, RETURN_PLACE}; use rustc_middle::ty::{self, DeducedParamAttrs, ParamEnv, Ty, TyCtxt}; use rustc_session::config::OptLevel; -use rustc_span::DUMMY_SP; /// A visitor that determines which arguments have been mutated. We can't use the mutability field /// on LocalDecl for this because it has no meaning post-optimization. @@ -232,7 +231,7 @@ pub fn deduced_param_attrs<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx [Ded body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map( |(arg_index, local_decl)| DeducedParamAttrs { read_only: !deduce_read_only.mutable_args.contains(arg_index) - && local_decl.ty.is_freeze(tcx.at(DUMMY_SP), ParamEnv::reveal_all()), + && local_decl.ty.is_freeze(tcx, ParamEnv::reveal_all()), }, ), ); diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index c19380ef89cc..4e8798b7a55d 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -312,7 +312,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) - let param_env = tcx.param_env(def_id); let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty); - let is_copy = self_ty.is_copy_modulo_regions(tcx.at(builder.span), param_env); + let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env); let dest = Place::return_place(); let src = tcx.mk_place_deref(Place::from(Local::new(1 + 0))); diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 5cd7a7f760f5..6079a02d1374 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1067,7 +1067,7 @@ fn find_vtable_types_for_unsizing<'tcx>( let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| { let param_env = ty::ParamEnv::reveal_all(); let type_has_metadata = |ty: Ty<'tcx>| -> bool { - if ty.is_sized(tcx.at(DUMMY_SP), param_env) { + if ty.is_sized(tcx, param_env) { return false; } let tail = tcx.struct_tail_erasing_lifetimes(ty, param_env); diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 1b58c9b864e4..a335f8e06bc9 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -69,7 +69,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { let ty = self.resolve_vars_if_possible(ty); if !(param_env, ty).needs_infer() { - return ty.is_copy_modulo_regions(self.tcx.at(span), param_env); + return ty.is_copy_modulo_regions(self.tcx, param_env); } let copy_def_id = self.tcx.require_lang_item(LangItem::Copy, None); diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 416c1ec510b0..6436713b3881 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -4,7 +4,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::traits::CodegenObligationError; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitable}; -use rustc_span::{sym, DUMMY_SP}; +use rustc_span::sym; use rustc_trait_selection::traits; use traits::{translate_substs, Reveal}; @@ -236,7 +236,7 @@ fn resolve_associated_item<'tcx>( if name == sym::clone { let self_ty = trait_ref.self_ty(); - let is_copy = self_ty.is_copy_modulo_regions(tcx.at(DUMMY_SP), param_env); + let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env); match self_ty.kind() { _ if is_copy => (), ty::Generator(..) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 345911f4309a..52ba0eee97cd 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -399,7 +399,7 @@ fn layout_of_uncached<'tcx>( } let pointee = tcx.normalize_erasing_regions(param_env, pointee); - if pointee.is_sized(tcx.at(DUMMY_SP), param_env) { + if pointee.is_sized(tcx, param_env) { return Ok(tcx.intern_layout(LayoutS::scalar(cx, data_ptr))); } @@ -755,8 +755,7 @@ fn layout_of_uncached<'tcx>( } else { let param_env = tcx.param_env(def.did()); let last_field = def.variant(v).fields.last().unwrap(); - let always_sized = - tcx.type_of(last_field.did).is_sized(tcx.at(DUMMY_SP), param_env); + let always_sized = tcx.type_of(last_field.did).is_sized(tcx, param_env); if !always_sized { StructKind::MaybeUnsized } else { StructKind::AlwaysSized } }; diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index d390a3081530..024dcd591bd7 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -109,7 +109,7 @@ where for component in components { match *component.kind() { - _ if component.is_copy_modulo_regions(tcx.at(DUMMY_SP), self.param_env) => (), + _ if component.is_copy_modulo_regions(tcx, self.param_env) => (), ty::Closure(_, substs) => { queue_type(self, substs.as_closure().tupled_upvars_ty()); From 0185be2ce45efdd988df2b2ee69b764f9e3c7f6c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 27 Oct 2022 13:07:07 +0200 Subject: [PATCH 129/171] Migrate line numbers CSS to CSS variables --- src/librustdoc/html/static/css/rustdoc.css | 8 ++++++++ src/librustdoc/html/static/css/themes/ayu.css | 12 +++--------- src/librustdoc/html/static/css/themes/dark.css | 14 +++----------- src/librustdoc/html/static/css/themes/light.css | 14 +++----------- 4 files changed, 17 insertions(+), 31 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index b60c77195639..c20912dc69a3 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -571,10 +571,18 @@ ul.block, .block li { padding: 13px 8px; border-top-left-radius: 5px; border-bottom-left-radius: 5px; + border-color: var(--example-line-numbers-border-color); } .src-line-numbers span { cursor: pointer; + color: var(--src-line-numbers-span-color); +} +.src-line-numbers .line-highlighted { + background-color: var(--src-line-number-highlighted-background-color); +} +.src-line-numbers :target { + background-color: transparent; } .search-loading { diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 33817c16808c..fdfdb3e19667 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -55,6 +55,9 @@ Original by Dempfi (https://github.com/dempfi/ayu) --code-highlight-question-mark-color: #ff9011; --code-highlight-comment-color: #788797; --code-highlight-doc-comment-color: #a1ac88; + --example-line-numbers-border-color: none; + --src-line-numbers-span-color: #5c6773; + --src-line-number-highlighted-background-color: rgba(255, 236, 164, 0.06); } .slider { @@ -112,10 +115,8 @@ pre, .rustdoc.source .example-wrap { color: #ff7733; } -.src-line-numbers span { color: #5c6773; } .src-line-numbers .line-highlighted { color: #708090; - background-color: rgba(255, 236, 164, 0.06); padding-right: 4px; border-right: 1px solid #ffb44c; } @@ -170,13 +171,6 @@ details.rustdoc-toggle > summary::before { color: #788797; } -.src-line-numbers :target { background-color: transparent; } - -pre.example-line-numbers { - color: #5c67736e; - border: none; -} - a.test-arrow { font-size: 100%; color: #788797; diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index d88710288b90..361d3d4a2259 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -50,6 +50,9 @@ --code-highlight-question-mark-color: #ff9011; --code-highlight-comment-color: #8d8d8b; --code-highlight-doc-comment-color: #8ca375; + --example-line-numbers-border-color: #4a4949; + --src-line-numbers-span-color: #3b91e2; + --src-line-number-highlighted-background-color: #0a042f; } .slider { @@ -69,11 +72,6 @@ input:focus + .slider { drop-shadow(0 -1px 0 #fff) } -.src-line-numbers span { color: #3B91E2; } -.src-line-numbers .line-highlighted { - background-color: #0a042f !important; -} - .content .item-info::before { color: #ccc; } body.source .example-wrap pre.rust a { @@ -95,12 +93,6 @@ details.rustdoc-toggle > summary::before { filter: invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%); } -.src-line-numbers :target { background-color: transparent; } - -pre.example-line-numbers { - border-color: #4a4949; -} - a.test-arrow { color: #dedede; background-color: rgba(78, 139, 202, 0.2); diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index cadc71dab959..5eb4bbcf834b 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -50,6 +50,9 @@ --code-highlight-question-mark-color: #ff9011; --code-highlight-comment-color: #8e908c; --code-highlight-doc-comment-color: #4d4d4c; + --example-line-numbers-border-color: #c7c7c7; + --src-line-numbers-span-color: #c67e2d; + --src-line-number-highlighted-background-color: #fdffd3; } .slider { @@ -68,11 +71,6 @@ input:focus + .slider { */ } -.src-line-numbers span { color: #c67e2d; } -.src-line-numbers .line-highlighted { - background-color: #FDFFD3 !important; -} - .content .item-info::before { color: #ccc; } body.source .example-wrap pre.rust a { @@ -90,12 +88,6 @@ body.source .example-wrap pre.rust a { filter: invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg) brightness(96%) contrast(93%); } -.src-line-numbers :target { background-color: transparent; } - -pre.example-line-numbers { - border-color: #c7c7c7; -} - a.test-arrow { color: #f5f5f5; background-color: rgba(78, 139, 202, 0.2); From 71e824de26189c514150840cae493f596e362f1c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 26 Oct 2022 17:51:20 +0200 Subject: [PATCH 130/171] Add tests for source line numbers colors --- src/test/rustdoc-gui/source-code-page.goml | 44 +++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml index 29d65fc7ebc7..a2dac2aa681d 100644 --- a/src/test/rustdoc-gui/source-code-page.goml +++ b/src/test/rustdoc-gui/source-code-page.goml @@ -1,5 +1,6 @@ // Checks that the interactions with the source code pages are working as expected. goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html" +show-text: true // Check that we can click on the line number. click: ".src-line-numbers > span:nth-child(4)" // This is the span for line 4. // Ensure that the page URL was updated. @@ -12,6 +13,48 @@ assert-attribute: (".src-line-numbers > span:nth-child(4)", {"class": "line-high assert-attribute: (".src-line-numbers > span:nth-child(5)", {"class": "line-highlighted"}) assert-attribute: (".src-line-numbers > span:nth-child(6)", {"class": "line-highlighted"}) assert-attribute-false: (".src-line-numbers > span:nth-child(7)", {"class": "line-highlighted"}) + +define-function: ( + "check-colors", + (theme, color, background_color, highlight_color, highlight_background_color), + [ + ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + ("reload"), + ("assert-css", ( + ".src-line-numbers > span:not(.line-highlighted)", + {"color": |color|, "background-color": |background_color|}, + ALL, + )), + ("assert-css", ( + ".src-line-numbers > span.line-highlighted", + {"color": |highlight_color|, "background-color": |highlight_background_color|}, + ALL, + )), + ], +) + +call-function: ("check-colors", { + "theme": "ayu", + "color": "rgb(92, 103, 115)", + "background_color": "rgba(0, 0, 0, 0)", + "highlight_color": "rgb(112, 128, 144)", + "highlight_background_color": "rgba(255, 236, 164, 0.06)", +}) +call-function: ("check-colors", { + "theme": "dark", + "color": "rgb(59, 145, 226)", + "background_color": "rgba(0, 0, 0, 0)", + "highlight_color": "rgb(59, 145, 226)", + "highlight_background_color": "rgb(10, 4, 47)", +}) +call-function: ("check-colors", { + "theme": "light", + "color": "rgb(198, 126, 45)", + "background_color": "rgba(0, 0, 0, 0)", + "highlight_color": "rgb(198, 126, 45)", + "highlight_background_color": "rgb(253, 255, 211)", +}) + // This is to ensure that the content is correctly align with the line numbers. compare-elements-position: ("//*[@id='1']", ".rust > code > span", ("y")) @@ -20,7 +63,6 @@ assert-css: (".src-line-numbers", {"text-align": "right"}) // Now let's check that clicking on something else than the line number doesn't // do anything (and certainly not add a `#NaN` to the URL!). -show-text: true goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html" // We use this assert-position to know where we will click. assert-position: ("//*[@id='1']", {"x": 104, "y": 112}) From 9117ea975834a86dadcb9ebbc40dd9a9fb0f78ae Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 27 Oct 2022 13:23:26 +0000 Subject: [PATCH 131/171] Introduce UnordMap, UnordSet, and UnordBag (see MCP 533) MCP 533: https://github.com/rust-lang/compiler-team/issues/533 Also, as an example, substitute UnordMap for FxHashMap in used_trait_imports query result. --- compiler/rustc_data_structures/src/lib.rs | 2 + compiler/rustc_data_structures/src/unord.rs | 382 ++++++++++++++++++ .../rustc_hir_analysis/src/check_unused.rs | 7 +- compiler/rustc_hir_typeck/src/lib.rs | 4 +- compiler/rustc_middle/src/arena.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 3 +- compiler/rustc_middle/src/ty/query.rs | 1 + .../rustc_query_impl/src/on_disk_cache.rs | 5 +- src/librustdoc/core.rs | 4 +- 10 files changed, 400 insertions(+), 12 deletions(-) create mode 100644 compiler/rustc_data_structures/src/unord.rs diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 467ac401d086..3a2000233c5d 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -22,6 +22,7 @@ #![feature(new_uninit)] #![feature(once_cell)] #![feature(rustc_attrs)] +#![feature(negative_impls)] #![feature(test)] #![feature(thread_id_value)] #![feature(vec_into_raw_parts)] @@ -86,6 +87,7 @@ pub mod steal; pub mod tagged_ptr; pub mod temp_dir; pub mod unhash; +pub mod unord; pub use ena::undo_log; pub use ena::unify; diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs new file mode 100644 index 000000000000..c015f1232cd9 --- /dev/null +++ b/compiler/rustc_data_structures/src/unord.rs @@ -0,0 +1,382 @@ +//! This module contains collection types that don't expose their internal +//! ordering. This is a useful property for deterministic computations, such +//! as required by the query system. + +use rustc_hash::{FxHashMap, FxHashSet}; +use smallvec::SmallVec; +use std::{ + borrow::Borrow, + hash::Hash, + iter::{Product, Sum}, +}; + +use crate::{ + fingerprint::Fingerprint, + stable_hasher::{HashStable, StableHasher, ToStableHashKey}, +}; + +/// `UnordItems` is the order-less version of `Iterator`. It only contains methods +/// that don't (easily) expose an ordering of the underlying items. +/// +/// Most methods take an `Fn` where the `Iterator`-version takes an `FnMut`. This +/// is to reduce the risk of accidentally leaking the internal order via the closure +/// environment. Otherwise one could easily do something like +/// +/// ```rust,ignore (pseudo code) +/// let mut ordered = vec![]; +/// unordered_items.all(|x| ordered.push(x)); +/// ``` +/// +/// It's still possible to do the same thing with an `Fn` by using interior mutability, +/// but the chance of doing it accidentally is reduced. +pub struct UnordItems>(I); + +impl> UnordItems { + #[inline] + pub fn map U>(self, f: F) -> UnordItems> { + UnordItems(self.0.map(f)) + } + + #[inline] + pub fn all bool>(mut self, f: F) -> bool { + self.0.all(f) + } + + #[inline] + pub fn any bool>(mut self, f: F) -> bool { + self.0.any(f) + } + + #[inline] + pub fn filter bool>(self, f: F) -> UnordItems> { + UnordItems(self.0.filter(f)) + } + + #[inline] + pub fn filter_map Option>( + self, + f: F, + ) -> UnordItems> { + UnordItems(self.0.filter_map(f)) + } + + #[inline] + pub fn max(self) -> Option + where + T: Ord, + { + self.0.max() + } + + #[inline] + pub fn min(self) -> Option + where + T: Ord, + { + self.0.min() + } + + #[inline] + pub fn sum(self) -> S + where + S: Sum, + { + self.0.sum() + } + + #[inline] + pub fn product(self) -> S + where + S: Product, + { + self.0.product() + } + + #[inline] + pub fn count(self) -> usize { + self.0.count() + } +} + +impl<'a, T: Clone + 'a, I: Iterator> UnordItems<&'a T, I> { + #[inline] + pub fn cloned(self) -> UnordItems> { + UnordItems(self.0.cloned()) + } +} + +impl<'a, T: Copy + 'a, I: Iterator> UnordItems<&'a T, I> { + #[inline] + pub fn copied(self) -> UnordItems> { + UnordItems(self.0.copied()) + } +} + +impl> UnordItems { + pub fn into_sorted(self, hcx: &HCX) -> Vec + where + T: ToStableHashKey, + { + let mut items: Vec = self.0.collect(); + items.sort_by_cached_key(|x| x.to_stable_hash_key(hcx)); + items + } + + pub fn into_sorted_small_vec(self, hcx: &HCX) -> SmallVec<[T; LEN]> + where + T: ToStableHashKey, + { + let mut items: SmallVec<[T; LEN]> = self.0.collect(); + items.sort_by_cached_key(|x| x.to_stable_hash_key(hcx)); + items + } +} + +/// This is a set collection type that tries very hard to not expose +/// any internal iteration. This is a useful property when trying to +/// uphold the determinism invariants imposed by the query system. +/// +/// This collection type is a good choice for set-like collections the +/// keys of which don't have a semantic ordering. +/// +/// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533) +/// for more information. +#[derive(Debug, Eq, PartialEq, Clone, Encodable, Decodable)] +pub struct UnordSet { + inner: FxHashSet, +} + +impl Default for UnordSet { + fn default() -> Self { + Self { inner: FxHashSet::default() } + } +} + +impl UnordSet { + #[inline] + pub fn new() -> Self { + Self { inner: Default::default() } + } + + #[inline] + pub fn len(&self) -> usize { + self.inner.len() + } + + #[inline] + pub fn insert(&mut self, v: V) -> bool { + self.inner.insert(v) + } + + #[inline] + pub fn contains(&self, v: &Q) -> bool + where + V: Borrow, + Q: Hash + Eq, + { + self.inner.contains(v) + } + + #[inline] + pub fn items<'a>(&'a self) -> UnordItems<&'a V, impl Iterator> { + UnordItems(self.inner.iter()) + } + + #[inline] + pub fn into_items(self) -> UnordItems> { + UnordItems(self.inner.into_iter()) + } + + // We can safely extend this UnordSet from a set of unordered values because that + // won't expose the internal ordering anywhere. + #[inline] + pub fn extend>(&mut self, items: UnordItems) { + self.inner.extend(items.0) + } +} + +impl Extend for UnordSet { + fn extend>(&mut self, iter: T) { + self.inner.extend(iter) + } +} + +impl> HashStable for UnordSet { + #[inline] + fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { + hash_iter_order_independent(self.inner.iter(), hcx, hasher); + } +} + +/// This is a map collection type that tries very hard to not expose +/// any internal iteration. This is a useful property when trying to +/// uphold the determinism invariants imposed by the query system. +/// +/// This collection type is a good choice for map-like collections the +/// keys of which don't have a semantic ordering. +/// +/// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533) +/// for more information. +#[derive(Debug, Eq, PartialEq, Clone, Encodable, Decodable)] +pub struct UnordMap { + inner: FxHashMap, +} + +impl Default for UnordMap { + fn default() -> Self { + Self { inner: FxHashMap::default() } + } +} + +impl Extend<(K, V)> for UnordMap { + fn extend>(&mut self, iter: T) { + self.inner.extend(iter) + } +} + +impl UnordMap { + #[inline] + pub fn len(&self) -> usize { + self.inner.len() + } + + #[inline] + pub fn insert(&mut self, k: K, v: V) -> Option { + self.inner.insert(k, v) + } + + #[inline] + pub fn contains_key(&self, k: &Q) -> bool + where + K: Borrow, + Q: Hash + Eq, + { + self.inner.contains_key(k) + } + + #[inline] + pub fn items<'a>(&'a self) -> UnordItems<(&'a K, &'a V), impl Iterator> { + UnordItems(self.inner.iter()) + } + + #[inline] + pub fn into_items(self) -> UnordItems<(K, V), impl Iterator> { + UnordItems(self.inner.into_iter()) + } + + // We can safely extend this UnordMap from a set of unordered values because that + // won't expose the internal ordering anywhere. + #[inline] + pub fn extend>(&mut self, items: UnordItems<(K, V), I>) { + self.inner.extend(items.0) + } +} + +impl, V: HashStable> HashStable for UnordMap { + #[inline] + fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { + hash_iter_order_independent(self.inner.iter(), hcx, hasher); + } +} + +/// This is a collection type that tries very hard to not expose +/// any internal iteration. This is a useful property when trying to +/// uphold the determinism invariants imposed by the query system. +/// +/// This collection type is a good choice for collections the +/// keys of which don't have a semantic ordering and don't implement +/// `Hash` or `Eq`. +/// +/// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533) +/// for more information. +#[derive(Default, Debug, Eq, PartialEq, Clone, Encodable, Decodable)] +pub struct UnordBag { + inner: Vec, +} + +impl UnordBag { + #[inline] + pub fn new() -> Self { + Self { inner: Default::default() } + } + + #[inline] + pub fn len(&self) -> usize { + self.inner.len() + } + + #[inline] + pub fn push(&mut self, v: V) { + self.inner.push(v); + } + + #[inline] + pub fn items<'a>(&'a self) -> UnordItems<&'a V, impl Iterator> { + UnordItems(self.inner.iter()) + } + + #[inline] + pub fn into_items(self) -> UnordItems> { + UnordItems(self.inner.into_iter()) + } + + // We can safely extend this UnordSet from a set of unordered values because that + // won't expose the internal ordering anywhere. + #[inline] + pub fn extend>(&mut self, items: UnordItems) { + self.inner.extend(items.0) + } +} + +impl Extend for UnordBag { + fn extend>(&mut self, iter: I) { + self.inner.extend(iter) + } +} + +impl> HashStable for UnordBag { + #[inline] + fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { + hash_iter_order_independent(self.inner.iter(), hcx, hasher); + } +} + +fn hash_iter_order_independent< + HCX, + T: HashStable, + I: Iterator + ExactSizeIterator, +>( + mut it: I, + hcx: &mut HCX, + hasher: &mut StableHasher, +) { + let len = it.len(); + len.hash_stable(hcx, hasher); + + match len { + 0 => { + // We're done + } + 1 => { + // No need to instantiate a hasher + it.next().unwrap().hash_stable(hcx, hasher); + } + _ => { + let mut accumulator = Fingerprint::ZERO; + for item in it { + let mut item_hasher = StableHasher::new(); + item.hash_stable(hcx, &mut item_hasher); + let item_fingerprint: Fingerprint = item_hasher.finish(); + accumulator = accumulator.combine_commutative(item_fingerprint); + } + accumulator.hash_stable(hcx, hasher); + } + } +} + +// Do not implement IntoIterator for the collections in this module. +// They only exist to hide iteration order in the first place. +impl !IntoIterator for UnordBag {} +impl !IntoIterator for UnordSet {} +impl !IntoIterator for UnordMap {} +impl !IntoIterator for UnordItems {} diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs index 922833f85806..d3df25907527 100644 --- a/compiler/rustc_hir_analysis/src/check_unused.rs +++ b/compiler/rustc_hir_analysis/src/check_unused.rs @@ -1,5 +1,6 @@ use crate::errors::{ExternCrateNotIdiomatic, UnusedExternCrate}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::unord::UnordSet; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -8,12 +9,12 @@ use rustc_session::lint; use rustc_span::{Span, Symbol}; pub fn check_crate(tcx: TyCtxt<'_>) { - let mut used_trait_imports: FxHashSet = FxHashSet::default(); + let mut used_trait_imports: UnordSet = Default::default(); for item_def_id in tcx.hir().body_owners() { let imports = tcx.used_trait_imports(item_def_id); debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports); - used_trait_imports.extend(imports.iter()); + used_trait_imports.extend(imports.items().copied()); } for &id in tcx.maybe_unused_trait_imports(()) { diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index e862d577573b..959c54866453 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -52,7 +52,7 @@ pub use inherited::{Inherited, InheritedBuilder}; use crate::check::check_fn; use crate::coercion::DynamicCoerceMany; use crate::gather_locals::GatherLocalsVisitor; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::unord::UnordSet; use rustc_errors::{struct_span_err, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::Res; @@ -174,7 +174,7 @@ fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool { } } -fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &FxHashSet { +fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet { &*tcx.typeck(def_id).used_trait_imports } diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index d2847e4bc12a..c94879c9f213 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -96,7 +96,7 @@ macro_rules! arena_types { // since we need to allocate this type on both the `rustc_hir` arena // (during lowering) and the `librustc_middle` arena (for decoding MIR) [decode] asm_template: rustc_ast::InlineAsmTemplatePiece, - [decode] used_trait_imports: rustc_data_structures::fx::FxHashSet, + [decode] used_trait_imports: rustc_data_structures::unord::UnordSet, [decode] is_late_bound_map: rustc_data_structures::fx::FxIndexSet, [decode] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 67c85ef0d3b5..5ee5adc37105 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -912,7 +912,7 @@ rustc_queries! { cache_on_disk_if { true } } - query used_trait_imports(key: LocalDefId) -> &'tcx FxHashSet { + query used_trait_imports(key: LocalDefId) -> &'tcx UnordSet { desc { |tcx| "finding used_trait_imports `{}`", tcx.def_path_str(key.to_def_id()) } cache_on_disk_if { true } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 94e3f3b63c81..3d7e2a0839ab 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -34,6 +34,7 @@ use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, RwLock, WorkerLocal}; +use rustc_data_structures::unord::UnordSet; use rustc_data_structures::vec_map::VecMap; use rustc_errors::{ DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan, @@ -531,7 +532,7 @@ pub struct TypeckResults<'tcx> { /// This is used for warning unused imports. During type /// checking, this `Lrc` should not be cloned: it must have a ref-count /// of 1 so that we can insert things into the set mutably. - pub used_trait_imports: Lrc>, + pub used_trait_imports: Lrc>, /// If any errors occurred while type-checking this body, /// this field will be set to `Some(ErrorGuaranteed)`. diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 9c97ce34f29e..1715837203c2 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -40,6 +40,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; +use rustc_data_structures::unord::UnordSet; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def::DefKind; diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs index a59216501127..8b14ce210a20 100644 --- a/compiler/rustc_query_impl/src/on_disk_cache.rs +++ b/compiler/rustc_query_impl/src/on_disk_cache.rs @@ -1,8 +1,9 @@ use crate::QueryCtxt; -use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; +use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, RwLock}; use rustc_data_structures::unhash::UnhashMap; +use rustc_data_structures::unord::UnordSet; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, StableCrateId, LOCAL_CRATE}; use rustc_hir::definitions::DefPathHash; use rustc_index::vec::{Idx, IndexVec}; @@ -792,7 +793,7 @@ impl<'a, 'tcx> Decodable> for DefId { } } -impl<'a, 'tcx> Decodable> for &'tcx FxHashSet { +impl<'a, 'tcx> Decodable> for &'tcx UnordSet { fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { RefDecodable::decode(d) } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 8232353f915b..642acb1fea9c 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -1,6 +1,7 @@ use rustc_ast::NodeId; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{self, Lrc}; +use rustc_data_structures::unord::UnordSet; use rustc_errors::emitter::{Emitter, EmitterWriter}; use rustc_errors::json::JsonEmitter; use rustc_feature::UnstableFeatures; @@ -288,8 +289,7 @@ pub(crate) fn create_config( providers.typeck_item_bodies = |_, _| {}; // hack so that `used_trait_imports` won't try to call typeck providers.used_trait_imports = |_, _| { - static EMPTY_SET: LazyLock> = - LazyLock::new(FxHashSet::default); + static EMPTY_SET: LazyLock> = LazyLock::new(UnordSet::default); &EMPTY_SET }; // In case typeck does end up being called, don't ICE in case there were name resolution errors From dc53c8f25fb0855c413cbb44041a106dfab9eef1 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 27 Oct 2022 18:32:17 +0400 Subject: [PATCH 132/171] Update tooling --- compiler/rustc_codegen_cranelift/src/base.rs | 6 +- .../rustc_codegen_cranelift/src/constant.rs | 3 +- src/librustdoc/clean/auto_trait.rs | 2 +- .../clippy_lints/src/casts/ptr_as_ptr.rs | 2 +- .../clippy/clippy_lints/src/dereference.rs | 10 +- .../clippy_lints/src/functions/must_use.rs | 2 +- .../clippy/clippy_lints/src/let_if_seq.rs | 2 +- src/tools/clippy/clippy_lints/src/mut_key.rs | 10 +- .../src/needless_pass_by_value.rs | 4 +- .../clippy/clippy_lints/src/non_copy_const.rs | 4 +- .../clippy/clippy_lints/src/question_mark.rs | 2 +- .../src/transmute/transmute_undefined_repr.rs | 165 +++++++++++------- .../src/types/redundant_allocation.rs | 18 +- .../clippy/clippy_lints/src/types/vec_box.rs | 2 +- src/tools/clippy/clippy_utils/src/ty.rs | 4 +- 15 files changed, 137 insertions(+), 99 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index a41b561598f6..1db44502742e 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -770,11 +770,7 @@ fn codegen_stmt<'tcx>( lval.write_cvalue(fx, CValue::by_val(operand, box_layout)); } Rvalue::NullaryOp(null_op, ty) => { - assert!( - lval.layout() - .ty - .is_sized(fx.tcx.at(stmt.source_info.span), ParamEnv::reveal_all()) - ); + assert!(lval.layout().ty.is_sized(fx.tcx, ParamEnv::reveal_all())); let layout = fx.layout_of(fx.monomorphize(ty)); let val = match null_op { NullOp::SizeOf => layout.size.bytes(), diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index d4bc3543b2d1..148b66d959e8 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -5,7 +5,6 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::{ read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar, }; -use rustc_span::DUMMY_SP; use cranelift_module::*; @@ -291,7 +290,7 @@ fn data_id_for_static( let is_mutable = if tcx.is_mutable_static(def_id) { true } else { - !ty.is_freeze(tcx.at(DUMMY_SP), ParamEnv::reveal_all()) + !ty.is_freeze(tcx, ParamEnv::reveal_all()) }; let align = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().align.pref.bytes(); diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index efa9242a4678..764a6d3aa48c 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -148,7 +148,7 @@ where }) .collect(); // We are only interested in case the type *doesn't* implement the Sized trait. - if !ty.is_sized(tcx.at(rustc_span::DUMMY_SP), param_env) { + if !ty.is_sized(tcx, param_env) { // In case `#![no_core]` is used, `sized_trait` returns nothing. if let Some(item) = tcx.lang_items().sized_trait().and_then(|sized_trait_did| { self.generate_for_trait(ty, sized_trait_did, param_env, item_def_id, &f, true) diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs index c2b9253ec35d..b9509ca656f7 100644 --- a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs @@ -26,7 +26,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: Option( cx.typeck_results().node_type(ty.ty.hir_id), binder_args, )) - .is_sized(cx.tcx.at(DUMMY_SP), cx.param_env.without_caller_bounds()), + .is_sized(cx.tcx, cx.param_env.without_caller_bounds()), ) } }, @@ -1005,7 +1005,7 @@ fn binding_ty_auto_deref_stability<'tcx>( cx.typeck_results().node_type(ty.ty.hir_id), binder_args, )) - .is_sized(cx.tcx.at(DUMMY_SP), cx.param_env.without_caller_bounds()), + .is_sized(cx.tcx, cx.param_env.without_caller_bounds()), ), TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err => { Position::ReborrowStable(precedence) @@ -1297,7 +1297,7 @@ impl<'tcx> TyPosition<'tcx> { fn position_for_result(self, cx: &LateContext<'tcx>) -> Position { match (self.position, self.ty) { (Position::ReborrowStable(precedence), Some(ty)) => { - Position::DerefStable(precedence, ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env)) + Position::DerefStable(precedence, ty.is_sized(cx.tcx, cx.param_env)) }, (position, _) => position, } @@ -1348,7 +1348,7 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc | ty::Tuple(_) | ty::Projection(_) => Position::DerefStable( precedence, - ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env.without_caller_bounds()), + ty.is_sized(cx.tcx, cx.param_env.without_caller_bounds()), ) .into(), }; diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index 3064b6c9d22f..922190a87d8c 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -188,7 +188,7 @@ fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &m // primitive types are never mutable ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false, ty::Adt(adt, substs) => { - tys.insert(adt.did()) && !ty.is_freeze(cx.tcx.at(span), cx.param_env) + tys.insert(adt.did()) && !ty.is_freeze(cx.tcx, cx.param_env) || KNOWN_WRAPPER_TYS .iter() .any(|&sym| cx.tcx.is_diagnostic_item(sym, adt.did())) diff --git a/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs index 13071d64441a..db41bc67da1a 100644 --- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs +++ b/src/tools/clippy/clippy_lints/src/let_if_seq.rs @@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq { let span = stmt.span.to(if_.span); let has_interior_mutability = !cx.typeck_results().node_type(canonical_id).is_freeze( - cx.tcx.at(span), + cx.tcx, cx.param_env, ); if has_interior_mutability { return; } diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs index 25d6ca83a94b..1d0744b631c6 100644 --- a/src/tools/clippy/clippy_lints/src/mut_key.rs +++ b/src/tools/clippy/clippy_lints/src/mut_key.rs @@ -136,12 +136,14 @@ fn check_ty<'tcx>(cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) { /// [`Hash`] or [`Ord`]. fn is_interior_mutable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span) -> bool { match *ty.kind() { - Ref(_, inner_ty, mutbl) => mutbl == hir::Mutability::Mut || is_interior_mutable_type(cx, inner_ty, span), + Ref(_, inner_ty, mutbl) => { + mutbl == hir::Mutability::Mut || is_interior_mutable_type(cx, inner_ty, span) + } Slice(inner_ty) => is_interior_mutable_type(cx, inner_ty, span), Array(inner_ty, size) => { size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0) && is_interior_mutable_type(cx, inner_ty, span) - }, + } Tuple(fields) => fields.iter().any(|ty| is_interior_mutable_type(cx, ty, span)), Adt(def, substs) => { // Special case for collections in `std` who's impl of `Hash` or `Ord` delegates to @@ -167,9 +169,9 @@ fn is_interior_mutable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Sp } else { !ty.has_escaping_bound_vars() && cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() - && !ty.is_freeze(cx.tcx.at(span), cx.param_env) + && !ty.is_freeze(cx.tcx, cx.param_env) } - }, + } _ => false, } } diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 9c949a28f44d..b2e9ce5c94d6 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -19,7 +19,7 @@ use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::{self, TypeVisitable}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::kw; -use rustc_span::{sym, Span, DUMMY_SP}; +use rustc_span::{sym, Span}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits; use rustc_trait_selection::traits::misc::can_type_implement_copy; @@ -184,7 +184,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { if !is_self(arg); if !ty.is_mutable_ptr(); if !is_copy(cx, ty); - if ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env); + if ty.is_sized(cx.tcx, cx.param_env); if !allowed_traits.iter().any(|&t| implements_trait(cx, ty, t, &[])); if !implements_borrow_trait; if !all_borrowable_trait; diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index a6742824bc56..671c16953aed 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -20,7 +20,7 @@ use rustc_middle::mir::interpret::{ConstValue, ErrorHandled}; use rustc_middle::ty::adjustment::Adjust; use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{sym, InnerSpan, Span, DUMMY_SP}; +use rustc_span::{sym, InnerSpan, Span}; // FIXME: this is a correctness problem but there's no suitable // warn-by-default category. @@ -136,7 +136,7 @@ fn is_unfrozen<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { // since it works when a pointer indirection involves (`Cell<*const T>`). // Making up a `ParamEnv` where every generic params and assoc types are `Freeze`is another option; // but I'm not sure whether it's a decent way, if possible. - cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && !ty.is_freeze(cx.tcx.at(DUMMY_SP), cx.param_env) + cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && !ty.is_freeze(cx.tcx, cx.param_env) } fn is_value_unfrozen_raw<'tcx>( diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index 328371fd602f..bb86fb3b7d42 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -94,7 +94,7 @@ fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Ex then { let mut applicability = Applicability::MachineApplicable; let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability); - let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx.at(caller.span), cx.param_env) && + let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env) && !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)); let sugg = if let Some(else_inner) = r#else { if eq_expr_value(cx, caller, peel_blocks(else_inner)) { diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs index 1c99a02e6c71..3d4bbbf648c6 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -5,7 +5,6 @@ use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_middle::ty::SubstsRef; use rustc_middle::ty::{self, IntTy, Ty, TypeAndMut, UintTy}; -use rustc_span::DUMMY_SP; #[expect(clippy::too_many_lines)] pub(super) fn check<'tcx>( @@ -28,24 +27,32 @@ pub(super) fn check<'tcx>( // `Repr(C)` <-> unordered type. // If the first field of the `Repr(C)` type matches then the transmute is ok - (ReducedTy::OrderedFields(_, Some(from_sub_ty)), ReducedTy::UnorderedFields(to_sub_ty)) - | (ReducedTy::UnorderedFields(from_sub_ty), ReducedTy::OrderedFields(_, Some(to_sub_ty))) => { + ( + ReducedTy::OrderedFields(_, Some(from_sub_ty)), + ReducedTy::UnorderedFields(to_sub_ty), + ) + | ( + ReducedTy::UnorderedFields(from_sub_ty), + ReducedTy::OrderedFields(_, Some(to_sub_ty)), + ) => { from_ty = from_sub_ty; to_ty = to_sub_ty; continue; - }, - (ReducedTy::OrderedFields(_, Some(from_sub_ty)), ReducedTy::Other(to_sub_ty)) if reduced_tys.to_fat_ptr => { + } + (ReducedTy::OrderedFields(_, Some(from_sub_ty)), ReducedTy::Other(to_sub_ty)) + if reduced_tys.to_fat_ptr => + { from_ty = from_sub_ty; to_ty = to_sub_ty; continue; - }, + } (ReducedTy::Other(from_sub_ty), ReducedTy::OrderedFields(_, Some(to_sub_ty))) if reduced_tys.from_fat_ptr => { from_ty = from_sub_ty; to_ty = to_sub_ty; continue; - }, + } // ptr <-> ptr (ReducedTy::Other(from_sub_ty), ReducedTy::Other(to_sub_ty)) @@ -55,19 +62,19 @@ pub(super) fn check<'tcx>( from_ty = from_sub_ty; to_ty = to_sub_ty; continue; - }, + } // fat ptr <-> (*size, *size) (ReducedTy::Other(_), ReducedTy::UnorderedFields(to_ty)) if reduced_tys.from_fat_ptr && is_size_pair(to_ty) => { return false; - }, + } (ReducedTy::UnorderedFields(from_ty), ReducedTy::Other(_)) if reduced_tys.to_fat_ptr && is_size_pair(from_ty) => { return false; - }, + } // fat ptr -> some struct | some struct -> fat ptr (ReducedTy::Other(_), _) if reduced_tys.from_fat_ptr => { @@ -78,12 +85,14 @@ pub(super) fn check<'tcx>( &format!("transmute from `{from_ty_orig}` which has an undefined layout"), |diag| { if from_ty_orig.peel_refs() != from_ty.peel_refs() { - diag.note(&format!("the contained type `{from_ty}` has an undefined layout")); + diag.note(&format!( + "the contained type `{from_ty}` has an undefined layout" + )); } }, ); return true; - }, + } (_, ReducedTy::Other(_)) if reduced_tys.to_fat_ptr => { span_lint_and_then( cx, @@ -92,14 +101,18 @@ pub(super) fn check<'tcx>( &format!("transmute to `{to_ty_orig}` which has an undefined layout"), |diag| { if to_ty_orig.peel_refs() != to_ty.peel_refs() { - diag.note(&format!("the contained type `{to_ty}` has an undefined layout")); + diag.note(&format!( + "the contained type `{to_ty}` has an undefined layout" + )); } }, ); return true; - }, + } - (ReducedTy::UnorderedFields(from_ty), ReducedTy::UnorderedFields(to_ty)) if from_ty != to_ty => { + (ReducedTy::UnorderedFields(from_ty), ReducedTy::UnorderedFields(to_ty)) + if from_ty != to_ty => + { let same_adt_did = if let (ty::Adt(from_def, from_subs), ty::Adt(to_def, to_subs)) = (from_ty.kind(), to_ty.kind()) && from_def == to_def @@ -126,19 +139,25 @@ pub(super) fn check<'tcx>( )); } else { if from_ty_orig.peel_refs() != from_ty { - diag.note(&format!("the contained type `{from_ty}` has an undefined layout")); + diag.note(&format!( + "the contained type `{from_ty}` has an undefined layout" + )); } if to_ty_orig.peel_refs() != to_ty { - diag.note(&format!("the contained type `{to_ty}` has an undefined layout")); + diag.note(&format!( + "the contained type `{to_ty}` has an undefined layout" + )); } } }, ); return true; - }, + } ( ReducedTy::UnorderedFields(from_ty), - ReducedTy::Other(_) | ReducedTy::OrderedFields(..) | ReducedTy::TypeErasure { raw_ptr_only: true }, + ReducedTy::Other(_) + | ReducedTy::OrderedFields(..) + | ReducedTy::TypeErasure { raw_ptr_only: true }, ) => { span_lint_and_then( cx, @@ -147,14 +166,18 @@ pub(super) fn check<'tcx>( &format!("transmute from `{from_ty_orig}` which has an undefined layout"), |diag| { if from_ty_orig.peel_refs() != from_ty { - diag.note(&format!("the contained type `{from_ty}` has an undefined layout")); + diag.note(&format!( + "the contained type `{from_ty}` has an undefined layout" + )); } }, ); return true; - }, + } ( - ReducedTy::Other(_) | ReducedTy::OrderedFields(..) | ReducedTy::TypeErasure { raw_ptr_only: true }, + ReducedTy::Other(_) + | ReducedTy::OrderedFields(..) + | ReducedTy::TypeErasure { raw_ptr_only: true }, ReducedTy::UnorderedFields(to_ty), ) => { span_lint_and_then( @@ -164,19 +187,25 @@ pub(super) fn check<'tcx>( &format!("transmute into `{to_ty_orig}` which has an undefined layout"), |diag| { if to_ty_orig.peel_refs() != to_ty { - diag.note(&format!("the contained type `{to_ty}` has an undefined layout")); + diag.note(&format!( + "the contained type `{to_ty}` has an undefined layout" + )); } }, ); return true; - }, + } ( - ReducedTy::OrderedFields(..) | ReducedTy::Other(_) | ReducedTy::TypeErasure { raw_ptr_only: true }, - ReducedTy::OrderedFields(..) | ReducedTy::Other(_) | ReducedTy::TypeErasure { raw_ptr_only: true }, + ReducedTy::OrderedFields(..) + | ReducedTy::Other(_) + | ReducedTy::TypeErasure { raw_ptr_only: true }, + ReducedTy::OrderedFields(..) + | ReducedTy::Other(_) + | ReducedTy::TypeErasure { raw_ptr_only: true }, ) | (ReducedTy::UnorderedFields(_), ReducedTy::UnorderedFields(_)) => { break; - }, + } } } @@ -194,42 +223,38 @@ struct ReducedTys<'tcx> { } /// Remove references so long as both types are references. -fn reduce_refs<'tcx>(cx: &LateContext<'tcx>, mut from_ty: Ty<'tcx>, mut to_ty: Ty<'tcx>) -> ReducedTys<'tcx> { +fn reduce_refs<'tcx>( + cx: &LateContext<'tcx>, + mut from_ty: Ty<'tcx>, + mut to_ty: Ty<'tcx>, +) -> ReducedTys<'tcx> { let mut from_raw_ptr = false; let mut to_raw_ptr = false; - let (from_fat_ptr, to_fat_ptr) = loop { - break match (from_ty.kind(), to_ty.kind()) { - ( - &(ty::Ref(_, from_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: from_sub_ty, .. })), - &(ty::Ref(_, to_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: to_sub_ty, .. })), - ) => { - from_raw_ptr = matches!(*from_ty.kind(), ty::RawPtr(_)); - from_ty = from_sub_ty; - to_raw_ptr = matches!(*to_ty.kind(), ty::RawPtr(_)); - to_ty = to_sub_ty; - continue; - }, - (&(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })), _) - if !unsized_ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env) => - { - (true, false) - }, - (_, &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. }))) - if !unsized_ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env) => - { - (false, true) - }, - _ => (false, false), + let (from_fat_ptr, to_fat_ptr) = + loop { + break match (from_ty.kind(), to_ty.kind()) { + ( + &(ty::Ref(_, from_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: from_sub_ty, .. })), + &(ty::Ref(_, to_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: to_sub_ty, .. })), + ) => { + from_raw_ptr = matches!(*from_ty.kind(), ty::RawPtr(_)); + from_ty = from_sub_ty; + to_raw_ptr = matches!(*to_ty.kind(), ty::RawPtr(_)); + to_ty = to_sub_ty; + continue; + } + ( + &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })), + _, + ) if !unsized_ty.is_sized(cx.tcx, cx.param_env) => (true, false), + ( + _, + &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })), + ) if !unsized_ty.is_sized(cx.tcx, cx.param_env) => (false, true), + _ => (false, false), + }; }; - }; - ReducedTys { - from_ty, - to_ty, - from_raw_ptr, - to_raw_ptr, - from_fat_ptr, - to_fat_ptr, - } + ReducedTys { from_ty, to_ty, from_raw_ptr, to_raw_ptr, from_fat_ptr, to_fat_ptr } } enum ReducedTy<'tcx> { @@ -252,11 +277,11 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> return match *ty.kind() { ty::Array(sub_ty, _) if matches!(sub_ty.kind(), ty::Int(_) | ty::Uint(_)) => { ReducedTy::TypeErasure { raw_ptr_only: false } - }, + } ty::Array(sub_ty, _) | ty::Slice(sub_ty) => { ty = sub_ty; continue; - }, + } ty::Tuple(args) if args.is_empty() => ReducedTy::TypeErasure { raw_ptr_only: false }, ty::Tuple(args) => { let mut iter = args.iter(); @@ -268,7 +293,7 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> continue; } ReducedTy::UnorderedFields(ty) - }, + } ty::Adt(def, substs) if def.is_struct() => { let mut iter = def .non_enum_variant() @@ -287,10 +312,12 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> } else { ReducedTy::UnorderedFields(ty) } - }, - ty::Adt(def, _) if def.is_enum() && (def.variants().is_empty() || is_c_void(cx, ty)) => { + } + ty::Adt(def, _) + if def.is_enum() && (def.variants().is_empty() || is_c_void(cx, ty)) => + { ReducedTy::TypeErasure { raw_ptr_only: false } - }, + } // TODO: Check if the conversion to or from at least one of a union's fields is valid. ty::Adt(def, _) if def.is_union() => ReducedTy::TypeErasure { raw_ptr_only: false }, ty::Foreign(_) | ty::Param(_) => ReducedTy::TypeErasure { raw_ptr_only: false }, @@ -329,7 +356,11 @@ fn same_except_params<'tcx>(subs1: SubstsRef<'tcx>, subs2: SubstsRef<'tcx>) -> b for (ty1, ty2) in subs1.types().zip(subs2.types()).filter(|(ty1, ty2)| ty1 != ty2) { match (ty1.kind(), ty2.kind()) { (ty::Param(_), _) | (_, ty::Param(_)) => (), - (ty::Adt(adt1, subs1), ty::Adt(adt2, subs2)) if adt1 == adt2 && same_except_params(subs1, subs2) => (), + (ty::Adt(adt1, subs1), ty::Adt(adt2, subs2)) + if adt1 == adt2 && same_except_params(subs1, subs2) => + { + () + } _ => return false, } } diff --git a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs index 7883353e3fef..2b964b64a330 100644 --- a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs +++ b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs @@ -9,7 +9,12 @@ use rustc_span::symbol::sym; use super::{utils, REDUNDANT_ALLOCATION}; -pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool { +pub(super) fn check( + cx: &LateContext<'_>, + hir_ty: &hir::Ty<'_>, + qpath: &QPath<'_>, + def_id: DefId, +) -> bool { let mut applicability = Applicability::MaybeIncorrect; let outer_sym = if Some(def_id) == cx.tcx.lang_items().owned_box() { "Box" @@ -29,7 +34,12 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ hir_ty.span, &format!("usage of `{outer_sym}<{generic_snippet}>`"), |diag| { - diag.span_suggestion(hir_ty.span, "try", format!("{generic_snippet}"), applicability); + diag.span_suggestion( + hir_ty.span, + "try", + format!("{generic_snippet}"), + applicability, + ); diag.note(&format!( "`{generic_snippet}` is already a pointer, `{outer_sym}<{generic_snippet}>` allocates a pointer on the heap" )); @@ -55,11 +65,11 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ // Reallocation of a fat pointer causes it to become thin. `hir_ty_to_ty` is safe to use // here because `mod.rs` guarantees this lint is only run on types outside of bodies and // is not run on locals. - if !hir_ty_to_ty(cx.tcx, ty).is_sized(cx.tcx.at(ty.span), cx.param_env) { + if !hir_ty_to_ty(cx.tcx, ty).is_sized(cx.tcx, cx.param_env) { return false; } ty.span - }, + } None => return false, }; if inner_sym == outer_sym { diff --git a/src/tools/clippy/clippy_lints/src/types/vec_box.rs b/src/tools/clippy/clippy_lints/src/types/vec_box.rs index 6c329d8cdf19..9ad2cb853d39 100644 --- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs @@ -40,7 +40,7 @@ pub(super) fn check( }); let ty_ty = hir_ty_to_ty(cx.tcx, boxed_ty); if !ty_ty.has_escaping_bound_vars(); - if ty_ty.is_sized(cx.tcx.at(ty.span), cx.param_env); + if ty_ty.is_sized(cx.tcx, cx.param_env); if let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes()); if ty_ty_size <= box_size_threshold; then { diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 3b5a9ba83568..4e024ce40179 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -18,7 +18,7 @@ use rustc_middle::ty::{ }; use rustc_middle::ty::{GenericArg, GenericArgKind}; use rustc_span::symbol::Ident; -use rustc_span::{sym, Span, Symbol, DUMMY_SP}; +use rustc_span::{sym, Span, Symbol}; use rustc_target::abi::{Size, VariantIdx}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::query::normalize::AtExt; @@ -28,7 +28,7 @@ use crate::{match_def_path, path_res, paths}; // Checks if the given type implements copy. pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - ty.is_copy_modulo_regions(cx.tcx.at(DUMMY_SP), cx.param_env) + ty.is_copy_modulo_regions(cx.tcx, cx.param_env) } /// This checks whether a given type is known to implement Debug. From f4ac137f3c7952c3b8e8278916ac030a6c3a9b6e Mon Sep 17 00:00:00 2001 From: Rageking8 Date: Thu, 27 Oct 2022 22:56:20 +0800 Subject: [PATCH 133/171] add test for issue 36007 --- src/test/ui/coercion/issue-36007.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/test/ui/coercion/issue-36007.rs diff --git a/src/test/ui/coercion/issue-36007.rs b/src/test/ui/coercion/issue-36007.rs new file mode 100644 index 000000000000..78812df870d0 --- /dev/null +++ b/src/test/ui/coercion/issue-36007.rs @@ -0,0 +1,20 @@ +// check-pass +#![feature(coerce_unsized, unsize)] + +use std::marker::Unsize; +use std::ops::CoerceUnsized; + +struct Foo(Box); + +impl CoerceUnsized> for Foo where T: Unsize {} + +struct Bar; + +trait Baz {} + +impl Baz for Bar {} + +fn main() { + let foo = Foo(Box::new(Bar)); + let foobar: Foo = foo; +} From c8c49710732a8cf9a71b7eed75d340e5f99383b8 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 27 Oct 2022 19:10:33 +0400 Subject: [PATCH 134/171] Update miri --- src/tools/miri/src/stacked_borrows/mod.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/tools/miri/src/stacked_borrows/mod.rs b/src/tools/miri/src/stacked_borrows/mod.rs index cc27b71eb560..5ec787dd4411 100644 --- a/src/tools/miri/src/stacked_borrows/mod.rs +++ b/src/tools/miri/src/stacked_borrows/mod.rs @@ -16,7 +16,6 @@ use rustc_middle::ty::{ layout::{HasParamEnv, LayoutOf}, Ty, }; -use rustc_span::DUMMY_SP; use rustc_target::abi::Abi; use rustc_target::abi::Size; use smallvec::SmallVec; @@ -714,12 +713,12 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' let mut kind_str = format!("{kind}"); match kind { RefKind::Unique { two_phase: false } - if !ty.is_unpin(this.tcx.at(DUMMY_SP), this.param_env()) => + if !ty.is_unpin(*this.tcx, this.param_env()) => { write!(kind_str, " (!Unpin pointee type {ty})").unwrap() }, RefKind::Shared - if !ty.is_freeze(this.tcx.at(DUMMY_SP), this.param_env()) => + if !ty.is_freeze(*this.tcx, this.param_env()) => { write!(kind_str, " (!Freeze pointee type {ty})").unwrap() }, @@ -834,7 +833,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' // There could be existing unique pointers reborrowed from them that should remain valid! let perm = match kind { RefKind::Unique { two_phase: false } - if place.layout.ty.is_unpin(this.tcx.at(DUMMY_SP), this.param_env()) => + if place.layout.ty.is_unpin(*this.tcx, this.param_env()) => { // Only if the type is unpin do we actually enforce uniqueness Permission::Unique From dce44faf5b11cc9dd4491d7ed9211455f81bbdf2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 27 Oct 2022 16:15:11 +0000 Subject: [PATCH 135/171] Revert "Make ClosureOutlivesRequirement not rely on an unresolved type" This reverts commit a6b5f95fb028f9feb4a2957c06b35035be2c6155. --- .../rustc_borrowck/src/constraints/mod.rs | 2 +- .../src/diagnostics/conflict_errors.rs | 10 ++++---- .../src/diagnostics/explain_borrow.rs | 12 +++++----- .../src/diagnostics/outlives_suggestion.rs | 2 +- .../src/diagnostics/region_errors.rs | 24 +++++++------------ .../rustc_borrowck/src/region_infer/mod.rs | 10 ++++---- .../src/type_check/canonical.rs | 10 ++++---- .../src/type_check/constraint_conversion.rs | 8 +++---- compiler/rustc_borrowck/src/type_check/mod.rs | 19 ++++++++++----- .../src/type_check/relate_tys.rs | 8 +++---- .../src/infer/canonical/query_response.rs | 2 +- compiler/rustc_infer/src/infer/mod.rs | 2 +- .../src/infer/outlives/obligations.rs | 8 +++---- compiler/rustc_middle/src/infer/canonical.rs | 6 +++-- compiler/rustc_middle/src/mir/mod.rs | 2 +- compiler/rustc_middle/src/mir/query.rs | 16 +++++-------- compiler/rustc_middle/src/traits/mod.rs | 2 +- .../ui/async-await/issues/issue-72312.stderr | 13 +++++----- ...er-to-static-comparing-against-free.stderr | 15 ++++++------ .../user-annotations/adt-nullary-enums.stderr | 16 ++++++------- 20 files changed, 93 insertions(+), 94 deletions(-) diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs index 58aeb43ef976..df04128135b8 100644 --- a/compiler/rustc_borrowck/src/constraints/mod.rs +++ b/compiler/rustc_borrowck/src/constraints/mod.rs @@ -92,7 +92,7 @@ pub struct OutlivesConstraint<'tcx> { pub span: Span, /// What caused this constraint? - pub category: ConstraintCategory, + pub category: ConstraintCategory<'tcx>, /// Variance diagnostic information pub variance_info: VarianceDiagInfo<'tcx>, diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 3f5d9fb62066..583bc2e281da 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -983,7 +983,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err: &mut Diagnostic, location: Location, issued_borrow: &BorrowData<'tcx>, - explanation: BorrowExplanation, + explanation: BorrowExplanation<'tcx>, ) { let used_in_call = matches!( explanation, @@ -1333,7 +1333,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow: &BorrowData<'tcx>, drop_span: Span, borrow_spans: UseSpans<'tcx>, - explanation: BorrowExplanation, + explanation: BorrowExplanation<'tcx>, ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { debug!( "report_local_value_does_not_live_long_enough(\ @@ -1539,7 +1539,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { drop_span: Span, borrow_spans: UseSpans<'tcx>, proper_span: Span, - explanation: BorrowExplanation, + explanation: BorrowExplanation<'tcx>, ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } = explanation @@ -1653,7 +1653,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow: &BorrowData<'tcx>, borrow_span: Span, return_span: Span, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, opt_place_desc: Option<&String>, ) -> Option> { let return_kind = match category { @@ -1748,7 +1748,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { use_span: UseSpans<'tcx>, var_span: Span, fr_name: &RegionName, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, constraint_span: Span, captured_var: &str, ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 545237bb3920..582d683dd359 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -21,7 +21,7 @@ use crate::{ use super::{find_use, RegionName, UseSpans}; #[derive(Debug)] -pub(crate) enum BorrowExplanation { +pub(crate) enum BorrowExplanation<'tcx> { UsedLater(LaterUseKind, Span, Option), UsedLaterInLoop(LaterUseKind, Span, Option), UsedLaterWhenDropped { @@ -30,7 +30,7 @@ pub(crate) enum BorrowExplanation { should_note_order: bool, }, MustBeValidFor { - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, from_closure: bool, span: Span, region_name: RegionName, @@ -49,7 +49,7 @@ pub(crate) enum LaterUseKind { Other, } -impl<'tcx> BorrowExplanation { +impl<'tcx> BorrowExplanation<'tcx> { pub(crate) fn is_explained(&self) -> bool { !matches!(self, BorrowExplanation::Unexplained) } @@ -284,7 +284,7 @@ impl<'tcx> BorrowExplanation { fn add_lifetime_bound_suggestion_to_diagnostic( &self, err: &mut Diagnostic, - category: &ConstraintCategory, + category: &ConstraintCategory<'tcx>, span: Span, region_name: &RegionName, ) { @@ -316,7 +316,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &self, borrow_region: RegionVid, outlived_region: RegionVid, - ) -> (ConstraintCategory, bool, Span, Option, Vec) { + ) -> (ConstraintCategory<'tcx>, bool, Span, Option, Vec) { let (blame_constraint, extra_info) = self.regioncx.best_blame_constraint( borrow_region, NllRegionVariableOrigin::FreeRegion, @@ -348,7 +348,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location: Location, borrow: &BorrowData<'tcx>, kind_place: Option<(WriteKind, Place<'tcx>)>, - ) -> BorrowExplanation { + ) -> BorrowExplanation<'tcx> { let regioncx = &self.regioncx; let body: &Body<'_> = &self.body; let tcx = self.infcx.tcx; diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index 245ea07d120b..35c3df768995 100644 --- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -161,7 +161,7 @@ impl OutlivesSuggestionBuilder { pub(crate) fn intermediate_suggestion( &mut self, mbcx: &MirBorrowckCtxt<'_, '_>, - errci: &ErrorConstraintInfo, + errci: &ErrorConstraintInfo<'_>, diag: &mut Diagnostic, ) { // Emit an intermediate note. diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index b619537f3176..15230718dc0d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -2,7 +2,6 @@ #![deny(rustc::diagnostic_outside_of_impl)] //! Error reporting machinery for lifetime errors. -use either::Either; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; use rustc_hir::def_id::DefId; @@ -17,7 +16,7 @@ use rustc_infer::infer::{ NllRegionVariableOrigin, RelateParamBound, }; use rustc_middle::hir::place::PlaceBase; -use rustc_middle::mir::{ConstraintCategory, ReturnConstraint, TerminatorKind}; +use rustc_middle::mir::{ConstraintCategory, ReturnConstraint}; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::Region; use rustc_middle::ty::TypeVisitor; @@ -40,7 +39,7 @@ use crate::{ MirBorrowckCtxt, }; -impl ConstraintDescription for ConstraintCategory { +impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> { fn description(&self) -> &'static str { // Must end with a space. Allows for empty names to be provided. match self { @@ -116,7 +115,7 @@ pub(crate) enum RegionErrorKind<'tcx> { /// Information about the various region constraints involved in a borrow checker error. #[derive(Clone, Debug)] -pub struct ErrorConstraintInfo { +pub struct ErrorConstraintInfo<'tcx> { // fr: outlived_fr pub(super) fr: RegionVid, pub(super) fr_is_local: bool, @@ -124,7 +123,7 @@ pub struct ErrorConstraintInfo { pub(super) outlived_fr_is_local: bool, // Category and span for best blame constraint - pub(super) category: ConstraintCategory, + pub(super) category: ConstraintCategory<'tcx>, pub(super) span: Span, } @@ -499,7 +498,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// ``` fn report_fnmut_error( &self, - errci: &ErrorConstraintInfo, + errci: &ErrorConstraintInfo<'tcx>, kind: ReturnConstraint, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let ErrorConstraintInfo { outlived_fr, span, .. } = errci; @@ -572,7 +571,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn report_escaping_data_error( &self, - errci: &ErrorConstraintInfo, + errci: &ErrorConstraintInfo<'tcx>, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let ErrorConstraintInfo { span, category, .. } = errci; @@ -676,7 +675,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// ``` fn report_general_error( &self, - errci: &ErrorConstraintInfo, + errci: &ErrorConstraintInfo<'tcx>, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let ErrorConstraintInfo { fr, @@ -789,7 +788,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { diag: &mut Diagnostic, f: Region<'tcx>, o: Region<'tcx>, - category: &ConstraintCategory, + category: &ConstraintCategory<'tcx>, ) { if !o.is_static() { return; @@ -797,12 +796,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let tcx = self.infcx.tcx; - let instance = - if let ConstraintCategory::CallArgument(location) = category - && let Either::Right(term) = self.body.stmt_at(*location) - && let TerminatorKind::Call { func, .. } = &term.kind - { - let func_ty = func.ty(self.body, tcx); + let instance = if let ConstraintCategory::CallArgument(Some(func_ty)) = category { let (fn_did, substs) = match func_ty.kind() { ty::FnDef(fn_did, substs) => (fn_did, substs), _ => return, diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 85b9bde2c819..8b63294fbab0 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -91,7 +91,7 @@ pub struct RegionInferenceContext<'tcx> { /// Map closure bounds to a `Span` that should be used for error reporting. closure_bounds_mapping: - FxHashMap>, + FxHashMap, Span)>>, /// Map universe indexes to information on why we created it. universe_causes: FxHashMap>, @@ -267,7 +267,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { member_constraints_in: MemberConstraintSet<'tcx, RegionVid>, closure_bounds_mapping: FxHashMap< Location, - FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>, + FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>, >, universe_causes: FxHashMap>, type_tests: Vec>, @@ -1807,7 +1807,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { pub(crate) fn retrieve_closure_constraint_info( &self, constraint: OutlivesConstraint<'tcx>, - ) -> Option<(ConstraintCategory, Span)> { + ) -> Option<(ConstraintCategory<'tcx>, Span)> { match constraint.locations { Locations::All(_) => None, Locations::Single(loc) => { @@ -1822,7 +1822,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { fr1: RegionVid, fr1_origin: NllRegionVariableOrigin, fr2: RegionVid, - ) -> (ConstraintCategory, ObligationCause<'tcx>) { + ) -> (ConstraintCategory<'tcx>, ObligationCause<'tcx>) { let BlameConstraint { category, cause, .. } = self .best_blame_constraint(fr1, fr1_origin, |r| self.provides_universal_region(r, fr1, fr2)) .0; @@ -2362,7 +2362,7 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx #[derive(Clone, Debug)] pub struct BlameConstraint<'tcx> { - pub category: ConstraintCategory, + pub category: ConstraintCategory<'tcx>, pub from_closure: bool, pub cause: ObligationCause<'tcx>, pub variance_info: ty::VarianceDiagInfo<'tcx>, diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 459ecfe17e3e..a581726a15c9 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -28,7 +28,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { pub(super) fn fully_perform_op( &mut self, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, op: Op, ) -> Fallible where @@ -85,7 +85,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { &mut self, trait_ref: ty::TraitRef<'tcx>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) { self.prove_predicate( ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate { @@ -124,7 +124,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { &mut self, predicates: impl IntoIterator>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) { for predicate in predicates { let predicate = predicate.to_predicate(self.tcx()); @@ -139,7 +139,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { &mut self, predicate: ty::Predicate<'tcx>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) { let param_env = self.param_env; self.fully_perform_op( @@ -164,7 +164,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { &mut self, value: T, location: impl NormalizeLocation, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) -> T where T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx, diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index d7e5a118a2e0..d5bfc2f52082 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -37,7 +37,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, locations: Locations, span: Span, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, constraints: &'a mut MirTypeckRegionConstraints<'tcx>, } @@ -50,7 +50,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, locations: Locations, span: Span, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, constraints: &'a mut MirTypeckRegionConstraints<'tcx>, ) -> Self { Self { @@ -175,7 +175,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { &mut self, sup: ty::RegionVid, sub: ty::RegionVid, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) { let category = match self.category { ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation => category, @@ -203,7 +203,7 @@ impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<' _origin: SubregionOrigin<'tcx>, a: ty::Region<'tcx>, b: ty::Region<'tcx>, - constraint_category: ConstraintCategory, + constraint_category: ConstraintCategory<'tcx>, ) { let b = self.to_region_vid(b); let a = self.to_region_vid(a); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 00cacd515a1e..dc0f0e7cd3c4 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -942,7 +942,7 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> { pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>, pub(crate) closure_bounds_mapping: - FxHashMap>, + FxHashMap, Span)>>, pub(crate) universe_causes: FxHashMap>, @@ -1133,7 +1133,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { fn push_region_constraints( &mut self, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, data: &QueryRegionConstraints<'tcx>, ) { debug!("constraints generated: {:#?}", data); @@ -1158,7 +1158,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { sub: Ty<'tcx>, sup: Ty<'tcx>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) -> Fallible<()> { // Use this order of parameters because the sup type is usually the // "expected" type in diagnostics. @@ -1171,7 +1171,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { expected: Ty<'tcx>, found: Ty<'tcx>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) -> Fallible<()> { self.relate_types(expected, ty::Variance::Invariant, found, locations, category) } @@ -1183,7 +1183,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { v: ty::Variance, user_ty: &UserTypeProjection, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) -> Fallible<()> { let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty; let mut curr_projected_ty = PlaceTy::from_ty(annotated_type); @@ -1618,12 +1618,19 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { span_mirbug!(self, term, "call to {:?} with wrong # of args", sig); } + let func_ty = if let TerminatorKind::Call { func, .. } = &term.kind { + Some(func.ty(body, self.infcx.tcx)) + } else { + None + }; + debug!(?func_ty); + for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() { let op_arg_ty = op_arg.ty(body, self.tcx()); let op_arg_ty = self.normalize(op_arg_ty, term_location); let category = if from_hir_call { - ConstraintCategory::CallArgument(term_location) + ConstraintCategory::CallArgument(func_ty) } else { ConstraintCategory::Boring }; diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index b53360ea61bb..c97a6a1a6587 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -28,7 +28,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { v: ty::Variance, b: Ty<'tcx>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) -> Fallible<()> { TypeRelating::new( self.infcx, @@ -45,7 +45,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { a: ty::SubstsRef<'tcx>, b: ty::SubstsRef<'tcx>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) -> Fallible<()> { TypeRelating::new( self.infcx, @@ -64,7 +64,7 @@ struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { locations: Locations, /// What category do we assign the resulting `'a: 'b` relationships? - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, /// Information so that error reporting knows what types we are relating /// when reporting a bound region error. @@ -75,7 +75,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { fn new( type_checker: &'me mut TypeChecker<'bccx, 'tcx>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, universe_info: UniverseInfo<'tcx>, ) -> Self { Self { type_checker, locations, category, universe_info } diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 608b5cc8756a..eb0135d76f1e 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -632,7 +632,7 @@ impl<'tcx> InferCtxt<'tcx> { /// creates query region constraints. pub fn make_query_region_constraints<'tcx>( tcx: TyCtxt<'tcx>, - outlives_obligations: impl Iterator, ty::Region<'tcx>, ConstraintCategory)>, + outlives_obligations: impl Iterator, ty::Region<'tcx>, ConstraintCategory<'tcx>)>, region_constraints: &RegionConstraintData<'tcx>, ) -> QueryRegionConstraints<'tcx> { let RegionConstraintData { constraints, verifys, givens, member_constraints } = diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 7e2ea6c0e269..ffb020398b85 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -425,7 +425,7 @@ pub enum SubregionOrigin<'tcx> { static_assert_size!(SubregionOrigin<'_>, 32); impl<'tcx> SubregionOrigin<'tcx> { - pub fn to_constraint_category(&self) -> ConstraintCategory { + pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> { match self { Self::Subtype(type_trace) => type_trace.cause.to_constraint_category(), Self::AscribeUserTypeProvePredicate(span) => ConstraintCategory::Predicate(*span), diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 5ebf80b7b748..6ca884799aa6 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -210,7 +210,7 @@ pub trait TypeOutlivesDelegate<'tcx> { origin: SubregionOrigin<'tcx>, a: ty::Region<'tcx>, b: ty::Region<'tcx>, - constraint_category: ConstraintCategory, + constraint_category: ConstraintCategory<'tcx>, ); fn push_verify( @@ -259,7 +259,7 @@ where origin: infer::SubregionOrigin<'tcx>, ty: Ty<'tcx>, region: ty::Region<'tcx>, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) { assert!(!ty.has_escaping_bound_vars()); @@ -273,7 +273,7 @@ where origin: infer::SubregionOrigin<'tcx>, components: &[Component<'tcx>], region: ty::Region<'tcx>, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) { for component in components.iter() { let origin = origin.clone(); @@ -529,7 +529,7 @@ impl<'cx, 'tcx> TypeOutlivesDelegate<'tcx> for &'cx InferCtxt<'tcx> { origin: SubregionOrigin<'tcx>, a: ty::Region<'tcx>, b: ty::Region<'tcx>, - _constraint_category: ConstraintCategory, + _constraint_category: ConstraintCategory<'tcx>, ) { self.sub_regions(origin, a, b) } diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index f4f1d82c3b8d..d3cf519b633c 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -302,8 +302,10 @@ impl<'tcx, V> Canonical<'tcx, V> { } } -pub type QueryOutlivesConstraint<'tcx> = - (ty::Binder<'tcx, ty::OutlivesPredicate, Region<'tcx>>>, ConstraintCategory); +pub type QueryOutlivesConstraint<'tcx> = ( + ty::Binder<'tcx, ty::OutlivesPredicate, Region<'tcx>>>, + ConstraintCategory<'tcx>, +); TrivialTypeTraversalAndLiftImpls! { for <'tcx> { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 3b80af184be4..79db35a764a8 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2904,7 +2904,7 @@ fn pretty_print_const_value<'tcx>( /// `Location` represents the position of the start of the statement; or, if /// `statement_index` equals the number of statements, then the start of the /// terminator. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable, TyEncodable, TyDecodable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)] pub struct Location { /// The block that the location is within. pub block: BasicBlock, diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 1d847d8f3d31..efd7357afc46 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -15,7 +15,7 @@ use smallvec::SmallVec; use std::cell::Cell; use std::fmt::{self, Debug}; -use super::{Field, Location, SourceInfo}; +use super::{Field, SourceInfo}; #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] pub enum UnsafetyViolationKind { @@ -314,12 +314,12 @@ pub struct ClosureOutlivesRequirement<'tcx> { pub blame_span: Span, // ... due to this reason. - pub category: ConstraintCategory, + pub category: ConstraintCategory<'tcx>, } // Make sure this enum doesn't unintentionally grow #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(ConstraintCategory, 16); +rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16); /// Outlives-constraints can be categorized to determine whether and why they /// are interesting (for error reporting). Order of variants indicates sort @@ -327,8 +327,8 @@ rustc_data_structures::static_assert_size!(ConstraintCategory, 16); /// /// See also `rustc_const_eval::borrow_check::constraints`. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] -#[derive(TyEncodable, TyDecodable, HashStable)] -pub enum ConstraintCategory { +#[derive(TyEncodable, TyDecodable, HashStable, Lift, TypeVisitable, TypeFoldable)] +pub enum ConstraintCategory<'tcx> { Return(ReturnConstraint), Yield, UseAsConst, @@ -342,7 +342,7 @@ pub enum ConstraintCategory { ClosureBounds, /// Contains the function type if available. - CallArgument(Location), + CallArgument(Option>), CopyBound, SizedBound, Assignment, @@ -368,10 +368,6 @@ pub enum ConstraintCategory { Internal, } -TrivialTypeTraversalAndLiftImpls! { - ConstraintCategory, -} - #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] #[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)] pub enum ReturnConstraint { diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 3adc2e1b73e4..e73d44bbb36c 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -185,7 +185,7 @@ impl<'tcx> ObligationCause<'tcx> { self } - pub fn to_constraint_category(&self) -> ConstraintCategory { + pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> { match self.code() { MatchImpl(cause, _) => cause.to_constraint_category(), AscribeUserTypeProvePredicate(predicate_span) => { diff --git a/src/test/ui/async-await/issues/issue-72312.stderr b/src/test/ui/async-await/issues/issue-72312.stderr index 5e5a980adb9f..aa947b690036 100644 --- a/src/test/ui/async-await/issues/issue-72312.stderr +++ b/src/test/ui/async-await/issues/issue-72312.stderr @@ -1,5 +1,5 @@ error[E0521]: borrowed data escapes outside of associated function - --> $DIR/issue-72312.rs:12:24 + --> $DIR/issue-72312.rs:12:9 | LL | pub async fn start(&self) { | ----- @@ -7,17 +7,16 @@ LL | pub async fn start(&self) { | `self` is a reference that is only valid in the associated function body | let's call the lifetime of this reference `'1` ... -LL | require_static(async move { - | ________________________^ +LL | / require_static(async move { LL | | LL | | LL | | LL | | &self; LL | | }); - | | ^ - | | | - | |_________`self` escapes the associated function body here - | argument requires that `'1` must outlive `'static` + | | ^ + | | | + | |__________`self` escapes the associated function body here + | argument requires that `'1` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index da4bc499c7e5..01293379700d 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -53,14 +53,15 @@ LL | fn case2() { error[E0597]: `a` does not live long enough --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:30:26 | -LL | let cell = Cell::new(&a); - | ----------^^- - | | | - | | borrowed value does not live long enough - | argument requires that `a` is borrowed for `'static` +LL | let cell = Cell::new(&a); + | ^^ borrowed value does not live long enough ... -LL | } - | - `a` dropped here while still borrowed +LL | / foo(cell, |cell_a, cell_x| { +LL | | cell_x.set(cell_a.get()); // forces 'a: 'x, implies 'a = 'static -> borrow error +LL | | }) + | |______- argument requires that `a` is borrowed for `'static` +LL | } + | - `a` dropped here while still borrowed error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/user-annotations/adt-nullary-enums.stderr b/src/test/ui/nll/user-annotations/adt-nullary-enums.stderr index bb7034122288..3326fa521fc9 100644 --- a/src/test/ui/nll/user-annotations/adt-nullary-enums.stderr +++ b/src/test/ui/nll/user-annotations/adt-nullary-enums.stderr @@ -1,14 +1,14 @@ error[E0597]: `c` does not live long enough --> $DIR/adt-nullary-enums.rs:33:41 | -LL | SomeEnum::SomeVariant(Cell::new(&c)), - | ----------^^- - | | | - | | borrowed value does not live long enough - | argument requires that `c` is borrowed for `'static` -... -LL | } - | - `c` dropped here while still borrowed +LL | / combine( +LL | | SomeEnum::SomeVariant(Cell::new(&c)), + | | ^^ borrowed value does not live long enough +LL | | SomeEnum::SomeOtherVariant::>, +LL | | ); + | |_____- argument requires that `c` is borrowed for `'static` +LL | } + | - `c` dropped here while still borrowed error[E0597]: `c` does not live long enough --> $DIR/adt-nullary-enums.rs:41:41 From 4e0c27bbfd263580c971aee1ef6960914e20a7ff Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 27 Oct 2022 16:22:06 +0000 Subject: [PATCH 136/171] Erase regions from CallArgument, add test + bless --- compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- .../project-fn-ret-invariant.oneuse.stderr | 10 +++--- .../cache/project-fn-ret-invariant.rs | 2 +- src/test/ui/borrowck/issue-103624.rs | 31 ++++++++++++++++ src/test/ui/borrowck/issue-103624.stderr | 35 +++++++++++++++++++ 5 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/borrowck/issue-103624.rs create mode 100644 src/test/ui/borrowck/issue-103624.stderr diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index dc0f0e7cd3c4..42c92e56e162 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1630,7 +1630,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let op_arg_ty = self.normalize(op_arg_ty, term_location); let category = if from_hir_call { - ConstraintCategory::CallArgument(func_ty) + ConstraintCategory::CallArgument(self.infcx.tcx.erase_regions(func_ty)) } else { ConstraintCategory::Boring }; diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr index cc1560162127..77841780f621 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr @@ -15,19 +15,19 @@ LL | let a = bar(f, x); = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:40:13 + --> $DIR/project-fn-ret-invariant.rs:42:13 | LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here -LL | let f = foo; // <-- No consistent type can be inferred for `f` here. -LL | let a = bar(f, x); +... +LL | let b = bar(f, y); | ^^^^^^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of a function pointer to `foo` - = note: the function `foo` is invariant over the parameter `'a` + = note: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Type<'a>` is invariant over the parameter `'a` = help: see for more information about variance help: `'a` and `'b` must be the same: replace one with the other diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs index 1075fd6e0923..e043379133ab 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs @@ -39,8 +39,8 @@ fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { let f = foo; // <-- No consistent type can be inferred for `f` here. let a = bar(f, x); //[oneuse]~^ ERROR lifetime may not live long enough - //[oneuse]~| ERROR lifetime may not live long enough let b = bar(f, y); + //[oneuse]~^ ERROR lifetime may not live long enough (a, b) } diff --git a/src/test/ui/borrowck/issue-103624.rs b/src/test/ui/borrowck/issue-103624.rs new file mode 100644 index 000000000000..f1fa95f92469 --- /dev/null +++ b/src/test/ui/borrowck/issue-103624.rs @@ -0,0 +1,31 @@ +// edition:2021 + +struct StructA { + b: StructB, +} + +async fn spawn_blocking(f: impl (Fn() -> T) + Send + Sync + 'static) -> T { + todo!() +} + +impl StructA { + async fn foo(&self) { + let bar = self.b.bar().await; + spawn_blocking(move || { + //~^ ERROR borrowed data escapes outside of associated function + self.b; + //~^ ERROR cannot move out of `self.b`, as `self` is a captured variable in an `Fn` closure + }) + .await; + } +} + +struct StructB {} + +impl StructB { + async fn bar(&self) -> Option { + None + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-103624.stderr b/src/test/ui/borrowck/issue-103624.stderr new file mode 100644 index 000000000000..e6a35dd8801a --- /dev/null +++ b/src/test/ui/borrowck/issue-103624.stderr @@ -0,0 +1,35 @@ +error[E0507]: cannot move out of `self.b`, as `self` is a captured variable in an `Fn` closure + --> $DIR/issue-103624.rs:16:13 + | +LL | async fn foo(&self) { + | ----- captured outer variable +LL | let bar = self.b.bar().await; +LL | spawn_blocking(move || { + | ------- captured by this `Fn` closure +LL | +LL | self.b; + | ^^^^^^ move occurs because `self.b` has type `StructB`, which does not implement the `Copy` trait + +error[E0521]: borrowed data escapes outside of associated function + --> $DIR/issue-103624.rs:14:9 + | +LL | async fn foo(&self) { + | ----- + | | + | `self` is a reference that is only valid in the associated function body + | let's call the lifetime of this reference `'1` +LL | let bar = self.b.bar().await; +LL | / spawn_blocking(move || { +LL | | +LL | | self.b; +LL | | +LL | | }) + | | ^ + | | | + | |__________`self` escapes the associated function body here + | argument requires that `'1` must outlive `'static` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0507, E0521. +For more information about an error, try `rustc --explain E0507`. From dd912add18e0a0498e3032781ea73ee846ee76cf Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 27 Oct 2022 09:48:06 -0700 Subject: [PATCH 137/171] rustdoc: stop hiding focus outlines on non-rustdoc-toggle details tags We really shouldn't be overriding this kind of stuff unless the browser default is really broken (like outlining the thing that isn't clickable). This directly reverts b8f4e74cbc938d3448507d422c98061c2b71c922. --- src/librustdoc/html/static/css/rustdoc.css | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 84a1fa2e28ec..5eb876b641c1 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -292,10 +292,6 @@ p:last-child { margin: 0; } -summary { - outline: none; -} - /* Fix some style changes due to normalize.css 8 */ button { @@ -1538,6 +1534,8 @@ details.rustdoc-toggle > summary.hideme { details.rustdoc-toggle > summary { list-style: none; + /* focus outline is shown on `::before` instead of this */ + outline: none; } details.rustdoc-toggle > summary::-webkit-details-marker, details.rustdoc-toggle > summary::marker { From 4d9114fe80613c304bc064d10b64d496cb7d3cdc Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 28 Oct 2022 01:18:26 +0800 Subject: [PATCH 138/171] Update cargo 6 commits in 9210810d1fd7b51ae0439a0a363cc50e36963455..7e484fc1a766f56dbc95380f45719698e0c82749 2022-10-25 22:31:50 +0000 to 2022-10-27 15:20:57 +0000 - fix(publish): Block until it is in index (rust-lang/cargo#11062) - Add Accept-Encoding request header to enable compression (rust-lang/cargo#11292) - Update contrib docs for highfive transition (rust-lang/cargo#11294) - Migrate from highfive to triagebot (rust-lang/cargo#11293) - Fix dupe word typos (rust-lang/cargo#11287) - Fix confusing error messages when using -Zsparse-registry (rust-lang/cargo#11283) --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 9210810d1fd7..7e484fc1a766 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 9210810d1fd7b51ae0439a0a363cc50e36963455 +Subproject commit 7e484fc1a766f56dbc95380f45719698e0c82749 From bfac2daef9912244d8a913a57b83c4e1b485993d Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 26 Oct 2022 22:07:56 +0100 Subject: [PATCH 139/171] Ignore test on mingw32 --- src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile b/src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile index 24d9742aef0b..50fca7f24e61 100644 --- a/src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile +++ b/src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile @@ -1,3 +1,8 @@ +# ignore-i686-pc-windows-gnu + +# This test doesn't work on 32-bit MinGW as cdylib has its own copy of unwinder +# so cross-DLL unwinding does not work. + include ../tools.mk all: From cb1e7d96767525fde3965f86bace8a5acf0dc643 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 27 Oct 2022 17:24:38 +0000 Subject: [PATCH 140/171] Only ban duplication across parameters. --- compiler/rustc_resolve/src/late.rs | 99 +++++++++++++------ compiler/rustc_resolve/src/lib.rs | 1 + ...-return-type-requires-explicit-lifetime.rs | 3 + 3 files changed, 71 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 40e71d4fc751..17a955326314 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -30,6 +30,7 @@ use rustc_span::{BytePos, Span}; use smallvec::{smallvec, SmallVec}; use rustc_span::source_map::{respan, Spanned}; +use std::assert_matches::debug_assert_matches; use std::collections::{hash_map::Entry, BTreeSet}; use std::mem::{replace, take}; @@ -1852,12 +1853,25 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { has_self: bool, inputs: impl Iterator, &'ast Ty)>, ) -> Result, Vec)> { - let outer_candidates = - replace(&mut self.lifetime_elision_candidates, Some(Default::default())); + enum Elision { + /// We have not found any candidate. + None, + /// We have a candidate bound to `self`. + Self_(LifetimeRes), + /// We have a candidate bound to a parameter. + Param(LifetimeRes), + /// We failed elision. + Err, + } - let mut elision_lifetime = None; - let mut lifetime_count = 0; + // Save elision state to reinstate it later. + let outer_candidates = self.lifetime_elision_candidates.take(); + + // Result of elision. + let mut elision_lifetime = Elision::None; + // Information for diagnostics. let mut parameter_info = Vec::new(); + let mut all_candidates = Vec::new(); let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; for (index, (pat, ty)) in inputs.enumerate() { @@ -1867,12 +1881,17 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings); } }); - self.visit_ty(ty); - if let Some(ref candidates) = self.lifetime_elision_candidates { - let new_count = candidates.len(); - let local_count = new_count - lifetime_count; - if local_count != 0 { + // Record elision candidates only for this parameter. + debug_assert_matches!(self.lifetime_elision_candidates, None); + self.lifetime_elision_candidates = Some(Default::default()); + self.visit_ty(ty); + let local_candidates = self.lifetime_elision_candidates.take(); + + if let Some(candidates) = local_candidates { + let distinct: FxHashSet<_> = candidates.iter().map(|(res, _)| *res).collect(); + let lifetime_count = distinct.len(); + if lifetime_count != 0 { parameter_info.push(ElisionFnParameter { index, ident: if let Some(pat) = pat && let PatKind::Ident(_, ident, _) = pat.kind { @@ -1880,48 +1899,64 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } else { None }, - lifetime_count: local_count, + lifetime_count, span: ty.span, }); + all_candidates.extend(candidates.into_iter().filter_map(|(_, candidate)| { + match candidate { + LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => { + None + } + LifetimeElisionCandidate::Missing(missing) => Some(missing), + } + })); + } + let mut distinct_iter = distinct.into_iter(); + if let Some(res) = distinct_iter.next() { + match elision_lifetime { + // We are the first parameter to bind lifetimes. + Elision::None => { + if distinct_iter.next().is_none() { + // We have a single lifetime => success. + elision_lifetime = Elision::Param(res) + } else { + // We have have multiple lifetimes => error. + elision_lifetime = Elision::Err; + } + } + // We have 2 parameters that bind lifetimes => error. + Elision::Param(_) => elision_lifetime = Elision::Err, + // `self` elision takes precedence over everything else. + Elision::Self_(_) | Elision::Err => {} + } } - lifetime_count = new_count; } // Handle `self` specially. if index == 0 && has_self { let self_lifetime = self.find_lifetime_for_self(ty); if let Set1::One(lifetime) = self_lifetime { - elision_lifetime = Some(lifetime); - self.lifetime_elision_candidates = None; + // We found `self` elision. + elision_lifetime = Elision::Self_(lifetime); } else { - self.lifetime_elision_candidates = Some(Default::default()); - lifetime_count = 0; + // We do not have `self` elision: disregard the `Elision::Param` that we may + // have found. + elision_lifetime = Elision::None; } } debug!("(resolving function / closure) recorded parameter"); } - let all_candidates = replace(&mut self.lifetime_elision_candidates, outer_candidates); - debug!(?all_candidates); + // Reinstate elision state. + debug_assert_matches!(self.lifetime_elision_candidates, None); + self.lifetime_elision_candidates = outer_candidates; - if let Some(res) = elision_lifetime { + if let Elision::Param(res) | Elision::Self_(res) = elision_lifetime { return Ok(res); } - // We do not have a `self` candidate, look at the full list. - let all_candidates = all_candidates.unwrap(); - if let [(res, _)] = &all_candidates[..] { - Ok(*res) - } else { - let all_candidates = all_candidates - .into_iter() - .filter_map(|(_, candidate)| match candidate { - LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => None, - LifetimeElisionCandidate::Missing(missing) => Some(missing), - }) - .collect(); - Err((all_candidates, parameter_info)) - } + // We do not have a candidate. + Err((all_candidates, parameter_info)) } /// List all the lifetimes that appear in the provided type. diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 1c1976af5054..a0f05878283e 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -7,6 +7,7 @@ //! Type-relative name resolution (methods, fields, associated items) happens in `rustc_hir_analysis`. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(drain_filter)] #![feature(if_let_guard)] diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs index ba769a4bcc0a..d0a8fe795efd 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs @@ -45,4 +45,7 @@ fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &isize { fn l<'a>(_: &'a str, _: &'a str) -> &str { "" } //~^ ERROR missing lifetime specifier +// This is ok because both `'a` are for the same parameter. +fn m<'a>(_: &'a Foo<'a>) -> &str { "" } + fn main() {} From 3f241086627b3c68a2abec0776ffff8037deaad9 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 27 Oct 2022 22:24:24 +0200 Subject: [PATCH 141/171] Move clippy::uninlined_format_args back to pedantic --- src/tools/clippy/clippy_lints/src/format_args.rs | 2 +- src/tools/clippy/clippy_lints/src/lib.register_all.rs | 1 - src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs | 1 + src/tools/clippy/clippy_lints/src/lib.register_style.rs | 1 - 4 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs index 32073536b45b..f0fe845d3303 100644 --- a/src/tools/clippy/clippy_lints/src/format_args.rs +++ b/src/tools/clippy/clippy_lints/src/format_args.rs @@ -115,7 +115,7 @@ declare_clippy_lint! { /// nothing will be suggested, e.g. `println!("{0}={1}", var, 1+2)`. #[clippy::version = "1.65.0"] pub UNINLINED_FORMAT_ARGS, - style, + pedantic, "using non-inlined variables in `format!` calls" } diff --git a/src/tools/clippy/clippy_lints/src/lib.register_all.rs b/src/tools/clippy/clippy_lints/src/lib.register_all.rs index f5ad52ba1892..c455e1561b71 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_all.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_all.rs @@ -72,7 +72,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(format::USELESS_FORMAT), LintId::of(format_args::FORMAT_IN_FORMAT_ARGS), LintId::of(format_args::TO_STRING_IN_FORMAT_ARGS), - LintId::of(format_args::UNINLINED_FORMAT_ARGS), LintId::of(format_args::UNUSED_FORMAT_SPECS), LintId::of(format_impl::PRINT_IN_FORMAT_IMPL), LintId::of(format_impl::RECURSIVE_FORMAT_IMPL), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs b/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs index 060d3bdc7c6f..44e969585b50 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs @@ -29,6 +29,7 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![ LintId::of(eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS), LintId::of(excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS), LintId::of(excessive_bools::STRUCT_EXCESSIVE_BOOLS), + LintId::of(format_args::UNINLINED_FORMAT_ARGS), LintId::of(functions::MUST_USE_CANDIDATE), LintId::of(functions::TOO_MANY_LINES), LintId::of(if_not_else::IF_NOT_ELSE), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_style.rs b/src/tools/clippy/clippy_lints/src/lib.register_style.rs index 6894d69e928a..3312f5648552 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_style.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_style.rs @@ -25,7 +25,6 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![ LintId::of(enum_variants::MODULE_INCEPTION), LintId::of(eta_reduction::REDUNDANT_CLOSURE), LintId::of(float_literal::EXCESSIVE_PRECISION), - LintId::of(format_args::UNINLINED_FORMAT_ARGS), LintId::of(from_over_into::FROM_OVER_INTO), LintId::of(from_str_radix_10::FROM_STR_RADIX_10), LintId::of(functions::DOUBLE_MUST_USE), From c00ff9c4d01e8ba64bf03aaf3bb7940874d3e094 Mon Sep 17 00:00:00 2001 From: Boxy Date: Thu, 27 Oct 2022 21:48:41 +0100 Subject: [PATCH 142/171] DoIt --- .../locales/en-US/hir_analysis.ftl | 2 + .../rustc_hir_analysis/src/collect/type_of.rs | 32 ++++++++- compiler/rustc_hir_analysis/src/errors.rs | 7 ++ src/test/ui/resolve/issue-23305.rs | 2 +- src/test/ui/resolve/issue-23305.stderr | 20 +----- src/test/ui/resolve/resolve-self-in-impl.rs | 8 +-- .../ui/resolve/resolve-self-in-impl.stderr | 68 +++---------------- 7 files changed, 56 insertions(+), 83 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl index 7ac44312695d..7cedfca5728c 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl @@ -146,3 +146,5 @@ hir_analysis_const_impl_for_non_const_trait = hir_analysis_const_bound_for_non_const_trait = ~const can only be applied to `#[const_trait]` traits + +hir_analysis_self_in_impl_self = `Self` is not valid at this location diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 32f359a81581..877cd75587be 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -319,7 +319,37 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } } ItemKind::TyAlias(self_ty, _) => icx.to_ty(self_ty), - ItemKind::Impl(hir::Impl { self_ty, .. }) => icx.to_ty(*self_ty), + ItemKind::Impl( + hir::Impl { self_ty, .. } + ) => { + struct MyVisitor(bool); + impl<'v> hir::intravisit::Visitor<'v> for MyVisitor { + fn visit_ty(&mut self, t: &'v Ty<'v>) { + if matches!( + &t.kind, + TyKind::Path(hir::QPath::Resolved( + _, + Path { + res: hir::def::Res::SelfTyAlias { .. }, + .. + }, + )) + ) { + self.0 = true; + return; + } + hir::intravisit::walk_ty(self, t); + } + } + + let mut my_visitor = MyVisitor(false); + my_visitor.visit_ty(self_ty); + + match my_visitor.0 { + true => { tcx.sess.emit_err(crate::errors::SelfInImplSelf { span: self_ty.span}); tcx.ty_error() }, + false => icx.to_ty(*self_ty), + } + }, ItemKind::Fn(..) => { let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); tcx.mk_fn_def(def_id.to_def_id(), substs) diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index bd0c1f5dd109..c3bfd0437ada 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -270,3 +270,10 @@ pub struct ConstBoundForNonConstTrait { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_self_in_impl_self)] +pub struct SelfInImplSelf { + #[primary_span] + pub span: Span, +} diff --git a/src/test/ui/resolve/issue-23305.rs b/src/test/ui/resolve/issue-23305.rs index 95635e12a63b..3e3d5ee2fda0 100644 --- a/src/test/ui/resolve/issue-23305.rs +++ b/src/test/ui/resolve/issue-23305.rs @@ -3,6 +3,6 @@ pub trait ToNbt { } impl dyn ToNbt {} -//~^ ERROR cycle detected +//~^ ERROR `Self` is not valid at this location fn main() {} diff --git a/src/test/ui/resolve/issue-23305.stderr b/src/test/ui/resolve/issue-23305.stderr index 20aeb7b995a6..1b2745de321c 100644 --- a/src/test/ui/resolve/issue-23305.stderr +++ b/src/test/ui/resolve/issue-23305.stderr @@ -1,22 +1,8 @@ -error[E0391]: cycle detected when computing type of `` - --> $DIR/issue-23305.rs:5:16 +error: `Self` is not valid at this location + --> $DIR/issue-23305.rs:5:6 | LL | impl dyn ToNbt {} - | ^^^^ - | - = note: ...which immediately requires computing type of `` again -note: cycle used when collecting item types in top-level module - --> $DIR/issue-23305.rs:1:1 - | -LL | / pub trait ToNbt { -LL | | fn new(val: T) -> Self; -LL | | } -LL | | -... | -LL | | -LL | | fn main() {} - | |____________^ + | ^^^^^^^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/resolve/resolve-self-in-impl.rs b/src/test/ui/resolve/resolve-self-in-impl.rs index 024fdc51ea31..f845e780bbfe 100644 --- a/src/test/ui/resolve/resolve-self-in-impl.rs +++ b/src/test/ui/resolve/resolve-self-in-impl.rs @@ -11,10 +11,10 @@ impl Tr for S where Self: Copy {} // OK impl Tr for S where S: Copy {} // OK impl Tr for S where Self::A: Copy {} // OK -impl Tr for Self {} //~ ERROR cycle detected -impl Tr for S {} //~ ERROR cycle detected -impl Self {} //~ ERROR cycle detected -impl S {} //~ ERROR cycle detected +impl Tr for Self {} //~ ERROR `Self` is not valid at this location +impl Tr for S {} //~ ERROR `Self` is not valid at this location +impl Self {} //~ ERROR `Self` is not valid at this location +impl S {} //~ ERROR `Self` is not valid at this location impl Tr for S {} //~ ERROR cycle detected fn main() {} diff --git a/src/test/ui/resolve/resolve-self-in-impl.stderr b/src/test/ui/resolve/resolve-self-in-impl.stderr index aa99c1a33352..93e2b4695fc0 100644 --- a/src/test/ui/resolve/resolve-self-in-impl.stderr +++ b/src/test/ui/resolve/resolve-self-in-impl.stderr @@ -1,78 +1,26 @@ -error[E0391]: cycle detected when computing type of `` +error: `Self` is not valid at this location --> $DIR/resolve-self-in-impl.rs:14:13 | LL | impl Tr for Self {} | ^^^^ - | - = note: ...which immediately requires computing type of `` again -note: cycle used when collecting item types in top-level module - --> $DIR/resolve-self-in-impl.rs:1:1 - | -LL | / #![feature(associated_type_defaults)] -LL | | -LL | | struct S(T); -LL | | trait Tr { -... | -LL | | -LL | | fn main() {} - | |____________^ -error[E0391]: cycle detected when computing type of `` - --> $DIR/resolve-self-in-impl.rs:15:15 +error: `Self` is not valid at this location + --> $DIR/resolve-self-in-impl.rs:15:13 | LL | impl Tr for S {} - | ^^^^ - | - = note: ...which immediately requires computing type of `` again -note: cycle used when collecting item types in top-level module - --> $DIR/resolve-self-in-impl.rs:1:1 - | -LL | / #![feature(associated_type_defaults)] -LL | | -LL | | struct S(T); -LL | | trait Tr { -... | -LL | | -LL | | fn main() {} - | |____________^ + | ^^^^^^^ -error[E0391]: cycle detected when computing type of `` +error: `Self` is not valid at this location --> $DIR/resolve-self-in-impl.rs:16:6 | LL | impl Self {} | ^^^^ - | - = note: ...which immediately requires computing type of `` again -note: cycle used when collecting item types in top-level module - --> $DIR/resolve-self-in-impl.rs:1:1 - | -LL | / #![feature(associated_type_defaults)] -LL | | -LL | | struct S(T); -LL | | trait Tr { -... | -LL | | -LL | | fn main() {} - | |____________^ -error[E0391]: cycle detected when computing type of `` - --> $DIR/resolve-self-in-impl.rs:17:8 +error: `Self` is not valid at this location + --> $DIR/resolve-self-in-impl.rs:17:6 | LL | impl S {} - | ^^^^ - | - = note: ...which immediately requires computing type of `` again -note: cycle used when collecting item types in top-level module - --> $DIR/resolve-self-in-impl.rs:1:1 - | -LL | / #![feature(associated_type_defaults)] -LL | | -LL | | struct S(T); -LL | | trait Tr { -... | -LL | | -LL | | fn main() {} - | |____________^ + | ^^^^^^^ error[E0391]: cycle detected when computing trait implemented by `` --> $DIR/resolve-self-in-impl.rs:18:1 From ca5a6e43dd6fcfddf436d36f6907d8ef44c7105b Mon Sep 17 00:00:00 2001 From: Boxy Date: Thu, 27 Oct 2022 22:18:26 +0100 Subject: [PATCH 143/171] use proper spans --- .../locales/en-US/hir_analysis.ftl | 4 +- .../rustc_hir_analysis/src/collect/type_of.rs | 13 +++--- compiler/rustc_hir_analysis/src/errors.rs | 6 ++- src/test/ui/resolve/issue-23305.rs | 2 +- src/test/ui/resolve/issue-23305.stderr | 8 ++-- src/test/ui/resolve/resolve-self-in-impl.rs | 9 +++-- .../ui/resolve/resolve-self-in-impl.stderr | 40 +++++++++++++------ 7 files changed, 54 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl index 7cedfca5728c..855866be6279 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl @@ -147,4 +147,6 @@ hir_analysis_const_impl_for_non_const_trait = hir_analysis_const_bound_for_non_const_trait = ~const can only be applied to `#[const_trait]` traits -hir_analysis_self_in_impl_self = `Self` is not valid at this location +hir_analysis_self_in_impl_self = + `Self` is not valid in the self type of an impl block + .note = replace `Self` with a different type \ No newline at end of file diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 877cd75587be..2032a4bce60c 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -322,7 +322,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { ItemKind::Impl( hir::Impl { self_ty, .. } ) => { - struct MyVisitor(bool); + struct MyVisitor(Vec); impl<'v> hir::intravisit::Visitor<'v> for MyVisitor { fn visit_ty(&mut self, t: &'v Ty<'v>) { if matches!( @@ -335,19 +335,22 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { }, )) ) { - self.0 = true; + self.0.push(t.span); return; } hir::intravisit::walk_ty(self, t); } } - let mut my_visitor = MyVisitor(false); + let mut my_visitor = MyVisitor(vec![]); my_visitor.visit_ty(self_ty); match my_visitor.0 { - true => { tcx.sess.emit_err(crate::errors::SelfInImplSelf { span: self_ty.span}); tcx.ty_error() }, - false => icx.to_ty(*self_ty), + spans if spans.len() > 0 => { + tcx.sess.emit_err(crate::errors::SelfInImplSelf { span: spans.into(), note: (), }); + tcx.ty_error() + }, + _ => icx.to_ty(*self_ty), } }, ItemKind::Fn(..) => { diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index c3bfd0437ada..6ed8244d119d 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1,7 +1,7 @@ //! Errors emitted by `rustc_hir_analysis`. -use rustc_errors::IntoDiagnostic; use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler}; +use rustc_errors::{IntoDiagnostic, MultiSpan}; use rustc_macros::{Diagnostic, LintDiagnostic}; use rustc_middle::ty::Ty; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -275,5 +275,7 @@ pub struct ConstBoundForNonConstTrait { #[diag(hir_analysis_self_in_impl_self)] pub struct SelfInImplSelf { #[primary_span] - pub span: Span, + pub span: MultiSpan, + #[note] + pub note: (), } diff --git a/src/test/ui/resolve/issue-23305.rs b/src/test/ui/resolve/issue-23305.rs index 3e3d5ee2fda0..6d7fe7c50a23 100644 --- a/src/test/ui/resolve/issue-23305.rs +++ b/src/test/ui/resolve/issue-23305.rs @@ -3,6 +3,6 @@ pub trait ToNbt { } impl dyn ToNbt {} -//~^ ERROR `Self` is not valid at this location +//~^ ERROR `Self` is not valid in the self type of an impl block fn main() {} diff --git a/src/test/ui/resolve/issue-23305.stderr b/src/test/ui/resolve/issue-23305.stderr index 1b2745de321c..aad1b583a324 100644 --- a/src/test/ui/resolve/issue-23305.stderr +++ b/src/test/ui/resolve/issue-23305.stderr @@ -1,8 +1,10 @@ -error: `Self` is not valid at this location - --> $DIR/issue-23305.rs:5:6 +error: `Self` is not valid in the self type of an impl block + --> $DIR/issue-23305.rs:5:16 | LL | impl dyn ToNbt {} - | ^^^^^^^^^^^^^^^ + | ^^^^ + | + = note: replace `Self` with a different type error: aborting due to previous error diff --git a/src/test/ui/resolve/resolve-self-in-impl.rs b/src/test/ui/resolve/resolve-self-in-impl.rs index f845e780bbfe..d0872d1b76f2 100644 --- a/src/test/ui/resolve/resolve-self-in-impl.rs +++ b/src/test/ui/resolve/resolve-self-in-impl.rs @@ -11,10 +11,11 @@ impl Tr for S where Self: Copy {} // OK impl Tr for S where S: Copy {} // OK impl Tr for S where Self::A: Copy {} // OK -impl Tr for Self {} //~ ERROR `Self` is not valid at this location -impl Tr for S {} //~ ERROR `Self` is not valid at this location -impl Self {} //~ ERROR `Self` is not valid at this location -impl S {} //~ ERROR `Self` is not valid at this location +impl Tr for Self {} //~ ERROR `Self` is not valid in the self type of an impl block +impl Tr for S {} //~ ERROR `Self` is not valid in the self type of an impl block +impl Self {} //~ ERROR `Self` is not valid in the self type of an impl block +impl S {} //~ ERROR `Self` is not valid in the self type of an impl block +impl (Self, Self) {} //~ ERROR `Self` is not valid in the self type of an impl block impl Tr for S {} //~ ERROR cycle detected fn main() {} diff --git a/src/test/ui/resolve/resolve-self-in-impl.stderr b/src/test/ui/resolve/resolve-self-in-impl.stderr index 93e2b4695fc0..9f9ed68898f6 100644 --- a/src/test/ui/resolve/resolve-self-in-impl.stderr +++ b/src/test/ui/resolve/resolve-self-in-impl.stderr @@ -1,34 +1,50 @@ -error: `Self` is not valid at this location +error: `Self` is not valid in the self type of an impl block --> $DIR/resolve-self-in-impl.rs:14:13 | LL | impl Tr for Self {} | ^^^^ + | + = note: replace `Self` with a different type -error: `Self` is not valid at this location - --> $DIR/resolve-self-in-impl.rs:15:13 +error: `Self` is not valid in the self type of an impl block + --> $DIR/resolve-self-in-impl.rs:15:15 | LL | impl Tr for S {} - | ^^^^^^^ + | ^^^^ + | + = note: replace `Self` with a different type -error: `Self` is not valid at this location +error: `Self` is not valid in the self type of an impl block --> $DIR/resolve-self-in-impl.rs:16:6 | LL | impl Self {} | ^^^^ + | + = note: replace `Self` with a different type -error: `Self` is not valid at this location - --> $DIR/resolve-self-in-impl.rs:17:6 +error: `Self` is not valid in the self type of an impl block + --> $DIR/resolve-self-in-impl.rs:17:8 | LL | impl S {} - | ^^^^^^^ + | ^^^^ + | + = note: replace `Self` with a different type -error[E0391]: cycle detected when computing trait implemented by `` - --> $DIR/resolve-self-in-impl.rs:18:1 +error: `Self` is not valid in the self type of an impl block + --> $DIR/resolve-self-in-impl.rs:18:7 + | +LL | impl (Self, Self) {} + | ^^^^ ^^^^ + | + = note: replace `Self` with a different type + +error[E0391]: cycle detected when computing trait implemented by `` + --> $DIR/resolve-self-in-impl.rs:19:1 | LL | impl Tr for S {} | ^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...which immediately requires computing trait implemented by `` again + = note: ...which immediately requires computing trait implemented by `` again note: cycle used when collecting item types in top-level module --> $DIR/resolve-self-in-impl.rs:1:1 | @@ -41,6 +57,6 @@ LL | | LL | | fn main() {} | |____________^ -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0391`. From b3425587a669d81b45f0d14f7fd6ae6108bf9444 Mon Sep 17 00:00:00 2001 From: Boxy Date: Thu, 27 Oct 2022 22:29:16 +0100 Subject: [PATCH 144/171] tidy + move logic to fn --- .../locales/en-US/hir_analysis.ftl | 4 +-- compiler/rustc_hir/src/hir.rs | 24 ++++++++++++++ .../rustc_hir_analysis/src/collect/type_of.rs | 33 +++---------------- 3 files changed, 30 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl index 855866be6279..62f004da0cae 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl @@ -147,6 +147,6 @@ hir_analysis_const_impl_for_non_const_trait = hir_analysis_const_bound_for_non_const_trait = ~const can only be applied to `#[const_trait]` traits -hir_analysis_self_in_impl_self = +hir_analysis_self_in_impl_self = `Self` is not valid in the self type of an impl block - .note = replace `Self` with a different type \ No newline at end of file + .note = replace `Self` with a different type diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index bc149e48d89e..9a9e40a3f43a 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2418,6 +2418,30 @@ impl<'hir> Ty<'hir> { } final_ty } + + pub fn find_self_aliases(&self) -> Vec { + use crate::intravisit::Visitor; + struct MyVisitor(Vec); + impl<'v> Visitor<'v> for MyVisitor { + fn visit_ty(&mut self, t: &'v Ty<'v>) { + if matches!( + &t.kind, + TyKind::Path(QPath::Resolved( + _, + Path { res: crate::def::Res::SelfTyAlias { .. }, .. }, + )) + ) { + self.0.push(t.span); + return; + } + crate::intravisit::walk_ty(self, t); + } + } + + let mut my_visitor = MyVisitor(vec![]); + my_visitor.visit_ty(self); + my_visitor.0 + } } /// Not represented directly in the AST; referred to by name through a `ty_path`. diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 2032a4bce60c..20903a68d6d9 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -319,36 +319,11 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } } ItemKind::TyAlias(self_ty, _) => icx.to_ty(self_ty), - ItemKind::Impl( - hir::Impl { self_ty, .. } - ) => { - struct MyVisitor(Vec); - impl<'v> hir::intravisit::Visitor<'v> for MyVisitor { - fn visit_ty(&mut self, t: &'v Ty<'v>) { - if matches!( - &t.kind, - TyKind::Path(hir::QPath::Resolved( - _, - Path { - res: hir::def::Res::SelfTyAlias { .. }, - .. - }, - )) - ) { - self.0.push(t.span); - return; - } - hir::intravisit::walk_ty(self, t); - } - } - - let mut my_visitor = MyVisitor(vec![]); - my_visitor.visit_ty(self_ty); - - match my_visitor.0 { - spans if spans.len() > 0 => { + ItemKind::Impl(hir::Impl { self_ty, .. }) => { + match self_ty.find_self_aliases() { + spans if spans.len() > 0 => { tcx.sess.emit_err(crate::errors::SelfInImplSelf { span: spans.into(), note: (), }); - tcx.ty_error() + tcx.ty_error() }, _ => icx.to_ty(*self_ty), } From 97423d331f5dbed3bbbf474e3b6bd2d8b7bd9af2 Mon Sep 17 00:00:00 2001 From: Bryan Garza <1396101+bryangarza@users.noreply.github.com> Date: Tue, 4 Oct 2022 01:27:11 +0000 Subject: [PATCH 145/171] Add tests for static async functions in traits This patch adds test cases for AFIT, the majority of which are currently expected to run as `check-fail`. --- .../in-trait/async-associated-types.rs | 24 +++++++ .../in-trait/async-associated-types.stderr | 57 +++++++++++++++++ .../async-associated-types2-desugared.rs | 31 +++++++++ .../async-associated-types2-desugared.stderr | 42 +++++++++++++ .../in-trait/async-associated-types2.rs | 32 ++++++++++ .../in-trait/async-associated-types2.stderr | 63 +++++++++++++++++++ .../ui/async-await/in-trait/async-example.rs | 17 +++++ .../in-trait/async-generics-and-bounds.rs | 21 +++++++ .../in-trait/async-generics-and-bounds.stderr | 37 +++++++++++ .../ui/async-await/in-trait/async-generics.rs | 18 ++++++ .../in-trait/async-generics.stderr | 37 +++++++++++ .../in-trait/async-lifetimes-and-bounds.rs | 20 ++++++ .../async-lifetimes-and-bounds.stderr | 23 +++++++ .../async-await/in-trait/async-lifetimes.rs | 18 ++++++ .../in-trait/async-lifetimes.stderr | 23 +++++++ .../async-await/in-trait/fn-not-async-err.rs | 17 +++++ .../in-trait/fn-not-async-err.stderr | 17 +++++ .../async-await/in-trait/fn-not-async-err2.rs | 21 +++++++ .../in-trait/fn-not-async-err2.stderr | 12 ++++ 19 files changed, 530 insertions(+) create mode 100644 src/test/ui/async-await/in-trait/async-associated-types.rs create mode 100644 src/test/ui/async-await/in-trait/async-associated-types.stderr create mode 100644 src/test/ui/async-await/in-trait/async-associated-types2-desugared.rs create mode 100644 src/test/ui/async-await/in-trait/async-associated-types2-desugared.stderr create mode 100644 src/test/ui/async-await/in-trait/async-associated-types2.rs create mode 100644 src/test/ui/async-await/in-trait/async-associated-types2.stderr create mode 100644 src/test/ui/async-await/in-trait/async-example.rs create mode 100644 src/test/ui/async-await/in-trait/async-generics-and-bounds.rs create mode 100644 src/test/ui/async-await/in-trait/async-generics-and-bounds.stderr create mode 100644 src/test/ui/async-await/in-trait/async-generics.rs create mode 100644 src/test/ui/async-await/in-trait/async-generics.stderr create mode 100644 src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.rs create mode 100644 src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.stderr create mode 100644 src/test/ui/async-await/in-trait/async-lifetimes.rs create mode 100644 src/test/ui/async-await/in-trait/async-lifetimes.stderr create mode 100644 src/test/ui/async-await/in-trait/fn-not-async-err.rs create mode 100644 src/test/ui/async-await/in-trait/fn-not-async-err.stderr create mode 100644 src/test/ui/async-await/in-trait/fn-not-async-err2.rs create mode 100644 src/test/ui/async-await/in-trait/fn-not-async-err2.stderr diff --git a/src/test/ui/async-await/in-trait/async-associated-types.rs b/src/test/ui/async-await/in-trait/async-associated-types.rs new file mode 100644 index 000000000000..0269f00bbab7 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-associated-types.rs @@ -0,0 +1,24 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Debug; + +trait MyTrait<'a, 'b, T> where Self: 'a, T: Debug + Sized + 'b { + type MyAssoc;// = (&'a T, &'b U); + + async fn foo(&'a self, key: &'b T) -> Self::MyAssoc; +} + +impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U { + type MyAssoc = (&'a U, &'b T); + + async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { + (self, key) + } +} +//~^^^^ ERROR cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements +//~| ERROR cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/async-associated-types.stderr b/src/test/ui/async-await/in-trait/async-associated-types.stderr new file mode 100644 index 000000000000..c1c66f9023bd --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-associated-types.stderr @@ -0,0 +1,57 @@ +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/async-associated-types.rs:17:43 + | +LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { + | ^^^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... + --> $DIR/async-associated-types.rs:14:6 + | +LL | impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U { + | ^^ +note: ...so that the types are compatible + --> $DIR/async-associated-types.rs:17:43 + | +LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { + | ^^^^^^^^^^^^^^ + = note: expected `(&'a U, &'b T)` + found `(&U, &T)` + = note: but, the lifetime must be valid for the static lifetime... +note: ...so that the types are compatible + --> $DIR/async-associated-types.rs:17:43 + | +LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { + | ^^^^^^^^^^^^^^ + = note: expected `MyTrait<'static, 'static, T>` + found `MyTrait<'_, '_, T>` + +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements + --> $DIR/async-associated-types.rs:17:43 + | +LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { + | ^^^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the lifetime `'b` as defined here... + --> $DIR/async-associated-types.rs:14:10 + | +LL | impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U { + | ^^ +note: ...so that the types are compatible + --> $DIR/async-associated-types.rs:17:43 + | +LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { + | ^^^^^^^^^^^^^^ + = note: expected `(&'a U, &'b T)` + found `(&U, &T)` + = note: but, the lifetime must be valid for the static lifetime... +note: ...so that the types are compatible + --> $DIR/async-associated-types.rs:17:43 + | +LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { + | ^^^^^^^^^^^^^^ + = note: expected `MyTrait<'static, 'static, T>` + found `MyTrait<'_, '_, T>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/async-await/in-trait/async-associated-types2-desugared.rs b/src/test/ui/async-await/in-trait/async-associated-types2-desugared.rs new file mode 100644 index 000000000000..85d29eb703e7 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-associated-types2-desugared.rs @@ -0,0 +1,31 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; + +trait MyTrait { + type Fut<'a>: Future + where + Self: 'a; + + async fn foo(&self) -> Self::Fut<'a>; + //~^ ERROR use of undeclared lifetime name `'a` + //~| ERROR the parameter type `Self` may not live long enough +} + +impl MyTrait for i32 { + type Fut<'a> = impl Future + 'a + where + Self: 'a; + //~^^^ ERROR `impl Trait` in type aliases is unstable + + fn foo<'a>(&'a self) -> Self::Fut<'a> { + async { + *self + } + } +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/async-associated-types2-desugared.stderr b/src/test/ui/async-await/in-trait/async-associated-types2-desugared.stderr new file mode 100644 index 000000000000..6bc553b26350 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-associated-types2-desugared.stderr @@ -0,0 +1,42 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/async-associated-types2-desugared.rs:13:38 + | +LL | async fn foo(&self) -> Self::Fut<'a>; + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'a` here + | +LL | async fn foo<'a>(&self) -> Self::Fut<'a>; + | ++++ +help: consider introducing lifetime `'a` here + | +LL | trait MyTrait<'a> { + | ++++ + +error[E0658]: `impl Trait` in type aliases is unstable + --> $DIR/async-associated-types2-desugared.rs:19:20 + | +LL | type Fut<'a> = impl Future + 'a + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable + +error[E0310]: the parameter type `Self` may not live long enough + --> $DIR/async-associated-types2-desugared.rs:13:28 + | +LL | async fn foo(&self) -> Self::Fut<'a>; + | ^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `Self: 'static`... + = note: ...so that the type `Self` will meet its required lifetime bounds... +note: ...that is required by this bound + --> $DIR/async-associated-types2-desugared.rs:11:15 + | +LL | Self: 'a; + | ^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0261, E0310, E0658. +For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/async-await/in-trait/async-associated-types2.rs b/src/test/ui/async-await/in-trait/async-associated-types2.rs new file mode 100644 index 000000000000..c2133b04bc84 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-associated-types2.rs @@ -0,0 +1,32 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; + +trait MyTrait { + type Fut<'a>: Future + where + Self: 'a; + + fn foo(&self) -> Self::Fut<'a>; + //~^ ERROR use of undeclared lifetime name `'a` +} + +impl MyTrait for i32 { + type Fut<'a> = impl Future + 'a + where + Self: 'a; + //~^^^ ERROR `impl Trait` in type aliases is unstable + //~| ERROR expected `::Fut<'a>` to be a future that resolves to `i32`, but it resolves to `<::Fut<'a> as Future>::Output` + + fn foo<'a>(&'a self) -> Self::Fut<'a> { + //~^ ERROR `impl` item signature doesn't match `trait` item signature + async { + *self + } + } +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/async-associated-types2.stderr b/src/test/ui/async-await/in-trait/async-associated-types2.stderr new file mode 100644 index 000000000000..f3343852fa09 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-associated-types2.stderr @@ -0,0 +1,63 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/async-associated-types2.rs:13:32 + | +LL | fn foo(&self) -> Self::Fut<'a>; + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'a` here + | +LL | fn foo<'a>(&self) -> Self::Fut<'a>; + | ++++ +help: consider introducing lifetime `'a` here + | +LL | trait MyTrait<'a> { + | ++++ + +error[E0658]: `impl Trait` in type aliases is unstable + --> $DIR/async-associated-types2.rs:18:20 + | +LL | type Fut<'a> = impl Future + 'a + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable + +error[E0271]: expected `::Fut<'a>` to be a future that resolves to `i32`, but it resolves to `<::Fut<'a> as Future>::Output` + --> $DIR/async-associated-types2.rs:18:20 + | +LL | type Fut<'a> = impl Future + 'a + | ^^^^^^^^^^^^^^^^ expected `i32`, found associated type + | + = note: expected type `i32` + found associated type `<::Fut<'a> as Future>::Output` +note: required by a bound in `MyTrait::Fut` + --> $DIR/async-associated-types2.rs:9:26 + | +LL | type Fut<'a>: Future + | ^^^^^^^^^^^^ required by this bound in `MyTrait::Fut` +help: consider constraining the associated type `<::Fut<'a> as Future>::Output` to `i32` + | +LL | type Fut<'a> = impl Future + 'a + | ++++++++++++++ + +error: `impl` item signature doesn't match `trait` item signature + --> $DIR/async-associated-types2.rs:24:5 + | +LL | fn foo(&self) -> Self::Fut<'a>; + | ------------------------------- expected `fn(&'1 i32) -> ::Fut<'static>` +... +LL | fn foo<'a>(&'a self) -> Self::Fut<'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 i32) -> ::Fut<'1>` + | + = note: expected `fn(&'1 i32) -> ::Fut<'static>` + found `fn(&'1 i32) -> ::Fut<'1>` +help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` + --> $DIR/async-associated-types2.rs:13:22 + | +LL | fn foo(&self) -> Self::Fut<'a>; + | ^^^^ consider borrowing this type parameter in the trait + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0261, E0271, E0658. +For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/async-await/in-trait/async-example.rs b/src/test/ui/async-await/in-trait/async-example.rs new file mode 100644 index 000000000000..2c2297c6b584 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-example.rs @@ -0,0 +1,17 @@ +// check-pass +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +trait MyTrait { + async fn foo(&self) -> i32; +} + +impl MyTrait for i32 { + async fn foo(&self) -> i32 { + *self + } +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/async-generics-and-bounds.rs b/src/test/ui/async-await/in-trait/async-generics-and-bounds.rs new file mode 100644 index 000000000000..d748430c5ee8 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-generics-and-bounds.rs @@ -0,0 +1,21 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Debug; +use std::hash::Hash; + +trait MyTrait { + async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; +} +//~^^ ERROR the parameter type `U` may not live long enough +//~| ERROR the parameter type `T` may not live long enough + +impl MyTrait for (T, U) { + async fn foo(&self) -> &(T, U) { + self + } +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/async-generics-and-bounds.stderr b/src/test/ui/async-await/in-trait/async-generics-and-bounds.stderr new file mode 100644 index 000000000000..8975ec21a015 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-generics-and-bounds.stderr @@ -0,0 +1,37 @@ +error[E0311]: the parameter type `U` may not live long enough + --> $DIR/async-generics-and-bounds.rs:10:28 + | +LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; + | ^^^^^^^ + | +note: the parameter type `U` must be valid for the anonymous lifetime as defined here... + --> $DIR/async-generics-and-bounds.rs:10:18 + | +LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; + | ^ +note: ...so that the reference type `&(T, U)` does not outlive the data it points at + --> $DIR/async-generics-and-bounds.rs:10:28 + | +LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; + | ^^^^^^^ + +error[E0311]: the parameter type `T` may not live long enough + --> $DIR/async-generics-and-bounds.rs:10:28 + | +LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; + | ^^^^^^^ + | +note: the parameter type `T` must be valid for the anonymous lifetime as defined here... + --> $DIR/async-generics-and-bounds.rs:10:18 + | +LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; + | ^ +note: ...so that the reference type `&(T, U)` does not outlive the data it points at + --> $DIR/async-generics-and-bounds.rs:10:28 + | +LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0311`. diff --git a/src/test/ui/async-await/in-trait/async-generics.rs b/src/test/ui/async-await/in-trait/async-generics.rs new file mode 100644 index 000000000000..3e6f70cd49f6 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-generics.rs @@ -0,0 +1,18 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +trait MyTrait { + async fn foo(&self) -> &(T, U); +} +//~^^ ERROR the parameter type `U` may not live long enough +//~| ERROR the parameter type `T` may not live long enough + +impl MyTrait for (T, U) { + async fn foo(&self) -> &(T, U) { + self + } +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/async-generics.stderr b/src/test/ui/async-await/in-trait/async-generics.stderr new file mode 100644 index 000000000000..84c7b3095368 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-generics.stderr @@ -0,0 +1,37 @@ +error[E0311]: the parameter type `U` may not live long enough + --> $DIR/async-generics.rs:7:28 + | +LL | async fn foo(&self) -> &(T, U); + | ^^^^^^^ + | +note: the parameter type `U` must be valid for the anonymous lifetime as defined here... + --> $DIR/async-generics.rs:7:18 + | +LL | async fn foo(&self) -> &(T, U); + | ^ +note: ...so that the reference type `&(T, U)` does not outlive the data it points at + --> $DIR/async-generics.rs:7:28 + | +LL | async fn foo(&self) -> &(T, U); + | ^^^^^^^ + +error[E0311]: the parameter type `T` may not live long enough + --> $DIR/async-generics.rs:7:28 + | +LL | async fn foo(&self) -> &(T, U); + | ^^^^^^^ + | +note: the parameter type `T` must be valid for the anonymous lifetime as defined here... + --> $DIR/async-generics.rs:7:18 + | +LL | async fn foo(&self) -> &(T, U); + | ^ +note: ...so that the reference type `&(T, U)` does not outlive the data it points at + --> $DIR/async-generics.rs:7:28 + | +LL | async fn foo(&self) -> &(T, U); + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0311`. diff --git a/src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.rs b/src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.rs new file mode 100644 index 000000000000..6a2276c96c8c --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.rs @@ -0,0 +1,20 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Debug; + +trait MyTrait<'a, 'b, T> { + async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T) where T: Debug + Sized; +} +//~^^ ERROR the parameter type `Self` may not live long enough +//~| ERROR the parameter type `T` may not live long enough + +impl<'a, 'b, T, U> MyTrait<'a, 'b, T> for U { + async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { + (self, key) + } +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.stderr b/src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.stderr new file mode 100644 index 000000000000..d74f80917a48 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.stderr @@ -0,0 +1,23 @@ +error[E0309]: the parameter type `Self` may not live long enough + --> $DIR/async-lifetimes-and-bounds.rs:9:43 + | +LL | async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T) where T: Debug + Sized; + | ^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `Self: 'a`... + = note: ...so that the reference type `&'a Self` does not outlive the data it points at + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/async-lifetimes-and-bounds.rs:9:43 + | +LL | async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T) where T: Debug + Sized; + | ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'b T` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | trait MyTrait<'a, 'b, T: 'b> { + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/async-await/in-trait/async-lifetimes.rs b/src/test/ui/async-await/in-trait/async-lifetimes.rs new file mode 100644 index 000000000000..1032a3435479 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-lifetimes.rs @@ -0,0 +1,18 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +trait MyTrait<'a, 'b, T> { + async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T); +} +//~^^ ERROR the parameter type `Self` may not live long enough +//~| ERROR the parameter type `T` may not live long enough + +impl<'a, 'b, T, U> MyTrait<'a, 'b, T> for U { + async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { + (self, key) + } +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/async-lifetimes.stderr b/src/test/ui/async-await/in-trait/async-lifetimes.stderr new file mode 100644 index 000000000000..780f75cf683d --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-lifetimes.stderr @@ -0,0 +1,23 @@ +error[E0309]: the parameter type `Self` may not live long enough + --> $DIR/async-lifetimes.rs:7:43 + | +LL | async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `Self: 'a`... + = note: ...so that the reference type `&'a Self` does not outlive the data it points at + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/async-lifetimes.rs:7:43 + | +LL | async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T); + | ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'b T` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | trait MyTrait<'a, 'b, T: 'b> { + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/async-await/in-trait/fn-not-async-err.rs b/src/test/ui/async-await/in-trait/fn-not-async-err.rs new file mode 100644 index 000000000000..f94d32145a29 --- /dev/null +++ b/src/test/ui/async-await/in-trait/fn-not-async-err.rs @@ -0,0 +1,17 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +trait MyTrait { + async fn foo(&self) -> i32; +} + +impl MyTrait for i32 { + fn foo(&self) -> i32 { + //~^ ERROR: `i32` is not a future [E0277] + *self + } +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/fn-not-async-err.stderr b/src/test/ui/async-await/in-trait/fn-not-async-err.stderr new file mode 100644 index 000000000000..03321dc5b5af --- /dev/null +++ b/src/test/ui/async-await/in-trait/fn-not-async-err.stderr @@ -0,0 +1,17 @@ +error[E0277]: `i32` is not a future + --> $DIR/fn-not-async-err.rs:11:22 + | +LL | fn foo(&self) -> i32 { + | ^^^ `i32` is not a future + | + = help: the trait `Future` is not implemented for `i32` + = note: i32 must be a future or must implement `IntoFuture` to be awaited +note: required by a bound in `MyTrait::foo::{opaque#0}` + --> $DIR/fn-not-async-err.rs:7:28 + | +LL | async fn foo(&self) -> i32; + | ^^^ required by this bound in `MyTrait::foo::{opaque#0}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/in-trait/fn-not-async-err2.rs b/src/test/ui/async-await/in-trait/fn-not-async-err2.rs new file mode 100644 index 000000000000..f617a19ab341 --- /dev/null +++ b/src/test/ui/async-await/in-trait/fn-not-async-err2.rs @@ -0,0 +1,21 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; + +trait MyTrait { + async fn foo(&self) -> i32; +} + +impl MyTrait for i32 { + fn foo(&self) -> impl Future { + //~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `impl` method return [E0562] + async { + *self + } + } +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/fn-not-async-err2.stderr b/src/test/ui/async-await/in-trait/fn-not-async-err2.stderr new file mode 100644 index 000000000000..f591f1847729 --- /dev/null +++ b/src/test/ui/async-await/in-trait/fn-not-async-err2.stderr @@ -0,0 +1,12 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return + --> $DIR/fn-not-async-err2.rs:13:22 + | +LL | fn foo(&self) -> impl Future { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. From 8a0ebca97eabaed14a36d90aa25327dcec2fa8b1 Mon Sep 17 00:00:00 2001 From: Bryan Garza <1396101+bryangarza@users.noreply.github.com> Date: Tue, 4 Oct 2022 23:35:49 +0000 Subject: [PATCH 146/171] Update static AFIT tests based on feedback --- .../in-trait/async-associated-types.rs | 2 +- .../async-associated-types2-desugared.rs | 31 --------- .../async-associated-types2-desugared.stderr | 42 ------------- .../in-trait/async-associated-types2.rs | 10 ++- .../in-trait/async-associated-types2.stderr | 63 ------------------- .../in-trait/fn-not-async-err2-rpitit.rs | 22 +++++++ .../async-await/in-trait/fn-not-async-err2.rs | 2 +- 7 files changed, 28 insertions(+), 144 deletions(-) delete mode 100644 src/test/ui/async-await/in-trait/async-associated-types2-desugared.rs delete mode 100644 src/test/ui/async-await/in-trait/async-associated-types2-desugared.stderr delete mode 100644 src/test/ui/async-await/in-trait/async-associated-types2.stderr create mode 100644 src/test/ui/async-await/in-trait/fn-not-async-err2-rpitit.rs diff --git a/src/test/ui/async-await/in-trait/async-associated-types.rs b/src/test/ui/async-await/in-trait/async-associated-types.rs index 0269f00bbab7..8f679190d7a1 100644 --- a/src/test/ui/async-await/in-trait/async-associated-types.rs +++ b/src/test/ui/async-await/in-trait/async-associated-types.rs @@ -6,7 +6,7 @@ use std::fmt::Debug; trait MyTrait<'a, 'b, T> where Self: 'a, T: Debug + Sized + 'b { - type MyAssoc;// = (&'a T, &'b U); + type MyAssoc; async fn foo(&'a self, key: &'b T) -> Self::MyAssoc; } diff --git a/src/test/ui/async-await/in-trait/async-associated-types2-desugared.rs b/src/test/ui/async-await/in-trait/async-associated-types2-desugared.rs deleted file mode 100644 index 85d29eb703e7..000000000000 --- a/src/test/ui/async-await/in-trait/async-associated-types2-desugared.rs +++ /dev/null @@ -1,31 +0,0 @@ -// edition: 2021 - -#![feature(async_fn_in_trait)] -#![allow(incomplete_features)] - -use std::future::Future; - -trait MyTrait { - type Fut<'a>: Future - where - Self: 'a; - - async fn foo(&self) -> Self::Fut<'a>; - //~^ ERROR use of undeclared lifetime name `'a` - //~| ERROR the parameter type `Self` may not live long enough -} - -impl MyTrait for i32 { - type Fut<'a> = impl Future + 'a - where - Self: 'a; - //~^^^ ERROR `impl Trait` in type aliases is unstable - - fn foo<'a>(&'a self) -> Self::Fut<'a> { - async { - *self - } - } -} - -fn main() {} diff --git a/src/test/ui/async-await/in-trait/async-associated-types2-desugared.stderr b/src/test/ui/async-await/in-trait/async-associated-types2-desugared.stderr deleted file mode 100644 index 6bc553b26350..000000000000 --- a/src/test/ui/async-await/in-trait/async-associated-types2-desugared.stderr +++ /dev/null @@ -1,42 +0,0 @@ -error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/async-associated-types2-desugared.rs:13:38 - | -LL | async fn foo(&self) -> Self::Fut<'a>; - | ^^ undeclared lifetime - | -help: consider introducing lifetime `'a` here - | -LL | async fn foo<'a>(&self) -> Self::Fut<'a>; - | ++++ -help: consider introducing lifetime `'a` here - | -LL | trait MyTrait<'a> { - | ++++ - -error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/async-associated-types2-desugared.rs:19:20 - | -LL | type Fut<'a> = impl Future + 'a - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #63063 for more information - = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable - -error[E0310]: the parameter type `Self` may not live long enough - --> $DIR/async-associated-types2-desugared.rs:13:28 - | -LL | async fn foo(&self) -> Self::Fut<'a>; - | ^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `Self: 'static`... - = note: ...so that the type `Self` will meet its required lifetime bounds... -note: ...that is required by this bound - --> $DIR/async-associated-types2-desugared.rs:11:15 - | -LL | Self: 'a; - | ^^ - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0261, E0310, E0658. -For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/async-await/in-trait/async-associated-types2.rs b/src/test/ui/async-await/in-trait/async-associated-types2.rs index c2133b04bc84..e546a0579c66 100644 --- a/src/test/ui/async-await/in-trait/async-associated-types2.rs +++ b/src/test/ui/async-await/in-trait/async-associated-types2.rs @@ -1,6 +1,8 @@ +// check-pass // edition: 2021 #![feature(async_fn_in_trait)] +#![feature(type_alias_impl_trait)] #![allow(incomplete_features)] use std::future::Future; @@ -10,19 +12,15 @@ trait MyTrait { where Self: 'a; - fn foo(&self) -> Self::Fut<'a>; - //~^ ERROR use of undeclared lifetime name `'a` + fn foo<'a>(&'a self) -> Self::Fut<'a>; } impl MyTrait for i32 { - type Fut<'a> = impl Future + 'a + type Fut<'a> = impl Future + 'a where Self: 'a; - //~^^^ ERROR `impl Trait` in type aliases is unstable - //~| ERROR expected `::Fut<'a>` to be a future that resolves to `i32`, but it resolves to `<::Fut<'a> as Future>::Output` fn foo<'a>(&'a self) -> Self::Fut<'a> { - //~^ ERROR `impl` item signature doesn't match `trait` item signature async { *self } diff --git a/src/test/ui/async-await/in-trait/async-associated-types2.stderr b/src/test/ui/async-await/in-trait/async-associated-types2.stderr deleted file mode 100644 index f3343852fa09..000000000000 --- a/src/test/ui/async-await/in-trait/async-associated-types2.stderr +++ /dev/null @@ -1,63 +0,0 @@ -error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/async-associated-types2.rs:13:32 - | -LL | fn foo(&self) -> Self::Fut<'a>; - | ^^ undeclared lifetime - | -help: consider introducing lifetime `'a` here - | -LL | fn foo<'a>(&self) -> Self::Fut<'a>; - | ++++ -help: consider introducing lifetime `'a` here - | -LL | trait MyTrait<'a> { - | ++++ - -error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/async-associated-types2.rs:18:20 - | -LL | type Fut<'a> = impl Future + 'a - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #63063 for more information - = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable - -error[E0271]: expected `::Fut<'a>` to be a future that resolves to `i32`, but it resolves to `<::Fut<'a> as Future>::Output` - --> $DIR/async-associated-types2.rs:18:20 - | -LL | type Fut<'a> = impl Future + 'a - | ^^^^^^^^^^^^^^^^ expected `i32`, found associated type - | - = note: expected type `i32` - found associated type `<::Fut<'a> as Future>::Output` -note: required by a bound in `MyTrait::Fut` - --> $DIR/async-associated-types2.rs:9:26 - | -LL | type Fut<'a>: Future - | ^^^^^^^^^^^^ required by this bound in `MyTrait::Fut` -help: consider constraining the associated type `<::Fut<'a> as Future>::Output` to `i32` - | -LL | type Fut<'a> = impl Future + 'a - | ++++++++++++++ - -error: `impl` item signature doesn't match `trait` item signature - --> $DIR/async-associated-types2.rs:24:5 - | -LL | fn foo(&self) -> Self::Fut<'a>; - | ------------------------------- expected `fn(&'1 i32) -> ::Fut<'static>` -... -LL | fn foo<'a>(&'a self) -> Self::Fut<'a> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 i32) -> ::Fut<'1>` - | - = note: expected `fn(&'1 i32) -> ::Fut<'static>` - found `fn(&'1 i32) -> ::Fut<'1>` -help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` - --> $DIR/async-associated-types2.rs:13:22 - | -LL | fn foo(&self) -> Self::Fut<'a>; - | ^^^^ consider borrowing this type parameter in the trait - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0261, E0271, E0658. -For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/async-await/in-trait/fn-not-async-err2-rpitit.rs b/src/test/ui/async-await/in-trait/fn-not-async-err2-rpitit.rs new file mode 100644 index 000000000000..faf9a43d352d --- /dev/null +++ b/src/test/ui/async-await/in-trait/fn-not-async-err2-rpitit.rs @@ -0,0 +1,22 @@ +// check-pass +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; + +trait MyTrait { + async fn foo(&self) -> i32; +} + +impl MyTrait for i32 { + fn foo(&self) -> impl Future + '_ { + async { + *self + } + } +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/fn-not-async-err2.rs b/src/test/ui/async-await/in-trait/fn-not-async-err2.rs index f617a19ab341..594baa91ad8b 100644 --- a/src/test/ui/async-await/in-trait/fn-not-async-err2.rs +++ b/src/test/ui/async-await/in-trait/fn-not-async-err2.rs @@ -8,7 +8,7 @@ use std::future::Future; trait MyTrait { async fn foo(&self) -> i32; } - + impl MyTrait for i32 { fn foo(&self) -> impl Future { //~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `impl` method return [E0562] From 11b1439380d2e7e915207cb708e78a9060af82b8 Mon Sep 17 00:00:00 2001 From: Bryan Garza <1396101+bryangarza@users.noreply.github.com> Date: Fri, 7 Oct 2022 16:08:56 +0000 Subject: [PATCH 147/171] Update tests based on feedback --- .../in-trait/async-associated-types.rs | 4 ++-- .../in-trait/async-associated-types.stderr | 16 ++++++++-------- .../ui/async-await/in-trait/async-example.rs | 17 ++++++++++++++++- .../in-trait/async-generics-and-bounds.rs | 4 ++-- .../in-trait/async-generics-and-bounds.stderr | 12 ++++++------ .../ui/async-await/in-trait/async-generics.rs | 4 ++-- .../async-await/in-trait/async-generics.stderr | 12 ++++++------ .../in-trait/async-lifetimes-and-bounds.rs | 4 ++-- .../in-trait/async-lifetimes-and-bounds.stderr | 4 ++-- .../ui/async-await/in-trait/async-lifetimes.rs | 4 ++-- 10 files changed, 48 insertions(+), 33 deletions(-) diff --git a/src/test/ui/async-await/in-trait/async-associated-types.rs b/src/test/ui/async-await/in-trait/async-associated-types.rs index 8f679190d7a1..a6f928f3b1ba 100644 --- a/src/test/ui/async-await/in-trait/async-associated-types.rs +++ b/src/test/ui/async-await/in-trait/async-associated-types.rs @@ -1,3 +1,5 @@ +// check-fail +// known-bug: #102682 // edition: 2021 #![feature(async_fn_in_trait)] @@ -18,7 +20,5 @@ impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U { (self, key) } } -//~^^^^ ERROR cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements -//~| ERROR cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements fn main() {} diff --git a/src/test/ui/async-await/in-trait/async-associated-types.stderr b/src/test/ui/async-await/in-trait/async-associated-types.stderr index c1c66f9023bd..0985150eee0d 100644 --- a/src/test/ui/async-await/in-trait/async-associated-types.stderr +++ b/src/test/ui/async-await/in-trait/async-associated-types.stderr @@ -1,16 +1,16 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/async-associated-types.rs:17:43 + --> $DIR/async-associated-types.rs:19:43 | LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { | ^^^^^^^^^^^^^^ | note: first, the lifetime cannot outlive the lifetime `'a` as defined here... - --> $DIR/async-associated-types.rs:14:6 + --> $DIR/async-associated-types.rs:16:6 | LL | impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U { | ^^ note: ...so that the types are compatible - --> $DIR/async-associated-types.rs:17:43 + --> $DIR/async-associated-types.rs:19:43 | LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { | ^^^^^^^^^^^^^^ @@ -18,7 +18,7 @@ LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { found `(&U, &T)` = note: but, the lifetime must be valid for the static lifetime... note: ...so that the types are compatible - --> $DIR/async-associated-types.rs:17:43 + --> $DIR/async-associated-types.rs:19:43 | LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { | ^^^^^^^^^^^^^^ @@ -26,18 +26,18 @@ LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { found `MyTrait<'_, '_, T>` error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements - --> $DIR/async-associated-types.rs:17:43 + --> $DIR/async-associated-types.rs:19:43 | LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { | ^^^^^^^^^^^^^^ | note: first, the lifetime cannot outlive the lifetime `'b` as defined here... - --> $DIR/async-associated-types.rs:14:10 + --> $DIR/async-associated-types.rs:16:10 | LL | impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U { | ^^ note: ...so that the types are compatible - --> $DIR/async-associated-types.rs:17:43 + --> $DIR/async-associated-types.rs:19:43 | LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { | ^^^^^^^^^^^^^^ @@ -45,7 +45,7 @@ LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { found `(&U, &T)` = note: but, the lifetime must be valid for the static lifetime... note: ...so that the types are compatible - --> $DIR/async-associated-types.rs:17:43 + --> $DIR/async-associated-types.rs:19:43 | LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { | ^^^^^^^^^^^^^^ diff --git a/src/test/ui/async-await/in-trait/async-example.rs b/src/test/ui/async-await/in-trait/async-example.rs index 2c2297c6b584..10387f09f0e9 100644 --- a/src/test/ui/async-await/in-trait/async-example.rs +++ b/src/test/ui/async-await/in-trait/async-example.rs @@ -6,12 +6,27 @@ trait MyTrait { async fn foo(&self) -> i32; + async fn bar(&self) -> i32; } impl MyTrait for i32 { async fn foo(&self) -> i32 { *self } + + async fn bar(&self) -> i32 { + self.foo().await + } } -fn main() {} +fn main() { + let x = 5; + // Calling from non-async context + let _ = x.foo(); + let _ = x.bar(); + // Calling from async block in non-async context + async { + let _ = x.foo(); + let _ = x.bar(); + }; +} diff --git a/src/test/ui/async-await/in-trait/async-generics-and-bounds.rs b/src/test/ui/async-await/in-trait/async-generics-and-bounds.rs index d748430c5ee8..a73d55adfece 100644 --- a/src/test/ui/async-await/in-trait/async-generics-and-bounds.rs +++ b/src/test/ui/async-await/in-trait/async-generics-and-bounds.rs @@ -1,3 +1,5 @@ +// check-fail +// known-bug: #102682 // edition: 2021 #![feature(async_fn_in_trait)] @@ -9,8 +11,6 @@ use std::hash::Hash; trait MyTrait { async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; } -//~^^ ERROR the parameter type `U` may not live long enough -//~| ERROR the parameter type `T` may not live long enough impl MyTrait for (T, U) { async fn foo(&self) -> &(T, U) { diff --git a/src/test/ui/async-await/in-trait/async-generics-and-bounds.stderr b/src/test/ui/async-await/in-trait/async-generics-and-bounds.stderr index 8975ec21a015..5c8d64fc6cb4 100644 --- a/src/test/ui/async-await/in-trait/async-generics-and-bounds.stderr +++ b/src/test/ui/async-await/in-trait/async-generics-and-bounds.stderr @@ -1,33 +1,33 @@ error[E0311]: the parameter type `U` may not live long enough - --> $DIR/async-generics-and-bounds.rs:10:28 + --> $DIR/async-generics-and-bounds.rs:12:28 | LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; | ^^^^^^^ | note: the parameter type `U` must be valid for the anonymous lifetime as defined here... - --> $DIR/async-generics-and-bounds.rs:10:18 + --> $DIR/async-generics-and-bounds.rs:12:18 | LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; | ^ note: ...so that the reference type `&(T, U)` does not outlive the data it points at - --> $DIR/async-generics-and-bounds.rs:10:28 + --> $DIR/async-generics-and-bounds.rs:12:28 | LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; | ^^^^^^^ error[E0311]: the parameter type `T` may not live long enough - --> $DIR/async-generics-and-bounds.rs:10:28 + --> $DIR/async-generics-and-bounds.rs:12:28 | LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; | ^^^^^^^ | note: the parameter type `T` must be valid for the anonymous lifetime as defined here... - --> $DIR/async-generics-and-bounds.rs:10:18 + --> $DIR/async-generics-and-bounds.rs:12:18 | LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; | ^ note: ...so that the reference type `&(T, U)` does not outlive the data it points at - --> $DIR/async-generics-and-bounds.rs:10:28 + --> $DIR/async-generics-and-bounds.rs:12:28 | LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; | ^^^^^^^ diff --git a/src/test/ui/async-await/in-trait/async-generics.rs b/src/test/ui/async-await/in-trait/async-generics.rs index 3e6f70cd49f6..67000e5770ee 100644 --- a/src/test/ui/async-await/in-trait/async-generics.rs +++ b/src/test/ui/async-await/in-trait/async-generics.rs @@ -1,3 +1,5 @@ +// check-fail +// known-bug: #102682 // edition: 2021 #![feature(async_fn_in_trait)] @@ -6,8 +8,6 @@ trait MyTrait { async fn foo(&self) -> &(T, U); } -//~^^ ERROR the parameter type `U` may not live long enough -//~| ERROR the parameter type `T` may not live long enough impl MyTrait for (T, U) { async fn foo(&self) -> &(T, U) { diff --git a/src/test/ui/async-await/in-trait/async-generics.stderr b/src/test/ui/async-await/in-trait/async-generics.stderr index 84c7b3095368..6ae73d9e3a60 100644 --- a/src/test/ui/async-await/in-trait/async-generics.stderr +++ b/src/test/ui/async-await/in-trait/async-generics.stderr @@ -1,33 +1,33 @@ error[E0311]: the parameter type `U` may not live long enough - --> $DIR/async-generics.rs:7:28 + --> $DIR/async-generics.rs:9:28 | LL | async fn foo(&self) -> &(T, U); | ^^^^^^^ | note: the parameter type `U` must be valid for the anonymous lifetime as defined here... - --> $DIR/async-generics.rs:7:18 + --> $DIR/async-generics.rs:9:18 | LL | async fn foo(&self) -> &(T, U); | ^ note: ...so that the reference type `&(T, U)` does not outlive the data it points at - --> $DIR/async-generics.rs:7:28 + --> $DIR/async-generics.rs:9:28 | LL | async fn foo(&self) -> &(T, U); | ^^^^^^^ error[E0311]: the parameter type `T` may not live long enough - --> $DIR/async-generics.rs:7:28 + --> $DIR/async-generics.rs:9:28 | LL | async fn foo(&self) -> &(T, U); | ^^^^^^^ | note: the parameter type `T` must be valid for the anonymous lifetime as defined here... - --> $DIR/async-generics.rs:7:18 + --> $DIR/async-generics.rs:9:18 | LL | async fn foo(&self) -> &(T, U); | ^ note: ...so that the reference type `&(T, U)` does not outlive the data it points at - --> $DIR/async-generics.rs:7:28 + --> $DIR/async-generics.rs:9:28 | LL | async fn foo(&self) -> &(T, U); | ^^^^^^^ diff --git a/src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.rs b/src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.rs index 6a2276c96c8c..3f7448cecd15 100644 --- a/src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.rs +++ b/src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.rs @@ -1,3 +1,5 @@ +// check-fail +// known-bug: #102682 // edition: 2021 #![feature(async_fn_in_trait)] @@ -8,8 +10,6 @@ use std::fmt::Debug; trait MyTrait<'a, 'b, T> { async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T) where T: Debug + Sized; } -//~^^ ERROR the parameter type `Self` may not live long enough -//~| ERROR the parameter type `T` may not live long enough impl<'a, 'b, T, U> MyTrait<'a, 'b, T> for U { async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { diff --git a/src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.stderr b/src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.stderr index d74f80917a48..0f0242027433 100644 --- a/src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.stderr +++ b/src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.stderr @@ -1,5 +1,5 @@ error[E0309]: the parameter type `Self` may not live long enough - --> $DIR/async-lifetimes-and-bounds.rs:9:43 + --> $DIR/async-lifetimes-and-bounds.rs:11:43 | LL | async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T) where T: Debug + Sized; | ^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T) where T: Debug = note: ...so that the reference type `&'a Self` does not outlive the data it points at error[E0309]: the parameter type `T` may not live long enough - --> $DIR/async-lifetimes-and-bounds.rs:9:43 + --> $DIR/async-lifetimes-and-bounds.rs:11:43 | LL | async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T) where T: Debug + Sized; | ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'b T` does not outlive the data it points at diff --git a/src/test/ui/async-await/in-trait/async-lifetimes.rs b/src/test/ui/async-await/in-trait/async-lifetimes.rs index 1032a3435479..5dc1672da68f 100644 --- a/src/test/ui/async-await/in-trait/async-lifetimes.rs +++ b/src/test/ui/async-await/in-trait/async-lifetimes.rs @@ -5,9 +5,9 @@ trait MyTrait<'a, 'b, T> { async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T); + //~^ ERROR the parameter type `Self` may not live long enough + //~| ERROR the parameter type `T` may not live long enough } -//~^^ ERROR the parameter type `Self` may not live long enough -//~| ERROR the parameter type `T` may not live long enough impl<'a, 'b, T, U> MyTrait<'a, 'b, T> for U { async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { From 9a05081d5fb13b3bee9d41b43692c9f38d521c96 Mon Sep 17 00:00:00 2001 From: Bryan Garza <1396101+bryangarza@users.noreply.github.com> Date: Fri, 7 Oct 2022 16:15:13 +0000 Subject: [PATCH 148/171] Add additional tests for static AFIT --- .../async-example-desugared-boxed-in-trait.rs | 21 +++++++++++++++++ ...nc-example-desugared-boxed-in-trait.stderr | 17 ++++++++++++++ .../in-trait/async-example-desugared-boxed.rs | 23 +++++++++++++++++++ .../async-example-desugared-in-trait.rs | 20 ++++++++++++++++ .../in-trait/async-example-desugared.rs | 22 ++++++++++++++++++ .../in-trait/async-recursive-generic.rs | 21 +++++++++++++++++ .../in-trait/async-recursive-generic.stderr | 12 ++++++++++ .../async-await/in-trait/async-recursive.rs | 21 +++++++++++++++++ .../in-trait/async-recursive.stderr | 12 ++++++++++ 9 files changed, 169 insertions(+) create mode 100644 src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs create mode 100644 src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr create mode 100644 src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs create mode 100644 src/test/ui/async-await/in-trait/async-example-desugared-in-trait.rs create mode 100644 src/test/ui/async-await/in-trait/async-example-desugared.rs create mode 100644 src/test/ui/async-await/in-trait/async-recursive-generic.rs create mode 100644 src/test/ui/async-await/in-trait/async-recursive-generic.stderr create mode 100644 src/test/ui/async-await/in-trait/async-recursive.rs create mode 100644 src/test/ui/async-await/in-trait/async-recursive.stderr diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs b/src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs new file mode 100644 index 000000000000..38ba297189c6 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs @@ -0,0 +1,21 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; +use std::pin::Pin; + +trait MyTrait { + fn foo(&self) -> Pin + '_>>; +} + +impl MyTrait for i32 { + async fn foo(&self) -> i32 { + //~^ ERROR method `foo` has an incompatible type for trait + *self + } +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr b/src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr new file mode 100644 index 000000000000..22d2928f2f56 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr @@ -0,0 +1,17 @@ +error[E0053]: method `foo` has an incompatible type for trait + --> $DIR/async-example-desugared-boxed-in-trait.rs:15:28 + | +LL | async fn foo(&self) -> i32 { + | ^^^ expected struct `Pin`, found opaque type + | +note: type in trait + --> $DIR/async-example-desugared-boxed-in-trait.rs:11:22 + | +LL | fn foo(&self) -> Pin + '_>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected fn pointer `fn(&i32) -> Pin>>` + found fn pointer `fn(&i32) -> impl Future` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs b/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs new file mode 100644 index 000000000000..e1131753885b --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs @@ -0,0 +1,23 @@ +// check-pass +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; +use std::pin::Pin; + +trait MyTrait { + async fn foo(&self) -> i32; +} + +impl MyTrait for i32 { + fn foo(&self) -> Pin + '_>> { + Box::pin(async { + *self + }) + } +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-in-trait.rs b/src/test/ui/async-await/in-trait/async-example-desugared-in-trait.rs new file mode 100644 index 000000000000..6f61781709e7 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-example-desugared-in-trait.rs @@ -0,0 +1,20 @@ +// check-pass +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; + +trait MyTrait { + fn foo(&self) -> impl Future + '_; +} + +impl MyTrait for i32 { + async fn foo(&self) -> i32 { + *self + } +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/async-example-desugared.rs b/src/test/ui/async-await/in-trait/async-example-desugared.rs new file mode 100644 index 000000000000..faf9a43d352d --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-example-desugared.rs @@ -0,0 +1,22 @@ +// check-pass +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; + +trait MyTrait { + async fn foo(&self) -> i32; +} + +impl MyTrait for i32 { + fn foo(&self) -> impl Future + '_ { + async { + *self + } + } +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/async-recursive-generic.rs b/src/test/ui/async-await/in-trait/async-recursive-generic.rs new file mode 100644 index 000000000000..6839abd381c3 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-recursive-generic.rs @@ -0,0 +1,21 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +trait MyTrait { + async fn foo_recursive(&self, n: usize) -> T; +} + +impl MyTrait for T where T: Copy { + async fn foo_recursive(&self, n: usize) -> T { + //~^ ERROR recursion in an `async fn` requires boxing + if n > 0 { + self.foo_recursive(n - 1).await + } else { + *self + } + } +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/async-recursive-generic.stderr b/src/test/ui/async-await/in-trait/async-recursive-generic.stderr new file mode 100644 index 000000000000..cab173bdd5b7 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-recursive-generic.stderr @@ -0,0 +1,12 @@ +error[E0733]: recursion in an `async fn` requires boxing + --> $DIR/async-recursive-generic.rs:11:48 + | +LL | async fn foo_recursive(&self, n: usize) -> T { + | ^ recursive `async fn` + | + = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` + = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0733`. diff --git a/src/test/ui/async-await/in-trait/async-recursive.rs b/src/test/ui/async-await/in-trait/async-recursive.rs new file mode 100644 index 000000000000..61119f8095bc --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-recursive.rs @@ -0,0 +1,21 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +trait MyTrait { + async fn foo_recursive(&self, n: usize) -> i32; +} + +impl MyTrait for i32 { + async fn foo_recursive(&self, n: usize) -> i32 { + //~^ ERROR recursion in an `async fn` requires boxing + if n > 0 { + self.foo_recursive(n - 1).await + } else { + *self + } + } +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/async-recursive.stderr b/src/test/ui/async-await/in-trait/async-recursive.stderr new file mode 100644 index 000000000000..9feff37b3fe4 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-recursive.stderr @@ -0,0 +1,12 @@ +error[E0733]: recursion in an `async fn` requires boxing + --> $DIR/async-recursive.rs:11:48 + | +LL | async fn foo_recursive(&self, n: usize) -> i32 { + | ^^^ recursive `async fn` + | + = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` + = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0733`. From 0b3b04643624027aadc891212dacfdcfa931ed0b Mon Sep 17 00:00:00 2001 From: Bryan Garza <1396101+bryangarza@users.noreply.github.com> Date: Thu, 27 Oct 2022 15:47:30 -0700 Subject: [PATCH 149/171] Update src/test/ui/async-await/in-trait/async-example.rs Co-authored-by: Michael Goulet --- src/test/ui/async-await/in-trait/async-example.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/async-await/in-trait/async-example.rs b/src/test/ui/async-await/in-trait/async-example.rs index 10387f09f0e9..abf94ef7450f 100644 --- a/src/test/ui/async-await/in-trait/async-example.rs +++ b/src/test/ui/async-await/in-trait/async-example.rs @@ -26,7 +26,7 @@ fn main() { let _ = x.bar(); // Calling from async block in non-async context async { - let _ = x.foo(); - let _ = x.bar(); + let _: i32 = x.foo().await; + let _: i32 = x.bar().await; }; } From bfdefdbfb740a2b41dbdf01299ecdf1610c54907 Mon Sep 17 00:00:00 2001 From: Bryan Garza <1396101+bryangarza@users.noreply.github.com> Date: Thu, 27 Oct 2022 22:55:50 +0000 Subject: [PATCH 150/171] Update tests based on feedback - Add comment to some tests that will break when #102745 is implemented - Mark a test with known-bug - Delete duplicate test --- .../in-trait/async-example-desugared-boxed.rs | 1 + .../async-example-desugared-in-trait.rs | 1 + .../in-trait/async-example-desugared.rs | 1 + .../async-await/in-trait/async-lifetimes.rs | 4 ++-- .../in-trait/async-lifetimes.stderr | 4 ++-- .../in-trait/fn-not-async-err2-rpitit.rs | 22 ------------------- 6 files changed, 7 insertions(+), 26 deletions(-) delete mode 100644 src/test/ui/async-await/in-trait/fn-not-async-err2-rpitit.rs diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs b/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs index e1131753885b..61d7e2520eab 100644 --- a/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs +++ b/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs @@ -13,6 +13,7 @@ trait MyTrait { } impl MyTrait for i32 { + // This will break once a PR that implements #102745 is merged fn foo(&self) -> Pin + '_>> { Box::pin(async { *self diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-in-trait.rs b/src/test/ui/async-await/in-trait/async-example-desugared-in-trait.rs index 6f61781709e7..feeda719e030 100644 --- a/src/test/ui/async-await/in-trait/async-example-desugared-in-trait.rs +++ b/src/test/ui/async-await/in-trait/async-example-desugared-in-trait.rs @@ -12,6 +12,7 @@ trait MyTrait { } impl MyTrait for i32 { + // This will break once a PR that implements #102745 is merged async fn foo(&self) -> i32 { *self } diff --git a/src/test/ui/async-await/in-trait/async-example-desugared.rs b/src/test/ui/async-await/in-trait/async-example-desugared.rs index faf9a43d352d..1313c9edd861 100644 --- a/src/test/ui/async-await/in-trait/async-example-desugared.rs +++ b/src/test/ui/async-await/in-trait/async-example-desugared.rs @@ -12,6 +12,7 @@ trait MyTrait { } impl MyTrait for i32 { + // This will break once a PR that implements #102745 is merged fn foo(&self) -> impl Future + '_ { async { *self diff --git a/src/test/ui/async-await/in-trait/async-lifetimes.rs b/src/test/ui/async-await/in-trait/async-lifetimes.rs index 5dc1672da68f..acbac471cf7e 100644 --- a/src/test/ui/async-await/in-trait/async-lifetimes.rs +++ b/src/test/ui/async-await/in-trait/async-lifetimes.rs @@ -1,3 +1,5 @@ +// check-fail +// known-bug: #102682 // edition: 2021 #![feature(async_fn_in_trait)] @@ -5,8 +7,6 @@ trait MyTrait<'a, 'b, T> { async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T); - //~^ ERROR the parameter type `Self` may not live long enough - //~| ERROR the parameter type `T` may not live long enough } impl<'a, 'b, T, U> MyTrait<'a, 'b, T> for U { diff --git a/src/test/ui/async-await/in-trait/async-lifetimes.stderr b/src/test/ui/async-await/in-trait/async-lifetimes.stderr index 780f75cf683d..9a7d294bb176 100644 --- a/src/test/ui/async-await/in-trait/async-lifetimes.stderr +++ b/src/test/ui/async-await/in-trait/async-lifetimes.stderr @@ -1,5 +1,5 @@ error[E0309]: the parameter type `Self` may not live long enough - --> $DIR/async-lifetimes.rs:7:43 + --> $DIR/async-lifetimes.rs:9:43 | LL | async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T); | ^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T); = note: ...so that the reference type `&'a Self` does not outlive the data it points at error[E0309]: the parameter type `T` may not live long enough - --> $DIR/async-lifetimes.rs:7:43 + --> $DIR/async-lifetimes.rs:9:43 | LL | async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T); | ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'b T` does not outlive the data it points at diff --git a/src/test/ui/async-await/in-trait/fn-not-async-err2-rpitit.rs b/src/test/ui/async-await/in-trait/fn-not-async-err2-rpitit.rs deleted file mode 100644 index faf9a43d352d..000000000000 --- a/src/test/ui/async-await/in-trait/fn-not-async-err2-rpitit.rs +++ /dev/null @@ -1,22 +0,0 @@ -// check-pass -// edition: 2021 - -#![feature(async_fn_in_trait)] -#![feature(return_position_impl_trait_in_trait)] -#![allow(incomplete_features)] - -use std::future::Future; - -trait MyTrait { - async fn foo(&self) -> i32; -} - -impl MyTrait for i32 { - fn foo(&self) -> impl Future + '_ { - async { - *self - } - } -} - -fn main() {} From 509d8ad454ee48d6b8f24728755d8ed9ec9628c8 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 27 Oct 2022 13:36:27 -0700 Subject: [PATCH 151/171] rustdoc: remove redundant `div.search-container` This wrapper DIV was originally added in 89e1fb322321c05497caa01372ceb7d5b57fa680, when it allowed the search bar's size to be calculated without using `calc()`. This `width` hack can be removed using flexbox. --- src/librustdoc/html/static/css/rustdoc.css | 19 +++++------- src/librustdoc/html/static/js/main.js | 2 +- src/librustdoc/html/templates/page.html | 34 ++++++++++------------ 3 files changed, 24 insertions(+), 31 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 934334e0c88b..65f6a79d5892 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -679,13 +679,16 @@ nav.sub { display: flex; align-items: center; } -nav.sub form { +.search-form { + position: relative; + display: flex; + height: 34px; flex-grow: 1; } .source nav.sub { margin: 0 0 15px 0; } -.source nav.sub form { +.source .search-form { margin-left: 32px; } @@ -776,11 +779,6 @@ table, padding-right: 1.25rem; } -.search-container { - position: relative; - display: flex; - height: 34px; -} .search-results-title { margin-top: 0; white-space: nowrap; @@ -856,15 +854,12 @@ so that we can apply CSS-filters to change the arrow color in themes */ -webkit-appearance: textfield for search inputs. That causes rounded corners and no border on iOS Safari. */ -webkit-appearance: none; - /* Override Normalize.css: we have margins and do - not want to overflow */ - box-sizing: border-box !important; outline: none; border: 1px solid var(--border-color); border-radius: 2px; padding: 8px; font-size: 1rem; - width: 100%; + flex-grow: 1; background-color: var(--button-background-color); color: var(--search-color); } @@ -1951,7 +1946,7 @@ in storage.js flex-direction: column; } - nav.sub form { + .search-form { align-self: stretch; } diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 0b816eace64b..33480fa41cf0 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -932,7 +932,7 @@ function loadCss(cssFileName) { * Hide all the popover menus. */ window.hidePopoverMenus = function() { - onEachLazy(document.querySelectorAll(".search-container .popover"), elem => { + onEachLazy(document.querySelectorAll(".search-form .popover"), elem => { elem.style.display = "none"; }); }; diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index ee8938ea6030..c32386916878 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -115,24 +115,22 @@ {#- -#} {%- endif -%}

{#- -#} -
{#- -#} - {#- This empty span is a hacky fix for Safari - See #93184 -#} - {#- -#} -
{#- -#} - ? {#- -#} -
{#- -#} -
{#- -#} - {#- -#} - Change settings {#- -#} - {#- -#} -
{#- -#} + {#- This empty span is a hacky fix for Safari - See #93184 -#} + {#- -#} +
{#- -#} + ? {#- -#} +
{#- -#} +
{#- -#} + {#- -#} + Change settings {#- -#} + {#- -#}
{#- -#} {#- -#} {#- -#} From 92b314ba30c396fab7e4ffeabf3ebf3f6101516a Mon Sep 17 00:00:00 2001 From: Rageking8 Date: Fri, 21 Oct 2022 18:37:35 +0800 Subject: [PATCH 152/171] add test for issue 98634 --- src/test/ui/async-await/issue-98634.rs | 50 ++++++++++++++++++ src/test/ui/async-await/issue-98634.stderr | 60 ++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 src/test/ui/async-await/issue-98634.rs create mode 100644 src/test/ui/async-await/issue-98634.stderr diff --git a/src/test/ui/async-await/issue-98634.rs b/src/test/ui/async-await/issue-98634.rs new file mode 100644 index 000000000000..b0d38687f01c --- /dev/null +++ b/src/test/ui/async-await/issue-98634.rs @@ -0,0 +1,50 @@ +// edition: 2021 + +use std::{ + future::Future, + pin::Pin, + task::{Context, Poll, Waker}, +}; + +pub struct StructAsync Pin>>> { + pub callback: F, +} + +impl Future for StructAsync +where + F: Fn() -> Pin>>, +{ + type Output = (); + + fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { + Poll::Pending + } +} + +async fn callback() {} + +struct Runtime; + +fn waker() -> &'static Waker { + todo!() +} + +impl Runtime { + #[track_caller] + pub fn block_on(&self, mut future: F) -> F::Output { + loop { + unsafe { + Pin::new_unchecked(&mut future).poll(&mut Context::from_waker(waker())); + } + } + } +} + +fn main() { + Runtime.block_on(async { + StructAsync { callback }.await; + //~^ ERROR expected `fn() -> impl Future {callback}` to be a fn item that returns `Pin + 'static)>>`, but it returns `impl Future` + //~| ERROR expected `fn() -> impl Future {callback}` to be a fn item that returns `Pin + 'static)>>`, but it returns `impl Future` + //~| ERROR expected `fn() -> impl Future {callback}` to be a fn item that returns `Pin + 'static)>>`, but it returns `impl Future` + }); +} diff --git a/src/test/ui/async-await/issue-98634.stderr b/src/test/ui/async-await/issue-98634.stderr new file mode 100644 index 000000000000..5160e48d88af --- /dev/null +++ b/src/test/ui/async-await/issue-98634.stderr @@ -0,0 +1,60 @@ +error[E0271]: expected `fn() -> impl Future {callback}` to be a fn item that returns `Pin + 'static)>>`, but it returns `impl Future` + --> $DIR/issue-98634.rs:45:23 + | +LL | StructAsync { callback }.await; + | ^^^^^^^^ expected struct `Pin`, found opaque type + | +note: while checking the return type of the `async fn` + --> $DIR/issue-98634.rs:24:21 + | +LL | async fn callback() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected struct `Pin + 'static)>>` + found opaque type `impl Future` +note: required by a bound in `StructAsync` + --> $DIR/issue-98634.rs:9:35 + | +LL | pub struct StructAsync Pin>>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StructAsync` + +error[E0271]: expected `fn() -> impl Future {callback}` to be a fn item that returns `Pin + 'static)>>`, but it returns `impl Future` + --> $DIR/issue-98634.rs:45:9 + | +LL | StructAsync { callback }.await; + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Pin`, found opaque type + | +note: while checking the return type of the `async fn` + --> $DIR/issue-98634.rs:24:21 + | +LL | async fn callback() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected struct `Pin + 'static)>>` + found opaque type `impl Future` +note: required by a bound in `StructAsync` + --> $DIR/issue-98634.rs:9:35 + | +LL | pub struct StructAsync Pin>>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StructAsync` + +error[E0271]: expected `fn() -> impl Future {callback}` to be a fn item that returns `Pin + 'static)>>`, but it returns `impl Future` + --> $DIR/issue-98634.rs:45:33 + | +LL | StructAsync { callback }.await; + | ^^^^^^ expected struct `Pin`, found opaque type + | +note: while checking the return type of the `async fn` + --> $DIR/issue-98634.rs:24:21 + | +LL | async fn callback() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected struct `Pin + 'static)>>` + found opaque type `impl Future` +note: required by a bound in `StructAsync` + --> $DIR/issue-98634.rs:9:35 + | +LL | pub struct StructAsync Pin>>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StructAsync` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0271`. From 064ad83cc3555fc2ca747cffaf0445365acb866c Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Fri, 28 Oct 2022 01:43:37 +0100 Subject: [PATCH 153/171] rustdoc-json-types: Improve ItemSummary::path docs --- src/rustdoc-json-types/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 7379b04ad167..4bc91fc4030e 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -51,6 +51,11 @@ pub struct ItemSummary { pub crate_id: u32, /// The list of path components for the fully qualified path of this item (e.g. /// `["std", "io", "lazy", "Lazy"]` for `std::io::lazy::Lazy`). + /// + /// Note that items can appear in multiple paths, and the one chosen is implementation + /// defined. Currenty, this is the full path to where the item was defined. Eg + /// [`String`] is currently `["alloc", "string", "String"]` and [`HashMap`] is + /// `["std", "collections", "hash", "map", "HashMap"]`, but this is subject to change. pub path: Vec, /// Whether this item is a struct, trait, macro, etc. pub kind: ItemKind, From a990b4c1d04921e346a8d56c0f0efed0121b4bce Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Fri, 28 Oct 2022 11:46:12 +0000 Subject: [PATCH 154/171] Retain ParamEnv constness when running deferred cast checks Fixes #103677. --- compiler/rustc_hir_typeck/src/cast.rs | 5 ++++- compiler/rustc_hir_typeck/src/expr.rs | 10 +++++++++- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 15 +++++++++++++-- .../ui/rfc-2632-const-trait-impl/issue-103677.rs | 5 +++++ .../clippy/clippy_lints/src/transmute/utils.rs | 3 ++- 5 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/issue-103677.rs diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 0e7576ecf8b0..60157c3b9abe 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -60,6 +60,8 @@ pub struct CastCheck<'tcx> { cast_ty: Ty<'tcx>, cast_span: Span, span: Span, + /// whether the cast is made in a const context or not. + pub constness: hir::Constness, } /// The kind of pointer and associated metadata (thin, length or vtable) - we @@ -210,9 +212,10 @@ impl<'a, 'tcx> CastCheck<'tcx> { cast_ty: Ty<'tcx>, cast_span: Span, span: Span, + constness: hir::Constness, ) -> Result, ErrorGuaranteed> { let expr_span = expr.span.find_ancestor_inside(span).unwrap_or(expr.span); - let check = CastCheck { expr, expr_ty, expr_span, cast_ty, cast_span, span }; + let check = CastCheck { expr, expr_ty, expr_span, cast_ty, cast_span, span, constness }; // For better error messages, check for some obviously unsized // cases now. We do a more thorough check at the end, once diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 41b00fda03eb..9fde62a81a1a 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1272,7 +1272,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { // Defer other checks until we're done type checking. let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut(); - match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) { + match cast::CastCheck::new( + self, + e, + t_expr, + t_cast, + t.span, + expr.span, + self.param_env.constness(), + ) { Ok(cast_check) => { debug!( "check_expr_cast: deferring cast from {:?} to {:?}: {:?}", diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 08a3cbccfb05..8e0fcb56c7f3 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -33,16 +33,27 @@ use rustc_span::{self, sym, Span}; use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext}; use std::iter; +use std::mem; use std::ops::ControlFlow; use std::slice; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub(in super::super) fn check_casts(&self) { - let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut(); + pub(in super::super) fn check_casts(&mut self) { + // don't hold the borrow to deferred_cast_checks while checking to avoid borrow checker errors + // when writing to `self.param_env`. + let mut deferred_cast_checks = mem::take(&mut *self.deferred_cast_checks.borrow_mut()); + debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len()); for cast in deferred_cast_checks.drain(..) { + let prev_env = self.param_env; + self.param_env = self.param_env.with_constness(cast.constness); + cast.check(self); + + self.param_env = prev_env; } + + *self.deferred_cast_checks.borrow_mut() = deferred_cast_checks; } pub(in super::super) fn check_transmutes(&self) { diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-103677.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-103677.rs new file mode 100644 index 000000000000..d81724a3685a --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/issue-103677.rs @@ -0,0 +1,5 @@ +// check-pass + +const _: fn(&String) = |s| { &*s as &str; }; + +fn main() {} diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs index 2f190e594a83..641cdf5d330e 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs @@ -3,6 +3,7 @@ use rustc_hir_typeck::{cast, FnCtxt, Inherited}; use rustc_lint::LateContext; use rustc_middle::ty::{cast::CastKind, Ty}; use rustc_span::DUMMY_SP; +use rustc_hir as hir; // check if the component types of the transmuted collection and the result have different ABI, // size or alignment @@ -56,7 +57,7 @@ fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx> if let Ok(check) = cast::CastCheck::new( &fn_ctxt, e, from_ty, to_ty, // We won't show any error to the user, so we don't care what the span is here. - DUMMY_SP, DUMMY_SP, + DUMMY_SP, DUMMY_SP, hir::Constness::NotConst, ) { let res = check.do_check(&fn_ctxt); From b3f9277a17e455d51b1c8c88f56e224e37b4159c Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Fri, 28 Oct 2022 14:17:34 +0200 Subject: [PATCH 155/171] Remove unneeded attribute. --- library/core/src/ffi/c_str.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 9f7c960d88fe..8923f548adf7 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -250,7 +250,6 @@ impl CStr { #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")] - #[rustc_allow_const_fn_unstable(const_eval_select)] pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr { // SAFETY: The caller has provided a pointer that points to a valid C // string with a NUL terminator of size less than `isize::MAX`, whose From c4420135fe148b25d0ac070a6d58d38ccae4625a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 28 Oct 2022 17:32:34 +0000 Subject: [PATCH 156/171] Emit proper error when casting to Ddyn-star --- compiler/rustc_hir_typeck/src/cast.rs | 8 +++++- .../ui/dyn-star/no-explicit-dyn-star-cast.rs | 13 +++++++++ .../dyn-star/no-explicit-dyn-star-cast.stderr | 28 +++++++++++++++++++ src/test/ui/dyn-star/no-explicit-dyn-star.rs | 8 ++++++ .../ui/dyn-star/no-explicit-dyn-star.stderr | 9 ++++++ 5 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/dyn-star/no-explicit-dyn-star-cast.rs create mode 100644 src/test/ui/dyn-star/no-explicit-dyn-star-cast.stderr create mode 100644 src/test/ui/dyn-star/no-explicit-dyn-star.rs create mode 100644 src/test/ui/dyn-star/no-explicit-dyn-star.stderr diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 0e7576ecf8b0..8ce1d8342b42 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -866,7 +866,13 @@ impl<'a, 'tcx> CastCheck<'tcx> { (Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast), - (_, DynStar) | (DynStar, _) => bug!("should be handled by `try_coerce`"), + (_, DynStar) | (DynStar, _) => { + if fcx.tcx.features().dyn_star { + bug!("should be handled by `try_coerce`") + } else { + Err(CastError::IllegalCast) + } + } } } diff --git a/src/test/ui/dyn-star/no-explicit-dyn-star-cast.rs b/src/test/ui/dyn-star/no-explicit-dyn-star-cast.rs new file mode 100644 index 000000000000..67240c8e8da0 --- /dev/null +++ b/src/test/ui/dyn-star/no-explicit-dyn-star-cast.rs @@ -0,0 +1,13 @@ +use std::fmt::Debug; + +fn make_dyn_star() { + let i = 42usize; + let dyn_i: dyn* Debug = i as dyn* Debug; + //~^ ERROR casting `usize` as `dyn* Debug` is invalid + //~| ERROR dyn* trait objects are unstable + //~| ERROR dyn* trait objects are unstable +} + +fn main() { + make_dyn_star(); +} diff --git a/src/test/ui/dyn-star/no-explicit-dyn-star-cast.stderr b/src/test/ui/dyn-star/no-explicit-dyn-star-cast.stderr new file mode 100644 index 000000000000..687d7db04647 --- /dev/null +++ b/src/test/ui/dyn-star/no-explicit-dyn-star-cast.stderr @@ -0,0 +1,28 @@ +error[E0658]: dyn* trait objects are unstable + --> $DIR/no-explicit-dyn-star-cast.rs:5:16 + | +LL | let dyn_i: dyn* Debug = i as dyn* Debug; + | ^^^^^^^^^^ + | + = note: see issue #91611 for more information + = help: add `#![feature(dyn_star)]` to the crate attributes to enable + +error[E0658]: dyn* trait objects are unstable + --> $DIR/no-explicit-dyn-star-cast.rs:5:34 + | +LL | let dyn_i: dyn* Debug = i as dyn* Debug; + | ^^^^^^^^^^ + | + = note: see issue #91611 for more information + = help: add `#![feature(dyn_star)]` to the crate attributes to enable + +error[E0606]: casting `usize` as `dyn* Debug` is invalid + --> $DIR/no-explicit-dyn-star-cast.rs:5:29 + | +LL | let dyn_i: dyn* Debug = i as dyn* Debug; + | ^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0606, E0658. +For more information about an error, try `rustc --explain E0606`. diff --git a/src/test/ui/dyn-star/no-explicit-dyn-star.rs b/src/test/ui/dyn-star/no-explicit-dyn-star.rs new file mode 100644 index 000000000000..4f726b7c6a69 --- /dev/null +++ b/src/test/ui/dyn-star/no-explicit-dyn-star.rs @@ -0,0 +1,8 @@ +// aux-build:dyn-star-foreign.rs + +extern crate dyn_star_foreign; + +fn main() { + dyn_star_foreign::require_dyn_star_display(1usize as _); + //~^ ERROR casting `usize` as `dyn* std::fmt::Display` is invalid +} diff --git a/src/test/ui/dyn-star/no-explicit-dyn-star.stderr b/src/test/ui/dyn-star/no-explicit-dyn-star.stderr new file mode 100644 index 000000000000..49706fae19e2 --- /dev/null +++ b/src/test/ui/dyn-star/no-explicit-dyn-star.stderr @@ -0,0 +1,9 @@ +error[E0606]: casting `usize` as `dyn* std::fmt::Display` is invalid + --> $DIR/no-explicit-dyn-star.rs:6:48 + | +LL | dyn_star_foreign::require_dyn_star_display(1usize as _); + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0606`. From 6bc5fddc00d3589a1b4a7b9bf74be74fcbf1ee35 Mon Sep 17 00:00:00 2001 From: xxchan Date: Fri, 28 Oct 2022 22:58:19 +0200 Subject: [PATCH 157/171] Add a test for TAIT used with impl/dyn Trait inside RPIT --- .../ui/type-alias-impl-trait/issue-101750.rs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/test/ui/type-alias-impl-trait/issue-101750.rs diff --git a/src/test/ui/type-alias-impl-trait/issue-101750.rs b/src/test/ui/type-alias-impl-trait/issue-101750.rs new file mode 100644 index 000000000000..f564f4fa702c --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-101750.rs @@ -0,0 +1,37 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +trait Trait {} + +type TAIT = impl Trait; + +struct Concrete; +impl Trait for Concrete {} + +fn tait() -> TAIT { + Concrete +} + +trait OuterTrait { + type Item; +} +struct Dummy { + t: T, +} +impl OuterTrait for Dummy { + type Item = T; +} + +fn tait_and_impl_trait() -> impl OuterTrait { + Dummy { + t: (tait(), Concrete), + } +} + +fn tait_and_dyn_trait() -> impl OuterTrait)> { + let b: Box = Box::new(Concrete); + Dummy { t: (tait(), b) } +} + +fn main() {} From 298253af98db70ce5dd0294698dfb89cb3bd09ab Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Thu, 27 Oct 2022 16:14:48 -0500 Subject: [PATCH 158/171] Specialize ToString for Symbol --- compiler/rustc_span/src/symbol.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3fe79370c374..7f16da52b443 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1901,6 +1901,13 @@ impl fmt::Display for Symbol { } } +// takes advantage of `str::to_string` specialization +impl ToString for Symbol { + fn to_string(&self) -> String { + self.as_str().to_string() + } +} + impl Encodable for Symbol { default fn encode(&self, s: &mut S) { s.emit_str(self.as_str()); From a36a37e5a8f3791d32435f58b34a110b68e4633b Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 29 Oct 2022 09:23:12 +0200 Subject: [PATCH 159/171] use consistent terminology I did not see other traits using the "interface" word --- library/core/src/async_iter/async_iter.rs | 2 +- library/core/src/iter/traits/iterator.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/async_iter/async_iter.rs b/library/core/src/async_iter/async_iter.rs index 016a3685e850..12a47f9fc762 100644 --- a/library/core/src/async_iter/async_iter.rs +++ b/library/core/src/async_iter/async_iter.rs @@ -2,7 +2,7 @@ use crate::ops::DerefMut; use crate::pin::Pin; use crate::task::{Context, Poll}; -/// An interface for dealing with asynchronous iterators. +/// A trait for dealing with asynchronous iterators. /// /// This is the main async iterator trait. For more about the concept of async iterators /// generally, please see the [module-level documentation]. In particular, you diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 789a87968d15..83c7e8977e9f 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -14,7 +14,7 @@ use super::super::{ fn _assert_is_object_safe(_: &dyn Iterator) {} -/// An interface for dealing with iterators. +/// A trait for dealing with iterators. /// /// This is the main iterator trait. For more about the concept of iterators /// generally, please see the [module-level documentation]. In particular, you From a3a3f4d8400069325bd35064cf1a2c7bf22d6991 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Sat, 29 Oct 2022 17:14:44 +0900 Subject: [PATCH 160/171] avoid unnecessary `&str` to `String` conversions --- .../rustc_mir_build/src/thir/pattern/check_match.rs | 2 +- compiler/rustc_resolve/src/late/diagnostics.rs | 5 +---- .../src/traits/const_evaluatable.rs | 12 ++++++------ 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 5984c800d838..505df022c574 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -507,7 +507,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { _ => "aren't", }, ), - " else { todo!() }".to_string(), + " else { todo!() }", Applicability::HasPlaceholders, ); } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 850f023b1c16..7d5fe32ee286 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -784,10 +784,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { return false; } err.code(rustc_errors::error_code!(E0411)); - err.span_label( - span, - "`Self` is only available in impls, traits, and type definitions".to_string(), - ); + err.span_label(span, "`Self` is only available in impls, traits, and type definitions"); if let Some(item_kind) = self.diagnostic_metadata.current_item { err.span_label( item_kind.ident.span, diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 84038625fb27..1de85e2f288b 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -192,12 +192,12 @@ pub fn is_const_evaluatable<'tcx>( } let concrete = infcx.const_eval_resolve(param_env, uv, Some(span)); match concrete { - Err(ErrorHandled::TooGeneric) => { - Err(NotConstEvaluatable::Error(infcx.tcx.sess.delay_span_bug( - span, - format!("Missing value for constant, but no error reported?"), - ))) - } + Err(ErrorHandled::TooGeneric) => Err(NotConstEvaluatable::Error( + infcx + .tcx + .sess + .delay_span_bug(span, "Missing value for constant, but no error reported?"), + )), Err(ErrorHandled::Linted) => { let reported = infcx .tcx From 4b353132f53b6b06c2eda7691a4b007838b1f013 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?joseLu=C3=ADs?= Date: Sat, 29 Oct 2022 10:49:53 +0200 Subject: [PATCH 161/171] fix typo in hashmap and hashset try_reserve method --- library/std/src/collections/hash/map.rs | 2 +- library/std/src/collections/hash/set.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 34983b976e3e..708edc5de475 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -759,7 +759,7 @@ where /// Tries to reserve capacity for at least `additional` more elements to be inserted /// in the `HashMap`. The collection may reserve more space to speculatively - /// avoid frequent reallocations. After calling `reserve`, + /// avoid frequent reallocations. After calling `try_reserve`, /// capacity will be greater than or equal to `self.len() + additional` if /// it returns `Ok(())`. /// Does nothing if capacity is already sufficient. diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index c36eeae3388d..cee884145c71 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -462,7 +462,7 @@ where /// Tries to reserve capacity for at least `additional` more elements to be inserted /// in the `HashSet`. The collection may reserve more space to speculatively - /// avoid frequent reallocations. After calling `reserve`, + /// avoid frequent reallocations. After calling `try_reserve`, /// capacity will be greater than or equal to `self.len() + additional` if /// it returns `Ok(())`. /// Does nothing if capacity is already sufficient. From c8c25ce5a15f3f50439b1d746fd507c6e28abe18 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Oct 2022 14:02:18 +1100 Subject: [PATCH 162/171] Rename some `OwnerId` fields. spastorino noticed some silly expressions like `item_id.def_id.def_id`. This commit renames several `def_id: OwnerId` fields as `owner_id`, so those expressions become `item_id.owner_id.def_id`. `item_id.owner_id.local_def_id` would be even clearer, but the use of `def_id` for values of type `LocalDefId` is *very* widespread, so I left that alone. --- compiler/rustc_ast_lowering/src/index.rs | 16 +-- compiler/rustc_ast_lowering/src/item.rs | 26 ++-- compiler/rustc_ast_lowering/src/lib.rs | 6 +- compiler/rustc_hir/src/hir.rs | 48 ++++---- compiler/rustc_hir/src/intravisit.rs | 4 +- compiler/rustc_hir/src/stable_hash_impls.rs | 8 +- .../rustc_hir_analysis/src/astconv/mod.rs | 2 +- .../rustc_hir_analysis/src/check/check.rs | 58 ++++----- .../rustc_hir_analysis/src/check/intrinsic.rs | 6 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 58 ++++----- .../rustc_hir_analysis/src/check_unused.rs | 4 +- .../src/coherence/inherent_impls.rs | 14 +-- .../src/coherence/inherent_impls_overlap.rs | 6 +- .../src/coherence/orphan.rs | 2 +- .../src/coherence/unsafety.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 16 +-- .../src/collect/lifetimes.rs | 8 +- .../rustc_hir_analysis/src/collect/type_of.rs | 32 ++--- .../rustc_hir_analysis/src/impl_wf_check.rs | 6 +- compiler/rustc_hir_analysis/src/lib.rs | 2 +- .../src/outlives/implicit_infer.rs | 2 +- .../rustc_hir_analysis/src/outlives/test.rs | 6 +- .../rustc_hir_analysis/src/variance/test.rs | 7 +- .../src/persist/dirty_clean.rs | 8 +- .../nice_region_error/static_impl_trait.rs | 2 +- .../rustc_interface/src/proc_macro_decls.rs | 2 +- compiler/rustc_lint/src/builtin.rs | 62 +++++----- .../src/opaque_hidden_inferred_bound.rs | 2 +- compiler/rustc_lint/src/traits.rs | 2 +- compiler/rustc_lint/src/types.rs | 2 +- .../rustc_metadata/src/foreign_modules.rs | 6 +- compiler/rustc_metadata/src/native_libs.rs | 16 +-- compiler/rustc_metadata/src/rmeta/encoder.rs | 33 ++--- compiler/rustc_middle/src/hir/map/mod.rs | 16 +-- compiler/rustc_middle/src/hir/mod.rs | 8 +- compiler/rustc_middle/src/mir/mono.rs | 6 +- compiler/rustc_middle/src/ty/error.rs | 6 +- compiler/rustc_middle/src/ty/print/pretty.rs | 4 +- compiler/rustc_monomorphize/src/collector.rs | 32 ++--- .../src/partitioning/default.rs | 6 +- compiler/rustc_passes/src/check_attr.rs | 2 +- compiler/rustc_passes/src/dead.rs | 46 +++---- compiler/rustc_passes/src/diagnostic_items.rs | 8 +- compiler/rustc_passes/src/entry.rs | 20 +-- compiler/rustc_passes/src/hir_id_validator.rs | 8 +- compiler/rustc_passes/src/lang_items.rs | 4 +- compiler/rustc_passes/src/layout_test.rs | 6 +- compiler/rustc_passes/src/reachable.rs | 20 +-- compiler/rustc_passes/src/stability.rs | 24 ++-- compiler/rustc_passes/src/weak_lang_items.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 115 ++++++++++-------- .../rustc_save_analysis/src/dump_visitor.rs | 76 ++++++------ compiler/rustc_save_analysis/src/lib.rs | 8 +- compiler/rustc_save_analysis/src/sig.rs | 10 +- compiler/rustc_symbol_mangling/src/test.rs | 8 +- .../rustc_trait_selection/src/traits/wf.rs | 8 +- compiler/rustc_ty_utils/src/assoc.rs | 16 +-- src/librustdoc/clean/mod.rs | 26 ++-- src/librustdoc/clean/types.rs | 12 +- src/librustdoc/visit_ast.rs | 8 +- .../obtain-borrowck/driver.rs | 12 +- .../clippy/clippy_lints/src/copy_iterator.rs | 2 +- .../src/default_union_representation.rs | 2 +- .../clippy/clippy_lints/src/dereference.rs | 16 +-- .../clippy_lints/src/derivable_impls.rs | 4 +- src/tools/clippy/clippy_lints/src/derive.rs | 4 +- src/tools/clippy/clippy_lints/src/doc.rs | 12 +- .../clippy/clippy_lints/src/empty_enum.rs | 2 +- .../clippy/clippy_lints/src/enum_variants.rs | 4 +- src/tools/clippy/clippy_lints/src/escape.rs | 2 +- .../clippy_lints/src/exhaustive_items.rs | 2 +- .../clippy_lints/src/fallible_impl_from.rs | 4 +- .../clippy/clippy_lints/src/from_over_into.rs | 2 +- .../clippy_lints/src/functions/must_use.rs | 20 +-- .../src/functions/not_unsafe_ptr_arg_deref.rs | 2 +- .../clippy_lints/src/functions/result.rs | 14 +-- .../clippy_lints/src/implicit_hasher.rs | 2 +- .../clippy_lints/src/inherent_to_string.rs | 4 +- .../src/iter_not_returning_iterator.rs | 4 +- .../clippy_lints/src/large_enum_variant.rs | 2 +- src/tools/clippy/clippy_lints/src/len_zero.rs | 10 +- .../clippy/clippy_lints/src/lifetimes.rs | 2 +- .../clippy_lints/src/manual_non_exhaustive.rs | 2 +- .../clippy/clippy_lints/src/methods/mod.rs | 12 +- .../clippy/clippy_lints/src/missing_doc.rs | 10 +- .../clippy/clippy_lints/src/missing_inline.rs | 10 +- src/tools/clippy/clippy_lints/src/mut_key.rs | 2 +- .../clippy_lints/src/new_without_default.rs | 4 +- .../clippy/clippy_lints/src/non_copy_const.rs | 2 +- .../src/non_send_fields_in_send_ty.rs | 2 +- .../src/only_used_in_recursion.rs | 16 +-- .../clippy_lints/src/operators/op_ref.rs | 2 +- .../clippy_lints/src/partialeq_ne_impl.rs | 2 +- .../clippy_lints/src/pass_by_ref_or_value.rs | 2 +- src/tools/clippy/clippy_lints/src/ptr.rs | 8 +- .../clippy_lints/src/redundant_pub_crate.rs | 8 +- .../src/return_self_not_must_use.rs | 2 +- .../clippy_lints/src/same_name_method.rs | 2 +- .../src/self_named_constructors.rs | 2 +- .../clippy_lints/src/trailing_empty_array.rs | 2 +- .../clippy/clippy_lints/src/types/mod.rs | 4 +- .../clippy/clippy_lints/src/unused_self.rs | 4 +- .../clippy_lints/src/unwrap_in_result.rs | 2 +- .../clippy_lints/src/upper_case_acronyms.rs | 2 +- src/tools/clippy/clippy_lints/src/use_self.rs | 4 +- .../clippy_lints/src/wildcard_imports.rs | 6 +- src/tools/clippy/clippy_utils/src/lib.rs | 2 +- 107 files changed, 618 insertions(+), 603 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 6d7167963433..f1851d7b40ea 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -112,19 +112,19 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_nested_item(&mut self, item: ItemId) { debug!("visit_nested_item: {:?}", item); - self.insert_nested(item.def_id.def_id); + self.insert_nested(item.owner_id.def_id); } fn visit_nested_trait_item(&mut self, item_id: TraitItemId) { - self.insert_nested(item_id.def_id.def_id); + self.insert_nested(item_id.owner_id.def_id); } fn visit_nested_impl_item(&mut self, item_id: ImplItemId) { - self.insert_nested(item_id.def_id.def_id); + self.insert_nested(item_id.owner_id.def_id); } fn visit_nested_foreign_item(&mut self, foreign_id: ForeignItemId) { - self.insert_nested(foreign_id.def_id.def_id); + self.insert_nested(foreign_id.owner_id.def_id); } fn visit_nested_body(&mut self, id: BodyId) { @@ -143,7 +143,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { #[instrument(level = "debug", skip(self))] fn visit_item(&mut self, i: &'hir Item<'hir>) { - debug_assert_eq!(i.def_id, self.owner); + debug_assert_eq!(i.owner_id, self.owner); self.with_parent(i.hir_id(), |this| { if let ItemKind::Struct(ref struct_def, _) = i.kind { // If this is a tuple or unit-like struct, register the constructor. @@ -157,7 +157,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { #[instrument(level = "debug", skip(self))] fn visit_foreign_item(&mut self, fi: &'hir ForeignItem<'hir>) { - debug_assert_eq!(fi.def_id, self.owner); + debug_assert_eq!(fi.owner_id, self.owner); self.with_parent(fi.hir_id(), |this| { intravisit::walk_foreign_item(this, fi); }); @@ -176,7 +176,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { #[instrument(level = "debug", skip(self))] fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) { - debug_assert_eq!(ti.def_id, self.owner); + debug_assert_eq!(ti.owner_id, self.owner); self.with_parent(ti.hir_id(), |this| { intravisit::walk_trait_item(this, ti); }); @@ -184,7 +184,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { #[instrument(level = "debug", skip(self))] fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) { - debug_assert_eq!(ii.def_id, self.owner); + debug_assert_eq!(ii.owner_id, self.owner); self.with_parent(ii.hir_id(), |this| { intravisit::walk_impl_item(this, ii); }); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 2117006df10f..76316a574acb 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -178,7 +178,7 @@ impl<'hir> LoweringContext<'_, 'hir> { pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> { let mut node_ids = - smallvec![hir::ItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }]; + smallvec![hir::ItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }]; if let ItemKind::Use(ref use_tree) = &i.kind { self.lower_item_id_use_tree(use_tree, i.id, &mut node_ids); } @@ -195,7 +195,7 @@ impl<'hir> LoweringContext<'_, 'hir> { UseTreeKind::Nested(ref nested_vec) => { for &(ref nested, id) in nested_vec { vec.push(hir::ItemId { - def_id: hir::OwnerId { def_id: self.local_def_id(id) }, + owner_id: hir::OwnerId { def_id: self.local_def_id(id) }, }); self.lower_item_id_use_tree(nested, id, vec); } @@ -206,7 +206,7 @@ impl<'hir> LoweringContext<'_, 'hir> { iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2]) { vec.push(hir::ItemId { - def_id: hir::OwnerId { def_id: self.local_def_id(id) }, + owner_id: hir::OwnerId { def_id: self.local_def_id(id) }, }); } } @@ -220,7 +220,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let attrs = self.lower_attrs(hir_id, &i.attrs); let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, vis_span, &i.kind); let item = hir::Item { - def_id: hir_id.expect_owner(), + owner_id: hir_id.expect_owner(), ident: self.lower_ident(ident), kind, vis_span, @@ -562,7 +562,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } let item = hir::Item { - def_id: hir::OwnerId { def_id: new_id }, + owner_id: hir::OwnerId { def_id: new_id }, ident: this.lower_ident(ident), kind, vis_span, @@ -640,7 +640,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } let item = hir::Item { - def_id: hir::OwnerId { def_id: new_hir_id }, + owner_id: hir::OwnerId { def_id: new_hir_id }, ident: this.lower_ident(ident), kind, vis_span, @@ -660,10 +660,10 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> { let hir_id = self.lower_node_id(i.id); - let def_id = hir_id.expect_owner(); + let owner_id = hir_id.expect_owner(); self.lower_attrs(hir_id, &i.attrs); let item = hir::ForeignItem { - def_id, + owner_id, ident: self.lower_ident(i.ident), kind: match i.kind { ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => { @@ -702,7 +702,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef { hir::ForeignItemRef { - id: hir::ForeignItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }, + id: hir::ForeignItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }, ident: self.lower_ident(i.ident), span: self.lower_span(i.span), } @@ -845,7 +845,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_attrs(hir_id, &i.attrs); let item = hir::TraitItem { - def_id: trait_item_def_id, + owner_id: trait_item_def_id, ident: self.lower_ident(i.ident), generics, kind, @@ -864,7 +864,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } AssocItemKind::MacCall(..) => unimplemented!(), }; - let id = hir::TraitItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }; + let id = hir::TraitItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }; hir::TraitItemRef { id, ident: self.lower_ident(i.ident), @@ -931,7 +931,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let hir_id = self.lower_node_id(i.id); self.lower_attrs(hir_id, &i.attrs); let item = hir::ImplItem { - def_id: hir_id.expect_owner(), + owner_id: hir_id.expect_owner(), ident: self.lower_ident(i.ident), generics, kind, @@ -944,7 +944,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef { hir::ImplItemRef { - id: hir::ImplItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }, + id: hir::ImplItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }, ident: self.lower_ident(i.ident), span: self.lower_span(i.span), kind: match &i.kind { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 427b71722abc..ff29d15f1b52 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1574,7 +1574,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // `impl Trait` now just becomes `Foo<'a, 'b, ..>`. hir::TyKind::OpaqueDef( - hir::ItemId { def_id: hir::OwnerId { def_id: opaque_ty_def_id } }, + hir::ItemId { owner_id: hir::OwnerId { def_id: opaque_ty_def_id } }, lifetimes, in_trait, ) @@ -1593,7 +1593,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Generate an `type Foo = impl Trait;` declaration. trace!("registering opaque type with id {:#?}", opaque_ty_id); let opaque_ty_item = hir::Item { - def_id: hir::OwnerId { def_id: opaque_ty_id }, + owner_id: hir::OwnerId { def_id: opaque_ty_id }, ident: Ident::empty(), kind: opaque_ty_item_kind, vis_span: self.lower_span(span.shrink_to_lo()), @@ -2044,7 +2044,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // async fn, so the *type parameters* are inherited. It's // only the lifetime parameters that we must supply. let opaque_ty_ref = hir::TyKind::OpaqueDef( - hir::ItemId { def_id: hir::OwnerId { def_id: opaque_ty_def_id } }, + hir::ItemId { owner_id: hir::OwnerId { def_id: opaque_ty_def_id } }, generic_args, in_trait, ); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 9a9e40a3f43a..ef00c1ffc302 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2207,14 +2207,14 @@ pub struct FnSig<'hir> { // so it can fetched later. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub struct TraitItemId { - pub def_id: OwnerId, + pub owner_id: OwnerId, } impl TraitItemId { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id.def_id) + HirId::make_owner(self.owner_id.def_id) } } @@ -2225,7 +2225,7 @@ impl TraitItemId { #[derive(Debug, HashStable_Generic)] pub struct TraitItem<'hir> { pub ident: Ident, - pub def_id: OwnerId, + pub owner_id: OwnerId, pub generics: &'hir Generics<'hir>, pub kind: TraitItemKind<'hir>, pub span: Span, @@ -2236,11 +2236,11 @@ impl TraitItem<'_> { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id.def_id) + HirId::make_owner(self.owner_id.def_id) } pub fn trait_item_id(&self) -> TraitItemId { - TraitItemId { def_id: self.def_id } + TraitItemId { owner_id: self.owner_id } } } @@ -2271,14 +2271,14 @@ pub enum TraitItemKind<'hir> { // so it can fetched later. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub struct ImplItemId { - pub def_id: OwnerId, + pub owner_id: OwnerId, } impl ImplItemId { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id.def_id) + HirId::make_owner(self.owner_id.def_id) } } @@ -2286,7 +2286,7 @@ impl ImplItemId { #[derive(Debug, HashStable_Generic)] pub struct ImplItem<'hir> { pub ident: Ident, - pub def_id: OwnerId, + pub owner_id: OwnerId, pub generics: &'hir Generics<'hir>, pub kind: ImplItemKind<'hir>, pub defaultness: Defaultness, @@ -2298,11 +2298,11 @@ impl ImplItem<'_> { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id.def_id) + HirId::make_owner(self.owner_id.def_id) } pub fn impl_item_id(&self) -> ImplItemId { - ImplItemId { def_id: self.def_id } + ImplItemId { owner_id: self.owner_id } } } @@ -2914,14 +2914,14 @@ impl<'hir> VariantData<'hir> { // so it can fetched later. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, Hash, HashStable_Generic)] pub struct ItemId { - pub def_id: OwnerId, + pub owner_id: OwnerId, } impl ItemId { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id.def_id) + HirId::make_owner(self.owner_id.def_id) } } @@ -2931,7 +2931,7 @@ impl ItemId { #[derive(Debug, HashStable_Generic)] pub struct Item<'hir> { pub ident: Ident, - pub def_id: OwnerId, + pub owner_id: OwnerId, pub kind: ItemKind<'hir>, pub span: Span, pub vis_span: Span, @@ -2941,11 +2941,11 @@ impl Item<'_> { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id.def_id) + HirId::make_owner(self.owner_id.def_id) } pub fn item_id(&self) -> ItemId { - ItemId { def_id: self.def_id } + ItemId { owner_id: self.owner_id } } } @@ -3158,14 +3158,14 @@ pub enum AssocItemKind { // so it can fetched later. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub struct ForeignItemId { - pub def_id: OwnerId, + pub owner_id: OwnerId, } impl ForeignItemId { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id.def_id) + HirId::make_owner(self.owner_id.def_id) } } @@ -3186,7 +3186,7 @@ pub struct ForeignItemRef { pub struct ForeignItem<'hir> { pub ident: Ident, pub kind: ForeignItemKind<'hir>, - pub def_id: OwnerId, + pub owner_id: OwnerId, pub span: Span, pub vis_span: Span, } @@ -3195,11 +3195,11 @@ impl ForeignItem<'_> { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id.def_id) + HirId::make_owner(self.owner_id.def_id) } pub fn foreign_item_id(&self) -> ForeignItemId { - ForeignItemId { def_id: self.def_id } + ForeignItemId { owner_id: self.owner_id } } } @@ -3291,10 +3291,10 @@ impl<'hir> OwnerNode<'hir> { pub fn def_id(self) -> OwnerId { match self { - OwnerNode::Item(Item { def_id, .. }) - | OwnerNode::TraitItem(TraitItem { def_id, .. }) - | OwnerNode::ImplItem(ImplItem { def_id, .. }) - | OwnerNode::ForeignItem(ForeignItem { def_id, .. }) => *def_id, + OwnerNode::Item(Item { owner_id, .. }) + | OwnerNode::TraitItem(TraitItem { owner_id, .. }) + | OwnerNode::ImplItem(ImplItem { owner_id, .. }) + | OwnerNode::ForeignItem(ForeignItem { owner_id, .. }) => *owner_id, OwnerNode::Crate(..) => crate::CRATE_HIR_ID.owner, } } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index f3bde099b134..be77e6fd36a0 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -912,7 +912,7 @@ pub fn walk_fn<'v, V: Visitor<'v>>( pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem<'v>) { // N.B., deliberately force a compilation error if/when new fields are added. - let TraitItem { ident, generics, ref defaultness, ref kind, span, def_id: _ } = *trait_item; + let TraitItem { ident, generics, ref defaultness, ref kind, span, owner_id: _ } = *trait_item; let hir_id = trait_item.hir_id(); visitor.visit_ident(ident); visitor.visit_generics(&generics); @@ -952,7 +952,7 @@ pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref: pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem<'v>) { // N.B., deliberately force a compilation error if/when new fields are added. let ImplItem { - def_id: _, + owner_id: _, ident, ref generics, ref kind, diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index 06b7a65662e7..23423e8f3b3b 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -49,7 +49,7 @@ impl ToStableHashKey for ItemId { #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { - self.def_id.def_id.to_stable_hash_key(hcx) + self.owner_id.def_id.to_stable_hash_key(hcx) } } @@ -58,7 +58,7 @@ impl ToStableHashKey for TraitItemId { #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { - self.def_id.def_id.to_stable_hash_key(hcx) + self.owner_id.def_id.to_stable_hash_key(hcx) } } @@ -67,7 +67,7 @@ impl ToStableHashKey for ImplItemId { #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { - self.def_id.def_id.to_stable_hash_key(hcx) + self.owner_id.def_id.to_stable_hash_key(hcx) } } @@ -76,7 +76,7 @@ impl ToStableHashKey for ForeignItemId #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { - self.def_id.def_id.to_stable_hash_key(hcx) + self.owner_id.def_id.to_stable_hash_key(hcx) } } diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 6baf98449775..38f195dabb90 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2661,7 +2661,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => { let opaque_ty = tcx.hir().item(item_id); - let def_id = item_id.def_id.to_def_id(); + let def_id = item_id.owner_id.to_def_id(); match opaque_ty.kind { hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => { diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index b302cee4816f..bc22adcd2416 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -227,17 +227,17 @@ fn check_opaque<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { return; } - let substs = InternalSubsts::identity_for_item(tcx, item.def_id.to_def_id()); - let span = tcx.def_span(item.def_id.def_id); + let substs = InternalSubsts::identity_for_item(tcx, item.owner_id.to_def_id()); + let span = tcx.def_span(item.owner_id.def_id); - check_opaque_for_inheriting_lifetimes(tcx, item.def_id.def_id, span); - if tcx.type_of(item.def_id.def_id).references_error() { + check_opaque_for_inheriting_lifetimes(tcx, item.owner_id.def_id, span); + if tcx.type_of(item.owner_id.def_id).references_error() { return; } - if check_opaque_for_cycles(tcx, item.def_id.def_id, substs, span, &origin).is_err() { + if check_opaque_for_cycles(tcx, item.owner_id.def_id, substs, span, &origin).is_err() { return; } - check_opaque_meets_bounds(tcx, item.def_id.def_id, substs, span, &origin); + check_opaque_meets_bounds(tcx, item.owner_id.def_id, substs, span, &origin); } /// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result /// in "inheriting lifetimes". @@ -492,25 +492,25 @@ fn check_opaque_meets_bounds<'tcx>( fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { debug!( "check_item_type(it.def_id={:?}, it.name={})", - id.def_id, - tcx.def_path_str(id.def_id.to_def_id()) + id.owner_id, + tcx.def_path_str(id.owner_id.to_def_id()) ); let _indenter = indenter(); - match tcx.def_kind(id.def_id) { + match tcx.def_kind(id.owner_id) { DefKind::Static(..) => { - tcx.ensure().typeck(id.def_id.def_id); - maybe_check_static_with_link_section(tcx, id.def_id.def_id); - check_static_inhabited(tcx, id.def_id.def_id); + tcx.ensure().typeck(id.owner_id.def_id); + maybe_check_static_with_link_section(tcx, id.owner_id.def_id); + check_static_inhabited(tcx, id.owner_id.def_id); } DefKind::Const => { - tcx.ensure().typeck(id.def_id.def_id); + tcx.ensure().typeck(id.owner_id.def_id); } DefKind::Enum => { let item = tcx.hir().item(id); let hir::ItemKind::Enum(ref enum_definition, _) = item.kind else { return; }; - check_enum(tcx, &enum_definition.variants, item.def_id.def_id); + check_enum(tcx, &enum_definition.variants, item.owner_id.def_id); } DefKind::Fn => {} // entirely within check_item_body DefKind::Impl => { @@ -518,12 +518,12 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { let hir::ItemKind::Impl(ref impl_) = it.kind else { return; }; - debug!("ItemKind::Impl {} with id {:?}", it.ident, it.def_id); - if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.def_id) { + debug!("ItemKind::Impl {} with id {:?}", it.ident, it.owner_id); + if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.owner_id) { check_impl_items_against_trait( tcx, it.span, - it.def_id.def_id, + it.owner_id.def_id, impl_trait_ref, &impl_.items, ); @@ -545,15 +545,15 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { fn_maybe_err(tcx, item.ident.span, abi); } hir::TraitItemKind::Type(.., Some(default)) => { - let assoc_item = tcx.associated_item(item.def_id); + let assoc_item = tcx.associated_item(item.owner_id); let trait_substs = - InternalSubsts::identity_for_item(tcx, it.def_id.to_def_id()); + InternalSubsts::identity_for_item(tcx, it.owner_id.to_def_id()); let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds( tcx, assoc_item, assoc_item, default.span, - ty::TraitRef { def_id: it.def_id.to_def_id(), substs: trait_substs }, + ty::TraitRef { def_id: it.owner_id.to_def_id(), substs: trait_substs }, ); } _ => {} @@ -561,16 +561,16 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { } } DefKind::Struct => { - check_struct(tcx, id.def_id.def_id); + check_struct(tcx, id.owner_id.def_id); } DefKind::Union => { - check_union(tcx, id.def_id.def_id); + check_union(tcx, id.owner_id.def_id); } DefKind::OpaqueTy => { check_opaque(tcx, id); } DefKind::ImplTraitPlaceholder => { - let parent = tcx.impl_trait_in_trait_parent(id.def_id.to_def_id()); + let parent = tcx.impl_trait_in_trait_parent(id.owner_id.to_def_id()); // Only check the validity of this opaque type if the function has a default body if let hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)), @@ -581,8 +581,8 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { } } DefKind::TyAlias => { - let pty_ty = tcx.type_of(id.def_id); - let generics = tcx.generics_of(id.def_id); + let pty_ty = tcx.type_of(id.owner_id); + let generics = tcx.generics_of(id.owner_id); check_type_params_are_used(tcx, &generics, pty_ty); } DefKind::ForeignMod => { @@ -604,7 +604,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { } } else { for item in items { - let def_id = item.id.def_id.def_id; + let def_id = item.id.owner_id.def_id; let generics = tcx.generics_of(def_id); let own_counts = generics.own_counts(); if generics.params.len() - own_counts.lifetimes != 0 { @@ -659,7 +659,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { // an error would be reported if this fails. - let _ = traits::OnUnimplementedDirective::of_item(tcx, item.def_id.to_def_id()); + let _ = traits::OnUnimplementedDirective::of_item(tcx, item.owner_id.to_def_id()); } pub(super) fn check_specialization_validity<'tcx>( @@ -746,7 +746,7 @@ fn check_impl_items_against_trait<'tcx>( let trait_def = tcx.trait_def(impl_trait_ref.def_id); for impl_item in impl_item_refs { - let ty_impl_item = tcx.associated_item(impl_item.id.def_id); + let ty_impl_item = tcx.associated_item(impl_item.id.owner_id); let ty_trait_item = if let Some(trait_item_id) = ty_impl_item.trait_item_def_id { tcx.associated_item(trait_item_id) } else { @@ -758,7 +758,7 @@ fn check_impl_items_against_trait<'tcx>( match impl_item_full.kind { hir::ImplItemKind::Const(..) => { let _ = tcx.compare_assoc_const_impl_item_with_trait_item(( - impl_item.id.def_id.def_id, + impl_item.id.owner_id.def_id, ty_impl_item.trait_item_def_id.unwrap(), )); } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 8be1cf04f8b6..609095c9ceaa 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -26,7 +26,7 @@ fn equate_intrinsic_type<'tcx>( ) { let (own_counts, span) = match &it.kind { hir::ForeignItemKind::Fn(.., generics) => { - let own_counts = tcx.generics_of(it.def_id.to_def_id()).own_counts(); + let own_counts = tcx.generics_of(it.owner_id.to_def_id()).own_counts(); (own_counts, generics.span) } _ => { @@ -57,7 +57,7 @@ fn equate_intrinsic_type<'tcx>( { let fty = tcx.mk_fn_ptr(sig); let cause = ObligationCause::new(it.span, it.hir_id(), ObligationCauseCode::IntrinsicType); - require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty); + require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.owner_id)), fty); } } @@ -129,7 +129,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir /// and in `library/core/src/intrinsics.rs`. pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n))); - let intrinsic_id = it.def_id.to_def_id(); + let intrinsic_id = it.owner_id.to_def_id(); let intrinsic_name = tcx.item_name(intrinsic_id); let name_str = intrinsic_name.as_str(); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 70a171c02b26..a23575004655 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -147,10 +147,10 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) { /// the types first. #[instrument(skip(tcx), level = "debug")] fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { - let def_id = item.def_id.def_id; + let def_id = item.owner_id.def_id; debug!( - ?item.def_id, + ?item.owner_id, item.name = ? tcx.def_path_str(def_id.to_def_id()) ); @@ -246,10 +246,10 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { } fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) { - let def_id = item.def_id.def_id; + let def_id = item.owner_id.def_id; debug!( - ?item.def_id, + ?item.owner_id, item.name = ? tcx.def_path_str(def_id.to_def_id()) ); @@ -263,7 +263,7 @@ fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) { } fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) { - let def_id = trait_item.def_id.def_id; + let def_id = trait_item.owner_id.def_id; let (method_sig, span) = match trait_item.kind { hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span), @@ -275,7 +275,7 @@ fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) { let encl_trait_def_id = tcx.local_parent(def_id); let encl_trait = tcx.hir().expect_item(encl_trait_def_id); - let encl_trait_def_id = encl_trait.def_id.to_def_id(); + let encl_trait_def_id = encl_trait.owner_id.to_def_id(); let fn_lang_item_name = if Some(encl_trait_def_id) == tcx.lang_items().fn_trait() { Some("fn") } else if Some(encl_trait_def_id) == tcx.lang_items().fn_mut_trait() { @@ -348,7 +348,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe loop { let mut should_continue = false; for gat_item in associated_items { - let gat_def_id = gat_item.id.def_id; + let gat_def_id = gat_item.id.owner_id; let gat_item = tcx.associated_item(gat_def_id); // If this item is not an assoc ty, or has no substs, then it's not a GAT if gat_item.kind != ty::AssocKind::Type { @@ -365,7 +365,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe // constrains the GAT with individually. let mut new_required_bounds: Option>> = None; for item in associated_items { - let item_def_id = item.id.def_id; + let item_def_id = item.id.owner_id; // Skip our own GAT, since it does not constrain itself at all. if item_def_id == gat_def_id { continue; @@ -790,7 +790,7 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem let (trait_name, trait_def_id) = match tcx.hir().get_by_def_id(tcx.hir().get_parent_item(item.hir_id()).def_id) { hir::Node::Item(item) => match item.kind { - hir::ItemKind::Trait(..) => (item.ident, item.def_id), + hir::ItemKind::Trait(..) => (item.ident, item.owner_id), _ => return, }, _ => return, @@ -845,7 +845,7 @@ fn check_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) { _ => (None, impl_item.span), }; - check_associated_item(tcx, impl_item.def_id.def_id, span, method_sig); + check_associated_item(tcx, impl_item.owner_id.def_id, span, method_sig); } fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) { @@ -1045,11 +1045,11 @@ fn check_type_defn<'tcx, F>( ) where F: FnMut(&WfCheckingCtxt<'_, 'tcx>) -> Vec>, { - let _ = tcx.representability(item.def_id.def_id); + let _ = tcx.representability(item.owner_id.def_id); - enter_wf_checking_ctxt(tcx, item.span, item.def_id.def_id, |wfcx| { + enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| { let variants = lookup_fields(wfcx); - let packed = tcx.adt_def(item.def_id).repr().packed(); + let packed = tcx.adt_def(item.owner_id).repr().packed(); for variant in &variants { // All field types must be well-formed. @@ -1073,7 +1073,7 @@ fn check_type_defn<'tcx, F>( // Just treat unresolved type expression as if it needs drop. true } else { - ty.needs_drop(tcx, tcx.param_env(item.def_id)) + ty.needs_drop(tcx, tcx.param_env(item.owner_id)) } } }; @@ -1121,15 +1121,15 @@ fn check_type_defn<'tcx, F>( } } - check_where_clauses(wfcx, item.span, item.def_id.def_id); + check_where_clauses(wfcx, item.span, item.owner_id.def_id); }); } #[instrument(skip(tcx, item))] fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { - debug!(?item.def_id); + debug!(?item.owner_id); - let def_id = item.def_id.def_id; + let def_id = item.owner_id.def_id; let trait_def = tcx.trait_def(def_id); if trait_def.is_marker || matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker) @@ -1240,13 +1240,13 @@ fn check_impl<'tcx>( ast_trait_ref: &Option>, constness: hir::Constness, ) { - enter_wf_checking_ctxt(tcx, item.span, item.def_id.def_id, |wfcx| { + enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| { match *ast_trait_ref { Some(ref ast_trait_ref) => { // `#[rustc_reservation_impl]` impls are not real impls and // therefore don't need to be WF (the trait's `Self: Trait` predicate // won't hold). - let trait_ref = tcx.impl_trait_ref(item.def_id).unwrap(); + let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap(); let trait_ref = wfcx.normalize(ast_trait_ref.path.span, None, trait_ref); let trait_pred = ty::TraitPredicate { trait_ref, @@ -1268,7 +1268,7 @@ fn check_impl<'tcx>( wfcx.register_obligations(obligations); } None => { - let self_ty = tcx.type_of(item.def_id); + let self_ty = tcx.type_of(item.owner_id); let self_ty = wfcx.normalize( item.span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), @@ -1282,7 +1282,7 @@ fn check_impl<'tcx>( } } - check_where_clauses(wfcx, item.span, item.def_id.def_id); + check_where_clauses(wfcx, item.span, item.owner_id.def_id); }); } @@ -1778,14 +1778,14 @@ fn check_variances_for_type_defn<'tcx>( item: &hir::Item<'tcx>, hir_generics: &hir::Generics<'_>, ) { - let ty = tcx.type_of(item.def_id); + let ty = tcx.type_of(item.owner_id); if tcx.has_error_field(ty) { return; } - let ty_predicates = tcx.predicates_of(item.def_id); + let ty_predicates = tcx.predicates_of(item.owner_id); assert_eq!(ty_predicates.parent, None); - let variances = tcx.variances_of(item.def_id); + let variances = tcx.variances_of(item.owner_id); let mut constrained_parameters: FxHashSet<_> = variances .iter() @@ -1798,7 +1798,7 @@ fn check_variances_for_type_defn<'tcx>( // Lazily calculated because it is only needed in case of an error. let explicitly_bounded_params = LazyCell::new(|| { - let icx = crate::collect::ItemCtxt::new(tcx, item.def_id.to_def_id()); + let icx = crate::collect::ItemCtxt::new(tcx, item.owner_id.to_def_id()); hir_generics .predicates .iter() @@ -1919,10 +1919,10 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalDefId) { let items = tcx.hir_module_items(module); - items.par_items(|item| tcx.ensure().check_well_formed(item.def_id)); - items.par_impl_items(|item| tcx.ensure().check_well_formed(item.def_id)); - items.par_trait_items(|item| tcx.ensure().check_well_formed(item.def_id)); - items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.def_id)); + items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id)); + items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id)); + items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id)); + items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id)); } /////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs index 922833f85806..aaceaae89600 100644 --- a/compiler/rustc_hir_analysis/src/check_unused.rs +++ b/compiler/rustc_hir_analysis/src/check_unused.rs @@ -89,11 +89,11 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) { let mut crates_to_lint = vec![]; for id in tcx.hir().items() { - if matches!(tcx.def_kind(id.def_id), DefKind::ExternCrate) { + if matches!(tcx.def_kind(id.owner_id), DefKind::ExternCrate) { let item = tcx.hir().item(id); if let hir::ItemKind::ExternCrate(orig_name) = item.kind { crates_to_lint.push(ExternCrateToLint { - def_id: item.def_id.to_def_id(), + def_id: item.owner_id.to_def_id(), span: item.span, orig_name, warn_if_unused: !item.ident.as_str().starts_with('_'), diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index 308ad5d5fc2c..2890c149b3af 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -58,7 +58,7 @@ const ADD_ATTR: &str = impl<'tcx> InherentCollect<'tcx> { fn check_def_id(&mut self, item: &hir::Item<'_>, self_ty: Ty<'tcx>, def_id: DefId) { - let impl_def_id = item.def_id; + let impl_def_id = item.owner_id; if let Some(def_id) = def_id.as_local() { // Add the implementation to the mapping from implementation to base // type def ID, if there is a base type for this implementation and @@ -89,7 +89,7 @@ impl<'tcx> InherentCollect<'tcx> { for impl_item in items { if !self .tcx - .has_attr(impl_item.id.def_id.to_def_id(), sym::rustc_allow_incoherent_impl) + .has_attr(impl_item.id.owner_id.to_def_id(), sym::rustc_allow_incoherent_impl) { struct_span_err!( self.tcx.sess, @@ -135,7 +135,7 @@ impl<'tcx> InherentCollect<'tcx> { for item in items { if !self .tcx - .has_attr(item.id.def_id.to_def_id(), sym::rustc_allow_incoherent_impl) + .has_attr(item.id.owner_id.to_def_id(), sym::rustc_allow_incoherent_impl) { struct_span_err!( self.tcx.sess, @@ -177,7 +177,7 @@ impl<'tcx> InherentCollect<'tcx> { } fn check_item(&mut self, id: hir::ItemId) { - if !matches!(self.tcx.def_kind(id.def_id), DefKind::Impl) { + if !matches!(self.tcx.def_kind(id.owner_id), DefKind::Impl) { return; } @@ -186,7 +186,7 @@ impl<'tcx> InherentCollect<'tcx> { return; }; - let self_ty = self.tcx.type_of(item.def_id); + let self_ty = self.tcx.type_of(item.owner_id); match *self_ty.kind() { ty::Adt(def, _) => { self.check_def_id(item, self_ty, def.did()); @@ -221,7 +221,7 @@ impl<'tcx> InherentCollect<'tcx> { | ty::Never | ty::FnPtr(_) | ty::Tuple(..) => { - self.check_primitive_impl(item.def_id.def_id, self_ty, items, ty.span) + self.check_primitive_impl(item.owner_id.def_id, self_ty, items, ty.span) } ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => { let mut err = struct_span_err!( @@ -243,7 +243,7 @@ impl<'tcx> InherentCollect<'tcx> { | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) => { - bug!("unexpected impl self type of impl: {:?} {:?}", item.def_id, self_ty); + bug!("unexpected impl self type of impl: {:?} {:?}", item.owner_id, self_ty); } ty::Error(_) => {} } diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index 130eb8005b06..972769eb1970 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -156,14 +156,14 @@ impl<'tcx> InherentOverlapChecker<'tcx> { } fn check_item(&mut self, id: hir::ItemId) { - let def_kind = self.tcx.def_kind(id.def_id); + let def_kind = self.tcx.def_kind(id.owner_id); if !matches!(def_kind, DefKind::Enum | DefKind::Struct | DefKind::Trait | DefKind::Union) { return; } - let impls = self.tcx.inherent_impls(id.def_id); + let impls = self.tcx.inherent_impls(id.owner_id); - let overlap_mode = OverlapMode::get(self.tcx, id.def_id.to_def_id()); + let overlap_mode = OverlapMode::get(self.tcx, id.owner_id.to_def_id()); let impls_items = impls .iter() diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 1307f74f2107..bb45c3823d83 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -101,7 +101,7 @@ fn do_orphan_check_impl<'tcx>( span_bug!(sp, "opaque type not found, but `has_opaque_types` is set") } - match traits::orphan_check(tcx, item.def_id.to_def_id()) { + match traits::orphan_check(tcx, item.owner_id.to_def_id()) { Ok(()) => {} Err(err) => emit_orphan_check_error( tcx, diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index 25b2ed76adf2..a34815b45b3a 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -13,7 +13,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { let item = tcx.hir().expect_item(def_id); let hir::ItemKind::Impl(ref impl_) = item.kind else { bug!() }; - if let Some(trait_ref) = tcx.impl_trait_ref(item.def_id) { + if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) { let trait_def = tcx.trait_def(trait_ref.def_id); let unsafe_attr = impl_.generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle"); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index e261bb07f954..346d2e2fc4b1 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -571,7 +571,7 @@ fn get_new_lifetime_name<'tcx>( fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { let it = tcx.hir().item(item_id); debug!("convert: item {} with id {}", it.ident, it.hir_id()); - let def_id = item_id.def_id.def_id; + let def_id = item_id.owner_id.def_id; match it.kind { // These don't define types. @@ -583,11 +583,11 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { hir::ItemKind::ForeignMod { items, .. } => { for item in items { let item = tcx.hir().foreign_item(item.id); - tcx.ensure().generics_of(item.def_id); - tcx.ensure().type_of(item.def_id); - tcx.ensure().predicates_of(item.def_id); + tcx.ensure().generics_of(item.owner_id); + tcx.ensure().type_of(item.owner_id); + tcx.ensure().predicates_of(item.owner_id); match item.kind { - hir::ForeignItemKind::Fn(..) => tcx.ensure().fn_sig(item.def_id), + hir::ForeignItemKind::Fn(..) => tcx.ensure().fn_sig(item.owner_id), hir::ForeignItemKind::Static(..) => { let mut visitor = HirPlaceholderCollector::default(); visitor.visit_foreign_item(item); @@ -683,7 +683,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { let trait_item = tcx.hir().trait_item(trait_item_id); - let def_id = trait_item_id.def_id; + let def_id = trait_item_id.owner_id; tcx.ensure().generics_of(def_id); match trait_item.kind { @@ -730,7 +730,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { } fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) { - let def_id = impl_item_id.def_id; + let def_id = impl_item_id.owner_id; tcx.ensure().generics_of(def_id); tcx.ensure().type_of(def_id); tcx.ensure().predicates_of(def_id); @@ -1010,7 +1010,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { match item { Some(item) if matches!(item.kind, hir::AssocItemKind::Fn { .. }) => { - if !tcx.impl_defaultness(item.id.def_id).has_value() { + if !tcx.impl_defaultness(item.id.owner_id).has_value() { tcx.sess .struct_span_err( item.span, diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs index c1214698cf77..3f263a6de24e 100644 --- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs +++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs @@ -331,8 +331,8 @@ fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetime /// `resolve_lifetimes`. fn resolve_lifetimes_for<'tcx>(tcx: TyCtxt<'tcx>, def_id: hir::OwnerId) -> &'tcx ResolveLifetimes { let item_id = item_for(tcx, def_id.def_id); - let local_def_id = item_id.def_id.def_id; - if item_id.def_id == def_id { + let local_def_id = item_id.owner_id.def_id; + if item_id.owner_id == def_id { let item = tcx.hir().item(item_id); match item.kind { hir::ItemKind::Trait(..) => tcx.resolve_lifetimes_trait_definition(local_def_id), @@ -557,11 +557,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // their owner, we can keep going until we find the Item that owns that. We then // conservatively add all resolved lifetimes. Otherwise we run into problems in // cases like `type Foo<'a> = impl Bar`. - for (_hir_id, node) in self.tcx.hir().parent_iter(item.def_id.into()) { + for (_hir_id, node) in self.tcx.hir().parent_iter(item.owner_id.into()) { match node { hir::Node::Item(parent_item) => { let resolved_lifetimes: &ResolveLifetimes = self.tcx.resolve_lifetimes( - item_for(self.tcx, parent_item.def_id.def_id).def_id.def_id, + item_for(self.tcx, parent_item.owner_id.def_id).owner_id.def_id, ); // We need to add *all* deps, since opaque tys may want them from *us* for (&owner, defs) in resolved_lifetimes.defs.iter() { diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 20903a68d6d9..bccd26481de0 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -643,24 +643,24 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T intravisit::walk_expr(self, ex); } fn visit_item(&mut self, it: &'tcx Item<'tcx>) { - trace!(?it.def_id); + trace!(?it.owner_id); // The opaque type itself or its children are not within its reveal scope. - if it.def_id.def_id != self.def_id { - self.check(it.def_id.def_id); + if it.owner_id.def_id != self.def_id { + self.check(it.owner_id.def_id); intravisit::walk_item(self, it); } } fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) { - trace!(?it.def_id); + trace!(?it.owner_id); // The opaque type itself or its children are not within its reveal scope. - if it.def_id.def_id != self.def_id { - self.check(it.def_id.def_id); + if it.owner_id.def_id != self.def_id { + self.check(it.owner_id.def_id); intravisit::walk_impl_item(self, it); } } fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) { - trace!(?it.def_id); - self.check(it.def_id.def_id); + trace!(?it.owner_id); + self.check(it.owner_id.def_id); intravisit::walk_trait_item(self, it); } } @@ -772,24 +772,24 @@ fn find_opaque_ty_constraints_for_rpit( intravisit::walk_expr(self, ex); } fn visit_item(&mut self, it: &'tcx Item<'tcx>) { - trace!(?it.def_id); + trace!(?it.owner_id); // The opaque type itself or its children are not within its reveal scope. - if it.def_id.def_id != self.def_id { - self.check(it.def_id.def_id); + if it.owner_id.def_id != self.def_id { + self.check(it.owner_id.def_id); intravisit::walk_item(self, it); } } fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) { - trace!(?it.def_id); + trace!(?it.owner_id); // The opaque type itself or its children are not within its reveal scope. - if it.def_id.def_id != self.def_id { - self.check(it.def_id.def_id); + if it.owner_id.def_id != self.def_id { + self.check(it.owner_id.def_id); intravisit::walk_impl_item(self, it); } } fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) { - trace!(?it.def_id); - self.check(it.def_id.def_id); + trace!(?it.owner_id); + self.check(it.owner_id.def_id); intravisit::walk_trait_item(self, it); } } diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index a84257b939c5..136f6199911a 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -55,10 +55,10 @@ fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { let min_specialization = tcx.features().min_specialization; let module = tcx.hir_module_items(module_def_id); for id in module.items() { - if matches!(tcx.def_kind(id.def_id), DefKind::Impl) { - enforce_impl_params_are_constrained(tcx, id.def_id.def_id); + if matches!(tcx.def_kind(id.owner_id), DefKind::Impl) { + enforce_impl_params_are_constrained(tcx, id.owner_id.def_id); if min_specialization { - check_min_specialization(tcx, id.def_id.def_id); + check_min_specialization(tcx, id.owner_id.def_id); } } } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index dba505149de8..525cd24190a4 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -381,7 +381,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { error = true; } if let hir::IsAsync::Async = sig.header.asyncness { - let span = tcx.def_span(it.def_id); + let span = tcx.def_span(it.owner_id); struct_span_err!( tcx.sess, span, diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs index 064a70107fe8..90c6edb65e46 100644 --- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs +++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs @@ -29,7 +29,7 @@ pub(super) fn infer_predicates<'tcx>( // Visit all the crates and infer predicates for id in tcx.hir().items() { - let item_did = id.def_id; + let item_did = id.owner_id; debug!("InferVisitor::visit_item(item={:?})", item_did); diff --git a/compiler/rustc_hir_analysis/src/outlives/test.rs b/compiler/rustc_hir_analysis/src/outlives/test.rs index eb0e1203405c..fa2ac56593bc 100644 --- a/compiler/rustc_hir_analysis/src/outlives/test.rs +++ b/compiler/rustc_hir_analysis/src/outlives/test.rs @@ -6,11 +6,11 @@ pub fn test_inferred_outlives(tcx: TyCtxt<'_>) { for id in tcx.hir().items() { // For unit testing: check for a special "rustc_outlives" // attribute and report an error with various results if found. - if tcx.has_attr(id.def_id.to_def_id(), sym::rustc_outlives) { - let inferred_outlives_of = tcx.inferred_outlives_of(id.def_id); + if tcx.has_attr(id.owner_id.to_def_id(), sym::rustc_outlives) { + let inferred_outlives_of = tcx.inferred_outlives_of(id.owner_id); struct_span_err!( tcx.sess, - tcx.def_span(id.def_id), + tcx.def_span(id.owner_id), E0640, "{:?}", inferred_outlives_of diff --git a/compiler/rustc_hir_analysis/src/variance/test.rs b/compiler/rustc_hir_analysis/src/variance/test.rs index 2ba87db880b4..83ed3e44b3d7 100644 --- a/compiler/rustc_hir_analysis/src/variance/test.rs +++ b/compiler/rustc_hir_analysis/src/variance/test.rs @@ -6,9 +6,10 @@ pub fn test_variance(tcx: TyCtxt<'_>) { // For unit testing: check for a special "rustc_variance" // attribute and report an error with various results if found. for id in tcx.hir().items() { - if tcx.has_attr(id.def_id.to_def_id(), sym::rustc_variance) { - let variances_of = tcx.variances_of(id.def_id); - struct_span_err!(tcx.sess, tcx.def_span(id.def_id), E0208, "{:?}", variances_of).emit(); + if tcx.has_attr(id.owner_id.to_def_id(), sym::rustc_variance) { + let variances_of = tcx.variances_of(id.owner_id); + struct_span_err!(tcx.sess, tcx.def_span(id.owner_id), E0208, "{:?}", variances_of) + .emit(); } } } diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 9c19f16a496b..79e2d371ed37 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -149,19 +149,19 @@ pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { let crate_items = tcx.hir_crate_items(()); for id in crate_items.items() { - dirty_clean_visitor.check_item(id.def_id.def_id); + dirty_clean_visitor.check_item(id.owner_id.def_id); } for id in crate_items.trait_items() { - dirty_clean_visitor.check_item(id.def_id.def_id); + dirty_clean_visitor.check_item(id.owner_id.def_id); } for id in crate_items.impl_items() { - dirty_clean_visitor.check_item(id.def_id.def_id); + dirty_clean_visitor.check_item(id.owner_id.def_id); } for id in crate_items.foreign_items() { - dirty_clean_visitor.check_item(id.def_id.def_id); + dirty_clean_visitor.check_item(id.owner_id.def_id); } let mut all_attrs = FindAllAttrs { tcx, found_attrs: vec![] }; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index a74c172fa0c1..9bf755d7fcdf 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -306,7 +306,7 @@ pub fn suggest_new_region_bound( }; // Get the identity type for this RPIT - let did = item_id.def_id.to_def_id(); + let did = item_id.owner_id.to_def_id(); let ty = tcx.mk_opaque(did, ty::InternalSubsts::identity_for_item(tcx, did)); if let Some(span) = opaque diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs index 2b1b931b7326..4c236c693d0f 100644 --- a/compiler/rustc_interface/src/proc_macro_decls.rs +++ b/compiler/rustc_interface/src/proc_macro_decls.rs @@ -9,7 +9,7 @@ fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option { for id in tcx.hir().items() { let attrs = finder.tcx.hir().attrs(id.hir_id()); if finder.tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) { - finder.decls = Some(id.def_id.def_id); + finder.decls = Some(id.owner_id.def_id); } } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index fa20e34f9ca2..be69a825db6a 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -177,7 +177,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxPointers { | hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { - self.check_heap_type(cx, it.span, cx.tcx.type_of(it.def_id)) + self.check_heap_type(cx, it.span, cx.tcx.type_of(it.owner_id)) } _ => (), } @@ -606,9 +606,9 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { match it.kind { hir::ItemKind::Trait(..) => { // Issue #11592: traits are always considered exported, even when private. - if cx.tcx.visibility(it.def_id) + if cx.tcx.visibility(it.owner_id) == ty::Visibility::Restricted( - cx.tcx.parent_module_from_def_id(it.def_id.def_id).to_def_id(), + cx.tcx.parent_module_from_def_id(it.owner_id.def_id).to_def_id(), ) { return; @@ -627,15 +627,15 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { _ => return, }; - let (article, desc) = cx.tcx.article_and_description(it.def_id.to_def_id()); + let (article, desc) = cx.tcx.article_and_description(it.owner_id.to_def_id()); - self.check_missing_docs_attrs(cx, it.def_id.def_id, article, desc); + self.check_missing_docs_attrs(cx, it.owner_id.def_id, article, desc); } fn check_trait_item(&mut self, cx: &LateContext<'_>, trait_item: &hir::TraitItem<'_>) { - let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id()); + let (article, desc) = cx.tcx.article_and_description(trait_item.owner_id.to_def_id()); - self.check_missing_docs_attrs(cx, trait_item.def_id.def_id, article, desc); + self.check_missing_docs_attrs(cx, trait_item.owner_id.def_id, article, desc); } fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { @@ -662,13 +662,13 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { } } - let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id()); - self.check_missing_docs_attrs(cx, impl_item.def_id.def_id, article, desc); + let (article, desc) = cx.tcx.article_and_description(impl_item.owner_id.to_def_id()); + self.check_missing_docs_attrs(cx, impl_item.owner_id.def_id, article, desc); } fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'_>) { - let (article, desc) = cx.tcx.article_and_description(foreign_item.def_id.to_def_id()); - self.check_missing_docs_attrs(cx, foreign_item.def_id.def_id, article, desc); + let (article, desc) = cx.tcx.article_and_description(foreign_item.owner_id.to_def_id()); + self.check_missing_docs_attrs(cx, foreign_item.owner_id.def_id, article, desc); } fn check_field_def(&mut self, cx: &LateContext<'_>, sf: &hir::FieldDef<'_>) { @@ -721,7 +721,7 @@ declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS]) impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - if !cx.effective_visibilities.is_reachable(item.def_id.def_id) { + if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) { return; } let (def, ty) = match item.kind { @@ -729,21 +729,21 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { if !ast_generics.params.is_empty() { return; } - let def = cx.tcx.adt_def(item.def_id); + let def = cx.tcx.adt_def(item.owner_id); (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[]))) } hir::ItemKind::Union(_, ref ast_generics) => { if !ast_generics.params.is_empty() { return; } - let def = cx.tcx.adt_def(item.def_id); + let def = cx.tcx.adt_def(item.owner_id); (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[]))) } hir::ItemKind::Enum(_, ref ast_generics) => { if !ast_generics.params.is_empty() { return; } - let def = cx.tcx.adt_def(item.def_id); + let def = cx.tcx.adt_def(item.owner_id); (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[]))) } _ => return, @@ -814,7 +814,7 @@ impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]); impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - if !cx.effective_visibilities.is_reachable(item.def_id.def_id) { + if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) { return; } @@ -841,7 +841,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations { debug!("{:?}", self.impling_types); } - if !self.impling_types.as_ref().unwrap().contains(&item.def_id.def_id) { + if !self.impling_types.as_ref().unwrap().contains(&item.owner_id.def_id) { cx.struct_span_lint( MISSING_DEBUG_IMPLEMENTATIONS, item.span, @@ -1226,7 +1226,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { check_no_mangle_on_generic_fn( no_mangle_attr, Some(generics), - cx.tcx.hir().get_generics(it.id.def_id.def_id).unwrap(), + cx.tcx.hir().get_generics(it.id.owner_id.def_id).unwrap(), it.span, ); } @@ -1415,11 +1415,11 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub { if let hir::ItemKind::Use(_, hir::UseKind::ListStem) = &item.kind { return; } - self.perform_lint(cx, "item", item.def_id.def_id, item.vis_span, true); + self.perform_lint(cx, "item", item.owner_id.def_id, item.vis_span, true); } fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'tcx>) { - self.perform_lint(cx, "item", foreign_item.def_id.def_id, foreign_item.vis_span, true); + self.perform_lint(cx, "item", foreign_item.owner_id.def_id, foreign_item.vis_span, true); } fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) { @@ -1429,8 +1429,8 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub { fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { // Only lint inherent impl items. - if cx.tcx.associated_item(impl_item.def_id).trait_item_def_id.is_none() { - self.perform_lint(cx, "item", impl_item.def_id.def_id, impl_item.vis_span, false); + if cx.tcx.associated_item(impl_item.owner_id).trait_item_def_id.is_none() { + self.perform_lint(cx, "item", impl_item.owner_id.def_id, impl_item.vis_span, false); } } } @@ -1639,7 +1639,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { use rustc_middle::ty::PredicateKind::*; if cx.tcx.features().trivial_bounds { - let predicates = cx.tcx.predicates_of(item.def_id); + let predicates = cx.tcx.predicates_of(item.owner_id); for &(predicate, span) in predicates.predicates { let predicate_kind_name = match predicate.kind().skip_binder() { Trait(..) => "trait", @@ -1882,7 +1882,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems { if let hir::ItemKind::Mod(..) = it.kind { } else { self.items_nameable = false; - self.boundary = Some(it.def_id); + self.boundary = Some(it.owner_id); } return; } @@ -1899,7 +1899,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems { } fn check_item_post(&mut self, _cx: &LateContext<'_>, it: &hir::Item<'_>) { - if !self.items_nameable && self.boundary == Some(it.def_id) { + if !self.items_nameable && self.boundary == Some(it.owner_id) { self.items_nameable = true; } } @@ -2165,7 +2165,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { use rustc_middle::middle::resolve_lifetime::Region; - let def_id = item.def_id.def_id; + let def_id = item.owner_id.def_id; if let hir::ItemKind::Struct(_, ref hir_generics) | hir::ItemKind::Enum(_, ref hir_generics) | hir::ItemKind::Union(_, ref hir_generics) = item.kind @@ -2744,7 +2744,7 @@ impl ClashingExternDeclarations { /// Insert a new foreign item into the seen set. If a symbol with the same name already exists /// for the item, return its HirId without updating the set. fn insert(&mut self, tcx: TyCtxt<'_>, fi: &hir::ForeignItem<'_>) -> Option { - let did = fi.def_id.to_def_id(); + let did = fi.owner_id.to_def_id(); let instance = Instance::new(did, ty::List::identity_for_item(tcx, did)); let name = Symbol::intern(tcx.symbol_name(instance).name); if let Some(&hir_id) = self.seen_decls.get(&name) { @@ -2762,14 +2762,14 @@ impl ClashingExternDeclarations { /// symbol's name. fn name_of_extern_decl(tcx: TyCtxt<'_>, fi: &hir::ForeignItem<'_>) -> SymbolName { if let Some((overridden_link_name, overridden_link_name_span)) = - tcx.codegen_fn_attrs(fi.def_id).link_name.map(|overridden_link_name| { + tcx.codegen_fn_attrs(fi.owner_id).link_name.map(|overridden_link_name| { // FIXME: Instead of searching through the attributes again to get span // information, we could have codegen_fn_attrs also give span information back for // where the attribute was defined. However, until this is found to be a // bottleneck, this does just fine. ( overridden_link_name, - tcx.get_attr(fi.def_id.to_def_id(), sym::link_name).unwrap().span, + tcx.get_attr(fi.owner_id.to_def_id(), sym::link_name).unwrap().span, ) }) { @@ -2986,10 +2986,10 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations { let tcx = cx.tcx; if let Some(existing_hid) = self.insert(tcx, this_fi) { let existing_decl_ty = tcx.type_of(tcx.hir().local_def_id(existing_hid)); - let this_decl_ty = tcx.type_of(this_fi.def_id); + let this_decl_ty = tcx.type_of(this_fi.owner_id); debug!( "ClashingExternDeclarations: Comparing existing {:?}: {:?} to this {:?}: {:?}", - existing_hid, existing_decl_ty, this_fi.def_id, this_decl_ty + existing_hid, existing_decl_ty, this_fi.owner_id, this_decl_ty ); // Check that the declarations match. if !Self::structurally_same_type( diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 7f6f4a0abb4a..00bf287ba6bd 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -61,7 +61,7 @@ declare_lint_pass!(OpaqueHiddenInferredBound => [OPAQUE_HIDDEN_INFERRED_BOUND]); impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { let hir::ItemKind::OpaqueTy(_) = &item.kind else { return; }; - let def_id = item.def_id.def_id.to_def_id(); + let def_id = item.owner_id.def_id.to_def_id(); let infcx = &cx.tcx.infer_ctxt().build(); // For every projection predicate in the opaque type's explicit bounds, // check that the type that we're assigning actually satisfies the bounds diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index a118dda8b40f..f22f38aa2cea 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -89,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { use rustc_middle::ty::PredicateKind::*; - let predicates = cx.tcx.explicit_predicates_of(item.def_id); + let predicates = cx.tcx.explicit_predicates_of(item.owner_id); for &(predicate, span) in predicates.predicates { let Trait(trait_predicate) = predicate.kind().skip_binder() else { continue diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 7c99bb2790fd..1b95f0e29d05 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1360,7 +1360,7 @@ declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]); impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences { fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { if let hir::ItemKind::Enum(ref enum_definition, _) = it.kind { - let t = cx.tcx.type_of(it.def_id); + let t = cx.tcx.type_of(it.owner_id); let ty = cx.tcx.erase_regions(t); let Ok(layout) = cx.layout_of(ty) else { return }; let Variants::Multiple { diff --git a/compiler/rustc_metadata/src/foreign_modules.rs b/compiler/rustc_metadata/src/foreign_modules.rs index 2ca4cd17fdf0..d1c2f3104d07 100644 --- a/compiler/rustc_metadata/src/foreign_modules.rs +++ b/compiler/rustc_metadata/src/foreign_modules.rs @@ -6,13 +6,13 @@ use rustc_session::cstore::ForeignModule; pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec { let mut modules = Vec::new(); for id in tcx.hir().items() { - if !matches!(tcx.def_kind(id.def_id), DefKind::ForeignMod) { + if !matches!(tcx.def_kind(id.owner_id), DefKind::ForeignMod) { continue; } let item = tcx.hir().item(id); if let hir::ItemKind::ForeignMod { items, .. } = item.kind { - let foreign_items = items.iter().map(|it| it.id.def_id.to_def_id()).collect(); - modules.push(ForeignModule { foreign_items, def_id: id.def_id.to_def_id() }); + let foreign_items = items.iter().map(|it| it.id.owner_id.to_def_id()).collect(); + modules.push(ForeignModule { foreign_items, def_id: id.owner_id.to_def_id() }); } } modules diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 676c67bad827..20a2e78299ae 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -98,7 +98,7 @@ struct Collector<'tcx> { impl<'tcx> Collector<'tcx> { fn process_item(&mut self, id: rustc_hir::ItemId) { - if !matches!(self.tcx.def_kind(id.def_id), DefKind::ForeignMod) { + if !matches!(self.tcx.def_kind(id.owner_id), DefKind::ForeignMod) { return; } @@ -372,17 +372,17 @@ impl<'tcx> Collector<'tcx> { } _ => { for child_item in foreign_mod_items { - if self.tcx.def_kind(child_item.id.def_id).has_codegen_attrs() + if self.tcx.def_kind(child_item.id.owner_id).has_codegen_attrs() && self .tcx - .codegen_fn_attrs(child_item.id.def_id) + .codegen_fn_attrs(child_item.id.owner_id) .link_ordinal .is_some() { let link_ordinal_attr = self .tcx .hir() - .attrs(child_item.id.def_id.into()) + .attrs(child_item.id.owner_id.into()) .iter() .find(|a| a.has_name(sym::link_ordinal)) .unwrap(); @@ -402,7 +402,7 @@ impl<'tcx> Collector<'tcx> { filename, kind, cfg, - foreign_module: Some(it.def_id.to_def_id()), + foreign_module: Some(it.owner_id.to_def_id()), wasm_import_module: wasm_import_module.map(|(name, _)| name), verbatim, dll_imports, @@ -505,7 +505,7 @@ impl<'tcx> Collector<'tcx> { fn i686_arg_list_size(&self, item: &hir::ForeignItemRef) -> usize { let argument_types: &List> = self.tcx.erase_late_bound_regions( self.tcx - .type_of(item.id.def_id) + .type_of(item.id.owner_id) .fn_sig(self.tcx) .inputs() .map_bound(|slice| self.tcx.mk_type_list(slice.iter())), @@ -557,7 +557,7 @@ impl<'tcx> Collector<'tcx> { } }; - let codegen_fn_attrs = self.tcx.codegen_fn_attrs(item.id.def_id); + let codegen_fn_attrs = self.tcx.codegen_fn_attrs(item.id.owner_id); let import_name_type = codegen_fn_attrs .link_ordinal .map_or(import_name_type, |ord| Some(PeImportNameType::Ordinal(ord))); @@ -567,7 +567,7 @@ impl<'tcx> Collector<'tcx> { import_name_type, calling_convention, span: item.span, - is_fn: self.tcx.def_kind(item.id.def_id).is_fn_like(), + is_fn: self.tcx.def_kind(item.id.owner_id).is_fn_like(), } } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 4e69b42416f5..049514ec7b24 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1290,21 +1290,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // from name resolution point of view. hir::ItemKind::ForeignMod { items, .. } => { for foreign_item in items { - yield foreign_item.id.def_id.def_id.local_def_index; + yield foreign_item.id.owner_id.def_id.local_def_index; } } // Only encode named non-reexport children, reexports are encoded // separately and unnamed items are not used by name resolution. hir::ItemKind::ExternCrate(..) => continue, hir::ItemKind::Struct(ref vdata, _) => { - yield item_id.def_id.def_id.local_def_index; + yield item_id.owner_id.def_id.local_def_index; // Encode constructors which take a separate slot in value namespace. if let Some(ctor_hir_id) = vdata.ctor_hir_id() { yield tcx.hir().local_def_id(ctor_hir_id).local_def_index; } } - _ if tcx.def_key(item_id.def_id.to_def_id()).get_opt_name().is_some() => { - yield item_id.def_id.def_id.local_def_index; + _ if tcx.def_key(item_id.owner_id.to_def_id()).get_opt_name().is_some() => { + yield item_id.owner_id.def_id.local_def_index; } _ => continue, } @@ -1541,7 +1541,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.macro_definition[def_id] <- &*macro_def.body); } hir::ItemKind::Mod(ref m) => { - return self.encode_info_for_mod(item.def_id.def_id, m); + return self.encode_info_for_mod(item.owner_id.def_id, m); } hir::ItemKind::OpaqueTy(..) => { self.encode_explicit_item_bounds(def_id); @@ -1673,7 +1673,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // normally in the visitor walk. match item.kind { hir::ItemKind::Enum(..) => { - let def = self.tcx.adt_def(item.def_id.to_def_id()); + let def = self.tcx.adt_def(item.owner_id.to_def_id()); for (i, variant) in def.variants().iter_enumerated() { self.encode_enum_variant_info(def, i); @@ -1683,7 +1683,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } hir::ItemKind::Struct(ref struct_def, _) => { - let def = self.tcx.adt_def(item.def_id.to_def_id()); + let def = self.tcx.adt_def(item.owner_id.to_def_id()); // If the struct has a constructor, encode it. if let Some(ctor_hir_id) = struct_def.ctor_hir_id() { let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id); @@ -1692,13 +1692,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } hir::ItemKind::Impl { .. } => { for &trait_item_def_id in - self.tcx.associated_item_def_ids(item.def_id.to_def_id()).iter() + self.tcx.associated_item_def_ids(item.owner_id.to_def_id()).iter() { self.encode_info_for_impl_item(trait_item_def_id); } } hir::ItemKind::Trait(..) => { - for &item_def_id in self.tcx.associated_item_def_ids(item.def_id.to_def_id()).iter() + for &item_def_id in + self.tcx.associated_item_def_ids(item.owner_id.to_def_id()).iter() { self.encode_info_for_trait_item(item_def_id); } @@ -1939,8 +1940,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { FxHashMap::default(); for id in tcx.hir().items() { - if matches!(tcx.def_kind(id.def_id), DefKind::Impl) { - if let Some(trait_ref) = tcx.impl_trait_ref(id.def_id) { + if matches!(tcx.def_kind(id.owner_id), DefKind::Impl) { + if let Some(trait_ref) = tcx.impl_trait_ref(id.owner_id) { let simplified_self_ty = fast_reject::simplify_type( self.tcx, trait_ref.self_ty(), @@ -1950,7 +1951,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fx_hash_map .entry(trait_ref.def_id) .or_default() - .push((id.def_id.def_id.local_def_index, simplified_self_ty)); + .push((id.owner_id.def_id.local_def_index, simplified_self_ty)); } } } @@ -2091,12 +2092,12 @@ impl<'a, 'tcx> Visitor<'tcx> for EncodeContext<'a, 'tcx> { intravisit::walk_item(self, item); match item.kind { hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => {} // ignore these - _ => self.encode_info_for_item(item.def_id.to_def_id(), item), + _ => self.encode_info_for_item(item.owner_id.to_def_id(), item), } } fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem<'tcx>) { intravisit::walk_foreign_item(self, ni); - self.encode_info_for_foreign_item(ni.def_id.to_def_id(), ni); + self.encode_info_for_foreign_item(ni.owner_id.to_def_id(), ni); } fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) { intravisit::walk_generics(self, generics); @@ -2315,8 +2316,8 @@ pub fn provide(providers: &mut Providers) { let mut traits = Vec::new(); for id in tcx.hir().items() { - if matches!(tcx.def_kind(id.def_id), DefKind::Trait | DefKind::TraitAlias) { - traits.push(id.def_id.to_def_id()) + if matches!(tcx.def_kind(id.owner_id), DefKind::Trait | DefKind::TraitAlias) { + traits.push(id.owner_id.to_def_id()) } } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 302f12a6f7d4..83a4d16d7a92 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -354,19 +354,19 @@ impl<'hir> Map<'hir> { } pub fn item(self, id: ItemId) -> &'hir Item<'hir> { - self.tcx.hir_owner(id.def_id).unwrap().node.expect_item() + self.tcx.hir_owner(id.owner_id).unwrap().node.expect_item() } pub fn trait_item(self, id: TraitItemId) -> &'hir TraitItem<'hir> { - self.tcx.hir_owner(id.def_id).unwrap().node.expect_trait_item() + self.tcx.hir_owner(id.owner_id).unwrap().node.expect_trait_item() } pub fn impl_item(self, id: ImplItemId) -> &'hir ImplItem<'hir> { - self.tcx.hir_owner(id.def_id).unwrap().node.expect_impl_item() + self.tcx.hir_owner(id.owner_id).unwrap().node.expect_impl_item() } pub fn foreign_item(self, id: ForeignItemId) -> &'hir ForeignItem<'hir> { - self.tcx.hir_owner(id.def_id).unwrap().node.expect_foreign_item() + self.tcx.hir_owner(id.owner_id).unwrap().node.expect_foreign_item() } pub fn body(self, id: BodyId) -> &'hir Body<'hir> { @@ -1377,14 +1377,14 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> { fn visit_item(&mut self, item: &'hir Item<'hir>) { if associated_body(Node::Item(item)).is_some() { - self.body_owners.push(item.def_id.def_id); + self.body_owners.push(item.owner_id.def_id); } self.items.push(item.item_id()); // Items that are modules are handled here instead of in visit_mod. if let ItemKind::Mod(module) = &item.kind { - self.submodules.push(item.def_id); + self.submodules.push(item.owner_id); // A module collector does not recurse inside nested modules. if self.crate_collector { intravisit::walk_mod(self, module, item.hir_id()); @@ -1413,7 +1413,7 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> { fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) { if associated_body(Node::TraitItem(item)).is_some() { - self.body_owners.push(item.def_id.def_id); + self.body_owners.push(item.owner_id.def_id); } self.trait_items.push(item.trait_item_id()); @@ -1422,7 +1422,7 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> { fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) { if associated_body(Node::ImplItem(item)).is_some() { - self.body_owners.push(item.def_id.def_id); + self.body_owners.push(item.owner_id.def_id); } self.impl_items.push(item.impl_item_id()); diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 1ce98a03c8a6..1c6264ad0365 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -67,10 +67,10 @@ impl ModuleItems { pub fn definitions(&self) -> impl Iterator + '_ { self.items .iter() - .map(|id| id.def_id.def_id) - .chain(self.trait_items.iter().map(|id| id.def_id.def_id)) - .chain(self.impl_items.iter().map(|id| id.def_id.def_id)) - .chain(self.foreign_items.iter().map(|id| id.def_id.def_id)) + .map(|id| id.owner_id.def_id) + .chain(self.trait_items.iter().map(|id| id.owner_id.def_id)) + .chain(self.impl_items.iter().map(|id| id.owner_id.def_id)) + .chain(self.foreign_items.iter().map(|id| id.owner_id.def_id)) } pub fn par_items(&self, f: impl Fn(ItemId) + Send + Sync) { diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index fdda62719ee1..15a24aa4ace5 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -81,7 +81,7 @@ impl<'tcx> MonoItem<'tcx> { MonoItem::Fn(instance) => tcx.symbol_name(instance), MonoItem::Static(def_id) => tcx.symbol_name(Instance::mono(tcx, def_id)), MonoItem::GlobalAsm(item_id) => { - SymbolName::new(tcx, &format!("global_asm_{:?}", item_id.def_id)) + SymbolName::new(tcx, &format!("global_asm_{:?}", item_id.owner_id)) } } } @@ -182,7 +182,7 @@ impl<'tcx> MonoItem<'tcx> { match *self { MonoItem::Fn(Instance { def, .. }) => def.def_id().as_local(), MonoItem::Static(def_id) => def_id.as_local(), - MonoItem::GlobalAsm(item_id) => Some(item_id.def_id.def_id), + MonoItem::GlobalAsm(item_id) => Some(item_id.owner_id.def_id), } .map(|def_id| tcx.def_span(def_id)) } @@ -373,7 +373,7 @@ impl<'tcx> CodegenUnit<'tcx> { } } MonoItem::Static(def_id) => def_id.as_local().map(Idx::index), - MonoItem::GlobalAsm(item_id) => Some(item_id.def_id.def_id.index()), + MonoItem::GlobalAsm(item_id) => Some(item_id.owner_id.def_id.index()), }, item.symbol_name(tcx), ) diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 52f16ad88f69..4e6cdb786025 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -872,9 +872,9 @@ fn foo(&self) -> Self::T { String::new() } // FIXME: account for returning some type in a trait fn impl that has // an assoc type as a return type (#72076). if let hir::Defaultness::Default { has_value: true } = - self.impl_defaultness(item.id.def_id) + self.impl_defaultness(item.id.owner_id) { - if self.type_of(item.id.def_id) == found { + if self.type_of(item.id.owner_id) == found { diag.span_label( item.span, "associated type defaults can't be assumed inside the \ @@ -894,7 +894,7 @@ fn foo(&self) -> Self::T { String::new() } })) => { for item in &items[..] { if let hir::AssocItemKind::Type = item.kind { - if self.type_of(item.id.def_id) == found { + if self.type_of(item.id.owner_id) == found { diag.span_label(item.span, "expected this associated type"); return true; } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index c1c2e162f283..ef9aa236bacf 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2740,7 +2740,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N // Iterate all local crate items no matter where they are defined. let hir = tcx.hir(); for id in hir.items() { - if matches!(tcx.def_kind(id.def_id), DefKind::Use) { + if matches!(tcx.def_kind(id.owner_id), DefKind::Use) { continue; } @@ -2749,7 +2749,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N continue; } - let def_id = item.def_id.to_def_id(); + let def_id = item.owner_id.to_def_id(); let ns = tcx.def_kind(def_id).ns().unwrap_or(Namespace::TypeNS); collect_fn(&item.ident, ns, def_id); } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 5cd7a7f760f5..52b0948f44ac 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1192,7 +1192,7 @@ struct RootCollector<'a, 'tcx> { impl<'v> RootCollector<'_, 'v> { fn process_item(&mut self, id: hir::ItemId) { - match self.tcx.def_kind(id.def_id) { + match self.tcx.def_kind(id.owner_id) { DefKind::Enum | DefKind::Struct | DefKind::Union => { let item = self.tcx.hir().item(id); match item.kind { @@ -1203,12 +1203,14 @@ impl<'v> RootCollector<'_, 'v> { if self.mode == MonoItemCollectionMode::Eager { debug!( "RootCollector: ADT drop-glue for {}", - self.tcx.def_path_str(item.def_id.to_def_id()) + self.tcx.def_path_str(item.owner_id.to_def_id()) ); - let ty = - Instance::new(item.def_id.to_def_id(), InternalSubsts::empty()) - .ty(self.tcx, ty::ParamEnv::reveal_all()); + let ty = Instance::new( + item.owner_id.to_def_id(), + InternalSubsts::empty(), + ) + .ty(self.tcx, ty::ParamEnv::reveal_all()); visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output); } } @@ -1219,23 +1221,23 @@ impl<'v> RootCollector<'_, 'v> { DefKind::GlobalAsm => { debug!( "RootCollector: ItemKind::GlobalAsm({})", - self.tcx.def_path_str(id.def_id.to_def_id()) + self.tcx.def_path_str(id.owner_id.to_def_id()) ); self.output.push(dummy_spanned(MonoItem::GlobalAsm(id))); } DefKind::Static(..) => { debug!( "RootCollector: ItemKind::Static({})", - self.tcx.def_path_str(id.def_id.to_def_id()) + self.tcx.def_path_str(id.owner_id.to_def_id()) ); - self.output.push(dummy_spanned(MonoItem::Static(id.def_id.to_def_id()))); + self.output.push(dummy_spanned(MonoItem::Static(id.owner_id.to_def_id()))); } DefKind::Const => { // const items only generate mono items if they are // actually used somewhere. Just declaring them is insufficient. // but even just declaring them must collect the items they refer to - if let Ok(val) = self.tcx.const_eval_poly(id.def_id.to_def_id()) { + if let Ok(val) = self.tcx.const_eval_poly(id.owner_id.to_def_id()) { collect_const_value(self.tcx, val, &mut self.output); } } @@ -1246,15 +1248,15 @@ impl<'v> RootCollector<'_, 'v> { } } DefKind::Fn => { - self.push_if_root(id.def_id.def_id); + self.push_if_root(id.owner_id.def_id); } _ => {} } } fn process_impl_item(&mut self, id: hir::ImplItemId) { - if matches!(self.tcx.def_kind(id.def_id), DefKind::AssocFn) { - self.push_if_root(id.def_id.def_id); + if matches!(self.tcx.def_kind(id.owner_id), DefKind::AssocFn) { + self.push_if_root(id.owner_id.def_id); } } @@ -1352,13 +1354,13 @@ fn create_mono_items_for_default_impls<'tcx>( debug!( "create_mono_items_for_default_impls(item={})", - tcx.def_path_str(item.def_id.to_def_id()) + tcx.def_path_str(item.owner_id.to_def_id()) ); - if let Some(trait_ref) = tcx.impl_trait_ref(item.def_id) { + if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) { let param_env = ty::ParamEnv::reveal_all(); let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref); - let overridden_methods = tcx.impl_item_implementor_ids(item.def_id); + let overridden_methods = tcx.impl_item_implementor_ids(item.owner_id); for method in tcx.provided_trait_methods(trait_ref.def_id) { if overridden_methods.contains_key(&method.def_id) { continue; diff --git a/compiler/rustc_monomorphize/src/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs index 15276569c32f..29009c48050e 100644 --- a/compiler/rustc_monomorphize/src/partitioning/default.rs +++ b/compiler/rustc_monomorphize/src/partitioning/default.rs @@ -319,7 +319,7 @@ fn characteristic_def_id_of_mono_item<'tcx>( Some(def_id) } MonoItem::Static(def_id) => Some(def_id), - MonoItem::GlobalAsm(item_id) => Some(item_id.def_id.to_def_id()), + MonoItem::GlobalAsm(item_id) => Some(item_id.owner_id.to_def_id()), } } @@ -411,9 +411,9 @@ fn mono_item_visibility<'tcx>( }; } MonoItem::GlobalAsm(item_id) => { - return if tcx.is_reachable_non_generic(item_id.def_id) { + return if tcx.is_reachable_non_generic(item_id.owner_id) { *can_be_internalized = false; - default_visibility(tcx, item_id.def_id.to_def_id(), false) + default_visibility(tcx, item_id.owner_id.to_def_id(), false) } else { Visibility::Hidden }; diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index b19e85427e72..27a57adf964a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2062,7 +2062,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { // so this lets us continue to run them while maintaining backwards compatibility. // In the long run, the checks should be harmonized. if let ItemKind::Macro(ref macro_def, _) = item.kind { - let def_id = item.def_id.to_def_id(); + let def_id = item.owner_id.to_def_id(); if macro_def.macro_rules && !self.tcx.has_attr(def_id, sym::macro_export) { check_non_exported_macro_for_invalid_attrs(self.tcx, item); } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 2fb46f47da27..753d01f46cab 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -280,8 +280,8 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } fn visit_node(&mut self, node: Node<'tcx>) { - if let Node::ImplItem(hir::ImplItem { def_id, .. }) = node - && self.should_ignore_item(def_id.to_def_id()) + if let Node::ImplItem(hir::ImplItem { owner_id, .. }) = node + && self.should_ignore_item(owner_id.to_def_id()) { return; } @@ -293,7 +293,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { match node { Node::Item(item) => match item.kind { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { - let def = self.tcx.adt_def(item.def_id); + let def = self.tcx.adt_def(item.owner_id); self.repr_has_repr_c = def.repr().c(); self.repr_has_repr_simd = def.repr().simd(); @@ -306,7 +306,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { intravisit::walk_trait_item(self, trait_item); } Node::ImplItem(impl_item) => { - let item = self.tcx.local_parent(impl_item.def_id.def_id); + let item = self.tcx.local_parent(impl_item.owner_id.def_id); if self.tcx.impl_trait_ref(item).is_none() { //// If it's a type whose items are live, then it's live, too. //// This is done to handle the case where, for example, the static @@ -517,10 +517,10 @@ fn check_item<'tcx>( ) { let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, id.hir_id()); if allow_dead_code { - worklist.push(id.def_id.def_id); + worklist.push(id.owner_id.def_id); } - match tcx.def_kind(id.def_id) { + match tcx.def_kind(id.owner_id) { DefKind::Enum => { let item = tcx.hir().item(id); if let hir::ItemKind::Enum(ref enum_def, _) = item.kind { @@ -540,15 +540,15 @@ fn check_item<'tcx>( } } DefKind::Impl => { - let of_trait = tcx.impl_trait_ref(id.def_id); + let of_trait = tcx.impl_trait_ref(id.owner_id); if of_trait.is_some() { - worklist.push(id.def_id.def_id); + worklist.push(id.owner_id.def_id); } // get DefIds from another query let local_def_ids = tcx - .associated_item_def_ids(id.def_id) + .associated_item_def_ids(id.owner_id) .iter() .filter_map(|def_id| def_id.as_local()); @@ -566,12 +566,12 @@ fn check_item<'tcx>( if let hir::ItemKind::Struct(ref variant_data, _) = item.kind && let Some(ctor_hir_id) = variant_data.ctor_hir_id() { - struct_constructors.insert(tcx.hir().local_def_id(ctor_hir_id), item.def_id.def_id); + struct_constructors.insert(tcx.hir().local_def_id(ctor_hir_id), item.owner_id.def_id); } } DefKind::GlobalAsm => { // global_asm! is always live. - worklist.push(id.def_id.def_id); + worklist.push(id.owner_id.def_id); } _ => {} } @@ -579,12 +579,12 @@ fn check_item<'tcx>( fn check_trait_item<'tcx>(tcx: TyCtxt<'tcx>, worklist: &mut Vec, id: hir::TraitItemId) { use hir::TraitItemKind::{Const, Fn}; - if matches!(tcx.def_kind(id.def_id), DefKind::AssocConst | DefKind::AssocFn) { + if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) { let trait_item = tcx.hir().trait_item(id); if matches!(trait_item.kind, Const(_, Some(_)) | Fn(_, hir::TraitFn::Provided(_))) && has_allow_dead_code_or_lang_attr(tcx, trait_item.hir_id()) { - worklist.push(trait_item.def_id.def_id); + worklist.push(trait_item.owner_id.def_id); } } } @@ -594,10 +594,10 @@ fn check_foreign_item<'tcx>( worklist: &mut Vec, id: hir::ForeignItemId, ) { - if matches!(tcx.def_kind(id.def_id), DefKind::Static(_) | DefKind::Fn) + if matches!(tcx.def_kind(id.owner_id), DefKind::Static(_) | DefKind::Fn) && has_allow_dead_code_or_lang_attr(tcx, id.hir_id()) { - worklist.push(id.def_id.def_id); + worklist.push(id.owner_id.def_id); } } @@ -861,19 +861,19 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) { let module_items = tcx.hir_module_items(module); for item in module_items.items() { - if !live_symbols.contains(&item.def_id.def_id) { - let parent = tcx.local_parent(item.def_id.def_id); + if !live_symbols.contains(&item.owner_id.def_id) { + let parent = tcx.local_parent(item.owner_id.def_id); if parent != module && !live_symbols.contains(&parent) { // We already have diagnosed something. continue; } - visitor.check_definition(item.def_id.def_id); + visitor.check_definition(item.owner_id.def_id); continue; } - let def_kind = tcx.def_kind(item.def_id); + let def_kind = tcx.def_kind(item.owner_id); if let DefKind::Struct | DefKind::Union | DefKind::Enum = def_kind { - let adt = tcx.adt_def(item.def_id); + let adt = tcx.adt_def(item.owner_id); let mut dead_variants = Vec::new(); for variant in adt.variants() { @@ -917,7 +917,7 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) { } visitor.warn_dead_fields_and_variants( - item.def_id.def_id, + item.owner_id.def_id, "constructed", dead_variants, false, @@ -926,11 +926,11 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) { } for impl_item in module_items.impl_items() { - visitor.check_definition(impl_item.def_id.def_id); + visitor.check_definition(impl_item.owner_id.def_id); } for foreign_item in module_items.foreign_items() { - visitor.check_definition(foreign_item.def_id.def_id); + visitor.check_definition(foreign_item.owner_id.def_id); } // We do not warn trait items. diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index 3f991cf65724..a72056e00b1e 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -73,19 +73,19 @@ fn diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> DiagnosticItems let crate_items = tcx.hir_crate_items(()); for id in crate_items.items() { - observe_item(tcx, &mut diagnostic_items, id.def_id.def_id); + observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id); } for id in crate_items.trait_items() { - observe_item(tcx, &mut diagnostic_items, id.def_id.def_id); + observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id); } for id in crate_items.impl_items() { - observe_item(tcx, &mut diagnostic_items, id.def_id.def_id); + observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id); } for id in crate_items.foreign_items() { - observe_item(tcx, &mut diagnostic_items, id.def_id.def_id); + observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id); } diagnostic_items diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index 38a259ca8846..5885f45ae45d 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -62,7 +62,7 @@ fn entry_point_type(ctxt: &EntryContext<'_>, id: ItemId, at_root: bool) -> Entry } else if ctxt.tcx.sess.contains_name(attrs, sym::rustc_main) { EntryPointType::RustcMainAttr } else { - if let Some(name) = ctxt.tcx.opt_item_name(id.def_id.to_def_id()) + if let Some(name) = ctxt.tcx.opt_item_name(id.owner_id.to_def_id()) && name == sym::main { if at_root { // This is a top-level function so can be `main`. @@ -82,7 +82,7 @@ fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Opti } fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { - let at_root = ctxt.tcx.opt_local_parent(id.def_id.def_id) == Some(CRATE_DEF_ID); + let at_root = ctxt.tcx.opt_local_parent(id.owner_id.def_id) == Some(CRATE_DEF_ID); match entry_point_type(ctxt, id, at_root) { EntryPointType::None => { @@ -90,7 +90,7 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { ctxt.tcx.sess.emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe }); } } - _ if !matches!(ctxt.tcx.def_kind(id.def_id), DefKind::Fn) => { + _ if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) => { for attr in [sym::start, sym::rustc_main] { if let Some(span) = attr_span_by_symbol(ctxt, id, attr) { ctxt.tcx.sess.emit_err(AttrOnlyInFunctions { span, attr }); @@ -102,16 +102,16 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) { ctxt.tcx.sess.emit_err(AttrOnlyOnRootMain { span, attr: sym::unix_sigpipe }); } - ctxt.non_main_fns.push(ctxt.tcx.def_span(id.def_id)); + ctxt.non_main_fns.push(ctxt.tcx.def_span(id.owner_id)); } EntryPointType::RustcMainAttr => { if ctxt.attr_main_fn.is_none() { - ctxt.attr_main_fn = Some((id.def_id.def_id, ctxt.tcx.def_span(id.def_id))); + ctxt.attr_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id))); } else { ctxt.tcx.sess.emit_err(MultipleRustcMain { - span: ctxt.tcx.def_span(id.def_id.to_def_id()), + span: ctxt.tcx.def_span(id.owner_id.to_def_id()), first: ctxt.attr_main_fn.unwrap().1, - additional: ctxt.tcx.def_span(id.def_id.to_def_id()), + additional: ctxt.tcx.def_span(id.owner_id.to_def_id()), }); } } @@ -120,11 +120,11 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { ctxt.tcx.sess.emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe }); } if ctxt.start_fn.is_none() { - ctxt.start_fn = Some((id.def_id.def_id, ctxt.tcx.def_span(id.def_id))); + ctxt.start_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id))); } else { ctxt.tcx.sess.emit_err(MultipleStartFunctions { - span: ctxt.tcx.def_span(id.def_id), - labeled: ctxt.tcx.def_span(id.def_id.to_def_id()), + span: ctxt.tcx.def_span(id.owner_id), + labeled: ctxt.tcx.def_span(id.owner_id.to_def_id()), previous: ctxt.start_fn.unwrap().1, }); } diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index 3ee8c8bcb1de..88bb39debb11 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -126,7 +126,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { fn visit_item(&mut self, i: &'hir hir::Item<'hir>) { let mut inner_visitor = self.new_visitor(self.hir_map); - inner_visitor.check(i.def_id, |this| intravisit::walk_item(this, i)); + inner_visitor.check(i.owner_id, |this| intravisit::walk_item(this, i)); } fn visit_id(&mut self, hir_id: HirId) { @@ -148,16 +148,16 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { fn visit_foreign_item(&mut self, i: &'hir hir::ForeignItem<'hir>) { let mut inner_visitor = self.new_visitor(self.hir_map); - inner_visitor.check(i.def_id, |this| intravisit::walk_foreign_item(this, i)); + inner_visitor.check(i.owner_id, |this| intravisit::walk_foreign_item(this, i)); } fn visit_trait_item(&mut self, i: &'hir hir::TraitItem<'hir>) { let mut inner_visitor = self.new_visitor(self.hir_map); - inner_visitor.check(i.def_id, |this| intravisit::walk_trait_item(this, i)); + inner_visitor.check(i.owner_id, |this| intravisit::walk_trait_item(this, i)); } fn visit_impl_item(&mut self, i: &'hir hir::ImplItem<'hir>) { let mut inner_visitor = self.new_visitor(self.hir_map); - inner_visitor.check(i.def_id, |this| intravisit::walk_impl_item(this, i)); + inner_visitor.check(i.owner_id, |this| intravisit::walk_impl_item(this, i)); } } diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 71b0735192ac..df811be2a7e4 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -217,9 +217,9 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems { let crate_items = tcx.hir_crate_items(()); for id in crate_items.items() { - collector.check_for_lang(Target::from_def_kind(tcx.def_kind(id.def_id)), id.hir_id()); + collector.check_for_lang(Target::from_def_kind(tcx.def_kind(id.owner_id)), id.hir_id()); - if matches!(tcx.def_kind(id.def_id), DefKind::Enum) { + if matches!(tcx.def_kind(id.owner_id), DefKind::Enum) { let item = tcx.hir().item(id); if let hir::ItemKind::Enum(def, ..) = &item.kind { for variant in def.variants { diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index c1085094962a..5322baee7473 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -15,11 +15,11 @@ pub fn test_layout(tcx: TyCtxt<'_>) { // if the `rustc_attrs` feature is not enabled, don't bother testing layout for id in tcx.hir().items() { if matches!( - tcx.def_kind(id.def_id), + tcx.def_kind(id.owner_id), DefKind::TyAlias | DefKind::Enum | DefKind::Struct | DefKind::Union ) { - for attr in tcx.get_attrs(id.def_id.to_def_id(), sym::rustc_layout) { - dump_layout_of(tcx, id.def_id.def_id, attr); + for attr in tcx.get_attrs(id.owner_id.to_def_id(), sym::rustc_layout) { + dump_layout_of(tcx, id.owner_id.def_id, attr); } } } diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 273cab7922e3..10d5fc5d6711 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -29,7 +29,7 @@ fn item_might_be_inlined(tcx: TyCtxt<'_>, item: &hir::Item<'_>, attrs: &CodegenF match item.kind { hir::ItemKind::Fn(ref sig, ..) if sig.header.is_const() => true, hir::ItemKind::Impl { .. } | hir::ItemKind::Fn(..) => { - let generics = tcx.generics_of(item.def_id); + let generics = tcx.generics_of(item.owner_id); generics.requires_monomorphization(tcx) } _ => false, @@ -42,7 +42,7 @@ fn method_might_be_inlined( impl_src: LocalDefId, ) -> bool { let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id().owner.to_def_id()); - let generics = tcx.generics_of(impl_item.def_id); + let generics = tcx.generics_of(impl_item.owner_id); if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) { return true; } @@ -216,7 +216,7 @@ impl<'tcx> ReachableContext<'tcx> { if item_might_be_inlined( self.tcx, &item, - self.tcx.codegen_fn_attrs(item.def_id), + self.tcx.codegen_fn_attrs(item.owner_id), ) { self.visit_nested_body(body); } @@ -305,11 +305,11 @@ fn check_item<'tcx>( worklist: &mut Vec, effective_visibilities: &privacy::EffectiveVisibilities, ) { - if has_custom_linkage(tcx, id.def_id.def_id) { - worklist.push(id.def_id.def_id); + if has_custom_linkage(tcx, id.owner_id.def_id) { + worklist.push(id.owner_id.def_id); } - if !matches!(tcx.def_kind(id.def_id), DefKind::Impl) { + if !matches!(tcx.def_kind(id.owner_id), DefKind::Impl) { return; } @@ -318,8 +318,8 @@ fn check_item<'tcx>( if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref trait_ref), ref items, .. }) = item.kind { - if !effective_visibilities.is_reachable(item.def_id.def_id) { - worklist.extend(items.iter().map(|ii_ref| ii_ref.id.def_id.def_id)); + if !effective_visibilities.is_reachable(item.owner_id.def_id) { + worklist.extend(items.iter().map(|ii_ref| ii_ref.id.owner_id.def_id)); let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res else { unreachable!(); @@ -403,8 +403,8 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet { } for id in crate_items.impl_items() { - if has_custom_linkage(tcx, id.def_id.def_id) { - reachable_context.worklist.push(id.def_id.def_id); + if has_custom_linkage(tcx, id.owner_id.def_id) { + reachable_context.worklist.push(id.owner_id.def_id); } } } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index d7655655d78c..78afa2f25f8e 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -378,7 +378,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { } self.annotate( - i.def_id.def_id, + i.owner_id.def_id, i.span, fn_sig, kind, @@ -397,7 +397,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { }; self.annotate( - ti.def_id.def_id, + ti.owner_id.def_id, ti.span, fn_sig, AnnotationKind::Required, @@ -420,7 +420,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { }; self.annotate( - ii.def_id.def_id, + ii.owner_id.def_id, ii.span, fn_sig, kind, @@ -478,7 +478,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) { self.annotate( - i.def_id.def_id, + i.owner_id.def_id, i.span, None, AnnotationKind::Required, @@ -569,25 +569,25 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { hir::ItemKind::Impl(hir::Impl { of_trait: None, .. }) | hir::ItemKind::ForeignMod { .. } ) { - self.check_missing_stability(i.def_id.def_id, i.span); + self.check_missing_stability(i.owner_id.def_id, i.span); } // Ensure stable `const fn` have a const stability attribute. - self.check_missing_const_stability(i.def_id.def_id, i.span); + self.check_missing_const_stability(i.owner_id.def_id, i.span); intravisit::walk_item(self, i) } fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) { - self.check_missing_stability(ti.def_id.def_id, ti.span); + self.check_missing_stability(ti.owner_id.def_id, ti.span); intravisit::walk_trait_item(self, ti); } fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) { let impl_def_id = self.tcx.hir().get_parent_item(ii.hir_id()); if self.tcx.impl_trait_ref(impl_def_id).is_none() { - self.check_missing_stability(ii.def_id.def_id, ii.span); - self.check_missing_const_stability(ii.def_id.def_id, ii.span); + self.check_missing_stability(ii.owner_id.def_id, ii.span); + self.check_missing_const_stability(ii.owner_id.def_id, ii.span); } intravisit::walk_impl_item(self, ii); } @@ -606,7 +606,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { } fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) { - self.check_missing_stability(i.def_id.def_id, i.span); + self.check_missing_stability(i.owner_id.def_id, i.span); intravisit::walk_foreign_item(self, i); } // Note that we don't need to `check_missing_stability` for default generic parameters, @@ -712,7 +712,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { return; } - let Some(cnum) = self.tcx.extern_mod_stmt_cnum(item.def_id.def_id) else { + let Some(cnum) = self.tcx.extern_mod_stmt_cnum(item.owner_id.def_id) else { return; }; let def_id = cnum.as_def_id(); @@ -765,7 +765,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { } for impl_item_ref in *items { - let impl_item = self.tcx.associated_item(impl_item_ref.id.def_id); + let impl_item = self.tcx.associated_item(impl_item_ref.id.owner_id); if let Some(def_id) = impl_item.trait_item_def_id { // Pass `None` to skip deprecation warnings. diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index 92024989a75e..959ee600c070 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -34,7 +34,7 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem items.missing.push(item); } } else { - let span = tcx.def_span(id.def_id); + let span = tcx.def_span(id.owner_id); tcx.sess.emit_err(UnknownExternLangItem { span, lang_item }); } } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index df8454ed4ee0..865d6306bd34 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -505,9 +505,9 @@ impl<'tcx> EmbargoVisitor<'tcx> { fn update_macro_reachable_mod(&mut self, module_def_id: LocalDefId, defining_mod: LocalDefId) { let module = self.tcx.hir().get_module(module_def_id).0; for item_id in module.item_ids { - let def_kind = self.tcx.def_kind(item_id.def_id); - let vis = self.tcx.local_visibility(item_id.def_id.def_id); - self.update_macro_reachable_def(item_id.def_id.def_id, def_kind, vis, defining_mod); + let def_kind = self.tcx.def_kind(item_id.owner_id); + let vis = self.tcx.local_visibility(item_id.owner_id.def_id); + self.update_macro_reachable_def(item_id.owner_id.def_id, def_kind, vis, defining_mod); } if let Some(exports) = self.tcx.module_reexports(module_def_id) { for export in exports { @@ -628,13 +628,13 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { let item_level = match item.kind { hir::ItemKind::Impl { .. } => { let impl_level = Option::::of_impl( - item.def_id.def_id, + item.owner_id.def_id, self.tcx, &self.effective_visibilities, ); - self.update(item.def_id.def_id, impl_level) + self.update(item.owner_id.def_id, impl_level) } - _ => self.get(item.def_id.def_id), + _ => self.get(item.owner_id.def_id), }; // Update levels of nested things. @@ -653,15 +653,15 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { hir::ItemKind::Impl(ref impl_) => { for impl_item_ref in impl_.items { if impl_.of_trait.is_some() - || self.tcx.visibility(impl_item_ref.id.def_id).is_public() + || self.tcx.visibility(impl_item_ref.id.owner_id).is_public() { - self.update(impl_item_ref.id.def_id.def_id, item_level); + self.update(impl_item_ref.id.owner_id.def_id, item_level); } } } hir::ItemKind::Trait(.., trait_item_refs) => { for trait_item_ref in trait_item_refs { - self.update(trait_item_ref.id.def_id.def_id, item_level); + self.update(trait_item_ref.id.owner_id.def_id, item_level); } } hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => { @@ -677,12 +677,12 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } } hir::ItemKind::Macro(ref macro_def, _) => { - self.update_reachability_from_macro(item.def_id.def_id, macro_def); + self.update_reachability_from_macro(item.owner_id.def_id, macro_def); } hir::ItemKind::ForeignMod { items, .. } => { for foreign_item in items { - if self.tcx.visibility(foreign_item.id.def_id).is_public() { - self.update(foreign_item.id.def_id.def_id, item_level); + if self.tcx.visibility(foreign_item.id.owner_id).is_public() { + self.update(foreign_item.id.owner_id.def_id, item_level); } } } @@ -719,7 +719,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { // in the reachability pass (`middle/reachable.rs`). Types are marked as link-time // reachable if they are returned via `impl Trait`, even from private functions. let exist_level = cmp::max(item_level, Some(Level::ReachableThroughImplTrait)); - self.reach(item.def_id.def_id, exist_level).generics().predicates().ty(); + self.reach(item.owner_id.def_id, exist_level).generics().predicates().ty(); } } // Visit everything. @@ -728,20 +728,20 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { | hir::ItemKind::Fn(..) | hir::ItemKind::TyAlias(..) => { if item_level.is_some() { - self.reach(item.def_id.def_id, item_level).generics().predicates().ty(); + self.reach(item.owner_id.def_id, item_level).generics().predicates().ty(); } } hir::ItemKind::Trait(.., trait_item_refs) => { if item_level.is_some() { - self.reach(item.def_id.def_id, item_level).generics().predicates(); + self.reach(item.owner_id.def_id, item_level).generics().predicates(); for trait_item_ref in trait_item_refs { let tcx = self.tcx; - let mut reach = self.reach(trait_item_ref.id.def_id.def_id, item_level); + let mut reach = self.reach(trait_item_ref.id.owner_id.def_id, item_level); reach.generics().predicates(); if trait_item_ref.kind == AssocItemKind::Type - && !tcx.impl_defaultness(trait_item_ref.id.def_id).has_value() + && !tcx.impl_defaultness(trait_item_ref.id.owner_id).has_value() { // No type to visit. } else { @@ -752,22 +752,22 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } hir::ItemKind::TraitAlias(..) => { if item_level.is_some() { - self.reach(item.def_id.def_id, item_level).generics().predicates(); + self.reach(item.owner_id.def_id, item_level).generics().predicates(); } } // Visit everything except for private impl items. hir::ItemKind::Impl(ref impl_) => { if item_level.is_some() { - self.reach(item.def_id.def_id, item_level) + self.reach(item.owner_id.def_id, item_level) .generics() .predicates() .ty() .trait_ref(); for impl_item_ref in impl_.items { - let impl_item_level = self.get(impl_item_ref.id.def_id.def_id); + let impl_item_level = self.get(impl_item_ref.id.owner_id.def_id); if impl_item_level.is_some() { - self.reach(impl_item_ref.id.def_id.def_id, impl_item_level) + self.reach(impl_item_ref.id.owner_id.def_id, impl_item_level) .generics() .predicates() .ty(); @@ -779,7 +779,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { // Visit everything, but enum variants have their own levels. hir::ItemKind::Enum(ref def, _) => { if item_level.is_some() { - self.reach(item.def_id.def_id, item_level).generics().predicates(); + self.reach(item.owner_id.def_id, item_level).generics().predicates(); } for variant in def.variants { let variant_level = self.get(self.tcx.hir().local_def_id(variant.id)); @@ -790,13 +790,13 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } // Corner case: if the variant is reachable, but its // enum is not, make the enum reachable as well. - self.reach(item.def_id.def_id, variant_level).ty(); + self.reach(item.owner_id.def_id, variant_level).ty(); } if let Some(hir_id) = variant.data.ctor_hir_id() { let ctor_def_id = self.tcx.hir().local_def_id(hir_id); let ctor_level = self.get(ctor_def_id); if ctor_level.is_some() { - self.reach(item.def_id.def_id, ctor_level).ty(); + self.reach(item.owner_id.def_id, ctor_level).ty(); } } } @@ -804,9 +804,9 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { // Visit everything, but foreign items have their own levels. hir::ItemKind::ForeignMod { items, .. } => { for foreign_item in items { - let foreign_item_level = self.get(foreign_item.id.def_id.def_id); + let foreign_item_level = self.get(foreign_item.id.owner_id.def_id); if foreign_item_level.is_some() { - self.reach(foreign_item.id.def_id.def_id, foreign_item_level) + self.reach(foreign_item.id.owner_id.def_id, foreign_item_level) .generics() .predicates() .ty(); @@ -816,7 +816,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { // Visit everything except for private fields. hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { if item_level.is_some() { - self.reach(item.def_id.def_id, item_level).generics().predicates(); + self.reach(item.owner_id.def_id, item_level).generics().predicates(); for field in struct_def.fields() { let def_id = self.tcx.hir().local_def_id(field.hir_id); let field_level = self.get(def_id); @@ -829,7 +829,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { let ctor_def_id = self.tcx.hir().local_def_id(hir_id); let ctor_level = self.get(ctor_def_id); if ctor_level.is_some() { - self.reach(item.def_id.def_id, ctor_level).ty(); + self.reach(item.owner_id.def_id, ctor_level).ty(); } } } @@ -952,7 +952,7 @@ impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> { impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - self.effective_visibility_diagnostic(item.def_id.def_id); + self.effective_visibility_diagnostic(item.owner_id.def_id); match item.kind { hir::ItemKind::Enum(ref def, _) => { @@ -976,13 +976,13 @@ impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> { } fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem<'tcx>) { - self.effective_visibility_diagnostic(item.def_id.def_id); + self.effective_visibility_diagnostic(item.owner_id.def_id); } fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem<'tcx>) { - self.effective_visibility_diagnostic(item.def_id.def_id); + self.effective_visibility_diagnostic(item.owner_id.def_id); } fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { - self.effective_visibility_diagnostic(item.def_id.def_id); + self.effective_visibility_diagnostic(item.owner_id.def_id); } } @@ -1065,7 +1065,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - let orig_current_item = mem::replace(&mut self.current_item, item.def_id.def_id); + let orig_current_item = mem::replace(&mut self.current_item, item.owner_id.def_id); intravisit::walk_item(self, item); self.current_item = orig_current_item; } @@ -1368,7 +1368,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { // Check types in item interfaces. fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - let orig_current_item = mem::replace(&mut self.current_item, item.def_id.def_id); + let orig_current_item = mem::replace(&mut self.current_item, item.owner_id.def_id); let old_maybe_typeck_results = self.maybe_typeck_results.take(); intravisit::walk_item(self, item); self.maybe_typeck_results = old_maybe_typeck_results; @@ -1512,7 +1512,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { hir::ItemKind::ForeignMod { .. } => {} hir::ItemKind::Trait(.., bounds, _) => { - if !self.trait_is_public(item.def_id.def_id) { + if !self.trait_is_public(item.owner_id.def_id) { return; } @@ -1574,7 +1574,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { match impl_item.kind { hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) => self .effective_visibilities - .is_reachable(impl_item_ref.id.def_id.def_id), + .is_reachable(impl_item_ref.id.owner_id.def_id), hir::ImplItemKind::Type(_) => false, } }); @@ -1593,7 +1593,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item.kind { hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) - if self.item_is_public(impl_item.def_id.def_id) => + if self.item_is_public(impl_item.owner_id.def_id) => { intravisit::walk_impl_item(self, impl_item) } @@ -1634,8 +1634,10 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // methods will be visible as `Public::foo`. let mut found_pub_static = false; for impl_item_ref in impl_.items { - if self.effective_visibilities.is_reachable(impl_item_ref.id.def_id.def_id) - || self.tcx.visibility(impl_item_ref.id.def_id).is_public() + if self + .effective_visibilities + .is_reachable(impl_item_ref.id.owner_id.def_id) + || self.tcx.visibility(impl_item_ref.id.owner_id).is_public() { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item_ref.kind { @@ -1663,7 +1665,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { hir::ItemKind::TyAlias(..) => return, // Not at all public, so we don't care. - _ if !self.item_is_public(item.def_id.def_id) => { + _ if !self.item_is_public(item.owner_id.def_id) => { return; } @@ -1694,7 +1696,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { - if self.effective_visibilities.is_reachable(item.def_id.def_id) { + if self.effective_visibilities.is_reachable(item.owner_id.def_id) { intravisit::walk_foreign_item(self, item) } } @@ -1931,7 +1933,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { pub fn check_item(&mut self, id: ItemId) { let tcx = self.tcx; - let def_id = id.def_id.def_id; + let def_id = id.owner_id.def_id; let item_visibility = tcx.local_visibility(def_id); let def_kind = tcx.def_kind(def_id); @@ -1947,17 +1949,17 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { DefKind::Trait => { let item = tcx.hir().item(id); if let hir::ItemKind::Trait(.., trait_item_refs) = item.kind { - self.check(item.def_id.def_id, item_visibility).generics().predicates(); + self.check(item.owner_id.def_id, item_visibility).generics().predicates(); for trait_item_ref in trait_item_refs { self.check_assoc_item( - trait_item_ref.id.def_id.def_id, + trait_item_ref.id.owner_id.def_id, trait_item_ref.kind, item_visibility, ); if let AssocItemKind::Type = trait_item_ref.kind { - self.check(trait_item_ref.id.def_id.def_id, item_visibility).bounds(); + self.check(trait_item_ref.id.owner_id.def_id, item_visibility).bounds(); } } } @@ -1968,7 +1970,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { DefKind::Enum => { let item = tcx.hir().item(id); if let hir::ItemKind::Enum(ref def, _) = item.kind { - self.check(item.def_id.def_id, item_visibility).generics().predicates(); + self.check(item.owner_id.def_id, item_visibility).generics().predicates(); for variant in def.variants { for field in variant.data.fields() { @@ -1983,8 +1985,11 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { let item = tcx.hir().item(id); if let hir::ItemKind::ForeignMod { items, .. } = item.kind { for foreign_item in items { - let vis = tcx.local_visibility(foreign_item.id.def_id.def_id); - self.check(foreign_item.id.def_id.def_id, vis).generics().predicates().ty(); + let vis = tcx.local_visibility(foreign_item.id.owner_id.def_id); + self.check(foreign_item.id.owner_id.def_id, vis) + .generics() + .predicates() + .ty(); } } } @@ -1994,7 +1999,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { if let hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) = item.kind { - self.check(item.def_id.def_id, item_visibility).generics().predicates(); + self.check(item.owner_id.def_id, item_visibility).generics().predicates(); for field in struct_def.fields() { let def_id = tcx.hir().local_def_id(field.hir_id); @@ -2011,20 +2016,24 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { let item = tcx.hir().item(id); if let hir::ItemKind::Impl(ref impl_) = item.kind { let impl_vis = - ty::Visibility::of_impl(item.def_id.def_id, tcx, &Default::default()); + ty::Visibility::of_impl(item.owner_id.def_id, tcx, &Default::default()); // check that private components do not appear in the generics or predicates of inherent impls // this check is intentionally NOT performed for impls of traits, per #90586 if impl_.of_trait.is_none() { - self.check(item.def_id.def_id, impl_vis).generics().predicates(); + self.check(item.owner_id.def_id, impl_vis).generics().predicates(); } for impl_item_ref in impl_.items { let impl_item_vis = if impl_.of_trait.is_none() { - min(tcx.local_visibility(impl_item_ref.id.def_id.def_id), impl_vis, tcx) + min( + tcx.local_visibility(impl_item_ref.id.owner_id.def_id), + impl_vis, + tcx, + ) } else { impl_vis }; self.check_assoc_item( - impl_item_ref.id.def_id.def_id, + impl_item_ref.id.owner_id.def_id, impl_item_ref.kind, impl_item_vis, ); diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index d0752e5a20d0..df5d992f6633 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -345,14 +345,14 @@ impl<'tcx> DumpVisitor<'tcx> { body: hir::BodyId, ) { let map = self.tcx.hir(); - self.nest_typeck_results(item.def_id.def_id, |v| { + self.nest_typeck_results(item.owner_id.def_id, |v| { let body = map.body(body); if let Some(fn_data) = v.save_ctxt.get_item_data(item) { down_cast_data!(fn_data, DefData, item.span); v.process_formals(body.params, &fn_data.qualname); v.process_generic_params(ty_params, &fn_data.qualname, item.hir_id()); - v.dumper.dump_def(&access_from!(v.save_ctxt, item.def_id.def_id), fn_data); + v.dumper.dump_def(&access_from!(v.save_ctxt, item.owner_id.def_id), fn_data); } for arg in decl.inputs { @@ -373,10 +373,10 @@ impl<'tcx> DumpVisitor<'tcx> { typ: &'tcx hir::Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) { - self.nest_typeck_results(item.def_id.def_id, |v| { + self.nest_typeck_results(item.owner_id.def_id, |v| { if let Some(var_data) = v.save_ctxt.get_item_data(item) { down_cast_data!(var_data, DefData, item.span); - v.dumper.dump_def(&access_from!(v.save_ctxt, item.def_id.def_id), var_data); + v.dumper.dump_def(&access_from!(v.save_ctxt, item.owner_id.def_id), var_data); } v.visit_ty(&typ); v.visit_expr(expr); @@ -436,7 +436,7 @@ impl<'tcx> DumpVisitor<'tcx> { ) { debug!("process_struct {:?} {:?}", item, item.span); let name = item.ident.to_string(); - let qualname = format!("::{}", self.tcx.def_path_str(item.def_id.to_def_id())); + let qualname = format!("::{}", self.tcx.def_path_str(item.owner_id.to_def_id())); let kind = match item.kind { hir::ItemKind::Struct(_, _) => DefKind::Struct, @@ -473,10 +473,10 @@ impl<'tcx> DumpVisitor<'tcx> { let span = self.span_from_span(item.ident.span); let attrs = self.tcx.hir().attrs(item.hir_id()); self.dumper.dump_def( - &access_from!(self.save_ctxt, item.def_id.def_id), + &access_from!(self.save_ctxt, item.owner_id.def_id), Def { kind, - id: id_from_def_id(item.def_id.to_def_id()), + id: id_from_def_id(item.owner_id.to_def_id()), span, name, qualname: qualname.clone(), @@ -491,7 +491,7 @@ impl<'tcx> DumpVisitor<'tcx> { ); } - self.nest_typeck_results(item.def_id.def_id, |v| { + self.nest_typeck_results(item.owner_id.def_id, |v| { for field in def.fields() { v.process_struct_field_def(field, item.hir_id()); v.visit_ty(&field.ty); @@ -513,7 +513,7 @@ impl<'tcx> DumpVisitor<'tcx> { }; down_cast_data!(enum_data, DefData, item.span); - let access = access_from!(self.save_ctxt, item.def_id.def_id); + let access = access_from!(self.save_ctxt, item.owner_id.def_id); for variant in enum_definition.variants { let name = variant.ident.name.to_string(); @@ -528,7 +528,7 @@ impl<'tcx> DumpVisitor<'tcx> { if !self.span.filter_generated(name_span) { let span = self.span_from_span(name_span); let id = id_from_hir_id(variant.id, &self.save_ctxt); - let parent = Some(id_from_def_id(item.def_id.to_def_id())); + let parent = Some(id_from_def_id(item.owner_id.to_def_id())); let attrs = self.tcx.hir().attrs(variant.id); self.dumper.dump_def( @@ -566,7 +566,7 @@ impl<'tcx> DumpVisitor<'tcx> { if !self.span.filter_generated(name_span) { let span = self.span_from_span(name_span); let id = id_from_hir_id(variant.id, &self.save_ctxt); - let parent = Some(id_from_def_id(item.def_id.to_def_id())); + let parent = Some(id_from_def_id(item.owner_id.to_def_id())); let attrs = self.tcx.hir().attrs(variant.id); self.dumper.dump_def( @@ -612,14 +612,14 @@ impl<'tcx> DumpVisitor<'tcx> { } let map = self.tcx.hir(); - self.nest_typeck_results(item.def_id.def_id, |v| { + self.nest_typeck_results(item.owner_id.def_id, |v| { v.visit_ty(&impl_.self_ty); if let Some(trait_ref) = &impl_.of_trait { v.process_path(trait_ref.hir_ref_id, &hir::QPath::Resolved(None, &trait_ref.path)); } v.process_generic_params(&impl_.generics, "", item.hir_id()); for impl_item in impl_.items { - v.process_impl_item(map.impl_item(impl_item.id), item.def_id.to_def_id()); + v.process_impl_item(map.impl_item(impl_item.id), item.owner_id.to_def_id()); } }); } @@ -632,7 +632,7 @@ impl<'tcx> DumpVisitor<'tcx> { methods: &'tcx [hir::TraitItemRef], ) { let name = item.ident.to_string(); - let qualname = format!("::{}", self.tcx.def_path_str(item.def_id.to_def_id())); + let qualname = format!("::{}", self.tcx.def_path_str(item.owner_id.to_def_id())); let mut val = name.clone(); if !generics.params.is_empty() { val.push_str(&generic_params_to_string(generics.params)); @@ -642,13 +642,13 @@ impl<'tcx> DumpVisitor<'tcx> { val.push_str(&bounds_to_string(trait_refs)); } if !self.span.filter_generated(item.ident.span) { - let id = id_from_def_id(item.def_id.to_def_id()); + let id = id_from_def_id(item.owner_id.to_def_id()); let span = self.span_from_span(item.ident.span); let children = - methods.iter().map(|i| id_from_def_id(i.id.def_id.to_def_id())).collect(); + methods.iter().map(|i| id_from_def_id(i.id.owner_id.to_def_id())).collect(); let attrs = self.tcx.hir().attrs(item.hir_id()); self.dumper.dump_def( - &access_from!(self.save_ctxt, item.def_id.def_id), + &access_from!(self.save_ctxt, item.owner_id.def_id), Def { kind: DefKind::Trait, id, @@ -692,7 +692,7 @@ impl<'tcx> DumpVisitor<'tcx> { kind: RelationKind::SuperTrait, span, from: id_from_def_id(id), - to: id_from_def_id(item.def_id.to_def_id()), + to: id_from_def_id(item.owner_id.to_def_id()), }); } } @@ -702,7 +702,7 @@ impl<'tcx> DumpVisitor<'tcx> { self.process_generic_params(generics, &qualname, item.hir_id()); for method in methods { let map = self.tcx.hir(); - self.process_trait_item(map.trait_item(method.id), item.def_id.to_def_id()) + self.process_trait_item(map.trait_item(method.id), item.owner_id.to_def_id()) } } @@ -710,7 +710,7 @@ impl<'tcx> DumpVisitor<'tcx> { fn process_mod(&mut self, item: &'tcx hir::Item<'tcx>) { if let Some(mod_data) = self.save_ctxt.get_item_data(item) { down_cast_data!(mod_data, DefData, item.span); - self.dumper.dump_def(&access_from!(self.save_ctxt, item.def_id.def_id), mod_data); + self.dumper.dump_def(&access_from!(self.save_ctxt, item.owner_id.def_id), mod_data); } } @@ -981,7 +981,7 @@ impl<'tcx> DumpVisitor<'tcx> { let body = body.map(|b| self.tcx.hir().body(b).value); let attrs = self.tcx.hir().attrs(trait_item.hir_id()); self.process_assoc_const( - trait_item.def_id.def_id, + trait_item.owner_id.def_id, trait_item.ident, &ty, body, @@ -995,7 +995,7 @@ impl<'tcx> DumpVisitor<'tcx> { self.process_method( sig, body, - trait_item.def_id.def_id, + trait_item.owner_id.def_id, trait_item.ident, &trait_item.generics, trait_item.span, @@ -1005,11 +1005,11 @@ impl<'tcx> DumpVisitor<'tcx> { // FIXME do something with _bounds (for type refs) let name = trait_item.ident.name.to_string(); let qualname = - format!("::{}", self.tcx.def_path_str(trait_item.def_id.to_def_id())); + format!("::{}", self.tcx.def_path_str(trait_item.owner_id.to_def_id())); if !self.span.filter_generated(trait_item.ident.span) { let span = self.span_from_span(trait_item.ident.span); - let id = id_from_def_id(trait_item.def_id.to_def_id()); + let id = id_from_def_id(trait_item.owner_id.to_def_id()); let attrs = self.tcx.hir().attrs(trait_item.hir_id()); self.dumper.dump_def( @@ -1051,7 +1051,7 @@ impl<'tcx> DumpVisitor<'tcx> { let body = self.tcx.hir().body(body); let attrs = self.tcx.hir().attrs(impl_item.hir_id()); self.process_assoc_const( - impl_item.def_id.def_id, + impl_item.owner_id.def_id, impl_item.ident, &ty, Some(&body.value), @@ -1063,7 +1063,7 @@ impl<'tcx> DumpVisitor<'tcx> { self.process_method( sig, Some(body), - impl_item.def_id.def_id, + impl_item.owner_id.def_id, impl_item.ident, &impl_item.generics, impl_item.span, @@ -1088,7 +1088,7 @@ impl<'tcx> DumpVisitor<'tcx> { let filename = sm.span_to_filename(krate_mod.spans.inner_span); let data_id = id_from_hir_id(id, &self.save_ctxt); let children = - krate_mod.item_ids.iter().map(|i| id_from_def_id(i.def_id.to_def_id())).collect(); + krate_mod.item_ids.iter().map(|i| id_from_def_id(i.owner_id.to_def_id())).collect(); let span = self.span_from_span(krate_mod.spans.inner_span); let attrs = self.tcx.hir().attrs(id); @@ -1137,10 +1137,10 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { hir::ItemKind::Use(path, hir::UseKind::Single) => { let sub_span = path.segments.last().unwrap().ident.span; if !self.span.filter_generated(sub_span) { - let access = access_from!(self.save_ctxt, item.def_id.def_id); + let access = access_from!(self.save_ctxt, item.owner_id.def_id); let ref_id = self.lookup_def_id(item.hir_id()).map(id_from_def_id); let span = self.span_from_span(sub_span); - let parent = self.save_ctxt.tcx.local_parent(item.def_id.def_id); + let parent = self.save_ctxt.tcx.local_parent(item.owner_id.def_id); self.dumper.import( &access, Import { @@ -1158,16 +1158,16 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { } hir::ItemKind::Use(path, hir::UseKind::Glob) => { // Make a comma-separated list of names of imported modules. - let names = self.tcx.names_imported_by_glob_use(item.def_id.def_id); + let names = self.tcx.names_imported_by_glob_use(item.owner_id.def_id); let names: Vec<_> = names.iter().map(|n| n.to_string()).collect(); // Otherwise it's a span with wrong macro expansion info, which // we don't want to track anyway, since it's probably macro-internal `use` if let Some(sub_span) = self.span.sub_span_of_star(item.span) { if !self.span.filter_generated(item.span) { - let access = access_from!(self.save_ctxt, item.def_id.def_id); + let access = access_from!(self.save_ctxt, item.owner_id.def_id); let span = self.span_from_span(sub_span); - let parent = self.save_ctxt.tcx.local_parent(item.def_id.def_id); + let parent = self.save_ctxt.tcx.local_parent(item.owner_id.def_id); self.dumper.import( &access, Import { @@ -1188,7 +1188,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { let name_span = item.ident.span; if !self.span.filter_generated(name_span) { let span = self.span_from_span(name_span); - let parent = self.save_ctxt.tcx.local_parent(item.def_id.def_id); + let parent = self.save_ctxt.tcx.local_parent(item.owner_id.def_id); self.dumper.import( &Access { public: false, reachable: false }, Import { @@ -1228,15 +1228,15 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { intravisit::walk_mod(self, m, item.hir_id()); } hir::ItemKind::TyAlias(ty, ref generics) => { - let qualname = format!("::{}", self.tcx.def_path_str(item.def_id.to_def_id())); + let qualname = format!("::{}", self.tcx.def_path_str(item.owner_id.to_def_id())); let value = ty_to_string(&ty); if !self.span.filter_generated(item.ident.span) { let span = self.span_from_span(item.ident.span); - let id = id_from_def_id(item.def_id.to_def_id()); + let id = id_from_def_id(item.owner_id.to_def_id()); let attrs = self.tcx.hir().attrs(item.hir_id()); self.dumper.dump_def( - &access_from!(self.save_ctxt, item.def_id.def_id), + &access_from!(self.save_ctxt, item.owner_id.def_id), Def { kind: DefKind::Type, id, @@ -1324,7 +1324,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { } hir::TyKind::OpaqueDef(item_id, _, _) => { let item = self.tcx.hir().item(item_id); - self.nest_typeck_results(item_id.def_id.def_id, |v| v.visit_item(item)); + self.nest_typeck_results(item_id.owner_id.def_id, |v| v.visit_item(item)); } _ => intravisit::walk_ty(self, t), } @@ -1431,7 +1431,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { } fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { - let access = access_from!(self.save_ctxt, item.def_id.def_id); + let access = access_from!(self.save_ctxt, item.owner_id.def_id); match item.kind { hir::ForeignItemKind::Fn(decl, _, ref generics) => { diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index d1ed0e078d21..d0155c908a2b 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -141,7 +141,7 @@ impl<'tcx> SaveContext<'tcx> { } pub fn get_extern_item_data(&self, item: &hir::ForeignItem<'_>) -> Option { - let def_id = item.def_id.to_def_id(); + let def_id = item.owner_id.to_def_id(); let qualname = format!("::{}", self.tcx.def_path_str(def_id)); let attrs = self.tcx.hir().attrs(item.hir_id()); match item.kind { @@ -205,7 +205,7 @@ impl<'tcx> SaveContext<'tcx> { } pub fn get_item_data(&self, item: &hir::Item<'_>) -> Option { - let def_id = item.def_id.to_def_id(); + let def_id = item.owner_id.to_def_id(); let attrs = self.tcx.hir().attrs(item.hir_id()); match item.kind { hir::ItemKind::Fn(ref sig, ref generics, _) => { @@ -297,7 +297,7 @@ impl<'tcx> SaveContext<'tcx> { children: m .item_ids .iter() - .map(|i| id_from_def_id(i.def_id.to_def_id())) + .map(|i| id_from_def_id(i.owner_id.to_def_id())) .collect(), decl_id: None, docs: self.docs_for_attrs(attrs), @@ -363,7 +363,7 @@ impl<'tcx> SaveContext<'tcx> { parent: None, children: items .iter() - .map(|i| id_from_def_id(i.id.def_id.to_def_id())) + .map(|i| id_from_def_id(i.id.owner_id.to_def_id())) .collect(), docs: String::new(), sig: None, diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index 62e9f6520fbb..83c51d213be3 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -337,7 +337,7 @@ impl<'hir> Sig for hir::Item<'hir> { } let name = self.ident.to_string(); let defs = vec![SigElement { - id: id_from_def_id(self.def_id.to_def_id()), + id: id_from_def_id(self.owner_id.to_def_id()), start: offset + text.len(), end: offset + text.len() + name.len(), }]; @@ -359,7 +359,7 @@ impl<'hir> Sig for hir::Item<'hir> { let mut text = "const ".to_owned(); let name = self.ident.to_string(); let defs = vec![SigElement { - id: id_from_def_id(self.def_id.to_def_id()), + id: id_from_def_id(self.owner_id.to_def_id()), start: offset + text.len(), end: offset + text.len() + name.len(), }]; @@ -428,7 +428,7 @@ impl<'hir> Sig for hir::Item<'hir> { let mut text = "mod ".to_owned(); let name = self.ident.to_string(); let defs = vec![SigElement { - id: id_from_def_id(self.def_id.to_def_id()), + id: id_from_def_id(self.owner_id.to_def_id()), start: offset + text.len(), end: offset + text.len() + name.len(), }]; @@ -764,7 +764,7 @@ impl<'hir> Sig for hir::ForeignItem<'hir> { } let name = self.ident.to_string(); let defs = vec![SigElement { - id: id_from_def_id(self.def_id.to_def_id()), + id: id_from_def_id(self.owner_id.to_def_id()), start: offset + text.len(), end: offset + text.len() + name.len(), }]; @@ -780,7 +780,7 @@ impl<'hir> Sig for hir::ForeignItem<'hir> { let mut text = "type ".to_owned(); let name = self.ident.to_string(); let defs = vec![SigElement { - id: id_from_def_id(self.def_id.to_def_id()), + id: id_from_def_id(self.owner_id.to_def_id()), start: offset + text.len(), end: offset + text.len() + name.len(), }]; diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs index c8c6fe2bf852..150459ce0f53 100644 --- a/compiler/rustc_symbol_mangling/src/test.rs +++ b/compiler/rustc_symbol_mangling/src/test.rs @@ -26,19 +26,19 @@ pub fn report_symbol_names(tcx: TyCtxt<'_>) { let crate_items = tcx.hir_crate_items(()); for id in crate_items.items() { - symbol_names.process_attrs(id.def_id.def_id); + symbol_names.process_attrs(id.owner_id.def_id); } for id in crate_items.trait_items() { - symbol_names.process_attrs(id.def_id.def_id); + symbol_names.process_attrs(id.owner_id.def_id); } for id in crate_items.impl_items() { - symbol_names.process_attrs(id.def_id.def_id); + symbol_names.process_attrs(id.owner_id.def_id); } for id in crate_items.foreign_items() { - symbol_names.process_attrs(id.def_id.def_id); + symbol_names.process_attrs(id.owner_id.def_id); } }) } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 30feabe1a095..8908fe230b0e 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -214,7 +214,9 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( trait_ref, item, cause, pred ); let (items, impl_def_id) = match item { - Some(hir::Item { kind: hir::ItemKind::Impl(impl_), def_id, .. }) => (impl_.items, *def_id), + Some(hir::Item { kind: hir::ItemKind::Impl(impl_), owner_id, .. }) => { + (impl_.items, *owner_id) + } _ => return, }; let fix_span = @@ -236,7 +238,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id) && let Some(impl_item_span) = items .iter() - .find(|item| item.id.def_id.to_def_id() == impl_item_id) + .find(|item| item.id.owner_id.to_def_id() == impl_item_id) .map(fix_span) { cause.span = impl_item_span; @@ -251,7 +253,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( tcx.impl_item_implementor_ids(impl_def_id).get(&item_def_id) && let Some(impl_item_span) = items .iter() - .find(|item| item.id.def_id.to_def_id() == impl_item_id) + .find(|item| item.id.owner_id.to_def_id() == impl_item_id) .map(fix_span) { cause.span = impl_item_span; diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 3e2553c425ed..424b52309d3a 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -17,10 +17,10 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] { let item = tcx.hir().expect_item(def_id.expect_local()); match item.kind { hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter( - trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.def_id.to_def_id()), + trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id()), ), hir::ItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter( - impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.def_id.to_def_id()), + impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()), ), hir::ItemKind::TraitAlias(..) => &[], _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"), @@ -46,7 +46,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem { match parent_item.kind { hir::ItemKind::Impl(ref impl_) => { if let Some(impl_item_ref) = - impl_.items.iter().find(|i| i.id.def_id.to_def_id() == def_id) + impl_.items.iter().find(|i| i.id.owner_id.to_def_id() == def_id) { let assoc_item = associated_item_from_impl_item_ref(impl_item_ref); debug_assert_eq!(assoc_item.def_id, def_id); @@ -56,7 +56,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem { hir::ItemKind::Trait(.., ref trait_item_refs) => { if let Some(trait_item_ref) = - trait_item_refs.iter().find(|i| i.id.def_id.to_def_id() == def_id) + trait_item_refs.iter().find(|i| i.id.owner_id.to_def_id() == def_id) { let assoc_item = associated_item_from_trait_item_ref(trait_item_ref); debug_assert_eq!(assoc_item.def_id, def_id); @@ -75,7 +75,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem { } fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty::AssocItem { - let def_id = trait_item_ref.id.def_id; + let owner_id = trait_item_ref.id.owner_id; let (kind, has_self) = match trait_item_ref.kind { hir::AssocItemKind::Const => (ty::AssocKind::Const, false), hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self), @@ -85,15 +85,15 @@ fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty ty::AssocItem { name: trait_item_ref.ident.name, kind, - def_id: def_id.to_def_id(), - trait_item_def_id: Some(def_id.to_def_id()), + def_id: owner_id.to_def_id(), + trait_item_def_id: Some(owner_id.to_def_id()), container: ty::TraitContainer, fn_has_self_parameter: has_self, } } fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::AssocItem { - let def_id = impl_item_ref.id.def_id; + let def_id = impl_item_ref.id.owner_id; let (kind, has_self) = match impl_item_ref.kind { hir::AssocItemKind::Const => (ty::AssocKind::Const, false), hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d5322f5c4662..64a18757b26e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1042,7 +1042,7 @@ fn clean_poly_trait_ref<'tcx>( } fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext<'tcx>) -> Item { - let local_did = trait_item.def_id.to_def_id(); + let local_did = trait_item.owner_id.to_def_id(); cx.with_param_env(local_did, |cx| { let inner = match trait_item.kind { hir::TraitItemKind::Const(ty, Some(default)) => AssocConstItem( @@ -1094,7 +1094,7 @@ pub(crate) fn clean_impl_item<'tcx>( impl_: &hir::ImplItem<'tcx>, cx: &mut DocContext<'tcx>, ) -> Item { - let local_did = impl_.def_id.to_def_id(); + let local_did = impl_.owner_id.to_def_id(); cx.with_param_env(local_did, |cx| { let inner = match impl_.kind { hir::ImplItemKind::Const(ty, expr) => { @@ -1103,7 +1103,7 @@ pub(crate) fn clean_impl_item<'tcx>( } hir::ImplItemKind::Fn(ref sig, body) => { let m = clean_function(cx, sig, impl_.generics, body); - let defaultness = cx.tcx.impl_defaultness(impl_.def_id); + let defaultness = cx.tcx.impl_defaultness(impl_.owner_id); MethodItem(m, Some(defaultness)) } hir::ImplItemKind::Type(hir_ty) => { @@ -1120,7 +1120,7 @@ pub(crate) fn clean_impl_item<'tcx>( let mut what_rustc_thinks = Item::from_def_id_and_parts(local_did, Some(impl_.ident.name), inner, cx); - let impl_ref = cx.tcx.impl_trait_ref(cx.tcx.local_parent(impl_.def_id.def_id)); + let impl_ref = cx.tcx.impl_trait_ref(cx.tcx.local_parent(impl_.owner_id.def_id)); // Trait impl items always inherit the impl's visibility -- // we don't want to show `pub`. @@ -1958,7 +1958,7 @@ fn clean_maybe_renamed_item<'tcx>( ) -> Vec { use hir::ItemKind; - let def_id = item.def_id.to_def_id(); + let def_id = item.owner_id.to_def_id(); let mut name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id())); cx.with_param_env(def_id, |cx| { let kind = match item.kind { @@ -2100,11 +2100,11 @@ fn clean_extern_crate<'tcx>( cx: &mut DocContext<'tcx>, ) -> Vec { // this is the ID of the `extern crate` statement - let cnum = cx.tcx.extern_mod_stmt_cnum(krate.def_id.def_id).unwrap_or(LOCAL_CRATE); + let cnum = cx.tcx.extern_mod_stmt_cnum(krate.owner_id.def_id).unwrap_or(LOCAL_CRATE); // this is the ID of the crate itself let crate_def_id = cnum.as_def_id(); let attrs = cx.tcx.hir().attrs(krate.hir_id()); - let ty_vis = cx.tcx.visibility(krate.def_id); + let ty_vis = cx.tcx.visibility(krate.owner_id); let please_inline = ty_vis.is_public() && attrs.iter().any(|a| { a.has_name(sym::doc) @@ -2122,7 +2122,7 @@ fn clean_extern_crate<'tcx>( if let Some(items) = inline::try_inline( cx, cx.tcx.parent_module(krate.hir_id()).to_def_id(), - Some(krate.def_id.to_def_id()), + Some(krate.owner_id.to_def_id()), res, name, Some(attrs), @@ -2158,11 +2158,11 @@ fn clean_use_statement<'tcx>( return Vec::new(); } - let visibility = cx.tcx.visibility(import.def_id); + let visibility = cx.tcx.visibility(import.owner_id); let attrs = cx.tcx.hir().attrs(import.hir_id()); let inline_attr = attrs.lists(sym::doc).get_word_attr(sym::inline); let pub_underscore = visibility.is_public() && name == kw::Underscore; - let current_mod = cx.tcx.parent_module_from_def_id(import.def_id.def_id); + let current_mod = cx.tcx.parent_module_from_def_id(import.owner_id.def_id); // The parent of the module in which this import resides. This // is the same as `current_mod` if that's already the top @@ -2233,7 +2233,7 @@ fn clean_use_statement<'tcx>( } if !denied { let mut visited = FxHashSet::default(); - let import_def_id = import.def_id.to_def_id(); + let import_def_id = import.owner_id.to_def_id(); if let Some(mut items) = inline::try_inline( cx, @@ -2256,7 +2256,7 @@ fn clean_use_statement<'tcx>( Import::new_simple(name, resolve_use_source(cx, path), true) }; - vec![Item::from_def_id_and_parts(import.def_id.to_def_id(), None, ImportItem(inner), cx)] + vec![Item::from_def_id_and_parts(import.owner_id.to_def_id(), None, ImportItem(inner), cx)] } fn clean_maybe_renamed_foreign_item<'tcx>( @@ -2264,7 +2264,7 @@ fn clean_maybe_renamed_foreign_item<'tcx>( item: &hir::ForeignItem<'tcx>, renamed: Option, ) -> Item { - let def_id = item.def_id.to_def_id(); + let def_id = item.owner_id.to_def_id(); cx.with_param_env(def_id, |cx| { let kind = match item.kind { hir::ForeignItemKind::Fn(decl, names, generics) => { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 4c130b2ffec7..cd1f972dce84 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -240,13 +240,13 @@ impl ExternalCrate { let item = tcx.hir().item(id); match item.kind { hir::ItemKind::Mod(_) => { - as_keyword(Res::Def(DefKind::Mod, id.def_id.to_def_id())) + as_keyword(Res::Def(DefKind::Mod, id.owner_id.to_def_id())) } hir::ItemKind::Use(path, hir::UseKind::Single) - if tcx.visibility(id.def_id).is_public() => + if tcx.visibility(id.owner_id).is_public() => { as_keyword(path.res.expect_non_local()) - .map(|(_, prim)| (id.def_id.to_def_id(), prim)) + .map(|(_, prim)| (id.owner_id.to_def_id(), prim)) } _ => None, } @@ -308,14 +308,14 @@ impl ExternalCrate { let item = tcx.hir().item(id); match item.kind { hir::ItemKind::Mod(_) => { - as_primitive(Res::Def(DefKind::Mod, id.def_id.to_def_id())) + as_primitive(Res::Def(DefKind::Mod, id.owner_id.to_def_id())) } hir::ItemKind::Use(path, hir::UseKind::Single) - if tcx.visibility(id.def_id).is_public() => + if tcx.visibility(id.owner_id).is_public() => { as_primitive(path.res.expect_non_local()).map(|(_, prim)| { // Pretend the primitive is local. - (id.def_id.to_def_id(), prim) + (id.owner_id.to_def_id(), prim) }) } _ => None, diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 8023ec9fa9a2..06dffce555f9 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -295,11 +295,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { debug!("visiting item {:?}", item); let name = renamed.unwrap_or(item.ident.name); - let def_id = item.def_id.to_def_id(); + let def_id = item.owner_id.to_def_id(); let is_pub = self.cx.tcx.visibility(def_id).is_public(); if is_pub { - self.store_path(item.def_id.to_def_id()); + self.store_path(item.owner_id.to_def_id()); } match item.kind { @@ -360,7 +360,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // 3. We're inlining, since a reexport where inlining has been requested // should be inlined even if it is also documented at the top level. - let def_id = item.def_id.to_def_id(); + let def_id = item.owner_id.to_def_id(); let is_macro_2_0 = !macro_def.macro_rules; let nonexported = !self.cx.tcx.has_attr(def_id, sym::macro_export); @@ -405,7 +405,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { om: &mut Module<'tcx>, ) { // If inlining we only want to include public functions. - if !self.inlining || self.cx.tcx.visibility(item.def_id).is_public() { + if !self.inlining || self.cx.tcx.visibility(item.owner_id).is_public() { om.foreigns.push((item, renamed)); } } diff --git a/src/test/run-make-fulldeps/obtain-borrowck/driver.rs b/src/test/run-make-fulldeps/obtain-borrowck/driver.rs index 8f78bda033ec..a6c60df83a63 100644 --- a/src/test/run-make-fulldeps/obtain-borrowck/driver.rs +++ b/src/test/run-make-fulldeps/obtain-borrowck/driver.rs @@ -69,25 +69,25 @@ impl rustc_driver::Callbacks for CompilerCalls { let crate_items = tcx.hir_crate_items(()); for id in crate_items.items() { - if matches!(tcx.def_kind(id.def_id), DefKind::Fn) { - bodies.push(id.def_id); + if matches!(tcx.def_kind(id.owner_id), DefKind::Fn) { + bodies.push(id.owner_id); } } for id in crate_items.trait_items() { - if matches!(tcx.def_kind(id.def_id), DefKind::AssocFn) { + if matches!(tcx.def_kind(id.owner_id), DefKind::AssocFn) { let trait_item = hir.trait_item(id); if let rustc_hir::TraitItemKind::Fn(_, trait_fn) = &trait_item.kind { if let rustc_hir::TraitFn::Provided(_) = trait_fn { - bodies.push(trait_item.def_id); + bodies.push(trait_item.owner_id); } } } } for id in crate_items.impl_items() { - if matches!(tcx.def_kind(id.def_id), DefKind::AssocFn) { - bodies.push(id.def_id); + if matches!(tcx.def_kind(id.owner_id), DefKind::AssocFn) { + bodies.push(id.owner_id); } } diff --git a/src/tools/clippy/clippy_lints/src/copy_iterator.rs b/src/tools/clippy/clippy_lints/src/copy_iterator.rs index 026683f60062..e38f77268530 100644 --- a/src/tools/clippy/clippy_lints/src/copy_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/copy_iterator.rs @@ -43,7 +43,7 @@ impl<'tcx> LateLintPass<'tcx> for CopyIterator { of_trait: Some(ref trait_ref), .. }) = item.kind; - let ty = cx.tcx.type_of(item.def_id); + let ty = cx.tcx.type_of(item.owner_id); if is_copy(cx, ty); if let Some(trait_id) = trait_ref.trait_def_id(); if cx.tcx.is_diagnostic_item(sym::Iterator, trait_id); diff --git a/src/tools/clippy/clippy_lints/src/default_union_representation.rs b/src/tools/clippy/clippy_lints/src/default_union_representation.rs index 741edc131960..dec357ab75c3 100644 --- a/src/tools/clippy/clippy_lints/src/default_union_representation.rs +++ b/src/tools/clippy/clippy_lints/src/default_union_representation.rs @@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultUnionRepresentation { None, &format!( "consider annotating `{}` with `#[repr(C)]` to explicitly specify memory layout", - cx.tcx.def_path_str(item.def_id.to_def_id()) + cx.tcx.def_path_str(item.owner_id.to_def_id()) ), ); } diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index a95d9f5390de..c029031363bb 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -715,47 +715,47 @@ fn walk_parents<'tcx>( }, Node::Item(&Item { kind: ItemKind::Static(..) | ItemKind::Const(..), - def_id, + owner_id, span, .. }) | Node::TraitItem(&TraitItem { kind: TraitItemKind::Const(..), - def_id, + owner_id, span, .. }) | Node::ImplItem(&ImplItem { kind: ImplItemKind::Const(..), - def_id, + owner_id, span, .. }) if span.ctxt() == ctxt => { - let ty = cx.tcx.type_of(def_id.def_id); + let ty = cx.tcx.type_of(owner_id.def_id); Some(ty_auto_deref_stability(cx, ty, precedence).position_for_result(cx)) }, Node::Item(&Item { kind: ItemKind::Fn(..), - def_id, + owner_id, span, .. }) | Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(..), - def_id, + owner_id, span, .. }) | Node::ImplItem(&ImplItem { kind: ImplItemKind::Fn(..), - def_id, + owner_id, span, .. }) if span.ctxt() == ctxt => { let output = cx .tcx - .erase_late_bound_regions(cx.tcx.fn_sig(def_id.to_def_id()).output()); + .erase_late_bound_regions(cx.tcx.fn_sig(owner_id.to_def_id()).output()); Some(ty_auto_deref_stability(cx, output, precedence).position_for_result(cx)) }, diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs index 06ae5abeaeb9..ae8f6b794499 100644 --- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs +++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs @@ -70,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls { self_ty, .. }) = item.kind; - if !cx.tcx.has_attr(item.def_id.to_def_id(), sym::automatically_derived); + if !cx.tcx.has_attr(item.owner_id.to_def_id(), sym::automatically_derived); if !item.span.from_expansion(); if let Some(def_id) = trait_ref.trait_def_id(); if cx.tcx.is_diagnostic_item(sym::Default, def_id); @@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls { if let Some(Node::ImplItem(impl_item)) = cx.tcx.hir().find(impl_item_hir); if let ImplItemKind::Fn(_, b) = &impl_item.kind; if let Body { value: func_expr, .. } = cx.tcx.hir().body(*b); - if let Some(adt_def) = cx.tcx.type_of(item.def_id).ty_adt_def(); + if let Some(adt_def) = cx.tcx.type_of(item.owner_id).ty_adt_def(); if let attrs = cx.tcx.hir().attrs(item.hir_id()); if !attrs.iter().any(|attr| attr.doc_str().is_some()); if let child_attrs = cx.tcx.hir().attrs(impl_item_hir); diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index fad984d05ca9..102a02138bc8 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -210,8 +210,8 @@ impl<'tcx> LateLintPass<'tcx> for Derive { .. }) = item.kind { - let ty = cx.tcx.type_of(item.def_id); - let is_automatically_derived = cx.tcx.has_attr(item.def_id.to_def_id(), sym::automatically_derived); + let ty = cx.tcx.type_of(item.owner_id); + let is_automatically_derived = cx.tcx.has_attr(item.owner_id.to_def_id(), sym::automatically_derived); check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived); check_ord_partial_ord(cx, item.span, trait_ref, ty, is_automatically_derived); diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs index b47fa6c7ecf5..24d6a6951af8 100644 --- a/src/tools/clippy/clippy_lints/src/doc.rs +++ b/src/tools/clippy/clippy_lints/src/doc.rs @@ -257,17 +257,17 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown { let headers = check_attrs(cx, &self.valid_idents, attrs); match item.kind { hir::ItemKind::Fn(ref sig, _, body_id) => { - if !(is_entrypoint_fn(cx, item.def_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) { + if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) { let body = cx.tcx.hir().body(body_id); let mut fpu = FindPanicUnwrap { cx, - typeck_results: cx.tcx.typeck(item.def_id.def_id), + typeck_results: cx.tcx.typeck(item.owner_id.def_id), panic_span: None, }; fpu.visit_expr(body.value); lint_for_missing_headers( cx, - item.def_id.def_id, + item.owner_id.def_id, item.span, sig, headers, @@ -304,7 +304,7 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown { let headers = check_attrs(cx, &self.valid_idents, attrs); if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind { if !in_external_macro(cx.tcx.sess, item.span) { - lint_for_missing_headers(cx, item.def_id.def_id, item.span, sig, headers, None, None); + lint_for_missing_headers(cx, item.owner_id.def_id, item.span, sig, headers, None, None); } } } @@ -319,13 +319,13 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown { let body = cx.tcx.hir().body(body_id); let mut fpu = FindPanicUnwrap { cx, - typeck_results: cx.tcx.typeck(item.def_id.def_id), + typeck_results: cx.tcx.typeck(item.owner_id.def_id), panic_span: None, }; fpu.visit_expr(body.value); lint_for_missing_headers( cx, - item.def_id.def_id, + item.owner_id.def_id, item.span, sig, headers, diff --git a/src/tools/clippy/clippy_lints/src/empty_enum.rs b/src/tools/clippy/clippy_lints/src/empty_enum.rs index bbebc0244141..0570c2a10138 100644 --- a/src/tools/clippy/clippy_lints/src/empty_enum.rs +++ b/src/tools/clippy/clippy_lints/src/empty_enum.rs @@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for EmptyEnum { } if let ItemKind::Enum(..) = item.kind { - let ty = cx.tcx.type_of(item.def_id); + let ty = cx.tcx.type_of(item.owner_id); let adt = ty.ty_adt_def().expect("already checked whether this is an enum"); if adt.variants().is_empty() { span_lint_and_help( diff --git a/src/tools/clippy/clippy_lints/src/enum_variants.rs b/src/tools/clippy/clippy_lints/src/enum_variants.rs index 2c3487a6e10f..223545fa7984 100644 --- a/src/tools/clippy/clippy_lints/src/enum_variants.rs +++ b/src/tools/clippy/clippy_lints/src/enum_variants.rs @@ -265,7 +265,7 @@ impl LateLintPass<'_> for EnumVariantNames { } // The `module_name_repetitions` lint should only trigger if the item has the module in its // name. Having the same name is accepted. - if cx.tcx.visibility(item.def_id).is_public() && item_camel.len() > mod_camel.len() { + if cx.tcx.visibility(item.owner_id).is_public() && item_camel.len() > mod_camel.len() { let matching = count_match_start(mod_camel, &item_camel); let rmatching = count_match_end(mod_camel, &item_camel); let nchars = mod_camel.chars().count(); @@ -296,7 +296,7 @@ impl LateLintPass<'_> for EnumVariantNames { } } if let ItemKind::Enum(ref def, _) = item.kind { - if !(self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(item.def_id.def_id)) { + if !(self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(item.owner_id.def_id)) { check_variant(cx, self.threshold, def, item_name, item.span); } } diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index c9a8307eba4f..7f1a4c4beb1f 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal { // be sure we have `self` parameter in this function if trait_item.kind == (AssocItemKind::Fn { has_self: true }) { trait_self_ty = Some( - TraitRef::identity(cx.tcx, trait_item.id.def_id.to_def_id()) + TraitRef::identity(cx.tcx, trait_item.id.owner_id.to_def_id()) .self_ty() .skip_binder(), ); diff --git a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs index bb07b29b0763..1fece5d1c480 100644 --- a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs +++ b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs @@ -73,7 +73,7 @@ impl LateLintPass<'_> for ExhaustiveItems { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { if_chain! { if let ItemKind::Enum(..) | ItemKind::Struct(..) = item.kind; - if cx.effective_visibilities.is_exported(item.def_id.def_id); + if cx.effective_visibilities.is_exported(item.owner_id.def_id); let attrs = cx.tcx.hir().attrs(item.hir_id()); if !attrs.iter().any(|a| a.has_name(sym::non_exhaustive)); then { diff --git a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs index ef24a5d06ad0..0a633f242a5f 100644 --- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs +++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs @@ -55,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for FallibleImplFrom { // check for `impl From for ..` if_chain! { if let hir::ItemKind::Impl(impl_) = &item.kind; - if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.def_id); + if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id); if cx.tcx.is_diagnostic_item(sym::From, impl_trait_ref.def_id); then { lint_impl_body(cx, item.span, impl_.items); @@ -107,7 +107,7 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[h let body = cx.tcx.hir().body(body_id); let mut fpu = FindPanicUnwrap { lcx: cx, - typeck_results: cx.tcx.typeck(impl_item.id.def_id.def_id), + typeck_results: cx.tcx.typeck(impl_item.id.owner_id.def_id), result: Vec::new(), }; fpu.visit_expr(body.value); diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs index 95eda4ea8827..8b24a4962fb2 100644 --- a/src/tools/clippy/clippy_lints/src/from_over_into.rs +++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs @@ -76,7 +76,7 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto { && let Some(into_trait_seg) = hir_trait_ref.path.segments.last() // `impl Into for self_ty` && let Some(GenericArgs { args: [GenericArg::Type(target_ty)], .. }) = into_trait_seg.args - && let Some(middle_trait_ref) = cx.tcx.impl_trait_ref(item.def_id) + && let Some(middle_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id) && cx.tcx.is_diagnostic_item(sym::Into, middle_trait_ref.def_id) { span_lint_and_then( diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index 32cba5e608ad..3c7ab9c3182c 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -22,9 +22,9 @@ use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT}; pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { let attrs = cx.tcx.hir().attrs(item.hir_id()); - let attr = cx.tcx.get_attr(item.def_id.to_def_id(), sym::must_use); + let attr = cx.tcx.get_attr(item.owner_id.to_def_id(), sym::must_use); if let hir::ItemKind::Fn(ref sig, _generics, ref body_id) = item.kind { - let is_public = cx.effective_visibilities.is_exported(item.def_id.def_id); + let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); if let Some(attr) = attr { check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr); @@ -34,7 +34,7 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_> sig.decl, cx.tcx.hir().body(*body_id), item.span, - item.def_id.def_id, + item.owner_id.def_id, item.span.with_hi(sig.decl.output.span().hi()), "this function could have a `#[must_use]` attribute", ); @@ -44,20 +44,20 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_> pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) { if let hir::ImplItemKind::Fn(ref sig, ref body_id) = item.kind { - let is_public = cx.effective_visibilities.is_exported(item.def_id.def_id); + let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); let attrs = cx.tcx.hir().attrs(item.hir_id()); - let attr = cx.tcx.get_attr(item.def_id.to_def_id(), sym::must_use); + let attr = cx.tcx.get_attr(item.owner_id.to_def_id(), sym::must_use); if let Some(attr) = attr { check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr); - } else if is_public && !is_proc_macro(cx.sess(), attrs) && trait_ref_of_method(cx, item.def_id.def_id).is_none() + } else if is_public && !is_proc_macro(cx.sess(), attrs) && trait_ref_of_method(cx, item.owner_id.def_id).is_none() { check_must_use_candidate( cx, sig.decl, cx.tcx.hir().body(*body_id), item.span, - item.def_id.def_id, + item.owner_id.def_id, item.span.with_hi(sig.decl.output.span().hi()), "this method could have a `#[must_use]` attribute", ); @@ -67,11 +67,11 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { if let hir::TraitItemKind::Fn(ref sig, ref eid) = item.kind { - let is_public = cx.effective_visibilities.is_exported(item.def_id.def_id); + let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); let attrs = cx.tcx.hir().attrs(item.hir_id()); - let attr = cx.tcx.get_attr(item.def_id.to_def_id(), sym::must_use); + let attr = cx.tcx.get_attr(item.owner_id.to_def_id(), sym::must_use); if let Some(attr) = attr { check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr); } else if let hir::TraitFn::Provided(eid) = *eid { @@ -82,7 +82,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr sig.decl, body, item.span, - item.def_id.def_id, + item.owner_id.def_id, item.span.with_hi(sig.decl.output.span().hi()), "this method could have a `#[must_use]` attribute", ); diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs index 0831b5cc38bd..2c0bf551fd7e 100644 --- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs +++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs @@ -31,7 +31,7 @@ pub(super) fn check_fn<'tcx>( pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { if let hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(eid)) = item.kind { let body = cx.tcx.hir().body(eid); - check_raw_ptr(cx, sig.header.unsafety, sig.decl, body, item.def_id.def_id); + check_raw_ptr(cx, sig.header.unsafety, sig.decl, body, item.owner_id.def_id); } } diff --git a/src/tools/clippy/clippy_lints/src/functions/result.rs b/src/tools/clippy/clippy_lints/src/functions/result.rs index c5ce56dd2cef..5c63fb2acb11 100644 --- a/src/tools/clippy/clippy_lints/src/functions/result.rs +++ b/src/tools/clippy/clippy_lints/src/functions/result.rs @@ -34,9 +34,9 @@ fn result_err_ty<'tcx>( pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, large_err_threshold: u64) { if let hir::ItemKind::Fn(ref sig, _generics, _) = item.kind - && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id.def_id, item.span) + && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.owner_id.def_id, item.span) { - if cx.effective_visibilities.is_exported(item.def_id.def_id) { + if cx.effective_visibilities.is_exported(item.owner_id.def_id) { let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); check_result_unit_err(cx, err_ty, fn_header_span); } @@ -47,10 +47,10 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, l pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::ImplItem<'tcx>, large_err_threshold: u64) { // Don't lint if method is a trait's implementation, we can't do anything about those if let hir::ImplItemKind::Fn(ref sig, _) = item.kind - && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id.def_id, item.span) - && trait_ref_of_method(cx, item.def_id.def_id).is_none() + && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.owner_id.def_id, item.span) + && trait_ref_of_method(cx, item.owner_id.def_id).is_none() { - if cx.effective_visibilities.is_exported(item.def_id.def_id) { + if cx.effective_visibilities.is_exported(item.owner_id.def_id) { let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); check_result_unit_err(cx, err_ty, fn_header_span); } @@ -61,8 +61,8 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::ImplItem pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::TraitItem<'tcx>, large_err_threshold: u64) { if let hir::TraitItemKind::Fn(ref sig, _) = item.kind { let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); - if let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id.def_id, item.span) { - if cx.effective_visibilities.is_exported(item.def_id.def_id) { + if let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.owner_id.def_id, item.span) { + if cx.effective_visibilities.is_exported(item.owner_id.def_id) { check_result_unit_err(cx, err_ty, fn_header_span); } check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold); diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs index 6415f35ddd03..94e06cf704ba 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs @@ -111,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { } } - if !cx.effective_visibilities.is_exported(item.def_id.def_id) { + if !cx.effective_visibilities.is_exported(item.owner_id.def_id) { return; } diff --git a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs index 676136df572b..14a37f535b46 100644 --- a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs +++ b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs @@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString { if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id()), sym::String); // Filters instances of to_string which are required by a trait - if trait_ref_of_method(cx, impl_item.def_id.def_id).is_none(); + if trait_ref_of_method(cx, impl_item.owner_id.def_id).is_none(); then { show_lint(cx, impl_item); @@ -124,7 +124,7 @@ fn show_lint(cx: &LateContext<'_>, item: &ImplItem<'_>) { .expect("Failed to get trait ID of `Display`!"); // Get the real type of 'self' - let self_type = cx.tcx.fn_sig(item.def_id).input(0); + let self_type = cx.tcx.fn_sig(item.owner_id).input(0); let self_type = self_type.skip_binder().peel_refs(); // Emit either a warning or an error diff --git a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs index ea9f046fb973..e76de77f195d 100644 --- a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs @@ -44,7 +44,7 @@ impl<'tcx> LateLintPass<'tcx> for IterNotReturningIterator { let name = item.ident.name.as_str(); if matches!(name, "iter" | "iter_mut") { if let TraitItemKind::Fn(fn_sig, _) = &item.kind { - check_sig(cx, name, fn_sig, item.def_id.def_id); + check_sig(cx, name, fn_sig, item.owner_id.def_id); } } } @@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for IterNotReturningIterator { ) { if let ImplItemKind::Fn(fn_sig, _) = &item.kind { - check_sig(cx, name, fn_sig, item.def_id.def_id); + check_sig(cx, name, fn_sig, item.owner_id.def_id); } } } diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs index 8ed7e4bb196c..06e957285499 100644 --- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs +++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs @@ -123,7 +123,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant { return; } if let ItemKind::Enum(ref def, _) = item.kind { - let ty = cx.tcx.type_of(item.def_id); + let ty = cx.tcx.type_of(item.owner_id); let Adt(adt, subst) = ty.kind() else { panic!("already checked whether this is an enum") }; diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 6e31812d7053..b0cba40c27a5 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -134,7 +134,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { if item.ident.name == sym::len; if let ImplItemKind::Fn(sig, _) = &item.kind; if sig.decl.implicit_self.has_implicit_self(); - if cx.effective_visibilities.is_exported(item.def_id.def_id); + if cx.effective_visibilities.is_exported(item.owner_id.def_id); if matches!(sig.decl.output, FnRetTy::Return(_)); if let Some(imp) = get_parent_as_impl(cx.tcx, item.hir_id()); if imp.of_trait.is_none(); @@ -143,7 +143,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { if let Some(local_id) = ty_id.as_local(); let ty_hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_id); if !is_lint_allowed(cx, LEN_WITHOUT_IS_EMPTY, ty_hir_id); - if let Some(output) = parse_len_output(cx, cx.tcx.fn_sig(item.def_id).skip_binder()); + if let Some(output) = parse_len_output(cx, cx.tcx.fn_sig(item.owner_id).skip_binder()); then { let (name, kind) = match cx.tcx.hir().find(ty_hir_id) { Some(Node::ForeignItem(x)) => (x.ident.name, "extern type"), @@ -195,7 +195,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items fn is_named_self(cx: &LateContext<'_>, item: &TraitItemRef, name: Symbol) -> bool { item.ident.name == name && if let AssocItemKind::Fn { has_self } = item.kind { - has_self && { cx.tcx.fn_sig(item.id.def_id).inputs().skip_binder().len() == 1 } + has_self && { cx.tcx.fn_sig(item.id.owner_id).inputs().skip_binder().len() == 1 } } else { false } @@ -210,11 +210,11 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items } } - if cx.effective_visibilities.is_exported(visited_trait.def_id.def_id) + if cx.effective_visibilities.is_exported(visited_trait.owner_id.def_id) && trait_items.iter().any(|i| is_named_self(cx, i, sym::len)) { let mut current_and_super_traits = DefIdSet::default(); - fill_trait_set(visited_trait.def_id.to_def_id(), &mut current_and_super_traits, cx); + fill_trait_set(visited_trait.owner_id.to_def_id(), &mut current_and_super_traits, cx); let is_empty = sym!(is_empty); let is_empty_method_found = current_and_super_traits diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index aef253303a8f..3bf2d7e4ea4e 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { if let ImplItemKind::Fn(ref sig, id) = item.kind { - let report_extra_lifetimes = trait_ref_of_method(cx, item.def_id.def_id).is_none(); + let report_extra_lifetimes = trait_ref_of_method(cx, item.owner_id.def_id).is_none(); check_fn_inner( cx, sig.decl, diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs index 6a42275322b4..6806c1466968 100644 --- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs +++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs @@ -166,7 +166,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum { if let Some((id, span)) = iter.next() && iter.next().is_none() { - self.potential_enums.push((item.def_id.def_id, id, item.span, span)); + self.potential_enums.push((item.owner_id.def_id, id, item.span, span)); } } } diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index adfa7426607f..8a76ba0b064b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -3250,15 +3250,15 @@ impl<'tcx> LateLintPass<'tcx> for Methods { let name = impl_item.ident.name.as_str(); let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id; let item = cx.tcx.hir().expect_item(parent); - let self_ty = cx.tcx.type_of(item.def_id); + let self_ty = cx.tcx.type_of(item.owner_id); let implements_trait = matches!(item.kind, hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. })); if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind { - let method_sig = cx.tcx.fn_sig(impl_item.def_id); + let method_sig = cx.tcx.fn_sig(impl_item.owner_id); let method_sig = cx.tcx.erase_late_bound_regions(method_sig); let first_arg_ty_opt = method_sig.inputs().iter().next().copied(); // if this impl block implements a trait, lint in trait definition instead - if !implements_trait && cx.effective_visibilities.is_exported(impl_item.def_id.def_id) { + if !implements_trait && cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) { // check missing trait implementations for method_config in &TRAIT_METHODS { if name == method_config.method_name @@ -3292,7 +3292,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if sig.decl.implicit_self.has_implicit_self() && !(self.avoid_breaking_exported_api - && cx.effective_visibilities.is_exported(impl_item.def_id.def_id)) + && cx.effective_visibilities.is_exported(impl_item.owner_id.def_id)) && let Some(first_arg) = iter_input_pats(sig.decl, cx.tcx.hir().body(id)).next() && let Some(first_arg_ty) = first_arg_ty_opt { @@ -3370,7 +3370,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { then { let first_arg_span = first_arg_ty.span; let first_arg_ty = hir_ty_to_ty(cx.tcx, first_arg_ty); - let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()) + let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id()) .self_ty() .skip_binder(); wrong_self_convention::check( @@ -3389,7 +3389,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if item.ident.name == sym::new; if let TraitItemKind::Fn(_, _) = item.kind; let ret_ty = return_ty(cx, item.hir_id()); - let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()) + let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id()) .self_ty() .skip_binder(); if !ret_ty.contains(self_ty); diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index b3f1553cfea9..2a63681db60e 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -131,7 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { hir::ItemKind::Fn(..) => { // ignore main() if it.ident.name == sym::main { - let at_root = cx.tcx.local_parent(it.def_id.def_id) == CRATE_DEF_ID; + let at_root = cx.tcx.local_parent(it.owner_id.def_id) == CRATE_DEF_ID; if at_root { return; } @@ -155,7 +155,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { | hir::ItemKind::Use(..) => return, }; - let (article, desc) = cx.tcx.article_and_description(it.def_id.to_def_id()); + let (article, desc) = cx.tcx.article_and_description(it.owner_id.to_def_id()); let attrs = cx.tcx.hir().attrs(it.hir_id()); if !is_from_proc_macro(cx, it) { @@ -164,7 +164,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { } fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx hir::TraitItem<'_>) { - let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id()); + let (article, desc) = cx.tcx.article_and_description(trait_item.owner_id.to_def_id()); let attrs = cx.tcx.hir().attrs(trait_item.hir_id()); if !is_from_proc_macro(cx, trait_item) { @@ -174,7 +174,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { // If the method is an impl for a trait, don't doc. - if let Some(cid) = cx.tcx.associated_item(impl_item.def_id).impl_container(cx.tcx) { + if let Some(cid) = cx.tcx.associated_item(impl_item.owner_id).impl_container(cx.tcx) { if cx.tcx.impl_trait_ref(cid).is_some() { return; } @@ -182,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { return; } - let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id()); + let (article, desc) = cx.tcx.article_and_description(impl_item.owner_id.to_def_id()); let attrs = cx.tcx.hir().attrs(impl_item.hir_id()); if !is_from_proc_macro(cx, impl_item) { self.check_missing_docs_attrs(cx, attrs, impl_item.span, article, desc); diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index ed9da2d92173..758ce47cf114 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { return; } - if !cx.effective_visibilities.is_exported(it.def_id.def_id) { + if !cx.effective_visibilities.is_exported(it.owner_id.def_id) { return; } match it.kind { @@ -105,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { match tit_.kind { hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => {}, hir::TraitItemKind::Fn(..) => { - if cx.tcx.impl_defaultness(tit.id.def_id).has_value() { + if cx.tcx.impl_defaultness(tit.id.owner_id).has_value() { // trait method with default body needs inline in case // an impl is not provided let desc = "a default trait method"; @@ -142,7 +142,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { } // If the item being implemented is not exported, then we don't need #[inline] - if !cx.effective_visibilities.is_exported(impl_item.def_id.def_id) { + if !cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) { return; } @@ -151,7 +151,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { hir::ImplItemKind::Const(..) | hir::ImplItemKind::Type(_) => return, }; - let assoc_item = cx.tcx.associated_item(impl_item.def_id); + let assoc_item = cx.tcx.associated_item(impl_item.owner_id); let container_id = assoc_item.container_id(cx.tcx); let trait_def_id = match assoc_item.container { TraitContainer => Some(container_id), @@ -159,7 +159,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { }; if let Some(trait_def_id) = trait_def_id { - if trait_def_id.is_local() && !cx.effective_visibilities.is_exported(impl_item.def_id.def_id) { + if trait_def_id.is_local() && !cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) { // If a trait is being implemented for an item, and the // trait is not exported, we don't need #[inline] return; diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs index 25d6ca83a94b..8a2e77980b36 100644 --- a/src/tools/clippy/clippy_lints/src/mut_key.rs +++ b/src/tools/clippy/clippy_lints/src/mut_key.rs @@ -89,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableKeyType { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'tcx>) { if let hir::ImplItemKind::Fn(ref sig, ..) = item.kind { - if trait_ref_of_method(cx, item.def_id.def_id).is_none() { + if trait_ref_of_method(cx, item.owner_id.def_id).is_none() { check_sig(cx, item.hir_id(), sig.decl); } } diff --git a/src/tools/clippy/clippy_lints/src/new_without_default.rs b/src/tools/clippy/clippy_lints/src/new_without_default.rs index 99166c68936c..54a3c82b713d 100644 --- a/src/tools/clippy/clippy_lints/src/new_without_default.rs +++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs @@ -84,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { // can't be implemented for unsafe new return; } - if cx.tcx.is_doc_hidden(impl_item.def_id.def_id) { + if cx.tcx.is_doc_hidden(impl_item.owner_id.def_id) { // shouldn't be implemented when it is hidden in docs return; } @@ -96,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { if_chain! { if sig.decl.inputs.is_empty(); if name == sym::new; - if cx.effective_visibilities.is_reachable(impl_item.def_id.def_id); + if cx.effective_visibilities.is_reachable(impl_item.owner_id.def_id); let self_def_id = cx.tcx.hir().get_parent_item(id); let self_ty = cx.tcx.type_of(self_def_id); if self_ty == return_ty(cx, id); diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index a6742824bc56..938560b625ee 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -303,7 +303,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { if let Some(of_trait_def_id) = of_trait_ref.trait_def_id(); if let Some(of_assoc_item) = cx .tcx - .associated_item(impl_item.def_id) + .associated_item(impl_item.owner_id) .trait_item_def_id; if cx .tcx diff --git a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs index ddef7352de88..714c0ff227bf 100644 --- a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs +++ b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs @@ -89,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy { if let Some(trait_id) = trait_ref.trait_def_id(); if send_trait == trait_id; if hir_impl.polarity == ImplPolarity::Positive; - if let Some(ty_trait_ref) = cx.tcx.impl_trait_ref(item.def_id); + if let Some(ty_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id); if let self_ty = ty_trait_ref.self_ty(); if let ty::Adt(adt_def, impl_trait_substs) = self_ty.kind(); then { diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs index d64a9cf71e17..7722a476d7b4 100644 --- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs @@ -227,25 +227,25 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion { // `skip_params` is either `0` or `1` to skip the `self` parameter in trait functions. // It can't be renamed, and it can't be removed without removing it from multiple functions. let (fn_id, fn_kind, skip_params) = match get_parent_node(cx.tcx, body.value.hir_id) { - Some(Node::Item(i)) => (i.def_id.to_def_id(), FnKind::Fn, 0), + Some(Node::Item(i)) => (i.owner_id.to_def_id(), FnKind::Fn, 0), Some(Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(ref sig, _), - def_id, + owner_id, .. })) => ( - def_id.to_def_id(), + owner_id.to_def_id(), FnKind::TraitFn, usize::from(sig.decl.implicit_self.has_implicit_self()), ), Some(Node::ImplItem(&ImplItem { kind: ImplItemKind::Fn(ref sig, _), - def_id, + owner_id, .. })) => { #[allow(trivial_casts)] - if let Some(Node::Item(item)) = get_parent_node(cx.tcx, def_id.into()) - && let Some(trait_ref) = cx.tcx.impl_trait_ref(item.def_id) - && let Some(trait_item_id) = cx.tcx.associated_item(def_id).trait_item_def_id + if let Some(Node::Item(item)) = get_parent_node(cx.tcx, owner_id.into()) + && let Some(trait_ref) = cx.tcx.impl_trait_ref(item.owner_id) + && let Some(trait_item_id) = cx.tcx.associated_item(owner_id).trait_item_def_id { ( trait_item_id, @@ -253,7 +253,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion { usize::from(sig.decl.implicit_self.has_implicit_self()), ) } else { - (def_id.to_def_id(), FnKind::Fn, 0) + (owner_id.to_def_id(), FnKind::Fn, 0) } }, _ => return, diff --git a/src/tools/clippy/clippy_lints/src/operators/op_ref.rs b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs index 1085e6089441..71b31b5e4a56 100644 --- a/src/tools/clippy/clippy_lints/src/operators/op_ref.rs +++ b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs @@ -204,7 +204,7 @@ fn are_equal<'tcx>(cx: &LateContext<'tcx>, middle_ty: Ty<'_>, hir_ty: &rustc_hir if let ty::Adt(adt_def, _) = middle_ty.kind(); if let Some(local_did) = adt_def.did().as_local(); let item = cx.tcx.hir().expect_item(local_did); - let middle_ty_id = item.def_id.to_def_id(); + let middle_ty_id = item.owner_id.to_def_id(); if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind; if let Res::Def(_, hir_ty_id) = path.res; diff --git a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs index 09ac514d014e..5aa3c6f2f934 100644 --- a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs +++ b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs @@ -36,7 +36,7 @@ impl<'tcx> LateLintPass<'tcx> for PartialEqNeImpl { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if_chain! { if let ItemKind::Impl(Impl { of_trait: Some(ref trait_ref), items: impl_items, .. }) = item.kind; - if !cx.tcx.has_attr(item.def_id.to_def_id(), sym::automatically_derived); + if !cx.tcx.has_attr(item.owner_id.to_def_id(), sym::automatically_derived); if let Some(eq_trait) = cx.tcx.lang_items().eq_trait(); if trait_ref.path.res.def_id() == eq_trait; then { diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index c55985275db6..f9fd3645668a 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -261,7 +261,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue { } if let hir::TraitItemKind::Fn(method_sig, _) = &item.kind { - self.check_poly_fn(cx, item.def_id.def_id, method_sig.decl, None); + self.check_poly_fn(cx, item.owner_id.def_id, method_sig.decl, None); } } diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index 40db315bf272..0d74c90a834f 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -164,7 +164,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { check_mut_from_ref(cx, sig, None); for arg in check_fn_args( cx, - cx.tcx.fn_sig(item.def_id).skip_binder().inputs(), + cx.tcx.fn_sig(item.owner_id).skip_binder().inputs(), sig.decl.inputs, &[], ) @@ -188,7 +188,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { let (item_id, sig, is_trait_item) = match parents.next() { Some((_, Node::Item(i))) => { if let ItemKind::Fn(sig, ..) = &i.kind { - (i.def_id, sig, false) + (i.owner_id, sig, false) } else { return; } @@ -200,14 +200,14 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { return; } if let ImplItemKind::Fn(sig, _) = &i.kind { - (i.def_id, sig, false) + (i.owner_id, sig, false) } else { return; } }, Some((_, Node::TraitItem(i))) => { if let TraitItemKind::Fn(sig, _) = &i.kind { - (i.def_id, sig, true) + (i.owner_id, sig, true) } else { return; } diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs index bc73613a1502..26075e9f70fa 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs @@ -46,12 +46,12 @@ impl_lint_pass!(RedundantPubCrate => [REDUNDANT_PUB_CRATE]); impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { if_chain! { - if cx.tcx.visibility(item.def_id.def_id) == ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id()); - if !cx.effective_visibilities.is_exported(item.def_id.def_id) && self.is_exported.last() == Some(&false); + if cx.tcx.visibility(item.owner_id.def_id) == ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id()); + if !cx.effective_visibilities.is_exported(item.owner_id.def_id) && self.is_exported.last() == Some(&false); if is_not_macro_export(item); then { let span = item.span.with_hi(item.ident.span.hi()); - let descr = cx.tcx.def_kind(item.def_id).descr(item.def_id.to_def_id()); + let descr = cx.tcx.def_kind(item.owner_id).descr(item.owner_id.to_def_id()); span_lint_and_then( cx, REDUNDANT_PUB_CRATE, @@ -70,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { } if let ItemKind::Mod { .. } = item.kind { - self.is_exported.push(cx.effective_visibilities.is_exported(item.def_id.def_id)); + self.is_exported.push(cx.effective_visibilities.is_exported(item.owner_id.def_id)); } } diff --git a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs index 7f34be5e7fd8..b77faf7322bd 100644 --- a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs +++ b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs @@ -128,7 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for ReturnSelfNotMustUse { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'tcx>) { if let TraitItemKind::Fn(ref sig, _) = item.kind { - check_method(cx, sig.decl, item.def_id.def_id, item.span, item.hir_id()); + check_method(cx, sig.decl, item.owner_id.def_id, item.span, item.hir_id()); } } } diff --git a/src/tools/clippy/clippy_lints/src/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs index 4249063d2d47..caab5851bafc 100644 --- a/src/tools/clippy/clippy_lints/src/same_name_method.rs +++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs @@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod { let mut map = FxHashMap::::default(); for id in cx.tcx.hir().items() { - if matches!(cx.tcx.def_kind(id.def_id), DefKind::Impl) + if matches!(cx.tcx.def_kind(id.owner_id), DefKind::Impl) && let item = cx.tcx.hir().item(id) && let ItemKind::Impl(Impl { items, diff --git a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs index 1ac538f4c7c0..71b387c66a33 100644 --- a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs +++ b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs @@ -53,7 +53,7 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors { let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id; let item = cx.tcx.hir().expect_item(parent); - let self_ty = cx.tcx.type_of(item.def_id); + let self_ty = cx.tcx.type_of(item.owner_id); let ret_ty = return_ty(cx, impl_item.hir_id()); // Do not check trait impls diff --git a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs index 58cc057a39ed..8cf3efc8dc73 100644 --- a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs +++ b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs @@ -46,7 +46,7 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray { None, &format!( "consider annotating `{}` with `#[repr(C)]` or another `repr` attribute", - cx.tcx.def_path_str(item.def_id.to_def_id()) + cx.tcx.def_path_str(item.owner_id.to_def_id()) ), ); } diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 40cdcc3865ba..f6de87b0526c 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -333,7 +333,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - let is_exported = cx.effective_visibilities.is_exported(item.def_id.def_id); + let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id); match item.kind { ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => self.check_ty( @@ -392,7 +392,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'_>) { - let is_exported = cx.effective_visibilities.is_exported(item.def_id.def_id); + let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id); let context = CheckTyContext { is_exported, diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs index 62ab927d2f5c..42bccc7212b3 100644 --- a/src/tools/clippy/clippy_lints/src/unused_self.rs +++ b/src/tools/clippy/clippy_lints/src/unused_self.rs @@ -56,12 +56,12 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf { } let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id; let parent_item = cx.tcx.hir().expect_item(parent); - let assoc_item = cx.tcx.associated_item(impl_item.def_id); + let assoc_item = cx.tcx.associated_item(impl_item.owner_id); if_chain! { if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind; if assoc_item.fn_has_self_parameter; if let ImplItemKind::Fn(.., body_id) = &impl_item.kind; - if !cx.effective_visibilities.is_exported(impl_item.def_id.def_id) || !self.avoid_breaking_exported_api; + if !cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) || !self.avoid_breaking_exported_api; let body = cx.tcx.hir().body(*body_id); if let [self_param, ..] = body.params; if !is_local_used(cx, body, self_param.pat.hir_id); diff --git a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs index a69719b127b2..f3611d174340 100644 --- a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs +++ b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs @@ -76,7 +76,7 @@ impl<'tcx> LateLintPass<'tcx> for UnwrapInResult { fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_item: &'tcx hir::ImplItem<'_>) { if let ImplItemKind::Fn(_, body_id) = impl_item.kind { let body = cx.tcx.hir().body(body_id); - let typeck = cx.tcx.typeck(impl_item.def_id.def_id); + let typeck = cx.tcx.typeck(impl_item.owner_id.def_id); let mut result = Vec::new(); let _: Option = for_each_expr(body.value, |e| { // check for `expect` diff --git a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs index 7a20148c70a5..1d2d3eb12e11 100644 --- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs +++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs @@ -105,7 +105,7 @@ impl LateLintPass<'_> for UpperCaseAcronyms { fn check_item(&mut self, cx: &LateContext<'_>, it: &Item<'_>) { // do not lint public items or in macros if in_external_macro(cx.sess(), it.span) - || (self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(it.def_id.def_id)) + || (self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(it.owner_id.def_id)) { return; } diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index 65f1b5462081..c6cdf3f85fc3 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -106,7 +106,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { if !is_from_proc_macro(cx, item); // expensive, should be last check then { StackItem::Check { - impl_id: item.def_id.def_id, + impl_id: item.owner_id.def_id, in_body: 0, types_to_skip: std::iter::once(self_ty.hir_id).collect(), } @@ -143,7 +143,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { // trait, not in the impl of the trait. let trait_method = cx .tcx - .associated_item(impl_item.def_id) + .associated_item(impl_item.owner_id) .trait_item_def_id .expect("impl method matches a trait method"); let trait_method_sig = cx.tcx.fn_sig(trait_method); diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs index 301eed9a1fbf..be98344470b9 100644 --- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs +++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs @@ -120,14 +120,14 @@ impl LateLintPass<'_> for WildcardImports { if is_test_module_or_function(cx.tcx, item) { self.test_modules_deep = self.test_modules_deep.saturating_add(1); } - let module = cx.tcx.parent_module_from_def_id(item.def_id.def_id); - if cx.tcx.visibility(item.def_id.def_id) != ty::Visibility::Restricted(module.to_def_id()) { + let module = cx.tcx.parent_module_from_def_id(item.owner_id.def_id); + if cx.tcx.visibility(item.owner_id.def_id) != ty::Visibility::Restricted(module.to_def_id()) { return; } if_chain! { if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind; if self.warn_on_all || !self.check_exceptions(item, use_path.segments); - let used_imports = cx.tcx.names_imported_by_glob_use(item.def_id.def_id); + let used_imports = cx.tcx.names_imported_by_glob_use(item.owner_id.def_id); if !used_imports.is_empty(); // Already handled by `unused_imports` then { let mut applicability = Applicability::MachineApplicable; diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 052db3f3a039..3ebfc5e00e14 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2281,7 +2281,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalDefId, f: impl Fn(&[Symbol Entry::Vacant(entry) => { let mut names = Vec::new(); for id in tcx.hir().module_items(module) { - if matches!(tcx.def_kind(id.def_id), DefKind::Const) + if matches!(tcx.def_kind(id.owner_id), DefKind::Const) && let item = tcx.hir().item(id) && let ItemKind::Const(ty, _body) = item.kind { if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind { From f0234f1976564c541d6aa1f04312e5acc22b2f3e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 27 Oct 2022 21:48:34 +0200 Subject: [PATCH 163/171] Add missing impl blocks for item reexported from private mod in JSON output --- src/librustdoc/passes/stripper.rs | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index f293a6fcc6df..89efddf76ef7 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -1,9 +1,11 @@ //! A collection of utility functions for the `strip_*` passes. use rustc_hir::def_id::DefId; use rustc_middle::middle::privacy::EffectiveVisibilities; +use rustc_span::symbol::sym; + use std::mem; -use crate::clean::{self, Item, ItemId, ItemIdSet}; +use crate::clean::{self, Item, ItemId, ItemIdSet, NestedAttributesExt}; use crate::fold::{strip_item, DocFolder}; use crate::formats::cache::Cache; @@ -151,6 +153,22 @@ pub(crate) struct ImplStripper<'a> { pub(crate) document_private: bool, } +impl<'a> ImplStripper<'a> { + #[inline] + fn should_keep_impl(&self, item: &Item, for_def_id: DefId) -> bool { + if !for_def_id.is_local() || self.retained.contains(&for_def_id.into()) { + true + } else if self.is_json_output { + // If the "for" item is exported and the impl block isn't `#[doc(hidden)]`, then we + // need to keep it. + self.cache.access_levels.is_exported(for_def_id) + && !item.attrs.lists(sym::doc).has_word(sym::hidden) + } else { + false + } + } +} + impl<'a> DocFolder for ImplStripper<'a> { fn fold_item(&mut self, i: Item) -> Option { if let clean::ImplItem(ref imp) = *i.kind { @@ -178,15 +196,17 @@ impl<'a> DocFolder for ImplStripper<'a> { return None; } } + // Because we don't inline in `maybe_inline_local` if the output format is JSON, + // we need to make a special check for JSON output: we want to keep it unless it has + // a `#[doc(hidden)]` attribute if the `for_` type is exported. if let Some(did) = imp.for_.def_id(self.cache) { - if did.is_local() && !imp.for_.is_assoc_ty() && !self.retained.contains(&did.into()) - { + if !imp.for_.is_assoc_ty() && !self.should_keep_impl(&i, did) { debug!("ImplStripper: impl item for stripped type; removing"); return None; } } if let Some(did) = imp.trait_.as_ref().map(|t| t.def_id()) { - if did.is_local() && !self.retained.contains(&did.into()) { + if !self.should_keep_impl(&i, did) { debug!("ImplStripper: impl item for stripped trait; removing"); return None; } @@ -194,7 +214,7 @@ impl<'a> DocFolder for ImplStripper<'a> { if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) { for typaram in generics { if let Some(did) = typaram.def_id(self.cache) { - if did.is_local() && !self.retained.contains(&did.into()) { + if !self.should_keep_impl(&i, did) { debug!( "ImplStripper: stripped item in trait's generics; removing impl" ); From 0ef36b89459956af005b4186e4321f7f0376ec7d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 27 Oct 2022 21:48:54 +0200 Subject: [PATCH 164/171] Add regression test for missing item from private mod in JSON output --- src/librustdoc/passes/stripper.rs | 2 +- .../reexport_method_from_private_module.rs | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/test/rustdoc-json/reexport/reexport_method_from_private_module.rs diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index 89efddf76ef7..0089ce63d07b 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -161,7 +161,7 @@ impl<'a> ImplStripper<'a> { } else if self.is_json_output { // If the "for" item is exported and the impl block isn't `#[doc(hidden)]`, then we // need to keep it. - self.cache.access_levels.is_exported(for_def_id) + self.cache.effective_visibilities.is_exported(for_def_id) && !item.attrs.lists(sym::doc).has_word(sym::hidden) } else { false diff --git a/src/test/rustdoc-json/reexport/reexport_method_from_private_module.rs b/src/test/rustdoc-json/reexport/reexport_method_from_private_module.rs new file mode 100644 index 000000000000..239b1a23b43d --- /dev/null +++ b/src/test/rustdoc-json/reexport/reexport_method_from_private_module.rs @@ -0,0 +1,28 @@ +// Regression test for . + +// @set impl_S = "$.index[*][?(@.docs=='impl S')].id" +// @has "$.index[*][?(@.name=='S')].inner.impls[*]" $impl_S +// @set is_present = "$.index[*][?(@.name=='is_present')].id" +// @is "$.index[*][?(@.docs=='impl S')].inner.items[*]" $is_present +// @!has "$.index[*][?(@.name=='hidden_impl')]" +// @!has "$.index[*][?(@.name=='hidden_fn')]" + +#![no_std] + +mod private_mod { + pub struct S; + + /// impl S + impl S { + pub fn is_present() {} + #[doc(hidden)] + pub fn hidden_fn() {} + } + + #[doc(hidden)] + impl S { + pub fn hidden_impl() {} + } +} + +pub use private_mod::*; From 4fac361ea3faead329e22b2874f05999ae2c5dc2 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 29 Oct 2022 12:23:10 +0200 Subject: [PATCH 165/171] Fix z-indexes of code example feature and cleanup its CSS --- src/librustdoc/html/highlight.rs | 4 ++ src/librustdoc/html/render/mod.rs | 6 +-- src/librustdoc/html/sources.rs | 9 ++++- src/librustdoc/html/static/css/rustdoc.css | 45 +++++++++------------- 4 files changed, 30 insertions(+), 34 deletions(-) diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 5e28204b21d8..28136cc48d65 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -72,8 +72,12 @@ pub(crate) fn render_source_with_highlighting( line_numbers: Buffer, href_context: HrefContext<'_, '_, '_>, decoration_info: DecorationInfo, + extra: Option<&str>, ) { write_header(out, "", Some(line_numbers), Tooltip::None); + if let Some(extra) = extra { + out.push_str(extra); + } write_code(out, src, Some(href_context), Some(decoration_info)); write_footer(out, None); } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 96c57c8c85d4..27dea8ec0b31 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2869,10 +2869,6 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite write!(w, r#" "#); } - if needs_expansion { - write!(w, r#""#); - } - // Look for the example file in the source map if it exists, otherwise return a dummy span let file_span = (|| { let source_map = tcx.sess.source_map(); @@ -2906,7 +2902,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite cx, &root_path, highlight::DecorationInfo(decoration_info), - sources::SourceContext::Embedded { offset: line_min }, + sources::SourceContext::Embedded { offset: line_min, needs_expansion }, ); write!(w, "
"); diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 7ab65bff3469..8a01c01049d6 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -258,7 +258,7 @@ where pub(crate) enum SourceContext { Standalone, - Embedded { offset: usize }, + Embedded { offset: usize, needs_expansion: bool }, } /// Wrapper struct to render the source code of a file. This will do things like @@ -274,14 +274,18 @@ pub(crate) fn print_src( ) { let lines = s.lines().count(); let mut line_numbers = Buffer::empty_from(buf); + let extra; line_numbers.write_str("
");
     match source_context {
         SourceContext::Standalone => {
+            extra = None;
             for line in 1..=lines {
                 writeln!(line_numbers, "{0}", line)
             }
         }
-        SourceContext::Embedded { offset } => {
+        SourceContext::Embedded { offset, needs_expansion } => {
+            extra =
+                if needs_expansion { Some(r#""#) } else { None };
             for line in 1..=lines {
                 writeln!(line_numbers, "{0}", line + offset)
             }
@@ -297,5 +301,6 @@ pub(crate) fn print_src(
         line_numbers,
         highlight::HrefContext { context, file_span, root_path, current_href },
         decoration_info,
+        extra,
     );
 }
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 09371dc027b8..178b5fb2d1da 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -2028,45 +2028,36 @@ in storage.js
 	padding-bottom: 0;
 }
 
-.scraped-example .code-wrapper .prev {
-	position: absolute;
-	top: 0.25em;
-	right: 2.25em;
-	z-index: 100;
-	cursor: pointer;
-}
-
-.scraped-example .code-wrapper .next {
-	position: absolute;
-	top: 0.25em;
-	right: 1.25em;
-	z-index: 100;
-	cursor: pointer;
-}
-
+.scraped-example .code-wrapper .next,
+.scraped-example .code-wrapper .prev,
 .scraped-example .code-wrapper .expand {
 	position: absolute;
 	top: 0.25em;
-	right: 0.25em;
-	z-index: 100;
+	z-index: 1;
 	cursor: pointer;
 }
-
-.scraped-example:not(.expanded) .code-wrapper:before {
-	content: " ";
-	width: 100%;
-	height: 5px;
-	position: absolute;
-	z-index: 100;
-	top: 0;
+.scraped-example .code-wrapper .prev {
+	right: 2.25em;
+}
+.scraped-example .code-wrapper .next {
+	right: 1.25em;
+}
+.scraped-example .code-wrapper .expand {
+	right: 0.25em;
 }
 
+.scraped-example:not(.expanded) .code-wrapper:before,
 .scraped-example:not(.expanded) .code-wrapper:after {
 	content: " ";
 	width: 100%;
 	height: 5px;
 	position: absolute;
-	z-index: 100;
+	z-index: 1;
+}
+.scraped-example:not(.expanded) .code-wrapper:before {
+	top: 0;
+}
+.scraped-example:not(.expanded) .code-wrapper:after {
 	bottom: 0;
 }
 

From 4cc03c16ada6da657ba41e1620f9d5ea0e55fc9f Mon Sep 17 00:00:00 2001
From: Mark Rousskov 
Date: Sat, 29 Oct 2022 10:28:52 -0400
Subject: [PATCH 166/171] Bump to 1.67.0

---
 src/version | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/version b/src/version
index b6148bc0a759..65ee0959841f 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.66.0
+1.67.0

From d490ff461cce1d96f6eb9b54891c5c5106c8a098 Mon Sep 17 00:00:00 2001
From: Michael Howell 
Date: Sat, 29 Oct 2022 09:04:31 -0700
Subject: [PATCH 167/171] rustdoc: use CSS margin/padding shorthand when all
 are being set

---
 src/librustdoc/html/static/css/rustdoc.css | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 09371dc027b8..aa08d608b160 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -493,9 +493,7 @@ ul.block, .block li {
 .sidebar h2 {
 	overflow-wrap: anywhere;
 	padding: 0;
-	margin: 0;
-	margin-top: 0.7rem;
-	margin-bottom: 0.7rem;
+	margin: 0.7rem 0;
 }
 
 .sidebar h3 {
@@ -805,10 +803,8 @@ table,
 }
 #crate-search {
 	min-width: 115px;
-	padding: 0;
 	/* keep these two in sync with "@-moz-document url-prefix()" below */
-	padding-left: 4px;
-	padding-right: 23px;
+	padding: 0 23px 0 4px;
 	/* prevents the