From 68fd1ce3139ca6517f2c46ad12866147aca6b178 Mon Sep 17 00:00:00 2001 From: feniljain Date: Mon, 12 Dec 2022 16:48:55 +0530 Subject: [PATCH 001/116] feat: bump variant suggestion for enums in patterns completion --- crates/ide-completion/src/completions.rs | 2 ++ crates/ide-completion/src/render/pattern.rs | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs index 296dfc14250f..cac5dccde2b2 100644 --- a/crates/ide-completion/src/completions.rs +++ b/crates/ide-completion/src/completions.rs @@ -496,6 +496,7 @@ impl Completions { variant, local_name.clone(), None, + false, )); } @@ -514,6 +515,7 @@ impl Completions { variant, None, path, + true, )); } diff --git a/crates/ide-completion/src/render/pattern.rs b/crates/ide-completion/src/render/pattern.rs index c845ff21aaba..edb727b57d2b 100644 --- a/crates/ide-completion/src/render/pattern.rs +++ b/crates/ide-completion/src/render/pattern.rs @@ -7,6 +7,7 @@ use syntax::SmolStr; use crate::{ context::{ParamContext, ParamKind, PathCompletionCtx, PatternContext}, + item::CompletionRelevanceTypeMatch, render::{ variant::{format_literal_label, format_literal_lookup, visible_fields}, RenderContext, @@ -37,7 +38,7 @@ pub(crate) fn render_struct_pat( let lookup = format_literal_lookup(name.as_str(), kind); let pat = render_pat(&ctx, pattern_ctx, &escaped_name, kind, &visible_fields, fields_omitted)?; - Some(build_completion(ctx, label, lookup, pat, strukt)) + Some(build_completion(ctx, label, lookup, pat, strukt, false)) } pub(crate) fn render_variant_pat( @@ -47,6 +48,7 @@ pub(crate) fn render_variant_pat( variant: hir::Variant, local_name: Option, path: Option<&hir::ModPath>, + is_exact_type_match: bool, ) -> Option { let _p = profile::span("render_variant_pat"); @@ -81,7 +83,7 @@ pub(crate) fn render_variant_pat( } }; - Some(build_completion(ctx, label, lookup, pat, variant)) + Some(build_completion(ctx, label, lookup, pat, variant, is_exact_type_match)) } fn build_completion( @@ -90,13 +92,20 @@ fn build_completion( lookup: SmolStr, pat: String, def: impl HasAttrs + Copy, + is_exact_type_match: bool, ) -> CompletionItem { + let mut relevance = ctx.completion_relevance(); + + if is_exact_type_match { + relevance.type_match = Some(CompletionRelevanceTypeMatch::Exact); + } + let mut item = CompletionItem::new(CompletionItemKind::Binding, ctx.source_range(), label); item.set_documentation(ctx.docs(def)) .set_deprecated(ctx.is_deprecated(def)) .detail(&pat) .lookup_by(lookup) - .set_relevance(ctx.completion_relevance()); + .set_relevance(relevance); match ctx.snippet_cap() { Some(snippet_cap) => item.insert_snippet(snippet_cap, pat), None => item.insert_text(pat), From 794988c53b2ae41cabc23ee1dfb20e7d13b7dc3f Mon Sep 17 00:00:00 2001 From: feniljain Date: Sat, 17 Dec 2022 16:58:42 +0530 Subject: [PATCH 002/116] feat: filter already present enum variants in match arms --- crates/ide-completion/src/completions.rs | 25 +++++---- crates/ide-completion/src/completions/expr.rs | 1 + .../src/completions/flyimport.rs | 5 +- .../ide-completion/src/completions/pattern.rs | 1 + crates/ide-completion/src/context.rs | 2 + crates/ide-completion/src/context/analysis.rs | 53 ++++++++++++++++++- crates/ide-completion/src/render/pattern.rs | 2 +- crates/ide-completion/src/tests/record.rs | 41 ++++++++++++++ 8 files changed, 114 insertions(+), 16 deletions(-) diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs index cac5dccde2b2..fddd02fc13e2 100644 --- a/crates/ide-completion/src/completions.rs +++ b/crates/ide-completion/src/completions.rs @@ -23,7 +23,7 @@ pub(crate) mod env_vars; use std::iter; -use hir::{known, ScopeDef}; +use hir::{known, ScopeDef, Variant}; use ide_db::{imports::import_assets::LocatedImport, SymbolKind}; use syntax::ast; @@ -538,18 +538,25 @@ fn enum_variants_with_paths( enum_: hir::Enum, impl_: &Option, cb: impl Fn(&mut Completions, &CompletionContext<'_>, hir::Variant, hir::ModPath), + missing_variants: Option>, ) { - let variants = enum_.variants(ctx.db); + let mut process_variant = |variant: Variant| { + let self_path = hir::ModPath::from_segments( + hir::PathKind::Plain, + iter::once(known::SELF_TYPE).chain(iter::once(variant.name(ctx.db))), + ); + + cb(acc, ctx, variant, self_path); + }; + + let variants = match missing_variants { + Some(missing_variants) => missing_variants, + None => enum_.variants(ctx.db), + }; if let Some(impl_) = impl_.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) { if impl_.self_ty(ctx.db).as_adt() == Some(hir::Adt::Enum(enum_)) { - for &variant in &variants { - let self_path = hir::ModPath::from_segments( - hir::PathKind::Plain, - iter::once(known::SELF_TYPE).chain(iter::once(variant.name(ctx.db))), - ); - cb(acc, ctx, variant, self_path); - } + variants.iter().for_each(|variant| process_variant(*variant)); } } diff --git a/crates/ide-completion/src/completions/expr.rs b/crates/ide-completion/src/completions/expr.rs index 3192b21cfb2e..8946011280a9 100644 --- a/crates/ide-completion/src/completions/expr.rs +++ b/crates/ide-completion/src/completions/expr.rs @@ -208,6 +208,7 @@ pub(crate) fn complete_expr_path( |acc, ctx, variant, path| { acc.add_qualified_enum_variant(ctx, path_ctx, variant, path) }, + None, ); } } diff --git a/crates/ide-completion/src/completions/flyimport.rs b/crates/ide-completion/src/completions/flyimport.rs index 364969af9c9a..0979f6a6dfc7 100644 --- a/crates/ide-completion/src/completions/flyimport.rs +++ b/crates/ide-completion/src/completions/flyimport.rs @@ -5,10 +5,7 @@ use ide_db::imports::{ insert_use::ImportScope, }; use itertools::Itertools; -use syntax::{ - ast::{self}, - AstNode, SyntaxNode, T, -}; +use syntax::{ast, AstNode, SyntaxNode, T}; use crate::{ context::{ diff --git a/crates/ide-completion/src/completions/pattern.rs b/crates/ide-completion/src/completions/pattern.rs index 58d5bf114cca..6ad6a06f11ae 100644 --- a/crates/ide-completion/src/completions/pattern.rs +++ b/crates/ide-completion/src/completions/pattern.rs @@ -58,6 +58,7 @@ pub(crate) fn complete_pattern( |acc, ctx, variant, path| { acc.add_qualified_variant_pat(ctx, pattern_ctx, variant, path); }, + Some(pattern_ctx.missing_variants.clone()), ); } } diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs index aa77f449530e..954e88e093e1 100644 --- a/crates/ide-completion/src/context.rs +++ b/crates/ide-completion/src/context.rs @@ -220,6 +220,8 @@ pub(super) struct PatternContext { /// The record pattern this name or ref is a field of pub(super) record_pat: Option, pub(super) impl_: Option, + /// List of missing variants in a match expr + pub(super) missing_variants: Vec, } #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index c142a7305f9e..73375250b5fe 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -1,7 +1,7 @@ //! Module responsible for analyzing the code surrounding the cursor for completion. use std::iter; -use hir::{Semantics, Type, TypeInfo}; +use hir::{Semantics, Type, TypeInfo, Variant}; use ide_db::{active_parameter::ActiveParameter, RootDatabase}; use syntax::{ algo::{find_node_at_offset, non_trivia_sibling}, @@ -1111,6 +1111,9 @@ fn pattern_context_for( pat: ast::Pat, ) -> PatternContext { let mut param_ctx = None; + + let mut missing_variants = vec![]; + let (refutability, has_type_ascription) = pat .syntax() @@ -1140,7 +1143,52 @@ fn pattern_context_for( })(); return (PatternRefutability::Irrefutable, has_type_ascription) }, - ast::MatchArm(_) => PatternRefutability::Refutable, + ast::MatchArm(match_arm) => { + let missing_variants_opt = match_arm + .syntax() + .parent() + .and_then(ast::MatchArmList::cast) + .and_then(|match_arm_list| { + match_arm_list + .syntax() + .parent() + .and_then(ast::MatchExpr::cast) + .and_then(|match_expr| { + let expr_opt = find_opt_node_in_file(&original_file, match_expr.expr()); + + expr_opt.and_then(|expr| { + sema.type_of_expr(&expr)? + .adjusted() + .autoderef(sema.db) + .find_map(|ty| match ty.as_adt() { + Some(hir::Adt::Enum(e)) => Some(e), + _ => None, + }).and_then(|enum_| { + Some(enum_.variants(sema.db)) + }) + }) + }).and_then(|variants| { + Some(variants.iter().filter_map(|variant| { + let variant_name = variant.name(sema.db).to_string(); + + let variant_already_present = match_arm_list.arms().any(|arm| { + arm.pat().and_then(|pat| { + let pat_already_present = pat.syntax().to_string().contains(&variant_name); + pat_already_present.then(|| pat_already_present) + }).is_some() + }); + + (!variant_already_present).then_some(variant.clone()) + }).collect::>()) + }) + }); + + if let Some(missing_variants_) = missing_variants_opt { + missing_variants = missing_variants_; + }; + + PatternRefutability::Refutable + }, ast::LetExpr(_) => PatternRefutability::Refutable, ast::ForExpr(_) => PatternRefutability::Irrefutable, _ => PatternRefutability::Irrefutable, @@ -1162,6 +1210,7 @@ fn pattern_context_for( ref_token, record_pat: None, impl_: fetch_immediate_impl(sema, original_file, pat.syntax()), + missing_variants, } } diff --git a/crates/ide-completion/src/render/pattern.rs b/crates/ide-completion/src/render/pattern.rs index edb727b57d2b..9cf766ce66c5 100644 --- a/crates/ide-completion/src/render/pattern.rs +++ b/crates/ide-completion/src/render/pattern.rs @@ -38,7 +38,7 @@ pub(crate) fn render_struct_pat( let lookup = format_literal_lookup(name.as_str(), kind); let pat = render_pat(&ctx, pattern_ctx, &escaped_name, kind, &visible_fields, fields_omitted)?; - Some(build_completion(ctx, label, lookup, pat, strukt, false)) + Some(build_completion(ctx, label, lookup, pat, strukt, true)) } pub(crate) fn render_variant_pat( diff --git a/crates/ide-completion/src/tests/record.rs b/crates/ide-completion/src/tests/record.rs index 328faaa060f0..8b8c56d1d5a7 100644 --- a/crates/ide-completion/src/tests/record.rs +++ b/crates/ide-completion/src/tests/record.rs @@ -46,6 +46,47 @@ fn foo(s: Struct) { ); } +#[test] +fn record_pattern_field_enum() { + check( + r#" +enum Baz { FOO, BAR } + +fn foo(baz: Baz) { + match baz { + Baz::FOO => (), + $0 + } +} +"#, + expect![[r#" + en Baz + bn Baz::BAR Baz::BAR$0 + kw mut + kw ref + "#]], + ); + + check( + r#" +enum Baz { FOO, BAR } + +fn foo(baz: Baz) { + match baz { + FOO => (), + $0 + } +} +"#, + expect![[r#" + en Baz + bn Baz::BAR Baz::BAR$0 + kw mut + kw ref + "#]], + ); +} + #[test] fn pattern_enum_variant() { check( From 77de724f92ab111b9cbf48b968552a974168d983 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Mon, 20 Feb 2023 09:45:55 +0000 Subject: [PATCH 003/116] Distribute libntdll.a with windows-gnu toolchains This allows loading some essential functions (e.g. read/write file) at load time instead of lazily. --- library/std/src/sys/windows/c.rs | 87 +++++++++++++++----------------- src/bootstrap/dist.rs | 1 + 2 files changed, 41 insertions(+), 47 deletions(-) diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index f58dcf1287be..15ffa257d572 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -287,7 +287,6 @@ pub const STATUS_INVALID_PARAMETER: NTSTATUS = 0xc000000d_u32 as _; pub const STATUS_PENDING: NTSTATUS = 0x103 as _; pub const STATUS_END_OF_FILE: NTSTATUS = 0xC0000011_u32 as _; -pub const STATUS_NOT_IMPLEMENTED: NTSTATUS = 0xC0000002_u32 as _; // Equivalent to the `NT_SUCCESS` C preprocessor macro. // See: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values @@ -1262,6 +1261,46 @@ extern "system" { ) -> NTSTATUS; } +#[link(name = "ntdll")] +extern "system" { + pub fn NtCreateFile( + FileHandle: *mut HANDLE, + DesiredAccess: ACCESS_MASK, + ObjectAttributes: *const OBJECT_ATTRIBUTES, + IoStatusBlock: *mut IO_STATUS_BLOCK, + AllocationSize: *mut i64, + FileAttributes: ULONG, + ShareAccess: ULONG, + CreateDisposition: ULONG, + CreateOptions: ULONG, + EaBuffer: *mut c_void, + EaLength: ULONG, + ) -> NTSTATUS; + pub fn NtReadFile( + FileHandle: BorrowedHandle<'_>, + Event: HANDLE, + ApcRoutine: Option, + ApcContext: *mut c_void, + IoStatusBlock: &mut IO_STATUS_BLOCK, + Buffer: *mut crate::mem::MaybeUninit, + Length: ULONG, + ByteOffset: Option<&LARGE_INTEGER>, + Key: Option<&ULONG>, + ) -> NTSTATUS; + pub fn NtWriteFile( + FileHandle: BorrowedHandle<'_>, + Event: HANDLE, + ApcRoutine: Option, + ApcContext: *mut c_void, + IoStatusBlock: &mut IO_STATUS_BLOCK, + Buffer: *const u8, + Length: ULONG, + ByteOffset: Option<&LARGE_INTEGER>, + Key: Option<&ULONG>, + ) -> NTSTATUS; + pub fn RtlNtStatusToDosError(Status: NTSTATUS) -> ULONG; +} + // Functions that aren't available on every version of Windows that we support, // but we still use them and just provide some form of a fallback implementation. compat_fn_with_fallback! { @@ -1302,52 +1341,6 @@ compat_fn_optional! { compat_fn_with_fallback! { pub static NTDLL: &CStr = ansi_str!("ntdll"); - pub fn NtCreateFile( - FileHandle: *mut HANDLE, - DesiredAccess: ACCESS_MASK, - ObjectAttributes: *const OBJECT_ATTRIBUTES, - IoStatusBlock: *mut IO_STATUS_BLOCK, - AllocationSize: *mut i64, - FileAttributes: ULONG, - ShareAccess: ULONG, - CreateDisposition: ULONG, - CreateOptions: ULONG, - EaBuffer: *mut c_void, - EaLength: ULONG - ) -> NTSTATUS { - STATUS_NOT_IMPLEMENTED - } - pub fn NtReadFile( - FileHandle: BorrowedHandle<'_>, - Event: HANDLE, - ApcRoutine: Option, - ApcContext: *mut c_void, - IoStatusBlock: &mut IO_STATUS_BLOCK, - Buffer: *mut crate::mem::MaybeUninit, - Length: ULONG, - ByteOffset: Option<&LARGE_INTEGER>, - Key: Option<&ULONG> - ) -> NTSTATUS { - STATUS_NOT_IMPLEMENTED - } - pub fn NtWriteFile( - FileHandle: BorrowedHandle<'_>, - Event: HANDLE, - ApcRoutine: Option, - ApcContext: *mut c_void, - IoStatusBlock: &mut IO_STATUS_BLOCK, - Buffer: *const u8, - Length: ULONG, - ByteOffset: Option<&LARGE_INTEGER>, - Key: Option<&ULONG> - ) -> NTSTATUS { - STATUS_NOT_IMPLEMENTED - } - pub fn RtlNtStatusToDosError( - Status: NTSTATUS - ) -> ULONG { - Status as ULONG - } pub fn NtCreateKeyedEvent( KeyedEventHandle: LPHANDLE, DesiredAccess: ACCESS_MASK, diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 9b2b549612d8..c7c967b3e2e6 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -234,6 +234,7 @@ fn make_win_dist( "libkernel32.a", "libmsimg32.a", "libmsvcrt.a", + "libntdll.a", "libodbc32.a", "libole32.a", "liboleaut32.a", From 8123eb49d4f222c84e243f18e77d01ba44aad578 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Mon, 20 Feb 2023 10:41:26 +0000 Subject: [PATCH 004/116] Move `NtWriteFile` miri shim to `foreign_items` --- src/tools/miri/src/shims/windows/dlsym.rs | 69 ------------------- .../miri/src/shims/windows/foreign_items.rs | 68 ++++++++++++++++++ 2 files changed, 68 insertions(+), 69 deletions(-) diff --git a/src/tools/miri/src/shims/windows/dlsym.rs b/src/tools/miri/src/shims/windows/dlsym.rs index 60dd299c4381..7e2051fc98a0 100644 --- a/src/tools/miri/src/shims/windows/dlsym.rs +++ b/src/tools/miri/src/shims/windows/dlsym.rs @@ -1,5 +1,4 @@ use rustc_middle::mir; -use rustc_target::abi::Size; use rustc_target::spec::abi::Abi; use log::trace; @@ -11,7 +10,6 @@ use crate::*; #[derive(Debug, Copy, Clone)] pub enum Dlsym { - NtWriteFile, SetThreadDescription, WaitOnAddress, WakeByAddressSingle, @@ -23,7 +21,6 @@ impl Dlsym { pub fn from_str<'tcx>(name: &str) -> InterpResult<'tcx, Option> { Ok(match name { "GetSystemTimePreciseAsFileTime" => None, - "NtWriteFile" => Some(Dlsym::NtWriteFile), "SetThreadDescription" => Some(Dlsym::SetThreadDescription), "WaitOnAddress" => Some(Dlsym::WaitOnAddress), "WakeByAddressSingle" => Some(Dlsym::WakeByAddressSingle), @@ -49,72 +46,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.check_abi(abi, Abi::System { unwind: false })?; match dlsym { - Dlsym::NtWriteFile => { - if !this.frame_in_std() { - throw_unsup_format!( - "`NtWriteFile` support is crude and just enough for stdout to work" - ); - } - - let [ - handle, - _event, - _apc_routine, - _apc_context, - io_status_block, - buf, - n, - byte_offset, - _key, - ] = check_arg_count(args)?; - let handle = this.read_target_isize(handle)?; - let buf = this.read_pointer(buf)?; - let n = this.read_scalar(n)?.to_u32()?; - let byte_offset = this.read_target_usize(byte_offset)?; // is actually a pointer - let io_status_block = this.deref_operand(io_status_block)?; - - if byte_offset != 0 { - throw_unsup_format!( - "`NtWriteFile` `ByteOffset` paremeter is non-null, which is unsupported" - ); - } - - let written = if handle == -11 || handle == -12 { - // stdout/stderr - use std::io::{self, Write}; - - let buf_cont = - this.read_bytes_ptr_strip_provenance(buf, Size::from_bytes(u64::from(n)))?; - let res = if this.machine.mute_stdout_stderr { - Ok(buf_cont.len()) - } else if handle == -11 { - io::stdout().write(buf_cont) - } else { - io::stderr().write(buf_cont) - }; - // We write at most `n` bytes, which is a `u32`, so we cannot have written more than that. - res.ok().map(|n| u32::try_from(n).unwrap()) - } else { - throw_unsup_format!( - "on Windows, writing to anything except stdout/stderr is not supported" - ) - }; - // We have to put the result into io_status_block. - if let Some(n) = written { - let io_status_information = - this.mplace_field_named(&io_status_block, "Information")?; - this.write_scalar( - Scalar::from_target_usize(n.into(), this), - &io_status_information.into(), - )?; - } - // Return whether this was a success. >= 0 is success. - // For the error code we arbitrarily pick 0xC0000185, STATUS_IO_DEVICE_ERROR. - this.write_scalar( - Scalar::from_u32(if written.is_some() { 0 } else { 0xC0000185u32 }), - dest, - )?; - } Dlsym::SetThreadDescription => { let [handle, name] = check_arg_count(args)?; diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index a3d7176a9768..665c7ed438f3 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -69,6 +69,74 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(result, dest)?; } + // File related shims + "NtWriteFile" => { + if !this.frame_in_std() { + throw_unsup_format!( + "`NtWriteFile` support is crude and just enough for stdout to work" + ); + } + + let [ + handle, + _event, + _apc_routine, + _apc_context, + io_status_block, + buf, + n, + byte_offset, + _key, + ] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + let handle = this.read_target_isize(handle)?; + let buf = this.read_pointer(buf)?; + let n = this.read_scalar(n)?.to_u32()?; + let byte_offset = this.read_target_usize(byte_offset)?; // is actually a pointer + let io_status_block = this.deref_operand(io_status_block)?; + + if byte_offset != 0 { + throw_unsup_format!( + "`NtWriteFile` `ByteOffset` paremeter is non-null, which is unsupported" + ); + } + + let written = if handle == -11 || handle == -12 { + // stdout/stderr + use std::io::{self, Write}; + + let buf_cont = + this.read_bytes_ptr_strip_provenance(buf, Size::from_bytes(u64::from(n)))?; + let res = if this.machine.mute_stdout_stderr { + Ok(buf_cont.len()) + } else if handle == -11 { + io::stdout().write(buf_cont) + } else { + io::stderr().write(buf_cont) + }; + // We write at most `n` bytes, which is a `u32`, so we cannot have written more than that. + res.ok().map(|n| u32::try_from(n).unwrap()) + } else { + throw_unsup_format!( + "on Windows, writing to anything except stdout/stderr is not supported" + ) + }; + // We have to put the result into io_status_block. + if let Some(n) = written { + let io_status_information = + this.mplace_field_named(&io_status_block, "Information")?; + this.write_scalar( + Scalar::from_target_usize(n.into(), this), + &io_status_information.into(), + )?; + } + // Return whether this was a success. >= 0 is success. + // For the error code we arbitrarily pick 0xC0000185, STATUS_IO_DEVICE_ERROR. + this.write_scalar( + Scalar::from_u32(if written.is_some() { 0 } else { 0xC0000185u32 }), + dest, + )?; + } + // Allocation "HeapAlloc" => { let [handle, flags, size] = From b69de642026176f89c52e36f0b2f52cb0777456a Mon Sep 17 00:00:00 2001 From: Tobias Decking Date: Sat, 4 Mar 2023 00:10:52 +0100 Subject: [PATCH 005/116] Add inlining annotations --- library/core/src/num/dec2flt/common.rs | 1 + library/core/src/num/dec2flt/float.rs | 4 ++++ library/core/src/num/dec2flt/lemire.rs | 2 ++ library/core/src/num/dec2flt/mod.rs | 11 ++++++++++- library/core/src/num/dec2flt/number.rs | 1 + 5 files changed, 18 insertions(+), 1 deletion(-) diff --git a/library/core/src/num/dec2flt/common.rs b/library/core/src/num/dec2flt/common.rs index 17957d7e7704..3e8d75df3786 100644 --- a/library/core/src/num/dec2flt/common.rs +++ b/library/core/src/num/dec2flt/common.rs @@ -192,6 +192,7 @@ pub struct BiasedFp { } impl BiasedFp { + #[inline] pub const fn zero_pow2(e: i32) -> Self { Self { f: 0, e } } diff --git a/library/core/src/num/dec2flt/float.rs b/library/core/src/num/dec2flt/float.rs index 5921c5ed4725..1c9d68999d6f 100644 --- a/library/core/src/num/dec2flt/float.rs +++ b/library/core/src/num/dec2flt/float.rs @@ -118,11 +118,13 @@ impl RawFloat for f32 { const SMALLEST_POWER_OF_TEN: i32 = -65; const LARGEST_POWER_OF_TEN: i32 = 38; + #[inline] fn from_u64(v: u64) -> Self { debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH); v as _ } + #[inline] fn from_u64_bits(v: u64) -> Self { f32::from_bits((v & 0xFFFFFFFF) as u32) } @@ -169,11 +171,13 @@ impl RawFloat for f64 { const SMALLEST_POWER_OF_TEN: i32 = -342; const LARGEST_POWER_OF_TEN: i32 = 308; + #[inline] fn from_u64(v: u64) -> Self { debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH); v as _ } + #[inline] fn from_u64_bits(v: u64) -> Self { f64::from_bits(v) } diff --git a/library/core/src/num/dec2flt/lemire.rs b/library/core/src/num/dec2flt/lemire.rs index 9f7594460a1d..3bc052df7a6c 100644 --- a/library/core/src/num/dec2flt/lemire.rs +++ b/library/core/src/num/dec2flt/lemire.rs @@ -118,10 +118,12 @@ pub fn compute_float(q: i64, mut w: u64) -> BiasedFp { /// This uses a pre-computed integer approximation for /// log2(10), where 217706 / 2^16 is accurate for the /// entire range of non-finite decimal exponents. +#[inline] fn power(q: i32) -> i32 { (q.wrapping_mul(152_170 + 65536) >> 16) + 63 } +#[inline] fn full_multiplication(a: u64, b: u64) -> (u64, u64) { let r = (a as u128) * (b as u128); (r as u64, (r >> 64) as u64) diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs index f8d493e8b627..e9fe65716863 100644 --- a/library/core/src/num/dec2flt/mod.rs +++ b/library/core/src/num/dec2flt/mod.rs @@ -147,7 +147,13 @@ macro_rules! from_str_float_impl { /// representable floating-point number to the number represented /// by `src` (following the same rules for rounding as for the /// results of primitive operations). - #[inline] + // We add the `#[inline(never)]` attribute, since its content will + // be filled with that of `dec2flt`, which has #[inline(always)]. + // Since `dec2flt` is generic, a normal inline attribute on this function + // with `dec2flt` having no attributes results in heavily repeated + // generation of `dec2flt`, despite the fact only a maximum of 2 + // posiible instances. Adding #[inline(never)] avoids this. + #[inline(never)] fn from_str(src: &str) -> Result { dec2flt(src) } @@ -202,12 +208,14 @@ impl fmt::Display for ParseFloatError { } } +#[inline] pub(super) fn pfe_empty() -> ParseFloatError { ParseFloatError { kind: FloatErrorKind::Empty } } // Used in unit tests, keep public. // This is much better than making FloatErrorKind and ParseFloatError::kind public. +#[inline] pub fn pfe_invalid() -> ParseFloatError { ParseFloatError { kind: FloatErrorKind::Invalid } } @@ -220,6 +228,7 @@ fn biased_fp_to_float(x: BiasedFp) -> T { } /// Converts a decimal string into a floating point number. +#[inline(always)] // Will be inlined into a function with `#[inline(never)]`, see above pub fn dec2flt(s: &str) -> Result { let mut s = s.as_bytes(); let c = if let Some(&c) = s.first() { diff --git a/library/core/src/num/dec2flt/number.rs b/library/core/src/num/dec2flt/number.rs index 405f7e7b6135..8589e2bbd4fa 100644 --- a/library/core/src/num/dec2flt/number.rs +++ b/library/core/src/num/dec2flt/number.rs @@ -33,6 +33,7 @@ pub struct Number { impl Number { /// Detect if the float can be accurately reconstructed from native floats. + #[inline] fn is_fast_path(&self) -> bool { F::MIN_EXPONENT_FAST_PATH <= self.exponent && self.exponent <= F::MAX_EXPONENT_DISGUISED_FAST_PATH From dd45f01411122cb9a5c2c179776c882c006329e3 Mon Sep 17 00:00:00 2001 From: Tobias Decking Date: Sat, 4 Mar 2023 00:23:50 +0100 Subject: [PATCH 006/116] typo --- library/core/src/num/dec2flt/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs index e9fe65716863..e0c73ef0eee3 100644 --- a/library/core/src/num/dec2flt/mod.rs +++ b/library/core/src/num/dec2flt/mod.rs @@ -152,7 +152,7 @@ macro_rules! from_str_float_impl { // Since `dec2flt` is generic, a normal inline attribute on this function // with `dec2flt` having no attributes results in heavily repeated // generation of `dec2flt`, despite the fact only a maximum of 2 - // posiible instances. Adding #[inline(never)] avoids this. + // possible instances. Adding #[inline(never)] avoids this. #[inline(never)] fn from_str(src: &str) -> Result { dec2flt(src) From db2c6e0385352743c94eb48416b5e486380eaac3 Mon Sep 17 00:00:00 2001 From: Tobias Decking Date: Sat, 4 Mar 2023 00:31:17 +0100 Subject: [PATCH 007/116] Update comment. --- library/core/src/num/dec2flt/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs index e0c73ef0eee3..58ffb950ad86 100644 --- a/library/core/src/num/dec2flt/mod.rs +++ b/library/core/src/num/dec2flt/mod.rs @@ -152,7 +152,7 @@ macro_rules! from_str_float_impl { // Since `dec2flt` is generic, a normal inline attribute on this function // with `dec2flt` having no attributes results in heavily repeated // generation of `dec2flt`, despite the fact only a maximum of 2 - // possible instances. Adding #[inline(never)] avoids this. + // possible instances can ever exist. Adding #[inline(never)] avoids this. #[inline(never)] fn from_str(src: &str) -> Result { dec2flt(src) From b44b50a0f743eed29925d68deb2ae87931668bc2 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sat, 4 Mar 2023 18:37:14 +0000 Subject: [PATCH 008/116] Add comment on what libs should be in target_libs --- src/bootstrap/dist.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index c7c967b3e2e6..38f25bc6331d 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -208,6 +208,8 @@ fn make_win_dist( rustc_dlls.push("libgcc_s_seh-1.dll"); } + // Libraries necessary to link the windows-gnu toolchains. + // System libraries will be preferred if they are available (see #67429). let target_libs = [ //MinGW libs "libgcc.a", @@ -221,6 +223,7 @@ fn make_win_dist( "libmoldname.a", "libpthread.a", //Windows import libs + //This should contain only the set of libraries necessary to link the standard library. "libadvapi32.a", "libbcrypt.a", "libcomctl32.a", From 7650bd15d5f16130e0ea098dbbc444d2b833c9dd Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Fri, 16 Dec 2022 19:39:19 +0100 Subject: [PATCH 009/116] Add cpass to incremental tests --- src/tools/compiletest/src/runtest.rs | 50 +++++++++++++++++++--------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 41c23ff86b25..ad3d1bddef04 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -278,13 +278,15 @@ impl<'test> TestCx<'test> { Incremental => { let revision = self.revision.expect("incremental tests require a list of revisions"); - if revision.starts_with("rpass") || revision.starts_with("rfail") { + if revision.starts_with("cpass") + || revision.starts_with("rpass") + || revision.starts_with("rfail") + { true } else if revision.starts_with("cfail") { - // FIXME: would be nice if incremental revs could start with "cpass" pm.is_some() } else { - panic!("revision name must begin with rpass, rfail, or cfail"); + panic!("revision name must begin with cpass, rpass, rfail, or cfail"); } } mode => panic!("unimplemented for mode {:?}", mode), @@ -384,6 +386,20 @@ impl<'test> TestCx<'test> { } } + fn run_cpass_test(&self) { + let emit_metadata = self.should_emit_metadata(self.pass_mode()); + let proc_res = self.compile_test(WillExecute::No, emit_metadata); + + if !proc_res.status.success() { + self.fatal_proc_rec("compilation failed!", &proc_res); + } + + // FIXME(#41968): Move this check to tidy? + if !errors::load_errors(&self.testpaths.file, self.revision).is_empty() { + self.fatal("compile-pass tests with expected warnings should be moved to ui/"); + } + } + fn run_rpass_test(&self) { let emit_metadata = self.should_emit_metadata(self.pass_mode()); let should_run = self.run_if_enabled(); @@ -393,17 +409,15 @@ impl<'test> TestCx<'test> { self.fatal_proc_rec("compilation failed!", &proc_res); } + // FIXME(#41968): Move this check to tidy? + if !errors::load_errors(&self.testpaths.file, self.revision).is_empty() { + self.fatal("run-pass tests with expected warnings should be moved to ui/"); + } + if let WillExecute::Disabled = should_run { return; } - // FIXME(#41968): Move this check to tidy? - let expected_errors = errors::load_errors(&self.testpaths.file, self.revision); - assert!( - expected_errors.is_empty(), - "run-pass tests with expected warnings should be moved to ui/" - ); - let proc_res = self.exec_compiled_test(); if !proc_res.status.success() { self.fatal_proc_rec("test run failed!", &proc_res); @@ -2903,10 +2917,11 @@ impl<'test> TestCx<'test> { fn run_incremental_test(&self) { // Basic plan for a test incremental/foo/bar.rs: // - load list of revisions rpass1, cfail2, rpass3 - // - each should begin with `rpass`, `cfail`, or `rfail` - // - if `rpass`, expect compile and execution to succeed + // - each should begin with `cpass`, `rpass`, `cfail`, or `rfail` + // - if `cpass`, expect compilation to succeed, don't execute + // - if `rpass`, expect compilation and execution to succeed // - if `cfail`, expect compilation to fail - // - if `rfail`, expect execution to fail + // - if `rfail`, expect compilation to succeed and execution to fail // - create a directory build/foo/bar.incremental // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass1 // - because name of revision starts with "rpass", expect success @@ -2930,7 +2945,12 @@ impl<'test> TestCx<'test> { print!("revision={:?} props={:#?}", revision, self.props); } - if revision.starts_with("rpass") { + if revision.starts_with("cpass") { + if self.props.should_ice { + self.fatal("can only use should-ice in cfail tests"); + } + self.run_cpass_test(); + } else if revision.starts_with("rpass") { if self.props.should_ice { self.fatal("can only use should-ice in cfail tests"); } @@ -2943,7 +2963,7 @@ impl<'test> TestCx<'test> { } else if revision.starts_with("cfail") { self.run_cfail_test(); } else { - self.fatal("revision name must begin with rpass, rfail, or cfail"); + self.fatal("revision name must begin with cpass, rpass, rfail, or cfail"); } } From 97915ab943001b5a74df4b3e22e7c0a469433fb9 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Fri, 16 Dec 2022 19:42:53 +0100 Subject: [PATCH 010/116] Add note for mismatched types with circular dependencies --- .../src/infer/error_reporting/mod.rs | 21 +++++++---- .../auxiliary/circular-dependencies-aux.rs | 10 +++++ tests/incremental/circular-dependencies.rs | 37 +++++++++++++++++++ 3 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 tests/incremental/auxiliary/circular-dependencies-aux.rs create mode 100644 tests/incremental/circular-dependencies.rs diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 8a2b800af0e8..7ce6bd418ebe 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -613,9 +613,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } let report_path_match = |err: &mut Diagnostic, did1: DefId, did2: DefId| { - // Only external crates, if either is from a local - // module we could have false positives - if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate { + // Only report definitions from different crates. If both definitions + // are from a local module we could have false positives, e.g. + // let _ = [{struct Foo; Foo}, {struct Foo; Foo}]; + if did1.krate != did2.krate { let abs_path = |def_id| AbsolutePathPrinter { tcx: self.tcx }.print_def_path(def_id, &[]); @@ -627,10 +628,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { }; if same_path().unwrap_or(false) { let crate_name = self.tcx.crate_name(did1.krate); - err.note(&format!( - "perhaps two different versions of crate `{}` are being used?", - crate_name - )); + let msg = if did1.is_local() || did2.is_local() { + format!( + "the crate `{crate_name}` is compiled multiple times, possibly with different configurations" + ) + } else { + format!( + "perhaps two different versions of crate `{crate_name}` are being used?" + ) + }; + err.note(msg); } } }; diff --git a/tests/incremental/auxiliary/circular-dependencies-aux.rs b/tests/incremental/auxiliary/circular-dependencies-aux.rs new file mode 100644 index 000000000000..0e74eb1b2f26 --- /dev/null +++ b/tests/incremental/auxiliary/circular-dependencies-aux.rs @@ -0,0 +1,10 @@ +// edition: 2021 +// compile-flags: --crate-type lib --extern circular_dependencies={{build-base}}/circular-dependencies/libcircular_dependencies.rmeta --emit dep-info,metadata + +use circular_dependencies::Foo; + +pub fn consume_foo(_: Foo) {} + +pub fn produce_foo() -> Foo { + Foo +} diff --git a/tests/incremental/circular-dependencies.rs b/tests/incremental/circular-dependencies.rs new file mode 100644 index 000000000000..10673066a9df --- /dev/null +++ b/tests/incremental/circular-dependencies.rs @@ -0,0 +1,37 @@ +// ignore-tidy-linelength +// revisions: cpass1 cfail2 +// edition: 2021 +// [cpass1] compile-flags: --crate-type lib --emit dep-info,metadata +// [cfail2] aux-build: circular-dependencies-aux.rs +// [cfail2] compile-flags: --test --extern aux={{build-base}}/circular-dependencies/auxiliary/libcircular_dependencies_aux.rmeta -L dependency={{build-base}}/circular-dependencies + +pub struct Foo; +//[cfail2]~^ NOTE `Foo` is defined in the current crate +//[cfail2]~| NOTE `Foo` is defined in the current crate +//[cfail2]~| NOTE `circular_dependencies::Foo` is defined in crate `circular_dependencies` +//[cfail2]~| NOTE `circular_dependencies::Foo` is defined in crate `circular_dependencies` + +pub fn consume_foo(_: Foo) {} +//[cfail2]~^ NOTE function defined here + +pub fn produce_foo() -> Foo { + Foo +} + +#[test] +fn test() { + aux::consume_foo(produce_foo()); + //[cfail2]~^ ERROR mismatched types [E0308] + //[cfail2]~| NOTE expected `circular_dependencies::Foo`, found `Foo` + //[cfail2]~| NOTE arguments to this function are incorrect + //[cfail2]~| NOTE `Foo` and `circular_dependencies::Foo` have similar names, but are actually distinct types + //[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations + //[cfail2]~| NOTE function defined here + + consume_foo(aux::produce_foo()); + //[cfail2]~^ ERROR mismatched types [E0308] + //[cfail2]~| NOTE expected `Foo`, found `circular_dependencies::Foo` + //[cfail2]~| NOTE arguments to this function are incorrect + //[cfail2]~| NOTE `circular_dependencies::Foo` and `Foo` have similar names, but are actually distinct types + //[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations +} From dfe4c49e9b8f724d43328eee46b733f65d3d5b25 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Mon, 6 Mar 2023 21:11:01 +0100 Subject: [PATCH 011/116] Use Edition 2021 :pat in matches macro This makes the macro syntax used in documentation more readable. --- library/core/src/macros/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 3b026bc0e0f3..529f62f4d6cd 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -340,9 +340,9 @@ pub macro debug_assert_matches($($arg:tt)*) { #[stable(feature = "matches_macro", since = "1.42.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "matches_macro")] macro_rules! matches { - ($expression:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => { + ($expression:expr, $pattern:pat $(if $guard:expr)? $(,)?) => { match $expression { - $( $pattern )|+ $( if $guard )? => true, + $pattern $(if $guard)? => true, _ => false } }; From c21f1d09de3a6a7bb4952f400919e936032b8ee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 11 Mar 2023 00:00:00 +0000 Subject: [PATCH 012/116] read_buf_exact: on error, all read bytes are appended to the buffer Guarantee that when `read_buf_exact` returns, all bytes read will be appended to the buffer. Including the case when the operations fails. The motivating use case are operations on a non-blocking reader. When `read_buf_exact` fails with `ErrorKind::WouldBlock` error, the operation can be resumed at a later time. --- library/std/src/io/mod.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index b2b6d86134b6..4b31c552eedd 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -823,8 +823,22 @@ pub trait Read { /// Read the exact number of bytes required to fill `cursor`. /// - /// This is equivalent to the [`read_exact`](Read::read_exact) method, except that it is passed a [`BorrowedCursor`] rather than `[u8]` to - /// allow use with uninitialized buffers. + /// This is similar to the [`read_exact`](Read::read_exact) method, except + /// that it is passed a [`BorrowedCursor`] rather than `[u8]` to allow use + /// with uninitialized buffers. + /// + /// # Errors + /// + /// If this function encounters an error of the kind [`ErrorKind::Interrupted`] + /// then the error is ignored and the operation will continue. + /// + /// If this function encounters an "end of file" before completely filling + /// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`]. + /// + /// If any other read error is encountered then this function immediately + /// returns. + /// + /// If this function returns an error, all bytes read will be appended to `cursor`. #[unstable(feature = "read_buf", issue = "78485")] fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_>) -> Result<()> { while cursor.capacity() > 0 { From 8dd0f20ee65883d12775ae4d552596b815ac9977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 27 Feb 2023 05:56:48 +0100 Subject: [PATCH 013/116] Optimize dep node backtrace and ignore fatal errors --- .../rustc_query_system/src/dep_graph/graph.rs | 90 +++++++++---------- .../rustc_query_system/src/dep_graph/mod.rs | 23 ++++- 2 files changed, 63 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 8a9a12386064..5604da469621 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -6,7 +6,6 @@ use rustc_data_structures::sharded::{self, Sharded}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc, Ordering}; -use rustc_data_structures::OnDrop; use rustc_index::vec::IndexVec; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use smallvec::{smallvec, SmallVec}; @@ -54,6 +53,11 @@ impl From for QueryInvocationId { } } +pub struct MarkFrame<'a> { + index: SerializedDepNodeIndex, + parent: Option<&'a MarkFrame<'a>>, +} + #[derive(PartialEq)] pub enum DepNodeColor { Red, @@ -710,32 +714,26 @@ impl DepGraphData { let prev_index = self.previous.node_to_index_opt(dep_node)?; match self.colors.get(prev_index) { - Some(DepNodeColor::Green(dep_node_index)) => return Some((prev_index, dep_node_index)), - Some(DepNodeColor::Red) => return None, - None => {} + Some(DepNodeColor::Green(dep_node_index)) => Some((prev_index, dep_node_index)), + Some(DepNodeColor::Red) => None, + None => { + // This DepNode and the corresponding query invocation existed + // in the previous compilation session too, so we can try to + // mark it as green by recursively marking all of its + // dependencies green. + self.try_mark_previous_green(qcx, prev_index, &dep_node, None) + .map(|dep_node_index| (prev_index, dep_node_index)) + } } - - let backtrace = backtrace_printer(qcx.dep_context().sess(), self, prev_index); - - // This DepNode and the corresponding query invocation existed - // in the previous compilation session too, so we can try to - // mark it as green by recursively marking all of its - // dependencies green. - let ret = self - .try_mark_previous_green(qcx, prev_index, &dep_node) - .map(|dep_node_index| (prev_index, dep_node_index)); - - // We succeeded, no backtrace. - backtrace.disable(); - return ret; } - #[instrument(skip(self, qcx, parent_dep_node_index), level = "debug")] + #[instrument(skip(self, qcx, parent_dep_node_index, frame), level = "debug")] fn try_mark_parent_green>( &self, qcx: Qcx, parent_dep_node_index: SerializedDepNodeIndex, dep_node: &DepNode, + frame: Option<&MarkFrame<'_>>, ) -> Option<()> { let dep_dep_node_color = self.colors.get(parent_dep_node_index); let dep_dep_node = &self.previous.index_to_node(parent_dep_node_index); @@ -767,7 +765,8 @@ impl DepGraphData { dep_dep_node, dep_dep_node.hash, ); - let node_index = self.try_mark_previous_green(qcx, parent_dep_node_index, dep_dep_node); + let node_index = + self.try_mark_previous_green(qcx, parent_dep_node_index, dep_dep_node, frame); if node_index.is_some() { debug!("managed to MARK dependency {dep_dep_node:?} as green",); @@ -777,7 +776,7 @@ impl DepGraphData { // We failed to mark it green, so we try to force the query. debug!("trying to force dependency {dep_dep_node:?}"); - if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node) { + if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node, data, frame) { // The DepNode could not be forced. debug!("dependency {dep_dep_node:?} could not be forced"); return None; @@ -816,13 +815,16 @@ impl DepGraphData { } /// Try to mark a dep-node which existed in the previous compilation session as green. - #[instrument(skip(self, qcx, prev_dep_node_index), level = "debug")] + #[instrument(skip(self, qcx, prev_dep_node_index, frame), level = "debug")] fn try_mark_previous_green>( &self, qcx: Qcx, prev_dep_node_index: SerializedDepNodeIndex, dep_node: &DepNode, + frame: Option<&MarkFrame<'_>>, ) -> Option { + let frame = MarkFrame { index: prev_dep_node_index, parent: frame }; + #[cfg(not(parallel_compiler))] { debug_assert!(!self.dep_node_exists(dep_node)); @@ -837,10 +839,7 @@ impl DepGraphData { let prev_deps = self.previous.edge_targets_from(prev_dep_node_index); for &dep_dep_node_index in prev_deps { - let backtrace = backtrace_printer(qcx.dep_context().sess(), self, dep_dep_node_index); - let success = self.try_mark_parent_green(qcx, dep_dep_node_index, dep_node); - backtrace.disable(); - success?; + self.try_mark_parent_green(qcx, dep_dep_node_index, dep_node, Some(&frame))?; } // If we got here without hitting a `return` that means that all @@ -1414,25 +1413,24 @@ impl DepNodeColorMap { } } -fn backtrace_printer<'a, K: DepKind>( - sess: &'a rustc_session::Session, - graph: &'a DepGraphData, - node: SerializedDepNodeIndex, -) -> OnDrop { - OnDrop( - #[inline(never)] - #[cold] - move || { - let node = graph.previous.index_to_node(node); +#[inline(never)] +#[cold] +pub(crate) fn print_markframe_trace( + graph: &DepGraphData, + frame: Option<&MarkFrame<'_>>, +) { + eprintln!("there was a panic while trying to force a dep node"); + eprintln!("try_mark_green dep node stack:"); + + let mut i = 0; + let mut current = frame; + while let Some(frame) = current { // Do not try to rely on DepNode's Debug implementation, since it may panic. - let diag = rustc_errors::Diagnostic::new( - rustc_errors::Level::FailureNote, - &format!( - "encountered while trying to mark dependency green: {:?}({})", - node.kind, node.hash - ), - ); - sess.diagnostic().force_print_diagnostic(diag); - }, - ) + let node = graph.previous.index_to_node(frame.index); + eprintln!("#{i} {:?} ({})", node.kind, node.hash); + current = frame.parent; + i += 1; + } + + eprintln!("end of try_mark_green dep node stack"); } diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index 5a7b9ae2ab43..f70a91397436 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -17,8 +17,10 @@ use rustc_data_structures::profiling::SelfProfilerRef; use rustc_serialize::{opaque::FileEncoder, Encodable}; use rustc_session::Session; -use std::fmt; use std::hash::Hash; +use std::{fmt, panic}; + +use self::graph::{print_markframe_trace, DepGraphData, MarkFrame}; pub trait DepContext: Copy { type DepKind: self::DepKind; @@ -53,11 +55,24 @@ pub trait DepContext: Copy { } /// Try to force a dep node to execute and see if it's green. - #[instrument(skip(self), level = "debug")] - fn try_force_from_dep_node(self, dep_node: DepNode) -> bool { + #[inline] + #[instrument(skip(self, graph, frame), level = "debug")] + fn try_force_from_dep_node( + self, + dep_node: DepNode, + graph: &DepGraphData, + frame: Option<&MarkFrame<'_>>, + ) -> bool { let cb = self.dep_kind_info(dep_node.kind); if let Some(f) = cb.force_from_dep_node { - f(self, dep_node); + if let Err(value) = panic::catch_unwind(panic::AssertUnwindSafe(|| { + f(self, dep_node); + })) { + if !value.is::() { + print_markframe_trace(graph, frame); + } + panic::resume_unwind(value) + } true } else { false From 867de8bbb87667a721dd409cefc294b0a1c303a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 9 Mar 2023 08:35:01 +0100 Subject: [PATCH 014/116] Remove `graph` parameter from `try_force_from_dep_node` --- compiler/rustc_query_system/src/dep_graph/graph.rs | 8 +++++--- compiler/rustc_query_system/src/dep_graph/mod.rs | 7 +++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 5604da469621..0963e8e8bdfc 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -776,7 +776,7 @@ impl DepGraphData { // We failed to mark it green, so we try to force the query. debug!("trying to force dependency {dep_dep_node:?}"); - if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node, data, frame) { + if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node, frame) { // The DepNode could not be forced. debug!("dependency {dep_dep_node:?} could not be forced"); return None; @@ -1416,9 +1416,11 @@ impl DepNodeColorMap { #[inline(never)] #[cold] pub(crate) fn print_markframe_trace( - graph: &DepGraphData, + graph: &DepGraph, frame: Option<&MarkFrame<'_>>, ) { + let data = graph.data.as_ref().unwrap(); + eprintln!("there was a panic while trying to force a dep node"); eprintln!("try_mark_green dep node stack:"); @@ -1426,7 +1428,7 @@ pub(crate) fn print_markframe_trace( let mut current = frame; while let Some(frame) = current { // Do not try to rely on DepNode's Debug implementation, since it may panic. - let node = graph.previous.index_to_node(frame.index); + let node = data.previous.index_to_node(frame.index); eprintln!("#{i} {:?} ({})", node.kind, node.hash); current = frame.parent; i += 1; diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index f70a91397436..40e7131987fa 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -20,7 +20,7 @@ use rustc_session::Session; use std::hash::Hash; use std::{fmt, panic}; -use self::graph::{print_markframe_trace, DepGraphData, MarkFrame}; +use self::graph::{print_markframe_trace, MarkFrame}; pub trait DepContext: Copy { type DepKind: self::DepKind; @@ -56,11 +56,10 @@ pub trait DepContext: Copy { /// Try to force a dep node to execute and see if it's green. #[inline] - #[instrument(skip(self, graph, frame), level = "debug")] + #[instrument(skip(self, frame), level = "debug")] fn try_force_from_dep_node( self, dep_node: DepNode, - graph: &DepGraphData, frame: Option<&MarkFrame<'_>>, ) -> bool { let cb = self.dep_kind_info(dep_node.kind); @@ -69,7 +68,7 @@ pub trait DepContext: Copy { f(self, dep_node); })) { if !value.is::() { - print_markframe_trace(graph, frame); + print_markframe_trace(self.dep_graph(), frame); } panic::resume_unwind(value) } From f48ff4a2cf440088ef7f8a806190956ad4d38607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 9 Mar 2023 08:37:51 +0100 Subject: [PATCH 015/116] Use `Debug` for formatting the dep nodes --- compiler/rustc_query_system/src/dep_graph/graph.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 0963e8e8bdfc..02cb9c452a8c 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -1427,9 +1427,8 @@ pub(crate) fn print_markframe_trace( let mut i = 0; let mut current = frame; while let Some(frame) = current { - // Do not try to rely on DepNode's Debug implementation, since it may panic. let node = data.previous.index_to_node(frame.index); - eprintln!("#{i} {:?} ({})", node.kind, node.hash); + eprintln!("#{i} {:?}", node); current = frame.parent; i += 1; } From c6da2f9d96a71bee04d194a85ed76edb0259db5b Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 27 Feb 2023 13:07:44 +0000 Subject: [PATCH 016/116] Remove uses of `box_syntax` in rustc and tools --- crates/ide-completion/src/tests/attribute.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ide-completion/src/tests/attribute.rs b/crates/ide-completion/src/tests/attribute.rs index 4e60820dd6d6..c97144b61b6d 100644 --- a/crates/ide-completion/src/tests/attribute.rs +++ b/crates/ide-completion/src/tests/attribute.rs @@ -857,9 +857,9 @@ mod lint { #[test] fn lint_feature() { check_edit( - "box_syntax", + "box_patterns", r#"#[feature(box_$0)] struct Test;"#, - r#"#[feature(box_syntax)] struct Test;"#, + r#"#[feature(box_patterns)] struct Test;"#, ) } From 2df7770d5e8e32728e0add987c65ce8a95fc475d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 10 Mar 2023 22:19:48 +0100 Subject: [PATCH 017/116] Add lint for useless anonymous reexports --- compiler/rustc_lint/messages.ftl | 3 + compiler/rustc_lint/src/lib.rs | 3 + compiler/rustc_lint/src/lints.rs | 7 +++ compiler/rustc_lint/src/reexports.rs | 82 ++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 compiler/rustc_lint/src/reexports.rs diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 68e62c9789ae..1924ae08c393 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -508,3 +508,6 @@ lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its ass .specifically = this associated type bound is unsatisfied for `{$proj_ty}` lint_opaque_hidden_inferred_bound_sugg = add this bound + +lint_useless_anonymous_reexport = useless anonymous re-export + .note = only anonymous re-exports of traits are useful, this is {$article} `${desc}` diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index b3578540516d..c2cc2fcdf551 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -74,6 +74,7 @@ mod opaque_hidden_inferred_bound; mod pass_by_value; mod passes; mod redundant_semicolon; +mod reexports; mod traits; mod types; mod unused; @@ -111,6 +112,7 @@ use noop_method_call::*; use opaque_hidden_inferred_bound::*; use pass_by_value::*; use redundant_semicolon::*; +use reexports::*; use traits::*; use types::*; use unused::*; @@ -242,6 +244,7 @@ late_lint_methods!( OpaqueHiddenInferredBound: OpaqueHiddenInferredBound, MultipleSupertraitUpcastable: MultipleSupertraitUpcastable, MapUnitFn: MapUnitFn, + UselessAnonymousReexport: UselessAnonymousReexport, ] ] ); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 20ab0af58565..ac73f0830f68 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1530,3 +1530,10 @@ pub struct UnusedAllocationDiag; #[derive(LintDiagnostic)] #[diag(lint_unused_allocation_mut)] pub struct UnusedAllocationMutDiag; + +#[derive(LintDiagnostic)] +#[diag(lint_useless_anonymous_reexport)] +pub struct UselessAnonymousReexportDiag { + pub article: &'static str, + pub desc: &'static str, +} diff --git a/compiler/rustc_lint/src/reexports.rs b/compiler/rustc_lint/src/reexports.rs new file mode 100644 index 000000000000..8737a57ea026 --- /dev/null +++ b/compiler/rustc_lint/src/reexports.rs @@ -0,0 +1,82 @@ +use crate::lints::UselessAnonymousReexportDiag; +use crate::{LateContext, LateLintPass, LintContext}; +use rustc_hir::def::DefKind; +use rustc_hir::def_id::DefId; +use rustc_hir::{Item, ItemKind, UseKind}; +use rustc_middle::ty::Visibility; +use rustc_span::symbol::kw; +use rustc_span::Span; + +declare_lint! { + /// The `useless_anonymous_reexport` lint checks if anonymous re-exports + /// are re-exports of traits. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(useless_anonymous_reexport)] + /// + /// mod sub { + /// pub struct Bar; + /// } + /// + /// pub use self::sub::Bar as _; + /// # fn main() {} + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Anonymous re-exports are only useful if it's a re-export of a trait + /// in case you want to give access to it. If you re-export any other kind, + /// you won't be able to use it since its name won't be accessible. + pub USELESS_ANONYMOUS_REEXPORT, + Warn, + "useless anonymous re-export" +} + +declare_lint_pass!(UselessAnonymousReexport => [USELESS_ANONYMOUS_REEXPORT]); + +fn emit_err(cx: &LateContext<'_>, span: Span, def_id: DefId) { + let article = cx.tcx.def_descr_article(def_id); + let desc = cx.tcx.def_descr(def_id); + cx.emit_spanned_lint( + USELESS_ANONYMOUS_REEXPORT, + span, + UselessAnonymousReexportDiag { article, desc }, + ); +} + +impl<'tcx> LateLintPass<'tcx> for UselessAnonymousReexport { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { + if let ItemKind::Use(path, kind) = item.kind && + !matches!(kind, UseKind::Glob) && + item.ident.name == kw::Underscore && + // We only want re-exports. If it's just a `use X;`, then we ignore it. + match cx.tcx.local_visibility(item.owner_id.def_id) { + Visibility::Public => true, + Visibility::Restricted(level) => { + level != cx.tcx.parent_module_from_def_id(item.owner_id.def_id) + } + } + { + for def_id in path.res.iter().filter_map(|r| r.opt_def_id()) { + match cx.tcx.def_kind(def_id) { + DefKind::Trait | DefKind::TraitAlias => {} + DefKind::TyAlias => { + let ty = cx.tcx.type_of(def_id); + if !ty.0.is_trait() { + emit_err(cx, item.span, def_id); + break; + } + } + _ => { + emit_err(cx, item.span, def_id); + break; + } + } + } + } + } +} From ac4ea529801ed087041768f1708637cc8277db49 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 10 Mar 2023 22:20:29 +0100 Subject: [PATCH 018/116] Add test for useless_anonymous_reexport lint --- compiler/rustc_lint/messages.ftl | 2 +- compiler/rustc_lint/src/lints.rs | 1 + tests/ui/lint/anonymous-reexport.rs | 16 ++++++++++++++++ tests/ui/lint/anonymous-reexport.stderr | 20 ++++++++++++++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 tests/ui/lint/anonymous-reexport.rs create mode 100644 tests/ui/lint/anonymous-reexport.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 1924ae08c393..c822237413c7 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -510,4 +510,4 @@ lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its ass lint_opaque_hidden_inferred_bound_sugg = add this bound lint_useless_anonymous_reexport = useless anonymous re-export - .note = only anonymous re-exports of traits are useful, this is {$article} `${desc}` + .note = only anonymous re-exports of traits are useful, this is {$article} `{$desc}` diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index ac73f0830f68..8d058517118c 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1533,6 +1533,7 @@ pub struct UnusedAllocationMutDiag; #[derive(LintDiagnostic)] #[diag(lint_useless_anonymous_reexport)] +#[note] pub struct UselessAnonymousReexportDiag { pub article: &'static str, pub desc: &'static str, diff --git a/tests/ui/lint/anonymous-reexport.rs b/tests/ui/lint/anonymous-reexport.rs new file mode 100644 index 000000000000..380e7792bdd3 --- /dev/null +++ b/tests/ui/lint/anonymous-reexport.rs @@ -0,0 +1,16 @@ +#![deny(useless_anonymous_reexport)] +#![crate_type = "rlib"] + +mod my_mod { + pub trait Foo {} + pub type TyFoo = dyn Foo; + pub struct Bar; + pub type TyBar = Bar; +} + +pub use self::my_mod::Foo as _; +pub use self::my_mod::TyFoo as _; +pub use self::my_mod::Bar as _; //~ ERROR +pub use self::my_mod::TyBar as _; //~ ERROR +#[allow(unused_imports)] +use self::my_mod::TyBar as _; diff --git a/tests/ui/lint/anonymous-reexport.stderr b/tests/ui/lint/anonymous-reexport.stderr new file mode 100644 index 000000000000..fafa855e5faf --- /dev/null +++ b/tests/ui/lint/anonymous-reexport.stderr @@ -0,0 +1,20 @@ +error: useless anonymous re-export + --> $DIR/anonymous-reexport.rs:13:1 + | +LL | pub use self::my_mod::Bar as _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/anonymous-reexport.rs:1:9 + | +LL | #![deny(useless_anonymous_reexport)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: useless anonymous re-export + --> $DIR/anonymous-reexport.rs:14:1 + | +LL | pub use self::my_mod::TyBar as _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From 7b0fa085b093be4cca285441703d91caa216e4dc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 12 Mar 2023 15:23:32 +0100 Subject: [PATCH 019/116] Update failing ui tests --- tests/ui/imports/issue-99695-b.fixed | 2 +- tests/ui/imports/issue-99695-b.rs | 2 +- tests/ui/imports/issue-99695.fixed | 2 +- tests/ui/imports/issue-99695.rs | 2 +- tests/ui/lint/anonymous-reexport.rs | 5 ++++ tests/ui/lint/anonymous-reexport.stderr | 37 ++++++++++++++++++++++++- 6 files changed, 45 insertions(+), 5 deletions(-) diff --git a/tests/ui/imports/issue-99695-b.fixed b/tests/ui/imports/issue-99695-b.fixed index 0e60c73b67a4..0f688fa28235 100644 --- a/tests/ui/imports/issue-99695-b.fixed +++ b/tests/ui/imports/issue-99695-b.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![allow(unused, nonstandard_style)] +#![allow(unused, nonstandard_style, useless_anonymous_reexport)] mod m { mod p { diff --git a/tests/ui/imports/issue-99695-b.rs b/tests/ui/imports/issue-99695-b.rs index 031443a1f5df..b433997e53f6 100644 --- a/tests/ui/imports/issue-99695-b.rs +++ b/tests/ui/imports/issue-99695-b.rs @@ -1,5 +1,5 @@ // run-rustfix -#![allow(unused, nonstandard_style)] +#![allow(unused, nonstandard_style, useless_anonymous_reexport)] mod m { mod p { diff --git a/tests/ui/imports/issue-99695.fixed b/tests/ui/imports/issue-99695.fixed index 6bf228b23aad..17ff409324e3 100644 --- a/tests/ui/imports/issue-99695.fixed +++ b/tests/ui/imports/issue-99695.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![allow(unused, nonstandard_style)] +#![allow(unused, nonstandard_style, useless_anonymous_reexport)] mod m { #[macro_export] macro_rules! nu { diff --git a/tests/ui/imports/issue-99695.rs b/tests/ui/imports/issue-99695.rs index f7199f1497ab..b8979bcb7345 100644 --- a/tests/ui/imports/issue-99695.rs +++ b/tests/ui/imports/issue-99695.rs @@ -1,5 +1,5 @@ // run-rustfix -#![allow(unused, nonstandard_style)] +#![allow(unused, nonstandard_style, useless_anonymous_reexport)] mod m { #[macro_export] macro_rules! nu { diff --git a/tests/ui/lint/anonymous-reexport.rs b/tests/ui/lint/anonymous-reexport.rs index 380e7792bdd3..5d56ae6f969b 100644 --- a/tests/ui/lint/anonymous-reexport.rs +++ b/tests/ui/lint/anonymous-reexport.rs @@ -12,5 +12,10 @@ pub use self::my_mod::Foo as _; pub use self::my_mod::TyFoo as _; pub use self::my_mod::Bar as _; //~ ERROR pub use self::my_mod::TyBar as _; //~ ERROR +pub use self::my_mod::{Bar as _}; //~ ERROR +pub use self::my_mod::{Bar as _, Foo as _}; //~ ERROR +pub use self::my_mod::{Bar as _, TyBar as _}; +//~^ ERROR +//~| ERROR #[allow(unused_imports)] use self::my_mod::TyBar as _; diff --git a/tests/ui/lint/anonymous-reexport.stderr b/tests/ui/lint/anonymous-reexport.stderr index fafa855e5faf..f4f8b41c417a 100644 --- a/tests/ui/lint/anonymous-reexport.stderr +++ b/tests/ui/lint/anonymous-reexport.stderr @@ -4,6 +4,7 @@ error: useless anonymous re-export LL | pub use self::my_mod::Bar as _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: only anonymous re-exports of traits are useful, this is a `struct` note: the lint level is defined here --> $DIR/anonymous-reexport.rs:1:9 | @@ -15,6 +16,40 @@ error: useless anonymous re-export | LL | pub use self::my_mod::TyBar as _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only anonymous re-exports of traits are useful, this is a `type alias` -error: aborting due to 2 previous errors +error: useless anonymous re-export + --> $DIR/anonymous-reexport.rs:15:24 + | +LL | pub use self::my_mod::{Bar as _}; + | ^^^^^^^^ + | + = note: only anonymous re-exports of traits are useful, this is a `struct` + +error: useless anonymous re-export + --> $DIR/anonymous-reexport.rs:16:24 + | +LL | pub use self::my_mod::{Bar as _, Foo as _}; + | ^^^^^^^^ + | + = note: only anonymous re-exports of traits are useful, this is a `struct` + +error: useless anonymous re-export + --> $DIR/anonymous-reexport.rs:17:24 + | +LL | pub use self::my_mod::{Bar as _, TyBar as _}; + | ^^^^^^^^ + | + = note: only anonymous re-exports of traits are useful, this is a `struct` + +error: useless anonymous re-export + --> $DIR/anonymous-reexport.rs:17:34 + | +LL | pub use self::my_mod::{Bar as _, TyBar as _}; + | ^^^^^^^^^^ + | + = note: only anonymous re-exports of traits are useful, this is a `type alias` + +error: aborting due to 6 previous errors From b2f6fd4f961fc7e4fbfdb80cae2e6065f8436f15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 13 Mar 2023 10:42:24 +0200 Subject: [PATCH 020/116] :arrow_up: rust-analyzer --- Cargo.lock | 2 + crates/flycheck/src/lib.rs | 109 +- crates/hir-def/src/attr.rs | 48 +- crates/hir-def/src/body.rs | 31 +- crates/hir-def/src/body/lower.rs | 200 ++- crates/hir-def/src/body/pretty.rs | 95 +- crates/hir-def/src/body/scope.rs | 50 +- crates/hir-def/src/body/tests/block.rs | 22 + crates/hir-def/src/child_by_source.rs | 3 +- crates/hir-def/src/data.rs | 37 +- crates/hir-def/src/db.rs | 11 +- crates/hir-def/src/expr.rs | 69 +- crates/hir-def/src/generics.rs | 44 +- crates/hir-def/src/import_map.rs | 2 + crates/hir-def/src/item_scope.rs | 1 + crates/hir-def/src/item_tree.rs | 17 +- crates/hir-def/src/item_tree/lower.rs | 137 +- crates/hir-def/src/item_tree/pretty.rs | 29 +- crates/hir-def/src/keys.rs | 5 +- crates/hir-def/src/lang_item.rs | 6 +- crates/hir-def/src/lib.rs | 17 +- .../macro_expansion_tests/builtin_fn_macro.rs | 2 +- .../macro_expansion_tests/mbe/regression.rs | 1 + crates/hir-def/src/nameres.rs | 18 +- crates/hir-def/src/nameres/collector.rs | 29 +- crates/hir-def/src/nameres/path_resolution.rs | 4 +- .../hir-def/src/nameres/tests/incremental.rs | 1 + crates/hir-def/src/path.rs | 4 +- crates/hir-def/src/path/lower.rs | 4 +- crates/hir-def/src/resolver.rs | 258 ++- crates/hir-def/src/type_ref.rs | 62 +- crates/hir-def/src/visibility.rs | 7 +- crates/hir-expand/src/builtin_fn_macro.rs | 2 +- crates/hir-expand/src/lib.rs | 26 +- crates/hir-ty/Cargo.toml | 1 + crates/hir-ty/src/builder.rs | 9 + crates/hir-ty/src/chalk_db.rs | 3 +- crates/hir-ty/src/chalk_ext.rs | 7 +- crates/hir-ty/src/consteval.rs | 503 ++---- crates/hir-ty/src/consteval/tests.rs | 965 +++++++++- crates/hir-ty/src/db.rs | 25 +- crates/hir-ty/src/diagnostics/decl_check.rs | 5 +- crates/hir-ty/src/diagnostics/expr.rs | 31 +- crates/hir-ty/src/diagnostics/match_check.rs | 3 +- crates/hir-ty/src/diagnostics/unsafe_check.rs | 6 +- crates/hir-ty/src/display.rs | 187 +- crates/hir-ty/src/infer.rs | 215 ++- crates/hir-ty/src/infer/coerce.rs | 60 +- crates/hir-ty/src/infer/expr.rs | 772 +++++--- crates/hir-ty/src/infer/pat.rs | 345 ++-- crates/hir-ty/src/infer/path.rs | 147 +- crates/hir-ty/src/infer/unify.rs | 5 +- crates/hir-ty/src/inhabitedness.rs | 19 +- crates/hir-ty/src/interner.rs | 4 +- crates/hir-ty/src/layout.rs | 16 +- crates/hir-ty/src/layout/adt.rs | 13 +- crates/hir-ty/src/layout/tests.rs | 21 +- crates/hir-ty/src/lib.rs | 49 +- crates/hir-ty/src/lower.rs | 30 +- crates/hir-ty/src/method_resolution.rs | 121 +- crates/hir-ty/src/mir.rs | 863 +++++++++ crates/hir-ty/src/mir/borrowck.rs | 223 +++ crates/hir-ty/src/mir/eval.rs | 1253 +++++++++++++ crates/hir-ty/src/mir/lower.rs | 1577 +++++++++++++++++ crates/hir-ty/src/mir/lower/as_place.rs | 237 +++ crates/hir-ty/src/mir/pretty.rs | 348 ++++ crates/hir-ty/src/tests.rs | 38 +- crates/hir-ty/src/tests/coercion.rs | 3 +- crates/hir-ty/src/tests/diagnostics.rs | 21 + crates/hir-ty/src/tests/method_resolution.rs | 4 +- crates/hir-ty/src/tests/patterns.rs | 30 +- crates/hir-ty/src/tests/regression.rs | 20 +- crates/hir-ty/src/tests/simple.rs | 24 +- crates/hir-ty/src/utils.rs | 7 +- crates/hir/src/attrs.rs | 5 +- crates/hir/src/db.rs | 5 +- crates/hir/src/diagnostics.rs | 47 +- crates/hir/src/display.rs | 49 +- crates/hir/src/from_id.rs | 13 +- crates/hir/src/has_source.rs | 21 +- crates/hir/src/lib.rs | 512 ++++-- crates/hir/src/semantics.rs | 36 +- crates/hir/src/semantics/source_to_def.rs | 38 +- crates/hir/src/source_analyzer.rs | 42 +- crates/hir/src/symbols.rs | 4 + .../src/handlers/add_explicit_type.rs | 4 +- .../handlers/convert_iter_for_each_to_for.rs | 19 +- .../src/handlers/convert_match_to_let_else.rs | 83 +- .../src/handlers/extract_function.rs | 25 +- .../src/handlers/extract_variable.rs | 2 +- .../src/handlers/fix_visibility.rs | 4 + .../src/handlers/generate_function.rs | 148 +- .../handlers/generate_is_empty_from_len.rs | 9 +- .../ide-assists/src/handlers/generate_new.rs | 2 +- .../src/handlers/inline_local_variable.rs | 11 +- crates/ide-assists/src/handlers/remove_dbg.rs | 134 +- .../src/handlers/replace_if_let_with_match.rs | 27 +- .../src/handlers/replace_method_eager_lazy.rs | 310 ++++ .../src/handlers/replace_or_with_or_else.rs | 364 ---- crates/ide-assists/src/lib.rs | 6 +- crates/ide-assists/src/tests/generated.rs | 84 +- crates/ide-completion/src/completions/dot.rs | 2 +- .../src/completions/flyimport.rs | 5 +- crates/ide-completion/src/completions/type.rs | 4 +- crates/ide-completion/src/context.rs | 15 +- crates/ide-completion/src/item.rs | 3 +- crates/ide-completion/src/render.rs | 3 + crates/ide-completion/src/render/macro_.rs | 59 + crates/ide-db/src/active_parameter.rs | 1 + crates/ide-db/src/apply_change.rs | 64 +- crates/ide-db/src/defs.rs | 21 +- crates/ide-db/src/helpers.rs | 10 +- crates/ide-db/src/imports/import_assets.rs | 2 +- crates/ide-db/src/lib.rs | 4 +- crates/ide-db/src/rename.rs | 105 +- crates/ide-db/src/search.rs | 50 +- crates/ide-db/src/source_change.rs | 8 + ...ntructor.rs => use_trivial_constructor.rs} | 0 .../src/handlers/break_outside_of_loop.rs | 23 +- .../src/handlers/expected_function.rs | 39 + .../src/handlers/missing_fields.rs | 2 +- .../src/handlers/missing_match_arms.rs | 5 +- .../src/handlers/mutability_errors.rs | 625 +++++++ .../src/handlers/private_assoc_item.rs | 38 + .../replace_filter_map_next_with_find_map.rs | 13 +- .../src/handlers/type_mismatch.rs | 86 +- .../src/handlers/unresolved_field.rs | 148 ++ .../src/handlers/unresolved_method.rs | 131 ++ crates/ide-diagnostics/src/lib.rs | 10 +- crates/ide-ssr/src/matching.rs | 2 +- crates/ide/src/doc_links.rs | 15 +- crates/ide/src/file_structure.rs | 79 +- crates/ide/src/goto_definition.rs | 25 +- crates/ide/src/highlight_related.rs | 57 +- crates/ide/src/hover.rs | 1 + crates/ide/src/hover/render.rs | 31 +- crates/ide/src/hover/tests.rs | 350 +++- crates/ide/src/inlay_hints/adjustment.rs | 5 +- crates/ide/src/inlay_hints/bind_pat.rs | 117 +- crates/ide/src/inlay_hints/chaining.rs | 12 +- crates/ide/src/inlay_hints/discriminant.rs | 10 +- crates/ide/src/lib.rs | 5 + crates/ide/src/markup.rs | 2 +- crates/ide/src/moniker.rs | 3 + crates/ide/src/move_item.rs | 1 + crates/ide/src/navigation_target.rs | 26 +- crates/ide/src/references.rs | 32 + crates/ide/src/rename.rs | 22 + crates/ide/src/runnables.rs | 290 ++- crates/ide/src/signature_help.rs | 6 +- crates/ide/src/static_index.rs | 1 + .../ide/src/syntax_highlighting/highlight.rs | 5 +- crates/ide/src/syntax_highlighting/inject.rs | 1 + crates/ide/src/syntax_highlighting/tags.rs | 1 + .../test_data/highlight_attributes.html | 2 +- crates/ide/src/syntax_highlighting/tests.rs | 2 +- crates/ide/src/view_mir.rs | 29 + crates/parser/src/grammar.rs | 4 + crates/parser/src/grammar/attributes.rs | 2 +- crates/parser/src/grammar/expressions.rs | 28 +- crates/parser/src/grammar/expressions/atom.rs | 10 +- crates/parser/src/grammar/items/traits.rs | 2 +- crates/parser/src/grammar/paths.rs | 6 + crates/parser/src/syntax_kind/generated.rs | 1 + .../0049_let_else_right_curly_brace_for.rast | 58 + .../0049_let_else_right_curly_brace_for.rs | 6 + .../0050_let_else_right_curly_brace_loop.rast | 46 + .../0050_let_else_right_curly_brace_loop.rs | 6 + ...0051_let_else_right_curly_brace_match.rast | 85 + .../0051_let_else_right_curly_brace_match.rs | 8 + ...0052_let_else_right_curly_brace_while.rast | 49 + .../0052_let_else_right_curly_brace_while.rs | 6 + .../0053_let_else_right_curly_brace_if.rast | 57 + .../err/0053_let_else_right_curly_brace_if.rs | 7 + .../err/0016_angled_path_without_qual.rast | 49 + .../err/0016_angled_path_without_qual.rs | 2 + .../err/0017_let_else_right_curly_brace.rast | 69 + .../err/0017_let_else_right_curly_brace.rs | 1 + .../parser/inline/ok/0151_trait_alias.rast | 2 +- .../ok/0177_trait_alias_where_clause.rast | 4 +- crates/project-model/src/build_scripts.rs | 84 +- crates/project-model/src/cargo_workspace.rs | 2 + crates/project-model/src/sysroot.rs | 21 +- crates/project-model/src/tests.rs | 9 + crates/project-model/src/workspace.rs | 60 +- .../default_12483297303756020505_0.profraw | Bin 25152 -> 0 bytes .../rust-analyzer/src/cli/analysis_stats.rs | 187 +- crates/rust-analyzer/src/cli/diagnostics.rs | 4 +- crates/rust-analyzer/src/cli/lsif.rs | 5 +- crates/rust-analyzer/src/cli/scip.rs | 5 +- crates/rust-analyzer/src/cli/ssr.rs | 5 +- crates/rust-analyzer/src/config.rs | 51 +- crates/rust-analyzer/src/handlers.rs | 10 + crates/rust-analyzer/src/lsp_ext.rs | 8 + crates/rust-analyzer/src/main_loop.rs | 71 +- crates/rust-analyzer/src/reload.rs | 99 +- crates/rust-analyzer/src/to_proto.rs | 4 +- crates/syntax/Cargo.toml | 1 + crates/syntax/rust.ungram | 10 +- crates/syntax/src/ast.rs | 12 +- crates/syntax/src/ast/generated/nodes.rs | 43 +- crates/syntax/src/ast/node_ext.rs | 75 + crates/syntax/src/ast/traits.rs | 4 +- crates/syntax/src/tests/ast_src.rs | 1 + crates/syntax/src/tests/sourcegen_ast.rs | 1 + crates/test-utils/src/fixture.rs | 4 +- crates/test-utils/src/minicore.rs | 49 + crates/toolchain/src/lib.rs | 21 +- docs/dev/lsp-extensions.md | 13 +- docs/user/generated_config.adoc | 15 +- editors/code/package.json | 31 +- editors/code/src/commands.ts | 35 +- editors/code/src/ctx.ts | 34 +- editors/code/src/lsp_ext.ts | 3 + editors/code/src/main.ts | 2 + editors/code/src/toolchain.ts | 30 +- lib/la-arena/src/map.rs | 6 + 217 files changed, 12639 insertions(+), 3059 deletions(-) create mode 100644 crates/hir-ty/src/mir.rs create mode 100644 crates/hir-ty/src/mir/borrowck.rs create mode 100644 crates/hir-ty/src/mir/eval.rs create mode 100644 crates/hir-ty/src/mir/lower.rs create mode 100644 crates/hir-ty/src/mir/lower/as_place.rs create mode 100644 crates/hir-ty/src/mir/pretty.rs create mode 100644 crates/ide-assists/src/handlers/replace_method_eager_lazy.rs delete mode 100644 crates/ide-assists/src/handlers/replace_or_with_or_else.rs rename crates/ide-db/src/{use_trivial_contructor.rs => use_trivial_constructor.rs} (100%) create mode 100644 crates/ide-diagnostics/src/handlers/expected_function.rs create mode 100644 crates/ide-diagnostics/src/handlers/mutability_errors.rs create mode 100644 crates/ide-diagnostics/src/handlers/unresolved_field.rs create mode 100644 crates/ide-diagnostics/src/handlers/unresolved_method.rs create mode 100644 crates/ide/src/view_mir.rs create mode 100644 crates/parser/test_data/parser/err/0049_let_else_right_curly_brace_for.rast create mode 100644 crates/parser/test_data/parser/err/0049_let_else_right_curly_brace_for.rs create mode 100644 crates/parser/test_data/parser/err/0050_let_else_right_curly_brace_loop.rast create mode 100644 crates/parser/test_data/parser/err/0050_let_else_right_curly_brace_loop.rs create mode 100644 crates/parser/test_data/parser/err/0051_let_else_right_curly_brace_match.rast create mode 100644 crates/parser/test_data/parser/err/0051_let_else_right_curly_brace_match.rs create mode 100644 crates/parser/test_data/parser/err/0052_let_else_right_curly_brace_while.rast create mode 100644 crates/parser/test_data/parser/err/0052_let_else_right_curly_brace_while.rs create mode 100644 crates/parser/test_data/parser/err/0053_let_else_right_curly_brace_if.rast create mode 100644 crates/parser/test_data/parser/err/0053_let_else_right_curly_brace_if.rs create mode 100644 crates/parser/test_data/parser/inline/err/0016_angled_path_without_qual.rast create mode 100644 crates/parser/test_data/parser/inline/err/0016_angled_path_without_qual.rs create mode 100644 crates/parser/test_data/parser/inline/err/0017_let_else_right_curly_brace.rast create mode 100644 crates/parser/test_data/parser/inline/err/0017_let_else_right_curly_brace.rs delete mode 100644 crates/rust-analyzer/default_12483297303756020505_0.profraw diff --git a/Cargo.lock b/Cargo.lock index ec197767259d..fc77515b63bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -572,6 +572,7 @@ dependencies = [ "chalk-recursive", "chalk-solve", "cov-mark", + "either", "ena", "expect-test", "hir-def", @@ -1714,6 +1715,7 @@ name = "syntax" version = "0.0.0" dependencies = [ "cov-mark", + "either", "expect-test", "indexmap", "itertools", diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index 11f7b068ecb1..accb14a51deb 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs @@ -76,7 +76,7 @@ impl fmt::Display for FlycheckConfig { #[derive(Debug)] pub struct FlycheckHandle { // XXX: drop order is significant - sender: Sender, + sender: Sender, _thread: jod_thread::JoinHandle, id: usize, } @@ -89,7 +89,7 @@ impl FlycheckHandle { workspace_root: AbsPathBuf, ) -> FlycheckHandle { let actor = FlycheckActor::new(id, sender, config, workspace_root); - let (sender, receiver) = unbounded::(); + let (sender, receiver) = unbounded::(); let thread = jod_thread::Builder::new() .name("Flycheck".to_owned()) .spawn(move || actor.run(receiver)) @@ -99,12 +99,12 @@ impl FlycheckHandle { /// Schedule a re-start of the cargo check worker. pub fn restart(&self) { - self.sender.send(Restart::Yes).unwrap(); + self.sender.send(StateChange::Restart).unwrap(); } /// Stop this cargo check worker. pub fn cancel(&self) { - self.sender.send(Restart::No).unwrap(); + self.sender.send(StateChange::Cancel).unwrap(); } pub fn id(&self) -> usize { @@ -149,9 +149,9 @@ pub enum Progress { DidFailToRestart(String), } -enum Restart { - Yes, - No, +enum StateChange { + Restart, + Cancel, } /// A [`FlycheckActor`] is a single check instance of a workspace. @@ -172,7 +172,7 @@ struct FlycheckActor { } enum Event { - Restart(Restart), + RequestStateChange(StateChange), CheckEvent(Option), } @@ -191,30 +191,31 @@ impl FlycheckActor { self.send(Message::Progress { id: self.id, progress }); } - fn next_event(&self, inbox: &Receiver) -> Option { + 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() { // give restarts a preference so check outputs don't block a restart or stop - return Some(Event::Restart(msg)); + return Some(Event::RequestStateChange(msg)); } select! { - recv(inbox) -> msg => msg.ok().map(Event::Restart), + recv(inbox) -> msg => msg.ok().map(Event::RequestStateChange), recv(check_chan.unwrap_or(&never())) -> msg => Some(Event::CheckEvent(msg.ok())), } } - fn run(mut self, inbox: Receiver) { + fn run(mut self, inbox: Receiver) { 'event: while let Some(event) = self.next_event(&inbox) { match event { - Event::Restart(Restart::No) => { + Event::RequestStateChange(StateChange::Cancel) => { + tracing::debug!(flycheck_id = self.id, "flycheck cancelled"); self.cancel_check_process(); } - Event::Restart(Restart::Yes) => { + Event::RequestStateChange(StateChange::Restart) => { // Cancel the previously spawned process self.cancel_check_process(); while let Ok(restart) = inbox.recv_timeout(Duration::from_millis(50)) { // restart chained with a stop, so just cancel - if let Restart::No = restart { + if let StateChange::Cancel = restart { continue 'event; } } @@ -255,10 +256,20 @@ impl FlycheckActor { } Event::CheckEvent(Some(message)) => match message { CargoMessage::CompilerArtifact(msg) => { + tracing::trace!( + flycheck_id = self.id, + artifact = msg.target.name, + "artifact received" + ); self.report_progress(Progress::DidCheckCrate(msg.target.name)); } CargoMessage::Diagnostic(msg) => { + tracing::trace!( + flycheck_id = self.id, + message = msg.message, + "diagnostic received" + ); self.send(Message::AddDiagnostic { id: self.id, workspace_root: self.root.clone(), @@ -445,42 +456,56 @@ impl CargoActor { // simply skip a line if it doesn't parse, which just ignores any // erroneous output. - let mut error = String::new(); - let mut read_at_least_one_message = false; + let mut stdout_errors = String::new(); + let mut stderr_errors = String::new(); + let mut read_at_least_one_stdout_message = false; + let mut read_at_least_one_stderr_message = false; + let process_line = |line: &str, error: &mut String| { + // Try to deserialize a message from Cargo or Rustc. + let mut deserializer = serde_json::Deserializer::from_str(line); + deserializer.disable_recursion_limit(); + if let Ok(message) = JsonMessage::deserialize(&mut deserializer) { + match message { + // Skip certain kinds of messages to only spend time on what's useful + JsonMessage::Cargo(message) => match message { + cargo_metadata::Message::CompilerArtifact(artifact) if !artifact.fresh => { + self.sender.send(CargoMessage::CompilerArtifact(artifact)).unwrap(); + } + cargo_metadata::Message::CompilerMessage(msg) => { + self.sender.send(CargoMessage::Diagnostic(msg.message)).unwrap(); + } + _ => (), + }, + JsonMessage::Rustc(message) => { + self.sender.send(CargoMessage::Diagnostic(message)).unwrap(); + } + } + return true; + } + + error.push_str(line); + error.push('\n'); + return false; + }; let output = streaming_output( self.stdout, self.stderr, &mut |line| { - read_at_least_one_message = true; - - // Try to deserialize a message from Cargo or Rustc. - let mut deserializer = serde_json::Deserializer::from_str(line); - deserializer.disable_recursion_limit(); - if let Ok(message) = JsonMessage::deserialize(&mut deserializer) { - match message { - // Skip certain kinds of messages to only spend time on what's useful - JsonMessage::Cargo(message) => match message { - cargo_metadata::Message::CompilerArtifact(artifact) - if !artifact.fresh => - { - self.sender.send(CargoMessage::CompilerArtifact(artifact)).unwrap(); - } - cargo_metadata::Message::CompilerMessage(msg) => { - self.sender.send(CargoMessage::Diagnostic(msg.message)).unwrap(); - } - _ => (), - }, - JsonMessage::Rustc(message) => { - self.sender.send(CargoMessage::Diagnostic(message)).unwrap(); - } - } + if process_line(line, &mut stdout_errors) { + read_at_least_one_stdout_message = true; } }, &mut |line| { - error.push_str(line); - error.push('\n'); + if process_line(line, &mut stderr_errors) { + read_at_least_one_stderr_message = true; + } }, ); + + let read_at_least_one_message = + read_at_least_one_stdout_message || read_at_least_one_stderr_message; + let mut error = stdout_errors; + error.push_str(&stderr_errors); match output { Ok(_) => Ok((read_at_least_one_message, error)), Err(e) => Err(io::Error::new(e.kind(), format!("{e:?}: {error}"))), diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index fcd92ad33858..200072c172eb 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -300,6 +300,7 @@ impl AttrsWithOwner { AdtId::UnionId(it) => attrs_from_item_tree(it.lookup(db).id, db), }, AttrDefId::TraitId(it) => attrs_from_item_tree(it.lookup(db).id, db), + AttrDefId::TraitAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db), AttrDefId::MacroId(it) => match it { MacroId::Macro2Id(it) => attrs_from_item_tree(it.lookup(db).id, db), MacroId::MacroRulesId(it) => attrs_from_item_tree(it.lookup(db).id, db), @@ -315,26 +316,14 @@ impl AttrsWithOwner { let src = it.parent().child_source(db); RawAttrs::from_attrs_owner( db.upcast(), - src.with_value(src.value[it.local_id()].as_ref().either( - |it| match it { - ast::TypeOrConstParam::Type(it) => it as _, - ast::TypeOrConstParam::Const(it) => it as _, - }, - |it| it as _, - )), + src.with_value(&src.value[it.local_id()]), ) } GenericParamId::TypeParamId(it) => { let src = it.parent().child_source(db); RawAttrs::from_attrs_owner( db.upcast(), - src.with_value(src.value[it.local_id()].as_ref().either( - |it| match it { - ast::TypeOrConstParam::Type(it) => it as _, - ast::TypeOrConstParam::Const(it) => it as _, - }, - |it| it as _, - )), + src.with_value(&src.value[it.local_id()]), ) } GenericParamId::LifetimeParamId(it) => { @@ -404,6 +393,7 @@ impl AttrsWithOwner { AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), + AttrDefId::TraitAliasId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), AttrDefId::TypeAliasId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), AttrDefId::MacroId(id) => match id { MacroId::Macro2Id(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), @@ -412,28 +402,14 @@ impl AttrsWithOwner { }, AttrDefId::ImplId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), AttrDefId::GenericParamId(id) => match id { - GenericParamId::ConstParamId(id) => { - id.parent().child_source(db).map(|source| match &source[id.local_id()] { - Either::Left(ast::TypeOrConstParam::Type(id)) => { - ast::AnyHasAttrs::new(id.clone()) - } - Either::Left(ast::TypeOrConstParam::Const(id)) => { - ast::AnyHasAttrs::new(id.clone()) - } - Either::Right(id) => ast::AnyHasAttrs::new(id.clone()), - }) - } - GenericParamId::TypeParamId(id) => { - id.parent().child_source(db).map(|source| match &source[id.local_id()] { - Either::Left(ast::TypeOrConstParam::Type(id)) => { - ast::AnyHasAttrs::new(id.clone()) - } - Either::Left(ast::TypeOrConstParam::Const(id)) => { - ast::AnyHasAttrs::new(id.clone()) - } - Either::Right(id) => ast::AnyHasAttrs::new(id.clone()), - }) - } + GenericParamId::ConstParamId(id) => id + .parent() + .child_source(db) + .map(|source| ast::AnyHasAttrs::new(source[id.local_id()].clone())), + GenericParamId::TypeParamId(id) => id + .parent() + .child_source(db) + .map(|source| ast::AnyHasAttrs::new(source[id.local_id()].clone())), GenericParamId::LifetimeParamId(id) => id .parent .child_source(db) diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs index 8fd9255b8b13..3be477d48774 100644 --- a/crates/hir-def/src/body.rs +++ b/crates/hir-def/src/body.rs @@ -24,7 +24,7 @@ use syntax::{ast, AstPtr, SyntaxNode, SyntaxNodePtr}; use crate::{ attr::Attrs, db::DefDatabase, - expr::{dummy_expr_id, Expr, ExprId, Label, LabelId, Pat, PatId}, + expr::{dummy_expr_id, Binding, BindingId, Expr, ExprId, Label, LabelId, Pat, PatId}, item_scope::BuiltinShadowMode, macro_id_to_def_id, nameres::DefMap, @@ -270,7 +270,7 @@ pub struct Mark { pub struct Body { pub exprs: Arena, pub pats: Arena, - pub or_pats: FxHashMap>, + pub bindings: Arena, pub labels: Arena