From 595d9e6ebbb97757cecf0ade7228b8f8f7420eeb Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Mon, 10 Jul 2023 21:50:03 +0900 Subject: [PATCH 001/197] fix: don't use control flow when extracted fn contains tail expr of original fn --- .../src/handlers/extract_function.rs | 119 +++++++++--------- 1 file changed, 57 insertions(+), 62 deletions(-) diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs index e9db38aca0f0..80a60b4a667d 100644 --- a/crates/ide-assists/src/handlers/extract_function.rs +++ b/crates/ide-assists/src/handlers/extract_function.rs @@ -1385,31 +1385,30 @@ enum FlowHandler { impl FlowHandler { fn from_ret_ty(fun: &Function, ret_ty: &FunType) -> FlowHandler { - match &fun.control_flow.kind { - None => FlowHandler::None, - Some(flow_kind) => { - let action = flow_kind.clone(); - if let FunType::Unit = ret_ty { - match flow_kind { - FlowKind::Return(None) - | FlowKind::Break(_, None) - | FlowKind::Continue(_) => FlowHandler::If { action }, - FlowKind::Return(_) | FlowKind::Break(_, _) => { - FlowHandler::IfOption { action } - } - FlowKind::Try { kind } => FlowHandler::Try { kind: kind.clone() }, - } - } else { - match flow_kind { - FlowKind::Return(None) - | FlowKind::Break(_, None) - | FlowKind::Continue(_) => FlowHandler::MatchOption { none: action }, - FlowKind::Return(_) | FlowKind::Break(_, _) => { - FlowHandler::MatchResult { err: action } - } - FlowKind::Try { kind } => FlowHandler::Try { kind: kind.clone() }, - } + if fun.contains_tail_expr { + return FlowHandler::None; + } + let Some(action) = fun.control_flow.kind.clone() else { + return FlowHandler::None; + }; + + if let FunType::Unit = ret_ty { + match action { + FlowKind::Return(None) | FlowKind::Break(_, None) | FlowKind::Continue(_) => { + FlowHandler::If { action } } + FlowKind::Return(_) | FlowKind::Break(_, _) => FlowHandler::IfOption { action }, + FlowKind::Try { kind } => FlowHandler::Try { kind }, + } + } else { + match action { + FlowKind::Return(None) | FlowKind::Break(_, None) | FlowKind::Continue(_) => { + FlowHandler::MatchOption { none: action } + } + FlowKind::Return(_) | FlowKind::Break(_, _) => { + FlowHandler::MatchResult { err: action } + } + FlowKind::Try { kind } => FlowHandler::Try { kind }, } } } @@ -1654,11 +1653,7 @@ impl Function { fn make_ret_ty(&self, ctx: &AssistContext<'_>, module: hir::Module) -> Option { let fun_ty = self.return_type(ctx); - let handler = if self.contains_tail_expr { - FlowHandler::None - } else { - FlowHandler::from_ret_ty(self, &fun_ty) - }; + let handler = FlowHandler::from_ret_ty(self, &fun_ty); let ret_ty = match &handler { FlowHandler::None => { if matches!(fun_ty, FunType::Unit) { @@ -1728,11 +1723,7 @@ fn make_body( fun: &Function, ) -> ast::BlockExpr { let ret_ty = fun.return_type(ctx); - let handler = if fun.contains_tail_expr { - FlowHandler::None - } else { - FlowHandler::from_ret_ty(fun, &ret_ty) - }; + let handler = FlowHandler::from_ret_ty(fun, &ret_ty); let block = match &fun.body { FunctionBody::Expr(expr) => { @@ -4471,7 +4462,7 @@ async fn foo() -> Result<(), ()> { "#, r#" async fn foo() -> Result<(), ()> { - fun_name().await? + fun_name().await } async fn $0fun_name() -> Result<(), ()> { @@ -4690,7 +4681,7 @@ fn $0fun_name() { check_assist( extract_function, r#" -//- minicore: result +//- minicore: result, try fn foo() -> Result<(), i64> { $0Result::::Ok(0)?; Ok(())$0 @@ -4698,7 +4689,7 @@ fn foo() -> Result<(), i64> { "#, r#" fn foo() -> Result<(), i64> { - fun_name()? + fun_name() } fn $0fun_name() -> Result<(), i64> { @@ -5753,6 +5744,34 @@ fn $0fun_name(t: T, v: V) -> i32 where T: Into + Copy, V: Into { ); } + #[test] + fn tail_expr_no_extra_control_flow() { + check_assist( + extract_function, + r#" +//- minicore: result +fn fallible() -> Result<(), ()> { + $0if true { + return Err(()); + } + Ok(())$0 +} +"#, + r#" +fn fallible() -> Result<(), ()> { + fun_name() +} + +fn $0fun_name() -> Result<(), ()> { + if true { + return Err(()); + } + Ok(()) +} +"#, + ); + } + #[test] fn non_tail_expr_of_tail_expr_loop() { check_assist( @@ -5800,12 +5819,6 @@ fn $0fun_name() -> ControlFlow<()> { extract_function, r#" //- minicore: option, try -impl core::ops::Try for Option { - type Output = T; - type Residual = Option; -} -impl core::ops::FromResidual for Option {} - fn f() -> Option<()> { if true { let a = $0if true { @@ -5820,12 +5833,6 @@ fn f() -> Option<()> { } "#, r#" -impl core::ops::Try for Option { - type Output = T; - type Residual = Option; -} -impl core::ops::FromResidual for Option {} - fn f() -> Option<()> { if true { let a = fun_name()?;; @@ -5852,12 +5859,6 @@ fn $0fun_name() -> Option<()> { extract_function, r#" //- minicore: option, try -impl core::ops::Try for Option { - type Output = T; - type Residual = Option; -} -impl core::ops::FromResidual for Option {} - fn f() -> Option<()> { if true { $0{ @@ -5874,15 +5875,9 @@ fn f() -> Option<()> { } "#, r#" -impl core::ops::Try for Option { - type Output = T; - type Residual = Option; -} -impl core::ops::FromResidual for Option {} - fn f() -> Option<()> { if true { - fun_name()? + fun_name() } else { None } From 008b639ef525533dc03ff6c73f05de13ab6f202d Mon Sep 17 00:00:00 2001 From: Max Heller Date: Thu, 27 Jul 2023 21:17:10 -0400 Subject: [PATCH 002/197] handle `#[cfg]`s on generic parameters --- crates/hir-def/src/generics.rs | 19 ++++++++++++++- crates/hir-def/src/item_tree.rs | 15 +++++++++--- crates/hir-def/src/item_tree/lower.rs | 35 +++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index d7d44e413880..6fe429c8d9a7 100644 --- a/crates/hir-def/src/generics.rs +++ b/crates/hir-def/src/generics.rs @@ -21,6 +21,7 @@ use crate::{ db::DefDatabase, dyn_map::{keys, DynMap}, expander::Expander, + item_tree::ItemTree, lower::LowerCtx, nameres::{DefMap, MacroSubNs}, src::{HasChildSource, HasSource}, @@ -154,12 +155,28 @@ impl GenericParams { def: GenericDefId, ) -> Interned { let _p = profile::span("generic_params_query"); + + let krate = def.module(db).krate; + let cfg_options = db.crate_graph(); + let cfg_options = &cfg_options[krate].cfg_options; + let enabled_params = |params: &GenericParams, item_tree: &ItemTree| { + let enabled = |param| item_tree.attrs(db, krate, param).is_cfg_enabled(cfg_options); + Interned::new(GenericParams { + type_or_consts: (params.type_or_consts.iter()) + .filter_map(|(idx, param)| enabled(idx.into()).then(|| param.clone())) + .collect(), + lifetimes: (params.lifetimes.iter()) + .filter_map(|(idx, param)| enabled(idx.into()).then(|| param.clone())) + .collect(), + where_predicates: params.where_predicates.clone(), + }) + }; macro_rules! id_to_generics { ($id:ident) => {{ let id = $id.lookup(db).id; let tree = id.item_tree(db); let item = &tree[id.value]; - item.generic_params.clone() + enabled_params(&item.generic_params, &tree) }}; } diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 6f80bb6e07ce..96c176d60f48 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -64,7 +64,7 @@ use triomphe::Arc; use crate::{ attr::Attrs, db::DefDatabase, - generics::GenericParams, + generics::{GenericParams, LifetimeParamData, TypeOrConstParamData}, path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, type_ref::{Mutability, TraitRef, TypeBound, TypeRef}, visibility::RawVisibility, @@ -296,10 +296,12 @@ pub enum AttrOwner { Variant(Idx), Field(Idx), Param(Idx), + TypeOrConstParamData(Idx), + LifetimeParamData(Idx), } macro_rules! from_attrs { - ( $( $var:ident($t:ty) ),+ ) => { + ( $( $var:ident($t:ty) ),+ $(,)? ) => { $( impl From<$t> for AttrOwner { fn from(t: $t) -> AttrOwner { @@ -310,7 +312,14 @@ macro_rules! from_attrs { }; } -from_attrs!(ModItem(ModItem), Variant(Idx), Field(Idx), Param(Idx)); +from_attrs!( + ModItem(ModItem), + Variant(Idx), + Field(Idx), + Param(Idx), + TypeOrConstParamData(Idx), + LifetimeParamData(Idx), +); /// Trait implemented by all item nodes in the item tree. pub trait ItemTreeNode: Clone { diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index 46633667ed3e..7dffd6fc18a1 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -605,6 +605,41 @@ impl<'a> Ctx<'a> { generics.fill(&self.body_ctx, node); generics.shrink_to_fit(); + + if let Some(params) = node.generic_param_list() { + let params_by_name: FxHashMap<_, _> = params + .generic_params() + .filter_map(|param| { + let name = match ¶m { + ast::GenericParam::ConstParam(param) => param.name()?.as_name(), + ast::GenericParam::LifetimeParam(param) => { + Name::new_lifetime(¶m.lifetime()?) + } + ast::GenericParam::TypeParam(param) => param.name()?.as_name(), + }; + Some((name, param)) + }) + .collect(); + for (idx, param) in generics.type_or_consts.iter() { + if let Some(name) = param.name() { + if let Some(param) = params_by_name.get(name) { + self.add_attrs( + idx.into(), + RawAttrs::new(self.db.upcast(), param, self.hygiene()), + ); + } + } + } + for (idx, param) in generics.lifetimes.iter() { + if let Some(param) = params_by_name.get(¶m.name) { + self.add_attrs( + idx.into(), + RawAttrs::new(self.db.upcast(), param, self.hygiene()), + ); + } + } + } + Interned::new(generics) } From 37a8493138c43caebfe7b62964a2558d21d1be25 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Fri, 28 Jul 2023 06:45:35 -0400 Subject: [PATCH 003/197] tests --- crates/hir-def/src/item_tree/pretty.rs | 27 ++++++++++++++------------ crates/hir-def/src/item_tree/tests.rs | 12 ++++++++++++ crates/ide/src/hover/tests.rs | 19 ++++++++++++++++++ 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs index ddf668d20b05..703eac7063f6 100644 --- a/crates/hir-def/src/item_tree/pretty.rs +++ b/crates/hir-def/src/item_tree/pretty.rs @@ -16,7 +16,7 @@ pub(super) fn print_item_tree(db: &dyn ExpandDatabase, tree: &ItemTree) -> Strin let mut p = Printer { db, tree, buf: String::new(), indent_level: 0, needs_indent: true }; if let Some(attrs) = tree.attrs.get(&AttrOwner::TopLevel) { - p.print_attrs(attrs, true); + p.print_attrs(attrs, true, "\n"); } p.blank(); @@ -84,22 +84,23 @@ impl Printer<'_> { } } - fn print_attrs(&mut self, attrs: &RawAttrs, inner: bool) { + fn print_attrs(&mut self, attrs: &RawAttrs, inner: bool, separated_by: &str) { let inner = if inner { "!" } else { "" }; for attr in &**attrs { - wln!( + w!( self, - "#{}[{}{}]", + "#{}[{}{}]{}", inner, attr.path.display(self.db), attr.input.as_ref().map(|it| it.to_string()).unwrap_or_default(), + separated_by, ); } } - fn print_attrs_of(&mut self, of: impl Into) { + fn print_attrs_of(&mut self, of: impl Into, separated_by: &str) { if let Some(attrs) = self.tree.attrs.get(&of.into()) { - self.print_attrs(attrs, false); + self.print_attrs(attrs, false, separated_by); } } @@ -118,7 +119,7 @@ impl Printer<'_> { self.indented(|this| { for field in fields.clone() { let Field { visibility, name, type_ref, ast_id: _ } = &this.tree[field]; - this.print_attrs_of(field); + this.print_attrs_of(field, "\n"); this.print_visibility(*visibility); w!(this, "{}: ", name.display(self.db)); this.print_type_ref(type_ref); @@ -132,7 +133,7 @@ impl Printer<'_> { self.indented(|this| { for field in fields.clone() { let Field { visibility, name, type_ref, ast_id: _ } = &this.tree[field]; - this.print_attrs_of(field); + this.print_attrs_of(field, "\n"); this.print_visibility(*visibility); w!(this, "{}: ", name.display(self.db)); this.print_type_ref(type_ref); @@ -195,7 +196,7 @@ impl Printer<'_> { } fn print_mod_item(&mut self, item: ModItem) { - self.print_attrs_of(item); + self.print_attrs_of(item, "\n"); match item { ModItem::Import(it) => { @@ -261,7 +262,7 @@ impl Printer<'_> { if !params.is_empty() { self.indented(|this| { for param in params.clone() { - this.print_attrs_of(param); + this.print_attrs_of(param, "\n"); match &this.tree[param] { Param::Normal(ty) => { if flags.contains(FnFlags::HAS_SELF_PARAM) { @@ -319,7 +320,7 @@ impl Printer<'_> { self.indented(|this| { for variant in variants.clone() { let Variant { name, fields, ast_id: _ } = &this.tree[variant]; - this.print_attrs_of(variant); + this.print_attrs_of(variant, "\n"); w!(this, "{}", name.display(self.db)); this.print_fields(fields); wln!(this, ","); @@ -484,11 +485,12 @@ impl Printer<'_> { w!(self, "<"); let mut first = true; - for (_, lt) in params.lifetimes.iter() { + for (idx, lt) in params.lifetimes.iter() { if !first { w!(self, ", "); } first = false; + self.print_attrs_of(idx, " "); w!(self, "{}", lt.name.display(self.db)); } for (idx, x) in params.type_or_consts.iter() { @@ -496,6 +498,7 @@ impl Printer<'_> { w!(self, ", "); } first = false; + self.print_attrs_of(idx, " "); match x { TypeOrConstParamData::TypeParamData(ty) => match &ty.name { Some(name) => w!(self, "{}", name.display(self.db)), diff --git a/crates/hir-def/src/item_tree/tests.rs b/crates/hir-def/src/item_tree/tests.rs index 5ded4b6b273a..4180f817209e 100644 --- a/crates/hir-def/src/item_tree/tests.rs +++ b/crates/hir-def/src/item_tree/tests.rs @@ -358,3 +358,15 @@ trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {} "#]], ) } + +#[test] +fn generics_with_attributes() { + check( + r#" +struct S<#[cfg(never)] T>; + "#, + expect![[r#" + pub(self) struct S<#[cfg(never)] T>; + "#]], + ) +} diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 00e21433daae..2e18e7c6d190 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -6451,3 +6451,22 @@ fn test() { "#]], ); } + +#[test] +fn generic_params_disabled_by_cfg() { + check( + r#" +struct S<#[cfg(never)] T>; +fn test() { + let s$0: S = S; +} +"#, + expect![[r#" + *s* + + ```rust + let s: S // size = 0, align = 1 + ``` + "#]], + ); +} From f42d361a22fadd7ddff4d4474b0c896387c7557c Mon Sep 17 00:00:00 2001 From: Catherine Flores Date: Sat, 29 Jul 2023 06:58:29 +0000 Subject: [PATCH 004/197] Allow explicit `#[repr(Rust)]` --- compiler/rustc_attr/src/builtin.rs | 2 ++ compiler/rustc_middle/src/ty/mod.rs | 1 + compiler/rustc_passes/messages.ftl | 2 +- compiler/rustc_passes/src/check_attr.rs | 1 + tests/ui/abi/explicit_repr_rust.rs | 12 ++++++++++++ tests/ui/issues/issue-43988.stderr | 4 ++-- tests/ui/repr/invalid_repr_list_help.stderr | 10 +++++----- 7 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 tests/ui/abi/explicit_repr_rust.rs diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 6cce3a56f081..c427772c082b 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -940,6 +940,7 @@ where #[derive(PartialEq, Debug, Encodable, Decodable, Copy, Clone)] pub enum ReprAttr { ReprInt(IntType), + ReprRust, ReprC, ReprPacked(u32), ReprSimd, @@ -988,6 +989,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec { let mut recognised = false; if item.is_word() { let hint = match item.name_or_empty() { + sym::Rust => Some(ReprRust), sym::C => Some(ReprC), sym::packed => Some(ReprPacked(1)), sym::simd => Some(ReprSimd), diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 0411890ab513..3b11bfc02ab6 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2257,6 +2257,7 @@ impl<'tcx> TyCtxt<'tcx> { for attr in self.get_attrs(did, sym::repr) { for r in attr::parse_repr_attr(&self.sess, attr) { flags.insert(match r { + attr::ReprRust => ReprFlags::empty(), attr::ReprC => ReprFlags::IS_C, attr::ReprPacked(pack) => { let pack = Align::from_bytes(pack as u64).unwrap(); diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 0aa3d6265dce..81a6914815e0 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -706,7 +706,7 @@ passes_unrecognized_field = passes_unrecognized_repr_hint = unrecognized representation hint - .help = valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + .help = valid reprs are `Rust`, `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` passes_unused = unused attribute diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 4d7ebe3fefef..127020c03ba6 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1683,6 +1683,7 @@ impl CheckAttrVisitor<'_> { } match hint.name_or_empty() { + sym::Rust => {} sym::C => { is_c = true; match target { diff --git a/tests/ui/abi/explicit_repr_rust.rs b/tests/ui/abi/explicit_repr_rust.rs new file mode 100644 index 000000000000..4f8cab3bf0ef --- /dev/null +++ b/tests/ui/abi/explicit_repr_rust.rs @@ -0,0 +1,12 @@ +// check-pass + +#[repr(Rust)] +struct A; + +#[repr(Rust, align(16))] +struct B; + +#[repr(Rust, packed)] +struct C; + +fn main() {} diff --git a/tests/ui/issues/issue-43988.stderr b/tests/ui/issues/issue-43988.stderr index 02c5dd5bfb77..a68d4945d824 100644 --- a/tests/ui/issues/issue-43988.stderr +++ b/tests/ui/issues/issue-43988.stderr @@ -32,7 +32,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(nothing)] | ^^^^^^^ | - = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust`, `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error[E0552]: unrecognized representation hint --> $DIR/issue-43988.rs:18:12 @@ -40,7 +40,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(something_not_real)] | ^^^^^^^^^^^^^^^^^^ | - = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust`, `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error[E0518]: attribute should be applied to function or closure --> $DIR/issue-43988.rs:30:5 diff --git a/tests/ui/repr/invalid_repr_list_help.stderr b/tests/ui/repr/invalid_repr_list_help.stderr index 48a6af3dd4c1..68cfce4065c5 100644 --- a/tests/ui/repr/invalid_repr_list_help.stderr +++ b/tests/ui/repr/invalid_repr_list_help.stderr @@ -4,7 +4,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(uwu)] | ^^^ | - = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust`, `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error[E0552]: unrecognized representation hint --> $DIR/invalid_repr_list_help.rs:6:8 @@ -12,7 +12,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(uwu = "a")] | ^^^^^^^^^ | - = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust`, `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error[E0552]: unrecognized representation hint --> $DIR/invalid_repr_list_help.rs:9:8 @@ -20,7 +20,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(uwu(4))] | ^^^^^^ | - = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust`, `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error[E0552]: unrecognized representation hint --> $DIR/invalid_repr_list_help.rs:14:8 @@ -28,7 +28,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(uwu, u8)] | ^^^ | - = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust`, `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` warning: unknown `doc` attribute `owo` --> $DIR/invalid_repr_list_help.rs:20:7 @@ -46,7 +46,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(uwu)] | ^^^ | - = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust`, `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error: aborting due to 5 previous errors; 1 warning emitted From 784379eb796deb3c799473093f59555eb8cf17f1 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Sat, 29 Jul 2023 15:23:35 -0400 Subject: [PATCH 005/197] wip --- crates/ide-completion/src/context/analysis.rs | 10 +++++ crates/ide-completion/src/tests/type_pos.rs | 37 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index 3ea50659030c..4f5266051be1 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -884,6 +884,16 @@ fn classify_name_ref( }; let make_path_kind_type = |ty: ast::Type| { let location = type_location(ty.syntax()); + if let Some(p) = ty.syntax().parent() { + if ast::GenericArg::can_cast(p.kind()) || ast::GenericArgList::can_cast(p.kind()) { + if let Some(p) = p.parent().and_then(|p| p.parent()) { + if let Some(segment) = ast::PathSegment::cast(p) { + let path = segment.parent_path().top_path(); + dbg!(sema.resolve_path(&path)); + } + } + } + } PathKind::Type { location: location.unwrap_or(TypeLocation::Other) } }; diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs index 8cb1ff4a125f..4869ac17ad91 100644 --- a/crates/ide-completion/src/tests/type_pos.rs +++ b/crates/ide-completion/src/tests/type_pos.rs @@ -719,3 +719,40 @@ pub struct S; "#]], ) } + +#[test] +fn completes_const_and_type_generics_separately() { + check( + r#" +struct Foo; +const X: usize = 0; +mod foo { + fn foo() {} +} +fn main() { + self::foo::foo::(); +} +"#, + expect![[r#" + st Foo + bt u32 + kw crate:: + kw self:: + "#]], + ); + check( + r#" +struct Foo; +const X: usize = 0; +fn foo() {} +fn main() { + foo::(); +} +"#, + expect![[r#" + ct X + kw crate:: + kw self:: + "#]], + ); +} From c4cff802691aa1ffb3da820e89dfecc41ef13de7 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Sun, 30 Jul 2023 11:12:49 -0400 Subject: [PATCH 006/197] use nodes from actual file --- crates/ide-completion/src/context/analysis.rs | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index 4f5266051be1..aeec1ea6f775 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -883,18 +883,25 @@ fn classify_name_ref( } }; let make_path_kind_type = |ty: ast::Type| { - let location = type_location(ty.syntax()); - if let Some(p) = ty.syntax().parent() { - if ast::GenericArg::can_cast(p.kind()) || ast::GenericArgList::can_cast(p.kind()) { - if let Some(p) = p.parent().and_then(|p| p.parent()) { - if let Some(segment) = ast::PathSegment::cast(p) { - let path = segment.parent_path().top_path(); - dbg!(sema.resolve_path(&path)); - } + let location = type_location(ty.syntax()).unwrap_or(TypeLocation::Other); + match &location { + TypeLocation::TupleField => (), + TypeLocation::TypeAscription(_) => (), + TypeLocation::GenericArgList(args) => { + dbg!(&args); + if let Some(segment) = + args.as_ref().and_then(|args| ast::PathSegment::cast(args.syntax().parent()?)) + { + let path = dbg!(segment.parent_path().top_path()); + dbg!(sema.resolve_path(&path)); } } + TypeLocation::TypeBound => (), + TypeLocation::ImplTarget => (), + TypeLocation::ImplTrait => (), + TypeLocation::Other => (), } - PathKind::Type { location: location.unwrap_or(TypeLocation::Other) } + PathKind::Type { location } }; let mut kind_macro_call = |it: ast::MacroCall| { From b9ee4a51678ad4ed1bd93b9fc756b3d2877959d3 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Sun, 30 Jul 2023 15:36:42 -0400 Subject: [PATCH 007/197] working for path segments --- crates/ide-completion/src/completions/type.rs | 32 +++++++--- crates/ide-completion/src/context.rs | 2 +- crates/ide-completion/src/context/analysis.rs | 60 ++++++++++++------- crates/ide-completion/src/tests/type_pos.rs | 20 +++++-- 4 files changed, 76 insertions(+), 38 deletions(-) diff --git a/crates/ide-completion/src/completions/type.rs b/crates/ide-completion/src/completions/type.rs index e47054756389..de855242ee32 100644 --- a/crates/ide-completion/src/completions/type.rs +++ b/crates/ide-completion/src/completions/type.rs @@ -24,12 +24,23 @@ pub(crate) fn complete_type_path( // no values in type places ScopeDef::ModuleDef(Function(_) | Variant(_) | Static(_)) | ScopeDef::Local(_) => false, // unless its a constant in a generic arg list position - ScopeDef::ModuleDef(Const(_)) | ScopeDef::GenericParam(ConstParam(_)) => { - matches!(location, TypeLocation::GenericArgList(_)) - } - ScopeDef::ImplSelfType(_) => { - !matches!(location, TypeLocation::ImplTarget | TypeLocation::ImplTrait) - } + ScopeDef::ModuleDef(Const(_)) | ScopeDef::GenericParam(ConstParam(_)) => match location + { + TypeLocation::GenericArgList(location) => match location { + Some((_, Some(generic_param))) => { + matches!(generic_param, ast::GenericParam::ConstParam(_)) + } + _ => true, + }, + _ => false, + }, + ScopeDef::ImplSelfType(_) => match location { + TypeLocation::ImplTarget | TypeLocation::ImplTrait => false, + TypeLocation::GenericArgList(Some((_, Some(generic_param)))) => { + matches!(generic_param, ast::GenericParam::TypeParam(_)) + } + _ => true, + }, // Don't suggest attribute macros and derives. ScopeDef::ModuleDef(Macro(mac)) => mac.is_fn_like(ctx.db), // Type things are fine @@ -38,7 +49,12 @@ pub(crate) fn complete_type_path( ) | ScopeDef::AdtSelfType(_) | ScopeDef::Unknown - | ScopeDef::GenericParam(TypeParam(_)) => true, + | ScopeDef::GenericParam(TypeParam(_)) => match location { + TypeLocation::GenericArgList(Some((_, Some(generic_param)))) => { + matches!(generic_param, ast::GenericParam::TypeParam(_)) + } + _ => true, + }, } }; @@ -157,7 +173,7 @@ pub(crate) fn complete_type_path( }); return; } - TypeLocation::GenericArgList(Some(arg_list)) => { + TypeLocation::GenericArgList(Some((arg_list, generic_param))) => { let in_assoc_type_arg = ctx .original_token .parent_ancestors() diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs index 3cb65b2729ac..8ec5c6c8bfd2 100644 --- a/crates/ide-completion/src/context.rs +++ b/crates/ide-completion/src/context.rs @@ -155,7 +155,7 @@ pub(crate) struct ExprCtx { pub(crate) enum TypeLocation { TupleField, TypeAscription(TypeAscriptionTarget), - GenericArgList(Option), + GenericArgList(Option<(ast::GenericArgList, Option)>), TypeBound, ImplTarget, ImplTrait, diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index aeec1ea6f775..cc9e4581bed3 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -1,11 +1,11 @@ //! Module responsible for analyzing the code surrounding the cursor for completion. use std::iter; -use hir::{Semantics, Type, TypeInfo, Variant}; +use hir::{HasSource, Semantics, Type, TypeInfo, Variant}; use ide_db::{active_parameter::ActiveParameter, RootDatabase}; use syntax::{ algo::{find_node_at_offset, non_trivia_sibling}, - ast::{self, AttrKind, HasArgList, HasLoopBody, HasName, NameOrNameRef}, + ast::{self, AttrKind, HasArgList, HasGenericParams, HasLoopBody, HasName, NameOrNameRef}, match_ast, AstNode, AstToken, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextSize, T, }; @@ -774,9 +774,40 @@ fn classify_name_ref( ast::TypeBound(_) => TypeLocation::TypeBound, // is this case needed? ast::TypeBoundList(_) => TypeLocation::TypeBound, - ast::GenericArg(it) => TypeLocation::GenericArgList(find_opt_node_in_file_compensated(sema, original_file, it.syntax().parent().and_then(ast::GenericArgList::cast))), + ast::GenericArg(it) => { + let location = find_opt_node_in_file_compensated(sema, original_file, it.syntax().parent().and_then(ast::GenericArgList::cast)) + .map(|args| { + // Determine the index of the parameter in the `GenericArgList` + // (subtract 1 because `siblings` includes the node itself) + let param_idx = it.syntax().siblings(Direction::Prev).count() - 1; + let param = args + .syntax() + .parent() + .and_then(|p| ast::PathSegment::cast(p)) + .and_then(|segment| sema.resolve_path(&segment.parent_path().top_path())) + .and_then(|resolved| { + match resolved { + hir::PathResolution::Def(def) => match def { + hir::ModuleDef::Function(func) => { + let src = func.source(sema.db)?; + let params = src.value.generic_param_list()?; + params.generic_params().nth(param_idx) + } + _ => None, + }, + _ => None, + } + }); + (args, param) + }); + TypeLocation::GenericArgList(location) + }, // is this case needed? - ast::GenericArgList(it) => TypeLocation::GenericArgList(find_opt_node_in_file_compensated(sema, original_file, Some(it))), + ast::GenericArgList(it) => { + let location = find_opt_node_in_file_compensated(sema, original_file, Some(it)) + .map(|node| (node, None)); + TypeLocation::GenericArgList(location) + }, ast::TupleField(_) => TypeLocation::TupleField, _ => return None, } @@ -883,25 +914,8 @@ fn classify_name_ref( } }; let make_path_kind_type = |ty: ast::Type| { - let location = type_location(ty.syntax()).unwrap_or(TypeLocation::Other); - match &location { - TypeLocation::TupleField => (), - TypeLocation::TypeAscription(_) => (), - TypeLocation::GenericArgList(args) => { - dbg!(&args); - if let Some(segment) = - args.as_ref().and_then(|args| ast::PathSegment::cast(args.syntax().parent()?)) - { - let path = dbg!(segment.parent_path().top_path()); - dbg!(sema.resolve_path(&path)); - } - } - TypeLocation::TypeBound => (), - TypeLocation::ImplTarget => (), - TypeLocation::ImplTrait => (), - TypeLocation::Other => (), - } - PathKind::Type { location } + let location = type_location(ty.syntax()); + PathKind::Type { location: location.unwrap_or(TypeLocation::Other) } }; let mut kind_macro_call = |it: ast::MacroCall| { diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs index 4869ac17ad91..2a05aef17f94 100644 --- a/crates/ide-completion/src/tests/type_pos.rs +++ b/crates/ide-completion/src/tests/type_pos.rs @@ -726,15 +726,21 @@ fn completes_const_and_type_generics_separately() { r#" struct Foo; const X: usize = 0; -mod foo { - fn foo() {} -} +fn foo() {} fn main() { - self::foo::foo::(); + foo::(); } "#, expect![[r#" + en Enum + ma makro!(…) macro_rules! makro + md module st Foo + st Record + st Tuple + st Unit + tt Trait + un Union bt u32 kw crate:: kw self:: @@ -744,13 +750,15 @@ fn main() { r#" struct Foo; const X: usize = 0; -fn foo() {} +fn foo() {} fn main() { - foo::(); + foo::<_, $0>(); } "#, expect![[r#" + ct CONST ct X + ma makro!(…) macro_rules! makro kw crate:: kw self:: "#]], From 3205ed7a41ef016d0b445cf723c3eb5684956270 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Wed, 2 Aug 2023 09:19:56 -0400 Subject: [PATCH 008/197] simplify storing generic parameter attributes in item tree --- crates/hir-def/src/generics.rs | 27 ++++++++++---- crates/hir-def/src/item_tree/lower.rs | 51 ++++++++------------------- 2 files changed, 35 insertions(+), 43 deletions(-) diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index 6fe429c8d9a7..b0fb27e81d9b 100644 --- a/crates/hir-def/src/generics.rs +++ b/crates/hir-def/src/generics.rs @@ -21,7 +21,7 @@ use crate::{ db::DefDatabase, dyn_map::{keys, DynMap}, expander::Expander, - item_tree::ItemTree, + item_tree::{AttrOwner, ItemTree}, lower::LowerCtx, nameres::{DefMap, MacroSubNs}, src::{HasChildSource, HasSource}, @@ -215,9 +215,14 @@ impl GenericParams { } } - pub(crate) fn fill(&mut self, lower_ctx: &LowerCtx<'_>, node: &dyn HasGenericParams) { + pub(crate) fn fill( + &mut self, + lower_ctx: &LowerCtx<'_>, + node: &dyn HasGenericParams, + add_param_attrs: impl FnMut(AttrOwner, ast::GenericParam), + ) { if let Some(params) = node.generic_param_list() { - self.fill_params(lower_ctx, params) + self.fill_params(lower_ctx, params, add_param_attrs) } if let Some(where_clause) = node.where_clause() { self.fill_where_predicates(lower_ctx, where_clause); @@ -235,7 +240,12 @@ impl GenericParams { } } - fn fill_params(&mut self, lower_ctx: &LowerCtx<'_>, params: ast::GenericParamList) { + fn fill_params( + &mut self, + lower_ctx: &LowerCtx<'_>, + params: ast::GenericParamList, + mut add_param_attrs: impl FnMut(AttrOwner, ast::GenericParam), + ) { for type_or_const_param in params.type_or_const_params() { match type_or_const_param { ast::TypeOrConstParam::Type(type_param) => { @@ -249,13 +259,14 @@ impl GenericParams { default, provenance: TypeParamProvenance::TypeParamList, }; - self.type_or_consts.alloc(param.into()); + let idx = self.type_or_consts.alloc(param.into()); let type_ref = TypeRef::Path(name.into()); self.fill_bounds( lower_ctx, type_param.type_bound_list(), Either::Left(type_ref), ); + add_param_attrs(idx.into(), ast::GenericParam::TypeParam(type_param)); } ast::TypeOrConstParam::Const(const_param) => { let name = const_param.name().map_or_else(Name::missing, |it| it.as_name()); @@ -267,7 +278,8 @@ impl GenericParams { ty: Interned::new(ty), has_default: const_param.default_val().is_some(), }; - self.type_or_consts.alloc(param.into()); + let idx = self.type_or_consts.alloc(param.into()); + add_param_attrs(idx.into(), ast::GenericParam::ConstParam(const_param)); } } } @@ -275,13 +287,14 @@ impl GenericParams { let name = lifetime_param.lifetime().map_or_else(Name::missing, |lt| Name::new_lifetime(<)); let param = LifetimeParamData { name: name.clone() }; - self.lifetimes.alloc(param); + let idx = self.lifetimes.alloc(param); let lifetime_ref = LifetimeRef::new_name(name); self.fill_bounds( lower_ctx, lifetime_param.type_bound_list(), Either::Right(lifetime_ref), ); + add_param_attrs(idx.into(), ast::GenericParam::LifetimeParam(lifetime_param)); } } diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index 7dffd6fc18a1..d66ea743e869 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -602,44 +602,23 @@ impl<'a> Ctx<'a> { generics.fill_bounds(&self.body_ctx, bounds, Either::Left(self_param)); } - generics.fill(&self.body_ctx, node); + let add_param_attrs = |item, param| { + let attrs = RawAttrs::new(self.db.upcast(), ¶m, self.body_ctx.hygiene()); + // This is identical to the body of `Ctx::add_attrs()` but we can't call that here + // because it requires `&mut self` and the call to `generics.fill()` below also + // references `self`. + match self.tree.attrs.entry(item) { + Entry::Occupied(mut entry) => { + *entry.get_mut() = entry.get().merge(attrs); + } + Entry::Vacant(entry) => { + entry.insert(attrs); + } + } + }; + generics.fill(&self.body_ctx, node, add_param_attrs); generics.shrink_to_fit(); - - if let Some(params) = node.generic_param_list() { - let params_by_name: FxHashMap<_, _> = params - .generic_params() - .filter_map(|param| { - let name = match ¶m { - ast::GenericParam::ConstParam(param) => param.name()?.as_name(), - ast::GenericParam::LifetimeParam(param) => { - Name::new_lifetime(¶m.lifetime()?) - } - ast::GenericParam::TypeParam(param) => param.name()?.as_name(), - }; - Some((name, param)) - }) - .collect(); - for (idx, param) in generics.type_or_consts.iter() { - if let Some(name) = param.name() { - if let Some(param) = params_by_name.get(name) { - self.add_attrs( - idx.into(), - RawAttrs::new(self.db.upcast(), param, self.hygiene()), - ); - } - } - } - for (idx, param) in generics.lifetimes.iter() { - if let Some(param) = params_by_name.get(¶m.name) { - self.add_attrs( - idx.into(), - RawAttrs::new(self.db.upcast(), param, self.hygiene()), - ); - } - } - } - Interned::new(generics) } From f4038a6bf1927aee3c5a34d7ffe14da4e7ba0560 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Tue, 1 Aug 2023 18:15:32 -0400 Subject: [PATCH 009/197] support AssocTypeArg and MethodCalls --- crates/ide-completion/src/context/analysis.rs | 94 +++++++++++----- crates/ide-completion/src/tests/type_pos.rs | 100 ++++++++++++++++-- 2 files changed, 159 insertions(+), 35 deletions(-) diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index cc9e4581bed3..7fd3147a7391 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -719,6 +719,70 @@ fn classify_name_ref( None }; + let generic_arg_location = |arg: ast::GenericArg| { + let location = find_opt_node_in_file_compensated( + sema, + original_file, + arg.syntax().parent().and_then(ast::GenericArgList::cast), + ) + .map(|args| { + // Determine the index of the parameter in the `GenericArgList` + // (subtract 1 because `siblings` includes the node itself) + let param_idx = arg.syntax().siblings(Direction::Prev).count() - 1; + let parent = args.syntax().parent(); + let param = parent.and_then(|parent| { + match_ast! { + match parent { + ast::PathSegment(segment) => { + match sema.resolve_path(&segment.parent_path().top_path())? { + hir::PathResolution::Def(def) => match def { + hir::ModuleDef::Function(func) => { + let src = func.source(sema.db)?; + let params = src.value.generic_param_list()?; + params.generic_params().nth(param_idx) + } + _ => None, + }, + _ => None, + } + }, + ast::MethodCallExpr(call) => { + let func = sema.resolve_method_call(&call)?; + let src = func.source(sema.db)?; + let params = src.value.generic_param_list()?; + params.generic_params().nth(param_idx) + }, + ast::AssocTypeArg(arg) => { + let trait_ = ast::PathSegment::cast(arg.syntax().parent()?.parent()?)?; + match sema.resolve_path(&trait_.parent_path().top_path())? { + hir::PathResolution::Def(def) => match def { + hir::ModuleDef::Trait(trait_) => { + let trait_items = trait_.items(sema.db); + let assoc_ty = trait_items.iter().find_map(|item| match item { + hir::AssocItem::TypeAlias(assoc_ty) => { + (assoc_ty.name(sema.db).as_str()? == arg.name_ref()?.text()) + .then_some(assoc_ty) + }, + _ => None, + })?; + let src = assoc_ty.source(sema.db)?; + let params = src.value.generic_param_list()?; + params.generic_params().nth(param_idx) + } + _ => None, + }, + _ => None, + } + }, + _ => None, + } + } + }); + (args, param) + }); + TypeLocation::GenericArgList(location) + }; + let type_location = |node: &SyntaxNode| { let parent = node.parent()?; let res = match_ast! { @@ -774,34 +838,8 @@ fn classify_name_ref( ast::TypeBound(_) => TypeLocation::TypeBound, // is this case needed? ast::TypeBoundList(_) => TypeLocation::TypeBound, - ast::GenericArg(it) => { - let location = find_opt_node_in_file_compensated(sema, original_file, it.syntax().parent().and_then(ast::GenericArgList::cast)) - .map(|args| { - // Determine the index of the parameter in the `GenericArgList` - // (subtract 1 because `siblings` includes the node itself) - let param_idx = it.syntax().siblings(Direction::Prev).count() - 1; - let param = args - .syntax() - .parent() - .and_then(|p| ast::PathSegment::cast(p)) - .and_then(|segment| sema.resolve_path(&segment.parent_path().top_path())) - .and_then(|resolved| { - match resolved { - hir::PathResolution::Def(def) => match def { - hir::ModuleDef::Function(func) => { - let src = func.source(sema.db)?; - let params = src.value.generic_param_list()?; - params.generic_params().nth(param_idx) - } - _ => None, - }, - _ => None, - } - }); - (args, param) - }); - TypeLocation::GenericArgList(location) - }, + ast::TypeArg(it) => generic_arg_location(ast::GenericArg::TypeArg(it)), + ast::GenericArg(it) => generic_arg_location(it), // is this case needed? ast::GenericArgList(it) => { let location = find_opt_node_in_file_compensated(sema, original_file, Some(it)) diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs index 2a05aef17f94..67110b3d7fbe 100644 --- a/crates/ide-completion/src/tests/type_pos.rs +++ b/crates/ide-completion/src/tests/type_pos.rs @@ -724,11 +724,70 @@ pub struct S; fn completes_const_and_type_generics_separately() { check( r#" -struct Foo; + struct Foo; + const X: usize = 0; + fn foo() {} + fn main() { + foo::(); + } + "#, + expect![[r#" + en Enum + ma makro!(…) macro_rules! makro + md module + st Foo + st Record + st Tuple + st Unit + tt Trait + un Union + bt u32 + kw crate:: + kw self:: + "#]], + ); + check( + r#" + struct Foo; + const X: usize = 0; + fn foo() {} + fn main() { + foo::<_, $0>(); + } + "#, + expect![[r#" + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], + ); + + check( + r#" const X: usize = 0; -fn foo() {} +struct Foo; +impl Foo { fn bar(self) {} } fn main() { - foo::(); + Foo.bar::(); +} +"#, + expect![[r#" + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], + ); + check( + r#" +const X: usize = 0; +struct Foo; +impl Foo { fn bar(self) {} } +fn main() { + Foo.bar::<_, $0>(); } "#, expect![[r#" @@ -746,14 +805,15 @@ fn main() { kw self:: "#]], ); + check( r#" -struct Foo; const X: usize = 0; -fn foo() {} -fn main() { - foo::<_, $0>(); +struct Foo; +trait Bar { + type Baz; } +fn foo = ()>>() {} "#, expect![[r#" ct CONST @@ -763,4 +823,30 @@ fn main() { kw self:: "#]], ); + check( + r#" +const X: usize = 0; +struct Foo; +trait Bar { + type Baz; +} +fn foo = ()>>() {} +"#, + expect![[r#" + en Enum + ma makro!(…) macro_rules! makro + md module + st Foo + st Record + st Tuple + st Unit + tt Bar + tt Trait + tp T + un Union + bt u32 + kw crate:: + kw self:: + "#]], + ); } From 1b3e20fe686e5544feb134a7b1ffcd406a1189e6 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Wed, 2 Aug 2023 17:59:26 -0400 Subject: [PATCH 010/197] handle more cases --- crates/ide-completion/src/completions/type.rs | 2 +- crates/ide-completion/src/context/analysis.rs | 44 ++-- crates/ide-completion/src/tests/type_pos.rs | 196 ++++++++++-------- 3 files changed, 136 insertions(+), 106 deletions(-) diff --git a/crates/ide-completion/src/completions/type.rs b/crates/ide-completion/src/completions/type.rs index de855242ee32..69b1e1fd11fc 100644 --- a/crates/ide-completion/src/completions/type.rs +++ b/crates/ide-completion/src/completions/type.rs @@ -173,7 +173,7 @@ pub(crate) fn complete_type_path( }); return; } - TypeLocation::GenericArgList(Some((arg_list, generic_param))) => { + TypeLocation::GenericArgList(Some((arg_list, _))) => { let in_assoc_type_arg = ctx .original_token .parent_ancestors() diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index 7fd3147a7391..4bd429c57234 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -726,20 +726,30 @@ fn classify_name_ref( arg.syntax().parent().and_then(ast::GenericArgList::cast), ) .map(|args| { - // Determine the index of the parameter in the `GenericArgList` - // (subtract 1 because `siblings` includes the node itself) - let param_idx = arg.syntax().siblings(Direction::Prev).count() - 1; - let parent = args.syntax().parent(); - let param = parent.and_then(|parent| { - match_ast! { + let param = (|| { + let parent = args.syntax().parent()?; + let params = match_ast! { match parent { ast::PathSegment(segment) => { match sema.resolve_path(&segment.parent_path().top_path())? { hir::PathResolution::Def(def) => match def { hir::ModuleDef::Function(func) => { - let src = func.source(sema.db)?; - let params = src.value.generic_param_list()?; - params.generic_params().nth(param_idx) + func.source(sema.db)?.value.generic_param_list() + } + hir::ModuleDef::Adt(adt) => { + adt.source(sema.db)?.value.generic_param_list() + } + hir::ModuleDef::Variant(variant) => { + variant.parent_enum(sema.db).source(sema.db)?.value.generic_param_list() + } + hir::ModuleDef::Trait(trait_) => { + trait_.source(sema.db)?.value.generic_param_list() + } + hir::ModuleDef::TraitAlias(trait_) => { + trait_.source(sema.db)?.value.generic_param_list() + } + hir::ModuleDef::TypeAlias(ty_) => { + ty_.source(sema.db)?.value.generic_param_list() } _ => None, }, @@ -748,9 +758,7 @@ fn classify_name_ref( }, ast::MethodCallExpr(call) => { let func = sema.resolve_method_call(&call)?; - let src = func.source(sema.db)?; - let params = src.value.generic_param_list()?; - params.generic_params().nth(param_idx) + func.source(sema.db)?.value.generic_param_list() }, ast::AssocTypeArg(arg) => { let trait_ = ast::PathSegment::cast(arg.syntax().parent()?.parent()?)?; @@ -765,9 +773,7 @@ fn classify_name_ref( }, _ => None, })?; - let src = assoc_ty.source(sema.db)?; - let params = src.value.generic_param_list()?; - params.generic_params().nth(param_idx) + assoc_ty.source(sema.db)?.value.generic_param_list() } _ => None, }, @@ -776,8 +782,12 @@ fn classify_name_ref( }, _ => None, } - } - }); + }?; + // Determine the index of the parameter in the `GenericArgList` + // (subtract 1 because `siblings` includes the node itself) + let param_idx = arg.syntax().siblings(Direction::Prev).count() - 1; + params.generic_params().nth(param_idx) + })(); (args, param) }); TypeLocation::GenericArgList(location) diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs index 67110b3d7fbe..27bcf4c630ae 100644 --- a/crates/ide-completion/src/tests/type_pos.rs +++ b/crates/ide-completion/src/tests/type_pos.rs @@ -722,16 +722,31 @@ pub struct S; #[test] fn completes_const_and_type_generics_separately() { - check( + let type_completion_cases = [ + // Function r#" - struct Foo; - const X: usize = 0; - fn foo() {} - fn main() { - foo::(); - } - "#, - expect![[r#" +struct Foo; +const X: usize = 0; +fn foo() {} +fn main() { + foo::(); +} + "#, + // Method + r#" +const X: usize = 0; +struct Foo; +impl Foo { fn bar(self) {} } +fn main() { + Foo.bar::<_, $0>(); +} + "#, + ]; + + for case in type_completion_cases { + check( + case, + expect![[r#" en Enum ma makro!(…) macro_rules! makro md module @@ -745,66 +760,8 @@ fn completes_const_and_type_generics_separately() { kw crate:: kw self:: "#]], - ); - check( - r#" - struct Foo; - const X: usize = 0; - fn foo() {} - fn main() { - foo::<_, $0>(); + ) } - "#, - expect![[r#" - ct CONST - ct X - ma makro!(…) macro_rules! makro - kw crate:: - kw self:: - "#]], - ); - - check( - r#" -const X: usize = 0; -struct Foo; -impl Foo { fn bar(self) {} } -fn main() { - Foo.bar::(); -} -"#, - expect![[r#" - ct CONST - ct X - ma makro!(…) macro_rules! makro - kw crate:: - kw self:: - "#]], - ); - check( - r#" -const X: usize = 0; -struct Foo; -impl Foo { fn bar(self) {} } -fn main() { - Foo.bar::<_, $0>(); -} -"#, - expect![[r#" - en Enum - ma makro!(…) macro_rules! makro - md module - st Foo - st Record - st Tuple - st Unit - tt Trait - un Union - bt u32 - kw crate:: - kw self:: - "#]], - ); check( r#" @@ -813,25 +770,8 @@ struct Foo; trait Bar { type Baz; } -fn foo = ()>>() {} -"#, - expect![[r#" - ct CONST - ct X - ma makro!(…) macro_rules! makro - kw crate:: - kw self:: - "#]], - ); - check( - r#" -const X: usize = 0; -struct Foo; -trait Bar { - type Baz; -} -fn foo = ()>>() {} -"#, +fn foo(_: impl Bar = ()>) {} + "#, expect![[r#" en Enum ma makro!(…) macro_rules! makro @@ -842,11 +782,91 @@ fn foo = ()>>() {} st Unit tt Bar tt Trait - tp T un Union bt u32 kw crate:: kw self:: "#]], ); + + let const_completion_cases = [ + // Function params + r#" +struct Foo; +const X: usize = 0; +fn foo() {} +fn main() { + foo::<_, $0>(); +} + "#, + // Method params + r#" +const X: usize = 0; +struct Foo; +impl Foo { fn bar(self) {} } +fn main() { + Foo.bar::(); +} + "#, + // Associated type params + r#" +const X: usize = 0; +struct Foo; +trait Bar { + type Baz; +} +fn foo = ()>>() {} + "#, + // Type params + r#" +const X: usize = 0; +struct Foo(T); +fn main() { + let _: Foo::<_, $0> = todo!(); +} + "#, + // Enum variant params + r#" +const X: usize = 0; +struct Foo(T); +type Bar = Foo; +fn main() { + let _: Bar:: = todo!(); +} + "#, + r#" +const X: usize = 0; +enum Foo { A(T), B } +fn main() { + Foo::B::<(), $0>; +} + "#, + // Trait params + r#" +const X: usize = 0; +trait Foo {} +impl Foo<(), $0> for () {} + "#, + // Trait alias params + r#" +#![feature(trait_alias)] +const X: usize = 0; +trait Foo {} +trait Bar = Foo; +fn foo>() {} + "#, + ]; + + for case in const_completion_cases { + check( + case, + expect![[r#" + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], + ); + } } From 50db877bfa8a03dfaddb80f03737d62bce38f9a5 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Sat, 5 Aug 2023 08:00:39 -0400 Subject: [PATCH 011/197] optimization and #[cfg] filtering for function generic params --- crates/hir-def/src/generics.rs | 53 +++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index b0fb27e81d9b..540fa115a00b 100644 --- a/crates/hir-def/src/generics.rs +++ b/crates/hir-def/src/generics.rs @@ -159,17 +159,47 @@ impl GenericParams { let krate = def.module(db).krate; let cfg_options = db.crate_graph(); let cfg_options = &cfg_options[krate].cfg_options; - let enabled_params = |params: &GenericParams, item_tree: &ItemTree| { + + // Returns the generic parameters that are enabled under the current `#[cfg]` options + let enabled_params = |params: &Interned, item_tree: &ItemTree| { let enabled = |param| item_tree.attrs(db, krate, param).is_cfg_enabled(cfg_options); - Interned::new(GenericParams { - type_or_consts: (params.type_or_consts.iter()) - .filter_map(|(idx, param)| enabled(idx.into()).then(|| param.clone())) - .collect(), - lifetimes: (params.lifetimes.iter()) - .filter_map(|(idx, param)| enabled(idx.into()).then(|| param.clone())) - .collect(), - where_predicates: params.where_predicates.clone(), - }) + + // In the common case, no parameters will by disabled by `#[cfg]` attributes. + // Therefore, make a first pass to check if all parameters are enabled and, if so, + // clone the `Interned` instead of recreating an identical copy. + let all_type_or_consts_enabled = + params.type_or_consts.iter().all(|(idx, _)| enabled(idx.into())); + let all_lifetimes_enabled = params.lifetimes.iter().all(|(idx, _)| enabled(idx.into())); + + if all_type_or_consts_enabled && all_lifetimes_enabled { + params.clone() + } else { + Interned::new(GenericParams { + type_or_consts: all_type_or_consts_enabled + .then(|| params.type_or_consts.clone()) + .unwrap_or_else(|| { + params + .type_or_consts + .iter() + .filter_map(|(idx, param)| { + enabled(idx.into()).then(|| param.clone()) + }) + .collect() + }), + lifetimes: all_lifetimes_enabled + .then(|| params.lifetimes.clone()) + .unwrap_or_else(|| { + params + .lifetimes + .iter() + .filter_map(|(idx, param)| { + enabled(idx.into()).then(|| param.clone()) + }) + .collect() + }), + where_predicates: params.where_predicates.clone(), + }) + } }; macro_rules! id_to_generics { ($id:ident) => {{ @@ -186,7 +216,8 @@ impl GenericParams { let tree = loc.id.item_tree(db); let item = &tree[loc.id.value]; - let mut generic_params = GenericParams::clone(&item.explicit_generic_params); + let enabled_params = enabled_params(&item.explicit_generic_params, &tree); + let mut generic_params = GenericParams::clone(&enabled_params); let module = loc.container.module(db); let func_data = db.function_data(id); From ee39905370c84085335276b49c04d58399cb3697 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Sat, 5 Aug 2023 08:10:00 -0400 Subject: [PATCH 012/197] update tests --- crates/ide-completion/src/tests/type_pos.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs index 27bcf4c630ae..6369f31788cf 100644 --- a/crates/ide-completion/src/tests/type_pos.rs +++ b/crates/ide-completion/src/tests/type_pos.rs @@ -384,10 +384,8 @@ trait Trait2: Trait1 { fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {} "#, expect![[r#" - ct CONST - cp CONST_PARAM en Enum - ma makro!(…) macro_rules! makro + ma makro!(…) macro_rules! makro md module st Record st Tuple @@ -437,7 +435,6 @@ trait Tr { impl Tr<$0 "#, expect![[r#" - ct CONST en Enum ma makro!(…) macro_rules! makro md module @@ -485,7 +482,6 @@ trait MyTrait { fn f(t: impl MyTrait { fn f(t: impl MyTrait { fn f(t: impl MyTrait { fn f(t: impl MyTrait = ()>>() {} const X: usize = 0; struct Foo(T); fn main() { - let _: Foo::<_, $0> = todo!(); + let _: Foo::<_, $0> = Foo(()); } "#, // Enum variant params @@ -831,7 +824,7 @@ const X: usize = 0; struct Foo(T); type Bar = Foo; fn main() { - let _: Bar:: = todo!(); + let _: Bar:: = Bar(()); } "#, r#" From 5e6d646ccc0677f6ea68da7ef964cfee2c1e28f0 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Sat, 5 Aug 2023 08:14:44 -0400 Subject: [PATCH 013/197] remove unnecessary branch --- crates/ide-completion/src/context/analysis.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index 4bd429c57234..8de4d0827f9c 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -848,7 +848,6 @@ fn classify_name_ref( ast::TypeBound(_) => TypeLocation::TypeBound, // is this case needed? ast::TypeBoundList(_) => TypeLocation::TypeBound, - ast::TypeArg(it) => generic_arg_location(ast::GenericArg::TypeArg(it)), ast::GenericArg(it) => generic_arg_location(it), // is this case needed? ast::GenericArgList(it) => { From d48606fefed56931414313d4f10ac8b53756c5df Mon Sep 17 00:00:00 2001 From: Max Heller Date: Sat, 5 Aug 2023 08:22:58 -0400 Subject: [PATCH 014/197] unroll test loop --- crates/ide-completion/src/tests/type_pos.rs | 197 +++++++++++++------- 1 file changed, 134 insertions(+), 63 deletions(-) diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs index 6369f31788cf..31ff9cf956e2 100644 --- a/crates/ide-completion/src/tests/type_pos.rs +++ b/crates/ide-completion/src/tests/type_pos.rs @@ -715,8 +715,8 @@ pub struct S; #[test] fn completes_const_and_type_generics_separately() { - let type_completion_cases = [ - // Function + // Function generic params + check( r#" struct Foo; const X: usize = 0; @@ -725,7 +725,41 @@ fn main() { foo::(); } "#, - // Method + expect![[r#" + en Enum + ma makro!(…) macro_rules! makro + md module + st Foo + st Record + st Tuple + st Unit + tt Trait + un Union + bt u32 + kw crate:: + kw self:: + "#]], + ); + check( + r#" +struct Foo; +const X: usize = 0; +fn foo() {} +fn main() { + foo::<_, $0>(); +} + "#, + expect![[r#" + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], + ); + + // Method generic params + check( r#" const X: usize = 0; struct Foo; @@ -734,28 +768,40 @@ fn main() { Foo.bar::<_, $0>(); } "#, - ]; - - for case in type_completion_cases { - check( - case, - expect![[r#" - en Enum - ma makro!(…) macro_rules! makro - md module - st Foo - st Record - st Tuple - st Unit - tt Trait - un Union - bt u32 - kw crate:: - kw self:: - "#]], - ) - } + expect![[r#" + en Enum + ma makro!(…) macro_rules! makro + md module + st Foo + st Record + st Tuple + st Unit + tt Trait + un Union + bt u32 + kw crate:: + kw self:: + "#]], + ); + check( + r#" +const X: usize = 0; +struct Foo; +impl Foo { fn bar(self) {} } +fn main() { + Foo.bar::(); +} + "#, + expect![[r#" + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], + ); + // Associated type generic params check( r#" const X: usize = 0; @@ -781,27 +827,7 @@ fn foo(_: impl Bar = ()>) {} kw self:: "#]], ); - - let const_completion_cases = [ - // Function params - r#" -struct Foo; -const X: usize = 0; -fn foo() {} -fn main() { - foo::<_, $0>(); -} - "#, - // Method params - r#" -const X: usize = 0; -struct Foo; -impl Foo { fn bar(self) {} } -fn main() { - Foo.bar::(); -} - "#, - // Associated type params + check( r#" const X: usize = 0; struct Foo; @@ -810,7 +836,17 @@ trait Bar { } fn foo = ()>>() {} "#, - // Type params + expect![[r#" + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], + ); + + // Type generic params + check( r#" const X: usize = 0; struct Foo(T); @@ -818,7 +854,17 @@ fn main() { let _: Foo::<_, $0> = Foo(()); } "#, - // Enum variant params + expect![[r#" + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], + ); + + // Type alias generic params + check( r#" const X: usize = 0; struct Foo(T); @@ -827,6 +873,17 @@ fn main() { let _: Bar:: = Bar(()); } "#, + expect![[r#" + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], + ); + + // Enum variant params + check( r#" const X: usize = 0; enum Foo { A(T), B } @@ -834,13 +891,33 @@ fn main() { Foo::B::<(), $0>; } "#, - // Trait params + expect![[r#" + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], + ); + + // Trait params + check( r#" const X: usize = 0; trait Foo {} impl Foo<(), $0> for () {} "#, - // Trait alias params + expect![[r#" + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], + ); + + // Trait alias params + check( r#" #![feature(trait_alias)] const X: usize = 0; @@ -848,18 +925,12 @@ trait Foo {} trait Bar = Foo; fn foo>() {} "#, - ]; - - for case in const_completion_cases { - check( - case, - expect![[r#" - ct CONST - ct X - ma makro!(…) macro_rules! makro - kw crate:: - kw self:: - "#]], - ); - } + expect![[r#" + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], + ); } From bed1114b8ba258acb243c938e7b2915424426474 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Sat, 5 Aug 2023 09:07:29 -0400 Subject: [PATCH 015/197] handle omitted lifetime params --- crates/ide-completion/src/completions/type.rs | 11 +- crates/ide-completion/src/context/analysis.rs | 24 +- crates/ide-completion/src/tests/type_pos.rs | 345 ++++++++++-------- 3 files changed, 223 insertions(+), 157 deletions(-) diff --git a/crates/ide-completion/src/completions/type.rs b/crates/ide-completion/src/completions/type.rs index 69b1e1fd11fc..f4efaecba8af 100644 --- a/crates/ide-completion/src/completions/type.rs +++ b/crates/ide-completion/src/completions/type.rs @@ -20,7 +20,16 @@ pub(crate) fn complete_type_path( let scope_def_applicable = |def| { use hir::{GenericParam::*, ModuleDef::*}; match def { - ScopeDef::GenericParam(LifetimeParam(_)) | ScopeDef::Label(_) => false, + ScopeDef::GenericParam(LifetimeParam(_)) => { + matches!( + location, + TypeLocation::GenericArgList(Some(( + _, + Some(ast::GenericParam::LifetimeParam(_)) + ))) + ) + } + ScopeDef::Label(_) => false, // no values in type places ScopeDef::ModuleDef(Function(_) | Variant(_) | Static(_)) | ScopeDef::Local(_) => false, // unless its a constant in a generic arg list position diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index 8de4d0827f9c..dfceb67f2096 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -783,9 +783,27 @@ fn classify_name_ref( _ => None, } }?; - // Determine the index of the parameter in the `GenericArgList` - // (subtract 1 because `siblings` includes the node itself) - let param_idx = arg.syntax().siblings(Direction::Prev).count() - 1; + // Determine the index of the argument in the `GenericArgList` and match it with + // the corresponding parameter in the `GenericParamList`. + // Since lifetime parameters are often omitted, ignore them for the purposes of + // matching the argument with its parameter unless a lifetime argument is provided + // explicitly. That is, for `struct S<'a, 'b, T>`, match `S::<$0>` to to `T` and + // `S::<'a, $0, _>` to `'b`. + let mut explicit_lifetime_arg = false; + let arg_idx = arg + .syntax() + .siblings(Direction::Prev) + // Skip the node itself + .skip(1) + .map(|arg| if ast::LifetimeArg::can_cast(arg.kind()) { explicit_lifetime_arg = true }) + .count(); + let param_idx = if explicit_lifetime_arg { + arg_idx + } else { + // Lifetimes parameters always precede type and generic parameters, + // so offset the argument index by the total number of lifetime params + arg_idx + params.lifetime_params().count() + }; params.generic_params().nth(param_idx) })(); (args, param) diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs index 31ff9cf956e2..4b4413910941 100644 --- a/crates/ide-completion/src/tests/type_pos.rs +++ b/crates/ide-completion/src/tests/type_pos.rs @@ -718,216 +718,255 @@ fn completes_const_and_type_generics_separately() { // Function generic params check( r#" -struct Foo; -const X: usize = 0; -fn foo() {} -fn main() { - foo::(); -} - "#, + struct Foo; + const X: usize = 0; + fn foo() {} + fn main() { + foo::(); + } + "#, expect![[r#" - en Enum - ma makro!(…) macro_rules! makro - md module - st Foo - st Record - st Tuple - st Unit - tt Trait - un Union - bt u32 - kw crate:: - kw self:: - "#]], + en Enum + ma makro!(…) macro_rules! makro + md module + st Foo + st Record + st Tuple + st Unit + tt Trait + un Union + bt u32 + kw crate:: + kw self:: + "#]], ); check( r#" -struct Foo; -const X: usize = 0; -fn foo() {} -fn main() { - foo::<_, $0>(); -} - "#, + struct Foo; + const X: usize = 0; + fn foo() {} + fn main() { + foo::<_, $0>(); + } + "#, expect![[r#" - ct CONST - ct X - ma makro!(…) macro_rules! makro - kw crate:: - kw self:: - "#]], + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], ); // Method generic params check( r#" -const X: usize = 0; -struct Foo; -impl Foo { fn bar(self) {} } -fn main() { - Foo.bar::<_, $0>(); -} - "#, + const X: usize = 0; + struct Foo; + impl Foo { fn bar(self) {} } + fn main() { + Foo.bar::<_, $0>(); + } + "#, expect![[r#" - en Enum - ma makro!(…) macro_rules! makro - md module - st Foo - st Record - st Tuple - st Unit - tt Trait - un Union - bt u32 - kw crate:: - kw self:: - "#]], + en Enum + ma makro!(…) macro_rules! makro + md module + st Foo + st Record + st Tuple + st Unit + tt Trait + un Union + bt u32 + kw crate:: + kw self:: + "#]], ); check( r#" -const X: usize = 0; -struct Foo; -impl Foo { fn bar(self) {} } -fn main() { - Foo.bar::(); -} - "#, + const X: usize = 0; + struct Foo; + impl Foo { fn bar(self) {} } + fn main() { + Foo.bar::(); + } + "#, expect![[r#" - ct CONST - ct X - ma makro!(…) macro_rules! makro - kw crate:: - kw self:: - "#]], + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], ); // Associated type generic params check( r#" -const X: usize = 0; -struct Foo; -trait Bar { - type Baz; -} -fn foo(_: impl Bar = ()>) {} - "#, + const X: usize = 0; + struct Foo; + trait Bar { + type Baz; + } + fn foo(_: impl Bar = ()>) {} + "#, expect![[r#" - en Enum - ma makro!(…) macro_rules! makro - md module - st Foo - st Record - st Tuple - st Unit - tt Bar - tt Trait - un Union - bt u32 - kw crate:: - kw self:: - "#]], + en Enum + ma makro!(…) macro_rules! makro + md module + st Foo + st Record + st Tuple + st Unit + tt Bar + tt Trait + un Union + bt u32 + kw crate:: + kw self:: + "#]], ); check( r#" -const X: usize = 0; -struct Foo; -trait Bar { - type Baz; -} -fn foo = ()>>() {} - "#, + const X: usize = 0; + struct Foo; + trait Bar { + type Baz; + } + fn foo = ()>>() {} + "#, expect![[r#" - ct CONST - ct X - ma makro!(…) macro_rules! makro - kw crate:: - kw self:: - "#]], + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], ); // Type generic params check( r#" -const X: usize = 0; -struct Foo(T); -fn main() { - let _: Foo::<_, $0> = Foo(()); -} - "#, + const X: usize = 0; + struct Foo(T); + fn main() { + let _: Foo::<_, $0> = Foo(()); + } + "#, expect![[r#" - ct CONST - ct X - ma makro!(…) macro_rules! makro - kw crate:: - kw self:: - "#]], + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], ); // Type alias generic params check( r#" -const X: usize = 0; -struct Foo(T); -type Bar = Foo; -fn main() { - let _: Bar:: = Bar(()); -} - "#, + const X: usize = 0; + struct Foo(T); + type Bar = Foo; + fn main() { + let _: Bar:: = Bar(()); + } + "#, expect![[r#" - ct CONST - ct X - ma makro!(…) macro_rules! makro - kw crate:: - kw self:: - "#]], + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], ); // Enum variant params check( r#" -const X: usize = 0; -enum Foo { A(T), B } -fn main() { - Foo::B::<(), $0>; -} - "#, + const X: usize = 0; + enum Foo { A(T), B } + fn main() { + Foo::B::<(), $0>; + } + "#, expect![[r#" - ct CONST - ct X - ma makro!(…) macro_rules! makro - kw crate:: - kw self:: - "#]], + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], ); // Trait params check( r#" -const X: usize = 0; -trait Foo {} -impl Foo<(), $0> for () {} - "#, + const X: usize = 0; + trait Foo {} + impl Foo<(), $0> for () {} + "#, expect![[r#" - ct CONST - ct X - ma makro!(…) macro_rules! makro - kw crate:: - kw self:: - "#]], + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], ); // Trait alias params check( r#" -#![feature(trait_alias)] -const X: usize = 0; -trait Foo {} -trait Bar = Foo; -fn foo>() {} + #![feature(trait_alias)] + const X: usize = 0; + trait Foo {} + trait Bar = Foo; + fn foo>() {} + "#, + expect![[r#" + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], + ); + + // Omitted lifetime params + check( + r#" +struct S<'a, 'b, const C: usize, T>(core::marker::PhantomData<&'a &'b T>); +fn foo<'a>() { S::; } "#, expect![[r#" ct CONST - ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], + ); + // Explicit lifetime params + check( + r#" +struct S<'a, 'b, const C: usize, T>(core::marker::PhantomData<&'a &'b T>); +fn foo<'a>() { S::<'static, 'static, F$0, _>; } + "#, + expect![[r#" + ct CONST + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], + ); + check( + r#" +struct S<'a, 'b, const C: usize, T>(core::marker::PhantomData<&'a &'b T>); +fn foo<'a>() { S::<'static, F$0, _, _>; } + "#, + expect![[r#" + lt 'a ma makro!(…) macro_rules! makro kw crate:: kw self:: From 9b636e23265705f5ca4f5965a0e207fefd869990 Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Sun, 6 Aug 2023 01:46:29 +0330 Subject: [PATCH 016/197] Support `libc::getenv` in mir interpreter --- crates/base-db/src/fixture.rs | 4 ++- crates/base-db/src/input.rs | 6 +++++ crates/hir-ty/src/mir/eval/shim.rs | 32 ++++++++++++++++++++++ crates/hir-ty/src/mir/eval/tests.rs | 42 +++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 1 deletion(-) diff --git a/crates/base-db/src/fixture.rs b/crates/base-db/src/fixture.rs index 323ee4260e4f..aaac0fc37907 100644 --- a/crates/base-db/src/fixture.rs +++ b/crates/base-db/src/fixture.rs @@ -130,6 +130,7 @@ impl ChangeFixture { let mut default_crate_root: Option = None; let mut default_target_data_layout: Option = None; let mut default_cfg = CfgOptions::default(); + let mut default_env = Env::new_for_test_fixture(); let mut file_set = FileSet::default(); let mut current_source_root_kind = SourceRootKind::Local; @@ -200,6 +201,7 @@ impl ChangeFixture { assert!(default_crate_root.is_none()); default_crate_root = Some(file_id); default_cfg = meta.cfg; + default_env.extend(meta.env.iter().map(|(x, y)| (x.to_owned(), y.to_owned()))); default_target_data_layout = meta.target_data_layout; } @@ -220,7 +222,7 @@ impl ChangeFixture { None, default_cfg, Default::default(), - Env::new_for_test_fixture(), + default_env, false, CrateOrigin::Local { repo: None, name: None }, default_target_data_layout diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs index c47799f13209..b75c7079be78 100644 --- a/crates/base-db/src/input.rs +++ b/crates/base-db/src/input.rs @@ -686,6 +686,12 @@ impl fmt::Display for Edition { } } +impl Extend<(String, String)> for Env { + fn extend>(&mut self, iter: T) { + self.entries.extend(iter); + } +} + impl FromIterator<(String, String)> for Env { fn from_iter>(iter: T) -> Self { Env { entries: FromIterator::from_iter(iter) } diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs index b2e29fd34b5f..bfd7d7c1f2c2 100644 --- a/crates/hir-ty/src/mir/eval/shim.rs +++ b/crates/hir-ty/src/mir/eval/shim.rs @@ -473,6 +473,38 @@ impl Evaluator<'_> { self.write_memory_using_ref(destination.addr, destination.size)?.fill(0); Ok(()) } + "getenv" => { + let [name] = args else { + return Err(MirEvalError::TypeError("libc::write args are not provided")); + }; + let mut name_buf = vec![]; + let name = { + let mut index = Address::from_bytes(name.get(self)?)?; + loop { + let byte = self.read_memory(index, 1)?[0]; + index = index.offset(1); + if byte == 0 { + break; + } + name_buf.push(byte); + } + String::from_utf8_lossy(&name_buf) + }; + let value = self.db.crate_graph()[self.crate_id].env.get(&name); + match value { + None => { + // Write null as fail + self.write_memory_using_ref(destination.addr, destination.size)?.fill(0); + } + Some(mut value) => { + value.push('\0'); + let addr = self.heap_allocate(value.len(), 1)?; + self.write_memory(addr, value.as_bytes())?; + self.write_memory(destination.addr, &addr.to_bytes())?; + } + } + Ok(()) + } _ => not_supported!("unknown external function {as_str}"), } } diff --git a/crates/hir-ty/src/mir/eval/tests.rs b/crates/hir-ty/src/mir/eval/tests.rs index 46165cf3d694..ff30dc6dade5 100644 --- a/crates/hir-ty/src/mir/eval/tests.rs +++ b/crates/hir-ty/src/mir/eval/tests.rs @@ -729,6 +729,48 @@ fn main() { ) } +#[test] +fn posix_getenv() { + check_pass( + r#" +//- /main.rs env:foo=bar + +type c_char = u8; + +extern "C" { + pub fn getenv(s: *const c_char) -> *mut c_char; +} + +fn should_not_reach() { + _ // FIXME: replace this function with panic when that works +} + +fn main() { + let result = getenv(b"foo\0" as *const _); + if *result != b'b' { + should_not_reach(); + } + let result = (result as usize + 1) as *const c_char; + if *result != b'a' { + should_not_reach(); + } + let result = (result as usize + 1) as *const c_char; + if *result != b'r' { + should_not_reach(); + } + let result = (result as usize + 1) as *const c_char; + if *result != 0 { + should_not_reach(); + } + let result = getenv(b"not found\0" as *const _); + if result as usize != 0 { + should_not_reach(); + } +} +"#, + ); +} + #[test] fn posix_tls() { check_pass( From 0c433c23b155734aa190157c8899b5d854a75c5a Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Mon, 7 Aug 2023 00:59:35 +0900 Subject: [PATCH 017/197] Support doc links that resolve to fields --- crates/hir-def/src/resolver.rs | 38 +------ crates/hir/src/attrs.rs | 179 ++++++++++++++++++++++++------ crates/hir/src/lib.rs | 2 +- crates/ide-db/src/defs.rs | 12 +- crates/ide/src/doc_links/tests.rs | 56 ++++++++++ 5 files changed, 219 insertions(+), 68 deletions(-) diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index b112c1070d49..d04d2fa0e979 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -21,11 +21,11 @@ use crate::{ path::{ModPath, Path, PathKind}, per_ns::PerNs, visibility::{RawVisibility, Visibility}, - AdtId, AssocItemId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, - EnumVariantId, ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, - HasModule, ImplId, ItemContainerId, LifetimeParamId, LocalModuleId, Lookup, Macro2Id, MacroId, - MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitAliasId, TraitId, - TypeAliasId, TypeOrConstParamId, TypeOwnerId, TypeParamId, UseId, VariantId, + AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, + ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, + ItemContainerId, LifetimeParamId, LocalModuleId, Lookup, Macro2Id, MacroId, MacroRulesId, + ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, + TypeOrConstParamId, TypeOwnerId, TypeParamId, UseId, VariantId, }; #[derive(Debug, Clone)] @@ -148,34 +148,6 @@ impl Resolver { self.resolve_module_path(db, path, BuiltinShadowMode::Module) } - // FIXME: This shouldn't exist - pub fn resolve_module_path_in_trait_assoc_items( - &self, - db: &dyn DefDatabase, - path: &ModPath, - ) -> Option { - let (item_map, module) = self.item_scope(); - let (module_res, idx) = - item_map.resolve_path(db, module, path, BuiltinShadowMode::Module, None); - match module_res.take_types()? { - ModuleDefId::TraitId(it) => { - let idx = idx?; - let unresolved = &path.segments()[idx..]; - let assoc = match unresolved { - [it] => it, - _ => return None, - }; - let &(_, assoc) = db.trait_data(it).items.iter().find(|(n, _)| n == assoc)?; - Some(match assoc { - AssocItemId::FunctionId(it) => PerNs::values(it.into(), Visibility::Public), - AssocItemId::ConstId(it) => PerNs::values(it.into(), Visibility::Public), - AssocItemId::TypeAliasId(it) => PerNs::types(it.into(), Visibility::Public), - }) - } - _ => None, - } - } - pub fn resolve_path_in_type_ns( &self, db: &dyn DefDatabase, diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index 0f2fb2c81181..cd0410168c23 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -3,18 +3,18 @@ use hir_def::{ attr::{AttrsWithOwner, Documentation}, item_scope::ItemInNs, - path::ModPath, - resolver::HasResolver, - AttrDefId, GenericParamId, ModuleDefId, + path::{ModPath, Path}, + resolver::{HasResolver, Resolver, TypeNs}, + AssocItemId, AttrDefId, GenericParamId, ModuleDefId, }; -use hir_expand::hygiene::Hygiene; +use hir_expand::{hygiene::Hygiene, name::Name}; use hir_ty::db::HirDatabase; use syntax::{ast, AstNode}; use crate::{ - Adt, AssocItem, Const, ConstParam, Enum, ExternCrateDecl, Field, Function, GenericParam, Impl, - LifetimeParam, Macro, Module, ModuleDef, Static, Struct, Trait, TraitAlias, TypeAlias, - TypeParam, Union, Variant, + Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, Enum, ExternCrateDecl, Field, + Function, GenericParam, Impl, LifetimeParam, Macro, Module, ModuleDef, Static, Struct, Trait, + TraitAlias, TypeAlias, TypeParam, Union, Variant, VariantDef, }; pub trait HasAttrs { @@ -25,7 +25,7 @@ pub trait HasAttrs { db: &dyn HirDatabase, link: &str, ns: Option, - ) -> Option; + ) -> Option; } #[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)] @@ -35,6 +35,13 @@ pub enum Namespace { Macros, } +/// Subset of `ide_db::Definition` that doc links can resolve to. +pub enum DocLinkDef { + ModuleDef(ModuleDef), + Field(Field), + SelfType(Trait), +} + macro_rules! impl_has_attrs { ($(($def:ident, $def_id:ident),)*) => {$( impl HasAttrs for $def { @@ -46,9 +53,14 @@ macro_rules! impl_has_attrs { let def = AttrDefId::$def_id(self.into()); db.attrs(def).docs() } - fn resolve_doc_path(self, db: &dyn HirDatabase, link: &str, ns: Option) -> Option { + fn resolve_doc_path( + self, + db: &dyn HirDatabase, + link: &str, + ns: Option + ) -> Option { let def = AttrDefId::$def_id(self.into()); - resolve_doc_path(db, def, link, ns).map(ModuleDef::from) + resolve_doc_path(db, def, link, ns) } } )*}; @@ -79,7 +91,12 @@ macro_rules! impl_has_attrs_enum { fn docs(self, db: &dyn HirDatabase) -> Option { $enum::$variant(self).docs(db) } - fn resolve_doc_path(self, db: &dyn HirDatabase, link: &str, ns: Option) -> Option { + fn resolve_doc_path( + self, + db: &dyn HirDatabase, + link: &str, + ns: Option + ) -> Option { $enum::$variant(self).resolve_doc_path(db, link, ns) } } @@ -111,7 +128,7 @@ impl HasAttrs for AssocItem { db: &dyn HirDatabase, link: &str, ns: Option, - ) -> Option { + ) -> Option { match self { AssocItem::Function(it) => it.resolve_doc_path(db, link, ns), AssocItem::Const(it) => it.resolve_doc_path(db, link, ns), @@ -147,9 +164,9 @@ impl HasAttrs for ExternCrateDecl { db: &dyn HirDatabase, link: &str, ns: Option, - ) -> Option { + ) -> Option { let def = AttrDefId::ExternCrateId(self.into()); - resolve_doc_path(db, def, link, ns).map(ModuleDef::from) + resolve_doc_path(db, def, link, ns) } } @@ -159,7 +176,7 @@ fn resolve_doc_path( def: AttrDefId, link: &str, ns: Option, -) -> Option { +) -> Option { let resolver = match def { AttrDefId::ModuleId(it) => it.resolver(db.upcast()), AttrDefId::FieldId(it) => it.parent.resolver(db.upcast()), @@ -184,8 +201,107 @@ fn resolve_doc_path( .resolver(db.upcast()), }; - let modpath = { - // FIXME: this is not how we should get a mod path here + let mut modpath = modpath_from_str(db, link)?; + + let resolved = resolver.resolve_module_path_in_items(db.upcast(), &modpath); + if resolved.is_none() { + let last_name = modpath.pop_segment()?; + resolve_assoc_or_field(db, resolver, modpath, last_name, ns) + } else { + let def = match ns { + Some(Namespace::Types) => resolved.take_types(), + Some(Namespace::Values) => resolved.take_values(), + Some(Namespace::Macros) => resolved.take_macros().map(ModuleDefId::MacroId), + None => resolved.iter_items().next().map(|it| match it { + ItemInNs::Types(it) => it, + ItemInNs::Values(it) => it, + ItemInNs::Macros(it) => ModuleDefId::MacroId(it), + }), + }; + Some(DocLinkDef::ModuleDef(def?.into())) + } +} + +fn resolve_assoc_or_field( + db: &dyn HirDatabase, + resolver: Resolver, + path: ModPath, + name: Name, + ns: Option, +) -> Option { + let path = Path::from_known_path_with_no_generic(path); + // FIXME: This does not handle `Self` on trait definitions, which we should resolve to the + // trait itself. + let base_def = resolver.resolve_path_in_type_ns_fully(db.upcast(), &path)?; + + let ty = match base_def { + TypeNs::SelfType(id) => Impl::from(id).self_ty(db), + TypeNs::GenericParam(_) => { + // Even if this generic parameter has some trait bounds, rustdoc doesn't + // resolve `name` to trait items. + return None; + } + TypeNs::AdtId(id) | TypeNs::AdtSelfType(id) => Adt::from(id).ty(db), + TypeNs::EnumVariantId(id) => { + // Enum variants don't have path candidates. + let variant = Variant::from(id); + return resolve_field(db, variant.into(), name, ns); + } + TypeNs::TypeAliasId(id) => { + let alias = TypeAlias::from(id); + if alias.as_assoc_item(db).is_some() { + // We don't normalize associated type aliases, so we have nothing to + // resolve `name` to. + return None; + } + alias.ty(db) + } + TypeNs::BuiltinType(id) => BuiltinType::from(id).ty(db), + TypeNs::TraitId(id) => { + // Doc paths in this context may only resolve to an item of this trait + // (i.e. no items of its supertraits), so we need to handle them here + // independently of others. + return db.trait_data(id).items.iter().find(|it| it.0 == name).map(|(_, assoc_id)| { + let def = match *assoc_id { + AssocItemId::FunctionId(it) => ModuleDef::Function(it.into()), + AssocItemId::ConstId(it) => ModuleDef::Const(it.into()), + AssocItemId::TypeAliasId(it) => ModuleDef::TypeAlias(it.into()), + }; + DocLinkDef::ModuleDef(def) + }); + } + TypeNs::TraitAliasId(_) => { + // XXX: Do these get resolved? + return None; + } + }; + + // FIXME: Resolve associated items here, e.g. `Option::map`. Note that associated items take + // precedence over fields. + + let variant_def = match ty.as_adt()? { + Adt::Struct(it) => it.into(), + Adt::Union(it) => it.into(), + Adt::Enum(_) => return None, + }; + resolve_field(db, variant_def, name, ns) +} + +fn resolve_field( + db: &dyn HirDatabase, + def: VariantDef, + name: Name, + ns: Option, +) -> Option { + if let Some(Namespace::Types | Namespace::Macros) = ns { + return None; + } + def.fields(db).into_iter().find(|f| f.name(db) == name).map(DocLinkDef::Field) +} + +fn modpath_from_str(db: &dyn HirDatabase, link: &str) -> Option { + // FIXME: this is not how we should get a mod path here. + let try_get_modpath = |link: &str| { let ast_path = ast::SourceFile::parse(&format!("type T = {link};")) .syntax_node() .descendants() @@ -193,23 +309,20 @@ fn resolve_doc_path( if ast_path.syntax().text() != link { return None; } - ModPath::from_src(db.upcast(), ast_path, &Hygiene::new_unhygienic())? + ModPath::from_src(db.upcast(), ast_path, &Hygiene::new_unhygienic()) }; - let resolved = resolver.resolve_module_path_in_items(db.upcast(), &modpath); - let resolved = if resolved.is_none() { - resolver.resolve_module_path_in_trait_assoc_items(db.upcast(), &modpath)? - } else { - resolved - }; - match ns { - Some(Namespace::Types) => resolved.take_types(), - Some(Namespace::Values) => resolved.take_values(), - Some(Namespace::Macros) => resolved.take_macros().map(ModuleDefId::MacroId), - None => resolved.iter_items().next().map(|it| match it { - ItemInNs::Types(it) => it, - ItemInNs::Values(it) => it, - ItemInNs::Macros(it) => ModuleDefId::MacroId(it), - }), + let full = try_get_modpath(link); + if full.is_some() { + return full; } + + // Tuple field names cannot be a part of `ModPath` usually, but rustdoc can + // resolve doc paths like `TupleStruct::0`. + // FIXME: Find a better way to handle these. + let (base, maybe_tuple_field) = link.rsplit_once("::")?; + let tuple_field = Name::new_tuple_field(maybe_tuple_field.parse().ok()?); + let mut modpath = try_get_modpath(base)?; + modpath.push_segment(tuple_field); + Some(modpath) } diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index bf041b61f2fb..de60c88844de 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -87,7 +87,7 @@ use triomphe::Arc; use crate::db::{DefDatabase, HirDatabase}; pub use crate::{ - attrs::{HasAttrs, Namespace}, + attrs::{DocLinkDef, HasAttrs, Namespace}, diagnostics::{ AnyDiagnostic, BreakOutsideOfLoop, CaseType, ExpectedFunction, InactiveCode, IncoherentImpl, IncorrectCase, InvalidDeriveTarget, MacroDefError, MacroError, diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index 5e4562d9c583..4ce80532e8ef 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -7,7 +7,7 @@ use arrayvec::ArrayVec; use hir::{ - Adt, AsAssocItem, AssocItem, BuiltinAttr, BuiltinType, Const, Crate, DeriveHelper, + Adt, AsAssocItem, AssocItem, BuiltinAttr, BuiltinType, Const, Crate, DeriveHelper, DocLinkDef, ExternCrateDecl, Field, Function, GenericParam, HasVisibility, Impl, Label, Local, Macro, Module, ModuleDef, Name, PathResolution, Semantics, Static, ToolModule, Trait, TraitAlias, TypeAlias, Variant, Visibility, @@ -649,3 +649,13 @@ impl From for Definition { } } } + +impl From for Definition { + fn from(def: DocLinkDef) -> Self { + match def { + DocLinkDef::ModuleDef(it) => it.into(), + DocLinkDef::Field(it) => it.into(), + DocLinkDef::SelfType(it) => it.into(), + } + } +} diff --git a/crates/ide/src/doc_links/tests.rs b/crates/ide/src/doc_links/tests.rs index 05a64b33bfdc..8036c77072b8 100644 --- a/crates/ide/src/doc_links/tests.rs +++ b/crates/ide/src/doc_links/tests.rs @@ -517,6 +517,62 @@ fn function(); ) } +#[test] +fn doc_links_field() { + check_doc_links( + r#" +/// [`S::f`] +/// [`S2::f`] +/// [`T::0`] +/// [`U::a`] +/// [`E::A::f`] +/// [`E::B::0`] +struct S$0 { + f: i32, + //^ S::f + //^ S2::f +} +type S2 = S; +struct T(i32); + //^^^ T::0 +union U { + a: i32, + //^ U::a +} +enum E { + A { f: i32 }, + //^ E::A::f + B(i32), + //^^^ E::B::0 +} +"#, + ); +} + +#[test] +fn doc_links_field_via_self() { + check_doc_links( + r#" +/// [`Self::f`] +struct S$0 { + f: i32, + //^ Self::f +} +"#, + ); +} + +#[test] +fn doc_links_tuple_field_via_self() { + check_doc_links( + r#" +/// [`Self::0`] +struct S$0(i32); + //^^^ Self::0 +"#, + ); +} + #[test] fn rewrite_html_root_url() { check_rewrite( From bb9d8229b87163d073bc1329bdc4f42676bead07 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Sun, 6 Aug 2023 12:04:29 -0400 Subject: [PATCH 018/197] cleanup --- crates/ide-completion/src/completions.rs | 4 +- crates/ide-completion/src/completions/type.rs | 113 +++++------------- crates/ide-completion/src/context.rs | 43 ++++++- crates/ide-completion/src/context/analysis.rs | 51 ++++++-- crates/ide-completion/src/tests/type_pos.rs | 18 +-- 5 files changed, 119 insertions(+), 110 deletions(-) diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs index 480cb77b4fd6..125ebc98a525 100644 --- a/crates/ide-completion/src/completions.rs +++ b/crates/ide-completion/src/completions.rs @@ -703,7 +703,9 @@ pub(super) fn complete_name_ref( TypeLocation::TypeAscription(ascription) => { r#type::complete_ascribed_type(acc, ctx, path_ctx, ascription); } - TypeLocation::GenericArgList(_) + TypeLocation::GenericArg(_) + | TypeLocation::AssocConstEq + | TypeLocation::AssocTypeEq | TypeLocation::TypeBound | TypeLocation::ImplTarget | TypeLocation::ImplTrait diff --git a/crates/ide-completion/src/completions/type.rs b/crates/ide-completion/src/completions/type.rs index f4efaecba8af..621dea0b9a55 100644 --- a/crates/ide-completion/src/completions/type.rs +++ b/crates/ide-completion/src/completions/type.rs @@ -1,7 +1,7 @@ //! Completion of names from the current scope in type position. use hir::{HirDisplay, ScopeDef}; -use syntax::{ast, AstNode, SyntaxKind}; +use syntax::{ast, AstNode}; use crate::{ context::{PathCompletionCtx, Qualified, TypeAscriptionTarget, TypeLocation}, @@ -20,36 +20,15 @@ pub(crate) fn complete_type_path( let scope_def_applicable = |def| { use hir::{GenericParam::*, ModuleDef::*}; match def { - ScopeDef::GenericParam(LifetimeParam(_)) => { - matches!( - location, - TypeLocation::GenericArgList(Some(( - _, - Some(ast::GenericParam::LifetimeParam(_)) - ))) - ) - } + ScopeDef::GenericParam(LifetimeParam(_)) => location.complete_lifetimes(), ScopeDef::Label(_) => false, // no values in type places ScopeDef::ModuleDef(Function(_) | Variant(_) | Static(_)) | ScopeDef::Local(_) => false, // unless its a constant in a generic arg list position - ScopeDef::ModuleDef(Const(_)) | ScopeDef::GenericParam(ConstParam(_)) => match location - { - TypeLocation::GenericArgList(location) => match location { - Some((_, Some(generic_param))) => { - matches!(generic_param, ast::GenericParam::ConstParam(_)) - } - _ => true, - }, - _ => false, - }, - ScopeDef::ImplSelfType(_) => match location { - TypeLocation::ImplTarget | TypeLocation::ImplTrait => false, - TypeLocation::GenericArgList(Some((_, Some(generic_param)))) => { - matches!(generic_param, ast::GenericParam::TypeParam(_)) - } - _ => true, - }, + ScopeDef::ModuleDef(Const(_)) | ScopeDef::GenericParam(ConstParam(_)) => { + location.complete_consts() + } + ScopeDef::ImplSelfType(_) => location.complete_self_type(), // Don't suggest attribute macros and derives. ScopeDef::ModuleDef(Macro(mac)) => mac.is_fn_like(ctx.db), // Type things are fine @@ -58,17 +37,12 @@ pub(crate) fn complete_type_path( ) | ScopeDef::AdtSelfType(_) | ScopeDef::Unknown - | ScopeDef::GenericParam(TypeParam(_)) => match location { - TypeLocation::GenericArgList(Some((_, Some(generic_param)))) => { - matches!(generic_param, ast::GenericParam::TypeParam(_)) - } - _ => true, - }, + | ScopeDef::GenericParam(TypeParam(_)) => location.complete_types(), } }; let add_assoc_item = |acc: &mut Completions, item| match item { - hir::AssocItem::Const(ct) if matches!(location, TypeLocation::GenericArgList(_)) => { + hir::AssocItem::Const(ct) if matches!(location, TypeLocation::GenericArg(_)) => { acc.add_const(ctx, ct) } hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => (), @@ -182,55 +156,32 @@ pub(crate) fn complete_type_path( }); return; } - TypeLocation::GenericArgList(Some((arg_list, _))) => { - let in_assoc_type_arg = ctx - .original_token - .parent_ancestors() - .any(|node| node.kind() == SyntaxKind::ASSOC_TYPE_ARG); + TypeLocation::GenericArg(Some((arg_list, in_trait, _))) => { + if let Some(trait_) = in_trait { + if arg_list.syntax().ancestors().find_map(ast::TypeBound::cast).is_some() { + let arg_idx = arg_list + .generic_args() + .filter(|arg| { + arg.syntax().text_range().end() + < ctx.original_token.text_range().start() + }) + .count(); - if !in_assoc_type_arg { - if let Some(path_seg) = - arg_list.syntax().parent().and_then(ast::PathSegment::cast) - { - if path_seg - .syntax() - .ancestors() - .find_map(ast::TypeBound::cast) - .is_some() - { - if let Some(hir::PathResolution::Def(hir::ModuleDef::Trait( - trait_, - ))) = ctx.sema.resolve_path(&path_seg.parent_path()) - { - let arg_idx = arg_list - .generic_args() - .filter(|arg| { - arg.syntax().text_range().end() - < ctx.original_token.text_range().start() - }) - .count(); - - let n_required_params = - trait_.type_or_const_param_count(ctx.sema.db, true); - if arg_idx >= n_required_params { - trait_ - .items_with_supertraits(ctx.sema.db) - .into_iter() - .for_each(|it| { - if let hir::AssocItem::TypeAlias(alias) = it { - cov_mark::hit!( - complete_assoc_type_in_generics_list - ); - acc.add_type_alias_with_eq(ctx, alias); - } - }); - - let n_params = - trait_.type_or_const_param_count(ctx.sema.db, false); - if arg_idx >= n_params { - return; // only show assoc types + let n_required_params = + trait_.type_or_const_param_count(ctx.sema.db, true); + if arg_idx >= n_required_params { + trait_.items_with_supertraits(ctx.sema.db).into_iter().for_each( + |it| { + if let hir::AssocItem::TypeAlias(alias) = it { + cov_mark::hit!(complete_assoc_type_in_generics_list); + acc.add_type_alias_with_eq(ctx, alias); } - } + }, + ); + + let n_params = trait_.type_or_const_param_count(ctx.sema.db, false); + if arg_idx >= n_params { + return; // only show assoc types } } } diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs index 8ec5c6c8bfd2..5537673d1ee1 100644 --- a/crates/ide-completion/src/context.rs +++ b/crates/ide-completion/src/context.rs @@ -155,13 +155,54 @@ pub(crate) struct ExprCtx { pub(crate) enum TypeLocation { TupleField, TypeAscription(TypeAscriptionTarget), - GenericArgList(Option<(ast::GenericArgList, Option)>), + /// Generic argument position e.g. `Foo<$0>` + GenericArg(Option<(ast::GenericArgList, Option, Option)>), + /// Associated type equality constraint e.g. `Foo` + AssocTypeEq, + /// Associated constant equality constraint e.g. `Foo` + AssocConstEq, TypeBound, ImplTarget, ImplTrait, Other, } +impl TypeLocation { + pub(crate) fn complete_lifetimes(&self) -> bool { + match self { + TypeLocation::GenericArg(Some((_, _, Some(param)))) => { + matches!(param, ast::GenericParam::LifetimeParam(_)) + } + _ => false, + } + } + + pub(crate) fn complete_consts(&self) -> bool { + match self { + TypeLocation::GenericArg(Some((_, _, Some(param)))) => { + matches!(param, ast::GenericParam::ConstParam(_)) + } + TypeLocation::AssocConstEq => true, + _ => false, + } + } + + pub(crate) fn complete_types(&self) -> bool { + match self { + TypeLocation::GenericArg(Some((_, _, Some(param)))) => { + matches!(param, ast::GenericParam::TypeParam(_)) + } + TypeLocation::AssocConstEq => false, + TypeLocation::AssocTypeEq => true, + _ => true, + } + } + + pub(crate) fn complete_self_type(&self) -> bool { + self.complete_types() && !matches!(self, TypeLocation::ImplTarget | TypeLocation::ImplTrait) + } +} + #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) enum TypeAscriptionTarget { Let(Option), diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index dfceb67f2096..87380067e879 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -720,12 +720,14 @@ fn classify_name_ref( }; let generic_arg_location = |arg: ast::GenericArg| { + let mut override_location = None; let location = find_opt_node_in_file_compensated( sema, original_file, arg.syntax().parent().and_then(ast::GenericArgList::cast), ) .map(|args| { + let mut in_trait = None; let param = (|| { let parent = args.syntax().parent()?; let params = match_ast! { @@ -743,7 +745,31 @@ fn classify_name_ref( variant.parent_enum(sema.db).source(sema.db)?.value.generic_param_list() } hir::ModuleDef::Trait(trait_) => { - trait_.source(sema.db)?.value.generic_param_list() + if let ast::GenericArg::AssocTypeArg(arg) = &arg { + let arg_name = arg.name_ref()?; + let arg_name = arg_name.text(); + for item in trait_.items_with_supertraits(sema.db) { + match item { + hir::AssocItem::TypeAlias(assoc_ty) => { + if assoc_ty.name(sema.db).as_str()? == arg_name { + override_location = Some(TypeLocation::AssocTypeEq); + return None; + } + }, + hir::AssocItem::Const(const_) => { + if const_.name(sema.db)?.as_str()? == arg_name { + override_location = Some(TypeLocation::AssocConstEq); + return None; + } + }, + _ => (), + } + } + return None; + } else { + in_trait = Some(trait_); + trait_.source(sema.db)?.value.generic_param_list() + } } hir::ModuleDef::TraitAlias(trait_) => { trait_.source(sema.db)?.value.generic_param_list() @@ -765,10 +791,12 @@ fn classify_name_ref( match sema.resolve_path(&trait_.parent_path().top_path())? { hir::PathResolution::Def(def) => match def { hir::ModuleDef::Trait(trait_) => { - let trait_items = trait_.items(sema.db); + let arg_name = arg.name_ref()?; + let arg_name = arg_name.text(); + let trait_items = trait_.items_with_supertraits(sema.db); let assoc_ty = trait_items.iter().find_map(|item| match item { hir::AssocItem::TypeAlias(assoc_ty) => { - (assoc_ty.name(sema.db).as_str()? == arg.name_ref()?.text()) + (assoc_ty.name(sema.db).as_str()? == arg_name) .then_some(assoc_ty) }, _ => None, @@ -784,11 +812,10 @@ fn classify_name_ref( } }?; // Determine the index of the argument in the `GenericArgList` and match it with - // the corresponding parameter in the `GenericParamList`. - // Since lifetime parameters are often omitted, ignore them for the purposes of - // matching the argument with its parameter unless a lifetime argument is provided - // explicitly. That is, for `struct S<'a, 'b, T>`, match `S::<$0>` to to `T` and - // `S::<'a, $0, _>` to `'b`. + // the corresponding parameter in the `GenericParamList`. Since lifetime parameters + // are often omitted, ignore them for the purposes of matching the argument with + // its parameter unless a lifetime argument is provided explicitly. That is, for + // `struct S<'a, 'b, T>`, match `S::<$0>` to `T` and `S::<'a, $0, _>` to `'b`. let mut explicit_lifetime_arg = false; let arg_idx = arg .syntax() @@ -806,9 +833,9 @@ fn classify_name_ref( }; params.generic_params().nth(param_idx) })(); - (args, param) + (args, in_trait, param) }); - TypeLocation::GenericArgList(location) + override_location.unwrap_or(TypeLocation::GenericArg(location)) }; let type_location = |node: &SyntaxNode| { @@ -870,8 +897,8 @@ fn classify_name_ref( // is this case needed? ast::GenericArgList(it) => { let location = find_opt_node_in_file_compensated(sema, original_file, Some(it)) - .map(|node| (node, None)); - TypeLocation::GenericArgList(location) + .map(|node| (node, None, None)); + TypeLocation::GenericArg(location) }, ast::TupleField(_) => TypeLocation::TupleField, _ => return None, diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs index 4b4413910941..f2ed7247039b 100644 --- a/crates/ide-completion/src/tests/type_pos.rs +++ b/crates/ide-completion/src/tests/type_pos.rs @@ -402,14 +402,13 @@ fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {} ); check( r#" -trait Trait2 { +trait Trait2 { type Foo; } fn foo<'lt, T: Trait2, const CONST_PARAM: usize>(_: T) {} "#, expect![[r#" - ct CONST en Enum ma makro!(…) macro_rules! makro md module @@ -620,7 +619,6 @@ trait MyTrait { fn f(t: impl MyTrait Date: Sun, 6 Aug 2023 12:04:33 -0400 Subject: [PATCH 019/197] FIXME --- crates/ide-completion/src/context/analysis.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index 87380067e879..2064ae34dd97 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -816,6 +816,9 @@ fn classify_name_ref( // are often omitted, ignore them for the purposes of matching the argument with // its parameter unless a lifetime argument is provided explicitly. That is, for // `struct S<'a, 'b, T>`, match `S::<$0>` to `T` and `S::<'a, $0, _>` to `'b`. + // FIXME: This operates on the syntax tree and will produce incorrect results when + // generic parameters are disabled by `#[cfg]` directives. It should operate on the + // HIR, but the functionality necessary to do so is not exposed at the moment. let mut explicit_lifetime_arg = false; let arg_idx = arg .syntax() From b96e4f2f4a209d2dd1fa3c87c26d370258003f1b Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Mon, 7 Aug 2023 02:12:35 +0330 Subject: [PATCH 020/197] Add mir lower support for tuple destructing assignment --- crates/hir-ty/src/consteval/tests.rs | 21 +++++++++++++ crates/hir-ty/src/mir/lower.rs | 44 ++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs index 666955fa1c38..666a7e81e315 100644 --- a/crates/hir-ty/src/consteval/tests.rs +++ b/crates/hir-ty/src/consteval/tests.rs @@ -1203,6 +1203,27 @@ fn destructing_assignment() { "#, 5, ); + check_number( + r#" + const GOAL: u8 = { + let (mut a, mut b) = (2, 5); + (a, b) = (b, a); + a * 10 + b + }; + "#, + 52, + ); + check_number( + r#" + struct Point { x: i32, y: i32 } + const GOAL: i32 = { + let mut p = Point { x: 5, y: 6 }; + (p.x, _) = (p.y, p.x); + p.x * 10 + p.y + }; + "#, + 66, + ); } #[test] diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 718df8331e2a..9eaa9e1c2f5f 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -1244,6 +1244,41 @@ impl<'ctx> MirLowerCtx<'ctx> { } } + fn lower_destructing_assignment( + &mut self, + mut current: BasicBlockId, + lhs: ExprId, + rhs: Place, + span: MirSpan, + ) -> Result> { + match &self.body.exprs[lhs] { + Expr::Tuple { exprs, is_assignee_expr: _ } => { + for (i, expr) in exprs.iter().enumerate() { + let Some(c) = self.lower_destructing_assignment( + current, + *expr, + rhs.project(ProjectionElem::TupleOrClosureField(i)), + span, + )? else { + return Ok(None); + }; + current = c; + } + Ok(Some(current)) + } + Expr::Underscore => Ok(Some(current)), + _ => { + let Some((lhs_place, current)) = + self.lower_expr_as_place(current, lhs, false)? + else { + return Ok(None); + }; + self.push_assignment(current, lhs_place, Operand::Copy(rhs).into(), span); + Ok(Some(current)) + } + } + } + fn lower_assignment( &mut self, current: BasicBlockId, @@ -1259,6 +1294,15 @@ impl<'ctx> MirLowerCtx<'ctx> { if matches!(&self.body.exprs[lhs], Expr::Underscore) { return Ok(Some(current)); } + if matches!( + &self.body.exprs[lhs], + Expr::Tuple { .. } | Expr::RecordLit { .. } | Expr::Call { .. } + ) { + let temp = self.temp(self.expr_ty_after_adjustments(rhs), current, rhs.into())?; + let temp = Place::from(temp); + self.push_assignment(current, temp.clone(), rhs_op.into(), span); + return self.lower_destructing_assignment(current, lhs, temp, span); + } let Some((lhs_place, current)) = self.lower_expr_as_place(current, lhs, false)? else { From aa55ce9567af6e810b66744f64981f2eb2ed0082 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 7 Aug 2023 12:03:15 +0300 Subject: [PATCH 021/197] Merge commit 'baee6b338b0ea076cd7a9f18d47f175dd2ba0e5d' into sync-from-ra --- crates/hir-def/src/attr.rs | 2 + crates/hir-def/src/body/lower.rs | 39 +- crates/hir-def/src/body/pretty.rs | 8 - crates/hir-def/src/body/scope.rs | 5 - crates/hir-def/src/child_by_source.rs | 23 +- crates/hir-def/src/data.rs | 13 + crates/hir-def/src/db.rs | 10 +- crates/hir-def/src/dyn_map/keys.rs | 3 +- crates/hir-def/src/expander.rs | 30 +- crates/hir-def/src/hir.rs | 9 - crates/hir-def/src/item_scope.rs | 12 + crates/hir-def/src/item_tree.rs | 16 +- crates/hir-def/src/item_tree/lower.rs | 6 +- crates/hir-def/src/item_tree/pretty.rs | 4 +- crates/hir-def/src/lib.rs | 54 +- .../macro_expansion_tests/builtin_fn_macro.rs | 2 +- .../hir-def/src/macro_expansion_tests/mbe.rs | 55 ++ crates/hir-def/src/nameres/collector.rs | 65 +- crates/hir-def/src/nameres/diagnostics.rs | 4 +- .../hir-def/src/nameres/tests/incremental.rs | 18 +- crates/hir-def/src/resolver.rs | 8 +- crates/hir-expand/src/db.rs | 5 +- crates/hir-expand/src/eager.rs | 141 ++-- crates/hir-expand/src/hygiene.rs | 26 +- crates/hir-expand/src/lib.rs | 18 + crates/hir-ty/src/consteval/tests.rs | 106 ++- .../hir-ty/src/consteval/tests/intrinsics.rs | 26 + crates/hir-ty/src/diagnostics/decl_check.rs | 1 + crates/hir-ty/src/display.rs | 22 +- crates/hir-ty/src/infer.rs | 34 +- crates/hir-ty/src/infer/cast.rs | 46 ++ crates/hir-ty/src/infer/closure.rs | 4 - crates/hir-ty/src/infer/expr.rs | 31 +- crates/hir-ty/src/infer/mutability.rs | 4 - crates/hir-ty/src/layout.rs | 24 +- crates/hir-ty/src/mir.rs | 1 + crates/hir-ty/src/mir/eval.rs | 444 +++++++---- crates/hir-ty/src/mir/eval/shim.rs | 117 ++- crates/hir-ty/src/mir/eval/tests.rs | 88 +++ crates/hir-ty/src/mir/lower.rs | 77 +- .../hir-ty/src/tests/display_source_code.rs | 19 + crates/hir-ty/src/tests/macros.rs | 4 + crates/hir-ty/src/tests/never_type.rs | 6 + crates/hir-ty/src/tests/regression.rs | 22 + crates/hir-ty/src/tests/simple.rs | 22 +- crates/hir/src/attrs.rs | 40 +- crates/hir/src/db.rs | 5 - crates/hir/src/display.rs | 18 +- crates/hir/src/from_id.rs | 5 +- crates/hir/src/has_source.rs | 14 +- crates/hir/src/lib.rs | 65 +- crates/hir/src/semantics.rs | 23 +- crates/hir/src/semantics/source_to_def.rs | 16 +- .../src/handlers/add_missing_impl_members.rs | 184 ++++- .../src/handlers/add_missing_match_arms.rs | 31 +- .../src/handlers/add_turbo_fish.rs | 4 +- ...ert_two_arm_bool_match_to_matches_macro.rs | 125 ++- .../src/handlers/destructure_tuple_binding.rs | 2 +- .../src/handlers/expand_glob_import.rs | 2 +- .../src/handlers/extract_function.rs | 2 +- .../src/handlers/extract_module.rs | 2 +- .../src/handlers/generate_default_from_new.rs | 38 +- .../src/handlers/generate_delegate_trait.rs | 70 +- .../src/handlers/generate_function.rs | 3 +- .../ide-assists/src/handlers/inline_call.rs | 2 +- .../ide-assists/src/handlers/inline_macro.rs | 3 +- .../src/handlers/move_const_to_impl.rs | 16 +- .../src/handlers/remove_unused_imports.rs | 739 ++++++++++++++++++ .../replace_derive_with_manual_impl.rs | 14 +- .../replace_named_generic_with_impl.rs | 2 +- crates/ide-assists/src/lib.rs | 2 + crates/ide-assists/src/tests.rs | 93 ++- crates/ide-assists/src/tests/generated.rs | 19 + crates/ide-assists/src/utils.rs | 15 +- crates/ide-completion/src/item.rs | 21 +- crates/ide-completion/src/tests/special.rs | 23 + crates/ide-db/src/defs.rs | 53 +- crates/ide-db/src/famous_defs.rs | 2 +- crates/ide-db/src/rename.rs | 18 +- crates/ide-db/src/search.rs | 12 +- crates/ide-db/src/source_change.rs | 204 +++-- .../src/handlers/macro_error.rs | 5 +- .../src/handlers/missing_fields.rs | 2 +- crates/ide-diagnostics/src/tests.rs | 5 +- crates/ide-ssr/src/search.rs | 2 +- crates/ide/src/doc_links.rs | 7 + crates/ide/src/goto_declaration.rs | 35 +- crates/ide/src/goto_definition.rs | 12 +- crates/ide/src/goto_implementation.rs | 90 +-- crates/ide/src/highlight_related.rs | 9 +- crates/ide/src/hover.rs | 17 +- crates/ide/src/hover/render.rs | 15 +- crates/ide/src/hover/tests.rs | 54 +- crates/ide/src/lib.rs | 2 +- crates/ide/src/moniker.rs | 15 + crates/ide/src/navigation_target.rs | 27 +- crates/ide/src/references.rs | 5 +- crates/ide/src/rename.rs | 327 +++++--- crates/ide/src/runnables.rs | 4 +- crates/ide/src/ssr.rs | 57 +- crates/ide/src/static_index.rs | 2 +- .../ide/src/syntax_highlighting/highlight.rs | 29 +- crates/ide/src/syntax_highlighting/inject.rs | 2 +- .../test_data/highlight_extern_crate.html | 3 +- .../test_data/highlight_keywords.html | 2 +- .../test_data/highlight_macros.html | 14 +- .../test_data/highlight_strings.html | 2 +- crates/ide/src/syntax_highlighting/tests.rs | 16 +- crates/mbe/src/expander.rs | 10 + crates/mbe/src/expander/matcher.rs | 10 +- crates/mbe/src/expander/transcriber.rs | 42 +- crates/mbe/src/lib.rs | 1 - crates/mbe/src/token_map.rs | 4 + crates/parser/src/grammar.rs | 34 + crates/parser/src/grammar/items.rs | 5 +- crates/parser/src/lib.rs | 3 + crates/parser/src/shortcuts.rs | 3 +- crates/parser/src/syntax_kind/generated.rs | 1 + crates/proc-macro-srv/src/server.rs | 21 +- .../rust-analyzer/src/cli/analysis_stats.rs | 2 +- crates/rust-analyzer/src/cli/diagnostics.rs | 2 +- crates/rust-analyzer/src/cli/run_tests.rs | 2 +- crates/rust-analyzer/src/cli/scip.rs | 38 + crates/rust-analyzer/src/handlers/request.rs | 3 +- crates/rust-analyzer/src/reload.rs | 5 + crates/rust-analyzer/src/to_proto.rs | 617 ++++++++++++++- crates/syntax/rust.ungram | 6 + crates/syntax/src/ast/edit_in_place.rs | 36 + crates/syntax/src/ast/generated/nodes.rs | 30 + crates/syntax/src/lib.rs | 4 +- crates/syntax/src/tests/ast_src.rs | 1 + crates/tt/src/lib.rs | 5 +- docs/user/manual.adoc | 23 + editors/code/package-lock.json | 10 +- editors/code/package.json | 13 +- editors/code/src/config.ts | 10 +- editors/code/src/ctx.ts | 10 +- editors/code/src/run.ts | 14 +- triagebot.toml | 4 + 139 files changed, 4248 insertions(+), 1042 deletions(-) create mode 100644 crates/hir-ty/src/infer/cast.rs create mode 100644 crates/ide-assists/src/handlers/remove_unused_imports.rs diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index c29446d8235a..fae07111806c 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -485,6 +485,7 @@ impl AttrsWithOwner { }, AttrDefId::ExternBlockId(it) => attrs_from_item_tree_loc(db, it), AttrDefId::ExternCrateId(it) => attrs_from_item_tree_loc(db, it), + AttrDefId::UseId(it) => attrs_from_item_tree_loc(db, it), }; let attrs = raw_attrs.filter(db.upcast(), def.krate(db)); @@ -570,6 +571,7 @@ impl AttrsWithOwner { }, AttrDefId::ExternBlockId(id) => any_has_attrs(db, id), AttrDefId::ExternCrateId(id) => any_has_attrs(db, id), + AttrDefId::UseId(id) => any_has_attrs(db, id), }; AttrSourceMap::new(owner.as_ref().map(|node| node as &dyn HasAttrs)) diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index 152c02743f77..3853a6ab3a57 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -313,13 +313,7 @@ impl ExprCollector<'_> { let body = self.collect_labelled_block_opt(label, e.loop_body()); self.alloc_expr(Expr::Loop { body, label }, syntax_ptr) } - ast::Expr::WhileExpr(e) => { - let label = e.label().map(|label| self.collect_label(label)); - let body = self.collect_labelled_block_opt(label, e.loop_body()); - let condition = self.collect_expr_opt(e.condition()); - - self.alloc_expr(Expr::While { condition, body, label }, syntax_ptr) - } + ast::Expr::WhileExpr(e) => self.collect_while_loop(syntax_ptr, e), ast::Expr::ForExpr(e) => self.collect_for_loop(syntax_ptr, e), ast::Expr::CallExpr(e) => { let is_rustc_box = { @@ -731,6 +725,32 @@ impl ExprCollector<'_> { expr_id } + /// Desugar `ast::WhileExpr` from: `[opt_ident]: while ` into: + /// ```ignore (pseudo-rust) + /// [opt_ident]: loop { + /// if { + /// + /// } + /// else { + /// break; + /// } + /// } + /// ``` + /// FIXME: Rustc wraps the condition in a construct equivalent to `{ let _t = ; _t }` + /// to preserve drop semantics. We should probably do the same in future. + fn collect_while_loop(&mut self, syntax_ptr: AstPtr, e: ast::WhileExpr) -> ExprId { + let label = e.label().map(|label| self.collect_label(label)); + let body = self.collect_labelled_block_opt(label, e.loop_body()); + let condition = self.collect_expr_opt(e.condition()); + let break_expr = + self.alloc_expr(Expr::Break { expr: None, label: None }, syntax_ptr.clone()); + let if_expr = self.alloc_expr( + Expr::If { condition, then_branch: body, else_branch: Some(break_expr) }, + syntax_ptr.clone(), + ); + self.alloc_expr(Expr::Loop { body: if_expr, label }, syntax_ptr) + } + /// Desugar `ast::ForExpr` from: `[opt_ident]: for in ` into: /// ```ignore (pseudo-rust) /// match IntoIterator::into_iter() { @@ -893,15 +913,14 @@ impl ExprCollector<'_> { self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr) } - fn collect_macro_call( + fn collect_macro_call( &mut self, mcall: ast::MacroCall, syntax_ptr: AstPtr, record_diagnostics: bool, - collector: F, + collector: impl FnOnce(&mut Self, Option) -> U, ) -> U where - F: FnOnce(&mut Self, Option) -> U, T: ast::AstNode, { // File containing the macro call. Expansion errors will be attached here. diff --git a/crates/hir-def/src/body/pretty.rs b/crates/hir-def/src/body/pretty.rs index eeaed87164dc..5d71abe37cc5 100644 --- a/crates/hir-def/src/body/pretty.rs +++ b/crates/hir-def/src/body/pretty.rs @@ -178,14 +178,6 @@ impl Printer<'_> { w!(self, "loop "); self.print_expr(*body); } - Expr::While { condition, body, label } => { - if let Some(lbl) = label { - w!(self, "{}: ", self.body[*lbl].name.display(self.db)); - } - w!(self, "while "); - self.print_expr(*condition); - self.print_expr(*body); - } Expr::Call { callee, args, is_assignee_expr: _ } => { self.print_expr(*callee); w!(self, "("); diff --git a/crates/hir-def/src/body/scope.rs b/crates/hir-def/src/body/scope.rs index 69741c445fba..2a90a09f25e8 100644 --- a/crates/hir-def/src/body/scope.rs +++ b/crates/hir-def/src/body/scope.rs @@ -228,11 +228,6 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope scopes.set_scope(expr, scope); compute_block_scopes(statements, *tail, body, scopes, &mut scope); } - Expr::While { condition, body: body_expr, label } => { - let mut scope = scopes.new_labeled_scope(*scope, make_label(label)); - compute_expr_scopes(*condition, body, scopes, &mut scope); - compute_expr_scopes(*body_expr, body, scopes, &mut scope); - } Expr::Loop { body: body_expr, label } => { let mut scope = scopes.new_labeled_scope(*scope, make_label(label)); compute_expr_scopes(*body_expr, body, scopes, &mut scope); diff --git a/crates/hir-def/src/child_by_source.rs b/crates/hir-def/src/child_by_source.rs index bb79e28f2673..4cfd318a4337 100644 --- a/crates/hir-def/src/child_by_source.rs +++ b/crates/hir-def/src/child_by_source.rs @@ -14,8 +14,8 @@ use crate::{ item_scope::ItemScope, nameres::DefMap, src::{HasChildSource, HasSource}, - AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, FieldId, ImplId, Lookup, MacroId, - ModuleDefId, ModuleId, TraitId, VariantId, + AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FieldId, ImplId, + Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId, VariantId, }; pub trait ChildBySource { @@ -91,6 +91,8 @@ impl ChildBySource for ItemScope { fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { self.declarations().for_each(|item| add_module_def(db, res, file_id, item)); self.impls().for_each(|imp| add_impl(db, res, file_id, imp)); + self.extern_crate_decls().for_each(|ext| add_extern_crate(db, res, file_id, ext)); + self.use_decls().for_each(|ext| add_use(db, res, file_id, ext)); self.unnamed_consts().for_each(|konst| { let loc = konst.lookup(db); if loc.id.file_id() == file_id { @@ -167,6 +169,23 @@ impl ChildBySource for ItemScope { map[keys::IMPL].insert(loc.source(db).value, imp) } } + fn add_extern_crate( + db: &dyn DefDatabase, + map: &mut DynMap, + file_id: HirFileId, + ext: ExternCrateId, + ) { + let loc = ext.lookup(db); + if loc.id.file_id() == file_id { + map[keys::EXTERN_CRATE].insert(loc.source(db).value, ext) + } + } + fn add_use(db: &dyn DefDatabase, map: &mut DynMap, file_id: HirFileId, ext: UseId) { + let loc = ext.lookup(db); + if loc.id.file_id() == file_id { + map[keys::USE].insert(loc.source(db).value, ext) + } + } } } diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index 54fe9a2e8440..91db68058b02 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -2,6 +2,7 @@ pub mod adt; +use base_db::CrateId; use hir_expand::{ name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind, }; @@ -467,6 +468,7 @@ pub struct ExternCrateDeclData { pub name: Name, pub alias: Option, pub visibility: RawVisibility, + pub crate_id: Option, } impl ExternCrateDeclData { @@ -478,10 +480,21 @@ impl ExternCrateDeclData { let item_tree = loc.id.item_tree(db); let extern_crate = &item_tree[loc.id.value]; + let name = extern_crate.name.clone(); + let crate_id = if name == hir_expand::name![self] { + Some(loc.container.krate()) + } else { + db.crate_def_map(loc.container.krate()) + .extern_prelude() + .find(|&(prelude_name, ..)| *prelude_name == name) + .map(|(_, root)| root.krate()) + }; + Arc::new(Self { name: extern_crate.name.clone(), visibility: item_tree[extern_crate.visibility].clone(), alias: extern_crate.alias.clone(), + crate_id, }) } } diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index 82e6dfb30c81..e34a6768f286 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -23,17 +23,17 @@ use crate::{ visibility::{self, Visibility}, AttrDefId, BlockId, BlockLoc, ConstBlockId, ConstBlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, - FunctionLoc, GenericDefId, ImplId, ImplLoc, ImportId, ImportLoc, InTypeConstId, InTypeConstLoc, - LocalEnumVariantId, LocalFieldId, Macro2Id, Macro2Loc, MacroRulesId, MacroRulesLoc, - ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, TraitAliasId, - TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, VariantId, + FunctionLoc, GenericDefId, ImplId, ImplLoc, InTypeConstId, InTypeConstLoc, LocalEnumVariantId, + LocalFieldId, Macro2Id, Macro2Loc, MacroRulesId, MacroRulesLoc, ProcMacroId, ProcMacroLoc, + StaticId, StaticLoc, StructId, StructLoc, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, + TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, VariantId, }; #[salsa::query_group(InternDatabaseStorage)] pub trait InternDatabase: SourceDatabase { // region: items #[salsa::interned] - fn intern_import(&self, loc: ImportLoc) -> ImportId; + fn intern_use(&self, loc: UseLoc) -> UseId; #[salsa::interned] fn intern_extern_crate(&self, loc: ExternCrateLoc) -> ExternCrateId; #[salsa::interned] diff --git a/crates/hir-def/src/dyn_map/keys.rs b/crates/hir-def/src/dyn_map/keys.rs index 4197d0106082..d0f2bfab4322 100644 --- a/crates/hir-def/src/dyn_map/keys.rs +++ b/crates/hir-def/src/dyn_map/keys.rs @@ -10,7 +10,7 @@ use crate::{ dyn_map::{DynMap, Policy}, ConstId, EnumId, EnumVariantId, ExternCrateId, FieldId, FunctionId, ImplId, LifetimeParamId, Macro2Id, MacroRulesId, ProcMacroId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, - TypeOrConstParamId, UnionId, + TypeOrConstParamId, UnionId, UseId, }; pub type Key = crate::dyn_map::Key>; @@ -26,6 +26,7 @@ pub const STRUCT: Key = Key::new(); pub const UNION: Key = Key::new(); pub const ENUM: Key = Key::new(); pub const EXTERN_CRATE: Key = Key::new(); +pub const USE: Key = Key::new(); pub const VARIANT: Key = Key::new(); pub const TUPLE_FIELD: Key = Key::new(); diff --git a/crates/hir-def/src/expander.rs b/crates/hir-def/src/expander.rs index cc85bd893ac4..6db8398bc986 100644 --- a/crates/hir-def/src/expander.rs +++ b/crates/hir-def/src/expander.rs @@ -164,18 +164,26 @@ impl Expander { return ExpandResult { value: None, err }; }; - Self::enter_expand_inner(db, call_id, err).map(|value| { - value.and_then(|InFile { file_id, value }| { - let parse = value.cast::()?; + let res = Self::enter_expand_inner(db, call_id, err); + match res.err { + // If proc-macro is disabled or unresolved, we want to expand to a missing expression + // instead of an empty tree which might end up in an empty block. + Some(ExpandError::UnresolvedProcMacro(_)) => res.map(|_| None), + _ => res.map(|value| { + value.and_then(|InFile { file_id, value }| { + let parse = value.cast::()?; - self.recursion_depth += 1; - self.hygiene = Hygiene::new(db.upcast(), file_id); - let old_file_id = std::mem::replace(&mut self.current_file_id, file_id); - let mark = - Mark { file_id: old_file_id, bomb: DropBomb::new("expansion mark dropped") }; - Some((mark, parse)) - }) - }) + self.recursion_depth += 1; + self.hygiene = Hygiene::new(db.upcast(), file_id); + let old_file_id = std::mem::replace(&mut self.current_file_id, file_id); + let mark = Mark { + file_id: old_file_id, + bomb: DropBomb::new("expansion mark dropped"), + }; + Some((mark, parse)) + }) + }), + } } } diff --git a/crates/hir-def/src/hir.rs b/crates/hir-def/src/hir.rs index 8a140a1ec181..6591c92ac62d 100644 --- a/crates/hir-def/src/hir.rs +++ b/crates/hir-def/src/hir.rs @@ -191,11 +191,6 @@ pub enum Expr { body: ExprId, label: Option, }, - While { - condition: ExprId, - body: ExprId, - label: Option, - }, Call { callee: ExprId, args: Box<[ExprId]>, @@ -379,10 +374,6 @@ impl Expr { } } Expr::Loop { body, .. } => f(*body), - Expr::While { condition, body, .. } => { - f(*condition); - f(*body); - } Expr::Call { callee, args, .. } => { f(*callee); args.iter().copied().for_each(f); diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs index 2ac1bcdc079f..873accafb43d 100644 --- a/crates/hir-def/src/item_scope.rs +++ b/crates/hir-def/src/item_scope.rs @@ -16,6 +16,7 @@ use syntax::ast; use crate::{ db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ConstId, ExternCrateId, HasModule, ImplId, LocalModuleId, MacroId, ModuleDefId, ModuleId, TraitId, + UseId, }; #[derive(Copy, Clone, Debug)] @@ -113,6 +114,17 @@ impl ItemScope { self.declarations.iter().copied() } + pub fn extern_crate_decls( + &self, + ) -> impl Iterator + ExactSizeIterator + '_ { + self.extern_crate_decls.iter().copied() + } + + pub fn use_decls(&self) -> impl Iterator + ExactSizeIterator + '_ { + // FIXME: to be implemented + std::iter::empty() + } + pub fn impls(&self) -> impl Iterator + ExactSizeIterator + '_ { self.impls.iter().copied() } diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 6f80bb6e07ce..c9b0f75f1a8a 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -188,7 +188,7 @@ impl ItemTree { fn shrink_to_fit(&mut self) { if let Some(data) = &mut self.data { let ItemTreeData { - imports, + uses, extern_crates, extern_blocks, functions, @@ -211,7 +211,7 @@ impl ItemTree { vis, } = &mut **data; - imports.shrink_to_fit(); + uses.shrink_to_fit(); extern_crates.shrink_to_fit(); extern_blocks.shrink_to_fit(); functions.shrink_to_fit(); @@ -262,7 +262,7 @@ static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(ModPath::from_kind(P #[derive(Default, Debug, Eq, PartialEq)] struct ItemTreeData { - imports: Arena, + uses: Arena, extern_crates: Arena, extern_blocks: Arena, functions: Arena, @@ -486,7 +486,7 @@ macro_rules! mod_items { } mod_items! { - Import in imports -> ast::Use, + Use in uses -> ast::Use, ExternCrate in extern_crates -> ast::ExternCrate, ExternBlock in extern_blocks -> ast::ExternBlock, Function in functions -> ast::Fn, @@ -541,7 +541,7 @@ impl Index> for ItemTree { } #[derive(Debug, Clone, Eq, PartialEq)] -pub struct Import { +pub struct Use { pub visibility: RawVisibilityId, pub ast_id: FileAstId, pub use_tree: UseTree, @@ -744,7 +744,7 @@ pub struct MacroDef { pub ast_id: FileAstId, } -impl Import { +impl Use { /// Maps a `UseTree` contained in this import back to its AST node. pub fn use_tree_to_ast( &self, @@ -870,7 +870,7 @@ macro_rules! impl_froms { impl ModItem { pub fn as_assoc_item(&self) -> Option { match self { - ModItem::Import(_) + ModItem::Use(_) | ModItem::ExternCrate(_) | ModItem::ExternBlock(_) | ModItem::Struct(_) @@ -892,7 +892,7 @@ impl ModItem { pub fn ast_id(&self, tree: &ItemTree) -> FileAstId { match self { - ModItem::Import(it) => tree[it.index].ast_id().upcast(), + ModItem::Use(it) => tree[it.index].ast_id().upcast(), ModItem::ExternCrate(it) => tree[it.index].ast_id().upcast(), ModItem::ExternBlock(it) => tree[it.index].ast_id().upcast(), ModItem::Function(it) => tree[it.index].ast_id().upcast(), diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index 46633667ed3e..7b898e62dbae 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -502,13 +502,13 @@ impl<'a> Ctx<'a> { Some(id(self.data().impls.alloc(res))) } - fn lower_use(&mut self, use_item: &ast::Use) -> Option> { + fn lower_use(&mut self, use_item: &ast::Use) -> Option> { let visibility = self.lower_visibility(use_item); let ast_id = self.source_ast_id_map.ast_id(use_item); let (use_tree, _) = lower_use_tree(self.db, self.hygiene(), use_item.use_tree()?)?; - let res = Import { visibility, ast_id, use_tree }; - Some(id(self.data().imports.alloc(res))) + let res = Use { visibility, ast_id, use_tree }; + Some(id(self.data().uses.alloc(res))) } fn lower_extern_crate( diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs index ddf668d20b05..da30830fe452 100644 --- a/crates/hir-def/src/item_tree/pretty.rs +++ b/crates/hir-def/src/item_tree/pretty.rs @@ -198,8 +198,8 @@ impl Printer<'_> { self.print_attrs_of(item); match item { - ModItem::Import(it) => { - let Import { visibility, use_tree, ast_id: _ } = &self.tree[it]; + ModItem::Use(it) => { + let Use { visibility, use_tree, ast_id: _ } = &self.tree[it]; self.print_visibility(*visibility); w!(self, "use "); self.print_use_tree(use_tree); diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 1e74e2dfcb4c..1901db8a0f9b 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -88,8 +88,8 @@ use crate::{ builtin_type::BuiltinType, data::adt::VariantData, item_tree::{ - Const, Enum, ExternCrate, Function, Impl, Import, ItemTreeId, ItemTreeNode, MacroDef, - MacroRules, Static, Struct, Trait, TraitAlias, TypeAlias, Union, + Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, MacroDef, MacroRules, + Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, }, }; @@ -121,6 +121,12 @@ impl From for ModuleDefId { } } +impl From for CrateRootModuleId { + fn from(krate: CrateId) -> Self { + CrateRootModuleId { krate } + } +} + impl TryFrom for CrateRootModuleId { type Error = (); @@ -318,9 +324,9 @@ type ImplLoc = ItemLoc; impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] -pub struct ImportId(salsa::InternId); -type ImportLoc = ItemLoc; -impl_intern!(ImportId, ImportLoc, intern_import, lookup_intern_import); +pub struct UseId(salsa::InternId); +type UseLoc = ItemLoc; +impl_intern!(UseId, UseLoc, intern_use, lookup_intern_use); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] pub struct ExternCrateId(salsa::InternId); @@ -836,6 +842,7 @@ pub enum AttrDefId { GenericParamId(GenericParamId), ExternBlockId(ExternBlockId), ExternCrateId(ExternCrateId), + UseId(UseId), } impl_from!( @@ -1073,6 +1080,7 @@ impl AttrDefId { } AttrDefId::MacroId(it) => it.module(db).krate, AttrDefId::ExternCrateId(it) => it.lookup(db).container.krate, + AttrDefId::UseId(it) => it.lookup(db).container.krate, } } } @@ -1083,7 +1091,7 @@ pub trait AsMacroCall { &self, db: &dyn ExpandDatabase, krate: CrateId, - resolver: impl Fn(path::ModPath) -> Option, + resolver: impl Fn(path::ModPath) -> Option + Copy, ) -> Option { self.as_call_id_with_errors(db, krate, resolver).ok()?.value } @@ -1092,7 +1100,7 @@ pub trait AsMacroCall { &self, db: &dyn ExpandDatabase, krate: CrateId, - resolver: impl Fn(path::ModPath) -> Option, + resolver: impl Fn(path::ModPath) -> Option + Copy, ) -> Result>, UnresolvedMacro>; } @@ -1101,7 +1109,7 @@ impl AsMacroCall for InFile<&ast::MacroCall> { &self, db: &dyn ExpandDatabase, krate: CrateId, - resolver: impl Fn(path::ModPath) -> Option, + resolver: impl Fn(path::ModPath) -> Option + Copy, ) -> Result>, UnresolvedMacro> { let expands_to = hir_expand::ExpandTo::from_call_site(self.value); let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value)); @@ -1112,12 +1120,13 @@ impl AsMacroCall for InFile<&ast::MacroCall> { return Ok(ExpandResult::only_err(ExpandError::other("malformed macro invocation"))); }; - macro_call_as_call_id_( + macro_call_as_call_id_with_eager( db, &AstIdWithPath::new(ast_id.file_id, ast_id.value, path), expands_to, krate, resolver, + resolver, ) } } @@ -1140,33 +1149,39 @@ fn macro_call_as_call_id( call: &AstIdWithPath, expand_to: ExpandTo, krate: CrateId, - resolver: impl Fn(path::ModPath) -> Option, + resolver: impl Fn(path::ModPath) -> Option + Copy, ) -> Result, UnresolvedMacro> { - macro_call_as_call_id_(db, call, expand_to, krate, resolver).map(|res| res.value) + macro_call_as_call_id_with_eager(db, call, expand_to, krate, resolver, resolver) + .map(|res| res.value) } -fn macro_call_as_call_id_( +fn macro_call_as_call_id_with_eager( db: &dyn ExpandDatabase, call: &AstIdWithPath, expand_to: ExpandTo, krate: CrateId, - resolver: impl Fn(path::ModPath) -> Option, + resolver: impl FnOnce(path::ModPath) -> Option, + eager_resolver: impl Fn(path::ModPath) -> Option, ) -> Result>, UnresolvedMacro> { let def = resolver(call.path.clone()).ok_or_else(|| UnresolvedMacro { path: call.path.clone() })?; - let res = if let MacroDefKind::BuiltInEager(..) = def.kind { - let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db)); - expand_eager_macro_input(db, krate, macro_call, def, &resolver)? - } else { - ExpandResult { + let res = match def.kind { + MacroDefKind::BuiltInEager(..) => { + let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db)); + expand_eager_macro_input(db, krate, macro_call, def, &|path| { + eager_resolver(path).filter(MacroDefId::is_fn_like) + }) + } + _ if def.is_fn_like() => ExpandResult { value: Some(def.as_lazy_macro( db, krate, MacroCallKind::FnLike { ast_id: call.ast_id, expand_to }, )), err: None, - } + }, + _ => return Err(UnresolvedMacro { path: call.path.clone() }), }; Ok(res) } @@ -1251,6 +1266,7 @@ fn derive_macro_as_call_id( resolver: impl Fn(path::ModPath) -> Option<(MacroId, MacroDefId)>, ) -> Result<(MacroId, MacroDefId, MacroCallId), UnresolvedMacro> { let (macro_id, def_id) = resolver(item_attr.path.clone()) + .filter(|(_, def_id)| def_id.is_derive()) .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?; let call_id = def_id.as_lazy_macro( db.upcast(), diff --git a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs index b232651db96e..1250cbb742c5 100644 --- a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs +++ b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs @@ -238,7 +238,7 @@ fn main() { /* error: expected expression */; /* error: expected expression, expected COMMA */; /* error: expected expression */::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(), ::core::fmt::Display::fmt), ]); - /* error: expected expression, expected R_PAREN */; + /* error: expected expression, expected expression */; ::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(5), ::core::fmt::Display::fmt), ]); } "##]], diff --git a/crates/hir-def/src/macro_expansion_tests/mbe.rs b/crates/hir-def/src/macro_expansion_tests/mbe.rs index b26f9867580b..2170cadcf83b 100644 --- a/crates/hir-def/src/macro_expansion_tests/mbe.rs +++ b/crates/hir-def/src/macro_expansion_tests/mbe.rs @@ -99,6 +99,30 @@ fn#19 main#20(#21)#21 {#22 ); } +#[test] +fn eager_expands_with_unresolved_within() { + check( + r#" +#[rustc_builtin_macro] +#[macro_export] +macro_rules! format_args {} + +fn main(foo: ()) { + format_args!("{} {} {}", format_args!("{}", 0), foo, identity!(10), "bar") +} +"#, + expect![[r##" +#[rustc_builtin_macro] +#[macro_export] +macro_rules! format_args {} + +fn main(foo: ()) { + /* error: unresolved macro identity */::core::fmt::Arguments::new_v1(&["", " ", " ", ], &[::core::fmt::ArgumentV1::new(&(::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(0), ::core::fmt::Display::fmt), ])), ::core::fmt::Display::fmt), ::core::fmt::ArgumentV1::new(&(foo), ::core::fmt::Display::fmt), ::core::fmt::ArgumentV1::new(&(identity!(10)), ::core::fmt::Display::fmt), ]) +} +"##]], + ); +} + #[test] fn token_mapping_eager() { check( @@ -848,6 +872,37 @@ fn foo() { ); } +#[test] +fn test_type_path_is_transcribed_as_expr_path() { + check( + r#" +macro_rules! m { + ($p:path) => { let $p; } +} +fn test() { + m!(S) + m!(S) + m!(S>) + m!(S<{ module::CONST < 42 }>) +} +"#, + expect![[r#" +macro_rules! m { + ($p:path) => { let $p; } +} +fn test() { + let S; + let S:: ; + let S:: > ; + let S:: < { + module::CONST<42 + } + > ; +} +"#]], + ); +} + #[test] fn test_expr() { check( diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index c048716d7403..eef54fc492e9 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -38,7 +38,7 @@ use crate::{ self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode, MacroCall, MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId, }, - macro_call_as_call_id, macro_id_to_def_id, + macro_call_as_call_id, macro_call_as_call_id_with_eager, macro_id_to_def_id, nameres::{ diagnostics::DefDiagnostic, mod_resolution::ModDir, @@ -52,10 +52,10 @@ use crate::{ tt, visibility::{RawVisibility, Visibility}, AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantId, - ExternBlockLoc, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, ImportLoc, Intern, - ItemContainerId, LocalModuleId, Macro2Id, Macro2Loc, MacroExpander, MacroId, MacroRulesId, - MacroRulesLoc, ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc, StructLoc, - TraitAliasLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, + ExternBlockLoc, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern, ItemContainerId, + LocalModuleId, Macro2Id, Macro2Loc, MacroExpander, MacroId, MacroRulesId, MacroRulesLoc, + ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc, StructLoc, TraitAliasLoc, + TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, UseLoc, }; static GLOB_RECURSION_LIMIT: Limit = Limit::new(100); @@ -146,7 +146,7 @@ impl PartialResolvedImport { #[derive(Clone, Debug, Eq, PartialEq)] enum ImportSource { - Import { id: ItemTreeId, use_tree: Idx }, + Use { id: ItemTreeId, use_tree: Idx }, ExternCrate(ItemTreeId), } @@ -166,7 +166,7 @@ impl Import { db: &dyn DefDatabase, krate: CrateId, tree: &ItemTree, - id: ItemTreeId, + id: ItemTreeId, mut cb: impl FnMut(Self), ) { let it = &tree[id.value]; @@ -181,7 +181,7 @@ impl Import { kind, is_prelude, is_macro_use: false, - source: ImportSource::Import { id, use_tree: idx }, + source: ImportSource::Use { id, use_tree: idx }, }); }); } @@ -1474,7 +1474,7 @@ impl DefCollector<'_> { } for directive in &self.unresolved_imports { - if let ImportSource::Import { id: import, use_tree } = directive.import.source { + if let ImportSource::Use { id: import, use_tree } = directive.import.source { if matches!( (directive.import.path.segments().first(), &directive.import.path.kind), (Some(krate), PathKind::Plain | PathKind::Abs) if diagnosed_extern_crates.contains(krate) @@ -1576,12 +1576,10 @@ impl ModCollector<'_, '_> { match item { ModItem::Mod(m) => self.collect_module(m, &attrs), - ModItem::Import(import_id) => { - let _import_id = ImportLoc { - container: module, - id: ItemTreeId::new(self.tree_id, import_id), - } - .intern(db); + ModItem::Use(import_id) => { + let _import_id = + UseLoc { container: module, id: ItemTreeId::new(self.tree_id, import_id) } + .intern(db); Import::from_use( db, krate, @@ -2187,7 +2185,7 @@ impl ModCollector<'_, '_> { // scopes without eager expansion. // Case 1: try to resolve macro calls with single-segment name and expand macro_rules - if let Ok(res) = macro_call_as_call_id( + if let Ok(res) = macro_call_as_call_id_with_eager( db.upcast(), &ast_id, mac.expand_to, @@ -2210,19 +2208,34 @@ impl ModCollector<'_, '_> { .map(|it| macro_id_to_def_id(self.def_collector.db, it)) }) }, - ) { - // Legacy macros need to be expanded immediately, so that any macros they produce - // are in scope. - if let Some(val) = res { - self.def_collector.collect_macro_expansion( + |path| { + let resolved_res = self.def_collector.def_map.resolve_path_fp_with_macro( + db, + ResolveMode::Other, self.module_id, - val, - self.macro_depth + 1, - container, + &path, + BuiltinShadowMode::Module, + Some(MacroSubNs::Bang), ); - } + resolved_res.resolved_def.take_macros().map(|it| macro_id_to_def_id(db, it)) + }, + ) { + // FIXME: if there were errors, this mightve been in the eager expansion from an + // unresolved macro, so we need to push this into late macro resolution. see fixme above + if res.err.is_none() { + // Legacy macros need to be expanded immediately, so that any macros they produce + // are in scope. + if let Some(val) = res.value { + self.def_collector.collect_macro_expansion( + self.module_id, + val, + self.macro_depth + 1, + container, + ); + } - return; + return; + } } // Case 2: resolve in module scope, expand during name resolution. diff --git a/crates/hir-def/src/nameres/diagnostics.rs b/crates/hir-def/src/nameres/diagnostics.rs index e82e97b628e9..9cffb3c9f37f 100644 --- a/crates/hir-def/src/nameres/diagnostics.rs +++ b/crates/hir-def/src/nameres/diagnostics.rs @@ -19,7 +19,7 @@ pub enum DefDiagnosticKind { UnresolvedExternCrate { ast: AstId }, - UnresolvedImport { id: ItemTreeId, index: Idx }, + UnresolvedImport { id: ItemTreeId, index: Idx }, UnconfiguredCode { ast: ErasedAstId, cfg: CfgExpr, opts: CfgOptions }, @@ -70,7 +70,7 @@ impl DefDiagnostic { pub(super) fn unresolved_import( container: LocalModuleId, - id: ItemTreeId, + id: ItemTreeId, index: Idx, ) -> Self { Self { in_module: container, kind: DefDiagnosticKind::UnresolvedImport { id, index } } diff --git a/crates/hir-def/src/nameres/tests/incremental.rs b/crates/hir-def/src/nameres/tests/incremental.rs index 4931c36bbca9..40d3a16540dc 100644 --- a/crates/hir-def/src/nameres/tests/incremental.rs +++ b/crates/hir-def/src/nameres/tests/incremental.rs @@ -213,17 +213,17 @@ pub type Ty = (); for (_, res) in module_data.scope.resolutions() { match res.values.or(res.types).unwrap().0 { - ModuleDefId::FunctionId(f) => drop(db.function_data(f)), + ModuleDefId::FunctionId(f) => _ = db.function_data(f), ModuleDefId::AdtId(adt) => match adt { - AdtId::StructId(it) => drop(db.struct_data(it)), - AdtId::UnionId(it) => drop(db.union_data(it)), - AdtId::EnumId(it) => drop(db.enum_data(it)), + AdtId::StructId(it) => _ = db.struct_data(it), + AdtId::UnionId(it) => _ = db.union_data(it), + AdtId::EnumId(it) => _ = db.enum_data(it), }, - ModuleDefId::ConstId(it) => drop(db.const_data(it)), - ModuleDefId::StaticId(it) => drop(db.static_data(it)), - ModuleDefId::TraitId(it) => drop(db.trait_data(it)), - ModuleDefId::TraitAliasId(it) => drop(db.trait_alias_data(it)), - ModuleDefId::TypeAliasId(it) => drop(db.type_alias_data(it)), + ModuleDefId::ConstId(it) => _ = db.const_data(it), + ModuleDefId::StaticId(it) => _ = db.static_data(it), + ModuleDefId::TraitId(it) => _ = db.trait_data(it), + ModuleDefId::TraitAliasId(it) => _ = db.trait_alias_data(it), + ModuleDefId::TypeAliasId(it) => _ = db.type_alias_data(it), ModuleDefId::EnumVariantId(_) | ModuleDefId::ModuleId(_) | ModuleDefId::MacroId(_) diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 10f5702845e2..b112c1070d49 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -25,7 +25,7 @@ use crate::{ EnumVariantId, ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId, LocalModuleId, Lookup, Macro2Id, MacroId, MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitAliasId, TraitId, - TypeAliasId, TypeOrConstParamId, TypeOwnerId, TypeParamId, VariantId, + TypeAliasId, TypeOrConstParamId, TypeOwnerId, TypeParamId, UseId, VariantId, }; #[derive(Debug, Clone)] @@ -1024,6 +1024,12 @@ impl HasResolver for ExternCrateId { } } +impl HasResolver for UseId { + fn resolver(self, db: &dyn DefDatabase) -> Resolver { + self.lookup(db).container.resolver(db) + } +} + impl HasResolver for TypeOwnerId { fn resolver(self, db: &dyn DefDatabase) -> Resolver { match self { diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs index 309c0930d1af..5292a5fa1b16 100644 --- a/crates/hir-expand/src/db.rs +++ b/crates/hir-expand/src/db.rs @@ -430,14 +430,13 @@ fn macro_arg_node( let loc = db.lookup_intern_macro_call(id); let arg = if let MacroDefKind::BuiltInEager(..) = loc.def.kind { let res = if let Some(EagerCallInfo { arg, .. }) = loc.eager.as_deref() { - Some(mbe::token_tree_to_syntax_node(&arg.0, mbe::TopEntryPoint::Expr).0) + Some(mbe::token_tree_to_syntax_node(&arg.0, mbe::TopEntryPoint::MacroEagerInput).0) } else { loc.kind .arg(db) .and_then(|arg| ast::TokenTree::cast(arg.value)) - .map(|tt| tt.reparse_as_expr().to_syntax()) + .map(|tt| tt.reparse_as_comma_separated_expr().to_syntax()) }; - match res { Some(res) if res.errors().is_empty() => res.syntax_node(), Some(res) => { diff --git a/crates/hir-expand/src/eager.rs b/crates/hir-expand/src/eager.rs index 876813eab5d5..4110f2847592 100644 --- a/crates/hir-expand/src/eager.rs +++ b/crates/hir-expand/src/eager.rs @@ -19,7 +19,7 @@ //! //! See the full discussion : use base_db::CrateId; -use rustc_hash::FxHashMap; +use rustc_hash::{FxHashMap, FxHashSet}; use syntax::{ted, Parse, SyntaxNode, TextRange, TextSize, WalkEvent}; use triomphe::Arc; @@ -29,7 +29,7 @@ use crate::{ hygiene::Hygiene, mod_path::ModPath, EagerCallInfo, ExpandError, ExpandResult, ExpandTo, InFile, MacroCallId, MacroCallKind, - MacroCallLoc, MacroDefId, MacroDefKind, UnresolvedMacro, + MacroCallLoc, MacroDefId, MacroDefKind, }; pub fn expand_eager_macro_input( @@ -38,7 +38,7 @@ pub fn expand_eager_macro_input( macro_call: InFile, def: MacroDefId, resolver: &dyn Fn(ModPath) -> Option, -) -> Result>, UnresolvedMacro> { +) -> ExpandResult> { let ast_map = db.ast_id_map(macro_call.file_id); // the expansion which the ast id map is built upon has no whitespace, so the offsets are wrong as macro_call is from the token tree that has whitespace! let call_id = InFile::new(macro_call.file_id, ast_map.ast_id(¯o_call.value)); @@ -71,41 +71,46 @@ pub fn expand_eager_macro_input( InFile::new(arg_id.as_file(), arg_exp.syntax_node()), krate, resolver, - )? + ) }; let err = parse_err.or(err); let Some((expanded_eager_input, mapping)) = expanded_eager_input else { - return Ok(ExpandResult { value: None, err }); + return ExpandResult { value: None, err }; }; - let og_tmap = mbe::syntax_node_to_token_map( - macro_call.value.token_tree().expect("macro_arg_text succeeded").syntax(), - ); - let (mut subtree, expanded_eager_input_token_map) = mbe::syntax_node_to_token_tree(&expanded_eager_input); - // The tokenmap and ids of subtree point into the expanded syntax node, but that is inaccessible from the outside - // so we need to remap them to the original input of the eager macro. - subtree.visit_ids(&|id| { - // Note: we discard all token ids of braces and the like here, but that's not too bad and only a temporary fix + let og_tmap = if let Some(tt) = macro_call.value.token_tree() { + let mut ids_used = FxHashSet::default(); + let mut og_tmap = mbe::syntax_node_to_token_map(tt.syntax()); + // The tokenmap and ids of subtree point into the expanded syntax node, but that is inaccessible from the outside + // so we need to remap them to the original input of the eager macro. + subtree.visit_ids(&mut |id| { + // Note: we discard all token ids of braces and the like here, but that's not too bad and only a temporary fix - if let Some(range) = - expanded_eager_input_token_map.first_range_by_token(id, syntax::SyntaxKind::TOMBSTONE) - { - // remap from expanded eager input to eager input expansion - if let Some(og_range) = mapping.get(&range) { - // remap from eager input expansion to original eager input - if let Some(&og_range) = ws_mapping.get(og_range) { - if let Some(og_token) = og_tmap.token_by_range(og_range) { - return og_token; + if let Some(range) = expanded_eager_input_token_map + .first_range_by_token(id, syntax::SyntaxKind::TOMBSTONE) + { + // remap from expanded eager input to eager input expansion + if let Some(og_range) = mapping.get(&range) { + // remap from eager input expansion to original eager input + if let Some(&og_range) = ws_mapping.get(og_range) { + if let Some(og_token) = og_tmap.token_by_range(og_range) { + ids_used.insert(og_token); + return og_token; + } } } } - } - tt::TokenId::UNSPECIFIED - }); + tt::TokenId::UNSPECIFIED + }); + og_tmap.filter(|id| ids_used.contains(&id)); + og_tmap + } else { + Default::default() + }; subtree.delimiter = crate::tt::Delimiter::unspecified(); let loc = MacroCallLoc { @@ -119,7 +124,7 @@ pub fn expand_eager_macro_input( kind: MacroCallKind::FnLike { ast_id: call_id, expand_to }, }; - Ok(ExpandResult { value: Some(db.intern_macro_call(loc)), err }) + ExpandResult { value: Some(db.intern_macro_call(loc)), err } } fn lazy_expand( @@ -145,13 +150,13 @@ fn eager_macro_recur( curr: InFile, krate: CrateId, macro_resolver: &dyn Fn(ModPath) -> Option, -) -> Result)>>, UnresolvedMacro> { +) -> ExpandResult)>> { let original = curr.value.clone_for_update(); let mut mapping = FxHashMap::default(); let mut replacements = Vec::new(); - // Note: We only report a single error inside of eager expansions + // FIXME: We only report a single error inside of eager expansions let mut error = None; let mut offset = 0i32; let apply_offset = |it: TextSize, offset: i32| { @@ -182,7 +187,14 @@ fn eager_macro_recur( } }; let def = match call.path().and_then(|path| ModPath::from_src(db, path, hygiene)) { - Some(path) => macro_resolver(path.clone()).ok_or(UnresolvedMacro { path })?, + Some(path) => match macro_resolver(path.clone()) { + Some(def) => def, + None => { + error = + Some(ExpandError::other(format!("unresolved macro {}", path.display(db)))); + continue; + } + }, None => { error = Some(ExpandError::other("malformed macro invocation")); continue; @@ -190,32 +202,31 @@ fn eager_macro_recur( }; let ExpandResult { value, err } = match def.kind { MacroDefKind::BuiltInEager(..) => { - let ExpandResult { value, err } = match expand_eager_macro_input( + let ExpandResult { value, err } = expand_eager_macro_input( db, krate, curr.with_value(call.clone()), def, macro_resolver, - ) { - Ok(it) => it, - Err(err) => return Err(err), - }; + ); match value { Some(call_id) => { let ExpandResult { value, err: err2 } = db.parse_macro_expansion(call_id.as_macro_file()); - let call_tt_start = - call.token_tree().unwrap().syntax().text_range().start(); - let call_start = apply_offset(call.syntax().text_range().start(), offset); - if let Some((_, arg_map, _)) = db.macro_arg(call_id).value.as_deref() { - mapping.extend(arg_map.entries().filter_map(|(tid, range)| { - value - .1 - .first_range_by_token(tid, syntax::SyntaxKind::TOMBSTONE) - .map(|r| (r + call_start, range + call_tt_start)) - })); - }; + if let Some(tt) = call.token_tree() { + let call_tt_start = tt.syntax().text_range().start(); + let call_start = + apply_offset(call.syntax().text_range().start(), offset); + if let Some((_, arg_map, _)) = db.macro_arg(call_id).value.as_deref() { + mapping.extend(arg_map.entries().filter_map(|(tid, range)| { + value + .1 + .first_range_by_token(tid, syntax::SyntaxKind::TOMBSTONE) + .map(|r| (r + call_start, range + call_tt_start)) + })); + } + } ExpandResult { value: Some(value.0.syntax_node().clone_for_update()), @@ -247,25 +258,27 @@ fn eager_macro_recur( parse.as_ref().map(|it| it.syntax_node()), krate, macro_resolver, - )?; + ); let err = err.or(error); - let call_tt_start = call.token_tree().unwrap().syntax().text_range().start(); - let call_start = apply_offset(call.syntax().text_range().start(), offset); - if let Some((_tt, arg_map, _)) = parse - .file_id - .macro_file() - .and_then(|id| db.macro_arg(id.macro_call_id).value) - .as_deref() - { - mapping.extend(arg_map.entries().filter_map(|(tid, range)| { - tm.first_range_by_token( - decl_mac.as_ref().map(|it| it.map_id_down(tid)).unwrap_or(tid), - syntax::SyntaxKind::TOMBSTONE, - ) - .map(|r| (r + call_start, range + call_tt_start)) - })); - }; + if let Some(tt) = call.token_tree() { + let call_tt_start = tt.syntax().text_range().start(); + let call_start = apply_offset(call.syntax().text_range().start(), offset); + if let Some((_tt, arg_map, _)) = parse + .file_id + .macro_file() + .and_then(|id| db.macro_arg(id.macro_call_id).value) + .as_deref() + { + mapping.extend(arg_map.entries().filter_map(|(tid, range)| { + tm.first_range_by_token( + decl_mac.as_ref().map(|it| it.map_id_down(tid)).unwrap_or(tid), + syntax::SyntaxKind::TOMBSTONE, + ) + .map(|r| (r + call_start, range + call_tt_start)) + })); + } + } // FIXME: Do we need to re-use _m here? ExpandResult { value: value.map(|(n, _m)| n), err } } @@ -275,7 +288,7 @@ fn eager_macro_recur( } // check if the whole original syntax is replaced if call.syntax() == &original { - return Ok(ExpandResult { value: value.zip(Some(mapping)), err: error }); + return ExpandResult { value: value.zip(Some(mapping)), err: error }; } if let Some(insert) = value { @@ -286,5 +299,5 @@ fn eager_macro_recur( } replacements.into_iter().rev().for_each(|(old, new)| ted::replace(old.syntax(), new)); - Ok(ExpandResult { value: Some((original, mapping)), err: error }) + ExpandResult { value: Some((original, mapping)), err: error } } diff --git a/crates/hir-expand/src/hygiene.rs b/crates/hir-expand/src/hygiene.rs index 54e74d50c87e..ade4a5928933 100644 --- a/crates/hir-expand/src/hygiene.rs +++ b/crates/hir-expand/src/hygiene.rs @@ -173,7 +173,7 @@ fn make_hygiene_info( db: &dyn ExpandDatabase, macro_file: MacroFile, loc: &MacroCallLoc, -) -> Option { +) -> HygieneInfo { let def = loc.def.ast_id().left().and_then(|id| { let def_tt = match id.to_node(db) { ast::Macro::MacroRules(mac) => mac.token_tree()?, @@ -204,7 +204,7 @@ fn make_hygiene_info( )) }); - Some(HygieneInfo { + HygieneInfo { file: macro_file, attr_input_or_mac_def_start: attr_input_or_mac_def .map(|it| it.map(|tt| tt.syntax().text_range().start())), @@ -212,7 +212,7 @@ fn make_hygiene_info( macro_arg, macro_def, exp_map, - }) + } } impl HygieneFrame { @@ -221,8 +221,7 @@ impl HygieneFrame { None => (None, None, false), Some(macro_file) => { let loc = db.lookup_intern_macro_call(macro_file.macro_call_id); - let info = - make_hygiene_info(db, macro_file, &loc).map(|info| (loc.kind.file_id(), info)); + let info = Some((make_hygiene_info(db, macro_file, &loc), loc.kind.file_id())); match loc.def.kind { MacroDefKind::Declarative(_) => { (info, Some(loc.def.krate), loc.def.local_inner) @@ -236,17 +235,14 @@ impl HygieneFrame { } }; - let (calling_file, info) = match info { - None => { - return HygieneFrame { - expansion: None, - local_inner, - krate, - call_site: None, - def_site: None, - }; + let Some((info, calling_file)) = info else { + return HygieneFrame { + expansion: None, + local_inner, + krate, + call_site: None, + def_site: None, } - Some(it) => it, }; let def_site = info.attr_input_or_mac_def_start.map(|it| db.hygiene_frame(it.file_id)); diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs index 9ed6c31ddde5..1f1e20f49e3c 100644 --- a/crates/hir-expand/src/lib.rs +++ b/crates/hir-expand/src/lib.rs @@ -415,6 +415,24 @@ impl MacroDefId { ) } + pub fn is_derive(&self) -> bool { + matches!( + self.kind, + MacroDefKind::BuiltInDerive(..) + | MacroDefKind::ProcMacro(_, ProcMacroKind::CustomDerive, _) + ) + } + + pub fn is_fn_like(&self) -> bool { + matches!( + self.kind, + MacroDefKind::BuiltIn(..) + | MacroDefKind::ProcMacro(_, ProcMacroKind::FuncLike, _) + | MacroDefKind::BuiltInEager(..) + | MacroDefKind::Declarative(..) + ) + } + pub fn is_attribute_derive(&self) -> bool { matches!(self.kind, MacroDefKind::BuiltInAttr(expander, ..) if expander.is_derive()) } diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs index 98ebe557245f..666955fa1c38 100644 --- a/crates/hir-ty/src/consteval/tests.rs +++ b/crates/hir-ty/src/consteval/tests.rs @@ -1186,6 +1186,25 @@ fn pattern_matching_ergonomics() { ); } +#[test] +fn destructing_assignment() { + check_number( + r#" + //- minicore: add + const fn f(i: &mut u8) -> &mut u8 { + *i += 1; + i + } + const GOAL: u8 = { + let mut i = 4; + _ = f(&mut i); + i + }; + "#, + 5, + ); +} + #[test] fn let_else() { check_number( @@ -1428,14 +1447,14 @@ fn builtin_derive_macro() { #[derive(Clone)] struct Y { field1: i32, - field2: u8, + field2: ((i32, u8), i64), } const GOAL: u8 = { - let x = X(2, Z::Foo(Y { field1: 4, field2: 5 }), 8); + let x = X(2, Z::Foo(Y { field1: 4, field2: ((32, 5), 12) }), 8); let x = x.clone(); let Z::Foo(t) = x.1; - t.field2 + t.field2.0 .1 }; "#, 5, @@ -1632,6 +1651,34 @@ const GOAL: i32 = { ); } +#[test] +fn closure_capture_unsized_type() { + check_number( + r#" + //- minicore: fn, copy, slice, index, coerce_unsized + fn f(x: &::Ty) -> &::Ty { + let c = || &*x; + c() + } + + trait A { + type Ty; + } + + impl A for i32 { + type Ty = [u8]; + } + + const GOAL: u8 = { + let k: &[u8] = &[1, 2, 3]; + let k = f::(k); + k[0] + k[1] + k[2] + } + "#, + 6, + ); +} + #[test] fn closure_and_impl_fn() { check_number( @@ -1717,6 +1764,24 @@ fn function_pointer_in_constants() { ); } +#[test] +fn function_pointer_and_niche_optimization() { + check_number( + r#" + //- minicore: option + const GOAL: i32 = { + let f: fn(i32) -> i32 = |x| x + 2; + let init = Some(f); + match init { + Some(t) => t(3), + None => 222, + } + }; + "#, + 5, + ); +} + #[test] fn function_pointer() { check_number( @@ -2331,11 +2396,14 @@ fn const_loop() { fn const_transfer_memory() { check_number( r#" - const A1: &i32 = &2; - const A2: &i32 = &5; - const GOAL: i32 = *A1 + *A2; + //- minicore: slice, index, coerce_unsized + const A1: &i32 = &1; + const A2: &i32 = &10; + const A3: [&i32; 3] = [&1, &2, &100]; + const A4: (i32, &i32) = (1, &1000); + const GOAL: i32 = *A1 + *A2 + *A3[2] + *A4.1; "#, - 7, + 1111, ); } @@ -2521,12 +2589,16 @@ fn const_trait_assoc() { ); check_number( r#" - //- minicore: size_of + //- minicore: size_of, fn //- /a/lib.rs crate:a use core::mem::size_of; pub struct S(T); impl S { - pub const X: usize = core::mem::size_of::(); + pub const X: usize = { + let k: T; + let f = || core::mem::size_of::(); + f() + }; } //- /main.rs crate:main deps:a use a::{S}; @@ -2602,9 +2674,9 @@ fn exec_limits() { } sum } - const GOAL: i32 = f(10000); + const GOAL: i32 = f(1000); "#, - 10000 * 10000, + 1000 * 1000, ); } @@ -2651,7 +2723,7 @@ fn unsized_field() { //- minicore: coerce_unsized, index, slice, transmute use core::mem::transmute; - struct Slice([u8]); + struct Slice([usize]); struct Slice2(Slice); impl Slice2 { @@ -2659,19 +2731,19 @@ fn unsized_field() { &self.0 } - fn as_bytes(&self) -> &[u8] { + fn as_bytes(&self) -> &[usize] { &self.as_inner().0 } } - const GOAL: u8 = unsafe { - let x: &[u8] = &[1, 2, 3]; + const GOAL: usize = unsafe { + let x: &[usize] = &[1, 2, 3]; let x: &Slice2 = transmute(x); let x = x.as_bytes(); - x[0] + x[1] + x[2] + x[0] + x[1] + x[2] + x.len() * 100 }; "#, - 6, + 306, ); } diff --git a/crates/hir-ty/src/consteval/tests/intrinsics.rs b/crates/hir-ty/src/consteval/tests/intrinsics.rs index 9253e31d77b6..2855f789001a 100644 --- a/crates/hir-ty/src/consteval/tests/intrinsics.rs +++ b/crates/hir-ty/src/consteval/tests/intrinsics.rs @@ -251,6 +251,28 @@ fn wrapping_add() { ); } +#[test] +fn ptr_offset_from() { + check_number( + r#" + //- minicore: index, slice, coerce_unsized + extern "rust-intrinsic" { + pub fn ptr_offset_from(ptr: *const T, base: *const T) -> isize; + pub fn ptr_offset_from_unsigned(ptr: *const T, base: *const T) -> usize; + } + + const GOAL: isize = { + let x = [1, 2, 3, 4, 5i32]; + let r1 = -ptr_offset_from(&x[0], &x[4]); + let r2 = ptr_offset_from(&x[3], &x[1]); + let r3 = ptr_offset_from_unsigned(&x[3], &x[0]) as isize; + r3 * 100 + r2 * 10 + r1 + }; + "#, + 324, + ); +} + #[test] fn saturating() { check_number( @@ -438,6 +460,8 @@ fn atomic() { pub fn atomic_nand_seqcst(dst: *mut T, src: T) -> T; pub fn atomic_or_release(dst: *mut T, src: T) -> T; pub fn atomic_xor_seqcst(dst: *mut T, src: T) -> T; + pub fn atomic_fence_seqcst(); + pub fn atomic_singlethreadfence_acqrel(); } fn should_not_reach() { @@ -452,6 +476,7 @@ fn atomic() { if (30, true) != atomic_cxchg_release_seqcst(&mut y, 30, 40) { should_not_reach(); } + atomic_fence_seqcst(); if (40, false) != atomic_cxchg_release_seqcst(&mut y, 30, 50) { should_not_reach(); } @@ -459,6 +484,7 @@ fn atomic() { should_not_reach(); } let mut z = atomic_xsub_seqcst(&mut x, -200); + atomic_singlethreadfence_acqrel(); atomic_xor_seqcst(&mut x, 1024); atomic_load_seqcst(&x) + z * 3 + atomic_load_seqcst(&y) * 2 }; diff --git a/crates/hir-ty/src/diagnostics/decl_check.rs b/crates/hir-ty/src/diagnostics/decl_check.rs index 5aaa2bcc7c2c..a94a962c1f85 100644 --- a/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/crates/hir-ty/src/diagnostics/decl_check.rs @@ -176,6 +176,7 @@ impl<'a> DeclValidator<'a> { AttrDefId::ImplId(iid) => Some(iid.lookup(self.db.upcast()).container.into()), AttrDefId::ExternBlockId(id) => Some(id.lookup(self.db.upcast()).container.into()), AttrDefId::ExternCrateId(id) => Some(id.lookup(self.db.upcast()).container.into()), + AttrDefId::UseId(id) => Some(id.lookup(self.db.upcast()).container.into()), // These warnings should not explore macro definitions at all AttrDefId::MacroId(_) => None, AttrDefId::AdtId(aid) => match aid { diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 96787959e1f2..1b4ee4613d61 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -48,22 +48,15 @@ use crate::{ }; pub trait HirWrite: fmt::Write { - fn start_location_link(&mut self, location: ModuleDefId); - fn end_location_link(&mut self); + fn start_location_link(&mut self, _location: ModuleDefId) {} + fn end_location_link(&mut self) {} } // String will ignore link metadata -impl HirWrite for String { - fn start_location_link(&mut self, _: ModuleDefId) {} - - fn end_location_link(&mut self) {} -} +impl HirWrite for String {} // `core::Formatter` will ignore metadata -impl HirWrite for fmt::Formatter<'_> { - fn start_location_link(&mut self, _: ModuleDefId) {} - fn end_location_link(&mut self) {} -} +impl HirWrite for fmt::Formatter<'_> {} pub struct HirFormatter<'a> { pub db: &'a dyn HirDatabase, @@ -885,6 +878,13 @@ impl HirDisplay for Ty { TyKind::FnDef(def, parameters) => { let def = from_chalk(db, *def); let sig = db.callable_item_signature(def).substitute(Interner, parameters); + + if f.display_target.is_source_code() { + // `FnDef` is anonymous and there's no surface syntax for it. Show it as a + // function pointer type. + return sig.hir_fmt(f); + } + f.start_location_link(def.into()); match def { CallableDefId::FunctionId(ff) => { diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 0a617dae7d43..b4915dbf0f99 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -13,6 +13,15 @@ //! to certain types. To record this, we use the union-find implementation from //! the `ena` crate, which is extracted from rustc. +mod cast; +pub(crate) mod closure; +mod coerce; +mod expr; +mod mutability; +mod pat; +mod path; +pub(crate) mod unify; + use std::{convert::identity, ops::Index}; use chalk_ir::{ @@ -60,15 +69,8 @@ pub use coerce::could_coerce; #[allow(unreachable_pub)] pub use unify::could_unify; -pub(crate) use self::closure::{CaptureKind, CapturedItem, CapturedItemWithoutTy}; - -pub(crate) mod unify; -mod path; -mod expr; -mod pat; -mod coerce; -pub(crate) mod closure; -mod mutability; +use cast::CastCheck; +pub(crate) use closure::{CaptureKind, CapturedItem, CapturedItemWithoutTy}; /// The entry point of type inference. pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc { @@ -508,6 +510,8 @@ pub(crate) struct InferenceContext<'a> { diverges: Diverges, breakables: Vec, + deferred_cast_checks: Vec, + // fields related to closure capture current_captures: Vec, current_closure: Option, @@ -582,7 +586,8 @@ impl<'a> InferenceContext<'a> { resolver, diverges: Diverges::Maybe, breakables: Vec::new(), - current_captures: vec![], + deferred_cast_checks: Vec::new(), + current_captures: Vec::new(), current_closure: None, deferred_closures: FxHashMap::default(), closure_dependencies: FxHashMap::default(), @@ -594,7 +599,7 @@ impl<'a> InferenceContext<'a> { // used this function for another workaround, mention it here. If you really need this function and believe that // there is no problem in it being `pub(crate)`, remove this comment. pub(crate) fn resolve_all(self) -> InferenceResult { - let InferenceContext { mut table, mut result, .. } = self; + let InferenceContext { mut table, mut result, deferred_cast_checks, .. } = self; // Destructure every single field so whenever new fields are added to `InferenceResult` we // don't forget to handle them here. let InferenceResult { @@ -622,6 +627,13 @@ impl<'a> InferenceContext<'a> { table.fallback_if_possible(); + // Comment from rustc: + // Even though coercion casts provide type hints, we check casts after fallback for + // backwards compatibility. This makes fallback a stronger type hint than a cast coercion. + for cast in deferred_cast_checks { + cast.check(&mut table); + } + // FIXME resolve obligations as well (use Guidance if necessary) table.resolve_obligations_as_possible(); diff --git a/crates/hir-ty/src/infer/cast.rs b/crates/hir-ty/src/infer/cast.rs new file mode 100644 index 000000000000..9e1c74b16fa0 --- /dev/null +++ b/crates/hir-ty/src/infer/cast.rs @@ -0,0 +1,46 @@ +//! Type cast logic. Basically coercion + additional casts. + +use crate::{infer::unify::InferenceTable, Interner, Ty, TyExt, TyKind}; + +#[derive(Clone, Debug)] +pub(super) struct CastCheck { + expr_ty: Ty, + cast_ty: Ty, +} + +impl CastCheck { + pub(super) fn new(expr_ty: Ty, cast_ty: Ty) -> Self { + Self { expr_ty, cast_ty } + } + + pub(super) fn check(self, table: &mut InferenceTable<'_>) { + // FIXME: This function currently only implements the bits that influence the type + // inference. We should return the adjustments on success and report diagnostics on error. + let expr_ty = table.resolve_ty_shallow(&self.expr_ty); + let cast_ty = table.resolve_ty_shallow(&self.cast_ty); + + if expr_ty.contains_unknown() || cast_ty.contains_unknown() { + return; + } + + if table.coerce(&expr_ty, &cast_ty).is_ok() { + return; + } + + if check_ref_to_ptr_cast(expr_ty, cast_ty, table) { + // Note that this type of cast is actually split into a coercion to a + // pointer type and a cast: + // &[T; N] -> *[T; N] -> *T + return; + } + + // FIXME: Check other kinds of non-coercion casts and report error if any? + } +} + +fn check_ref_to_ptr_cast(expr_ty: Ty, cast_ty: Ty, table: &mut InferenceTable<'_>) -> bool { + let Some((expr_inner_ty, _, _)) = expr_ty.as_reference() else { return false; }; + let Some((cast_inner_ty, _)) = cast_ty.as_raw_ptr() else { return false; }; + let TyKind::Array(expr_elt_ty, _) = expr_inner_ty.kind(Interner) else { return false; }; + table.coerce(expr_elt_ty, cast_inner_ty).is_ok() +} diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index 972e5321a475..1781f6c58f1c 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -488,10 +488,6 @@ impl InferenceContext<'_> { self.consume_expr(*tail); } } - Expr::While { condition, body, label: _ } => { - self.consume_expr(*condition); - self.consume_expr(*body); - } Expr::Call { callee, args, is_assignee_expr: _ } => { self.consume_expr(*callee); self.consume_exprs(args.iter().copied()); diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 72e6443beb77..8cbdae625267 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -46,8 +46,8 @@ use crate::{ }; use super::{ - coerce::auto_deref_adjust_steps, find_breakable, BreakableContext, Diverges, Expectation, - InferenceContext, InferenceDiagnostic, TypeMismatch, + cast::CastCheck, coerce::auto_deref_adjust_steps, find_breakable, BreakableContext, Diverges, + Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch, }; impl InferenceContext<'_> { @@ -198,19 +198,6 @@ impl InferenceContext<'_> { None => self.result.standard_types.never.clone(), } } - &Expr::While { condition, body, label } => { - self.with_breakable_ctx(BreakableKind::Loop, None, label, |this| { - this.infer_expr( - condition, - &Expectation::HasType(this.result.standard_types.bool_.clone()), - ); - this.infer_expr(body, &Expectation::HasType(TyBuilder::unit())); - }); - - // the body may not run, so it diverging doesn't mean we diverge - self.diverges = Diverges::Maybe; - TyBuilder::unit() - } Expr::Closure { body, args, ret_type, arg_types, closure_kind, capture_by: _ } => { assert_eq!(args.len(), arg_types.len()); @@ -574,16 +561,8 @@ impl InferenceContext<'_> { } Expr::Cast { expr, type_ref } => { let cast_ty = self.make_ty(type_ref); - // FIXME: propagate the "castable to" expectation - let inner_ty = self.infer_expr_no_expect(*expr); - match (inner_ty.kind(Interner), cast_ty.kind(Interner)) { - (TyKind::Ref(_, _, inner), TyKind::Raw(_, cast)) => { - // FIXME: record invalid cast diagnostic in case of mismatch - self.unify(inner, cast); - } - // FIXME check the other kinds of cast... - _ => (), - } + let expr_ty = self.infer_expr(*expr, &Expectation::Castable(cast_ty.clone())); + self.deferred_cast_checks.push(CastCheck::new(expr_ty, cast_ty.clone())); cast_ty } Expr::Ref { expr, rawness, mutability } => { @@ -1592,7 +1571,7 @@ impl InferenceContext<'_> { output: Ty, inputs: Vec, ) -> Vec { - if let Some(expected_ty) = expected_output.to_option(&mut self.table) { + if let Some(expected_ty) = expected_output.only_has_type(&mut self.table) { self.table.fudge_inference(|table| { if table.try_unify(&expected_ty, &output).is_ok() { table.resolve_with_fallback(inputs, &|var, kind, _, _| match kind { diff --git a/crates/hir-ty/src/infer/mutability.rs b/crates/hir-ty/src/infer/mutability.rs index f517bc2c09f1..396ca0044ff0 100644 --- a/crates/hir-ty/src/infer/mutability.rs +++ b/crates/hir-ty/src/infer/mutability.rs @@ -69,10 +69,6 @@ impl InferenceContext<'_> { self.infer_mut_expr(*tail, Mutability::Not); } } - &Expr::While { condition: c, body, label: _ } => { - self.infer_mut_expr(c, Mutability::Not); - self.infer_mut_expr(body, Mutability::Not); - } Expr::MethodCall { receiver: it, method_name: _, args, generic_args: _ } | Expr::Call { callee: it, args, is_assignee_expr: _ } => { self.infer_mut_not_expr_iter(args.iter().copied().chain(Some(*it))); diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs index ffc7a6f2ebd7..b15339d4434c 100644 --- a/crates/hir-ty/src/layout.rs +++ b/crates/hir-ty/src/layout.rs @@ -14,7 +14,7 @@ use triomphe::Arc; use crate::{ consteval::try_const_usize, db::HirDatabase, infer::normalize, layout::adt::struct_variant_idx, - utils::ClosureSubst, Interner, Substitution, TraitEnvironment, Ty, + utils::ClosureSubst, Interner, ProjectionTy, Substitution, TraitEnvironment, Ty, }; pub use self::{ @@ -279,7 +279,15 @@ pub fn layout_of_ty_query( // return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr))); // } - let unsized_part = struct_tail_erasing_lifetimes(db, pointee.clone()); + let mut unsized_part = struct_tail_erasing_lifetimes(db, pointee.clone()); + if let TyKind::AssociatedType(id, subst) = unsized_part.kind(Interner) { + unsized_part = TyKind::Alias(chalk_ir::AliasTy::Projection(ProjectionTy { + associated_ty_id: *id, + substitution: subst.clone(), + })) + .intern(Interner); + } + unsized_part = normalize(db, trait_env.clone(), unsized_part); let metadata = match unsized_part.kind(Interner) { TyKind::Slice(_) | TyKind::Str => { scalar_unit(dl, Primitive::Int(dl.ptr_sized_integer(), false)) @@ -362,8 +370,16 @@ pub fn layout_of_ty_query( return Err(LayoutError::NotImplemented) } TyKind::Error => return Err(LayoutError::HasErrorType), - TyKind::AssociatedType(_, _) - | TyKind::Alias(_) + TyKind::AssociatedType(id, subst) => { + // Try again with `TyKind::Alias` to normalize the associated type. + let ty = TyKind::Alias(chalk_ir::AliasTy::Projection(ProjectionTy { + associated_ty_id: *id, + substitution: subst.clone(), + })) + .intern(Interner); + return db.layout_of_ty(ty, trait_env); + } + TyKind::Alias(_) | TyKind::Placeholder(_) | TyKind::BoundVar(_) | TyKind::InferenceVar(_, _) => return Err(LayoutError::HasPlaceholder), diff --git a/crates/hir-ty/src/mir.rs b/crates/hir-ty/src/mir.rs index 922e49d281d0..4723c25ed080 100644 --- a/crates/hir-ty/src/mir.rs +++ b/crates/hir-ty/src/mir.rs @@ -234,6 +234,7 @@ impl Place { self.local == child.local && child.projection.starts_with(&self.projection) } + /// The place itself is not included fn iterate_over_parents(&self) -> impl Iterator + '_ { (0..self.projection.len()) .map(|x| &self.projection[0..x]) diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 7bd2756c14f4..9e30eed56f3a 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -1,6 +1,13 @@ //! This module provides a MIR interpreter, which is used in const eval. -use std::{borrow::Cow, cell::RefCell, collections::HashMap, fmt::Write, iter, mem, ops::Range}; +use std::{ + borrow::Cow, + cell::RefCell, + collections::{HashMap, HashSet}, + fmt::Write, + iter, mem, + ops::Range, +}; use base_db::{CrateId, FileId}; use chalk_ir::Mutability; @@ -39,7 +46,8 @@ use crate::{ use super::{ return_slot, AggregateKind, BasicBlockId, BinOp, CastKind, LocalId, MirBody, MirLowerError, - MirSpan, Operand, Place, ProjectionElem, Rvalue, StatementKind, TerminatorKind, UnOp, + MirSpan, Operand, Place, PlaceElem, ProjectionElem, Rvalue, StatementKind, TerminatorKind, + UnOp, }; mod shim; @@ -68,18 +76,22 @@ pub struct VTableMap { } impl VTableMap { + const OFFSET: usize = 1000; // We should add some offset to ids to make 0 (null) an invalid id. + fn id(&mut self, ty: Ty) -> usize { if let Some(it) = self.ty_to_id.get(&ty) { return *it; } - let id = self.id_to_ty.len(); + let id = self.id_to_ty.len() + VTableMap::OFFSET; self.id_to_ty.push(ty.clone()); self.ty_to_id.insert(ty, id); id } pub(crate) fn ty(&self, id: usize) -> Result<&Ty> { - self.id_to_ty.get(id).ok_or(MirEvalError::InvalidVTableId(id)) + id.checked_sub(VTableMap::OFFSET) + .and_then(|id| self.id_to_ty.get(id)) + .ok_or(MirEvalError::InvalidVTableId(id)) } fn ty_of_bytes(&self, bytes: &[u8]) -> Result<&Ty> { @@ -116,13 +128,18 @@ impl TlsData { } struct StackFrame { - body: Arc, locals: Locals, destination: Option, prev_stack_ptr: usize, span: (MirSpan, DefWithBodyId), } +#[derive(Clone)] +enum MirOrDynIndex { + Mir(Arc), + Dyn(usize), +} + pub struct Evaluator<'a> { db: &'a dyn HirDatabase, trait_env: Arc, @@ -141,6 +158,17 @@ pub struct Evaluator<'a> { stdout: Vec, stderr: Vec, layout_cache: RefCell>>, + projected_ty_cache: RefCell>, + not_special_fn_cache: RefCell>, + mir_or_dyn_index_cache: RefCell>, + /// Constantly dropping and creating `Locals` is very costly. We store + /// old locals that we normaly want to drop here, to reuse their allocations + /// later. + unused_locals_store: RefCell>>, + cached_ptr_size: usize, + cached_fn_trait_func: Option, + cached_fn_mut_trait_func: Option, + cached_fn_once_trait_func: Option, crate_id: CrateId, // FIXME: This is a workaround, see the comment on `interpret_mir` assert_placeholder_ty_is_unused: bool, @@ -313,6 +341,7 @@ pub enum MirEvalError { InvalidVTableId(usize), CoerceUnsizedError(Ty), LangItemNotFound(LangItem), + BrokenLayout(Layout), } impl MirEvalError { @@ -399,6 +428,7 @@ impl MirEvalError { | MirEvalError::TargetDataLayoutNotAvailable | MirEvalError::CoerceUnsizedError(_) | MirEvalError::LangItemNotFound(_) + | MirEvalError::BrokenLayout(_) | MirEvalError::InvalidVTableId(_) => writeln!(f, "{:?}", err)?, } Ok(()) @@ -433,6 +463,7 @@ impl std::fmt::Debug for MirEvalError { Self::CoerceUnsizedError(arg0) => { f.debug_tuple("CoerceUnsizedError").field(arg0).finish() } + Self::BrokenLayout(arg0) => f.debug_tuple("BrokenLayout").field(arg0).finish(), Self::InvalidVTableId(arg0) => f.debug_tuple("InvalidVTableId").field(arg0).finish(), Self::NotSupported(arg0) => f.debug_tuple("NotSupported").field(arg0).finish(), Self::InvalidConst(arg0) => { @@ -464,8 +495,16 @@ impl DropFlags { fn remove_place(&mut self, p: &Place) -> bool { // FIXME: replace parents with parts + if let Some(parent) = p.iterate_over_parents().find(|it| self.need_drop.contains(&it)) { + self.need_drop.remove(&parent); + return true; + } self.need_drop.remove(p) } + + fn clear(&mut self) { + self.need_drop.clear(); + } } #[derive(Debug)] @@ -508,6 +547,11 @@ pub fn interpret_mir( ) } +#[cfg(test)] +const EXECUTION_LIMIT: usize = 100_000; +#[cfg(not(test))] +const EXECUTION_LIMIT: usize = 10_000_000; + impl Evaluator<'_> { pub fn new<'a>( db: &'a dyn HirDatabase, @@ -531,9 +575,29 @@ impl Evaluator<'_> { stderr: vec![], assert_placeholder_ty_is_unused, stack_depth_limit: 100, - execution_limit: 1000_000, + execution_limit: EXECUTION_LIMIT, memory_limit: 1000_000_000, // 2GB, 1GB for stack and 1GB for heap layout_cache: RefCell::new(HashMap::default()), + projected_ty_cache: RefCell::new(HashMap::default()), + not_special_fn_cache: RefCell::new(HashSet::default()), + mir_or_dyn_index_cache: RefCell::new(HashMap::default()), + unused_locals_store: RefCell::new(HashMap::default()), + cached_ptr_size: match db.target_data_layout(crate_id) { + Some(it) => it.pointer_size.bytes_usize(), + None => 8, + }, + cached_fn_trait_func: db + .lang_item(crate_id, LangItem::Fn) + .and_then(|x| x.as_trait()) + .and_then(|x| db.trait_data(x).method_by_name(&name![call])), + cached_fn_mut_trait_func: db + .lang_item(crate_id, LangItem::FnMut) + .and_then(|x| x.as_trait()) + .and_then(|x| db.trait_data(x).method_by_name(&name![call_mut])), + cached_fn_once_trait_func: db + .lang_item(crate_id, LangItem::FnOnce) + .and_then(|x| x.as_trait()) + .and_then(|x| db.trait_data(x).method_by_name(&name![call_once])), } } @@ -554,10 +618,34 @@ impl Evaluator<'_> { } fn ptr_size(&self) -> usize { - match self.db.target_data_layout(self.crate_id) { - Some(it) => it.pointer_size.bytes_usize(), - None => 8, + self.cached_ptr_size + } + + fn projected_ty(&self, ty: Ty, proj: PlaceElem) -> Ty { + let pair = (ty, proj); + if let Some(r) = self.projected_ty_cache.borrow().get(&pair) { + return r.clone(); } + let (ty, proj) = pair; + let r = proj.projected_ty( + ty.clone(), + self.db, + |c, subst, f| { + let (def, _) = self.db.lookup_intern_closure(c.into()); + let infer = self.db.infer(def); + let (captures, _) = infer.closure_info(&c); + let parent_subst = ClosureSubst(subst).parent_subst(); + captures + .get(f) + .expect("broken closure field") + .ty + .clone() + .substitute(Interner, parent_subst) + }, + self.crate_id, + ); + self.projected_ty_cache.borrow_mut().insert((ty, proj), r.clone()); + r } fn place_addr_and_ty_and_metadata<'a>( @@ -570,23 +658,7 @@ impl Evaluator<'_> { let mut metadata: Option = None; // locals are always sized for proj in &*p.projection { let prev_ty = ty.clone(); - ty = proj.projected_ty( - ty, - self.db, - |c, subst, f| { - let (def, _) = self.db.lookup_intern_closure(c.into()); - let infer = self.db.infer(def); - let (captures, _) = infer.closure_info(&c); - let parent_subst = ClosureSubst(subst).parent_subst(); - captures - .get(f) - .expect("broken closure field") - .ty - .clone() - .substitute(Interner, parent_subst) - }, - self.crate_id, - ); + ty = self.projected_ty(ty, proj.clone()); match proj { ProjectionElem::Deref => { metadata = if self.size_align_of(&ty, locals)?.is_none() { @@ -680,8 +752,10 @@ impl Evaluator<'_> { .offset(u32::from(f.local_id.into_raw()) as usize) .bytes_usize(); addr = addr.offset(offset); - // FIXME: support structs with unsized fields - metadata = None; + // Unsized field metadata is equal to the metadata of the struct + if self.size_align_of(&ty, locals)?.is_some() { + metadata = None; + } } ProjectionElem::OpaqueCast(_) => not_supported!("opaque cast"), } @@ -702,9 +776,7 @@ impl Evaluator<'_> { } fn layout_adt(&self, adt: AdtId, subst: Substitution) -> Result> { - self.db.layout_of_adt(adt, subst.clone(), self.trait_env.clone()).map_err(|e| { - MirEvalError::LayoutError(e, TyKind::Adt(chalk_ir::AdtId(adt), subst).intern(Interner)) - }) + self.layout(&TyKind::Adt(chalk_ir::AdtId(adt), subst).intern(Interner)) } fn place_ty<'a>(&'a self, p: &Place, locals: &'a Locals) -> Result { @@ -740,18 +812,18 @@ impl Evaluator<'_> { return Err(MirEvalError::StackOverflow); } let mut current_block_idx = body.start_block; - let (mut locals, prev_stack_ptr) = self.create_locals_for_body(body.clone(), None)?; + let (mut locals, prev_stack_ptr) = self.create_locals_for_body(&body, None)?; self.fill_locals_for_body(&body, &mut locals, args)?; let prev_code_stack = mem::take(&mut self.code_stack); let span = (MirSpan::Unknown, body.owner); - self.code_stack.push(StackFrame { body, locals, destination: None, prev_stack_ptr, span }); + self.code_stack.push(StackFrame { locals, destination: None, prev_stack_ptr, span }); 'stack: loop { let Some(mut my_stack_frame) = self.code_stack.pop() else { not_supported!("missing stack frame"); }; let e = (|| { let mut locals = &mut my_stack_frame.locals; - let body = &*my_stack_frame.body; + let body = locals.body.clone(); loop { let current_block = &body.basic_blocks[current_block_idx]; if let Some(it) = self.execution_limit.checked_sub(1) { @@ -820,7 +892,7 @@ impl Evaluator<'_> { locals.drop_flags.add_place(destination.clone()); if let Some(stack_frame) = stack_frame { self.code_stack.push(my_stack_frame); - current_block_idx = stack_frame.body.start_block; + current_block_idx = stack_frame.locals.body.start_block; self.code_stack.push(stack_frame); return Ok(None); } else { @@ -861,18 +933,24 @@ impl Evaluator<'_> { let my_code_stack = mem::replace(&mut self.code_stack, prev_code_stack); let mut error_stack = vec![]; for frame in my_code_stack.into_iter().rev() { - if let DefWithBodyId::FunctionId(f) = frame.body.owner { + if let DefWithBodyId::FunctionId(f) = frame.locals.body.owner { error_stack.push((Either::Left(f), frame.span.0, frame.span.1)); } } return Err(MirEvalError::InFunction(Box::new(e), error_stack)); } }; + let return_interval = my_stack_frame.locals.ptr[return_slot()]; + self.unused_locals_store + .borrow_mut() + .entry(my_stack_frame.locals.body.owner) + .or_default() + .push(my_stack_frame.locals); match my_stack_frame.destination { None => { self.code_stack = prev_code_stack; self.stack_depth_limit += 1; - return Ok(my_stack_frame.locals.ptr[return_slot()].get(self)?.to_vec()); + return Ok(return_interval.get(self)?.to_vec()); } Some(bb) => { // We don't support const promotion, so we can't truncate the stack yet. @@ -910,39 +988,45 @@ impl Evaluator<'_> { fn create_locals_for_body( &mut self, - body: Arc, + body: &Arc, destination: Option, ) -> Result<(Locals, usize)> { let mut locals = - Locals { ptr: ArenaMap::new(), body: body.clone(), drop_flags: DropFlags::default() }; - let (locals_ptr, stack_size) = { + match self.unused_locals_store.borrow_mut().entry(body.owner).or_default().pop() { + None => Locals { + ptr: ArenaMap::new(), + body: body.clone(), + drop_flags: DropFlags::default(), + }, + Some(mut l) => { + l.drop_flags.clear(); + l.body = body.clone(); + l + } + }; + let stack_size = { let mut stack_ptr = self.stack.len(); - let addr = body - .locals - .iter() - .map(|(id, it)| { - if id == return_slot() { - if let Some(destination) = destination { - return Ok((id, destination)); - } + for (id, it) in body.locals.iter() { + if id == return_slot() { + if let Some(destination) = destination { + locals.ptr.insert(id, destination); + continue; } - let (size, align) = self.size_align_of_sized( - &it.ty, - &locals, - "no unsized local in extending stack", - )?; - while stack_ptr % align != 0 { - stack_ptr += 1; - } - let my_ptr = stack_ptr; - stack_ptr += size; - Ok((id, Interval { addr: Stack(my_ptr), size })) - }) - .collect::>>()?; - let stack_size = stack_ptr - self.stack.len(); - (addr, stack_size) + } + let (size, align) = self.size_align_of_sized( + &it.ty, + &locals, + "no unsized local in extending stack", + )?; + while stack_ptr % align != 0 { + stack_ptr += 1; + } + let my_ptr = stack_ptr; + stack_ptr += size; + locals.ptr.insert(id, Interval { addr: Stack(my_ptr), size }); + } + stack_ptr - self.stack.len() }; - locals.ptr = locals_ptr; let prev_stack_pointer = self.stack.len(); if stack_size > self.memory_limit { return Err(MirEvalError::Panic(format!( @@ -1543,12 +1627,18 @@ impl Evaluator<'_> { ) -> Result> { let mut result = vec![0; size]; if let Some((offset, size, value)) = tag { - result[offset..offset + size].copy_from_slice(&value.to_le_bytes()[0..size]); + match result.get_mut(offset..offset + size) { + Some(it) => it.copy_from_slice(&value.to_le_bytes()[0..size]), + None => return Err(MirEvalError::BrokenLayout(variant_layout.clone())), + } } for (i, op) in values.enumerate() { let offset = variant_layout.fields.offset(i).bytes_usize(); let op = op.get(&self)?; - result[offset..offset + op.len()].copy_from_slice(op); + match result.get_mut(offset..offset + op.len()) { + Some(it) => it.copy_from_slice(op), + None => return Err(MirEvalError::BrokenLayout(variant_layout.clone())), + } } Ok(result) } @@ -1671,6 +1761,11 @@ impl Evaluator<'_> { } fn size_align_of(&self, ty: &Ty, locals: &Locals) -> Result> { + if let Some(layout) = self.layout_cache.borrow().get(ty) { + return Ok(layout + .is_sized() + .then(|| (layout.size.bytes_usize(), layout.align.abi.bytes() as usize))); + } if let DefWithBodyId::VariantId(f) = locals.body.owner { if let Some((adt, _)) = ty.as_adt() { if AdtId::from(f.parent) == adt { @@ -1731,16 +1826,15 @@ impl Evaluator<'_> { } fn detect_fn_trait(&self, def: FunctionId) -> Option { - use LangItem::*; - let ItemContainerId::TraitId(parent) = self.db.lookup_intern_function(def).container else { - return None; - }; - let l = self.db.lang_attr(parent.into())?; - match l { - FnOnce => Some(FnTrait::FnOnce), - FnMut => Some(FnTrait::FnMut), - Fn => Some(FnTrait::Fn), - _ => None, + let def = Some(def); + if def == self.cached_fn_trait_func { + Some(FnTrait::Fn) + } else if def == self.cached_fn_mut_trait_func { + Some(FnTrait::FnMut) + } else if def == self.cached_fn_once_trait_func { + Some(FnTrait::FnOnce) + } else { + None } } @@ -1796,6 +1890,17 @@ impl Evaluator<'_> { } } } + chalk_ir::TyKind::Array(inner, len) => { + let len = match try_const_usize(this.db, &len) { + Some(it) => it as usize, + None => not_supported!("non evaluatable array len in patching addresses"), + }; + let size = this.size_of_sized(inner, locals, "inner of array")?; + for i in 0..len { + let offset = i * size; + rec(this, &bytes[offset..offset + size], inner, locals, mm)?; + } + } chalk_ir::TyKind::Tuple(_, subst) => { let layout = this.layout(ty)?; for (id, ty) in subst.iter(Interner).enumerate() { @@ -1904,10 +2009,31 @@ impl Evaluator<'_> { AdtId::UnionId(_) => (), AdtId::EnumId(_) => (), }, + TyKind::Tuple(_, subst) => { + for (id, ty) in subst.iter(Interner).enumerate() { + let ty = ty.assert_ty_ref(Interner); // Tuple only has type argument + let offset = layout.fields.offset(id).bytes_usize(); + self.patch_addresses(patch_map, old_vtable, addr.offset(offset), ty, locals)?; + } + } + TyKind::Array(inner, len) => { + let len = match try_const_usize(self.db, &len) { + Some(it) => it as usize, + None => not_supported!("non evaluatable array len in patching addresses"), + }; + let size = self.size_of_sized(inner, locals, "inner of array")?; + for i in 0..len { + self.patch_addresses( + patch_map, + old_vtable, + addr.offset(i * size), + inner, + locals, + )?; + } + } TyKind::AssociatedType(_, _) | TyKind::Scalar(_) - | TyKind::Tuple(_, _) - | TyKind::Array(_, _) | TyKind::Slice(_) | TyKind::Raw(_, _) | TyKind::OpaqueType(_, _) @@ -2051,6 +2177,40 @@ impl Evaluator<'_> { } } + fn get_mir_or_dyn_index( + &self, + def: FunctionId, + generic_args: Substitution, + locals: &Locals, + span: MirSpan, + ) -> Result { + let pair = (def, generic_args); + if let Some(r) = self.mir_or_dyn_index_cache.borrow().get(&pair) { + return Ok(r.clone()); + } + let (def, generic_args) = pair; + let r = if let Some(self_ty_idx) = + is_dyn_method(self.db, self.trait_env.clone(), def, generic_args.clone()) + { + MirOrDynIndex::Dyn(self_ty_idx) + } else { + let (imp, generic_args) = + self.db.lookup_impl_method(self.trait_env.clone(), def, generic_args.clone()); + let mir_body = self + .db + .monomorphized_mir_body(imp.into(), generic_args, self.trait_env.clone()) + .map_err(|e| { + MirEvalError::InFunction( + Box::new(MirEvalError::MirLowerError(imp, e)), + vec![(Either::Left(imp), span, locals.body.owner)], + ) + })?; + MirOrDynIndex::Mir(mir_body) + }; + self.mir_or_dyn_index_cache.borrow_mut().insert((def, generic_args), r.clone()); + Ok(r) + } + fn exec_fn_with_args( &mut self, def: FunctionId, @@ -2072,93 +2232,76 @@ impl Evaluator<'_> { return Ok(None); } let arg_bytes = args.iter().map(|it| IntervalOrOwned::Borrowed(it.interval)); - if let Some(self_ty_idx) = - is_dyn_method(self.db, self.trait_env.clone(), def, generic_args.clone()) - { - // In the layout of current possible receiver, which at the moment of writing this code is one of - // `&T`, `&mut T`, `Box`, `Rc`, `Arc`, and `Pin

` where `P` is one of possible recievers, - // the vtable is exactly in the `[ptr_size..2*ptr_size]` bytes. So we can use it without branching on - // the type. - let first_arg = arg_bytes.clone().next().unwrap(); - let first_arg = first_arg.get(self)?; - let ty = - self.vtable_map.ty_of_bytes(&first_arg[self.ptr_size()..self.ptr_size() * 2])?; - let mut args_for_target = args.to_vec(); - args_for_target[0] = IntervalAndTy { - interval: args_for_target[0].interval.slice(0..self.ptr_size()), - ty: ty.clone(), - }; - let ty = GenericArgData::Ty(ty.clone()).intern(Interner); - let generics_for_target = Substitution::from_iter( - Interner, - generic_args.iter(Interner).enumerate().map(|(i, it)| { - if i == self_ty_idx { - &ty - } else { - it - } - }), - ); - return self.exec_fn_with_args( - def, - &args_for_target, - generics_for_target, + match self.get_mir_or_dyn_index(def, generic_args.clone(), locals, span)? { + MirOrDynIndex::Dyn(self_ty_idx) => { + // In the layout of current possible receiver, which at the moment of writing this code is one of + // `&T`, `&mut T`, `Box`, `Rc`, `Arc`, and `Pin

` where `P` is one of possible recievers, + // the vtable is exactly in the `[ptr_size..2*ptr_size]` bytes. So we can use it without branching on + // the type. + let first_arg = arg_bytes.clone().next().unwrap(); + let first_arg = first_arg.get(self)?; + let ty = self + .vtable_map + .ty_of_bytes(&first_arg[self.ptr_size()..self.ptr_size() * 2])?; + let mut args_for_target = args.to_vec(); + args_for_target[0] = IntervalAndTy { + interval: args_for_target[0].interval.slice(0..self.ptr_size()), + ty: ty.clone(), + }; + let ty = GenericArgData::Ty(ty.clone()).intern(Interner); + let generics_for_target = Substitution::from_iter( + Interner, + generic_args.iter(Interner).enumerate().map(|(i, it)| { + if i == self_ty_idx { + &ty + } else { + it + } + }), + ); + return self.exec_fn_with_args( + def, + &args_for_target, + generics_for_target, + locals, + destination, + target_bb, + span, + ); + } + MirOrDynIndex::Mir(body) => self.exec_looked_up_function( + body, locals, + def, + arg_bytes, + span, destination, target_bb, - span, - ); + ), } - let (imp, generic_args) = - self.db.lookup_impl_method(self.trait_env.clone(), def, generic_args); - self.exec_looked_up_function( - generic_args, - locals, - imp, - arg_bytes, - span, - destination, - target_bb, - ) } fn exec_looked_up_function( &mut self, - generic_args: Substitution, + mir_body: Arc, locals: &Locals, - imp: FunctionId, + def: FunctionId, arg_bytes: impl Iterator, span: MirSpan, destination: Interval, target_bb: Option, ) -> Result> { - let def = imp.into(); - let mir_body = self - .db - .monomorphized_mir_body(def, generic_args, self.trait_env.clone()) - .map_err(|e| { - MirEvalError::InFunction( - Box::new(MirEvalError::MirLowerError(imp, e)), - vec![(Either::Left(imp), span, locals.body.owner)], - ) - })?; Ok(if let Some(target_bb) = target_bb { let (mut locals, prev_stack_ptr) = - self.create_locals_for_body(mir_body.clone(), Some(destination))?; + self.create_locals_for_body(&mir_body, Some(destination))?; self.fill_locals_for_body(&mir_body, &mut locals, arg_bytes.into_iter())?; let span = (span, locals.body.owner); - Some(StackFrame { - body: mir_body, - locals, - destination: Some(target_bb), - prev_stack_ptr, - span, - }) + Some(StackFrame { locals, destination: Some(target_bb), prev_stack_ptr, span }) } else { let result = self.interpret_mir(mir_body, arg_bytes).map_err(|e| { MirEvalError::InFunction( Box::new(e), - vec![(Either::Left(imp), span, locals.body.owner)], + vec![(Either::Left(def), span, locals.body.owner)], ) })?; destination.write_from_bytes(self, &result)?; @@ -2330,16 +2473,15 @@ impl Evaluator<'_> { // we can ignore drop in them. return Ok(()); }; - let (impl_drop_candidate, subst) = self.db.lookup_impl_method( - self.trait_env.clone(), - drop_fn, - Substitution::from1(Interner, ty.clone()), - ); - if impl_drop_candidate != drop_fn { + + let generic_args = Substitution::from1(Interner, ty.clone()); + if let Ok(MirOrDynIndex::Mir(body)) = + self.get_mir_or_dyn_index(drop_fn, generic_args, locals, span) + { self.exec_looked_up_function( - subst, + body, locals, - impl_drop_candidate, + drop_fn, [IntervalOrOwned::Owned(addr.to_bytes())].into_iter(), span, Interval { addr: Address::Invalid(0), size: 0 }, diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs index 9ad6087cad9e..b2e29fd34b5f 100644 --- a/crates/hir-ty/src/mir/eval/shim.rs +++ b/crates/hir-ty/src/mir/eval/shim.rs @@ -36,6 +36,9 @@ impl Evaluator<'_> { destination: Interval, span: MirSpan, ) -> Result { + if self.not_special_fn_cache.borrow().contains(&def) { + return Ok(false); + } let function_data = self.db.function_data(def); let is_intrinsic = match &function_data.abi { Some(abi) => *abi == Interned::new_str("rust-intrinsic"), @@ -124,9 +127,88 @@ impl Evaluator<'_> { destination.write_from_bytes(self, &result)?; return Ok(true); } + if let ItemContainerId::TraitId(t) = def.lookup(self.db.upcast()).container { + if self.db.lang_attr(t.into()) == Some(LangItem::Clone) { + let [self_ty] = generic_args.as_slice(Interner) else { + not_supported!("wrong generic arg count for clone"); + }; + let Some(self_ty) = self_ty.ty(Interner) else { + not_supported!("wrong generic arg kind for clone"); + }; + // Clone has special impls for tuples and function pointers + if matches!(self_ty.kind(Interner), TyKind::Function(_) | TyKind::Tuple(..)) { + self.exec_clone(def, args, self_ty.clone(), locals, destination, span)?; + return Ok(true); + } + // Return early to prevent caching clone as non special fn. + return Ok(false); + } + } + self.not_special_fn_cache.borrow_mut().insert(def); Ok(false) } + /// Clone has special impls for tuples and function pointers + fn exec_clone( + &mut self, + def: FunctionId, + args: &[IntervalAndTy], + self_ty: Ty, + locals: &Locals, + destination: Interval, + span: MirSpan, + ) -> Result<()> { + match self_ty.kind(Interner) { + TyKind::Function(_) => { + let [arg] = args else { + not_supported!("wrong arg count for clone"); + }; + let addr = Address::from_bytes(arg.get(self)?)?; + return destination + .write_from_interval(self, Interval { addr, size: destination.size }); + } + TyKind::Tuple(_, subst) => { + let [arg] = args else { + not_supported!("wrong arg count for clone"); + }; + let addr = Address::from_bytes(arg.get(self)?)?; + let layout = self.layout(&self_ty)?; + for (i, ty) in subst.iter(Interner).enumerate() { + let ty = ty.assert_ty_ref(Interner); + let size = self.layout(ty)?.size.bytes_usize(); + let tmp = self.heap_allocate(self.ptr_size(), self.ptr_size())?; + let arg = IntervalAndTy { + interval: Interval { addr: tmp, size: self.ptr_size() }, + ty: TyKind::Ref(Mutability::Not, static_lifetime(), ty.clone()) + .intern(Interner), + }; + let offset = layout.fields.offset(i).bytes_usize(); + self.write_memory(tmp, &addr.offset(offset).to_bytes())?; + self.exec_clone( + def, + &[arg], + ty.clone(), + locals, + destination.slice(offset..offset + size), + span, + )?; + } + } + _ => { + self.exec_fn_with_args( + def, + args, + Substitution::from1(Interner, self_ty), + locals, + destination, + None, + span, + )?; + } + } + Ok(()) + } + fn exec_alloc_fn( &mut self, alloc_fn: &str, @@ -618,12 +700,15 @@ impl Evaluator<'_> { else { return Err(MirEvalError::TypeError("type_name generic arg is not provided")); }; - let Ok(ty_name) = ty.display_source_code( + let ty_name = match ty.display_source_code( self.db, locals.body.owner.module(self.db.upcast()), true, - ) else { - not_supported!("fail in generating type_name using source code display"); + ) { + Ok(ty_name) => ty_name, + // Fallback to human readable display in case of `Err`. Ideally we want to use `display_source_code` to + // render full paths. + Err(_) => ty.display(self.db).to_string(), }; let len = ty_name.len(); let addr = self.heap_allocate(len, 1)?; @@ -679,7 +764,22 @@ impl Evaluator<'_> { let ans = lhs.wrapping_add(rhs); destination.write_from_bytes(self, &ans.to_le_bytes()[0..destination.size]) } - "wrapping_sub" | "unchecked_sub" | "ptr_offset_from_unsigned" | "ptr_offset_from" => { + "ptr_offset_from_unsigned" | "ptr_offset_from" => { + let [lhs, rhs] = args else { + return Err(MirEvalError::TypeError("wrapping_sub args are not provided")); + }; + let lhs = i128::from_le_bytes(pad16(lhs.get(self)?, false)); + let rhs = i128::from_le_bytes(pad16(rhs.get(self)?, false)); + let ans = lhs.wrapping_sub(rhs); + let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) + else { + return Err(MirEvalError::TypeError("ptr_offset_from generic arg is not provided")); + }; + let size = self.size_of_sized(ty, locals, "ptr_offset_from arg")? as i128; + let ans = ans / size; + destination.write_from_bytes(self, &ans.to_le_bytes()[0..destination.size]) + } + "wrapping_sub" | "unchecked_sub" => { let [lhs, rhs] = args else { return Err(MirEvalError::TypeError("wrapping_sub args are not provided")); }; @@ -1057,7 +1157,14 @@ impl Evaluator<'_> { _span: MirSpan, ) -> Result<()> { // We are a single threaded runtime with no UB checking and no optimization, so - // we can implement these as normal functions. + // we can implement atomic intrinsics as normal functions. + + if name.starts_with("singlethreadfence_") || name.starts_with("fence_") { + return Ok(()); + } + + // The rest of atomic intrinsics have exactly one generic arg + let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) else { return Err(MirEvalError::TypeError("atomic intrinsic generic arg is not provided")); }; diff --git a/crates/hir-ty/src/mir/eval/tests.rs b/crates/hir-ty/src/mir/eval/tests.rs index 93f4b699147f..46165cf3d694 100644 --- a/crates/hir-ty/src/mir/eval/tests.rs +++ b/crates/hir-ty/src/mir/eval/tests.rs @@ -182,6 +182,50 @@ fn main() { ); } +#[test] +fn drop_struct_field() { + check_pass( + r#" +//- minicore: drop, add, option, cell, builtin_impls + +use core::cell::Cell; + +fn should_not_reach() { + _ // FIXME: replace this function with panic when that works +} + +struct X<'a>(&'a Cell); +impl<'a> Drop for X<'a> { + fn drop(&mut self) { + self.0.set(self.0.get() + 1) + } +} + +struct Tuple<'a>(X<'a>, X<'a>, X<'a>); + +fn main() { + let s = Cell::new(0); + { + let x0 = X(&s); + let xt = Tuple(x0, X(&s), X(&s)); + let x1 = xt.1; + if s.get() != 0 { + should_not_reach(); + } + drop(xt.0); + if s.get() != 1 { + should_not_reach(); + } + } + // FIXME: this should be 3 + if s.get() != 2 { + should_not_reach(); + } +} +"#, + ); +} + #[test] fn drop_in_place() { check_pass( @@ -613,6 +657,50 @@ fn main() { ); } +#[test] +fn self_with_capital_s() { + check_pass( + r#" +//- minicore: fn, add, copy + +struct S1; + +impl S1 { + fn f() { + Self; + } +} + +struct S2 { + f1: i32, +} + +impl S2 { + fn f() { + Self { f1: 5 }; + } +} + +struct S3(i32); + +impl S3 { + fn f() { + Self(2); + Self; + let this = Self; + this(2); + } +} + +fn main() { + S1::f(); + S2::f(); + S3::f(); +} + "#, + ); +} + #[test] fn syscalls() { check_pass( diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 9f25175a3a9f..718df8331e2a 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -486,13 +486,10 @@ impl<'ctx> MirLowerCtx<'ctx> { ); Ok(Some(current)) } - ValueNs::FunctionId(_) | ValueNs::StructId(_) => { + ValueNs::FunctionId(_) | ValueNs::StructId(_) | ValueNs::ImplSelf(_) => { // It's probably a unit struct or a zero sized function, so no action is needed. Ok(Some(current)) } - it => { - not_supported!("unknown name {it:?} in value name space"); - } } } Expr::If { condition, then_branch, else_branch } => { @@ -585,36 +582,6 @@ impl<'ctx> MirLowerCtx<'ctx> { Ok(()) }) } - Expr::While { condition, body, label } => { - self.lower_loop(current, place, *label, expr_id.into(), |this, begin| { - let scope = this.push_drop_scope(); - let Some((discr, to_switch)) = - this.lower_expr_to_some_operand(*condition, begin)? - else { - return Ok(()); - }; - let fail_cond = this.new_basic_block(); - let after_cond = this.new_basic_block(); - this.set_terminator( - to_switch, - TerminatorKind::SwitchInt { - discr, - targets: SwitchTargets::static_if(1, after_cond, fail_cond), - }, - expr_id.into(), - ); - let fail_cond = this.drop_until_scope(this.drop_scopes.len() - 1, fail_cond); - let end = this.current_loop_end()?; - this.set_goto(fail_cond, end, expr_id.into()); - if let Some((_, block)) = this.lower_expr_as_place(after_cond, *body, true)? { - let block = scope.pop_and_drop(this, block); - this.set_goto(block, begin, expr_id.into()); - } else { - scope.pop_assume_dropped(this); - } - Ok(()) - }) - } Expr::Call { callee, args, .. } => { if let Some((func_id, generic_args)) = self.infer.method_resolution(expr_id) { let ty = chalk_ir::TyKind::FnDef( @@ -660,6 +627,11 @@ impl<'ctx> MirLowerCtx<'ctx> { expr_id.into(), ) } + TyKind::Closure(_, _) => { + not_supported!( + "method resolution not emitted for closure (Are Fn traits available?)" + ); + } TyKind::Error => { return Err(MirLowerError::MissingFunctionDefinition(self.owner, expr_id)) } @@ -1026,18 +998,7 @@ impl<'ctx> MirLowerCtx<'ctx> { self.push_assignment(current, lhs_place, r_value, expr_id.into()); return Ok(Some(current)); } else { - let Some((lhs_place, current)) = - self.lower_expr_as_place(current, *lhs, false)? - else { - return Ok(None); - }; - let Some((rhs_op, current)) = - self.lower_expr_to_some_operand(*rhs, current)? - else { - return Ok(None); - }; - self.push_assignment(current, lhs_place, rhs_op.into(), expr_id.into()); - return Ok(Some(current)); + return self.lower_assignment(current, *lhs, *rhs, expr_id.into()); } } let Some((lhs_op, current)) = self.lower_expr_to_some_operand(*lhs, current)? @@ -1283,6 +1244,30 @@ impl<'ctx> MirLowerCtx<'ctx> { } } + fn lower_assignment( + &mut self, + current: BasicBlockId, + lhs: ExprId, + rhs: ExprId, + span: MirSpan, + ) -> Result> { + let Some((rhs_op, current)) = + self.lower_expr_to_some_operand(rhs, current)? + else { + return Ok(None); + }; + if matches!(&self.body.exprs[lhs], Expr::Underscore) { + return Ok(Some(current)); + } + let Some((lhs_place, current)) = + self.lower_expr_as_place(current, lhs, false)? + else { + return Ok(None); + }; + self.push_assignment(current, lhs_place, rhs_op.into(), span); + Ok(Some(current)) + } + fn placeholder_subst(&mut self) -> Substitution { let placeholder_subst = match self.owner.as_generic_def_id() { Some(it) => TyBuilder::placeholder_subst(self.db, it), diff --git a/crates/hir-ty/src/tests/display_source_code.rs b/crates/hir-ty/src/tests/display_source_code.rs index 425432479e81..e75b037e38d3 100644 --- a/crates/hir-ty/src/tests/display_source_code.rs +++ b/crates/hir-ty/src/tests/display_source_code.rs @@ -227,3 +227,22 @@ fn f(a: impl Foo = i32>) { "#, ); } + +#[test] +fn fn_def_is_shown_as_fn_ptr() { + check_types_source_code( + r#" +fn foo(_: i32) -> i64 { 42 } +struct S(T); +enum E { A(usize) } +fn test() { + let f = foo; + //^ fn(i32) -> i64 + let f = S::; + //^ fn(i8) -> S + let f = E::A; + //^ fn(usize) -> E +} +"#, + ); +} diff --git a/crates/hir-ty/src/tests/macros.rs b/crates/hir-ty/src/tests/macros.rs index b71c457f0152..1e6e946a13f8 100644 --- a/crates/hir-ty/src/tests/macros.rs +++ b/crates/hir-ty/src/tests/macros.rs @@ -209,6 +209,8 @@ fn expr_macro_def_expanded_in_various_places() { 104..105 '_': IntoIterator::Item 117..119 '{}': () 124..134 '|| spam!()': impl Fn() -> isize + 140..156 'while ...!() {}': ! + 140..156 'while ...!() {}': () 140..156 'while ...!() {}': () 154..156 '{}': () 161..174 'break spam!()': ! @@ -300,6 +302,8 @@ fn expr_macro_rules_expanded_in_various_places() { 118..119 '_': IntoIterator::Item 131..133 '{}': () 138..148 '|| spam!()': impl Fn() -> isize + 154..170 'while ...!() {}': ! + 154..170 'while ...!() {}': () 154..170 'while ...!() {}': () 168..170 '{}': () 175..188 'break spam!()': ! diff --git a/crates/hir-ty/src/tests/never_type.rs b/crates/hir-ty/src/tests/never_type.rs index 59046c0435a3..5d809b823923 100644 --- a/crates/hir-ty/src/tests/never_type.rs +++ b/crates/hir-ty/src/tests/never_type.rs @@ -412,17 +412,23 @@ fn diverging_expression_3_break() { 355..654 '{ ...; }; }': () 398..399 'x': u32 407..433 '{ whil...; }; }': u32 + 409..430 'while ...eak; }': ! + 409..430 'while ...eak; }': () 409..430 'while ...eak; }': () 415..419 'true': bool 420..430 '{ break; }': () 422..427 'break': ! 537..538 'x': u32 546..564 '{ whil... {}; }': u32 + 548..561 'while true {}': ! + 548..561 'while true {}': () 548..561 'while true {}': () 554..558 'true': bool 559..561 '{}': () 615..616 'x': u32 624..651 '{ whil...; }; }': u32 + 626..648 'while ...urn; }': ! + 626..648 'while ...urn; }': () 626..648 'while ...urn; }': () 632..636 'true': bool 637..648 '{ return; }': () diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs index 8b95110233fd..6ea059065e93 100644 --- a/crates/hir-ty/src/tests/regression.rs +++ b/crates/hir-ty/src/tests/regression.rs @@ -1267,6 +1267,8 @@ fn test() { "#, expect![[r#" 10..59 '{ ... } }': () + 16..57 'while ... }': ! + 16..57 'while ... }': () 16..57 'while ... }': () 22..30 '{ true }': bool 24..28 'true': bool @@ -1978,3 +1980,23 @@ fn x(a: [i32; 4]) { "#, ); } + +#[test] +fn dont_unify_on_casts() { + // #15246 + check_types( + r#" +fn unify(_: [bool; 1]) {} +fn casted(_: *const bool) {} +fn default() -> T { loop {} } + +fn test() { + let foo = default(); + //^^^ [bool; 1] + + casted(&foo as *const _); + unify(foo); +} +"#, + ); +} diff --git a/crates/hir-ty/src/tests/simple.rs b/crates/hir-ty/src/tests/simple.rs index a0ff628435f3..2ad7946c8ac1 100644 --- a/crates/hir-ty/src/tests/simple.rs +++ b/crates/hir-ty/src/tests/simple.rs @@ -3513,7 +3513,6 @@ fn func() { ); } -// FIXME #[test] fn castable_to() { check_infer( @@ -3538,10 +3537,10 @@ fn func() { 120..122 '{}': () 138..184 '{ ...0]>; }': () 148..149 'x': Box<[i32; 0]> - 152..160 'Box::new': fn new<[{unknown}; 0]>([{unknown}; 0]) -> Box<[{unknown}; 0]> - 152..164 'Box::new([])': Box<[{unknown}; 0]> + 152..160 'Box::new': fn new<[i32; 0]>([i32; 0]) -> Box<[i32; 0]> + 152..164 'Box::new([])': Box<[i32; 0]> 152..181 'Box::n...2; 0]>': Box<[i32; 0]> - 161..163 '[]': [{unknown}; 0] + 161..163 '[]': [i32; 0] "#]], ); } @@ -3577,6 +3576,21 @@ fn f(t: Ark) { ); } +#[test] +fn ref_to_array_to_ptr_cast() { + check_types( + r#" +fn default() -> T { loop {} } +fn foo() { + let arr = [default()]; + //^^^ [i32; 1] + let ref_to_arr = &arr; + let casted = ref_to_arr as *const i32; +} +"#, + ); +} + #[test] fn const_dependent_on_local() { check_types( diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index cf8db2a5a24a..0f2fb2c81181 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -12,9 +12,9 @@ use hir_ty::db::HirDatabase; use syntax::{ast, AstNode}; use crate::{ - Adt, AssocItem, Const, ConstParam, Enum, Field, Function, GenericParam, Impl, LifetimeParam, - Macro, Module, ModuleDef, Static, Struct, Trait, TraitAlias, TypeAlias, TypeParam, Union, - Variant, + Adt, AssocItem, Const, ConstParam, Enum, ExternCrateDecl, Field, Function, GenericParam, Impl, + LifetimeParam, Macro, Module, ModuleDef, Static, Struct, Trait, TraitAlias, TypeAlias, + TypeParam, Union, Variant, }; pub trait HasAttrs { @@ -120,6 +120,39 @@ impl HasAttrs for AssocItem { } } +impl HasAttrs for ExternCrateDecl { + fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner { + let def = AttrDefId::ExternCrateId(self.into()); + db.attrs_with_owner(def) + } + fn docs(self, db: &dyn HirDatabase) -> Option { + let crate_docs = self.resolved_crate(db)?.root_module().attrs(db).docs().map(String::from); + let def = AttrDefId::ExternCrateId(self.into()); + let decl_docs = db.attrs(def).docs().map(String::from); + match (decl_docs, crate_docs) { + (None, None) => None, + (Some(decl_docs), None) => Some(decl_docs), + (None, Some(crate_docs)) => Some(crate_docs), + (Some(mut decl_docs), Some(crate_docs)) => { + decl_docs.push('\n'); + decl_docs.push('\n'); + decl_docs += &crate_docs; + Some(decl_docs) + } + } + .map(Documentation::new) + } + fn resolve_doc_path( + self, + db: &dyn HirDatabase, + link: &str, + ns: Option, + ) -> Option { + let def = AttrDefId::ExternCrateId(self.into()); + resolve_doc_path(db, def, link, ns).map(ModuleDef::from) + } +} + /// Resolves the item `link` points to in the scope of `def`. fn resolve_doc_path( db: &dyn HirDatabase, @@ -140,6 +173,7 @@ fn resolve_doc_path( AttrDefId::TypeAliasId(it) => it.resolver(db.upcast()), AttrDefId::ImplId(it) => it.resolver(db.upcast()), AttrDefId::ExternBlockId(it) => it.resolver(db.upcast()), + AttrDefId::UseId(it) => it.resolver(db.upcast()), AttrDefId::MacroId(it) => it.resolver(db.upcast()), AttrDefId::ExternCrateId(it) => it.resolver(db.upcast()), AttrDefId::GenericParamId(it) => match it { diff --git a/crates/hir/src/db.rs b/crates/hir/src/db.rs index f3a0608944b6..936581bfe32c 100644 --- a/crates/hir/src/db.rs +++ b/crates/hir/src/db.rs @@ -10,8 +10,3 @@ pub use hir_expand::db::{ MacroExpandQuery, ParseMacroExpansionErrorQuery, ParseMacroExpansionQuery, }; pub use hir_ty::db::*; - -#[test] -fn hir_database_is_object_safe() { - fn _assert_object_safe(_: &dyn HirDatabase) {} -} diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 4de9c872ad6f..9dfb98e459b9 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -18,9 +18,9 @@ use hir_ty::{ }; use crate::{ - Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Enum, Field, Function, GenericParam, - HasCrate, HasVisibility, LifetimeParam, Macro, Module, Static, Struct, Trait, TraitAlias, - TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam, Union, Variant, + Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, Field, + Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, Static, Struct, + Trait, TraitAlias, TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam, Union, Variant, }; impl HirDisplay for Function { @@ -238,6 +238,18 @@ impl HirDisplay for Type { } } +impl HirDisplay for ExternCrateDecl { + fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { + write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; + f.write_str("extern crate ")?; + write!(f, "{}", self.name(f.db).display(f.db.upcast()))?; + if let Some(alias) = self.alias(f.db) { + write!(f, " as {alias}",)?; + } + Ok(()) + } +} + impl HirDisplay for GenericParam { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { match self { diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs index de23902199f5..fc4bbffdb836 100644 --- a/crates/hir/src/from_id.rs +++ b/crates/hir/src/from_id.rs @@ -15,7 +15,7 @@ use crate::{ }; macro_rules! from_id { - ($(($id:path, $ty:path)),*) => {$( + ($(($id:path, $ty:path)),* $(,)?) => {$( impl From<$id> for $ty { fn from(id: $id) -> $ty { $ty { id } @@ -47,7 +47,8 @@ from_id![ (hir_def::TypeParamId, crate::TypeParam), (hir_def::ConstParamId, crate::ConstParam), (hir_def::LifetimeParamId, crate::LifetimeParam), - (hir_def::MacroId, crate::Macro) + (hir_def::MacroId, crate::Macro), + (hir_def::ExternCrateId, crate::ExternCrateDecl), ]; impl From for Adt { diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs index b46a3856d454..31cf8ba33643 100644 --- a/crates/hir/src/has_source.rs +++ b/crates/hir/src/has_source.rs @@ -11,9 +11,9 @@ use hir_expand::{HirFileId, InFile}; use syntax::ast; use crate::{ - db::HirDatabase, Adt, Const, Enum, Field, FieldSource, Function, Impl, LifetimeParam, - LocalSource, Macro, Module, Static, Struct, Trait, TraitAlias, TypeAlias, TypeOrConstParam, - Union, Variant, + db::HirDatabase, Adt, Const, Enum, ExternCrateDecl, Field, FieldSource, Function, Impl, + LifetimeParam, LocalSource, Macro, Module, Static, Struct, Trait, TraitAlias, TypeAlias, + TypeOrConstParam, Union, Variant, }; pub trait HasSource { @@ -207,3 +207,11 @@ impl HasSource for LocalSource { Some(self.source) } } + +impl HasSource for ExternCrateDecl { + type Ast = ast::ExternCrate; + + fn source(self, db: &dyn HirDatabase) -> Option> { + Some(self.id.lookup(db.upcast()).source(db.upcast())) + } +} diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index b094bb7a0688..bf041b61f2fb 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -48,14 +48,15 @@ use hir_def::{ layout::{self, ReprOptions, TargetDataLayout}, macro_id_to_def_id, nameres::{self, diagnostics::DefDiagnostic}, + path::ImportAlias, per_ns::PerNs, resolver::{HasResolver, Resolver}, src::HasSource as _, - AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, - EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, InTypeConstId, ItemContainerId, - LifetimeParamId, LocalEnumVariantId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, - StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, - UnionId, + AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, + EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, HasModule, ImplId, + InTypeConstId, ItemContainerId, LifetimeParamId, LocalEnumVariantId, LocalFieldId, Lookup, + MacroExpander, MacroId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, + TypeOrConstParamId, TypeParamId, UnionId, }; use hir_expand::{name::name, MacroCallKind}; use hir_ty::{ @@ -200,9 +201,8 @@ impl Crate { db.crate_graph().transitive_rev_deps(self.id).map(|id| Crate { id }) } - pub fn root_module(self, db: &dyn HirDatabase) -> Module { - let def_map = db.crate_def_map(self.id); - Module { id: def_map.crate_root().into() } + pub fn root_module(self) -> Module { + Module { id: CrateRootModuleId::from(self.id).into() } } pub fn modules(self, db: &dyn HirDatabase) -> Vec { @@ -247,7 +247,7 @@ impl Crate { /// Try to get the root URL of the documentation of a crate. pub fn get_html_root_url(self: &Crate, db: &dyn HirDatabase) -> Option { // Look for #![doc(html_root_url = "...")] - let attrs = db.attrs(AttrDefId::ModuleId(self.root_module(db).into())); + let attrs = db.attrs(AttrDefId::ModuleId(self.root_module().into())); let doc_url = attrs.by_key("doc").find_string_value_in_tt("html_root_url"); doc_url.map(|s| s.trim_matches('"').trim_end_matches('/').to_owned() + "/") } @@ -2128,6 +2128,47 @@ impl HasVisibility for Function { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct ExternCrateDecl { + pub(crate) id: ExternCrateId, +} + +impl ExternCrateDecl { + pub fn module(self, db: &dyn HirDatabase) -> Module { + self.id.module(db.upcast()).into() + } + + pub fn resolved_crate(self, db: &dyn HirDatabase) -> Option { + db.extern_crate_decl_data(self.id).crate_id.map(Into::into) + } + + pub fn name(self, db: &dyn HirDatabase) -> Name { + db.extern_crate_decl_data(self.id).name.clone() + } + + pub fn alias(self, db: &dyn HirDatabase) -> Option { + db.extern_crate_decl_data(self.id).alias.clone() + } + + /// Returns the name under which this crate is made accessible, taking `_` into account. + pub fn alias_or_name(self, db: &dyn HirDatabase) -> Option { + let extern_crate_decl_data = db.extern_crate_decl_data(self.id); + match &extern_crate_decl_data.alias { + Some(ImportAlias::Underscore) => None, + Some(ImportAlias::Alias(alias)) => Some(alias.clone()), + None => Some(extern_crate_decl_data.name.clone()), + } + } +} + +impl HasVisibility for ExternCrateDecl { + fn visibility(&self, db: &dyn HirDatabase) -> Visibility { + db.extern_crate_decl_data(self.id) + .visibility + .resolve(db.upcast(), &self.id.resolver(db.upcast())) + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct InTypeConst { pub(crate) id: InTypeConstId, @@ -4715,6 +4756,12 @@ pub trait HasContainer { fn container(&self, db: &dyn HirDatabase) -> ItemContainer; } +impl HasContainer for ExternCrateDecl { + fn container(&self, db: &dyn HirDatabase) -> ItemContainer { + container_id_to_hir(self.id.lookup(db.upcast()).container.into()) + } +} + impl HasContainer for Module { fn container(&self, db: &dyn HirDatabase) -> ItemContainer { // FIXME: handle block expressions as modules (their parent is in a different DefMap) diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 39a3e1c4489e..e99d2984c367 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -15,11 +15,7 @@ use hir_def::{ type_ref::Mutability, AsMacroCall, DefWithBodyId, FieldId, FunctionId, MacroId, TraitId, VariantId, }; -use hir_expand::{ - db::ExpandDatabase, - name::{known, AsName}, - ExpansionInfo, MacroCallId, -}; +use hir_expand::{db::ExpandDatabase, name::AsName, ExpansionInfo, MacroCallId}; use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet}; use smallvec::{smallvec, SmallVec}; @@ -439,10 +435,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { self.imp.resolve_path(path) } - pub fn resolve_extern_crate(&self, extern_crate: &ast::ExternCrate) -> Option { - self.imp.resolve_extern_crate(extern_crate) - } - pub fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option { self.imp.resolve_variant(record_lit).map(VariantDef::from) } @@ -1242,18 +1234,6 @@ impl<'db> SemanticsImpl<'db> { self.analyze(path.syntax())?.resolve_path(self.db, path) } - fn resolve_extern_crate(&self, extern_crate: &ast::ExternCrate) -> Option { - let krate = self.scope(extern_crate.syntax())?.krate(); - let name = extern_crate.name_ref()?.as_name(); - if name == known::SELF_PARAM { - return Some(krate); - } - krate - .dependencies(self.db) - .into_iter() - .find_map(|dep| (dep.name == name).then_some(dep.krate)) - } - fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option { self.analyze(record_lit.syntax())?.resolve_variant(self.db, record_lit) } @@ -1603,6 +1583,7 @@ to_def_impls![ (crate::Local, ast::SelfParam, self_param_to_def), (crate::Label, ast::Label, label_to_def), (crate::Adt, ast::Adt, adt_to_def), + (crate::ExternCrateDecl, ast::ExternCrate, extern_crate_to_def), ]; fn find_root(node: &SyntaxNode) -> SyntaxNode { diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index b971ca62387e..aabda3655602 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs @@ -93,9 +93,9 @@ use hir_def::{ DynMap, }, hir::{BindingId, LabelId}, - AdtId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, - GenericDefId, GenericParamId, ImplId, LifetimeParamId, MacroId, ModuleId, StaticId, StructId, - TraitAliasId, TraitId, TypeAliasId, TypeParamId, UnionId, VariantId, + AdtId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FieldId, + FunctionId, GenericDefId, GenericParamId, ImplId, LifetimeParamId, MacroId, ModuleId, StaticId, + StructId, TraitAliasId, TraitId, TypeAliasId, TypeParamId, UnionId, UseId, VariantId, }; use hir_expand::{attrs::AttrId, name::AsName, HirFileId, MacroCallId}; use rustc_hash::FxHashMap; @@ -203,6 +203,16 @@ impl SourceToDefCtx<'_, '_> { ) -> Option { self.to_def(src, keys::VARIANT) } + pub(super) fn extern_crate_to_def( + &mut self, + src: InFile, + ) -> Option { + self.to_def(src, keys::EXTERN_CRATE) + } + #[allow(dead_code)] + pub(super) fn use_to_def(&mut self, src: InFile) -> Option { + self.to_def(src, keys::USE) + } pub(super) fn adt_to_def( &mut self, InFile { file_id, value }: InFile, diff --git a/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/crates/ide-assists/src/handlers/add_missing_impl_members.rs index d07c6372628d..6aca716bb60a 100644 --- a/crates/ide-assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ide-assists/src/handlers/add_missing_impl_members.rs @@ -3,7 +3,10 @@ use syntax::ast::{self, make, AstNode}; use crate::{ assist_context::{AssistContext, Assists}, - utils::{add_trait_assoc_items_to_impl, filter_assoc_items, gen_trait_fn_body, DefaultMethods}, + utils::{ + add_trait_assoc_items_to_impl, filter_assoc_items, gen_trait_fn_body, DefaultMethods, + IgnoreAssocItems, + }, AssistId, AssistKind, }; @@ -43,6 +46,7 @@ pub(crate) fn add_missing_impl_members(acc: &mut Assists, ctx: &AssistContext<'_ acc, ctx, DefaultMethods::No, + IgnoreAssocItems::DocHiddenAttrPresent, "add_impl_missing_members", "Implement missing members", ) @@ -87,6 +91,7 @@ pub(crate) fn add_missing_default_members( acc, ctx, DefaultMethods::Only, + IgnoreAssocItems::DocHiddenAttrPresent, "add_impl_default_members", "Implement default members", ) @@ -96,6 +101,7 @@ fn add_missing_impl_members_inner( acc: &mut Assists, ctx: &AssistContext<'_>, mode: DefaultMethods, + ignore_items: IgnoreAssocItems, assist_id: &'static str, label: &'static str, ) -> Option<()> { @@ -115,10 +121,21 @@ fn add_missing_impl_members_inner( let trait_ref = impl_.trait_ref(ctx.db())?; let trait_ = trait_ref.trait_(); + let mut ign_item = ignore_items; + + if let IgnoreAssocItems::DocHiddenAttrPresent = ignore_items { + // Relax condition for local crates. + let db = ctx.db(); + if trait_.module(db).krate().origin(db).is_local() { + ign_item = IgnoreAssocItems::No; + } + } + let missing_items = filter_assoc_items( &ctx.sema, &ide_db::traits::get_missing_assoc_items(&ctx.sema, &impl_def), mode, + ign_item, ); if missing_items.is_empty() { @@ -1966,4 +1983,169 @@ impl AnotherTrait for () { "#, ); } + + #[test] + fn doc_hidden_default_impls_ignored() { + // doc(hidden) attr is ignored trait and impl both belong to the local crate. + check_assist( + add_missing_default_members, + r#" +struct Foo; +trait Trait { + #[doc(hidden)] + fn func_with_default_impl() -> u32 { + 42 + } + fn another_default_impl() -> u32 { + 43 + } +} +impl Tra$0it for Foo {}"#, + r#" +struct Foo; +trait Trait { + #[doc(hidden)] + fn func_with_default_impl() -> u32 { + 42 + } + fn another_default_impl() -> u32 { + 43 + } +} +impl Trait for Foo { + $0fn func_with_default_impl() -> u32 { + 42 + } + + fn another_default_impl() -> u32 { + 43 + } +}"#, + ) + } + + #[test] + fn doc_hidden_default_impls_lang_crates() { + // Not applicable because Eq has a single method and this has a #[doc(hidden)] attr set. + check_assist_not_applicable( + add_missing_default_members, + r#" +//- minicore: eq +use core::cmp::Eq; +struct Foo; +impl E$0q for Foo { /* $0 */ } +"#, + ) + } + + #[test] + fn doc_hidden_default_impls_lib_crates() { + check_assist( + add_missing_default_members, + r#" + //- /main.rs crate:a deps:b + struct B; + impl b::Exte$0rnTrait for B {} + //- /lib.rs crate:b new_source_root:library + pub trait ExternTrait { + #[doc(hidden)] + fn hidden_default() -> Option<()> { + todo!() + } + + fn unhidden_default() -> Option<()> { + todo!() + } + + fn unhidden_nondefault() -> Option<()>; + } + "#, + r#" + struct B; + impl b::ExternTrait for B { + $0fn unhidden_default() -> Option<()> { + todo!() + } + } + "#, + ) + } + + #[test] + fn doc_hidden_default_impls_local_crates() { + check_assist( + add_missing_default_members, + r#" +trait LocalTrait { + #[doc(hidden)] + fn no_skip_default() -> Option<()> { + todo!() + } + fn no_skip_default_2() -> Option<()> { + todo!() + } +} + +struct B; +impl Loc$0alTrait for B {} + "#, + r#" +trait LocalTrait { + #[doc(hidden)] + fn no_skip_default() -> Option<()> { + todo!() + } + fn no_skip_default_2() -> Option<()> { + todo!() + } +} + +struct B; +impl LocalTrait for B { + $0fn no_skip_default() -> Option<()> { + todo!() + } + + fn no_skip_default_2() -> Option<()> { + todo!() + } +} + "#, + ) + } + + #[test] + fn doc_hidden_default_impls_workspace_crates() { + check_assist( + add_missing_default_members, + r#" +//- /lib.rs crate:b new_source_root:local +trait LocalTrait { + #[doc(hidden)] + fn no_skip_default() -> Option<()> { + todo!() + } + fn no_skip_default_2() -> Option<()> { + todo!() + } +} + +//- /main.rs crate:a deps:b +struct B; +impl b::Loc$0alTrait for B {} + "#, + r#" +struct B; +impl b::LocalTrait for B { + $0fn no_skip_default() -> Option<()> { + todo!() + } + + fn no_skip_default_2() -> Option<()> { + todo!() + } +} + "#, + ) + } } diff --git a/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/crates/ide-assists/src/handlers/add_missing_match_arms.rs index ac0b74ee8e74..3b162d7c4d82 100644 --- a/crates/ide-assists/src/handlers/add_missing_match_arms.rs +++ b/crates/ide-assists/src/handlers/add_missing_match_arms.rs @@ -37,9 +37,9 @@ use crate::{utils, AssistContext, AssistId, AssistKind, Assists}; pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let match_expr = ctx.find_node_at_offset_with_descend::()?; let match_arm_list = match_expr.match_arm_list()?; - let target_range = ctx.sema.original_range(match_expr.syntax()).range; + let arm_list_range = ctx.sema.original_range_opt(match_arm_list.syntax())?; - if let None = cursor_at_trivial_match_arm_list(ctx, &match_expr, &match_arm_list) { + if cursor_at_trivial_match_arm_list(ctx, &match_expr, &match_arm_list).is_none() { let arm_list_range = ctx.sema.original_range(match_arm_list.syntax()).range; let cursor_in_range = arm_list_range.contains_range(ctx.selection_trimmed()); if cursor_in_range { @@ -198,7 +198,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) acc.add( AssistId("add_missing_match_arms", AssistKind::QuickFix), "Fill match arms", - target_range, + ctx.sema.original_range(match_expr.syntax()).range, |edit| { let new_match_arm_list = match_arm_list.clone_for_update(); @@ -262,9 +262,8 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) // Just replace the element that the original range came from let old_place = { // Find the original element - let old_file_range = ctx.sema.original_range(match_arm_list.syntax()); - let file = ctx.sema.parse(old_file_range.file_id); - let old_place = file.syntax().covering_element(old_file_range.range); + let file = ctx.sema.parse(arm_list_range.file_id); + let old_place = file.syntax().covering_element(arm_list_range.range); // Make `old_place` mut match old_place { @@ -1922,4 +1921,24 @@ fn foo(t: E) { }"#, ); } + + #[test] + fn not_applicable_when_match_arm_list_cannot_be_upmapped() { + check_assist_not_applicable( + add_missing_match_arms, + r#" +macro_rules! foo { + ($($t:tt)*) => { + $($t)* {} + } +} + +enum E { A } + +fn main() { + foo!(match E::A$0); +} +"#, + ); + } } diff --git a/crates/ide-assists/src/handlers/add_turbo_fish.rs b/crates/ide-assists/src/handlers/add_turbo_fish.rs index acf82e4b2579..36f68d176773 100644 --- a/crates/ide-assists/src/handlers/add_turbo_fish.rs +++ b/crates/ide-assists/src/handlers/add_turbo_fish.rs @@ -42,7 +42,9 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti let name_ref = ast::NameRef::cast(ident.parent()?)?; let def = match NameRefClass::classify(&ctx.sema, &name_ref)? { NameRefClass::Definition(def) => def, - NameRefClass::FieldShorthand { .. } => return None, + NameRefClass::FieldShorthand { .. } | NameRefClass::ExternCrateShorthand { .. } => { + return None + } }; let fun = match def { Definition::Function(it) => it, diff --git a/crates/ide-assists/src/handlers/convert_two_arm_bool_match_to_matches_macro.rs b/crates/ide-assists/src/handlers/convert_two_arm_bool_match_to_matches_macro.rs index b1b0f587cd33..6a5b11f54256 100644 --- a/crates/ide-assists/src/handlers/convert_two_arm_bool_match_to_matches_macro.rs +++ b/crates/ide-assists/src/handlers/convert_two_arm_bool_match_to_matches_macro.rs @@ -1,3 +1,6 @@ +use hir::Semantics; +use ide_db::RootDatabase; +use stdx::format_to; use syntax::ast::{self, AstNode}; use crate::{AssistContext, AssistId, AssistKind, Assists}; @@ -24,6 +27,7 @@ pub(crate) fn convert_two_arm_bool_match_to_matches_macro( acc: &mut Assists, ctx: &AssistContext<'_>, ) -> Option<()> { + use ArmBodyExpression::*; let match_expr = ctx.find_node_at_offset::()?; let match_arm_list = match_expr.match_arm_list()?; let mut arms = match_arm_list.arms(); @@ -33,21 +37,20 @@ pub(crate) fn convert_two_arm_bool_match_to_matches_macro( cov_mark::hit!(non_two_arm_match); return None; } - let first_arm_expr = first_arm.expr(); - let second_arm_expr = second_arm.expr(); + let first_arm_expr = first_arm.expr()?; + let second_arm_expr = second_arm.expr()?; + let first_arm_body = is_bool_literal_expr(&ctx.sema, &first_arm_expr)?; + let second_arm_body = is_bool_literal_expr(&ctx.sema, &second_arm_expr)?; - let invert_matches = if is_bool_literal_expr(&first_arm_expr, true) - && is_bool_literal_expr(&second_arm_expr, false) - { - false - } else if is_bool_literal_expr(&first_arm_expr, false) - && is_bool_literal_expr(&second_arm_expr, true) - { - true - } else { + if !matches!( + (&first_arm_body, &second_arm_body), + (Literal(true), Literal(false)) + | (Literal(false), Literal(true)) + | (Expression(_), Literal(false)) + ) { cov_mark::hit!(non_invert_bool_literal_arms); return None; - }; + } let target_range = ctx.sema.original_range(match_expr.syntax()).range; let expr = match_expr.expr()?; @@ -59,28 +62,55 @@ pub(crate) fn convert_two_arm_bool_match_to_matches_macro( |builder| { let mut arm_str = String::new(); if let Some(pat) = &first_arm.pat() { - arm_str += &pat.to_string(); + format_to!(arm_str, "{pat}"); } if let Some(guard) = &first_arm.guard() { arm_str += &format!(" {guard}"); } - if invert_matches { - builder.replace(target_range, format!("!matches!({expr}, {arm_str})")); - } else { - builder.replace(target_range, format!("matches!({expr}, {arm_str})")); - } + + let replace_with = match (first_arm_body, second_arm_body) { + (Literal(true), Literal(false)) => { + format!("matches!({expr}, {arm_str})") + } + (Literal(false), Literal(true)) => { + format!("!matches!({expr}, {arm_str})") + } + (Expression(body_expr), Literal(false)) => { + arm_str.push_str(match &first_arm.guard() { + Some(_) => " && ", + _ => " if ", + }); + format!("matches!({expr}, {arm_str}{body_expr})") + } + _ => { + unreachable!() + } + }; + builder.replace(target_range, replace_with); }, ) } -fn is_bool_literal_expr(expr: &Option, expect_bool: bool) -> bool { - if let Some(ast::Expr::Literal(lit)) = expr { +enum ArmBodyExpression { + Literal(bool), + Expression(ast::Expr), +} + +fn is_bool_literal_expr( + sema: &Semantics<'_, RootDatabase>, + expr: &ast::Expr, +) -> Option { + if let ast::Expr::Literal(lit) = expr { if let ast::LiteralKind::Bool(b) = lit.kind() { - return b == expect_bool; + return Some(ArmBodyExpression::Literal(b)); } } - return false; + if !sema.type_of_expr(expr)?.original.is_bool() { + return None; + } + + Some(ArmBodyExpression::Expression(expr.clone())) } #[cfg(test)] @@ -121,21 +151,6 @@ fn foo(a: Option) -> bool { ); } - #[test] - fn not_applicable_non_bool_literal_arms() { - cov_mark::check!(non_invert_bool_literal_arms); - check_assist_not_applicable( - convert_two_arm_bool_match_to_matches_macro, - r#" -fn foo(a: Option) -> bool { - match a$0 { - Some(val) => val == 3, - _ => false - } -} - "#, - ); - } #[test] fn not_applicable_both_false_arms() { cov_mark::check!(non_invert_bool_literal_arms); @@ -291,4 +306,40 @@ fn main() { }", ); } + + #[test] + fn convert_non_literal_bool() { + check_assist( + convert_two_arm_bool_match_to_matches_macro, + r#" +fn main() { + match 0$0 { + a @ 0..15 => a == 0, + _ => false, + } +} +"#, + r#" +fn main() { + matches!(0, a @ 0..15 if a == 0) +} +"#, + ); + check_assist( + convert_two_arm_bool_match_to_matches_macro, + r#" +fn main() { + match 0$0 { + a @ 0..15 if thing() => a == 0, + _ => false, + } +} +"#, + r#" +fn main() { + matches!(0, a @ 0..15 if thing() && a == 0) +} +"#, + ); + } } diff --git a/crates/ide-assists/src/handlers/destructure_tuple_binding.rs b/crates/ide-assists/src/handlers/destructure_tuple_binding.rs index ea71d165e6aa..f30ca2552d36 100644 --- a/crates/ide-assists/src/handlers/destructure_tuple_binding.rs +++ b/crates/ide-assists/src/handlers/destructure_tuple_binding.rs @@ -114,7 +114,7 @@ fn collect_data(ident_pat: IdentPat, ctx: &AssistContext<'_>) -> Option) -> bool { let search_scope = SearchScope::single_file(ctx.file_id()); - def.usages(&ctx.sema).in_scope(search_scope).at_least_one() + def.usages(&ctx.sema).in_scope(&search_scope).at_least_one() } #[derive(Debug, Clone)] diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs index e9db38aca0f0..b8b781ea48d4 100644 --- a/crates/ide-assists/src/handlers/extract_function.rs +++ b/crates/ide-assists/src/handlers/extract_function.rs @@ -384,7 +384,7 @@ impl LocalUsages { Self( Definition::Local(var) .usages(&ctx.sema) - .in_scope(SearchScope::single_file(ctx.file_id())) + .in_scope(&SearchScope::single_file(ctx.file_id())) .all(), ) } diff --git a/crates/ide-assists/src/handlers/extract_module.rs b/crates/ide-assists/src/handlers/extract_module.rs index de37f5f130fc..6839c5820dc9 100644 --- a/crates/ide-assists/src/handlers/extract_module.rs +++ b/crates/ide-assists/src/handlers/extract_module.rs @@ -478,7 +478,7 @@ impl Module { let selection_range = ctx.selection_trimmed(); let curr_file_id = ctx.file_id(); let search_scope = SearchScope::single_file(curr_file_id); - let usage_res = def.usages(&ctx.sema).in_scope(search_scope).all(); + let usage_res = def.usages(&ctx.sema).in_scope(&search_scope).all(); let file = ctx.sema.parse(curr_file_id); let mut exists_inside_sel = false; 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 860372941f79..7e4f140a28fa 100644 --- a/crates/ide-assists/src/handlers/generate_default_from_new.rs +++ b/crates/ide-assists/src/handlers/generate_default_from_new.rs @@ -15,6 +15,7 @@ use crate::{ // Generates default implementation from new method. // // ``` +// # //- minicore: default // struct Example { _inner: () } // // impl Example { @@ -54,6 +55,7 @@ pub(crate) fn generate_default_from_new(acc: &mut Assists, ctx: &AssistContext<' } let impl_ = fn_node.syntax().ancestors().find_map(ast::Impl::cast)?; + let self_ty = impl_.self_ty()?; if is_default_implemented(ctx, &impl_) { cov_mark::hit!(default_block_is_already_present); cov_mark::hit!(struct_in_module_with_default); @@ -70,15 +72,19 @@ pub(crate) fn generate_default_from_new(acc: &mut Assists, ctx: &AssistContext<' let default_code = " fn default() -> Self { Self::new() }"; - let code = generate_trait_impl_text_from_impl(&impl_, "Default", default_code); + let code = generate_trait_impl_text_from_impl(&impl_, self_ty, "Default", default_code); builder.insert(insert_location.end(), code); }, ) } // 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 impl_ty = impl_.self_ty().unwrap(); +fn generate_trait_impl_text_from_impl( + impl_: &ast::Impl, + self_ty: ast::Type, + trait_text: &str, + code: &str, +) -> String { let generic_params = impl_.generic_param_list().map(|generic_params| { let lifetime_params = generic_params.lifetime_params().map(ast::GenericParam::LifetimeParam); @@ -109,7 +115,7 @@ fn generate_trait_impl_text_from_impl(impl_: &ast::Impl, trait_text: &str, code: if let Some(generic_params) = &generic_params { format_to!(buf, "{generic_params}") } - format_to!(buf, " {trait_text} for {impl_ty}"); + format_to!(buf, " {trait_text} for {self_ty}"); match impl_.where_clause() { Some(where_clause) => { @@ -136,7 +142,9 @@ fn is_default_implemented(ctx: &AssistContext<'_>, impl_: &Impl) -> bool { let default = FamousDefs(&ctx.sema, krate).core_default_Default(); let default_trait = match default { Some(value) => value, - None => return false, + // Return `true` to avoid providing the assist because it makes no sense + // to impl `Default` when it's missing. + None => return true, }; ty.impls_trait(db, default_trait, &[]) @@ -480,6 +488,7 @@ impl Example { check_assist_not_applicable( generate_default_from_new, r#" +//- minicore: default struct Example { _inner: () } impl Example { @@ -655,4 +664,23 @@ mod test { "#, ); } + + #[test] + fn not_applicable_when_default_lang_item_is_missing() { + check_assist_not_applicable( + generate_default_from_new, + r#" +struct S; +impl S { + fn new$0() -> Self {} +} +"#, + ); + } + + #[test] + fn not_applicable_for_missing_self_ty() { + // Regression test for #15398. + check_assist_not_applicable(generate_default_from_new, "impl { fn new$0() -> Self {} }"); + } } diff --git a/crates/ide-assists/src/handlers/generate_delegate_trait.rs b/crates/ide-assists/src/handlers/generate_delegate_trait.rs index 185f47184d43..f4fa6a74c6b9 100644 --- a/crates/ide-assists/src/handlers/generate_delegate_trait.rs +++ b/crates/ide-assists/src/handlers/generate_delegate_trait.rs @@ -213,7 +213,9 @@ impl Struct { // continue; // } let signature = delegee.signature(db); - let delegate = generate_impl(ctx, self, &field.ty, &field.name, delegee); + let Some(delegate) = generate_impl(ctx, self, &field.ty, &field.name, delegee) else { + continue; + }; acc.add_group( &GroupLabel("Delegate trait impl for field...".to_owned()), @@ -237,7 +239,7 @@ fn generate_impl( field_ty: &ast::Type, field_name: &String, delegee: &Delegee, -) -> ast::Impl { +) -> Option { let delegate: ast::Impl; let source: ast::Impl; let genpar: Option; @@ -247,7 +249,7 @@ fn generate_impl( match delegee { Delegee::Bound(delegee) => { - let in_file = ctx.sema.source(delegee.0.to_owned()).unwrap(); + let in_file = ctx.sema.source(delegee.0.to_owned())?; let source: ast::Trait = in_file.value; delegate = make::impl_trait( @@ -293,15 +295,15 @@ fn generate_impl( None => {} }; - let target = ctx.sema.scope(strukt.strukt.syntax()).unwrap(); - let source = ctx.sema.scope(source.syntax()).unwrap(); + let target = ctx.sema.scope(strukt.strukt.syntax())?; + let source = ctx.sema.scope(source.syntax())?; let transform = PathTransform::trait_impl(&target, &source, delegee.0, delegate.clone()); transform.apply(&delegate.syntax()); } Delegee::Impls(delegee) => { - let in_file = ctx.sema.source(delegee.1.to_owned()).unwrap(); + let in_file = ctx.sema.source(delegee.1.to_owned())?; source = in_file.value; delegate = make::impl_trait( delegee.0.is_unsafe(db), @@ -341,8 +343,8 @@ fn generate_impl( } }); - let target = ctx.sema.scope(strukt.strukt.syntax()).unwrap(); - let source = ctx.sema.scope(source.syntax()).unwrap(); + let target = ctx.sema.scope(strukt.strukt.syntax())?; + let source = ctx.sema.scope(source.syntax())?; let transform = PathTransform::trait_impl(&target, &source, delegee.0, delegate.clone()); @@ -350,7 +352,7 @@ fn generate_impl( } } - delegate + Some(delegate) } fn process_assoc_item( @@ -359,19 +361,19 @@ fn process_assoc_item( base_name: &str, ) -> Option { match item { - AssocItem::Const(c) => Some(const_assoc_item(c, qual_path_ty)), - AssocItem::Fn(f) => Some(func_assoc_item(f, qual_path_ty, base_name)), + AssocItem::Const(c) => const_assoc_item(c, qual_path_ty), + AssocItem::Fn(f) => func_assoc_item(f, qual_path_ty, base_name), AssocItem::MacroCall(_) => { // FIXME : Handle MacroCall case. - // return Some(macro_assoc_item(mac, qual_path_ty)); + // macro_assoc_item(mac, qual_path_ty) None } - AssocItem::TypeAlias(ta) => Some(ty_assoc_item(ta, qual_path_ty)), + AssocItem::TypeAlias(ta) => ty_assoc_item(ta, qual_path_ty), } } -fn const_assoc_item(item: syntax::ast::Const, qual_path_ty: ast::Path) -> AssocItem { - let path_expr_segment = make::path_from_text(item.name().unwrap().to_string().as_str()); +fn const_assoc_item(item: syntax::ast::Const, qual_path_ty: ast::Path) -> Option { + let path_expr_segment = make::path_from_text(item.name()?.to_string().as_str()); // We want rhs of the const assignment to be a qualified path // The general case for const assigment can be found [here](`https://doc.rust-lang.org/reference/items/constant-items.html`) @@ -380,19 +382,19 @@ fn const_assoc_item(item: syntax::ast::Const, qual_path_ty: ast::Path) -> AssocI // FIXME : We can't rely on `make::path_qualified` for now but it would be nice to replace the following with it. // make::path_qualified(qual_path_ty, path_expr_segment.as_single_segment().unwrap()); let qualpath = qualpath(qual_path_ty, path_expr_segment); - let inner = make::item_const( - item.visibility(), - item.name().unwrap(), - item.ty().unwrap(), - make::expr_path(qualpath), - ) - .clone_for_update(); + let inner = + make::item_const(item.visibility(), item.name()?, item.ty()?, make::expr_path(qualpath)) + .clone_for_update(); - AssocItem::Const(inner) + Some(AssocItem::Const(inner)) } -fn func_assoc_item(item: syntax::ast::Fn, qual_path_ty: Path, base_name: &str) -> AssocItem { - let path_expr_segment = make::path_from_text(item.name().unwrap().to_string().as_str()); +fn func_assoc_item( + item: syntax::ast::Fn, + qual_path_ty: Path, + base_name: &str, +) -> Option { + let path_expr_segment = make::path_from_text(item.name()?.to_string().as_str()); let qualpath = qualpath(qual_path_ty, path_expr_segment); let call = match item.param_list() { @@ -415,7 +417,7 @@ fn func_assoc_item(item: syntax::ast::Fn, qual_path_ty: Path, base_name: &str) - if param_count > 0 { // Add SelfParam and a TOKEN::COMMA ted::insert_all( - Position::after(args.l_paren_token().unwrap()), + Position::after(args.l_paren_token()?), vec![ NodeOrToken::Node(tail_expr_self.syntax().clone_for_update()), NodeOrToken::Token(make::token(SyntaxKind::WHITESPACE)), @@ -425,7 +427,7 @@ fn func_assoc_item(item: syntax::ast::Fn, qual_path_ty: Path, base_name: &str) - } else { // Add SelfParam only ted::insert( - Position::after(args.l_paren_token().unwrap()), + Position::after(args.l_paren_token()?), NodeOrToken::Node(tail_expr_self.syntax().clone_for_update()), ); } @@ -444,10 +446,10 @@ fn func_assoc_item(item: syntax::ast::Fn, qual_path_ty: Path, base_name: &str) - let body = make::block_expr(vec![], Some(call)).clone_for_update(); let func = make::fn_( item.visibility(), - item.name().unwrap(), + item.name()?, item.generic_param_list(), item.where_clause(), - item.param_list().unwrap(), + item.param_list()?, body, item.ret_type(), item.async_token().is_some(), @@ -456,14 +458,14 @@ fn func_assoc_item(item: syntax::ast::Fn, qual_path_ty: Path, base_name: &str) - ) .clone_for_update(); - AssocItem::Fn(func.indent(edit::IndentLevel(1)).clone_for_update()) + Some(AssocItem::Fn(func.indent(edit::IndentLevel(1)).clone_for_update())) } -fn ty_assoc_item(item: syntax::ast::TypeAlias, qual_path_ty: Path) -> AssocItem { - let path_expr_segment = make::path_from_text(item.name().unwrap().to_string().as_str()); +fn ty_assoc_item(item: syntax::ast::TypeAlias, qual_path_ty: Path) -> Option { + let path_expr_segment = make::path_from_text(item.name()?.to_string().as_str()); let qualpath = qualpath(qual_path_ty, path_expr_segment); let ty = make::ty_path(qualpath); - let ident = item.name().unwrap().to_string(); + let ident = item.name()?.to_string(); let alias = make::ty_alias( ident.as_str(), @@ -474,7 +476,7 @@ fn ty_assoc_item(item: syntax::ast::TypeAlias, qual_path_ty: Path) -> AssocItem ) .clone_for_update(); - AssocItem::TypeAlias(alias) + Some(AssocItem::TypeAlias(alias)) } fn qualpath(qual_path_ty: ast::Path, path_expr_seg: ast::Path) -> ast::Path { diff --git a/crates/ide-assists/src/handlers/generate_function.rs b/crates/ide-assists/src/handlers/generate_function.rs index 8085572497aa..5b13e01b1330 100644 --- a/crates/ide-assists/src/handlers/generate_function.rs +++ b/crates/ide-assists/src/handlers/generate_function.rs @@ -1878,7 +1878,6 @@ where #[test] fn add_function_with_fn_arg() { - // FIXME: The argument in `bar` is wrong. check_assist( generate_function, r" @@ -1899,7 +1898,7 @@ fn foo() { bar(Baz::new); } -fn bar(new: fn) ${0:-> _} { +fn bar(new: fn() -> Baz) ${0:-> _} { todo!() } ", diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs index 67036029f5ee..ffab58509b18 100644 --- a/crates/ide-assists/src/handlers/inline_call.rs +++ b/crates/ide-assists/src/handlers/inline_call.rs @@ -80,7 +80,7 @@ pub(crate) fn inline_into_callers(acc: &mut Assists, ctx: &AssistContext<'_>) -> let is_recursive_fn = usages .clone() - .in_scope(SearchScope::file_range(FileRange { + .in_scope(&SearchScope::file_range(FileRange { file_id: def_file, range: func_body.syntax().text_range(), })) diff --git a/crates/ide-assists/src/handlers/inline_macro.rs b/crates/ide-assists/src/handlers/inline_macro.rs index 5aa8e56f5626..5d956b1a5e87 100644 --- a/crates/ide-assists/src/handlers/inline_macro.rs +++ b/crates/ide-assists/src/handlers/inline_macro.rs @@ -37,11 +37,10 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; pub(crate) fn inline_macro(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let unexpanded = ctx.find_node_at_offset::()?; let expanded = insert_ws_into(ctx.sema.expand(&unexpanded)?.clone_for_update()); - let text_range = unexpanded.syntax().text_range(); acc.add( - AssistId("inline_macro", AssistKind::RefactorRewrite), + AssistId("inline_macro", AssistKind::RefactorInline), format!("Inline macro"), text_range, |builder| builder.replace(text_range, expanded.to_string()), diff --git a/crates/ide-assists/src/handlers/move_const_to_impl.rs b/crates/ide-assists/src/handlers/move_const_to_impl.rs index e1849eb71d57..22d536b5afc3 100644 --- a/crates/ide-assists/src/handlers/move_const_to_impl.rs +++ b/crates/ide-assists/src/handlers/move_const_to_impl.rs @@ -82,17 +82,19 @@ pub(crate) fn move_const_to_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> return None; } - let usages = - Definition::Const(def).usages(&ctx.sema).in_scope(SearchScope::file_range(FileRange { - file_id: ctx.file_id(), - range: parent_fn.syntax().text_range(), - })); - acc.add( AssistId("move_const_to_impl", crate::AssistKind::RefactorRewrite), "Move const to impl block", const_.syntax().text_range(), |builder| { + let usages = Definition::Const(def) + .usages(&ctx.sema) + .in_scope(&SearchScope::file_range(FileRange { + file_id: ctx.file_id(), + range: parent_fn.syntax().text_range(), + })) + .all(); + let range_to_delete = match const_.syntax().next_sibling_or_token() { Some(s) if matches!(s.kind(), SyntaxKind::WHITESPACE) => { // Remove following whitespaces too. @@ -103,7 +105,7 @@ pub(crate) fn move_const_to_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> builder.delete(range_to_delete); let const_ref = format!("Self::{}", name.display(ctx.db())); - for range in usages.all().file_ranges().map(|it| it.range) { + for range in usages.file_ranges().map(|it| it.range) { builder.replace(range, const_ref.clone()); } diff --git a/crates/ide-assists/src/handlers/remove_unused_imports.rs b/crates/ide-assists/src/handlers/remove_unused_imports.rs new file mode 100644 index 000000000000..dd4839351fb4 --- /dev/null +++ b/crates/ide-assists/src/handlers/remove_unused_imports.rs @@ -0,0 +1,739 @@ +use std::collections::{hash_map::Entry, HashMap}; + +use hir::{InFile, Module, ModuleSource}; +use ide_db::{ + base_db::FileRange, + defs::Definition, + search::{FileReference, ReferenceCategory, SearchScope}, + RootDatabase, +}; +use syntax::{ast, AstNode}; +use text_edit::TextRange; + +use crate::{AssistContext, AssistId, AssistKind, Assists}; + +// Assist: remove_unused_imports +// +// Removes any use statements in the current selection that are unused. +// +// ``` +// struct X(); +// mod foo { +// use super::X$0; +// } +// ``` +// -> +// ``` +// struct X(); +// mod foo { +// } +// ``` +pub(crate) fn remove_unused_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + // First, grab the uses that intersect with the current selection. + let selected_el = match ctx.covering_element() { + syntax::NodeOrToken::Node(n) => n, + syntax::NodeOrToken::Token(t) => t.parent()?, + }; + + // This applies to all uses that are selected, or are ancestors of our selection. + let uses_up = selected_el.ancestors().skip(1).filter_map(ast::Use::cast); + let uses_down = selected_el + .descendants() + .filter(|x| x.text_range().intersect(ctx.selection_trimmed()).is_some()) + .filter_map(ast::Use::cast); + let uses = uses_up.chain(uses_down).collect::>(); + + // Maps use nodes to the scope that we should search through to find + let mut search_scopes = HashMap::>::new(); + + // iterator over all unused use trees + let mut unused = uses + .into_iter() + .flat_map(|u| u.syntax().descendants().filter_map(ast::UseTree::cast)) + .filter(|u| u.use_tree_list().is_none()) + .filter_map(|u| { + // Find any uses trees that are unused + + let use_module = ctx.sema.scope(&u.syntax()).map(|s| s.module())?; + let scope = match search_scopes.entry(use_module) { + Entry::Occupied(o) => o.into_mut(), + Entry::Vacant(v) => v.insert(module_search_scope(ctx.db(), use_module)), + }; + + // Gets the path associated with this use tree. If there isn't one, then ignore this use tree. + let path = if let Some(path) = u.path() { + path + } else if u.star_token().is_some() { + // This case maps to the situation where the * token is braced. + // In this case, the parent use tree's path is the one we should use to resolve the glob. + match u.syntax().ancestors().skip(1).find_map(ast::UseTree::cast) { + Some(parent_u) if parent_u.path().is_some() => parent_u.path().unwrap(), + _ => return None, + } + } else { + return None; + }; + + // Get the actual definition associated with this use item. + let res = match ctx.sema.resolve_path(&path) { + Some(x) => x, + None => { + return None; + } + }; + + let def = match res { + hir::PathResolution::Def(d) => Definition::from(d), + _ => return None, + }; + + if u.star_token().is_some() { + // Check if any of the children of this module are used + let def_mod = match def { + Definition::Module(module) => module, + _ => return None, + }; + + if !def_mod + .scope(ctx.db(), Some(use_module)) + .iter() + .filter_map(|(_, x)| match x { + hir::ScopeDef::ModuleDef(d) => Some(Definition::from(*d)), + _ => None, + }) + .any(|d| used_once_in_scope(ctx, d, scope)) + { + return Some(u); + } + } else if let Definition::Trait(ref t) = def { + // If the trait or any item is used. + if !std::iter::once(def) + .chain(t.items(ctx.db()).into_iter().map(Definition::from)) + .any(|d| used_once_in_scope(ctx, d, scope)) + { + return Some(u); + } + } else { + if !used_once_in_scope(ctx, def, &scope) { + return Some(u); + } + } + + None + }) + .peekable(); + + // Peek so we terminate early if an unused use is found. Only do the rest of the work if the user selects the assist. + if unused.peek().is_some() { + acc.add( + AssistId("remove_unused_imports", AssistKind::QuickFix), + "Remove all the unused imports", + selected_el.text_range(), + |builder| { + let unused: Vec = unused.map(|x| builder.make_mut(x)).collect(); + for node in unused { + node.remove_recursive(); + } + }, + ) + } else { + None + } +} + +fn used_once_in_scope(ctx: &AssistContext<'_>, def: Definition, scopes: &Vec) -> bool { + let mut found = false; + + for scope in scopes { + let mut search_non_import = |_, r: FileReference| { + // The import itself is a use; we must skip that. + if r.category != Some(ReferenceCategory::Import) { + found = true; + true + } else { + false + } + }; + def.usages(&ctx.sema).in_scope(scope).search(&mut search_non_import); + if found { + break; + } + } + + found +} + +/// Build a search scope spanning the given module but none of its submodules. +fn module_search_scope(db: &RootDatabase, module: hir::Module) -> Vec { + let (file_id, range) = { + let InFile { file_id, value } = module.definition_source(db); + if let Some((file_id, call_source)) = file_id.original_call_node(db) { + (file_id, Some(call_source.text_range())) + } else { + ( + file_id.original_file(db), + match value { + ModuleSource::SourceFile(_) => None, + ModuleSource::Module(it) => Some(it.syntax().text_range()), + ModuleSource::BlockExpr(it) => Some(it.syntax().text_range()), + }, + ) + } + }; + + fn split_at_subrange(first: TextRange, second: TextRange) -> (TextRange, Option) { + let intersect = first.intersect(second); + if let Some(intersect) = intersect { + let start_range = TextRange::new(first.start(), intersect.start()); + + if intersect.end() < first.end() { + (start_range, Some(TextRange::new(intersect.end(), first.end()))) + } else { + (start_range, None) + } + } else { + (first, None) + } + } + + let mut scopes = Vec::new(); + if let Some(range) = range { + let mut ranges = vec![range]; + + for child in module.children(db) { + let rng = match child.definition_source(db).value { + ModuleSource::SourceFile(_) => continue, + ModuleSource::Module(it) => it.syntax().text_range(), + ModuleSource::BlockExpr(_) => continue, + }; + let mut new_ranges = Vec::new(); + for old_range in ranges.iter_mut() { + let split = split_at_subrange(old_range.clone(), rng); + *old_range = split.0; + new_ranges.extend(split.1); + } + + ranges.append(&mut new_ranges); + } + + for range in ranges { + scopes.push(SearchScope::file_range(FileRange { file_id, range })); + } + } else { + scopes.push(SearchScope::single_file(file_id)); + } + + scopes +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable}; + + use super::*; + + #[test] + fn remove_unused() { + check_assist( + remove_unused_imports, + r#" +struct X(); +struct Y(); +mod z { + $0use super::X; + use super::Y;$0 +} +"#, + r#" +struct X(); +struct Y(); +mod z { +} +"#, + ); + } + + #[test] + fn remove_unused_is_precise() { + check_assist( + remove_unused_imports, + r#" +struct X(); +mod z { +$0use super::X;$0 + +fn w() { + struct X(); + let x = X(); +} +} +"#, + r#" +struct X(); +mod z { + +fn w() { + struct X(); + let x = X(); +} +} +"#, + ); + } + + #[test] + fn trait_name_use_is_use() { + check_assist_not_applicable( + remove_unused_imports, + r#" +struct X(); +trait Y { + fn f(); +} + +impl Y for X { + fn f() {} +} +mod z { +$0use super::X; +use super::Y;$0 + +fn w() { + X::f(); +} +} +"#, + ); + } + + #[test] + fn trait_item_use_is_use() { + check_assist_not_applicable( + remove_unused_imports, + r#" +struct X(); +trait Y { + fn f(self); +} + +impl Y for X { + fn f(self) {} +} +mod z { +$0use super::X; +use super::Y;$0 + +fn w() { + let x = X(); + x.f(); +} +} +"#, + ); + } + + #[test] + fn ranamed_trait_item_use_is_use() { + check_assist_not_applicable( + remove_unused_imports, + r#" +struct X(); +trait Y { + fn f(self); +} + +impl Y for X { + fn f(self) {} +} +mod z { +$0use super::X; +use super::Y as Z;$0 + +fn w() { + let x = X(); + x.f(); +} +} +"#, + ); + } + + #[test] + fn ranamed_underscore_trait_item_use_is_use() { + check_assist_not_applicable( + remove_unused_imports, + r#" +struct X(); +trait Y { + fn f(self); +} + +impl Y for X { + fn f(self) {} +} +mod z { +$0use super::X; +use super::Y as _;$0 + +fn w() { + let x = X(); + x.f(); +} +} +"#, + ); + } + + #[test] + fn dont_remove_used() { + check_assist_not_applicable( + remove_unused_imports, + r#" +struct X(); +struct Y(); +mod z { +$0use super::X; +use super::Y;$0 + +fn w() { + let x = X(); + let y = Y(); +} +} +"#, + ); + } + + #[test] + fn remove_unused_in_braces() { + check_assist( + remove_unused_imports, + r#" +struct X(); +struct Y(); +mod z { + $0use super::{X, Y};$0 + + fn w() { + let x = X(); + } +} +"#, + r#" +struct X(); +struct Y(); +mod z { + use super::{X}; + + fn w() { + let x = X(); + } +} +"#, + ); + } + + #[test] + fn remove_unused_under_cursor() { + check_assist( + remove_unused_imports, + r#" +struct X(); +mod z { + use super::X$0; +} +"#, + r#" +struct X(); +mod z { +} +"#, + ); + } + + #[test] + fn remove_multi_use_block() { + check_assist( + remove_unused_imports, + r#" +struct X(); +$0mod y { + use super::X; +} +mod z { + use super::X; +}$0 +"#, + r#" +struct X(); +mod y { +} +mod z { +} +"#, + ); + } + + #[test] + fn remove_nested() { + check_assist( + remove_unused_imports, + r#" +struct X(); +mod y { + struct Y(); + mod z { + use crate::{X, y::Y}$0; + fn f() { + let x = X(); + } + } +} +"#, + r#" +struct X(); +mod y { + struct Y(); + mod z { + use crate::{X}; + fn f() { + let x = X(); + } + } +} +"#, + ); + } + + #[test] + fn remove_nested_first_item() { + check_assist( + remove_unused_imports, + r#" +struct X(); +mod y { + struct Y(); + mod z { + use crate::{X, y::Y}$0; + fn f() { + let y = Y(); + } + } +} +"#, + r#" +struct X(); +mod y { + struct Y(); + mod z { + use crate::{y::Y}; + fn f() { + let y = Y(); + } + } +} +"#, + ); + } + + #[test] + fn remove_nested_all_unused() { + check_assist( + remove_unused_imports, + r#" +struct X(); +mod y { + struct Y(); + mod z { + use crate::{X, y::Y}$0; + } +} +"#, + r#" +struct X(); +mod y { + struct Y(); + mod z { + } +} +"#, + ); + } + + #[test] + fn remove_unused_glob() { + check_assist( + remove_unused_imports, + r#" +struct X(); +struct Y(); +mod z { + use super::*$0; +} +"#, + r#" +struct X(); +struct Y(); +mod z { +} +"#, + ); + } + + #[test] + fn remove_unused_braced_glob() { + check_assist( + remove_unused_imports, + r#" +struct X(); +struct Y(); +mod z { + use super::{*}$0; +} +"#, + r#" +struct X(); +struct Y(); +mod z { +} +"#, + ); + } + + #[test] + fn dont_remove_used_glob() { + check_assist_not_applicable( + remove_unused_imports, + r#" +struct X(); +struct Y(); +mod z { + use super::*$0; + + fn f() { + let x = X(); + } +} +"#, + ); + } + + #[test] + fn only_remove_from_selection() { + check_assist( + remove_unused_imports, + r#" +struct X(); +struct Y(); +mod z { + $0use super::X;$0 + use super::Y; +} +mod w { + use super::Y; +} +"#, + r#" +struct X(); +struct Y(); +mod z { + use super::Y; +} +mod w { + use super::Y; +} +"#, + ); + } + + #[test] + fn test_several_files() { + check_assist( + remove_unused_imports, + r#" +//- /foo.rs +pub struct X(); +pub struct Y(); + +//- /main.rs +$0use foo::X; +use foo::Y; +$0 +mod foo; +mod z { + use crate::foo::X; +} +"#, + r#" + +mod foo; +mod z { + use crate::foo::X; +} +"#, + ); + } + + #[test] + fn use_in_submodule_doesnt_count() { + check_assist( + remove_unused_imports, + r#" +struct X(); +mod z { + use super::X$0; + + mod w { + use crate::X; + + fn f() { + let x = X(); + } + } +} +"#, + r#" +struct X(); +mod z { + + mod w { + use crate::X; + + fn f() { + let x = X(); + } + } +} +"#, + ); + } + + #[test] + fn use_in_submodule_file_doesnt_count() { + check_assist( + remove_unused_imports, + r#" +//- /z/foo.rs +use crate::X; +fn f() { + let x = X(); +} + +//- /main.rs +pub struct X(); + +mod z { + use crate::X$0; + mod foo; +} +"#, + r#" +pub struct X(); + +mod z { + mod foo; +} +"#, + ); + } +} diff --git a/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs index c03bc2f41d50..ac45581b7b44 100644 --- a/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs @@ -10,7 +10,7 @@ use crate::{ assist_context::{AssistContext, Assists, SourceChangeBuilder}, utils::{ add_trait_assoc_items_to_impl, filter_assoc_items, gen_trait_fn_body, - generate_trait_impl_text, render_snippet, Cursor, DefaultMethods, + generate_trait_impl_text, render_snippet, Cursor, DefaultMethods, IgnoreAssocItems, }, AssistId, AssistKind, }; @@ -172,7 +172,17 @@ fn impl_def_from_trait( ) -> Option<(ast::Impl, ast::AssocItem)> { let trait_ = trait_?; let target_scope = sema.scope(annotated_name.syntax())?; - let trait_items = filter_assoc_items(sema, &trait_.items(sema.db), DefaultMethods::No); + + // Keep assoc items of local crates even if they have #[doc(hidden)] attr. + let ignore_items = if trait_.module(sema.db).krate().origin(sema.db).is_local() { + IgnoreAssocItems::No + } else { + IgnoreAssocItems::DocHiddenAttrPresent + }; + + let trait_items = + filter_assoc_items(sema, &trait_.items(sema.db), DefaultMethods::No, ignore_items); + if trait_items.is_empty() { return None; } diff --git a/crates/ide-assists/src/handlers/replace_named_generic_with_impl.rs b/crates/ide-assists/src/handlers/replace_named_generic_with_impl.rs index e7b62d49bb81..c7c0be4c7d4f 100644 --- a/crates/ide-assists/src/handlers/replace_named_generic_with_impl.rs +++ b/crates/ide-assists/src/handlers/replace_named_generic_with_impl.rs @@ -157,7 +157,7 @@ fn find_usages( file_id: FileId, ) -> UsageSearchResult { let file_range = FileRange { file_id, range: fn_.syntax().text_range() }; - type_param_def.usages(sema).in_scope(SearchScope::file_range(file_range)).all() + type_param_def.usages(sema).in_scope(&SearchScope::file_range(file_range)).all() } fn check_valid_usages(usages: &UsageSearchResult, param_list_range: TextRange) -> bool { diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs index a82f1f9dd8be..2ebb5ef9b190 100644 --- a/crates/ide-assists/src/lib.rs +++ b/crates/ide-assists/src/lib.rs @@ -184,6 +184,7 @@ mod handlers { mod raw_string; mod remove_dbg; mod remove_mut; + mod remove_unused_imports; mod remove_unused_param; mod remove_parentheses; mod reorder_fields; @@ -294,6 +295,7 @@ mod handlers { raw_string::make_usual_string, raw_string::remove_hash, remove_mut::remove_mut, + remove_unused_imports::remove_unused_imports, remove_unused_param::remove_unused_param, remove_parentheses::remove_parentheses, reorder_fields::reorder_fields, diff --git a/crates/ide-assists/src/tests.rs b/crates/ide-assists/src/tests.rs index 344f2bfcce14..cc3e251a8f2a 100644 --- a/crates/ide-assists/src/tests.rs +++ b/crates/ide-assists/src/tests.rs @@ -132,8 +132,13 @@ fn check_doc_test(assist_id: &str, before: &str, after: &str) { .filter(|it| !it.source_file_edits.is_empty() || !it.file_system_edits.is_empty()) .expect("Assist did not contain any source changes"); let mut actual = before; - if let Some(source_file_edit) = source_change.get_source_edit(file_id) { + if let Some((source_file_edit, snippet_edit)) = + source_change.get_source_and_snippet_edit(file_id) + { source_file_edit.apply(&mut actual); + if let Some(snippet_edit) = snippet_edit { + snippet_edit.apply(&mut actual); + } } actual }; @@ -191,9 +196,12 @@ fn check_with_config( && source_change.file_system_edits.len() == 0; let mut buf = String::new(); - for (file_id, edit) in source_change.source_file_edits { + for (file_id, (edit, snippet_edit)) in source_change.source_file_edits { let mut text = db.file_text(file_id).as_ref().to_owned(); edit.apply(&mut text); + if let Some(snippet_edit) = snippet_edit { + snippet_edit.apply(&mut text); + } if !skip_header { let sr = db.file_source_root(file_id); let sr = db.source_root(sr); @@ -485,18 +493,21 @@ pub fn test_some_range(a: int) -> bool { source_file_edits: { FileId( 0, - ): TextEdit { - indels: [ - Indel { - insert: "let $0var_name = 5;\n ", - delete: 45..45, - }, - Indel { - insert: "var_name", - delete: 59..60, - }, - ], - }, + ): ( + TextEdit { + indels: [ + Indel { + insert: "let $0var_name = 5;\n ", + delete: 45..45, + }, + Indel { + insert: "var_name", + delete: 59..60, + }, + ], + }, + None, + ), }, file_system_edits: [], is_snippet: true, @@ -544,18 +555,21 @@ pub fn test_some_range(a: int) -> bool { source_file_edits: { FileId( 0, - ): TextEdit { - indels: [ - Indel { - insert: "let $0var_name = 5;\n ", - delete: 45..45, - }, - Indel { - insert: "var_name", - delete: 59..60, - }, - ], - }, + ): ( + TextEdit { + indels: [ + Indel { + insert: "let $0var_name = 5;\n ", + delete: 45..45, + }, + Indel { + insert: "var_name", + delete: 59..60, + }, + ], + }, + None, + ), }, file_system_edits: [], is_snippet: true, @@ -581,18 +595,21 @@ pub fn test_some_range(a: int) -> bool { source_file_edits: { FileId( 0, - ): TextEdit { - indels: [ - Indel { - insert: "fun_name()", - delete: 59..60, - }, - Indel { - insert: "\n\nfn $0fun_name() -> i32 {\n 5\n}", - delete: 110..110, - }, - ], - }, + ): ( + TextEdit { + indels: [ + Indel { + insert: "fun_name()", + delete: 59..60, + }, + Indel { + insert: "\n\nfn $0fun_name() -> i32 {\n 5\n}", + delete: 110..110, + }, + ], + }, + None, + ), }, file_system_edits: [], is_snippet: true, diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index 4d47a199b7c2..6eadc3dbcbcc 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -952,6 +952,7 @@ fn doctest_generate_default_from_new() { check_doc_test( "generate_default_from_new", r#####" +//- minicore: default struct Example { _inner: () } impl Example { @@ -2233,6 +2234,24 @@ fn main() { ) } +#[test] +fn doctest_remove_unused_imports() { + check_doc_test( + "remove_unused_imports", + r#####" +struct X(); +mod foo { + use super::X$0; +} +"#####, + r#####" +struct X(); +mod foo { +} +"#####, + ) +} + #[test] fn doctest_remove_unused_param() { check_doc_test( diff --git a/crates/ide-assists/src/utils.rs b/crates/ide-assists/src/utils.rs index 03d8553506f1..a262570d94e7 100644 --- a/crates/ide-assists/src/utils.rs +++ b/crates/ide-assists/src/utils.rs @@ -3,7 +3,7 @@ use std::ops; pub(crate) use gen_trait_fn_body::gen_trait_fn_body; -use hir::{db::HirDatabase, HirDisplay, InFile, Semantics}; +use hir::{db::HirDatabase, HasAttrs as HirHasAttrs, HirDisplay, InFile, Semantics}; use ide_db::{ famous_defs::FamousDefs, path_transform::PathTransform, syntax_helpers::insert_whitespace_into_node::insert_ws_into, RootDatabase, SnippetCap, @@ -84,6 +84,12 @@ pub fn test_related_attribute(fn_def: &ast::Fn) -> Option { }) } +#[derive(Clone, Copy, PartialEq)] +pub enum IgnoreAssocItems { + DocHiddenAttrPresent, + No, +} + #[derive(Copy, Clone, PartialEq)] pub enum DefaultMethods { Only, @@ -94,11 +100,16 @@ pub fn filter_assoc_items( sema: &Semantics<'_, RootDatabase>, items: &[hir::AssocItem], default_methods: DefaultMethods, + ignore_items: IgnoreAssocItems, ) -> Vec> { return items .iter() - // Note: This throws away items with no source. .copied() + .filter(|assoc_item| { + !(ignore_items == IgnoreAssocItems::DocHiddenAttrPresent + && assoc_item.attrs(sema.db).has_doc_hidden()) + }) + // Note: This throws away items with no source. .filter_map(|assoc_item| { let item = match assoc_item { hir::AssocItem::Function(it) => sema.source(it)?.map(ast::AssocItem::Fn), diff --git a/crates/ide-completion/src/item.rs b/crates/ide-completion/src/item.rs index e850f7bfdf3f..0309952c29a8 100644 --- a/crates/ide-completion/src/item.rs +++ b/crates/ide-completion/src/item.rs @@ -427,9 +427,26 @@ impl Builder { let insert_text = self.insert_text.unwrap_or_else(|| label.to_string()); if !self.doc_aliases.is_empty() { - let doc_aliases = self.doc_aliases.into_iter().join(", "); + let doc_aliases = self.doc_aliases.iter().join(", "); label = SmolStr::from(format!("{label} (alias {doc_aliases})")); - lookup = SmolStr::from(format!("{lookup} {doc_aliases}")); + let lookup_doc_aliases = self + .doc_aliases + .iter() + // Don't include aliases in `lookup` that aren't valid identifiers as including + // them results in weird completion filtering behavior e.g. `Partial>` matching + // `PartialOrd` because it has an alias of ">". + .filter(|alias| { + let mut chars = alias.chars(); + chars.next().is_some_and(char::is_alphabetic) + && chars.all(|c| c.is_alphanumeric() || c == '_') + }) + // Deliberately concatenated without separators as adding separators e.g. + // `alias1, alias2` results in LSP clients continuing to display the completion even + // after typing a comma or space. + .join(""); + if !lookup_doc_aliases.is_empty() { + lookup = SmolStr::from(format!("{lookup}{lookup_doc_aliases}")); + } } if let [import_edit] = &*self.imports_to_add { // snippets can have multiple imports, but normal completions only have up to one diff --git a/crates/ide-completion/src/tests/special.rs b/crates/ide-completion/src/tests/special.rs index 3824720839eb..e80a289049f1 100644 --- a/crates/ide-completion/src/tests/special.rs +++ b/crates/ide-completion/src/tests/special.rs @@ -1280,3 +1280,26 @@ fn here_we_go() { "#]], ); } + +#[test] +fn completion_filtering_excludes_non_identifier_doc_aliases() { + check_edit( + "PartialOrdcmporder", + r#" +#[doc(alias = ">")] +#[doc(alias = "cmp")] +#[doc(alias = "order")] +trait PartialOrd {} + +struct Foo it.module(db), Definition::GenericParam(it) => it.module(db), Definition::Label(it) => it.module(db), + Definition::ExternCrateDecl(it) => it.module(db), Definition::DeriveHelper(it) => it.derive().module(db), Definition::BuiltinAttr(_) | Definition::BuiltinType(_) | Definition::ToolModule(_) => { return None @@ -93,6 +95,7 @@ impl Definition { Definition::TraitAlias(it) => it.visibility(db), Definition::TypeAlias(it) => it.visibility(db), Definition::Variant(it) => it.visibility(db), + Definition::ExternCrateDecl(it) => it.visibility(db), Definition::BuiltinType(_) => Visibility::Public, Definition::Macro(_) => return None, Definition::BuiltinAttr(_) @@ -127,6 +130,7 @@ impl Definition { Definition::BuiltinAttr(_) => return None, // FIXME Definition::ToolModule(_) => return None, // FIXME Definition::DeriveHelper(it) => it.name(db), + Definition::ExternCrateDecl(it) => return it.alias_or_name(db), }; Some(name) } @@ -196,6 +200,10 @@ impl IdentClass { res.push(Definition::Local(local_ref)); res.push(Definition::Field(field_ref)); } + IdentClass::NameRefClass(NameRefClass::ExternCrateShorthand { decl, krate }) => { + res.push(Definition::ExternCrateDecl(decl)); + res.push(Definition::Module(krate.root_module())); + } IdentClass::Operator( OperatorClass::Await(func) | OperatorClass::Prefix(func) @@ -222,6 +230,10 @@ impl IdentClass { res.push(Definition::Local(local_ref)); res.push(Definition::Field(field_ref)); } + IdentClass::NameRefClass(NameRefClass::ExternCrateShorthand { decl, krate }) => { + res.push(Definition::ExternCrateDecl(decl)); + res.push(Definition::Module(krate.root_module())); + } IdentClass::Operator(_) => (), } res @@ -310,6 +322,7 @@ impl NameClass { ast::Item::Enum(it) => Definition::Adt(hir::Adt::Enum(sema.to_def(&it)?)), ast::Item::Struct(it) => Definition::Adt(hir::Adt::Struct(sema.to_def(&it)?)), ast::Item::Union(it) => Definition::Adt(hir::Adt::Union(sema.to_def(&it)?)), + ast::Item::ExternCrate(it) => Definition::ExternCrateDecl(sema.to_def(&it)?), _ => return None, }; Some(definition) @@ -346,10 +359,8 @@ impl NameClass { let path = use_tree.path()?; sema.resolve_path(&path).map(Definition::from) } else { - let extern_crate = rename.syntax().parent().and_then(ast::ExternCrate::cast)?; - let krate = sema.resolve_extern_crate(&extern_crate)?; - let root_module = krate.root_module(sema.db); - Some(Definition::Module(root_module)) + sema.to_def(&rename.syntax().parent().and_then(ast::ExternCrate::cast)?) + .map(Definition::ExternCrateDecl) } } } @@ -427,7 +438,19 @@ impl OperatorClass { #[derive(Debug)] pub enum NameRefClass { Definition(Definition), - FieldShorthand { local_ref: Local, field_ref: Field }, + FieldShorthand { + local_ref: Local, + field_ref: Field, + }, + /// The specific situation where we have an extern crate decl without a rename + /// Here we have both a declaration and a reference. + /// ```rs + /// extern crate foo; + /// ``` + ExternCrateShorthand { + decl: ExternCrateDecl, + krate: Crate, + }, } impl NameRefClass { @@ -513,10 +536,14 @@ impl NameRefClass { } None }, - ast::ExternCrate(extern_crate) => { - let krate = sema.resolve_extern_crate(&extern_crate)?; - let root_module = krate.root_module(sema.db); - Some(NameRefClass::Definition(Definition::Module(root_module))) + ast::ExternCrate(extern_crate_ast) => { + let extern_crate = sema.to_def(&extern_crate_ast)?; + let krate = extern_crate.resolved_crate(sema.db)?; + Some(if extern_crate_ast.rename().is_some() { + NameRefClass::Definition(Definition::Module(krate.root_module())) + } else { + NameRefClass::ExternCrateShorthand { krate, decl: extern_crate } + }) }, _ => None } diff --git a/crates/ide-db/src/famous_defs.rs b/crates/ide-db/src/famous_defs.rs index c8341fed1c72..b63dde2c21e7 100644 --- a/crates/ide-db/src/famous_defs.rs +++ b/crates/ide-db/src/famous_defs.rs @@ -167,7 +167,7 @@ impl FamousDefs<'_, '_> { lang_crate => lang_crate, }; let std_crate = self.find_lang_crate(lang_crate)?; - let mut module = std_crate.root_module(db); + let mut module = std_crate.root_module(); for segment in path { module = module.children(db).find_map(|child| { let name = child.name(db)?; diff --git a/crates/ide-db/src/rename.rs b/crates/ide-db/src/rename.rs index 52a23b4b8f3d..aa0bb7cce691 100644 --- a/crates/ide-db/src/rename.rs +++ b/crates/ide-db/src/rename.rs @@ -82,8 +82,9 @@ impl Definition { } /// Textual range of the identifier which will change when renaming this - /// `Definition`. Note that some definitions, like builtin types, can't be - /// renamed. + /// `Definition`. Note that builtin types can't be + /// renamed and extern crate names will report its range, though a rename will introduce + /// an alias instead. pub fn range_for_rename(self, sema: &Semantics<'_, RootDatabase>) -> Option { let res = match self { Definition::Macro(mac) => { @@ -146,6 +147,16 @@ impl Definition { let lifetime = src.value.lifetime()?; src.with_value(lifetime.syntax()).original_file_range_opt(sema.db) } + Definition::ExternCrateDecl(it) => { + let src = it.source(sema.db)?; + if let Some(rename) = src.value.rename() { + let name = rename.name()?; + src.with_value(name.syntax()).original_file_range_opt(sema.db) + } else { + let name = src.value.name_ref()?; + src.with_value(name.syntax()).original_file_range_opt(sema.db) + } + } Definition::BuiltinType(_) => return None, Definition::SelfType(_) => return None, Definition::BuiltinAttr(_) => return None, @@ -526,6 +537,9 @@ fn source_edit_from_def( TextRange::new(range.start() + syntax::TextSize::from(1), range.end()), new_name.strip_prefix('\'').unwrap_or(new_name).to_owned(), ), + Definition::ExternCrateDecl(decl) if decl.alias(sema.db).is_none() => { + (TextRange::empty(range.end()), format!(" as {new_name}")) + } _ => (range, new_name.to_owned()), }; edit.replace(range, new_name); diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs index f3c0f79c5896..d5abd0991268 100644 --- a/crates/ide-db/src/search.rs +++ b/crates/ide-db/src/search.rs @@ -127,7 +127,7 @@ impl SearchScope { } /// Build a search scope spanning the given module and all its submodules. - fn module_and_children(db: &RootDatabase, module: hir::Module) -> SearchScope { + pub fn module_and_children(db: &RootDatabase, module: hir::Module) -> SearchScope { let mut entries = IntMap::default(); let (file_id, range) = { @@ -329,7 +329,7 @@ impl Definition { pub struct FindUsages<'a> { def: Definition, sema: &'a Semantics<'a, RootDatabase>, - scope: Option, + scope: Option<&'a SearchScope>, /// The container of our definition should it be an assoc item assoc_item_container: Option, /// whether to search for the `Self` type of the definition @@ -338,7 +338,7 @@ pub struct FindUsages<'a> { search_self_mod: bool, } -impl FindUsages<'_> { +impl<'a> FindUsages<'a> { /// Enable searching for `Self` when the definition is a type or `self` for modules. pub fn include_self_refs(mut self) -> Self { self.include_self_kw_refs = def_to_ty(self.sema, &self.def); @@ -347,12 +347,12 @@ impl FindUsages<'_> { } /// Limit the search to a given [`SearchScope`]. - pub fn in_scope(self, scope: SearchScope) -> Self { + pub fn in_scope(self, scope: &'a SearchScope) -> Self { self.set_scope(Some(scope)) } /// Limit the search to a given [`SearchScope`]. - pub fn set_scope(mut self, scope: Option) -> Self { + pub fn set_scope(mut self, scope: Option<&'a SearchScope>) -> Self { assert!(self.scope.is_none()); self.scope = scope; self @@ -376,7 +376,7 @@ impl FindUsages<'_> { res } - fn search(&self, sink: &mut dyn FnMut(FileId, FileReference) -> bool) { + pub fn search(&self, sink: &mut dyn FnMut(FileId, FileReference) -> bool) { let _p = profile::span("FindUsages:search"); let sema = self.sema; diff --git a/crates/ide-db/src/source_change.rs b/crates/ide-db/src/source_change.rs index fad0ca51a025..39763479c65a 100644 --- a/crates/ide-db/src/source_change.rs +++ b/crates/ide-db/src/source_change.rs @@ -7,17 +7,17 @@ use std::{collections::hash_map::Entry, iter, mem}; use crate::SnippetCap; use base_db::{AnchoredPathBuf, FileId}; +use itertools::Itertools; use nohash_hasher::IntMap; use stdx::never; use syntax::{ - algo, ast, ted, AstNode, SyntaxElement, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, - TextSize, + algo, AstNode, SyntaxElement, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextSize, }; use text_edit::{TextEdit, TextEditBuilder}; #[derive(Default, Debug, Clone)] pub struct SourceChange { - pub source_file_edits: IntMap, + pub source_file_edits: IntMap)>, pub file_system_edits: Vec, pub is_snippet: bool, } @@ -26,7 +26,7 @@ impl SourceChange { /// Creates a new SourceChange with the given label /// from the edits. pub fn from_edits( - source_file_edits: IntMap, + source_file_edits: IntMap)>, file_system_edits: Vec, ) -> Self { SourceChange { source_file_edits, file_system_edits, is_snippet: false } @@ -34,7 +34,7 @@ impl SourceChange { pub fn from_text_edit(file_id: FileId, edit: TextEdit) -> Self { SourceChange { - source_file_edits: iter::once((file_id, edit)).collect(), + source_file_edits: iter::once((file_id, (edit, None))).collect(), ..Default::default() } } @@ -42,12 +42,31 @@ impl SourceChange { /// Inserts a [`TextEdit`] for the given [`FileId`]. This properly handles merging existing /// edits for a file if some already exist. pub fn insert_source_edit(&mut self, file_id: FileId, edit: TextEdit) { + self.insert_source_and_snippet_edit(file_id, edit, None) + } + + /// Inserts a [`TextEdit`] and potentially a [`SnippetEdit`] for the given [`FileId`]. + /// This properly handles merging existing edits for a file if some already exist. + pub fn insert_source_and_snippet_edit( + &mut self, + file_id: FileId, + edit: TextEdit, + snippet_edit: Option, + ) { match self.source_file_edits.entry(file_id) { Entry::Occupied(mut entry) => { - never!(entry.get_mut().union(edit).is_err(), "overlapping edits for same file"); + let value = entry.get_mut(); + never!(value.0.union(edit).is_err(), "overlapping edits for same file"); + never!( + value.1.is_some() && snippet_edit.is_some(), + "overlapping snippet edits for same file" + ); + if value.1.is_none() { + value.1 = snippet_edit; + } } Entry::Vacant(entry) => { - entry.insert(edit); + entry.insert((edit, snippet_edit)); } } } @@ -56,7 +75,10 @@ impl SourceChange { self.file_system_edits.push(edit); } - pub fn get_source_edit(&self, file_id: FileId) -> Option<&TextEdit> { + pub fn get_source_and_snippet_edit( + &self, + file_id: FileId, + ) -> Option<&(TextEdit, Option)> { self.source_file_edits.get(&file_id) } @@ -70,7 +92,18 @@ impl SourceChange { impl Extend<(FileId, TextEdit)> for SourceChange { fn extend>(&mut self, iter: T) { - iter.into_iter().for_each(|(file_id, edit)| self.insert_source_edit(file_id, edit)); + self.extend(iter.into_iter().map(|(file_id, edit)| (file_id, (edit, None)))) + } +} + +impl Extend<(FileId, (TextEdit, Option))> for SourceChange { + fn extend))>>( + &mut self, + iter: T, + ) { + iter.into_iter().for_each(|(file_id, (edit, snippet_edit))| { + self.insert_source_and_snippet_edit(file_id, edit, snippet_edit) + }); } } @@ -82,6 +115,8 @@ impl Extend for SourceChange { impl From> for SourceChange { fn from(source_file_edits: IntMap) -> SourceChange { + let source_file_edits = + source_file_edits.into_iter().map(|(file_id, edit)| (file_id, (edit, None))).collect(); SourceChange { source_file_edits, file_system_edits: Vec::new(), is_snippet: false } } } @@ -94,6 +129,65 @@ impl FromIterator<(FileId, TextEdit)> for SourceChange { } } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct SnippetEdit(Vec<(u32, TextRange)>); + +impl SnippetEdit { + pub fn new(snippets: Vec) -> Self { + let mut snippet_ranges = snippets + .into_iter() + .zip(1..) + .with_position() + .map(|pos| { + let (snippet, index) = match pos { + itertools::Position::First(it) | itertools::Position::Middle(it) => it, + // last/only snippet gets index 0 + itertools::Position::Last((snippet, _)) + | itertools::Position::Only((snippet, _)) => (snippet, 0), + }; + + let range = match snippet { + Snippet::Tabstop(pos) => TextRange::empty(pos), + Snippet::Placeholder(range) => range, + }; + (index, range) + }) + .collect_vec(); + + snippet_ranges.sort_by_key(|(_, range)| range.start()); + + // Ensure that none of the ranges overlap + let disjoint_ranges = snippet_ranges + .iter() + .zip(snippet_ranges.iter().skip(1)) + .all(|((_, left), (_, right))| left.end() <= right.start() || left == right); + stdx::always!(disjoint_ranges); + + SnippetEdit(snippet_ranges) + } + + /// Inserts all of the snippets into the given text. + pub fn apply(&self, text: &mut String) { + // Start from the back so that we don't have to adjust ranges + for (index, range) in self.0.iter().rev() { + if range.is_empty() { + // is a tabstop + text.insert_str(range.start().into(), &format!("${index}")); + } else { + // is a placeholder + text.insert(range.end().into(), '}'); + text.insert_str(range.start().into(), &format!("${{{index}:")); + } + } + } + + /// Gets the underlying snippet index + text range + /// Tabstops are represented by an empty range, and placeholders use the range that they were given + pub fn into_edit_ranges(self) -> Vec<(u32, TextRange)> { + self.0 + } +} + pub struct SourceChangeBuilder { pub edit: TextEditBuilder, pub file_id: FileId, @@ -152,24 +246,19 @@ impl SourceChangeBuilder { } fn commit(&mut self) { - // Render snippets first so that they get bundled into the tree diff - if let Some(mut snippets) = self.snippet_builder.take() { - // Last snippet always has stop index 0 - let last_stop = snippets.places.pop().unwrap(); - last_stop.place(0); - - for (index, stop) in snippets.places.into_iter().enumerate() { - stop.place(index + 1) - } - } + let snippet_edit = self.snippet_builder.take().map(|builder| { + SnippetEdit::new( + builder.places.into_iter().map(PlaceSnippet::finalize_position).collect_vec(), + ) + }); if let Some(tm) = self.mutated_tree.take() { - algo::diff(&tm.immutable, &tm.mutable_clone).into_text_edit(&mut self.edit) + algo::diff(&tm.immutable, &tm.mutable_clone).into_text_edit(&mut self.edit); } let edit = mem::take(&mut self.edit).finish(); - if !edit.is_empty() { - self.source_change.insert_source_edit(self.file_id, edit); + if !edit.is_empty() || snippet_edit.is_some() { + self.source_change.insert_source_and_snippet_edit(self.file_id, edit, snippet_edit); } } @@ -275,6 +364,16 @@ impl SourceChangeBuilder { pub fn finish(mut self) -> SourceChange { self.commit(); + + // Only one file can have snippet edits + stdx::never!(self + .source_change + .source_file_edits + .iter() + .filter(|(_, (_, snippet_edit))| snippet_edit.is_some()) + .at_most_one() + .is_err()); + mem::take(&mut self.source_change) } } @@ -296,6 +395,13 @@ impl From for SourceChange { } } +pub enum Snippet { + /// A tabstop snippet (e.g. `$0`). + Tabstop(TextSize), + /// A placeholder snippet (e.g. `${0:placeholder}`). + Placeholder(TextRange), +} + enum PlaceSnippet { /// Place a tabstop before an element Before(SyntaxElement), @@ -306,57 +412,11 @@ enum PlaceSnippet { } impl PlaceSnippet { - /// Places the snippet before or over an element with the given tab stop index - fn place(self, order: usize) { - // ensure the target element is still attached - match &self { - PlaceSnippet::Before(element) - | PlaceSnippet::After(element) - | PlaceSnippet::Over(element) => { - // element should still be in the tree, but if it isn't - // then it's okay to just ignore this place - if stdx::never!(element.parent().is_none()) { - return; - } - } - } - + fn finalize_position(self) -> Snippet { match self { - PlaceSnippet::Before(element) => { - ted::insert_raw(ted::Position::before(&element), Self::make_tab_stop(order)); - } - PlaceSnippet::After(element) => { - ted::insert_raw(ted::Position::after(&element), Self::make_tab_stop(order)); - } - PlaceSnippet::Over(element) => { - let position = ted::Position::before(&element); - element.detach(); - - let snippet = ast::SourceFile::parse(&format!("${{{order}:_}}")) - .syntax_node() - .clone_for_update(); - - let placeholder = - snippet.descendants().find_map(ast::UnderscoreExpr::cast).unwrap(); - ted::replace(placeholder.syntax(), element); - - ted::insert_raw(position, snippet); - } + PlaceSnippet::Before(it) => Snippet::Tabstop(it.text_range().start()), + PlaceSnippet::After(it) => Snippet::Tabstop(it.text_range().end()), + PlaceSnippet::Over(it) => Snippet::Placeholder(it.text_range()), } } - - fn make_tab_stop(order: usize) -> SyntaxNode { - let stop = ast::SourceFile::parse(&format!("stop!(${order})")) - .syntax_node() - .descendants() - .find_map(ast::TokenTree::cast) - .unwrap() - .syntax() - .clone_for_update(); - - stop.first_token().unwrap().detach(); - stop.last_token().unwrap().detach(); - - stop - } } diff --git a/crates/ide-diagnostics/src/handlers/macro_error.rs b/crates/ide-diagnostics/src/handlers/macro_error.rs index 937e2f96642e..f54cdd63bbb6 100644 --- a/crates/ide-diagnostics/src/handlers/macro_error.rs +++ b/crates/ide-diagnostics/src/handlers/macro_error.rs @@ -51,6 +51,9 @@ macro_rules! compile_error { () => {} } compile_error!("compile_error macro works"); //^^^^^^^^^^^^^ error: compile_error macro works + + compile_error! { "compile_error macro braced works" } +//^^^^^^^^^^^^^ error: compile_error macro braced works "#, ); } @@ -77,7 +80,7 @@ macro_rules! m { fn f() { m!(); - //^^^^ error: unresolved macro `$crate::private::concat!` + //^^^^ error: unresolved macro $crate::private::concat } //- /core.rs crate:core diff --git a/crates/ide-diagnostics/src/handlers/missing_fields.rs b/crates/ide-diagnostics/src/handlers/missing_fields.rs index bb0e36ff3a1e..acc31cd117ad 100644 --- a/crates/ide-diagnostics/src/handlers/missing_fields.rs +++ b/crates/ide-diagnostics/src/handlers/missing_fields.rs @@ -208,7 +208,7 @@ fn get_default_constructor( } let krate = ctx.sema.to_module_def(d.file.original_file(ctx.sema.db))?.krate(); - let module = krate.root_module(ctx.sema.db); + let module = krate.root_module(); // Look for a ::new() associated function let has_new_func = ty diff --git a/crates/ide-diagnostics/src/tests.rs b/crates/ide-diagnostics/src/tests.rs index 4ac9d0a9fb73..ee0e0354906e 100644 --- a/crates/ide-diagnostics/src/tests.rs +++ b/crates/ide-diagnostics/src/tests.rs @@ -49,8 +49,11 @@ fn check_nth_fix(nth: usize, ra_fixture_before: &str, ra_fixture_after: &str) { let file_id = *source_change.source_file_edits.keys().next().unwrap(); let mut actual = db.file_text(file_id).to_string(); - for edit in source_change.source_file_edits.values() { + for (edit, snippet_edit) in source_change.source_file_edits.values() { edit.apply(&mut actual); + if let Some(snippet_edit) = snippet_edit { + snippet_edit.apply(&mut actual); + } } actual }; diff --git a/crates/ide-ssr/src/search.rs b/crates/ide-ssr/src/search.rs index 96c193bd5390..ca76d0a87b99 100644 --- a/crates/ide-ssr/src/search.rs +++ b/crates/ide-ssr/src/search.rs @@ -121,7 +121,7 @@ impl MatchFinder<'_> { // cache miss. This is a limitation of NLL and is fixed with Polonius. For now we do two // lookups in the case of a cache hit. if usage_cache.find(&definition).is_none() { - let usages = definition.usages(&self.sema).in_scope(self.search_scope()).all(); + let usages = definition.usages(&self.sema).in_scope(&self.search_scope()).all(); usage_cache.usages.push((definition, usages)); return &usage_cache.usages.last().unwrap().1; } diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index c90ba2125353..d240127f3761 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs @@ -153,6 +153,9 @@ pub(crate) fn external_docs( NameRefClass::FieldShorthand { local_ref: _, field_ref } => { Definition::Field(field_ref) } + NameRefClass::ExternCrateShorthand { decl, .. } => { + Definition::ExternCrateDecl(decl) + } }, ast::Name(name) => match NameClass::classify(sema, &name)? { NameClass::Definition(it) | NameClass::ConstReference(it) => it, @@ -209,6 +212,7 @@ pub(crate) fn resolve_doc_path_for_def( Definition::Macro(it) => it.resolve_doc_path(db, link, ns), Definition::Field(it) => it.resolve_doc_path(db, link, ns), Definition::SelfType(it) => it.resolve_doc_path(db, link, ns), + Definition::ExternCrateDecl(it) => it.resolve_doc_path(db, link, ns), Definition::BuiltinAttr(_) | Definition::ToolModule(_) | Definition::BuiltinType(_) @@ -617,6 +621,9 @@ fn filename_and_frag_for_def( // FIXME fragment numbering return Some((adt, file, Some(String::from("impl")))); } + Definition::ExternCrateDecl(it) => { + format!("{}/index.html", it.name(db).display(db.upcast())) + } Definition::Local(_) | Definition::GenericParam(_) | Definition::Label(_) diff --git a/crates/ide/src/goto_declaration.rs b/crates/ide/src/goto_declaration.rs index e70bc2ec5417..c39c696cfd9b 100644 --- a/crates/ide/src/goto_declaration.rs +++ b/crates/ide/src/goto_declaration.rs @@ -37,11 +37,15 @@ pub(crate) fn goto_declaration( match parent { ast::NameRef(name_ref) => match NameRefClass::classify(&sema, &name_ref)? { NameRefClass::Definition(it) => Some(it), - NameRefClass::FieldShorthand { field_ref, .. } => return field_ref.try_to_nav(db), + NameRefClass::FieldShorthand { field_ref, .. } => + return field_ref.try_to_nav(db), + NameRefClass::ExternCrateShorthand { decl, .. } => + return decl.try_to_nav(db), }, ast::Name(name) => match NameClass::classify(&sema, &name)? { NameClass::Definition(it) | NameClass::ConstReference(it) => Some(it), - NameClass::PatFieldShorthand { field_ref, .. } => return field_ref.try_to_nav(db), + NameClass::PatFieldShorthand { field_ref, .. } => + return field_ref.try_to_nav(db), }, _ => None } @@ -53,6 +57,7 @@ pub(crate) fn goto_declaration( Definition::Const(c) => c.as_assoc_item(db), Definition::TypeAlias(ta) => ta.as_assoc_item(db), Definition::Function(f) => f.as_assoc_item(db), + Definition::ExternCrateDecl(it) => return it.try_to_nav(db), _ => None, }?; @@ -211,4 +216,30 @@ fn main() { "#, ); } + + #[test] + fn goto_decl_for_extern_crate() { + check( + r#" +//- /main.rs crate:main deps:std +extern crate std$0; + /// ^^^ +//- /std/lib.rs crate:std +// empty +"#, + ) + } + + #[test] + fn goto_decl_for_renamed_extern_crate() { + check( + r#" +//- /main.rs crate:main deps:std +extern crate std as abc$0; + /// ^^^ +//- /std/lib.rs crate:std +// empty +"#, + ) + } } diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index 4e641357e372..21471ab2a03d 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -1,6 +1,9 @@ use std::mem::discriminant; -use crate::{doc_links::token_as_doc_comment, FilePosition, NavigationTarget, RangeInfo, TryToNav}; +use crate::{ + doc_links::token_as_doc_comment, navigation_target::ToNav, FilePosition, NavigationTarget, + RangeInfo, TryToNav, +}; use hir::{AsAssocItem, AssocItem, Semantics}; use ide_db::{ base_db::{AnchoredPath, FileId, FileLoader}, @@ -73,6 +76,13 @@ pub(crate) fn goto_definition( .definitions() .into_iter() .flat_map(|def| { + if let Definition::ExternCrateDecl(crate_def) = def { + return crate_def + .resolved_crate(db) + .map(|it| it.root_module().to_nav(sema.db)) + .into_iter() + .collect(); + } try_filter_trait_item_definition(sema, &def) .unwrap_or_else(|| def_to_nav(sema.db, def)) }) diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs index a1a119629a94..37166bdbd0c1 100644 --- a/crates/ide/src/goto_implementation.rs +++ b/crates/ide/src/goto_implementation.rs @@ -34,54 +34,50 @@ pub(crate) fn goto_implementation( _ => 0, })?; let range = original_token.text_range(); - let navs = sema - .descend_into_macros(original_token) - .into_iter() - .filter_map(|token| token.parent().and_then(ast::NameLike::cast)) - .filter_map(|node| match &node { - ast::NameLike::Name(name) => { - NameClass::classify(&sema, name).map(|class| match class { - NameClass::Definition(it) | NameClass::ConstReference(it) => it, - NameClass::PatFieldShorthand { local_def, field_ref: _ } => { - Definition::Local(local_def) - } - }) - } - ast::NameLike::NameRef(name_ref) => { - NameRefClass::classify(&sema, name_ref).map(|class| match class { - NameRefClass::Definition(def) => def, - NameRefClass::FieldShorthand { local_ref, field_ref: _ } => { - Definition::Local(local_ref) - } - }) - } - ast::NameLike::Lifetime(_) => None, - }) - .unique() - .filter_map(|def| { - let navs = match def { - Definition::Trait(trait_) => impls_for_trait(&sema, trait_), - Definition::Adt(adt) => impls_for_ty(&sema, adt.ty(sema.db)), - Definition::TypeAlias(alias) => impls_for_ty(&sema, alias.ty(sema.db)), - Definition::BuiltinType(builtin) => impls_for_ty(&sema, builtin.ty(sema.db)), - Definition::Function(f) => { - let assoc = f.as_assoc_item(sema.db)?; - let name = assoc.name(sema.db)?; - let trait_ = assoc.containing_trait_or_trait_impl(sema.db)?; - impls_for_trait_item(&sema, trait_, name) + let navs = + sema.descend_into_macros(original_token) + .into_iter() + .filter_map(|token| token.parent().and_then(ast::NameLike::cast)) + .filter_map(|node| match &node { + ast::NameLike::Name(name) => { + NameClass::classify(&sema, name).and_then(|class| match class { + NameClass::Definition(it) | NameClass::ConstReference(it) => Some(it), + NameClass::PatFieldShorthand { .. } => None, + }) } - Definition::Const(c) => { - let assoc = c.as_assoc_item(sema.db)?; - let name = assoc.name(sema.db)?; - let trait_ = assoc.containing_trait_or_trait_impl(sema.db)?; - impls_for_trait_item(&sema, trait_, name) - } - _ => return None, - }; - Some(navs) - }) - .flatten() - .collect(); + ast::NameLike::NameRef(name_ref) => NameRefClass::classify(&sema, name_ref) + .and_then(|class| match class { + NameRefClass::Definition(def) => Some(def), + NameRefClass::FieldShorthand { .. } + | NameRefClass::ExternCrateShorthand { .. } => None, + }), + ast::NameLike::Lifetime(_) => None, + }) + .unique() + .filter_map(|def| { + let navs = match def { + Definition::Trait(trait_) => impls_for_trait(&sema, trait_), + Definition::Adt(adt) => impls_for_ty(&sema, adt.ty(sema.db)), + Definition::TypeAlias(alias) => impls_for_ty(&sema, alias.ty(sema.db)), + Definition::BuiltinType(builtin) => impls_for_ty(&sema, builtin.ty(sema.db)), + Definition::Function(f) => { + let assoc = f.as_assoc_item(sema.db)?; + let name = assoc.name(sema.db)?; + let trait_ = assoc.containing_trait_or_trait_impl(sema.db)?; + impls_for_trait_item(&sema, trait_, name) + } + Definition::Const(c) => { + let assoc = c.as_assoc_item(sema.db)?; + let name = assoc.name(sema.db)?; + let trait_ = assoc.containing_trait_or_trait_impl(sema.db)?; + impls_for_trait_item(&sema, trait_, name) + } + _ => return None, + }; + Some(navs) + }) + .flatten() + .collect(); Some(RangeInfo { range, info: navs }) } diff --git a/crates/ide/src/highlight_related.rs b/crates/ide/src/highlight_related.rs index 7e545491f8e7..43e89a334bf5 100644 --- a/crates/ide/src/highlight_related.rs +++ b/crates/ide/src/highlight_related.rs @@ -100,10 +100,7 @@ fn highlight_closure_captures( .flat_map(|local| { let usages = Definition::Local(local) .usages(sema) - .set_scope(Some(SearchScope::file_range(FileRange { - file_id, - range: search_range, - }))) + .in_scope(&SearchScope::file_range(FileRange { file_id, range: search_range })) .include_self_refs() .all() .references @@ -139,7 +136,7 @@ fn highlight_references( .iter() .filter_map(|&d| { d.usages(sema) - .set_scope(Some(SearchScope::single_file(file_id))) + .in_scope(&SearchScope::single_file(file_id)) .include_self_refs() .all() .references @@ -183,7 +180,7 @@ fn highlight_references( .filter_map(|item| { Definition::from(item) .usages(sema) - .set_scope(Some(SearchScope::file_range(FileRange { + .set_scope(Some(&SearchScope::file_range(FileRange { file_id, range: trait_item_use_scope.text_range(), }))) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 5ef6ac948072..40659e6c2631 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -9,7 +9,7 @@ use either::Either; use hir::{db::DefDatabase, HasSource, LangItem, Semantics}; use ide_db::{ base_db::FileRange, - defs::{Definition, IdentClass, OperatorClass}, + defs::{Definition, IdentClass, NameRefClass, OperatorClass}, famous_defs::FamousDefs, helpers::pick_best_token, FxIndexSet, RootDatabase, @@ -186,7 +186,20 @@ fn hover_simple( // rendering poll is very confusing return None; } - Some(class.definitions().into_iter().zip(iter::once(node).cycle())) + if let IdentClass::NameRefClass(NameRefClass::ExternCrateShorthand { + decl, + .. + }) = class + { + return Some(vec![(Definition::ExternCrateDecl(decl), node)]); + } + Some( + class + .definitions() + .into_iter() + .zip(iter::once(node).cycle()) + .collect::>(), + ) }) .flatten() .unique_by(|&(def, _)| def) diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index ef33386a7e91..a33a6ee1816c 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -257,7 +257,7 @@ pub(super) fn keyword( let KeywordHint { description, keyword_mod, actions } = keyword_hints(sema, token, parent); let doc_owner = find_std_module(&famous_defs, &keyword_mod)?; - let docs = doc_owner.attrs(sema.db).docs()?; + let docs = doc_owner.docs(sema.db)?; let markup = process_markup( sema.db, Definition::Module(doc_owner), @@ -472,6 +472,7 @@ pub(super) fn definition( } Definition::GenericParam(it) => label_and_docs(db, it), Definition::Label(it) => return Some(Markup::fenced_block(&it.name(db).display(db))), + Definition::ExternCrateDecl(it) => label_and_docs(db, it), // FIXME: We should be able to show more info about these Definition::BuiltinAttr(it) => return render_builtin_attr(db, it), Definition::ToolModule(it) => return Some(Markup::fenced_block(&it.name(db))), @@ -620,7 +621,7 @@ where D: HasAttrs + HirDisplay, { let label = def.display(db).to_string(); - let docs = def.attrs(db).docs(); + let docs = def.docs(db); (label, docs) } @@ -645,7 +646,7 @@ where ) { format_to!(label, "{layout}"); } - let docs = def.attrs(db).docs(); + let docs = def.docs(db); (label, docs) } @@ -677,7 +678,7 @@ where ) { format_to!(label, "{layout}"); } - let docs = def.attrs(db).docs(); + let docs = def.docs(db); (label, docs) } @@ -696,7 +697,7 @@ where } else { def.display(db).to_string() }; - let docs = def.attrs(db).docs(); + let docs = def.docs(db); (label, docs) } @@ -727,14 +728,14 @@ fn builtin(famous_defs: &FamousDefs<'_, '_>, builtin: hir::BuiltinType) -> Optio // std exposes prim_{} modules with docstrings on the root to document the builtins let primitive_mod = format!("prim_{}", builtin.name().display(famous_defs.0.db)); let doc_owner = find_std_module(famous_defs, &primitive_mod)?; - let docs = doc_owner.attrs(famous_defs.0.db).docs()?; + let docs = doc_owner.docs(famous_defs.0.db)?; markup(Some(docs.into()), builtin.name().display(famous_defs.0.db).to_string(), None) } fn find_std_module(famous_defs: &FamousDefs<'_, '_>, name: &str) -> Option { let db = famous_defs.0.db; let std_crate = famous_defs.std()?; - let std_root_module = std_crate.root_module(db); + let std_root_module = std_crate.root_module(); std_root_module.children(db).find(|module| { module.name(db).map_or(false, |module| module.display(db).to_string() == name) }) diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 00e21433daae..ddc71dffa8a6 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -1616,6 +1616,9 @@ fn test_hover_extern_crate() { check( r#" //- /main.rs crate:main deps:std +//! Crate docs + +/// Decl docs! extern crate st$0d; //- /std/lib.rs crate:std //! Standard library for this test @@ -1624,23 +1627,32 @@ extern crate st$0d; //! abc123 "#, expect![[r#" - *std* + *std* - ```rust - extern crate std - ``` + ```rust + main + ``` - --- + ```rust + extern crate std + ``` - Standard library for this test + --- - Printed? - abc123 - "#]], + Decl docs! + + Standard library for this test + + Printed? + abc123 + "#]], ); check( r#" //- /main.rs crate:main deps:std +//! Crate docs + +/// Decl docs! extern crate std as ab$0c; //- /std/lib.rs crate:std //! Standard library for this test @@ -1649,19 +1661,25 @@ extern crate std as ab$0c; //! abc123 "#, expect![[r#" - *abc* + *abc* - ```rust - extern crate std - ``` + ```rust + main + ``` - --- + ```rust + extern crate std as abc + ``` - Standard library for this test + --- - Printed? - abc123 - "#]], + Decl docs! + + Standard library for this test + + Printed? + abc123 + "#]], ); } diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 0ad4c6c47e62..bf77d55d58e5 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -127,7 +127,7 @@ pub use ide_db::{ label::Label, line_index::{LineCol, LineIndex}, search::{ReferenceCategory, SearchScope}, - source_change::{FileSystemEdit, SourceChange}, + source_change::{FileSystemEdit, SnippetEdit, SourceChange}, symbol_index::Query, RootDatabase, SymbolKind, }; diff --git a/crates/ide/src/moniker.rs b/crates/ide/src/moniker.rs index d486a794e13b..17f3771b1a5a 100644 --- a/crates/ide/src/moniker.rs +++ b/crates/ide/src/moniker.rs @@ -177,6 +177,17 @@ pub(crate) fn def_to_moniker( }); } + // Qualify locals/parameters by their parent definition name. + if let Definition::Local(it) = def { + let parent_name = it.parent(db).name(db); + if let Some(name) = parent_name { + description.push(MonikerDescriptor { + name: name.display(db).to_string(), + desc: MonikerDescriptorKind::Method, + }); + } + } + let name_desc = match def { // These are handled by top-level guard (for performance). Definition::GenericParam(_) @@ -247,6 +258,10 @@ pub(crate) fn def_to_moniker( name: s.name(db).display(db).to_string(), desc: MonikerDescriptorKind::Meta, }, + Definition::ExternCrateDecl(m) => MonikerDescriptor { + name: m.name(db).display(db).to_string(), + desc: MonikerDescriptorKind::Namespace, + }, }; description.push(name_desc); diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs index c7abecb4f1e3..d1479dd1e584 100644 --- a/crates/ide/src/navigation_target.rs +++ b/crates/ide/src/navigation_target.rs @@ -102,7 +102,7 @@ impl NavigationTarget { full_range, SymbolKind::Module, ); - res.docs = module.attrs(db).docs(); + res.docs = module.docs(db); res.description = Some(module.display(db).to_string()); return res; } @@ -217,6 +217,7 @@ impl TryToNav for Definition { Definition::Trait(it) => it.try_to_nav(db), Definition::TraitAlias(it) => it.try_to_nav(db), Definition::TypeAlias(it) => it.try_to_nav(db), + Definition::ExternCrateDecl(it) => Some(it.try_to_nav(db)?), Definition::BuiltinType(_) => None, Definition::ToolModule(_) => None, Definition::BuiltinAttr(_) => None, @@ -375,6 +376,30 @@ impl TryToNav for hir::Impl { } } +impl TryToNav for hir::ExternCrateDecl { + fn try_to_nav(&self, db: &RootDatabase) -> Option { + let src = self.source(db)?; + let InFile { file_id, value } = src; + let focus = value + .rename() + .map_or_else(|| value.name_ref().map(Either::Left), |it| it.name().map(Either::Right)); + let (file_id, full_range, focus_range) = + orig_range_with_focus(db, file_id, value.syntax(), focus); + let mut res = NavigationTarget::from_syntax( + file_id, + self.alias_or_name(db).unwrap_or_else(|| self.name(db)).to_smol_str(), + focus_range, + full_range, + SymbolKind::Module, + ); + + res.docs = self.docs(db); + res.description = Some(self.display(db).to_string()); + res.container_name = container_name(db, *self); + Some(res) + } +} + impl TryToNav for hir::Field { fn try_to_nav(&self, db: &RootDatabase) -> Option { let src = self.source(db)?; diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index fdc5261ac38b..813f9ed943f2 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -74,7 +74,7 @@ pub(crate) fn find_all_refs( } }); let mut usages = - def.usages(sema).set_scope(search_scope.clone()).include_self_refs().all(); + def.usages(sema).set_scope(search_scope.as_ref()).include_self_refs().all(); if literal_search { retain_adt_literal_usages(&mut usages, def, sema); @@ -137,6 +137,9 @@ pub(crate) fn find_defs<'a>( NameRefClass::FieldShorthand { local_ref, field_ref: _ } => { Definition::Local(local_ref) } + NameRefClass::ExternCrateShorthand { decl, .. } => { + Definition::ExternCrateDecl(decl) + } } } ast::NameLike::Name(name) => match NameClass::classify(sema, &name)? { diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs index e10c46381022..dae8e71e8a09 100644 --- a/crates/ide/src/rename.rs +++ b/crates/ide/src/rename.rs @@ -145,7 +145,14 @@ fn find_definitions( if name .syntax() .parent() - .map_or(false, |it| ast::Rename::can_cast(it.kind())) => + .map_or(false, |it| ast::Rename::can_cast(it.kind())) + // FIXME: uncomment this once we resolve to usages to extern crate declarations + // && name + // .syntax() + // .ancestors() + // .nth(2) + // .map_or(true, |it| !ast::ExternCrate::can_cast(it.kind())) + => { bail!("Renaming aliases is currently unsupported") } @@ -165,7 +172,12 @@ fn find_definitions( NameRefClass::FieldShorthand { local_ref, field_ref: _ } => { Definition::Local(local_ref) } + NameRefClass::ExternCrateShorthand { decl, .. } => { + Definition::ExternCrateDecl(decl) + } }) + // FIXME: uncomment this once we resolve to usages to extern crate declarations + .filter(|def| !matches!(def, Definition::ExternCrateDecl(..))) .ok_or_else(|| format_err!("No references found at position")) .and_then(|def| { // if the name differs from the definitions name it has to be an alias @@ -367,7 +379,7 @@ mod tests { let mut file_id: Option = None; for edit in source_change.source_file_edits { file_id = Some(edit.0); - for indel in edit.1.into_iter() { + for indel in edit.1 .0.into_iter() { text_edit_builder.replace(indel.delete, indel.insert); } } @@ -895,14 +907,17 @@ mod foo$0; source_file_edits: { FileId( 1, - ): TextEdit { - indels: [ - Indel { - insert: "foo2", - delete: 4..7, - }, - ], - }, + ): ( + TextEdit { + indels: [ + Indel { + insert: "foo2", + delete: 4..7, + }, + ], + }, + None, + ), }, file_system_edits: [ MoveFile { @@ -944,24 +959,30 @@ use crate::foo$0::FooContent; source_file_edits: { FileId( 0, - ): TextEdit { - indels: [ - Indel { - insert: "quux", - delete: 8..11, - }, - ], - }, + ): ( + TextEdit { + indels: [ + Indel { + insert: "quux", + delete: 8..11, + }, + ], + }, + None, + ), FileId( 2, - ): TextEdit { - indels: [ - Indel { - insert: "quux", - delete: 11..14, - }, - ], - }, + ): ( + TextEdit { + indels: [ + Indel { + insert: "quux", + delete: 11..14, + }, + ], + }, + None, + ), }, file_system_edits: [ MoveFile { @@ -997,14 +1018,17 @@ mod fo$0o; source_file_edits: { FileId( 0, - ): TextEdit { - indels: [ - Indel { - insert: "foo2", - delete: 4..7, - }, - ], - }, + ): ( + TextEdit { + indels: [ + Indel { + insert: "foo2", + delete: 4..7, + }, + ], + }, + None, + ), }, file_system_edits: [ MoveDir { @@ -1047,14 +1071,17 @@ mod outer { mod fo$0o; } source_file_edits: { FileId( 0, - ): TextEdit { - indels: [ - Indel { - insert: "bar", - delete: 16..19, - }, - ], - }, + ): ( + TextEdit { + indels: [ + Indel { + insert: "bar", + delete: 16..19, + }, + ], + }, + None, + ), }, file_system_edits: [ MoveFile { @@ -1120,24 +1147,30 @@ pub mod foo$0; source_file_edits: { FileId( 0, - ): TextEdit { - indels: [ - Indel { - insert: "foo2", - delete: 27..30, - }, - ], - }, + ): ( + TextEdit { + indels: [ + Indel { + insert: "foo2", + delete: 27..30, + }, + ], + }, + None, + ), FileId( 1, - ): TextEdit { - indels: [ - Indel { - insert: "foo2", - delete: 8..11, - }, - ], - }, + ): ( + TextEdit { + indels: [ + Indel { + insert: "foo2", + delete: 8..11, + }, + ], + }, + None, + ), }, file_system_edits: [ MoveFile { @@ -1187,14 +1220,17 @@ mod quux; source_file_edits: { FileId( 0, - ): TextEdit { - indels: [ - Indel { - insert: "foo2", - delete: 4..7, - }, - ], - }, + ): ( + TextEdit { + indels: [ + Indel { + insert: "foo2", + delete: 4..7, + }, + ], + }, + None, + ), }, file_system_edits: [ MoveFile { @@ -1325,18 +1361,21 @@ pub fn baz() {} source_file_edits: { FileId( 0, - ): TextEdit { - indels: [ - Indel { - insert: "r#fn", - delete: 4..7, - }, - Indel { - insert: "r#fn", - delete: 22..25, - }, - ], - }, + ): ( + TextEdit { + indels: [ + Indel { + insert: "r#fn", + delete: 4..7, + }, + Indel { + insert: "r#fn", + delete: 22..25, + }, + ], + }, + None, + ), }, file_system_edits: [ MoveFile { @@ -1395,18 +1434,21 @@ pub fn baz() {} source_file_edits: { FileId( 0, - ): TextEdit { - indels: [ - Indel { - insert: "foo", - delete: 4..8, - }, - Indel { - insert: "foo", - delete: 23..27, - }, - ], - }, + ): ( + TextEdit { + indels: [ + Indel { + insert: "foo", + delete: 4..8, + }, + Indel { + insert: "foo", + delete: 23..27, + }, + ], + }, + None, + ), }, file_system_edits: [ MoveFile { @@ -2487,4 +2529,109 @@ fn main() { ", ) } + + #[test] + fn extern_crate() { + check_prepare( + r" +//- /lib.rs crate:main deps:foo +extern crate foo$0; +use foo as qux; +//- /foo.rs crate:foo +", + expect![[r#"No references found at position"#]], + ); + // FIXME: replace above check_prepare with this once we resolve to usages to extern crate declarations + // check( + // "bar", + // r" + // //- /lib.rs crate:main deps:foo + // extern crate foo$0; + // use foo as qux; + // //- /foo.rs crate:foo + // ", + // r" + // extern crate foo as bar; + // use bar as qux; + // ", + // ); + } + + #[test] + fn extern_crate_rename() { + check_prepare( + r" +//- /lib.rs crate:main deps:foo +extern crate foo as qux$0; +use qux as frob; +//- /foo.rs crate:foo +", + expect!["Renaming aliases is currently unsupported"], + ); + // FIXME: replace above check_prepare with this once we resolve to usages to extern crate + // declarations + // check( + // "bar", + // r" + // //- /lib.rs crate:main deps:foo + // extern crate foo as qux$0; + // use qux as frob; + // //- /foo.rs crate:foo + // ", + // r" + // extern crate foo as bar; + // use bar as frob; + // ", + // ); + } + + #[test] + fn extern_crate_self() { + check_prepare( + r" +extern crate self$0; +use self as qux; +", + expect!["No references found at position"], + ); + // FIXME: replace above check_prepare with this once we resolve to usages to extern crate declarations + // check( + // "bar", + // r" + // extern crate self$0; + // use self as qux; + // ", + // r" + // extern crate self as bar; + // use self as qux; + // ", + // ); + } + + #[test] + fn extern_crate_self_rename() { + check_prepare( + r" +//- /lib.rs crate:main deps:foo +extern crate self as qux$0; +use qux as frob; +//- /foo.rs crate:foo +", + expect!["Renaming aliases is currently unsupported"], + ); + // FIXME: replace above check_prepare with this once we resolve to usages to extern crate declarations + // check( + // "bar", + // r" + // //- /lib.rs crate:main deps:foo + // extern crate self as qux$0; + // use qux as frob; + // //- /foo.rs crate:foo + // ", + // r" + // extern crate self as bar; + // use bar as frob; + // ", + // ); + } } diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index 9fa0e6449b83..5f87a78551d2 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs @@ -232,7 +232,7 @@ fn find_related_tests( for def in defs { let defs = def .usages(sema) - .set_scope(search_scope.clone()) + .set_scope(search_scope.as_ref()) .all() .references .into_values() @@ -309,7 +309,7 @@ pub(crate) fn runnable_fn( ) -> Option { let name = def.name(sema.db).to_smol_str(); - let root = def.module(sema.db).krate().root_module(sema.db); + let root = def.module(sema.db).krate().root_module(); let kind = if name == "main" && def.module(sema.db) == root { RunnableKind::Bin diff --git a/crates/ide/src/ssr.rs b/crates/ide/src/ssr.rs index deaf3c9c416b..d8d81869a2f8 100644 --- a/crates/ide/src/ssr.rs +++ b/crates/ide/src/ssr.rs @@ -126,14 +126,17 @@ mod tests { source_file_edits: { FileId( 0, - ): TextEdit { - indels: [ - Indel { - insert: "3", - delete: 33..34, - }, - ], - }, + ): ( + TextEdit { + indels: [ + Indel { + insert: "3", + delete: 33..34, + }, + ], + }, + None, + ), }, file_system_edits: [], is_snippet: false, @@ -163,24 +166,30 @@ mod tests { source_file_edits: { FileId( 0, - ): TextEdit { - indels: [ - Indel { - insert: "3", - delete: 33..34, - }, - ], - }, + ): ( + TextEdit { + indels: [ + Indel { + insert: "3", + delete: 33..34, + }, + ], + }, + None, + ), FileId( 1, - ): TextEdit { - indels: [ - Indel { - insert: "3", - delete: 11..12, - }, - ], - }, + ): ( + TextEdit { + indels: [ + Indel { + insert: "3", + delete: 11..12, + }, + ], + }, + None, + ), }, file_system_edits: [], is_snippet: false, diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index 59e8300dcdbe..d8696198d3ba 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -88,7 +88,7 @@ pub struct StaticIndexedFile { fn all_modules(db: &dyn HirDatabase) -> Vec { let mut worklist: Vec<_> = - Crate::all(db).into_iter().map(|krate| krate.root_module(db)).collect(); + Crate::all(db).into_iter().map(|krate| krate.root_module()).collect(); let mut modules = Vec::new(); while let Some(module) = worklist.pop() { diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs index 3c40246a69d3..8e96bfa01ada 100644 --- a/crates/ide/src/syntax_highlighting/highlight.rs +++ b/crates/ide/src/syntax_highlighting/highlight.rs @@ -269,7 +269,26 @@ fn highlight_name_ref( h } - NameRefClass::FieldShorthand { .. } => SymbolKind::Field.into(), + NameRefClass::FieldShorthand { field_ref, .. } => { + highlight_def(sema, krate, field_ref.into()) + } + NameRefClass::ExternCrateShorthand { decl, krate: resolved_krate } => { + let mut h = HlTag::Symbol(SymbolKind::Module).into(); + + if resolved_krate != krate { + h |= HlMod::Library + } + let is_public = decl.visibility(db) == hir::Visibility::Public; + if is_public { + h |= HlMod::Public + } + let is_from_builtin_crate = resolved_krate.is_builtin(db); + if is_from_builtin_crate { + h |= HlMod::DefaultLibrary; + } + h |= HlMod::CrateRoot; + h + } }; h.tag = match name_ref.token_kind() { @@ -474,6 +493,14 @@ fn highlight_def( } h } + Definition::ExternCrateDecl(extern_crate) => { + let mut highlight = + Highlight::new(HlTag::Symbol(SymbolKind::Module)) | HlMod::CrateRoot; + if extern_crate.alias(db).is_none() { + highlight |= HlMod::Library; + } + highlight + } Definition::Label(_) => Highlight::new(HlTag::Symbol(SymbolKind::Label)), Definition::BuiltinAttr(_) => Highlight::new(HlTag::Symbol(SymbolKind::BuiltinAttr)), Definition::ToolModule(_) => Highlight::new(HlTag::Symbol(SymbolKind::ToolModule)), diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs index 901df147d32c..2657a641482a 100644 --- a/crates/ide/src/syntax_highlighting/inject.rs +++ b/crates/ide/src/syntax_highlighting/inject.rs @@ -288,7 +288,7 @@ fn find_doc_string_in_attr(attr: &hir::Attr, it: &ast::Attr) -> Option HlTag { let symbol = match def { - Definition::Module(_) => SymbolKind::Module, + Definition::Module(_) | Definition::ExternCrateDecl(_) => SymbolKind::Module, Definition::Function(_) => SymbolKind::Function, Definition::Adt(hir::Adt::Struct(_)) => SymbolKind::Struct, Definition::Adt(hir::Adt::Enum(_)) => SymbolKind::Enum, diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html b/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html index b15f7bca72b9..88a008796b37 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html @@ -44,5 +44,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .unresolved_reference { color: #FC5555; text-decoration: wavy underline; }

extern crate std;
-extern crate alloc as abc;
+extern crate alloc as abc;
+extern crate unresolved as definitely_unresolved;
 
\ No newline at end of file diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html b/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html index fd3b39855e20..2043752bc746 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html @@ -43,7 +43,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } -
extern crate self;
+
extern crate self;
 
 use crate;
 use self;
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html b/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
index c5fcec756808..06b66b302ae0 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
@@ -90,8 +90,18 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     }
 }
 
+#[rustc_builtin_macro]
+macro_rules! concat {}
+#[rustc_builtin_macro]
+macro_rules! include {}
+#[rustc_builtin_macro]
+macro_rules! format_args {}
+
+include!(concat!("foo/", "foo.rs"));
+
 fn main() {
-    println!("Hello, {}!", 92);
+    format_args!("Hello, {}!", 92);
     dont_color_me_braces!();
     noop!(noop!(1));
-}
\ No newline at end of file +} +
\ No newline at end of file diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html index dcac8eb73689..3ac8aa9cc9da 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html @@ -178,5 +178,5 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd toho!("{}fmt", 0); asm!("mov eax, {0}"); format_args!(concat!("{}"), "{}"); - format_args!("{} {} {} {} {} {}", backslash, format_args!("{}", 0), foo, "bar", toho!(), backslash); + format_args!("{} {} {} {} {} {}", backslash, format_args!("{}", 0), foo, "bar", toho!(), backslash); } \ No newline at end of file diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs index 696aa5900252..8749d355c85d 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs @@ -48,6 +48,7 @@ fn macros() { check_highlighting( r#" //- proc_macros: mirror +//- /lib.rs crate:lib proc_macros::mirror! { { ,i32 :x pub @@ -95,11 +96,23 @@ macro without_args { } } +#[rustc_builtin_macro] +macro_rules! concat {} +#[rustc_builtin_macro] +macro_rules! include {} +#[rustc_builtin_macro] +macro_rules! format_args {} + +include!(concat!("foo/", "foo.rs")); + fn main() { - println!("Hello, {}!", 92); + format_args!("Hello, {}!", 92); dont_color_me_braces!(); noop!(noop!(1)); } +//- /foo/foo.rs crate:foo +mod foo {} +use self::foo as bar; "#, expect_file!["./test_data/highlight_macros.html"], false, @@ -791,6 +804,7 @@ fn test_extern_crate() { //- /main.rs crate:main deps:std,alloc extern crate std; extern crate alloc as abc; +extern crate unresolved as definitely_unresolved; //- /std/lib.rs crate:std pub struct S; //- /alloc/lib.rs crate:alloc diff --git a/crates/mbe/src/expander.rs b/crates/mbe/src/expander.rs index 8e2181e977e1..f2d89d3efe5a 100644 --- a/crates/mbe/src/expander.rs +++ b/crates/mbe/src/expander.rs @@ -123,4 +123,14 @@ enum Fragment { /// proc-macro delimiter=none. As we later discovered, "none" delimiters are /// tricky to handle in the parser, and rustc doesn't handle those either. Expr(tt::TokenTree), + /// There are roughly two types of paths: paths in expression context, where a + /// separator `::` between an identifier and its following generic argument list + /// is mandatory, and paths in type context, where `::` can be omitted. + /// + /// Unlike rustc, we need to transform the parsed fragments back into tokens + /// during transcription. When the matched path fragment is a type-context path + /// and is trasncribed as an expression-context path, verbatim transcription + /// would cause a syntax error. We need to fix it up just before transcribing; + /// see `transcriber::fix_up_and_push_path_tt()`. + Path(tt::TokenTree), } diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs index 1a7b7eed2953..1471af98b75b 100644 --- a/crates/mbe/src/expander/matcher.rs +++ b/crates/mbe/src/expander/matcher.rs @@ -742,7 +742,11 @@ fn match_meta_var( is_2021: bool, ) -> ExpandResult> { let fragment = match kind { - MetaVarKind::Path => parser::PrefixEntryPoint::Path, + MetaVarKind::Path => { + return input + .expect_fragment(parser::PrefixEntryPoint::Path) + .map(|it| it.map(Fragment::Path)); + } MetaVarKind::Ty => parser::PrefixEntryPoint::Ty, MetaVarKind::Pat if is_2021 => parser::PrefixEntryPoint::PatTop, MetaVarKind::Pat => parser::PrefixEntryPoint::Pat, @@ -771,7 +775,7 @@ fn match_meta_var( .expect_fragment(parser::PrefixEntryPoint::Expr) .map(|tt| tt.map(Fragment::Expr)); } - _ => { + MetaVarKind::Ident | MetaVarKind::Tt | MetaVarKind::Lifetime | MetaVarKind::Literal => { let tt_result = match kind { MetaVarKind::Ident => input .expect_ident() @@ -799,7 +803,7 @@ fn match_meta_var( }) .map_err(|()| ExpandError::binding_error("expected literal")) } - _ => Err(ExpandError::UnexpectedToken), + _ => unreachable!(), }; return tt_result.map(|it| Some(Fragment::Tokens(it))).into(); } diff --git a/crates/mbe/src/expander/transcriber.rs b/crates/mbe/src/expander/transcriber.rs index 6161af185871..cdac2f1e3bb8 100644 --- a/crates/mbe/src/expander/transcriber.rs +++ b/crates/mbe/src/expander/transcriber.rs @@ -400,7 +400,8 @@ fn push_fragment(buf: &mut Vec, fragment: Fragment) { } buf.push(tt.into()) } - Fragment::Tokens(tt) | Fragment::Expr(tt) => buf.push(tt), + Fragment::Path(tt::TokenTree::Subtree(tt)) => fix_up_and_push_path_tt(buf, tt), + Fragment::Tokens(tt) | Fragment::Expr(tt) | Fragment::Path(tt) => buf.push(tt), } } @@ -411,6 +412,45 @@ fn push_subtree(buf: &mut Vec, tt: tt::Subtree) { } } +/// Inserts the path separator `::` between an identifier and its following generic +/// argument list, and then pushes into the buffer. See [`Fragment::Path`] for why +/// we need this fixup. +fn fix_up_and_push_path_tt(buf: &mut Vec, subtree: tt::Subtree) { + stdx::always!(matches!(subtree.delimiter.kind, tt::DelimiterKind::Invisible)); + let mut prev_was_ident = false; + // Note that we only need to fix up the top-level `TokenTree`s because the + // context of the paths in the descendant `Subtree`s won't be changed by the + // mbe transcription. + for tt in subtree.token_trees { + if prev_was_ident { + // Pedantically, `(T) -> U` in `FnOnce(T) -> U` is treated as a generic + // argument list and thus needs `::` between it and `FnOnce`. However in + // today's Rust this type of path *semantically* cannot appear as a + // top-level expression-context path, so we can safely ignore it. + if let tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: '<', .. })) = tt { + buf.push( + tt::Leaf::Punct(tt::Punct { + char: ':', + spacing: tt::Spacing::Joint, + span: tt::Span::unspecified(), + }) + .into(), + ); + buf.push( + tt::Leaf::Punct(tt::Punct { + char: ':', + spacing: tt::Spacing::Alone, + span: tt::Span::unspecified(), + }) + .into(), + ); + } + } + prev_was_ident = matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Ident(_))); + buf.push(tt); + } +} + /// Handles `${count(t, depth)}`. `our_depth` is the recursion depth and `count_depth` is the depth /// defined by the metavar expression. fn count( diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs index 665bce474a69..9d886a1c979a 100644 --- a/crates/mbe/src/lib.rs +++ b/crates/mbe/src/lib.rs @@ -28,7 +28,6 @@ use crate::{ tt_iter::TtIter, }; -// FIXME: we probably should re-think `token_tree_to_syntax_node` interfaces pub use self::tt::{Delimiter, DelimiterKind, Punct}; pub use ::parser::TopEntryPoint; diff --git a/crates/mbe/src/token_map.rs b/crates/mbe/src/token_map.rs index 9b2df89f9c71..73a27df5dbca 100644 --- a/crates/mbe/src/token_map.rs +++ b/crates/mbe/src/token_map.rs @@ -117,4 +117,8 @@ impl TokenMap { TokenTextRange::Delimiter(_) => None, }) } + + pub fn filter(&mut self, id: impl Fn(tt::TokenId) -> bool) { + self.entries.retain(|&(tid, _)| id(tid)); + } } diff --git a/crates/parser/src/grammar.rs b/crates/parser/src/grammar.rs index a868419821d8..333318f53b7e 100644 --- a/crates/parser/src/grammar.rs +++ b/crates/parser/src/grammar.rs @@ -165,6 +165,40 @@ pub(crate) mod entry { } m.complete(p, ERROR); } + + pub(crate) fn eager_macro_input(p: &mut Parser<'_>) { + let m = p.start(); + + let closing_paren_kind = match p.current() { + T!['{'] => T!['}'], + T!['('] => T![')'], + T!['['] => T![']'], + _ => { + p.error("expected `{`, `[`, `(`"); + while !p.at(EOF) { + p.bump_any(); + } + m.complete(p, ERROR); + return; + } + }; + p.bump_any(); + while !p.at(EOF) && !p.at(closing_paren_kind) { + expressions::expr(p); + if !p.at(EOF) && !p.at(closing_paren_kind) { + p.expect(T![,]); + } + } + p.expect(closing_paren_kind); + if p.at(EOF) { + m.complete(p, MACRO_EAGER_INPUT); + return; + } + while !p.at(EOF) { + p.bump_any(); + } + m.complete(p, ERROR); + } } } diff --git a/crates/parser/src/grammar/items.rs b/crates/parser/src/grammar/items.rs index 1c056819f4b7..4e850b1f74df 100644 --- a/crates/parser/src/grammar/items.rs +++ b/crates/parser/src/grammar/items.rs @@ -328,9 +328,6 @@ fn macro_rules(p: &mut Parser<'_>, m: Marker) { p.bump_remap(T![macro_rules]); p.expect(T![!]); - if p.at(IDENT) { - name(p); - } // Special-case `macro_rules! try`. // This is a hack until we do proper edition support @@ -340,6 +337,8 @@ fn macro_rules(p: &mut Parser<'_>, m: Marker) { let m = p.start(); p.bump_remap(IDENT); m.complete(p, NAME); + } else { + name(p); } match p.current() { diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index 1aba1f7674ff..c155e8aaf67b 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -75,6 +75,8 @@ pub enum TopEntryPoint { /// Edge case -- macros generally don't expand to attributes, with the /// exception of `cfg_attr` which does! MetaItem, + /// Edge case 2 -- eager macros expand their input to a delimited list of comma separated expressions + MacroEagerInput, } impl TopEntryPoint { @@ -87,6 +89,7 @@ impl TopEntryPoint { TopEntryPoint::Type => grammar::entry::top::type_, TopEntryPoint::Expr => grammar::entry::top::expr, TopEntryPoint::MetaItem => grammar::entry::top::meta_item, + TopEntryPoint::MacroEagerInput => grammar::entry::top::eager_macro_input, }; let mut p = parser::Parser::new(input); entry_point(&mut p); diff --git a/crates/parser/src/shortcuts.rs b/crates/parser/src/shortcuts.rs index 6e3ae656b025..53cdad64992c 100644 --- a/crates/parser/src/shortcuts.rs +++ b/crates/parser/src/shortcuts.rs @@ -223,7 +223,8 @@ fn n_attached_trivias<'a>( ) -> usize { match kind { CONST | ENUM | FN | IMPL | MACRO_CALL | MACRO_DEF | MACRO_RULES | MODULE | RECORD_FIELD - | STATIC | STRUCT | TRAIT | TUPLE_FIELD | TYPE_ALIAS | UNION | USE | VARIANT => { + | STATIC | STRUCT | TRAIT | TUPLE_FIELD | TYPE_ALIAS | UNION | USE | VARIANT + | EXTERN_CRATE => { let mut res = 0; let mut trivias = trivias.enumerate().peekable(); diff --git a/crates/parser/src/syntax_kind/generated.rs b/crates/parser/src/syntax_kind/generated.rs index a8fbcfacf7ec..48f407623d83 100644 --- a/crates/parser/src/syntax_kind/generated.rs +++ b/crates/parser/src/syntax_kind/generated.rs @@ -262,6 +262,7 @@ pub enum SyntaxKind { TYPE_BOUND_LIST, MACRO_ITEMS, MACRO_STMTS, + MACRO_EAGER_INPUT, #[doc(hidden)] __LAST, } diff --git a/crates/proc-macro-srv/src/server.rs b/crates/proc-macro-srv/src/server.rs index 1980d4c78bbe..fe18451d3848 100644 --- a/crates/proc-macro-srv/src/server.rs +++ b/crates/proc-macro-srv/src/server.rs @@ -17,7 +17,10 @@ use token_stream::TokenStreamBuilder; mod symbol; pub use symbol::*; -use std::ops::{Bound, Range}; +use std::{ + iter, + ops::{Bound, Range}, +}; use crate::tt; @@ -80,9 +83,7 @@ impl server::TokenStream for RustAnalyzer { stream.is_empty() } fn from_str(&mut self, src: &str) -> Self::TokenStream { - use std::str::FromStr; - - Self::TokenStream::from_str(src).expect("cannot parse string") + src.parse().expect("cannot parse string") } fn to_string(&mut self, stream: &Self::TokenStream) -> String { stream.to_string() @@ -101,7 +102,7 @@ impl server::TokenStream for RustAnalyzer { }, }; let tree = TokenTree::from(group); - Self::TokenStream::from_iter(vec![tree]) + Self::TokenStream::from_iter(iter::once(tree)) } bridge::TokenTree::Ident(ident) => { @@ -111,7 +112,7 @@ impl server::TokenStream for RustAnalyzer { let ident: tt::Ident = tt::Ident { text, span: ident.span }; let leaf = tt::Leaf::from(ident); let tree = TokenTree::from(leaf); - Self::TokenStream::from_iter(vec![tree]) + Self::TokenStream::from_iter(iter::once(tree)) } bridge::TokenTree::Literal(literal) => { @@ -123,7 +124,7 @@ impl server::TokenStream for RustAnalyzer { let literal = tt::Literal { text, span: literal.0.span }; let leaf = tt::Leaf::from(literal); let tree = TokenTree::from(leaf); - Self::TokenStream::from_iter(vec![tree]) + Self::TokenStream::from_iter(iter::once(tree)) } bridge::TokenTree::Punct(p) => { @@ -134,7 +135,7 @@ impl server::TokenStream for RustAnalyzer { }; let leaf = tt::Leaf::from(punct); let tree = TokenTree::from(leaf); - Self::TokenStream::from_iter(vec![tree]) + Self::TokenStream::from_iter(iter::once(tree)) } } } @@ -355,12 +356,12 @@ impl server::Server for RustAnalyzer { } fn intern_symbol(ident: &str) -> Self::Symbol { - // FIXME: should be self.interner once the proc-macro api allows is + // FIXME: should be `self.interner` once the proc-macro api allows it. Symbol::intern(&SYMBOL_INTERNER, &::tt::SmolStr::from(ident)) } fn with_symbol_string(symbol: &Self::Symbol, f: impl FnOnce(&str)) { - // FIXME: should be self.interner once the proc-macro api allows is + // FIXME: should be `self.interner` once the proc-macro api allows it. f(symbol.text(&SYMBOL_INTERNER).as_str()) } } diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index 33d7b5ed8789..f446a7c05966 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -128,7 +128,7 @@ impl flags::AnalysisStats { let mut visited_modules = FxHashSet::default(); let mut visit_queue = Vec::new(); for krate in krates { - let module = krate.root_module(db); + let module = krate.root_module(); let file_id = module.definition_source_file_id(db); let file_id = file_id.original_file(db); let source_root = db.file_source_root(file_id); diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs index 0db5fb4740ea..8541be715a93 100644 --- a/crates/rust-analyzer/src/cli/diagnostics.rs +++ b/crates/rust-analyzer/src/cli/diagnostics.rs @@ -80,7 +80,7 @@ impl flags::Diagnostics { fn all_modules(db: &dyn HirDatabase) -> Vec { let mut worklist: Vec<_> = - Crate::all(db).into_iter().map(|krate| krate.root_module(db)).collect(); + Crate::all(db).into_iter().map(|krate| krate.root_module()).collect(); let mut modules = Vec::new(); while let Some(module) = worklist.pop() { diff --git a/crates/rust-analyzer/src/cli/run_tests.rs b/crates/rust-analyzer/src/cli/run_tests.rs index b63a266a57ae..e1704199151a 100644 --- a/crates/rust-analyzer/src/cli/run_tests.rs +++ b/crates/rust-analyzer/src/cli/run_tests.rs @@ -76,7 +76,7 @@ fn all_modules(db: &dyn HirDatabase) -> Vec { let mut worklist: Vec<_> = Crate::all(db) .into_iter() .filter(|x| x.origin(db).is_local()) - .map(|krate| krate.root_module(db)) + .map(|krate| krate.root_module()) .collect(); let mut modules = Vec::new(); diff --git a/crates/rust-analyzer/src/cli/scip.rs b/crates/rust-analyzer/src/cli/scip.rs index 4579aca30219..44337f955e5c 100644 --- a/crates/rust-analyzer/src/cli/scip.rs +++ b/crates/rust-analyzer/src/cli/scip.rs @@ -416,6 +416,44 @@ pub mod module { ); } + #[test] + fn symbol_for_param() { + check_symbol( + r#" +//- /lib.rs crate:main deps:foo +use foo::example_mod::func; +fn main() { + func(42); +} +//- /foo/lib.rs crate:foo@0.1.0,https://a.b/foo.git library +pub mod example_mod { + pub fn func(x$0: usize) {} +} +"#, + "rust-analyzer cargo foo 0.1.0 example_mod/func().(x)", + ); + } + + #[test] + fn symbol_for_closure_param() { + check_symbol( + r#" +//- /lib.rs crate:main deps:foo +use foo::example_mod::func; +fn main() { + func(); +} +//- /foo/lib.rs crate:foo@0.1.0,https://a.b/foo.git library +pub mod example_mod { + pub fn func() { + let f = |x$0: usize| {}; + } +} +"#, + "rust-analyzer cargo foo 0.1.0 example_mod/func().(x)", + ); + } + #[test] fn local_symbol_for_local() { check_symbol( diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index aad74b7466a2..5f1f731cffb3 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -353,7 +353,8 @@ pub(crate) fn handle_on_type_formatting( }; // This should be a single-file edit - let (_, text_edit) = edit.source_file_edits.into_iter().next().unwrap(); + let (_, (text_edit, snippet_edit)) = edit.source_file_edits.into_iter().next().unwrap(); + stdx::never!(snippet_edit.is_none(), "on type formatting shouldn't use structured snippets"); let change = to_proto::snippet_text_edit_vec(&line_index, edit.is_snippet, text_edit); Ok(Some(change)) diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index 18d9151d4aab..0a2bb8224757 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -114,6 +114,11 @@ impl GlobalState { if self.proc_macro_clients.iter().any(|it| it.is_err()) { status.health = lsp_ext::Health::Warning; message.push_str("Failed to spawn one or more proc-macro servers.\n\n"); + for err in self.proc_macro_clients.iter() { + if let Err(err) = err { + format_to!(message, "- {err}\n"); + } + } } if !self.config.cargo_autoreload() && self.is_quiescent() diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 7a89533a5e92..7b32180e3eb8 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs @@ -10,8 +10,8 @@ use ide::{ CompletionItemKind, CompletionRelevance, Documentation, FileId, FileRange, FileSystemEdit, Fold, FoldKind, Highlight, HlMod, HlOperator, HlPunct, HlRange, HlTag, Indel, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayKind, Markup, NavigationTarget, ReferenceCategory, - RenameError, Runnable, Severity, SignatureHelp, SourceChange, StructureNodeKind, SymbolKind, - TextEdit, TextRange, TextSize, + RenameError, Runnable, Severity, SignatureHelp, SnippetEdit, SourceChange, StructureNodeKind, + SymbolKind, TextEdit, TextRange, TextSize, }; use itertools::Itertools; use serde_json::to_value; @@ -22,7 +22,7 @@ use crate::{ config::{CallInfoConfig, Config}, global_state::GlobalStateSnapshot, line_index::{LineEndings, LineIndex, PositionEncoding}, - lsp_ext, + lsp_ext::{self, SnippetTextEdit}, lsp_utils::invalid_params_error, semantic_tokens::{self, standard_fallback_type}, }; @@ -885,16 +885,136 @@ fn outside_workspace_annotation_id() -> String { String::from("OutsideWorkspace") } +fn merge_text_and_snippet_edits( + line_index: &LineIndex, + edit: TextEdit, + snippet_edit: SnippetEdit, +) -> Vec { + let mut edits: Vec = vec![]; + let mut snippets = snippet_edit.into_edit_ranges().into_iter().peekable(); + let mut text_edits = edit.into_iter(); + + while let Some(current_indel) = text_edits.next() { + let new_range = { + let insert_len = + TextSize::try_from(current_indel.insert.len()).unwrap_or(TextSize::from(u32::MAX)); + TextRange::at(current_indel.delete.start(), insert_len) + }; + + // insert any snippets before the text edit + for (snippet_index, snippet_range) in + snippets.take_while_ref(|(_, range)| range.end() < new_range.start()) + { + let snippet_range = if !stdx::always!( + snippet_range.is_empty(), + "placeholder range {:?} is before current text edit range {:?}", + snippet_range, + new_range + ) { + // only possible for tabstops, so make sure it's an empty/insert range + TextRange::empty(snippet_range.start()) + } else { + snippet_range + }; + + let range = range(&line_index, snippet_range); + let new_text = format!("${snippet_index}"); + + edits.push(SnippetTextEdit { + range, + new_text, + insert_text_format: Some(lsp_types::InsertTextFormat::SNIPPET), + annotation_id: None, + }) + } + + if snippets.peek().is_some_and(|(_, range)| new_range.intersect(*range).is_some()) { + // at least one snippet edit intersects this text edit, + // so gather all of the edits that intersect this text edit + let mut all_snippets = snippets + .take_while_ref(|(_, range)| new_range.intersect(*range).is_some()) + .collect_vec(); + + // ensure all of the ranges are wholly contained inside of the new range + all_snippets.retain(|(_, range)| { + stdx::always!( + new_range.contains_range(*range), + "found placeholder range {:?} which wasn't fully inside of text edit's new range {:?}", range, new_range + ) + }); + + let mut text_edit = text_edit(line_index, current_indel); + + // escape out snippet text + stdx::replace(&mut text_edit.new_text, '\\', r"\\"); + stdx::replace(&mut text_edit.new_text, '$', r"\$"); + + // ...and apply! + for (index, range) in all_snippets.iter().rev() { + let start = (range.start() - new_range.start()).into(); + let end = (range.end() - new_range.start()).into(); + + if range.is_empty() { + text_edit.new_text.insert_str(start, &format!("${index}")); + } else { + text_edit.new_text.insert(end, '}'); + text_edit.new_text.insert_str(start, &format!("${{{index}:")); + } + } + + edits.push(SnippetTextEdit { + range: text_edit.range, + new_text: text_edit.new_text, + insert_text_format: Some(lsp_types::InsertTextFormat::SNIPPET), + annotation_id: None, + }) + } else { + // snippet edit was beyond the current one + // since it wasn't consumed, it's available for the next pass + edits.push(snippet_text_edit(line_index, false, current_indel)); + } + } + + // insert any remaining tabstops + edits.extend(snippets.map(|(snippet_index, snippet_range)| { + let snippet_range = if !stdx::always!( + snippet_range.is_empty(), + "found placeholder snippet {:?} without a text edit", + snippet_range + ) { + TextRange::empty(snippet_range.start()) + } else { + snippet_range + }; + + let range = range(&line_index, snippet_range); + let new_text = format!("${snippet_index}"); + + SnippetTextEdit { + range, + new_text, + insert_text_format: Some(lsp_types::InsertTextFormat::SNIPPET), + annotation_id: None, + } + })); + + edits +} + pub(crate) fn snippet_text_document_edit( snap: &GlobalStateSnapshot, is_snippet: bool, file_id: FileId, edit: TextEdit, + snippet_edit: Option, ) -> Cancellable { let text_document = optional_versioned_text_document_identifier(snap, file_id); let line_index = snap.file_line_index(file_id)?; - let mut edits: Vec<_> = - edit.into_iter().map(|it| snippet_text_edit(&line_index, is_snippet, it)).collect(); + let mut edits = if let Some(snippet_edit) = snippet_edit { + merge_text_and_snippet_edits(&line_index, edit, snippet_edit) + } else { + edit.into_iter().map(|it| snippet_text_edit(&line_index, is_snippet, it)).collect() + }; if snap.analysis.is_library_file(file_id)? && snap.config.change_annotation_support() { for edit in &mut edits { @@ -974,8 +1094,14 @@ pub(crate) fn snippet_workspace_edit( let ops = snippet_text_document_ops(snap, op)?; document_changes.extend_from_slice(&ops); } - for (file_id, edit) in source_change.source_file_edits { - let edit = snippet_text_document_edit(snap, source_change.is_snippet, file_id, edit)?; + for (file_id, (edit, snippet_edit)) in source_change.source_file_edits { + let edit = snippet_text_document_edit( + snap, + source_change.is_snippet, + file_id, + edit, + snippet_edit, + )?; document_changes.push(lsp_ext::SnippetDocumentChangeOperation::Edit(edit)); } let mut workspace_edit = lsp_ext::SnippetWorkspaceEdit { @@ -1414,7 +1540,9 @@ pub(crate) fn rename_error(err: RenameError) -> crate::LspError { #[cfg(test)] mod tests { + use expect_test::{expect, Expect}; use ide::{Analysis, FilePosition}; + use ide_db::source_change::Snippet; use test_utils::extract_offset; use triomphe::Arc; @@ -1484,6 +1612,481 @@ fn bar(_: usize) {} assert!(!docs.contains("use crate::bar")); } + fn check_rendered_snippets(edit: TextEdit, snippets: SnippetEdit, expect: Expect) { + let text = r#"/* place to put all ranges in */"#; + let line_index = LineIndex { + index: Arc::new(ide::LineIndex::new(text)), + endings: LineEndings::Unix, + encoding: PositionEncoding::Utf8, + }; + + let res = merge_text_and_snippet_edits(&line_index, edit, snippets); + expect.assert_debug_eq(&res); + } + + #[test] + fn snippet_rendering_only_tabstops() { + let edit = TextEdit::builder().finish(); + let snippets = SnippetEdit::new(vec![ + Snippet::Tabstop(0.into()), + Snippet::Tabstop(0.into()), + Snippet::Tabstop(1.into()), + Snippet::Tabstop(1.into()), + ]); + + check_rendered_snippets( + edit, + snippets, + expect![[r#" + [ + SnippetTextEdit { + range: Range { + start: Position { + line: 0, + character: 0, + }, + end: Position { + line: 0, + character: 0, + }, + }, + new_text: "$1", + insert_text_format: Some( + Snippet, + ), + annotation_id: None, + }, + SnippetTextEdit { + range: Range { + start: Position { + line: 0, + character: 0, + }, + end: Position { + line: 0, + character: 0, + }, + }, + new_text: "$2", + insert_text_format: Some( + Snippet, + ), + annotation_id: None, + }, + SnippetTextEdit { + range: Range { + start: Position { + line: 0, + character: 1, + }, + end: Position { + line: 0, + character: 1, + }, + }, + new_text: "$3", + insert_text_format: Some( + Snippet, + ), + annotation_id: None, + }, + SnippetTextEdit { + range: Range { + start: Position { + line: 0, + character: 1, + }, + end: Position { + line: 0, + character: 1, + }, + }, + new_text: "$0", + insert_text_format: Some( + Snippet, + ), + annotation_id: None, + }, + ] + "#]], + ); + } + + #[test] + fn snippet_rendering_only_text_edits() { + let mut edit = TextEdit::builder(); + edit.insert(0.into(), "abc".to_owned()); + edit.insert(3.into(), "def".to_owned()); + let edit = edit.finish(); + let snippets = SnippetEdit::new(vec![]); + + check_rendered_snippets( + edit, + snippets, + expect![[r#" + [ + SnippetTextEdit { + range: Range { + start: Position { + line: 0, + character: 0, + }, + end: Position { + line: 0, + character: 0, + }, + }, + new_text: "abc", + insert_text_format: None, + annotation_id: None, + }, + SnippetTextEdit { + range: Range { + start: Position { + line: 0, + character: 3, + }, + end: Position { + line: 0, + character: 3, + }, + }, + new_text: "def", + insert_text_format: None, + annotation_id: None, + }, + ] + "#]], + ); + } + + #[test] + fn snippet_rendering_tabstop_after_text_edit() { + let mut edit = TextEdit::builder(); + edit.insert(0.into(), "abc".to_owned()); + let edit = edit.finish(); + let snippets = SnippetEdit::new(vec![Snippet::Tabstop(7.into())]); + + check_rendered_snippets( + edit, + snippets, + expect![[r#" + [ + SnippetTextEdit { + range: Range { + start: Position { + line: 0, + character: 0, + }, + end: Position { + line: 0, + character: 0, + }, + }, + new_text: "abc", + insert_text_format: None, + annotation_id: None, + }, + SnippetTextEdit { + range: Range { + start: Position { + line: 0, + character: 7, + }, + end: Position { + line: 0, + character: 7, + }, + }, + new_text: "$0", + insert_text_format: Some( + Snippet, + ), + annotation_id: None, + }, + ] + "#]], + ); + } + + #[test] + fn snippet_rendering_tabstops_before_text_edit() { + let mut edit = TextEdit::builder(); + edit.insert(2.into(), "abc".to_owned()); + let edit = edit.finish(); + let snippets = + SnippetEdit::new(vec![Snippet::Tabstop(0.into()), Snippet::Tabstop(0.into())]); + + check_rendered_snippets( + edit, + snippets, + expect![[r#" + [ + SnippetTextEdit { + range: Range { + start: Position { + line: 0, + character: 0, + }, + end: Position { + line: 0, + character: 0, + }, + }, + new_text: "$1", + insert_text_format: Some( + Snippet, + ), + annotation_id: None, + }, + SnippetTextEdit { + range: Range { + start: Position { + line: 0, + character: 0, + }, + end: Position { + line: 0, + character: 0, + }, + }, + new_text: "$0", + insert_text_format: Some( + Snippet, + ), + annotation_id: None, + }, + SnippetTextEdit { + range: Range { + start: Position { + line: 0, + character: 2, + }, + end: Position { + line: 0, + character: 2, + }, + }, + new_text: "abc", + insert_text_format: None, + annotation_id: None, + }, + ] + "#]], + ); + } + + #[test] + fn snippet_rendering_tabstops_between_text_edits() { + let mut edit = TextEdit::builder(); + edit.insert(0.into(), "abc".to_owned()); + edit.insert(7.into(), "abc".to_owned()); + let edit = edit.finish(); + let snippets = + SnippetEdit::new(vec![Snippet::Tabstop(4.into()), Snippet::Tabstop(4.into())]); + + check_rendered_snippets( + edit, + snippets, + expect![[r#" + [ + SnippetTextEdit { + range: Range { + start: Position { + line: 0, + character: 0, + }, + end: Position { + line: 0, + character: 0, + }, + }, + new_text: "abc", + insert_text_format: None, + annotation_id: None, + }, + SnippetTextEdit { + range: Range { + start: Position { + line: 0, + character: 4, + }, + end: Position { + line: 0, + character: 4, + }, + }, + new_text: "$1", + insert_text_format: Some( + Snippet, + ), + annotation_id: None, + }, + SnippetTextEdit { + range: Range { + start: Position { + line: 0, + character: 4, + }, + end: Position { + line: 0, + character: 4, + }, + }, + new_text: "$0", + insert_text_format: Some( + Snippet, + ), + annotation_id: None, + }, + SnippetTextEdit { + range: Range { + start: Position { + line: 0, + character: 7, + }, + end: Position { + line: 0, + character: 7, + }, + }, + new_text: "abc", + insert_text_format: None, + annotation_id: None, + }, + ] + "#]], + ); + } + + #[test] + fn snippet_rendering_multiple_tabstops_in_text_edit() { + let mut edit = TextEdit::builder(); + edit.insert(0.into(), "abcdefghijkl".to_owned()); + let edit = edit.finish(); + let snippets = SnippetEdit::new(vec![ + Snippet::Tabstop(0.into()), + Snippet::Tabstop(5.into()), + Snippet::Tabstop(12.into()), + ]); + + check_rendered_snippets( + edit, + snippets, + expect![[r#" + [ + SnippetTextEdit { + range: Range { + start: Position { + line: 0, + character: 0, + }, + end: Position { + line: 0, + character: 0, + }, + }, + new_text: "$1abcde$2fghijkl$0", + insert_text_format: Some( + Snippet, + ), + annotation_id: None, + }, + ] + "#]], + ); + } + + #[test] + fn snippet_rendering_multiple_placeholders_in_text_edit() { + let mut edit = TextEdit::builder(); + edit.insert(0.into(), "abcdefghijkl".to_owned()); + let edit = edit.finish(); + let snippets = SnippetEdit::new(vec![ + Snippet::Placeholder(TextRange::new(0.into(), 3.into())), + Snippet::Placeholder(TextRange::new(5.into(), 7.into())), + Snippet::Placeholder(TextRange::new(10.into(), 12.into())), + ]); + + check_rendered_snippets( + edit, + snippets, + expect![[r#" + [ + SnippetTextEdit { + range: Range { + start: Position { + line: 0, + character: 0, + }, + end: Position { + line: 0, + character: 0, + }, + }, + new_text: "${1:abc}de${2:fg}hij${0:kl}", + insert_text_format: Some( + Snippet, + ), + annotation_id: None, + }, + ] + "#]], + ); + } + + #[test] + fn snippet_rendering_escape_snippet_bits() { + // only needed for snippet formats + let mut edit = TextEdit::builder(); + edit.insert(0.into(), r"abc\def$".to_owned()); + edit.insert(8.into(), r"ghi\jkl$".to_owned()); + let edit = edit.finish(); + let snippets = + SnippetEdit::new(vec![Snippet::Placeholder(TextRange::new(0.into(), 3.into()))]); + + check_rendered_snippets( + edit, + snippets, + expect![[r#" + [ + SnippetTextEdit { + range: Range { + start: Position { + line: 0, + character: 0, + }, + end: Position { + line: 0, + character: 0, + }, + }, + new_text: "${0:abc}\\\\def\\$", + insert_text_format: Some( + Snippet, + ), + annotation_id: None, + }, + SnippetTextEdit { + range: Range { + start: Position { + line: 0, + character: 8, + }, + end: Position { + line: 0, + character: 8, + }, + }, + new_text: "ghi\\jkl$", + insert_text_format: None, + annotation_id: None, + }, + ] + "#]], + ); + } + // `Url` is not able to parse windows paths on unix machines. #[test] #[cfg(target_os = "windows")] diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram index b096c9974489..138ddd208979 100644 --- a/crates/syntax/rust.ungram +++ b/crates/syntax/rust.ungram @@ -72,6 +72,12 @@ TokenTree = MacroItems = Item* +MacroEagerInput = + '(' (Expr (',' Expr)* ','?)? ')' +| '{' (Expr (',' Expr)* ','?)? '}' +| '[' (Expr (',' Expr)* ','?)? ']' + + MacroStmts = statements:Stmt* Expr? diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs index 606804aea25f..a150d9e6c07d 100644 --- a/crates/syntax/src/ast/edit_in_place.rs +++ b/crates/syntax/src/ast/edit_in_place.rs @@ -380,6 +380,26 @@ impl Removable for ast::UseTree { } impl ast::UseTree { + /// Deletes the usetree node represented by the input. Recursively removes parents, including use nodes that become empty. + pub fn remove_recursive(self) { + let parent = self.syntax().parent(); + + self.remove(); + + if let Some(u) = parent.clone().and_then(ast::Use::cast) { + if u.use_tree().is_none() { + u.remove(); + } + } else if let Some(u) = parent.and_then(ast::UseTreeList::cast) { + if u.use_trees().next().is_none() { + let parent = u.syntax().parent().and_then(ast::UseTree::cast); + if let Some(u) = parent { + u.remove_recursive(); + } + } + } + } + pub fn get_or_create_use_tree_list(&self) -> ast::UseTreeList { match self.use_tree_list() { Some(it) => it, @@ -487,6 +507,22 @@ impl Removable for ast::Use { } } } + let prev_ws = self + .syntax() + .prev_sibling_or_token() + .and_then(|it| it.into_token()) + .and_then(ast::Whitespace::cast); + if let Some(prev_ws) = prev_ws { + let ws_text = prev_ws.syntax().text(); + let prev_newline = ws_text.rfind('\n').map(|x| x + 1).unwrap_or(0); + let rest = &ws_text[0..prev_newline]; + if rest.is_empty() { + ted::remove(prev_ws.syntax()); + } else { + ted::replace(prev_ws.syntax(), make::tokens::whitespace(rest)); + } + } + ted::remove(self.syntax()); } } diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index e520801ea2ed..0b27faa535da 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -197,6 +197,20 @@ pub struct MacroItems { impl ast::HasModuleItem for MacroItems {} impl MacroItems {} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct MacroEagerInput { + pub(crate) syntax: SyntaxNode, +} +impl MacroEagerInput { + pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) } + pub fn exprs(&self) -> AstChildren { support::children(&self.syntax) } + pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } + pub fn l_curly_token(&self) -> Option { support::token(&self.syntax, T!['{']) } + pub fn r_curly_token(&self) -> Option { support::token(&self.syntax, T!['}']) } + pub fn l_brack_token(&self) -> Option { support::token(&self.syntax, T!['[']) } + pub fn r_brack_token(&self) -> Option { support::token(&self.syntax, T![']']) } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MacroStmts { pub(crate) syntax: SyntaxNode, @@ -1922,6 +1936,17 @@ impl AstNode for MacroItems { } fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl AstNode for MacroEagerInput { + fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_EAGER_INPUT } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} impl AstNode for MacroStmts { fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_STMTS } fn cast(syntax: SyntaxNode) -> Option { @@ -4360,6 +4385,11 @@ impl std::fmt::Display for MacroItems { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for MacroEagerInput { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for MacroStmts { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs index bed240a6d735..4cd668a0cd56 100644 --- a/crates/syntax/src/lib.rs +++ b/crates/syntax/src/lib.rs @@ -172,7 +172,7 @@ impl SourceFile { } impl ast::TokenTree { - pub fn reparse_as_expr(self) -> Parse { + pub fn reparse_as_comma_separated_expr(self) -> Parse { let tokens = self.syntax().descendants_with_tokens().filter_map(NodeOrToken::into_token); let mut parser_input = parser::Input::default(); @@ -203,7 +203,7 @@ impl ast::TokenTree { } } - let parser_output = parser::TopEntryPoint::Expr.parse(&parser_input); + let parser_output = parser::TopEntryPoint::MacroEagerInput.parse(&parser_input); let mut tokens = self.syntax().descendants_with_tokens().filter_map(NodeOrToken::into_token); diff --git a/crates/syntax/src/tests/ast_src.rs b/crates/syntax/src/tests/ast_src.rs index c5783b91a0fd..e4db33f1c692 100644 --- a/crates/syntax/src/tests/ast_src.rs +++ b/crates/syntax/src/tests/ast_src.rs @@ -216,6 +216,7 @@ pub(crate) const KINDS_SRC: KindsSrc<'_> = KindsSrc { // macro related "MACRO_ITEMS", "MACRO_STMTS", + "MACRO_EAGER_INPUT", ], }; diff --git a/crates/tt/src/lib.rs b/crates/tt/src/lib.rs index 1b8d4ba42a59..b5a72bec079a 100644 --- a/crates/tt/src/lib.rs +++ b/crates/tt/src/lib.rs @@ -65,12 +65,12 @@ pub mod token_id { } impl TokenTree { pub const fn empty() -> Self { - Self::Subtree(Subtree { delimiter: Delimiter::unspecified(), token_trees: vec![] }) + Self::Subtree(Subtree::empty()) } } impl Subtree { - pub fn visit_ids(&mut self, f: &impl Fn(TokenId) -> TokenId) { + pub fn visit_ids(&mut self, f: &mut impl FnMut(TokenId) -> TokenId) { self.delimiter.open = f(self.delimiter.open); self.delimiter.close = f(self.delimiter.close); self.token_trees.iter_mut().for_each(|tt| match tt { @@ -122,7 +122,6 @@ impl_from!(Literal, Punct, Ident for Leaf); #[derive(Clone, PartialEq, Eq, Hash)] pub struct Subtree { - // FIXME, this should not be Option pub delimiter: Delimiter, pub token_trees: Vec>, } diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc index 2cf985adabc7..5dafd1a4c8c9 100644 --- a/docs/user/manual.adoc +++ b/docs/user/manual.adoc @@ -949,6 +949,29 @@ Or it is possible to specify vars more granularly: You can use any valid regular expression as a mask. Also note that a full runnable name is something like *run bin_or_example_name*, *test some::mod::test_name* or *test-mod some::mod*, so it is possible to distinguish binaries, single tests, and test modules with this masks: `"^run"`, `"^test "` (the trailing space matters!), and `"^test-mod"` respectively. +If needed, you can set different values for different platforms: +```jsonc +"rust-analyzer.runnables.extraEnv": [ + { + "platform": "win32", // windows only + env: { + "APP_DATA": "windows specific data" + } + }, + { + "platform": ["linux"], + "env": { + "APP_DATA": "linux data", + } + }, + { // for all platforms + "env": { + "APP_COMMON_DATA": "xxx", + } + } +] +``` + ==== Compiler feedback from external commands Instead of relying on the built-in `cargo check`, you can configure Code to run a command in the background and use the `$rustc-watch` problem matcher to generate inline error markers from its output. diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index 1c94f13d7451..20fe781ae9e4 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json @@ -18,7 +18,7 @@ "devDependencies": { "@tsconfig/strictest": "^2.0.1", "@types/node": "~16.11.7", - "@types/vscode": "~1.78.1", + "@types/vscode": "~1.75", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", "@vscode/test-electron": "^2.3.3", @@ -32,7 +32,7 @@ "typescript": "^5.1.6" }, "engines": { - "vscode": "^1.78.0" + "vscode": "^1.75.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -565,9 +565,9 @@ "dev": true }, "node_modules/@types/vscode": { - "version": "1.78.1", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.78.1.tgz", - "integrity": "sha512-wEA+54axejHu7DhcUfnFBan1IqFD1gBDxAFz8LoX06NbNDMRJv/T6OGthOs52yZccasKfN588EyffHWABkR0fg==", + "version": "1.75.1", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.75.1.tgz", + "integrity": "sha512-emg7wdsTFzdi+elvoyoA+Q8keEautdQHyY5LNmHVM4PTpY8JgOTVADrGVyXGepJ6dVW2OS5/xnLUWh+nZxvdiA==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { diff --git a/editors/code/package.json b/editors/code/package.json index a4897899cab1..76d7e91f3810 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -26,7 +26,7 @@ } }, "engines": { - "vscode": "^1.78.0" + "vscode": "^1.75.0" }, "enabledApiProposals": [], "scripts": { @@ -53,7 +53,7 @@ "devDependencies": { "@tsconfig/strictest": "^2.0.1", "@types/node": "~16.11.7", - "@types/vscode": "~1.78.1", + "@types/vscode": "~1.75", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", "@vscode/test-electron": "^2.3.3", @@ -328,6 +328,15 @@ "items": { "type": "object", "properties": { + "platform": { + "type": [ + "null", + "string", + "array" + ], + "default": null, + "markdownDescription": "Platform(s) filter like \"win32\" or [\"linux\", \"win32\"]. See [process.platform](https://nodejs.org/api/process.html#processplatform) values." + }, "mask": { "type": "string", "description": "Runnable name mask" diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index a047f9659a96..0e64054c11d5 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -6,10 +6,12 @@ import type { Env } from "./client"; import { log } from "./util"; import { expectNotUndefined, unwrapUndefinable } from "./undefinable"; -export type RunnableEnvCfg = - | undefined - | Record - | { mask?: string; env: Record }[]; +export type RunnableEnvCfgItem = { + mask?: string; + env: Record; + platform?: string | string[]; +}; +export type RunnableEnvCfg = undefined | Record | RunnableEnvCfgItem[]; export class Config { readonly extensionId = "rust-lang.rust-analyzer"; diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index ac144cbebb21..16c14ca54f25 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -414,7 +414,7 @@ export class Ctx { statusBar.tooltip.appendText(status.message ?? "Ready"); statusBar.color = undefined; statusBar.backgroundColor = undefined; - statusBar.command = "rust-analyzer.stopServer"; + statusBar.command = "rust-analyzer.openLogs"; this.dependencies?.refresh(); break; case "warning": @@ -442,14 +442,16 @@ export class Ctx { statusBar.tooltip.appendMarkdown( "\n\n[Start server](command:rust-analyzer.startServer)", ); - statusBar.color = undefined; - statusBar.backgroundColor = undefined; + statusBar.color = new vscode.ThemeColor("statusBarItem.warningForeground"); + statusBar.backgroundColor = new vscode.ThemeColor( + "statusBarItem.warningBackground", + ); statusBar.command = "rust-analyzer.startServer"; statusBar.text = `$(stop-circle) rust-analyzer`; return; } if (statusBar.tooltip.value) { - statusBar.tooltip.appendText("\n\n"); + statusBar.tooltip.appendMarkdown("\n\n---\n\n"); } statusBar.tooltip.appendMarkdown("\n\n[Open logs](command:rust-analyzer.openLogs)"); statusBar.tooltip.appendMarkdown( diff --git a/editors/code/src/run.ts b/editors/code/src/run.ts index c893d390554d..57881803a6a0 100644 --- a/editors/code/src/run.ts +++ b/editors/code/src/run.ts @@ -5,7 +5,7 @@ import * as tasks from "./tasks"; import type { CtxInit } from "./ctx"; import { makeDebugConfig } from "./debug"; -import type { Config, RunnableEnvCfg } from "./config"; +import type { Config, RunnableEnvCfg, RunnableEnvCfgItem } from "./config"; import { unwrapUndefinable } from "./undefinable"; const quickPickButtons = [ @@ -112,11 +112,21 @@ export function prepareEnv( } Object.assign(env, process.env as { [key: string]: string }); + const platform = process.platform; + + const checkPlatform = (it: RunnableEnvCfgItem) => { + if (it.platform) { + const platforms = Array.isArray(it.platform) ? it.platform : [it.platform]; + return platforms.indexOf(platform) >= 0; + } + return true; + }; if (runnableEnvCfg) { if (Array.isArray(runnableEnvCfg)) { for (const it of runnableEnvCfg) { - if (!it.mask || new RegExp(it.mask).test(runnable.label)) { + const masked = !it.mask || new RegExp(it.mask).test(runnable.label); + if (masked && checkPlatform(it)) { Object.assign(env, it.env); } } diff --git a/triagebot.toml b/triagebot.toml index a910e012b734..f0cd35399752 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -9,3 +9,7 @@ allow-unauthenticated = [ [autolabel."S-waiting-on-review"] new_pr = true + +[no-merges] +exclude_labels = ["sync"] +labels = ["has-merge-commits", "S-waiting-on-author"] From 31c30933cf0a94929d533078a402f15a1d350055 Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Tue, 8 Aug 2023 01:49:34 +0330 Subject: [PATCH 022/197] Support closure in clone shim --- crates/hir-ty/src/consteval/tests.rs | 24 ++++++++++ crates/hir-ty/src/mir/eval/shim.rs | 70 +++++++++++++++++++--------- 2 files changed, 73 insertions(+), 21 deletions(-) diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs index 666a7e81e315..74c62a08a2b7 100644 --- a/crates/hir-ty/src/consteval/tests.rs +++ b/crates/hir-ty/src/consteval/tests.rs @@ -1453,6 +1453,30 @@ fn from_trait() { ); } +#[test] +fn closure_clone() { + check_number( + r#" +//- minicore: clone, fn +struct S(u8); + +impl Clone for S(u8) { + fn clone(&self) -> S { + S(self.0 + 5) + } +} + +const GOAL: u8 = { + let s = S(3); + let cl = move || s; + let cl = cl.clone(); + cl().0 +} + "#, + 8, + ); +} + #[test] fn builtin_derive_macro() { check_number( diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs index bfd7d7c1f2c2..52943e97ac07 100644 --- a/crates/hir-ty/src/mir/eval/shim.rs +++ b/crates/hir-ty/src/mir/eval/shim.rs @@ -136,7 +136,10 @@ impl Evaluator<'_> { not_supported!("wrong generic arg kind for clone"); }; // Clone has special impls for tuples and function pointers - if matches!(self_ty.kind(Interner), TyKind::Function(_) | TyKind::Tuple(..)) { + if matches!( + self_ty.kind(Interner), + TyKind::Function(_) | TyKind::Tuple(..) | TyKind::Closure(..) + ) { self.exec_clone(def, args, self_ty.clone(), locals, destination, span)?; return Ok(true); } @@ -167,32 +170,26 @@ impl Evaluator<'_> { return destination .write_from_interval(self, Interval { addr, size: destination.size }); } + TyKind::Closure(id, subst) => { + let [arg] = args else { + not_supported!("wrong arg count for clone"); + }; + let addr = Address::from_bytes(arg.get(self)?)?; + let (closure_owner, _) = self.db.lookup_intern_closure((*id).into()); + let infer = self.db.infer(closure_owner); + let (captures, _) = infer.closure_info(id); + let layout = self.layout(&self_ty)?; + let ty_iter = captures.iter().map(|c| c.ty(subst)); + self.exec_clone_for_fields(ty_iter, layout, addr, def, locals, destination, span)?; + } TyKind::Tuple(_, subst) => { let [arg] = args else { not_supported!("wrong arg count for clone"); }; let addr = Address::from_bytes(arg.get(self)?)?; let layout = self.layout(&self_ty)?; - for (i, ty) in subst.iter(Interner).enumerate() { - let ty = ty.assert_ty_ref(Interner); - let size = self.layout(ty)?.size.bytes_usize(); - let tmp = self.heap_allocate(self.ptr_size(), self.ptr_size())?; - let arg = IntervalAndTy { - interval: Interval { addr: tmp, size: self.ptr_size() }, - ty: TyKind::Ref(Mutability::Not, static_lifetime(), ty.clone()) - .intern(Interner), - }; - let offset = layout.fields.offset(i).bytes_usize(); - self.write_memory(tmp, &addr.offset(offset).to_bytes())?; - self.exec_clone( - def, - &[arg], - ty.clone(), - locals, - destination.slice(offset..offset + size), - span, - )?; - } + let ty_iter = subst.iter(Interner).map(|ga| ga.assert_ty_ref(Interner).clone()); + self.exec_clone_for_fields(ty_iter, layout, addr, def, locals, destination, span)?; } _ => { self.exec_fn_with_args( @@ -209,6 +206,37 @@ impl Evaluator<'_> { Ok(()) } + fn exec_clone_for_fields( + &mut self, + ty_iter: impl Iterator, + layout: Arc, + addr: Address, + def: FunctionId, + locals: &Locals, + destination: Interval, + span: MirSpan, + ) -> Result<()> { + for (i, ty) in ty_iter.enumerate() { + let size = self.layout(&ty)?.size.bytes_usize(); + let tmp = self.heap_allocate(self.ptr_size(), self.ptr_size())?; + let arg = IntervalAndTy { + interval: Interval { addr: tmp, size: self.ptr_size() }, + ty: TyKind::Ref(Mutability::Not, static_lifetime(), ty.clone()).intern(Interner), + }; + let offset = layout.fields.offset(i).bytes_usize(); + self.write_memory(tmp, &addr.offset(offset).to_bytes())?; + self.exec_clone( + def, + &[arg], + ty, + locals, + destination.slice(offset..offset + size), + span, + )?; + } + Ok(()) + } + fn exec_alloc_fn( &mut self, alloc_fn: &str, From 9cb1f45e6f1aedddb475aa61a7bebd9fb26cc094 Mon Sep 17 00:00:00 2001 From: Adam Sandberg Ericsson Date: Sat, 13 May 2023 15:12:32 +0100 Subject: [PATCH 023/197] add check.ignore to list cargo check diagnostics to ignore (dead_code, unused_imports, ...) fixes #14798 --- crates/rust-analyzer/src/config.rs | 5 +++++ crates/rust-analyzer/src/diagnostics.rs | 2 ++ crates/rust-analyzer/src/diagnostics/to_proto.rs | 7 +++++++ docs/user/generated_config.adoc | 7 +++++++ editors/code/package.json | 9 +++++++++ 5 files changed, 30 insertions(+) diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index fa20c796ec27..4a31e0ba0a3d 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -150,6 +150,10 @@ config_data! { /// /// Set to `"all"` to pass `--all-features` to Cargo. check_features | checkOnSave_features: Option = "null", + /// List of `cargo check` (or other command specified in `check.command`) diagnostics to ignore. + /// + /// For example for `cargo check`: `dead_code`, `unused_imports`, `unused_variables`,... + check_ignore: FxHashSet = "[]", /// 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 @@ -1098,6 +1102,7 @@ impl Config { remap_prefix: self.data.diagnostics_remapPrefix.clone(), warnings_as_info: self.data.diagnostics_warningsAsInfo.clone(), warnings_as_hint: self.data.diagnostics_warningsAsHint.clone(), + check_ignore: self.data.check_ignore.clone(), } } diff --git a/crates/rust-analyzer/src/diagnostics.rs b/crates/rust-analyzer/src/diagnostics.rs index 33422fd058ef..b65f38a0c711 100644 --- a/crates/rust-analyzer/src/diagnostics.rs +++ b/crates/rust-analyzer/src/diagnostics.rs @@ -6,6 +6,7 @@ use std::mem; use ide::FileId; use ide_db::FxHashMap; use nohash_hasher::{IntMap, IntSet}; +use rustc_hash::FxHashSet; use triomphe::Arc; use crate::lsp_ext; @@ -17,6 +18,7 @@ pub struct DiagnosticsMapConfig { pub remap_prefix: FxHashMap, pub warnings_as_info: Vec, pub warnings_as_hint: Vec, + pub check_ignore: FxHashSet, } #[derive(Debug, Default, Clone)] diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs index e1d1130ff1b8..06564578d809 100644 --- a/crates/rust-analyzer/src/diagnostics/to_proto.rs +++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs @@ -292,6 +292,13 @@ pub(crate) fn map_rust_diagnostic_to_lsp( let mut source = String::from("rustc"); let mut code = rd.code.as_ref().map(|c| c.code.clone()); + + if let Some(code_val) = &code { + if config.check_ignore.contains(code_val) { + return Vec::new(); + } + } + if let Some(code_val) = &code { // See if this is an RFC #2103 scoped lint (e.g. from Clippy) let scoped_code: Vec<&str> = code_val.split("::").collect(); diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index ea00c9540ff1..820535cc1b0d 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -161,6 +161,13 @@ List of features to activate. Defaults to Set to `"all"` to pass `--all-features` to Cargo. -- +[[rust-analyzer.check.ignore]]rust-analyzer.check.ignore (default: `[]`):: ++ +-- +List of `cargo check` (or other command specified in `check.command`) diagnostics to ignore. + +For example for `cargo check`: `dead_code`, `unused_imports`, `unused_variables`,... +-- [[rust-analyzer.check.invocationLocation]]rust-analyzer.check.invocationLocation (default: `"workspace"`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index cd8b40e35575..f6b8450eef10 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -688,6 +688,15 @@ } ] }, + "rust-analyzer.check.ignore": { + "markdownDescription": "List of `cargo check` (or other command specified in `check.command`) diagnostics to ignore.\n\nFor example for `cargo check`: `dead_code`, `unused_imports`, `unused_variables`,...", + "default": [], + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, "rust-analyzer.check.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", From cba39f8553e751e6fb4626653153b1e980472565 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 8 Aug 2023 14:43:26 +0200 Subject: [PATCH 024/197] fix: Fix float parser hack creating empty NameRef tokens --- .../macro_expansion_tests/mbe/regression.rs | 27 +++++++++++++++++++ crates/mbe/src/syntax_bridge.rs | 1 + crates/parser/src/shortcuts.rs | 13 ++++++--- crates/syntax/src/lib.rs | 12 ++++++--- 4 files changed, 46 insertions(+), 7 deletions(-) diff --git a/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs b/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs index d8e4a4dcc7c2..b783de4ccc2b 100644 --- a/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs +++ b/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs @@ -909,3 +909,30 @@ macro_rules! with_std { "##]], ) } + +#[test] +fn eager_regression_15403() { + check( + r#" +#[rustc_builtin_macro] +#[macro_export] +macro_rules! format_args {} + +fn main() { + format_args /* +errors */ !("{}", line.1.); +} + +"#, + expect![[r##" +#[rustc_builtin_macro] +#[macro_export] +macro_rules! format_args {} + +fn main() { + /* error: expected field name or number *//* parse error: expected field name or number */ +::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(line.1.), ::core::fmt::Display::fmt), ]); +} + +"##]], + ); +} diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs index 62b2accf5cda..7b9bb61e696a 100644 --- a/crates/mbe/src/syntax_bridge.rs +++ b/crates/mbe/src/syntax_bridge.rs @@ -961,6 +961,7 @@ impl TtTreeSink<'_> { if has_pseudo_dot { assert!(right.is_empty(), "{left}.{right}"); } else { + assert!(!right.is_empty(), "{left}.{right}"); self.inner.start_node(SyntaxKind::NAME_REF); self.inner.token(SyntaxKind::INT_NUMBER, right); self.inner.finish_node(); diff --git a/crates/parser/src/shortcuts.rs b/crates/parser/src/shortcuts.rs index 53cdad64992c..2c47e3d086d6 100644 --- a/crates/parser/src/shortcuts.rs +++ b/crates/parser/src/shortcuts.rs @@ -46,12 +46,16 @@ impl LexedStr<'_> { // Tag the token as joint if it is float with a fractional part // we use this jointness to inform the parser about what token split // event to emit when we encounter a float literal in a field access - if kind == SyntaxKind::FLOAT_NUMBER && !self.text(i).ends_with('.') { - res.was_joint(); + if kind == SyntaxKind::FLOAT_NUMBER { + if !self.text(i).ends_with('.') { + res.was_joint(); + } else { + was_joint = false; + } + } else { + was_joint = true; } } - - was_joint = true; } } res @@ -204,6 +208,7 @@ impl Builder<'_, '_> { assert!(right.is_empty(), "{left}.{right}"); self.state = State::Normal; } else { + assert!(!right.is_empty(), "{left}.{right}"); (self.sink)(StrStep::Enter { kind: SyntaxKind::NAME_REF }); (self.sink)(StrStep::Token { kind: SyntaxKind::INT_NUMBER, text: right }); (self.sink)(StrStep::Exit); diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs index 4cd668a0cd56..27c8a13e58d6 100644 --- a/crates/syntax/src/lib.rs +++ b/crates/syntax/src/lib.rs @@ -195,11 +195,16 @@ impl ast::TokenTree { // Tag the token as joint if it is float with a fractional part // we use this jointness to inform the parser about what token split // event to emit when we encounter a float literal in a field access - if kind == SyntaxKind::FLOAT_NUMBER && !t.text().ends_with('.') { - parser_input.was_joint(); + if kind == SyntaxKind::FLOAT_NUMBER { + if !t.text().ends_with('.') { + parser_input.was_joint(); + } else { + was_joint = false; + } + } else { + was_joint = true; } } - was_joint = true; } } @@ -250,6 +255,7 @@ impl ast::TokenTree { if has_pseudo_dot { assert!(right.is_empty(), "{left}.{right}"); } else { + assert!(!right.is_empty(), "{left}.{right}"); builder.start_node(SyntaxKind::NAME_REF); builder.token(SyntaxKind::INT_NUMBER, right); builder.finish_node(); From 02d5c0ac56fd8a89cade6dd83cfd122c6adec691 Mon Sep 17 00:00:00 2001 From: Charles <63302440+Sarrus1@users.noreply.github.com> Date: Tue, 8 Aug 2023 14:55:56 +0200 Subject: [PATCH 025/197] chore: convert unwrap to except and add a debug log --- lib/lsp-server/src/stdio.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/lsp-server/src/stdio.rs b/lib/lsp-server/src/stdio.rs index 49a825e579b5..e487b9b46226 100644 --- a/lib/lsp-server/src/stdio.rs +++ b/lib/lsp-server/src/stdio.rs @@ -3,6 +3,8 @@ use std::{ thread, }; +use log::debug; + use crossbeam_channel::{bounded, Receiver, Sender}; use crate::Message; @@ -23,7 +25,8 @@ pub(crate) fn stdio_transport() -> (Sender, Receiver, IoThread while let Some(msg) = Message::read(&mut stdin)? { let is_exit = matches!(&msg, Message::Notification(n) if n.is_exit()); - reader_sender.send(msg).unwrap(); + debug!("sending message {:#?}", msg); + reader_sender.send(msg).expect("receiver was dropped, failed to send a message"); if is_exit { break; From ef5c6daf6ec0797c0e4c3b323853390f15078e70 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Mon, 24 Jul 2023 21:16:05 +0200 Subject: [PATCH 026/197] Rewrite DeMorgan without str manipulation. --- .../src/handlers/apply_demorgan.rs | 208 ++++++++++-------- crates/syntax/src/ast/make.rs | 2 +- 2 files changed, 116 insertions(+), 94 deletions(-) diff --git a/crates/ide-assists/src/handlers/apply_demorgan.rs b/crates/ide-assists/src/handlers/apply_demorgan.rs index 57cfa17cc8e1..05847a864f35 100644 --- a/crates/ide-assists/src/handlers/apply_demorgan.rs +++ b/crates/ide-assists/src/handlers/apply_demorgan.rs @@ -1,6 +1,10 @@ use std::collections::VecDeque; -use syntax::ast::{self, AstNode}; +use syntax::{ + ast::{self, AstNode, Expr::BinExpr}, + ted::{self, Position}, + SyntaxKind, +}; use crate::{utils::invert_boolean_expression, AssistContext, AssistId, AssistKind, Assists}; @@ -23,121 +27,115 @@ use crate::{utils::invert_boolean_expression, AssistContext, AssistId, AssistKin // } // ``` pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { - let expr = ctx.find_node_at_offset::()?; - let op = expr.op_kind()?; - let op_range = expr.op_token()?.text_range(); + let mut bin_expr = ctx.find_node_at_offset::()?; + let op = bin_expr.op_kind()?; + let op_range = bin_expr.op_token()?.text_range(); - let opposite_op = match op { - ast::BinaryOp::LogicOp(ast::LogicOp::And) => "||", - ast::BinaryOp::LogicOp(ast::LogicOp::Or) => "&&", - _ => return None, - }; - - let cursor_in_range = op_range.contains_range(ctx.selection_trimmed()); - if !cursor_in_range { + // Is the cursor on the expression's logical operator? + if !op_range.contains_range(ctx.selection_trimmed()) { return None; } - let mut expr = expr; - // Walk up the tree while we have the same binary operator - while let Some(parent_expr) = expr.syntax().parent().and_then(ast::BinExpr::cast) { - match expr.op_kind() { + while let Some(parent_expr) = bin_expr.syntax().parent().and_then(ast::BinExpr::cast) { + match parent_expr.op_kind() { Some(parent_op) if parent_op == op => { - expr = parent_expr; + bin_expr = parent_expr; } _ => break, } } - let mut expr_stack = vec![expr.clone()]; - let mut terms = Vec::new(); - let mut op_ranges = Vec::new(); + let op = bin_expr.op_kind()?; + let inv_token = match op { + ast::BinaryOp::LogicOp(ast::LogicOp::And) => SyntaxKind::PIPE2, + ast::BinaryOp::LogicOp(ast::LogicOp::Or) => SyntaxKind::AMP2, + _ => return None, + }; - // Find all the children with the same binary operator - while let Some(expr) = expr_stack.pop() { - let mut traverse_bin_expr_arm = |expr| { - if let ast::Expr::BinExpr(bin_expr) = expr { - if let Some(expr_op) = bin_expr.op_kind() { - if expr_op == op { - expr_stack.push(bin_expr); - } else { - terms.push(ast::Expr::BinExpr(bin_expr)); - } + let demorganed = bin_expr.clone_subtree().clone_for_update(); + + ted::replace(demorganed.op_token()?, ast::make::token(inv_token)); + let mut exprs = VecDeque::from(vec![ + (bin_expr.lhs()?, demorganed.lhs()?), + (bin_expr.rhs()?, demorganed.rhs()?), + ]); + + while let Some((expr, dm)) = exprs.pop_front() { + if let BinExpr(bin_expr) = &expr { + if let BinExpr(cbin_expr) = &dm { + if op == bin_expr.op_kind()? { + ted::replace(cbin_expr.op_token()?, ast::make::token(inv_token)); + exprs.push_back((bin_expr.lhs()?, cbin_expr.lhs()?)); + exprs.push_back((bin_expr.rhs()?, cbin_expr.rhs()?)); } else { - terms.push(ast::Expr::BinExpr(bin_expr)); + let mut inv = invert_boolean_expression(expr); + if inv.needs_parens_in(dm.syntax().parent()?) { + inv = ast::make::expr_paren(inv).clone_for_update(); + } + ted::replace(dm.syntax(), inv.syntax()); } } else { - terms.push(expr); + return None; } - }; - - op_ranges.extend(expr.op_token().map(|t| t.text_range())); - traverse_bin_expr_arm(expr.lhs()?); - traverse_bin_expr_arm(expr.rhs()?); + } else { + let mut inv = invert_boolean_expression(dm.clone_subtree()).clone_for_update(); + if inv.needs_parens_in(dm.syntax().parent()?) { + inv = ast::make::expr_paren(inv).clone_for_update(); + } + ted::replace(dm.syntax(), inv.syntax()); + } } + let paren_expr = bin_expr.syntax().parent().and_then(ast::ParenExpr::cast); + let neg_expr = paren_expr + .clone() + .and_then(|paren_expr| paren_expr.syntax().parent()) + .and_then(ast::PrefixExpr::cast) + .and_then(|prefix_expr| { + if prefix_expr.op_kind().unwrap() == ast::UnaryOp::Not { + Some(prefix_expr) + } else { + None + } + }); + acc.add( AssistId("apply_demorgan", AssistKind::RefactorRewrite), "Apply De Morgan's law", op_range, |edit| { - terms.sort_by_key(|t| t.syntax().text_range().start()); - let mut terms = VecDeque::from(terms); - - let paren_expr = expr.syntax().parent().and_then(ast::ParenExpr::cast); - - let neg_expr = paren_expr - .clone() - .and_then(|paren_expr| paren_expr.syntax().parent()) - .and_then(ast::PrefixExpr::cast) - .and_then(|prefix_expr| { - if prefix_expr.op_kind().unwrap() == ast::UnaryOp::Not { - Some(prefix_expr) - } else { - None - } - }); - - for op_range in op_ranges { - edit.replace(op_range, opposite_op); - } - if let Some(paren_expr) = paren_expr { - for term in terms { - let range = term.syntax().text_range(); - let not_term = invert_boolean_expression(term); - - edit.replace(range, not_term.syntax().text()); - } - if let Some(neg_expr) = neg_expr { cov_mark::hit!(demorgan_double_negation); - edit.replace(neg_expr.op_token().unwrap().text_range(), ""); + edit.replace_ast(ast::Expr::PrefixExpr(neg_expr), demorganed.into()); } else { cov_mark::hit!(demorgan_double_parens); - edit.replace(paren_expr.l_paren_token().unwrap().text_range(), "!("); + ted::insert_all_raw( + Position::before(demorganed.lhs().unwrap().syntax()), + vec![ + syntax::NodeOrToken::Token(ast::make::token(SyntaxKind::BANG)), + syntax::NodeOrToken::Token(ast::make::token(SyntaxKind::L_PAREN)), + ], + ); + + ted::append_child_raw( + demorganed.syntax(), + syntax::NodeOrToken::Token(ast::make::token(SyntaxKind::R_PAREN)), + ); + + edit.replace_ast(ast::Expr::ParenExpr(paren_expr), demorganed.into()); } } else { - if let Some(lhs) = terms.pop_front() { - let lhs_range = lhs.syntax().text_range(); - let not_lhs = invert_boolean_expression(lhs); - - edit.replace(lhs_range, format!("!({not_lhs}")); - } - - if let Some(rhs) = terms.pop_back() { - let rhs_range = rhs.syntax().text_range(); - let not_rhs = invert_boolean_expression(rhs); - - edit.replace(rhs_range, format!("{not_rhs})")); - } - - for term in terms { - let term_range = term.syntax().text_range(); - let not_term = invert_boolean_expression(term); - edit.replace(term_range, not_term.to_string()); - } + ted::insert_all_raw( + Position::before(demorganed.lhs().unwrap().syntax()), + vec![ + syntax::NodeOrToken::Token(ast::make::token(SyntaxKind::BANG)), + syntax::NodeOrToken::Token(ast::make::token(SyntaxKind::L_PAREN)), + ], + ); + ted::append_child_raw(demorganed.syntax(), ast::make::token(SyntaxKind::R_PAREN)); + edit.replace_ast(bin_expr, demorganed); } }, ) @@ -145,9 +143,8 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti #[cfg(test)] mod tests { - use crate::tests::{check_assist, check_assist_not_applicable}; - use super::*; + use crate::tests::{check_assist, check_assist_not_applicable}; #[test] fn demorgan_handles_leq() { @@ -213,7 +210,7 @@ fn f() { !(S <= S || S < S) } #[test] fn demorgan_doesnt_double_negation() { cov_mark::check!(demorgan_double_negation); - check_assist(apply_demorgan, "fn f() { !(x ||$0 x) }", "fn f() { (!x && !x) }") + check_assist(apply_demorgan, "fn f() { !(x ||$0 x) }", "fn f() { !x && !x }") } #[test] @@ -222,13 +219,38 @@ fn f() { !(S <= S || S < S) } check_assist(apply_demorgan, "fn f() { (x ||$0 x) }", "fn f() { !(!x && !x) }") } - // https://github.com/rust-lang/rust-analyzer/issues/10963 + // FIXME : This needs to go. + // // https://github.com/rust-lang/rust-analyzer/issues/10963 + // #[test] + // fn demorgan_doesnt_hang() { + // check_assist( + // apply_demorgan, + // "fn f() { 1 || 3 &&$0 4 || 5 }", + // "fn f() { !(!1 || !3 || !4) || 5 }", + // ) + // } + #[test] - fn demorgan_doesnt_hang() { + fn demorgan_keep_pars_for_op_precedence() { check_assist( apply_demorgan, - "fn f() { 1 || 3 &&$0 4 || 5 }", - "fn f() { !(!1 || !3 || !4) || 5 }", + "fn main() { + let _ = !(!a ||$0 !(b || c)); +} +", + "fn main() { + let _ = a && (b || c); +} +", + ); + } + + #[test] + fn demorgan_removes_pars_in_eq_precedence() { + check_assist( + apply_demorgan, + "fn() { let x = a && !(!b |$0| !c); }", + "fn() { let x = a && b && c; }", ) } } diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index 4c6db0ef06cb..c240008e7afb 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs @@ -1100,7 +1100,7 @@ pub mod tokens { pub(super) static SOURCE_FILE: Lazy> = Lazy::new(|| { SourceFile::parse( - "const C: <()>::Item = (1 != 1, 2 == 2, 3 < 3, 4 <= 4, 5 > 5, 6 >= 6, !true, *p, &p , &mut p)\n;\n\n", + "const C: <()>::Item = ( true && true , true || true , 1 != 1, 2 == 2, 3 < 3, 4 <= 4, 5 > 5, 6 >= 6, !true, *p, &p , &mut p)\n;\n\n", ) }); From 17f3055803f8d6551b746192a4ba78edb5b62995 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 8 Aug 2023 15:54:58 +0200 Subject: [PATCH 027/197] Rewrite DeMorgan v2 --- .../src/handlers/apply_demorgan.rs | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/crates/ide-assists/src/handlers/apply_demorgan.rs b/crates/ide-assists/src/handlers/apply_demorgan.rs index 05847a864f35..66bc2f6dadc3 100644 --- a/crates/ide-assists/src/handlers/apply_demorgan.rs +++ b/crates/ide-assists/src/handlers/apply_demorgan.rs @@ -87,24 +87,26 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti } } - let paren_expr = bin_expr.syntax().parent().and_then(ast::ParenExpr::cast); - let neg_expr = paren_expr - .clone() - .and_then(|paren_expr| paren_expr.syntax().parent()) - .and_then(ast::PrefixExpr::cast) - .and_then(|prefix_expr| { - if prefix_expr.op_kind().unwrap() == ast::UnaryOp::Not { - Some(prefix_expr) - } else { - None - } - }); + let dm_lhs = demorganed.lhs()?; acc.add( AssistId("apply_demorgan", AssistKind::RefactorRewrite), "Apply De Morgan's law", op_range, |edit| { + let paren_expr = bin_expr.syntax().parent().and_then(ast::ParenExpr::cast); + let neg_expr = paren_expr + .clone() + .and_then(|paren_expr| paren_expr.syntax().parent()) + .and_then(ast::PrefixExpr::cast) + .and_then(|prefix_expr| { + if prefix_expr.op_kind()? == ast::UnaryOp::Not { + Some(prefix_expr) + } else { + None + } + }); + if let Some(paren_expr) = paren_expr { if let Some(neg_expr) = neg_expr { cov_mark::hit!(demorgan_double_negation); @@ -112,7 +114,7 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti } else { cov_mark::hit!(demorgan_double_parens); ted::insert_all_raw( - Position::before(demorganed.lhs().unwrap().syntax()), + Position::before(dm_lhs.syntax()), vec![ syntax::NodeOrToken::Token(ast::make::token(SyntaxKind::BANG)), syntax::NodeOrToken::Token(ast::make::token(SyntaxKind::L_PAREN)), @@ -128,7 +130,7 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti } } else { ted::insert_all_raw( - Position::before(demorganed.lhs().unwrap().syntax()), + Position::before(dm_lhs.syntax()), vec![ syntax::NodeOrToken::Token(ast::make::token(SyntaxKind::BANG)), syntax::NodeOrToken::Token(ast::make::token(SyntaxKind::L_PAREN)), From 6aa03c5d1577b512ab6d339026fc6edf3233cd1a Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Wed, 9 Aug 2023 00:47:29 +0900 Subject: [PATCH 028/197] Use `Cast::cast()` instead of interning `GenericArgData` --- crates/hir-ty/src/builder.rs | 13 ++++++------ crates/hir-ty/src/consteval.rs | 4 ++-- crates/hir-ty/src/infer/expr.rs | 21 +++++++------------ crates/hir-ty/src/infer/unify.rs | 36 ++++++++++++-------------------- crates/hir-ty/src/lower.rs | 28 +++++++------------------ crates/hir-ty/src/mir/eval.rs | 8 +++---- crates/hir/src/lib.rs | 8 +++---- 7 files changed, 45 insertions(+), 73 deletions(-) diff --git a/crates/hir-ty/src/builder.rs b/crates/hir-ty/src/builder.rs index eec57ba3f80f..967e028bfb14 100644 --- a/crates/hir-ty/src/builder.rs +++ b/crates/hir-ty/src/builder.rs @@ -17,7 +17,8 @@ use smallvec::SmallVec; use crate::{ consteval::unknown_const_as_generic, db::HirDatabase, infer::unify::InferenceTable, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders, BoundVar, CallableSig, - GenericArg, Interner, ProjectionTy, Substitution, TraitRef, Ty, TyDefId, TyExt, TyKind, + GenericArg, GenericArgData, Interner, ProjectionTy, Substitution, TraitRef, Ty, TyDefId, TyExt, + TyKind, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -79,9 +80,9 @@ impl TyBuilder { let expected_kind = &self.param_kinds[self.vec.len()]; let arg_kind = match arg.data(Interner) { - chalk_ir::GenericArgData::Ty(_) => ParamKind::Type, - chalk_ir::GenericArgData::Lifetime(_) => panic!("Got lifetime in TyBuilder::push"), - chalk_ir::GenericArgData::Const(c) => { + GenericArgData::Ty(_) => ParamKind::Type, + GenericArgData::Lifetime(_) => panic!("Got lifetime in TyBuilder::push"), + GenericArgData::Const(c) => { let c = c.data(Interner); ParamKind::Const(c.ty.clone()) } @@ -139,8 +140,8 @@ impl TyBuilder { fn assert_match_kind(&self, a: &chalk_ir::GenericArg, e: &ParamKind) { match (a.data(Interner), e) { - (chalk_ir::GenericArgData::Ty(_), ParamKind::Type) - | (chalk_ir::GenericArgData::Const(_), ParamKind::Const(_)) => (), + (GenericArgData::Ty(_), ParamKind::Type) + | (GenericArgData::Const(_), ParamKind::Const(_)) => (), _ => panic!("Mismatched kinds: {a:?}, {:?}, {:?}", self.vec, self.param_kinds), } } diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs index 1c0f7b08da8c..0348680e5da1 100644 --- a/crates/hir-ty/src/consteval.rs +++ b/crates/hir-ty/src/consteval.rs @@ -1,7 +1,7 @@ //! Constant evaluation details use base_db::CrateId; -use chalk_ir::{BoundVar, DebruijnIndex, GenericArgData}; +use chalk_ir::{cast::Cast, BoundVar, DebruijnIndex}; use hir_def::{ hir::Expr, path::Path, @@ -120,7 +120,7 @@ pub fn unknown_const(ty: Ty) -> Const { } pub fn unknown_const_as_generic(ty: Ty) -> GenericArg { - GenericArgData::Const(unknown_const(ty)).intern(Interner) + unknown_const(ty).cast(Interner) } /// Interns a constant scalar with the given type diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 8cbdae625267..8b3521410848 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -5,9 +5,7 @@ use std::{ mem, }; -use chalk_ir::{ - cast::Cast, fold::Shift, DebruijnIndex, GenericArgData, Mutability, TyVariableKind, -}; +use chalk_ir::{cast::Cast, fold::Shift, DebruijnIndex, Mutability, TyVariableKind}; use hir_def::{ generics::TypeOrConstParamData, hir::{ @@ -750,7 +748,7 @@ impl InferenceContext<'_> { self.resolve_associated_type_with_params( self_ty, self.resolve_ops_index_output(), - &[GenericArgData::Ty(index_ty).intern(Interner)], + &[index_ty.cast(Interner)], ) } else { self.err_ty() @@ -1721,16 +1719,13 @@ impl InferenceContext<'_> { for (id, data) in def_generics.iter().skip(substs.len()) { match data { TypeOrConstParamData::TypeParamData(_) => { - substs.push(GenericArgData::Ty(self.table.new_type_var()).intern(Interner)) - } - TypeOrConstParamData::ConstParamData(_) => { - substs.push( - GenericArgData::Const(self.table.new_const_var( - self.db.const_param_ty(ConstParamId::from_unchecked(id)), - )) - .intern(Interner), - ) + substs.push(self.table.new_type_var().cast(Interner)) } + TypeOrConstParamData::ConstParamData(_) => substs.push( + self.table + .new_const_var(self.db.const_param_ty(ConstParamId::from_unchecked(id))) + .cast(Interner), + ), } } assert_eq!(substs.len(), total_len); diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs index 0fb71135b4de..169679b4636e 100644 --- a/crates/hir-ty/src/infer/unify.rs +++ b/crates/hir-ty/src/infer/unify.rs @@ -10,7 +10,6 @@ use chalk_solve::infer::ParameterEnaVariableExt; use either::Either; use ena::unify::UnifyKey; use hir_expand::name; -use stdx::never; use triomphe::Arc; use super::{InferOk, InferResult, InferenceContext, TypeError}; @@ -92,15 +91,10 @@ pub(crate) fn unify( let vars = Substitution::from_iter( Interner, tys.binders.iter(Interner).map(|it| match &it.kind { - chalk_ir::VariableKind::Ty(_) => { - GenericArgData::Ty(table.new_type_var()).intern(Interner) - } - chalk_ir::VariableKind::Lifetime => { - GenericArgData::Ty(table.new_type_var()).intern(Interner) - } // FIXME: maybe wrong? - chalk_ir::VariableKind::Const(ty) => { - GenericArgData::Const(table.new_const_var(ty.clone())).intern(Interner) - } + chalk_ir::VariableKind::Ty(_) => table.new_type_var().cast(Interner), + // FIXME: maybe wrong? + chalk_ir::VariableKind::Lifetime => table.new_type_var().cast(Interner), + chalk_ir::VariableKind::Const(ty) => table.new_const_var(ty.clone()).cast(Interner), }), ); let ty1_with_vars = vars.apply(tys.value.0.clone(), Interner); @@ -111,10 +105,10 @@ pub(crate) fn unify( // default any type vars that weren't unified back to their original bound vars // (kind of hacky) let find_var = |iv| { - vars.iter(Interner).position(|v| match v.interned() { - chalk_ir::GenericArgData::Ty(ty) => ty.inference_var(Interner), - chalk_ir::GenericArgData::Lifetime(lt) => lt.inference_var(Interner), - chalk_ir::GenericArgData::Const(c) => c.inference_var(Interner), + vars.iter(Interner).position(|v| match v.data(Interner) { + GenericArgData::Ty(ty) => ty.inference_var(Interner), + GenericArgData::Lifetime(lt) => lt.inference_var(Interner), + GenericArgData::Const(c) => c.inference_var(Interner), } == Some(iv)) }; let fallback = |iv, kind, default, binder| match kind { @@ -611,9 +605,9 @@ impl<'a> InferenceTable<'a> { fn check_changed(&mut self, canonicalized: &Canonicalized>) -> bool { canonicalized.free_vars.iter().any(|var| { let iv = match var.data(Interner) { - chalk_ir::GenericArgData::Ty(ty) => ty.inference_var(Interner), - chalk_ir::GenericArgData::Lifetime(lt) => lt.inference_var(Interner), - chalk_ir::GenericArgData::Const(c) => c.inference_var(Interner), + GenericArgData::Ty(ty) => ty.inference_var(Interner), + GenericArgData::Lifetime(lt) => lt.inference_var(Interner), + GenericArgData::Const(c) => c.inference_var(Interner), } .expect("free var is not inference var"); if self.var_unification_table.probe_var(iv).is_some() { @@ -690,14 +684,10 @@ impl<'a> InferenceTable<'a> { .fill(|it| { let arg = match it { ParamKind::Type => self.new_type_var(), - ParamKind::Const(ty) => { - never!("Tuple with const parameter"); - return GenericArgData::Const(self.new_const_var(ty.clone())) - .intern(Interner); - } + ParamKind::Const(_) => unreachable!("Tuple with const parameter"), }; arg_tys.push(arg.clone()); - GenericArgData::Ty(arg).intern(Interner) + arg.cast(Interner) }) .build(); diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 2837f400bceb..20dccfafb385 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -58,10 +58,9 @@ use crate::{ InTypeConstIdMetadata, }, AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy, - FnPointer, FnSig, FnSubst, GenericArgData, ImplTraitId, Interner, ParamKind, PolyFnSig, - ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, ReturnTypeImplTrait, - ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, - TyKind, WhereClause, + FnPointer, FnSig, FnSubst, ImplTraitId, Interner, ParamKind, PolyFnSig, ProjectionTy, + QuantifiedWhereClause, QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits, + Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause, }; #[derive(Debug)] @@ -1643,9 +1642,7 @@ pub(crate) fn generic_defaults_recover( .iter_id() .map(|id| { let val = match id { - Either::Left(_) => { - GenericArgData::Ty(TyKind::Error.intern(Interner)).intern(Interner) - } + Either::Left(_) => TyKind::Error.intern(Interner).cast(Interner), Either::Right(id) => unknown_const_as_generic(db.const_param_ty(id)), }; crate::make_binders(db, &generic_params, val) @@ -1991,16 +1988,9 @@ pub(crate) fn generic_arg_to_chalk<'a, T>( } }; Some(match (arg, kind) { - (GenericArg::Type(type_ref), ParamKind::Type) => { - let ty = for_type(this, type_ref); - GenericArgData::Ty(ty).intern(Interner) - } - (GenericArg::Const(c), ParamKind::Const(c_ty)) => { - GenericArgData::Const(for_const(this, c, c_ty)).intern(Interner) - } - (GenericArg::Const(_), ParamKind::Type) => { - GenericArgData::Ty(TyKind::Error.intern(Interner)).intern(Interner) - } + (GenericArg::Type(type_ref), ParamKind::Type) => for_type(this, type_ref).cast(Interner), + (GenericArg::Const(c), ParamKind::Const(c_ty)) => for_const(this, c, c_ty).cast(Interner), + (GenericArg::Const(_), ParamKind::Type) => TyKind::Error.intern(Interner).cast(Interner), (GenericArg::Type(t), ParamKind::Const(c_ty)) => { // We want to recover simple idents, which parser detects them // as types. Maybe here is not the best place to do it, but @@ -2010,9 +2000,7 @@ pub(crate) fn generic_arg_to_chalk<'a, T>( if p.kind == PathKind::Plain { if let [n] = p.segments() { let c = ConstRef::Path(n.clone()); - return Some( - GenericArgData::Const(for_const(this, &c, c_ty)).intern(Interner), - ); + return Some(for_const(this, &c, c_ty).cast(Interner)); } } } diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 9e30eed56f3a..12f82640102a 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -10,7 +10,7 @@ use std::{ }; use base_db::{CrateId, FileId}; -use chalk_ir::Mutability; +use chalk_ir::{cast::Cast, Mutability}; use either::Either; use hir_def::{ builtin_type::BuiltinType, @@ -40,8 +40,8 @@ use crate::{ name, static_lifetime, traits::FnTrait, utils::{detect_variant_from_bytes, ClosureSubst}, - CallableDefId, ClosureId, Const, ConstScalar, FnDefId, GenericArgData, Interner, MemoryMap, - Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, + CallableDefId, ClosureId, Const, ConstScalar, FnDefId, Interner, MemoryMap, Substitution, + TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, }; use super::{ @@ -2248,7 +2248,7 @@ impl Evaluator<'_> { interval: args_for_target[0].interval.slice(0..self.ptr_size()), ty: ty.clone(), }; - let ty = GenericArgData::Ty(ty.clone()).intern(Interner); + let ty = ty.clone().cast(Interner); let generics_for_target = Substitution::from_iter( Interner, generic_args.iter(Interner).enumerate().map(|(i, it)| { diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index bf041b61f2fb..964fa7875835 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -1273,7 +1273,7 @@ impl Adt { .fill(|x| { let r = it.next().unwrap_or_else(|| TyKind::Error.intern(Interner)); match x { - ParamKind::Type => GenericArgData::Ty(r).intern(Interner), + ParamKind::Type => r.cast(Interner), ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), } }) @@ -3716,7 +3716,7 @@ impl Type { .fill(|x| { let r = it.next().unwrap(); match x { - ParamKind::Type => GenericArgData::Ty(r).intern(Interner), + ParamKind::Type => r.cast(Interner), ParamKind::Const(ty) => { // FIXME: this code is not covered in tests. unknown_const_as_generic(ty.clone()) @@ -3749,9 +3749,7 @@ impl Type { .fill(|it| { // FIXME: this code is not covered in tests. match it { - ParamKind::Type => { - GenericArgData::Ty(args.next().unwrap().ty.clone()).intern(Interner) - } + ParamKind::Type => args.next().unwrap().ty.clone().cast(Interner), ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), } }) From 3bfe1d5d78e09aa1ba59b9d5740b211e7e0ce1a5 Mon Sep 17 00:00:00 2001 From: oxalica Date: Wed, 9 Aug 2023 00:04:55 +0800 Subject: [PATCH 029/197] Display fully qualified associated types correctly Currently they are formatted in the internal `Trait::Assoc` forms where `hir_ty::TypeRef` is formatted, like hover. --- crates/hir-ty/src/display.rs | 42 ++++++++++++++++++++++++++++------ crates/ide/src/hover/tests.rs | 43 +++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 7 deletions(-) diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 1b4ee4613d61..f6d6b00d740a 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -1809,6 +1809,25 @@ impl HirDisplay for Path { } } + // Convert trait's `Self` bound back to the surface syntax. Note there is no associated + // trait, so there can only be one path segment that `has_self_type`. The `Self` type + // itself can contain further qualified path through, which will be handled by recursive + // `hir_fmt`s. + // + // `trait_mod::Trait::Assoc` + // => + // `>::Assoc` + let trait_self_ty = self.segments().iter().find_map(|seg| { + let generic_args = seg.args_and_bindings?; + generic_args.has_self_type.then(|| &generic_args.args[0]) + }); + if let Some(ty) = trait_self_ty { + write!(f, "<")?; + ty.hir_fmt(f)?; + write!(f, " as ")?; + // Now format the path of the trait... + } + for (seg_idx, segment) in self.segments().iter().enumerate() { if !matches!(self.kind(), PathKind::Plain) || seg_idx > 0 { write!(f, "::")?; @@ -1840,15 +1859,12 @@ impl HirDisplay for Path { return Ok(()); } - write!(f, "<")?; let mut first = true; - for arg in generic_args.args.iter() { + // Skip the `Self` bound if exists. It's handled outside the loop. + for arg in &generic_args.args[generic_args.has_self_type as usize..] { if first { first = false; - if generic_args.has_self_type { - // FIXME: Convert to `` form. - write!(f, "Self = ")?; - } + write!(f, "<")?; } else { write!(f, ", ")?; } @@ -1857,6 +1873,7 @@ impl HirDisplay for Path { for binding in generic_args.bindings.iter() { if first { first = false; + write!(f, "<")?; } else { write!(f, ", ")?; } @@ -1872,9 +1889,20 @@ impl HirDisplay for Path { } } } - write!(f, ">")?; + + // There may be no generic arguments to print, in case of a trait having only a + // single `Self` bound which is converted to `::Assoc`. + if !first { + write!(f, ">")?; + } + + // Current position: `|` + if generic_args.has_self_type { + write!(f, ">")?; + } } } + Ok(()) } } diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 133a488e1dee..541cce8c5bfe 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -1556,6 +1556,49 @@ fn test_hover_function_show_types() { ); } +#[test] +fn test_hover_function_associated_type_params() { + check( + r#" +trait Foo { type Bar; } +impl Foo for i32 { type Bar = i64; } +fn foo(arg: ::Bar) {} +fn main() { foo$0; } +"#, + expect![[r#" + *foo* + + ```rust + test + ``` + + ```rust + fn foo(arg: ::Bar) + ``` + "#]], + ); + + check( + r#" +trait Foo { type Bar; } +impl Foo for i32 { type Bar = i32; } +fn foo(arg: <>::Bar as Foo>::Bar) {} +fn main() { foo$0; } +"#, + expect![[r#" + *foo* + + ```rust + test + ``` + + ```rust + fn foo(arg: <>::Bar as Foo>::Bar) + ``` + "#]], + ); +} + #[test] fn test_hover_function_pointer_show_identifiers() { check( From 52b43927240ca8c77ef24b92a580b9e9291e17f8 Mon Sep 17 00:00:00 2001 From: ponyii Date: Fri, 30 Jun 2023 17:31:04 +0400 Subject: [PATCH 030/197] the "add missing members" assists: implemented substitution of default values of const params --- crates/hir-def/src/generics.rs | 8 +-- crates/hir-def/src/hir/type_ref.rs | 11 +++ crates/hir-ty/src/lib.rs | 12 +++- crates/hir-ty/src/lower.rs | 71 +++++++++---------- crates/hir/src/lib.rs | 23 ++++-- .../src/handlers/add_missing_impl_members.rs | 39 +++++++++- crates/ide-db/src/path_transform.rs | 10 ++- crates/syntax/src/ast/make.rs | 5 ++ 8 files changed, 127 insertions(+), 52 deletions(-) diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index 540fa115a00b..531a503c1b64 100644 --- a/crates/hir-def/src/generics.rs +++ b/crates/hir-def/src/generics.rs @@ -25,7 +25,7 @@ use crate::{ lower::LowerCtx, nameres::{DefMap, MacroSubNs}, src::{HasChildSource, HasSource}, - type_ref::{LifetimeRef, TypeBound, TypeRef}, + type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef}, AdtId, ConstParamId, GenericDefId, HasModule, LifetimeParamId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId, }; @@ -49,7 +49,7 @@ pub struct LifetimeParamData { pub struct ConstParamData { pub name: Name, pub ty: Interned, - pub has_default: bool, + pub default: Option, } #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] @@ -76,7 +76,7 @@ impl TypeOrConstParamData { pub fn has_default(&self) -> bool { match self { TypeOrConstParamData::TypeParamData(it) => it.default.is_some(), - TypeOrConstParamData::ConstParamData(it) => it.has_default, + TypeOrConstParamData::ConstParamData(it) => it.default.is_some(), } } @@ -307,7 +307,7 @@ impl GenericParams { let param = ConstParamData { name, ty: Interned::new(ty), - has_default: const_param.default_val().is_some(), + default: ConstRef::from_default_param_value(lower_ctx, const_param), }; let idx = self.type_or_consts.alloc(param.into()); add_param_attrs(idx.into(), ast::GenericParam::ConstParam(const_param)); diff --git a/crates/hir-def/src/hir/type_ref.rs b/crates/hir-def/src/hir/type_ref.rs index 57f023ef35d4..e2d24625cea7 100644 --- a/crates/hir-def/src/hir/type_ref.rs +++ b/crates/hir-def/src/hir/type_ref.rs @@ -393,6 +393,17 @@ impl ConstRef { Self::Scalar(LiteralConstRef::Unknown) } + pub(crate) fn from_default_param_value( + _: &LowerCtx<'_>, + param: ast::ConstParam, + ) -> Option { + if let Some(expr) = param.default_val() { + // FIXME: pass the `ast_id` arg to recognize complex expressions + return Some(Self::from_expr(expr, None)); + } + None + } + pub fn display<'a>(&'a self, db: &'a dyn ExpandDatabase) -> impl fmt::Display + 'a { struct Display<'a>(&'a dyn ExpandDatabase, &'a ConstRef); impl fmt::Display for Display<'_> { diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index b3ca2a222580..1595622d2b20 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -57,7 +57,8 @@ use triomphe::Arc; use utils::Generics; use crate::{ - consteval::unknown_const, db::HirDatabase, infer::unify::InferenceTable, utils::generics, + consteval::unknown_const, db::HirDatabase, display::HirDisplay, infer::unify::InferenceTable, + utils::generics, }; pub use autoderef::autoderef; @@ -719,3 +720,12 @@ where value.visit_with(&mut collector, DebruijnIndex::INNERMOST); collector.placeholders.into_iter().collect() } + +pub fn known_const_to_string(konst: &Const, db: &dyn HirDatabase) -> Option { + if let ConstValue::Concrete(c) = &konst.interned().value { + if c.interned == ConstScalar::Unknown { + return None; + } + } + Some(konst.display(db).to_string()) +} diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 2837f400bceb..419a50ebe5fc 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -213,6 +213,19 @@ impl<'a> TyLoweringContext<'a> { self.lower_ty_ext(type_ref).0 } + pub fn lower_const(&self, const_ref: &ConstRef, const_type: Ty) -> Const { + const_or_path_to_chalk( + self.db, + self.resolver, + self.owner, + const_type, + const_ref, + self.type_param_mode, + || self.generics(), + self.in_binders, + ) + } + fn generics(&self) -> Generics { generics( self.db.upcast(), @@ -242,17 +255,7 @@ impl<'a> TyLoweringContext<'a> { } TypeRef::Array(inner, len) => { let inner_ty = self.lower_ty(inner); - let const_len = const_or_path_to_chalk( - self.db, - self.resolver, - self.owner, - TyBuilder::usize(), - len, - self.type_param_mode, - || self.generics(), - self.in_binders, - ); - + let const_len = self.lower_const(len, TyBuilder::usize()); TyKind::Array(inner_ty, const_len).intern(Interner) } TypeRef::Slice(inner) => { @@ -847,18 +850,7 @@ impl<'a> TyLoweringContext<'a> { arg, &mut (), |_, type_ref| self.lower_ty(type_ref), - |_, c, ty| { - const_or_path_to_chalk( - self.db, - self.resolver, - self.owner, - ty, - c, - self.type_param_mode, - || self.generics(), - self.in_binders, - ) - }, + |_, const_ref, ty| self.lower_const(const_ref, ty), ) { had_explicit_args = true; substs.push(x); @@ -1604,24 +1596,31 @@ pub(crate) fn generic_defaults_query( .iter() .enumerate() .map(|(idx, (id, p))| { - let p = match p { - TypeOrConstParamData::TypeParamData(p) => p, - TypeOrConstParamData::ConstParamData(_) => { - // FIXME: implement const generic defaults - let val = unknown_const_as_generic( + match p { + TypeOrConstParamData::TypeParamData(p) => { + let mut ty = p + .default + .as_ref() + .map_or(TyKind::Error.intern(Interner), |t| ctx.lower_ty(t)); + // Each default can only refer to previous parameters. + // Type variable default referring to parameter coming + // after it is forbidden (FIXME: report diagnostic) + ty = fallback_bound_vars(ty, idx, parent_start_idx); + return crate::make_binders(db, &generic_params, ty.cast(Interner)); + } + TypeOrConstParamData::ConstParamData(p) => { + let unknown = unknown_const_as_generic( db.const_param_ty(ConstParamId::from_unchecked(id)), ); + let val = p.default.as_ref().map_or(unknown, |c| { + let c = ctx.lower_const(c, ctx.lower_ty(&p.ty)); + chalk_ir::GenericArg::new(Interner, GenericArgData::Const(c)) + }); + // FIXME: check if complex default values refer to + // previous parameters they should not. return make_binders(db, &generic_params, val); } }; - let mut ty = - p.default.as_ref().map_or(TyKind::Error.intern(Interner), |t| ctx.lower_ty(t)); - - // Each default can only refer to previous parameters. - // Type variable default referring to parameter coming - // after it is forbidden (FIXME: report diagnostic) - ty = fallback_bound_vars(ty, idx, parent_start_idx); - crate::make_binders(db, &generic_params, ty.cast(Interner)) }) // FIXME: use `Arc::from_iter` when it becomes available .collect::>(), diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index de60c88844de..b577b3fb3279 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -62,13 +62,13 @@ use hir_expand::{name::name, MacroCallKind}; use hir_ty::{ all_super_traits, autoderef, consteval::{try_const_usize, unknown_const_as_generic, ConstEvalError, ConstExt}, - diagnostics::BodyValidationDiagnostic, + diagnostics::BodyValidationDiagnostic, known_const_to_string, layout::{Layout as TyLayout, RustcEnumVariantIdx, TagEncoding}, method_resolution::{self, TyFingerprint}, mir::{self, interpret_mir}, primitive::UintTy, traits::FnTrait, - AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, + AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg, GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution, TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, ValueTyDefId, WhereClause, @@ -3142,12 +3142,8 @@ impl TypeParam { } pub fn default(self, db: &dyn HirDatabase) -> Option { - let params = db.generic_defaults(self.id.parent()); - let local_idx = hir_ty::param_idx(db, self.id.into())?; + let ty = generic_arg_from_param(db, self.id.into())?; let resolver = self.id.parent().resolver(db.upcast()); - let ty = params.get(local_idx)?.clone(); - let subst = TyBuilder::placeholder_subst(db, self.id.parent()); - let ty = ty.substitute(Interner, &subst); match ty.data(Interner) { GenericArgData::Ty(it) => { Some(Type::new_with_resolver_inner(db, &resolver, it.clone())) @@ -3209,6 +3205,19 @@ impl ConstParam { pub fn ty(self, db: &dyn HirDatabase) -> Type { Type::new(db, self.id.parent(), db.const_param_ty(self.id)) } + + pub fn default(self, db: &dyn HirDatabase) -> Option { + let arg = generic_arg_from_param(db, self.id.into())?; + known_const_to_string(arg.constant(Interner)?, db) + } +} + +fn generic_arg_from_param(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option { + let params = db.generic_defaults(id.parent); + let local_idx = hir_ty::param_idx(db, id)?; + let ty = params.get(local_idx)?.clone(); + let subst = TyBuilder::placeholder_subst(db, id.parent); + Some(ty.substitute(Interner, &subst)) } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] diff --git a/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/crates/ide-assists/src/handlers/add_missing_impl_members.rs index 6aca716bb60a..ea659a2295dd 100644 --- a/crates/ide-assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ide-assists/src/handlers/add_missing_impl_members.rs @@ -422,7 +422,7 @@ impl<'x, 'y, T, V, U: Default> Trait<'x, 'y, T, V, U> for () { check_assist( add_missing_default_members, r#" -struct Bar { +struct Bar { bar: [i32, N] } @@ -439,7 +439,7 @@ impl Foo for S { $0 }"#, r#" -struct Bar { +struct Bar { bar: [i32, N] } @@ -483,6 +483,41 @@ impl Foo<42, {20 + 22}, X> for () { ) } + #[test] + fn test_const_substitution_with_defaults() { + check_assist( + add_missing_default_members, + r#" +trait Foo { + fn get_n(&self) -> usize { N } + fn get_m(&self) -> bool { M } + fn get_p(&self) -> char { P } + fn get_array(&self, arg: &T) -> [bool; N] { [M; N] } +} + +impl Foo for () { + $0 +}"#, + r#" +trait Foo { + fn get_n(&self) -> usize { N } + fn get_m(&self) -> bool { M } + fn get_p(&self) -> char { P } + fn get_array(&self, arg: &T) -> [bool; N] { [M; N] } +} + +impl Foo for () { + $0fn get_n(&self) -> usize { 42 } + + fn get_m(&self) -> bool { false } + + fn get_p(&self) -> char { 'a' } + + fn get_array(&self, arg: &X) -> [bool; 42] { [false; 42] } +}"#, + ); + } + #[test] fn test_cursor_after_empty_impl_def() { check_assist( diff --git a/crates/ide-db/src/path_transform.rs b/crates/ide-db/src/path_transform.rs index 1d0cb426a57c..cb04a0381bf0 100644 --- a/crates/ide-db/src/path_transform.rs +++ b/crates/ide-db/src/path_transform.rs @@ -158,8 +158,14 @@ impl<'a> PathTransform<'a> { const_substs.insert(k, expr.syntax().clone()); } } - (Either::Left(_), None) => (), // FIXME: get default const value - _ => (), // ignore mismatching params + (Either::Left(k), None) => { + if let Some(default) = k.default(db) { + let default = ast::make::expr_const_value(&default); + const_substs.insert(k, default.syntax().clone_for_update()); + // FIXME: transform the default value + } + } + _ => (), // ignore mismatching params }); let lifetime_substs: FxHashMap<_, _> = self .generic_def diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index 4c6db0ef06cb..1eefd949050c 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs @@ -503,11 +503,16 @@ pub fn hacky_block_expr( pub fn expr_unit() -> ast::Expr { expr_from_text("()") } + pub fn expr_literal(text: &str) -> ast::Literal { assert_eq!(text.trim(), text); ast_from_text(&format!("fn f() {{ let _ = {text}; }}")) } +pub fn expr_const_value(text: &str) -> ast::Expr { + ast_from_text(&format!("trait Foo {{}}")) +} + pub fn expr_empty_block() -> ast::Expr { expr_from_text("{}") } From 4ebdc6f0528365f32db4a529407d26a169c36617 Mon Sep 17 00:00:00 2001 From: ponyii Date: Mon, 10 Jul 2023 17:56:07 +0400 Subject: [PATCH 031/197] syntax update: the default value of `ConstParam` turned from `Expr` into `ConstArg` --- crates/hir-def/src/generics.rs | 2 +- crates/hir-def/src/hir/type_ref.rs | 12 ++++++------ crates/hir-ty/src/lib.rs | 4 ++++ crates/hir/src/lib.rs | 3 ++- .../src/handlers/extract_function.rs | 2 +- crates/ide-db/src/path_transform.rs | 7 ++++--- crates/parser/src/grammar/generic_params.rs | 2 +- ...0022_recover_from_missing_const_default.rast | 6 ++++-- .../ok/0188_const_param_default_path.rast | 15 ++++++++------- .../ok/0199_const_param_default_expression.rast | 17 +++++++++-------- .../ok/0200_const_param_default_literal.rast | 9 +++++---- crates/syntax/rust.ungram | 2 +- crates/syntax/src/ast/generated/nodes.rs | 2 +- crates/syntax/src/ast/make.rs | 2 +- 14 files changed, 48 insertions(+), 37 deletions(-) diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index 531a503c1b64..7ee27d26709a 100644 --- a/crates/hir-def/src/generics.rs +++ b/crates/hir-def/src/generics.rs @@ -307,7 +307,7 @@ impl GenericParams { let param = ConstParamData { name, ty: Interned::new(ty), - default: ConstRef::from_default_param_value(lower_ctx, const_param), + default: ConstRef::from_const_param(lower_ctx, const_param), }; let idx = self.type_or_consts.alloc(param.into()); add_param_attrs(idx.into(), ast::GenericParam::ConstParam(const_param)); diff --git a/crates/hir-def/src/hir/type_ref.rs b/crates/hir-def/src/hir/type_ref.rs index e2d24625cea7..c518f1b75b39 100644 --- a/crates/hir-def/src/hir/type_ref.rs +++ b/crates/hir-def/src/hir/type_ref.rs @@ -393,15 +393,15 @@ impl ConstRef { Self::Scalar(LiteralConstRef::Unknown) } - pub(crate) fn from_default_param_value( - _: &LowerCtx<'_>, + pub(crate) fn from_const_param( + lower_ctx: &LowerCtx<'_>, param: ast::ConstParam, ) -> Option { - if let Some(expr) = param.default_val() { - // FIXME: pass the `ast_id` arg to recognize complex expressions - return Some(Self::from_expr(expr, None)); + let default = param.default_val(); + match default { + Some(_) => Some(Self::from_const_arg(lower_ctx, default)), + None => None, } - None } pub fn display<'a>(&'a self, db: &'a dyn ExpandDatabase) -> impl fmt::Display + 'a { diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index 1595622d2b20..14346c279414 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -723,6 +723,10 @@ where pub fn known_const_to_string(konst: &Const, db: &dyn HirDatabase) -> Option { if let ConstValue::Concrete(c) = &konst.interned().value { + if let ConstScalar::UnevaluatedConst(GeneralConstId::InTypeConstId(_), _) = &c.interned { + // FIXME: stringify the block expression + return None; + } if c.interned == ConstScalar::Unknown { return None; } diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index b577b3fb3279..136b1b08533c 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -62,7 +62,8 @@ use hir_expand::{name::name, MacroCallKind}; use hir_ty::{ all_super_traits, autoderef, consteval::{try_const_usize, unknown_const_as_generic, ConstEvalError, ConstExt}, - diagnostics::BodyValidationDiagnostic, known_const_to_string, + diagnostics::BodyValidationDiagnostic, + known_const_to_string, layout::{Layout as TyLayout, RustcEnumVariantIdx, TagEncoding}, method_resolution::{self, TyFingerprint}, mir::{self, interpret_mir}, diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs index 7f61a68284cf..1340681ccab5 100644 --- a/crates/ide-assists/src/handlers/extract_function.rs +++ b/crates/ide-assists/src/handlers/extract_function.rs @@ -810,7 +810,7 @@ impl FunctionBody { (true, konst.body(), Some(sema.to_def(&konst)?.ty(sema.db))) }, ast::ConstParam(cp) => { - (true, cp.default_val(), Some(sema.to_def(&cp)?.ty(sema.db))) + (true, cp.default_val()?.expr(), Some(sema.to_def(&cp)?.ty(sema.db))) }, ast::ConstBlockPat(cbp) => { let expr = cbp.block_expr().map(ast::Expr::BlockExpr); diff --git a/crates/ide-db/src/path_transform.rs b/crates/ide-db/src/path_transform.rs index cb04a0381bf0..507200ea3ba1 100644 --- a/crates/ide-db/src/path_transform.rs +++ b/crates/ide-db/src/path_transform.rs @@ -160,9 +160,10 @@ impl<'a> PathTransform<'a> { } (Either::Left(k), None) => { if let Some(default) = k.default(db) { - let default = ast::make::expr_const_value(&default); - const_substs.insert(k, default.syntax().clone_for_update()); - // FIXME: transform the default value + if let Some(default) = ast::make::expr_const_value(&default).expr() { + const_substs.insert(k, default.syntax().clone_for_update()); + // FIXME: transform the default value + } } } _ => (), // ignore mismatching params diff --git a/crates/parser/src/grammar/generic_params.rs b/crates/parser/src/grammar/generic_params.rs index 8ed1c84c4c64..29d9b05d3f33 100644 --- a/crates/parser/src/grammar/generic_params.rs +++ b/crates/parser/src/grammar/generic_params.rs @@ -88,7 +88,7 @@ fn const_param(p: &mut Parser<'_>, m: Marker) { // test const_param_default_path // struct A; - generic_args::const_arg_expr(p); + generic_args::const_arg(p); } m.complete(p, CONST_PARAM); diff --git a/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rast b/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rast index 809ad1b8d5b9..49f163b164ae 100644 --- a/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rast +++ b/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rast @@ -20,7 +20,8 @@ SOURCE_FILE IDENT "i32" WHITESPACE " " EQ "=" - WHITESPACE " " + WHITESPACE " " + CONST_ARG COMMA "," WHITESPACE " " CONST_PARAM @@ -37,8 +38,9 @@ SOURCE_FILE IDENT "i32" WHITESPACE " " EQ "=" + CONST_ARG R_ANGLE ">" SEMICOLON ";" WHITESPACE "\n" -error 23: expected a generic const argument +error 24: expected a generic const argument error 40: expected a generic const argument diff --git a/crates/parser/test_data/parser/inline/ok/0188_const_param_default_path.rast b/crates/parser/test_data/parser/inline/ok/0188_const_param_default_path.rast index 11002bf98d01..3f5fb47d2875 100644 --- a/crates/parser/test_data/parser/inline/ok/0188_const_param_default_path.rast +++ b/crates/parser/test_data/parser/inline/ok/0188_const_param_default_path.rast @@ -21,16 +21,17 @@ SOURCE_FILE WHITESPACE " " EQ "=" WHITESPACE " " - PATH_EXPR - PATH + CONST_ARG + PATH_EXPR PATH + PATH + PATH_SEGMENT + NAME_REF + IDENT "i32" + COLON2 "::" PATH_SEGMENT NAME_REF - IDENT "i32" - COLON2 "::" - PATH_SEGMENT - NAME_REF - IDENT "MAX" + IDENT "MAX" R_ANGLE ">" SEMICOLON ";" WHITESPACE "\n" diff --git a/crates/parser/test_data/parser/inline/ok/0199_const_param_default_expression.rast b/crates/parser/test_data/parser/inline/ok/0199_const_param_default_expression.rast index 0607ff54fbb7..d6501137498a 100644 --- a/crates/parser/test_data/parser/inline/ok/0199_const_param_default_expression.rast +++ b/crates/parser/test_data/parser/inline/ok/0199_const_param_default_expression.rast @@ -21,14 +21,15 @@ SOURCE_FILE WHITESPACE " " EQ "=" WHITESPACE " " - BLOCK_EXPR - STMT_LIST - L_CURLY "{" - WHITESPACE " " - LITERAL - INT_NUMBER "1" - WHITESPACE " " - R_CURLY "}" + CONST_ARG + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE " " + LITERAL + INT_NUMBER "1" + WHITESPACE " " + R_CURLY "}" R_ANGLE ">" SEMICOLON ";" WHITESPACE "\n" diff --git a/crates/parser/test_data/parser/inline/ok/0200_const_param_default_literal.rast b/crates/parser/test_data/parser/inline/ok/0200_const_param_default_literal.rast index 8e52313651ce..6de10353bf06 100644 --- a/crates/parser/test_data/parser/inline/ok/0200_const_param_default_literal.rast +++ b/crates/parser/test_data/parser/inline/ok/0200_const_param_default_literal.rast @@ -21,10 +21,11 @@ SOURCE_FILE WHITESPACE " " EQ "=" WHITESPACE " " - PREFIX_EXPR - MINUS "-" - LITERAL - INT_NUMBER "1" + CONST_ARG + PREFIX_EXPR + MINUS "-" + LITERAL + INT_NUMBER "1" R_ANGLE ">" SEMICOLON ";" WHITESPACE "\n" diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram index 138ddd208979..ea7ebd85b335 100644 --- a/crates/syntax/rust.ungram +++ b/crates/syntax/rust.ungram @@ -296,7 +296,7 @@ TypeParam = ConstParam = Attr* 'const' Name ':' Type - ('=' default_val:Expr)? + ('=' default_val:ConstArg)? LifetimeParam = Attr* Lifetime (':' TypeBoundList?)? diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index 0b27faa535da..16448db04f8f 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -709,7 +709,7 @@ impl ConstParam { pub fn colon_token(&self) -> Option { support::token(&self.syntax, T![:]) } pub fn ty(&self) -> Option { support::child(&self.syntax) } pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } - pub fn default_val(&self) -> Option { support::child(&self.syntax) } + pub fn default_val(&self) -> Option { support::child(&self.syntax) } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index 1eefd949050c..217134385afb 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs @@ -509,7 +509,7 @@ pub fn expr_literal(text: &str) -> ast::Literal { ast_from_text(&format!("fn f() {{ let _ = {text}; }}")) } -pub fn expr_const_value(text: &str) -> ast::Expr { +pub fn expr_const_value(text: &str) -> ast::ConstArg { ast_from_text(&format!("trait Foo {{}}")) } From 4e2be8e959179f8b7f9614e1d147b878bbd2f071 Mon Sep 17 00:00:00 2001 From: ponyii Date: Tue, 11 Jul 2023 18:46:39 +0400 Subject: [PATCH 032/197] the "add missing members" assists: implemented the transformation of const param default values --- crates/hir-ty/src/lower.rs | 6 ++-- .../src/handlers/add_missing_impl_members.rs | 31 +++++++++++++++++++ crates/ide-db/src/path_transform.rs | 23 +++++++++----- 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 419a50ebe5fc..a885c32e7f94 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -1612,12 +1612,12 @@ pub(crate) fn generic_defaults_query( let unknown = unknown_const_as_generic( db.const_param_ty(ConstParamId::from_unchecked(id)), ); - let val = p.default.as_ref().map_or(unknown, |c| { + let mut val = p.default.as_ref().map_or(unknown, |c| { let c = ctx.lower_const(c, ctx.lower_ty(&p.ty)); chalk_ir::GenericArg::new(Interner, GenericArgData::Const(c)) }); - // FIXME: check if complex default values refer to - // previous parameters they should not. + // Each default can only refer to previous parameters, see above. + val = fallback_bound_vars(val, idx, parent_start_idx); return make_binders(db, &generic_params, val); } }; diff --git a/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/crates/ide-assists/src/handlers/add_missing_impl_members.rs index ea659a2295dd..d9faf3a7f6c1 100644 --- a/crates/ide-assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ide-assists/src/handlers/add_missing_impl_members.rs @@ -518,6 +518,37 @@ impl Foo for () { ); } + #[test] + fn test_const_substitution_with_defaults_2() { + check_assist( + add_missing_impl_members, + r#" +mod m { + pub const LEN: usize = 42; + pub trait Foo { + fn get_t(&self) -> T; + } +} + +impl m::Foo for () { + $0 +}"#, + r#" +mod m { + pub const LEN: usize = 42; + pub trait Foo { + fn get_t(&self) -> T; + } +} + +impl m::Foo for () { + fn get_t(&self) -> [bool; m::LEN] { + ${0:todo!()} + } +}"#, + ) + } + #[test] fn test_cursor_after_empty_impl_def() { check_assist( diff --git a/crates/ide-db/src/path_transform.rs b/crates/ide-db/src/path_transform.rs index 507200ea3ba1..efe13f060408 100644 --- a/crates/ide-db/src/path_transform.rs +++ b/crates/ide-db/src/path_transform.rs @@ -21,6 +21,7 @@ enum TypeOrConst { } type LifetimeName = String; +type DefaultedParam = Either; /// `PathTransform` substitutes path in SyntaxNodes in bulk. /// @@ -115,7 +116,7 @@ impl<'a> PathTransform<'a> { }; let mut type_substs: FxHashMap = Default::default(); let mut const_substs: FxHashMap = Default::default(); - let mut default_types: Vec = Default::default(); + let mut defaulted_params: Vec = Default::default(); self.generic_def .into_iter() .flat_map(|it| it.type_params(db)) @@ -139,7 +140,7 @@ impl<'a> PathTransform<'a> { &default.display_source_code(db, source_module.into(), false).ok() { type_substs.insert(k, ast::make::ty(default).clone_for_update()); - default_types.push(k); + defaulted_params.push(Either::Left(k)); } } } @@ -162,7 +163,7 @@ impl<'a> PathTransform<'a> { if let Some(default) = k.default(db) { if let Some(default) = ast::make::expr_const_value(&default).expr() { const_substs.insert(k, default.syntax().clone_for_update()); - // FIXME: transform the default value + defaulted_params.push(Either::Right(k)); } } } @@ -182,7 +183,7 @@ impl<'a> PathTransform<'a> { target_module, source_scope: self.source_scope, }; - ctx.transform_default_type_substs(default_types); + ctx.transform_default_values(defaulted_params); ctx } } @@ -219,13 +220,19 @@ impl Ctx<'_> { }); } - fn transform_default_type_substs(&self, default_types: Vec) { - for k in default_types { - let v = self.type_substs.get(&k).unwrap(); + fn transform_default_values(&self, defaulted_params: Vec) { + // By now the default values are simply copied from where they are declared + // and should be transformed. As any value is allowed to refer to previous + // generic (both type and const) parameters, they should be all iterated left-to-right. + for param in defaulted_params { + let value = match param { + Either::Left(k) => self.type_substs.get(&k).unwrap().syntax(), + Either::Right(k) => self.const_substs.get(&k).unwrap(), + }; // `transform_path` may update a node's parent and that would break the // tree traversal. Thus all paths in the tree are collected into a vec // so that such operation is safe. - let paths = postorder(&v.syntax()).filter_map(ast::Path::cast).collect::>(); + let paths = postorder(value).filter_map(ast::Path::cast).collect::>(); for path in paths { self.transform_path(path); } From 61cabe029fcd74aae6a2811768bc7f46f22354fe Mon Sep 17 00:00:00 2001 From: ponyii Date: Wed, 12 Jul 2023 18:31:40 +0400 Subject: [PATCH 033/197] the "add missing members" assists: supported bracketed default const values --- crates/hir-ty/src/lib.rs | 13 +++---- .../src/handlers/add_missing_impl_members.rs | 35 +++++++++++++++++++ crates/ide-db/src/path_transform.rs | 1 + 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index 14346c279414..d0bb16c7808f 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -52,6 +52,7 @@ use hir_expand::name; use la_arena::{Arena, Idx}; use mir::{MirEvalError, VTableMap}; use rustc_hash::FxHashSet; +use syntax::AstNode; use traits::FnTrait; use triomphe::Arc; use utils::Generics; @@ -723,12 +724,12 @@ where pub fn known_const_to_string(konst: &Const, db: &dyn HirDatabase) -> Option { if let ConstValue::Concrete(c) = &konst.interned().value { - if let ConstScalar::UnevaluatedConst(GeneralConstId::InTypeConstId(_), _) = &c.interned { - // FIXME: stringify the block expression - return None; - } - if c.interned == ConstScalar::Unknown { - return None; + match c.interned { + ConstScalar::UnevaluatedConst(GeneralConstId::InTypeConstId(cid), _) => { + return Some(cid.source(db.upcast()).syntax().to_string()); + } + ConstScalar::Unknown => return None, + _ => (), } } Some(konst.display(db).to_string()) diff --git a/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/crates/ide-assists/src/handlers/add_missing_impl_members.rs index d9faf3a7f6c1..c0e5429a22c9 100644 --- a/crates/ide-assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ide-assists/src/handlers/add_missing_impl_members.rs @@ -549,6 +549,41 @@ impl m::Foo for () { ) } + #[test] + fn test_const_substitution_with_defaults_3() { + check_assist( + add_missing_default_members, + r#" +mod m { + pub const VAL: usize = 0; + + pub trait Foo { + fn get_n(&self) -> usize { N } + fn get_m(&self) -> usize { M } + } +} + +impl m::Foo for () { + $0 +}"#, + r#" +mod m { + pub const VAL: usize = 0; + + pub trait Foo { + fn get_n(&self) -> usize { N } + fn get_m(&self) -> usize { M } + } +} + +impl m::Foo for () { + $0fn get_n(&self) -> usize { {40 + 2} } + + fn get_m(&self) -> usize { {m::VAL + 1} } +}"#, + ) + } + #[test] fn test_cursor_after_empty_impl_def() { check_assist( diff --git a/crates/ide-db/src/path_transform.rs b/crates/ide-db/src/path_transform.rs index efe13f060408..4bd4f1e845f1 100644 --- a/crates/ide-db/src/path_transform.rs +++ b/crates/ide-db/src/path_transform.rs @@ -156,6 +156,7 @@ impl<'a> PathTransform<'a> { // is a standalone statement or a part of another expresson) // and sometimes require slight modifications; see // https://doc.rust-lang.org/reference/statements.html#expression-statements + // (default values in curly brackets can cause the same problem) const_substs.insert(k, expr.syntax().clone()); } } From e4c45427dc398f7fc8f984d2d1b454f36d718fd9 Mon Sep 17 00:00:00 2001 From: ponyii Date: Tue, 8 Aug 2023 21:51:59 +0400 Subject: [PATCH 034/197] refactoring --- crates/hir-ty/src/lib.rs | 8 +++---- crates/hir-ty/src/lower.rs | 22 ++++++++++++-------- crates/hir/src/lib.rs | 6 +++--- crates/ide-db/src/imports/import_assets.rs | 4 ++-- crates/ide-db/src/path_transform.rs | 13 ++++++------ crates/ide-db/src/use_trivial_constructor.rs | 16 +++++++------- 6 files changed, 35 insertions(+), 34 deletions(-) diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index d0bb16c7808f..405bb001b5d1 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -52,7 +52,7 @@ use hir_expand::name; use la_arena::{Arena, Idx}; use mir::{MirEvalError, VTableMap}; use rustc_hash::FxHashSet; -use syntax::AstNode; +use syntax::ast::{make, ConstArg}; use traits::FnTrait; use triomphe::Arc; use utils::Generics; @@ -722,15 +722,15 @@ where collector.placeholders.into_iter().collect() } -pub fn known_const_to_string(konst: &Const, db: &dyn HirDatabase) -> Option { +pub fn known_const_to_ast(konst: &Const, db: &dyn HirDatabase) -> Option { if let ConstValue::Concrete(c) = &konst.interned().value { match c.interned { ConstScalar::UnevaluatedConst(GeneralConstId::InTypeConstId(cid), _) => { - return Some(cid.source(db.upcast()).syntax().to_string()); + return Some(cid.source(db.upcast())); } ConstScalar::Unknown => return None, _ => (), } } - Some(konst.display(db).to_string()) + Some(make::expr_const_value(konst.display(db).to_string().as_str())) } diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index a885c32e7f94..da5ee6fc428f 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -1606,21 +1606,25 @@ pub(crate) fn generic_defaults_query( // Type variable default referring to parameter coming // after it is forbidden (FIXME: report diagnostic) ty = fallback_bound_vars(ty, idx, parent_start_idx); - return crate::make_binders(db, &generic_params, ty.cast(Interner)); + crate::make_binders(db, &generic_params, ty.cast(Interner)) } TypeOrConstParamData::ConstParamData(p) => { - let unknown = unknown_const_as_generic( - db.const_param_ty(ConstParamId::from_unchecked(id)), + let mut val = p.default.as_ref().map_or_else( + || { + unknown_const_as_generic( + db.const_param_ty(ConstParamId::from_unchecked(id)), + ) + }, + |c| { + let c = ctx.lower_const(c, ctx.lower_ty(&p.ty)); + c.cast(Interner) + }, ); - let mut val = p.default.as_ref().map_or(unknown, |c| { - let c = ctx.lower_const(c, ctx.lower_ty(&p.ty)); - chalk_ir::GenericArg::new(Interner, GenericArgData::Const(c)) - }); // Each default can only refer to previous parameters, see above. val = fallback_bound_vars(val, idx, parent_start_idx); - return make_binders(db, &generic_params, val); + make_binders(db, &generic_params, val) } - }; + } }) // FIXME: use `Arc::from_iter` when it becomes available .collect::>(), diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 136b1b08533c..1d42e97aa3e7 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -63,7 +63,7 @@ use hir_ty::{ all_super_traits, autoderef, consteval::{try_const_usize, unknown_const_as_generic, ConstEvalError, ConstExt}, diagnostics::BodyValidationDiagnostic, - known_const_to_string, + known_const_to_ast, layout::{Layout as TyLayout, RustcEnumVariantIdx, TagEncoding}, method_resolution::{self, TyFingerprint}, mir::{self, interpret_mir}, @@ -3207,9 +3207,9 @@ impl ConstParam { Type::new(db, self.id.parent(), db.const_param_ty(self.id)) } - pub fn default(self, db: &dyn HirDatabase) -> Option { + pub fn default(self, db: &dyn HirDatabase) -> Option { let arg = generic_arg_from_param(db, self.id.into())?; - known_const_to_string(arg.constant(Interner)?, db) + known_const_to_ast(arg.constant(Interner)?, db) } } diff --git a/crates/ide-db/src/imports/import_assets.rs b/crates/ide-db/src/imports/import_assets.rs index e52dc3567754..e475c5cd66b6 100644 --- a/crates/ide-db/src/imports/import_assets.rs +++ b/crates/ide-db/src/imports/import_assets.rs @@ -6,7 +6,7 @@ use hir::{ use itertools::Itertools; use rustc_hash::FxHashSet; use syntax::{ - ast::{self, HasName}, + ast::{self, make, HasName}, utils::path_to_string_stripping_turbo_fish, AstNode, SyntaxNode, }; @@ -607,7 +607,7 @@ impl ImportCandidate { fn for_name(sema: &Semantics<'_, RootDatabase>, name: &ast::Name) -> Option { if sema .scope(name.syntax())? - .speculative_resolve(&ast::make::ext::ident_path(&name.text())) + .speculative_resolve(&make::ext::ident_path(&name.text())) .is_some() { return None; diff --git a/crates/ide-db/src/path_transform.rs b/crates/ide-db/src/path_transform.rs index 4bd4f1e845f1..fb75b5b45848 100644 --- a/crates/ide-db/src/path_transform.rs +++ b/crates/ide-db/src/path_transform.rs @@ -5,7 +5,7 @@ use either::Either; use hir::{AsAssocItem, HirDisplay, SemanticsScope}; use rustc_hash::FxHashMap; use syntax::{ - ast::{self, AstNode}, + ast::{self, make, AstNode}, ted, SyntaxNode, }; @@ -139,7 +139,7 @@ impl<'a> PathTransform<'a> { if let Some(default) = &default.display_source_code(db, source_module.into(), false).ok() { - type_substs.insert(k, ast::make::ty(default).clone_for_update()); + type_substs.insert(k, make::ty(default).clone_for_update()); defaulted_params.push(Either::Left(k)); } } @@ -162,7 +162,7 @@ impl<'a> PathTransform<'a> { } (Either::Left(k), None) => { if let Some(default) = k.default(db) { - if let Some(default) = ast::make::expr_const_value(&default).expr() { + if let Some(default) = default.expr() { const_substs.insert(k, default.syntax().clone_for_update()); defaulted_params.push(Either::Right(k)); } @@ -278,15 +278,14 @@ impl Ctx<'_> { hir::ModuleDef::Trait(trait_ref), false, )?; - match ast::make::ty_path(mod_path_to_ast(&found_path)) { + match make::ty_path(mod_path_to_ast(&found_path)) { ast::Type::PathType(path_ty) => Some(path_ty), _ => None, } }); - let segment = ast::make::path_segment_ty(subst.clone(), trait_ref); - let qualified = - ast::make::path_from_segments(std::iter::once(segment), false); + let segment = make::path_segment_ty(subst.clone(), trait_ref); + let qualified = make::path_from_segments(std::iter::once(segment), false); ted::replace(path.syntax(), qualified.clone_for_update().syntax()); } else if let Some(path_ty) = ast::PathType::cast(parent) { ted::replace( diff --git a/crates/ide-db/src/use_trivial_constructor.rs b/crates/ide-db/src/use_trivial_constructor.rs index f96ea29ae2f9..a915391ad90a 100644 --- a/crates/ide-db/src/use_trivial_constructor.rs +++ b/crates/ide-db/src/use_trivial_constructor.rs @@ -1,31 +1,29 @@ //! Functionality for generating trivial constructors use hir::StructKind; -use syntax::ast; +use syntax::ast::{make, Expr, Path}; /// given a type return the trivial constructor (if one exists) pub fn use_trivial_constructor( db: &crate::RootDatabase, - path: ast::Path, + path: Path, ty: &hir::Type, -) -> Option { +) -> Option { match ty.as_adt() { Some(hir::Adt::Enum(x)) => { if let &[variant] = &*x.variants(db) { if variant.kind(db) == hir::StructKind::Unit { - let path = ast::make::path_qualified( + let path = make::path_qualified( path, - syntax::ast::make::path_segment(ast::make::name_ref( - &variant.name(db).to_smol_str(), - )), + make::path_segment(make::name_ref(&variant.name(db).to_smol_str())), ); - return Some(syntax::ast::make::expr_path(path)); + return Some(make::expr_path(path)); } } } Some(hir::Adt::Struct(x)) if x.kind(db) == StructKind::Unit => { - return Some(syntax::ast::make::expr_path(path)); + return Some(make::expr_path(path)); } _ => {} } From 68e8379ec35f83ce22d3c57bad79e8a7bc7ea231 Mon Sep 17 00:00:00 2001 From: ponyii Date: Tue, 8 Aug 2023 22:16:28 +0400 Subject: [PATCH 035/197] fixed a merge-caused error --- crates/hir-def/src/generics.rs | 2 +- crates/hir-def/src/hir/type_ref.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index 7ee27d26709a..1e2535a8a999 100644 --- a/crates/hir-def/src/generics.rs +++ b/crates/hir-def/src/generics.rs @@ -307,7 +307,7 @@ impl GenericParams { let param = ConstParamData { name, ty: Interned::new(ty), - default: ConstRef::from_const_param(lower_ctx, const_param), + default: ConstRef::from_const_param(lower_ctx, &const_param), }; let idx = self.type_or_consts.alloc(param.into()); add_param_attrs(idx.into(), ast::GenericParam::ConstParam(const_param)); diff --git a/crates/hir-def/src/hir/type_ref.rs b/crates/hir-def/src/hir/type_ref.rs index c518f1b75b39..75adf21abdcb 100644 --- a/crates/hir-def/src/hir/type_ref.rs +++ b/crates/hir-def/src/hir/type_ref.rs @@ -395,7 +395,7 @@ impl ConstRef { pub(crate) fn from_const_param( lower_ctx: &LowerCtx<'_>, - param: ast::ConstParam, + param: &ast::ConstParam, ) -> Option { let default = param.default_val(); match default { From 6a2f83a8a25895922c477eb401f021f410904f9f Mon Sep 17 00:00:00 2001 From: oxalica Date: Wed, 9 Aug 2023 02:22:18 +0800 Subject: [PATCH 036/197] Impl `HirDisplay` for `SelfParam` --- crates/hir/src/display.rs | 63 ++++++++++++++++++++++----------------- crates/hir/src/lib.rs | 8 ----- 2 files changed, 36 insertions(+), 35 deletions(-) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 9dfb98e459b9..a701eb011920 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -8,7 +8,6 @@ use hir_def::{ type_ref::{TypeBound, TypeRef}, AdtId, GenericDefId, }; -use hir_expand::name; use hir_ty::{ display::{ write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError, @@ -19,8 +18,9 @@ use hir_ty::{ use crate::{ Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, Field, - Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, Static, Struct, - Trait, TraitAlias, TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam, Union, Variant, + Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, SelfParam, + Static, Struct, Trait, TraitAlias, TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam, + Union, Variant, }; impl HirDisplay for Function { @@ -57,37 +57,21 @@ impl HirDisplay for Function { f.write_char('(')?; - let write_self_param = |ty: &TypeRef, f: &mut HirFormatter<'_>| match ty { - TypeRef::Path(p) if p.is_self_type() => f.write_str("self"), - TypeRef::Reference(inner, lifetime, mut_) if matches!(&**inner, TypeRef::Path(p) if p.is_self_type()) => - { - f.write_char('&')?; - if let Some(lifetime) = lifetime { - write!(f, "{} ", lifetime.name.display(f.db.upcast()))?; - } - if let hir_def::type_ref::Mutability::Mut = mut_ { - f.write_str("mut ")?; - } - f.write_str("self") - } - _ => { - f.write_str("self: ")?; - ty.hir_fmt(f) - } - }; - let mut first = true; + let mut skip_self = 0; + if let Some(self_param) = self.self_param(db) { + self_param.hir_fmt(f)?; + first = false; + skip_self = 1; + } + // FIXME: Use resolved `param.ty` once we no longer discard lifetimes - for (type_ref, param) in data.params.iter().zip(self.assoc_fn_params(db)) { + for (type_ref, param) in data.params.iter().zip(self.assoc_fn_params(db)).skip(skip_self) { let local = param.as_local(db).map(|it| it.name(db)); if !first { f.write_str(", ")?; } else { first = false; - if local == Some(name!(self)) { - write_self_param(type_ref, f)?; - continue; - } } match local { Some(name) => write!(f, "{}: ", name.display(f.db.upcast()))?, @@ -137,6 +121,31 @@ impl HirDisplay for Function { } } +impl HirDisplay for SelfParam { + fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { + let data = f.db.function_data(self.func); + let param = data.params.first().unwrap(); + match &**param { + TypeRef::Path(p) if p.is_self_type() => f.write_str("self"), + TypeRef::Reference(inner, lifetime, mut_) if matches!(&**inner, TypeRef::Path(p) if p.is_self_type()) => + { + f.write_char('&')?; + if let Some(lifetime) = lifetime { + write!(f, "{} ", lifetime.name.display(f.db.upcast()))?; + } + if let hir_def::type_ref::Mutability::Mut = mut_ { + f.write_str("mut ")?; + } + f.write_str("self") + } + ty => { + f.write_str("self: ")?; + ty.hir_fmt(f) + } + } + } +} + impl HirDisplay for Adt { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { match self { diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index de60c88844de..77cadfbae343 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -2096,14 +2096,6 @@ impl SelfParam { .unwrap_or(Access::Owned) } - pub fn display(self, db: &dyn HirDatabase) -> &'static str { - match self.access(db) { - Access::Shared => "&self", - Access::Exclusive => "&mut self", - Access::Owned => "self", - } - } - pub fn source(&self, db: &dyn HirDatabase) -> Option> { let InFile { file_id, value } = Function::from(self.func).source(db)?; value From de86444756acc30878ed0ca95f686ff02b888b29 Mon Sep 17 00:00:00 2001 From: oxalica Date: Wed, 9 Aug 2023 02:42:08 +0800 Subject: [PATCH 037/197] Prefer `hir::SelfParam` and fix signature help of methods from macros --- crates/hir/src/lib.rs | 7 +++---- crates/ide-ssr/src/matching.rs | 6 ++++-- crates/ide/src/signature_help.rs | 21 ++++++++++++++++++++- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 77cadfbae343..60ab0c267f4b 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -4406,14 +4406,13 @@ impl Callable { Other => CallableKind::Other, } } - pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<(ast::SelfParam, Type)> { + pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<(SelfParam, Type)> { let func = match self.callee { Callee::Def(CallableDefId::FunctionId(it)) if self.is_bound_method => it, _ => return None, }; - let src = func.lookup(db.upcast()).source(db.upcast()); - let param_list = src.value.param_list()?; - Some((param_list.self_param()?, self.ty.derived(self.sig.params()[0].clone()))) + let func = Function { id: func }; + Some((func.self_param(db)?, self.ty.derived(self.sig.params()[0].clone()))) } pub fn n_params(&self) -> usize { self.sig.params().len() - if self.is_bound_method { 1 } else { 0 } diff --git a/crates/ide-ssr/src/matching.rs b/crates/ide-ssr/src/matching.rs index a8e883690883..60fcbbbd3979 100644 --- a/crates/ide-ssr/src/matching.rs +++ b/crates/ide-ssr/src/matching.rs @@ -560,8 +560,10 @@ impl<'db, 'sema> Matcher<'db, 'sema> { placeholder_value.autoref_kind = self .sema .resolve_method_call_as_callable(code) - .and_then(|callable| callable.receiver_param(self.sema.db)) - .map(|(self_param, _)| self_param.kind()) + .and_then(|callable| { + let (self_param, _) = callable.receiver_param(self.sema.db)?; + Some(self_param.source(self.sema.db)?.value.kind()) + }) .unwrap_or(ast::SelfParamKind::Owned); } } diff --git a/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs index 7795be54e264..e3ad817e06ac 100644 --- a/crates/ide/src/signature_help.rs +++ b/crates/ide/src/signature_help.rs @@ -202,7 +202,7 @@ fn signature_help_for_call( res.signature.push('('); { if let Some((self_param, _)) = callable.receiver_param(db) { - format_to!(res.signature, "{}", self_param) + format_to!(res.signature, "{}", self_param.display(db)) } let mut buf = String::new(); for (idx, (pat, ty)) in callable.params(db).into_iter().enumerate() { @@ -1314,6 +1314,25 @@ id! { ); } + #[test] + fn fn_signature_for_method_call_defined_in_macro() { + check( + r#" +macro_rules! id { ($($tt:tt)*) => { $($tt)* } } +struct S; +id! { + impl S { + fn foo<'a>(&'a mut self) {} + } +} +fn test() { S.foo($0); } +"#, + expect![[r#" + fn foo(&'a mut self) + "#]], + ); + } + #[test] fn call_info_for_lambdas() { check( From 021802c59c03b664bb02a1be8eae73ca1114fa26 Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Wed, 9 Aug 2023 00:27:23 +0330 Subject: [PATCH 038/197] Support enum in memory map patch address --- crates/hir-ty/src/consteval/tests.rs | 8 ++++---- crates/hir-ty/src/mir/eval.rs | 23 ++++++++++++++++++++++- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs index 74c62a08a2b7..7ad3659a4f6d 100644 --- a/crates/hir-ty/src/consteval/tests.rs +++ b/crates/hir-ty/src/consteval/tests.rs @@ -2441,14 +2441,14 @@ fn const_loop() { fn const_transfer_memory() { check_number( r#" - //- minicore: slice, index, coerce_unsized + //- minicore: slice, index, coerce_unsized, option const A1: &i32 = &1; const A2: &i32 = &10; const A3: [&i32; 3] = [&1, &2, &100]; - const A4: (i32, &i32) = (1, &1000); - const GOAL: i32 = *A1 + *A2 + *A3[2] + *A4.1; + const A4: (i32, &i32, Option<&i32>) = (1, &1000, Some(&10000)); + const GOAL: i32 = *A1 + *A2 + *A3[2] + *A4.1 + *A4.2.unwrap_or(&5); "#, - 1111, + 11111, ); } diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 9e30eed56f3a..f2114e712114 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -2007,7 +2007,28 @@ impl Evaluator<'_> { } } AdtId::UnionId(_) => (), - AdtId::EnumId(_) => (), + AdtId::EnumId(e) => { + if let Some((variant, layout)) = detect_variant_from_bytes( + &layout, + self.db, + self.trait_env.clone(), + self.read_memory(addr, layout.size.bytes_usize())?, + e, + ) { + let ev = EnumVariantId { parent: e, local_id: variant }; + for (i, (_, ty)) in self.db.field_types(ev.into()).iter().enumerate() { + let offset = layout.fields.offset(i).bytes_usize(); + let ty = ty.clone().substitute(Interner, subst); + self.patch_addresses( + patch_map, + old_vtable, + addr.offset(offset), + &ty, + locals, + )?; + } + } + } }, TyKind::Tuple(_, subst) => { for (id, ty) in subst.iter(Interner).enumerate() { From a1d9e453b9a273db44250baa5f2dc4f261617415 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Tue, 8 Aug 2023 11:06:54 -0400 Subject: [PATCH 039/197] Apply suggestions from code review Co-authored-by: Lukas Wirth --- crates/ide-completion/src/context.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs index 5537673d1ee1..90ad2ecaf910 100644 --- a/crates/ide-completion/src/context.rs +++ b/crates/ide-completion/src/context.rs @@ -169,19 +169,15 @@ pub(crate) enum TypeLocation { impl TypeLocation { pub(crate) fn complete_lifetimes(&self) -> bool { - match self { - TypeLocation::GenericArg(Some((_, _, Some(param)))) => { - matches!(param, ast::GenericParam::LifetimeParam(_)) - } - _ => false, - } + matches!( + self, + TypeLocation::GenericArg(Some((_, _, Some(ast::GenericParam::LifetimeParam(_))))) + ) } pub(crate) fn complete_consts(&self) -> bool { match self { - TypeLocation::GenericArg(Some((_, _, Some(param)))) => { - matches!(param, ast::GenericParam::ConstParam(_)) - } + TypeLocation::GenericArg(Some((_, _, Some(ast::GenericParam::ConstParam(_))))) => true, TypeLocation::AssocConstEq => true, _ => false, } From 0b57fa3931b88940678dcc0413fda4b4c97b4e93 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Tue, 8 Aug 2023 20:09:50 -0400 Subject: [PATCH 040/197] test --- crates/ide-completion/src/tests/type_pos.rs | 25 +++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs index f2ed7247039b..273716bd5130 100644 --- a/crates/ide-completion/src/tests/type_pos.rs +++ b/crates/ide-completion/src/tests/type_pos.rs @@ -634,6 +634,31 @@ fn f(t: impl MyTrait Date: Tue, 8 Aug 2023 20:37:23 -0400 Subject: [PATCH 041/197] convert TypeLocation::GenericArg to struct variant --- crates/ide-completion/src/completions.rs | 2 +- crates/ide-completion/src/completions/type.rs | 49 +++++++++---------- crates/ide-completion/src/context.rs | 21 ++++++-- crates/ide-completion/src/context/analysis.rs | 15 ++++-- 4 files changed, 52 insertions(+), 35 deletions(-) diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs index 125ebc98a525..7e2ecdbb858e 100644 --- a/crates/ide-completion/src/completions.rs +++ b/crates/ide-completion/src/completions.rs @@ -703,7 +703,7 @@ pub(super) fn complete_name_ref( TypeLocation::TypeAscription(ascription) => { r#type::complete_ascribed_type(acc, ctx, path_ctx, ascription); } - TypeLocation::GenericArg(_) + TypeLocation::GenericArg { .. } | TypeLocation::AssocConstEq | TypeLocation::AssocTypeEq | TypeLocation::TypeBound diff --git a/crates/ide-completion/src/completions/type.rs b/crates/ide-completion/src/completions/type.rs index 621dea0b9a55..a30fd13b1d5f 100644 --- a/crates/ide-completion/src/completions/type.rs +++ b/crates/ide-completion/src/completions/type.rs @@ -42,7 +42,7 @@ pub(crate) fn complete_type_path( }; let add_assoc_item = |acc: &mut Completions, item| match item { - hir::AssocItem::Const(ct) if matches!(location, TypeLocation::GenericArg(_)) => { + hir::AssocItem::Const(ct) if matches!(location, TypeLocation::GenericArg { .. }) => { acc.add_const(ctx, ct) } hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => (), @@ -156,33 +156,30 @@ pub(crate) fn complete_type_path( }); return; } - TypeLocation::GenericArg(Some((arg_list, in_trait, _))) => { - if let Some(trait_) = in_trait { - if arg_list.syntax().ancestors().find_map(ast::TypeBound::cast).is_some() { - let arg_idx = arg_list - .generic_args() - .filter(|arg| { - arg.syntax().text_range().end() - < ctx.original_token.text_range().start() - }) - .count(); + TypeLocation::GenericArg { + args: Some(arg_list), of_trait: Some(trait_), .. + } => { + if arg_list.syntax().ancestors().find_map(ast::TypeBound::cast).is_some() { + let arg_idx = arg_list + .generic_args() + .filter(|arg| { + arg.syntax().text_range().end() + < ctx.original_token.text_range().start() + }) + .count(); - let n_required_params = - trait_.type_or_const_param_count(ctx.sema.db, true); - if arg_idx >= n_required_params { - trait_.items_with_supertraits(ctx.sema.db).into_iter().for_each( - |it| { - if let hir::AssocItem::TypeAlias(alias) = it { - cov_mark::hit!(complete_assoc_type_in_generics_list); - acc.add_type_alias_with_eq(ctx, alias); - } - }, - ); - - let n_params = trait_.type_or_const_param_count(ctx.sema.db, false); - if arg_idx >= n_params { - return; // only show assoc types + let n_required_params = trait_.type_or_const_param_count(ctx.sema.db, true); + if arg_idx >= n_required_params { + trait_.items_with_supertraits(ctx.sema.db).into_iter().for_each(|it| { + if let hir::AssocItem::TypeAlias(alias) = it { + cov_mark::hit!(complete_assoc_type_in_generics_list); + acc.add_type_alias_with_eq(ctx, alias); } + }); + + let n_params = trait_.type_or_const_param_count(ctx.sema.db, false); + if arg_idx >= n_params { + return; // only show assoc types } } } diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs index 90ad2ecaf910..1fd635ba2e79 100644 --- a/crates/ide-completion/src/context.rs +++ b/crates/ide-completion/src/context.rs @@ -156,7 +156,14 @@ pub(crate) enum TypeLocation { TupleField, TypeAscription(TypeAscriptionTarget), /// Generic argument position e.g. `Foo<$0>` - GenericArg(Option<(ast::GenericArgList, Option, Option)>), + GenericArg { + /// The generic argument list containing the generic arg + args: Option, + /// `Some(trait_)` if `trait_` is being instantiated with `args` + of_trait: Option, + /// The generic parameter being filled in by the generic arg + corresponding_param: Option, + }, /// Associated type equality constraint e.g. `Foo` AssocTypeEq, /// Associated constant equality constraint e.g. `Foo` @@ -171,13 +178,19 @@ impl TypeLocation { pub(crate) fn complete_lifetimes(&self) -> bool { matches!( self, - TypeLocation::GenericArg(Some((_, _, Some(ast::GenericParam::LifetimeParam(_))))) + TypeLocation::GenericArg { + corresponding_param: Some(ast::GenericParam::LifetimeParam(_)), + .. + } ) } pub(crate) fn complete_consts(&self) -> bool { match self { - TypeLocation::GenericArg(Some((_, _, Some(ast::GenericParam::ConstParam(_))))) => true, + TypeLocation::GenericArg { + corresponding_param: Some(ast::GenericParam::ConstParam(_)), + .. + } => true, TypeLocation::AssocConstEq => true, _ => false, } @@ -185,7 +198,7 @@ impl TypeLocation { pub(crate) fn complete_types(&self) -> bool { match self { - TypeLocation::GenericArg(Some((_, _, Some(param)))) => { + TypeLocation::GenericArg { corresponding_param: Some(param), .. } => { matches!(param, ast::GenericParam::TypeParam(_)) } TypeLocation::AssocConstEq => false, diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index 2064ae34dd97..c66cb987fea8 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -838,7 +838,15 @@ fn classify_name_ref( })(); (args, in_trait, param) }); - override_location.unwrap_or(TypeLocation::GenericArg(location)) + let (arg_list, of_trait, corresponding_param) = match location { + Some((arg_list, of_trait, param)) => (Some(arg_list), of_trait, param), + _ => (None, None, None), + }; + override_location.unwrap_or(TypeLocation::GenericArg { + args: arg_list, + of_trait, + corresponding_param, + }) }; let type_location = |node: &SyntaxNode| { @@ -899,9 +907,8 @@ fn classify_name_ref( ast::GenericArg(it) => generic_arg_location(it), // is this case needed? ast::GenericArgList(it) => { - let location = find_opt_node_in_file_compensated(sema, original_file, Some(it)) - .map(|node| (node, None, None)); - TypeLocation::GenericArg(location) + let args = find_opt_node_in_file_compensated(sema, original_file, Some(it)); + TypeLocation::GenericArg { args, of_trait: None, corresponding_param: None } }, ast::TupleField(_) => TypeLocation::TupleField, _ => return None, From fb98f522d216ee0c28b56115b130c5374c444ed9 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Tue, 8 Aug 2023 20:55:35 -0400 Subject: [PATCH 042/197] fixme --- crates/ide-completion/src/tests/type_pos.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs index 273716bd5130..d518dd764102 100644 --- a/crates/ide-completion/src/tests/type_pos.rs +++ b/crates/ide-completion/src/tests/type_pos.rs @@ -753,6 +753,9 @@ fn completes_const_and_type_generics_separately() { kw self:: "#]], ); + // FIXME: This should probably also suggest completions for types, at least those that have + // associated constants usable in this position. For example, a user could be typing + // `foo::<_, { usize::MAX }>()`, but we currently don't suggest `usize` in constant position. check( r#" struct Foo; From 18b24f60d0423a7b88978ca08bcfca4a905583d1 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 9 Aug 2023 14:09:37 +0200 Subject: [PATCH 043/197] More error context when failing to invoke the rust toolchain --- crates/project-model/src/workspace.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index f51ea7eeb224..13463e9f72e3 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -167,7 +167,8 @@ impl ProjectWorkspace { cmd.envs(&config.extra_env); cmd.arg("--version").current_dir(current_dir); cmd - })?; + }) + .with_context(|| format!("Failed to query rust toolchain version at {current_dir}, is your toolchain setup correctly?"))?; anyhow::Ok( cargo_version .get(prefix.len()..) From 992b928a930c58348c55263e13f140c06912e58d Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 9 Aug 2023 15:20:42 +0200 Subject: [PATCH 044/197] Record import source IDs --- crates/hir-def/src/data.rs | 2 +- crates/hir-def/src/find_path.rs | 14 +- crates/hir-def/src/lib.rs | 11 + crates/hir-def/src/nameres.rs | 22 +- crates/hir-def/src/nameres/collector.rs | 294 ++++++++++-------- crates/hir-def/src/nameres/path_resolution.rs | 21 +- crates/hir-def/src/resolver.rs | 10 +- 7 files changed, 217 insertions(+), 157 deletions(-) diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index 91db68058b02..68defa3858fc 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -487,7 +487,7 @@ impl ExternCrateDeclData { db.crate_def_map(loc.container.krate()) .extern_prelude() .find(|&(prelude_name, ..)| *prelude_name == name) - .map(|(_, root)| root.krate()) + .map(|(_, (root, _))| root.krate()) }; Arc::new(Self { diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs index df2af4c89b08..59c250d75066 100644 --- a/crates/hir-def/src/find_path.rs +++ b/crates/hir-def/src/find_path.rs @@ -11,7 +11,7 @@ use crate::{ nameres::DefMap, path::{ModPath, PathKind}, visibility::Visibility, - ModuleDefId, ModuleId, + CrateRootModuleId, ModuleDefId, ModuleId, }; /// Find a path that can be used to refer to a certain item. This can depend on @@ -81,7 +81,7 @@ fn find_path_inner( } let def_map = from.def_map(db); - let crate_root = def_map.crate_root().into(); + let crate_root = def_map.crate_root(); // - if the item is a module, jump straight to module search if let ItemInNs::Types(ModuleDefId::ModuleId(module_id)) = item { let mut visited_modules = FxHashSet::default(); @@ -149,7 +149,7 @@ fn find_path_for_module( db: &dyn DefDatabase, def_map: &DefMap, visited_modules: &mut FxHashSet, - crate_root: ModuleId, + crate_root: CrateRootModuleId, from: ModuleId, module_id: ModuleId, max_len: usize, @@ -183,7 +183,7 @@ fn find_path_for_module( // - if the item is the crate root of a dependency crate, return the name from the extern prelude let root_def_map = crate_root.def_map(db); - for (name, def_id) in root_def_map.extern_prelude() { + for (name, (def_id, _extern_crate)) in root_def_map.extern_prelude() { if module_id == def_id { let name = scope_name.unwrap_or_else(|| name.clone()); @@ -192,7 +192,7 @@ fn find_path_for_module( def_map[local_id] .scope .type_(&name) - .filter(|&(id, _)| id != ModuleDefId::ModuleId(def_id)) + .filter(|&(id, _)| id != ModuleDefId::ModuleId(def_id.into())) }) .is_some(); let kind = if name_already_occupied_in_type_ns { @@ -244,7 +244,7 @@ fn find_in_prelude( item: ItemInNs, from: ModuleId, ) -> Option { - let prelude_module = root_def_map.prelude()?; + let (prelude_module, _) = root_def_map.prelude()?; // Preludes in block DefMaps are ignored, only the crate DefMap is searched let prelude_def_map = prelude_module.def_map(db); let prelude_scope = &prelude_def_map[prelude_module.local_id].scope; @@ -293,7 +293,7 @@ fn calculate_best_path( db: &dyn DefDatabase, def_map: &DefMap, visited_modules: &mut FxHashSet, - crate_root: ModuleId, + crate_root: CrateRootModuleId, max_len: usize, item: ItemInNs, from: ModuleId, diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 1901db8a0f9b..c40bbc0380ef 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -109,6 +109,17 @@ impl CrateRootModuleId { } } +impl PartialEq for CrateRootModuleId { + fn eq(&self, other: &ModuleId) -> bool { + other.block.is_none() && other.local_id == DefMap::ROOT && self.krate == other.krate + } +} +impl PartialEq for ModuleId { + fn eq(&self, other: &CrateRootModuleId) -> bool { + other == self + } +} + impl From for ModuleId { fn from(CrateRootModuleId { krate }: CrateRootModuleId) -> Self { ModuleId { krate, block: None, local_id: DefMap::ROOT } diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 86818ce26dd6..5c99f691a643 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -77,8 +77,8 @@ use crate::{ path::ModPath, per_ns::PerNs, visibility::Visibility, - AstId, BlockId, BlockLoc, CrateRootModuleId, FunctionId, LocalModuleId, Lookup, MacroExpander, - MacroId, ModuleId, ProcMacroId, + AstId, BlockId, BlockLoc, CrateRootModuleId, ExternCrateId, FunctionId, LocalModuleId, Lookup, + MacroExpander, MacroId, ModuleId, ProcMacroId, UseId, }; /// Contains the results of (early) name resolution. @@ -105,10 +105,10 @@ pub struct DefMap { /// The prelude is empty for non-block DefMaps (unless `#[prelude_import]` was used, /// but that attribute is nightly and when used in a block, it affects resolution globally /// so we aren't handling this correctly anyways). - prelude: Option, + prelude: Option<(ModuleId, Option)>, /// `macro_use` prelude that contains macros from `#[macro_use]`'d external crates. Note that /// this contains all kinds of macro, not just `macro_rules!` macro. - macro_use_prelude: FxHashMap, + macro_use_prelude: FxHashMap)>, /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper /// attributes. @@ -125,7 +125,7 @@ pub struct DefMap { #[derive(Clone, Debug, PartialEq, Eq)] struct DefMapCrateData { /// The extern prelude which contains all root modules of external crates that are in scope. - extern_prelude: FxHashMap, + extern_prelude: FxHashMap)>, /// Side table for resolving derive helpers. exported_derives: FxHashMap>, @@ -427,15 +427,19 @@ impl DefMap { self.block.map(|block| block.block) } - pub(crate) fn prelude(&self) -> Option { + pub(crate) fn prelude(&self) -> Option<(ModuleId, Option)> { self.prelude } - pub(crate) fn extern_prelude(&self) -> impl Iterator + '_ { - self.data.extern_prelude.iter().map(|(name, &def)| (name, def.into())) + pub(crate) fn extern_prelude( + &self, + ) -> impl Iterator))> + '_ { + self.data.extern_prelude.iter().map(|(name, &def)| (name, def)) } - pub(crate) fn macro_use_prelude(&self) -> impl Iterator + '_ { + pub(crate) fn macro_use_prelude( + &self, + ) -> impl Iterator))> + '_ { self.macro_use_prelude.iter().map(|(name, &def)| (name, def)) } diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index eef54fc492e9..f79f4ab0ba99 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -52,10 +52,10 @@ use crate::{ tt, visibility::{RawVisibility, Visibility}, AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantId, - ExternBlockLoc, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern, ItemContainerId, - LocalModuleId, Macro2Id, Macro2Loc, MacroExpander, MacroId, MacroRulesId, MacroRulesLoc, - ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc, StructLoc, TraitAliasLoc, - TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, UseLoc, + ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern, + ItemContainerId, LocalModuleId, Macro2Id, Macro2Loc, MacroExpander, MacroId, MacroRulesId, + MacroRulesLoc, ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc, StructLoc, + TraitAliasLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, UseId, UseLoc, }; static GLOB_RECURSION_LIMIT: Limit = Limit::new(100); @@ -144,10 +144,11 @@ impl PartialResolvedImport { } } +// FIXME: `item_tree_id` can be derived from `id`, look into deduplicating this #[derive(Clone, Debug, Eq, PartialEq)] enum ImportSource { - Use { id: ItemTreeId, use_tree: Idx }, - ExternCrate(ItemTreeId), + Use { item_tree_id: ItemTreeId, use_tree: Idx, id: UseId }, + ExternCrate { item_tree_id: ItemTreeId, id: ExternCrateId }, } #[derive(Debug, Eq, PartialEq)] @@ -166,11 +167,12 @@ impl Import { db: &dyn DefDatabase, krate: CrateId, tree: &ItemTree, - id: ItemTreeId, + item_tree_id: ItemTreeId, + id: UseId, mut cb: impl FnMut(Self), ) { - let it = &tree[id.value]; - let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into()); + let it = &tree[item_tree_id.value]; + let attrs = &tree.attrs(db, krate, ModItem::from(item_tree_id.value).into()); let visibility = &tree[it.visibility]; let is_prelude = attrs.by_key("prelude_import").exists(); it.use_tree.expand(|idx, path, kind, alias| { @@ -181,7 +183,7 @@ impl Import { kind, is_prelude, is_macro_use: false, - source: ImportSource::Use { id, use_tree: idx }, + source: ImportSource::Use { item_tree_id, use_tree: idx, id }, }); }); } @@ -190,10 +192,11 @@ impl Import { db: &dyn DefDatabase, krate: CrateId, tree: &ItemTree, - id: ItemTreeId, + item_tree_id: ItemTreeId, + id: ExternCrateId, ) -> Self { - let it = &tree[id.value]; - let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into()); + let it = &tree[item_tree_id.value]; + let attrs = &tree.attrs(db, krate, ModItem::from(item_tree_id.value).into()); let visibility = &tree[it.visibility]; Self { path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())), @@ -202,7 +205,7 @@ impl Import { kind: ImportKind::Plain, is_prelude: false, is_macro_use: attrs.by_key("macro_use").exists(), - source: ImportSource::ExternCrate(id), + source: ImportSource::ExternCrate { item_tree_id, id }, } } } @@ -280,7 +283,7 @@ impl DefCollector<'_> { if dep.is_prelude() { crate_data .extern_prelude - .insert(name.clone(), CrateRootModuleId { krate: dep.crate_id }); + .insert(name.clone(), (CrateRootModuleId { krate: dep.crate_id }, None)); } } @@ -557,7 +560,7 @@ impl DefCollector<'_> { match per_ns.types { Some((ModuleDefId::ModuleId(m), _)) => { - self.def_map.prelude = Some(m); + self.def_map.prelude = Some((m, None)); } types => { tracing::debug!( @@ -720,7 +723,13 @@ impl DefCollector<'_> { /// Exported macros are just all macros in the root module scope. /// Note that it contains not only all `#[macro_export]` macros, but also all aliases /// created by `use` in the root module, ignoring the visibility of `use`. - fn import_macros_from_extern_crate(&mut self, krate: CrateId, names: Option>) { + fn import_macros_from_extern_crate( + &mut self, + krate: CrateId, + names: Option>, + + extern_crate: Option, + ) { let def_map = self.db.crate_def_map(krate); // `#[macro_use]` brings macros into macro_use prelude. Yes, even non-`macro_rules!` // macros. @@ -729,12 +738,12 @@ impl DefCollector<'_> { for name in names { // FIXME: Report diagnostic on 404. if let Some(def) = root_scope.get(&name).take_macros() { - self.def_map.macro_use_prelude.insert(name, def); + self.def_map.macro_use_prelude.insert(name, (def, extern_crate)); } } } else { for (name, def) in root_scope.macros() { - self.def_map.macro_use_prelude.insert(name.clone(), def); + self.def_map.macro_use_prelude.insert(name.clone(), (def, extern_crate)); } } } @@ -771,48 +780,52 @@ impl DefCollector<'_> { let _p = profile::span("resolve_import") .detail(|| format!("{}", import.path.display(self.db.upcast()))); tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.data.edition); - if matches!(import.source, ImportSource::ExternCrate { .. }) { - let name = import - .path - .as_ident() - .expect("extern crate should have been desugared to one-element path"); + match import.source { + ImportSource::ExternCrate { .. } => { + let name = import + .path + .as_ident() + .expect("extern crate should have been desugared to one-element path"); - let res = self.resolve_extern_crate(name); + let res = self.resolve_extern_crate(name); - match res { - Some(res) => { - PartialResolvedImport::Resolved(PerNs::types(res.into(), Visibility::Public)) - } - None => PartialResolvedImport::Unresolved, - } - } else { - let res = self.def_map.resolve_path_fp_with_macro( - self.db, - ResolveMode::Import, - module_id, - &import.path, - BuiltinShadowMode::Module, - None, // An import may resolve to any kind of macro. - ); - - let def = res.resolved_def; - if res.reached_fixedpoint == ReachedFixedPoint::No || def.is_none() { - return PartialResolvedImport::Unresolved; - } - - if let Some(krate) = res.krate { - if krate != self.def_map.krate { - return PartialResolvedImport::Resolved( - def.filter_visibility(|v| matches!(v, Visibility::Public)), - ); + match res { + Some(res) => PartialResolvedImport::Resolved(PerNs::types( + res.into(), + Visibility::Public, + )), + None => PartialResolvedImport::Unresolved, } } + ImportSource::Use { .. } => { + let res = self.def_map.resolve_path_fp_with_macro( + self.db, + ResolveMode::Import, + module_id, + &import.path, + BuiltinShadowMode::Module, + None, // An import may resolve to any kind of macro. + ); - // Check whether all namespaces are resolved. - if def.is_full() { - PartialResolvedImport::Resolved(def) - } else { - PartialResolvedImport::Indeterminate(def) + let def = res.resolved_def; + if res.reached_fixedpoint == ReachedFixedPoint::No || def.is_none() { + return PartialResolvedImport::Unresolved; + } + + if let Some(krate) = res.krate { + if krate != self.def_map.krate { + return PartialResolvedImport::Resolved( + def.filter_visibility(|v| matches!(v, Visibility::Public)), + ); + } + } + + // Check whether all namespaces are resolved. + if def.is_full() { + PartialResolvedImport::Resolved(def) + } else { + PartialResolvedImport::Indeterminate(def) + } } } } @@ -859,17 +872,17 @@ impl DefCollector<'_> { tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 - if matches!(import.source, ImportSource::ExternCrate { .. }) - && self.def_map.block.is_none() - && module_id == DefMap::ROOT - { - if let (Some(ModuleDefId::ModuleId(def)), Some(name)) = (def.take_types(), name) - { - if let Ok(def) = def.try_into() { - Arc::get_mut(&mut self.def_map.data) - .unwrap() - .extern_prelude - .insert(name.clone(), def); + if let ImportSource::ExternCrate { id, .. } = import.source { + if self.def_map.block.is_none() && module_id == DefMap::ROOT { + if let (Some(ModuleDefId::ModuleId(def)), Some(name)) = + (def.take_types(), name) + { + if let Ok(def) = def.try_into() { + Arc::get_mut(&mut self.def_map.data) + .unwrap() + .extern_prelude + .insert(name.clone(), (def, Some(id))); + } } } } @@ -884,7 +897,13 @@ impl DefCollector<'_> { // Note: This dodgily overrides the injected prelude. The rustc // implementation seems to work the same though. cov_mark::hit!(std_prelude); - self.def_map.prelude = Some(m); + self.def_map.prelude = Some(( + m, + match import.source { + ImportSource::Use { id, .. } => Some(id), + ImportSource::ExternCrate { .. } => None, + }, + )); } else if m.krate != self.def_map.krate { cov_mark::hit!(glob_across_crates); // glob import from other crate => we can just import everything once @@ -1460,21 +1479,21 @@ impl DefCollector<'_> { // heuristic, but it works in practice. let mut diagnosed_extern_crates = FxHashSet::default(); for directive in &self.unresolved_imports { - if let ImportSource::ExternCrate(krate) = directive.import.source { - let item_tree = krate.item_tree(self.db); - let extern_crate = &item_tree[krate.value]; + if let ImportSource::ExternCrate { item_tree_id, id: _ } = directive.import.source { + let item_tree = item_tree_id.item_tree(self.db); + let extern_crate = &item_tree[item_tree_id.value]; diagnosed_extern_crates.insert(extern_crate.name.clone()); self.def_map.diagnostics.push(DefDiagnostic::unresolved_extern_crate( directive.module_id, - InFile::new(krate.file_id(), extern_crate.ast_id), + InFile::new(item_tree_id.file_id(), extern_crate.ast_id), )); } } for directive in &self.unresolved_imports { - if let ImportSource::Use { id: import, use_tree } = directive.import.source { + if let ImportSource::Use { item_tree_id, use_tree, id: _ } = directive.import.source { if matches!( (directive.import.path.segments().first(), &directive.import.path.kind), (Some(krate), PathKind::Plain | PathKind::Abs) if diagnosed_extern_crates.contains(krate) @@ -1484,7 +1503,7 @@ impl DefCollector<'_> { self.def_map.diagnostics.push(DefDiagnostic::unresolved_import( directive.module_id, - import, + item_tree_id, use_tree, )); } @@ -1519,72 +1538,66 @@ impl ModCollector<'_, '_> { self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone()); // Prelude module is always considered to be `#[macro_use]`. - if let Some(prelude_module) = self.def_collector.def_map.prelude { + if let Some((prelude_module, _use)) = self.def_collector.def_map.prelude { if prelude_module.krate != krate && is_crate_root { cov_mark::hit!(prelude_is_macro_use); - self.def_collector.import_macros_from_extern_crate(prelude_module.krate, None); + self.def_collector.import_macros_from_extern_crate( + prelude_module.krate, + None, + None, + ); } } + let db = self.def_collector.db; + let module_id = self.module_id; + let update_def = + |def_collector: &mut DefCollector<'_>, id, name: &Name, vis, has_constructor| { + def_collector.def_map.modules[module_id].scope.declare(id); + def_collector.update( + module_id, + &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))], + vis, + ImportType::Named, + ) + }; + let resolve_vis = |def_map: &DefMap, visibility| { + def_map + .resolve_visibility(db, module_id, visibility, false) + .unwrap_or(Visibility::Public) + }; - // This should be processed eagerly instead of deferred to resolving. - // `#[macro_use] extern crate` is hoisted to imports macros before collecting - // any other items. - // - // If we're not at the crate root, `macro_use`d extern crates are an error so let's just - // ignore them. - if is_crate_root { - for &item in items { - if let ModItem::ExternCrate(id) = item { - self.process_macro_use_extern_crate(id); - } - } - } - - for &item in items { - let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into()); + let mut process_mod_item = |item: ModItem| { + let attrs = self.item_tree.attrs(db, krate, item.into()); if let Some(cfg) = attrs.cfg() { if !self.is_cfg_enabled(&cfg) { self.emit_unconfigured_diagnostic(item, &cfg); - continue; + return; } } if let Err(()) = self.resolve_attributes(&attrs, item, container) { // Do not process the item. It has at least one non-builtin attribute, so the // fixed-point algorithm is required to resolve the rest of them. - continue; + return; } - let db = self.def_collector.db; - let module = self.def_collector.def_map.module_id(self.module_id); + let module = self.def_collector.def_map.module_id(module_id); let def_map = &mut self.def_collector.def_map; - let update_def = - |def_collector: &mut DefCollector<'_>, id, name: &Name, vis, has_constructor| { - def_collector.def_map.modules[self.module_id].scope.declare(id); - def_collector.update( - self.module_id, - &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))], - vis, - ImportType::Named, - ) - }; - let resolve_vis = |def_map: &DefMap, visibility| { - def_map - .resolve_visibility(db, self.module_id, visibility, false) - .unwrap_or(Visibility::Public) - }; match item { ModItem::Mod(m) => self.collect_module(m, &attrs), - ModItem::Use(import_id) => { - let _import_id = - UseLoc { container: module, id: ItemTreeId::new(self.tree_id, import_id) } - .intern(db); + ModItem::Use(item_tree_id) => { + let id = UseLoc { + container: module, + id: ItemTreeId::new(self.tree_id, item_tree_id), + } + .intern(db); Import::from_use( db, krate, self.item_tree, - ItemTreeId::new(self.tree_id, import_id), + ItemTreeId::new(self.tree_id, item_tree_id), + id, |import| { self.def_collector.unresolved_imports.push(ImportDirective { module_id: self.module_id, @@ -1594,22 +1607,27 @@ impl ModCollector<'_, '_> { }, ) } - ModItem::ExternCrate(import_id) => { - let extern_crate_id = ExternCrateLoc { + ModItem::ExternCrate(item_tree_id) => { + let id = ExternCrateLoc { container: module, - id: ItemTreeId::new(self.tree_id, import_id), + id: ItemTreeId::new(self.tree_id, item_tree_id), } .intern(db); + if is_crate_root { + self.process_macro_use_extern_crate(item_tree_id, id); + } + self.def_collector.def_map.modules[self.module_id] .scope - .define_extern_crate_decl(extern_crate_id); + .define_extern_crate_decl(id); self.def_collector.unresolved_imports.push(ImportDirective { module_id: self.module_id, import: Import::from_extern_crate( db, krate, self.item_tree, - ItemTreeId::new(self.tree_id, import_id), + ItemTreeId::new(self.tree_id, item_tree_id), + id, ), status: PartialResolvedImport::Unresolved, }) @@ -1768,10 +1786,32 @@ impl ModCollector<'_, '_> { ); } } + }; + + // extern crates should be processed eagerly instead of deferred to resolving. + // `#[macro_use] extern crate` is hoisted to imports macros before collecting + // any other items. + if is_crate_root { + items + .iter() + .filter(|it| matches!(it, ModItem::ExternCrate(..))) + .copied() + .for_each(&mut process_mod_item); + items + .iter() + .filter(|it| !matches!(it, ModItem::ExternCrate(..))) + .copied() + .for_each(process_mod_item); + } else { + items.iter().copied().for_each(process_mod_item); } } - fn process_macro_use_extern_crate(&mut self, extern_crate: FileItemTreeId) { + fn process_macro_use_extern_crate( + &mut self, + extern_crate: FileItemTreeId, + extern_crate_id: ExternCrateId, + ) { let db = self.def_collector.db; let attrs = self.item_tree.attrs( db, @@ -1802,7 +1842,7 @@ impl ModCollector<'_, '_> { let Some(paths) = attr.parse_path_comma_token_tree(db.upcast(), &hygiene) else { // `#[macro_use]` (without any paths) found, forget collected names and just import // all visible macros. - self.def_collector.import_macros_from_extern_crate(target_crate, None); + self.def_collector.import_macros_from_extern_crate(target_crate, None, Some(extern_crate_id)); return; }; for path in paths { @@ -1812,7 +1852,11 @@ impl ModCollector<'_, '_> { } } - self.def_collector.import_macros_from_extern_crate(target_crate, Some(single_imports)); + self.def_collector.import_macros_from_extern_crate( + target_crate, + Some(single_imports), + Some(extern_crate_id), + ); } fn collect_module(&mut self, module_id: FileItemTreeId, attrs: &Attrs) { @@ -2198,7 +2242,7 @@ impl ModCollector<'_, '_> { map[module].scope.get_legacy_macro(name)?.last().copied() }) .or_else(|| def_map[self.module_id].scope.get(name).take_macros()) - .or_else(|| def_map.macro_use_prelude.get(name).copied()) + .or_else(|| Some(def_map.macro_use_prelude.get(name).copied()?.0)) .filter(|&id| { sub_namespace_match( Some(MacroSubNs::from_id(db, id)), diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index de22ea101460..64cdbdce7708 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -299,7 +299,7 @@ impl DefMap { Some((_, segment)) => segment, None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), }; - if let Some(&def) = self.data.extern_prelude.get(segment) { + if let Some(&(def, _extern_crate)) = self.data.extern_prelude.get(segment) { tracing::debug!("absolute path {:?} resolved to crate {:?}", path, def); PerNs::types(def.into(), Visibility::Public) } else { @@ -452,15 +452,14 @@ impl DefMap { // Don't resolve extern prelude in block `DefMap`s. return PerNs::none(); } - self.data - .extern_prelude - .get(name) - .map_or(PerNs::none(), |&it| PerNs::types(it.into(), Visibility::Public)) + self.data.extern_prelude.get(name).map_or(PerNs::none(), |&(it, _extern_crate)| { + PerNs::types(it.into(), Visibility::Public) + }) }; let macro_use_prelude = || { - self.macro_use_prelude - .get(name) - .map_or(PerNs::none(), |&it| PerNs::macros(it.into(), Visibility::Public)) + self.macro_use_prelude.get(name).map_or(PerNs::none(), |&(it, _extern_crate)| { + PerNs::macros(it.into(), Visibility::Public) + }) }; let prelude = || self.resolve_in_prelude(db, name); @@ -492,14 +491,16 @@ impl DefMap { .extern_prelude .get(name) .copied() - .map_or(PerNs::none(), |it| PerNs::types(it.into(), Visibility::Public)) + .map_or(PerNs::none(), |(it, _extern_crate)| { + PerNs::types(it.into(), Visibility::Public) + }) }; from_crate_root.or_else(from_extern_prelude) } fn resolve_in_prelude(&self, db: &dyn DefDatabase, name: &Name) -> PerNs { - if let Some(prelude) = self.prelude { + if let Some((prelude, _use)) = self.prelude { let keep; let def_map = if prelude.krate == self.krate { self diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index d04d2fa0e979..17a1bf50b5e9 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -433,16 +433,16 @@ impl Resolver { res.add(name, ScopeDef::ModuleDef(ModuleDefId::MacroId(mac))); }) }); - def_map.macro_use_prelude().for_each(|(name, def)| { + def_map.macro_use_prelude().for_each(|(name, (def, _extern_crate))| { res.add(name, ScopeDef::ModuleDef(def.into())); }); - def_map.extern_prelude().for_each(|(name, def)| { - res.add(name, ScopeDef::ModuleDef(ModuleDefId::ModuleId(def))); + def_map.extern_prelude().for_each(|(name, (def, _extern_crate))| { + res.add(name, ScopeDef::ModuleDef(ModuleDefId::ModuleId(def.into()))); }); BUILTIN_SCOPE.iter().for_each(|(name, &def)| { res.add_per_ns(name, def); }); - if let Some(prelude) = def_map.prelude() { + if let Some((prelude, _use)) = def_map.prelude() { let prelude_def_map = prelude.def_map(db); for (name, def) in prelude_def_map[prelude.local_id].scope.entries() { res.add_per_ns(name, def) @@ -473,7 +473,7 @@ impl Resolver { } // Fill in the prelude traits - if let Some(prelude) = self.module_scope.def_map.prelude() { + if let Some((prelude, _use)) = self.module_scope.def_map.prelude() { let prelude_def_map = prelude.def_map(db); traits.extend(prelude_def_map[prelude.local_id].scope.traits()); } From c516dd51e9eb53e7d4275d1f1d543dce643e492a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 9 Aug 2023 15:54:10 +0200 Subject: [PATCH 045/197] Simplify --- crates/hir-def/src/nameres/collector.rs | 69 ++++++++++--------------- 1 file changed, 27 insertions(+), 42 deletions(-) diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index f79f4ab0ba99..9a7e6bdcc8af 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -147,8 +147,16 @@ impl PartialResolvedImport { // FIXME: `item_tree_id` can be derived from `id`, look into deduplicating this #[derive(Clone, Debug, Eq, PartialEq)] enum ImportSource { - Use { item_tree_id: ItemTreeId, use_tree: Idx, id: UseId }, - ExternCrate { item_tree_id: ItemTreeId, id: ExternCrateId }, + Use { + item_tree_id: ItemTreeId, + use_tree: Idx, + id: UseId, + is_prelude: bool, + }, + ExternCrate { + item_tree_id: ItemTreeId, + id: ExternCrateId, + }, } #[derive(Debug, Eq, PartialEq)] @@ -158,53 +166,41 @@ struct Import { visibility: RawVisibility, kind: ImportKind, source: ImportSource, - is_prelude: bool, - is_macro_use: bool, } impl Import { fn from_use( - db: &dyn DefDatabase, - krate: CrateId, tree: &ItemTree, item_tree_id: ItemTreeId, id: UseId, + is_prelude: bool, mut cb: impl FnMut(Self), ) { let it = &tree[item_tree_id.value]; - let attrs = &tree.attrs(db, krate, ModItem::from(item_tree_id.value).into()); let visibility = &tree[it.visibility]; - let is_prelude = attrs.by_key("prelude_import").exists(); it.use_tree.expand(|idx, path, kind, alias| { cb(Self { path, alias, visibility: visibility.clone(), kind, - is_prelude, - is_macro_use: false, - source: ImportSource::Use { item_tree_id, use_tree: idx, id }, + source: ImportSource::Use { item_tree_id, use_tree: idx, id, is_prelude }, }); }); } fn from_extern_crate( - db: &dyn DefDatabase, - krate: CrateId, tree: &ItemTree, item_tree_id: ItemTreeId, id: ExternCrateId, ) -> Self { let it = &tree[item_tree_id.value]; - let attrs = &tree.attrs(db, krate, ModItem::from(item_tree_id.value).into()); let visibility = &tree[it.visibility]; Self { path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())), alias: it.alias.clone(), visibility: visibility.clone(), kind: ImportKind::Plain, - is_prelude: false, - is_macro_use: attrs.by_key("macro_use").exists(), source: ImportSource::ExternCrate { item_tree_id, id }, } } @@ -893,17 +889,11 @@ impl DefCollector<'_> { tracing::debug!("glob import: {:?}", import); match def.take_types() { Some(ModuleDefId::ModuleId(m)) => { - if import.is_prelude { + if let ImportSource::Use { id, is_prelude: true, .. } = import.source { // Note: This dodgily overrides the injected prelude. The rustc // implementation seems to work the same though. cov_mark::hit!(std_prelude); - self.def_map.prelude = Some(( - m, - match import.source { - ImportSource::Use { id, .. } => Some(id), - ImportSource::ExternCrate { .. } => None, - }, - )); + self.def_map.prelude = Some((m, Some(id))); } else if m.krate != self.def_map.krate { cov_mark::hit!(glob_across_crates); // glob import from other crate => we can just import everything once @@ -1493,7 +1483,9 @@ impl DefCollector<'_> { } for directive in &self.unresolved_imports { - if let ImportSource::Use { item_tree_id, use_tree, id: _ } = directive.import.source { + if let ImportSource::Use { item_tree_id, use_tree, id: _, is_prelude: _ } = + directive.import.source + { if matches!( (directive.import.path.segments().first(), &directive.import.path.kind), (Some(krate), PathKind::Plain | PathKind::Abs) if diagnosed_extern_crates.contains(krate) @@ -1592,12 +1584,12 @@ impl ModCollector<'_, '_> { id: ItemTreeId::new(self.tree_id, item_tree_id), } .intern(db); + let is_prelude = attrs.by_key("prelude_import").exists(); Import::from_use( - db, - krate, self.item_tree, ItemTreeId::new(self.tree_id, item_tree_id), id, + is_prelude, |import| { self.def_collector.unresolved_imports.push(ImportDirective { module_id: self.module_id, @@ -1614,7 +1606,11 @@ impl ModCollector<'_, '_> { } .intern(db); if is_crate_root { - self.process_macro_use_extern_crate(item_tree_id, id); + self.process_macro_use_extern_crate( + item_tree_id, + id, + attrs.by_key("macro_use").attrs(), + ); } self.def_collector.def_map.modules[self.module_id] @@ -1623,8 +1619,6 @@ impl ModCollector<'_, '_> { self.def_collector.unresolved_imports.push(ImportDirective { module_id: self.module_id, import: Import::from_extern_crate( - db, - krate, self.item_tree, ItemTreeId::new(self.tree_id, item_tree_id), id, @@ -1807,22 +1801,13 @@ impl ModCollector<'_, '_> { } } - fn process_macro_use_extern_crate( + fn process_macro_use_extern_crate<'a>( &mut self, extern_crate: FileItemTreeId, extern_crate_id: ExternCrateId, + macro_use_attrs: impl Iterator, ) { let db = self.def_collector.db; - let attrs = self.item_tree.attrs( - db, - self.def_collector.def_map.krate, - ModItem::from(extern_crate).into(), - ); - if let Some(cfg) = attrs.cfg() { - if !self.is_cfg_enabled(&cfg) { - return; - } - } let target_crate = match self.def_collector.resolve_extern_crate(&self.item_tree[extern_crate].name) { @@ -1838,7 +1823,7 @@ impl ModCollector<'_, '_> { let mut single_imports = Vec::new(); let hygiene = Hygiene::new_unhygienic(); - for attr in attrs.by_key("macro_use").attrs() { + for attr in macro_use_attrs { let Some(paths) = attr.parse_path_comma_token_tree(db.upcast(), &hygiene) else { // `#[macro_use]` (without any paths) found, forget collected names and just import // all visible macros. From 4e4dda5f59ca6c07a8fe111ff5c0e33caa12a907 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Wed, 9 Aug 2023 16:40:23 +0200 Subject: [PATCH 046/197] Deunwrap convert_named_struct_to_tuple_struct --- .../src/handlers/convert_named_struct_to_tuple_struct.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs b/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs index fe1cb6fce363..76f021ed912f 100644 --- a/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs +++ b/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs @@ -161,9 +161,9 @@ fn process_struct_name_reference( let path_segment = name_ref.syntax().parent().and_then(ast::PathSegment::cast)?; // A `PathSegment` always belongs to a `Path`, so there's at least one `Path` at this point. let full_path = - path_segment.syntax().parent()?.ancestors().map_while(ast::Path::cast).last().unwrap(); + path_segment.syntax().parent()?.ancestors().map_while(ast::Path::cast).last()?; - if full_path.segment().unwrap().name_ref()? != *name_ref { + if full_path.segment()?.name_ref()? != *name_ref { // `name_ref` isn't the last segment of the path, so `full_path` doesn't point to the // struct we want to edit. return None; From b658f9a9548315801d3f0a706ccd32b9c772a33e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Wed, 9 Aug 2023 17:54:34 +0300 Subject: [PATCH 047/197] Remove unwrap from Remove dbg --- crates/ide-assists/src/handlers/remove_dbg.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/ide-assists/src/handlers/remove_dbg.rs b/crates/ide-assists/src/handlers/remove_dbg.rs index a403d5bc672d..e2b822232898 100644 --- a/crates/ide-assists/src/handlers/remove_dbg.rs +++ b/crates/ide-assists/src/handlers/remove_dbg.rs @@ -39,14 +39,11 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( let replacements = macro_calls.into_iter().filter_map(compute_dbg_replacement).collect::>(); - if replacements.is_empty() { - return None; - } acc.add( AssistId("remove_dbg", AssistKind::Refactor), "Remove dbg!()", - replacements.iter().map(|&(range, _)| range).reduce(|acc, range| acc.cover(range)).unwrap(), + replacements.iter().map(|&(range, _)| range).reduce(|acc, range| acc.cover(range))?, |builder| { for (range, expr) in replacements { if let Some(expr) = expr { From 63aba76735c387c15230039b9ac7712a18962cb7 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 9 Aug 2023 17:06:52 +0200 Subject: [PATCH 048/197] Remove unnecessary ItemTreeId field in ImportSource --- crates/hir-def/src/nameres/collector.rs | 26 ++++++++----------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 9a7e6bdcc8af..92d5cdd09bd7 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -144,19 +144,10 @@ impl PartialResolvedImport { } } -// FIXME: `item_tree_id` can be derived from `id`, look into deduplicating this #[derive(Clone, Debug, Eq, PartialEq)] enum ImportSource { - Use { - item_tree_id: ItemTreeId, - use_tree: Idx, - id: UseId, - is_prelude: bool, - }, - ExternCrate { - item_tree_id: ItemTreeId, - id: ExternCrateId, - }, + Use { use_tree: Idx, id: UseId, is_prelude: bool }, + ExternCrate { id: ExternCrateId }, } #[derive(Debug, Eq, PartialEq)] @@ -184,7 +175,7 @@ impl Import { alias, visibility: visibility.clone(), kind, - source: ImportSource::Use { item_tree_id, use_tree: idx, id, is_prelude }, + source: ImportSource::Use { use_tree: idx, id, is_prelude }, }); }); } @@ -201,7 +192,7 @@ impl Import { alias: it.alias.clone(), visibility: visibility.clone(), kind: ImportKind::Plain, - source: ImportSource::ExternCrate { item_tree_id, id }, + source: ImportSource::ExternCrate { id }, } } } @@ -1469,7 +1460,8 @@ impl DefCollector<'_> { // heuristic, but it works in practice. let mut diagnosed_extern_crates = FxHashSet::default(); for directive in &self.unresolved_imports { - if let ImportSource::ExternCrate { item_tree_id, id: _ } = directive.import.source { + if let ImportSource::ExternCrate { id } = directive.import.source { + let item_tree_id = self.db.lookup_intern_extern_crate(id).id; let item_tree = item_tree_id.item_tree(self.db); let extern_crate = &item_tree[item_tree_id.value]; @@ -1483,16 +1475,14 @@ impl DefCollector<'_> { } for directive in &self.unresolved_imports { - if let ImportSource::Use { item_tree_id, use_tree, id: _, is_prelude: _ } = - directive.import.source - { + if let ImportSource::Use { use_tree, id, is_prelude: _ } = directive.import.source { if matches!( (directive.import.path.segments().first(), &directive.import.path.kind), (Some(krate), PathKind::Plain | PathKind::Abs) if diagnosed_extern_crates.contains(krate) ) { continue; } - + let item_tree_id = self.db.lookup_intern_use(id).id; self.def_map.diagnostics.push(DefDiagnostic::unresolved_import( directive.module_id, item_tree_id, From ebf27058cd84c116bf6dc6c8b06d589e97eda165 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Wed, 9 Aug 2023 17:17:43 +0200 Subject: [PATCH 049/197] minor : Deunwrap convert_to_guarded_return --- .../src/handlers/convert_to_guarded_return.rs | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/crates/ide-assists/src/handlers/convert_to_guarded_return.rs b/crates/ide-assists/src/handlers/convert_to_guarded_return.rs index dcb96ab8af44..7d0e424769ec 100644 --- a/crates/ide-assists/src/handlers/convert_to_guarded_return.rs +++ b/crates/ide-assists/src/handlers/convert_to_guarded_return.rs @@ -58,7 +58,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext<' return None; } - let bound_ident = pat.fields().next().unwrap(); + let bound_ident = pat.fields().next()?; if !ast::IdentPat::can_cast(bound_ident.syntax().kind()) { return None; } @@ -108,6 +108,15 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext<' then_block.syntax().last_child_or_token().filter(|t| t.kind() == T!['}'])?; + let then_block_items = then_block.dedent(IndentLevel(1)).clone_for_update(); + + let end_of_then = then_block_items.syntax().last_child_or_token()?; + let end_of_then = if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) { + end_of_then.prev_sibling_or_token()? + } else { + end_of_then + }; + let target = if_expr.syntax().text_range(); acc.add( AssistId("convert_to_guarded_return", AssistKind::RefactorRewrite), @@ -141,16 +150,6 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext<' } }; - let then_block_items = then_block.dedent(IndentLevel(1)).clone_for_update(); - - let end_of_then = then_block_items.syntax().last_child_or_token().unwrap(); - let end_of_then = - if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) { - end_of_then.prev_sibling_or_token().unwrap() - } else { - end_of_then - }; - let then_statements = replacement .children_with_tokens() .chain( From 7e04142f25761f9555553081fc9e38e605579184 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 9 Aug 2023 20:06:08 +0200 Subject: [PATCH 050/197] Fix pinned version of lsp-types --- crates/hir-def/src/item_tree.rs | 2 +- crates/rust-analyzer/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 701fee40ab22..1495cc68e3fc 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -794,7 +794,7 @@ impl UseTree { fn expand_impl( &self, prefix: Option, - cb: &mut dyn FnMut(Idx, ModPath, ImportKind, Option), + cb: &mut impl FnMut(Idx, ModPath, ImportKind, Option), ) { fn concat_mod_paths( prefix: Option, diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index 5bfac7ee45c6..1f9d6db93144 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml @@ -24,7 +24,7 @@ crossbeam-channel = "0.5.5" dissimilar = "1.0.4" itertools = "0.10.5" scip = "0.1.1" -lsp-types = { version = "=0.94", features = ["proposed"] } +lsp-types = { version = "=0.94.0", features = ["proposed"] } parking_lot = "0.12.1" xflags = "0.3.0" oorandom = "11.1.3" From c81a0681a26c557e2f46dcb1876fcafa24d569b3 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Wed, 9 Aug 2023 23:42:52 +0200 Subject: [PATCH 051/197] Deunwrap generate_delegate_methods --- .../src/handlers/generate_delegate_methods.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/crates/ide-assists/src/handlers/generate_delegate_methods.rs index 31fc69562c95..bbac0a26ea4c 100644 --- a/crates/ide-assists/src/handlers/generate_delegate_methods.rs +++ b/crates/ide-assists/src/handlers/generate_delegate_methods.rs @@ -95,6 +95,9 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' let Some(impl_def) = find_struct_impl(ctx, &adt, std::slice::from_ref(&name)) else { continue; }; + + let field = make::ext::field_from_idents(["self", &field_name])?; + acc.add_group( &GroupLabel("Generate delegate methods…".to_owned()), AssistId("generate_delegate_methods", AssistKind::Generate), @@ -115,11 +118,7 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' Some(list) => convert_param_list_to_arg_list(list), None => make::arg_list([]), }; - let tail_expr = make::expr_method_call( - make::ext::field_from_idents(["self", &field_name]).unwrap(), // This unwrap is ok because we have at least 1 arg in the list - make::name_ref(&name), - arg_list, - ); + let tail_expr = make::expr_method_call(field, make::name_ref(&name), arg_list); let ret_type = method_source.ret_type(); let is_async = method_source.async_token().is_some(); let is_const = method_source.const_token().is_some(); From 423b00a83a72c9468dde600ace59ed14ae0f77a5 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Thu, 10 Aug 2023 01:22:26 +0200 Subject: [PATCH 052/197] Deunwrap remove_unused_imports --- crates/ide-assists/src/handlers/remove_unused_imports.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ide-assists/src/handlers/remove_unused_imports.rs b/crates/ide-assists/src/handlers/remove_unused_imports.rs index dd4839351fb4..5fcab8c02b06 100644 --- a/crates/ide-assists/src/handlers/remove_unused_imports.rs +++ b/crates/ide-assists/src/handlers/remove_unused_imports.rs @@ -67,7 +67,7 @@ pub(crate) fn remove_unused_imports(acc: &mut Assists, ctx: &AssistContext<'_>) // This case maps to the situation where the * token is braced. // In this case, the parent use tree's path is the one we should use to resolve the glob. match u.syntax().ancestors().skip(1).find_map(ast::UseTree::cast) { - Some(parent_u) if parent_u.path().is_some() => parent_u.path().unwrap(), + Some(parent_u) if parent_u.path().is_some() => parent_u.path()?, _ => return None, } } else { From 94b3481808e5033cf45800cc9e22e15d5245aa1a Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Thu, 10 Aug 2023 01:46:51 +0200 Subject: [PATCH 053/197] Deunwrap generate_derive --- .../src/handlers/generate_derive.rs | 50 ++++++++++++------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/crates/ide-assists/src/handlers/generate_derive.rs b/crates/ide-assists/src/handlers/generate_derive.rs index 747f70f9f6f9..5e67537c80b7 100644 --- a/crates/ide-assists/src/handlers/generate_derive.rs +++ b/crates/ide-assists/src/handlers/generate_derive.rs @@ -27,33 +27,45 @@ pub(crate) fn generate_derive(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt let cap = ctx.config.snippet_cap?; let nominal = ctx.find_node_at_offset::()?; let target = nominal.syntax().text_range(); + let derive_attr = nominal + .attrs() + .filter_map(|x| x.as_simple_call()) + .filter(|(name, _arg)| name == "derive") + .map(|(_name, arg)| arg) + .next(); + + let (derive, delimiter) = match &derive_attr { + None => { + let derive = make::attr_outer(make::meta_token_tree( + make::ext::ident_path("derive"), + make::token_tree(T!['('], vec![]).clone_for_update(), + )) + .clone_for_update(); + let delimiter = derive.meta()?.token_tree()?.r_paren_token()?; + (derive, delimiter) + } + Some(tt) => { + // Create an outer attribute just so that we avoid using + // unwrap in edit closure. + let _derive = make::attr_outer(make::meta_token_tree( + make::ext::ident_path("derive"), + make::token_tree(T!['('], vec![]), + )); + (_derive, tt.right_delimiter_token()?) + } + }; + acc.add(AssistId("generate_derive", AssistKind::Generate), "Add `#[derive]`", target, |edit| { - let derive_attr = nominal - .attrs() - .filter_map(|x| x.as_simple_call()) - .filter(|(name, _arg)| name == "derive") - .map(|(_name, arg)| arg) - .next(); match derive_attr { None => { - let derive = make::attr_outer(make::meta_token_tree( - make::ext::ident_path("derive"), - make::token_tree(T!['('], vec![]).clone_for_update(), - )) - .clone_for_update(); - let nominal = edit.make_mut(nominal); nominal.add_attr(derive.clone()); - edit.add_tabstop_before_token( - cap, - derive.meta().unwrap().token_tree().unwrap().r_paren_token().unwrap(), - ); + edit.add_tabstop_before_token(cap, delimiter); } - Some(tt) => { + Some(_) => { // Just move the cursor. - let tt = edit.make_mut(tt); - edit.add_tabstop_before_token(cap, tt.right_delimiter_token().unwrap()); + edit.add_tabstop_before_token(cap, delimiter); } }; }) From e5b23e3bc1ad9c5ea70922c74ce9bba4f4dcf299 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 10 Aug 2023 18:52:27 +0200 Subject: [PATCH 054/197] Derive block attributes from block item tree --- crates/hir-def/src/attr.rs | 10 ++++------ crates/hir-def/src/body/lower.rs | 4 +++- crates/hir-def/src/db.rs | 6 ++++++ crates/hir-def/src/item_tree.rs | 17 +++++++++-------- crates/hir-def/src/item_tree/lower.rs | 3 +++ crates/hir-def/src/nameres.rs | 11 +++++++---- crates/hir-expand/src/attrs.rs | 9 +-------- crates/syntax/src/ast/node_ext.rs | 8 ++++++++ 8 files changed, 41 insertions(+), 27 deletions(-) diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index fae07111806c..75607e51732e 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -431,12 +431,10 @@ impl AttrsWithOwner { .item_tree(db) .raw_attrs(AttrOwner::ModItem(definition_tree_id.value.into())) .clone(), - ModuleOrigin::BlockExpr { block } => RawAttrs::from_attrs_owner( - db.upcast(), - InFile::new(block.file_id, block.to_node(db.upcast())) - .as_ref() - .map(|it| it as &dyn ast::HasAttrs), - ), + ModuleOrigin::BlockExpr { id, block } => { + let tree = db.block_item_tree_query(id); + tree.raw_attrs(AttrOwner::TopLevel).clone() + } } } AttrDefId::FieldId(it) => { diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index 3853a6ab3a57..889544e151fc 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -1100,7 +1100,9 @@ impl ExprCollector<'_> { ast::Stmt::ExprStmt(es) => matches!(es.expr(), Some(ast::Expr::MacroExpr(_))), _ => false, }); - statement_has_item || matches!(block.tail_expr(), Some(ast::Expr::MacroExpr(_))) + statement_has_item + || matches!(block.tail_expr(), Some(ast::Expr::MacroExpr(_))) + || (block.may_carry_attributes() && block.attrs().next().is_some()) }; let block_id = if block_has_items { diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index e34a6768f286..5d2edf9f304c 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -82,6 +82,12 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast Arc; + #[salsa::invoke(ItemTree::block_item_tree_query)] + // FIXME: Investigate memory usage increase if this were not transparent + // Also make sure to `shrink_to_fit` if you do + #[salsa::transparent] + fn block_item_tree_query(&self, block_id: BlockId) -> Arc; + #[salsa::invoke(crate_def_map_wait)] #[salsa::transparent] fn crate_def_map(&self, krate: CrateId) -> Arc; diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 1495cc68e3fc..62292779571d 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -143,6 +143,14 @@ impl ItemTree { Arc::new(item_tree) } + pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc { + let loc = db.lookup_intern_block(block); + let block = loc.ast_id.to_node(db.upcast()); + + let ctx = lower::Ctx::new(db, loc.ast_id.file_id); + Arc::new(ctx.lower_block(&block)) + } + /// Returns an iterator over all items located at the top level of the `HirFileId` this /// `ItemTree` was created from. pub fn top_level_items(&self) -> &[ModItem] { @@ -178,13 +186,6 @@ impl ItemTree { self.data.get_or_insert_with(Box::default) } - fn block_item_tree(db: &dyn DefDatabase, block: BlockId) -> Arc { - let loc = db.lookup_intern_block(block); - let block = loc.ast_id.to_node(db.upcast()); - let ctx = lower::Ctx::new(db, loc.ast_id.file_id); - Arc::new(ctx.lower_block(&block)) - } - fn shrink_to_fit(&mut self) { if let Some(data) = &mut self.data { let ItemTreeData { @@ -382,7 +383,7 @@ impl TreeId { pub(crate) fn item_tree(&self, db: &dyn DefDatabase) -> Arc { match self.block { - Some(block) => ItemTree::block_item_tree(db, block), + Some(block) => ItemTree::block_item_tree_query(db, block), None => db.file_item_tree(self.file), } } diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index e719f9291bd3..f8efc8022347 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -77,6 +77,9 @@ impl<'a> Ctx<'a> { } pub(super) fn lower_block(mut self, block: &ast::BlockExpr) -> ItemTree { + self.tree + .attrs + .insert(AttrOwner::TopLevel, RawAttrs::new(self.db.upcast(), block, self.hygiene())); self.tree.top_level = block .statements() .filter_map(|stmt| match stmt { diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 5c99f691a643..2785b98fd6a4 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -227,6 +227,7 @@ pub enum ModuleOrigin { }, /// Pseudo-module introduced by a block scope (contains only inner items). BlockExpr { + id: BlockId, block: AstId, }, } @@ -269,7 +270,7 @@ impl ModuleOrigin { definition.file_id, ModuleSource::Module(definition.to_node(db.upcast())), ), - ModuleOrigin::BlockExpr { block } => { + ModuleOrigin::BlockExpr { block, .. } => { InFile::new(block.file_id, ModuleSource::BlockExpr(block.to_node(db.upcast()))) } } @@ -325,8 +326,10 @@ impl DefMap { // modules declared by blocks with items. At the moment, we don't use // this visibility for anything outside IDE, so that's probably OK. let visibility = Visibility::Module(ModuleId { krate, local_id, block: None }); - let module_data = - ModuleData::new(ModuleOrigin::BlockExpr { block: block.ast_id }, visibility); + let module_data = ModuleData::new( + ModuleOrigin::BlockExpr { block: block.ast_id, id: block_id }, + visibility, + ); let mut def_map = DefMap::empty(krate, parent_map.data.edition, module_data); def_map.data = parent_map.data.clone(); @@ -643,7 +646,7 @@ impl ModuleData { definition.into() } ModuleOrigin::Inline { definition, .. } => definition.file_id, - ModuleOrigin::BlockExpr { block } => block.file_id, + ModuleOrigin::BlockExpr { block, .. } => block.file_id, } } diff --git a/crates/hir-expand/src/attrs.rs b/crates/hir-expand/src/attrs.rs index 4c918e55b92a..0ec2422b30cf 100644 --- a/crates/hir-expand/src/attrs.rs +++ b/crates/hir-expand/src/attrs.rs @@ -342,14 +342,7 @@ fn inner_attributes( ast::Impl(it) => it.assoc_item_list()?.syntax().clone(), ast::Module(it) => it.item_list()?.syntax().clone(), ast::BlockExpr(it) => { - use syntax::SyntaxKind::{BLOCK_EXPR , EXPR_STMT}; - // Block expressions accept outer and inner attributes, but only when they are the outer - // expression of an expression statement or the final expression of another block expression. - let may_carry_attributes = matches!( - it.syntax().parent().map(|it| it.kind()), - Some(BLOCK_EXPR | EXPR_STMT) - ); - if !may_carry_attributes { + if !it.may_carry_attributes() { return None } syntax.clone() diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index 3308077da5b1..691d0c618f38 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -61,6 +61,14 @@ impl ast::BlockExpr { pub fn tail_expr(&self) -> Option { self.stmt_list()?.tail_expr() } + /// Block expressions accept outer and inner attributes, but only when they are the outer + /// expression of an expression statement or the final expression of another block expression. + pub fn may_carry_attributes(&self) -> bool { + matches!( + self.syntax().parent().map(|it| it.kind()), + Some(SyntaxKind::BLOCK_EXPR | SyntaxKind::EXPR_STMT) + ) + } } #[derive(Debug, PartialEq, Eq, Clone)] From fde2d9b47c1ca1a5b4c816e72acb784f7731f03e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 10 Aug 2023 19:04:46 +0200 Subject: [PATCH 055/197] Deduplicate FileId field in ModuleOrigin --- crates/hir-def/src/attr.rs | 2 +- crates/hir-def/src/nameres.rs | 31 ++++++++++++++----------- crates/hir-def/src/nameres/collector.rs | 8 +++---- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index 75607e51732e..a5db75a91ebd 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -431,7 +431,7 @@ impl AttrsWithOwner { .item_tree(db) .raw_attrs(AttrOwner::ModItem(definition_tree_id.value.into())) .clone(), - ModuleOrigin::BlockExpr { id, block } => { + ModuleOrigin::BlockExpr { id, .. } => { let tree = db.block_item_tree_query(id); tree.raw_attrs(AttrOwner::TopLevel).clone() } diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 2785b98fd6a4..9dc595ee7ee7 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -60,7 +60,7 @@ mod tests; use std::{cmp::Ord, ops::Deref}; use base_db::{CrateId, Edition, FileId, ProcMacroKind}; -use hir_expand::{name::Name, HirFileId, InFile, MacroCallId, MacroDefId}; +use hir_expand::{ast_id_map::FileAstId, name::Name, HirFileId, InFile, MacroCallId, MacroDefId}; use itertools::Itertools; use la_arena::Arena; use profile::Count; @@ -217,13 +217,13 @@ pub enum ModuleOrigin { /// Note that non-inline modules, by definition, live inside non-macro file. File { is_mod_rs: bool, - declaration: AstId, + declaration: FileAstId, declaration_tree_id: ItemTreeId, definition: FileId, }, Inline { definition_tree_id: ItemTreeId, - definition: AstId, + definition: FileAstId, }, /// Pseudo-module introduced by a block scope (contains only inner items). BlockExpr { @@ -235,8 +235,12 @@ pub enum ModuleOrigin { impl ModuleOrigin { pub fn declaration(&self) -> Option> { match self { - ModuleOrigin::File { declaration: module, .. } - | ModuleOrigin::Inline { definition: module, .. } => Some(*module), + &ModuleOrigin::File { declaration, declaration_tree_id, .. } => { + Some(AstId::new(declaration_tree_id.file_id(), declaration)) + } + &ModuleOrigin::Inline { definition, definition_tree_id } => { + Some(AstId::new(definition_tree_id.file_id(), definition)) + } ModuleOrigin::CrateRoot { .. } | ModuleOrigin::BlockExpr { .. } => None, } } @@ -261,14 +265,15 @@ impl ModuleOrigin { /// That is, a file or a `mod foo {}` with items. fn definition_source(&self, db: &dyn DefDatabase) -> InFile { match self { - ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => { - let file_id = *definition; - let sf = db.parse(file_id).tree(); - InFile::new(file_id.into(), ModuleSource::SourceFile(sf)) + &ModuleOrigin::File { definition, .. } | &ModuleOrigin::CrateRoot { definition } => { + let sf = db.parse(definition).tree(); + InFile::new(definition.into(), ModuleSource::SourceFile(sf)) } - ModuleOrigin::Inline { definition, .. } => InFile::new( - definition.file_id, - ModuleSource::Module(definition.to_node(db.upcast())), + &ModuleOrigin::Inline { definition, definition_tree_id } => InFile::new( + definition_tree_id.file_id(), + ModuleSource::Module( + AstId::new(definition_tree_id.file_id(), definition).to_node(db.upcast()), + ), ), ModuleOrigin::BlockExpr { block, .. } => { InFile::new(block.file_id, ModuleSource::BlockExpr(block.to_node(db.upcast()))) @@ -645,7 +650,7 @@ impl ModuleData { ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => { definition.into() } - ModuleOrigin::Inline { definition, .. } => definition.file_id, + ModuleOrigin::Inline { definition_tree_id, .. } => definition_tree_id.file_id(), ModuleOrigin::BlockExpr { block, .. } => block.file_id, } } diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 92d5cdd09bd7..410bbe025353 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -1843,7 +1843,7 @@ impl ModCollector<'_, '_> { ModKind::Inline { items } => { let module_id = self.push_child_module( module.name.clone(), - AstId::new(self.file_id(), module.ast_id), + module.ast_id, None, &self.item_tree[module.visibility], module_id, @@ -1881,7 +1881,7 @@ impl ModCollector<'_, '_> { if is_enabled { let module_id = self.push_child_module( module.name.clone(), - ast_id, + ast_id.value, Some((file_id, is_mod_rs)), &self.item_tree[module.visibility], module_id, @@ -1908,7 +1908,7 @@ impl ModCollector<'_, '_> { Err(candidates) => { self.push_child_module( module.name.clone(), - ast_id, + ast_id.value, None, &self.item_tree[module.visibility], module_id, @@ -1925,7 +1925,7 @@ impl ModCollector<'_, '_> { fn push_child_module( &mut self, name: Name, - declaration: AstId, + declaration: FileAstId, definition: Option<(FileId, bool)>, visibility: &crate::visibility::RawVisibility, mod_tree_id: FileItemTreeId, From bfad781a77cf2eb945694718e9cb3ab2830ecb28 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 10 Aug 2023 19:22:46 +0200 Subject: [PATCH 056/197] Memoize block_item_tree_query --- crates/hir-def/src/db.rs | 3 --- crates/hir-def/src/item_tree.rs | 6 ++++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index 5d2edf9f304c..31c1a713031c 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -83,9 +83,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast Arc; #[salsa::invoke(ItemTree::block_item_tree_query)] - // FIXME: Investigate memory usage increase if this were not transparent - // Also make sure to `shrink_to_fit` if you do - #[salsa::transparent] fn block_item_tree_query(&self, block_id: BlockId) -> Arc; #[salsa::invoke(crate_def_map_wait)] diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 62292779571d..5734f1c67b6a 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -148,7 +148,9 @@ impl ItemTree { let block = loc.ast_id.to_node(db.upcast()); let ctx = lower::Ctx::new(db, loc.ast_id.file_id); - Arc::new(ctx.lower_block(&block)) + let mut item_tree = ctx.lower_block(&block); + item_tree.shrink_to_fit(); + Arc::new(item_tree) } /// Returns an iterator over all items located at the top level of the `HirFileId` this @@ -383,7 +385,7 @@ impl TreeId { pub(crate) fn item_tree(&self, db: &dyn DefDatabase) -> Arc { match self.block { - Some(block) => ItemTree::block_item_tree_query(db, block), + Some(block) => db.block_item_tree_query(block), None => db.file_item_tree(self.file), } } From 9adff006e884287f3924cd599dcdb0fe58308623 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 10 Aug 2023 20:10:19 +0200 Subject: [PATCH 057/197] Simplify --- crates/hir-def/src/item_tree.rs | 4 ++-- crates/hir-def/src/nameres.rs | 7 +++---- crates/hir-def/src/nameres/collector.rs | 10 +++++----- crates/hir-expand/src/lib.rs | 5 +---- crates/hir-ty/src/mir/lower.rs | 4 ++-- crates/hir/src/lib.rs | 20 +++++++------------- 6 files changed, 20 insertions(+), 30 deletions(-) diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 5734f1c67b6a..957a5cf2e2bd 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -68,7 +68,7 @@ use crate::{ path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, type_ref::{Mutability, TraitRef, TypeBound, TypeRef}, visibility::RawVisibility, - BlockId, + BlockId, Lookup, }; #[derive(Copy, Clone, Eq, PartialEq)] @@ -144,7 +144,7 @@ impl ItemTree { } pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc { - let loc = db.lookup_intern_block(block); + let loc = block.lookup(db); let block = loc.ast_id.to_node(db.upcast()); let ctx = lower::Ctx::new(db, loc.ast_id.file_id); diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 9dc595ee7ee7..f93125e224db 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -320,9 +320,7 @@ impl DefMap { } pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc { - let block: BlockLoc = db.lookup_intern_block(block_id); - - let tree_id = TreeId::new(block.ast_id.file_id, Some(block_id)); + let block: BlockLoc = block_id.lookup(db); let parent_map = block.module.def_map(db); let krate = block.module.krate; @@ -346,7 +344,8 @@ impl DefMap { }, }); - let def_map = collector::collect_defs(db, def_map, tree_id); + let def_map = + collector::collect_defs(db, def_map, TreeId::new(block.ast_id.file_id, Some(block_id))); Arc::new(def_map) } diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 410bbe025353..e3253404d49f 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -53,9 +53,9 @@ use crate::{ visibility::{RawVisibility, Visibility}, AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantId, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern, - ItemContainerId, LocalModuleId, Macro2Id, Macro2Loc, MacroExpander, MacroId, MacroRulesId, - MacroRulesLoc, ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc, StructLoc, - TraitAliasLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, UseId, UseLoc, + ItemContainerId, LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId, + MacroRulesId, MacroRulesLoc, ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc, + StructLoc, TraitAliasLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, UseId, UseLoc, }; static GLOB_RECURSION_LIMIT: Limit = Limit::new(100); @@ -1461,7 +1461,7 @@ impl DefCollector<'_> { let mut diagnosed_extern_crates = FxHashSet::default(); for directive in &self.unresolved_imports { if let ImportSource::ExternCrate { id } = directive.import.source { - let item_tree_id = self.db.lookup_intern_extern_crate(id).id; + let item_tree_id = id.lookup(self.db).id; let item_tree = item_tree_id.item_tree(self.db); let extern_crate = &item_tree[item_tree_id.value]; @@ -1482,7 +1482,7 @@ impl DefCollector<'_> { ) { continue; } - let item_tree_id = self.db.lookup_intern_use(id).id; + let item_tree_id = id.lookup(self.db).id; self.def_map.diagnostics.push(DefDiagnostic::unresolved_import( directive.module_id, item_tree_id, diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs index 1f1e20f49e3c..ba14553d90e3 100644 --- a/crates/hir-expand/src/lib.rs +++ b/crates/hir-expand/src/lib.rs @@ -544,7 +544,7 @@ impl MacroCallKind { }; let range = match kind { - MacroCallKind::FnLike { ast_id, .. } => ast_id.to_node(db).syntax().text_range(), + MacroCallKind::FnLike { ast_id, .. } => ast_id.to_ptr(db).text_range(), MacroCallKind::Derive { ast_id, derive_attr_index, .. } => { // FIXME: should be the range of the macro name, not the whole derive // FIXME: handle `cfg_attr` @@ -840,9 +840,6 @@ impl AstId { pub type ErasedAstId = InFile; impl ErasedAstId { - pub fn to_node(&self, db: &dyn db::ExpandDatabase) -> SyntaxNode { - self.to_ptr(db).to_node(&db.parse_or_expand(self.file_id)) - } pub fn to_ptr(&self, db: &dyn db::ExpandDatabase) -> SyntaxNodePtr { db.ast_id_map(self.file_id).get_raw(self.value) } diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 9eaa9e1c2f5f..7ab0c1f7f2f8 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -15,7 +15,7 @@ use hir_def::{ path::Path, resolver::{resolver_for_expr, HasResolver, ResolveValueResult, ValueNs}, AdtId, DefWithBodyId, EnumVariantId, GeneralConstId, HasModule, ItemContainerId, LocalFieldId, - TraitId, TypeOrConstParamId, + Lookup, TraitId, TypeOrConstParamId, }; use hir_expand::name::Name; use la_arena::ArenaMap; @@ -372,7 +372,7 @@ impl<'ctx> MirLowerCtx<'ctx> { match &self.body.exprs[expr_id] { Expr::Missing => { if let DefWithBodyId::FunctionId(f) = self.owner { - let assoc = self.db.lookup_intern_function(f); + let assoc = f.lookup(self.db.upcast()); if let ItemContainerId::TraitId(t) = assoc.container { let name = &self.db.function_data(f).name; return Err(MirLowerError::TraitFunctionDefinition(t, name.clone())); diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index b1c00d816f81..46def6c052f4 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -719,20 +719,18 @@ fn emit_def_diagnostic_( ) { match diag { DefDiagnosticKind::UnresolvedModule { ast: declaration, candidates } => { - let decl = declaration.to_node(db.upcast()); + let decl = declaration.to_ptr(db.upcast()); acc.push( UnresolvedModule { - decl: InFile::new(declaration.file_id, AstPtr::new(&decl)), + decl: InFile::new(declaration.file_id, decl), candidates: candidates.clone(), } .into(), ) } DefDiagnosticKind::UnresolvedExternCrate { ast } => { - let item = ast.to_node(db.upcast()); - acc.push( - UnresolvedExternCrate { decl: InFile::new(ast.file_id, AstPtr::new(&item)) }.into(), - ); + let item = ast.to_ptr(db.upcast()); + acc.push(UnresolvedExternCrate { decl: InFile::new(ast.file_id, item) }.into()); } DefDiagnosticKind::UnresolvedImport { id, index } => { @@ -747,14 +745,10 @@ fn emit_def_diagnostic_( } DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => { - let item = ast.to_node(db.upcast()); + let item = ast.to_ptr(db.upcast()); acc.push( - InactiveCode { - node: ast.with_value(SyntaxNodePtr::new(&item).into()), - cfg: cfg.clone(), - opts: opts.clone(), - } - .into(), + InactiveCode { node: ast.with_value(item), cfg: cfg.clone(), opts: opts.clone() } + .into(), ); } DefDiagnosticKind::UnresolvedProcMacro { ast, krate } => { From 0ef541e535c9d301a62fe039c6904e4d82a5c824 Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Tue, 8 Aug 2023 14:15:29 -0700 Subject: [PATCH 058/197] Increase the buffer size for discover project command The default value for maxBuffer is 1 MiB[1]. If the discover project command returns stdout or stderr that is greater than 1 MiB, the extension would error with "RangeError: stderr maxBuffer length exceeded". Set the default value for maxBuffer to 10 MiB for project discovery. [1] https://nodejs.org/api/child_process.html#child_processexeccommand-options-callback --- editors/code/src/util.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/editors/code/src/util.ts b/editors/code/src/util.ts index 38ce6761578f..0ddb2922198b 100644 --- a/editors/code/src/util.ts +++ b/editors/code/src/util.ts @@ -151,6 +151,7 @@ export function execute(command: string, options: ExecOptions): Promise } export function executeDiscoverProject(command: string, options: ExecOptions): Promise { + options = Object.assign({ maxBuffer: 10 * 1024 * 1024 }, options); log.info(`running command: ${command}`); return new Promise((resolve, reject) => { exec(command, options, (err, stdout, _) => { From 687bffa49375aa00bacc51f5d9adfb84a9453e17 Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Mon, 7 Aug 2023 14:24:41 -0700 Subject: [PATCH 059/197] Use the same DISubprogram for each instance of the same inlined function within the caller --- compiler/rustc_codegen_gcc/src/debuginfo.rs | 2 +- .../src/debuginfo/create_scope_map.rs | 35 ++++++---- .../rustc_codegen_llvm/src/debuginfo/mod.rs | 70 +++++++++++-------- .../rustc_codegen_ssa/src/mir/debuginfo.rs | 14 +++- compiler/rustc_codegen_ssa/src/mir/mod.rs | 2 +- .../rustc_codegen_ssa/src/traits/debuginfo.rs | 2 +- .../debuginfo-inline-callsite-location.rs | 26 +++++++ 7 files changed, 103 insertions(+), 48 deletions(-) create mode 100644 tests/codegen/debuginfo-inline-callsite-location.rs diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs index a81585d41284..d1bfd833cd87 100644 --- a/compiler/rustc_codegen_gcc/src/debuginfo.rs +++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs @@ -55,7 +55,7 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> { _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _llfn: RValue<'gcc>, _mir: &mir::Body<'tcx>, - ) -> Option> { + ) -> Option> { // TODO(antoyo) None } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index d174a3593b99..7a68c291aa59 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -20,7 +20,7 @@ pub fn compute_mir_scopes<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>, mir: &Body<'tcx>, - debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>, + debug_context: &mut FunctionDebugContext<'tcx, &'ll DIScope, &'ll DILocation>, ) { // Find all scopes with variables defined in them. let variables = if cx.sess().opts.debuginfo == DebugInfo::Full { @@ -51,7 +51,7 @@ fn make_mir_scope<'ll, 'tcx>( instance: Instance<'tcx>, mir: &Body<'tcx>, variables: &Option>, - debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>, + debug_context: &mut FunctionDebugContext<'tcx, &'ll DIScope, &'ll DILocation>, instantiated: &mut BitSet, scope: SourceScope, ) { @@ -84,7 +84,6 @@ fn make_mir_scope<'ll, 'tcx>( } let loc = cx.lookup_debug_loc(scope_data.span.lo()); - let file_metadata = file_metadata(cx, &loc.file); let dbg_scope = match scope_data.inlined { Some((callee, _)) => { @@ -95,18 +94,26 @@ fn make_mir_scope<'ll, 'tcx>( ty::ParamEnv::reveal_all(), ty::EarlyBinder::bind(callee), ); - let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty()); - cx.dbg_scope_fn(callee, callee_fn_abi, None) + debug_context.inlined_function_scopes.entry(callee).or_insert_with(|| { + let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty()); + cx.dbg_scope_fn(callee, callee_fn_abi, None) + }) + } + None => { + let file_metadata = file_metadata(cx, &loc.file); + debug_context + .lexical_blocks + .entry((parent_scope.dbg_scope, loc.line, loc.col, file_metadata)) + .or_insert_with(|| unsafe { + llvm::LLVMRustDIBuilderCreateLexicalBlock( + DIB(cx), + parent_scope.dbg_scope, + file_metadata, + loc.line, + loc.col, + ) + }) } - None => unsafe { - llvm::LLVMRustDIBuilderCreateLexicalBlock( - DIB(cx), - parent_scope.dbg_scope, - file_metadata, - loc.line, - loc.col, - ) - }, }; let inlined_at = scope_data.inlined.map(|(_, callsite_span)| { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 40714a0afe91..d03819b16881 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -5,7 +5,7 @@ use rustc_codegen_ssa::mir::debuginfo::VariableKind::*; use self::metadata::{file_metadata, type_di_node}; use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER}; use self::namespace::mangled_name_of_instance; -use self::utils::{create_DIArray, is_node_local_to_unit, DIB}; +use self::utils::{create_DIArray, debug_context, is_node_local_to_unit, DIB}; use crate::abi::FnAbi; use crate::builder::Builder; @@ -67,6 +67,8 @@ pub struct CodegenUnitDebugContext<'ll, 'tcx> { type_map: metadata::TypeMap<'ll, 'tcx>, namespace_map: RefCell>, recursion_marker_type: OnceCell<&'ll DIType>, + /// Maps a varaible (name, scope, kind (argument or local), span) to its debug information. + variables: RefCell>, } impl Drop for CodegenUnitDebugContext<'_, '_> { @@ -91,6 +93,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { type_map: Default::default(), namespace_map: RefCell::new(Default::default()), recursion_marker_type: OnceCell::new(), + variables: RefCell::new(Default::default()), } } @@ -292,7 +295,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn_abi: &FnAbi<'tcx, Ty<'tcx>>, llfn: &'ll Value, mir: &mir::Body<'tcx>, - ) -> Option> { + ) -> Option> { if self.sess().opts.debuginfo == DebugInfo::None { return None; } @@ -304,8 +307,11 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { file_start_pos: BytePos(0), file_end_pos: BytePos(0), }; - let mut fn_debug_context = - FunctionDebugContext { scopes: IndexVec::from_elem(empty_scope, &mir.source_scopes) }; + let mut fn_debug_context = FunctionDebugContext { + scopes: IndexVec::from_elem(empty_scope, &mir.source_scopes), + inlined_function_scopes: Default::default(), + lexical_blocks: Default::default(), + }; // Fill in all the scopes, with the information from the MIR body. compute_mir_scopes(self, instance, mir, &mut fn_debug_context); @@ -606,33 +612,39 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { variable_kind: VariableKind, span: Span, ) -> &'ll DIVariable { - let loc = self.lookup_debug_loc(span.lo()); - let file_metadata = file_metadata(self, &loc.file); + debug_context(self) + .variables + .borrow_mut() + .entry((variable_name, scope_metadata, variable_kind, span)) + .or_insert_with(|| { + let loc = self.lookup_debug_loc(span.lo()); + let file_metadata = file_metadata(self, &loc.file); - let type_metadata = type_di_node(self, variable_type); + let type_metadata = type_di_node(self, variable_type); - let (argument_index, dwarf_tag) = match variable_kind { - ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable), - LocalVariable => (0, DW_TAG_auto_variable), - }; - let align = self.align_of(variable_type); + let (argument_index, dwarf_tag) = match variable_kind { + ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable), + LocalVariable => (0, DW_TAG_auto_variable), + }; + let align = self.align_of(variable_type); - let name = variable_name.as_str(); - unsafe { - llvm::LLVMRustDIBuilderCreateVariable( - DIB(self), - dwarf_tag, - scope_metadata, - name.as_ptr().cast(), - name.len(), - file_metadata, - loc.line, - type_metadata, - true, - DIFlags::FlagZero, - argument_index, - align.bytes() as u32, - ) - } + let name = variable_name.as_str(); + unsafe { + llvm::LLVMRustDIBuilderCreateVariable( + DIB(self), + dwarf_tag, + scope_metadata, + name.as_ptr().cast(), + name.len(), + file_metadata, + loc.line, + type_metadata, + true, + DIFlags::FlagZero, + argument_index, + align.bytes() as u32, + ) + } + }) } } diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index 4167a85ccd59..b9d5b54dc621 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -1,10 +1,12 @@ use crate::traits::*; +use rustc_data_structures::fx::FxHashMap; use rustc_index::IndexVec; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir; use rustc_middle::ty; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; +use rustc_middle::ty::Instance; use rustc_middle::ty::Ty; use rustc_session::config::DebugInfo; use rustc_span::symbol::{kw, Symbol}; @@ -17,11 +19,19 @@ use super::{FunctionCx, LocalRef}; use std::ops::Range; -pub struct FunctionDebugContext { +pub struct FunctionDebugContext<'tcx, S, L> { + /// Maps from source code to the corresponding debug info scope. pub scopes: IndexVec>, + + /// Maps from a given inlined function to its debug info declaration. + pub inlined_function_scopes: FxHashMap, S>, + + /// Maps from a lexical block (parent scope, line, column, file) to its debug info declaration. + /// This is particularily useful if the parent scope is an inlined function. + pub lexical_blocks: FxHashMap<(S, u32, u32, S), S>, } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Eq, PartialEq, Hash)] pub enum VariableKind { ArgumentVariable(usize /*index*/), LocalVariable, diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 3464f910829d..ccf93f208d50 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -45,7 +45,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { mir: &'tcx mir::Body<'tcx>, - debug_context: Option>, + debug_context: Option>, llfn: Bx::Function, diff --git a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs index 63fecaf34fd5..4acc0ea076c1 100644 --- a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs @@ -26,7 +26,7 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes { fn_abi: &FnAbi<'tcx, Ty<'tcx>>, llfn: Self::Function, mir: &mir::Body<'tcx>, - ) -> Option>; + ) -> Option>; // FIXME(eddyb) find a common convention for all of the debuginfo-related // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.). diff --git a/tests/codegen/debuginfo-inline-callsite-location.rs b/tests/codegen/debuginfo-inline-callsite-location.rs new file mode 100644 index 000000000000..e2ea9dda4a09 --- /dev/null +++ b/tests/codegen/debuginfo-inline-callsite-location.rs @@ -0,0 +1,26 @@ +// compile-flags: -g -O + +// Check that each inline call site for the same function uses the same "sub-program" so that LLVM +// can correctly merge the debug info if it merges the inlined code (e.g., for merging of tail +// calls to panic. + +// CHECK: tail call void @_ZN4core9panicking5panic17h{{([0-9a-z]{16})}}E +// CHECK-SAME: !dbg ![[#first_dbg:]] +// CHECK: tail call void @_ZN4core9panicking5panic17h{{([0-9a-z]{16})}}E +// CHECK-SAME: !dbg ![[#second_dbg:]] + +// CHECK: ![[#func_dbg:]] = distinct !DISubprogram(name: "unwrap" +// CHECK: ![[#first_dbg]] = !DILocation(line: [[#]] +// CHECK-SAME: scope: ![[#func_dbg]], inlinedAt: ![[#]]) +// CHECK: ![[#second_dbg]] = !DILocation(line: [[#]] +// CHECK-SAME: scope: ![[#func_dbg]], inlinedAt: ![[#]]) + +#![crate_type = "lib"] + +#[no_mangle] +extern "C" fn add_numbers(x: &Option, y: &Option) -> i32 { + let x1 = x.unwrap(); + let y1 = y.unwrap(); + + x1 + y1 +} From c1c8e787d22b06bff095b261e3f2e6c539cf590e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 10 Aug 2023 20:11:03 +0200 Subject: [PATCH 060/197] Preserve `resolve_obligations_as_possible` temporary allocation across calls --- crates/hir-ty/src/infer/unify.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs index 169679b4636e..0a68a9f3b583 100644 --- a/crates/hir-ty/src/infer/unify.rs +++ b/crates/hir-ty/src/infer/unify.rs @@ -143,6 +143,9 @@ pub(crate) struct InferenceTable<'a> { var_unification_table: ChalkInferenceTable, type_variable_table: Vec, pending_obligations: Vec>>, + /// Double buffer used in [`Self::resolve_obligations_as_possible`] to cut down on + /// temporary allocations. + resolve_obligations_buffer: Vec>>, } pub(crate) struct InferenceTableSnapshot { @@ -159,6 +162,7 @@ impl<'a> InferenceTable<'a> { var_unification_table: ChalkInferenceTable::new(), type_variable_table: Vec::new(), pending_obligations: Vec::new(), + resolve_obligations_buffer: Vec::new(), } } @@ -510,10 +514,10 @@ impl<'a> InferenceTable<'a> { pub(crate) fn resolve_obligations_as_possible(&mut self) { let _span = profile::span("resolve_obligations_as_possible"); let mut changed = true; - let mut obligations = Vec::new(); - while changed { - changed = false; + let mut obligations = mem::take(&mut self.resolve_obligations_buffer); + while mem::take(&mut changed) { mem::swap(&mut self.pending_obligations, &mut obligations); + for canonicalized in obligations.drain(..) { if !self.check_changed(&canonicalized) { self.pending_obligations.push(canonicalized); @@ -528,6 +532,8 @@ impl<'a> InferenceTable<'a> { self.register_obligation_in_env(uncanonical); } } + self.resolve_obligations_buffer = obligations; + self.resolve_obligations_buffer.clear(); } pub(crate) fn fudge_inference>( From d6d188fce2f2dec3b6d290477c7727b420b0c320 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 12 Aug 2023 06:32:23 +0200 Subject: [PATCH 061/197] fix: Fix `only_types` config filtering out traits from world symbols --- crates/ide-db/src/symbol_index.rs | 2 ++ crates/ide/src/navigation_target.rs | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/ide-db/src/symbol_index.rs b/crates/ide-db/src/symbol_index.rs index b54c43b296b2..ad1ce453ecaa 100644 --- a/crates/ide-db/src/symbol_index.rs +++ b/crates/ide-db/src/symbol_index.rs @@ -323,6 +323,8 @@ impl Query { hir::ModuleDef::Adt(..) | hir::ModuleDef::TypeAlias(..) | hir::ModuleDef::BuiltinType(..) + | hir::ModuleDef::TraitAlias(..) + | hir::ModuleDef::Trait(..) ) { continue; diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs index d1479dd1e584..0740bfbc7b19 100644 --- a/crates/ide/src/navigation_target.rs +++ b/crates/ide/src/navigation_target.rs @@ -175,8 +175,12 @@ impl TryToNav for FileSymbol { Some(NavigationTarget { file_id: full_range.file_id, - name: if self.is_alias { self.def.name(db)?.to_smol_str() } else { self.name.clone() }, - alias: if self.is_alias { Some(self.name.clone()) } else { None }, + name: self + .is_alias + .then(|| self.def.name(db)) + .flatten() + .map_or_else(|| self.name.clone(), |it| it.to_smol_str()), + alias: self.is_alias.then(|| self.name.clone()), kind: Some(hir::ModuleDefId::from(self.def).into()), full_range: full_range.range, focus_range, From 33f9250d2139fa00038736515b9e22c51c419c01 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 12 Aug 2023 07:10:20 +0200 Subject: [PATCH 062/197] Pass server extraEnv to isValidExecutable --- editors/code/src/bootstrap.ts | 2 +- editors/code/src/util.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/editors/code/src/bootstrap.ts b/editors/code/src/bootstrap.ts index ef4dff095cf9..6cf399599d94 100644 --- a/editors/code/src/bootstrap.ts +++ b/editors/code/src/bootstrap.ts @@ -20,7 +20,7 @@ export async function bootstrap( log.info("Using server binary at", path); - if (!isValidExecutable(path)) { + if (!isValidExecutable(path, config.serverExtraEnv)) { 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.`); diff --git a/editors/code/src/util.ts b/editors/code/src/util.ts index 38ce6761578f..e53945257726 100644 --- a/editors/code/src/util.ts +++ b/editors/code/src/util.ts @@ -2,6 +2,7 @@ import * as vscode from "vscode"; import { strict as nativeAssert } from "assert"; import { exec, type ExecOptions, spawnSync } from "child_process"; import { inspect } from "util"; +import { Env } from "./client"; export function assert(condition: boolean, explanation: string): asserts condition { try { @@ -93,10 +94,13 @@ export function isDocumentInWorkspace(document: RustDocument): boolean { return false; } -export function isValidExecutable(path: string): boolean { +export function isValidExecutable(path: string, extraEnv: Env): boolean { log.debug("Checking availability of a binary at", path); - const res = spawnSync(path, ["--version"], { encoding: "utf8" }); + const res = spawnSync(path, ["--version"], { + encoding: "utf8", + env: { ...process.env, ...extraEnv }, + }); const printOutput = res.error ? log.warn : log.info; printOutput(path, "--version:", res); From 9ac88d8d36b0e53ace1d67e98ec7c38363cd76d8 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 11 Aug 2023 09:58:55 +0200 Subject: [PATCH 063/197] Fix parser being stuck in eager macro inputs --- crates/hir-def/src/body/lower.rs | 3 ++ .../macro_expansion_tests/builtin_fn_macro.rs | 2 +- .../macro_expansion_tests/mbe/regression.rs | 38 +++++++++++++++++++ crates/parser/src/grammar.rs | 4 +- 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index 3853a6ab3a57..3389fdfb15ed 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -505,6 +505,9 @@ impl ExprCollector<'_> { let mut args = Vec::new(); let mut arg_types = Vec::new(); if let Some(pl) = e.param_list() { + let num_params = pl.params().count(); + args.reserve_exact(num_params); + arg_types.reserve_exact(num_params); for param in pl.params() { let pat = this.collect_pat_top(param.pat()); let type_ref = diff --git a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs index 1250cbb742c5..b232651db96e 100644 --- a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs +++ b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs @@ -238,7 +238,7 @@ fn main() { /* error: expected expression */; /* error: expected expression, expected COMMA */; /* error: expected expression */::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(), ::core::fmt::Display::fmt), ]); - /* error: expected expression, expected expression */; + /* error: expected expression, expected R_PAREN */; ::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(5), ::core::fmt::Display::fmt), ]); } "##]], diff --git a/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs b/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs index b783de4ccc2b..97554f93f1c1 100644 --- a/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs +++ b/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs @@ -936,3 +936,41 @@ fn main() { "##]], ); } + +#[test] +fn eager_regression_154032() { + check( + r#" +#[rustc_builtin_macro] +#[macro_export] +macro_rules! format_args {} + +fn main() { + format_args /* +errors */ !("{}", &[0 2]); +} + +"#, + expect![[r##" +#[rustc_builtin_macro] +#[macro_export] +macro_rules! format_args {} + +fn main() { + /* error: expected COMMA, expected R_BRACK, expected COMMA, expected COMMA, expected expression, expected R_PAREN *//* parse error: expected COMMA */ +/* parse error: expected R_BRACK */ +/* parse error: expected COMMA */ +/* parse error: expected COMMA */ +/* parse error: expected expression */ +/* parse error: expected R_PAREN */ +/* parse error: expected R_PAREN */ +/* parse error: expected expression, item or let statement */ +/* parse error: expected expression, item or let statement */ +/* parse error: expected expression, item or let statement */ +/* parse error: expected expression, item or let statement */ +/* parse error: expected expression, item or let statement */ +::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(&[0 2]), ::core::fmt::Display::fmt), ]); +} + +"##]], + ); +} diff --git a/crates/parser/src/grammar.rs b/crates/parser/src/grammar.rs index 333318f53b7e..6a2a9adce15c 100644 --- a/crates/parser/src/grammar.rs +++ b/crates/parser/src/grammar.rs @@ -184,7 +184,9 @@ pub(crate) mod entry { }; p.bump_any(); while !p.at(EOF) && !p.at(closing_paren_kind) { - expressions::expr(p); + if expressions::expr(p).is_none() { + break; + } if !p.at(EOF) && !p.at(closing_paren_kind) { p.expect(T![,]); } From 90dc2f839b05bf0467bac71d9be738eab6423dc7 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sat, 12 Aug 2023 02:13:37 -0700 Subject: [PATCH 064/197] Name what ln_gamma does The previous description omitted some important details. --- library/std/src/f32.rs | 4 +++- library/std/src/f64.rs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index a53b85352136..878b13581ac4 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -978,7 +978,9 @@ impl f32 { unsafe { cmath::tgammaf(self) } } - /// Returns the natural logarithm of the gamma function. + /// Natural logarithm of the absolute value of the gamma function + /// + /// The integer part of the tuple indicates the sign of the gamma function. /// /// # Examples /// diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index a1cec22c97ae..e12cdb1b4ecd 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -978,7 +978,9 @@ impl f64 { unsafe { cmath::tgamma(self) } } - /// Returns the natural logarithm of the gamma function. + /// Natural logarithm of the absolute value of the gamma function + /// + /// The integer part of the tuple indicates the sign of the gamma function. /// /// # Examples /// From d51521e28044edcff0a1f7666629e5e7aea73727 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 7 Jan 2023 14:48:55 +0100 Subject: [PATCH 065/197] Add warning block support in rustdoc --- src/librustdoc/html/static/css/rustdoc.css | 26 ++++++++++++++++--- src/librustdoc/html/static/css/themes/ayu.css | 1 + .../html/static/css/themes/dark.css | 1 + .../html/static/css/themes/light.css | 1 + 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index b1de8c1529e7..da4da50106ab 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -270,7 +270,7 @@ ul ul, ol ul, ul ol, ol ol { margin-bottom: .625em; } -p { +p, .docblock > .warning { /* Paragraph spacing at least 1.5 times line spacing per Web Content Accessibility Guidelines. Line-height is 1.5rem, so line spacing is .5rem; .75em is 1.5 times that. https://www.w3.org/WAI/WCAG21/Understanding/visual-presentation.html */ @@ -278,7 +278,7 @@ p { } /* For the last child of a div, the margin will be taken care of by the margin-top of the next item. */ -p:last-child { +p:last-child, .docblock > .warning:last-child { margin: 0; } @@ -1096,7 +1096,7 @@ pre.rust .doccomment { } .example-wrap.ignore .tooltip { - color: var(--codeblock-ignore-color); + color: var(--codeblock-ignore-color); } .example-wrap.compile_fail:hover .tooltip, @@ -1124,6 +1124,26 @@ pre.rust .doccomment { font-size: 1.25rem; } +/* This class only exists for users who want to draw attention to a particular element in their +documentation. */ +.content .docblock .warning { + border-left: 2px solid var(--warning-border-color); + padding: 14px; + position: relative; + /* The "!important" part is required because the rule is otherwise overruled in this CSS + selector: ".docblock > :not(.more-examples-toggle):not(.example-wrap)" */ + overflow-x: visible !important; +} +.content .docblock .warning::before { + color: var(--warning-border-color); + content: "ⓘ"; + position: absolute; + left: -25px; + top: 5px; + font-weight: bold; + font-size: 1.25rem; +} + a.test-arrow { visibility: hidden; position: absolute; diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index d8dae51eb1bf..c81a80eeca05 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -31,6 +31,7 @@ Original by Dempfi (https://github.com/dempfi/ayu) --codeblock-error-color: rgba(255, 0, 0, .5); --codeblock-ignore-hover-color: rgb(255, 142, 0); --codeblock-ignore-color: rgba(255, 142, 0, .6); + --warning-border-color: rgb(255, 142, 0); --type-link-color: #ffa0a5; --trait-link-color: #39afd7; --assoc-item-link-color: #39afd7; diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index 2b302988734f..0f8b1dc24a65 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -26,6 +26,7 @@ --codeblock-error-color: rgba(255, 0, 0, .5); --codeblock-ignore-hover-color: rgb(255, 142, 0); --codeblock-ignore-color: rgba(255, 142, 0, .6); + --warning-border-color: rgb(255, 142, 0); --type-link-color: #2dbfb8; --trait-link-color: #b78cf2; --assoc-item-link-color: #d2991d; diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 56fd8cbef121..39ea44a11654 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -26,6 +26,7 @@ --codeblock-error-color: rgba(255, 0, 0, .5); --codeblock-ignore-hover-color: rgb(255, 142, 0); --codeblock-ignore-color: rgba(255, 142, 0, .6); + --warning-border-color: rgb(255, 142, 0); --type-link-color: #ad378a; --trait-link-color: #6e4fc9; --assoc-item-link-color: #3873ad; From 57d2b84a57225717c6af8748574b4a847d62433c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 7 Jan 2023 14:49:11 +0100 Subject: [PATCH 066/197] Add documentation for warning blocks in rustdoc book --- src/doc/rustdoc/src/how-to-write-documentation.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/doc/rustdoc/src/how-to-write-documentation.md b/src/doc/rustdoc/src/how-to-write-documentation.md index 1fa9f8144760..aaabaa6098f5 100644 --- a/src/doc/rustdoc/src/how-to-write-documentation.md +++ b/src/doc/rustdoc/src/how-to-write-documentation.md @@ -254,6 +254,18 @@ characters: So, no need to manually enter those Unicode characters! +### Adding a warning block + +If you want to make a "warning" stand out in the documentation, you can wrap it like this: + +```md +/// documentation +/// +///
A big warning!
+/// +/// more documentation +``` + [`backtrace`]: https://docs.rs/backtrace/0.3.50/backtrace/ [commonmark markdown specification]: https://commonmark.org/ [commonmark quick reference]: https://commonmark.org/help/ From 1d42913058d4005655ea51b2d9dde707791c6541 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 7 Jan 2023 14:50:03 +0100 Subject: [PATCH 067/197] Add GUI test for warning blocks --- .../rustdoc/src/how-to-write-documentation.md | 3 +- tests/rustdoc-gui/src/test_docs/lib.rs | 12 +++++ tests/rustdoc-gui/warning-block.goml | 45 +++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 tests/rustdoc-gui/warning-block.goml diff --git a/src/doc/rustdoc/src/how-to-write-documentation.md b/src/doc/rustdoc/src/how-to-write-documentation.md index aaabaa6098f5..acab1a93690c 100644 --- a/src/doc/rustdoc/src/how-to-write-documentation.md +++ b/src/doc/rustdoc/src/how-to-write-documentation.md @@ -256,7 +256,8 @@ So, no need to manually enter those Unicode characters! ### Adding a warning block -If you want to make a "warning" stand out in the documentation, you can wrap it like this: +If you want to make a warning or similar note stand out in the documentation, +you can wrap it like this: ```md /// documentation diff --git a/tests/rustdoc-gui/src/test_docs/lib.rs b/tests/rustdoc-gui/src/test_docs/lib.rs index 49484ee08696..38180aef762b 100644 --- a/tests/rustdoc-gui/src/test_docs/lib.rs +++ b/tests/rustdoc-gui/src/test_docs/lib.rs @@ -65,6 +65,18 @@ impl Foo { pub fn must_use(&self) -> bool { true } + + /// hello + /// + ///
this is a warning
+ /// + /// done + pub fn warning1() {} + + /// Checking there is no bottom margin if "warning" is the last element. + /// + ///
this is a warning
+ pub fn warning2() {} } impl AsRef for Foo { diff --git a/tests/rustdoc-gui/warning-block.goml b/tests/rustdoc-gui/warning-block.goml new file mode 100644 index 000000000000..2a935bd1a9bb --- /dev/null +++ b/tests/rustdoc-gui/warning-block.goml @@ -0,0 +1,45 @@ +// Test to check that the "warning blocks" are displayed as expected. +go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html" +show-text: true + +define-function: ( + "check-warning", + (theme, color, border_color, background_color), + block { + set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + + // The IDs are added directly into the DOM to make writing this test easier. + assert-css: ("#doc-warning-1", { + "margin-bottom": "12px", + "color": |color|, + "border-left": "2px solid " + |border_color|, + "background-color": |background_color|, + }) + assert-css: ("#doc-warning-2", { + "margin-bottom": "0px", + "color": |color|, + "border-left": "2px solid " + |border_color|, + "background-color": |background_color|, + }) + }, +) + +call-function: ("check-warning", { + "theme": "ayu", + "color": "rgb(197, 197, 197)", + "border_color": "rgb(255, 142, 0)", + "background_color": "rgba(0, 0, 0, 0)", +}) +call-function: ("check-warning", { + "theme": "dark", + "color": "rgb(221, 221, 221)", + "border_color": "rgb(255, 142, 0)", + "background_color": "rgba(0, 0, 0, 0)", +}) +call-function: ("check-warning", { + "theme": "light", + "color": "rgb(0, 0, 0)", + "border_color": "rgb(255, 142, 0)", + "background_color": "rgba(0, 0, 0, 0)", +}) From e76d20e072cd25ca2df21ef51e973bf666f4c840 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 12 Aug 2023 08:25:51 +0200 Subject: [PATCH 068/197] Add status bar button to toggle check on save state --- editors/code/package.json | 5 +++++ editors/code/src/commands.ts | 7 +++++++ editors/code/src/config.ts | 33 +++++++++++++++++++++++++++++++++ editors/code/src/ctx.ts | 18 ++++++++++++++++-- editors/code/src/main.ts | 1 + editors/code/src/util.ts | 2 +- 6 files changed, 63 insertions(+), 3 deletions(-) diff --git a/editors/code/package.json b/editors/code/package.json index 96fc8d7ecf0a..83460c82c11c 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -292,6 +292,11 @@ "command": "rust-analyzer.viewMemoryLayout", "title": "View Memory Layout", "category": "rust-analyzer" + }, + { + "command": "rust-analyzer.toggleCheckOnSave", + "title": "Toggle Check on Save", + "category": "rust-analyzer" } ], "keybindings": [ diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts index e21f536f26aa..aba37bac27df 100644 --- a/editors/code/src/commands.ts +++ b/editors/code/src/commands.ts @@ -1407,3 +1407,10 @@ locate() ctx.pushExtCleanup(document); }; } + +export function toggleCheckOnSave(ctx: Ctx): Cmd { + return async () => { + await ctx.config.toggleCheckOnSave(); + ctx.refreshServerStatus(); + }; +} diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 0e64054c11d5..39e2f767c764 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -216,6 +216,39 @@ export class Config { ), ); } + get checkOnSave() { + return this.get("checkOnSave") ?? false; + } + async toggleCheckOnSave() { + const config = this.cfg.inspect("checkOnSave") ?? { key: "checkOnSave" }; + let overrideInLanguage; + let target; + let value; + if ( + config.workspaceFolderValue !== undefined || + config.workspaceFolderLanguageValue !== undefined + ) { + target = vscode.ConfigurationTarget.WorkspaceFolder; + overrideInLanguage = config.workspaceFolderLanguageValue; + value = config.workspaceFolderValue || config.workspaceFolderLanguageValue; + } else if ( + config.workspaceValue !== undefined || + config.workspaceLanguageValue !== undefined + ) { + target = vscode.ConfigurationTarget.Workspace; + overrideInLanguage = config.workspaceLanguageValue; + value = config.workspaceValue || config.workspaceLanguageValue; + } else if (config.globalValue !== undefined || config.globalLanguageValue !== undefined) { + target = vscode.ConfigurationTarget.Global; + overrideInLanguage = config.globalLanguageValue; + value = config.globalValue || config.globalLanguageValue; + } else if (config.defaultValue !== undefined || config.defaultLanguageValue !== undefined) { + overrideInLanguage = config.defaultLanguageValue; + value = config.defaultValue || config.defaultLanguageValue; + } + await this.cfg.update("checkOnSave", !(value || false), target || null, overrideInLanguage); + } + get traceExtension() { return this.get("trace.extension"); } diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index 16c14ca54f25..363a7a82e686 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -94,6 +94,7 @@ export class Ctx { private unlinkedFiles: vscode.Uri[]; private _dependencies: RustDependenciesProvider | undefined; private _treeView: vscode.TreeView | undefined; + private lastStatus: ServerStatusParams | { health: "stopped" } = { health: "stopped" }; get client() { return this._client; @@ -404,7 +405,15 @@ export class Ctx { } setServerStatus(status: ServerStatusParams | { health: "stopped" }) { + this.lastStatus = status; + this.updateStatusBarItem(); + } + refreshServerStatus() { + this.updateStatusBarItem(); + } + private updateStatusBarItem() { let icon = ""; + const status = this.lastStatus; const statusBar = this.statusBar; statusBar.show(); statusBar.tooltip = new vscode.MarkdownString("", true); @@ -447,13 +456,18 @@ export class Ctx { "statusBarItem.warningBackground", ); statusBar.command = "rust-analyzer.startServer"; - statusBar.text = `$(stop-circle) rust-analyzer`; + statusBar.text = "$(stop-circle) rust-analyzer"; return; } if (statusBar.tooltip.value) { statusBar.tooltip.appendMarkdown("\n\n---\n\n"); } - statusBar.tooltip.appendMarkdown("\n\n[Open logs](command:rust-analyzer.openLogs)"); + statusBar.tooltip.appendMarkdown("\n\n[Open Logs](command:rust-analyzer.openLogs)"); + statusBar.tooltip.appendMarkdown( + `\n\n[${ + this.config.checkOnSave ? "Disable" : "Enable" + } Check on Save](command:rust-analyzer.toggleCheckOnSave)`, + ); statusBar.tooltip.appendMarkdown( "\n\n[Reload Workspace](command:rust-analyzer.reloadWorkspace)", ); diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 448150bac06f..ee5e5b1b80c8 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -180,6 +180,7 @@ function createCommands(): Record { ssr: { enabled: commands.ssr }, serverVersion: { enabled: commands.serverVersion }, viewMemoryLayout: { enabled: commands.viewMemoryLayout }, + toggleCheckOnSave: { enabled: commands.toggleCheckOnSave }, // Internal commands which are invoked by the server. applyActionGroup: { enabled: commands.applyActionGroup }, applySnippetWorkspaceEdit: { enabled: commands.applySnippetWorkspaceEditCommand }, diff --git a/editors/code/src/util.ts b/editors/code/src/util.ts index e53945257726..1e83c281a134 100644 --- a/editors/code/src/util.ts +++ b/editors/code/src/util.ts @@ -2,7 +2,7 @@ import * as vscode from "vscode"; import { strict as nativeAssert } from "assert"; import { exec, type ExecOptions, spawnSync } from "child_process"; import { inspect } from "util"; -import { Env } from "./client"; +import type { Env } from "./client"; export function assert(condition: boolean, explanation: string): asserts condition { try { From 4c67becd44ee47ec4f966f1173b410647875bb65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Tue, 15 Aug 2023 17:35:29 +0300 Subject: [PATCH 069/197] Always collect memory usage info in analysis-stats --- crates/profile/src/stop_watch.rs | 20 +++++++------------ .../rust-analyzer/src/cli/analysis_stats.rs | 8 +++----- crates/rust-analyzer/src/cli/flags.rs | 3 --- xtask/src/metrics.rs | 4 +--- 4 files changed, 11 insertions(+), 24 deletions(-) diff --git a/crates/profile/src/stop_watch.rs b/crates/profile/src/stop_watch.rs index 71303d5a6316..814a02574028 100644 --- a/crates/profile/src/stop_watch.rs +++ b/crates/profile/src/stop_watch.rs @@ -10,13 +10,13 @@ pub struct StopWatch { time: Instant, #[cfg(target_os = "linux")] counter: Option, - memory: Option, + memory: MemoryUsage, } pub struct StopWatchSpan { pub time: Duration, pub instructions: Option, - pub memory: Option, + pub memory: MemoryUsage, } impl StopWatch { @@ -45,20 +45,16 @@ impl StopWatch { None } }; + let memory = MemoryUsage::now(); let time = Instant::now(); StopWatch { time, #[cfg(target_os = "linux")] counter, - memory: None, + memory, } } - pub fn memory(mut self, yes: bool) -> StopWatch { - if yes { - self.memory = Some(MemoryUsage::now()); - } - self - } + pub fn elapsed(&mut self) -> StopWatchSpan { let time = self.time.elapsed(); @@ -69,7 +65,7 @@ impl StopWatch { #[cfg(not(target_os = "linux"))] let instructions = None; - let memory = self.memory.map(|it| MemoryUsage::now() - it); + let memory = MemoryUsage::now() - self.memory; StopWatchSpan { time, instructions, memory } } } @@ -93,9 +89,7 @@ impl fmt::Display for StopWatchSpan { } write!(f, ", {instructions}{prefix}instr")?; } - if let Some(memory) = self.memory { - write!(f, ", {memory}")?; - } + write!(f, ", {}", self.memory)?; Ok(()) } } diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index f446a7c05966..4a03be1893c7 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -235,9 +235,7 @@ impl flags::AnalysisStats { if let Some(instructions) = total_span.instructions { report_metric("total instructions", instructions, "#instr"); } - if let Some(memory) = total_span.memory { - report_metric("total memory", memory.allocated.megabytes() as u64, "MB"); - } + report_metric("total memory", total_span.memory.allocated.megabytes() as u64, "MB"); if env::var("RA_COUNT").is_ok() { eprintln!("{}", profile::countme::get_all()); @@ -257,7 +255,7 @@ impl flags::AnalysisStats { eprintln!("source files: {total_file_size}, macro files: {total_macro_file_size}"); } - if self.memory_usage && verbosity.is_verbose() { + if verbosity.is_verbose() { print_memory_usage(host, vfs); } @@ -814,7 +812,7 @@ impl flags::AnalysisStats { } fn stop_watch(&self) -> StopWatch { - StopWatch::start().memory(self.memory_usage) + StopWatch::start() } } diff --git a/crates/rust-analyzer/src/cli/flags.rs b/crates/rust-analyzer/src/cli/flags.rs index 13b7f039bb0f..419440b6df7b 100644 --- a/crates/rust-analyzer/src/cli/flags.rs +++ b/crates/rust-analyzer/src/cli/flags.rs @@ -62,8 +62,6 @@ xflags::xflags! { optional --randomize /// Run type inference in parallel. optional --parallel - /// Collect memory usage statistics. - optional --memory-usage /// Print the total length of all source and macro files (whitespace is not counted). optional --source-stats @@ -191,7 +189,6 @@ pub struct AnalysisStats { pub output: Option, pub randomize: bool, pub parallel: bool, - pub memory_usage: bool, pub source_stats: bool, pub only: Option, pub with_deps: bool, diff --git a/xtask/src/metrics.rs b/xtask/src/metrics.rs index 68537423195e..e4710260409c 100644 --- a/xtask/src/metrics.rs +++ b/xtask/src/metrics.rs @@ -103,9 +103,7 @@ impl Metrics { path: &str, ) -> anyhow::Result<()> { eprintln!("\nMeasuring analysis-stats/{name}"); - let output = - cmd!(sh, "./target/release/rust-analyzer -q analysis-stats --memory-usage {path}") - .read()?; + let output = cmd!(sh, "./target/release/rust-analyzer -q analysis-stats {path}").read()?; for (metric, value, unit) in parse_metrics(&output) { self.report(&format!("analysis-stats/{name}/{metric}"), value, unit.into()); } From c737c62e70cf8627e01e0b3a1088e96bff1b154d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 15 Aug 2023 16:03:17 +0200 Subject: [PATCH 070/197] Make Sharded an enum and specialize it for the single thread case --- compiler/rustc_data_structures/src/sharded.rs | 66 +++++++++---------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs index 40cbf14958e7..6bc0b346d921 100644 --- a/compiler/rustc_data_structures/src/sharded.rs +++ b/compiler/rustc_data_structures/src/sharded.rs @@ -1,31 +1,25 @@ use crate::fx::{FxHashMap, FxHasher}; #[cfg(parallel_compiler)] -use crate::sync::is_dyn_thread_safe; -use crate::sync::{CacheAligned, Lock, LockGuard}; +use crate::sync::{is_dyn_thread_safe, CacheAligned}; +use crate::sync::{Lock, LockGuard}; use std::borrow::Borrow; use std::collections::hash_map::RawEntryMut; use std::hash::{Hash, Hasher}; use std::mem; -#[cfg(parallel_compiler)] // 32 shards is sufficient to reduce contention on an 8-core Ryzen 7 1700, // but this should be tested on higher core count CPUs. How the `Sharded` type gets used // may also affect the ideal number of shards. -const SHARD_BITS: usize = 5; - -#[cfg(not(parallel_compiler))] -const SHARD_BITS: usize = 0; +const SHARD_BITS: usize = if cfg!(parallel_compiler) { 5 } else { 0 }; pub const SHARDS: usize = 1 << SHARD_BITS; /// An array of cache-line aligned inner locked structures with convenience methods. -pub struct Sharded { - /// This mask is used to ensure that accesses are inbounds of `shards`. - /// When dynamic thread safety is off, this field is set to 0 causing only - /// a single shard to be used for greater cache efficiency. +/// A single field is used when the compiler uses only one thread. +pub enum Sharded { + Single(Lock), #[cfg(parallel_compiler)] - mask: usize, - shards: [CacheAligned>; SHARDS], + Shards(Box<[CacheAligned>; SHARDS]>), } impl Default for Sharded { @@ -38,29 +32,14 @@ impl Default for Sharded { impl Sharded { #[inline] pub fn new(mut value: impl FnMut() -> T) -> Self { - Sharded { - #[cfg(parallel_compiler)] - mask: if is_dyn_thread_safe() { SHARDS - 1 } else { 0 }, - shards: [(); SHARDS].map(|()| CacheAligned(Lock::new(value()))), - } - } - - #[inline(always)] - fn mask(&self) -> usize { #[cfg(parallel_compiler)] - { - if SHARDS == 1 { 0 } else { self.mask } + if is_dyn_thread_safe() { + return Sharded::Shards(Box::new( + [(); SHARDS].map(|()| CacheAligned(Lock::new(value()))), + )); } - #[cfg(not(parallel_compiler))] - { - 0 - } - } - #[inline(always)] - fn count(&self) -> usize { - // `self.mask` is always one below the used shard count - self.mask() + 1 + Sharded::Single(Lock::new(value())) } /// The shard is selected by hashing `val` with `FxHasher`. @@ -75,9 +54,24 @@ impl Sharded { } #[inline] - pub fn get_shard_by_index(&self, i: usize) -> &Lock { - // SAFETY: The index get ANDed with the mask, ensuring it is always inbounds. - unsafe { &self.shards.get_unchecked(i & self.mask()).0 } + pub fn get_shard_by_index(&self, _i: usize) -> &Lock { + match self { + Self::Single(single) => &single, + #[cfg(parallel_compiler)] + Self::Shards(shards) => { + // SAFETY: The index gets ANDed with the shard mask, ensuring it is always inbounds. + unsafe { &shards.get_unchecked(_i & (SHARDS - 1)).0 } + } + } + } + + #[inline] + fn count(&self) -> usize { + match self { + Self::Single(..) => 1, + #[cfg(parallel_compiler)] + Self::Shards(..) => SHARDS, + } } pub fn lock_shards(&self) -> Vec> { From fec5ff989025ee01f7659da28e95d0fe0feafa86 Mon Sep 17 00:00:00 2001 From: ponyii Date: Tue, 15 Aug 2023 20:26:42 +0400 Subject: [PATCH 071/197] start hovering default values of generic constants --- crates/hir/src/display.rs | 5 ++++ crates/ide/src/hover/tests.rs | 45 ++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index a701eb011920..ac171026d5d7 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -366,6 +366,11 @@ fn write_generic_params( delim(f)?; write!(f, "const {}: ", name.display(f.db.upcast()))?; c.ty.hir_fmt(f)?; + + if let Some(default) = &c.default { + f.write_str(" = ")?; + write!(f, "{}", default.display(f.db.upcast()))?; + } } } } diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 541cce8c5bfe..d0f9f7b0e16d 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -3335,7 +3335,50 @@ struct S$0T(T); ``` ```rust - struct ST + struct ST + ``` + "#]], + ); +} + +#[test] +fn const_generic_default_value() { + check( + r#" +struct Foo; +struct S$0T(T); +"#, + expect![[r#" + *ST* + + ```rust + test + ``` + + ```rust + struct ST + ``` + "#]], + ); +} + +#[test] +fn const_generic_default_value_2() { + check( + r#" +struct Foo; +const VAL = 1; +struct S$0T(T); +"#, + expect![[r#" + *ST* + + ```rust + test + ``` + + ```rust + struct ST ``` "#]], ); From 2a78173ff86753bfe9525943925a98d2636c6da1 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Wed, 16 Aug 2023 00:22:08 +0200 Subject: [PATCH 072/197] v2 --- .../src/handlers/generate_derive.rs | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/crates/ide-assists/src/handlers/generate_derive.rs b/crates/ide-assists/src/handlers/generate_derive.rs index 5e67537c80b7..53ba144ba9e3 100644 --- a/crates/ide-assists/src/handlers/generate_derive.rs +++ b/crates/ide-assists/src/handlers/generate_derive.rs @@ -34,38 +34,39 @@ pub(crate) fn generate_derive(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt .map(|(_name, arg)| arg) .next(); - let (derive, delimiter) = match &derive_attr { - None => { - let derive = make::attr_outer(make::meta_token_tree( - make::ext::ident_path("derive"), - make::token_tree(T!['('], vec![]).clone_for_update(), - )) - .clone_for_update(); - let delimiter = derive.meta()?.token_tree()?.r_paren_token()?; - (derive, delimiter) - } - Some(tt) => { - // Create an outer attribute just so that we avoid using - // unwrap in edit closure. - let _derive = make::attr_outer(make::meta_token_tree( - make::ext::ident_path("derive"), - make::token_tree(T!['('], vec![]), - )); - (_derive, tt.right_delimiter_token()?) - } + let delimiter = match &derive_attr { + None => None, + Some(tt) => Some(tt.right_delimiter_token()?), }; acc.add(AssistId("generate_derive", AssistKind::Generate), "Add `#[derive]`", target, |edit| { match derive_attr { None => { + let derive = make::attr_outer(make::meta_token_tree( + make::ext::ident_path("derive"), + make::token_tree(T!['('], vec![]).clone_for_update(), + )) + .clone_for_update(); + let nominal = edit.make_mut(nominal); nominal.add_attr(derive.clone()); + let delimiter = derive + .meta() + .expect("make::attr_outer was expected to have Meta") + .token_tree() + .expect("failed to get token tree out of Meta") + .r_paren_token() + .expect("make::attr_outer was expected to have a R_PAREN"); + edit.add_tabstop_before_token(cap, delimiter); } Some(_) => { // Just move the cursor. - edit.add_tabstop_before_token(cap, delimiter); + edit.add_tabstop_before_token( + cap, + delimiter.expect("Right delim token could not be found."), + ); } }; }) From 81220c0acef24bd88e960a9b2c2eea3140365864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 16 Aug 2023 10:00:25 +0200 Subject: [PATCH 073/197] Keep SHARDS fixed instead of a function of `cfg!(parallel_compiler)` --- compiler/rustc_data_structures/src/sharded.rs | 23 +++++++++++++++---- .../rustc_query_system/src/dep_graph/graph.rs | 2 +- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs index 6bc0b346d921..39cce5c8ee6f 100644 --- a/compiler/rustc_data_structures/src/sharded.rs +++ b/compiler/rustc_data_structures/src/sharded.rs @@ -10,9 +10,10 @@ use std::mem; // 32 shards is sufficient to reduce contention on an 8-core Ryzen 7 1700, // but this should be tested on higher core count CPUs. How the `Sharded` type gets used // may also affect the ideal number of shards. -const SHARD_BITS: usize = if cfg!(parallel_compiler) { 5 } else { 0 }; +const SHARD_BITS: usize = 5; -pub const SHARDS: usize = 1 << SHARD_BITS; +#[cfg(parallel_compiler)] +const SHARDS: usize = 1 << SHARD_BITS; /// An array of cache-line aligned inner locked structures with convenience methods. /// A single field is used when the compiler uses only one thread. @@ -44,8 +45,12 @@ impl Sharded { /// The shard is selected by hashing `val` with `FxHasher`. #[inline] - pub fn get_shard_by_value(&self, val: &K) -> &Lock { - self.get_shard_by_hash(if SHARDS == 1 { 0 } else { make_hash(val) }) + pub fn get_shard_by_value(&self, _val: &K) -> &Lock { + match self { + Self::Single(single) => &single, + #[cfg(parallel_compiler)] + Self::Shards(shards) => self.get_shard_by_hash(make_hash(_val)), + } } #[inline] @@ -83,6 +88,16 @@ impl Sharded { } } +#[inline] +pub fn shards() -> usize { + #[cfg(parallel_compiler)] + if is_dyn_thread_safe() { + return SHARDS; + } + + 1 +} + pub type ShardedHashMap = Sharded>; impl ShardedHashMap { diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 30422ea11026..0d4d13ac20d4 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -1166,7 +1166,7 @@ impl CurrentDepGraph { )), new_node_to_index: Sharded::new(|| { FxHashMap::with_capacity_and_hasher( - new_node_count_estimate / sharded::SHARDS, + new_node_count_estimate / sharded::shards(), Default::default(), ) }), From 53b292478d1f25209d90a6f657066e45989f3b3e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 16 Aug 2023 10:07:18 +0200 Subject: [PATCH 074/197] internal: Add offset param to token descending API --- crates/hir-expand/src/lib.rs | 14 +--- crates/hir/src/semantics.rs | 81 ++++++++++++++----- .../extract_expressions_from_format_string.rs | 2 +- .../src/handlers/extract_function.rs | 2 +- crates/ide-db/src/helpers.rs | 2 +- crates/ide-db/src/search.rs | 4 +- crates/ide/src/call_hierarchy.rs | 10 ++- crates/ide/src/doc_links.rs | 10 +-- crates/ide/src/expand_macro.rs | 47 ++++++----- crates/ide/src/extend_selection.rs | 29 ++++--- crates/ide/src/goto_declaration.rs | 8 +- crates/ide/src/goto_definition.rs | 54 ++++++------- crates/ide/src/goto_implementation.rs | 15 ++-- crates/ide/src/goto_type_definition.rs | 8 +- crates/ide/src/highlight_related.rs | 17 ++-- crates/ide/src/hover.rs | 4 +- crates/ide/src/lib.rs | 2 +- crates/ide/src/moniker.rs | 2 +- crates/ide/src/references.rs | 2 +- crates/ide/src/signature_help.rs | 11 ++- crates/ide/src/syntax_highlighting.rs | 4 +- 21 files changed, 185 insertions(+), 143 deletions(-) diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs index ba14553d90e3..4be55126b862 100644 --- a/crates/hir-expand/src/lib.rs +++ b/crates/hir-expand/src/lib.rs @@ -37,7 +37,7 @@ use either::Either; use syntax::{ algo::{self, skip_trivia_token}, ast::{self, AstNode, HasDocComments}, - AstPtr, Direction, SyntaxNode, SyntaxNodePtr, SyntaxToken, + AstPtr, Direction, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextSize, }; use crate::{ @@ -642,6 +642,8 @@ impl ExpansionInfo { db: &dyn db::ExpandDatabase, item: Option, token: InFile<&SyntaxToken>, + // FIXME: use this for range mapping, so that we can resolve inline format args + _relative_token_offset: Option, ) -> Option> + '_> { assert_eq!(token.file_id, self.arg.file_id); let token_id_in_attr_input = if let Some(item) = item { @@ -1051,16 +1053,6 @@ impl InFile { } } } - - pub fn ancestors_with_macros( - self, - db: &dyn db::ExpandDatabase, - ) -> impl Iterator> + '_ { - self.value.parent().into_iter().flat_map({ - let file_id = self.file_id; - move |parent| InFile::new(file_id, &parent).ancestors_with_macros(db) - }) - } } #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index e99d2984c367..25b5bd365e38 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -170,6 +170,8 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { self.imp.is_derive_annotated(item) } + /// Expand the macro call with a different token tree, mapping the `token_to_map` down into the + /// expansion. `token_to_map` should be a token from the `speculative args` node. pub fn speculative_expand( &self, actual_macro_call: &ast::MacroCall, @@ -179,6 +181,8 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { self.imp.speculative_expand(actual_macro_call, speculative_args, token_to_map) } + /// Expand the macro call with a different item as the input, mapping the `token_to_map` down into the + /// expansion. `token_to_map` should be a token from the `speculative args` node. pub fn speculative_expand_attr_macro( &self, actual_macro_call: &ast::Item, @@ -201,14 +205,22 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { ) } - /// Descend the token into macrocalls to its first mapped counterpart. - pub fn descend_into_macros_single(&self, token: SyntaxToken) -> SyntaxToken { - self.imp.descend_into_macros_single(token) + /// Descend the token into its macro call if it is part of one, returning the token in the + /// expansion that it is associated with. If `offset` points into the token's range, it will + /// be considered for the mapping in case of inline format args. + pub fn descend_into_macros_single(&self, token: SyntaxToken, offset: TextSize) -> SyntaxToken { + self.imp.descend_into_macros_single(token, offset) } - /// Descend the token into macrocalls to all its mapped counterparts. - pub fn descend_into_macros(&self, token: SyntaxToken) -> SmallVec<[SyntaxToken; 1]> { - self.imp.descend_into_macros(token) + /// Descend the token into its macro call if it is part of one, returning the tokens in the + /// expansion that it is associated with. If `offset` points into the token's range, it will + /// be considered for the mapping in case of inline format args. + pub fn descend_into_macros( + &self, + token: SyntaxToken, + offset: TextSize, + ) -> SmallVec<[SyntaxToken; 1]> { + self.imp.descend_into_macros(token, offset) } /// Descend the token into macrocalls to all its mapped counterparts that have the same text as the input token. @@ -217,12 +229,17 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { pub fn descend_into_macros_with_same_text( &self, token: SyntaxToken, + offset: TextSize, ) -> SmallVec<[SyntaxToken; 1]> { - self.imp.descend_into_macros_with_same_text(token) + self.imp.descend_into_macros_with_same_text(token, offset) } - pub fn descend_into_macros_with_kind_preference(&self, token: SyntaxToken) -> SyntaxToken { - self.imp.descend_into_macros_with_kind_preference(token) + pub fn descend_into_macros_with_kind_preference( + &self, + token: SyntaxToken, + offset: TextSize, + ) -> SyntaxToken { + self.imp.descend_into_macros_with_kind_preference(token, offset) } /// Maps a node down by mapping its first and last token down. @@ -665,7 +682,7 @@ impl<'db> SemanticsImpl<'db> { }; if first == last { - self.descend_into_macros_impl(first, &mut |InFile { value, .. }| { + self.descend_into_macros_impl(first, 0.into(), &mut |InFile { value, .. }| { if let Some(node) = value.parent_ancestors().find_map(N::cast) { res.push(node) } @@ -674,7 +691,7 @@ impl<'db> SemanticsImpl<'db> { } else { // Descend first and last token, then zip them to look for the node they belong to let mut scratch: SmallVec<[_; 1]> = smallvec![]; - self.descend_into_macros_impl(first, &mut |token| { + self.descend_into_macros_impl(first, 0.into(), &mut |token| { scratch.push(token); false }); @@ -682,6 +699,7 @@ impl<'db> SemanticsImpl<'db> { let mut scratch = scratch.into_iter(); self.descend_into_macros_impl( last, + 0.into(), &mut |InFile { value: last, file_id: last_fid }| { if let Some(InFile { value: first, file_id: first_fid }) = scratch.next() { if first_fid == last_fid { @@ -705,19 +723,27 @@ impl<'db> SemanticsImpl<'db> { res } - fn descend_into_macros(&self, token: SyntaxToken) -> SmallVec<[SyntaxToken; 1]> { + fn descend_into_macros( + &self, + token: SyntaxToken, + offset: TextSize, + ) -> SmallVec<[SyntaxToken; 1]> { let mut res = smallvec![]; - self.descend_into_macros_impl(token, &mut |InFile { value, .. }| { + self.descend_into_macros_impl(token, offset, &mut |InFile { value, .. }| { res.push(value); false }); res } - fn descend_into_macros_with_same_text(&self, token: SyntaxToken) -> SmallVec<[SyntaxToken; 1]> { + fn descend_into_macros_with_same_text( + &self, + token: SyntaxToken, + offset: TextSize, + ) -> SmallVec<[SyntaxToken; 1]> { let text = token.text(); let mut res = smallvec![]; - self.descend_into_macros_impl(token.clone(), &mut |InFile { value, .. }| { + self.descend_into_macros_impl(token.clone(), offset, &mut |InFile { value, .. }| { if value.text() == text { res.push(value); } @@ -729,7 +755,11 @@ impl<'db> SemanticsImpl<'db> { res } - fn descend_into_macros_with_kind_preference(&self, token: SyntaxToken) -> SyntaxToken { + fn descend_into_macros_with_kind_preference( + &self, + token: SyntaxToken, + offset: TextSize, + ) -> SyntaxToken { let fetch_kind = |token: &SyntaxToken| match token.parent() { Some(node) => match node.kind() { kind @ (SyntaxKind::NAME | SyntaxKind::NAME_REF) => { @@ -741,7 +771,7 @@ impl<'db> SemanticsImpl<'db> { }; let preferred_kind = fetch_kind(&token); let mut res = None; - self.descend_into_macros_impl(token.clone(), &mut |InFile { value, .. }| { + self.descend_into_macros_impl(token.clone(), offset, &mut |InFile { value, .. }| { if fetch_kind(&value) == preferred_kind { res = Some(value); true @@ -755,9 +785,9 @@ impl<'db> SemanticsImpl<'db> { res.unwrap_or(token) } - fn descend_into_macros_single(&self, token: SyntaxToken) -> SyntaxToken { + fn descend_into_macros_single(&self, token: SyntaxToken, offset: TextSize) -> SyntaxToken { let mut res = token.clone(); - self.descend_into_macros_impl(token, &mut |InFile { value, .. }| { + self.descend_into_macros_impl(token, offset, &mut |InFile { value, .. }| { res = value; true }); @@ -767,9 +797,13 @@ impl<'db> SemanticsImpl<'db> { fn descend_into_macros_impl( &self, token: SyntaxToken, + // FIXME: We might want this to be Option to be able to opt out of subrange + // mapping, specifically for node downmapping + offset: TextSize, f: &mut dyn FnMut(InFile) -> bool, ) { let _p = profile::span("descend_into_macros"); + let relative_token_offset = token.text_range().start().checked_sub(offset); let parent = match token.parent() { Some(it) => it, None => return, @@ -796,7 +830,12 @@ impl<'db> SemanticsImpl<'db> { self.cache(value, file_id); } - let mapped_tokens = expansion_info.map_token_down(self.db.upcast(), item, token)?; + let mapped_tokens = expansion_info.map_token_down( + self.db.upcast(), + item, + token, + relative_token_offset, + )?; let len = stack.len(); // requeue the tokens we got from mapping our current token down @@ -943,7 +982,7 @@ impl<'db> SemanticsImpl<'db> { offset: TextSize, ) -> impl Iterator + '_> + '_ { node.token_at_offset(offset) - .map(move |token| self.descend_into_macros(token)) + .map(move |token| self.descend_into_macros(token, offset)) .map(|descendants| { descendants.into_iter().map(move |it| self.token_ancestors_with_macros(it)) }) diff --git a/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs b/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs index 4f3b6e0c287c..c3d925cb26c4 100644 --- a/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs +++ b/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs @@ -48,7 +48,7 @@ pub(crate) fn extract_expressions_from_format_string( let tt = fmt_string.syntax().parent().and_then(ast::TokenTree::cast)?; let expanded_t = ast::String::cast( - ctx.sema.descend_into_macros_with_kind_preference(fmt_string.syntax().clone()), + ctx.sema.descend_into_macros_with_kind_preference(fmt_string.syntax().clone(), 0.into()), )?; if !is_format_string(&expanded_t) { return None; diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs index 1340681ccab5..ea7a21e77a4a 100644 --- a/crates/ide-assists/src/handlers/extract_function.rs +++ b/crates/ide-assists/src/handlers/extract_function.rs @@ -750,7 +750,7 @@ impl FunctionBody { .descendants_with_tokens() .filter_map(SyntaxElement::into_token) .filter(|it| matches!(it.kind(), SyntaxKind::IDENT | T![self])) - .flat_map(|t| sema.descend_into_macros(t)) + .flat_map(|t| sema.descend_into_macros(t, 0.into())) .for_each(|t| add_name_if_local(t.parent().and_then(ast::NameRef::cast))); } } diff --git a/crates/ide-db/src/helpers.rs b/crates/ide-db/src/helpers.rs index 1eb8f00020b1..330af442f754 100644 --- a/crates/ide-db/src/helpers.rs +++ b/crates/ide-db/src/helpers.rs @@ -117,7 +117,7 @@ pub fn get_definition( sema: &Semantics<'_, RootDatabase>, token: SyntaxToken, ) -> Option { - for token in sema.descend_into_macros(token) { + for token in sema.descend_into_macros(token, 0.into()) { let def = IdentClass::classify_token(sema, &token).map(IdentClass::definitions_no_ops); if let Some(&[x]) = def.as_deref() { return Some(x); diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs index d5abd0991268..7e00d3686529 100644 --- a/crates/ide-db/src/search.rs +++ b/crates/ide-db/src/search.rs @@ -456,14 +456,14 @@ impl<'a> FindUsages<'a> { it.text().trim_start_matches("r#") == name }) .into_iter() - .flat_map(|token| { + .flat_map(move |token| { // FIXME: There should be optimization potential here // Currently we try to descend everything we find which // means we call `Semantics::descend_into_macros` on // every textual hit. That function is notoriously // expensive even for things that do not get down mapped // into macros. - sema.descend_into_macros(token).into_iter().filter_map(|it| it.parent()) + sema.descend_into_macros(token, offset).into_iter().filter_map(|it| it.parent()) }) }; diff --git a/crates/ide/src/call_hierarchy.rs b/crates/ide/src/call_hierarchy.rs index dd1d0d75c63e..f834f2ce5927 100644 --- a/crates/ide/src/call_hierarchy.rs +++ b/crates/ide/src/call_hierarchy.rs @@ -74,18 +74,20 @@ pub(crate) fn incoming_calls( Some(calls.into_items()) } -pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Option> { +pub(crate) fn outgoing_calls( + db: &RootDatabase, + FilePosition { file_id, offset }: FilePosition, +) -> Option> { let sema = Semantics::new(db); - let file_id = position.file_id; let file = sema.parse(file_id); let file = file.syntax(); - let token = pick_best_token(file.token_at_offset(position.offset), |kind| match kind { + let token = pick_best_token(file.token_at_offset(offset), |kind| match kind { IDENT => 1, _ => 0, })?; let mut calls = CallLocations::default(); - sema.descend_into_macros(token) + sema.descend_into_macros(token, offset) .into_iter() .filter_map(|it| it.parent_ancestors().nth(1).and_then(ast::Item::cast)) .filter_map(|item| match item { diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index d240127f3761..901f7a2a79ae 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs @@ -131,19 +131,19 @@ pub(crate) fn remove_links(markdown: &str) -> String { // |=== pub(crate) fn external_docs( db: &RootDatabase, - position: &FilePosition, + FilePosition { file_id, offset }: FilePosition, target_dir: Option<&OsStr>, sysroot: Option<&OsStr>, ) -> Option { let sema = &Semantics::new(db); - let file = sema.parse(position.file_id).syntax().clone(); - let token = pick_best_token(file.token_at_offset(position.offset), |kind| match kind { + let file = sema.parse(file_id).syntax().clone(); + let token = pick_best_token(file.token_at_offset(offset), |kind| match kind { IDENT | INT_NUMBER | T![self] => 3, T!['('] | T![')'] => 2, kind if kind.is_trivia() => 0, _ => 1, })?; - let token = sema.descend_into_macros_single(token); + let token = sema.descend_into_macros_single(token, offset); let node = token.parent()?; let definition = match_ast! { @@ -285,7 +285,7 @@ impl DocCommentToken { let original_start = doc_token.text_range().start(); let relative_comment_offset = offset - original_start - prefix_len; - sema.descend_into_macros(doc_token).into_iter().find_map(|t| { + sema.descend_into_macros(doc_token, offset).into_iter().find_map(|t| { let (node, descended_prefix_len) = match_ast! { match t { ast::Comment(comment) => (t.parent()?, TextSize::try_from(comment.prefix().len()).ok()?), diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs index d6bbf2bf794d..119a9c7c3f40 100644 --- a/crates/ide/src/expand_macro.rs +++ b/crates/ide/src/expand_macro.rs @@ -40,28 +40,33 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option< // struct Bar; // ``` - let derive = sema.descend_into_macros(tok.clone()).into_iter().find_map(|descended| { - let hir_file = sema.hir_file_for(&descended.parent()?); - if !hir_file.is_derive_attr_pseudo_expansion(db) { - return None; - } + let derive = + sema.descend_into_macros(tok.clone(), 0.into()).into_iter().find_map(|descended| { + let hir_file = sema.hir_file_for(&descended.parent()?); + if !hir_file.is_derive_attr_pseudo_expansion(db) { + return None; + } - let name = descended.parent_ancestors().filter_map(ast::Path::cast).last()?.to_string(); - // up map out of the #[derive] expansion - let token = hir::InFile::new(hir_file, descended).upmap(db)?.value; - let attr = token.parent_ancestors().find_map(ast::Attr::cast)?; - let expansions = sema.expand_derive_macro(&attr)?; - let idx = attr - .token_tree()? - .token_trees_and_tokens() - .filter_map(NodeOrToken::into_token) - .take_while(|it| it != &token) - .filter(|it| it.kind() == T![,]) - .count(); - let expansion = - format(db, SyntaxKind::MACRO_ITEMS, position.file_id, expansions.get(idx).cloned()?); - Some(ExpandedMacro { name, expansion }) - }); + let name = descended.parent_ancestors().filter_map(ast::Path::cast).last()?.to_string(); + // up map out of the #[derive] expansion + let token = hir::InFile::new(hir_file, descended).upmap(db)?.value; + let attr = token.parent_ancestors().find_map(ast::Attr::cast)?; + let expansions = sema.expand_derive_macro(&attr)?; + let idx = attr + .token_tree()? + .token_trees_and_tokens() + .filter_map(NodeOrToken::into_token) + .take_while(|it| it != &token) + .filter(|it| it.kind() == T![,]) + .count(); + let expansion = format( + db, + SyntaxKind::MACRO_ITEMS, + position.file_id, + expansions.get(idx).cloned()?, + ); + Some(ExpandedMacro { name, expansion }) + }); if derive.is_some() { return derive; diff --git a/crates/ide/src/extend_selection.rs b/crates/ide/src/extend_selection.rs index f90618222446..3d89599c5832 100644 --- a/crates/ide/src/extend_selection.rs +++ b/crates/ide/src/extend_selection.rs @@ -17,8 +17,6 @@ use crate::FileRange; // Extends or shrinks the current selection to the encompassing syntactic construct // (expression, statement, item, module, etc). It works with multiple cursors. // -// This is a standard LSP feature and not a protocol extension. -// // |=== // | Editor | Shortcut // @@ -142,8 +140,10 @@ fn extend_tokens_from_range( // compute original mapped token range let extended = { - let fst_expanded = sema.descend_into_macros_single(first_token.clone()); - let lst_expanded = sema.descend_into_macros_single(last_token.clone()); + let fst_expanded = + sema.descend_into_macros_single(first_token.clone(), original_range.start()); + let lst_expanded = + sema.descend_into_macros_single(last_token.clone(), original_range.end()); let mut lca = algo::least_common_ancestor(&fst_expanded.parent()?, &lst_expanded.parent()?)?; lca = shallowest_node(&lca); @@ -154,13 +154,16 @@ fn extend_tokens_from_range( }; // Compute parent node range - let validate = |token: &SyntaxToken| -> bool { - let expanded = sema.descend_into_macros_single(token.clone()); - let parent = match expanded.parent() { - Some(it) => it, - None => return false, - }; - algo::least_common_ancestor(&extended, &parent).as_ref() == Some(&extended) + let validate = |offset: TextSize| { + let extended = &extended; + move |token: &SyntaxToken| -> bool { + let expanded = sema.descend_into_macros_single(token.clone(), offset); + let parent = match expanded.parent() { + Some(it) => it, + None => return false, + }; + algo::least_common_ancestor(extended, &parent).as_ref() == Some(extended) + } }; // Find the first and last text range under expanded parent @@ -168,14 +171,14 @@ fn extend_tokens_from_range( let token = token.prev_token()?; skip_trivia_token(token, Direction::Prev) }) - .take_while(validate) + .take_while(validate(original_range.start())) .last()?; let last = successors(Some(last_token), |token| { let token = token.next_token()?; skip_trivia_token(token, Direction::Next) }) - .take_while(validate) + .take_while(validate(original_range.end())) .last()?; let range = first.text_range().cover(last.text_range()); diff --git a/crates/ide/src/goto_declaration.rs b/crates/ide/src/goto_declaration.rs index c39c696cfd9b..7e0fab42608b 100644 --- a/crates/ide/src/goto_declaration.rs +++ b/crates/ide/src/goto_declaration.rs @@ -20,16 +20,16 @@ use crate::{ // - fields in patterns will navigate to the field declaration of the struct, union or variant pub(crate) fn goto_declaration( db: &RootDatabase, - position: FilePosition, + position @ FilePosition { file_id, offset }: FilePosition, ) -> Option>> { let sema = Semantics::new(db); - let file = sema.parse(position.file_id).syntax().clone(); + let file = sema.parse(file_id).syntax().clone(); let original_token = file - .token_at_offset(position.offset) + .token_at_offset(offset) .find(|it| matches!(it.kind(), IDENT | T![self] | T![super] | T![crate] | T![Self]))?; let range = original_token.text_range(); let info: Vec = sema - .descend_into_macros(original_token) + .descend_into_macros(original_token, offset) .iter() .filter_map(|token| { let parent = token.parent()?; diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index 21471ab2a03d..e09b9f391482 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -29,45 +29,39 @@ use syntax::{ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextRange, T}; // image::https://user-images.githubusercontent.com/48062697/113065563-025fbe00-91b1-11eb-83e4-a5a703610b23.gif[] pub(crate) fn goto_definition( db: &RootDatabase, - position: FilePosition, + FilePosition { file_id, offset }: FilePosition, ) -> Option>> { let sema = &Semantics::new(db); - let file = sema.parse(position.file_id).syntax().clone(); - let original_token = - pick_best_token(file.token_at_offset(position.offset), |kind| match kind { - IDENT - | INT_NUMBER - | LIFETIME_IDENT - | T![self] - | T![super] - | T![crate] - | T![Self] - | COMMENT => 4, - // index and prefix ops - T!['['] | T![']'] | T![?] | T![*] | T![-] | T![!] => 3, - kind if kind.is_keyword() => 2, - T!['('] | T![')'] => 2, - kind if kind.is_trivia() => 0, - _ => 1, - })?; + 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 => 4, + // index and prefix ops + T!['['] | T![']'] | T![?] | T![*] | T![-] | T![!] => 3, + kind if kind.is_keyword() => 2, + T!['('] | T![')'] => 2, + kind if kind.is_trivia() => 0, + _ => 1, + })?; if let Some(doc_comment) = token_as_doc_comment(&original_token) { - return doc_comment.get_definition_with_descend_at( - sema, - position.offset, - |def, _, link_range| { - let nav = def.try_to_nav(db)?; - Some(RangeInfo::new(link_range, vec![nav])) - }, - ); + return doc_comment.get_definition_with_descend_at(sema, offset, |def, _, link_range| { + let nav = def.try_to_nav(db)?; + Some(RangeInfo::new(link_range, vec![nav])) + }); } let navs = sema - .descend_into_macros(original_token.clone()) + .descend_into_macros(original_token.clone(), offset) .into_iter() .filter_map(|token| { let parent = token.parent()?; if let Some(tt) = ast::TokenTree::cast(parent) { - if let Some(x) = try_lookup_include_path(sema, tt, token.clone(), position.file_id) - { + if let Some(x) = try_lookup_include_path(sema, tt, token.clone(), file_id) { return Some(vec![x]); } } diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs index 37166bdbd0c1..544c6b42317e 100644 --- a/crates/ide/src/goto_implementation.rs +++ b/crates/ide/src/goto_implementation.rs @@ -22,20 +22,19 @@ use crate::{FilePosition, NavigationTarget, RangeInfo, TryToNav}; // image::https://user-images.githubusercontent.com/48062697/113065566-02f85480-91b1-11eb-9288-aaad8abd8841.gif[] pub(crate) fn goto_implementation( db: &RootDatabase, - position: FilePosition, + FilePosition { file_id, offset }: FilePosition, ) -> Option>> { let sema = Semantics::new(db); - let source_file = sema.parse(position.file_id); + let source_file = sema.parse(file_id); let syntax = source_file.syntax().clone(); - let original_token = - pick_best_token(syntax.token_at_offset(position.offset), |kind| match kind { - IDENT | T![self] | INT_NUMBER => 1, - _ => 0, - })?; + let original_token = pick_best_token(syntax.token_at_offset(offset), |kind| match kind { + IDENT | T![self] | INT_NUMBER => 1, + _ => 0, + })?; let range = original_token.text_range(); let navs = - sema.descend_into_macros(original_token) + sema.descend_into_macros(original_token, offset) .into_iter() .filter_map(|token| token.parent().and_then(ast::NameLike::cast)) .filter_map(|node| match &node { diff --git a/crates/ide/src/goto_type_definition.rs b/crates/ide/src/goto_type_definition.rs index 6048990f7492..955923d76910 100644 --- a/crates/ide/src/goto_type_definition.rs +++ b/crates/ide/src/goto_type_definition.rs @@ -16,13 +16,13 @@ use crate::{FilePosition, NavigationTarget, RangeInfo, TryToNav}; // image::https://user-images.githubusercontent.com/48062697/113020657-b560f500-917a-11eb-9007-0f809733a338.gif[] pub(crate) fn goto_type_definition( db: &RootDatabase, - position: FilePosition, + FilePosition { file_id, offset }: FilePosition, ) -> Option>> { let sema = hir::Semantics::new(db); - let file: ast::SourceFile = sema.parse(position.file_id); + let file: ast::SourceFile = sema.parse(file_id); let token: SyntaxToken = - pick_best_token(file.syntax().token_at_offset(position.offset), |kind| match kind { + pick_best_token(file.syntax().token_at_offset(offset), |kind| match kind { IDENT | INT_NUMBER | T![self] => 2, kind if kind.is_trivia() => 0, _ => 1, @@ -37,7 +37,7 @@ pub(crate) fn goto_type_definition( } }; let range = token.text_range(); - sema.descend_into_macros(token) + sema.descend_into_macros(token, offset) .into_iter() .filter_map(|token| { let ty = sema diff --git a/crates/ide/src/highlight_related.rs b/crates/ide/src/highlight_related.rs index 43e89a334bf5..46a0464e9e6e 100644 --- a/crates/ide/src/highlight_related.rs +++ b/crates/ide/src/highlight_related.rs @@ -15,6 +15,7 @@ use syntax::{ SyntaxKind::{self, IDENT, INT_NUMBER}, SyntaxNode, SyntaxToken, TextRange, T, }; +use text_edit::TextSize; use crate::{navigation_target::ToNav, references, NavigationTarget, TryToNav}; @@ -51,7 +52,7 @@ pub struct HighlightRelatedConfig { pub(crate) fn highlight_related( sema: &Semantics<'_, RootDatabase>, config: HighlightRelatedConfig, - FilePosition { offset, file_id }: FilePosition, + pos @ FilePosition { offset, file_id }: FilePosition, ) -> Option> { let _p = profile::span("highlight_related"); let syntax = sema.parse(file_id).syntax().clone(); @@ -79,7 +80,7 @@ pub(crate) fn highlight_related( } T![|] if config.closure_captures => highlight_closure_captures(sema, token, file_id), T![move] if config.closure_captures => highlight_closure_captures(sema, token, file_id), - _ if config.references => highlight_references(sema, &syntax, token, file_id), + _ if config.references => highlight_references(sema, &syntax, token, pos), _ => None, } } @@ -129,9 +130,9 @@ fn highlight_references( sema: &Semantics<'_, RootDatabase>, node: &SyntaxNode, token: SyntaxToken, - file_id: FileId, + FilePosition { file_id, offset }: FilePosition, ) -> Option> { - let defs = find_defs(sema, token.clone()); + let defs = find_defs(sema, token.clone(), offset); let usages = defs .iter() .filter_map(|&d| { @@ -455,8 +456,12 @@ fn cover_range(r0: Option, r1: Option) -> Option, token: SyntaxToken) -> FxHashSet { - sema.descend_into_macros(token) +fn find_defs( + sema: &Semantics<'_, RootDatabase>, + token: SyntaxToken, + offset: TextSize, +) -> FxHashSet { + sema.descend_into_macros(token, offset) .into_iter() .filter_map(|token| IdentClass::classify_token(sema, &token)) .map(IdentClass::definitions_no_ops) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 40659e6c2631..21934b9480ef 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -162,9 +162,9 @@ fn hover_simple( // prefer descending the same token kind in attribute expansions, in normal macros text // equivalency is more important let descended = if in_attr { - [sema.descend_into_macros_with_kind_preference(original_token.clone())].into() + [sema.descend_into_macros_with_kind_preference(original_token.clone(), offset)].into() } else { - sema.descend_into_macros_with_same_text(original_token.clone()) + sema.descend_into_macros_with_same_text(original_token.clone(), offset) }; let descended = || descended.iter(); diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index bf77d55d58e5..c9cdbff7d7d3 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -484,7 +484,7 @@ impl Analysis { sysroot: Option<&OsStr>, ) -> Cancellable { self.with_db(|db| { - doc_links::external_docs(db, &position, target_dir, sysroot).unwrap_or_default() + doc_links::external_docs(db, position, target_dir, sysroot).unwrap_or_default() }) } diff --git a/crates/ide/src/moniker.rs b/crates/ide/src/moniker.rs index 17f3771b1a5a..2ca2b5b1d5f3 100644 --- a/crates/ide/src/moniker.rs +++ b/crates/ide/src/moniker.rs @@ -99,7 +99,7 @@ pub(crate) fn moniker( }); } let navs = sema - .descend_into_macros(original_token.clone()) + .descend_into_macros(original_token.clone(), offset) .into_iter() .filter_map(|token| { IdentClass::classify_token(sema, &token).map(IdentClass::definitions_no_ops).map(|it| { diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index 813f9ed943f2..2d0295692ac0 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -126,7 +126,7 @@ pub(crate) fn find_defs<'a>( ) }); token.map(|token| { - sema.descend_into_macros_with_same_text(token) + sema.descend_into_macros_with_same_text(token, offset) .into_iter() .filter_map(|it| ast::NameLike::cast(it.parent()?)) .filter_map(move |name_like| { diff --git a/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs index e3ad817e06ac..847ab3d21adc 100644 --- a/crates/ide/src/signature_help.rs +++ b/crates/ide/src/signature_help.rs @@ -67,17 +67,20 @@ impl SignatureHelp { } /// Computes parameter information for the given position. -pub(crate) fn signature_help(db: &RootDatabase, position: FilePosition) -> Option { +pub(crate) fn signature_help( + db: &RootDatabase, + FilePosition { file_id, offset }: FilePosition, +) -> Option { let sema = Semantics::new(db); - let file = sema.parse(position.file_id); + let file = sema.parse(file_id); let file = file.syntax(); let token = file - .token_at_offset(position.offset) + .token_at_offset(offset) .left_biased() // if the cursor is sandwiched between two space tokens and the call is unclosed // this prevents us from leaving the CallExpression .and_then(|tok| algo::skip_trivia_token(tok, Direction::Prev))?; - let token = sema.descend_into_macros_single(token); + let token = sema.descend_into_macros_single(token, offset); for node in token.parent_ancestors() { match_ast! { diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index ae97236409eb..bb01c81d66fb 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs @@ -395,10 +395,10 @@ fn traverse( NodeOrToken::Token(token) if token.kind() != COMMENT => { let token = match attr_or_derive_item { Some(AttrOrDerive::Attr(_)) => { - sema.descend_into_macros_with_kind_preference(token) + sema.descend_into_macros_with_kind_preference(token, 0.into()) } Some(AttrOrDerive::Derive(_)) | None => { - sema.descend_into_macros_single(token) + sema.descend_into_macros_single(token, 0.into()) } }; match token.parent().and_then(ast::NameLike::cast) { From 0823f0c32b600dafcc707e76dc1898eadc3c2b59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 16 Aug 2023 10:44:32 +0200 Subject: [PATCH 075/197] Remove `count` --- compiler/rustc_data_structures/src/sharded.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs index 39cce5c8ee6f..52ab5a7fb144 100644 --- a/compiler/rustc_data_structures/src/sharded.rs +++ b/compiler/rustc_data_structures/src/sharded.rs @@ -49,7 +49,7 @@ impl Sharded { match self { Self::Single(single) => &single, #[cfg(parallel_compiler)] - Self::Shards(shards) => self.get_shard_by_hash(make_hash(_val)), + Self::Shards(..) => self.get_shard_by_hash(make_hash(_val)), } } @@ -70,21 +70,20 @@ impl Sharded { } } - #[inline] - fn count(&self) -> usize { + pub fn lock_shards(&self) -> Vec> { match self { - Self::Single(..) => 1, + Self::Single(single) => vec![single.lock()], #[cfg(parallel_compiler)] - Self::Shards(..) => SHARDS, + Self::Shards(shards) => shards.iter().map(|shard| shard.0.lock()).collect(), } } - pub fn lock_shards(&self) -> Vec> { - (0..self.count()).map(|i| self.get_shard_by_index(i).lock()).collect() - } - pub fn try_lock_shards(&self) -> Option>> { - (0..self.count()).map(|i| self.get_shard_by_index(i).try_lock()).collect() + match self { + Self::Single(single) => Some(vec![single.try_lock()?]), + #[cfg(parallel_compiler)] + Self::Shards(shards) => shards.iter().map(|shard| shard.0.try_lock()).collect(), + } } } From af8048266cd87e7855cb150803260887aa93d01a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 16 Aug 2023 11:18:11 +0200 Subject: [PATCH 076/197] Prepare ItemScope for IDE import resolution --- crates/hir-def/src/find_path.rs | 18 +++ crates/hir-def/src/import_map.rs | 17 ++- crates/hir-def/src/item_scope.rs | 130 +++++++++++++----- crates/hir-def/src/lib.rs | 21 +++ crates/hir-def/src/nameres.rs | 1 + crates/hir-def/src/nameres/collector.rs | 7 +- crates/hir-def/src/nameres/path_resolution.rs | 2 +- .../hir-def/src/nameres/tests/incremental.rs | 2 +- crates/hir-def/src/per_ns.rs | 34 +++-- crates/hir-def/src/resolver.rs | 6 +- crates/ide-db/src/lib.rs | 3 + 11 files changed, 174 insertions(+), 67 deletions(-) diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs index 59c250d75066..234d3eaed566 100644 --- a/crates/hir-def/src/find_path.rs +++ b/crates/hir-def/src/find_path.rs @@ -1293,4 +1293,22 @@ pub mod prelude { "None", ); } + + #[test] + fn different_crate_renamed_through_dep() { + check_found_path( + r#" +//- /main.rs crate:main deps:intermediate +$0 +//- /intermediate.rs crate:intermediate deps:std +pub extern crate std as std_renamed; +//- /std.rs crate:std +pub struct S; + "#, + "intermediate::std_renamed::S", + "intermediate::std_renamed::S", + "intermediate::std_renamed::S", + "intermediate::std_renamed::S", + ); + } } diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs index d742b2eef0a4..5d7bb0b49d7e 100644 --- a/crates/hir-def/src/import_map.rs +++ b/crates/hir-def/src/import_map.rs @@ -114,6 +114,9 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> FxIndexMap FxIndexMap { - entry.insert(depth); - } + Entry::Vacant(entry) => _ = entry.insert((depth, is_doc_hidden)), Entry::Occupied(mut entry) => { - if depth < *entry.get() { - entry.insert(depth); - } else { + let &(occ_depth, occ_is_doc_hidden) = entry.get(); + // Prefer the one that is not doc(hidden), + // Otherwise, if both have the same doc(hidden)-ness and the new path is shorter, prefer that one. + let overwrite_entry = occ_is_doc_hidden && !is_doc_hidden + || occ_is_doc_hidden == is_doc_hidden && depth < occ_depth; + if !overwrite_entry { continue; } + entry.insert((depth, is_doc_hidden)); } } diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs index 873accafb43d..03fc5c3abdef 100644 --- a/crates/hir-def/src/item_scope.rs +++ b/crates/hir-def/src/item_scope.rs @@ -6,6 +6,7 @@ use std::collections::hash_map::Entry; use base_db::CrateId; use hir_expand::{attrs::AttrId, db::ExpandDatabase, name::Name, AstId, MacroCallId}; use itertools::Itertools; +use la_arena::Idx; use once_cell::sync::Lazy; use profile::Count; use rustc_hash::{FxHashMap, FxHashSet}; @@ -32,15 +33,50 @@ pub struct PerNsGlobImports { macros: FxHashSet<(LocalModuleId, Name)>, } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum ImportOrExternCrate { + Import(ImportId), + Glob(UseId), + ExternCrate(ExternCrateId), +} + +impl ImportOrExternCrate { + pub fn into_import(self) -> Option { + match self { + ImportOrExternCrate::Import(it) => Some(it), + _ => None, + } + } + + pub fn into_glob(self) -> Option { + match self { + ImportOrExternCrate::Glob(it) => Some(it), + _ => None, + } + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum ImportOrDef { + Import(ImportId), + ExternCrate(ExternCrateId), + Def(ModuleDefId), +} +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct ImportId { + pub import: UseId, + pub idx: Idx, +} + #[derive(Debug, Default, PartialEq, Eq)] pub struct ItemScope { _c: Count, /// Defs visible in this scope. This includes `declarations`, but also /// imports. - types: FxHashMap, - values: FxHashMap, - macros: FxHashMap, + types: FxHashMap)>, + values: FxHashMap)>, + macros: FxHashMap)>, unresolved: FxHashSet, /// The defs declared in this scope. Each def has a single scope where it is @@ -50,7 +86,14 @@ pub struct ItemScope { impls: Vec, unnamed_consts: Vec, /// Traits imported via `use Trait as _;`. - unnamed_trait_imports: FxHashMap, + unnamed_trait_imports: FxHashMap)>, + + // the resolutions of the imports of this scope + use_imports_types: FxHashMap, + use_imports_values: FxHashMap, + use_imports_macros: FxHashMap, + + use_decls: Vec, extern_crate_decls: Vec, /// Macros visible in current module in legacy textual scope /// @@ -121,8 +164,7 @@ impl ItemScope { } pub fn use_decls(&self) -> impl Iterator + ExactSizeIterator + '_ { - // FIXME: to be implemented - std::iter::empty() + self.use_decls.iter().copied() } pub fn impls(&self) -> impl Iterator + ExactSizeIterator + '_ { @@ -132,13 +174,13 @@ impl ItemScope { pub fn values( &self, ) -> impl Iterator + ExactSizeIterator + '_ { - self.values.values().copied() + self.values.values().copied().map(|(a, b, _)| (a, b)) } - pub fn types( + pub(crate) fn types( &self, ) -> impl Iterator + ExactSizeIterator + '_ { - self.types.values().copied() + self.types.values().copied().map(|(def, vis, _)| (def, vis)) } pub fn unnamed_consts(&self) -> impl Iterator + '_ { @@ -165,33 +207,48 @@ impl ItemScope { } pub(crate) fn type_(&self, name: &Name) -> Option<(ModuleDefId, Visibility)> { - self.types.get(name).copied() + self.types.get(name).copied().map(|(a, b, _)| (a, b)) } /// XXX: this is O(N) rather than O(1), try to not introduce new usages. pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> { - let (def, mut iter) = match item { - ItemInNs::Macros(def) => { - return self.macros.iter().find_map(|(name, &(other_def, vis))| { - (other_def == def).then_some((name, vis)) - }); - } - ItemInNs::Types(def) => (def, self.types.iter()), - ItemInNs::Values(def) => (def, self.values.iter()), - }; - iter.find_map(|(name, &(other_def, vis))| (other_def == def).then_some((name, vis))) + match item { + ItemInNs::Macros(def) => self + .macros + .iter() + .find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))), + ItemInNs::Types(def) => self + .types + .iter() + .find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))), + + ItemInNs::Values(def) => self + .values + .iter() + .find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))), + } } pub(crate) fn traits(&self) -> impl Iterator + '_ { self.types .values() - .filter_map(|&(def, _)| match def { + .filter_map(|&(def, _, _)| match def { ModuleDefId::TraitId(t) => Some(t), _ => None, }) .chain(self.unnamed_trait_imports.keys().copied()) } + pub(crate) fn resolutions(&self) -> impl Iterator, PerNs)> + '_ { + self.entries().map(|(name, res)| (Some(name.clone()), res)).chain( + self.unnamed_trait_imports + .iter() + .map(|(tr, (vis, _))| (None, PerNs::types(ModuleDefId::TraitId(*tr), *vis))), + ) + } +} + +impl ItemScope { pub(crate) fn declare(&mut self, def: ModuleDefId) { self.declarations.push(def) } @@ -278,11 +335,11 @@ impl ItemScope { } pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option { - self.unnamed_trait_imports.get(&tr).copied() + self.unnamed_trait_imports.get(&tr).copied().map(|(a, _)| a) } pub(crate) fn push_unnamed_trait(&mut self, tr: TraitId, vis: Visibility) { - self.unnamed_trait_imports.insert(tr, vis); + self.unnamed_trait_imports.insert(tr, (vis, None)); } pub(crate) fn push_res_with_import( @@ -343,27 +400,18 @@ impl ItemScope { changed } - pub(crate) fn resolutions(&self) -> impl Iterator, PerNs)> + '_ { - self.entries().map(|(name, res)| (Some(name.clone()), res)).chain( - self.unnamed_trait_imports - .iter() - .map(|(tr, vis)| (None, PerNs::types(ModuleDefId::TraitId(*tr), *vis))), - ) - } - /// Marks everything that is not a procedural macro as private to `this_module`. pub(crate) fn censor_non_proc_macros(&mut self, this_module: ModuleId) { self.types .values_mut() - .chain(self.values.values_mut()) + .map(|(def, vis, _)| (def, vis)) + .chain(self.values.values_mut().map(|(def, vis, _)| (def, vis))) .map(|(_, v)| v) - .chain(self.unnamed_trait_imports.values_mut()) + .chain(self.unnamed_trait_imports.values_mut().map(|(vis, _)| vis)) .for_each(|vis| *vis = Visibility::Module(this_module)); - for (mac, vis) in self.macros.values_mut() { - if let MacroId::ProcMacroId(_) = mac { - // FIXME: Technically this is insufficient since reexports of proc macros are also - // forbidden. Practically nobody does that. + for (mac, vis, import) in self.macros.values_mut() { + if matches!(mac, MacroId::ProcMacroId(_) if import.is_none()) { continue; } @@ -415,10 +463,17 @@ impl ItemScope { attr_macros, derive_macros, extern_crate_decls, + use_decls, + use_imports_values, + use_imports_types, + use_imports_macros, } = self; types.shrink_to_fit(); values.shrink_to_fit(); macros.shrink_to_fit(); + use_imports_types.shrink_to_fit(); + use_imports_values.shrink_to_fit(); + use_imports_macros.shrink_to_fit(); unresolved.shrink_to_fit(); declarations.shrink_to_fit(); impls.shrink_to_fit(); @@ -428,6 +483,7 @@ impl ItemScope { attr_macros.shrink_to_fit(); derive_macros.shrink_to_fit(); extern_crate_decls.shrink_to_fit(); + use_decls.shrink_to_fit(); } } diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index c40bbc0380ef..3c0ed8c2e51a 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -865,6 +865,7 @@ impl_from!( ConstId, FunctionId, TraitId, + TraitAliasId, TypeAliasId, MacroId(Macro2Id, MacroRulesId, ProcMacroId), ImplId, @@ -873,6 +874,26 @@ impl_from!( for AttrDefId ); +impl TryFrom for AttrDefId { + type Error = (); + + fn try_from(value: ModuleDefId) -> Result { + match value { + ModuleDefId::ModuleId(it) => Ok(it.into()), + ModuleDefId::FunctionId(it) => Ok(it.into()), + ModuleDefId::AdtId(it) => Ok(it.into()), + ModuleDefId::EnumVariantId(it) => Ok(it.into()), + ModuleDefId::ConstId(it) => Ok(it.into()), + ModuleDefId::StaticId(it) => Ok(it.into()), + ModuleDefId::TraitId(it) => Ok(it.into()), + ModuleDefId::TypeAliasId(it) => Ok(it.into()), + ModuleDefId::TraitAliasId(id) => Ok(id.into()), + ModuleDefId::MacroId(id) => Ok(id.into()), + ModuleDefId::BuiltinType(_) => Err(()), + } + } +} + impl From for AttrDefId { fn from(acid: ItemContainerId) -> Self { match acid { diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index f93125e224db..f2110410980f 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -108,6 +108,7 @@ pub struct DefMap { prelude: Option<(ModuleId, Option)>, /// `macro_use` prelude that contains macros from `#[macro_use]`'d external crates. Note that /// this contains all kinds of macro, not just `macro_rules!` macro. + /// ExternCrateId being None implies it being imported from the general prelude import. macro_use_prelude: FxHashMap)>, /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index e3253404d49f..b6658e4552cb 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -33,7 +33,7 @@ use crate::{ attr_macro_as_call_id, db::DefDatabase, derive_macro_as_call_id, - item_scope::{ImportType, PerNsGlobImports}, + item_scope::{ImportOrExternCrate, ImportType, PerNsGlobImports}, item_tree::{ self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode, MacroCall, MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId, @@ -546,8 +546,8 @@ impl DefCollector<'_> { self.def_map.resolve_path(self.db, DefMap::ROOT, &path, BuiltinShadowMode::Other, None); match per_ns.types { - Some((ModuleDefId::ModuleId(m), _)) => { - self.def_map.prelude = Some((m, None)); + Some((ModuleDefId::ModuleId(m), _, import)) => { + self.def_map.prelude = Some((m, import.and_then(ImportOrExternCrate::into_glob))); } types => { tracing::debug!( @@ -714,7 +714,6 @@ impl DefCollector<'_> { &mut self, krate: CrateId, names: Option>, - extern_crate: Option, ) { let def_map = self.db.crate_def_map(krate); diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index 64cdbdce7708..fc296e1e588f 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -65,7 +65,7 @@ impl PerNs { db: &dyn DefDatabase, expected: Option, ) -> Self { - self.macros = self.macros.filter(|&(id, _)| { + self.macros = self.macros.filter(|&(id, _, _)| { let this = MacroSubNs::from_id(db, id); sub_namespace_match(Some(this), expected) }); diff --git a/crates/hir-def/src/nameres/tests/incremental.rs b/crates/hir-def/src/nameres/tests/incremental.rs index 40d3a16540dc..4a86f88e57af 100644 --- a/crates/hir-def/src/nameres/tests/incremental.rs +++ b/crates/hir-def/src/nameres/tests/incremental.rs @@ -212,7 +212,7 @@ pub type Ty = (); } for (_, res) in module_data.scope.resolutions() { - match res.values.or(res.types).unwrap().0 { + match res.values.map(|(a, _, _)| a).or(res.types.map(|(a, _, _)| a)).unwrap() { ModuleDefId::FunctionId(f) => _ = db.function_data(f), ModuleDefId::AdtId(adt) => match adt { AdtId::StructId(it) => _ = db.struct_data(it), diff --git a/crates/hir-def/src/per_ns.rs b/crates/hir-def/src/per_ns.rs index 2bc1f8e926e9..f32a97d1a3a2 100644 --- a/crates/hir-def/src/per_ns.rs +++ b/crates/hir-def/src/per_ns.rs @@ -3,13 +3,17 @@ //! //! `PerNs` (per namespace) captures this. -use crate::{item_scope::ItemInNs, visibility::Visibility, MacroId, ModuleDefId}; +use crate::{ + item_scope::{ImportId, ImportOrExternCrate, ItemInNs}, + visibility::Visibility, + MacroId, ModuleDefId, +}; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct PerNs { - pub types: Option<(ModuleDefId, Visibility)>, - pub values: Option<(ModuleDefId, Visibility)>, - pub macros: Option<(MacroId, Visibility)>, + pub types: Option<(ModuleDefId, Visibility, Option)>, + pub values: Option<(ModuleDefId, Visibility, Option)>, + pub macros: Option<(MacroId, Visibility, Option)>, } impl Default for PerNs { @@ -24,19 +28,19 @@ impl PerNs { } pub fn values(t: ModuleDefId, v: Visibility) -> PerNs { - PerNs { types: None, values: Some((t, v)), macros: None } + PerNs { types: None, values: Some((t, v, None)), macros: None } } pub fn types(t: ModuleDefId, v: Visibility) -> PerNs { - PerNs { types: Some((t, v)), values: None, macros: None } + PerNs { types: Some((t, v, None)), values: None, macros: None } } pub fn both(types: ModuleDefId, values: ModuleDefId, v: Visibility) -> PerNs { - PerNs { types: Some((types, v)), values: Some((values, v)), macros: None } + PerNs { types: Some((types, v, None)), values: Some((values, v, None)), macros: None } } pub fn macros(macro_: MacroId, v: Visibility) -> PerNs { - PerNs { types: None, values: None, macros: Some((macro_, v)) } + PerNs { types: None, values: None, macros: Some((macro_, v, None)) } } pub fn is_none(&self) -> bool { @@ -52,7 +56,7 @@ impl PerNs { } pub fn take_types_vis(self) -> Option<(ModuleDefId, Visibility)> { - self.types + self.types.map(|(a, b, _)| (a, b)) } pub fn take_values(self) -> Option { @@ -66,17 +70,17 @@ impl PerNs { pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs { let _p = profile::span("PerNs::filter_visibility"); PerNs { - types: self.types.filter(|(_, v)| f(*v)), - values: self.values.filter(|(_, v)| f(*v)), - macros: self.macros.filter(|(_, v)| f(*v)), + types: self.types.filter(|&(_, v, _)| f(v)), + values: self.values.filter(|&(_, v, _)| f(v)), + macros: self.macros.filter(|&(_, v, _)| f(v)), } } pub fn with_visibility(self, vis: Visibility) -> PerNs { PerNs { - types: self.types.map(|(it, _)| (it, vis)), - values: self.values.map(|(it, _)| (it, vis)), - macros: self.macros.map(|(it, _)| (it, vis)), + types: self.types.map(|(it, _, c)| (it, vis, c)), + values: self.values.map(|(it, _, c)| (it, vis, c)), + macros: self.macros.map(|(it, _, import)| (it, vis, import)), } } diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 17a1bf50b5e9..28ab0f8f6eeb 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -864,13 +864,13 @@ impl ScopeNames { } } fn add_per_ns(&mut self, name: &Name, def: PerNs) { - if let &Some((ty, _)) = &def.types { + if let &Some((ty, _, _)) = &def.types { self.add(name, ScopeDef::ModuleDef(ty)) } - if let &Some((def, _)) = &def.values { + if let &Some((def, _, _)) = &def.values { self.add(name, ScopeDef::ModuleDef(def)) } - if let &Some((mac, _)) = &def.macros { + if let &Some((mac, _, _)) = &def.macros { self.add(name, ScopeDef::ModuleDef(ModuleDefId::MacroId(mac))) } if def.is_none() { diff --git a/crates/ide-db/src/lib.rs b/crates/ide-db/src/lib.rs index f27ed485d814..ac3511ba47b3 100644 --- a/crates/ide-db/src/lib.rs +++ b/crates/ide-db/src/lib.rs @@ -94,18 +94,21 @@ impl fmt::Debug for RootDatabase { } impl Upcast for RootDatabase { + #[inline] fn upcast(&self) -> &(dyn ExpandDatabase + 'static) { &*self } } impl Upcast for RootDatabase { + #[inline] fn upcast(&self) -> &(dyn DefDatabase + 'static) { &*self } } impl Upcast for RootDatabase { + #[inline] fn upcast(&self) -> &(dyn HirDatabase + 'static) { &*self } From 42a708083a59ece9599723f69536ddb6e987e6e4 Mon Sep 17 00:00:00 2001 From: Georgii Rylov Date: Thu, 10 Aug 2023 14:06:41 +0100 Subject: [PATCH 077/197] Fix a pthread_t handle leak #114610 --- library/std/src/sys/wasi/thread.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/library/std/src/sys/wasi/thread.rs b/library/std/src/sys/wasi/thread.rs index dbad425976a3..99717613f57c 100644 --- a/library/std/src/sys/wasi/thread.rs +++ b/library/std/src/sys/wasi/thread.rs @@ -47,6 +47,7 @@ cfg_if::cfg_if! { stack_size: libc::size_t, ) -> ffi::c_int; pub fn pthread_attr_destroy(attr: *mut pthread_attr_t) -> ffi::c_int; + pub fn pthread_detach(thread: pthread_t) -> ffi::c_int; } } @@ -178,6 +179,17 @@ impl Thread { } } +cfg_if::cfg_if! { + if #[cfg(target_feature = "atomics")] { + impl Drop for Thread { + fn drop(&mut self) { + let ret = unsafe { libc::pthread_detach(self.id) }; + debug_assert_eq!(ret, 0); + } + } + } +} + pub fn available_parallelism() -> io::Result { unsupported() } From 9b00e5f06f51703c5294af602959d3f92c095aa7 Mon Sep 17 00:00:00 2001 From: Georgii Rylov Date: Wed, 16 Aug 2023 11:19:22 +0100 Subject: [PATCH 078/197] address comments --- library/std/src/sys/wasi/thread.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/library/std/src/sys/wasi/thread.rs b/library/std/src/sys/wasi/thread.rs index 99717613f57c..a0eefa8811a3 100644 --- a/library/std/src/sys/wasi/thread.rs +++ b/library/std/src/sys/wasi/thread.rs @@ -54,6 +54,13 @@ cfg_if::cfg_if! { pub struct Thread { id: libc::pthread_t, } + + impl Drop for Thread { + fn drop(&mut self) { + let ret = unsafe { libc::pthread_detach(self.id) }; + debug_assert_eq!(ret, 0); + } + } } else { pub struct Thread(!); } @@ -179,17 +186,6 @@ impl Thread { } } -cfg_if::cfg_if! { - if #[cfg(target_feature = "atomics")] { - impl Drop for Thread { - fn drop(&mut self) { - let ret = unsafe { libc::pthread_detach(self.id) }; - debug_assert_eq!(ret, 0); - } - } - } -} - pub fn available_parallelism() -> io::Result { unsupported() } From c4e9b5ac649c62a46110660b612776468ba0d07f Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 17 Aug 2023 09:33:15 +0200 Subject: [PATCH 079/197] Add import info to item scope dumps --- crates/hir-def/src/body/tests/block.rs | 20 +- crates/hir-def/src/item_scope.rs | 248 ++++++++++++++---- crates/hir-def/src/nameres/collector.rs | 125 +++++---- crates/hir-def/src/nameres/tests.rs | 80 +++--- crates/hir-def/src/nameres/tests/globs.rs | 18 +- crates/hir-def/src/nameres/tests/macros.rs | 52 ++-- .../src/nameres/tests/mod_resolution.rs | 32 +-- .../hir-def/src/nameres/tests/primitives.rs | 4 +- 8 files changed, 364 insertions(+), 215 deletions(-) diff --git a/crates/hir-def/src/body/tests/block.rs b/crates/hir-def/src/body/tests/block.rs index 4e015a7fbbb0..44eeed9e3fb2 100644 --- a/crates/hir-def/src/body/tests/block.rs +++ b/crates/hir-def/src/body/tests/block.rs @@ -38,9 +38,9 @@ fn outer() { "#, expect![[r#" block scope - CrateStruct: t - PlainStruct: t v - SelfStruct: t + CrateStruct: ti + PlainStruct: ti vi + SelfStruct: ti Struct: v SuperStruct: _ @@ -66,7 +66,7 @@ fn outer() { "#, expect![[r#" block scope - imported: t v + imported: ti vi name: v crate @@ -92,9 +92,9 @@ fn outer() { "#, expect![[r#" block scope - inner1: t + inner1: ti inner2: v - outer: v + outer: vi block scope inner: v @@ -121,7 +121,7 @@ struct Struct {} "#, expect![[r#" block scope - Struct: t + Struct: ti crate Struct: t @@ -153,7 +153,7 @@ fn outer() { "#, expect![[r#" block scope - ResolveMe: t + ResolveMe: ti block scope m2: t @@ -214,7 +214,7 @@ fn f() { "#, expect![[r#" block scope - ResolveMe: t + ResolveMe: ti block scope h: v @@ -292,7 +292,7 @@ pub mod cov_mark { nested: v crate - cov_mark: t + cov_mark: ti f: v "#]], ); diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs index 03fc5c3abdef..59a1c5f49e24 100644 --- a/crates/hir-def/src/item_scope.rs +++ b/crates/hir-def/src/item_scope.rs @@ -20,12 +20,6 @@ use crate::{ UseId, }; -#[derive(Copy, Clone, Debug)] -pub(crate) enum ImportType { - Glob, - Named, -} - #[derive(Debug, Default)] pub struct PerNsGlobImports { types: FxHashSet<(LocalModuleId, Name)>, @@ -35,6 +29,12 @@ pub struct PerNsGlobImports { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum ImportOrExternCrate { + Import(ImportId), + ExternCrate(ExternCrateId), +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum ImportType { Import(ImportId), Glob(UseId), ExternCrate(ExternCrateId), @@ -47,13 +47,6 @@ impl ImportOrExternCrate { _ => None, } } - - pub fn into_glob(self) -> Option { - match self { - ImportOrExternCrate::Glob(it) => Some(it), - _ => None, - } - } } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -89,9 +82,9 @@ pub struct ItemScope { unnamed_trait_imports: FxHashMap)>, // the resolutions of the imports of this scope - use_imports_types: FxHashMap, - use_imports_values: FxHashMap, - use_imports_macros: FxHashMap, + use_imports_types: FxHashMap, + use_imports_values: FxHashMap, + use_imports_macros: FxHashMap, use_decls: Vec, extern_crate_decls: Vec, @@ -347,51 +340,185 @@ impl ItemScope { glob_imports: &mut PerNsGlobImports, lookup: (LocalModuleId, Name), def: PerNs, - def_import_type: ImportType, + import: Option, ) -> bool { let mut changed = false; - macro_rules! check_changed { - ( - $changed:ident, - ( $this:ident / $def:ident ) . $field:ident, - $glob_imports:ident [ $lookup:ident ], - $def_import_type:ident - ) => {{ - if let Some(fld) = $def.$field { - let existing = $this.$field.entry($lookup.1.clone()); - match existing { - Entry::Vacant(entry) => { - match $def_import_type { - ImportType::Glob => { - $glob_imports.$field.insert($lookup.clone()); - } - ImportType::Named => { - $glob_imports.$field.remove(&$lookup); - } - } - - entry.insert(fld); - $changed = true; + if let Some(mut fld) = def.types { + let existing = self.types.entry(lookup.1.clone()); + match existing { + Entry::Vacant(entry) => { + match import { + Some(ImportType::Glob(_)) => { + glob_imports.types.insert(lookup.clone()); } - Entry::Occupied(mut entry) - if matches!($def_import_type, ImportType::Named) => - { - if $glob_imports.$field.remove(&$lookup) { - cov_mark::hit!(import_shadowed); - entry.insert(fld); - $changed = true; - } + _ => _ = glob_imports.types.remove(&lookup), + } + let import = match import { + Some(ImportType::ExternCrate(extern_crate)) => { + Some(ImportOrExternCrate::ExternCrate(extern_crate)) } - _ => {} + Some(ImportType::Import(import)) => { + Some(ImportOrExternCrate::Import(import)) + } + None | Some(ImportType::Glob(_)) => None, + }; + let prev = std::mem::replace(&mut fld.2, import); + if let Some(ImportOrExternCrate::Import(import)) = import { + self.use_imports_values.insert( + import, + match prev { + Some(ImportOrExternCrate::Import(import)) => { + ImportOrDef::Import(import) + } + Some(ImportOrExternCrate::ExternCrate(import)) => { + ImportOrDef::ExternCrate(import) + } + None => ImportOrDef::Def(fld.0), + }, + ); + } + entry.insert(fld); + changed = true; + } + Entry::Occupied(mut entry) if !matches!(import, Some(ImportType::Glob(..))) => { + if glob_imports.types.remove(&lookup) { + let import = match import { + Some(ImportType::ExternCrate(extern_crate)) => { + Some(ImportOrExternCrate::ExternCrate(extern_crate)) + } + Some(ImportType::Import(import)) => { + Some(ImportOrExternCrate::Import(import)) + } + None | Some(ImportType::Glob(_)) => None, + }; + let prev = std::mem::replace(&mut fld.2, import); + if let Some(ImportOrExternCrate::Import(import)) = import { + self.use_imports_values.insert( + import, + match prev { + Some(ImportOrExternCrate::Import(import)) => { + ImportOrDef::Import(import) + } + Some(ImportOrExternCrate::ExternCrate(import)) => { + ImportOrDef::ExternCrate(import) + } + None => ImportOrDef::Def(fld.0), + }, + ); + } + cov_mark::hit!(import_shadowed); + entry.insert(fld); + changed = true; } } - }}; + _ => {} + } } - check_changed!(changed, (self / def).types, glob_imports[lookup], def_import_type); - check_changed!(changed, (self / def).values, glob_imports[lookup], def_import_type); - check_changed!(changed, (self / def).macros, glob_imports[lookup], def_import_type); + if let Some(mut fld) = def.values { + let existing = self.values.entry(lookup.1.clone()); + match existing { + Entry::Vacant(entry) => { + match import { + Some(ImportType::Glob(_)) => { + glob_imports.values.insert(lookup.clone()); + } + _ => _ = glob_imports.values.remove(&lookup), + } + let import = match import { + Some(ImportType::Import(import)) => Some(import), + _ => None, + }; + let prev = std::mem::replace(&mut fld.2, import); + if let Some(import) = import { + self.use_imports_values.insert( + import, + match prev { + Some(import) => ImportOrDef::Import(import), + None => ImportOrDef::Def(fld.0), + }, + ); + } + entry.insert(fld); + changed = true; + } + Entry::Occupied(mut entry) if !matches!(import, Some(ImportType::Glob(..))) => { + if glob_imports.values.remove(&lookup) { + cov_mark::hit!(import_shadowed); + let import = match import { + Some(ImportType::Import(import)) => Some(import), + _ => None, + }; + let prev = std::mem::replace(&mut fld.2, import); + if let Some(import) = import { + self.use_imports_values.insert( + import, + match prev { + Some(import) => ImportOrDef::Import(import), + None => ImportOrDef::Def(fld.0), + }, + ); + } + entry.insert(fld); + changed = true; + } + } + _ => {} + } + } + + if let Some(mut fld) = def.macros { + let existing = self.macros.entry(lookup.1.clone()); + match existing { + Entry::Vacant(entry) => { + match import { + Some(ImportType::Glob(_)) => { + glob_imports.macros.insert(lookup.clone()); + } + _ => _ = glob_imports.macros.remove(&lookup), + } + let import = match import { + Some(ImportType::Import(import)) => Some(import), + _ => None, + }; + let prev = std::mem::replace(&mut fld.2, import); + if let Some(import) = import { + self.use_imports_macros.insert( + import, + match prev { + Some(import) => ImportOrDef::Import(import), + None => ImportOrDef::Def(fld.0.into()), + }, + ); + } + entry.insert(fld); + changed = true; + } + Entry::Occupied(mut entry) if !matches!(import, Some(ImportType::Glob(..))) => { + if glob_imports.macros.remove(&lookup) { + cov_mark::hit!(import_shadowed); + let import = match import { + Some(ImportType::Import(import)) => Some(import), + _ => None, + }; + let prev = std::mem::replace(&mut fld.2, import); + if let Some(import) = import { + self.use_imports_macros.insert( + import, + match prev { + Some(import) => ImportOrDef::Import(import), + None => ImportOrDef::Def(fld.0.into()), + }, + ); + } + entry.insert(fld); + changed = true; + } + } + _ => {} + } + } if def.is_none() && self.unresolved.insert(lookup.1) { changed = true; @@ -430,14 +557,25 @@ impl ItemScope { name.map_or("_".to_string(), |name| name.display(db).to_string()) ); - if def.types.is_some() { + if let Some((.., i)) = def.types { buf.push_str(" t"); + match i { + Some(ImportOrExternCrate::Import(_)) => buf.push('i'), + Some(ImportOrExternCrate::ExternCrate(_)) => buf.push('e'), + None => (), + } } - if def.values.is_some() { + if let Some((.., i)) = def.values { buf.push_str(" v"); + if i.is_some() { + buf.push('i'); + } } - if def.macros.is_some() { + if let Some((.., i)) = def.macros { buf.push_str(" m"); + if i.is_some() { + buf.push('i'); + } } if def.is_none() { buf.push_str(" _"); diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index b6658e4552cb..48eaec0f4e54 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -33,7 +33,7 @@ use crate::{ attr_macro_as_call_id, db::DefDatabase, derive_macro_as_call_id, - item_scope::{ImportOrExternCrate, ImportType, PerNsGlobImports}, + item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports}, item_tree::{ self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode, MacroCall, MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId, @@ -146,7 +146,7 @@ impl PartialResolvedImport { #[derive(Clone, Debug, Eq, PartialEq)] enum ImportSource { - Use { use_tree: Idx, id: UseId, is_prelude: bool }, + Use { use_tree: Idx, id: UseId, is_prelude: bool, kind: ImportKind }, ExternCrate { id: ExternCrateId }, } @@ -155,7 +155,6 @@ struct Import { path: ModPath, alias: Option, visibility: RawVisibility, - kind: ImportKind, source: ImportSource, } @@ -174,8 +173,7 @@ impl Import { path, alias, visibility: visibility.clone(), - kind, - source: ImportSource::Use { use_tree: idx, id, is_prelude }, + source: ImportSource::Use { use_tree: idx, id, is_prelude, kind }, }); }); } @@ -191,7 +189,6 @@ impl Import { path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())), alias: it.alias.clone(), visibility: visibility.clone(), - kind: ImportKind::Plain, source: ImportSource::ExternCrate { id }, } } @@ -225,7 +222,7 @@ struct DefCollector<'a> { db: &'a dyn DefDatabase, def_map: DefMap, deps: FxHashMap, - glob_imports: FxHashMap>, + glob_imports: FxHashMap>, unresolved_imports: Vec, indeterminate_imports: Vec, unresolved_macros: Vec, @@ -547,7 +544,11 @@ impl DefCollector<'_> { match per_ns.types { Some((ModuleDefId::ModuleId(m), _, import)) => { - self.def_map.prelude = Some((m, import.and_then(ImportOrExternCrate::into_glob))); + // FIXME: This should specifically look for a glob import somehow and record that here + self.def_map.prelude = Some(( + m, + import.and_then(ImportOrExternCrate::into_import).map(|it| it.import), + )); } types => { tracing::debug!( @@ -649,7 +650,7 @@ impl DefCollector<'_> { module_id, &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))], Visibility::Public, - ImportType::Named, + None, ); } } @@ -685,7 +686,7 @@ impl DefCollector<'_> { module_id, &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))], vis, - ImportType::Named, + None, ); } @@ -700,7 +701,7 @@ impl DefCollector<'_> { module_id, &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))], Visibility::Public, - ImportType::Named, + None, ); } @@ -720,16 +721,19 @@ impl DefCollector<'_> { // `#[macro_use]` brings macros into macro_use prelude. Yes, even non-`macro_rules!` // macros. let root_scope = &def_map[DefMap::ROOT].scope; - if let Some(names) = names { - for name in names { - // FIXME: Report diagnostic on 404. - if let Some(def) = root_scope.get(&name).take_macros() { - self.def_map.macro_use_prelude.insert(name, (def, extern_crate)); + match names { + Some(names) => { + for name in names { + // FIXME: Report diagnostic on 404. + if let Some(def) = root_scope.get(&name).take_macros() { + self.def_map.macro_use_prelude.insert(name, (def, extern_crate)); + } } } - } else { - for (name, def) in root_scope.macros() { - self.def_map.macro_use_prelude.insert(name.clone(), (def, extern_crate)); + None => { + for (name, def) in root_scope.macros() { + self.def_map.macro_use_prelude.insert(name.clone(), (def, extern_crate)); + } } } } @@ -836,8 +840,9 @@ impl DefCollector<'_> { .resolve_visibility(self.db, module_id, &directive.import.visibility, false) .unwrap_or(Visibility::Public); - match import.kind { - ImportKind::Plain | ImportKind::TypeOnly => { + match import.source { + ImportSource::ExternCrate { .. } + | ImportSource::Use { kind: ImportKind::Plain | ImportKind::TypeOnly, .. } => { let name = match &import.alias { Some(ImportAlias::Alias(name)) => Some(name), Some(ImportAlias::Underscore) => None, @@ -850,32 +855,36 @@ impl DefCollector<'_> { }, }; - if import.kind == ImportKind::TypeOnly { - def.values = None; - def.macros = None; - } - - tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); - - // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 - if let ImportSource::ExternCrate { id, .. } = import.source { - if self.def_map.block.is_none() && module_id == DefMap::ROOT { - if let (Some(ModuleDefId::ModuleId(def)), Some(name)) = - (def.take_types(), name) - { - if let Ok(def) = def.try_into() { - Arc::get_mut(&mut self.def_map.data) - .unwrap() - .extern_prelude - .insert(name.clone(), (def, Some(id))); + let imp = match import.source { + // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 + ImportSource::ExternCrate { id, .. } => { + if self.def_map.block.is_none() && module_id == DefMap::ROOT { + if let (Some(ModuleDefId::ModuleId(def)), Some(name)) = + (def.take_types(), name) + { + if let Ok(def) = def.try_into() { + Arc::get_mut(&mut self.def_map.data) + .unwrap() + .extern_prelude + .insert(name.clone(), (def, Some(id))); + } } } + ImportType::ExternCrate(id) } - } + ImportSource::Use { kind, id, use_tree, .. } => { + if kind == ImportKind::TypeOnly { + def.values = None; + def.macros = None; + } + ImportType::Import(ImportId { import: id, idx: use_tree }) + } + }; + tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); - self.update(module_id, &[(name.cloned(), def)], vis, ImportType::Named); + self.update(module_id, &[(name.cloned(), def)], vis, Some(imp)); } - ImportKind::Glob => { + ImportSource::Use { kind: ImportKind::Glob, id, .. } => { tracing::debug!("glob import: {:?}", import); match def.take_types() { Some(ModuleDefId::ModuleId(m)) => { @@ -900,7 +909,7 @@ impl DefCollector<'_> { .filter(|(_, res)| !res.is_none()) .collect::>(); - self.update(module_id, &items, vis, ImportType::Glob); + self.update(module_id, &items, vis, Some(ImportType::Glob(id))); } else { // glob import from same crate => we do an initial // import, and then need to propagate any further @@ -932,11 +941,11 @@ impl DefCollector<'_> { .filter(|(_, res)| !res.is_none()) .collect::>(); - self.update(module_id, &items, vis, ImportType::Glob); + self.update(module_id, &items, vis, Some(ImportType::Glob(id))); // record the glob import in case we add further items let glob = self.glob_imports.entry(m.local_id).or_default(); - if !glob.iter().any(|(mid, _)| *mid == module_id) { - glob.push((module_id, vis)); + if !glob.iter().any(|(mid, _, _)| *mid == module_id) { + glob.push((module_id, vis, id)); } } } @@ -962,7 +971,7 @@ impl DefCollector<'_> { (Some(name), res) }) .collect::>(); - self.update(module_id, &resolutions, vis, ImportType::Glob); + self.update(module_id, &resolutions, vis, Some(ImportType::Glob(id))); } Some(d) => { tracing::debug!("glob import {:?} from non-module/enum {:?}", import, d); @@ -982,10 +991,10 @@ impl DefCollector<'_> { resolutions: &[(Option, PerNs)], // Visibility this import will have vis: Visibility, - import_type: ImportType, + import: Option, ) { self.db.unwind_if_cancelled(); - self.update_recursive(module_id, resolutions, vis, import_type, 0) + self.update_recursive(module_id, resolutions, vis, import, 0) } fn update_recursive( @@ -996,7 +1005,7 @@ impl DefCollector<'_> { // All resolutions are imported with this visibility; the visibilities in // the `PerNs` values are ignored and overwritten vis: Visibility, - import_type: ImportType, + import: Option, depth: usize, ) { if GLOB_RECURSION_LIMIT.check(depth).is_err() { @@ -1013,7 +1022,7 @@ impl DefCollector<'_> { &mut self.from_glob_import, (module_id, name.clone()), res.with_visibility(vis), - import_type, + import, ); } None => { @@ -1058,7 +1067,7 @@ impl DefCollector<'_> { .get(&module_id) .into_iter() .flatten() - .filter(|(glob_importing_module, _)| { + .filter(|(glob_importing_module, _, _)| { // we know all resolutions have the same visibility (`vis`), so we // just need to check that once vis.is_visible_from_def_map(self.db, &self.def_map, *glob_importing_module) @@ -1066,12 +1075,12 @@ impl DefCollector<'_> { .cloned() .collect::>(); - for (glob_importing_module, glob_import_vis) in glob_imports { + for (glob_importing_module, glob_import_vis, use_) in glob_imports { self.update_recursive( glob_importing_module, resolutions, glob_import_vis, - ImportType::Glob, + Some(ImportType::Glob(use_)), depth + 1, ); } @@ -1474,7 +1483,9 @@ impl DefCollector<'_> { } for directive in &self.unresolved_imports { - if let ImportSource::Use { use_tree, id, is_prelude: _ } = directive.import.source { + if let ImportSource::Use { use_tree, id, is_prelude: _, kind: _ } = + directive.import.source + { if matches!( (directive.import.path.segments().first(), &directive.import.path.kind), (Some(krate), PathKind::Plain | PathKind::Abs) if diagnosed_extern_crates.contains(krate) @@ -1538,7 +1549,7 @@ impl ModCollector<'_, '_> { module_id, &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))], vis, - ImportType::Named, + None, ) }; let resolve_vis = |def_map: &DefMap, visibility| { @@ -1968,7 +1979,7 @@ impl ModCollector<'_, '_> { self.module_id, &[(Some(name), PerNs::from_def(def, vis, false))], vis, - ImportType::Named, + None, ); res } diff --git a/crates/hir-def/src/nameres/tests.rs b/crates/hir-def/src/nameres/tests.rs index dd7c3c363062..e7cc44b04da8 100644 --- a/crates/hir-def/src/nameres/tests.rs +++ b/crates/hir-def/src/nameres/tests.rs @@ -168,7 +168,7 @@ pub struct Baz; "#, expect![[r#" crate - Foo: t v + Foo: ti vi foo: t crate::foo @@ -194,8 +194,8 @@ pub enum Quux {}; "#, expect![[r#" crate - Baz: t v - Quux: t + Baz: ti vi + Quux: ti foo: t crate::foo @@ -225,11 +225,11 @@ pub struct Baz; "#, expect![[r#" crate - Baz: t v + Baz: ti vi foo: t crate::foo - Baz: t v + Baz: ti vi bar: t crate::foo::bar @@ -274,7 +274,7 @@ use self::E::V; expect![[r#" crate E: t - V: t v + V: ti vi "#]], ); } @@ -307,7 +307,7 @@ pub struct FromLib; crate::foo Bar: _ - FromLib: t v + FromLib: ti vi "#]], ); } @@ -328,7 +328,7 @@ pub struct Baz; "#, expect![[r#" crate - Baz: t + Baz: ti foo: t crate::foo @@ -352,7 +352,7 @@ pub struct Baz; "#, expect![[r#" crate - Baz: t v + Baz: ti vi "#]], ); } @@ -375,13 +375,13 @@ pub struct Arc; expect![[r#" crate alloc: t - alloc_crate: t + alloc_crate: te sync: t crate::alloc crate::sync - Arc: t v + Arc: ti vi "#]], ); } @@ -404,13 +404,13 @@ pub struct Arc; expect![[r#" crate alloc: t - alloc_crate: t + alloc_crate: te sync: t crate::alloc crate::sync - Arc: t v + Arc: ti vi "#]], ); } @@ -426,7 +426,7 @@ extern crate self as bla; "#, expect![[r#" crate - bla: t + bla: te "#]], ); } @@ -447,7 +447,7 @@ pub struct Baz; "#, expect![[r#" crate - Baz: t v + Baz: ti vi "#]], ); } @@ -465,7 +465,7 @@ pub struct Bar; "#, expect![[r#" crate - Bar: t v + Bar: ti vi foo: v "#]], ); @@ -492,9 +492,9 @@ fn no_std_prelude() { } "#, expect![[r#" - crate - Rust: t v - "#]], + crate + Rust: ti vi + "#]], ); } @@ -516,9 +516,9 @@ fn edition_specific_preludes() { } "#, expect![[r#" - crate - Rust2018: t v - "#]], + crate + Rust2018: ti vi + "#]], ); check( r#" @@ -533,9 +533,9 @@ fn edition_specific_preludes() { } "#, expect![[r#" - crate - Rust2021: t v - "#]], + crate + Rust2021: ti vi + "#]], ); } @@ -563,8 +563,8 @@ pub mod prelude { "#, expect![[r#" crate - Bar: t v - Foo: t v + Bar: ti vi + Foo: ti vi "#]], ); } @@ -590,7 +590,7 @@ pub mod prelude { "#, expect![[r#" crate - Bar: t v + Bar: ti vi Baz: _ Foo: _ "#]], @@ -619,8 +619,8 @@ pub mod prelude { expect![[r#" crate Bar: _ - Baz: t v - Foo: t v + Baz: ti vi + Foo: ti vi "#]], ); } @@ -643,7 +643,7 @@ mod b { "#, expect![[r#" crate - T: t v + T: ti vi a: t b: t @@ -816,8 +816,8 @@ fn bar() {} expect![[r#" crate bar: v - baz: v - foo: t + baz: vi + foo: ti "#]], ); } @@ -836,7 +836,7 @@ use self::m::S::{self}; "#, expect![[r#" crate - S: t + S: ti m: t crate::m @@ -860,8 +860,8 @@ pub const settings: () = (); "#, expect![[r#" crate - Settings: t v - settings: v + Settings: ti vi + settings: vi "#]], ) } @@ -890,8 +890,8 @@ pub struct Struct; "#, expect![[r#" crate - Struct: t v - dep: t + Struct: ti vi + dep: te "#]], ); } @@ -917,13 +917,13 @@ use some_module::unknown_func; crate other_module: t some_module: t - unknown_func: v + unknown_func: vi crate::other_module some_submodule: t crate::other_module::some_submodule - unknown_func: v + unknown_func: vi crate::some_module unknown_func: v diff --git a/crates/hir-def/src/nameres/tests/globs.rs b/crates/hir-def/src/nameres/tests/globs.rs index 88a3c76393f0..1ca74b5da6bf 100644 --- a/crates/hir-def/src/nameres/tests/globs.rs +++ b/crates/hir-def/src/nameres/tests/globs.rs @@ -24,7 +24,7 @@ pub struct Baz; foo: t crate::foo - Baz: t v + Baz: ti vi Foo: t v bar: t @@ -237,9 +237,9 @@ pub mod baz { pub struct Bar; } "#, expect![[r#" crate - Bar: t v + Bar: ti vi bar: t - baz: t + baz: ti foo: t crate::bar @@ -276,9 +276,9 @@ pub mod baz { pub struct Bar; } "#, expect![[r#" crate - Bar: t v + Bar: ti vi bar: t - baz: t + baz: ti foo: t crate::bar @@ -323,7 +323,7 @@ mod d { X: t v crate::b - foo: t + foo: ti crate::c foo: t @@ -332,8 +332,8 @@ mod d { Y: t v crate::d - Y: t v - foo: t + Y: ti vi + foo: ti "#]], ); } @@ -355,7 +355,7 @@ use event::Event; "#, expect![[r#" crate - Event: t + Event: ti event: t crate::event diff --git a/crates/hir-def/src/nameres/tests/macros.rs b/crates/hir-def/src/nameres/tests/macros.rs index f4cca8d68d0a..e64fa0b46f13 100644 --- a/crates/hir-def/src/nameres/tests/macros.rs +++ b/crates/hir-def/src/nameres/tests/macros.rs @@ -203,8 +203,8 @@ macro_rules! bar { expect![[r#" crate Foo: t - bar: m - foo: m + bar: mi + foo: mi "#]], ); } @@ -251,7 +251,7 @@ mod priv_mod { Bar: t v Foo: t v bar: t - foo: t + foo: te crate::bar Baz: t v @@ -318,9 +318,9 @@ macro_rules! baz3 { () => { struct OkBaz3; } } OkBaz1: t v OkBaz2: t v OkBaz3: t v - all: t - empty: t - multiple: t + all: te + empty: te + multiple: te "#]], ); } @@ -551,8 +551,8 @@ fn baz() {} "#, expect![[r#" crate - bar: t m - baz: t v m + bar: ti mi + baz: ti v mi foo: t m "#]], ); @@ -583,7 +583,7 @@ mod m { crate Alias: t v Direct: t v - foo: t + foo: te "#]], ); } @@ -628,9 +628,9 @@ mod m { m: t crate::m - alias1: m - alias2: m - alias3: m + alias1: mi + alias2: mi + alias3: mi not_found: _ "#]], ); @@ -682,11 +682,11 @@ pub struct Baz; "#, expect![[r#" crate - Bar: t v - Baz: t v + Bar: ti vi + Baz: ti vi Foo: t v - FooSelf: t v - foo: t + FooSelf: ti vi + foo: te m: t crate::m @@ -725,7 +725,7 @@ pub struct bar; "#, expect![[r#" crate - bar: t v + bar: ti vi "#]], ); } @@ -1340,7 +1340,7 @@ pub mod prelude { crate Ok: t v bar: m - dep: t + dep: te foo: m ok: v "#]], @@ -1370,13 +1370,13 @@ macro_rules! mk_foo { } "#, expect![[r#" - crate - a: t - lib: t + crate + a: t + lib: te - crate::a - Ok: t v - "#]], + crate::a + Ok: t v + "#]], ); } @@ -1427,8 +1427,8 @@ pub mod prelude { expect![[r#" crate Ok: t v - bar: m - foo: m + bar: mi + foo: mi ok: v "#]], ); diff --git a/crates/hir-def/src/nameres/tests/mod_resolution.rs b/crates/hir-def/src/nameres/tests/mod_resolution.rs index 81bc0ff91e3a..1327d9aa62e1 100644 --- a/crates/hir-def/src/nameres/tests/mod_resolution.rs +++ b/crates/hir-def/src/nameres/tests/mod_resolution.rs @@ -80,18 +80,18 @@ pub trait Iterator; prelude: t crate::iter - Iterator: t + Iterator: ti traits: t crate::iter::traits - Iterator: t + Iterator: ti iterator: t crate::iter::traits::iterator Iterator: t crate::prelude - Iterator: t + Iterator: ti "#]], ); } @@ -109,7 +109,7 @@ pub struct Bar; "#, expect![[r#" crate - Bar: t v + Bar: ti vi foo: t crate::foo @@ -139,7 +139,7 @@ pub struct Baz; "#, expect![[r#" crate - Bar: t v + Bar: ti vi r#async: t crate::r#async @@ -176,8 +176,8 @@ pub struct Bar; "#, expect![[r#" crate - Bar: t v - Foo: t v + Bar: ti vi + Foo: ti vi r#async: t crate::r#async @@ -207,7 +207,7 @@ pub struct Bar; "#, expect![[r#" crate - Bar: t v + Bar: ti vi foo: t crate::foo @@ -236,7 +236,7 @@ pub struct Baz; foo: t crate::foo - Baz: t v + Baz: ti vi bar: t crate::foo::bar @@ -265,7 +265,7 @@ pub struct Baz; foo: t crate::foo - Baz: t v + Baz: ti vi bar: t crate::foo::bar @@ -292,7 +292,7 @@ use super::Baz; foo: t crate::foo - Baz: t v + Baz: ti vi "#]], ); } @@ -626,7 +626,7 @@ pub struct Baz; "#, expect![[r#" crate - Baz: t v + Baz: ti vi foo: t crate::foo @@ -660,7 +660,7 @@ pub struct Baz; foo: t crate::foo - Baz: t v + Baz: ti vi bar: t crate::foo::bar @@ -694,7 +694,7 @@ pub struct Baz; foo: t crate::foo - Baz: t v + Baz: ti vi bar: t crate::foo::bar @@ -728,7 +728,7 @@ pub struct Baz; foo: t crate::foo - Baz: t v + Baz: ti vi bar: t crate::foo::bar @@ -868,7 +868,7 @@ pub mod hash { pub trait Hash {} } "#, expect![[r#" crate - Hash: t + Hash: ti core: t crate::core diff --git a/crates/hir-def/src/nameres/tests/primitives.rs b/crates/hir-def/src/nameres/tests/primitives.rs index 215e8952d902..271eb1c79b12 100644 --- a/crates/hir-def/src/nameres/tests/primitives.rs +++ b/crates/hir-def/src/nameres/tests/primitives.rs @@ -14,10 +14,10 @@ pub use i32 as int; expect![[r#" crate foo: t - int: t + int: ti crate::foo - int: t + int: ti "#]], ); } From a17d73ad36baaec68078fe8b44c0b43e94a8e46a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 17 Aug 2023 10:52:13 +0200 Subject: [PATCH 080/197] Thread imports through the resolver --- crates/hir-def/src/item_scope.rs | 60 ++++++--- .../hir-def/src/macro_expansion_tests/mod.rs | 2 +- crates/hir-def/src/nameres/collector.rs | 13 +- crates/hir-def/src/nameres/path_resolution.rs | 76 +++++++----- crates/hir-def/src/per_ns.rs | 37 ++++-- crates/hir-def/src/resolver.rs | 116 +++++++++++------- crates/hir-ty/src/diagnostics/unsafe_check.rs | 2 +- crates/hir-ty/src/infer.rs | 8 +- crates/hir-ty/src/infer/closure.rs | 2 +- crates/hir-ty/src/infer/path.rs | 4 +- crates/hir-ty/src/lower.rs | 12 +- crates/hir-ty/src/mir/lower.rs | 4 +- .../hir-ty/src/mir/lower/pattern_matching.rs | 2 +- crates/hir/src/semantics.rs | 2 +- crates/hir/src/source_analyzer.rs | 9 +- 15 files changed, 218 insertions(+), 131 deletions(-) diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs index 59a1c5f49e24..0baf3fa7f444 100644 --- a/crates/hir-def/src/item_scope.rs +++ b/crates/hir-def/src/item_scope.rs @@ -34,7 +34,7 @@ pub enum ImportOrExternCrate { } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum ImportType { +pub(crate) enum ImportType { Import(ImportId), Glob(UseId), ExternCrate(ExternCrateId), @@ -118,7 +118,7 @@ struct DeriveMacroInvocation { pub(crate) static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { BuiltinType::ALL .iter() - .map(|(name, ty)| (name.clone(), PerNs::types((*ty).into(), Visibility::Public))) + .map(|(name, ty)| (name.clone(), PerNs::types((*ty).into(), Visibility::Public, None))) .collect() }); @@ -234,9 +234,16 @@ impl ItemScope { pub(crate) fn resolutions(&self) -> impl Iterator, PerNs)> + '_ { self.entries().map(|(name, res)| (Some(name.clone()), res)).chain( - self.unnamed_trait_imports - .iter() - .map(|(tr, (vis, _))| (None, PerNs::types(ModuleDefId::TraitId(*tr), *vis))), + self.unnamed_trait_imports.iter().map(|(tr, (vis, i))| { + ( + None, + PerNs::types( + ModuleDefId::TraitId(*tr), + *vis, + i.map(ImportOrExternCrate::Import), + ), + ) + }), ) } } @@ -327,11 +334,13 @@ impl ItemScope { }) } + // FIXME: This is only used in collection, we should move the relevant parts of it out of ItemScope pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option { self.unnamed_trait_imports.get(&tr).copied().map(|(a, _)| a) } pub(crate) fn push_unnamed_trait(&mut self, tr: TraitId, vis: Visibility) { + // FIXME: import self.unnamed_trait_imports.insert(tr, (vis, None)); } @@ -344,6 +353,8 @@ impl ItemScope { ) -> bool { let mut changed = false; + // FIXME: Document and simplify this + if let Some(mut fld) = def.types { let existing = self.types.entry(lookup.1.clone()); match existing { @@ -626,28 +637,39 @@ impl ItemScope { } impl PerNs { - pub(crate) fn from_def(def: ModuleDefId, v: Visibility, has_constructor: bool) -> PerNs { + pub(crate) fn from_def( + def: ModuleDefId, + v: Visibility, + has_constructor: bool, + import: Option, + ) -> PerNs { match def { - ModuleDefId::ModuleId(_) => PerNs::types(def, v), - ModuleDefId::FunctionId(_) => PerNs::values(def, v), + ModuleDefId::ModuleId(_) => PerNs::types(def, v, import), + ModuleDefId::FunctionId(_) => { + PerNs::values(def, v, import.and_then(ImportOrExternCrate::into_import)) + } ModuleDefId::AdtId(adt) => match adt { - AdtId::UnionId(_) => PerNs::types(def, v), - AdtId::EnumId(_) => PerNs::types(def, v), + AdtId::UnionId(_) => PerNs::types(def, v, import), + AdtId::EnumId(_) => PerNs::types(def, v, import), AdtId::StructId(_) => { if has_constructor { - PerNs::both(def, def, v) + PerNs::both(def, def, v, import) } else { - PerNs::types(def, v) + PerNs::types(def, v, import) } } }, - ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v), - ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def, v), - ModuleDefId::TraitId(_) => PerNs::types(def, v), - ModuleDefId::TraitAliasId(_) => PerNs::types(def, v), - ModuleDefId::TypeAliasId(_) => PerNs::types(def, v), - ModuleDefId::BuiltinType(_) => PerNs::types(def, v), - ModuleDefId::MacroId(mac) => PerNs::macros(mac, v), + ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v, import), + ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => { + PerNs::values(def, v, import.and_then(ImportOrExternCrate::into_import)) + } + ModuleDefId::TraitId(_) => PerNs::types(def, v, import), + ModuleDefId::TraitAliasId(_) => PerNs::types(def, v, import), + ModuleDefId::TypeAliasId(_) => PerNs::types(def, v, import), + ModuleDefId::BuiltinType(_) => PerNs::types(def, v, import), + ModuleDefId::MacroId(mac) => { + PerNs::macros(mac, v, import.and_then(ImportOrExternCrate::into_import)) + } } } } diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs index 7a87e61c6939..8adced4e0824 100644 --- a/crates/hir-def/src/macro_expansion_tests/mod.rs +++ b/crates/hir-def/src/macro_expansion_tests/mod.rs @@ -131,7 +131,7 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream .as_call_id_with_errors(&db, krate, |path| { resolver .resolve_path_as_macro(&db, &path, Some(MacroSubNs::Bang)) - .map(|it| macro_id_to_def_id(&db, it)) + .map(|(it, _)| macro_id_to_def_id(&db, it)) }) .unwrap(); let macro_call_id = res.value.unwrap(); diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 48eaec0f4e54..e9e71a8747f8 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -648,7 +648,7 @@ impl DefCollector<'_> { self.def_map.modules[module_id].scope.declare(macro_.into()); self.update( module_id, - &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))], + &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))], Visibility::Public, None, ); @@ -684,7 +684,7 @@ impl DefCollector<'_> { self.def_map.modules[module_id].scope.declare(macro_.into()); self.update( module_id, - &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))], + &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))], vis, None, ); @@ -699,7 +699,7 @@ impl DefCollector<'_> { self.def_map.modules[module_id].scope.declare(macro_.into()); self.update( module_id, - &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))], + &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))], Visibility::Public, None, ); @@ -783,6 +783,7 @@ impl DefCollector<'_> { Some(res) => PartialResolvedImport::Resolved(PerNs::types( res.into(), Visibility::Public, + None, )), None => PartialResolvedImport::Unresolved, } @@ -967,7 +968,7 @@ impl DefCollector<'_> { .map(|(local_id, variant_data)| { let name = variant_data.name.clone(); let variant = EnumVariantId { parent: e, local_id }; - let res = PerNs::both(variant.into(), variant.into(), vis); + let res = PerNs::both(variant.into(), variant.into(), vis, None); (Some(name), res) }) .collect::>(); @@ -1547,7 +1548,7 @@ impl ModCollector<'_, '_> { def_collector.def_map.modules[module_id].scope.declare(id); def_collector.update( module_id, - &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))], + &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor, None))], vis, None, ) @@ -1977,7 +1978,7 @@ impl ModCollector<'_, '_> { def_map.modules[self.module_id].scope.declare(def); self.def_collector.update( self.module_id, - &[(Some(name), PerNs::from_def(def, vis, false))], + &[(Some(name), PerNs::from_def(def, vis, false, None))], vis, None, ); diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index fc296e1e588f..460a908b6db2 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -15,8 +15,9 @@ use hir_expand::name::Name; use triomphe::Arc; use crate::{ + data::adt::VariantData, db::DefDatabase, - item_scope::BUILTIN_SCOPE, + item_scope::{ImportOrExternCrate, BUILTIN_SCOPE}, nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs}, path::{ModPath, PathKind}, per_ns::PerNs, @@ -196,15 +197,15 @@ impl DefMap { PathKind::DollarCrate(krate) => { if krate == self.krate { cov_mark::hit!(macro_dollar_crate_self); - PerNs::types(self.crate_root().into(), Visibility::Public) + PerNs::types(self.crate_root().into(), Visibility::Public, None) } else { let def_map = db.crate_def_map(krate); let module = def_map.module_id(Self::ROOT); cov_mark::hit!(macro_dollar_crate_other); - PerNs::types(module.into(), Visibility::Public) + PerNs::types(module.into(), Visibility::Public, None) } } - PathKind::Crate => PerNs::types(self.crate_root().into(), Visibility::Public), + PathKind::Crate => PerNs::types(self.crate_root().into(), Visibility::Public, None), // plain import or absolute path in 2015: crate-relative with // fallback to extern prelude (with the simplification in // rust-lang/rust#57745) @@ -291,7 +292,7 @@ impl DefMap { ); } - PerNs::types(module.into(), Visibility::Public) + PerNs::types(module.into(), Visibility::Public, None) } PathKind::Abs => { // 2018-style absolute path -- only extern prelude @@ -299,9 +300,13 @@ impl DefMap { Some((_, segment)) => segment, None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), }; - if let Some(&(def, _extern_crate)) = self.data.extern_prelude.get(segment) { + if let Some(&(def, extern_crate)) = self.data.extern_prelude.get(segment) { tracing::debug!("absolute path {:?} resolved to crate {:?}", path, def); - PerNs::types(def.into(), Visibility::Public) + PerNs::types( + def.into(), + Visibility::Public, + extern_crate.map(ImportOrExternCrate::ExternCrate), + ) } else { return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude } @@ -309,7 +314,7 @@ impl DefMap { }; for (i, segment) in segments { - let (curr, vis) = match curr_per_ns.take_types_vis() { + let (curr, vis, imp) = match curr_per_ns.take_types_full() { Some(r) => r, None => { // we still have path segments left, but the path so far @@ -364,18 +369,20 @@ impl DefMap { Some(local_id) => { let variant = EnumVariantId { parent: e, local_id }; match &*enum_data.variants[local_id].variant_data { - crate::data::adt::VariantData::Record(_) => { - PerNs::types(variant.into(), Visibility::Public) - } - crate::data::adt::VariantData::Tuple(_) - | crate::data::adt::VariantData::Unit => { - PerNs::both(variant.into(), variant.into(), Visibility::Public) + VariantData::Record(_) => { + PerNs::types(variant.into(), Visibility::Public, None) } + VariantData::Tuple(_) | VariantData::Unit => PerNs::both( + variant.into(), + variant.into(), + Visibility::Public, + None, + ), } } None => { return ResolvePathResult::with( - PerNs::types(e.into(), vis), + PerNs::types(e.into(), vis, imp), ReachedFixedPoint::Yes, Some(i), Some(self.krate), @@ -393,7 +400,7 @@ impl DefMap { ); return ResolvePathResult::with( - PerNs::types(s, vis), + PerNs::types(s, vis, imp), ReachedFixedPoint::Yes, Some(i), Some(self.krate), @@ -430,7 +437,7 @@ impl DefMap { .filter(|&id| { sub_namespace_match(Some(MacroSubNs::from_id(db, id)), expected_macro_subns) }) - .map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public)); + .map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public, None)); let from_scope = self[module].scope.get(name).filter_macro(db, expected_macro_subns); let from_builtin = match self.block { Some(_) => { @@ -449,16 +456,26 @@ impl DefMap { let extern_prelude = || { if self.block.is_some() { - // Don't resolve extern prelude in block `DefMap`s. + // Don't resolve extern prelude in block `DefMap`s, defer it to the crate def map so + // that blocks can properly shadow them return PerNs::none(); } - self.data.extern_prelude.get(name).map_or(PerNs::none(), |&(it, _extern_crate)| { - PerNs::types(it.into(), Visibility::Public) + self.data.extern_prelude.get(name).map_or(PerNs::none(), |&(it, extern_crate)| { + PerNs::types( + it.into(), + Visibility::Public, + extern_crate.map(ImportOrExternCrate::ExternCrate), + ) }) }; let macro_use_prelude = || { self.macro_use_prelude.get(name).map_or(PerNs::none(), |&(it, _extern_crate)| { - PerNs::macros(it.into(), Visibility::Public) + PerNs::macros( + it.into(), + Visibility::Public, + // FIXME? + None, // extern_crate.map(ImportOrExternCrate::ExternCrate), + ) }) }; let prelude = || self.resolve_in_prelude(db, name); @@ -487,13 +504,16 @@ impl DefMap { // Don't resolve extern prelude in block `DefMap`s. return PerNs::none(); } - self.data - .extern_prelude - .get(name) - .copied() - .map_or(PerNs::none(), |(it, _extern_crate)| { - PerNs::types(it.into(), Visibility::Public) - }) + self.data.extern_prelude.get(name).copied().map_or( + PerNs::none(), + |(it, extern_crate)| { + PerNs::types( + it.into(), + Visibility::Public, + extern_crate.map(ImportOrExternCrate::ExternCrate), + ) + }, + ) }; from_crate_root.or_else(from_extern_prelude) diff --git a/crates/hir-def/src/per_ns.rs b/crates/hir-def/src/per_ns.rs index f32a97d1a3a2..3f3f9f424919 100644 --- a/crates/hir-def/src/per_ns.rs +++ b/crates/hir-def/src/per_ns.rs @@ -27,20 +27,29 @@ impl PerNs { PerNs { types: None, values: None, macros: None } } - pub fn values(t: ModuleDefId, v: Visibility) -> PerNs { - PerNs { types: None, values: Some((t, v, None)), macros: None } + pub fn values(t: ModuleDefId, v: Visibility, i: Option) -> PerNs { + PerNs { types: None, values: Some((t, v, i)), macros: None } } - pub fn types(t: ModuleDefId, v: Visibility) -> PerNs { - PerNs { types: Some((t, v, None)), values: None, macros: None } + pub fn types(t: ModuleDefId, v: Visibility, i: Option) -> PerNs { + PerNs { types: Some((t, v, i)), values: None, macros: None } } - pub fn both(types: ModuleDefId, values: ModuleDefId, v: Visibility) -> PerNs { - PerNs { types: Some((types, v, None)), values: Some((values, v, None)), macros: None } + pub fn both( + types: ModuleDefId, + values: ModuleDefId, + v: Visibility, + i: Option, + ) -> PerNs { + PerNs { + types: Some((types, v, i)), + values: Some((values, v, i.and_then(ImportOrExternCrate::into_import))), + macros: None, + } } - pub fn macros(macro_: MacroId, v: Visibility) -> PerNs { - PerNs { types: None, values: None, macros: Some((macro_, v, None)) } + pub fn macros(macro_: MacroId, v: Visibility, i: Option) -> PerNs { + PerNs { types: None, values: None, macros: Some((macro_, v, i)) } } pub fn is_none(&self) -> bool { @@ -55,18 +64,26 @@ impl PerNs { self.types.map(|it| it.0) } - pub fn take_types_vis(self) -> Option<(ModuleDefId, Visibility)> { - self.types.map(|(a, b, _)| (a, b)) + pub fn take_types_full(self) -> Option<(ModuleDefId, Visibility, Option)> { + self.types } pub fn take_values(self) -> Option { self.values.map(|it| it.0) } + pub fn take_values_import(self) -> Option<(ModuleDefId, Option)> { + self.values.map(|it| (it.0, it.2)) + } + pub fn take_macros(self) -> Option { self.macros.map(|it| it.0) } + pub fn take_macros_import(self) -> Option<(MacroId, Option)> { + self.macros.map(|it| (it.0, it.2)) + } + pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs { let _p = profile::span("PerNs::filter_visibility"); PerNs { diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 28ab0f8f6eeb..62576100ea44 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -15,7 +15,7 @@ use crate::{ db::DefDatabase, generics::{GenericParams, TypeOrConstParamData}, hir::{BindingId, ExprId, LabelId}, - item_scope::{BuiltinShadowMode, BUILTIN_SCOPE}, + item_scope::{BuiltinShadowMode, ImportId, ImportOrExternCrate, BUILTIN_SCOPE}, lang_item::LangItemTarget, nameres::{DefMap, MacroSubNs}, path::{ModPath, Path, PathKind}, @@ -100,8 +100,8 @@ pub enum TypeNs { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ResolveValueResult { - ValueNs(ValueNs), - Partial(TypeNs, usize), + ValueNs(ValueNs, Option), + Partial(TypeNs, usize, Option), } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -152,7 +152,7 @@ impl Resolver { &self, db: &dyn DefDatabase, path: &Path, - ) -> Option<(TypeNs, Option)> { + ) -> Option<(TypeNs, Option, Option)> { let path = match path { Path::Normal { mod_path, .. } => mod_path, Path::LangItem(l) => { @@ -169,6 +169,7 @@ impl Resolver { | LangItemTarget::Static(_) => return None, }, None, + None, )) } }; @@ -185,17 +186,17 @@ impl Resolver { Scope::ExprScope(_) => continue, Scope::GenericParams { params, def } => { if let Some(id) = params.find_type_by_name(first_name, *def) { - return Some((TypeNs::GenericParam(id), remaining_idx())); + return Some((TypeNs::GenericParam(id), remaining_idx(), None)); } } &Scope::ImplDefScope(impl_) => { if first_name == &name![Self] { - return Some((TypeNs::SelfType(impl_), remaining_idx())); + return Some((TypeNs::SelfType(impl_), remaining_idx(), None)); } } &Scope::AdtScope(adt) => { if first_name == &name![Self] { - return Some((TypeNs::AdtSelfType(adt), remaining_idx())); + return Some((TypeNs::AdtSelfType(adt), remaining_idx(), None)); } } Scope::BlockScope(m) => { @@ -208,12 +209,24 @@ impl Resolver { self.module_scope.resolve_path_in_type_ns(db, path) } + pub fn resolve_path_in_type_ns_fully_with_imports( + &self, + db: &dyn DefDatabase, + path: &Path, + ) -> Option<(TypeNs, Option)> { + let (res, unresolved, imp) = self.resolve_path_in_type_ns(db, path)?; + if unresolved.is_some() { + return None; + } + Some((res, imp)) + } + pub fn resolve_path_in_type_ns_fully( &self, db: &dyn DefDatabase, path: &Path, ) -> Option { - let (res, unresolved) = self.resolve_path_in_type_ns(db, path)?; + let (res, unresolved, _) = self.resolve_path_in_type_ns(db, path)?; if unresolved.is_some() { return None; } @@ -235,7 +248,6 @@ impl Resolver { RawVisibility::Public => Some(Visibility::Public), } } - pub fn resolve_path_in_value_ns( &self, db: &dyn DefDatabase, @@ -244,17 +256,20 @@ impl Resolver { let path = match path { Path::Normal { mod_path, .. } => mod_path, Path::LangItem(l) => { - return Some(ResolveValueResult::ValueNs(match *l { - LangItemTarget::Function(it) => ValueNs::FunctionId(it), - LangItemTarget::Static(it) => ValueNs::StaticId(it), - LangItemTarget::Struct(it) => ValueNs::StructId(it), - LangItemTarget::EnumVariant(it) => ValueNs::EnumVariantId(it), - LangItemTarget::Union(_) - | LangItemTarget::ImplDef(_) - | LangItemTarget::TypeAlias(_) - | LangItemTarget::Trait(_) - | LangItemTarget::EnumId(_) => return None, - })) + return Some(ResolveValueResult::ValueNs( + match *l { + LangItemTarget::Function(it) => ValueNs::FunctionId(it), + LangItemTarget::Static(it) => ValueNs::StaticId(it), + LangItemTarget::Struct(it) => ValueNs::StructId(it), + LangItemTarget::EnumVariant(it) => ValueNs::EnumVariantId(it), + LangItemTarget::Union(_) + | LangItemTarget::ImplDef(_) + | LangItemTarget::TypeAlias(_) + | LangItemTarget::Trait(_) + | LangItemTarget::EnumId(_) => return None, + }, + None, + )) } }; let n_segments = path.segments().len(); @@ -276,20 +291,24 @@ impl Resolver { .find(|entry| entry.name() == first_name); if let Some(e) = entry { - return Some(ResolveValueResult::ValueNs(ValueNs::LocalBinding( - e.binding(), - ))); + return Some(ResolveValueResult::ValueNs( + ValueNs::LocalBinding(e.binding()), + None, + )); } } Scope::GenericParams { params, def } => { if let Some(id) = params.find_const_by_name(first_name, *def) { let val = ValueNs::GenericParam(id); - return Some(ResolveValueResult::ValueNs(val)); + return Some(ResolveValueResult::ValueNs(val, None)); } } &Scope::ImplDefScope(impl_) => { if first_name == &name![Self] { - return Some(ResolveValueResult::ValueNs(ValueNs::ImplSelf(impl_))); + return Some(ResolveValueResult::ValueNs( + ValueNs::ImplSelf(impl_), + None, + )); } } // bare `Self` doesn't work in the value namespace in a struct/enum definition @@ -308,18 +327,22 @@ impl Resolver { Scope::GenericParams { params, def } => { if let Some(id) = params.find_type_by_name(first_name, *def) { let ty = TypeNs::GenericParam(id); - return Some(ResolveValueResult::Partial(ty, 1)); + return Some(ResolveValueResult::Partial(ty, 1, None)); } } &Scope::ImplDefScope(impl_) => { if first_name == &name![Self] { - return Some(ResolveValueResult::Partial(TypeNs::SelfType(impl_), 1)); + return Some(ResolveValueResult::Partial( + TypeNs::SelfType(impl_), + 1, + None, + )); } } Scope::AdtScope(adt) => { if first_name == &name![Self] { let ty = TypeNs::AdtSelfType(*adt); - return Some(ResolveValueResult::Partial(ty, 1)); + return Some(ResolveValueResult::Partial(ty, 1, None)); } } Scope::BlockScope(m) => { @@ -340,7 +363,7 @@ impl Resolver { // `use core::u16;`. if path.kind == PathKind::Plain && n_segments > 1 { if let Some(builtin) = BuiltinType::by_name(first_name) { - return Some(ResolveValueResult::Partial(TypeNs::BuiltinType(builtin), 1)); + return Some(ResolveValueResult::Partial(TypeNs::BuiltinType(builtin), 1, None)); } } @@ -353,7 +376,7 @@ impl Resolver { path: &Path, ) -> Option { match self.resolve_path_in_value_ns(db, path)? { - ResolveValueResult::ValueNs(it) => Some(it), + ResolveValueResult::ValueNs(it, _) => Some(it), ResolveValueResult::Partial(..) => None, } } @@ -363,12 +386,12 @@ impl Resolver { db: &dyn DefDatabase, path: &ModPath, expected_macro_kind: Option, - ) -> Option { + ) -> Option<(MacroId, Option)> { let (item_map, module) = self.item_scope(); item_map .resolve_path(db, module, path, BuiltinShadowMode::Other, expected_macro_kind) .0 - .take_macros() + .take_macros_import() } /// Returns a set of names available in the current scope. @@ -776,11 +799,12 @@ impl ModuleItemMap { self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other); match idx { None => { - let value = to_value_ns(module_def)?; - Some(ResolveValueResult::ValueNs(value)) + let (value, import) = to_value_ns(module_def)?; + Some(ResolveValueResult::ValueNs(value, import)) } Some(idx) => { - let ty = match module_def.take_types()? { + let (def, _, import) = module_def.take_types_full()?; + let ty = match def { ModuleDefId::AdtId(it) => TypeNs::AdtId(it), ModuleDefId::TraitId(it) => TypeNs::TraitId(it), ModuleDefId::TraitAliasId(it) => TypeNs::TraitAliasId(it), @@ -794,7 +818,7 @@ impl ModuleItemMap { | ModuleDefId::MacroId(_) | ModuleDefId::StaticId(_) => return None, }; - Some(ResolveValueResult::Partial(ty, idx)) + Some(ResolveValueResult::Partial(ty, idx, import)) } } } @@ -803,16 +827,17 @@ impl ModuleItemMap { &self, db: &dyn DefDatabase, path: &ModPath, - ) -> Option<(TypeNs, Option)> { + ) -> Option<(TypeNs, Option, Option)> { let (module_def, idx) = self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other); - let res = to_type_ns(module_def)?; - Some((res, idx)) + let (res, import) = to_type_ns(module_def)?; + Some((res, idx, import)) } } -fn to_value_ns(per_ns: PerNs) -> Option { - let res = match per_ns.take_values()? { +fn to_value_ns(per_ns: PerNs) -> Option<(ValueNs, Option)> { + let (def, import) = per_ns.take_values_import()?; + let res = match def { ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it), ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it), ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it), @@ -827,11 +852,12 @@ fn to_value_ns(per_ns: PerNs) -> Option { | ModuleDefId::MacroId(_) | ModuleDefId::ModuleId(_) => return None, }; - Some(res) + Some((res, import)) } -fn to_type_ns(per_ns: PerNs) -> Option { - let res = match per_ns.take_types()? { +fn to_type_ns(per_ns: PerNs) -> Option<(TypeNs, Option)> { + let (def, _, import) = per_ns.take_types_full()?; + let res = match def { ModuleDefId::AdtId(it) => TypeNs::AdtId(it), ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it), @@ -847,7 +873,7 @@ fn to_type_ns(per_ns: PerNs) -> Option { | ModuleDefId::StaticId(_) | ModuleDefId::ModuleId(_) => return None, }; - Some(res) + Some((res, import)) } type FxIndexMap = IndexMap>; diff --git a/crates/hir-ty/src/diagnostics/unsafe_check.rs b/crates/hir-ty/src/diagnostics/unsafe_check.rs index 9f9a56ffab06..cbca0e801d4d 100644 --- a/crates/hir-ty/src/diagnostics/unsafe_check.rs +++ b/crates/hir-ty/src/diagnostics/unsafe_check.rs @@ -75,7 +75,7 @@ fn walk_unsafe( Expr::Path(path) => { let resolver = resolver_for_expr(db.upcast(), def, current); let value_or_partial = resolver.resolve_path_in_value_ns(db.upcast(), path); - if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id))) = value_or_partial { + if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id), _)) = value_or_partial { if db.static_data(id).mutable { unsafe_expr_cb(UnsafeExpr { expr: current, inside_unsafe_block }); } diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index b4915dbf0f99..0fb4934444b4 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -1017,7 +1017,7 @@ impl<'a> InferenceContext<'a> { let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into()); let (resolution, unresolved) = if value_ns { match self.resolver.resolve_path_in_value_ns(self.db.upcast(), path) { - Some(ResolveValueResult::ValueNs(value)) => match value { + Some(ResolveValueResult::ValueNs(value, _)) => match value { ValueNs::EnumVariantId(var) => { let substs = ctx.substs_from_path(path, var.into(), true); let ty = self.db.ty(var.parent.into()); @@ -1033,12 +1033,14 @@ impl<'a> InferenceContext<'a> { ValueNs::ImplSelf(impl_id) => (TypeNs::SelfType(impl_id), None), _ => return (self.err_ty(), None), }, - Some(ResolveValueResult::Partial(typens, unresolved)) => (typens, Some(unresolved)), + Some(ResolveValueResult::Partial(typens, unresolved, _)) => { + (typens, Some(unresolved)) + } None => return (self.err_ty(), None), } } else { match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) { - Some(it) => it, + Some((it, idx, _)) => (it, idx), None => return (self.err_ty(), None), } }; diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index 1781f6c58f1c..23efe616f4f6 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -322,7 +322,7 @@ impl InferenceContext<'_> { Expr::Path(p) => { let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); if let Some(r) = resolver.resolve_path_in_value_ns(self.db.upcast(), p) { - if let ResolveValueResult::ValueNs(v) = r { + if let ResolveValueResult::ValueNs(v, _) = r { if let ValueNs::LocalBinding(b) = v { return Some(HirPlace { local: b, projections: vec![] }); } diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs index 79d9e21e797c..2a51c84db3aa 100644 --- a/crates/hir-ty/src/infer/path.rs +++ b/crates/hir-ty/src/infer/path.rs @@ -61,8 +61,8 @@ impl InferenceContext<'_> { self.resolver.resolve_path_in_value_ns(self.db.upcast(), path)?; match value_or_partial { - ResolveValueResult::ValueNs(it) => (it, None), - ResolveValueResult::Partial(def, remaining_index) => self + ResolveValueResult::ValueNs(it, _) => (it, None), + ResolveValueResult::Partial(def, remaining_index, _) => self .resolve_assoc_item(def, path, remaining_index, id) .map(|(it, substs)| (it, Some(substs)))?, } diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 20dccfafb385..0ab04b83cf83 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -390,11 +390,9 @@ impl<'a> TyLoweringContext<'a> { let ty = { let macro_call = macro_call.to_node(self.db.upcast()); let resolver = |path| { - self.resolver.resolve_path_as_macro( - self.db.upcast(), - &path, - Some(MacroSubNs::Bang), - ) + self.resolver + .resolve_path_as_macro(self.db.upcast(), &path, Some(MacroSubNs::Bang)) + .map(|(it, _)| it) }; match expander.enter_expand::(self.db.upcast(), macro_call, resolver) { @@ -446,7 +444,7 @@ impl<'a> TyLoweringContext<'a> { return None; } let resolution = match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) { - Some((it, None)) => it, + Some((it, None, _)) => it, _ => return None, }; match resolution { @@ -626,7 +624,7 @@ impl<'a> TyLoweringContext<'a> { return self.lower_ty_relative_path(ty, res, path.segments()); } - let (resolution, remaining_index) = + let (resolution, remaining_index, _) = match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) { Some(it) => it, None => return (TyKind::Error.intern(Interner), None), diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 7ab0c1f7f2f8..51cf882d0539 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -1352,14 +1352,14 @@ impl<'ctx> MirLowerCtx<'ctx> { .resolve_path_in_value_ns(self.db.upcast(), c) .ok_or_else(unresolved_name)?; match pr { - ResolveValueResult::ValueNs(v) => { + ResolveValueResult::ValueNs(v, _) => { if let ValueNs::ConstId(c) = v { self.lower_const_to_operand(Substitution::empty(Interner), c.into(), ty) } else { not_supported!("bad path in range pattern"); } } - ResolveValueResult::Partial(_, _) => { + ResolveValueResult::Partial(_, _, _) => { not_supported!("associated constants in range pattern") } } diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs index 3354cbd76a0a..1cdfd9197422 100644 --- a/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -323,7 +323,7 @@ impl MirLowerCtx<'_> { break 'b (c, x.1); } } - if let ResolveValueResult::ValueNs(v) = pr { + if let ResolveValueResult::ValueNs(v, _) = pr { if let ValueNs::ConstId(c) = v { break 'b (c, Substitution::empty(Interner)); } diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index e99d2984c367..55760ba75abc 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -606,7 +606,7 @@ impl<'db> SemanticsImpl<'db> { let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| { resolver .resolve_path_as_macro(self.db.upcast(), &path, Some(MacroSubNs::Bang)) - .map(|it| macro_id_to_def_id(self.db.upcast(), it)) + .map(|(it, _)| macro_id_to_def_id(self.db.upcast(), it)) })?; hir_expand::db::expand_speculative( self.db.upcast(), diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 3499daf11403..f29fb1edf00b 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -487,7 +487,7 @@ impl SourceAnalyzer { let path = macro_call.value.path().and_then(|ast| Path::from_src(ast, &ctx))?; self.resolver .resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Bang)) - .map(|it| it.into()) + .map(|(it, _)| it.into()) } pub(crate) fn resolve_bind_pat_to_const( @@ -760,7 +760,7 @@ impl SourceAnalyzer { let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| { self.resolver .resolve_path_as_macro(db.upcast(), &path, Some(MacroSubNs::Bang)) - .map(|it| macro_id_to_def_id(db.upcast(), it)) + .map(|(it, _)| macro_id_to_def_id(db.upcast(), it)) })?; Some(macro_call_id.as_file()).filter(|it| it.expansion_level(db.upcast()) < 64) } @@ -966,6 +966,7 @@ pub(crate) fn resolve_hir_path_as_attr_macro( ) -> Option { resolver .resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Attr)) + .map(|(it, _)| it) .map(Into::into) } @@ -983,7 +984,7 @@ fn resolve_hir_path_( res.map(|ty_ns| (ty_ns, path.segments().first())) } None => { - let (ty, remaining_idx) = resolver.resolve_path_in_type_ns(db.upcast(), path)?; + let (ty, remaining_idx, _) = resolver.resolve_path_in_type_ns(db.upcast(), path)?; match remaining_idx { Some(remaining_idx) => { if remaining_idx + 1 == path.segments().len() { @@ -1067,7 +1068,7 @@ fn resolve_hir_path_( let macros = || { resolver .resolve_path_as_macro(db.upcast(), path.mod_path()?, None) - .map(|def| PathResolution::Def(ModuleDef::Macro(def.into()))) + .map(|(def, _)| PathResolution::Def(ModuleDef::Macro(def.into()))) }; if prefer_value_ns { values().or_else(types) } else { types().or_else(values) } From 637f496a814ec850e3a18064c648e0835f56c90c Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 17 Aug 2023 12:17:41 +0200 Subject: [PATCH 081/197] fix: Fix auto-import (and completions) importing `#[doc(hidden)]` items --- crates/hir-def/src/find_path.rs | 49 ++++++++++++++++++ crates/hir-def/src/import_map.rs | 27 ++++++++-- crates/hir-def/src/item_scope.rs | 11 ++-- crates/hir-def/src/lib.rs | 12 ++++- crates/hir-def/src/per_ns.rs | 16 ++++-- crates/hir/src/attrs.rs | 2 +- crates/ide-completion/src/tests/flyimport.rs | 54 ++++++++++++++++++++ 7 files changed, 155 insertions(+), 16 deletions(-) diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs index 234d3eaed566..b60e79091050 100644 --- a/crates/hir-def/src/find_path.rs +++ b/crates/hir-def/src/find_path.rs @@ -224,6 +224,7 @@ fn find_path_for_module( ) } +// FIXME: Do we still need this now that we record import origins, and hence aliases? fn find_in_scope( db: &dyn DefDatabase, def_map: &DefMap, @@ -346,6 +347,11 @@ fn calculate_best_path( let extern_paths = crate_graph[from.krate].dependencies.iter().filter_map(|dep| { let import_map = db.import_map(dep.crate_id); import_map.import_info_for(item).and_then(|info| { + if info.is_doc_hidden { + // the item or import is `#[doc(hidden)]`, so skip it as it is in an external crate + return None; + } + // Determine best path for containing module and append last segment from `info`. // FIXME: we should guide this to look up the path locally, or from the same crate again? let mut path = find_path_for_module( @@ -1311,4 +1317,47 @@ pub struct S; "intermediate::std_renamed::S", ); } + + #[test] + fn different_crate_doc_hidden() { + check_found_path( + r#" +//- /main.rs crate:main deps:intermediate +$0 +//- /intermediate.rs crate:intermediate deps:std +#[doc(hidden)] +pub extern crate std; +pub extern crate std as longer; +//- /std.rs crate:std +pub struct S; + "#, + "intermediate::longer::S", + "intermediate::longer::S", + "intermediate::longer::S", + "intermediate::longer::S", + ); + } + + #[test] + fn respect_doc_hidden() { + check_found_path( + r#" +//- /main.rs crate:main deps:std,lazy_static +$0 +//- /lazy_static.rs crate:lazy_static deps:core +#[doc(hidden)] +pub use core::ops::Deref as __Deref; +//- /std.rs crate:std deps:core +pub use core::ops; +//- /core.rs crate:core +pub mod ops { + pub trait Deref {} +} + "#, + "std::ops::Deref", + "std::ops::Deref", + "std::ops::Deref", + "std::ops::Deref", + ); + } } diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs index 5d7bb0b49d7e..c961d7d86d8c 100644 --- a/crates/hir-def/src/import_map.rs +++ b/crates/hir-def/src/import_map.rs @@ -11,6 +11,7 @@ use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet, FxHasher}; use triomphe::Arc; +use crate::item_scope::ImportOrExternCrate; use crate::{ db::DefDatabase, item_scope::ItemInNs, nameres::DefMap, visibility::Visibility, AssocItemId, ModuleDefId, ModuleId, TraitId, @@ -29,6 +30,8 @@ pub struct ImportInfo { pub container: ModuleId, /// Whether the import is a trait associated item or not. pub is_trait_assoc_item: bool, + /// Whether this item is annotated with `#[doc(hidden)]`. + pub is_doc_hidden: bool, } /// A map from publicly exported items to its name. @@ -113,14 +116,27 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> FxIndexMap Some(id.into()), + ImportOrExternCrate::Import(id) => Some(id.import.into()), + } + } else { + match item { + ItemInNs::Types(id) | ItemInNs::Values(id) => id.try_into().ok(), + ItemInNs::Macros(id) => Some(id.into()), + } + }; + let is_doc_hidden = + attr_id.map_or(false, |attr_id| db.attrs(attr_id).has_doc_hidden()); let import_info = ImportInfo { name: name.clone(), container: module, is_trait_assoc_item: false, + is_doc_hidden, }; match depth_map.entry(item) { @@ -171,10 +187,10 @@ fn collect_trait_assoc_items( trait_import_info: &ImportInfo, ) { let _p = profile::span("collect_trait_assoc_items"); - for (assoc_item_name, item) in &db.trait_data(tr).items { + for &(ref assoc_item_name, item) in &db.trait_data(tr).items { let module_def_id = match item { - AssocItemId::FunctionId(f) => ModuleDefId::from(*f), - AssocItemId::ConstId(c) => ModuleDefId::from(*c), + AssocItemId::FunctionId(f) => ModuleDefId::from(f), + AssocItemId::ConstId(c) => ModuleDefId::from(c), // cannot use associated type aliases directly: need a `::TypeAlias` // qualifier, ergo no need to store it for imports in import_map AssocItemId::TypeAliasId(_) => { @@ -192,6 +208,7 @@ fn collect_trait_assoc_items( container: trait_import_info.container, name: assoc_item_name.clone(), is_trait_assoc_item: true, + is_doc_hidden: db.attrs(item.into()).has_doc_hidden(), }; map.insert(assoc_item, assoc_item_info); } diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs index 0baf3fa7f444..699231fd3788 100644 --- a/crates/hir-def/src/item_scope.rs +++ b/crates/hir-def/src/item_scope.rs @@ -66,7 +66,8 @@ pub struct ItemScope { _c: Count, /// Defs visible in this scope. This includes `declarations`, but also - /// imports. + /// imports. The imports belong to this module and can be resolved by using them on + /// the `use_imports_*` fields. types: FxHashMap)>, values: FxHashMap)>, macros: FxHashMap)>, @@ -375,8 +376,8 @@ impl ItemScope { None | Some(ImportType::Glob(_)) => None, }; let prev = std::mem::replace(&mut fld.2, import); - if let Some(ImportOrExternCrate::Import(import)) = import { - self.use_imports_values.insert( + if let Some(import) = import { + self.use_imports_types.insert( import, match prev { Some(ImportOrExternCrate::Import(import)) => { @@ -404,8 +405,8 @@ impl ItemScope { None | Some(ImportType::Glob(_)) => None, }; let prev = std::mem::replace(&mut fld.2, import); - if let Some(ImportOrExternCrate::Import(import)) = import { - self.use_imports_values.insert( + if let Some(import) = import { + self.use_imports_types.insert( import, match prev { Some(ImportOrExternCrate::Import(import)) => { diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 3c0ed8c2e51a..3f87fe62b83c 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -870,7 +870,8 @@ impl_from!( MacroId(Macro2Id, MacroRulesId, ProcMacroId), ImplId, GenericParamId, - ExternCrateId + ExternCrateId, + UseId for AttrDefId ); @@ -904,6 +905,15 @@ impl From for AttrDefId { } } } +impl From for AttrDefId { + fn from(assoc: AssocItemId) -> Self { + match assoc { + AssocItemId::FunctionId(it) => AttrDefId::FunctionId(it), + AssocItemId::ConstId(it) => AttrDefId::ConstId(it), + AssocItemId::TypeAliasId(it) => AttrDefId::TypeAliasId(it), + } + } +} #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum VariantId { diff --git a/crates/hir-def/src/per_ns.rs b/crates/hir-def/src/per_ns.rs index 3f3f9f424919..da9c13740b35 100644 --- a/crates/hir-def/src/per_ns.rs +++ b/crates/hir-def/src/per_ns.rs @@ -117,12 +117,20 @@ impl PerNs { } } - pub fn iter_items(self) -> impl Iterator { + pub fn iter_items(self) -> impl Iterator)> { let _p = profile::span("PerNs::iter_items"); self.types - .map(|it| ItemInNs::Types(it.0)) + .map(|it| (ItemInNs::Types(it.0), it.2)) .into_iter() - .chain(self.values.map(|it| ItemInNs::Values(it.0)).into_iter()) - .chain(self.macros.map(|it| ItemInNs::Macros(it.0)).into_iter()) + .chain( + self.values + .map(|it| (ItemInNs::Values(it.0), it.2.map(ImportOrExternCrate::Import))) + .into_iter(), + ) + .chain( + self.macros + .map(|it| (ItemInNs::Macros(it.0), it.2.map(ImportOrExternCrate::Import))) + .into_iter(), + ) } } diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index cd0410168c23..364405f56a8e 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -212,7 +212,7 @@ fn resolve_doc_path( Some(Namespace::Types) => resolved.take_types(), Some(Namespace::Values) => resolved.take_values(), Some(Namespace::Macros) => resolved.take_macros().map(ModuleDefId::MacroId), - None => resolved.iter_items().next().map(|it| match it { + None => resolved.iter_items().next().map(|(it, _)| match it { ItemInNs::Types(it) => it, ItemInNs::Values(it) => it, ItemInNs::Macros(it) => ModuleDefId::MacroId(it), diff --git a/crates/ide-completion/src/tests/flyimport.rs b/crates/ide-completion/src/tests/flyimport.rs index 8c038c0fbaa1..4cdfd546f6ad 100644 --- a/crates/ide-completion/src/tests/flyimport.rs +++ b/crates/ide-completion/src/tests/flyimport.rs @@ -1286,3 +1286,57 @@ macro_rules! println { expect![""], ) } + +#[test] +fn no_completions_for_external_doc_hidden_in_path() { + check( + r#" +//- /main.rs crate:main deps:dep +fn main() { + Span$0 +} +//- /lib.rs crate:dep +#[doc(hidden)] +pub mod bridge { + pub mod server { + pub trait Span + } +} +pub mod bridge2 { + #[doc(hidden)] + pub mod server2 { + pub trait Span + } +} +"#, + expect![""], + ); + // unless re-exported + check( + r#" +//- /main.rs crate:main deps:dep +fn main() { + Span$0 +} +//- /lib.rs crate:dep +#[doc(hidden)] +pub mod bridge { + pub mod server { + pub trait Span + } +} +pub use bridge::server::Span; +pub mod bridge2 { + #[doc(hidden)] + pub mod server2 { + pub trait Span2 + } +} +pub use bridge2::server2::Span2; +"#, + expect![[r#" + tt Span (use dep::Span) + tt Span2 (use dep::Span2) + "#]], + ); +} From eb6244c5f91884a612c2fd16a2a5439237129f64 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 18 Aug 2023 11:46:35 +0200 Subject: [PATCH 082/197] Record import aliases in symbol index --- crates/hir-def/src/item_scope.rs | 74 ++++++- crates/hir-def/src/item_tree.rs | 13 ++ crates/hir-def/src/item_tree/lower.rs | 2 +- crates/hir-def/src/per_ns.rs | 7 + crates/hir-def/src/src.rs | 19 +- crates/hir/src/attrs.rs | 8 +- crates/hir/src/lib.rs | 3 +- crates/hir/src/symbols.rs | 40 +++- crates/ide-db/src/symbol_index.rs | 9 +- .../test_symbol_index_collection.txt | 203 ++++++++++++++++++ 10 files changed, 360 insertions(+), 18 deletions(-) diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs index 699231fd3788..7c11fb9d1367 100644 --- a/crates/hir-def/src/item_scope.rs +++ b/crates/hir-def/src/item_scope.rs @@ -16,8 +16,8 @@ use syntax::ast; use crate::{ db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ConstId, - ExternCrateId, HasModule, ImplId, LocalModuleId, MacroId, ModuleDefId, ModuleId, TraitId, - UseId, + ExternCrateId, HasModule, ImplId, LocalModuleId, Lookup, MacroId, ModuleDefId, ModuleId, + TraitId, UseId, }; #[derive(Debug, Default)] @@ -55,7 +55,7 @@ pub enum ImportOrDef { ExternCrate(ExternCrateId), Def(ModuleDefId), } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] pub struct ImportId { pub import: UseId, pub idx: Idx, @@ -142,11 +142,77 @@ impl ItemScope { .chain(self.values.keys()) .chain(self.macros.keys()) .chain(self.unresolved.iter()) - .sorted() .unique() + .sorted() .map(move |name| (name, self.get(name))) } + pub fn imports(&self) -> impl Iterator + '_ { + self.use_imports_types + .keys() + .copied() + .filter_map(ImportOrExternCrate::into_import) + .chain(self.use_imports_values.keys().copied()) + .chain(self.use_imports_macros.keys().copied()) + .unique() + .sorted() + } + + pub fn fully_resolve_import(&self, db: &dyn DefDatabase, mut import: ImportId) -> PerNs { + let mut res = PerNs::none(); + + let mut def_map; + let mut scope = self; + while let Some(&m) = scope.use_imports_macros.get(&import) { + match m { + ImportOrDef::Import(i) => { + let module_id = i.import.lookup(db).container; + def_map = module_id.def_map(db); + scope = &def_map[module_id.local_id].scope; + import = i; + } + ImportOrDef::Def(ModuleDefId::MacroId(def)) => { + res.macros = Some((def, Visibility::Public, None)); + break; + } + _ => break, + } + } + let mut scope = self; + while let Some(&m) = scope.use_imports_types.get(&ImportOrExternCrate::Import(import)) { + match m { + ImportOrDef::Import(i) => { + let module_id = i.import.lookup(db).container; + def_map = module_id.def_map(db); + scope = &def_map[module_id.local_id].scope; + import = i; + } + ImportOrDef::Def(def) => { + res.types = Some((def, Visibility::Public, None)); + break; + } + _ => break, + } + } + let mut scope = self; + while let Some(&m) = scope.use_imports_values.get(&import) { + match m { + ImportOrDef::Import(i) => { + let module_id = i.import.lookup(db).container; + def_map = module_id.def_map(db); + scope = &def_map[module_id.local_id].scope; + import = i; + } + ImportOrDef::Def(def) => { + res.values = Some((def, Visibility::Public, None)); + break; + } + _ => break, + } + } + res + } + pub fn declarations(&self) -> impl Iterator + '_ { self.declarations.iter().copied() } diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 957a5cf2e2bd..3e1922750b9a 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -773,6 +773,19 @@ impl Use { lower::lower_use_tree(db, &hygiene, ast_use_tree).expect("failed to lower use tree"); source_map[index].clone() } + /// Maps a `UseTree` contained in this import back to its AST node. + pub fn use_tree_source_map( + &self, + db: &dyn DefDatabase, + file_id: HirFileId, + ) -> Arena { + // Re-lower the AST item and get the source map. + // Note: The AST unwraps are fine, since if they fail we should have never obtained `index`. + let ast = InFile::new(file_id, self.ast_id).to_node(db.upcast()); + let ast_use_tree = ast.use_tree().expect("missing `use_tree`"); + let hygiene = Hygiene::new(db.upcast(), file_id); + lower::lower_use_tree(db, &hygiene, ast_use_tree).expect("failed to lower use tree").1 + } } #[derive(Clone, Copy, Debug, Eq, PartialEq)] diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index f8efc8022347..e4702c113b85 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -780,7 +780,7 @@ impl UseTreeLowering<'_> { } } -pub(super) fn lower_use_tree( +pub(crate) fn lower_use_tree( db: &dyn DefDatabase, hygiene: &Hygiene, tree: ast::UseTree, diff --git a/crates/hir-def/src/per_ns.rs b/crates/hir-def/src/per_ns.rs index da9c13740b35..14890364d0bd 100644 --- a/crates/hir-def/src/per_ns.rs +++ b/crates/hir-def/src/per_ns.rs @@ -9,6 +9,13 @@ use crate::{ MacroId, ModuleDefId, }; +#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)] +pub enum Namespace { + Types, + Values, + Macros, +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct PerNs { pub types: Option<(ModuleDefId, Visibility, Option)>, diff --git a/crates/hir-def/src/src.rs b/crates/hir-def/src/src.rs index 6047f770d4d3..3770103cda53 100644 --- a/crates/hir-def/src/src.rs +++ b/crates/hir-def/src/src.rs @@ -5,8 +5,8 @@ use la_arena::ArenaMap; use syntax::ast; use crate::{ - db::DefDatabase, item_tree::ItemTreeNode, AssocItemLoc, ItemLoc, Macro2Loc, MacroRulesLoc, - ProcMacroLoc, + db::DefDatabase, item_tree::ItemTreeNode, AssocItemLoc, ItemLoc, Lookup, Macro2Loc, + MacroRulesLoc, ProcMacroLoc, UseId, }; pub trait HasSource { @@ -83,3 +83,18 @@ pub trait HasChildSource { type Value; fn child_source(&self, db: &dyn DefDatabase) -> InFile>; } + +impl HasChildSource> for UseId { + type Value = ast::UseTree; + fn child_source( + &self, + db: &dyn DefDatabase, + ) -> InFile, Self::Value>> { + let loc = &self.lookup(db); + let use_ = &loc.id.item_tree(db)[loc.id.value]; + InFile::new( + loc.id.file_id(), + use_.use_tree_source_map(db, loc.id.file_id()).into_iter().collect(), + ) + } +} diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index 364405f56a8e..121e5a0a2493 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -4,6 +4,7 @@ use hir_def::{ attr::{AttrsWithOwner, Documentation}, item_scope::ItemInNs, path::{ModPath, Path}, + per_ns::Namespace, resolver::{HasResolver, Resolver, TypeNs}, AssocItemId, AttrDefId, GenericParamId, ModuleDefId, }; @@ -28,13 +29,6 @@ pub trait HasAttrs { ) -> Option; } -#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)] -pub enum Namespace { - Types, - Values, - Macros, -} - /// Subset of `ide_db::Definition` that doc links can resolve to. pub enum DocLinkDef { ModuleDef(ModuleDef), diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 583e26c136c0..512fe7e0428a 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -88,7 +88,7 @@ use triomphe::Arc; use crate::db::{DefDatabase, HirDatabase}; pub use crate::{ - attrs::{DocLinkDef, HasAttrs, Namespace}, + attrs::{DocLinkDef, HasAttrs}, diagnostics::{ AnyDiagnostic, BreakOutsideOfLoop, CaseType, ExpectedFunction, InactiveCode, IncoherentImpl, IncorrectCase, InvalidDeriveTarget, MacroDefError, MacroError, @@ -122,6 +122,7 @@ pub use { lang_item::LangItem, nameres::{DefMap, ModuleSource}, path::{ModPath, PathKind}, + per_ns::Namespace, type_ref::{Mutability, TypeRef}, visibility::Visibility, // FIXME: This is here since some queries take it as input that are used diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs index 43d957412bc8..ca7874c3683c 100644 --- a/crates/hir/src/symbols.rs +++ b/crates/hir/src/symbols.rs @@ -2,8 +2,10 @@ use base_db::FileRange; use hir_def::{ - src::HasSource, AdtId, AssocItemId, DefWithBodyId, HasModule, ImplId, Lookup, MacroId, - ModuleDefId, ModuleId, TraitId, + item_scope::ItemInNs, + src::{HasChildSource, HasSource}, + AdtId, AssocItemId, DefWithBodyId, HasModule, ImplId, Lookup, MacroId, ModuleDefId, ModuleId, + TraitId, }; use hir_expand::{HirFileId, InFile}; use hir_ty::db::HirDatabase; @@ -167,6 +169,40 @@ impl<'a> SymbolCollector<'a> { self.collect_from_impl(impl_id); } + // Record renamed imports. + // In case it imports multiple items under different namespaces we just pick one arbitrarily + // for now. + for id in scope.imports() { + let loc = id.import.lookup(self.db.upcast()); + loc.id.item_tree(self.db.upcast()); + let source = id.import.child_source(self.db.upcast()); + let Some(use_tree_src) = source.value.get(id.idx) else { continue }; + let Some(rename) = use_tree_src.rename() else { continue }; + let Some(name) = rename.name() else { continue }; + + let res = scope.fully_resolve_import(self.db.upcast(), id); + res.iter_items().for_each(|(item, _)| { + let def = match item { + ItemInNs::Types(def) | ItemInNs::Values(def) => def, + ItemInNs::Macros(def) => ModuleDefId::from(def), + } + .into(); + let dec_loc = DeclarationLocation { + hir_file_id: source.file_id, + ptr: SyntaxNodePtr::new(use_tree_src.syntax()), + name_ptr: SyntaxNodePtr::new(name.syntax()), + }; + + self.symbols.push(FileSymbol { + name: name.text().into(), + def, + container_name: self.current_container_name.clone(), + loc: dec_loc, + is_alias: false, + }); + }); + } + for const_id in scope.unnamed_consts() { self.collect_from_body(const_id); } diff --git a/crates/ide-db/src/symbol_index.rs b/crates/ide-db/src/symbol_index.rs index ad1ce453ecaa..f699f999baf7 100644 --- a/crates/ide-db/src/symbol_index.rs +++ b/crates/ide-db/src/symbol_index.rs @@ -419,9 +419,16 @@ const CONST_WITH_INNER: () = { mod b_mod; + +use define_struct as really_define_struct; +use Macro as ItemLikeMacro; +use Macro as Trait; // overlay namespaces //- /b_mod.rs struct StructInModB; - "#, +use super::Macro as SuperItemLikeMacro; +use crate::b_mod::StructInModB as ThisStruct; +use crate::Trait as IsThisJustATrait; +"#, ); let symbols: Vec<_> = Crate::from(db.test_crate()) diff --git a/crates/ide-db/src/test_data/test_symbol_index_collection.txt b/crates/ide-db/src/test_data/test_symbol_index_collection.txt index 1a00e29384e5..87ad5844c64c 100644 --- a/crates/ide-db/src/test_data/test_symbol_index_collection.txt +++ b/crates/ide-db/src/test_data/test_symbol_index_collection.txt @@ -118,6 +118,35 @@ container_name: None, is_alias: false, }, + FileSymbol { + name: "ItemLikeMacro", + def: Macro( + Macro { + id: Macro2Id( + Macro2Id( + 0, + ), + ), + }, + ), + loc: DeclarationLocation { + hir_file_id: FileId( + FileId( + 0, + ), + ), + ptr: SyntaxNodePtr { + kind: USE_TREE, + range: 654..676, + }, + name_ptr: SyntaxNodePtr { + kind: NAME, + range: 663..676, + }, + }, + container_name: None, + is_alias: false, + }, FileSymbol { name: "Macro", def: Macro( @@ -352,6 +381,35 @@ container_name: None, is_alias: false, }, + FileSymbol { + name: "Trait", + def: Macro( + Macro { + id: Macro2Id( + Macro2Id( + 0, + ), + ), + }, + ), + loc: DeclarationLocation { + hir_file_id: FileId( + FileId( + 0, + ), + ), + ptr: SyntaxNodePtr { + kind: USE_TREE, + range: 682..696, + }, + name_ptr: SyntaxNodePtr { + kind: NAME, + range: 691..696, + }, + }, + container_name: None, + is_alias: false, + }, FileSymbol { name: "Union", def: Adt( @@ -551,6 +609,35 @@ container_name: None, is_alias: false, }, + FileSymbol { + name: "really_define_struct", + def: Macro( + Macro { + id: MacroRulesId( + MacroRulesId( + 1, + ), + ), + }, + ), + loc: DeclarationLocation { + hir_file_id: FileId( + FileId( + 0, + ), + ), + ptr: SyntaxNodePtr { + kind: USE_TREE, + range: 611..648, + }, + name_ptr: SyntaxNodePtr { + kind: NAME, + range: 628..648, + }, + }, + container_name: None, + is_alias: false, + }, FileSymbol { name: "trait_fn", def: Function( @@ -631,6 +718,35 @@ }, }, [ + FileSymbol { + name: "IsThisJustATrait", + def: Macro( + Macro { + id: Macro2Id( + Macro2Id( + 0, + ), + ), + }, + ), + loc: DeclarationLocation { + hir_file_id: FileId( + FileId( + 1, + ), + ), + ptr: SyntaxNodePtr { + kind: USE_TREE, + range: 111..143, + }, + name_ptr: SyntaxNodePtr { + kind: NAME, + range: 127..143, + }, + }, + container_name: None, + is_alias: false, + }, FileSymbol { name: "StructInModB", def: Adt( @@ -660,6 +776,93 @@ container_name: None, is_alias: false, }, + FileSymbol { + name: "SuperItemLikeMacro", + def: Macro( + Macro { + id: Macro2Id( + Macro2Id( + 0, + ), + ), + }, + ), + loc: DeclarationLocation { + hir_file_id: FileId( + FileId( + 1, + ), + ), + ptr: SyntaxNodePtr { + kind: USE_TREE, + range: 25..59, + }, + name_ptr: SyntaxNodePtr { + kind: NAME, + range: 41..59, + }, + }, + container_name: None, + is_alias: false, + }, + FileSymbol { + name: "ThisStruct", + def: Adt( + Struct( + Struct { + id: StructId( + 3, + ), + }, + ), + ), + loc: DeclarationLocation { + hir_file_id: FileId( + FileId( + 1, + ), + ), + ptr: SyntaxNodePtr { + kind: USE_TREE, + range: 65..105, + }, + name_ptr: SyntaxNodePtr { + kind: NAME, + range: 95..105, + }, + }, + container_name: None, + is_alias: false, + }, + FileSymbol { + name: "ThisStruct", + def: Adt( + Struct( + Struct { + id: StructId( + 3, + ), + }, + ), + ), + loc: DeclarationLocation { + hir_file_id: FileId( + FileId( + 1, + ), + ), + ptr: SyntaxNodePtr { + kind: USE_TREE, + range: 65..105, + }, + name_ptr: SyntaxNodePtr { + kind: NAME, + range: 95..105, + }, + }, + container_name: None, + is_alias: false, + }, ], ), ] From 132a2c6cf29649d0b57f3efe9fe72beef8fc7c9e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 19 Aug 2023 12:49:07 +0200 Subject: [PATCH 083/197] elaborate a bit on the (lack of) safety in 'Mmap::map' --- compiler/rustc_data_structures/src/memmap.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_data_structures/src/memmap.rs b/compiler/rustc_data_structures/src/memmap.rs index ca908671ae53..30403a614426 100644 --- a/compiler/rustc_data_structures/src/memmap.rs +++ b/compiler/rustc_data_structures/src/memmap.rs @@ -11,9 +11,14 @@ pub struct Mmap(Vec); #[cfg(not(target_arch = "wasm32"))] impl Mmap { + /// # Safety + /// + /// The given file must not be mutated (i.e., not written, not truncated, ...) until the mapping is closed. + /// + /// However in practice most callers do not ensure this, so uses of this function are likely unsound. #[inline] pub unsafe fn map(file: File) -> io::Result { - // Safety: this is in fact not safe. + // Safety: the caller must ensure that this is safe. unsafe { memmap2::Mmap::map(&file).map(Mmap) } } } From dadbfe7f4bc0153214caf5febb08b148ad64acc0 Mon Sep 17 00:00:00 2001 From: Alex Kladov Date: Sat, 19 Aug 2023 13:36:07 +0100 Subject: [PATCH 084/197] upgrade lsp server --- Cargo.lock | 10 +++++----- Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f8806794979e..26b62181630e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -999,12 +999,11 @@ checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "lsp-server" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3711e4d6f491dc9edc0f1df80e204f38206775ac92c1241e89b79229a850bc00" +version = "0.7.2" dependencies = [ "crossbeam-channel", "log", + "lsp-types", "serde", "serde_json", ] @@ -1012,10 +1011,11 @@ dependencies = [ [[package]] name = "lsp-server" version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ea9ae5a5082ca3b6ae824fc7666cd206b99168a4d4c769ad8fe9cc740df6a6" dependencies = [ "crossbeam-channel", "log", - "lsp-types", "serde", "serde_json", ] @@ -1555,7 +1555,7 @@ dependencies = [ "ide-ssr", "itertools", "load-cargo", - "lsp-server 0.7.1", + "lsp-server 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-types", "mbe", "mimalloc", diff --git a/Cargo.toml b/Cargo.toml index f6a50bfa6b2c..12425b6756fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -86,7 +86,7 @@ proc-macro-test = { path = "./crates/proc-macro-test" } # In-tree crates that are published separately and follow semver. See lib/README.md line-index = { version = "0.1.0-pre.1" } la-arena = { version = "0.3.1" } -lsp-server = { version = "0.7.1" } +lsp-server = { version = "0.7.2" } # non-local crates smallvec = { version = "1.10.0", features = [ From 6c46b98a9532b93c538b3553a7ff6ab4aa50655c Mon Sep 17 00:00:00 2001 From: Alex Kladov Date: Sat, 19 Aug 2023 13:41:13 +0100 Subject: [PATCH 085/197] fix: avoid problematic serde release serde 1.0.172 and up rely on opaque non-reproducible binary blobs to function, explicitly not providing a library-level opt-out. This is problematic for two reasons: - directly, unauditable binary blobs are a security issue. - indirectly, it becomes much harder to predict future behaviors of the crate. As such, I am willing to go on a limb here and forbid building rust-analyzer with those versions of serde. Normally, my philosophy is to defer the choice to the end user, but it's also a design constraint of rust-analyzer that we don't run random binaries downloaded from the internet without explicit user's concent. Concretely, this upper-bounds serde for both rust-analyzer workspace, as well as the lsp-server lib. See https://github.com/serde-rs/serde/issues/2538 for wider context. --- Cargo.lock | 10 +++++----- Cargo.toml | 3 ++- lib/lsp-server/Cargo.toml | 5 +++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 26b62181630e..d0f5abd8fd48 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1000,22 +1000,22 @@ checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "lsp-server" version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ea9ae5a5082ca3b6ae824fc7666cd206b99168a4d4c769ad8fe9cc740df6a6" dependencies = [ "crossbeam-channel", "log", - "lsp-types", "serde", "serde_json", ] [[package]] name = "lsp-server" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ea9ae5a5082ca3b6ae824fc7666cd206b99168a4d4c769ad8fe9cc740df6a6" +version = "0.7.3" dependencies = [ "crossbeam-channel", "log", + "lsp-types", "serde", "serde_json", ] @@ -1555,7 +1555,7 @@ dependencies = [ "ide-ssr", "itertools", "load-cargo", - "lsp-server 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lsp-server 0.7.2", "lsp-types", "mbe", "mimalloc", diff --git a/Cargo.toml b/Cargo.toml index 12425b6756fa..44f01ac832d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -97,7 +97,8 @@ smallvec = { version = "1.10.0", features = [ smol_str = "0.2.0" nohash-hasher = "0.2.0" text-size = "1.1.0" -serde = { version = "1.0.156", features = ["derive"] } +# See https://github.com/serde-rs/serde/issues/2538#issuecomment-1684517372 for why we pin serde +serde = { version = "1.0.156, < 1.0.172", features = ["derive"] } serde_json = "1.0.96" triomphe = { version = "0.1.8", default-features = false, features = ["std"] } # can't upgrade due to dashmap depending on 0.12.3 currently diff --git a/lib/lsp-server/Cargo.toml b/lib/lsp-server/Cargo.toml index 01707d301918..e1c49db39d53 100644 --- a/lib/lsp-server/Cargo.toml +++ b/lib/lsp-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lsp-server" -version = "0.7.2" +version = "0.7.3" description = "Generic LSP server scaffold." license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/rust-analyzer/tree/master/lib/lsp-server" @@ -9,7 +9,8 @@ edition = "2021" [dependencies] log = "0.4.17" serde_json = "1.0.96" -serde = { version = "1.0.156", features = ["derive"] } +# See https://github.com/serde-rs/serde/issues/2538#issuecomment-1684517372 for why we pin serde +serde = { version = "1.0.156, < 1.0.172", features = ["derive"] } crossbeam-channel = "0.5.6" [dev-dependencies] From 1cebc0ca13b5e818e6c5a1b6a5e6ddf9008d433d Mon Sep 17 00:00:00 2001 From: Alex Kladov Date: Sat, 19 Aug 2023 15:28:32 +0100 Subject: [PATCH 086/197] internal: post-bump lsp-server version --- Cargo.lock | 10 +++++----- Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0f5abd8fd48..9e838fcc880a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -999,12 +999,11 @@ checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "lsp-server" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ea9ae5a5082ca3b6ae824fc7666cd206b99168a4d4c769ad8fe9cc740df6a6" +version = "0.7.3" dependencies = [ "crossbeam-channel", "log", + "lsp-types", "serde", "serde_json", ] @@ -1012,10 +1011,11 @@ dependencies = [ [[package]] name = "lsp-server" version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72417faa455bfb4e5bf14b157d8e2ca2ed74b4e89b8cf42ea2d864825ae5c8a2" dependencies = [ "crossbeam-channel", "log", - "lsp-types", "serde", "serde_json", ] @@ -1555,7 +1555,7 @@ dependencies = [ "ide-ssr", "itertools", "load-cargo", - "lsp-server 0.7.2", + "lsp-server 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-types", "mbe", "mimalloc", diff --git a/Cargo.toml b/Cargo.toml index 44f01ac832d5..5eb59d6db116 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -86,7 +86,7 @@ proc-macro-test = { path = "./crates/proc-macro-test" } # In-tree crates that are published separately and follow semver. See lib/README.md line-index = { version = "0.1.0-pre.1" } la-arena = { version = "0.3.1" } -lsp-server = { version = "0.7.2" } +lsp-server = { version = "0.7.3" } # non-local crates smallvec = { version = "1.10.0", features = [ From acd3542b8d4cf9b4bc1cf6c99f76bb2fb938fe20 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 19 Aug 2023 18:47:08 +0000 Subject: [PATCH 087/197] Don't do intra-pass validation on MIR shims --- compiler/rustc_mir_transform/src/shim.rs | 6 +++++- .../auxiliary/drop-shim-relates-opaque-aux.rs | 21 +++++++++++++++++++ .../drop-shim-relates-opaque-issue-114375.rs | 10 +++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/ui/type-alias-impl-trait/auxiliary/drop-shim-relates-opaque-aux.rs create mode 100644 tests/ui/type-alias-impl-trait/drop-shim-relates-opaque-issue-114375.rs diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 5e8ba4f544c9..603a829412be 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -90,7 +90,11 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' }; debug!("make_shim({:?}) = untransformed {:?}", instance, result); - pm::run_passes( + // We don't validate MIR here because the shims may generate code that's + // only valid in a reveal-all param-env. However, since we do initial + // validation with the MirBuilt phase, which uses a user-facing param-env. + // This causes validation errors when TAITs are involved. + pm::run_passes_no_validate( tcx, &mut result, &[ diff --git a/tests/ui/type-alias-impl-trait/auxiliary/drop-shim-relates-opaque-aux.rs b/tests/ui/type-alias-impl-trait/auxiliary/drop-shim-relates-opaque-aux.rs new file mode 100644 index 000000000000..54a22510066f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auxiliary/drop-shim-relates-opaque-aux.rs @@ -0,0 +1,21 @@ +// crate foo + +#![feature(type_alias_impl_trait)] + +type Tait = impl Sized; +fn _constrain() -> Tait {} + +struct WrapperWithDrop(T); +impl Drop for WrapperWithDrop { + fn drop(&mut self) {} +} + +pub struct Foo(WrapperWithDrop); + +trait Id { + type Id: ?Sized; +} +impl Id for T { + type Id = T; +} +pub struct Bar(WrapperWithDrop<::Id>); diff --git a/tests/ui/type-alias-impl-trait/drop-shim-relates-opaque-issue-114375.rs b/tests/ui/type-alias-impl-trait/drop-shim-relates-opaque-issue-114375.rs new file mode 100644 index 000000000000..51d287049725 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/drop-shim-relates-opaque-issue-114375.rs @@ -0,0 +1,10 @@ +// aux-build:drop-shim-relates-opaque-aux.rs +// compile-flags: -Zvalidate-mir --crate-type=lib +// build-pass + +extern crate drop_shim_relates_opaque_aux; + +pub fn drop_foo(_: drop_shim_relates_opaque_aux::Foo) {} +pub fn drop_bar(_: drop_shim_relates_opaque_aux::Bar) {} + +fn main() {} From fad7d220fd2daefe8ee778b8cafbbeaf2dda4fc5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 19 Aug 2023 23:27:50 +0000 Subject: [PATCH 088/197] Warn on elided lifetimes in associated constants --- compiler/rustc_lint/src/context.rs | 8 ++ compiler/rustc_lint_defs/src/builtin.rs | 42 ++++++++++ compiler/rustc_lint_defs/src/lib.rs | 4 + compiler/rustc_resolve/src/late.rs | 79 +++++++++++++------ ...nfer-placeholder-in-non-suggestable-pos.rs | 2 + ...-placeholder-in-non-suggestable-pos.stderr | 16 +++- .../ui/consts/assoc-const-elided-lifetime.rs | 19 +++++ .../consts/assoc-const-elided-lifetime.stderr | 33 ++++++++ 8 files changed, 178 insertions(+), 25 deletions(-) create mode 100644 tests/ui/consts/assoc-const-elided-lifetime.rs create mode 100644 tests/ui/consts/assoc-const-elided-lifetime.stderr diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index f73797415bc7..aabefb729f3d 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -966,6 +966,14 @@ pub trait LintContext: Sized { Applicability::MachineApplicable ); } + BuiltinLintDiagnostics::AssociatedConstElidedLifetime { elided, span } => { + db.span_suggestion_verbose( + if elided { span.shrink_to_hi() } else { span }, + "use the `'static` lifetime", + if elided { "'static " } else { "'static" }, + Applicability::MachineApplicable + ); + } } // Rewrap `db`, and pass control to the user. decorate(db) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 96c31a90da86..0aa37642b740 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3376,6 +3376,7 @@ declare_lint_pass! { DEPRECATED_IN_FUTURE, DEPRECATED_WHERE_CLAUSE_LOCATION, DUPLICATE_MACRO_ATTRIBUTES, + ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, ELIDED_LIFETIMES_IN_PATHS, EXPORTED_PRIVATE_DEPENDENCIES, FFI_UNWIND_CALLS, @@ -4527,3 +4528,44 @@ declare_lint! { reference: "issue #114095 ", }; } + +declare_lint! { + /// The `elided_lifetimes_in_associated_constant` lint detects elided lifetimes + /// that were erroneously allowed in associated constants. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(elided_lifetimes_in_associated_constant)] + /// + /// struct Foo; + /// + /// impl Foo { + /// const STR: &str = "hello, world"; + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Previous version of Rust + /// + /// Implicit static-in-const behavior was decided [against] for associated + /// constants because of ambiguity. This, however, regressed and the compiler + /// erroneously treats elided lifetimes in associated constants as lifetime + /// parameters on the impl. + /// + /// This is a [future-incompatible] lint to transition this to a + /// hard error in the future. + /// + /// [against]: https://github.com/rust-lang/rust/issues/38831 + /// [future-incompatible]: ../index.md#future-incompatible-lints + pub ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, + Warn, + "elided lifetimes cannot be used in associated constants in impls", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseError, + reference: "issue #115010 ", + }; +} diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index f350957f72f1..d68d08472548 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -572,6 +572,10 @@ pub enum BuiltinLintDiagnostics { /// The span of the unnecessarily-qualified path to remove. removal_span: Span, }, + AssociatedConstElidedLifetime { + elided: bool, + span: Span, + }, } /// Lints that are buffered up early on in the `Session` before the diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index c87db96a5dd9..22d084c8e0b5 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -311,6 +311,10 @@ enum LifetimeRibKind { /// error on default object bounds (e.g., `Box`). AnonymousReportError, + /// Resolves elided lifetimes to `'static`, but gives a warning that this behavior + /// is a bug and will be reverted soon. + AnonymousWarnToStatic(NodeId), + /// Signal we cannot find which should be the anonymous lifetime. ElisionFailure, @@ -1148,6 +1152,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, } LifetimeRibKind::AnonymousCreateParameter { .. } | LifetimeRibKind::AnonymousReportError + | LifetimeRibKind::AnonymousWarnToStatic(_) | LifetimeRibKind::Elided(_) | LifetimeRibKind::ElisionFailure | LifetimeRibKind::ConcreteAnonConst(_) @@ -1515,6 +1520,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // lifetime would be illegal. LifetimeRibKind::Item | LifetimeRibKind::AnonymousReportError + | LifetimeRibKind::AnonymousWarnToStatic(_) | LifetimeRibKind::ElisionFailure => Some(LifetimeUseSet::Many), // An anonymous lifetime is legal here, and bound to the right // place, go ahead. @@ -1576,7 +1582,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { | LifetimeRibKind::Elided(_) | LifetimeRibKind::Generics { .. } | LifetimeRibKind::ElisionFailure - | LifetimeRibKind::AnonymousReportError => {} + | LifetimeRibKind::AnonymousReportError + | LifetimeRibKind::AnonymousWarnToStatic(_) => {} } } @@ -1616,6 +1623,25 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { self.record_lifetime_res(lifetime.id, res, elision_candidate); return; } + LifetimeRibKind::AnonymousWarnToStatic(node_id) => { + self.record_lifetime_res(lifetime.id, LifetimeRes::Static, elision_candidate); + let msg = if elided { + "`&` without an explicit lifetime name cannot be used here" + } else { + "`'_` cannot be used here" + }; + self.r.lint_buffer.buffer_lint_with_diagnostic( + lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, + node_id, + lifetime.ident.span, + msg, + lint::BuiltinLintDiagnostics::AssociatedConstElidedLifetime { + elided, + span: lifetime.ident.span, + }, + ); + return; + } LifetimeRibKind::AnonymousReportError => { let (msg, note) = if elided { ( @@ -1811,7 +1837,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // // impl Foo for std::cell::Ref // note lack of '_ // async fn foo(_: std::cell::Ref) { ... } - LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. } => { + LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. } + | LifetimeRibKind::AnonymousWarnToStatic(_) => { let sess = self.r.tcx.sess; let mut err = rustc_errors::struct_span_err!( sess, @@ -2898,7 +2925,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { match &item.kind { AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => { debug!("resolve_implementation AssocItemKind::Const"); - self.with_generic_param_rib( &generics.params, RibKind::AssocItem, @@ -2908,28 +2934,33 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { kind: LifetimeBinderKind::ConstItem, }, |this| { - // If this is a trait impl, ensure the const - // exists in trait - this.check_trait_item( - item.id, - item.ident, - &item.kind, - ValueNS, - item.span, - seen_trait_items, - |i, s, c| ConstNotMemberOfTrait(i, s, c), - ); + this.with_lifetime_rib( + LifetimeRibKind::AnonymousWarnToStatic(item.id), + |this| { + // If this is a trait impl, ensure the const + // exists in trait + this.check_trait_item( + item.id, + item.ident, + &item.kind, + ValueNS, + item.span, + seen_trait_items, + |i, s, c| ConstNotMemberOfTrait(i, s, c), + ); - this.visit_generics(generics); - this.visit_ty(ty); - if let Some(expr) = expr { - // We allow arbitrary const expressions inside of associated consts, - // even if they are potentially not const evaluatable. - // - // Type parameters can already be used and as associated consts are - // not used as part of the type system, this is far less surprising. - this.resolve_const_body(expr, None); - } + this.visit_generics(generics); + this.visit_ty(ty); + if let Some(expr) = expr { + // We allow arbitrary const expressions inside of associated consts, + // even if they are potentially not const evaluatable. + // + // Type parameters can already be used and as associated consts are + // not used as part of the type system, this is far less surprising. + this.resolve_const_body(expr, None); + } + }, + ); }, ); } diff --git a/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.rs b/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.rs index 40896c32e111..1e0b77b0d3bd 100644 --- a/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.rs +++ b/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.rs @@ -5,6 +5,8 @@ trait Trait { impl Trait for () { const ASSOC: &dyn Fn(_) = 1i32; //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated constants + //~| WARN `&` without an explicit lifetime name cannot be used here + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! } fn main() {} diff --git a/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr b/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr index 993a08faba99..f8c02420f96a 100644 --- a/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr +++ b/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr @@ -1,9 +1,23 @@ +warning: `&` without an explicit lifetime name cannot be used here + --> $DIR/infer-placeholder-in-non-suggestable-pos.rs:6:18 + | +LL | const ASSOC: &dyn Fn(_) = 1i32; + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #115010 + = note: `#[warn(elided_lifetimes_in_associated_constant)]` on by default +help: use the `'static` lifetime + | +LL | const ASSOC: &'static dyn Fn(_) = 1i32; + | +++++++ + error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants --> $DIR/infer-placeholder-in-non-suggestable-pos.rs:6:26 | LL | const ASSOC: &dyn Fn(_) = 1i32; | ^ not allowed in type signatures -error: aborting due to previous error +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/consts/assoc-const-elided-lifetime.rs b/tests/ui/consts/assoc-const-elided-lifetime.rs new file mode 100644 index 000000000000..10cd33a8fed5 --- /dev/null +++ b/tests/ui/consts/assoc-const-elided-lifetime.rs @@ -0,0 +1,19 @@ +#![deny(elided_lifetimes_in_associated_constant)] + +use std::marker::PhantomData; + +struct Foo<'a> { + x: PhantomData<&'a ()>, +} + +impl<'a> Foo<'a> { + const FOO: Foo<'_> = Foo { x: PhantomData::<&()> }; + //~^ ERROR `'_` cannot be used here + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + + const BAR: &() = &(); + //~^ ERROR `&` without an explicit lifetime name cannot be used here + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +} + +fn main() {} diff --git a/tests/ui/consts/assoc-const-elided-lifetime.stderr b/tests/ui/consts/assoc-const-elided-lifetime.stderr new file mode 100644 index 000000000000..a1eeaff4ba87 --- /dev/null +++ b/tests/ui/consts/assoc-const-elided-lifetime.stderr @@ -0,0 +1,33 @@ +error: `'_` cannot be used here + --> $DIR/assoc-const-elided-lifetime.rs:10:20 + | +LL | const FOO: Foo<'_> = Foo { x: PhantomData::<&()> }; + | ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #115010 +note: the lint level is defined here + --> $DIR/assoc-const-elided-lifetime.rs:1:9 + | +LL | #![deny(elided_lifetimes_in_associated_constant)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: use the `'static` lifetime + | +LL | const FOO: Foo<'static> = Foo { x: PhantomData::<&()> }; + | ~~~~~~~ + +error: `&` without an explicit lifetime name cannot be used here + --> $DIR/assoc-const-elided-lifetime.rs:14:16 + | +LL | const BAR: &() = &(); + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #115010 +help: use the `'static` lifetime + | +LL | const BAR: &'static () = &(); + | +++++++ + +error: aborting due to 2 previous errors + From 4170ca4be92f1a8e4bfd1d2815c12804710b7087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 20 Aug 2023 01:59:44 +0200 Subject: [PATCH 089/197] Ensure that THIR unsafety check is done before stealing it. Fixes #111520. --- compiler/rustc_mir_build/src/build/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 2a23a69b5841..e614046e83e7 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -56,7 +56,8 @@ pub(crate) fn closure_saved_names_of_captured_variables<'tcx>( /// Construct the MIR for a given `DefId`. fn mir_build(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> { // Ensure unsafeck and abstract const building is ran before we steal the THIR. - tcx.ensure_with_value().thir_check_unsafety(def); + tcx.ensure_with_value() + .thir_check_unsafety(tcx.typeck_root_def_id(def.to_def_id()).expect_local()); tcx.ensure_with_value().thir_abstract_const(def); if let Err(e) = tcx.check_match(def) { return construct_error(tcx, def, e); From 1f7bad0d128c6b005ffadb683fffb8cc02f66c7d Mon Sep 17 00:00:00 2001 From: Catherine Flores Date: Sun, 20 Aug 2023 13:22:39 +0000 Subject: [PATCH 090/197] Clarify that `Rust` is default repr --- compiler/rustc_passes/messages.ftl | 2 +- tests/ui/issues/issue-43988.stderr | 4 ++-- tests/ui/repr/invalid_repr_list_help.stderr | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 81a6914815e0..ffcaac176c58 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -706,7 +706,7 @@ passes_unrecognized_field = passes_unrecognized_repr_hint = unrecognized representation hint - .help = valid reprs are `Rust`, `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + .help = valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` passes_unused = unused attribute diff --git a/tests/ui/issues/issue-43988.stderr b/tests/ui/issues/issue-43988.stderr index a68d4945d824..7bbb8ed2ca94 100644 --- a/tests/ui/issues/issue-43988.stderr +++ b/tests/ui/issues/issue-43988.stderr @@ -32,7 +32,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(nothing)] | ^^^^^^^ | - = help: valid reprs are `Rust`, `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error[E0552]: unrecognized representation hint --> $DIR/issue-43988.rs:18:12 @@ -40,7 +40,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(something_not_real)] | ^^^^^^^^^^^^^^^^^^ | - = help: valid reprs are `Rust`, `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error[E0518]: attribute should be applied to function or closure --> $DIR/issue-43988.rs:30:5 diff --git a/tests/ui/repr/invalid_repr_list_help.stderr b/tests/ui/repr/invalid_repr_list_help.stderr index 68cfce4065c5..7ffe1287eb32 100644 --- a/tests/ui/repr/invalid_repr_list_help.stderr +++ b/tests/ui/repr/invalid_repr_list_help.stderr @@ -4,7 +4,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(uwu)] | ^^^ | - = help: valid reprs are `Rust`, `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error[E0552]: unrecognized representation hint --> $DIR/invalid_repr_list_help.rs:6:8 @@ -12,7 +12,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(uwu = "a")] | ^^^^^^^^^ | - = help: valid reprs are `Rust`, `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error[E0552]: unrecognized representation hint --> $DIR/invalid_repr_list_help.rs:9:8 @@ -20,7 +20,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(uwu(4))] | ^^^^^^ | - = help: valid reprs are `Rust`, `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error[E0552]: unrecognized representation hint --> $DIR/invalid_repr_list_help.rs:14:8 @@ -28,7 +28,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(uwu, u8)] | ^^^ | - = help: valid reprs are `Rust`, `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` warning: unknown `doc` attribute `owo` --> $DIR/invalid_repr_list_help.rs:20:7 @@ -46,7 +46,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(uwu)] | ^^^ | - = help: valid reprs are `Rust`, `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error: aborting due to 5 previous errors; 1 warning emitted From 37e0e8af10514a2064915389f22743fb690e3f93 Mon Sep 17 00:00:00 2001 From: Jessie Chatham Spencer Date: Thu, 30 Mar 2023 08:53:36 +0200 Subject: [PATCH 091/197] Implement extern crate completion --- crates/hir-def/src/resolver.rs | 19 +++++ crates/hir/src/semantics.rs | 8 +++ crates/ide-completion/src/completions.rs | 2 + .../src/completions/extern_crate.rs | 71 +++++++++++++++++++ crates/ide-completion/src/context.rs | 1 + crates/ide-completion/src/context/analysis.rs | 4 ++ 6 files changed, 105 insertions(+) create mode 100644 crates/ide-completion/src/completions/extern_crate.rs diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 62576100ea44..2f9187009e2d 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -12,6 +12,7 @@ use triomphe::Arc; use crate::{ body::scope::{ExprScopes, ScopeId}, builtin_type::BuiltinType, + data::ExternCrateDeclData, db::DefDatabase, generics::{GenericParams, TypeOrConstParamData}, hir::{BindingId, ExprId, LabelId}, @@ -451,6 +452,7 @@ impl Resolver { def_map[module_id].scope.entries().for_each(|(name, def)| { res.add_per_ns(name, def); }); + def_map[module_id].scope.legacy_macros().for_each(|(name, macs)| { macs.iter().for_each(|&mac| { res.add(name, ScopeDef::ModuleDef(ModuleDefId::MacroId(mac))); @@ -474,6 +476,23 @@ impl Resolver { res.map } + pub fn extern_crate_decls_in_scope<'a>( + &'a self, + db: &'a dyn DefDatabase, + ) -> impl Iterator + 'a { + self.module_scope.def_map[self.module_scope.module_id] + .scope + .extern_crate_decls() + .map(|id| ExternCrateDeclData::extern_crate_decl_data_query(db, id).name.clone()) + } + + pub fn extern_crates_in_scope<'a>(&'a self) -> impl Iterator + 'a { + self.module_scope + .def_map + .extern_prelude() + .map(|(name, module_id)| (name.clone(), module_id.0.into())) + } + pub fn traits_in_scope(&self, db: &dyn DefDatabase) -> FxHashSet { // FIXME(trait_alias): Trait alias brings aliased traits in scope! Note that supertraits of // aliased traits are NOT brought in scope (unless also aliased). diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 65ccb8b07331..b8d4ecd44142 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -1722,6 +1722,14 @@ impl SemanticsScope<'_> { |name, id| cb(name, id.into()), ) } + + pub fn extern_crates(&self) -> impl Iterator + '_ { + self.resolver.extern_crates_in_scope().map(|(name, id)| (name, Module { id })) + } + + pub fn extern_crate_decls(&self) -> impl Iterator + '_ { + self.resolver.extern_crate_decls_in_scope(self.db.upcast()) + } } #[derive(Debug)] diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs index 7e2ecdbb858e..f60ac150164c 100644 --- a/crates/ide-completion/src/completions.rs +++ b/crates/ide-completion/src/completions.rs @@ -20,6 +20,7 @@ pub(crate) mod r#type; pub(crate) mod use_; pub(crate) mod vis; pub(crate) mod env_vars; +pub(crate) mod extern_crate; use std::iter; @@ -739,6 +740,7 @@ pub(super) fn complete_name_ref( } } } + NameRefKind::ExternCrate => extern_crate::complete_extern_crate(acc, ctx), NameRefKind::DotAccess(dot_access) => { flyimport::import_on_the_fly_dot(acc, ctx, dot_access); dot::complete_dot(acc, ctx, dot_access); diff --git a/crates/ide-completion/src/completions/extern_crate.rs b/crates/ide-completion/src/completions/extern_crate.rs new file mode 100644 index 000000000000..0d0e143f5f68 --- /dev/null +++ b/crates/ide-completion/src/completions/extern_crate.rs @@ -0,0 +1,71 @@ +//! Completion for extern crates + +use hir::{HasAttrs, Name}; +use ide_db::SymbolKind; + +use crate::{context::CompletionContext, CompletionItem, CompletionItemKind}; + +use super::Completions; + +pub(crate) fn complete_extern_crate(acc: &mut Completions, ctx: &CompletionContext<'_>) { + let imported_extern_crates: Vec = ctx.scope.extern_crate_decls().collect(); + + for (name, module) in ctx.scope.extern_crates() { + if imported_extern_crates.contains(&name) { + continue; + } + + let mut item = CompletionItem::new( + CompletionItemKind::SymbolKind(SymbolKind::Module), + ctx.source_range(), + name.to_smol_str(), + ); + item.set_documentation(module.docs(ctx.db)); + + item.add_to(acc, ctx.db); + } +} + +#[cfg(test)] +mod test { + use crate::tests::completion_list_no_kw; + + #[test] + fn can_complete_extern_crate() { + let case = r#" +//- /lib.rs crate:other_crate_a +// nothing here +//- /other_crate_b.rs crate:other_crate_b +pub mod good_mod{} +//- /lib.rs crate:crate_c +// nothing here +//- /lib.rs crate:lib deps:other_crate_a,other_crate_b,crate_c extern-prelude:other_crate_a +extern crate oth$0 +mod other_mod {} +"#; + + let completion_list = completion_list_no_kw(case); + + assert_eq!("md other_crate_a\n".to_string(), completion_list); + } + + #[test] + fn will_not_complete_existing_import() { + let case = r#" +//- /lib.rs crate:other_crate_a +// nothing here +//- /lib.rs crate:crate_c +// nothing here +//- /lib.rs crate:other_crate_b +// +//- /lib.rs crate:lib deps:other_crate_a,other_crate_b,crate_c extern-prelude:other_crate_a,other_crate_b +extern crate other_crate_b; +extern crate oth$0 +mod other_mod {} +"#; + + let completion_list = completion_list_no_kw(case); + + assert_eq!("md other_crate_a\n".to_string(), completion_list); + } +} diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs index 1fd635ba2e79..0da7ba6d0001 100644 --- a/crates/ide-completion/src/context.rs +++ b/crates/ide-completion/src/context.rs @@ -351,6 +351,7 @@ pub(super) enum NameRefKind { expr: ast::RecordExpr, }, Pattern(PatternContext), + ExternCrate, } /// The identifier we are currently completing. diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index c66cb987fea8..1e6b2f319aad 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -624,6 +624,10 @@ fn classify_name_ref( }); return Some(make_res(kind)); }, + ast::ExternCrate(_) => { + let kind = NameRefKind::ExternCrate; + return Some(make_res(kind)); + }, ast::MethodCallExpr(method) => { let receiver = find_opt_node_in_file(original_file, method.receiver()); let kind = NameRefKind::DotAccess(DotAccess { From 31032ecb1550a402a726e9c244f6a716b214cc9d Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Sun, 20 Aug 2023 21:13:52 -0400 Subject: [PATCH 092/197] Add projection obligations when comparing impl too --- .../src/check/compare_impl_item.rs | 9 +++++- .../implied_bounds_entailment_alias_var.rs | 32 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 tests/ui/implied-bounds/implied_bounds_entailment_alias_var.rs diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index ad02ca252c40..bd0ab6463f08 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -342,9 +342,16 @@ fn compare_method_predicate_entailment<'tcx>( continue; }; for obligation in obligations { + debug!(?obligation); match obligation.predicate.kind().skip_binder() { + // We need to register Projection oblgiations too, because we may end up with + // an implied `X::Item: 'a`, which gets desugared into `X::Item = ?0`, `?0: 'a`. + // If we only register the region outlives obligation, this leads to an unconstrained var. + // See `implied_bounds_entailment_alias_var` test. ty::PredicateKind::Clause( - ty::ClauseKind::RegionOutlives(..) | ty::ClauseKind::TypeOutlives(..), + ty::ClauseKind::RegionOutlives(..) + | ty::ClauseKind::TypeOutlives(..) + | ty::ClauseKind::Projection(..), ) => ocx.register_obligation(obligation), ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { if wf_args_seen.insert(arg) { diff --git a/tests/ui/implied-bounds/implied_bounds_entailment_alias_var.rs b/tests/ui/implied-bounds/implied_bounds_entailment_alias_var.rs new file mode 100644 index 000000000000..e0df96b0de8e --- /dev/null +++ b/tests/ui/implied-bounds/implied_bounds_entailment_alias_var.rs @@ -0,0 +1,32 @@ +// check-pass + +trait Data { + type Elem; +} + +impl> Data for ArrayBase { + type Elem = F; +} + +struct DatasetIter<'a, R: Data> { + data: &'a R::Elem, +} + +pub struct ArrayBase { + data: S, +} + +trait Trait { + type Item; + fn next() -> Option; +} + +impl<'a, D: Data> Trait for DatasetIter<'a, ArrayBase> { + type Item = (); + + fn next() -> Option { + None + } +} + +fn main() {} From 82ce7b14613c4703e2a21775c60c578ac9246db2 Mon Sep 17 00:00:00 2001 From: Sebastian Toh Date: Thu, 3 Aug 2023 11:39:03 +0800 Subject: [PATCH 093/197] Add note when matching on tuples/ADTs containing non-exhaustive types --- .../src/thir/pattern/check_match.rs | 45 +++-- .../pointer-sized-int.deny.stderr | 4 + ...2-types-containing-non-exhaustive-types.rs | 67 +++++++ ...pes-containing-non-exhaustive-types.stderr | 170 ++++++++++++++++++ .../non-exhaustive-pattern-witness.stderr | 2 + .../tuple-struct-nonexhaustive.stderr | 2 + 6 files changed, 276 insertions(+), 14 deletions(-) create mode 100644 tests/ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.rs create mode 100644 tests/ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.stderr 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 383e80851f0d..f46cf0dc0ff1 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -7,6 +7,7 @@ use crate::errors::*; use rustc_arena::TypedArena; use rustc_ast::Mutability; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, @@ -660,6 +661,17 @@ fn report_arm_reachability<'p, 'tcx>( } } +fn collect_non_exhaustive_tys<'p, 'tcx>( + pat: &DeconstructedPat<'p, 'tcx>, + non_exhaustive_tys: &mut FxHashSet>, +) { + if matches!(pat.ctor(), Constructor::NonExhaustive) { + non_exhaustive_tys.insert(pat.ty()); + } + pat.iter_fields() + .for_each(|field_pat| collect_non_exhaustive_tys(field_pat, non_exhaustive_tys)) +} + /// Report that a match is not exhaustive. fn non_exhaustive_match<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, @@ -717,22 +729,27 @@ fn non_exhaustive_match<'p, 'tcx>( scrut_ty, if is_variant_list_non_exhaustive { ", which is marked as non-exhaustive" } else { "" } )); - if (scrut_ty == cx.tcx.types.usize || scrut_ty == cx.tcx.types.isize) - && !is_empty_match - && witnesses.len() == 1 - && matches!(witnesses[0].ctor(), Constructor::NonExhaustive) - { - err.note(format!( - "`{scrut_ty}` does not have a fixed maximum value, so a wildcard `_` is necessary to match \ - exhaustively", - )); - if cx.tcx.sess.is_nightly_build() { - err.help(format!( - "add `#![feature(precise_pointer_size_matching)]` to the crate attributes to \ - enable precise `{scrut_ty}` matching", - )); + + if !is_empty_match && witnesses.len() == 1 { + let mut non_exhaustive_tys = FxHashSet::default(); + collect_non_exhaustive_tys(&witnesses[0], &mut non_exhaustive_tys); + + for ty in non_exhaustive_tys { + if ty == cx.tcx.types.usize || ty == cx.tcx.types.isize { + err.note(format!( + "`{ty}` does not have a fixed maximum value, so a wildcard `_` is necessary to match \ + exhaustively", + )); + if cx.tcx.sess.is_nightly_build() { + err.help(format!( + "add `#![feature(precise_pointer_size_matching)]` to the crate attributes to \ + enable precise `{ty}` matching", + )); + } + } } } + if let ty::Ref(_, sub_ty, _) = scrut_ty.kind() { if !sub_ty.is_inhabited_from(cx.tcx, cx.module, cx.param_env) { err.note("references are always considered inhabited"); diff --git a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr index 0e0f0c3e11ee..df330c60b1e8 100644 --- a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr +++ b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr @@ -77,6 +77,8 @@ LL | m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize:: | ^^^^^^^^^^^^^^ pattern `(_, _)` not covered | = note: the matched value is of type `(usize, bool)` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL | match $s { $($t)+ => {}, (_, _) => todo!() } @@ -131,6 +133,8 @@ LL | m!((0isize, true), (isize::MIN..5, true) | ^^^^^^^^^^^^^^ pattern `(_, _)` not covered | = note: the matched value is of type `(isize, bool)` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL | match $s { $($t)+ => {}, (_, _) => todo!() } diff --git a/tests/ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.rs b/tests/ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.rs new file mode 100644 index 000000000000..8f58227ee2c6 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.rs @@ -0,0 +1,67 @@ +struct A { + a: T, +} + +struct B(T, U); + +fn main() { + match 0 { + //~^ ERROR non-exhaustive patterns: `_` not covered [E0004] + 0 => (), + 1..=usize::MAX => (), + } + + match (0usize, 0usize) { + //~^ ERROR non-exhaustive patterns: `(_, _)` not covered [E0004] + (0, 0) => (), + (1..=usize::MAX, 1..=usize::MAX) => (), + } + + match (0isize, 0usize) { + //~^ ERROR non-exhaustive patterns: `(_, _)` not covered [E0004] + (isize::MIN..=isize::MAX, 0) => (), + (isize::MIN..=isize::MAX, 1..=usize::MAX) => (), + } + + // Should not report note about usize not having fixed max value + match Some(1usize) { + //~^ ERROR non-exhaustive patterns: `Some(_)` not covered + None => {} + } + + match Some(4) { + //~^ ERROR non-exhaustive patterns: `Some(_)` not covered + Some(0) => (), + Some(1..=usize::MAX) => (), + None => (), + } + + match Some(Some(Some(0))) { + //~^ ERROR non-exhaustive patterns: `Some(Some(Some(_)))` not covered + Some(Some(Some(0))) => (), + Some(Some(Some(1..=usize::MAX))) => (), + Some(Some(None)) => (), + Some(None) => (), + None => (), + } + + match (A { a: 0usize }) { + //~^ ERROR non-exhaustive patterns: `A { .. }` not covered [E0004] + A { a: 0 } => (), + A { a: 1..=usize::MAX } => (), + } + + match B(0isize, 0usize) { + //~^ ERROR non-exhaustive patterns: `B(_, _)` not covered [E0004] + B(isize::MIN..=isize::MAX, 0) => (), + B(isize::MIN..=isize::MAX, 1..=usize::MAX) => (), + } + + // Should report only the note about usize not having fixed max value and not report + // report the note about isize + match B(0isize, 0usize) { + //~^ ERROR non-exhaustive patterns: `B(_, _)` not covered [E0004] + B(_, 0) => (), + B(_, 1..=usize::MAX) => (), + } +} diff --git a/tests/ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.stderr b/tests/ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.stderr new file mode 100644 index 000000000000..ea1d99e20ae1 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.stderr @@ -0,0 +1,170 @@ +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:8:11 + | +LL | match 0 { + | ^ pattern `_` not covered + | + = note: the matched value is of type `usize` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ 1..=usize::MAX => (), +LL ~ _ => todo!(), + | + +error[E0004]: non-exhaustive patterns: `(_, _)` not covered + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:14:11 + | +LL | match (0usize, 0usize) { + | ^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered + | + = note: the matched value is of type `(usize, usize)` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ (1..=usize::MAX, 1..=usize::MAX) => (), +LL ~ (_, _) => todo!(), + | + +error[E0004]: non-exhaustive patterns: `(_, _)` not covered + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:20:11 + | +LL | match (0isize, 0usize) { + | ^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered + | + = note: the matched value is of type `(isize, usize)` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ (isize::MIN..=isize::MAX, 1..=usize::MAX) => (), +LL ~ (_, _) => todo!(), + | + +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:27:11 + | +LL | match Some(1usize) { + | ^^^^^^^^^^^^ pattern `Some(_)` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => {}, +LL + Some(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:32:11 + | +LL | match Some(4) { + | ^^^^^^^ pattern `Some(_)` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => (), +LL ~ Some(_) => todo!(), + | + +error[E0004]: non-exhaustive patterns: `Some(Some(Some(_)))` not covered + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:39:11 + | +LL | match Some(Some(Some(0))) { + | ^^^^^^^^^^^^^^^^^^^ pattern `Some(Some(Some(_)))` not covered + | +note: `Option>>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + | + = note: not covered + | + = note: not covered + = note: the matched value is of type `Option>>` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => (), +LL ~ Some(Some(Some(_))) => todo!(), + | + +error[E0004]: non-exhaustive patterns: `A { .. }` not covered + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:48:11 + | +LL | match (A { a: 0usize }) { + | ^^^^^^^^^^^^^^^^^ pattern `A { .. }` not covered + | +note: `A` defined here + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:1:8 + | +LL | struct A { + | ^ + = note: the matched value is of type `A` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ A { a: 1..=usize::MAX } => (), +LL ~ A { .. } => todo!(), + | + +error[E0004]: non-exhaustive patterns: `B(_, _)` not covered + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:54:11 + | +LL | match B(0isize, 0usize) { + | ^^^^^^^^^^^^^^^^^ pattern `B(_, _)` not covered + | +note: `B` defined here + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:5:8 + | +LL | struct B(T, U); + | ^ + = note: the matched value is of type `B` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ B(isize::MIN..=isize::MAX, 1..=usize::MAX) => (), +LL ~ B(_, _) => todo!(), + | + +error[E0004]: non-exhaustive patterns: `B(_, _)` not covered + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:62:11 + | +LL | match B(0isize, 0usize) { + | ^^^^^^^^^^^^^^^^^ pattern `B(_, _)` not covered + | +note: `B` defined here + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:5:8 + | +LL | struct B(T, U); + | ^ + = note: the matched value is of type `B` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ B(_, 1..=usize::MAX) => (), +LL ~ B(_, _) => todo!(), + | + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr index b8af566de7c6..d798ec722ddd 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr +++ b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr @@ -10,6 +10,8 @@ note: `Foo` defined here LL | struct Foo { | ^^^ = note: the matched value is of type `Foo` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ Foo { first: false, second: Some([1, 2, 3, 4]) } => (), diff --git a/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr b/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr index e2a65ff85240..50c7fc889f42 100644 --- a/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr +++ b/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr @@ -10,6 +10,8 @@ note: `Foo` defined here LL | struct Foo(isize, isize); | ^^^ = note: the matched value is of type `Foo` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ Foo(2, b) => println!("{}", b), From 887cc48ba8929f7fcc3d43258d5b7c76b1e2f8ea Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 21 Aug 2023 09:21:06 +0200 Subject: [PATCH 094/197] fix help text for rust-analyzer.check.invocation{Strategy,Location} --- crates/rust-analyzer/src/config.rs | 8 ++++---- docs/user/generated_config.adoc | 8 ++++---- editors/code/package.json | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 4a31e0ba0a3d..40c50f6d1768 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -157,15 +157,15 @@ config_data! { /// 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`. + /// This falls back to "root" if `#rust-analyzer.cargo.check.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#` + /// This config only has an effect when `#rust-analyzer.cargo.check.overrideCommand#` /// is set. check_invocationLocation | checkOnSave_invocationLocation: InvocationLocation = "\"workspace\"", - /// Specifies the invocation strategy to use when running the checkOnSave command. + /// Specifies the invocation strategy to use when running the check command. /// 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#` + /// This config only has an effect when `#rust-analyzer.cargo.check.overrideCommand#` /// is set. check_invocationStrategy | checkOnSave_invocationStrategy: InvocationStrategy = "\"per_workspace\"", /// Whether to pass `--no-default-features` to Cargo. Defaults to diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 820535cc1b0d..71feed0f72ca 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -173,18 +173,18 @@ For example for `cargo check`: `dead_code`, `unused_imports`, `unused_variables` -- 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`. + This falls back to "root" if `#rust-analyzer.cargo.check.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#` +This config only has an effect when `#rust-analyzer.cargo.check.overrideCommand#` is set. -- [[rust-analyzer.check.invocationStrategy]]rust-analyzer.check.invocationStrategy (default: `"per_workspace"`):: + -- -Specifies the invocation strategy to use when running the checkOnSave command. +Specifies the invocation strategy to use when running the check command. 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#` +This config only has an effect when `#rust-analyzer.cargo.check.overrideCommand#` is set. -- [[rust-analyzer.check.noDefaultFeatures]]rust-analyzer.check.noDefaultFeatures (default: `null`):: diff --git a/editors/code/package.json b/editors/code/package.json index 83460c82c11c..44f1b81675a5 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -715,7 +715,7 @@ "uniqueItems": true }, "rust-analyzer.check.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.", + "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.check.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.check.overrideCommand#`\nis set.", "default": "workspace", "type": "string", "enum": [ @@ -728,7 +728,7 @@ ] }, "rust-analyzer.check.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.\nIf `once` is set, the command will be executed once.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.", + "markdownDescription": "Specifies the invocation strategy to use when running the check 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.check.overrideCommand#`\nis set.", "default": "per_workspace", "type": "string", "enum": [ From 07b57f9a7a7c532497215e7973ae54d479f68cf9 Mon Sep 17 00:00:00 2001 From: Dmitry Murzin Date: Mon, 21 Aug 2023 12:51:51 +0300 Subject: [PATCH 095/197] Add `suggestion` for some `#[deprecated]` items --- library/alloc/src/lib.rs | 1 + library/alloc/src/slice.rs | 2 +- library/core/src/mem/mod.rs | 4 ++-- library/core/src/str/mod.rs | 2 +- ...issue-84637-deprecated-associated-function.fixed | 2 ++ .../issue-84637-deprecated-associated-function.rs | 2 ++ ...ssue-84637-deprecated-associated-function.stderr | 13 ++++++++++++- 7 files changed, 21 insertions(+), 5 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 967ad3a0e690..9d9743a43782 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -118,6 +118,7 @@ #![feature(const_waker)] #![feature(core_intrinsics)] #![feature(core_panic)] +#![feature(deprecated_suggestion)] #![feature(dispatch_from_dyn)] #![feature(error_generic_member_access)] #![feature(error_in_core)] diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 093dcbbe8bf7..aa3b7b7e1914 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -592,7 +592,7 @@ impl [T] { /// ``` #[rustc_allow_incoherent_impl] #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated(since = "1.3.0", note = "renamed to join")] + #[deprecated(since = "1.3.0", note = "renamed to join", suggestion = "join")] pub fn connect(&self, sep: Separator) -> >::Output where Self: Join, diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 2fff3f0efd73..732fcce0f293 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -413,7 +413,7 @@ pub const unsafe fn size_of_val_raw(val: *const T) -> usize { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(note = "use `align_of` instead", since = "1.2.0")] +#[deprecated(note = "use `align_of` instead", since = "1.2.0", suggestion = "align_of")] pub fn min_align_of() -> usize { intrinsics::min_align_of::() } @@ -436,7 +436,7 @@ pub fn min_align_of() -> usize { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(note = "use `align_of_val` instead", since = "1.2.0")] +#[deprecated(note = "use `align_of_val` instead", since = "1.2.0", suggestion = "align_of_val")] pub fn min_align_of_val(val: &T) -> usize { // SAFETY: val is a reference, so it's a valid raw pointer unsafe { intrinsics::min_align_of_val(val) } diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 9a93bb72903f..5f5d931a2672 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -993,7 +993,7 @@ impl str { /// An iterator over the lines of a string. #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated(since = "1.4.0", note = "use lines() instead now")] + #[deprecated(since = "1.4.0", note = "use lines() instead now", suggestion = "lines")] #[inline] #[allow(deprecated)] pub fn lines_any(&self) -> LinesAny<'_> { diff --git a/tests/ui/deprecation/issue-84637-deprecated-associated-function.fixed b/tests/ui/deprecation/issue-84637-deprecated-associated-function.fixed index 85e882870946..659b54655222 100644 --- a/tests/ui/deprecation/issue-84637-deprecated-associated-function.fixed +++ b/tests/ui/deprecation/issue-84637-deprecated-associated-function.fixed @@ -6,4 +6,6 @@ fn main() { let _foo = str::trim_start(" aoeu"); //~ ERROR use of deprecated method `core::str::::trim_left`: superseded by `trim_start` [deprecated] let _bar = " aoeu".trim_start(); //~ ERROR use of deprecated method `core::str::::trim_left`: superseded by `trim_start` [deprecated] + + let _baz = ["a", "b"].join(" "); //~ ERROR use of deprecated method `std::slice::::connect`: renamed to join [deprecated] } diff --git a/tests/ui/deprecation/issue-84637-deprecated-associated-function.rs b/tests/ui/deprecation/issue-84637-deprecated-associated-function.rs index 246de2f5e4bf..cfc6c4450b4a 100644 --- a/tests/ui/deprecation/issue-84637-deprecated-associated-function.rs +++ b/tests/ui/deprecation/issue-84637-deprecated-associated-function.rs @@ -6,4 +6,6 @@ fn main() { let _foo = str::trim_left(" aoeu"); //~ ERROR use of deprecated method `core::str::::trim_left`: superseded by `trim_start` [deprecated] let _bar = " aoeu".trim_left(); //~ ERROR use of deprecated method `core::str::::trim_left`: superseded by `trim_start` [deprecated] + + let _baz = ["a", "b"].connect(" "); //~ ERROR use of deprecated method `std::slice::::connect`: renamed to join [deprecated] } diff --git a/tests/ui/deprecation/issue-84637-deprecated-associated-function.stderr b/tests/ui/deprecation/issue-84637-deprecated-associated-function.stderr index 3b518d1802bc..d1f5ea3602a8 100644 --- a/tests/ui/deprecation/issue-84637-deprecated-associated-function.stderr +++ b/tests/ui/deprecation/issue-84637-deprecated-associated-function.stderr @@ -25,5 +25,16 @@ help: replace the use of the deprecated method LL | let _bar = " aoeu".trim_start(); | ~~~~~~~~~~ -error: aborting due to 2 previous errors +error: use of deprecated method `std::slice::::connect`: renamed to join + --> $DIR/issue-84637-deprecated-associated-function.rs:10:27 + | +LL | let _baz = ["a", "b"].connect(" "); + | ^^^^^^^ + | +help: replace the use of the deprecated method + | +LL | let _baz = ["a", "b"].join(" "); + | ~~~~ + +error: aborting due to 3 previous errors From fd2982c0a7bf1bc52685547849ba1d96c93d69c9 Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Mon, 21 Aug 2023 18:45:02 +0700 Subject: [PATCH 096/197] Fix syntax in E0191 explanation. This trait needs `dyn` in modern Rust. Fixes #115042. --- compiler/rustc_error_codes/src/error_codes/E0191.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0191.md b/compiler/rustc_error_codes/src/error_codes/E0191.md index 46b773bdc50d..344ac221698a 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0191.md +++ b/compiler/rustc_error_codes/src/error_codes/E0191.md @@ -7,8 +7,8 @@ trait Trait { type Bar; } -type Foo = Trait; // error: the value of the associated type `Bar` (from - // the trait `Trait`) must be specified +type Foo = dyn Trait; // error: the value of the associated type `Bar` (from + // the trait `Trait`) must be specified ``` Trait objects need to have all associated types specified. Please verify that @@ -20,5 +20,5 @@ trait Trait { type Bar; } -type Foo = Trait; // ok! +type Foo = dyn Trait; // ok! ``` From 44cc3105b13f0e2dcc9aec8d019dc40011104bc5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 21 Aug 2023 09:55:27 +0200 Subject: [PATCH 097/197] stable_mir: docs clarification --- compiler/rustc_smir/src/stable_mir/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs index 19061742b64b..2ae334c6a959 100644 --- a/compiler/rustc_smir/src/stable_mir/mod.rs +++ b/compiler/rustc_smir/src/stable_mir/mod.rs @@ -1,6 +1,6 @@ //! Module that implements the public interface to the Stable MIR. //! -//! This module shall contain all type definitions and APIs that we expect 3P tools to invoke to +//! This module shall contain all type definitions and APIs that we expect third-party tools to invoke to //! interact with the compiler. //! //! The goal is to eventually move this module to its own crate which shall be published on From dfbac25fbadd9f417ac207838cae291c6cbc6f46 Mon Sep 17 00:00:00 2001 From: Christiaan Biesterbosch Date: Mon, 21 Aug 2023 14:25:57 +0200 Subject: [PATCH 098/197] Fix table issues in platform support documentation --- src/doc/rustc/src/platform-support.md | 6 +++--- src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 371ee378d1ac..bd33b8fb6ccd 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -271,8 +271,8 @@ target | std | host | notes `i686-uwp-windows-gnu` | ? | | `i686-uwp-windows-msvc` | ? | | `i686-wrs-vxworks` | ? | | -[`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * | LoongArch64 Bare-metal (LP64D ABI) -[`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | LoongArch64 Bare-metal (LP64S ABI) +[`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64D ABI) +[`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64S ABI) [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? | | Motorola 680x0 Linux `mips-unknown-linux-uclibc` | ✓ | | MIPS Linux with uClibc [`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? | | MIPS64 for OpenWrt Linux MUSL @@ -321,7 +321,7 @@ target | std | host | notes `thumbv7a-pc-windows-msvc` | ? | | `thumbv7a-uwp-windows-msvc` | ✓ | | `thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7-A Linux with NEON, MUSL -[`wasm32-wasi-preview1-threads`](platform-support/wasm32-wasi-preview1-threads.md) | ✓ | WebAssembly with WASI Preview 1 and threads +[`wasm32-wasi-preview1-threads`](platform-support/wasm32-wasi-preview1-threads.md) | ✓ | | WebAssembly with WASI Preview 1 and threads [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly `x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64 [`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ? | | x86 64-bit tvOS diff --git a/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md index 8bc9381342dd..f8cd92f9257e 100644 --- a/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md +++ b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md @@ -8,6 +8,7 @@ TEEOS is a mini os run in TrustZone, for trusted/security apps. The kernel of TE It's very small that there is no RwLock, no network, no stdin, and no file system for apps in TEEOS. Some abbreviation: + | Abbreviation | The full text | Description | | ---- | ---- | ---- | | TEE | Trusted Execution Environment | ARM TrustZone divides the system into two worlds/modes -- the secure world/mode and the normal world/mode. TEE is in the secure world/mode. | From 53245709f68280943b4d2a3995883fc1b90087f9 Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Mon, 21 Aug 2023 18:32:58 +0700 Subject: [PATCH 099/197] docs: Add example, reference link for `type` keyword. Fixes #114281. --- library/std/src/keyword_docs.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index eb46f4e54bb6..873bfb6218b6 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -1820,7 +1820,7 @@ mod true_keyword {} #[doc(keyword = "type")] // -/// Define an alias for an existing type. +/// Define an [alias] for an existing type. /// /// The syntax is `type Name = ExistingType;`. /// @@ -1838,6 +1838,13 @@ mod true_keyword {} /// assert_eq!(m, k); /// ``` /// +/// A type can be generic: +/// +/// ```rust +/// # use std::sync::{Arc, Mutex}; +/// type ArcMutex = Arc>; +/// ``` +/// /// In traits, `type` is used to declare an [associated type]: /// /// ```rust @@ -1860,6 +1867,7 @@ mod true_keyword {} /// /// [`trait`]: keyword.trait.html /// [associated type]: ../reference/items/associated-items.html#associated-types +/// [alias]: ../reference/items/type-aliases.html mod type_keyword {} #[doc(keyword = "unsafe")] From 5dce0e66b9424ed1070e5b37ca21ffee62957595 Mon Sep 17 00:00:00 2001 From: allaboutevemirolive Date: Mon, 21 Aug 2023 13:31:58 -0400 Subject: [PATCH 100/197] Redefine the pluralize macro's arm --- compiler/rustc_lint_defs/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index f350957f72f1..1d0e367abba3 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -23,8 +23,9 @@ pub mod builtin; #[macro_export] macro_rules! pluralize { + // Pluralize based on count (e.g., apples) ($x:expr) => { - if $x != 1 { "s" } else { "" } + if $x == 1 { "" } else { "s" } }; ("has", $x:expr) => { if $x == 1 { "has" } else { "have" } From 88bd304a1000be95e15c319ca79564e168ba02c3 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 21 Aug 2023 10:06:05 -0700 Subject: [PATCH 101/197] docs: add alias log1p to ln_1p This is what the function is called in several other languages: * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/log1p * https://numpy.org/doc/stable/reference/generated/numpy.log1p.html * https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/log1p-log1pf-log1pl2?view=msvc-170 It also confused people at URLO: https://users.rust-lang.org/t/64-bit-trigonometry/98599/27 --- library/std/src/f32.rs | 1 + library/std/src/f64.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index a659b552f473..776899dbcfd6 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -822,6 +822,7 @@ impl f32 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[doc(alias = "log1p")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index 721e1fb754e1..4f4f5f024718 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -822,6 +822,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-20); /// ``` + #[doc(alias = "log1p")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] From ea9e442222ed256c8ac70693d5966dd9fe2bde4b Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Mon, 21 Aug 2023 12:53:39 -0700 Subject: [PATCH 102/197] rustdoc: Rename "Type Definition" to "Type Alias" This matches the name used by the Rust Reference [1], which is also what people usually call these items. [1]: https://doc.rust-lang.org/reference/items/type-aliases.html --- src/librustdoc/html/render/mod.rs | 2 +- src/librustdoc/html/render/print_item.rs | 2 +- src/librustdoc/html/static/js/main.js | 2 +- tests/rustdoc/issue-105735-overlapping-reexport-2.rs | 2 +- tests/rustdoc/issue-109449-doc-hidden-reexports.rs | 6 +++--- tests/rustdoc/sidebar-all-page.rs | 5 ++--- tests/rustdoc/titles.rs | 2 +- 7 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index ac9c180a6a86..0eddaec2999a 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2123,7 +2123,7 @@ impl ItemSection { Self::Unions => "Unions", Self::Enums => "Enums", Self::Functions => "Functions", - Self::TypeDefinitions => "Type Definitions", + Self::TypeDefinitions => "Type Aliases", Self::Statics => "Statics", Self::Constants => "Constants", Self::Traits => "Traits", diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 6cab34986223..a4af1c25cfcc 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -198,7 +198,7 @@ pub(super) fn print_item( clean::StructItem(..) => "Struct ", clean::UnionItem(..) => "Union ", clean::EnumItem(..) => "Enum ", - clean::TypedefItem(..) => "Type Definition ", + clean::TypedefItem(..) => "Type Alias ", clean::MacroItem(..) => "Macro ", clean::ProcMacroItem(ref mac) => match mac.kind { MacroKind::Bang => "Macro ", diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 254b0d8bf5a4..cb653d6b8dfd 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -499,7 +499,7 @@ function preLoadCss(cssUrl) { block("static", "static", "Statics"); block("trait", "traits", "Traits"); block("fn", "functions", "Functions"); - block("type", "types", "Type Definitions"); + block("type", "types", "Type Aliases"); block("foreigntype", "foreign-types", "Foreign Types"); block("keyword", "keywords", "Keywords"); block("traitalias", "trait-aliases", "Trait Aliases"); diff --git a/tests/rustdoc/issue-105735-overlapping-reexport-2.rs b/tests/rustdoc/issue-105735-overlapping-reexport-2.rs index 910824839489..5d2c553d8a51 100644 --- a/tests/rustdoc/issue-105735-overlapping-reexport-2.rs +++ b/tests/rustdoc/issue-105735-overlapping-reexport-2.rs @@ -8,7 +8,7 @@ // @has - '//*[@class="item-name"]/a[@class="constant"]' 'AtomicU8' // We also ensure we don't have another item displayed. // @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 2 -// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Type Definitions' +// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Type Aliases' // @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Constants' mod other { diff --git a/tests/rustdoc/issue-109449-doc-hidden-reexports.rs b/tests/rustdoc/issue-109449-doc-hidden-reexports.rs index b0c225401804..3b836a219312 100644 --- a/tests/rustdoc/issue-109449-doc-hidden-reexports.rs +++ b/tests/rustdoc/issue-109449-doc-hidden-reexports.rs @@ -104,7 +104,7 @@ pub mod glob_reexport { // @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 3 // @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Re-exports' // @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Structs' - // @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Type Definitions' + // @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Type Aliases' // Now we check we have 1 re-export and 2 inlined items. // If not item from a glob re-export is visible, we don't show the re-export. @@ -135,9 +135,9 @@ pub mod doc_hidden_reexport { // @has - '//a[@class="struct"]' 'Reexport' // Check that the `#[doc(hidden)]` re-export's attributes are not taken into account. // @has - '//*[@class="desc docblock-short"]' 'Visible. Original.' + /// Visible. + pub use self::Bar3 as Reexport; /// Hidden. #[doc(hidden)] pub use crate::private::Bar3; - /// Visible. - pub use self::Bar3 as Reexport; } diff --git a/tests/rustdoc/sidebar-all-page.rs b/tests/rustdoc/sidebar-all-page.rs index 45a6ba8ed2e1..4c8a0f543a56 100644 --- a/tests/rustdoc/sidebar-all-page.rs +++ b/tests/rustdoc/sidebar-all-page.rs @@ -1,5 +1,4 @@ #![crate_name = "foo"] - #![feature(rustc_attrs)] // @has 'foo/all.html' @@ -9,7 +8,7 @@ // @has - '//*[@class="sidebar-elems"]//li' 'Functions' // @has - '//*[@class="sidebar-elems"]//li' 'Traits' // @has - '//*[@class="sidebar-elems"]//li' 'Macros' -// @has - '//*[@class="sidebar-elems"]//li' 'Type Definitions' +// @has - '//*[@class="sidebar-elems"]//li' 'Type Aliases' // @has - '//*[@class="sidebar-elems"]//li' 'Constants' // @has - '//*[@class="sidebar-elems"]//li' 'Statics' // @has - '//*[@class="sidebar-elems"]//li' 'Primitive Types' @@ -26,7 +25,7 @@ pub fn foo() {} pub trait Trait {} #[macro_export] macro_rules! foo { - () => {} + () => {}; } pub type Type = u8; pub const FOO: u8 = 0; diff --git a/tests/rustdoc/titles.rs b/tests/rustdoc/titles.rs index e1feb1cd64fe..f6a059de620a 100644 --- a/tests/rustdoc/titles.rs +++ b/tests/rustdoc/titles.rs @@ -30,7 +30,7 @@ pub struct FooStruct; // @matches 'foo/enum.FooEnum.html' '//h2[@class="location"]' 'FooEnum' pub enum FooEnum {} -// @matches 'foo/type.FooType.html' '//h1' 'Type Definition foo::FooType' +// @matches 'foo/type.FooType.html' '//h1' 'Type Alias foo::FooType' // @matches 'foo/type.FooType.html' '//h2[@class="location"]' 'FooType' pub type FooType = FooStruct; From bf766cd31bf045dfe7f37d4146f36aff001438ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 21 Aug 2023 19:59:27 +0000 Subject: [PATCH 103/197] Add test for #115019 --- .../overlaping-bound-suggestion.rs | 12 ++++++++ .../overlaping-bound-suggestion.stderr | 29 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 tests/ui/associated-type-bounds/overlaping-bound-suggestion.rs create mode 100644 tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr diff --git a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.rs b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.rs new file mode 100644 index 000000000000..3853bc8594fa --- /dev/null +++ b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.rs @@ -0,0 +1,12 @@ +#![allow(bare_trait_objects)] +#![feature(associated_type_bounds)] +trait Item { + type Core; +} +pub struct Flatten { + inner: >::IntoIterator as Item>::Core, + //~^ ERROR E0191 + //~| ERROR E0223 +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr new file mode 100644 index 000000000000..8bea440ddbad --- /dev/null +++ b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr @@ -0,0 +1,29 @@ +error[E0191]: the value of the associated types `IntoIter` (from trait `IntoIterator`), `IntoIter` (from trait `IntoIterator`), `Item` (from trait `IntoIterator`), `Item` (from trait `IntoIterator`) must be specified + --> $DIR/overlaping-bound-suggestion.rs:7:13 + | +LL | inner: >::IntoIterator as Item>::Core, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | associated types `Item`, `IntoIter` must be specified + | associated types `Item`, `IntoIter` must be specified + | +help: specify the associated types + | +LL | inner: , Item = Type, IntoIter = Type>IntoIterator>::IntoIterator as Item>::Core, + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/overlaping-bound-suggestion.rs:7:13 + | +LL | inner: >::IntoIterator as Item>::Core, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `IntoIterator` implemented for `(dyn IntoIterator + 'static)`, you could use the fully-qualified path + | +LL | inner: <<(dyn IntoIterator + 'static) as Example>::IntoIterator as Item>::Core, + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0191, E0223. +For more information about an error, try `rustc --explain E0191`. From 89e6597dfe12b40c72ca4c3d479568e3a4ec1e7a Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 21 Aug 2023 13:13:44 -0700 Subject: [PATCH 104/197] Reassign sparc-unknown-none-elf to tier 3 It should never have been moved to tier 2. It is a new platform and the maintainer has agreed to do tier 3 maintenance for it, not tier 2. --- src/doc/rustc/src/platform-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 371ee378d1ac..206471d90351 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -176,7 +176,6 @@ target | std | notes `thumbv8m.base-none-eabi` | * | Bare ARMv8-M Baseline `thumbv8m.main-none-eabi` | * | Bare ARMv8-M Mainline `thumbv8m.main-none-eabihf` | * | Bare ARMv8-M Mainline, hardfloat -[`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | Bare 32-bit SPARC V7+ `wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten `wasm32-unknown-unknown` | ✓ | WebAssembly `wasm32-wasi` | ✓ | WebAssembly with WASI @@ -314,6 +313,7 @@ target | std | host | notes [`riscv64-linux-android`](platform-support/android.md) | | | RISC-V 64-bit Android `s390x-unknown-linux-musl` | | | S390x Linux (kernel 3.2, MUSL) `sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux +[`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | Bare 32-bit SPARC V7+ [`sparc64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/sparc64 [`sparc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/sparc64 `thumbv4t-none-eabi` | * | | Thumb-mode Bare ARMv4T From 062d247cd795847be51df9e3f818f0eb52ac0d18 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Mon, 21 Aug 2023 13:56:22 -0700 Subject: [PATCH 105/197] rustdoc: Rename `clean` items from typedef to type alias --- src/librustdoc/clean/inline.rs | 8 ++++---- src/librustdoc/clean/mod.rs | 14 +++++++++----- src/librustdoc/clean/types.rs | 14 +++++++------- src/librustdoc/fold.rs | 2 +- src/librustdoc/formats/cache.rs | 2 +- src/librustdoc/formats/item_type.rs | 8 ++++---- src/librustdoc/html/render/mod.rs | 18 +++++++++--------- src/librustdoc/html/render/print_item.rs | 10 +++++----- src/librustdoc/html/render/sidebar.rs | 8 ++++---- src/librustdoc/json/conversions.rs | 10 +++++----- .../passes/check_doc_test_visibility.rs | 2 +- src/librustdoc/passes/stripper.rs | 2 +- src/librustdoc/visit.rs | 2 +- 13 files changed, 52 insertions(+), 48 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index cac211307404..cc86a3d74757 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -80,9 +80,9 @@ pub(crate) fn try_inline( clean::UnionItem(build_union(cx, did)) } Res::Def(DefKind::TyAlias { .. }, did) => { - record_extern_fqn(cx, did, ItemType::Typedef); + record_extern_fqn(cx, did, ItemType::TypeAlias); build_impls(cx, did, attrs_without_docs, &mut ret); - clean::TypedefItem(build_type_alias(cx, did)) + clean::TypeAliasItem(build_type_alias(cx, did)) } Res::Def(DefKind::Enum, did) => { record_extern_fqn(cx, did, ItemType::Enum); @@ -287,7 +287,7 @@ fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union { clean::Union { generics, fields } } -fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> Box { +fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> Box { let predicates = cx.tcx.explicit_predicates_of(did); let type_ = clean_middle_ty( ty::Binder::dummy(cx.tcx.type_of(did).instantiate_identity()), @@ -296,7 +296,7 @@ fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> Box None, ); - Box::new(clean::Typedef { + Box::new(clean::TypeAlias { type_, generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates), item_type: None, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ee1d0be27bfd..1e85284371db 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1219,7 +1219,7 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext None, ); AssocTypeItem( - Box::new(Typedef { + Box::new(TypeAlias { type_: clean_ty(default, cx), generics, item_type: Some(item_type), @@ -1264,7 +1264,7 @@ pub(crate) fn clean_impl_item<'tcx>( None, ); AssocTypeItem( - Box::new(Typedef { type_, generics, item_type: Some(item_type) }), + Box::new(TypeAlias { type_, generics, item_type: Some(item_type) }), Vec::new(), ) } @@ -1461,7 +1461,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( if tcx.defaultness(assoc_item.def_id).has_value() { AssocTypeItem( - Box::new(Typedef { + Box::new(TypeAlias { type_: clean_middle_ty( ty::Binder::dummy( tcx.type_of(assoc_item.def_id).instantiate_identity(), @@ -1480,7 +1480,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( } } else { AssocTypeItem( - Box::new(Typedef { + Box::new(TypeAlias { type_: clean_middle_ty( ty::Binder::dummy( tcx.type_of(assoc_item.def_id).instantiate_identity(), @@ -2617,7 +2617,11 @@ fn clean_maybe_renamed_item<'tcx>( cx.current_type_aliases.remove(&def_id); } } - TypedefItem(Box::new(Typedef { type_: rustdoc_ty, generics, item_type: Some(ty) })) + TypeAliasItem(Box::new(TypeAlias { + type_: rustdoc_ty, + generics, + item_type: Some(ty), + })) } ItemKind::Enum(ref def, generics) => EnumItem(Enum { variants: def.variants.iter().map(|v| clean_variant(v, cx)).collect(), diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 49bde1d31526..9cf3c068b602 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -530,8 +530,8 @@ impl Item { pub(crate) fn is_ty_method(&self) -> bool { self.type_() == ItemType::TyMethod } - pub(crate) fn is_typedef(&self) -> bool { - self.type_() == ItemType::Typedef + pub(crate) fn is_type_alias(&self) -> bool { + self.type_() == ItemType::TypeAlias } pub(crate) fn is_primitive(&self) -> bool { self.type_() == ItemType::Primitive @@ -799,7 +799,7 @@ pub(crate) enum ItemKind { EnumItem(Enum), FunctionItem(Box), ModuleItem(Module), - TypedefItem(Box), + TypeAliasItem(Box), OpaqueTyItem(OpaqueTy), StaticItem(Static), ConstantItem(Constant), @@ -832,7 +832,7 @@ pub(crate) enum ItemKind { /// The bounds may be non-empty if there is a `where` clause. TyAssocTypeItem(Generics, Vec), /// An associated type in a trait impl or a provided one in a trait declaration. - AssocTypeItem(Box, Vec), + AssocTypeItem(Box, Vec), /// An item that has been stripped by a rustdoc pass StrippedItem(Box), KeywordItem, @@ -857,7 +857,7 @@ impl ItemKind { ExternCrateItem { .. } | ImportItem(_) | FunctionItem(_) - | TypedefItem(_) + | TypeAliasItem(_) | OpaqueTyItem(_) | StaticItem(_) | ConstantItem(_) @@ -891,7 +891,7 @@ impl ItemKind { | ModuleItem(_) | ExternCrateItem { .. } | FunctionItem(_) - | TypedefItem(_) + | TypeAliasItem(_) | OpaqueTyItem(_) | StaticItem(_) | ConstantItem(_) @@ -2230,7 +2230,7 @@ pub(crate) struct PathSegment { } #[derive(Clone, Debug)] -pub(crate) struct Typedef { +pub(crate) struct TypeAlias { pub(crate) type_: Type, pub(crate) generics: Generics, /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index 656aeefb01a4..ceba643ed5f0 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -55,7 +55,7 @@ pub(crate) trait DocFolder: Sized { ExternCrateItem { src: _ } | ImportItem(_) | FunctionItem(_) - | TypedefItem(_) + | TypeAliasItem(_) | OpaqueTyItem(_) | StaticItem(_) | ConstantItem(_) diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index d1deda0c7164..9a34e7cce8ad 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -389,7 +389,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { match *item.kind { clean::StructItem(..) | clean::EnumItem(..) - | clean::TypedefItem(..) + | clean::TypeAliasItem(..) | clean::TraitItem(..) | clean::TraitAliasItem(..) | clean::FunctionItem(..) diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index a788935581fa..fd79160ff4a8 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -29,7 +29,7 @@ pub(crate) enum ItemType { Struct = 3, Enum = 4, Function = 5, - Typedef = 6, + TypeAlias = 6, Static = 7, Trait = 8, Impl = 9, @@ -75,7 +75,7 @@ impl<'a> From<&'a clean::Item> for ItemType { clean::UnionItem(..) => ItemType::Union, clean::EnumItem(..) => ItemType::Enum, clean::FunctionItem(..) => ItemType::Function, - clean::TypedefItem(..) => ItemType::Typedef, + clean::TypeAliasItem(..) => ItemType::TypeAlias, clean::OpaqueTyItem(..) => ItemType::OpaqueTy, clean::StaticItem(..) => ItemType::Static, clean::ConstantItem(..) => ItemType::Constant, @@ -115,7 +115,7 @@ impl From for ItemType { DefKind::Struct => Self::Struct, DefKind::Union => Self::Union, DefKind::Trait => Self::Trait, - DefKind::TyAlias { .. } => Self::Typedef, + DefKind::TyAlias { .. } => Self::TypeAlias, DefKind::TraitAlias => Self::TraitAlias, DefKind::Macro(kind) => match kind { MacroKind::Bang => ItemType::Macro, @@ -156,7 +156,7 @@ impl ItemType { ItemType::Union => "union", ItemType::Enum => "enum", ItemType::Function => "fn", - ItemType::Typedef => "type", + ItemType::TypeAlias => "type", ItemType::Static => "static", ItemType::Trait => "trait", ItemType::Impl => "impl", diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 0eddaec2999a..a98b59c61811 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -279,7 +279,7 @@ impl AllTypes { ItemType::Trait => self.traits.insert(ItemEntry::new(new_url, name)), ItemType::Macro => self.macros.insert(ItemEntry::new(new_url, name)), ItemType::Function => self.functions.insert(ItemEntry::new(new_url, name)), - ItemType::Typedef => self.typedefs.insert(ItemEntry::new(new_url, name)), + ItemType::TypeAlias => self.typedefs.insert(ItemEntry::new(new_url, name)), ItemType::OpaqueTy => self.opaque_tys.insert(ItemEntry::new(new_url, name)), ItemType::Static => self.statics.insert(ItemEntry::new(new_url, name)), ItemType::Constant => self.constants.insert(ItemEntry::new(new_url, name)), @@ -318,7 +318,7 @@ impl AllTypes { sections.insert(ItemSection::Functions); } if !self.typedefs.is_empty() { - sections.insert(ItemSection::TypeDefinitions); + sections.insert(ItemSection::TypeAliases); } if !self.opaque_tys.is_empty() { sections.insert(ItemSection::OpaqueTypes); @@ -374,7 +374,7 @@ impl AllTypes { print_entries(f, &self.attribute_macros, ItemSection::AttributeMacros); print_entries(f, &self.derive_macros, ItemSection::DeriveMacros); print_entries(f, &self.functions, ItemSection::Functions); - print_entries(f, &self.typedefs, ItemSection::TypeDefinitions); + print_entries(f, &self.typedefs, ItemSection::TypeAliases); print_entries(f, &self.trait_aliases, ItemSection::TraitAliases); print_entries(f, &self.opaque_tys, ItemSection::OpaqueTypes); print_entries(f, &self.statics, ItemSection::Statics); @@ -1237,7 +1237,7 @@ fn render_deref_methods( .iter() .find_map(|item| match *item.kind { clean::AssocTypeItem(box ref t, _) => Some(match *t { - clean::Typedef { item_type: Some(ref type_), .. } => (type_, &t.type_), + clean::TypeAlias { item_type: Some(ref type_), .. } => (type_, &t.type_), _ => (&t.type_, &t.type_), }), _ => None, @@ -2035,7 +2035,7 @@ pub(crate) enum ItemSection { Statics, Traits, Functions, - TypeDefinitions, + TypeAliases, Unions, Implementations, TypeMethods, @@ -2067,7 +2067,7 @@ impl ItemSection { Statics, Traits, Functions, - TypeDefinitions, + TypeAliases, Unions, Implementations, TypeMethods, @@ -2093,7 +2093,7 @@ impl ItemSection { Self::Unions => "unions", Self::Enums => "enums", Self::Functions => "functions", - Self::TypeDefinitions => "types", + Self::TypeAliases => "types", Self::Statics => "statics", Self::Constants => "constants", Self::Traits => "traits", @@ -2123,7 +2123,7 @@ impl ItemSection { Self::Unions => "Unions", Self::Enums => "Enums", Self::Functions => "Functions", - Self::TypeDefinitions => "Type Aliases", + Self::TypeAliases => "Type Aliases", Self::Statics => "Statics", Self::Constants => "Constants", Self::Traits => "Traits", @@ -2154,7 +2154,7 @@ fn item_ty_to_section(ty: ItemType) -> ItemSection { ItemType::Union => ItemSection::Unions, ItemType::Enum => ItemSection::Enums, ItemType::Function => ItemSection::Functions, - ItemType::Typedef => ItemSection::TypeDefinitions, + ItemType::TypeAlias => ItemSection::TypeAliases, ItemType::Static => ItemSection::Statics, ItemType::Constant => ItemSection::Constants, ItemType::Trait => ItemSection::Traits, diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index a4af1c25cfcc..cb78f903462c 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -198,7 +198,7 @@ pub(super) fn print_item( clean::StructItem(..) => "Struct ", clean::UnionItem(..) => "Union ", clean::EnumItem(..) => "Enum ", - clean::TypedefItem(..) => "Type Alias ", + clean::TypeAliasItem(..) => "Type Alias ", clean::MacroItem(..) => "Macro ", clean::ProcMacroItem(ref mac) => match mac.kind { MacroKind::Bang => "Macro ", @@ -273,7 +273,7 @@ pub(super) fn print_item( clean::StructItem(ref s) => item_struct(buf, cx, item, s), clean::UnionItem(ref s) => item_union(buf, cx, item, s), clean::EnumItem(ref e) => item_enum(buf, cx, item, e), - clean::TypedefItem(ref t) => item_typedef(buf, cx, item, t), + clean::TypeAliasItem(ref t) => item_type_alias(buf, cx, item, t), clean::MacroItem(ref m) => item_macro(buf, cx, item, m), clean::ProcMacroItem(ref m) => item_proc_macro(buf, cx, item, m), clean::PrimitiveItem(_) => item_primitive(buf, cx, item), @@ -343,7 +343,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: ItemType::Static => 8, ItemType::Trait => 9, ItemType::Function => 10, - ItemType::Typedef => 12, + ItemType::TypeAlias => 12, ItemType::Union => 13, _ => 14 + ty as u8, } @@ -1217,8 +1217,8 @@ fn item_opaque_ty( .unwrap(); } -fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Typedef) { - fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) { +fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TypeAlias) { + fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) { wrap_item(w, |w| { write!( w, diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index f3da610565c4..b96b1536156c 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -82,7 +82,7 @@ pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buf clean::PrimitiveItem(_) => sidebar_primitive(cx, it), clean::UnionItem(ref u) => sidebar_union(cx, it, u), clean::EnumItem(ref e) => sidebar_enum(cx, it, e), - clean::TypedefItem(_) => sidebar_typedef(cx, it), + clean::TypeAliasItem(_) => sidebar_type_alias(cx, it), clean::ModuleItem(ref m) => vec![sidebar_module(&m.items)], clean::ForeignTypeItem => sidebar_foreign_type(cx, it), _ => vec![], @@ -100,7 +100,7 @@ pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buf || it.is_union() || it.is_enum() || it.is_mod() - || it.is_typedef() + || it.is_type_alias() { ( match *it.kind { @@ -230,7 +230,7 @@ fn sidebar_primitive<'a>(cx: &'a Context<'_>, it: &'a clean::Item) -> Vec(cx: &'a Context<'_>, it: &'a clean::Item) -> Vec> { +fn sidebar_type_alias<'a>(cx: &'a Context<'_>, it: &'a clean::Item) -> Vec> { let mut items = vec![]; sidebar_assoc_items(cx, it, &mut items); items @@ -334,7 +334,7 @@ fn sidebar_deref_methods<'a>( if let Some((target, real_target)) = impl_.inner_impl().items.iter().find_map(|item| match *item.kind { clean::AssocTypeItem(box ref t, _) => Some(match *t { - clean::Typedef { item_type: Some(ref type_), .. } => (type_, &t.type_), + clean::TypeAlias { item_type: Some(ref type_), .. } => (type_, &t.type_), _ => (&t.type_, &t.type_), }), _ => None, diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 8673138f6496..f857a4c8a49f 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -311,7 +311,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { StaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)), ForeignStaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)), ForeignTypeItem => ItemEnum::ForeignType, - TypedefItem(t) => ItemEnum::Typedef(t.into_tcx(tcx)), + TypeAliasItem(t) => ItemEnum::Typedef(t.into_tcx(tcx)), OpaqueTyItem(t) => ItemEnum::OpaqueTy(t.into_tcx(tcx)), ConstantItem(c) => ItemEnum::Constant(c.into_tcx(tcx)), MacroItem(m) => ItemEnum::Macro(m.source), @@ -787,9 +787,9 @@ pub(crate) fn from_macro_kind(kind: rustc_span::hygiene::MacroKind) -> MacroKind } } -impl FromWithTcx> for Typedef { - fn from_tcx(typedef: Box, tcx: TyCtxt<'_>) -> Self { - let clean::Typedef { type_, generics, item_type: _ } = *typedef; +impl FromWithTcx> for Typedef { + fn from_tcx(typedef: Box, tcx: TyCtxt<'_>) -> Self { + let clean::TypeAlias { type_, generics, item_type: _ } = *typedef; Typedef { type_: type_.into_tcx(tcx), generics: generics.into_tcx(tcx) } } } @@ -827,7 +827,7 @@ impl FromWithTcx for ItemKind { Union => ItemKind::Union, Enum => ItemKind::Enum, Function | TyMethod | Method => ItemKind::Function, - Typedef => ItemKind::Typedef, + TypeAlias => ItemKind::Typedef, OpaqueTy => ItemKind::OpaqueTy, Static => ItemKind::Static, Constant => ItemKind::Constant, diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index e732a4057606..96224d7c6e2e 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -60,7 +60,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - | clean::VariantItem(_) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) - | clean::TypedefItem(_) + | clean::TypeAliasItem(_) | clean::StaticItem(_) | clean::ConstantItem(_) | clean::ExternCrateItem { .. } diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index 64a4ace5b9f8..b35618415943 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -49,7 +49,7 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { } // These items can all get re-exported clean::OpaqueTyItem(..) - | clean::TypedefItem(..) + | clean::TypeAliasItem(..) | clean::StaticItem(..) | clean::StructItem(..) | clean::EnumItem(..) diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs index 390b94361219..01e6cb4b93bf 100644 --- a/src/librustdoc/visit.rs +++ b/src/librustdoc/visit.rs @@ -25,7 +25,7 @@ pub(crate) trait DocVisitor: Sized { ExternCrateItem { src: _ } | ImportItem(_) | FunctionItem(_) - | TypedefItem(_) + | TypeAliasItem(_) | OpaqueTyItem(_) | StaticItem(_) | ConstantItem(_) From c90a5b2019e5a862c8fb5ae39dcf6ad5f4c65b09 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Mon, 21 Aug 2023 14:01:26 -0700 Subject: [PATCH 106/197] rustdoc-json: Rename typedef to type alias --- src/librustdoc/html/render/mod.rs | 10 +++++----- src/librustdoc/json/conversions.rs | 12 ++++++------ src/librustdoc/json/mod.rs | 2 +- src/rustdoc-json-types/lib.rs | 8 ++++---- src/tools/jsondoclint/src/item_kind.rs | 4 ++-- src/tools/jsondoclint/src/validator.rs | 6 +++--- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index a98b59c61811..aef8f1a74fb5 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -235,7 +235,7 @@ struct AllTypes { traits: FxHashSet, macros: FxHashSet, functions: FxHashSet, - typedefs: FxHashSet, + type_aliases: FxHashSet, opaque_tys: FxHashSet, statics: FxHashSet, constants: FxHashSet, @@ -255,7 +255,7 @@ impl AllTypes { traits: new_set(100), macros: new_set(100), functions: new_set(100), - typedefs: new_set(100), + type_aliases: new_set(100), opaque_tys: new_set(100), statics: new_set(100), constants: new_set(100), @@ -279,7 +279,7 @@ impl AllTypes { ItemType::Trait => self.traits.insert(ItemEntry::new(new_url, name)), ItemType::Macro => self.macros.insert(ItemEntry::new(new_url, name)), ItemType::Function => self.functions.insert(ItemEntry::new(new_url, name)), - ItemType::TypeAlias => self.typedefs.insert(ItemEntry::new(new_url, name)), + ItemType::TypeAlias => self.type_aliases.insert(ItemEntry::new(new_url, name)), ItemType::OpaqueTy => self.opaque_tys.insert(ItemEntry::new(new_url, name)), ItemType::Static => self.statics.insert(ItemEntry::new(new_url, name)), ItemType::Constant => self.constants.insert(ItemEntry::new(new_url, name)), @@ -317,7 +317,7 @@ impl AllTypes { if !self.functions.is_empty() { sections.insert(ItemSection::Functions); } - if !self.typedefs.is_empty() { + if !self.type_aliases.is_empty() { sections.insert(ItemSection::TypeAliases); } if !self.opaque_tys.is_empty() { @@ -374,7 +374,7 @@ impl AllTypes { print_entries(f, &self.attribute_macros, ItemSection::AttributeMacros); print_entries(f, &self.derive_macros, ItemSection::DeriveMacros); print_entries(f, &self.functions, ItemSection::Functions); - print_entries(f, &self.typedefs, ItemSection::TypeAliases); + print_entries(f, &self.type_aliases, ItemSection::TypeAliases); print_entries(f, &self.trait_aliases, ItemSection::TraitAliases); print_entries(f, &self.opaque_tys, ItemSection::OpaqueTypes); print_entries(f, &self.statics, ItemSection::Statics); diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index f857a4c8a49f..66b5798797f6 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -311,7 +311,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { StaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)), ForeignStaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)), ForeignTypeItem => ItemEnum::ForeignType, - TypeAliasItem(t) => ItemEnum::Typedef(t.into_tcx(tcx)), + TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_tcx(tcx)), OpaqueTyItem(t) => ItemEnum::OpaqueTy(t.into_tcx(tcx)), ConstantItem(c) => ItemEnum::Constant(c.into_tcx(tcx)), MacroItem(m) => ItemEnum::Macro(m.source), @@ -787,10 +787,10 @@ pub(crate) fn from_macro_kind(kind: rustc_span::hygiene::MacroKind) -> MacroKind } } -impl FromWithTcx> for Typedef { - fn from_tcx(typedef: Box, tcx: TyCtxt<'_>) -> Self { - let clean::TypeAlias { type_, generics, item_type: _ } = *typedef; - Typedef { type_: type_.into_tcx(tcx), generics: generics.into_tcx(tcx) } +impl FromWithTcx> for TypeAlias { + fn from_tcx(type_alias: Box, tcx: TyCtxt<'_>) -> Self { + let clean::TypeAlias { type_, generics, item_type: _ } = *type_alias; + TypeAlias { type_: type_.into_tcx(tcx), generics: generics.into_tcx(tcx) } } } @@ -827,7 +827,7 @@ impl FromWithTcx for ItemKind { Union => ItemKind::Union, Enum => ItemKind::Enum, Function | TyMethod | Method => ItemKind::Function, - TypeAlias => ItemKind::Typedef, + TypeAlias => ItemKind::TypeAlias, OpaqueTy => ItemKind::OpaqueTy, Static => ItemKind::Static, Constant => ItemKind::Constant, diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index cd791ce000bf..27e8a27ba2f2 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -184,7 +184,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { | types::ItemEnum::Variant(_) | types::ItemEnum::TraitAlias(_) | types::ItemEnum::Impl(_) - | types::ItemEnum::Typedef(_) + | types::ItemEnum::TypeAlias(_) | types::ItemEnum::OpaqueTy(_) | types::ItemEnum::Constant(_) | types::ItemEnum::Static(_) diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index ba8eeaa66824..5d979521885a 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; use std::path::PathBuf; /// rustdoc format-version. -pub const FORMAT_VERSION: u32 = 26; +pub const FORMAT_VERSION: u32 = 27; /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information /// about the language items in the local crate, as well as info about external items to allow @@ -203,7 +203,7 @@ pub enum ItemKind { Enum, Variant, Function, - Typedef, + TypeAlias, OpaqueTy, Constant, Trait, @@ -242,7 +242,7 @@ pub enum ItemEnum { TraitAlias(TraitAlias), Impl(Impl), - Typedef(Typedef), + TypeAlias(TypeAlias), OpaqueTy(OpaqueTy), Constant(Constant), @@ -696,7 +696,7 @@ pub enum MacroKind { } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct Typedef { +pub struct TypeAlias { #[serde(rename = "type")] pub type_: Type, pub generics: Generics, diff --git a/src/tools/jsondoclint/src/item_kind.rs b/src/tools/jsondoclint/src/item_kind.rs index 45a9c93ee0b5..d48e6533a206 100644 --- a/src/tools/jsondoclint/src/item_kind.rs +++ b/src/tools/jsondoclint/src/item_kind.rs @@ -148,7 +148,7 @@ impl Kind { ItemEnum::Trait(_) => Trait, ItemEnum::TraitAlias(_) => TraitAlias, ItemEnum::Impl(_) => Impl, - ItemEnum::Typedef(_) => Typedef, + ItemEnum::TypeAlias(_) => Typedef, ItemEnum::OpaqueTy(_) => OpaqueTy, ItemEnum::Constant(_) => Constant, ItemEnum::Static(_) => Static, @@ -186,7 +186,7 @@ impl Kind { ItemKind::StructField => StructField, ItemKind::Trait => Trait, ItemKind::TraitAlias => TraitAlias, - ItemKind::Typedef => Typedef, + ItemKind::TypeAlias => Typedef, ItemKind::Union => Union, ItemKind::Variant => Variant, } diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs index bf8a64acf08d..79b1551f3011 100644 --- a/src/tools/jsondoclint/src/validator.rs +++ b/src/tools/jsondoclint/src/validator.rs @@ -5,7 +5,7 @@ use rustdoc_json_types::{ Constant, Crate, DynTrait, Enum, FnDecl, Function, FunctionPointer, GenericArg, GenericArgs, GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, ItemSummary, Module, OpaqueTy, Path, Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, - Type, TypeBinding, TypeBindingKind, Typedef, Union, Variant, VariantKind, WherePredicate, + Type, TypeAlias, TypeBinding, TypeBindingKind, Union, Variant, VariantKind, WherePredicate, }; use serde_json::Value; @@ -99,7 +99,7 @@ impl<'a> Validator<'a> { ItemEnum::Trait(x) => self.check_trait(x, id), ItemEnum::TraitAlias(x) => self.check_trait_alias(x), ItemEnum::Impl(x) => self.check_impl(x, id), - ItemEnum::Typedef(x) => self.check_typedef(x), + ItemEnum::TypeAlias(x) => self.check_typedef(x), ItemEnum::OpaqueTy(x) => self.check_opaque_ty(x), ItemEnum::Constant(x) => self.check_constant(x), ItemEnum::Static(x) => self.check_static(x), @@ -221,7 +221,7 @@ impl<'a> Validator<'a> { } } - fn check_typedef(&mut self, x: &'a Typedef) { + fn check_typedef(&mut self, x: &'a TypeAlias) { self.check_generics(&x.generics); self.check_type(&x.type_); } From 3df9b4d65d7230911b3ca826a62788d65f7a3001 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 21 Aug 2023 12:05:45 -0700 Subject: [PATCH 107/197] rustdoc: use unicode-aware checks for redundant explicit link fastpath Fixes #115064 --- .../passes/collect_intra_doc_links.rs | 11 +++-------- .../passes/lint/redundant_explicit_links.rs | 7 +------ .../lints/redundant_explicit_links-utf8.rs | 18 ++++++++++++++++++ 3 files changed, 22 insertions(+), 14 deletions(-) create mode 100644 tests/rustdoc-ui/lints/redundant_explicit_links-utf8.rs diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 36872266ee12..7b0a7a90d316 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1430,20 +1430,15 @@ impl LinkCollector<'_, '_> { // Otherwise, check if 2 links are same, if so, skip the resolve process. // // Notice that this algorithm is passive, might possibly miss actual redudant cases. - let explicit_link = &explicit_link.to_string(); + let explicit_link = explicit_link.to_string(); let display_text = ori_link.display_text.as_ref().unwrap(); - let display_len = display_text.len(); - let explicit_len = explicit_link.len(); - if display_len == explicit_len { + if display_text.len() == explicit_link.len() { // Whether they are same or not, skip the resolve process. return; } - if (explicit_len >= display_len - && &explicit_link[(explicit_len - display_len)..] == display_text) - || (display_len >= explicit_len - && &display_text[(display_len - explicit_len)..] == explicit_link) + if explicit_link.ends_with(&display_text[..]) || display_text.ends_with(&explicit_link[..]) { self.resolve_with_disambiguator_cached( display_res_info, diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index ef0f8716aa88..67cd2cc9732b 100644 --- a/src/librustdoc/passes/lint/redundant_explicit_links.rs +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -98,13 +98,8 @@ fn check_redundant_explicit_link<'md>( let explicit_link = dest.to_string(); let display_link = link_data.resolvable_link.clone()?; - let explicit_len = explicit_link.len(); - let display_len = display_link.len(); - if (explicit_len >= display_len - && &explicit_link[(explicit_len - display_len)..] == display_link) - || (display_len >= explicit_len - && &display_link[(display_len - explicit_len)..] == explicit_link) + if explicit_link.ends_with(&display_link) || display_link.ends_with(&explicit_link) { match link_type { LinkType::Inline | LinkType::ReferenceUnknown => { diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links-utf8.rs b/tests/rustdoc-ui/lints/redundant_explicit_links-utf8.rs new file mode 100644 index 000000000000..fecefb7b25ff --- /dev/null +++ b/tests/rustdoc-ui/lints/redundant_explicit_links-utf8.rs @@ -0,0 +1,18 @@ +// check-pass + +/// [`…foo`] [`…bar`] [`Err`] +pub struct Broken {} + +/// [`…`] [`…`] [`Err`] +pub struct Broken2 {} + +/// [`…`][…] [`…`][…] [`Err`] +pub struct Broken3 {} + +/// […………………………][Broken3] +pub struct Broken4 {} + +/// [Broken3][…………………………] +pub struct Broken5 {} + +pub struct Err; From d9f7005ab6e8376417ff115b569498907b5c787c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 22 Aug 2023 00:50:25 +0200 Subject: [PATCH 108/197] Allow overwriting ExpnId for concurrent decoding --- compiler/rustc_span/src/hygiene.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 9f2ff4378425..6f0e544a5974 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1277,11 +1277,11 @@ pub fn register_expn_id( let expn_id = ExpnId { krate, local_id }; HygieneData::with(|hygiene_data| { let _old_data = hygiene_data.foreign_expn_data.insert(expn_id, data); - debug_assert!(_old_data.is_none()); + debug_assert!(_old_data.is_none() || cfg!(parallel_compiler)); let _old_hash = hygiene_data.foreign_expn_hashes.insert(expn_id, hash); - debug_assert!(_old_hash.is_none()); + debug_assert!(_old_hash.is_none() || cfg!(parallel_compiler)); let _old_id = hygiene_data.expn_hash_to_expn_id.insert(hash, expn_id); - debug_assert!(_old_id.is_none()); + debug_assert!(_old_id.is_none() || cfg!(parallel_compiler)); }); expn_id } From 4d9ac5df59f400e76ce7532fa1b6b459d4a1c70c Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Mon, 21 Aug 2023 16:20:00 -0700 Subject: [PATCH 109/197] Fix test --- tests/rustdoc-gui/sidebar.goml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/rustdoc-gui/sidebar.goml b/tests/rustdoc-gui/sidebar.goml index 574cc629a043..913d72932b9f 100644 --- a/tests/rustdoc-gui/sidebar.goml +++ b/tests/rustdoc-gui/sidebar.goml @@ -67,7 +67,7 @@ assert-text: (".sidebar-elems section ul > li:nth-child(5)", "Enums") assert-text: (".sidebar-elems section ul > li:nth-child(6)", "Constants") assert-text: (".sidebar-elems section ul > li:nth-child(7)", "Traits") assert-text: (".sidebar-elems section ul > li:nth-child(8)", "Functions") -assert-text: (".sidebar-elems section ul > li:nth-child(9)", "Type Definitions") +assert-text: (".sidebar-elems section ul > li:nth-child(9)", "Type Aliases") assert-text: (".sidebar-elems section ul > li:nth-child(10)", "Unions") assert-text: (".sidebar-elems section ul > li:nth-child(11)", "Keywords") assert-text: ("#structs + .item-table .item-name > a", "Foo") @@ -102,7 +102,7 @@ assert-text: (".sidebar-elems > section ul.block > li:nth-child(1)", "Modules") assert-text: (".sidebar-elems > section ul.block > li:nth-child(2)", "Structs") assert-text: (".sidebar-elems > section ul.block > li:nth-child(3)", "Traits") assert-text: (".sidebar-elems > section ul.block > li:nth-child(4)", "Functions") -assert-text: (".sidebar-elems > section ul.block > li:nth-child(5)", "Type Definitions") +assert-text: (".sidebar-elems > section ul.block > li:nth-child(5)", "Type Aliases") assert-text: ("#functions + .item-table .item-name > a", "foobar") click: "#functions + .item-table .item-name > a" From b1c609e2a6716cb76d2690d86d2d9c255cacbb18 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 21 Aug 2023 20:43:04 +0000 Subject: [PATCH 110/197] Fix elided lifetimes in rust-lang/rust --- src/bootstrap/tool.rs | 2 +- src/tools/rust-analyzer/crates/test-utils/src/fixture.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index e6d27757ac66..07ff3da6b4aa 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -601,7 +601,7 @@ pub struct RustAnalyzer { } impl RustAnalyzer { - pub const ALLOW_FEATURES: &str = + pub const ALLOW_FEATURES: &'static str = "proc_macro_internals,proc_macro_diagnostic,proc_macro_span,proc_macro_span_shrink"; } diff --git a/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs b/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs index 75e7a3fec004..3f8b5a089690 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs @@ -313,7 +313,7 @@ impl FixtureWithProjectMeta { } impl MiniCore { - const RAW_SOURCE: &str = include_str!("./minicore.rs"); + const RAW_SOURCE: &'static str = include_str!("./minicore.rs"); fn has_flag(&self, flag: &str) -> bool { self.activated_flags.iter().any(|it| it == flag) From 0383131f7f48c7ff65b982c4c07dd8a7e6d5ed5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Tue, 22 Aug 2023 00:00:00 +0000 Subject: [PATCH 111/197] Contents of reachable statics is reachable --- compiler/rustc_passes/src/reachable.rs | 10 +++------- tests/ui/cross-crate/auxiliary/static_init_aux.rs | 4 ++++ tests/ui/cross-crate/static-init.rs | 3 +++ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index f9d34ea71baf..e62833b358b5 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -98,15 +98,11 @@ impl<'tcx> Visitor<'tcx> for ReachableContext<'tcx> { self.worklist.push(def_id); } else { match res { - // If this path leads to a constant, then we need to - // recurse into the constant to continue finding - // items that are reachable. - Res::Def(DefKind::Const | DefKind::AssocConst, _) => { + // Reachable constants and reachable statics can have their contents inlined + // into other crates. Mark them as reachable and recurse into their body. + Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::Static(_), _) => { self.worklist.push(def_id); } - - // If this wasn't a static, then the destination is - // surely reachable. _ => { self.reachable_symbols.insert(def_id); } diff --git a/tests/ui/cross-crate/auxiliary/static_init_aux.rs b/tests/ui/cross-crate/auxiliary/static_init_aux.rs index 3b664f43654e..5e172ef3198a 100644 --- a/tests/ui/cross-crate/auxiliary/static_init_aux.rs +++ b/tests/ui/cross-crate/auxiliary/static_init_aux.rs @@ -1,10 +1,14 @@ pub static V: &u32 = &X; pub static F: fn() = f; +pub static G: fn() = G0; static X: u32 = 42; +static G0: fn() = g; pub fn v() -> *const u32 { V } fn f() {} + +fn g() {} diff --git a/tests/ui/cross-crate/static-init.rs b/tests/ui/cross-crate/static-init.rs index 2e893c5d9bff..0b50c41fc5ed 100644 --- a/tests/ui/cross-crate/static-init.rs +++ b/tests/ui/cross-crate/static-init.rs @@ -1,9 +1,11 @@ +// Regression test for #84455 and #115052. // run-pass // aux-build:static_init_aux.rs extern crate static_init_aux as aux; static V: &u32 = aux::V; static F: fn() = aux::F; +static G: fn() = aux::G; fn v() -> *const u32 { V @@ -12,4 +14,5 @@ fn v() -> *const u32 { fn main() { assert_eq!(aux::v(), crate::v()); F(); + G(); } From e41240e45b58ea1bcf42fe5503cafec4c9dca1a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 22 Aug 2023 02:36:41 +0200 Subject: [PATCH 112/197] Fix races conditions with `SyntaxContext` decoding --- .../src/sync/worker_local.rs | 6 + compiler/rustc_span/src/hygiene.rs | 114 ++++++++++++------ 2 files changed, 86 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_data_structures/src/sync/worker_local.rs b/compiler/rustc_data_structures/src/sync/worker_local.rs index 8c84daf4f165..27d687c3cfeb 100644 --- a/compiler/rustc_data_structures/src/sync/worker_local.rs +++ b/compiler/rustc_data_structures/src/sync/worker_local.rs @@ -171,3 +171,9 @@ impl Deref for WorkerLocal { unsafe { &self.locals.get_unchecked(self.registry.id().verify()).0 } } } + +impl Default for WorkerLocal { + fn default() -> Self { + WorkerLocal::new(|_| T::default()) + } +} diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 9f2ff4378425..37ec2f0801c8 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -34,11 +34,13 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::HashingControls; use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher}; -use rustc_data_structures::sync::{Lock, Lrc}; +use rustc_data_structures::sync::{Lock, Lrc, WorkerLocal}; use rustc_data_structures::unhash::UnhashMap; use rustc_index::IndexVec; use rustc_macros::HashStable_Generic; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; +use std::cell::RefCell; +use std::collections::hash_map::Entry; use std::fmt; use std::hash::Hash; @@ -1241,13 +1243,25 @@ impl HygieneEncodeContext { #[derive(Default)] /// Additional information used to assist in decoding hygiene data -pub struct HygieneDecodeContext { +struct HygieneDecodeContextInner { // Maps serialized `SyntaxContext` ids to a `SyntaxContext` in the current // global `HygieneData`. When we deserialize a `SyntaxContext`, we need to create // a new id in the global `HygieneData`. This map tracks the ID we end up picking, // so that multiple occurrences of the same serialized id are decoded to the same - // `SyntaxContext` - remapped_ctxts: Lock>>, + // `SyntaxContext`. This only stores `SyntaxContext`s which are completly decoded. + remapped_ctxts: Vec>, + + /// Maps serialized `SyntaxContext` ids that are currently being decoded to a `SyntaxContext`. + decoding: FxHashMap, +} + +#[derive(Default)] +/// Additional information used to assist in decoding hygiene data +pub struct HygieneDecodeContext { + inner: Lock, + + /// A set of serialized `SyntaxContext` ids that are currently being decoded on each thread. + local_in_progress: WorkerLocal>>, } /// Register an expansion which has been decoded from the on-disk-cache for the local crate. @@ -1331,38 +1345,56 @@ pub fn decode_syntax_context SyntaxContext return SyntaxContext::root(); } - let outer_ctxts = &context.remapped_ctxts; + let ctxt = { + let mut inner = context.inner.lock(); - // Ensure that the lock() temporary is dropped early - { - if let Some(ctxt) = outer_ctxts.lock().get(raw_id as usize).copied().flatten() { + if let Some(ctxt) = inner.remapped_ctxts.get(raw_id as usize).copied().flatten() { + // This has already beeen decoded. return ctxt; } - } - // Allocate and store SyntaxContext id *before* calling the decoder function, - // as the SyntaxContextData may reference itself. - let new_ctxt = HygieneData::with(|hygiene_data| { - let new_ctxt = SyntaxContext(hygiene_data.syntax_context_data.len() as u32); - // Push a dummy SyntaxContextData to ensure that nobody else can get the - // same ID as us. This will be overwritten after call `decode_Data` - hygiene_data.syntax_context_data.push(SyntaxContextData { - outer_expn: ExpnId::root(), - outer_transparency: Transparency::Transparent, - parent: SyntaxContext::root(), - opaque: SyntaxContext::root(), - opaque_and_semitransparent: SyntaxContext::root(), - dollar_crate_name: kw::Empty, - }); - let mut ctxts = outer_ctxts.lock(); - let new_len = raw_id as usize + 1; - if ctxts.len() < new_len { - ctxts.resize(new_len, None); + match inner.decoding.entry(raw_id) { + Entry::Occupied(ctxt_entry) => { + match context.local_in_progress.borrow_mut().entry(raw_id) { + Entry::Occupied(..) => { + // We're decoding this already on the current thread. Return here + // and let the function higher up the stack finish decoding to handle + // recursive cases. + return *ctxt_entry.get(); + } + Entry::Vacant(entry) => { + entry.insert(()); + + // Some other thread is current decoding this. Race with it. + *ctxt_entry.get() + } + } + } + Entry::Vacant(entry) => { + // We are the first thread to start decoding. Mark the current thread as being progress. + context.local_in_progress.borrow_mut().insert(raw_id, ()); + + // Allocate and store SyntaxContext id *before* calling the decoder function, + // as the SyntaxContextData may reference itself. + let new_ctxt = HygieneData::with(|hygiene_data| { + let new_ctxt = SyntaxContext(hygiene_data.syntax_context_data.len() as u32); + // Push a dummy SyntaxContextData to ensure that nobody else can get the + // same ID as us. This will be overwritten after call `decode_Data` + hygiene_data.syntax_context_data.push(SyntaxContextData { + outer_expn: ExpnId::root(), + outer_transparency: Transparency::Transparent, + parent: SyntaxContext::root(), + opaque: SyntaxContext::root(), + opaque_and_semitransparent: SyntaxContext::root(), + dollar_crate_name: kw::Empty, + }); + new_ctxt + }); + entry.insert(new_ctxt); + new_ctxt + } } - ctxts[raw_id as usize] = Some(new_ctxt); - drop(ctxts); - new_ctxt - }); + }; // Don't try to decode data while holding the lock, since we need to // be able to recursively decode a SyntaxContext @@ -1375,14 +1407,28 @@ pub fn decode_syntax_context SyntaxContext // Overwrite the dummy data with our decoded SyntaxContextData HygieneData::with(|hygiene_data| { let dummy = std::mem::replace( - &mut hygiene_data.syntax_context_data[new_ctxt.as_u32() as usize], + &mut hygiene_data.syntax_context_data[ctxt.as_u32() as usize], ctxt_data, ); // Make sure nothing weird happening while `decode_data` was running - assert_eq!(dummy.dollar_crate_name, kw::Empty); + if cfg!(not(parallel_compiler)) { + assert_eq!(dummy.dollar_crate_name, kw::Empty); + } }); - new_ctxt + // Mark the context as completed + + context.local_in_progress.borrow_mut().remove(&raw_id); + + let mut inner = context.inner.lock(); + let new_len = raw_id as usize + 1; + if inner.remapped_ctxts.len() < new_len { + inner.remapped_ctxts.resize(new_len, None); + } + inner.remapped_ctxts[raw_id as usize] = Some(ctxt); + inner.decoding.remove(&raw_id); + + ctxt } fn for_all_ctxts_in( From 28de139d3545ec7e98dcb0e56349c0d5af0c3909 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 22 Aug 2023 08:48:39 +0200 Subject: [PATCH 113/197] bootstrap/miri: respect config_locked_deps --- src/bootstrap/test.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index d0d62db08071..db3b7ffbea4e 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -630,6 +630,10 @@ impl Step for Miri { cargo.env("MIRI_SYSROOT", &miri_sysroot); cargo.env("MIRI_HOST_SYSROOT", sysroot); cargo.env("MIRI", &miri); + if builder.config.locked_deps { + // enforce lockfiles + cargo.env("CARGO_EXTRA_FLAGS", "--locked"); + } // Set the target. cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg()); @@ -675,6 +679,9 @@ impl Step for Miri { ); cargo.add_rustc_lib_path(builder, compiler); cargo.arg("--").arg("miri").arg("test"); + if builder.config.locked_deps { + cargo.arg("--locked"); + } cargo .arg("--manifest-path") .arg(builder.src.join("src/tools/miri/test-cargo-miri/Cargo.toml")); From 1b9159e44827cea877788a951e6b0e1adfd27e5c Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Tue, 22 Aug 2023 06:57:36 +0000 Subject: [PATCH 114/197] Add disclaimer on size assertion macro Sometimes people are inspired by rustc to add size assertions to their code and copy the macro. This is bad because it causes hard build errors. rustc happens to be special where it makes this okay. --- compiler/rustc_index/src/lib.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index 9942c70c4ae7..0c5f6ff7a79f 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -29,6 +29,13 @@ pub use {idx::Idx, slice::IndexSlice, vec::IndexVec}; pub use rustc_macros::newtype_index; /// Type size assertion. The first argument is a type and the second argument is its expected size. +/// Note to the reader: Emitting hard errors from size assertions like this is generally not +/// recommended, especially in libraries, because they can cause build failures if the layout +/// algorithm or dependencies change. Here in rustc we control the toolchain and layout algorithm, +/// so the former is not a problem. For the latter we have a lockfile as rustc is an application and +/// precompiled library. +/// +/// Short version: Don't copy this macro into your own code. Use a `#[test]` instead. #[macro_export] macro_rules! static_assert_size { ($ty:ty, $size:expr) => { From ddf89a877601b9e16d777e7b5d06d2ae32e56929 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Tue, 22 Aug 2023 08:05:00 +0000 Subject: [PATCH 115/197] Remove myself from review rotation --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index a06195cc3340..b5047fd4344f 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -505,7 +505,6 @@ compiler-team-contributors = [ "@TaKO8Ki", "@WaffleLapkin", "@b-naber", - "@fee1-dead", ] compiler = [ "compiler-team", From d16e9c3369cddb3ed4e37cc5d29ff095df77d48b Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Tue, 22 Aug 2023 10:19:57 +0200 Subject: [PATCH 116/197] Convert it into a warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: León Orell Valerian Liehr --- compiler/rustc_index/src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index 0c5f6ff7a79f..76b493353ccd 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -29,13 +29,18 @@ pub use {idx::Idx, slice::IndexSlice, vec::IndexVec}; pub use rustc_macros::newtype_index; /// Type size assertion. The first argument is a type and the second argument is its expected size. -/// Note to the reader: Emitting hard errors from size assertions like this is generally not +/// +///
+/// +/// Emitting hard errors from size assertions like this is generally not /// recommended, especially in libraries, because they can cause build failures if the layout /// algorithm or dependencies change. Here in rustc we control the toolchain and layout algorithm, /// so the former is not a problem. For the latter we have a lockfile as rustc is an application and /// precompiled library. /// /// Short version: Don't copy this macro into your own code. Use a `#[test]` instead. +/// +///
#[macro_export] macro_rules! static_assert_size { ($ty:ty, $size:expr) => { From 0e070aa548e32f6ba8dd4cc28e9c71d9ccfb7ff3 Mon Sep 17 00:00:00 2001 From: Ethan Brierley Date: Tue, 22 Aug 2023 09:09:12 +0100 Subject: [PATCH 117/197] Always use `os-release` rather than `/lib` to detect `NixOS` [Two users over on zulip](https://rust-lang.zulipchat.com/#narrow/stream/122651-general/topic/Bootstrapping.20on.20NixOS) bumped into issues where NixOS wasn't being properly detected. I believe this was caused by the presence of `/lib` on their machines. `/lib` is not standard on NixOS but can still be created by users or scripts. We are already checking `/etc/os-release`. The presence of `ID=nixos` in it's output should be trustworthy and we shouldn't then go on to also check for `/lib`. --- src/bootstrap/bootstrap.py | 9 ++------- src/bootstrap/download.rs | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index f44a05a6b281..c5c70f2e18a1 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -644,7 +644,7 @@ class RustBuild(object): return False # If the user has asked binaries to be patched for Nix, then - # don't check for NixOS or `/lib`. + # don't check for NixOS. if self.get_toml("patch-binaries-for-nix", "build") == "true": return True @@ -652,14 +652,9 @@ class RustBuild(object): # The latter one does not exist on NixOS when using tmpfs as root. try: with open("/etc/os-release", "r") as f: - if not any(ln.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"') for ln in f): - return False + return any(ln.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"') for ln in f) except FileNotFoundError: return False - if os.path.exists("/lib"): - return False - - return True answer = self._should_fix_bins_and_dylibs = get_answer() if answer: diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs index a4135b06e9de..52162bf42ea4 100644 --- a/src/bootstrap/download.rs +++ b/src/bootstrap/download.rs @@ -105,7 +105,7 @@ impl Config { matches!(l.trim(), "ID=nixos" | "ID='nixos'" | "ID=\"nixos\"") }), }; - is_nixos && !Path::new("/lib").exists() + is_nixos }); if val { eprintln!("info: You seem to be using Nix."); From 1fac8a0eab870f25fa4c8ab21f0e14e54cdda4a4 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 22 Aug 2023 20:30:19 +1000 Subject: [PATCH 118/197] Treat `StatementKind::Coverage` as completely opaque for SMIR purposes Coverage statements in MIR are heavily tied to internal details of the coverage implementation that are likely to change, and are unlikely to be useful to third-party tools for the foreseeable future. --- compiler/rustc_smir/src/rustc_smir/mod.rs | 56 +------------------ .../rustc_smir/src/stable_mir/mir/body.rs | 43 ++------------ 2 files changed, 5 insertions(+), 94 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 7e8ac9a141a7..69909fcea0a8 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -14,7 +14,6 @@ use crate::stable_mir::ty::{ }; use crate::stable_mir::{self, Context}; use rustc_hir as hir; -use rustc_middle::mir::coverage::CodeRegion; use rustc_middle::mir::interpret::alloc_range; use rustc_middle::mir::{self, ConstantKind}; use rustc_middle::ty::{self, Ty, TyCtxt, Variance}; @@ -168,10 +167,7 @@ impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> { variance: variance.stable(tables), } } - Coverage(coverage) => stable_mir::mir::Statement::Coverage(stable_mir::mir::Coverage { - kind: coverage.kind.stable(tables), - code_region: coverage.code_region.as_ref().map(|reg| reg.stable(tables)), - }), + Coverage(coverage) => stable_mir::mir::Statement::Coverage(opaque(coverage)), Intrinsic(intrinstic) => { stable_mir::mir::Statement::Intrinsic(intrinstic.stable(tables)) } @@ -472,30 +468,6 @@ impl<'tcx> Stable<'tcx> for mir::Place<'tcx> { } } -impl<'tcx> Stable<'tcx> for mir::coverage::CoverageKind { - type T = stable_mir::mir::CoverageKind; - fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { - use rustc_middle::mir::coverage::CoverageKind; - match self { - CoverageKind::Counter { function_source_hash, id } => { - stable_mir::mir::CoverageKind::Counter { - function_source_hash: *function_source_hash as usize, - id: opaque(id), - } - } - CoverageKind::Expression { id, lhs, op, rhs } => { - stable_mir::mir::CoverageKind::Expression { - id: opaque(id), - lhs: opaque(lhs), - op: op.stable(tables), - rhs: opaque(rhs), - } - } - CoverageKind::Unreachable => stable_mir::mir::CoverageKind::Unreachable, - } - } -} - impl<'tcx> Stable<'tcx> for mir::UserTypeProjection { type T = stable_mir::mir::UserTypeProjection; @@ -504,18 +476,6 @@ impl<'tcx> Stable<'tcx> for mir::UserTypeProjection { } } -impl<'tcx> Stable<'tcx> for mir::coverage::Op { - type T = stable_mir::mir::Op; - - fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { - use rustc_middle::mir::coverage::Op::*; - match self { - Subtract => stable_mir::mir::Op::Subtract, - Add => stable_mir::mir::Op::Add, - } - } -} - impl<'tcx> Stable<'tcx> for mir::Local { type T = stable_mir::mir::Local; fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { @@ -562,20 +522,6 @@ impl<'tcx> Stable<'tcx> for ty::UserTypeAnnotationIndex { } } -impl<'tcx> Stable<'tcx> for CodeRegion { - type T = stable_mir::mir::CodeRegion; - - fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { - stable_mir::mir::CodeRegion { - file_name: self.file_name.as_str().to_string(), - start_line: self.start_line as usize, - start_col: self.start_col as usize, - end_line: self.end_line as usize, - end_col: self.end_col as usize, - } - } -} - impl<'tcx> Stable<'tcx> for mir::UnwindAction { type T = stable_mir::mir::UnwindAction; fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs index c16bd6cbd70e..a2ab51ff8467 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/body.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs @@ -135,9 +135,10 @@ pub enum AsyncGeneratorKind { } pub(crate) type LocalDefId = Opaque; -pub(crate) type CounterValueReference = Opaque; -pub(crate) type InjectedExpressionId = Opaque; -pub(crate) type ExpressionOperandId = Opaque; +/// [`rustc_middle::mir::Coverage`] is heavily tied to internal details of the +/// coverage implementation that are likely to change, and are unlikely to be +/// useful to third-party tools for the foreseeable future. +pub(crate) type Coverage = Opaque; /// The FakeReadCause describes the type of pattern why a FakeRead statement exists. #[derive(Clone, Debug)] @@ -166,42 +167,6 @@ pub enum Variance { Bivariant, } -#[derive(Clone, Debug)] -pub enum Op { - Subtract, - Add, -} - -#[derive(Clone, Debug)] -pub enum CoverageKind { - Counter { - function_source_hash: usize, - id: CounterValueReference, - }, - Expression { - id: InjectedExpressionId, - lhs: ExpressionOperandId, - op: Op, - rhs: ExpressionOperandId, - }, - Unreachable, -} - -#[derive(Clone, Debug)] -pub struct CodeRegion { - pub file_name: String, - pub start_line: usize, - pub start_col: usize, - pub end_line: usize, - pub end_col: usize, -} - -#[derive(Clone, Debug)] -pub struct Coverage { - pub kind: CoverageKind, - pub code_region: Option, -} - #[derive(Clone, Debug)] pub struct CopyNonOverlapping { pub src: Operand, From c8522adb9709cc62123fe4e68082abf90cdffc62 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 21 Aug 2023 09:12:15 -0400 Subject: [PATCH 119/197] Replace version placeholders with 1.73.0 --- compiler/rustc_feature/src/active.rs | 12 ++++++------ library/alloc/src/rc.rs | 2 +- library/alloc/src/sync.rs | 2 +- library/core/src/num/uint_macros.rs | 12 ++++++------ library/core/src/ptr/non_null.rs | 2 +- library/core/src/str/traits.rs | 2 +- library/std/src/ffi/mod.rs | 2 +- library/std/src/fs.rs | 6 +++--- library/std/src/io/util.rs | 4 ++-- library/std/src/os/unix/fs.rs | 6 +++--- library/std/src/process.rs | 2 +- library/std/src/thread/local.rs | 18 +++++++++--------- 12 files changed, 35 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index f5708f933d50..f5bc140c049f 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -282,7 +282,7 @@ declare_features! ( (active, arm_target_feature, "1.27.0", Some(44839), None), (active, avx512_target_feature, "1.27.0", Some(44839), None), (active, bpf_target_feature, "1.54.0", Some(44839), None), - (active, csky_target_feature, "CURRENT_RUSTC_VERSION", Some(44839), None), + (active, csky_target_feature, "1.73.0", Some(44839), None), (active, ermsb_target_feature, "1.49.0", Some(44839), None), (active, hexagon_target_feature, "1.27.0", Some(44839), None), (active, mips_target_feature, "1.27.0", Some(44839), None), @@ -315,7 +315,7 @@ declare_features! ( /// Allows `extern "ptx-*" fn()`. (active, abi_ptx, "1.15.0", Some(38788), None), /// Allows `extern "riscv-interrupt-m" fn()` and `extern "riscv-interrupt-s" fn()`. - (active, abi_riscv_interrupt, "CURRENT_RUSTC_VERSION", Some(111889), None), + (active, abi_riscv_interrupt, "1.73.0", Some(111889), None), /// Allows `extern "x86-interrupt" fn()`. (active, abi_x86_interrupt, "1.17.0", Some(40180), None), /// Allows additional const parameter types, such as `&'static str` or user defined types @@ -341,7 +341,7 @@ declare_features! ( /// Allows async functions to be declared, implemented, and used in traits. (active, async_fn_in_trait, "1.66.0", Some(91611), None), /// Allows `#[track_caller]` on async functions. - (active, async_fn_track_caller, "CURRENT_RUSTC_VERSION", Some(110011), None), + (active, async_fn_track_caller, "1.73.0", Some(110011), None), /// Allows builtin # foo() syntax (active, builtin_syntax, "1.71.0", Some(110680), None), /// Allows `c"foo"` literals. @@ -353,7 +353,7 @@ declare_features! ( /// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour. (active, cfg_overflow_checks, "1.71.0", Some(111466), None), /// Provides the relocation model information as cfg entry - (active, cfg_relocation_model, "CURRENT_RUSTC_VERSION", Some(114929), None), + (active, cfg_relocation_model, "1.73.0", Some(114929), None), /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used. (active, cfg_sanitize, "1.41.0", Some(39699), None), /// Allows `cfg(target_abi = "...")`. @@ -411,7 +411,7 @@ declare_features! ( /// Allows having using `suggestion` in the `#[deprecated]` attribute. (active, deprecated_suggestion, "1.61.0", Some(94785), None), /// Allows using the `#[diagnostic]` attribute tool namespace - (active, diagnostic_namespace, "CURRENT_RUSTC_VERSION", Some(94785), None), + (active, diagnostic_namespace, "1.73.0", Some(94785), None), /// Controls errors in trait implementations. (active, do_not_recommend, "1.67.0", Some(51992), None), /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`. @@ -456,7 +456,7 @@ declare_features! ( /// Allows non-trivial generic constants which have to have wfness manually propagated to callers (incomplete, generic_const_exprs, "1.56.0", Some(76560), None), /// Allows generic parameters and where-clauses on free & associated const items. - (incomplete, generic_const_items, "CURRENT_RUSTC_VERSION", Some(113521), None), + (incomplete, generic_const_items, "1.73.0", Some(113521), None), /// Allows using `..=X` as a patterns in slices. (active, half_open_range_patterns_in_slices, "1.66.0", Some(67264), None), /// Allows `if let` guard in match arms. diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index afed3fdf7459..c485680f92ec 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2719,7 +2719,7 @@ impl Weak { /// ``` #[inline] #[stable(feature = "downgraded_weak", since = "1.10.0")] - #[rustc_const_stable(feature = "const_weak_new", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_weak_new", since = "1.73.0")] #[must_use] pub const fn new() -> Weak { Weak { diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 476a4fea54f8..d3b7558440c6 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -2501,7 +2501,7 @@ impl Weak { /// ``` #[inline] #[stable(feature = "downgraded_weak", since = "1.10.0")] - #[rustc_const_stable(feature = "const_weak_new", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_weak_new", since = "1.73.0")] #[must_use] pub const fn new() -> Weak { Weak { diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 81148c7cc51f..23ca37817d4f 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2077,8 +2077,8 @@ macro_rules! uint_impl { /// ``` #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".div_ceil(4), 2);")] /// ``` - #[stable(feature = "int_roundings1", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_roundings1", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_roundings1", since = "1.73.0")] + #[rustc_const_stable(feature = "int_roundings1", since = "1.73.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2113,8 +2113,8 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(8), 16);")] #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(8), 24);")] /// ``` - #[stable(feature = "int_roundings1", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_roundings1", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_roundings1", since = "1.73.0")] + #[rustc_const_stable(feature = "int_roundings1", since = "1.73.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2140,8 +2140,8 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(1_", stringify!($SelfT), ".checked_next_multiple_of(0), None);")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_next_multiple_of(2), None);")] /// ``` - #[stable(feature = "int_roundings1", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_roundings1", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_roundings1", since = "1.73.0")] + #[rustc_const_stable(feature = "int_roundings1", since = "1.73.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 9582ca9e0bef..e0fd347a0495 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -367,7 +367,7 @@ impl NonNull { /// /// [the module documentation]: crate::ptr#safety #[stable(feature = "nonnull", since = "1.25.0")] - #[rustc_const_stable(feature = "const_nonnull_as_ref", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_nonnull_as_ref", since = "1.73.0")] #[must_use] #[inline(always)] pub const unsafe fn as_ref<'a>(&self) -> &'a T { diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index 49f9f6d4ad1e..2b37af66bd6a 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -265,7 +265,7 @@ unsafe impl SliceIndex for ops::Range { /// inclusion/exclusion) does not point to the starting byte offset of /// a character (as defined by `is_char_boundary`), if `begin > end`, or if /// `end > len`. -#[stable(feature = "slice_index_str_with_ops_bound_pair", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_index_str_with_ops_bound_pair", since = "1.73.0")] unsafe impl SliceIndex for (ops::Bound, ops::Bound) { type Output = str; diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index b0484474712f..ee9f6ed087c9 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -156,7 +156,7 @@ #[stable(feature = "alloc_c_string", since = "1.64.0")] pub use alloc::ffi::{CString, FromVecWithNulError, IntoStringError, NulError}; -#[stable(feature = "cstr_from_bytes_until_nul", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "cstr_from_bytes_until_nul", since = "1.73.0")] pub use core::ffi::FromBytesUntilNulError; #[stable(feature = "core_c_str", since = "1.64.0")] pub use core::ffi::{CStr, FromBytesWithNulError}; diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index a7e65305386e..4094e378034e 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -849,7 +849,7 @@ impl Seek for File { } } -#[stable(feature = "io_traits_arc", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "io_traits_arc", since = "1.73.0")] impl Read for Arc { fn read(&mut self, buf: &mut [u8]) -> io::Result { (&**self).read(buf) @@ -871,7 +871,7 @@ impl Read for Arc { (&**self).read_to_string(buf) } } -#[stable(feature = "io_traits_arc", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "io_traits_arc", since = "1.73.0")] impl Write for Arc { fn write(&mut self, buf: &[u8]) -> io::Result { (&**self).write(buf) @@ -888,7 +888,7 @@ impl Write for Arc { (&**self).flush() } } -#[stable(feature = "io_traits_arc", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "io_traits_arc", since = "1.73.0")] impl Seek for Arc { fn seek(&mut self, pos: SeekFrom) -> io::Result { (&**self).seek(pos) diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index 3840ffe7eeca..6bc8f181c905 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -100,7 +100,7 @@ impl SizeHint for Empty { } } -#[stable(feature = "empty_write", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "empty_write", since = "1.73.0")] impl Write for Empty { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { @@ -124,7 +124,7 @@ impl Write for Empty { } } -#[stable(feature = "empty_write", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "empty_write", since = "1.73.0")] impl Write for &Empty { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index 88326aaf2955..029de8fbf760 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -1007,7 +1007,7 @@ impl DirBuilderExt for fs::DirBuilder { /// Ok(()) /// } /// ``` -#[stable(feature = "unix_chown", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "unix_chown", since = "1.73.0")] pub fn chown>(dir: P, uid: Option, gid: Option) -> io::Result<()> { sys::fs::chown(dir.as_ref(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX)) } @@ -1027,7 +1027,7 @@ pub fn chown>(dir: P, uid: Option, gid: Option) -> io:: /// Ok(()) /// } /// ``` -#[stable(feature = "unix_chown", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "unix_chown", since = "1.73.0")] pub fn fchown(fd: F, uid: Option, gid: Option) -> io::Result<()> { sys::fs::fchown(fd.as_fd().as_raw_fd(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX)) } @@ -1047,7 +1047,7 @@ pub fn fchown(fd: F, uid: Option, gid: Option) -> io::Result< /// Ok(()) /// } /// ``` -#[stable(feature = "unix_chown", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "unix_chown", since = "1.73.0")] pub fn lchown>(dir: P, uid: Option, gid: Option) -> io::Result<()> { sys::fs::lchown(dir.as_ref(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX)) } diff --git a/library/std/src/process.rs b/library/std/src/process.rs index f54d59341750..7380b45b00fe 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1535,7 +1535,7 @@ impl From for Stdio { pub struct ExitStatus(imp::ExitStatus); /// The default value is one which indicates successful completion. -#[stable(feature = "process-exitcode-default", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "process-exitcode-default", since = "1.73.0")] impl Default for ExitStatus { fn default() -> Self { // Ideally this would be done by ExitCode::default().into() but that is complicated. diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 21515adc6c42..09994e47f0a6 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -325,7 +325,7 @@ impl LocalKey> { /// /// assert_eq!(X.get(), 123); /// ``` - #[stable(feature = "local_key_cell_methods", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "local_key_cell_methods", since = "1.73.0")] pub fn set(&'static self, value: T) { self.initialize_with(Cell::new(value), |value, cell| { if let Some(value) = value { @@ -358,7 +358,7 @@ impl LocalKey> { /// /// assert_eq!(X.get(), 1); /// ``` - #[stable(feature = "local_key_cell_methods", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "local_key_cell_methods", since = "1.73.0")] pub fn get(&'static self) -> T where T: Copy, @@ -388,7 +388,7 @@ impl LocalKey> { /// assert_eq!(X.take(), Some(1)); /// assert_eq!(X.take(), None); /// ``` - #[stable(feature = "local_key_cell_methods", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "local_key_cell_methods", since = "1.73.0")] pub fn take(&'static self) -> T where T: Default, @@ -418,7 +418,7 @@ impl LocalKey> { /// assert_eq!(X.replace(2), 1); /// assert_eq!(X.replace(3), 2); /// ``` - #[stable(feature = "local_key_cell_methods", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "local_key_cell_methods", since = "1.73.0")] pub fn replace(&'static self, value: T) -> T { self.with(|cell| cell.replace(value)) } @@ -448,7 +448,7 @@ impl LocalKey> { /// /// X.with_borrow(|v| assert!(v.is_empty())); /// ``` - #[stable(feature = "local_key_cell_methods", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "local_key_cell_methods", since = "1.73.0")] pub fn with_borrow(&'static self, f: F) -> R where F: FnOnce(&T) -> R, @@ -481,7 +481,7 @@ impl LocalKey> { /// /// X.with_borrow(|v| assert_eq!(*v, vec![1])); /// ``` - #[stable(feature = "local_key_cell_methods", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "local_key_cell_methods", since = "1.73.0")] pub fn with_borrow_mut(&'static self, f: F) -> R where F: FnOnce(&mut T) -> R, @@ -517,7 +517,7 @@ impl LocalKey> { /// /// X.with_borrow(|v| assert_eq!(*v, vec![1, 2, 3])); /// ``` - #[stable(feature = "local_key_cell_methods", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "local_key_cell_methods", since = "1.73.0")] pub fn set(&'static self, value: T) { self.initialize_with(RefCell::new(value), |value, cell| { if let Some(value) = value { @@ -558,7 +558,7 @@ impl LocalKey> { /// /// X.with_borrow(|v| assert!(v.is_empty())); /// ``` - #[stable(feature = "local_key_cell_methods", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "local_key_cell_methods", since = "1.73.0")] pub fn take(&'static self) -> T where T: Default, @@ -589,7 +589,7 @@ impl LocalKey> { /// /// X.with_borrow(|v| assert_eq!(*v, vec![1, 2, 3])); /// ``` - #[stable(feature = "local_key_cell_methods", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "local_key_cell_methods", since = "1.73.0")] pub fn replace(&'static self, value: T) -> T { self.with(|cell| cell.replace(value)) } From 068e3d97d0f1da0019e6e98dbd151d5e9df548b1 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 22 Aug 2023 06:58:03 -0400 Subject: [PATCH 120/197] Update stage0 to next beta --- src/stage0.json | 738 ++++++++++++++++++++++++------------------------ 1 file changed, 370 insertions(+), 368 deletions(-) diff --git a/src/stage0.json b/src/stage0.json index 5f54504b8ea7..201f9a0c612f 100644 --- a/src/stage0.json +++ b/src/stage0.json @@ -17,379 +17,381 @@ "tool is executed." ], "compiler": { - "date": "2023-07-12", + "date": "2023-08-22", "version": "beta" }, "rustfmt": { - "date": "2023-07-13", + "date": "2023-08-22", "version": "nightly" }, "checksums_sha256": { - "dist/2023-07-12/cargo-beta-aarch64-apple-darwin.tar.gz": "2abd085e1805419ca8ae0227f7f974790beac8f4f0dcfaa6e57857f6b79a96b3", - "dist/2023-07-12/cargo-beta-aarch64-apple-darwin.tar.xz": "f28bfa89ae8b20a06a90fcb2a34840a8473c504986742ff111e4c0722507ce35", - "dist/2023-07-12/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "50206cd7b01c9f978f433660c30de8b3f8799eb19ef371e88236065719732322", - "dist/2023-07-12/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "6359961e60f32569af03bdddc0e6e996f0b22d124a3c21272a44c0e1cd5ce414", - "dist/2023-07-12/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "be5e354a88c9ca8cb696d7383670279d8933f1bf4bf1599a5c4f17d884b05707", - "dist/2023-07-12/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "6180ee4c1087044ba9e1c7b8ddc289b75824e34ed88dd153b63ee8674d8b3405", - "dist/2023-07-12/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "9632cff665c36d62eeae355e9322c3bea2bc09efd6fadf49dca603bd54545c6f", - "dist/2023-07-12/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "b91560ef397310ffd96179201b696b8eeb4713787174b37517aa043690740dbc", - "dist/2023-07-12/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "d0654b7f734262cd7d6bb8924a063f9f48f2510f8a5a58d050efba90fde40204", - "dist/2023-07-12/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "6271ded5e5e50697626d67f0d6faa54f0d0daa6aa61a3e98354c62a74f1bb87e", - "dist/2023-07-12/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "6a9b804c6217f8a76d72fc10a7b9566d00c36dff5eb9df238c56bc7d26b4f0d0", - "dist/2023-07-12/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "f2b67e0a7bd0b304f89e4b938c46c7551f34f40d87f0909a07363fcd903ab3b9", - "dist/2023-07-12/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "c0fbf9d4d7638dc4ae6cc5d136a69cbce0ec5c3c31bd8103a6e2783c27690b0d", - "dist/2023-07-12/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "cb67aea7aa1295d5bdfbfde784300b779a7bc350af864bc2ee8d7b268648c6e5", - "dist/2023-07-12/cargo-beta-i686-pc-windows-gnu.tar.gz": "4a4bfb185e226d1b6c310fc25ff5b13bab088fa4d98425b90878aa0446ee22bf", - "dist/2023-07-12/cargo-beta-i686-pc-windows-gnu.tar.xz": "d265ad80a372223d9c99a1d3232d379287d847ea1c3afde29f320d3950198e9b", - "dist/2023-07-12/cargo-beta-i686-pc-windows-msvc.tar.gz": "6c566bdb668e6ac7b068c285b7fe2e3cf7d0f4f065663165f2a9e4256b78e4cf", - "dist/2023-07-12/cargo-beta-i686-pc-windows-msvc.tar.xz": "c70d668d38fe9946a887ab18bb08ca74d2a8e36f6ead9d78deae55b532abef34", - "dist/2023-07-12/cargo-beta-i686-unknown-linux-gnu.tar.gz": "82d996b76d6ce55d64c82a33d3278c609bcbbef854c94d98cd4c5290958d542f", - "dist/2023-07-12/cargo-beta-i686-unknown-linux-gnu.tar.xz": "cf06a97a9e60e8936482da06a659f3eb4133d0ea3b5498e45b160fbd513e3d2e", - "dist/2023-07-12/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz": "816c8112da3efdc27e8930944a6560ae8e8597755af22d8af4b2bbe910f08a93", - "dist/2023-07-12/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz": "c59fc50e68d9d2afbc725ea420db701593bfa074abd7b97e3c7dfc676e0647b0", - "dist/2023-07-12/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "d7327116f5fc8ab665fdb086fda93af287de6ff91c2762e1867b0e40acda231a", - "dist/2023-07-12/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "24ec8fd09995c20e216b071c86405b0e3a1cd038c66700b47321188d09cb83a0", - "dist/2023-07-12/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "f937ff68855c59bafb3412761cf8f6a0c0d91c9729000a4ea58eed53569803b3", - "dist/2023-07-12/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "b51d94d00ce0af91a8abe2ea152b2331689fc1799d212c11ac4ca0fc4dca652c", - "dist/2023-07-12/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "5ed88bc49511d1e2496eab00ef4ea5677868113e83aac6e1e61fdb5b9f56f1b5", - "dist/2023-07-12/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "a5b9594e97947abba39877fb0e99bf329d5447e7a7d557dab994c24e381ced12", - "dist/2023-07-12/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "c269533aeec8a1cdc25e3a3057ea8c9da571d7f3617cba9f1fe0c4193ab38f70", - "dist/2023-07-12/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "7094f76b4f7d1d1d34a5214b531ccecca4b2ad09fb23b534d334bece2718c78c", - "dist/2023-07-12/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "012a515e3acab001cd72ef38144edd0372a6d813912990dc5409f340bd4856e8", - "dist/2023-07-12/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "fceb8dc2356b8dfa4009e60d8a0742c940553beed385a0b6ba1526fc329f36cc", - "dist/2023-07-12/cargo-beta-x86_64-apple-darwin.tar.gz": "5dd74b549dd46809b8f56d8ed5052303bd64b14f5583bc89379624f6a22836b4", - "dist/2023-07-12/cargo-beta-x86_64-apple-darwin.tar.xz": "f0b33f85cd5585e272a90736e3d188d7f53886a97a75aaae5f4d6dda85867baa", - "dist/2023-07-12/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "be049bb6fc3f7b079b425ecd8fcbeae3cae29c8a32a290f70d5f2a7522d67b87", - "dist/2023-07-12/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "b04f7c83691abcefb5fb985013ec8d98fe4ce773d0b3291127efb1b00a7ab08e", - "dist/2023-07-12/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "c1b853dec72570534a64c7f94e0008057a2365b0f060d17b84bdef19080b6bbb", - "dist/2023-07-12/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "146d305a0fc14a1b7bb6586dd3130d09b72d2497ddbc10c3e739444bded037ca", - "dist/2023-07-12/cargo-beta-x86_64-unknown-freebsd.tar.gz": "235948cf05dcfef80e21e66f5b08ddab18eb8f14b2ea8fcbeed22cdad8611868", - "dist/2023-07-12/cargo-beta-x86_64-unknown-freebsd.tar.xz": "28008794b923bb103f46a0a24bf66ce5f43a647ed5b4fefc649b8734a2f80ffb", - "dist/2023-07-12/cargo-beta-x86_64-unknown-illumos.tar.gz": "7d6a9f53a0e5758e7155c7cba0385c6ab7e0cee7f98a62172c108dca909a2188", - "dist/2023-07-12/cargo-beta-x86_64-unknown-illumos.tar.xz": "3314f50099b488cd027074241bde9fa0a12a6ca6f14afa9f0db5dd62080c318c", - "dist/2023-07-12/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "2632324d31641f783528bbfa98b6b16738d4ba59933a7919360bde5279092c5a", - "dist/2023-07-12/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "0057a55a30c38002b03c032a0f742dd326236f25b67b3c3d791661ef6f653c1b", - "dist/2023-07-12/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "03b787105749e431e1c043fe7e019984a602a6a7ec382f78e1b960a5fe7466d9", - "dist/2023-07-12/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "5ccf1875d484d41a8e6828f4c96d1915c644e99369dae73a161fd10a97937ff6", - "dist/2023-07-12/cargo-beta-x86_64-unknown-netbsd.tar.gz": "2df957be57157dc20ee4ec1434c5c8ef57b2f61d9ca681510f9cac397cd31f8d", - "dist/2023-07-12/cargo-beta-x86_64-unknown-netbsd.tar.xz": "5cecc38b971653fc6ae1f393080723350dde6e17597f2da6bb76788f23402bf4", - "dist/2023-07-12/rust-std-beta-aarch64-apple-darwin.tar.gz": "e6008a3c5b826be78f6dbde565c0b148339d7e37bec0adde575e91a065903955", - "dist/2023-07-12/rust-std-beta-aarch64-apple-darwin.tar.xz": "735118e8d1ab40d504e345e0b5d844b90d0b04689ff4f5dda9c6f141944eb9af", - "dist/2023-07-12/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "7b930f3a915d98be424d7ccde639f0350cdfb97422367b8a336f5688704ecf35", - "dist/2023-07-12/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "4dd1e2ff92a85a76108d2f90b37245f7851c214454386aed053b528a31d0f46b", - "dist/2023-07-12/rust-std-beta-aarch64-apple-ios.tar.gz": "8415958461754cb3f9e86e9f47f2bbd26395e89a9bbbc21dbc54572a59c72b24", - "dist/2023-07-12/rust-std-beta-aarch64-apple-ios.tar.xz": "e88fd506a62568b49a5be056e9aeb4a9db6833216cf68adafc24769b0942eb4a", - "dist/2023-07-12/rust-std-beta-aarch64-linux-android.tar.gz": "41489a5701378265ace4a15b7ea9107fc5579c0bc3967e075e4c8769d3b0ac61", - "dist/2023-07-12/rust-std-beta-aarch64-linux-android.tar.xz": "86bb3088f26f3fd9c83220ea6d39135fc002d36696dc15c56d754065b13105c3", - "dist/2023-07-12/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "621bfd6e6253f35fe78321f3f8f45cd2fb0e290502f4b659d75b9e401a5b06da", - "dist/2023-07-12/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "2fb251d461489dfa8721ef12ff212aa77fc9a0a6e6952c22cdb8ff36eee39fe2", - "dist/2023-07-12/rust-std-beta-aarch64-unknown-fuchsia.tar.gz": "879f1ab511497baeb614d263e6bcb105bd084c8aa190ffbdd565fd14c87c7a48", - "dist/2023-07-12/rust-std-beta-aarch64-unknown-fuchsia.tar.xz": "c40816547ad6ecac58c13c21540239c7ba87b4970a2bbc2f3d9c64aef1f22f82", - "dist/2023-07-12/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "d53b23527d184087adb14574b4a1f2a4e1fa387a271c080af2c7aa96c0ef2033", - "dist/2023-07-12/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "7122261bd5a72b8426d2325a88fda0983e24cf58882c24eea85ab9f8861fecf7", - "dist/2023-07-12/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "6b5326823ce3564f9f67db5d9193349df8001adec9849b7bdf01ea06b342f5b3", - "dist/2023-07-12/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "10a89967e1600ac7e857715c9d61991710b88dfa3da8b117fc5be2c2fac26859", - "dist/2023-07-12/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "ddd5ed0c6aa3499f40e9ce18a43627f8e1f33be3ac056d109045d2df65128cca", - "dist/2023-07-12/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "c6c61e5e2fe43ade33fb21683d382d4f101071e14dd18f4dec5b16b792b35850", - "dist/2023-07-12/rust-std-beta-aarch64-unknown-none.tar.gz": "1cff4acc6b0889450c00a67dec433f274c6f141bd047ff530f573d46a3bcaaff", - "dist/2023-07-12/rust-std-beta-aarch64-unknown-none.tar.xz": "1528aada81564d7359bc80f6c15e98e29d1685057ba83e57ef59952e870a1042", - "dist/2023-07-12/rust-std-beta-aarch64-unknown-uefi.tar.gz": "e2e2fc8f4b037fda67a80024b6fe73f5b616376b4def317ccd6e78e2b4776859", - "dist/2023-07-12/rust-std-beta-aarch64-unknown-uefi.tar.xz": "3ecfd0f3ecbd2bb5e4bbed886d127fa33893360f898041a384afef4629693dbd", - "dist/2023-07-12/rust-std-beta-arm-linux-androideabi.tar.gz": "0be665812e347a20cc097918e362904088afcc8b45c741b1da29f9e991d9c3d0", - "dist/2023-07-12/rust-std-beta-arm-linux-androideabi.tar.xz": "9a65ff8ec3a03afd1cf5bba933eaa602e3e9f29a003be9f8835b21c2e5b8d26a", - "dist/2023-07-12/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "5e1387faf662f7c227b075cc5b860f064864a1ebd1ce85ab5840fb136f38ff69", - "dist/2023-07-12/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "4bb9dc22d45b34620120ab5f4aacd2799181f4bb006f40a83cead84b582ed669", - "dist/2023-07-12/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "d7996b74fe236e453bff636361389f6183194784f4b997d144fd456d4b55257e", - "dist/2023-07-12/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "578a99158925d329a57b74d82524d3c97fef1d9a801c39f5b03366aa60d217a6", - "dist/2023-07-12/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "a02bbe42972483d2ff5b26e1948f9d5d3c9512019f5cba0514b57a248847afc3", - "dist/2023-07-12/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "37fcc7982aabbd77c76f1886feaac1fc87fc4a1ad35edb80a5be381c88f65125", - "dist/2023-07-12/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "52622b53c8fa0d16090d59543432e7d531f7eb6812730b79aeb96a8d1c993290", - "dist/2023-07-12/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "a5af3735e6337c79c45a1b0d538c3627cd89ddd4d5d40d75e711d86004dbfe8b", - "dist/2023-07-12/rust-std-beta-armebv7r-none-eabi.tar.gz": "8fd0e463083548198255142e617a726f2b6a055665e534755e8b879e420041fc", - "dist/2023-07-12/rust-std-beta-armebv7r-none-eabi.tar.xz": "2b407208e51a8f3f82ede1a98ec33d12345f3c7f2ae1ddf25232dcd30aca915e", - "dist/2023-07-12/rust-std-beta-armebv7r-none-eabihf.tar.gz": "57ea6af7f77135d9f5d8541139caa562d8901a167e77e3de0a75b427090a60ce", - "dist/2023-07-12/rust-std-beta-armebv7r-none-eabihf.tar.xz": "7a14e34060161073191d858c2450b5dd69d827261c6fc5f56a003753232bec32", - "dist/2023-07-12/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "03d0ba0d24e07788aa7fb9c85515f82a697fb224a52a904f96970f8f329849e1", - "dist/2023-07-12/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "fb55245b1c7e6f074d8120d7b28e25a6882a3ef8c8afe4c7601078f385644eda", - "dist/2023-07-12/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "d1fb9a2001db3060ceb6d6deb0e0f35db7da5d47b0d174c2f4d5ba9a82ad22f1", - "dist/2023-07-12/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "8e0ec621b890b455988a931bc8eabc96840faf2fc7b311776aa06a1b55a4f554", - "dist/2023-07-12/rust-std-beta-armv7-linux-androideabi.tar.gz": "96d01a8dc88041d804e33fcca5d64ca10503a855a394606533aacc1e142289e1", - "dist/2023-07-12/rust-std-beta-armv7-linux-androideabi.tar.xz": "75c42686a8f379f19971235855e24ae7ce0b5d91768c00532857d304f45e5cef", - "dist/2023-07-12/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "a097e5fdd835551e969c4e1d6cf767633d79101709362a9a26d3056bf8ecd32c", - "dist/2023-07-12/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "f056e2c6cbb40ba34598a60901c959b828d086a84ceba03f9eaa3d7f48b7c6c6", - "dist/2023-07-12/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "1995003b8ef8ee5dbee66d46a1233d6fe0182ccb6b9c14c976cc40e5099324ef", - "dist/2023-07-12/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "08d9e6293cd3a89d6e42b0939c668a58ac010603fd4eee9775dde468a33bd0dd", - "dist/2023-07-12/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "092d13520760e9540663ffc08e17be223a815e2dd7c0899033fe6676edb74264", - "dist/2023-07-12/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "9e7d6923f8c90c779767eb40a55ef958420737679a5065e2a5ca49a6e34dacc5", - "dist/2023-07-12/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "c232cde2921c0c2d1a0f8fab64ddcae2b7dd7ed5cbf180370ece302949826a88", - "dist/2023-07-12/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "7681e242675bb765a1aacd3c8ebc6894eeb709ce7d85e5ff94cd63e52eb4e989", - "dist/2023-07-12/rust-std-beta-armv7a-none-eabi.tar.gz": "4a777b4a7e8b157d78aaab73ae4e9185821a7887dbad68612db3b5bd7428729b", - "dist/2023-07-12/rust-std-beta-armv7a-none-eabi.tar.xz": "d823b49c8d4b2615223b68cf6b6ac22836551aa5c1df0f68e1336c2be7ffe7ec", - "dist/2023-07-12/rust-std-beta-armv7r-none-eabi.tar.gz": "12e8242d480dc45108e615cb5625a07b77054a88fff72dce51c313e57a3ec8ef", - "dist/2023-07-12/rust-std-beta-armv7r-none-eabi.tar.xz": "0cef6562f5ee0850fdfbf0be00e18a5643a951d169df00b4e068c932fe04b048", - "dist/2023-07-12/rust-std-beta-armv7r-none-eabihf.tar.gz": "71818e3855455bf6cc3fc2f04b7ebbf95e32f28f636d08d9513ab1be88aece49", - "dist/2023-07-12/rust-std-beta-armv7r-none-eabihf.tar.xz": "b4bcb177e8fb157e50b93e07144889127b218804ede359d542ccdb0a0fc8a4a0", - "dist/2023-07-12/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "d16b2accc56ee37e2e527e0371a689530d30a6ff316bbb85664710419a5effca", - "dist/2023-07-12/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "6b828e1b7941d6a9ed085051c378227c99ebc5b4899dfd222c368b2edaa6f7fd", - "dist/2023-07-12/rust-std-beta-i586-pc-windows-msvc.tar.gz": "d35e870fb7cda230cebf82d6e4241f0535e534c861fed1a5158f47f8a18bb33b", - "dist/2023-07-12/rust-std-beta-i586-pc-windows-msvc.tar.xz": "36404cc649e16efbdf0fb6afdf2130af1ab46618ee8130c431370be618d7e182", - "dist/2023-07-12/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "682e74d110324cf0f53121f7b8ef0bd6e5bc355b2fd1d2eb183bee85d26a3bf0", - "dist/2023-07-12/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "1ea30b0d14e7a5a82aee09b8e4ba87856158b31ec6b83e77929e2e9784698d43", - "dist/2023-07-12/rust-std-beta-i586-unknown-linux-musl.tar.gz": "b83d3652bd440b91ab2b145cd0ea3108203ccaa9beeea099220cd76d92a7f64f", - "dist/2023-07-12/rust-std-beta-i586-unknown-linux-musl.tar.xz": "ab78b6ca9136606d48afe42ce32e5a96cc07d4ea61856a500a9c7dd837983288", - "dist/2023-07-12/rust-std-beta-i686-linux-android.tar.gz": "5522933a886774ef4c490a8d928834d35c5a31b9066a8ec3b9b80de7d121dc37", - "dist/2023-07-12/rust-std-beta-i686-linux-android.tar.xz": "896cf7f6b611b676d40c9c20aafed11d7746a349a55658d03a8c6d197595006d", - "dist/2023-07-12/rust-std-beta-i686-pc-windows-gnu.tar.gz": "bcf7eca5717e3643a4f6a1ca4412bbf0466c0ffe0075eda441a0ed9060b0aacc", - "dist/2023-07-12/rust-std-beta-i686-pc-windows-gnu.tar.xz": "89fe6ed9068cb187eeb8c372dc04b7a10d6c9289d2374f0c59eaf6234fbd438b", - "dist/2023-07-12/rust-std-beta-i686-pc-windows-msvc.tar.gz": "8d381d2b4370a454793e66828e75a006093277e890d38e7e94582f094c390539", - "dist/2023-07-12/rust-std-beta-i686-pc-windows-msvc.tar.xz": "25f0bb9b88de1d2f54d1b42a23569dbcab7b37885f2b8a78665739352af9fbf7", - "dist/2023-07-12/rust-std-beta-i686-unknown-freebsd.tar.gz": "435e26724e1799d2330e4d5262ba2995c46d601917fa3d1e0afefe989903eebe", - "dist/2023-07-12/rust-std-beta-i686-unknown-freebsd.tar.xz": "87afb9db4d7f02e23ab7531fa57c574fedbf2b6232260006b59ef40bca15e06b", - "dist/2023-07-12/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "ceb59a15be998cb908f1a59460475b569e02bedab180396713e0d8418d55c909", - "dist/2023-07-12/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "3fcb9e8f60eeeba76558976ff06cdfd5ecbf2294c603af2398e044d2e04429e8", - "dist/2023-07-12/rust-std-beta-i686-unknown-linux-musl.tar.gz": "c6a77d8f3c9eb6ce6e91a7e8fad8fba84c8b13f4bce9e565a65b01f307c005ac", - "dist/2023-07-12/rust-std-beta-i686-unknown-linux-musl.tar.xz": "b01833d247e906c8b1e4c0c9ca5b4c37dd4166824693cc6d4a85ab881e482854", - "dist/2023-07-12/rust-std-beta-i686-unknown-uefi.tar.gz": "1ffc65c298d91782a9f2b772f82e411d8e164e0a245b1eb0e2f81382f378076d", - "dist/2023-07-12/rust-std-beta-i686-unknown-uefi.tar.xz": "68b511d1a3685ea45644a0d40f5b456cef34ba48719947789f7330984a027699", - "dist/2023-07-12/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz": "0cd83da690cb1870b77c918f029273cced0d03f204fa42c4eec8930e6fcea8ba", - "dist/2023-07-12/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz": "9e215a989ed9e2f1c4581c1f38c475564b46f6b90dde91b63b88290cb7866a48", - "dist/2023-07-12/rust-std-beta-mips-unknown-linux-musl.tar.gz": "e66d3f598c38536f2db2e42b8b231acddc04c3edbb017d37adfd77a3378bf6c3", - "dist/2023-07-12/rust-std-beta-mips-unknown-linux-musl.tar.xz": "f030f5412e912004239febcb88c8fc489a7d35b95c02b750ba582a7ff895b79a", - "dist/2023-07-12/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "903649d2da11a054ffbeb440beb5c0f668bbc4a3c8f931a47b559659aba0eacd", - "dist/2023-07-12/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "ef1656bf4bd5b1fb90fdd1348808b81fb4b6da470966864ba823979890a1bb31", - "dist/2023-07-12/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "e2f37ad36fb7ec9d15a85c467ffb1af69a14f8a073a105e0341c5bf7f2feaa13", - "dist/2023-07-12/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "fcd15fe90bfb887fef0a83d1371283a965edfef029924d060ea4775be83669ce", - "dist/2023-07-12/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "8025e30f46c2f350a028c32be6b07472b40ce0dce8b4339753eeee391ff1639e", - "dist/2023-07-12/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "430eba57898d01285ae9b4351e5fca4179d638501b8004a559b2aec9daeaac20", - "dist/2023-07-12/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "f87733ff046a233cb9e68793dc3fbdf04cf8f639d1ec8e80f78d495dd168ab9f", - "dist/2023-07-12/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "d5756b6d7852bfe305283ac59cff20985e94f85f03bbb1c220d8e1b28b93392f", - "dist/2023-07-12/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "e193958bfd05581adc4e08599940f8dd77c565724c188bb331c61a1d2a030379", - "dist/2023-07-12/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "497b919f34d29412406202724fb20500d22cbc838df05128bc259826b4698f6a", - "dist/2023-07-12/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "499a17483bc7fbfdb3bd234c683eda4cb8e5270deb43c66253ad265cb72df0a3", - "dist/2023-07-12/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "8d209a47b988c987c93c32066d2f80bfa522e23f172bf8ac7a9c166408e98136", - "dist/2023-07-12/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "1795b4a2621f718915267eda5184d417406390490946f9295f3096322d4136cd", - "dist/2023-07-12/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "facdc96f065df0dfe2396445b44ed640a4e9922220dfe5c79df93b650bb8c982", - "dist/2023-07-12/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "fe297caa7916f58c7483103ee88641f02c75955e652b262e35b0f53efe3163d0", - "dist/2023-07-12/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "f0c06945c158f4613e336420c869c1b4f35d1a867c11dd227f9fee2f1b5dfaf3", - "dist/2023-07-12/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "ef8c7b0bd6055cfbeafdf36e3569804d4513cf0bf9e49f0a621860c0f203160b", - "dist/2023-07-12/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "96c16adbaddc9711e51ed1d626d4cc4c41f58b7e498987697b8f5177c577c2c6", - "dist/2023-07-12/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "5835365c7ebf66026d5ca60aff4c161991f49b0bf7ac626d95a8bd28b04fe759", - "dist/2023-07-12/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "07cf34b72aba65becbed5a0465f5b0a2154427100a8520af99d9b64af2ad8483", - "dist/2023-07-12/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "8241523fbcfee63cd6c62c19b7198f0a6fe8038dd886eed410b05903739105c3", - "dist/2023-07-12/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "78006dd24bf206104c0c2b1c54e8281234f6758ceff28fdbd5a39f280bd09bd4", - "dist/2023-07-12/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "be35239b3c6f35d9616055f92c0cdd014d1b55d62424d4aaf8e42930b0ce9e25", - "dist/2023-07-12/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "8f4bad99a3eefb9e46453425a48e47e6669e8ed1e3de3de07769e6faaca5af34", - "dist/2023-07-12/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "2523a411d75ba8bd18aa41438039f5c27dc7eb62a0cfa8f3e625d2f50a2258ec", - "dist/2023-07-12/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "6fbfc96c33502a4cc6484ed8899a9c9de011cb41f4656773f2a3b19b342ba6ac", - "dist/2023-07-12/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "c653216ff5ad0ffd50e7dfe5682c1ca51bbfa5d3bc8194cb8144ae80e617ead7", - "dist/2023-07-12/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "306f4a01fe16a5cf72fdc687bcb520b14e60b1b3b3bacb4a2073a2bda0714a1c", - "dist/2023-07-12/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "ed071c2f96c5ef162aa7865ff4c45432c0a30bcf09311202b9a96d29102d98c7", - "dist/2023-07-12/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "63a2579ef0aa3342f7998803705a6e574891e135090c85c9894f767dd60b780a", - "dist/2023-07-12/rust-std-beta-sparcv9-sun-solaris.tar.gz": "1dbf5fac46eff7e390e2577041c3c8f462e36eb0bf71f97e5273a934d4f99d08", - "dist/2023-07-12/rust-std-beta-sparcv9-sun-solaris.tar.xz": "81d66825005b0a501dddd22db16d7d783a7d1114a735c6734c447b469f67f1b3", - "dist/2023-07-12/rust-std-beta-thumbv6m-none-eabi.tar.gz": "e8a6fcd3fd68770ac582531ed12e9b11e4aac808c9ffd6eef2e15e01737717f8", - "dist/2023-07-12/rust-std-beta-thumbv6m-none-eabi.tar.xz": "08d11f9af0acbb3f01e8d36cd209f4164e1e7c0b1896add89e96d09895eb81f2", - "dist/2023-07-12/rust-std-beta-thumbv7em-none-eabi.tar.gz": "904f54943102586198c83d779102d5d913f35b743fc5258d7a435eb8a414faaa", - "dist/2023-07-12/rust-std-beta-thumbv7em-none-eabi.tar.xz": "80d4be9cee0123fdecf5f92a550323e4864b00800df5be48e7a5992330b09a9d", - "dist/2023-07-12/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "9c887c04608167e70ac66c7ca28f2adcb5b3111cd308203cb91c1e3d54910d60", - "dist/2023-07-12/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "0ae9f88cca6bafbb4fd6fcfa6c17550f0f478b38c8d061b276e10e5c8dc41510", - "dist/2023-07-12/rust-std-beta-thumbv7m-none-eabi.tar.gz": "9a6d40873beb20ea62a5a211cbec6df52dbb886b3c30d8b46086711c9d46f9ce", - "dist/2023-07-12/rust-std-beta-thumbv7m-none-eabi.tar.xz": "cdea56ba84ffdb31dde025073149e79a58f245f281a8cd2584c3032b649b8489", - "dist/2023-07-12/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "dc7b75d01d002b0e373737b0cccd7be2d396dee45f3da5174bf7bf94ae492949", - "dist/2023-07-12/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "c602afb2b5d6c4b6319f90297102c9d8c192e53e1b55a047c37b1d8280ce7100", - "dist/2023-07-12/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "0af441e446e4f7b1dad0593eb91d0bff30698fe66b0355928f95d08044aab4f1", - "dist/2023-07-12/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "3119430271c51189b66b2f033db32c6969f767985165270a9012a7535a89840e", - "dist/2023-07-12/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "87599a0c69951178be32f649f86a14c466771657d3d065e15749372daecc255b", - "dist/2023-07-12/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "a3dc1e688fa5bf81a5563831bf7a50b699392566da5dcdd35f773965c63d3c76", - "dist/2023-07-12/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "93056ded57a786931d0727c3c22a0e18c3939591848d1781b60d4235cb9a909d", - "dist/2023-07-12/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "a20c785842f9edcc85f7ded87c5c15de1ff96f9e268055ed4b9bcfa79034df93", - "dist/2023-07-12/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "a2382c5801287d9657ef1bb1ed8032b3f43fe4d0541529ed31aba967ec93a1b9", - "dist/2023-07-12/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "eaf0252d5ff159b8fd6788e63077ae1b87d7d529509d4c137452771477b8ff87", - "dist/2023-07-12/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "d6f4ecbcfcdc8f67a2bd0fadb955d716cfc030f7d1af1d05d71a2fcc16a8fd6e", - "dist/2023-07-12/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "1c7a720a53ef38055b23f078212d6fbfce39d715d4f12c2254d4ebd1c1cd1f4d", - "dist/2023-07-12/rust-std-beta-wasm32-unknown-unknown.tar.gz": "aa3c539b1ba267233b0310e5d8f8a97ed8a75ea6db96ff93fdcb4e7416be6609", - "dist/2023-07-12/rust-std-beta-wasm32-unknown-unknown.tar.xz": "dc3cbf54d1d46945e192d0f8b8d88cb77211d0d64d3f11a0d85b280d46dec35d", - "dist/2023-07-12/rust-std-beta-wasm32-wasi.tar.gz": "5731012231903dcf24ac529dcb3b08c598dc32857e3daefb636fdfd9c8e8cb83", - "dist/2023-07-12/rust-std-beta-wasm32-wasi.tar.xz": "5afac33b9009665436b2f522f6b26543f1287fd1972d6d3c3c74e2de8b1ef791", - "dist/2023-07-12/rust-std-beta-x86_64-apple-darwin.tar.gz": "30f925d5e75433e29e9448568bf4182902c02deb8eea53cc2645e1d530b8c327", - "dist/2023-07-12/rust-std-beta-x86_64-apple-darwin.tar.xz": "627d5378da2c26482f7461f82ec792987e67affafea079565b57bd86792058e7", - "dist/2023-07-12/rust-std-beta-x86_64-apple-ios.tar.gz": "db07a73405b8cc49c95c7d19c6a51e3aa88a1d7fda722e82e883efb12a763230", - "dist/2023-07-12/rust-std-beta-x86_64-apple-ios.tar.xz": "6ff23b2d7d8b0df0ea8475ca26775c094857166df94688595b6f0a5d58f8bdfa", - "dist/2023-07-12/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "103628b332971a4ac1998ebb9dd8e258f78de85510e12b78e4d9e7c0e61e8747", - "dist/2023-07-12/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "ce708d121273e40785975a5bca01fc1f51caf713ca1b5144e9aadd053f153ae7", - "dist/2023-07-12/rust-std-beta-x86_64-linux-android.tar.gz": "f949c2945a7458d2196d59b6f7fb15236182cfb0df20b7a07b3db63cd882915e", - "dist/2023-07-12/rust-std-beta-x86_64-linux-android.tar.xz": "d8106d2042e18ac1401e8735229adeaf24b276a3cfd2f9e8f9b67a14c2f64dd9", - "dist/2023-07-12/rust-std-beta-x86_64-pc-solaris.tar.gz": "b9e46bfa7576b0af27ce97106d8d243a5536de4e195c70a49c7df959c3c51f6d", - "dist/2023-07-12/rust-std-beta-x86_64-pc-solaris.tar.xz": "07489a82384a92becfc5ddfa1c2154613d32bed30409e64f520b06b52219a620", - "dist/2023-07-12/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "44c447c64aea3a471bcde4e2908c812e4f7cac949f29273037e42b1d19deef8a", - "dist/2023-07-12/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "c12b7a419935c6a6fc8fff4133e6abbc51ac579085e9ac503899ca0b65918d56", - "dist/2023-07-12/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "ae163e45e5470117db8c363badf7bafcb54755c016d7f83d04d969f63ba219a8", - "dist/2023-07-12/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "b64d506318824b764a0b5cf75768d4c1ca43773863c70aa73fb2d0df654d2690", - "dist/2023-07-12/rust-std-beta-x86_64-sun-solaris.tar.gz": "12bed740d7c0a3a5b2e85a8ae377ca97341e7eed5eb7d0b347a5d2ad362e5d21", - "dist/2023-07-12/rust-std-beta-x86_64-sun-solaris.tar.xz": "887930cc08da83c766ccdcc59bc6e983fff512dffedd911eaead1d4c5611dfab", - "dist/2023-07-12/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "778967f9f2e2802970e9b24a8edefc815746a200eddca4c400c5c615b8eb98e9", - "dist/2023-07-12/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "3b24a6ec9d65b2838d9985a210e6f9d39cd880830e03a90c472f6b2b9ff18e30", - "dist/2023-07-12/rust-std-beta-x86_64-unknown-fuchsia.tar.gz": "402b86e5b082e07c214023d412773c27733ac1493e5f559c52bbce7dc56c895b", - "dist/2023-07-12/rust-std-beta-x86_64-unknown-fuchsia.tar.xz": "571cee5f07dd3b4f053ef5f4e830bbae0ce2f95004e2ff13e029d27a7956b338", - "dist/2023-07-12/rust-std-beta-x86_64-unknown-illumos.tar.gz": "5bac95d69f03e59390023ed50084f20ee5ec2757a2890fc2486fe71cf7028d47", - "dist/2023-07-12/rust-std-beta-x86_64-unknown-illumos.tar.xz": "0a9a8fa23076619ec7e7ec60a293a46989cd0c7e4d3ef8ac76f5521747702ef2", - "dist/2023-07-12/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "227fd782a16425da1d63b4475351764298859ddcc50a2786b4ab0126a63fe559", - "dist/2023-07-12/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "2a7a6b36b2138daf5b97e307bd7f440d1b962f5c51a6bbec61f56b0bb909365d", - "dist/2023-07-12/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "a909474b87ff6abd09f4be16deb3210eec24cb1668eeddf1ffe683a542aa64e0", - "dist/2023-07-12/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "3ec154062ae28ecdb79cb2adb06db0acb9bc2633906318f9457b9e349a249237", - "dist/2023-07-12/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "108f9407bf5f7d2360d4d007a63792f1b5c2f03bf492cb553bcd36110d4f9ac6", - "dist/2023-07-12/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "8764f19bd2ee50000789433c9d1ba4771c3ed8f5f93d478998bb329013d4c1d0", - "dist/2023-07-12/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "0c95d624aede0298da1e08e4ce65f358f34eabccc47903dda65298f70b3d08c1", - "dist/2023-07-12/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "982bb81104b7ecfe0ef5a29e2e8047ba22691fea55449651b8cb2592798b34b1", - "dist/2023-07-12/rust-std-beta-x86_64-unknown-none.tar.gz": "023f68b3c2f26e2fe9d3bd8a176853c1ab7b82158d3c68181411bf9a3dbc02bf", - "dist/2023-07-12/rust-std-beta-x86_64-unknown-none.tar.xz": "b5203c4036b38d9bd41d87e662212b4a0dd2098f42ce016146ef781d864d5d16", - "dist/2023-07-12/rust-std-beta-x86_64-unknown-redox.tar.gz": "79c54bdd460dfce0be833185e27b698a18a50bc63706eed5ad6a55fd43f00cc3", - "dist/2023-07-12/rust-std-beta-x86_64-unknown-redox.tar.xz": "994752c9b73fa13fdda515296329e1b687dc98197401a5db4e93bdd00ef1a3a6", - "dist/2023-07-12/rust-std-beta-x86_64-unknown-uefi.tar.gz": "254008e9f38d1420d9f6c68563c0475ed26128cf7918749aae19054b658f5eea", - "dist/2023-07-12/rust-std-beta-x86_64-unknown-uefi.tar.xz": "63eb6b43d7c526413907af2ae261135ab6cd30ba6d82ba92fbca8c9df7dbfbb9", - "dist/2023-07-12/rustc-beta-aarch64-apple-darwin.tar.gz": "361629903acc59fd7b9e23381ba10adcbac9b2ac1f9fa8ac995a6b7b34c73a72", - "dist/2023-07-12/rustc-beta-aarch64-apple-darwin.tar.xz": "74d498d2cc984cd1dbef636b3feecb81adea0e7ba581b4b27364ec4f26a81f76", - "dist/2023-07-12/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "be27c9217645d381c43014133e6654cd699bc3695310fcf3669d254d03c855c1", - "dist/2023-07-12/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "54850fa60693e3b353ac186695eca1714d96bf4a26528bc221754a4ef41dcd13", - "dist/2023-07-12/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "ff73babf1ca49c0d7bc61691ebead9d88fe60475e0daa99be57fc63d80c54db1", - "dist/2023-07-12/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "006bc3e8ad7e08112b9bd1b217f78795f251ff5c40845263eafaa24cda564fb7", - "dist/2023-07-12/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "e0d2afd64d312b174f877503dec692effa0f828a14801363bc639308e964815d", - "dist/2023-07-12/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "2100939e2080fad8040434e0d5afb38238a583deb9d2d87983ce3509d1f34fd5", - "dist/2023-07-12/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "b34aebfdafa0d27ceb2bf1494de0894dff09ceee7f924f805f55bee64c9144e3", - "dist/2023-07-12/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "b79fdc2786057e5267b3b00b4903786f16a522aadc2f3dd8bb8456e42400862c", - "dist/2023-07-12/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "e2e86e88c21e02fd16e5cc78a8de023af33a52d9b5006dd6884de5d97459ca1c", - "dist/2023-07-12/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "9e3d480fbd3387aca0acd8c63a45d91e2148117fd5dc532885328ab39cbc9d11", - "dist/2023-07-12/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "b08a6627dc24f348cc6eb9c89a63099ffdc1e71d562ccce0a7906ef279b4cccf", - "dist/2023-07-12/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "57d4513f8dfe30a2a62886d931ac317d956fa723b4d72c458f77c4be28144ec2", - "dist/2023-07-12/rustc-beta-i686-pc-windows-gnu.tar.gz": "6950bca30824403a94c1a272d4bf7a5771dfe608c20a3045ea6a48a5ad789851", - "dist/2023-07-12/rustc-beta-i686-pc-windows-gnu.tar.xz": "7891a4ca20a622138c5008824c01c6de7b5b4306381375d95b3063518eb7883b", - "dist/2023-07-12/rustc-beta-i686-pc-windows-msvc.tar.gz": "cbf66d5ed4dbae45e1738c4ea3879886ec59062bc59be93b2b526c49634fabe5", - "dist/2023-07-12/rustc-beta-i686-pc-windows-msvc.tar.xz": "01d52825cd5d184028f6fa2b47d061254e500324c43db0c7ee4cfede9f801791", - "dist/2023-07-12/rustc-beta-i686-unknown-linux-gnu.tar.gz": "04f9d64cde2749214fbfa849c72df4bece1c0c9bd485933acf41e4b38bb90976", - "dist/2023-07-12/rustc-beta-i686-unknown-linux-gnu.tar.xz": "387b72fec91c8afbf088819248b8333198a1588ff2ef3fced9dc75a0d28152ac", - "dist/2023-07-12/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz": "d6d6d499f388395cf0234ecbc250ad8c17201388502cc0b1d4dcd145938edf59", - "dist/2023-07-12/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz": "2f83df3cd76a236ed170b9b9eece1be1297f2159226d6ca13826ed345ebc25ba", - "dist/2023-07-12/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "fde554a543eba35030ff0b4c3402b5c24c372a7071d1e489797106b51392caeb", - "dist/2023-07-12/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "7d8dae3414126ed8d34dffa577d59b236d1b04dd9aaeee8e83bf50ef3269cceb", - "dist/2023-07-12/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "558622fcbf845cc05114680d20edb596f243304b5d540f8df3c575d0c2c681ce", - "dist/2023-07-12/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "4716b40dfa7ad351e9c476742d119167b30c5c4c2b2316808d6587ff0de69c7c", - "dist/2023-07-12/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "c97ad88f524cda10fc59e083f543b603a84e47c4cff2af51bd6294b0c04fa52b", - "dist/2023-07-12/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "0cba6173edc10993176e466b2f0c353551b7f544d499eca90e143c40bd855288", - "dist/2023-07-12/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "0d0a9cf77521a372271e6c37b7ca9b1ea879e1f8ccbad07e88a047268fbffb02", - "dist/2023-07-12/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "8f5e09fb6febc5965ec762d88ab812385ec133a732f006c6a61aedd3be6a7ce1", - "dist/2023-07-12/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "35fdc9549f2ae6545458ca9a899a2e6ecca33864709f28c3479bf547b86bd843", - "dist/2023-07-12/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "4f3ef47d674787313ce445ae453661302df3cd5c36e4f135b4cbf1ebd60a1e3d", - "dist/2023-07-12/rustc-beta-x86_64-apple-darwin.tar.gz": "ac623b79329ffae330e76d79a9ca741962725a072e045b8b7d9b2d6fee5a57b3", - "dist/2023-07-12/rustc-beta-x86_64-apple-darwin.tar.xz": "439cce8c9f3d614a8eefa45bc42723a15e9dfdefa83cb48f1751ba8aaf1fccb6", - "dist/2023-07-12/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "4f91add8c303b2c82ff9d2c5bb0723b298e0e1f5ddca524af9c1fde490d0d346", - "dist/2023-07-12/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "cda1396c2eddf49e42cab04fe152b4edea0d9ef61ebe987307962a1c5dd1e55b", - "dist/2023-07-12/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "993f06513b965731fdd678208985a85b0edb94887df4f4518b8190f1bb9c9faa", - "dist/2023-07-12/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "7a41f05c27619407a4a4ae6acf5ad567f2504d4b8e7462e0fc409513b3086dc3", - "dist/2023-07-12/rustc-beta-x86_64-unknown-freebsd.tar.gz": "19ab69319c2c52580e447cc22471fb18a25b06849c1fe79783eb067e0f75f1c7", - "dist/2023-07-12/rustc-beta-x86_64-unknown-freebsd.tar.xz": "684cbc8205f08c9e7aa6de7fc72422dbc87d5e842367f0c3e40f2206f3bd1045", - "dist/2023-07-12/rustc-beta-x86_64-unknown-illumos.tar.gz": "af31123f89adca1858eea5e5f00e42913aeeda1dbc7572d557a7ae132928f3f7", - "dist/2023-07-12/rustc-beta-x86_64-unknown-illumos.tar.xz": "e4f711e5b81663ddc2d5b5f85b74488bcbd0535c8e170fb99e3fbe7d6931e937", - "dist/2023-07-12/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "6f781b40006f6552a0f4642808950ac570d6b4a17e15bcb373a385ac5f822bb3", - "dist/2023-07-12/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "af7d049238fdf1d538059b918d5ab0e3751ada2f3a339a7479a295d08b5aa963", - "dist/2023-07-12/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "bbcfa001617d591fb663b55f1c072c5bd1c5ae57a245a00d6fcbe02ab52ef4e7", - "dist/2023-07-12/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "56ecccd46000dcfda0996da364509b7b2a739132693f776d63f9b1d74fb8c546", - "dist/2023-07-12/rustc-beta-x86_64-unknown-netbsd.tar.gz": "181b946f424be9a5430f79d56c80324e2a72ed638e571fbfc7d1af370d4aaf11", - "dist/2023-07-12/rustc-beta-x86_64-unknown-netbsd.tar.xz": "2bc9406b45f14e2efb47c9475ae89a3ec9ce780c402d27f11c4a6217a5845258", - "dist/2023-07-13/rustc-nightly-aarch64-apple-darwin.tar.gz": "4298aa816d4a6c1004e4a480f77e0d321a47c4b5e2048ed705a5a7d632a43bcc", - "dist/2023-07-13/rustc-nightly-aarch64-apple-darwin.tar.xz": "0758cf22ed98bba897ad3bff5c3fc49367d3fea25185e1b39cea417941c7ce42", - "dist/2023-07-13/rustc-nightly-aarch64-pc-windows-msvc.tar.gz": "0db596a386aac8d2d35293e8466a710498102ca6d68a16d60ebbfffa2cc67950", - "dist/2023-07-13/rustc-nightly-aarch64-pc-windows-msvc.tar.xz": "6a51533a6bdf3ec705fb7d09f076e67393b4090159ce6bfc8ab9a4abbda1b421", - "dist/2023-07-13/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz": "c6dd529410c4ceb5ef851380e1f12581fe0d2240b9224bf4727f4ef0dd93f7ab", - "dist/2023-07-13/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz": "7b3d71fd596292c3989c2e8982fe2d488f90449e68114be331f7589b296b9b1d", - "dist/2023-07-13/rustc-nightly-aarch64-unknown-linux-musl.tar.gz": "8551f98fb1030ff712a68b97cc1c67bbb19ec51748f92ac7d149b0d1e2f08ada", - "dist/2023-07-13/rustc-nightly-aarch64-unknown-linux-musl.tar.xz": "853b80262a5e58dd8c831a42f0efb229e5eb8516c6d4ddafc02152e2e55b6706", - "dist/2023-07-13/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz": "d04649a98a7410594bd4ac776a638d7312838e0b15cdf53236b953406a1bcf87", - "dist/2023-07-13/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz": "6319a00b08efdac3a379d587d8c11507a79446e9ef2421f6539af9a734ec2ce5", - "dist/2023-07-13/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz": "9739f7d186d5a92d9e775bda150ad1893fa14720f2e3662d61220d125a68868e", - "dist/2023-07-13/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz": "818fc51517ad026bda8c3eefa3065d3d6d9e465f600398404987e9c8420ba933", - "dist/2023-07-13/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "557e197ddd49d62e271108c8c0f17618d58c6b77841aee75cf190a260de8b522", - "dist/2023-07-13/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "a60b73f673e80f02ff1c1151e63d883b8e390ec447cb3154b1fd4ac4b4b9af78", - "dist/2023-07-13/rustc-nightly-i686-pc-windows-gnu.tar.gz": "31fe306c7b547d1e595d82b7195d972a3e8dbcace6bf786557d0ff14b7f3a243", - "dist/2023-07-13/rustc-nightly-i686-pc-windows-gnu.tar.xz": "32dcb5830ae51effd7f8bc6c2dc8c61863952c1eb34a3f6a5e5a7ca1e632660c", - "dist/2023-07-13/rustc-nightly-i686-pc-windows-msvc.tar.gz": "4ecb180c07b1f1f15f51508e0d2290204052ce98be2203c8d2257f620b0a3c32", - "dist/2023-07-13/rustc-nightly-i686-pc-windows-msvc.tar.xz": "e9a6e85dc43561d644988e862db6d3af53b14397e8aff1b162fe6f29c65062ed", - "dist/2023-07-13/rustc-nightly-i686-unknown-linux-gnu.tar.gz": "4fdb462e10993e386f03396f98379bdfe45d60c38bce2102243d566d4eb0178d", - "dist/2023-07-13/rustc-nightly-i686-unknown-linux-gnu.tar.xz": "759d1c97a06baa0f7d56705a0d4b4bd954057d140b1a28e34db1d2a59c85307a", - "dist/2023-07-13/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz": "5f0ebf7b582bb3e8112e8287a33966670f33c46db6fc4569963a7aa0c1b6daf7", - "dist/2023-07-13/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz": "044f6d651b03b1c74bd5ed86139119ed0cfd4643576860770a784557c864388d", - "dist/2023-07-13/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz": "9fef5ebfd5b50d256d85e24ecfe3953da80bce799c83eb8f453e70b20424274e", - "dist/2023-07-13/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz": "8d3c75ae12ef9273279c5c715680e0ec5035bbc642ac3e6e9d5e31f718b4d625", - "dist/2023-07-13/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz": "acb5e2e805023eaf2403385d26f1bf6fa91dc505f2a030bb3ef1b1c415cd2251", - "dist/2023-07-13/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz": "7bbb565705d19c01404e519c3b15db717678995f5ec5fbb572937ae7ee2efded", - "dist/2023-07-13/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "9af44902fc657866446dfa52a8e5f561e69e555c49c0e6f32d739b4a6af98a59", - "dist/2023-07-13/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "f9e877a64286b78876f33f7506086118653d01674333c59907e8cdf71c4e95a2", - "dist/2023-07-13/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "c5a1fb8c5f3a69adadac4a7c0f8734cc14b8ce1e383530419a095c4db6645b11", - "dist/2023-07-13/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "521e7be385877a0f4069435efa9308fc5d33e4f90294270a7f8df9327ce222c1", - "dist/2023-07-13/rustc-nightly-s390x-unknown-linux-gnu.tar.gz": "55d9efc83614e5fcc4a7ccd0581a95a66ada4577198b25b0f4e7067ee72cdbd9", - "dist/2023-07-13/rustc-nightly-s390x-unknown-linux-gnu.tar.xz": "6c88031cd1d59fb6c2f971b3ca9aea2e029f8481cd41824ffdb67a085feab5f1", - "dist/2023-07-13/rustc-nightly-x86_64-apple-darwin.tar.gz": "b75c6defcd94b930ced62a7ee18000a68cf6bf255479ead60395ca3158f2f198", - "dist/2023-07-13/rustc-nightly-x86_64-apple-darwin.tar.xz": "ea1dc2985f708823719589fb029de961b179cf19bb228a4745cc26a47415a5de", - "dist/2023-07-13/rustc-nightly-x86_64-pc-windows-gnu.tar.gz": "c1602297eab6a276aa367b2f85d004d236d26cd4b4133e4cffb941ef3c858c74", - "dist/2023-07-13/rustc-nightly-x86_64-pc-windows-gnu.tar.xz": "06965d8332f0fc167886f6e9a3ff9a558aa3513711ea309bab5f30185a9afee7", - "dist/2023-07-13/rustc-nightly-x86_64-pc-windows-msvc.tar.gz": "80c3d27142473a89beb1969cbfdba7281ca237ec8f2a5b20c75eeb14c5e2e771", - "dist/2023-07-13/rustc-nightly-x86_64-pc-windows-msvc.tar.xz": "52fe4134ef2ab35ffa251669a30ca6c9aa94a3ca97238f46f9aad0b2b9dac70f", - "dist/2023-07-13/rustc-nightly-x86_64-unknown-freebsd.tar.gz": "837f628f7775d13b661c1e7dd7a1de649264abca247aeeb6cbab05faaf7e83c2", - "dist/2023-07-13/rustc-nightly-x86_64-unknown-freebsd.tar.xz": "732a597647702c2672f559c83a8e829c36dcb8fe92bf8abdcc1cf2526ba2d8af", - "dist/2023-07-13/rustc-nightly-x86_64-unknown-illumos.tar.gz": "07eed9287f36cc6650838e27b7148c26d588b96b522e1b72f58ceebec4b0dd87", - "dist/2023-07-13/rustc-nightly-x86_64-unknown-illumos.tar.xz": "70cb988d67159941502900f803e29bdb53f81057d68393965ebd63fe42e2cba4", - "dist/2023-07-13/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz": "adbe0dd7ba4df92f199118943bc25d3a467d6c1d3249817b74e05c7d59a76846", - "dist/2023-07-13/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "c999ab64cbbed8bc2853b717190d6d4aac871363c7182e06c5144e50d34621b5", - "dist/2023-07-13/rustc-nightly-x86_64-unknown-linux-musl.tar.gz": "1bc5368592390eee2478d48f75fbeb5e9f3f8e4fc2f6e3e6952fa08e7c8f46f6", - "dist/2023-07-13/rustc-nightly-x86_64-unknown-linux-musl.tar.xz": "15559729aefc45dcc1b28333e6166a2fe5b1e0d30521b9a1ecd80134c859ed85", - "dist/2023-07-13/rustc-nightly-x86_64-unknown-netbsd.tar.gz": "f918703cc31c800e35d739ef146733de486a6fbb2a0c78f993352a1242352f0b", - "dist/2023-07-13/rustc-nightly-x86_64-unknown-netbsd.tar.xz": "777d69d7190825ea83dc44712d0372b1a225b3e4fde66d1b9ac4ea981d54a031", - "dist/2023-07-13/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "998a5c80bfb2450869e6975aeb178104f3424df6b88fccb9c549ff95fb0a62e7", - "dist/2023-07-13/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "84f8e77132b4ce46086907bbaa3bbfbe151400d8110f075cbaa31e80616d9891", - "dist/2023-07-13/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "63a8b8302007b9052a0016200332e85b24f758960eca25ba7ffb7f8d5c6ed409", - "dist/2023-07-13/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "291d17a39390b1259d47e8b1c9495d80817e12854cb3ede2a91b50a8c7a998f4", - "dist/2023-07-13/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "c5c5d47c25fecaed410f1c0004e30abbc436b5dc85110f657f1ddc87b10933da", - "dist/2023-07-13/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "c7da897bf78cc051fa0028b93253348ad4b89c3dec9782d093db98b1814cd828", - "dist/2023-07-13/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "2be878ea50ad540b17658dd29bec4124c43654f4668c62e7a4b2c7b5ad07155b", - "dist/2023-07-13/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "b355c1bd4140205c613c539021e0194535fb3c94b3eba2a2dd6ae314a7bca891", - "dist/2023-07-13/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "84e711b5e26487bad148d9968ac7236fddddd050761a3069ce10a8e222a860a1", - "dist/2023-07-13/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "fff567ecf3c426558c8cd84776870d833511049dbc531ed5e71733694afe5f70", - "dist/2023-07-13/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "61b48838a1f0097a8060f4a01e3b5ee2acdf409ca681ee7c78c120ee59a82e1a", - "dist/2023-07-13/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "687576f050b1266236e986557eea10fe4354d6be3ab930c5874aac9accc19a7f", - "dist/2023-07-13/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "003e572ef26cc1f39449fc7c488be6ba4fc180a432512036c2035c5249b5a7ae", - "dist/2023-07-13/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "dad6a37c9054bad090e3fc69679ef61cf95f16063623aba72f8002a95d548020", - "dist/2023-07-13/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "707a6ea9565d9c65b0aa3eac205659c41c70da0f6301d04caa4291716e70aa18", - "dist/2023-07-13/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "0546e09197a129dbf27b93ff6e0d84d0dc1a4b40e49ec131e29cd2c3636a950c", - "dist/2023-07-13/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "d7a15e31b67f1897a2968d58b0578fd6489e55709cea5747b9b49f5aa2e4d62b", - "dist/2023-07-13/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "5b1bfa464636528d7245b7524fe471fdafc2bd088efc5d99823a5d3b31afd48f", - "dist/2023-07-13/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "ab7d0ac3cbf01cdfd0aba52d869208469d49193a81ba59502d08a377cea883f1", - "dist/2023-07-13/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "f18f262a288c55b72b434abbb0d304eb6bae7db27fccfb2bdca6eef9078c0f68", - "dist/2023-07-13/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz": "6e95d58a682e0f924b71d40827f156e3a52b5c90bf3347b4b67c275f1e372537", - "dist/2023-07-13/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz": "c68cf075f8eba37e424a1ad79c87963070b20fb38c0e140bbf9733368e45077d", - "dist/2023-07-13/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "f41f9f8f383b12ab0d93b63647aef8e57431475ccb41675d69071a69fdebb6fc", - "dist/2023-07-13/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "ce097e23de16a0f0208fd669c71c372dcc99ab3114af573cc38b1b58ed5b10d0", - "dist/2023-07-13/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "6fd13a4f75c4d3ce82a7d7e54051c308d7a18be89c829ab0fe313c6735c74a8d", - "dist/2023-07-13/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "66c363a6804f279ea8ac52db85b6ad37b3075f59a6cf2f9be213f2849a76880f", - "dist/2023-07-13/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "480fef935283819bfa03c8d4ccc9300bc1c6669371c4ba41af2e8e3bd547e8cb", - "dist/2023-07-13/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "a3eb16f78498a99dda46398befbb0d4a876e62b9db9b344e472ba072c8583846", - "dist/2023-07-13/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "607a0582cd382a04c8131cb03cfc48092eac953953aeafa06dbe84889553eea5", - "dist/2023-07-13/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "0bf682b38cef792c1514b2277c8a933c27d87197895b83c3a67684ebed134ea4", - "dist/2023-07-13/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "1579084ae15cfc842f587e1e208693cdf7fcfe76dd818efb3b98d01a39b1f93b", - "dist/2023-07-13/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "361ad2ecb131f2c0ed773c864c02f59d960264fd86cf3397e81b58bb9d0237a3", - "dist/2023-07-13/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "429150699fc23b90bb034b2b06dbc27f74f0fcd467225afc012ac7dd639228c6", - "dist/2023-07-13/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "31468dbf051c1edcd69873264c28e046d5d6e1867ba9255b8a0e97905b536fcf", - "dist/2023-07-13/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "38e8742bb196216409e474e07deaac2d2a842d1372f3b7e1ad24c039cc0fb609", - "dist/2023-07-13/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "8287a9058332bc41f7b83788d5c3af2bfdca6986301e3d97cdb583b619967c2e", - "dist/2023-07-13/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "db584715b7df3be2d97878cc45102474b551e13604e71485dd14e68dfe3706f0", - "dist/2023-07-13/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "6fd6ee9dca05b8560536c738cb0b4020aa37397acc4a1888f4fed5a89e461d8f", - "dist/2023-07-13/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "8bccffaf50ff3d3ea7197f0a5b2fa075996afe9de602821a5638ee5d7c56e610", - "dist/2023-07-13/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "0ee2812579304231d29c32d32e5b908751e369ce7776b9773a3cf89d5fdb00d0", - "dist/2023-07-13/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "9f26ef23056f20f722f3616632cad8d03428248f126c83ed682ab4f67268e7df", - "dist/2023-07-13/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "1265d7f28cf332db9f467d02f0a77ffdfa926bbf7ad5d148cb04ec888abcfc49", - "dist/2023-07-13/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "74a5d268d82c39eb2b23b5324ce978647e59591e586f7c52d9187d7843990e1e", - "dist/2023-07-13/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "4b16832cd24285705a29e3e9aaec554675852200763bffc6124005211c38f37e", - "dist/2023-07-13/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "0cd34367c1ee4a61cf7bf26591aa65de6651c0a0912afdd1f08cea60da35ea91", - "dist/2023-07-13/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "5321648a640b3ab57d329a1ec5e83f30825c2a8ca73a4135c1c003726d86b28b", - "dist/2023-07-13/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "298c887d59f8f1a7a4d02335224fa1b9b3ccdf540fe5bbf00417d083352c4149", - "dist/2023-07-13/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "f0e6bc108a89407273790d228d51351046183a4eefd64631879cba6fa72c60d4" + "dist/2023-08-22/cargo-beta-aarch64-apple-darwin.tar.gz": "3a683934876a9794ee7ddbcf7cbf5d804d111fe02b324aa0a0321ec9cdfa8cfe", + "dist/2023-08-22/cargo-beta-aarch64-apple-darwin.tar.xz": "6543aef16521f2d7b4b6eb9e69e003dd8adc3f35a3af7d9d35a6fe8580ccc407", + "dist/2023-08-22/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "c8f7ec0b5b796c5218372ffd717728b3d70b56e6ac9002e351ef165c45455f66", + "dist/2023-08-22/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "d6778d5c515222a53a446ced90fe249613a537538ef2cb5aa5bdd807043907ca", + "dist/2023-08-22/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "c077c1851e22ae9b13bb2cb6227602b57427916a7412a63365711c10a8c05df6", + "dist/2023-08-22/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "a33dbbc00ef63ed18e48e42328f25932d1adf62531ed614c650d5e16ba68efac", + "dist/2023-08-22/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "0a68d407c8301f5dadb99cab2583c4e036539b52f46936995fb3ece4ab009551", + "dist/2023-08-22/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "577bb44224b03d5e50f511176a2a28cc900fd39ca581c7ccdd8c098c1ca48e9a", + "dist/2023-08-22/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "5cfea3f60889c5ea51398427fd34166f94c57718a65556abbc942decdf23366b", + "dist/2023-08-22/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "546b0f2b40edfede8176d68ec8278f7908d606f7f22daf3837fcc5beb5a04284", + "dist/2023-08-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "362157d5d3d6ccfd7734f2fbc6e3af28b85c7fec7bb1ca7c82fd5cb786c877c2", + "dist/2023-08-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "05c51f3d4479a6f5ad562406e13e33cfd1c193a1d48190210fa2cea48da019f9", + "dist/2023-08-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "ead8d3d836f57d6dd02a1643446c9d8a34bf20d64e1bc402181ac8e44848c877", + "dist/2023-08-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "ee127cafb6411ef6a4f7cacf2ea90b69b86201f488abd9acb3e82d22fbf56dec", + "dist/2023-08-22/cargo-beta-i686-pc-windows-gnu.tar.gz": "141bfa0ab5bac465ff7cdd91adbc2c293e78cabe458f2d425c6c0ae9b2659d66", + "dist/2023-08-22/cargo-beta-i686-pc-windows-gnu.tar.xz": "dc90fcd745217c237fd570a8ada5c45773066cf58e26bcb87476d5775da32906", + "dist/2023-08-22/cargo-beta-i686-pc-windows-msvc.tar.gz": "07fd85b164a96ef666099fddd03add274e70b11d9343344c627adfcd5c5d4d48", + "dist/2023-08-22/cargo-beta-i686-pc-windows-msvc.tar.xz": "96fcc0fca2870cf3d4ee8ca167b059b9e4d09bb81c88517cccdd1a082f5aa233", + "dist/2023-08-22/cargo-beta-i686-unknown-linux-gnu.tar.gz": "cc9f41d9de949b08964c6604eb75fc2fb3b79d939e9134c54698aaf4fb701dc3", + "dist/2023-08-22/cargo-beta-i686-unknown-linux-gnu.tar.xz": "e5c557c9704ccd9d5d39d3dad5537c3ef152d0b997806f9d9ad0bb91a2ef2fd7", + "dist/2023-08-22/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz": "ce2082ae94f4ab525e500374ac57bc13d32f8ec1a7dd9896bcd9c9d9c5e3eaf4", + "dist/2023-08-22/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz": "ff18d5b23fd463be8461c27a0ee4a4662f1be1d57f69358597faf915ae42d92a", + "dist/2023-08-22/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "4eb7ee68f3932b4519c9c4fb55b8e79ec0a1dd0a40b17cfaf2c0685201280e74", + "dist/2023-08-22/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "95aebdc6896767735e6e8b5e9ec31511fae8281bd258757f25cf9b91230e2a61", + "dist/2023-08-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "758fd95274033cd40809988da287a72de426267a2fc399d46992a97177f08264", + "dist/2023-08-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "c33c0da9d12fcf19ef145d22f5e8046bcf0df344f325932d620c11620e87b880", + "dist/2023-08-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "71485becac68eb4c47627152a1958226a8b1815f8c5121ef8e4886109a1da559", + "dist/2023-08-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "c03bc6285489d415c5f520c268430edd5edff9aa2c0bd3ceecacf4e916edc4b4", + "dist/2023-08-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "a0f18fe47623d2c30008cf9becdc4dc781b397efe3cf163fd6c4459ae824e641", + "dist/2023-08-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "8b67e2d9ff285903baa094a23c1a4bd9a959ab6f99193c93a9c1695fcde6ffa8", + "dist/2023-08-22/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "399ecc7f0d6f0efd9ae2c4bf382ea45f0054f4baa87a415e2f4cb9998fee8f24", + "dist/2023-08-22/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "465b456e2c34f9066f9ecae13f8e6608cc8cebe3218036794996ed9643a20c3e", + "dist/2023-08-22/cargo-beta-x86_64-apple-darwin.tar.gz": "297bdd5712507eb14c39e37128a24960cacab0319a885fef205b5b31978f4100", + "dist/2023-08-22/cargo-beta-x86_64-apple-darwin.tar.xz": "5a4bcf28c268bdc7a863e7c89595522ad0b6a6ebb3ed3408adc57670c76b5d21", + "dist/2023-08-22/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "f70ce4727665a4cc5f9d7dba8ae91a50a5ab9b834b88eb525a8b213fec25624f", + "dist/2023-08-22/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "7349e7a7c20fd38332a27119ef72f09b8b54ac3c7bc937547f478c3f2bc619f0", + "dist/2023-08-22/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "de204ef0efe760c974ed2f58a3cee7532a1275bbb146f7a648360cee5548b2fb", + "dist/2023-08-22/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "b1f77cd3deeb33f2cb24a568c4530e3cffd6194c8f1363baad356d12f3aa6899", + "dist/2023-08-22/cargo-beta-x86_64-unknown-freebsd.tar.gz": "56a2770793bb768684a84b4d99d8287bb04365c4017c3c0802d36a37e33281af", + "dist/2023-08-22/cargo-beta-x86_64-unknown-freebsd.tar.xz": "c9ae52f1212ff635f3300befbd33e575c308e14ff13f0ac30d5d97a3797788f1", + "dist/2023-08-22/cargo-beta-x86_64-unknown-illumos.tar.gz": "8e5ad86ea47eb4901cc7efae579c855a1b3eeee889c7e39fa248eea4465ac6fb", + "dist/2023-08-22/cargo-beta-x86_64-unknown-illumos.tar.xz": "56b3d2363c98537bd70d5e54b1caa446446edfd9fbf3efafd1f1e5ed24985c02", + "dist/2023-08-22/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "61bb143b2a7969fecb28755227e258d2018d8344c5325b2709b3d3b34aeb6bd8", + "dist/2023-08-22/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "6a5ff803aa4e57e35175fb62cea3687f26a55e9ec6bb0e9066fce27c4f4df727", + "dist/2023-08-22/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "2af897d7e7a9b09d645dde71b81a1757e5ebdeaa0291d5c50ddc95d3b9fe08eb", + "dist/2023-08-22/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "41fac61a6ca64490400807dfdcb96076926e61174ec295e8c6534b41e5541e71", + "dist/2023-08-22/cargo-beta-x86_64-unknown-netbsd.tar.gz": "29d324fb629b1aadc67d207b9a4e3156674a762970131399b10a7d8a6de152bb", + "dist/2023-08-22/cargo-beta-x86_64-unknown-netbsd.tar.xz": "a1f216345774fa9b812ebe3f8adaa4e0be152d095e73f289fa70d53d04d27fda", + "dist/2023-08-22/rust-std-beta-aarch64-apple-darwin.tar.gz": "0b45d8fba14876a6323c8adc8368916f8581c868d63c10ab65c0e50f4c021a32", + "dist/2023-08-22/rust-std-beta-aarch64-apple-darwin.tar.xz": "f471a9373c16260f8ed8b467c6065847a788864289d979efb406e99976d14dc2", + "dist/2023-08-22/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "3c0e3226b47a8742061587050048db97843e6c96b08930ada010c07fe06c89e6", + "dist/2023-08-22/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "7739c05595dadb2f021881b0e38d16cfbd705b0a5d31ac395b8fabb2244c8050", + "dist/2023-08-22/rust-std-beta-aarch64-apple-ios.tar.gz": "261b76a4f1ba923477163a868b539781911c7d0bc8dc944530d806eeb6634cde", + "dist/2023-08-22/rust-std-beta-aarch64-apple-ios.tar.xz": "c16102bef9f2d4fdf3c970e2f4e8316b4b2540b43855860be7828209b63c8fb3", + "dist/2023-08-22/rust-std-beta-aarch64-linux-android.tar.gz": "2b6e30df92c4b0c6e464ab59a37865ac91b4c4c4863b06f2bc872d50e2799bd1", + "dist/2023-08-22/rust-std-beta-aarch64-linux-android.tar.xz": "dc8e6fd9d6952969c97af01358034c9ea21182fd5061dc92527aae73b4305bff", + "dist/2023-08-22/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "773e9b29d36ea66a79df8cbfe0ea28ec77b31b1b042563584a1830d814eec269", + "dist/2023-08-22/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "e40c8120fc1850818ffbd151d152b317f7d306fc27d8305bfc376cf55d7a5863", + "dist/2023-08-22/rust-std-beta-aarch64-unknown-fuchsia.tar.gz": "c61713b4a7f96a6813f96672811de1d979e732db07c177e7a031bc7a3f22781d", + "dist/2023-08-22/rust-std-beta-aarch64-unknown-fuchsia.tar.xz": "1f54408288a19041e58114766263928ec7bee7815c392d25bb1abb5ba2107b13", + "dist/2023-08-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "90be82b6fa985c80ee709113c6fae68c0a6055a6b3b63b84e34d98d1f192dfbd", + "dist/2023-08-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "a2367d58c58aab240049fd5819f7a1862365c8ccdbdbe43cb94fc74ec4b424e8", + "dist/2023-08-22/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "2525b581645aeb8c07129a7680f7ef76e87af4633fd533ac991fd4868049b72e", + "dist/2023-08-22/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "6dcca8f5b63968ebc6adc066d76a4ef53112f52dd160f135b0a029832fe25060", + "dist/2023-08-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "8f07966490ea30beea51e79dd158c41699cc0cc5a5b3cfe211f3452b2d1265ad", + "dist/2023-08-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "9cf5cceb96eb5e2bd6bf05ab663a92db637c7af3c58bb921ea75b61b9075ecab", + "dist/2023-08-22/rust-std-beta-aarch64-unknown-none.tar.gz": "41622341bffd5352c4248535f952f721638ad9e0ebc74b5452f41dd6ee261017", + "dist/2023-08-22/rust-std-beta-aarch64-unknown-none.tar.xz": "cd149fd111b65631e2535ae79dc0fbc4ae69d6ebd25d4f91751f76699be74f2f", + "dist/2023-08-22/rust-std-beta-aarch64-unknown-uefi.tar.gz": "b884565f46a93bd75bbb86a5565d5c6fbba925372d00b8fbb5782f6948f1c6ed", + "dist/2023-08-22/rust-std-beta-aarch64-unknown-uefi.tar.xz": "24c4e88d966a7437a9008a02101c0eb333a78fade9e71113491b586b89d80bbe", + "dist/2023-08-22/rust-std-beta-arm-linux-androideabi.tar.gz": "9b47e40f002a9c8134fa96f3c8566a5ccb5543903804254c59d7102dcde59725", + "dist/2023-08-22/rust-std-beta-arm-linux-androideabi.tar.xz": "96d2b153979301ec03b04b2a35052e2be1edf67693dbef43bdd46eec258604ed", + "dist/2023-08-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "4f4b08d6773721b796c8a4928061647285e7b06e5a93472fa3578d7f5f96ac83", + "dist/2023-08-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "61b62b29fe465550e07e62eddf786086c3a38a7e98c533cc86a689b657061fd6", + "dist/2023-08-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "22091e84c962c9291481454825401693b757ee5cc2332a2a3d8a95c93bb8bd6b", + "dist/2023-08-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "48e273442bc827d22b177e8b33b1be897da20389ead5cce2de2bb4c936ebc845", + "dist/2023-08-22/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "74c06121290814a97c82a0dbb8160721d27210d58a3a4b1b5818daca8265fc01", + "dist/2023-08-22/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "e15a6a3372901716856e606b369392d270dff0b3293988e5c621b86b384f3dc1", + "dist/2023-08-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "e1acaa191877b3debb6b0b59c3aa47937f0113fc3084dbe193944916fd4e810f", + "dist/2023-08-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "e94f16fbd527f39c1b9b3f09b977d7fd07547bdcf00385a2a3a235130c82140b", + "dist/2023-08-22/rust-std-beta-armebv7r-none-eabi.tar.gz": "26fb63d61f57b3ae18d5c014430ed9311cad890d88b8560b1094f2d1f674a394", + "dist/2023-08-22/rust-std-beta-armebv7r-none-eabi.tar.xz": "ff7d3403858c5e77da1da28c7ad81085151dc0c004189a331d3e5f3d8a2d93f9", + "dist/2023-08-22/rust-std-beta-armebv7r-none-eabihf.tar.gz": "f7a2b8e8810a19540186d6c9677c487bdac387a94dc6268cbff778dd93ac1b3a", + "dist/2023-08-22/rust-std-beta-armebv7r-none-eabihf.tar.xz": "b4a7c4b6d47dd3a57b1e05afeabb381d624ba1ebf8e789aa10f00a7efc6b329a", + "dist/2023-08-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "ce7810ab026a6dea1732d983238df88d21ca94ef10f78a06ec2e366149a6ed76", + "dist/2023-08-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "b31641f975c76f63f8c43402db571edb3b335b5dbae1b95c6362d3515d5d28d1", + "dist/2023-08-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "75438e97bf98c48c448ea8b96fba21a5f31c919f2da8c8fe048bd54950964ffe", + "dist/2023-08-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "c8e1c0f109722ca0918dcba00544692abf8d04a98f86b586b513f06d77111c4f", + "dist/2023-08-22/rust-std-beta-armv7-linux-androideabi.tar.gz": "fdc3d9960d0ff11c03e9c7d0c997aba7a5e480b860410a422035f69359d12451", + "dist/2023-08-22/rust-std-beta-armv7-linux-androideabi.tar.xz": "a2acf41ea19e582b99fcbf56e37eb35e9a309bc6183553cbaf12b9dff976dab8", + "dist/2023-08-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "81d1d1459526343aa5ab66432eab7dc9557d0c07550cbdafbbf5e402be7eb833", + "dist/2023-08-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "baa369b9c1df4820f6a8593193bb5376002c79e81dc0681c2329a45ea664a87b", + "dist/2023-08-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "b9e06051b2705ce2680723e3209ed0099a05cf2f2c71342e1176c16e485ee66e", + "dist/2023-08-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "5633759d31f4b390f2f9b5f63a0dc7f027a2dbe1241fe7089c06931c360a5f46", + "dist/2023-08-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "141232d8b440588d181c2d550151879ad6bae9a5af7875e6428bac6e65f6d8e6", + "dist/2023-08-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "5a82fe0b4e9476b642134071858288e47137aa26de88bc892580ab777650094b", + "dist/2023-08-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "8d9821484c5bbe8c51d7d54859fb8bc475ea6cc2f863fadb29b2973daf3535e7", + "dist/2023-08-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "e68834499329dac318fd51c49dd23836c3a6db0eca746869f8dc38d286b5f8ec", + "dist/2023-08-22/rust-std-beta-armv7a-none-eabi.tar.gz": "3353d69ace1f00b7c9d6291144a0ce73edefc5e7498fcb04dcc336edcb3030f4", + "dist/2023-08-22/rust-std-beta-armv7a-none-eabi.tar.xz": "d783d9ab96541426a5cdb2e6e866d0b9b1492e64030011aa3503b6558a4b3acc", + "dist/2023-08-22/rust-std-beta-armv7r-none-eabi.tar.gz": "28b6a82549de0a84323ff7db7104da9f978d2044997681b2ecfd6fbc7e14f806", + "dist/2023-08-22/rust-std-beta-armv7r-none-eabi.tar.xz": "f32aa5def56e3ff083d380de063ff5239f19b2b2ff8648f1f092512a621c8291", + "dist/2023-08-22/rust-std-beta-armv7r-none-eabihf.tar.gz": "f7a57d763304b64e732b46dab90bcf93c712e5e0e5b558ac20033658f4b27e2f", + "dist/2023-08-22/rust-std-beta-armv7r-none-eabihf.tar.xz": "4b74d5e31d3317b0f5519693005ad4c2b3b5093531deae630ab210e177f5b41f", + "dist/2023-08-22/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "691200324336964bb254c98350f6d2c0e545a42d7c6903c76a7812b068cc18b9", + "dist/2023-08-22/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "c2c0ddf54f7dcb60c069117c7139c2c1f57e8f9976447651df2dc9c6507b3ef9", + "dist/2023-08-22/rust-std-beta-i586-pc-windows-msvc.tar.gz": "971a6f1507ac8e47a9e2435f9f0fc5a24f77393c6ae189057bae8cd1ac35d5da", + "dist/2023-08-22/rust-std-beta-i586-pc-windows-msvc.tar.xz": "4af5f8c029f2486073ac4b71725526cc1ef4f3861ba652190cb940273fb2ebbf", + "dist/2023-08-22/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "4676906af1dca83ae3dba5972444ca2b15a755223ae999ec9eb66072125b9d60", + "dist/2023-08-22/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "a2b556a5afe3c69e91eed6d7c6ff31971598eeb35c227b7aca46548b80eff7fa", + "dist/2023-08-22/rust-std-beta-i586-unknown-linux-musl.tar.gz": "e8501702dca37516dd8b567c277b74d19a2e1142ca4c97b881b3428aa3a0bdfd", + "dist/2023-08-22/rust-std-beta-i586-unknown-linux-musl.tar.xz": "a0fd2fcd9a0844fd4063b80189a342d77e6d0c087fb240e28ffbd1b98813ec13", + "dist/2023-08-22/rust-std-beta-i686-linux-android.tar.gz": "ed1445ae201aa69997b850037b98beff658e92a25e860ab525617836de366d72", + "dist/2023-08-22/rust-std-beta-i686-linux-android.tar.xz": "e9be5e895d4e61d3130a502ae3aae8b796028fe8334f161659e90c8feb38d8d0", + "dist/2023-08-22/rust-std-beta-i686-pc-windows-gnu.tar.gz": "41666fb8c03e1403f67f6fb595b1c21c522faac78ed8a9664d476f69825d15ed", + "dist/2023-08-22/rust-std-beta-i686-pc-windows-gnu.tar.xz": "64db89392d6aabdaf39d810f3aa8692a50ad68214db5ae08565462e8ebb1ddde", + "dist/2023-08-22/rust-std-beta-i686-pc-windows-msvc.tar.gz": "cf1e94aa60bd9c273216df658b9cc7c947b3f8b47f1eb4f7df63c07a328ec0a9", + "dist/2023-08-22/rust-std-beta-i686-pc-windows-msvc.tar.xz": "e69ca7df48d927d6fdd40b4de3e5c8d402aac9aa29e7f3cbbd45d3227a4a438d", + "dist/2023-08-22/rust-std-beta-i686-unknown-freebsd.tar.gz": "ec23333c6c7af11adcd8a01c6f722a6103c92a925c197a1f2797780ae1b84c42", + "dist/2023-08-22/rust-std-beta-i686-unknown-freebsd.tar.xz": "301c39d275e3b1d32076364c627cb4953ed200dcf092d4a7925ac662a165ca48", + "dist/2023-08-22/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "722ffca25c78d9a83632773ab0bc36e0b999cea66f767dfd2e15171790c14cc9", + "dist/2023-08-22/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "384ab84d4a8d6fa5429cd5e13a72591a50041e84e846f12105001c1defea08f8", + "dist/2023-08-22/rust-std-beta-i686-unknown-linux-musl.tar.gz": "913a316a08a15b123f6b136335886a4886de0d0cb06f02b14f82b436e34c83f8", + "dist/2023-08-22/rust-std-beta-i686-unknown-linux-musl.tar.xz": "6b440b91f3ba0319d39e73181b173d630098eec1ca76298a13afc69afd156c58", + "dist/2023-08-22/rust-std-beta-i686-unknown-uefi.tar.gz": "a32f3b2e6951316af9c557bc128b95b797586881cefa0f311e6e44779d4c6bd3", + "dist/2023-08-22/rust-std-beta-i686-unknown-uefi.tar.xz": "7deb5fff47eb1ba074f1835f9db54afbc892fce287c0ca2a2590e8bbd6d2168d", + "dist/2023-08-22/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz": "1f825781e403bbfef798a8038c3c4f800b838923b306866b21314902db06701c", + "dist/2023-08-22/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz": "a0b341d9464a8a68c7c395ff051ae384066ce0f97e0a3c50b8adf6ef253ef6d8", + "dist/2023-08-22/rust-std-beta-mips-unknown-linux-musl.tar.gz": "526041c26f3854c25b60969bf45e52d5f3d9e1548f9ea06942c0673434b115bb", + "dist/2023-08-22/rust-std-beta-mips-unknown-linux-musl.tar.xz": "c01d689e540777f8120775d05f93631e31ffcb05bdafcea2d3f1eda8af915f9e", + "dist/2023-08-22/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "f03f3b2767b2775e8f74d190ac1614307f2576c8966eedf710663bf39cf99027", + "dist/2023-08-22/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "9df204a1c45770e72c49e334ccdc47779825b1c0ae979576f40393a6ef05de2a", + "dist/2023-08-22/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "4892c903b692ea7fbd59d9dacf3ddc886fc0eb771d817c3dc906a875238d1f91", + "dist/2023-08-22/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "47cb42fd72f3dc488d30a959447698932fcc9499f50fb78e585fd208465c64c4", + "dist/2023-08-22/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "9d2b04e6ca70c95f157f9e273776bf10979090871307f67b4aed4f8532dd9905", + "dist/2023-08-22/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "70b260a23b6dc2c43041e15167de8a8589d2e33a65feada35a1ea9c3912db93e", + "dist/2023-08-22/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "a5af9e233e3fd518a2976dc75e5e79555fb9722c9b532f6d6a16c2944968f660", + "dist/2023-08-22/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "5d83a2ae7ebe2242f6370febe19fbf606d0282d57ba2dcb08b483c4cf0fb084d", + "dist/2023-08-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "9160571a2ec98b1fc91a10134c842c34c8370ac9990adfcf6368e90a259a4b89", + "dist/2023-08-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "be22e907234b415684e90af6c0a3a5ebec114511235f223de0ff2393a929cfe8", + "dist/2023-08-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "c73d1e7282d6f85097f13931a7ff5b66bfc807605284b35cacf2a94f9fb4ba0a", + "dist/2023-08-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "75e7578497fefdf7aae1b1d0a4e20855cfb06ed2f58bcea5cfdb8e71ba224c35", + "dist/2023-08-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "b692e3bc1199f3a7687fd8e5d6224696e56280ea989c402d88ef3da3fad2ee2a", + "dist/2023-08-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "61e86b7e3a9f8004bfa1a72cef3bd62eee1ee67964c747d6387d62ab8680f237", + "dist/2023-08-22/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "4d5c1935405d66a7e1a7532b165ffcddd4501fab25f346a0c57d06d7d480f370", + "dist/2023-08-22/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "a581a2224049bbeefdf81ed556960fbabe3d762abbd9ea7765425b2d9d0403cc", + "dist/2023-08-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "64d1a7bdd061ac16c585ae035e7b1d2f7b4ee4c2a71f491cf4ec39d3a9cf4904", + "dist/2023-08-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "528bd7a62c69a53c3aab2488be12de23199fb0a3aa4b117e1b906af7b06233a9", + "dist/2023-08-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "6808261b20282eedf3ae11e6300379ff1dafcb4fc22c0fd7eba5fb8e31fe4a97", + "dist/2023-08-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "2782284032eda7797d725e8986bcc5104a28f46e13c9774d8c1b115a3e192cb8", + "dist/2023-08-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "2e77b3d53304eae6cc8111d627f8114e4e0b759a66a696937632a95cb213302d", + "dist/2023-08-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "a8592a9d233085e65f87f7d5c290fb3bd3a88f9fe3492a5bad4afd5f64def27c", + "dist/2023-08-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "8d753ca5922d7fe6782a8dcc366447fd0062784a21f90b210c3946e6eeeb0a0e", + "dist/2023-08-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "29fc30370d9b08aaf9b5b36a23c463a494f673a3cc9207dd600dce9498b0c6f5", + "dist/2023-08-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "587e51be642bd19528ac7942b2026be31086d12dc81dc8a324ff662328b2fb1b", + "dist/2023-08-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "38759bbd4ad799e02c9a3c5947ca5637a2b7b716fe51e986788ea424d3dc0310", + "dist/2023-08-22/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "bf702a5aaed572fc753d27d786ccc9f83664d6b66812d9a9e8b3ba63397857de", + "dist/2023-08-22/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "187906dad30dd2da2f608e3713b6cb2ffaaf491c8109f4d381d4ba9b92e5c82d", + "dist/2023-08-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "368835053411c9a9ea8a96813f12724989aa6e00b160f7e75628155b038e06a5", + "dist/2023-08-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "f85bf85725ab2ba21e83f5d024cc1c9bccb5fe4b90760f0d34383a0cfca000cc", + "dist/2023-08-22/rust-std-beta-sparcv9-sun-solaris.tar.gz": "1f5632a33b2a94354e062821b5ed5a99810ed0d88c8e8370349c08f4541095f3", + "dist/2023-08-22/rust-std-beta-sparcv9-sun-solaris.tar.xz": "dba0efff671c805c9fa1893bc41a9076436bff1a10f8a5bfa59f5cf01e22cfe6", + "dist/2023-08-22/rust-std-beta-thumbv6m-none-eabi.tar.gz": "3d88eb30d86fe6f486f45bd36d53667f1f886636235f16ac197eb1b6287d228b", + "dist/2023-08-22/rust-std-beta-thumbv6m-none-eabi.tar.xz": "69907d0d70f4a70ca5d28cb9ce19824c6cccc85db206b6b993516980dd469a51", + "dist/2023-08-22/rust-std-beta-thumbv7em-none-eabi.tar.gz": "7bedf1b999e78505f61b409dad228877c92def1df273d58347f8379e8496c0f1", + "dist/2023-08-22/rust-std-beta-thumbv7em-none-eabi.tar.xz": "125b71e59a23077ab7b5e618a48022c467d5e9c4d8e069ed101f9d9634a9e2cf", + "dist/2023-08-22/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "6e396659da4b82f5d66168569f9f8d7283b506d56423916a6e506f489557e07a", + "dist/2023-08-22/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "830981defa1a25be5fb9e7367126802a4f3c50f251bc5b77c80693189a02fe2c", + "dist/2023-08-22/rust-std-beta-thumbv7m-none-eabi.tar.gz": "7d457a6697ea4f0786036791b0769fc581ef44c748ce76717e84f93776af4de5", + "dist/2023-08-22/rust-std-beta-thumbv7m-none-eabi.tar.xz": "03551f2cc2ed4337db19c0b6dd9d7e155988dc7a9d8ed0914ee2fdb4a0e83f9b", + "dist/2023-08-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "b209802836c48d3ba7b61b31b1192e2b0eaf38333c307541004c4ff2bbc83453", + "dist/2023-08-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "6ec3cbe221f47c412b6f45bb8a3ceb039078462be5a64c3f226595c276aa40c1", + "dist/2023-08-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "ef40a875465653f636270fd610def70c2b6d1fd0f3cc5622736ea3d9fccfeb1c", + "dist/2023-08-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "79060f7930e9e6ffa1aedfb1f5926b96541fccd4b6e861fc2b9452ef5eca77a2", + "dist/2023-08-22/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "2f33509dc88e1033cbb8b3478b1f7c27065eccb12d54b65a4cdbf331be111636", + "dist/2023-08-22/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "2b92276477d70ea1f02befe72d7a18dc65a1c727dcc5e6ca6e13b0e6d6395648", + "dist/2023-08-22/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "d4e70b2edcbbd81bd68635b067f413de2c4fae69227f70cb78d9a3a90c0cae7d", + "dist/2023-08-22/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "c01c168943c37de7b5c76a49ae329327c45e7eedd65419f47523b26a1ab7aae6", + "dist/2023-08-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "7cf03fca058895f05cb583248fd25526f8d54d2607cc484aac63581312162ea0", + "dist/2023-08-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "18c8bcd69494f91938e51b8b9cc0dac01533be3b380e5c939096eb35ba7cbe34", + "dist/2023-08-22/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "550440258ce3b993180c285ce9ad363a0e604704d92f924018bff5be68a94944", + "dist/2023-08-22/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "0622611a929a752ecf2c15e6590b6a50ec3fdfa0c7b0fc9f927be3a641ef6fee", + "dist/2023-08-22/rust-std-beta-wasm32-unknown-unknown.tar.gz": "338f5bc7db5648b9b578889bf197fdb120c7c1b6be6a6c41b1e1efab2b19d87a", + "dist/2023-08-22/rust-std-beta-wasm32-unknown-unknown.tar.xz": "6fe28fa351a51f48051010aab7399d9a9bc43b7c60fb9ec5dc8a0323f6ebfcea", + "dist/2023-08-22/rust-std-beta-wasm32-wasi-preview1-threads.tar.gz": "b2d3aeba309f689f20902e41058c400f79f28c9fd8b9b03e4bb0562d1ed9e087", + "dist/2023-08-22/rust-std-beta-wasm32-wasi-preview1-threads.tar.xz": "1d1de7bec3f1744082e0805601a6058ecc39d14064456d9910640a4f1f84604a", + "dist/2023-08-22/rust-std-beta-wasm32-wasi.tar.gz": "45ec2a9e021e7d7b521349a69f85efbac748f8b4abda6212bb0c7273f8053d0e", + "dist/2023-08-22/rust-std-beta-wasm32-wasi.tar.xz": "53bb87e58a84e5afa029d66e5dfe85a6e9ca8b5987c5543af6eb039f052b428c", + "dist/2023-08-22/rust-std-beta-x86_64-apple-darwin.tar.gz": "7acc137790fa64ebe1ff5152abd86f42c643ad6d858f130d1b210d80e98893b5", + "dist/2023-08-22/rust-std-beta-x86_64-apple-darwin.tar.xz": "b9da0c71bbe58c152f39a3f3f79308a49fcbc41944211024c097c156e124a56c", + "dist/2023-08-22/rust-std-beta-x86_64-apple-ios.tar.gz": "915831f0eb14aac95e1416fadaff2b6e0ede3f6968fb5b941986004eb389b887", + "dist/2023-08-22/rust-std-beta-x86_64-apple-ios.tar.xz": "2f7df0e1c43eb73232db1f888d42a639deb4d69e6cb09d11581b23687131f6d0", + "dist/2023-08-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "89203b4d908fde29b0fe45d0e1665cbcee7c34d40bdfbce6d97e31b7d608136a", + "dist/2023-08-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "9d006df537590eb7d1ec8014348103d3a1d91bd2e627ebcc4f179e83737b4915", + "dist/2023-08-22/rust-std-beta-x86_64-linux-android.tar.gz": "0569509106e866b3a06cc814f928481f0a06859d498440196d5994f23591b5cb", + "dist/2023-08-22/rust-std-beta-x86_64-linux-android.tar.xz": "dac7a334e980f4525b126d33e9609edcc3aad12c3fb011d715a0722d68722dd1", + "dist/2023-08-22/rust-std-beta-x86_64-pc-solaris.tar.gz": "1a34ab28dda35646171ef49f0a7274943bdaa8bc73a15261d16decec2ecb64c9", + "dist/2023-08-22/rust-std-beta-x86_64-pc-solaris.tar.xz": "55a1c71616a85144950cfd92fa7f64471396d5e2c8744bc936c3fcc209bead1b", + "dist/2023-08-22/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "d60cfada9d49c518d90dc0b4040bef383f857a15c6dd9e9983b8fdbfe8b24ea6", + "dist/2023-08-22/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "1102177596d61d23b5f9c9a93ec31fe5d9e0f271d7b49edbd47bcd59f4309ed2", + "dist/2023-08-22/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "0383b7094b6c02266c144223c868ead1edaf55517bdab7e94953f8282bc4420e", + "dist/2023-08-22/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "b2933c0d4600cdbcafd22196b70158721c0a16e864ff292fd6b919fad05355d2", + "dist/2023-08-22/rust-std-beta-x86_64-sun-solaris.tar.gz": "a5b0092f5a045601bed31bdb83dd7f15a332f7579a624f073103c67e7a57af7a", + "dist/2023-08-22/rust-std-beta-x86_64-sun-solaris.tar.xz": "1b0111216a66e7d7ae9b7b996567e932dcf7b50e202bba9281d1dfd704e26e3e", + "dist/2023-08-22/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "cc5e94874385ae0ec2a9a8dbb3efafdb88fc5134cb2be4f378298c9e413e18b4", + "dist/2023-08-22/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "9653bf3ea33bf9502eb90b72c0696af0cc90dea54e9d6e5be97783db3e8286bc", + "dist/2023-08-22/rust-std-beta-x86_64-unknown-fuchsia.tar.gz": "6193c991d35a6fc0386b42ff1944f473ffa95012ca2fb43008200d6e5cb78d78", + "dist/2023-08-22/rust-std-beta-x86_64-unknown-fuchsia.tar.xz": "3a6c169f6f09d7bda84aaffa348a1b379cfe221b567b67ad35391b9e5e3e34ca", + "dist/2023-08-22/rust-std-beta-x86_64-unknown-illumos.tar.gz": "6299ee2cf0aaa5da48aab83230f55effeebf47a72ccd7dd27b4649629d5f3b6b", + "dist/2023-08-22/rust-std-beta-x86_64-unknown-illumos.tar.xz": "7fc1c33439be25983b4a02c8fa4b783e3187f94f6109e4f4deaf64cb83e124b5", + "dist/2023-08-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "76b1bda97f8c56213d4cc39e8d8cde59f0e6a50e9ac209b70b163dc58e346f52", + "dist/2023-08-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "14ef16f6c0e545badc8b49b16a9ead85cb4cc2c5e6f74105fea039866eddf111", + "dist/2023-08-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "df96bcc3a4f3c6c028fb7252057bbf8367b73061d6cdeb50c4e28211f96d46b0", + "dist/2023-08-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "2fa0fae38e0b8633065313fda983503a74c436798bf7f76e1c58ca76e8767491", + "dist/2023-08-22/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "f3ec6da0eded1e8b042e1d4d8de9161e0e1af7998618315aff462892573302a1", + "dist/2023-08-22/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "34ad894da8a3e315832adf6ae7ea7bef486219bd2c1011f849a47092cde958b4", + "dist/2023-08-22/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "3ec57e0485fa7e30ef93939fecf945a24fd47bef044eb0a91652ce6d8c8e5e50", + "dist/2023-08-22/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "02fb83bd1e43d10fc6afd3113c29fdb917e87bff0f039421ce297eff91351bde", + "dist/2023-08-22/rust-std-beta-x86_64-unknown-none.tar.gz": "97f65c1033980d6746d894d9cdef3793029d80e4820295b9a3128df497acb4ae", + "dist/2023-08-22/rust-std-beta-x86_64-unknown-none.tar.xz": "add0537d2ae67b696896368b7aa94f7357b0b6c313097f9eec00bd8f00395a7d", + "dist/2023-08-22/rust-std-beta-x86_64-unknown-redox.tar.gz": "7149623b9e584e41f0f6233aeb05a5aaff57a118cf13c41306e18eaf23de5929", + "dist/2023-08-22/rust-std-beta-x86_64-unknown-redox.tar.xz": "48be526da0d8a8dadeb4e7418a49a07396e132001034282515b859eba7c64d14", + "dist/2023-08-22/rust-std-beta-x86_64-unknown-uefi.tar.gz": "dc14c0faec4cbfa1572102aa5cb2148a58a9c120b40fcd3f092a839f58007dfc", + "dist/2023-08-22/rust-std-beta-x86_64-unknown-uefi.tar.xz": "ac0f60f26c61dcc659aa061be217d161099f404d38dd158f5a6f214143c308df", + "dist/2023-08-22/rustc-beta-aarch64-apple-darwin.tar.gz": "15b0448e87b74a06cc5f21431beb452884b836fb12ea8ccbbaaaa571bbbcd2d1", + "dist/2023-08-22/rustc-beta-aarch64-apple-darwin.tar.xz": "81044b7c60f619f58e5e21da1ccab36c2ce6da364aced4d7df403718f81f4ed2", + "dist/2023-08-22/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "c9f89bdf460cdfd50d11817aa2096de7a25d23be63f8e2e45de460bc7a221722", + "dist/2023-08-22/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "a484613c8b31462985ec6db77343298111e23b9034143fa528ebeccf00bedef5", + "dist/2023-08-22/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "1de5c389e1b60a8b585d35f44228466e1a6977b34c37067f11649aa7e703e1e4", + "dist/2023-08-22/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "424d6192234aa52a21acf10ee4339a9af293bb07e94c9cede67b4f82e421374d", + "dist/2023-08-22/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "bb7ac313a0d2c02eb59061a2d17672f0a73486cb6045e3ab43fef610fe32eacb", + "dist/2023-08-22/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "246e61b5674c3fdd2a11d033a987ead6dcc02b20301db791cfb1f31fe2bccc67", + "dist/2023-08-22/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "5380406b9921dc72ab29afcda33bb3d7dfab593c54ae3d5b3054d7a4f526befc", + "dist/2023-08-22/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "5834f4ab2100b21dd4c1313d2a58bed761543d60a0df5cc9e9d8ce1d086638f2", + "dist/2023-08-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "8a9aa58e47d9463aa71952c4c8e214f230c23f7c5a8c55706da02a84e31120aa", + "dist/2023-08-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "f832bd965354c1f6a8b982693ce66037a0a4b5eb242a915ab84a1545e90be598", + "dist/2023-08-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "da4fca6be3d3df88383cbd5f10556789e5f3bd16e05b4c09543edb14dcc8ce8b", + "dist/2023-08-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "d499d8b50ebc3af595872b359e40a41689adfe2a9ea7c7149cf556956370a5ab", + "dist/2023-08-22/rustc-beta-i686-pc-windows-gnu.tar.gz": "6e841881e0393b438e33f3c16f1d24a7036781844ac4eebf79042a33499f0f3d", + "dist/2023-08-22/rustc-beta-i686-pc-windows-gnu.tar.xz": "fe096f5ed90a3a2cf1d5da74c6b8e081b36dd868c4a1b6ea51e4a2e13cee2794", + "dist/2023-08-22/rustc-beta-i686-pc-windows-msvc.tar.gz": "b2b9485f44a0e25aaa56b3d1f82f1f6f224683800688ee4482d1c4025c337d03", + "dist/2023-08-22/rustc-beta-i686-pc-windows-msvc.tar.xz": "2c0e8c9ed8cae5e37ef60f1c5fc55f4370a260bad70cd675fa79d78737f9ca1f", + "dist/2023-08-22/rustc-beta-i686-unknown-linux-gnu.tar.gz": "27ba8f3457389683db058dbbee48b6844b9be5c0fc23711c00300b28a8b4f17b", + "dist/2023-08-22/rustc-beta-i686-unknown-linux-gnu.tar.xz": "2b45ee2cd1cb093bda5154280d0c81573fcdf512841ac5fbc1d1edb460da7c58", + "dist/2023-08-22/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz": "af5f367d0b97719ef4d3606276881015f069338d002ae3af8ad5be58f0778c2c", + "dist/2023-08-22/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz": "a37e870c5e25e9b4c3de30922461f756306424a7f85ab22da84c88b647c56100", + "dist/2023-08-22/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "7df41c44859a38a2652dd3a23524e75157283b276cb621e2c4dd04185841bd61", + "dist/2023-08-22/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "60ece70118660eff11744f6fde293b2dc27bd18a0b7d0cfd81e22c195a13a828", + "dist/2023-08-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "50bb7eec6172dde937dc8f9b3d6d3fcced7f896a19eb7fc82f83685a9745e293", + "dist/2023-08-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "23eec58bee6d42200d88b16ff0fa3977ab0223578369fc6a69787b5a52c44c62", + "dist/2023-08-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "051b46807d53e72a61ee38c28466620b2a03f9b5ebadde3c1c8b6dcbb35b6b7a", + "dist/2023-08-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "60382fa331885257998ea7fa93e55e47dddedaab04e962b21330c90ab61f4714", + "dist/2023-08-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "24e89e00a5e10256f41dba5f07009c2b2ea82ffdf54b6a9c3fea6b13daa2891b", + "dist/2023-08-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "5468061289f37b2014fcc52699ab8979a33ebeffb1c45e23a78607ec7589b3a2", + "dist/2023-08-22/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "34e892a6f59b53b2c7252045de9eabe437ff9d01accb051c74ce7912ab2fddc3", + "dist/2023-08-22/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "9fce7533f11da73efc00b31f5728ca1201c29915673b966840b2e0228f93aa74", + "dist/2023-08-22/rustc-beta-x86_64-apple-darwin.tar.gz": "41602031cb330fe01bd40e17ebf19a3925875f217604bde070e4c8536e971176", + "dist/2023-08-22/rustc-beta-x86_64-apple-darwin.tar.xz": "f19b3fa42e68810fd70a294206fdd8387dc9364fb5cde34cf87ef1ccd6aa6234", + "dist/2023-08-22/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "bbe52f430c7e9fd369341bc3c2931b79d79ee02c68d6a1a91919f5c09fff4e03", + "dist/2023-08-22/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "3f96c6b646bafb6104ce64eab83fd9c75734bd7e8b53b0b6db143b5a44fc1cb8", + "dist/2023-08-22/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "0a70402149eb92027265d5ea27c08fd14b0837a488c210f8ca7386981eea8f54", + "dist/2023-08-22/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "614228860c1f94fce353d279ee8dcb9ad3a7daa7233341c8c8e51035d6dcaefe", + "dist/2023-08-22/rustc-beta-x86_64-unknown-freebsd.tar.gz": "8a28760c696bda3e79306fc68c3c9a7b05b2a8ddc5008876f27029fdcbbc91dc", + "dist/2023-08-22/rustc-beta-x86_64-unknown-freebsd.tar.xz": "b21b5e26ccb28c2bf8a089a6f62abc4d10d6a4aabadf694aff8273150e6e7673", + "dist/2023-08-22/rustc-beta-x86_64-unknown-illumos.tar.gz": "d46020acb9676fc928c50d1042c2db820f27708e8dd7d708cbbe1056f787583a", + "dist/2023-08-22/rustc-beta-x86_64-unknown-illumos.tar.xz": "e92ded96d7663211d513c5dbefa2367d3c2e7ec3d37ff435884c25a2dc8761b4", + "dist/2023-08-22/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "65e7494ba34014b63d43e95662440b4d70c8ba2f43e6a22ada051f31a83c3620", + "dist/2023-08-22/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "960aef4123b24c63427c6d1bd92dda8417126c589def5213d972057d011caae6", + "dist/2023-08-22/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "4cd355a18503b2a3d081f77d9ac07e6cbc4d273b6cdabf4f9f05aef398cc39d6", + "dist/2023-08-22/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "97b5013d624a203c5906f5eaa82c3a47716e1612534698270082e47a06cc13d5", + "dist/2023-08-22/rustc-beta-x86_64-unknown-netbsd.tar.gz": "59da6428300c6b406da96142ada02d0fa9b3f1b5938c457ded9afc8d52c73046", + "dist/2023-08-22/rustc-beta-x86_64-unknown-netbsd.tar.xz": "c549da0eed22ec875603d42152134780f34acc40e4ba9ddd36f4f31e78a17dfb", + "dist/2023-08-22/rustc-nightly-aarch64-apple-darwin.tar.gz": "e80a43c2bbadff8b7976673d94228d7326a6e871cdf12d802f663b2773c6f187", + "dist/2023-08-22/rustc-nightly-aarch64-apple-darwin.tar.xz": "e90eb430d5485ea4f431952a68e6ceb9de8f6b92ccb64675059970b512ba539f", + "dist/2023-08-22/rustc-nightly-aarch64-pc-windows-msvc.tar.gz": "b21f280c54b5b0820f48767df4c611b7554c3bc5427194a1fe7e632cab7827ac", + "dist/2023-08-22/rustc-nightly-aarch64-pc-windows-msvc.tar.xz": "f2812b599f99858485d91b349a570bacab343db4bc622d8134a9993ce0da7471", + "dist/2023-08-22/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz": "059d6f34def7e471b9970713bdedf4ed3f83fc3d9b6a6f28e510b5e28d3a9413", + "dist/2023-08-22/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz": "95b36f95b1e697922b6dceeaceb74da030d436340cb4ba764101c218c3bcb786", + "dist/2023-08-22/rustc-nightly-aarch64-unknown-linux-musl.tar.gz": "ffdd8605187f7f6696586b7c7ab38300bb3d119e23726205d7f8a0a0bd102e90", + "dist/2023-08-22/rustc-nightly-aarch64-unknown-linux-musl.tar.xz": "7e1df24c13f88a49eae939930a8dceaa6dd6a23c1dbec16e3fa4f18c4bcced15", + "dist/2023-08-22/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz": "1a36c109a723388c322afa3fb7b7f64c9f38423a3894b8ebcd9aced032ba1bdb", + "dist/2023-08-22/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz": "f689a7d295e13a14e379efdf0c9a59f6ee5b8d4ee45e21ff68c684575c26e866", + "dist/2023-08-22/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz": "a60de4bbe5cb6ebb6081ba19d86f586661666cc40c74102a13b54f175930e561", + "dist/2023-08-22/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz": "b57f05ddd91bce96f61b24a93cbf9ce61bdf82d15976c44427797a0692388cc1", + "dist/2023-08-22/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "ce3ea06a26eb6345c98b7bad9943ce70e67e145ae5dc082e4bfde2c897c1aea0", + "dist/2023-08-22/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "5021ab61e2988e3f2f3a1531609621db7a2e1fc72eeae4338e3d16b40043d769", + "dist/2023-08-22/rustc-nightly-i686-pc-windows-gnu.tar.gz": "3bbf47ed743a313ea3d2def98173d323a13959e1bcfc8cd2f07a86997a0c2f51", + "dist/2023-08-22/rustc-nightly-i686-pc-windows-gnu.tar.xz": "578b6d37a9caca822102b3d484fb6bc32338d9ac72c423f4c1479835db446ae9", + "dist/2023-08-22/rustc-nightly-i686-pc-windows-msvc.tar.gz": "22798dc3d624f06a14908cf18658246045fd321566f786e6f75ce7a0d762a4c1", + "dist/2023-08-22/rustc-nightly-i686-pc-windows-msvc.tar.xz": "0c8d2fa9cb8a5cfab2c51792644c8ca436aef7bfc9d0c1950f9976fc4480f402", + "dist/2023-08-22/rustc-nightly-i686-unknown-linux-gnu.tar.gz": "52a7969782803b0f15debd0df1876e033b05e93506e1d9662a98c0aa175c043b", + "dist/2023-08-22/rustc-nightly-i686-unknown-linux-gnu.tar.xz": "69a79df0344f0279848bdbea5e8158d7a45f6d8c8966ecb5a055be064750d5a3", + "dist/2023-08-22/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz": "2fbd751601bd1cb94f064f4ff00ea1c909db059661524aa49b9e56f5ede07a52", + "dist/2023-08-22/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz": "5d51a4ac70e5b34304cd8dd05333d2d5933977e03e386bbe10cf8e43eec2e5c6", + "dist/2023-08-22/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz": "73f57e1a2d6056ae14ce6ab5ec7068241acfe59882bc2521de60d11d2dac3ee7", + "dist/2023-08-22/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz": "82faa86f7d1be9f184eec46a7c135787c37c750bb667f05bd3b872f55fbe2935", + "dist/2023-08-22/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz": "3f5e3ea359e2f7377b1d44d3cfb8516e23725e919deb5ebb32f96e8612ab2e6c", + "dist/2023-08-22/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz": "e156e85b6070a5155331eabb3c3de91279a56628b892a313561ed866b9667c93", + "dist/2023-08-22/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "83a9082d158c1093a98c75fdde9f65c729b245cf40cc06d88731e473a9ec0cba", + "dist/2023-08-22/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "61bbaf76b250a6e292d99a65a95127daa6cf0075cbdedf68033cfccd221bf8bd", + "dist/2023-08-22/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "6574e5cfac1a56cc3ec20352eebe6c6bb0825a1060df48893866909fb7005321", + "dist/2023-08-22/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "ad2240a704fca3320dccaa2bbbbe52a5b2df2556967cae4efa40334c36f66a59", + "dist/2023-08-22/rustc-nightly-s390x-unknown-linux-gnu.tar.gz": "c319fe1d20e9520b1d6c033cfd04f91286d68637caea7d2e43e335f9d9397527", + "dist/2023-08-22/rustc-nightly-s390x-unknown-linux-gnu.tar.xz": "1c52cb26303f89969190c06580206d1f5d511c91c63fccde78e515930f9da4dc", + "dist/2023-08-22/rustc-nightly-x86_64-apple-darwin.tar.gz": "db6e355efddd7aa18f3fec72d87df4b91794c8b8c07236d6d9454d5912c9994b", + "dist/2023-08-22/rustc-nightly-x86_64-apple-darwin.tar.xz": "afbfca7d7c7f8a94575269098f6166729bfb441b657ea77f7de6621e0a9a3f87", + "dist/2023-08-22/rustc-nightly-x86_64-pc-windows-gnu.tar.gz": "7bfcbbbfe4adab954e9c70b8ea6bfb9d52116782dcdeb9b5be147430c4f242e0", + "dist/2023-08-22/rustc-nightly-x86_64-pc-windows-gnu.tar.xz": "05e7e901fa944075ea20d65d81f80986c51699c2ac5c5a2cfa2e5a07c16f4b0d", + "dist/2023-08-22/rustc-nightly-x86_64-pc-windows-msvc.tar.gz": "74d07b4289dd2f382c7ef5881ed24a1f99c44b9805857d15a8d45d0c7fea623e", + "dist/2023-08-22/rustc-nightly-x86_64-pc-windows-msvc.tar.xz": "25bb5590a8107f6525c4987291f8f46360ffdf67dd47f7087a2c9e441e20296f", + "dist/2023-08-22/rustc-nightly-x86_64-unknown-freebsd.tar.gz": "727fcc6ee093e8b105560b6f9644451aa5fb5f88e12e883a270a094ee47aa3bf", + "dist/2023-08-22/rustc-nightly-x86_64-unknown-freebsd.tar.xz": "c33d57fc3783bead4c54352ccfa4b4f129e34e16970efdd872b562fe99e1652d", + "dist/2023-08-22/rustc-nightly-x86_64-unknown-illumos.tar.gz": "c1f4fd00eea1e5fcd64e0eecbf7daec3a39d72822b4792c12c3885bb7d34048d", + "dist/2023-08-22/rustc-nightly-x86_64-unknown-illumos.tar.xz": "ba3783813d65a4be685c3720c865365f03b9124938e02be790c438d212fa1bb1", + "dist/2023-08-22/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz": "7a0365317617af7b18f535f39e2a8da23cd8f1b7ff95be9af1de9b6d4ae461de", + "dist/2023-08-22/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "bdd970bee618fc6299249ec162ab7e38efdf52c77cd431ad9268f327a6f0905d", + "dist/2023-08-22/rustc-nightly-x86_64-unknown-linux-musl.tar.gz": "43f5736c02efbc0170d23124976546b3fc03b2a30582c3685cb53f7417359692", + "dist/2023-08-22/rustc-nightly-x86_64-unknown-linux-musl.tar.xz": "3abf2518323294fcc0decc9e3f01bf610116b8f42b07fa9d34769bd438ae17f9", + "dist/2023-08-22/rustc-nightly-x86_64-unknown-netbsd.tar.gz": "1dc5af741b22db8bf16ef7eb05821ef0d5b3e518244867a2bba484a773a03b9e", + "dist/2023-08-22/rustc-nightly-x86_64-unknown-netbsd.tar.xz": "4c2e5268a6a4537c67795c89c45a414e9b001068017aff0b6ea73c1b2e9d95c2", + "dist/2023-08-22/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "606431eea9341f6ee2079ef919d34e583678f8f1e0bcd66fa73eea9175996a77", + "dist/2023-08-22/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "b122cc0367be4b5433eba7e1b2ca919ec265cd31c5b1766e4853b947d16268b5", + "dist/2023-08-22/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "094456d974c3bff34b4ea47f159a2e12dc41c0c88ab710debfb63ecba102b6f1", + "dist/2023-08-22/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "e777f86c75261bfcc3dcb2c7e91ad4052a7e6263b59dd78d6e5a50a43cb9de1b", + "dist/2023-08-22/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "82b9bd94ef7065587471716fd7848bdfbe0d0938df7832b035d78274e51598fc", + "dist/2023-08-22/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "d8453e40ca7819830e9ef8bb3c3086a4708479cd01aa3434fa878bbdb0e21cc2", + "dist/2023-08-22/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "17e913c782aef22a021c75c204f04d290f6abfc76ac3c2fc899bf3ba2b96e8e5", + "dist/2023-08-22/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "97b145924a76dc1f0e6d2c18c65725d0bd92308ee21d779ff1d1c3a857221ad6", + "dist/2023-08-22/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "aa36dea771d819ba1f4f2997fb8e38fc02d57da7417bba9354e499c15ab56c6b", + "dist/2023-08-22/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "c5b3ab26ec79e479de1bc93ab60e48c95e6a24931bdaf8c2e9a6508fb8d8253f", + "dist/2023-08-22/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "2639378c9e51ec50ddb739bc18d12ed43e98a5dff1a1e5cfd154c0b91f233000", + "dist/2023-08-22/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "c189e78bae3474c17f693401c9f7e13f064370ecf709e69b62a140e94c772e82", + "dist/2023-08-22/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "b7e175569f174d7422756bc3c312a1dcde78b8563cc96330772b2b7ca6458685", + "dist/2023-08-22/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "0fad29a56dea92b2083d46e9a93d186f32d162461da897e2aca1b94cf8ad259a", + "dist/2023-08-22/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "35ba679d27b08bdbb381a7517b189743e1aaaccc0f0ad33fa6397d53005f1bd6", + "dist/2023-08-22/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "37cfd4697506172d2826b1a047cd1d78e24ad32e1334fd89602a6b2dd45fecc3", + "dist/2023-08-22/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "e6dbb37669c307e235b610aa292691e2f767bafc7c90dca5f9c3db70a782914f", + "dist/2023-08-22/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "1df368db6dcf9bc06ef68e5c56e1961f6fef57c07b2edbdb537c5eeccc315d5b", + "dist/2023-08-22/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "bd3694c1b40d86c5729bdafa5516a827da2d741a04a3f91f955f2d1165177324", + "dist/2023-08-22/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "0ffa91610757b4c8fce43cef6d76b0f47a442dea14dc893581134e8a0237b32b", + "dist/2023-08-22/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz": "92ec1025ed12fabd541530124b08498abf54ad14c22a11a6cd9be54fa330b0f7", + "dist/2023-08-22/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz": "850ab1756cf50b9e56dab7b2dbbbdd0dab9146fa792ce3bd59af0ec5a0c1a4fd", + "dist/2023-08-22/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "02cd3b78627002f26007ece8e64808a58c80bd4362333c1150b4901c73ae6b8c", + "dist/2023-08-22/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "f453e12fad664f6a3c76de94e34ecd4a668cc26bdec982079dc8c57c9fa85c7f", + "dist/2023-08-22/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "92d7336a7e4a6a9e06f72e72b8402af0fe60bc6da7616bcee11e810a5217ec8a", + "dist/2023-08-22/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "08a96d8600357882f7b278c7e65c8be95ec153bd7059c14847b47abb4e27a28e", + "dist/2023-08-22/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "7d80dfaaa65c1237813ca8cc8c52a878d5e4dfb99b6e5051cd679bd31ce3a4ae", + "dist/2023-08-22/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "a76b23cbad7fd5838a6297b9234a5a09cf6adf0cb377910180d30caa6de2696e", + "dist/2023-08-22/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "4f74e990e6d6e2eb80c503794e55f80e554dd2b6bfecd902ccdd19841b8e83d4", + "dist/2023-08-22/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "7323dc37bb3a0ec5979e0e0818aef876010422a539971e7fbbbb39e66bbe5a70", + "dist/2023-08-22/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "cc369508a03517983bcab4f17e391d4074b002d9f3b5ec8729375b345df6cf86", + "dist/2023-08-22/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "465d88c1ca8c5e36a579d48334c60f5ce226eb4c5a851849fe76a7d8ad803154", + "dist/2023-08-22/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "d2cb215423c824355d7d450b8d555c3f7390b08911fbf5114474869d9d8d2fb8", + "dist/2023-08-22/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "d5a4e117f8d3f1a7a88dbd1e1e71fe352fafce10770d6dc1f2644eef591bfad5", + "dist/2023-08-22/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "6601080db240890b1a9b7a2af54c576b2ab112b15b504a3475fa77b0b214b309", + "dist/2023-08-22/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "a40ed6b0fcb5bc909dcbdc93b65024f155792df980a48757b71ae391dbb427cc", + "dist/2023-08-22/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "64c4a913fd398fb49823d7687932c9defc3e4d0312967a21c90e57b5a6e2ea66", + "dist/2023-08-22/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "75e814a65ccd1b3721ff6300b83aebfcd8f402f18e02df230586604cc56efb10", + "dist/2023-08-22/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "186928533dc8dc7874c56bb0ce95930d7cd76c9838a9203509c01c3f0d1e88d7", + "dist/2023-08-22/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "4bae607aa830e898d77e20397377cad51108843480a76f6d8f076bdc27a69d7e", + "dist/2023-08-22/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "1610cd254b57537c592f5d9c8d5522d03a25405db4862c18759001ced85169d6", + "dist/2023-08-22/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "2cd850cadef23f7061e88e3aed20cdbcd772badb11792f34110facb681c9846a", + "dist/2023-08-22/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "db5b9f91e2350d337c19c07c4f30419ef1a222cb7f9ad1f95c851ad2a78993fc", + "dist/2023-08-22/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "b7abfba5b3c7c5b33bd64e5caddab8a62fc7d1298e913323a3712a2af80b01da", + "dist/2023-08-22/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "bcaa9389f053f133c1bbf96a50035de0d2c1e4132a9f8deb5edf83da9da75616", + "dist/2023-08-22/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "1e2cec2188e9dcbcb23b81a9a0f22eb70143a207438853b702d5d2d90786a92a", + "dist/2023-08-22/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "afd7e619f99ebdc2095f3a0db4a55684e1919c2cf145ff3d1e18169e6e868742", + "dist/2023-08-22/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "ee05ae0326941d38704abeb44c868a326966f6dbbc3fcc79585a8ca1f84a4b21" } } From d2744175ac1620cc094fcb842c9c60c8889ea603 Mon Sep 17 00:00:00 2001 From: mojave2 <0109chenchen@gmail.com> Date: Fri, 18 Aug 2023 14:49:01 +0800 Subject: [PATCH 121/197] unknown unstable lint command line fix ##113702 fix #113702 unknown unstable lint command lint improve impelementation --- compiler/rustc_hir_analysis/src/check/mod.rs | 1 + compiler/rustc_lint/src/levels.rs | 28 ++++++++++++------- compiler/rustc_session/messages.ftl | 3 ++ compiler/rustc_session/src/errors.rs | 6 ++++ compiler/rustc_session/src/parse.rs | 17 +++++++---- .../deny-unstable-lint-command-line.stderr | 6 ++-- ...-unknown-unstable-lint-command-line.stderr | 6 ++-- 7 files changed, 46 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 4cf3587327d2..d83316613666 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -289,6 +289,7 @@ fn default_body_is_unstable( &tcx.sess.parse_sess, feature, rustc_feature::GateIssue::Library(issue), + false, ); err.emit(); diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 1f4e5fa4d3b3..0a40d17f98ed 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -12,7 +12,7 @@ use rustc_ast as ast; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{DecorateLint, DiagnosticBuilder, DiagnosticMessage, MultiSpan}; -use rustc_feature::Features; +use rustc_feature::{Features, GateIssue}; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::HirId; @@ -24,12 +24,14 @@ use rustc_middle::lint::{ }; use rustc_middle::query::Providers; use rustc_middle::ty::{RegisteredTools, TyCtxt}; -use rustc_session::lint::builtin::{RENAMED_AND_REMOVED_LINTS, UNKNOWN_LINTS, UNUSED_ATTRIBUTES}; use rustc_session::lint::{ - builtin::{self, FORBIDDEN_LINT_GROUPS, SINGLE_USE_LIFETIMES, UNFULFILLED_LINT_EXPECTATIONS}, + builtin::{ + self, FORBIDDEN_LINT_GROUPS, RENAMED_AND_REMOVED_LINTS, SINGLE_USE_LIFETIMES, + UNFULFILLED_LINT_EXPECTATIONS, UNKNOWN_LINTS, UNUSED_ATTRIBUTES, + }, Level, Lint, LintExpectationId, LintId, }; -use rustc_session::parse::{add_feature_diagnostics, feature_err}; +use rustc_session::parse::feature_err; use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -566,7 +568,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { continue; } - if self.check_gated_lint(id, DUMMY_SP) { + if self.check_gated_lint(id, DUMMY_SP, true) { let src = LintLevelSource::CommandLine(lint_flag_val, orig_level); self.insert(id, (level, src)); } @@ -837,7 +839,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { reason, }; for &id in *ids { - if self.check_gated_lint(id, attr.span) { + if self.check_gated_lint(id, attr.span, false) { self.insert_spec(id, (level, src)); } } @@ -854,7 +856,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { reason, }; for &id in ids { - if self.check_gated_lint(id, attr.span) { + if self.check_gated_lint(id, attr.span, false) { self.insert_spec(id, (level, src)); } } @@ -955,7 +957,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { reason, }; for &id in ids { - if self.check_gated_lint(id, attr.span) { + if self.check_gated_lint(id, attr.span, false) { self.insert_spec(id, (level, src)); } } @@ -1000,7 +1002,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { // FIXME only emit this once for each attribute, instead of repeating it 4 times for // pre-expansion lints, post-expansion lints, `shallow_lint_levels_on` and `lint_expectations`. #[track_caller] - fn check_gated_lint(&self, lint_id: LintId, span: Span) -> bool { + fn check_gated_lint(&self, lint_id: LintId, span: Span, lint_from_cli: bool) -> bool { if let Some(feature) = lint_id.lint.feature_gate { if !self.features.enabled(feature) { let lint = builtin::UNKNOWN_LINTS; @@ -1015,7 +1017,13 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { |lint| { lint.set_arg("name", lint_id.lint.name_lower()); lint.note(fluent::lint_note); - add_feature_diagnostics(lint, &self.sess.parse_sess, feature); + rustc_session::parse::add_feature_diagnostics_for_issue( + lint, + &self.sess.parse_sess, + feature, + GateIssue::Language, + lint_from_cli, + ); lint }, ); diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index b07c6db599e2..e06b63809445 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -8,6 +8,9 @@ session_cannot_mix_and_match_sanitizers = `-Zsanitizer={$first}` is incompatible session_cgu_not_recorded = CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded +session_cli_feature_diagnostic_help = + add `-Zcrate-attr="feature({$feature})"` to the command-line options to enable + session_crate_name_does_not_match = `--crate-name` and `#[crate_name]` are required to match, but `{$s}` != `{$name}` session_crate_name_empty = crate name must not be empty diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 78940462b2c8..5f8bbfca8908 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -57,6 +57,12 @@ pub struct FeatureDiagnosticHelp { pub feature: Symbol, } +#[derive(Subdiagnostic)] +#[help(session_cli_feature_diagnostic_help)] +pub struct CliFeatureDiagnosticHelp { + pub feature: Symbol, +} + #[derive(Diagnostic)] #[diag(session_not_circumvent_feature)] pub struct NotCircumventFeature; diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 1cf63e9b7ba7..671204c0d8ef 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -2,7 +2,9 @@ //! It also serves as an input to the parser itself. use crate::config::CheckCfg; -use crate::errors::{FeatureDiagnosticForIssue, FeatureDiagnosticHelp, FeatureGateError}; +use crate::errors::{ + CliFeatureDiagnosticHelp, FeatureDiagnosticForIssue, FeatureDiagnosticHelp, FeatureGateError, +}; use crate::lint::{ builtin::UNSTABLE_SYNTAX_PRE_EXPANSION, BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId, }; @@ -110,7 +112,7 @@ pub fn feature_err_issue( } let mut err = sess.create_err(FeatureGateError { span, explain: explain.into() }); - add_feature_diagnostics_for_issue(&mut err, sess, feature, issue); + add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false); err } @@ -139,7 +141,7 @@ pub fn feature_warn_issue( explain: &'static str, ) { let mut err = sess.span_diagnostic.struct_span_warn(span, explain); - add_feature_diagnostics_for_issue(&mut err, sess, feature, issue); + add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false); // Decorate this as a future-incompatibility lint as in rustc_middle::lint::struct_lint_level let lint = UNSTABLE_SYNTAX_PRE_EXPANSION; @@ -158,7 +160,7 @@ pub fn feature_warn_issue( /// Adds the diagnostics for a feature to an existing error. pub fn add_feature_diagnostics(err: &mut Diagnostic, sess: &ParseSess, feature: Symbol) { - add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language); + add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language, false); } /// Adds the diagnostics for a feature to an existing error. @@ -171,6 +173,7 @@ pub fn add_feature_diagnostics_for_issue( sess: &ParseSess, feature: Symbol, issue: GateIssue, + feature_from_cli: bool, ) { if let Some(n) = find_feature_issue(feature, issue) { err.subdiagnostic(FeatureDiagnosticForIssue { n }); @@ -178,7 +181,11 @@ pub fn add_feature_diagnostics_for_issue( // #23973: do not suggest `#![feature(...)]` if we are in beta/stable if sess.unstable_features.is_nightly_build() { - err.subdiagnostic(FeatureDiagnosticHelp { feature }); + if feature_from_cli { + err.subdiagnostic(CliFeatureDiagnosticHelp { feature }); + } else { + err.subdiagnostic(FeatureDiagnosticHelp { feature }); + } } } diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr index aa73b824a570..32f8d2f45dc8 100644 --- a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr +++ b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr @@ -1,18 +1,18 @@ error: unknown lint: `test_unstable_lint` | = note: the `test_unstable_lint` lint is unstable - = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable = note: requested on the command line with `-D unknown-lints` error: unknown lint: `test_unstable_lint` | = note: the `test_unstable_lint` lint is unstable - = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable error: unknown lint: `test_unstable_lint` | = note: the `test_unstable_lint` lint is unstable - = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable error: aborting due to 3 previous errors diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr index 82851c80064b..dd9ecf02fa6b 100644 --- a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr +++ b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr @@ -1,18 +1,18 @@ warning: unknown lint: `test_unstable_lint` | = note: the `test_unstable_lint` lint is unstable - = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable = note: requested on the command line with `-W unknown-lints` warning: unknown lint: `test_unstable_lint` | = note: the `test_unstable_lint` lint is unstable - = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable warning: unknown lint: `test_unstable_lint` | = note: the `test_unstable_lint` lint is unstable - = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable warning: 3 warnings emitted From 265c1b5d5025a1cb3bdc26b99f35317079a55c36 Mon Sep 17 00:00:00 2001 From: kadiwa Date: Tue, 22 Aug 2023 14:43:53 +0200 Subject: [PATCH 122/197] add regression test for not memcpying padding bytes --- .../{box-maybe-uninit.rs => box-uninit-bytes.rs} | 14 ++++++++++++++ 1 file changed, 14 insertions(+) rename tests/codegen/{box-maybe-uninit.rs => box-uninit-bytes.rs} (76%) diff --git a/tests/codegen/box-maybe-uninit.rs b/tests/codegen/box-uninit-bytes.rs similarity index 76% rename from tests/codegen/box-maybe-uninit.rs rename to tests/codegen/box-uninit-bytes.rs index 282af99b0673..732da0a17949 100644 --- a/tests/codegen/box-maybe-uninit.rs +++ b/tests/codegen/box-uninit-bytes.rs @@ -25,6 +25,20 @@ pub fn box_uninitialized2() -> Box> { Box::new(MaybeUninit::uninit()) } +#[repr(align(1024))] +pub struct LotsaPadding(usize); + +// Boxing a value with padding should not copy junk from the stack +#[no_mangle] +pub fn box_lotsa_padding() -> Box { + // CHECK-LABEL: @box_lotsa_padding + // CHECK-NOT: alloca + // CHECK-NOT: getelementptr + // CHECK-NOT: memcpy + // CHECK-NOT: memset + Box::new(LotsaPadding(42)) +} + // Hide the `allocalign` attribute in the declaration of __rust_alloc // from the CHECK-NOT above, and also verify the attributes got set reasonably. // CHECK: declare {{(dso_local )?}}noalias noundef ptr @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+}} allocalign noundef) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]] From 7ee77b5d1b91adf4c683d0d871015fe68ebca9ea Mon Sep 17 00:00:00 2001 From: Urgau Date: Tue, 22 Aug 2023 15:41:07 +0200 Subject: [PATCH 123/197] Add support for ptr::write for the invalid_reference_casting lint --- compiler/rustc_lint/src/reference_casting.rs | 64 ++++++++++++++------ compiler/rustc_span/src/symbol.rs | 3 + library/core/src/ptr/mod.rs | 3 + tests/ui/lint/reference_casting.rs | 11 ++++ tests/ui/lint/reference_casting.stderr | 47 ++++++++++++-- 5 files changed, 106 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs index 2577cabb3f0f..883f6242b564 100644 --- a/compiler/rustc_lint/src/reference_casting.rs +++ b/compiler/rustc_lint/src/reference_casting.rs @@ -56,20 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting { } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - // &mut - let inner = if let ExprKind::AddrOf(_, Mutability::Mut, expr) = expr.kind { - expr - // = ... - } else if let ExprKind::Assign(expr, _, _) = expr.kind { - expr - // += ... - } else if let ExprKind::AssignOp(_, expr, _) = expr.kind { - expr - } else { - return; - }; - - let ExprKind::Unary(UnOp::Deref, e) = &inner.kind else { + let Some((is_assignment, e)) = is_operation_we_care_about(cx, expr) else { return; }; @@ -86,15 +73,58 @@ impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting { cx.emit_spanned_lint( INVALID_REFERENCE_CASTING, expr.span, - if matches!(expr.kind, ExprKind::AddrOf(..)) { - InvalidReferenceCastingDiag::BorrowAsMut { orig_cast } - } else { + if is_assignment { InvalidReferenceCastingDiag::AssignToRef { orig_cast } + } else { + InvalidReferenceCastingDiag::BorrowAsMut { orig_cast } }, ); } } +fn is_operation_we_care_about<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'tcx>, +) -> Option<(bool, &'tcx Expr<'tcx>)> { + fn deref_assign_or_addr_of<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<(bool, &'tcx Expr<'tcx>)> { + // &mut + let inner = if let ExprKind::AddrOf(_, Mutability::Mut, expr) = expr.kind { + expr + // = ... + } else if let ExprKind::Assign(expr, _, _) = expr.kind { + expr + // += ... + } else if let ExprKind::AssignOp(_, expr, _) = expr.kind { + expr + } else { + return None; + }; + + if let ExprKind::Unary(UnOp::Deref, e) = &inner.kind { + Some((!matches!(expr.kind, ExprKind::AddrOf(..)), e)) + } else { + None + } + } + + fn ptr_write<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'tcx>, + ) -> Option<(bool, &'tcx Expr<'tcx>)> { + if let ExprKind::Call(path, [arg_ptr, _arg_val]) = e.kind + && let ExprKind::Path(ref qpath) = path.kind + && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() + && matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::ptr_write | sym::ptr_write_volatile | sym::ptr_write_unaligned)) + { + Some((true, arg_ptr)) + } else { + None + } + } + + deref_assign_or_addr_of(e).or_else(|| ptr_write(cx, e)) +} + fn is_cast_from_const_to_mut<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool { let e = e.peel_blocks(); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 28a2dfebcfe9..8aec12f128ec 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1179,6 +1179,9 @@ symbols! { ptr_offset_from, ptr_offset_from_unsigned, ptr_unique, + ptr_write, + ptr_write_unaligned, + ptr_write_volatile, pub_macro_rules, pub_restricted, public, diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 5f094ac4e7e6..01e360448992 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1357,6 +1357,7 @@ pub const unsafe fn read_unaligned(src: *const T) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] +#[rustc_diagnostic_item = "ptr_write"] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write(dst: *mut T, src: T) { // Semantically, it would be fine for this to be implemented as a @@ -1459,6 +1460,7 @@ pub const unsafe fn write(dst: *mut T, src: T) { #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] +#[rustc_diagnostic_item = "ptr_write_unaligned"] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write_unaligned(dst: *mut T, src: T) { // SAFETY: the caller must guarantee that `dst` is valid for writes. @@ -1607,6 +1609,7 @@ pub unsafe fn read_volatile(src: *const T) -> T { /// ``` #[inline] #[stable(feature = "volatile", since = "1.9.0")] +#[rustc_diagnostic_item = "ptr_write_volatile"] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn write_volatile(dst: *mut T, src: T) { // SAFETY: the caller must uphold the safety contract for `volatile_store`. diff --git a/tests/ui/lint/reference_casting.rs b/tests/ui/lint/reference_casting.rs index 6c38bca3daa9..92d985948ec3 100644 --- a/tests/ui/lint/reference_casting.rs +++ b/tests/ui/lint/reference_casting.rs @@ -71,6 +71,11 @@ unsafe fn assign_to_ref() { //~^ ERROR assigning to `&T` is undefined behavior *std::mem::transmute::<_, *mut i32>(num) += 1; //~^ ERROR assigning to `&T` is undefined behavior + std::ptr::write( + //~^ ERROR assigning to `&T` is undefined behavior + std::mem::transmute::<*const i32, *mut i32>(num), + -1i32, + ); let value = num as *const i32 as *mut i32; *value = 1; @@ -79,6 +84,12 @@ unsafe fn assign_to_ref() { //~^ ERROR assigning to `&T` is undefined behavior *(num as *const _ as usize as *mut i32) = 2; //~^ ERROR assigning to `&T` is undefined behavior + std::ptr::write(value, 2); + //~^ ERROR assigning to `&T` is undefined behavior + std::ptr::write_unaligned(value, 2); + //~^ ERROR assigning to `&T` is undefined behavior + std::ptr::write_volatile(value, 2); + //~^ ERROR assigning to `&T` is undefined behavior unsafe fn generic_assign_to_ref(this: &T, a: T) { *(this as *const _ as *mut _) = a; diff --git a/tests/ui/lint/reference_casting.stderr b/tests/ui/lint/reference_casting.stderr index 7ff9b76a85e9..c1589f138351 100644 --- a/tests/ui/lint/reference_casting.stderr +++ b/tests/ui/lint/reference_casting.stderr @@ -131,7 +131,17 @@ LL | *std::mem::transmute::<_, *mut i32>(num) += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:76:5 + --> $DIR/reference_casting.rs:74:5 + | +LL | / std::ptr::write( +LL | | +LL | | std::mem::transmute::<*const i32, *mut i32>(num), +LL | | -1i32, +LL | | ); + | |_____^ + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:81:5 | LL | let value = num as *const i32 as *mut i32; | ----------------------------- casting happend here @@ -139,22 +149,49 @@ LL | *value = 1; | ^^^^^^^^^^ error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:78:5 + --> $DIR/reference_casting.rs:83:5 | LL | *(num as *const i32).cast::().cast_mut() = 2; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:80:5 + --> $DIR/reference_casting.rs:85:5 | LL | *(num as *const _ as usize as *mut i32) = 2; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:84:9 + --> $DIR/reference_casting.rs:87:5 + | +LL | let value = num as *const i32 as *mut i32; + | ----------------------------- casting happend here +... +LL | std::ptr::write(value, 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:89:5 + | +LL | let value = num as *const i32 as *mut i32; + | ----------------------------- casting happend here +... +LL | std::ptr::write_unaligned(value, 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:91:5 + | +LL | let value = num as *const i32 as *mut i32; + | ----------------------------- casting happend here +... +LL | std::ptr::write_volatile(value, 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:95:9 | LL | *(this as *const _ as *mut _) = a; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 25 previous errors +error: aborting due to 29 previous errors From d5269a1d7ba86896be6ad158530f7787272c46f9 Mon Sep 17 00:00:00 2001 From: David Wood Date: Tue, 22 Aug 2023 16:15:00 +0100 Subject: [PATCH 124/197] triagebot: add dependency licensing pings Signed-off-by: David Wood --- triagebot.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index b5047fd4344f..2f380ef1ddaa 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -470,6 +470,10 @@ Otherwise, you can ignore this comment. [mentions."src/tools/x"] message = "`src/tools/x` was changed. Bump version of Cargo.toml in `src/tools/x` so tidy will suggest installing the new version." +[mentions."src/tools/tidy/src/deps.rs"] +message = "Third-party dependency whitelist may have been modified! You must ensure that any new dependencies have compatible licenses before merging." +cc = ["@davidtwco", "@wesleywiser"] + [mentions."src/bootstrap/defaults/config.compiler.toml"] message = "This PR changes src/bootstrap/defaults/config.compiler.toml. If appropriate, please also update `config.codegen.toml` so the defaults are in sync." [mentions."src/bootstrap/defaults/config.codegen.toml"] From 6aef5b331ffcb6816fb8900f5e2d87948e7cff84 Mon Sep 17 00:00:00 2001 From: David Koloski Date: Tue, 22 Aug 2023 15:29:10 +0000 Subject: [PATCH 125/197] Disable bootstrap rustc version check Mitigates #115065 --- src/bootstrap/config.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 4821d20a8989..762e66ac7cc3 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -1276,7 +1276,8 @@ impl Config { } config.initial_rustc = if let Some(rustc) = build.rustc { - config.check_build_rustc_version(&rustc); + // FIXME(#115065): re-enable this check + // config.check_build_rustc_version(&rustc); PathBuf::from(rustc) } else { config.download_beta_toolchain(); From b86285af1661abb0824ead4ea89db0e5c898c422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 21 Aug 2023 21:01:27 +0000 Subject: [PATCH 126/197] Do not emit invalid suggestion in E0191 when spans overlap Fix #115019. --- .../rustc_hir_analysis/src/astconv/errors.rs | 16 +++++++++++++++- .../overlaping-bound-suggestion.stderr | 5 ----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index bd311c98facf..6082d4469791 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -597,7 +597,21 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } } - if !suggestions.is_empty() { + suggestions.sort_by_key(|&(span, _)| span); + // There are cases where one bound points to a span within another bound's span, like when + // you have code like the following (#115019), so we skip providing a suggestion in those + // cases to avoid having a malformed suggestion. + // + // pub struct Flatten { + // inner: >::IntoIterator as Item>::core, + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + // | ^^^^^^^^^^^^^^^^^^^^^ + // | | + // | associated types `Item`, `IntoIter` must be specified + // associated types `Item`, `IntoIter` must be specified + // } + let overlaps = suggestions.windows(2).any(|pair| pair[0].0.overlaps(pair[1].0)); + if !suggestions.is_empty() && !overlaps { err.multipart_suggestion( format!("specify the associated type{}", pluralize!(types_count)), suggestions, diff --git a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr index 8bea440ddbad..61299550e98a 100644 --- a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr +++ b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr @@ -6,11 +6,6 @@ LL | inner: >::IntoIterator as Item> | | | | | associated types `Item`, `IntoIter` must be specified | associated types `Item`, `IntoIter` must be specified - | -help: specify the associated types - | -LL | inner: , Item = Type, IntoIter = Type>IntoIterator>::IntoIterator as Item>::Core, - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/overlaping-bound-suggestion.rs:7:13 From 3977ed1e69e6fc14e76e19bead3d6d725fc2129d Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Tue, 22 Aug 2023 12:26:35 -0400 Subject: [PATCH 127/197] ArchiveWrapper: handle LLVM API update In llvm/llvm-project@f740bcb3707a17ed4ccd52157089011a586cc2a6 a boolean parameter changed to an enum. r? @nikic @rustbot label: +llvm-main --- compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp index 35d6b9ed7a44..54fdc84c77d2 100644 --- a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp @@ -203,7 +203,12 @@ LLVMRustWriteArchive(char *Dst, size_t NumMembers, } } +#if LLVM_VERSION_LT(18, 0) auto Result = writeArchive(Dst, Members, WriteSymbtab, Kind, true, false); +#else + auto SymtabMode = WriteSymbtab ? SymtabWritingMode::NormalSymtab : SymtabWritingMode::NoSymtab; + auto Result = writeArchive(Dst, Members, SymtabMode, Kind, true, false); +#endif if (!Result) return LLVMRustResult::Success; LLVMRustSetLastError(toString(std::move(Result)).c_str()); From 35187c7e6474d346eea3113c4ae34d26d6b18756 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 22 Aug 2023 10:42:12 -0700 Subject: [PATCH 128/197] Skip ExpandYamlAnchors when the config is missing The dist-src tarball does not include `.github/` at all, so we can't check whether it needs to be regenerated. --- src/bootstrap/test.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index db3b7ffbea4e..d1018978f78c 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1174,6 +1174,11 @@ impl Step for ExpandYamlAnchors { /// appropriate configuration for all our CI providers. This step ensures the tool was called /// by the user before committing CI changes. fn run(self, builder: &Builder<'_>) { + // Note: `.github/` is not included in dist-src tarballs + if !builder.src.join(".github/workflows/ci.yml").exists() { + builder.info("Skipping YAML anchors check: GitHub Actions config not found"); + return; + } builder.info("Ensuring the YAML anchors in the GitHub Actions config were expanded"); builder.run_delaying_failure( &mut builder.tool_cmd(Tool::ExpandYamlAnchors).arg("check").arg(&builder.src), From 015b5cb3066a85eee4524762f8bc7cf00f09b3be Mon Sep 17 00:00:00 2001 From: ouz-a Date: Tue, 22 Aug 2023 13:01:37 +0300 Subject: [PATCH 129/197] add generics_of to smir --- compiler/rustc_smir/src/rustc_internal/mod.rs | 8 ++ compiler/rustc_smir/src/rustc_smir/mod.rs | 73 ++++++++++++++++++- compiler/rustc_smir/src/stable_mir/mod.rs | 3 +- compiler/rustc_smir/src/stable_mir/ty.rs | 58 ++++++++++++--- 4 files changed, 129 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 078ff67446f6..ebacb7cce836 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -80,6 +80,10 @@ impl<'tcx> Tables<'tcx> { self.def_ids[impl_def.0] } + pub fn generic_def_id(&self, generic_def: &stable_mir::ty::GenericDef) -> DefId { + self.def_ids[generic_def.0] + } + pub fn crate_item(&mut self, did: DefId) -> stable_mir::CrateItem { stable_mir::CrateItem(self.create_def_id(did)) } @@ -120,6 +124,10 @@ impl<'tcx> Tables<'tcx> { stable_mir::ty::TraitDef(self.create_def_id(did)) } + pub fn generic_def(&mut self, did: DefId) -> stable_mir::ty::GenericDef { + stable_mir::ty::GenericDef(self.create_def_id(did)) + } + pub fn const_def(&mut self, did: DefId) -> stable_mir::ty::ConstDef { stable_mir::ty::ConstDef(self.create_def_id(did)) } diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 7e8ac9a141a7..aea59c31379e 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -10,7 +10,8 @@ use crate::rustc_internal::{self, opaque}; use crate::stable_mir::mir::{CopyNonOverlapping, UserTypeProjection, VariantIdx}; use crate::stable_mir::ty::{ - allocation_filter, new_allocation, Const, FloatTy, IntTy, Movability, RigidTy, TyKind, UintTy, + allocation_filter, new_allocation, Const, FloatTy, GenericDef, GenericParamDef, IntTy, + Movability, RigidTy, TyKind, UintTy, }; use crate::stable_mir::{self, Context}; use rustc_hir as hir; @@ -101,6 +102,12 @@ impl<'tcx> Context for Tables<'tcx> { let ty = self.types[ty.0]; ty.stable(self) } + + fn generics_of(&mut self, generic_def: &GenericDef) -> stable_mir::ty::Generics { + let def_id = self.generic_def_id(generic_def); + let generic_def = self.tcx.generics_of(def_id); + generic_def.stable(self) + } } pub struct Tables<'tcx> { @@ -1205,3 +1212,67 @@ impl<'tcx> Stable<'tcx> for ty::TraitRef<'tcx> { TraitRef { def_id: rustc_internal::trait_def(self.def_id), args: self.args.stable(tables) } } } + +impl<'tcx> Stable<'tcx> for ty::Generics { + type T = stable_mir::ty::Generics; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + use stable_mir::ty::Generics; + + let params: Vec<_> = self.params.iter().map(|param| param.stable(tables)).collect(); + let param_def_id_to_index = + params.iter().map(|param| (param.def_id, param.index)).collect(); + + Generics { + parent: self.parent.map(|did| tables.generic_def(did)), + parent_count: self.parent_count, + params, + param_def_id_to_index, + has_self: self.has_self, + has_late_bound_regions: self + .has_late_bound_regions + .as_ref() + .map(|late_bound_regions| late_bound_regions.stable(tables)), + host_effect_index: self.host_effect_index, + } + } +} + +impl<'tcx> Stable<'tcx> for rustc_span::Span { + type T = stable_mir::ty::Span; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + opaque(self) + } +} + +impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind { + type T = stable_mir::ty::GenericParamDefKind; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + use stable_mir::ty::GenericParamDefKind; + match self { + ty::GenericParamDefKind::Lifetime => GenericParamDefKind::Lifetime, + ty::GenericParamDefKind::Type { has_default, synthetic } => { + GenericParamDefKind::Type { has_default: *has_default, synthetic: *synthetic } + } + ty::GenericParamDefKind::Const { has_default } => { + GenericParamDefKind::Const { has_default: *has_default } + } + } + } +} + +impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDef { + type T = stable_mir::ty::GenericParamDef; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + GenericParamDef { + name: self.name.to_string(), + def_id: tables.generic_def(self.def_id), + index: self.index, + pure_wrt_drop: self.pure_wrt_drop, + kind: self.kind.stable(tables), + } + } +} diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs index 2ae334c6a959..8e38e394b982 100644 --- a/compiler/rustc_smir/src/stable_mir/mod.rs +++ b/compiler/rustc_smir/src/stable_mir/mod.rs @@ -15,7 +15,7 @@ use std::cell::Cell; use crate::rustc_smir::Tables; -use self::ty::{ImplDef, ImplTrait, TraitDecl, TraitDef, Ty, TyKind}; +use self::ty::{GenericDef, Generics, ImplDef, ImplTrait, TraitDecl, TraitDef, Ty, TyKind}; pub mod mir; pub mod ty; @@ -110,6 +110,7 @@ pub trait Context { fn trait_decl(&mut self, trait_def: &TraitDef) -> TraitDecl; fn all_trait_impls(&mut self) -> ImplTraitDecls; fn trait_impl(&mut self, trait_impl: &ImplDef) -> ImplTrait; + fn generics_of(&mut self, generic_def: &GenericDef) -> Generics; /// Get information about the local crate. fn local_crate(&self) -> Crate; /// Retrieve a list of all external crates. diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 7a6601f09da4..fe7fef5d0c17 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -22,7 +22,7 @@ pub struct Const { type Ident = Opaque; pub(crate) type Region = Opaque; -type Span = Opaque; +pub type Span = Opaque; #[derive(Clone, Debug)] pub enum TyKind { @@ -87,34 +87,37 @@ pub enum Movability { Movable, } -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct ForeignDef(pub(crate) DefId); -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct FnDef(pub(crate) DefId); -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct ClosureDef(pub(crate) DefId); -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct GeneratorDef(pub(crate) DefId); -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct ParamDef(pub(crate) DefId); -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct BrNamedDef(pub(crate) DefId); -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct AdtDef(pub(crate) DefId); -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct AliasDef(pub(crate) DefId); -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct TraitDef(pub(crate) DefId); -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub struct GenericDef(pub(crate) DefId); + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct ConstDef(pub(crate) DefId); impl TraitDef { @@ -132,6 +135,12 @@ impl ImplDef { } } +impl GenericDef { + pub fn generics_of(&self) -> Generics { + with(|tcx| tcx.generics_of(self)) + } +} + #[derive(Clone, Debug)] pub struct GenericArgs(pub Vec); @@ -461,3 +470,30 @@ pub struct TraitRef { pub def_id: TraitDef, pub args: GenericArgs, } + +#[derive(Clone, Debug)] +pub struct Generics { + pub parent: Option, + pub parent_count: usize, + pub params: Vec, + pub param_def_id_to_index: Vec<(GenericDef, u32)>, + pub has_self: bool, + pub has_late_bound_regions: Option, + pub host_effect_index: Option, +} + +#[derive(Clone, Debug)] +pub enum GenericParamDefKind { + Lifetime, + Type { has_default: bool, synthetic: bool }, + Const { has_default: bool }, +} + +#[derive(Clone, Debug)] +pub struct GenericParamDef { + pub name: super::Symbol, + pub def_id: GenericDef, + pub index: u32, + pub pure_wrt_drop: bool, + pub kind: GenericParamDefKind, +} From 1097e0957e299613fac4ea58c85aaf8204075a62 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Tue, 22 Aug 2023 15:30:26 -0400 Subject: [PATCH 130/197] Fix spelling mistake --- compiler/rustc_codegen_llvm/src/debuginfo/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index d03819b16881..9cdeae2841b7 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -67,7 +67,7 @@ pub struct CodegenUnitDebugContext<'ll, 'tcx> { type_map: metadata::TypeMap<'ll, 'tcx>, namespace_map: RefCell>, recursion_marker_type: OnceCell<&'ll DIType>, - /// Maps a varaible (name, scope, kind (argument or local), span) to its debug information. + /// Maps a variable (name, scope, kind (argument or local), span) to its debug information. variables: RefCell>, } From ca055f148be2fb2ef1102c894330366be32c490f Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Thu, 17 Aug 2023 11:16:20 +0100 Subject: [PATCH 131/197] Automatically add OS labels to std PRs --- triagebot.toml | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 2c71b650f68c..e4bcb9361aff 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -177,6 +177,98 @@ exclude_labels = [ "T-*", ] +[autolabel."O-android"] +trigger_files = [ + "library/std/src/os/android" +] + +[autolabel."O-fuchsia"] +trigger_files = [ + "library/std/src/os/fuchsia" +] + +[autolabel."O-hermit"] +trigger_files = [ + "library/std/src/sys/hermit", + "library/std/src/os/hermit" +] + +[autolabel."O-ios"] +trigger_files = [ + "library/std/src/os/ios" +] + +[autolabel."O-itron"] +trigger_files = [ + "library/std/src/sys/itron" +] + +[autolabel."O-linux"] +trigger_files = [ + "library/std/src/os/linux" +] + +[autolabel."O-macos"] +trigger_files = [ + "library/std/src/os/macos" +] + +[autolabel."O-netbsd"] +trigger_files = [ + "library/std/src/os/netbsd" +] + +[autolabel."O-redox"] +trigger_files = [ + "library/std/src/os/redox" +] + +[autolabel."O-SGX"] +trigger_files = [ + "library/std/src/sys/sgx", + "library/std/src/os/fortanix_sgx" +] + +[autolabel."O-solaris"] +trigger_files = [ + "library/std/src/os/solaris" +] + +[autolabel."O-solid"] +trigger_files = [ + "library/std/src/sys/solid", + "library/std/src/os/solid" +] + +[autolabel."O-unix"] +trigger_files = [ + "library/std/src/sys/unix", + "library/std/src/os/unix" +] + +[autolabel."O-wasi"] +trigger_files = [ + "library/std/src/sys/wasi", + "library/std/src/os/wasi" +] + +[autolabel."O-wasm"] +trigger_files = [ + "library/std/src/sys/wasm", + "library/std/src/os/wasm" +] + +[autolabel."O-watchos"] +trigger_files = [ + "library/std/src/os/watchos" +] + +[autolabel."O-windows"] +trigger_files = [ + "library/std/src/sys/windows", + "library/std/src/os/windows" +] + [autolabel."T-bootstrap"] trigger_files = [ "x.py", From 4332e8417d15f304741208e82ab969768f0dc11d Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 22 Aug 2023 16:16:44 -0400 Subject: [PATCH 132/197] drive-by fix to Python doc comment. --- src/bootstrap/bootstrap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index c5c70f2e18a1..c71ecc0a1396 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -623,7 +623,7 @@ class RustBuild(object): def should_fix_bins_and_dylibs(self): """Whether or not `fix_bin_or_dylib` needs to be run; can only be True - on NixOS. + on NixOS or if config.toml has `build.patch-binaries-for-nix` set. """ if self._should_fix_bins_and_dylibs is not None: return self._should_fix_bins_and_dylibs From 3c6f4cc743316ff4b7f76a6492f78d6eb83dcf50 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 22 Aug 2023 17:45:54 -0400 Subject: [PATCH 133/197] Better diagnostics for people using nix subshell on non-NixOS. 1. Turned patch-binaries-for-nix from a boolean into a ternary flag: true, false, and unset. 2. When patch-binaries-for-nix is unset, we continue with the existing NixOS detection heuristic (look for nixos in /etc/os-release, if present), but if we are not atop NixOS, then issue a note if we see the IN_NIX_SHELL environment variable telling the user to consider setting patch-binaries-for-nix explicitly. --- src/bootstrap/bootstrap.py | 23 +++++++++++++++++++---- src/bootstrap/config.rs | 4 ++-- src/bootstrap/download.rs | 13 +++++++++++-- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index c71ecc0a1396..588164e4a85c 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -643,18 +643,33 @@ class RustBuild(object): if ostype != "Linux": return False - # If the user has asked binaries to be patched for Nix, then - # don't check for NixOS. + # If the user has explicitly indicated whether binaries should be + # patched for Nix, then don't check for NixOS. if self.get_toml("patch-binaries-for-nix", "build") == "true": return True + if self.get_toml("patch-binaries-for-nix", "build") == "false": + return False + + # Assume we should fix until we see evidence that it is not NixOS + should_fix_retval = True # Use `/etc/os-release` instead of `/etc/NIXOS`. # The latter one does not exist on NixOS when using tmpfs as root. try: with open("/etc/os-release", "r") as f: - return any(ln.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"') for ln in f) + should_fix_retval = any(ln.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"') for ln in f) except FileNotFoundError: - return False + should_fix_retval = False + + # If not on NixOS, then warn if user seems to be atop Nix shell + if not should_fix_retval: + in_nix_shell = os.getenv('IN_NIX_SHELL') + if in_nix_shell: + print("The IN_NIX_SHELL environment variable is set to `{}`;".format(in_nix_shell), + "you may need to set `patch-binaries-for-nix=true` in your config.toml", + file=sys.stderr) + + return should_fix_retval answer = self._should_fix_bins_and_dylibs = get_answer() if answer: diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 4821d20a8989..fc2c91f76b45 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -137,7 +137,7 @@ pub struct Config { pub json_output: bool, pub test_compare_mode: bool, pub color: Color, - pub patch_binaries_for_nix: bool, + pub patch_binaries_for_nix: Option, pub stage0_metadata: Stage0Metadata, pub stdout_is_tty: bool, @@ -1338,7 +1338,7 @@ impl Config { set(&mut config.local_rebuild, build.local_rebuild); set(&mut config.print_step_timings, build.print_step_timings); set(&mut config.print_step_rusage, build.print_step_rusage); - set(&mut config.patch_binaries_for_nix, build.patch_binaries_for_nix); + config.patch_binaries_for_nix = build.patch_binaries_for_nix; config.verbose = cmp::max(config.verbose, flags.verbose as usize); diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs index 52162bf42ea4..bf8cb4bd7683 100644 --- a/src/bootstrap/download.rs +++ b/src/bootstrap/download.rs @@ -91,8 +91,8 @@ impl Config { // NOTE: this intentionally comes after the Linux check: // - patchelf only works with ELF files, so no need to run it on Mac or Windows // - On other Unix systems, there is no stable syscall interface, so Nix doesn't manage the global libc. - if self.patch_binaries_for_nix { - return true; + if let Some(explicit_value) = self.patch_binaries_for_nix { + return explicit_value; } // Use `/etc/os-release` instead of `/etc/NIXOS`. @@ -105,6 +105,15 @@ impl Config { matches!(l.trim(), "ID=nixos" | "ID='nixos'" | "ID=\"nixos\"") }), }; + if !is_nixos { + let in_nix_shell = env::var("IN_NIX_SHELL"); + if let Ok(in_nix_shell) = in_nix_shell { + eprintln!( + "The IN_NIX_SHELL environment variable is set to `{in_nix_shell}`; \ + you may need to set `patch-binaries-for-nix=true` in your config.toml" + ); + } + } is_nixos }); if val { From 5ee08a0c9393bf94dc7d2943fdd2c2cd2b616c82 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 23 Jul 2023 12:00:58 -0700 Subject: [PATCH 134/197] ci: Update FreeBSD and illumos binutils to 2.40 The current old 2.25 seems to cause trouble to #106511. Install texinfo to dist-x86_64-freebsd/Dockerfile like other containers to fix ``` MAKEINFO doc/bfd.info /binutils/binutils-2.40/missing: 81: /binutils/binutils-2.40/missing: makeinfo: not found WARNING: 'makeinfo' is missing on your system. ``` --- src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile | 1 + src/ci/docker/scripts/freebsd-toolchain.sh | 2 +- src/ci/docker/scripts/illumos-toolchain.sh | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile index 377d4a9ce5eb..b3c5f41bdd7d 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile @@ -13,6 +13,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ sudo \ bzip2 \ xz-utils \ + texinfo \ wget \ libssl-dev \ pkg-config \ diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh index 17cd456b995a..0d02636db919 100755 --- a/src/ci/docker/scripts/freebsd-toolchain.sh +++ b/src/ci/docker/scripts/freebsd-toolchain.sh @@ -4,7 +4,7 @@ set -eux arch=$1 -binutils_version=2.25.1 +binutils_version=2.40 freebsd_version=12.3 triple=$arch-unknown-freebsd12 sysroot=/usr/local/$triple diff --git a/src/ci/docker/scripts/illumos-toolchain.sh b/src/ci/docker/scripts/illumos-toolchain.sh index 3f1d5f3426ab..0b2c09b3eed9 100644 --- a/src/ci/docker/scripts/illumos-toolchain.sh +++ b/src/ci/docker/scripts/illumos-toolchain.sh @@ -52,8 +52,8 @@ SYSROOT_URL='https://github.com/illumos/sysroot/releases/download/' SYSROOT_URL+="$SYSROOT_VER/$SYSROOT_TAR" SYSROOT_DIR="$PREFIX/sysroot" -BINUTILS_VERSION='2.25.1' -BINUTILS_SUM='b5b14added7d78a8d1ca70b5cb75fef57ce2197264f4f5835326b0df22ac9f22' +BINUTILS_VERSION='2.40' +BINUTILS_SUM='f8298eb153a4b37d112e945aa5cb2850040bcf26a3ea65b5a715c83afe05e48a' BINUTILS_BASE="binutils-$BINUTILS_VERSION" BINUTILS_TAR="$BINUTILS_BASE.tar.bz2" BINUTILS_URL="https://ftp.gnu.org/gnu/binutils/$BINUTILS_TAR" From 4c14ca3141e3adefa8d30a03d6050dbf9b6699bf Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Tue, 22 Aug 2023 12:20:35 -0700 Subject: [PATCH 135/197] Bump backtrace to 0.3.69 --- Cargo.lock | 50 ++++++++++++----------------------------------- library/backtrace | 2 +- 2 files changed, 14 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4ebbb16442ea..7337901bc3a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "addr2line" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" -dependencies = [ - "gimli 0.27.3", -] - [[package]] name = "addr2line" version = "0.21.0" @@ -18,7 +9,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "compiler_builtins", - "gimli 0.28.0", + "gimli", "rustc-std-workspace-alloc", "rustc-std-workspace-core", ] @@ -180,7 +171,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9792d37ca5173d7e7f4fe453739a0671d0557915a030a383d6b866476bbc3e71" dependencies = [ - "object 0.32.0", + "object", ] [[package]] @@ -246,16 +237,16 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ - "addr2line 0.20.0", + "addr2line", "cc", "cfg-if", "libc", "miniz_oxide", - "object 0.31.1", + "object", "rustc-demangle", ] @@ -1435,12 +1426,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "gimli" -version = "0.27.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" - [[package]] name = "gimli" version = "0.28.0" @@ -2430,15 +2415,6 @@ dependencies = [ "libc", ] -[[package]] -name = "object" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" -dependencies = [ - "memchr", -] - [[package]] name = "object" version = "0.32.0" @@ -3357,7 +3333,7 @@ dependencies = [ "cstr", "libc", "measureme", - "object 0.32.0", + "object", "rustc-demangle", "rustc_ast", "rustc_attr", @@ -3393,7 +3369,7 @@ dependencies = [ "itertools", "jobserver", "libc", - "object 0.32.0", + "object", "pathdiff", "regex", "rustc_arena", @@ -4327,7 +4303,7 @@ name = "rustc_target" version = "0.0.0" dependencies = [ "bitflags 1.3.2", - "object 0.32.0", + "object", "rustc_abi", "rustc_data_structures", "rustc_feature", @@ -4856,7 +4832,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" name = "std" version = "0.0.0" dependencies = [ - "addr2line 0.21.0", + "addr2line", "alloc", "cfg-if", "compiler_builtins", @@ -4867,7 +4843,7 @@ dependencies = [ "hermit-abi 0.3.2", "libc", "miniz_oxide", - "object 0.32.0", + "object", "panic_abort", "panic_unwind", "profiler_builtins", @@ -5171,9 +5147,9 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4db52ee8fec06e119b692ef3dd2c4cf621a99204c1b8c47407870ed050305b9b" dependencies = [ - "gimli 0.28.0", + "gimli", "hashbrown 0.14.0", - "object 0.32.0", + "object", "tracing", ] diff --git a/library/backtrace b/library/backtrace index e1c49fbd6124..99faef833f89 160000 --- a/library/backtrace +++ b/library/backtrace @@ -1 +1 @@ -Subproject commit e1c49fbd6124a1b626cdf19871aff68c362bdf07 +Subproject commit 99faef833f890fe89f1a959d89b951954118828b From 42f993fd0239acc898d4a37af1beeff51d29940b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 22 Aug 2023 15:24:35 -0700 Subject: [PATCH 136/197] Update the links for Stabilized APIs in 1.72.0 * Use `stable` instead of `nightly` paths. * Fix the anchors for `CStr::to_*` links. --- RELEASES.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 722f7e5dd083..242b1c2eefd2 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -65,16 +65,16 @@ Rustdoc Stabilized APIs --------------- -- [`impl Sync for mpsc::Sender`](https://doc.rust-lang.org/nightly/std/sync/mpsc/struct.Sender.html#impl-Sync-for-Sender%3CT%3E) -- [`impl TryFrom<&OsStr> for &str`](https://doc.rust-lang.org/nightly/std/primitive.str.html#impl-TryFrom%3C%26'a+OsStr%3E-for-%26'a+str) -- [`String::leak`](https://doc.rust-lang.org/nightly/alloc/string/struct.String.html#method.leak) +- [`impl Sync for mpsc::Sender`](https://doc.rust-lang.org/stable/std/sync/mpsc/struct.Sender.html#impl-Sync-for-Sender%3CT%3E) +- [`impl TryFrom<&OsStr> for &str`](https://doc.rust-lang.org/stable/std/primitive.str.html#impl-TryFrom%3C%26'a+OsStr%3E-for-%26'a+str) +- [`String::leak`](https://doc.rust-lang.org/stable/alloc/string/struct.String.html#method.leak) These APIs are now stable in const contexts: -- [`CStr::from_bytes_with_nul`](https://doc.rust-lang.org/nightly/std/ffi/struct.CStr.html#method.from_bytes_with_nul) -- [`CStr::to_bytes`](https://doc.rust-lang.org/nightly/std/ffi/struct.CStr.html#method.from_bytes_with_nul) -- [`CStr::to_bytes_with_nul`](https://doc.rust-lang.org/nightly/std/ffi/struct.CStr.html#method.from_bytes_with_nul) -- [`CStr::to_str`](https://doc.rust-lang.org/nightly/std/ffi/struct.CStr.html#method.from_bytes_with_nul) +- [`CStr::from_bytes_with_nul`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#method.from_bytes_with_nul) +- [`CStr::to_bytes`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#method.to_bytes) +- [`CStr::to_bytes_with_nul`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#method.to_bytes_with_nul) +- [`CStr::to_str`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#method.to_str) From 4dd31a22a47e00eb70341205cb5260e10fabc2d8 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Wed, 23 Aug 2023 01:06:48 +0100 Subject: [PATCH 137/197] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 80eca0e58fb2..2cc50bc0b63a 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 80eca0e58fb2ff52c1e94fc191b55b37ed73e0e4 +Subproject commit 2cc50bc0b63ad20da193e002ba11d391af0104b7 From 91cf04d2072a463759173f0173da2a44faadeb20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 23 Aug 2023 00:58:09 +0000 Subject: [PATCH 138/197] Fix clippy lint for identical `if`/`else` contraining `?` expressions Follow up to #114819. --- .../clippy/clippy_utils/src/hir_utils.rs | 3 ++- .../clippy/tests/ui/if_same_then_else2.rs | 2 +- .../clippy/tests/ui/if_same_then_else2.stderr | 21 ++++++++++++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index fdc35cd4ddf8..98441e83eb4a 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -10,6 +10,7 @@ use rustc_hir::{ GenericArgs, Guard, HirId, HirIdMap, InlineAsmOperand, Let, Lifetime, LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding, }; +use rustc_hir::MatchSource::TryDesugar; use rustc_lexer::{tokenize, TokenKind}; use rustc_lint::LateContext; use rustc_middle::ty::TypeckResults; @@ -311,7 +312,7 @@ impl HirEqInterExpr<'_, '_, '_> { lls == rls && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.ident.name == r.ident.name) }, (&ExprKind::Match(le, la, ref ls), &ExprKind::Match(re, ra, ref rs)) => { - ls == rs + (ls == rs || (matches!((ls, rs), (TryDesugar(_), TryDesugar(_))))) && self.eq_expr(le, re) && over(la, ra, |l, r| { self.eq_pat(l.pat, r.pat) diff --git a/src/tools/clippy/tests/ui/if_same_then_else2.rs b/src/tools/clippy/tests/ui/if_same_then_else2.rs index c545434efe5b..0b171f21d0cc 100644 --- a/src/tools/clippy/tests/ui/if_same_then_else2.rs +++ b/src/tools/clippy/tests/ui/if_same_then_else2.rs @@ -98,7 +98,7 @@ fn if_same_then_else2() -> Result<&'static str, ()> { }; if true { - // FIXME: should emit "this `if` has identical blocks" + //~^ ERROR: this `if` has identical blocks Ok("foo")?; } else { Ok("foo")?; diff --git a/src/tools/clippy/tests/ui/if_same_then_else2.stderr b/src/tools/clippy/tests/ui/if_same_then_else2.stderr index 37fe787d1de3..56e5f3e45b22 100644 --- a/src/tools/clippy/tests/ui/if_same_then_else2.stderr +++ b/src/tools/clippy/tests/ui/if_same_then_else2.stderr @@ -82,6 +82,25 @@ LL | | f32::NAN LL | | }; | |_____^ +error: this `if` has identical blocks + --> $DIR/if_same_then_else2.rs:100:13 + | +LL | if true { + | _____________^ +LL | | +LL | | Ok("foo")?; +LL | | } else { + | |_____^ + | +note: same as this + --> $DIR/if_same_then_else2.rs:103:12 + | +LL | } else { + | ____________^ +LL | | Ok("foo")?; +LL | | } + | |_____^ + error: this `if` has identical blocks --> $DIR/if_same_then_else2.rs:124:20 | @@ -103,5 +122,5 @@ LL | | return Ok(&foo[0..]); LL | | } | |_____^ -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors From 15beac89754f93a218b1075a8a92757b265d7b69 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 22 Aug 2023 17:59:58 -0700 Subject: [PATCH 139/197] Update LLVM submodule to 17.0.0-rc3 --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index 1833c2be108a..50eecd007f6b 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 1833c2be108aefcb5d25f6280cf9763b1feb8005 +Subproject commit 50eecd007f6bf135ad60493bc62102739038d59a From 65217a72b08b21ae252794d0363796092e2219d7 Mon Sep 17 00:00:00 2001 From: Tomoaki Kawada Date: Wed, 23 Aug 2023 11:44:18 +0900 Subject: [PATCH 140/197] kmc-solid: Import `std::sync::PoisonError` in `std::sys::solid::os` --- library/std/src/sys/solid/os.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/solid/os.rs b/library/std/src/sys/solid/os.rs index 9f4e66d628b4..ff81544ba915 100644 --- a/library/std/src/sys/solid/os.rs +++ b/library/std/src/sys/solid/os.rs @@ -8,7 +8,7 @@ use crate::os::{ solid::ffi::{OsStrExt, OsStringExt}, }; use crate::path::{self, PathBuf}; -use crate::sync::RwLock; +use crate::sync::{PoisonError, RwLock}; use crate::sys::common::small_c_string::run_with_cstr; use crate::vec; From aa7730003e01f6c7bd0fa6a7fea4dc9ea6aa63c5 Mon Sep 17 00:00:00 2001 From: Urgau Date: Tue, 22 Aug 2023 17:17:44 +0200 Subject: [PATCH 141/197] Improve note for the invalid_reference_casting lint Add link to the book interior mutability chapter, https://doc.rust-lang.org/book/ch15-05-interior-mutability.html. --- compiler/rustc_lint/messages.ftl | 2 + compiler/rustc_lint/src/lints.rs | 2 + .../const-generics/issues/issue-100313.stderr | 1 + tests/ui/lint/reference_casting.stderr | 57 +++++++++++++++++++ 4 files changed, 62 insertions(+) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index c4a7f717840c..d7cb159149d8 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -323,6 +323,8 @@ lint_invalid_reference_casting_assign_to_ref = assigning to `&T` is undefined be lint_invalid_reference_casting_borrow_as_mut = casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` .label = casting happend here +lint_invalid_reference_casting_note_book = for more information, visit + lint_lintpass_by_hand = implementing `LintPass` by hand .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 25982a458538..993c576d6970 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -764,11 +764,13 @@ pub enum InvalidFromUtf8Diag { #[derive(LintDiagnostic)] pub enum InvalidReferenceCastingDiag { #[diag(lint_invalid_reference_casting_borrow_as_mut)] + #[note(lint_invalid_reference_casting_note_book)] BorrowAsMut { #[label] orig_cast: Option, }, #[diag(lint_invalid_reference_casting_assign_to_ref)] + #[note(lint_invalid_reference_casting_note_book)] AssignToRef { #[label] orig_cast: Option, diff --git a/tests/ui/const-generics/issues/issue-100313.stderr b/tests/ui/const-generics/issues/issue-100313.stderr index 42ad4d61c8e0..796966b22d51 100644 --- a/tests/ui/const-generics/issues/issue-100313.stderr +++ b/tests/ui/const-generics/issues/issue-100313.stderr @@ -4,6 +4,7 @@ error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` LL | *(B as *const bool as *mut bool) = false; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: for more information, visit = note: `#[deny(invalid_reference_casting)]` on by default error[E0080]: evaluation of constant value failed diff --git a/tests/ui/lint/reference_casting.stderr b/tests/ui/lint/reference_casting.stderr index c1589f138351..47b95460ec38 100644 --- a/tests/ui/lint/reference_casting.stderr +++ b/tests/ui/lint/reference_casting.stderr @@ -4,6 +4,7 @@ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is LL | let _num = &mut *(num as *const i32 as *mut i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: for more information, visit = note: `#[deny(invalid_reference_casting)]` on by default error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` @@ -11,54 +12,72 @@ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is | LL | let _num = &mut *(num as *const i32).cast_mut(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` --> $DIR/reference_casting.rs:23:16 | LL | let _num = &mut *std::ptr::from_ref(num).cast_mut(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` --> $DIR/reference_casting.rs:25:16 | LL | let _num = &mut *std::ptr::from_ref({ num }).cast_mut(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` --> $DIR/reference_casting.rs:27:16 | LL | let _num = &mut *{ std::ptr::from_ref(num) }.cast_mut(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` --> $DIR/reference_casting.rs:29:16 | LL | let _num = &mut *(std::ptr::from_ref({ num }) as *mut i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` --> $DIR/reference_casting.rs:31:16 | LL | let _num = &mut *(num as *const i32).cast::().cast_mut(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` --> $DIR/reference_casting.rs:33:16 | LL | let _num = &mut *(num as *const i32).cast::().cast_mut().cast_const().cast_mut(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` --> $DIR/reference_casting.rs:35:16 | LL | let _num = &mut *(std::ptr::from_ref(static_u8()) as *mut i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` --> $DIR/reference_casting.rs:37:16 | LL | let _num = &mut *std::mem::transmute::<_, *mut i32>(num); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` --> $DIR/reference_casting.rs:41:16 @@ -67,6 +86,8 @@ LL | let deferred = num as *const i32 as *mut i32; | ----------------------------- casting happend here LL | let _num = &mut *deferred; | ^^^^^^^^^^^^^^ + | + = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` --> $DIR/reference_casting.rs:44:16 @@ -75,60 +96,80 @@ LL | let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).ca | ---------------------------------------------------------------------------- casting happend here LL | let _num = &mut *deferred; | ^^^^^^^^^^^^^^ + | + = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` --> $DIR/reference_casting.rs:46:16 | LL | let _num = &mut *(num as *const _ as usize as *mut i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` --> $DIR/reference_casting.rs:50:9 | LL | &mut *((this as *const _) as *mut _) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:60:5 | LL | *(a as *const _ as *mut _) = String::from("Replaced"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:62:5 | LL | *(a as *const _ as *mut String) += " world"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:64:5 | LL | *std::ptr::from_ref(num).cast_mut() += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:66:5 | LL | *std::ptr::from_ref({ num }).cast_mut() += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:68:5 | LL | *{ std::ptr::from_ref(num) }.cast_mut() += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:70:5 | LL | *(std::ptr::from_ref({ num }) as *mut i32) += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:72:5 | LL | *std::mem::transmute::<_, *mut i32>(num) += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:74:5 @@ -139,6 +180,8 @@ LL | | std::mem::transmute::<*const i32, *mut i32>(num), LL | | -1i32, LL | | ); | |_____^ + | + = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:81:5 @@ -147,18 +190,24 @@ LL | let value = num as *const i32 as *mut i32; | ----------------------------- casting happend here LL | *value = 1; | ^^^^^^^^^^ + | + = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:83:5 | LL | *(num as *const i32).cast::().cast_mut() = 2; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:85:5 | LL | *(num as *const _ as usize as *mut i32) = 2; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:87:5 @@ -168,6 +217,8 @@ LL | let value = num as *const i32 as *mut i32; ... LL | std::ptr::write(value, 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:89:5 @@ -177,6 +228,8 @@ LL | let value = num as *const i32 as *mut i32; ... LL | std::ptr::write_unaligned(value, 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:91:5 @@ -186,12 +239,16 @@ LL | let value = num as *const i32 as *mut i32; ... LL | std::ptr::write_volatile(value, 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:95:9 | LL | *(this as *const _ as *mut _) = a; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit error: aborting due to 29 previous errors From 03fd2d4379cc0f5d6a04dd1708c75d2f828f598e Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Wed, 23 Aug 2023 21:57:18 +0900 Subject: [PATCH 142/197] Allow MaybeUninit in input and output of inline assembly --- .../src/check/intrinsicck.rs | 53 ++++++++++++------- tests/codegen/asm-maybe-uninit.rs | 27 ++++++++++ 2 files changed, 61 insertions(+), 19 deletions(-) create mode 100644 tests/codegen/asm-maybe-uninit.rs diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index 945953edd5ae..cd7e99172045 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -44,20 +44,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { false } - fn check_asm_operand_type( - &self, - idx: usize, - reg: InlineAsmRegOrRegClass, - expr: &'tcx hir::Expr<'tcx>, - template: &[InlineAsmTemplatePiece], - is_input: bool, - tied_input: Option<(&'tcx hir::Expr<'tcx>, Option)>, - target_features: &FxIndexSet, - ) -> Option { - let ty = (self.get_operand_ty)(expr); - if ty.has_non_region_infer() { - bug!("inference variable in asm operand ty: {:?} {:?}", expr, ty); - } + fn get_asm_ty(&self, ty: Ty<'tcx>) -> Option { let asm_ty_isize = match self.tcx.sess.target.pointer_width { 16 => InlineAsmType::I16, 32 => InlineAsmType::I32, @@ -65,10 +52,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { _ => unreachable!(), }; - let asm_ty = match *ty.kind() { - // `!` is allowed for input but not for output (issue #87802) - ty::Never if is_input => return None, - _ if ty.references_error() => return None, + match *ty.kind() { ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Some(InlineAsmType::I8), ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Some(InlineAsmType::I16), ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Some(InlineAsmType::I32), @@ -99,7 +83,6 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { }; match ty.kind() { - ty::Never | ty::Error(_) => return None, ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Some(InlineAsmType::VecI8(size)), ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => { Some(InlineAsmType::VecI16(size)) @@ -128,6 +111,38 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { } ty::Infer(_) => unreachable!(), _ => None, + } + } + + fn check_asm_operand_type( + &self, + idx: usize, + reg: InlineAsmRegOrRegClass, + expr: &'tcx hir::Expr<'tcx>, + template: &[InlineAsmTemplatePiece], + is_input: bool, + tied_input: Option<(&'tcx hir::Expr<'tcx>, Option)>, + target_features: &FxIndexSet, + ) -> Option { + let ty = (self.get_operand_ty)(expr); + if ty.has_non_region_infer() { + bug!("inference variable in asm operand ty: {:?} {:?}", expr, ty); + } + + let asm_ty = match *ty.kind() { + // `!` is allowed for input but not for output (issue #87802) + ty::Never if is_input => return None, + _ if ty.references_error() => return None, + ty::Adt(adt, args) if Some(adt.did()) == self.tcx.lang_items().maybe_uninit() => { + let fields = &adt.non_enum_variant().fields; + let ty = fields[FieldIdx::from_u32(1)].ty(self.tcx, args); + let ty::Adt(ty, args) = ty.kind() else { unreachable!() }; + assert!(ty.is_manually_drop()); + let fields = &ty.non_enum_variant().fields; + let ty = fields[FieldIdx::from_u32(0)].ty(self.tcx, args); + self.get_asm_ty(ty) + } + _ => self.get_asm_ty(ty), }; let Some(asm_ty) = asm_ty else { let msg = format!("cannot use value of type `{ty}` for inline assembly"); diff --git a/tests/codegen/asm-maybe-uninit.rs b/tests/codegen/asm-maybe-uninit.rs new file mode 100644 index 000000000000..d7e4a9489546 --- /dev/null +++ b/tests/codegen/asm-maybe-uninit.rs @@ -0,0 +1,27 @@ +// compile-flags: -O +// only-x86_64 + +#![crate_type = "rlib"] +#![allow(asm_sub_register)] + +use std::mem::MaybeUninit; +use std::arch::asm; + +// CHECK-LABEL: @int +#[no_mangle] +pub unsafe fn int(x: MaybeUninit) -> MaybeUninit { + let y: MaybeUninit; + asm!("/*{}{}*/", in(reg) x, out(reg) y); + y +} + +// CHECK-LABEL: @inout +#[no_mangle] +pub unsafe fn inout(mut x: i32) -> MaybeUninit { + let mut y: MaybeUninit; + asm!("/*{}*/", inout(reg) x => y); + asm!("/*{}*/", inout(reg) y => x); + asm!("/*{}*/", inlateout(reg) x => y); + asm!("/*{}*/", inlateout(reg) y => x); + y +} From 735e9c0c510927c309005dfa5db32bb13a573bae Mon Sep 17 00:00:00 2001 From: Eric Mark Martin Date: Tue, 22 Aug 2023 00:15:38 -0400 Subject: [PATCH 143/197] stable types for predicates --- compiler/rustc_smir/src/rustc_smir/mod.rs | 202 ++++++++++++++++++++-- compiler/rustc_smir/src/stable_mir/ty.rs | 78 +++++++++ 2 files changed, 269 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index aea59c31379e..1f3e7cb97d16 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -200,7 +200,7 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> { stable_mir::mir::Rvalue::Repeat(op.stable(tables), len) } Ref(region, kind, place) => stable_mir::mir::Rvalue::Ref( - opaque(region), + region.stable(tables), kind.stable(tables), place.stable(tables), ), @@ -842,12 +842,9 @@ impl<'tcx> Stable<'tcx> for ty::GenericArgKind<'tcx> { fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { use stable_mir::ty::GenericArgKind; match self { - ty::GenericArgKind::Lifetime(region) => GenericArgKind::Lifetime(opaque(region)), + ty::GenericArgKind::Lifetime(region) => GenericArgKind::Lifetime(region.stable(tables)), ty::GenericArgKind::Type(ty) => GenericArgKind::Type(tables.intern_ty(*ty)), - ty::GenericArgKind::Const(cnst) => { - let cnst = ConstantKind::from_const(*cnst, tables.tcx); - GenericArgKind::Const(stable_mir::ty::Const { literal: cnst.stable(tables) }) - } + ty::GenericArgKind::Const(cnst) => GenericArgKind::Const(cnst.stable(tables)), } } } @@ -1053,16 +1050,14 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> { } ty::Str => TyKind::RigidTy(RigidTy::Str), ty::Array(ty, constant) => { - let cnst = ConstantKind::from_const(*constant, tables.tcx); - let cnst = stable_mir::ty::Const { literal: cnst.stable(tables) }; - TyKind::RigidTy(RigidTy::Array(tables.intern_ty(*ty), cnst)) + TyKind::RigidTy(RigidTy::Array(tables.intern_ty(*ty), constant.stable(tables))) } ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(tables.intern_ty(*ty))), ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => { TyKind::RigidTy(RigidTy::RawPtr(tables.intern_ty(*ty), mutbl.stable(tables))) } ty::Ref(region, ty, mutbl) => TyKind::RigidTy(RigidTy::Ref( - opaque(region), + region.stable(tables), tables.intern_ty(*ty), mutbl.stable(tables), )), @@ -1077,7 +1072,7 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> { .iter() .map(|existential_predicate| existential_predicate.stable(tables)) .collect(), - opaque(region), + region.stable(tables), dyn_kind.stable(tables), )) } @@ -1112,6 +1107,15 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> { } } +impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { + type T = stable_mir::ty::Const; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + let cnst = ConstantKind::from_const(*self, tables.tcx); + stable_mir::ty::Const { literal: cnst.stable(tables) } + } +} + impl<'tcx> Stable<'tcx> for ty::ParamTy { type T = stable_mir::ty::ParamTy; fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { @@ -1276,3 +1280,179 @@ impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDef { } } } + +impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> { + type T = stable_mir::ty::PredicateKind; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + use ty::PredicateKind; + match self { + PredicateKind::Clause(clause_kind) => { + stable_mir::ty::PredicateKind::Clause(clause_kind.stable(tables)) + } + PredicateKind::ObjectSafe(did) => { + stable_mir::ty::PredicateKind::ObjectSafe(tables.trait_def(*did)) + } + PredicateKind::ClosureKind(did, generic_args, closure_kind) => { + stable_mir::ty::PredicateKind::ClosureKind( + tables.closure_def(*did), + generic_args.stable(tables), + closure_kind.stable(tables), + ) + } + PredicateKind::Subtype(subtype_predicate) => { + stable_mir::ty::PredicateKind::SubType(subtype_predicate.stable(tables)) + } + PredicateKind::Coerce(coerce_predicate) => { + stable_mir::ty::PredicateKind::Coerce(coerce_predicate.stable(tables)) + } + PredicateKind::ConstEquate(a, b) => { + stable_mir::ty::PredicateKind::ConstEquate(a.stable(tables), b.stable(tables)) + } + PredicateKind::Ambiguous => stable_mir::ty::PredicateKind::Ambiguous, + PredicateKind::AliasRelate(a, b, alias_relation_direction) => { + stable_mir::ty::PredicateKind::AliasRelate( + a.unpack().stable(tables), + b.unpack().stable(tables), + alias_relation_direction.stable(tables), + ) + } + } + } +} + +impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> { + type T = stable_mir::ty::ClauseKind; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + use ty::ClauseKind::*; + match *self { + Trait(trait_object) => stable_mir::ty::ClauseKind::Trait(trait_object.stable(tables)), + RegionOutlives(region_outlives) => { + stable_mir::ty::ClauseKind::RegionOutlives(region_outlives.stable(tables)) + } + TypeOutlives(type_outlives) => { + let ty::OutlivesPredicate::<_, _>(a, b) = type_outlives; + stable_mir::ty::ClauseKind::TypeOutlives(stable_mir::ty::OutlivesPredicate( + tables.intern_ty(a), + b.stable(tables), + )) + } + Projection(projection_predicate) => { + stable_mir::ty::ClauseKind::Projection(projection_predicate.stable(tables)) + } + ConstArgHasType(const_, ty) => stable_mir::ty::ClauseKind::ConstArgHasType( + const_.stable(tables), + tables.intern_ty(ty), + ), + WellFormed(generic_arg) => { + stable_mir::ty::ClauseKind::WellFormed(generic_arg.unpack().stable(tables)) + } + ConstEvaluatable(const_) => { + stable_mir::ty::ClauseKind::ConstEvaluatable(const_.stable(tables)) + } + } + } +} + +impl<'tcx> Stable<'tcx> for ty::ClosureKind { + type T = stable_mir::ty::ClosureKind; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + use ty::ClosureKind::*; + match self { + Fn => stable_mir::ty::ClosureKind::Fn, + FnMut => stable_mir::ty::ClosureKind::FnMut, + FnOnce => stable_mir::ty::ClosureKind::FnOnce, + } + } +} + +impl<'tcx> Stable<'tcx> for ty::SubtypePredicate<'tcx> { + type T = stable_mir::ty::SubtypePredicate; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + let ty::SubtypePredicate { a, b, a_is_expected: _ } = self; + stable_mir::ty::SubtypePredicate { a: tables.intern_ty(*a), b: tables.intern_ty(*b) } + } +} + +impl<'tcx> Stable<'tcx> for ty::CoercePredicate<'tcx> { + type T = stable_mir::ty::CoercePredicate; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + let ty::CoercePredicate { a, b } = self; + stable_mir::ty::CoercePredicate { a: tables.intern_ty(*a), b: tables.intern_ty(*b) } + } +} + +impl<'tcx> Stable<'tcx> for ty::AliasRelationDirection { + type T = stable_mir::ty::AliasRelationDirection; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + use ty::AliasRelationDirection::*; + match self { + Equate => stable_mir::ty::AliasRelationDirection::Equate, + Subtype => stable_mir::ty::AliasRelationDirection::Subtype, + } + } +} + +impl<'tcx> Stable<'tcx> for ty::TraitPredicate<'tcx> { + type T = stable_mir::ty::TraitPredicate; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + let ty::TraitPredicate { trait_ref, polarity } = self; + stable_mir::ty::TraitPredicate { + trait_ref: trait_ref.stable(tables), + polarity: polarity.stable(tables), + } + } +} + +impl<'tcx, A, B, U, V> Stable<'tcx> for ty::OutlivesPredicate +where + A: Stable<'tcx, T = U>, + B: Stable<'tcx, T = V>, +{ + type T = stable_mir::ty::OutlivesPredicate; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + let ty::OutlivesPredicate(a, b) = self; + stable_mir::ty::OutlivesPredicate(a.stable(tables), b.stable(tables)) + } +} + +impl<'tcx> Stable<'tcx> for ty::ProjectionPredicate<'tcx> { + type T = stable_mir::ty::ProjectionPredicate; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + let ty::ProjectionPredicate { projection_ty, term } = self; + stable_mir::ty::ProjectionPredicate { + projection_ty: projection_ty.stable(tables), + term: term.unpack().stable(tables), + } + } +} + +impl<'tcx> Stable<'tcx> for ty::ImplPolarity { + type T = stable_mir::ty::ImplPolarity; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + use ty::ImplPolarity::*; + match self { + Positive => stable_mir::ty::ImplPolarity::Positive, + Negative => stable_mir::ty::ImplPolarity::Negative, + Reservation => stable_mir::ty::ImplPolarity::Reservation, + } + } +} + +impl<'tcx> Stable<'tcx> for ty::Region<'tcx> { + type T = stable_mir::ty::Region; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + // FIXME: add a real implementation of stable regions + opaque(self) + } +} diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index fe7fef5d0c17..79389f92a507 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -497,3 +497,81 @@ pub struct GenericParamDef { pub pure_wrt_drop: bool, pub kind: GenericParamDefKind, } + +pub struct GenericPredicates { + pub parent: Option, + pub predicates: Vec, +} + +#[derive(Clone, Debug)] +pub enum PredicateKind { + Clause(ClauseKind), + ObjectSafe(TraitDef), + ClosureKind(ClosureDef, GenericArgs, ClosureKind), + SubType(SubtypePredicate), + Coerce(CoercePredicate), + ConstEquate(Const, Const), + Ambiguous, + AliasRelate(TermKind, TermKind, AliasRelationDirection), +} + +#[derive(Clone, Debug)] +pub enum ClauseKind { + Trait(TraitPredicate), + RegionOutlives(RegionOutlivesPredicate), + TypeOutlives(TypeOutlivesPredicate), + Projection(ProjectionPredicate), + ConstArgHasType(Const, Ty), + WellFormed(GenericArgKind), + ConstEvaluatable(Const), +} + +#[derive(Clone, Debug)] +pub enum ClosureKind { + Fn, + FnMut, + FnOnce, +} + +#[derive(Clone, Debug)] +pub struct SubtypePredicate { + pub a: Ty, + pub b: Ty, +} + +#[derive(Clone, Debug)] +pub struct CoercePredicate { + pub a: Ty, + pub b: Ty, +} + +#[derive(Clone, Debug)] +pub enum AliasRelationDirection { + Equate, + Subtype, +} + +#[derive(Clone, Debug)] +pub struct TraitPredicate { + pub trait_ref: TraitRef, + pub polarity: ImplPolarity, +} + +#[derive(Clone, Debug)] +pub struct OutlivesPredicate(pub A, pub B); + +pub type RegionOutlivesPredicate = OutlivesPredicate; +pub type TypeOutlivesPredicate = OutlivesPredicate; + +#[derive(Clone, Debug)] +pub struct ProjectionPredicate { + pub projection_ty: AliasTy, + pub term: TermKind, +} + +#[derive(Clone, Debug)] +pub enum ImplPolarity { + Positive, + Negative, + Reservation, +} From 7ab27c5ed5a3ed71056091f914ff84f98be1d753 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 23 Aug 2023 15:53:48 +0200 Subject: [PATCH 144/197] Add unstable `--no-html-source` rustdoc flag --- src/librustdoc/config.rs | 4 ++++ src/librustdoc/html/render/context.rs | 3 ++- src/librustdoc/lib.rs | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 81fb13f4166b..1ce7efdfc20e 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -273,6 +273,8 @@ pub(crate) struct RenderOptions { pub(crate) call_locations: AllCallLocations, /// If `true`, Context::init will not emit shared files. pub(crate) no_emit_shared: bool, + /// If `true`, HTML source code pages won't be generated. + pub(crate) html_no_source: bool, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -686,6 +688,7 @@ impl Options { let generate_link_to_definition = matches.opt_present("generate-link-to-definition"); let extern_html_root_takes_precedence = matches.opt_present("extern-html-root-takes-precedence"); + let html_no_source = matches.opt_present("html-no-source"); if generate_link_to_definition && (show_coverage || output_format != OutputFormat::Html) { diag.struct_err( @@ -769,6 +772,7 @@ impl Options { generate_link_to_definition, call_locations, no_emit_shared: false, + html_no_source, }; Ok((options, render_options)) } diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index d7ff248a9bff..bb1c186668cd 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -463,6 +463,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { generate_link_to_definition, call_locations, no_emit_shared, + html_no_source, .. } = options; @@ -488,7 +489,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { scrape_examples_extension: !call_locations.is_empty(), }; let mut issue_tracker_base_url = None; - let mut include_sources = true; + let mut include_sources = !html_no_source; // Crawl the crate attributes looking for attributes which control how we're // going to emit HTML diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 8220df5d4f37..92e06f3ab0fd 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -656,6 +656,9 @@ fn opts() -> Vec { "[rust]", ) }), + unstable("html-no-source", |o| { + o.optflag("", "html-no-source", "Disable HTML source code pages generation") + }), ] } From d3f35e96c17de681f091b980eabff49bbd8652dd Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 23 Aug 2023 15:54:04 +0200 Subject: [PATCH 145/197] Add test for `--no-html-source` flag --- tests/rustdoc/html-no-source.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 tests/rustdoc/html-no-source.rs diff --git a/tests/rustdoc/html-no-source.rs b/tests/rustdoc/html-no-source.rs new file mode 100644 index 000000000000..25615a73c3f4 --- /dev/null +++ b/tests/rustdoc/html-no-source.rs @@ -0,0 +1,30 @@ +// compile-flags: -Zunstable-options --html-no-source + +// This test ensures that the `--html-no-source` flag disables +// the creation of the `src` folder. + +#![feature(staged_api)] +#![stable(feature = "bar", since = "1.0")] +#![crate_name = "foo"] + +// Ensures that there is no items in the corresponding "src" folder. +// @files 'src/foo' '[]' + +// @has foo/fn.foo.html +// @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · ' +// @!has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · source · ' +#[stable(feature = "bar", since = "1.0")] +pub fn foo() {} + +// @has foo/struct.Bar.html +// @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · ' +// @!has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · source · ' +#[stable(feature = "bar", since = "1.0")] +pub struct Bar; + +impl Bar { + // @has - '//*[@id="method.bar"]/*[@class="since rightside"]' '2.0' + // @!has - '//*[@id="method.bar"]/*[@class="rightside"]' '2.0 ·' + #[stable(feature = "foobar", since = "2.0")] + pub fn bar() {} +} From 73ccfc56832b1948f2656c867744be6438d5ac4b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 23 Aug 2023 16:33:07 +0200 Subject: [PATCH 146/197] Update run-make/issue-88756-default-output test --- tests/run-make/issue-88756-default-output/output-default.stdout | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/run-make/issue-88756-default-output/output-default.stdout b/tests/run-make/issue-88756-default-output/output-default.stdout index b280698230dd..de8ff0e5f89f 100644 --- a/tests/run-make/issue-88756-default-output/output-default.stdout +++ b/tests/run-make/issue-88756-default-output/output-default.stdout @@ -191,6 +191,8 @@ Options: removed, see issue #44136 for more information + --html-no-source + Disable HTML source code pages generation @path Read newline separated options from `path` From 107cb5c9045f8fadab431e42c8ba2335004efe47 Mon Sep 17 00:00:00 2001 From: Eric Mark Martin Date: Tue, 22 Aug 2023 01:09:10 -0400 Subject: [PATCH 147/197] predicates of --- compiler/rustc_smir/src/rustc_smir/mod.rs | 38 +++++++++++++++++------ compiler/rustc_smir/src/stable_mir/mod.rs | 15 ++++++++- compiler/rustc_smir/src/stable_mir/ty.rs | 2 +- 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 1f3e7cb97d16..392dbafcb3eb 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -108,6 +108,23 @@ impl<'tcx> Context for Tables<'tcx> { let generic_def = self.tcx.generics_of(def_id); generic_def.stable(self) } + + fn predicates_of( + &mut self, + trait_def: &stable_mir::ty::TraitDef, + ) -> stable_mir::GenericPredicates { + let trait_def_id = self.trait_def_id(trait_def); + let ty::GenericPredicates { parent, predicates } = self.tcx.predicates_of(trait_def_id); + stable_mir::GenericPredicates { + parent: parent.map(|did| self.trait_def(did)), + predicates: predicates + .iter() + .map(|(clause, span)| { + (clause.as_predicate().kind().skip_binder().stable(self), span.stable(self)) + }) + .collect(), + } + } } pub struct Tables<'tcx> { @@ -947,12 +964,12 @@ impl<'tcx> Stable<'tcx> for ty::BoundTyKind { impl<'tcx> Stable<'tcx> for ty::BoundRegionKind { type T = stable_mir::ty::BoundRegionKind; - fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { use stable_mir::ty::BoundRegionKind; match self { ty::BoundRegionKind::BrAnon(option_span) => { - BoundRegionKind::BrAnon(option_span.map(|span| opaque(&span))) + BoundRegionKind::BrAnon(option_span.map(|span| span.stable(tables))) } ty::BoundRegionKind::BrNamed(def_id, symbol) => { BoundRegionKind::BrNamed(rustc_internal::br_named_def(*def_id), symbol.to_string()) @@ -1242,14 +1259,6 @@ impl<'tcx> Stable<'tcx> for ty::Generics { } } -impl<'tcx> Stable<'tcx> for rustc_span::Span { - type T = stable_mir::ty::Span; - - fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { - opaque(self) - } -} - impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind { type T = stable_mir::ty::GenericParamDefKind; @@ -1456,3 +1465,12 @@ impl<'tcx> Stable<'tcx> for ty::Region<'tcx> { opaque(self) } } + +impl<'tcx> Stable<'tcx> for rustc_span::Span { + type T = stable_mir::ty::Span; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + // FIXME: add a real implementation of stable spans + opaque(self) + } +} diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs index 8e38e394b982..360f2195c1c3 100644 --- a/compiler/rustc_smir/src/stable_mir/mod.rs +++ b/compiler/rustc_smir/src/stable_mir/mod.rs @@ -15,7 +15,9 @@ use std::cell::Cell; use crate::rustc_smir::Tables; -use self::ty::{GenericDef, Generics, ImplDef, ImplTrait, TraitDecl, TraitDef, Ty, TyKind}; +use self::ty::{ + GenericDef, Generics, ImplDef, ImplTrait, PredicateKind, Span, TraitDecl, TraitDef, Ty, TyKind, +}; pub mod mir; pub mod ty; @@ -38,6 +40,12 @@ pub type TraitDecls = Vec; /// A list of impl trait decls. pub type ImplTraitDecls = Vec; +/// A list of predicates. +pub struct GenericPredicates { + pub parent: Option, + pub predicates: Vec<(PredicateKind, Span)>, +} + /// Holds information about a crate. #[derive(Clone, PartialEq, Eq, Debug)] pub struct Crate { @@ -101,6 +109,10 @@ pub fn trait_impl(trait_impl: &ImplDef) -> ImplTrait { with(|cx| cx.trait_impl(trait_impl)) } +pub fn predicates_of(trait_def: &TraitDef) -> GenericPredicates { + with(|cx| cx.predicates_of(trait_def)) +} + pub trait Context { fn entry_fn(&mut self) -> Option; /// Retrieve all items of the local crate that have a MIR associated with them. @@ -111,6 +123,7 @@ pub trait Context { fn all_trait_impls(&mut self) -> ImplTraitDecls; fn trait_impl(&mut self, trait_impl: &ImplDef) -> ImplTrait; fn generics_of(&mut self, generic_def: &GenericDef) -> Generics; + fn predicates_of(&mut self, trait_def: &TraitDef) -> GenericPredicates; /// Get information about the local crate. fn local_crate(&self) -> Crate; /// Retrieve a list of all external crates. diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 79389f92a507..5929823b1bbc 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -22,7 +22,7 @@ pub struct Const { type Ident = Opaque; pub(crate) type Region = Opaque; -pub type Span = Opaque; +pub(crate) type Span = Opaque; #[derive(Clone, Debug)] pub enum TyKind { From 9cabc91a5fa20d4656674b2fad59dc3880f90103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 31 Jul 2023 17:39:51 +0200 Subject: [PATCH 148/197] Use LLVM 17 as the host compiler --- src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh index 9b274cc277e7..02b023fe75bf 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh @@ -4,7 +4,7 @@ set -ex source shared.sh -LLVM=llvmorg-16.0.0 +LLVM=llvmorg-17.0.0-rc3 mkdir llvm-project cd llvm-project From 1c5f1762b71c46d537c9cbfd3cc60f82b9175793 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 23 Aug 2023 16:00:42 +0000 Subject: [PATCH 149/197] Do not convert copies of packed projections to moves. --- .../src/dead_store_elimination.rs | 4 +++ ...cked.DeadStoreElimination.panic-abort.diff | 15 +++++++++++ ...ked.DeadStoreElimination.panic-unwind.diff | 15 +++++++++++ .../dead-store-elimination/call_arg_copy.rs | 26 +++++++++++++++++++ 4 files changed, 60 insertions(+) create mode 100644 tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-abort.diff create mode 100644 tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-unwind.diff diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 3f988930b5e6..47c1c465e563 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -12,6 +12,7 @@ //! will still not cause any further changes. //! +use crate::util::is_disaligned; use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; @@ -31,6 +32,8 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS .iterate_to_fixpoint() .into_results_cursor(body); + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + // For blocks with a call terminator, if an argument copy can be turned into a move, // record it as (block, argument index). let mut call_operands_to_move = Vec::new(); @@ -49,6 +52,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS && !place.is_indirect() && !borrowed.contains(place.local) && !state.contains(place.local) + && !is_disaligned(tcx, body, param_env, place) { call_operands_to_move.push((bb, index)); } diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-abort.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-abort.diff new file mode 100644 index 000000000000..dc0f9073416f --- /dev/null +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-abort.diff @@ -0,0 +1,15 @@ +- // MIR for `move_packed` before DeadStoreElimination ++ // MIR for `move_packed` after DeadStoreElimination + + fn move_packed(_1: Packed) -> () { + let mut _0: (); + + bb0: { + _0 = use_both(const 0_i32, (_1.1: i32)) -> [return: bb1, unwind unreachable]; + } + + bb1: { + return; + } + } + diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-unwind.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-unwind.diff new file mode 100644 index 000000000000..86ef026ec5c8 --- /dev/null +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-unwind.diff @@ -0,0 +1,15 @@ +- // MIR for `move_packed` before DeadStoreElimination ++ // MIR for `move_packed` after DeadStoreElimination + + fn move_packed(_1: Packed) -> () { + let mut _0: (); + + bb0: { + _0 = use_both(const 0_i32, (_1.1: i32)) -> [return: bb1, unwind continue]; + } + + bb1: { + return; + } + } + diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs index 41f91fc13061..f09cdee14822 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs @@ -2,6 +2,12 @@ // unit-test: DeadStoreElimination // compile-flags: -Zmir-enable-passes=+CopyProp +#![feature(core_intrinsics)] +#![feature(custom_mir)] +#![allow(internal_features)] + +use std::intrinsics::mir::*; + #[inline(never)] fn use_both(_: i32, _: i32) {} @@ -10,6 +16,26 @@ fn move_simple(x: i32) { use_both(x, x); } +#[repr(packed)] +struct Packed { + x: u8, + y: i32, +} + +// EMIT_MIR call_arg_copy.move_packed.DeadStoreElimination.diff +#[custom_mir(dialect = "analysis")] +fn move_packed(packed: Packed) { + mir!( + { + Call(RET = use_both(0, packed.y), ret) + } + ret = { + Return() + } + ) +} + fn main() { move_simple(1); + move_packed(Packed { x: 0, y: 1 }); } From 6101ddd793daf8bea541073c2d9462e252e81cec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 23 Aug 2023 19:50:24 +0200 Subject: [PATCH 150/197] Check that the old values match --- compiler/rustc_span/src/hygiene.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 6f0e544a5974..23c858498a13 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1279,9 +1279,9 @@ pub fn register_expn_id( let _old_data = hygiene_data.foreign_expn_data.insert(expn_id, data); debug_assert!(_old_data.is_none() || cfg!(parallel_compiler)); let _old_hash = hygiene_data.foreign_expn_hashes.insert(expn_id, hash); - debug_assert!(_old_hash.is_none() || cfg!(parallel_compiler)); + debug_assert!(_old_hash.is_none() || _old_hash == Some(hash)); let _old_id = hygiene_data.expn_hash_to_expn_id.insert(hash, expn_id); - debug_assert!(_old_id.is_none() || cfg!(parallel_compiler)); + debug_assert!(_old_id.is_none() || _old_id == Some(expn_id)); }); expn_id } From f3d81917fc546420cb9deadc22cbab30133abd79 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 5 Jan 2023 13:55:24 -0800 Subject: [PATCH 151/197] Default relax_elf_relocations to true This option tells LLVM to emit relaxable relocation types R_X86_64_GOTPCRELX/R_X86_64_REX_GOTPCRELX/R_386_GOT32X in applicable cases. True matches Clang's CMake default since 2020-08 [1] and latest LLVM default[2]. This also works around a GNU ld<2.41 issue[3] when using general-dynamic/local-dynamic TLS models in `-Z plt=no` mode with latest LLVM. [1]: https://github.com/llvm/llvm-project/commit/c41a18cf61790fc898dcda1055c3efbf442c14c0 [2]: https://github.com/llvm/llvm-project/commit/2aedfdd9b82e6c72a28576d0e8ea854f1300ff4e [3]: https://sourceware.org/bugzilla/show_bug.cgi?id=24784 --- compiler/rustc_interface/src/tests.rs | 2 +- compiler/rustc_target/src/spec/mod.rs | 2 +- compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index e3d66d18388c..db669ca7250e 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -821,7 +821,7 @@ fn test_unstable_options_tracking_hash() { tracked!(profile_emit, Some(PathBuf::from("abc"))); tracked!(profile_sample_use, Some(PathBuf::from("abc"))); tracked!(profiler_runtime, "abc".to_string()); - tracked!(relax_elf_relocations, Some(true)); + tracked!(relax_elf_relocations, Some(false)); tracked!(relro_level, Some(RelroLevel::Full)); tracked!(remap_cwd_prefix, Some(PathBuf::from("abc"))); tracked!(report_delayed_bugs, true); diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 31b6961bb622..f8d40c4142d4 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2216,7 +2216,7 @@ impl Default for TargetOptions { mcount: "mcount".into(), llvm_mcount_intrinsic: None, llvm_abiname: "".into(), - relax_elf_relocations: false, + relax_elf_relocations: true, llvm_args: cvs![], use_ctors_section: false, eh_frame_header: true, diff --git a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs b/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs index a7ed74f47212..dc1e5967859c 100644 --- a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs +++ b/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs @@ -69,7 +69,6 @@ pub fn target() -> Target { position_independent_executables: true, pre_link_args, override_export_symbols: Some(EXPORT_SYMBOLS.iter().cloned().map(Cow::from).collect()), - relax_elf_relocations: true, ..Default::default() }; Target { From 246a6a6589b118c0a08e449f981bb4ae07bc089a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 23 Aug 2023 20:16:22 +0200 Subject: [PATCH 152/197] Extend comment on assertion --- compiler/rustc_span/src/hygiene.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 37ec2f0801c8..ab57d5c6803f 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1410,8 +1410,12 @@ pub fn decode_syntax_context SyntaxContext &mut hygiene_data.syntax_context_data[ctxt.as_u32() as usize], ctxt_data, ); - // Make sure nothing weird happening while `decode_data` was running if cfg!(not(parallel_compiler)) { + // Make sure nothing weird happened while `decode_data` was running. + // We used `kw::Empty` for the dummy value and we expect nothing to be + // modifying the dummy entry. + // This does not hold for the parallel compiler as another thread may + // have inserted the fully decoded data. assert_eq!(dummy.dollar_crate_name, kw::Empty); } }); From d4ab99d946590e5d62a0aafc0e8fd1d4605e4bc6 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 23 Aug 2023 11:47:35 -0700 Subject: [PATCH 153/197] rustdoc: Rename typedef to type alias in jsondoclint --- src/tools/jsondoclint/src/item_kind.rs | 12 ++++++------ src/tools/jsondoclint/src/validator.rs | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/tools/jsondoclint/src/item_kind.rs b/src/tools/jsondoclint/src/item_kind.rs index d48e6533a206..9bd04e11cb39 100644 --- a/src/tools/jsondoclint/src/item_kind.rs +++ b/src/tools/jsondoclint/src/item_kind.rs @@ -12,7 +12,7 @@ pub(crate) enum Kind { Enum, Variant, Function, - Typedef, + TypeAlias, OpaqueTy, Constant, Trait, @@ -45,7 +45,7 @@ impl Kind { Trait => true, TraitAlias => true, Impl => true, - Typedef => true, + TypeAlias => true, Constant => true, Static => true, Macro => true, @@ -98,7 +98,7 @@ impl Kind { Kind::Union => false, Kind::Enum => false, Kind::Variant => false, - Kind::Typedef => false, + Kind::TypeAlias => false, Kind::OpaqueTy => false, Kind::Constant => false, Kind::Trait => false, @@ -131,7 +131,7 @@ impl Kind { matches!(self, Kind::Trait | Kind::TraitAlias) } pub fn is_type(self) -> bool { - matches!(self, Kind::Struct | Kind::Enum | Kind::Union | Kind::Typedef) + matches!(self, Kind::Struct | Kind::Enum | Kind::Union | Kind::TypeAlias) } pub fn from_item(i: &Item) -> Self { @@ -148,7 +148,7 @@ impl Kind { ItemEnum::Trait(_) => Trait, ItemEnum::TraitAlias(_) => TraitAlias, ItemEnum::Impl(_) => Impl, - ItemEnum::TypeAlias(_) => Typedef, + ItemEnum::TypeAlias(_) => TypeAlias, ItemEnum::OpaqueTy(_) => OpaqueTy, ItemEnum::Constant(_) => Constant, ItemEnum::Static(_) => Static, @@ -186,7 +186,7 @@ impl Kind { ItemKind::StructField => StructField, ItemKind::Trait => Trait, ItemKind::TraitAlias => TraitAlias, - ItemKind::TypeAlias => Typedef, + ItemKind::TypeAlias => TypeAlias, ItemKind::Union => Union, ItemKind::Variant => Variant, } diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs index 79b1551f3011..592e97310a4f 100644 --- a/src/tools/jsondoclint/src/validator.rs +++ b/src/tools/jsondoclint/src/validator.rs @@ -37,7 +37,7 @@ pub struct Validator<'a> { enum PathKind { Trait, - /// Structs, Enums, Unions and Typedefs. + /// Structs, Enums, Unions and TypeAliases. /// /// This doesn't include trait's because traits are not types. Type, @@ -99,7 +99,7 @@ impl<'a> Validator<'a> { ItemEnum::Trait(x) => self.check_trait(x, id), ItemEnum::TraitAlias(x) => self.check_trait_alias(x), ItemEnum::Impl(x) => self.check_impl(x, id), - ItemEnum::TypeAlias(x) => self.check_typedef(x), + ItemEnum::TypeAlias(x) => self.check_type_alias(x), ItemEnum::OpaqueTy(x) => self.check_opaque_ty(x), ItemEnum::Constant(x) => self.check_constant(x), ItemEnum::Static(x) => self.check_static(x), @@ -221,7 +221,7 @@ impl<'a> Validator<'a> { } } - fn check_typedef(&mut self, x: &'a TypeAlias) { + fn check_type_alias(&mut self, x: &'a TypeAlias) { self.check_generics(&x.generics); self.check_type(&x.type_); } @@ -450,7 +450,7 @@ impl<'a> Validator<'a> { } fn add_type_id(&mut self, id: &'a Id) { - self.add_id_checked(id, Kind::is_type, "Type (Struct, Enum, Union or Typedef)"); + self.add_id_checked(id, Kind::is_type, "Type (Struct, Enum, Union or TypeAlias)"); } /// Add an Id that appeared in a trait From 912d11d4d1d36cb1c7a686b43a64b5f96dd58fe4 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 23 Aug 2023 11:52:49 -0700 Subject: [PATCH 154/197] Fix rustdoc-json tests --- tests/rustdoc-json/fn_pointer/abi.rs | 14 ++-- tests/rustdoc-json/fn_pointer/generics.rs | 14 ++-- tests/rustdoc-json/fn_pointer/qualifiers.rs | 12 ++-- .../rustdoc-json/primitives/primitive_type.rs | 10 +-- tests/rustdoc-json/type/dyn.rs | 64 +++++++++---------- tests/rustdoc-json/type/fn_lifetime.rs | 38 +++++------ tests/rustdoc-json/type/generic_default.rs | 42 ++++++------ 7 files changed, 97 insertions(+), 97 deletions(-) diff --git a/tests/rustdoc-json/fn_pointer/abi.rs b/tests/rustdoc-json/fn_pointer/abi.rs index 77c0e82330f2..dbe316f573db 100644 --- a/tests/rustdoc-json/fn_pointer/abi.rs +++ b/tests/rustdoc-json/fn_pointer/abi.rs @@ -2,23 +2,23 @@ #![feature(abi_vectorcall)] -// @is "$.index[*][?(@.name=='AbiRust')].inner.typedef.type.function_pointer.header.abi" \"Rust\" +// @is "$.index[*][?(@.name=='AbiRust')].inner.type_alias.type.function_pointer.header.abi" \"Rust\" pub type AbiRust = fn(); -// @is "$.index[*][?(@.name=='AbiC')].inner.typedef.type.function_pointer.header.abi" '{"C": {"unwind": false}}' +// @is "$.index[*][?(@.name=='AbiC')].inner.type_alias.type.function_pointer.header.abi" '{"C": {"unwind": false}}' pub type AbiC = extern "C" fn(); -// @is "$.index[*][?(@.name=='AbiSystem')].inner.typedef.type.function_pointer.header.abi" '{"System": {"unwind": false}}' +// @is "$.index[*][?(@.name=='AbiSystem')].inner.type_alias.type.function_pointer.header.abi" '{"System": {"unwind": false}}' pub type AbiSystem = extern "system" fn(); -// @is "$.index[*][?(@.name=='AbiCUnwind')].inner.typedef.type.function_pointer.header.abi" '{"C": {"unwind": true}}' +// @is "$.index[*][?(@.name=='AbiCUnwind')].inner.type_alias.type.function_pointer.header.abi" '{"C": {"unwind": true}}' pub type AbiCUnwind = extern "C-unwind" fn(); -// @is "$.index[*][?(@.name=='AbiSystemUnwind')].inner.typedef.type.function_pointer.header.abi" '{"System": {"unwind": true}}' +// @is "$.index[*][?(@.name=='AbiSystemUnwind')].inner.type_alias.type.function_pointer.header.abi" '{"System": {"unwind": true}}' pub type AbiSystemUnwind = extern "system-unwind" fn(); -// @is "$.index[*][?(@.name=='AbiVecorcall')].inner.typedef.type.function_pointer.header.abi.Other" '"\"vectorcall\""' +// @is "$.index[*][?(@.name=='AbiVecorcall')].inner.type_alias.type.function_pointer.header.abi.Other" '"\"vectorcall\""' pub type AbiVecorcall = extern "vectorcall" fn(); -// @is "$.index[*][?(@.name=='AbiVecorcallUnwind')].inner.typedef.type.function_pointer.header.abi.Other" '"\"vectorcall-unwind\""' +// @is "$.index[*][?(@.name=='AbiVecorcallUnwind')].inner.type_alias.type.function_pointer.header.abi.Other" '"\"vectorcall-unwind\""' pub type AbiVecorcallUnwind = extern "vectorcall-unwind" fn(); diff --git a/tests/rustdoc-json/fn_pointer/generics.rs b/tests/rustdoc-json/fn_pointer/generics.rs index 48672f12da1a..3b82561ec7df 100644 --- a/tests/rustdoc-json/fn_pointer/generics.rs +++ b/tests/rustdoc-json/fn_pointer/generics.rs @@ -3,11 +3,11 @@ #![feature(no_core)] #![no_core] -// @count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.decl.inputs[*]" 1 -// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.decl.inputs[0][0]" '"val"' -// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.decl.inputs[0][1].borrowed_ref.lifetime" \"\'c\" -// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.decl.output.primitive" \"i32\" -// @count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.generic_params[*]" 1 -// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.generic_params[0].name" \"\'c\" -// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }' +// @count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1 +// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[0][0]" '"val"' +// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[0][1].borrowed_ref.lifetime" \"\'c\" +// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.output.primitive" \"i32\" +// @count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[*]" 1 +// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[0].name" \"\'c\" +// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }' pub type WithHigherRankTraitBounds = for<'c> fn(val: &'c i32) -> i32; diff --git a/tests/rustdoc-json/fn_pointer/qualifiers.rs b/tests/rustdoc-json/fn_pointer/qualifiers.rs index 0ab776c21eda..1a62eb2bae8b 100644 --- a/tests/rustdoc-json/fn_pointer/qualifiers.rs +++ b/tests/rustdoc-json/fn_pointer/qualifiers.rs @@ -1,11 +1,11 @@ // ignore-tidy-linelength -// @is "$.index[*][?(@.name=='FnPointer')].inner.typedef.type.function_pointer.header.unsafe" false -// @is "$.index[*][?(@.name=='FnPointer')].inner.typedef.type.function_pointer.header.const" false -// @is "$.index[*][?(@.name=='FnPointer')].inner.typedef.type.function_pointer.header.async" false +// @is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.unsafe" false +// @is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.const" false +// @is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.async" false pub type FnPointer = fn(); -// @is "$.index[*][?(@.name=='UnsafePointer')].inner.typedef.type.function_pointer.header.unsafe" true -// @is "$.index[*][?(@.name=='UnsafePointer')].inner.typedef.type.function_pointer.header.const" false -// @is "$.index[*][?(@.name=='UnsafePointer')].inner.typedef.type.function_pointer.header.async" false +// @is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.unsafe" true +// @is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.const" false +// @is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.async" false pub type UnsafePointer = unsafe fn(); diff --git a/tests/rustdoc-json/primitives/primitive_type.rs b/tests/rustdoc-json/primitives/primitive_type.rs index 5f251b3b8901..89c5d06c0b22 100644 --- a/tests/rustdoc-json/primitives/primitive_type.rs +++ b/tests/rustdoc-json/primitives/primitive_type.rs @@ -1,17 +1,17 @@ #![feature(never_type)] // @is "$.index[*][?(@.name=='PrimNever')].visibility" \"public\" -// @is "$.index[*][?(@.name=='PrimNever')].inner.typedef.type.primitive" \"never\" +// @is "$.index[*][?(@.name=='PrimNever')].inner.type_alias.type.primitive" \"never\" pub type PrimNever = !; -// @is "$.index[*][?(@.name=='PrimStr')].inner.typedef.type.primitive" \"str\" +// @is "$.index[*][?(@.name=='PrimStr')].inner.type_alias.type.primitive" \"str\" pub type PrimStr = str; -// @is "$.index[*][?(@.name=='PrimBool')].inner.typedef.type.primitive" \"bool\" +// @is "$.index[*][?(@.name=='PrimBool')].inner.type_alias.type.primitive" \"bool\" pub type PrimBool = bool; -// @is "$.index[*][?(@.name=='PrimChar')].inner.typedef.type.primitive" \"char\" +// @is "$.index[*][?(@.name=='PrimChar')].inner.type_alias.type.primitive" \"char\" pub type PrimChar = char; -// @is "$.index[*][?(@.name=='PrimU8')].inner.typedef.type.primitive" \"u8\" +// @is "$.index[*][?(@.name=='PrimU8')].inner.type_alias.type.primitive" \"u8\" pub type PrimU8 = u8; diff --git a/tests/rustdoc-json/type/dyn.rs b/tests/rustdoc-json/type/dyn.rs index e5ee60fad59f..4db65b61dc6d 100644 --- a/tests/rustdoc-json/type/dyn.rs +++ b/tests/rustdoc-json/type/dyn.rs @@ -7,40 +7,40 @@ use std::fmt::Debug; // @set weird_order = "$.index[*][?(@.name=='WeirdOrder')].id" // @ismany "$.index[*][?(@.name=='dyn')].inner.module.items[*]" $sync_int_gen $ref_fn $weird_order -// @has "$.index[*][?(@.name=='SyncIntGen')].inner.typedef" -// @is "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.generics" '{"params": [], "where_predicates": []}' -// @has "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path" -// @is "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.name" \"Box\" -// @is "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.bindings" [] -// @count "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args" 1 -// @has "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait" -// @is "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.lifetime" \"\'static\" -// @count "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[*]" 3 -// @is "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].generic_params" [] -// @is "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].generic_params" [] -// @is "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].generic_params" [] -// @is "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.name" '"Fn"' -// @is "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.name" '"Send"' -// @is "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].trait.name" '"Sync"' -// @is "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.args" '{"parenthesized": {"inputs": [],"output": {"primitive": "i32"}}}' +// @has "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias" +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.generics" '{"params": [], "where_predicates": []}' +// @has "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path" +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.name" \"Box\" +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.bindings" [] +// @count "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args" 1 +// @has "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait" +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.lifetime" \"\'static\" +// @count "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[*]" 3 +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].generic_params" [] +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].generic_params" [] +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].generic_params" [] +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.name" '"Fn"' +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.name" '"Send"' +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].trait.name" '"Sync"' +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.args" '{"parenthesized": {"inputs": [],"output": {"primitive": "i32"}}}' pub type SyncIntGen = Box i32 + Send + Sync + 'static>; -// @has "$.index[*][?(@.name=='RefFn')].inner.typedef" -// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.generics" '{"params": [{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"}],"where_predicates": []}' -// @has "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref" -// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.mutable" 'false' -// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.lifetime" "\"'a\"" -// @has "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait" -// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.lifetime" null -// @count "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[*]" 1 -// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' -// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"' -// @has "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref" -// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref.lifetime" "\"'b\"" -// @has "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref" -// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref.lifetime" "\"'b\"" +// @has "$.index[*][?(@.name=='RefFn')].inner.type_alias" +// @is "$.index[*][?(@.name=='RefFn')].inner.type_alias.generics" '{"params": [{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"}],"where_predicates": []}' +// @has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref" +// @is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.mutable" 'false' +// @is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.lifetime" "\"'a\"" +// @has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait" +// @is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.lifetime" null +// @count "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[*]" 1 +// @is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' +// @is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"' +// @has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref" +// @is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref.lifetime" "\"'b\"" +// @has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref" +// @is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref.lifetime" "\"'b\"" pub type RefFn<'a> = &'a dyn for<'b> Fn(&'b i32) -> &'b i32; -// @is "$.index[*][?(@.name=='WeirdOrder')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.name" '"Send"' -// @is "$.index[*][?(@.name=='WeirdOrder')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.name" '"Debug"' +// @is "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.name" '"Send"' +// @is "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.name" '"Debug"' pub type WeirdOrder = Box; diff --git a/tests/rustdoc-json/type/fn_lifetime.rs b/tests/rustdoc-json/type/fn_lifetime.rs index 424c5dce273a..4aca303e6dcd 100644 --- a/tests/rustdoc-json/type/fn_lifetime.rs +++ b/tests/rustdoc-json/type/fn_lifetime.rs @@ -1,26 +1,26 @@ // ignore-tidy-linelength -// @has "$.index[*][?(@.name=='GenericFn')].inner.typedef" +// @has "$.index[*][?(@.name=='GenericFn')].inner.type_alias" -// @ismany "$.index[*][?(@.name=='GenericFn')].inner.typedef.generics.params[*].name" \"\'a\" -// @has "$.index[*][?(@.name=='GenericFn')].inner.typedef.generics.params[*].kind.lifetime" -// @count "$.index[*][?(@.name=='GenericFn')].inner.typedef.generics.params[*].kind.lifetime.outlives[*]" 0 -// @count "$.index[*][?(@.name=='GenericFn')].inner.typedef.generics.where_predicates[*]" 0 -// @count "$.index[*][?(@.name=='GenericFn')].inner.typedef.type.function_pointer.generic_params[*]" 0 -// @count "$.index[*][?(@.name=='GenericFn')].inner.typedef.type.function_pointer.decl.inputs[*]" 1 -// @is "$.index[*][?(@.name=='GenericFn')].inner.typedef.type.function_pointer.decl.inputs[*][1].borrowed_ref.lifetime" \"\'a\" -// @is "$.index[*][?(@.name=='GenericFn')].inner.typedef.type.function_pointer.decl.output.borrowed_ref.lifetime" \"\'a\" +// @ismany "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.params[*].name" \"\'a\" +// @has "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.params[*].kind.lifetime" +// @count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.params[*].kind.lifetime.outlives[*]" 0 +// @count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.where_predicates[*]" 0 +// @count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.generic_params[*]" 0 +// @count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1 +// @is "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.inputs[*][1].borrowed_ref.lifetime" \"\'a\" +// @is "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.output.borrowed_ref.lifetime" \"\'a\" pub type GenericFn<'a> = fn(&'a i32) -> &'a i32; -// @has "$.index[*][?(@.name=='ForAll')].inner.typedef" -// @count "$.index[*][?(@.name=='ForAll')].inner.typedef.generics.params[*]" 0 -// @count "$.index[*][?(@.name=='ForAll')].inner.typedef.generics.where_predicates[*]" 0 -// @count "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.generic_params[*]" 1 -// @is "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.generic_params[*].name" \"\'a\" -// @has "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.generic_params[*].kind.lifetime" -// @count "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.generic_params[*].kind.lifetime.outlives[*]" 0 -// @count "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.decl.inputs[*]" 1 -// @is "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.decl.inputs[*][1].borrowed_ref.lifetime" \"\'a\" -// @is "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.decl.output.borrowed_ref.lifetime" \"\'a\" +// @has "$.index[*][?(@.name=='ForAll')].inner.type_alias" +// @count "$.index[*][?(@.name=='ForAll')].inner.type_alias.generics.params[*]" 0 +// @count "$.index[*][?(@.name=='ForAll')].inner.type_alias.generics.where_predicates[*]" 0 +// @count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*]" 1 +// @is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].name" \"\'a\" +// @has "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].kind.lifetime" +// @count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].kind.lifetime.outlives[*]" 0 +// @count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1 +// @is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.inputs[*][1].borrowed_ref.lifetime" \"\'a\" +// @is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.output.borrowed_ref.lifetime" \"\'a\" pub type ForAll = for<'a> fn(&'a i32) -> &'a i32; diff --git a/tests/rustdoc-json/type/generic_default.rs b/tests/rustdoc-json/type/generic_default.rs index b46428745324..30817a42e8ac 100644 --- a/tests/rustdoc-json/type/generic_default.rs +++ b/tests/rustdoc-json/type/generic_default.rs @@ -9,25 +9,25 @@ pub enum Result { // @set my_error = "$.index[*][?(@.name=='MyError')].id" pub struct MyError {} -// @has "$.index[*][?(@.name=='MyResult')].inner.typedef" -// @count "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.where_predicates[*]" 0 -// @count "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[*]" 2 -// @is "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[0].name" \"T\" -// @is "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[1].name" \"E\" -// @has "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[0].kind.type" -// @has "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[1].kind.type" -// @count "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[0].kind.type.bounds[*]" 0 -// @count "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[1].kind.type.bounds[*]" 0 -// @is "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[0].kind.type.default" null -// @has "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[1].kind.type.default.resolved_path" -// @is "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[1].kind.type.default.resolved_path.id" $my_error -// @is "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[1].kind.type.default.resolved_path.name" \"MyError\" -// @has "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path" -// @is "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.id" $result -// @is "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.name" \"Result\" -// @is "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.args.angle_bracketed.bindings" [] -// @has "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.generic" -// @has "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.args.angle_bracketed.args[1].type.generic" -// @is "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.generic" \"T\" -// @is "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.args.angle_bracketed.args[1].type.generic" \"E\" +// @has "$.index[*][?(@.name=='MyResult')].inner.type_alias" +// @count "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.where_predicates[*]" 0 +// @count "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[*]" 2 +// @is "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[0].name" \"T\" +// @is "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].name" \"E\" +// @has "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[0].kind.type" +// @has "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type" +// @count "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[0].kind.type.bounds[*]" 0 +// @count "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.bounds[*]" 0 +// @is "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[0].kind.type.default" null +// @has "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path" +// @is "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path.id" $my_error +// @is "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path.name" \"MyError\" +// @has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path" +// @is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.id" $result +// @is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.name" \"Result\" +// @is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.bindings" [] +// @has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic" +// @has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[1].type.generic" +// @is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic" \"T\" +// @is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[1].type.generic" \"E\" pub type MyResult = Result; From c1a7af0f2a691c2e74479156475018b497f3c288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 23 Aug 2023 21:39:16 +0000 Subject: [PATCH 155/197] Suggest mutable borrow on read only for-loop that should be mutable ``` error[E0596]: cannot borrow `*test` as mutable, as it is behind a `&` reference --> $DIR/suggest-mut-iterator.rs:22:9 | LL | for test in &tests { | ------ this iterator yields `&` references LL | test.add(2); | ^^^^ `test` is a `&` reference, so the data it refers to cannot be borrowed as mutable | help: use a mutable iterator instead | LL | for test in &mut tests { | +++ ``` Address #114311. --- .../src/diagnostics/mutability_errors.rs | 179 +++++++++--------- tests/ui/borrowck/suggest-mut-iterator.fixed | 30 +++ tests/ui/borrowck/suggest-mut-iterator.rs | 30 +++ tests/ui/borrowck/suggest-mut-iterator.stderr | 16 ++ 4 files changed, 167 insertions(+), 88 deletions(-) create mode 100644 tests/ui/borrowck/suggest-mut-iterator.fixed create mode 100644 tests/ui/borrowck/suggest-mut-iterator.rs create mode 100644 tests/ui/borrowck/suggest-mut-iterator.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index d62541daf073..31e863b8a4ed 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -225,17 +225,17 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } if suggest { borrow_spans.var_subdiag( - None, - &mut err, - Some(mir::BorrowKind::Mut { kind: mir::MutBorrowKind::Default }), - |_kind, var_span| { - let place = self.describe_any_place(access_place.as_ref()); - crate::session_diagnostics::CaptureVarCause::MutableBorrowUsePlaceClosure { - place, - var_span, - } - }, - ); + None, + &mut err, + Some(mir::BorrowKind::Mut { kind: mir::MutBorrowKind::Default }), + |_kind, var_span| { + let place = self.describe_any_place(access_place.as_ref()); + crate::session_diagnostics::CaptureVarCause::MutableBorrowUsePlaceClosure { + place, + var_span, + } + }, + ); } borrow_span } @@ -262,11 +262,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } => { err.span_label(span, format!("cannot {act}")); - if let Some(span) = get_mut_span_in_struct_field( - self.infcx.tcx, - Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty, - *field, - ) { + let place = Place::ty_from(local, proj_base, self.body, self.infcx.tcx); + if let Some(span) = get_mut_span_in_struct_field(self.infcx.tcx, place.ty, *field) { err.span_suggestion_verbose( span, "consider changing this to be mutable", @@ -781,83 +778,88 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Attempt to search similar mutable associated items for suggestion. // In the future, attempt in all path but initially for RHS of for_loop - fn suggest_similar_mut_method_for_for_loop(&self, err: &mut Diagnostic) { + fn suggest_similar_mut_method_for_for_loop(&self, err: &mut Diagnostic, span: Span) { use hir::{ - Expr, - ExprKind::{Block, Call, DropTemps, Match, MethodCall}, + BorrowKind, Expr, + ExprKind::{AddrOf, Block, Call, MethodCall}, }; let hir_map = self.infcx.tcx.hir(); - if let Some(body_id) = hir_map.maybe_body_owned_by(self.mir_def_id()) { - if let Block( - hir::Block { - expr: - Some(Expr { - kind: - DropTemps(Expr { - kind: - Match( - Expr { - kind: - Call( - _, - [ - Expr { - kind: - MethodCall(path_segment, _, _, span), - hir_id, - .. - }, - .., - ], - ), - .. - }, - .., - ), - .. - }), - .. - }), - .. - }, - _, - ) = hir_map.body(body_id).value.kind - { - let opt_suggestions = self - .infcx - .tcx - .typeck(path_segment.hir_id.owner.def_id) - .type_dependent_def_id(*hir_id) - .and_then(|def_id| self.infcx.tcx.impl_of_method(def_id)) - .map(|def_id| self.infcx.tcx.associated_items(def_id)) - .map(|assoc_items| { - assoc_items - .in_definition_order() - .map(|assoc_item_def| assoc_item_def.ident(self.infcx.tcx)) - .filter(|&ident| { - let original_method_ident = path_segment.ident; - original_method_ident != ident - && ident - .as_str() - .starts_with(&original_method_ident.name.to_string()) - }) - .map(|ident| format!("{ident}()")) - .peekable() - }); + struct Finder<'tcx> { + span: Span, + expr: Option<&'tcx Expr<'tcx>>, + } - if let Some(mut suggestions) = opt_suggestions - && suggestions.peek().is_some() - { - err.span_suggestions( - *span, - "use mutable method", - suggestions, - Applicability::MaybeIncorrect, - ); + impl<'tcx> Visitor<'tcx> for Finder<'tcx> { + fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) { + if e.span == self.span && self.expr.is_none() { + self.expr = Some(e); + } + hir::intravisit::walk_expr(self, e); + } + } + if let Some(body_id) = hir_map.maybe_body_owned_by(self.mir_def_id()) + && let Block(block, _) = hir_map.body(body_id).value.kind + { + // `span` corresponds to the expression being iterated, find the `for`-loop desugared + // expression with that span in order to identify potential fixes when encountering a + // read-only iterator that should be mutable. + let mut v = Finder { + span, + expr: None, + }; + v.visit_block(block); + if let Some(expr) = v.expr && let Call(_, [expr]) = expr.kind { + match expr.kind { + MethodCall(path_segment, _, _, span) => { + // We have `for _ in iter.read_only_iter()`, try to + // suggest `for _ in iter.mutable_iter()` instead. + let opt_suggestions = self + .infcx + .tcx + .typeck(path_segment.hir_id.owner.def_id) + .type_dependent_def_id(expr.hir_id) + .and_then(|def_id| self.infcx.tcx.impl_of_method(def_id)) + .map(|def_id| self.infcx.tcx.associated_items(def_id)) + .map(|assoc_items| { + assoc_items + .in_definition_order() + .map(|assoc_item_def| assoc_item_def.ident(self.infcx.tcx)) + .filter(|&ident| { + let original_method_ident = path_segment.ident; + original_method_ident != ident + && ident.as_str().starts_with( + &original_method_ident.name.to_string(), + ) + }) + .map(|ident| format!("{ident}()")) + .peekable() + }); + + if let Some(mut suggestions) = opt_suggestions + && suggestions.peek().is_some() + { + err.span_suggestions( + span, + "use mutable method", + suggestions, + Applicability::MaybeIncorrect, + ); + } + } + AddrOf(BorrowKind::Ref, Mutability::Not, expr) => { + // We have `for _ in &i`, suggest `for _ in &mut i`. + err.span_suggestion_verbose( + expr.span.shrink_to_lo(), + "use a mutable iterator instead", + "mut ".to_string(), + Applicability::MachineApplicable, + ); + } + _ => {} } } - }; + } } /// Targeted error when encountering an `FnMut` closure where an `Fn` closure was expected. @@ -1003,9 +1005,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { match opt_assignment_rhs_span.and_then(|s| s.desugaring_kind()) { // on for loops, RHS points to the iterator part Some(DesugaringKind::ForLoop) => { - self.suggest_similar_mut_method_for_for_loop(err); + let span = opt_assignment_rhs_span.unwrap(); + self.suggest_similar_mut_method_for_for_loop(err, span); err.span_label( - opt_assignment_rhs_span.unwrap(), + span, format!("this iterator yields `{pointer_sigil}` {pointer_desc}s",), ); None diff --git a/tests/ui/borrowck/suggest-mut-iterator.fixed b/tests/ui/borrowck/suggest-mut-iterator.fixed new file mode 100644 index 000000000000..16512b8a3cd8 --- /dev/null +++ b/tests/ui/borrowck/suggest-mut-iterator.fixed @@ -0,0 +1,30 @@ +// run-rustfix +struct Test { + a: u32 +} + +impl Test { + pub fn add(&mut self, value: u32) { + self.a += value; + } + + pub fn print_value(&self) { + println!("Value of a is: {}", self.a); + } +} + +fn main() { + let mut tests = Vec::new(); + for i in 0..=10 { + tests.push(Test {a: i}); + } + for test in &mut tests { + test.add(2); //~ ERROR cannot borrow `*test` as mutable, as it is behind a `&` reference + } + for test in &mut tests { + test.add(2); + } + for test in &tests { + test.print_value(); + } +} diff --git a/tests/ui/borrowck/suggest-mut-iterator.rs b/tests/ui/borrowck/suggest-mut-iterator.rs new file mode 100644 index 000000000000..276edeccb22a --- /dev/null +++ b/tests/ui/borrowck/suggest-mut-iterator.rs @@ -0,0 +1,30 @@ +// run-rustfix +struct Test { + a: u32 +} + +impl Test { + pub fn add(&mut self, value: u32) { + self.a += value; + } + + pub fn print_value(&self) { + println!("Value of a is: {}", self.a); + } +} + +fn main() { + let mut tests = Vec::new(); + for i in 0..=10 { + tests.push(Test {a: i}); + } + for test in &tests { + test.add(2); //~ ERROR cannot borrow `*test` as mutable, as it is behind a `&` reference + } + for test in &mut tests { + test.add(2); + } + for test in &tests { + test.print_value(); + } +} diff --git a/tests/ui/borrowck/suggest-mut-iterator.stderr b/tests/ui/borrowck/suggest-mut-iterator.stderr new file mode 100644 index 000000000000..77f991a9a61c --- /dev/null +++ b/tests/ui/borrowck/suggest-mut-iterator.stderr @@ -0,0 +1,16 @@ +error[E0596]: cannot borrow `*test` as mutable, as it is behind a `&` reference + --> $DIR/suggest-mut-iterator.rs:22:9 + | +LL | for test in &tests { + | ------ this iterator yields `&` references +LL | test.add(2); + | ^^^^ `test` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: use a mutable iterator instead + | +LL | for test in &mut tests { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. From 0a916062aac997071d020159bd6f12a57ca3fd2c Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 22 Aug 2023 07:06:38 -0400 Subject: [PATCH 156/197] Bump cfg(bootstrap) --- compiler/rustc_abi/src/lib.rs | 2 +- compiler/rustc_arena/src/lib.rs | 2 +- compiler/rustc_borrowck/src/lib.rs | 2 +- compiler/rustc_data_structures/src/lib.rs | 2 +- compiler/rustc_error_messages/src/lib.rs | 2 +- compiler/rustc_errors/src/lib.rs | 2 +- compiler/rustc_expand/src/lib.rs | 2 +- compiler/rustc_hir/src/lib.rs | 2 +- compiler/rustc_index/src/lib.rs | 2 +- compiler/rustc_lint/src/lib.rs | 2 +- compiler/rustc_macros/src/lib.rs | 2 +- compiler/rustc_middle/src/lib.rs | 2 +- compiler/rustc_parse/src/lib.rs | 2 +- compiler/rustc_query_impl/src/lib.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 2 +- compiler/rustc_session/src/lib.rs | 2 +- compiler/rustc_span/src/lib.rs | 2 +- compiler/rustc_target/src/lib.rs | 2 +- compiler/rustc_type_ir/src/lib.rs | 2 +- library/alloc/src/lib.rs | 4 ++-- library/alloc/tests/vec.rs | 1 - library/core/src/cell.rs | 3 +-- library/core/src/intrinsics.rs | 16 ---------------- library/core/src/intrinsics/mir.rs | 6 +++--- library/core/src/lib.rs | 4 ++-- library/panic_abort/src/lib.rs | 2 +- library/panic_unwind/src/lib.rs | 3 +-- library/proc_macro/src/lib.rs | 2 +- library/profiler_builtins/src/lib.rs | 2 +- library/std/src/lib.rs | 4 ++-- library/test/src/lib.rs | 2 +- library/unwind/src/lib.rs | 2 +- src/tools/compiletest/src/runtest.rs | 18 +++--------------- 33 files changed, 38 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 12dd1542d799..7f2cab3eb11d 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1,5 +1,5 @@ #![cfg_attr(feature = "nightly", feature(step_trait, rustc_attrs, min_specialization))] -#![cfg_attr(all(not(bootstrap), feature = "nightly"), allow(internal_features))] +#![cfg_attr(feature = "nightly", allow(internal_features))] use std::fmt; #[cfg(feature = "nightly")] diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index e45b7c154faf..f14463fe9402 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -24,7 +24,7 @@ #![deny(unsafe_op_in_unsafe_fn)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #![allow(clippy::mut_from_ref)] // Arena allocators are one of the places where this pattern is fine. use smallvec::SmallVec; diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index ef2788efbcfc..3f544bf72098 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -11,7 +11,7 @@ #![feature(trusted_step)] #![feature(try_blocks)] #![recursion_limit = "256"] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #[macro_use] extern crate rustc_middle; diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 33772089744d..bee5a89c4c73 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -37,7 +37,7 @@ #![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #![deny(unsafe_op_in_unsafe_fn)] #[macro_use] diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 3bf15505090c..6c29144569d4 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -4,7 +4,7 @@ #![feature(type_alias_impl_trait)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 34518b53759d..db5df554d23e 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -15,7 +15,7 @@ #![feature(box_patterns)] #![feature(error_reporter)] #![allow(incomplete_features)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index c4a9b2ace9a0..8b1fc5b90b43 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -11,7 +11,7 @@ #![feature(try_blocks)] #![recursion_limit = "256"] #![deny(rustc::untranslatable_diagnostic)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 34214931a081..094d5b1e77cf 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -13,7 +13,7 @@ #![recursion_limit = "256"] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index 9942c70c4ae7..c3de446a66e9 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -12,7 +12,7 @@ test ) )] -#![cfg_attr(all(not(bootstrap), feature = "nightly"), allow(internal_features))] +#![cfg_attr(feature = "nightly", allow(internal_features))] #[cfg(feature = "nightly")] pub mod bit_set; diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 585b10e79e48..e578f09b58fe 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -40,7 +40,7 @@ #![recursion_limit = "256"] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #[macro_use] extern crate rustc_middle; diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index f4593d0fe736..85829906f4ef 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -7,7 +7,7 @@ #![allow(rustc::default_hash_types)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #![recursion_limit = "128"] use synstructure::decl_derive; diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index d3fc1b2850ea..50b69181d67e 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -63,7 +63,7 @@ #![feature(macro_metavar_expr)] #![recursion_limit = "512"] #![allow(rustc::potential_query_instability)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #[macro_use] extern crate bitflags; diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 892be36aae77..598adbe79859 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -8,7 +8,7 @@ #![feature(never_type)] #![feature(rustc_attrs)] #![recursion_limit = "256"] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 53005ede8437..775870106b19 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -11,7 +11,7 @@ #![allow(rustc::potential_query_instability, unused_parens)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #[macro_use] extern crate rustc_middle; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 76e54e60d142..410705952bf9 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -18,7 +18,7 @@ #![recursion_limit = "256"] #![allow(rustdoc::private_intra_doc_links)] #![allow(rustc::potential_query_instability)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index a270817f3109..d6c746a7bd85 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -10,7 +10,7 @@ #![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index c24b8d9ec170..efaed0f68ceb 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -23,7 +23,7 @@ #![feature(round_char_boundary)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index b52002b12396..e838e11131f6 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -19,7 +19,7 @@ #![feature(step_trait)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] use std::path::{Path, PathBuf}; diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index b0f8ea7a05da..e0abc7f04f57 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -6,7 +6,7 @@ #![feature(unwrap_infallible)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #[macro_use] extern crate bitflags; diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index efe8f5a8bcf3..e43b6ac40391 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -88,8 +88,8 @@ #![warn(missing_docs)] #![allow(explicit_outlives_requirements)] #![warn(multiple_supertrait_upcastable)] -#![cfg_attr(not(bootstrap), allow(internal_features))] -#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))] +#![allow(internal_features)] +#![allow(rustdoc::redundant_explicit_links)] // // Library features: // tidy-alphabetical-start diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 183dd8e6e593..9cb27899f109 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -2499,7 +2499,6 @@ fn test_into_flattened_size_overflow() { let _ = v.into_flattened(); } -#[cfg(not(bootstrap))] #[test] fn test_box_zero_allocator() { use core::{alloc::AllocError, cell::RefCell}; diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index bf4c682d33e5..4bbe61ca3e77 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1893,8 +1893,7 @@ impl fmt::Display for RefMut<'_, T> { /// on an _exclusive_ `UnsafeCell`. Even though `T` and `UnsafeCell` have the /// same memory layout, the following is not allowed and undefined behavior: /// -#[cfg_attr(bootstrap, doc = "```rust,no_run")] -#[cfg_attr(not(bootstrap), doc = "```rust,compile_fail")] +/// ```rust,compile_fail /// # use std::cell::UnsafeCell; /// unsafe fn not_allowed(ptr: &UnsafeCell) -> &mut T { /// let t = ptr as *const UnsafeCell as *mut T; diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 676d4f2f38ca..605870b8a7b9 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2399,7 +2399,6 @@ extern "rust-intrinsic" { /// that differs. That allows optimizations that can read in large chunks. /// /// [valid]: crate::ptr#safety - #[cfg(not(bootstrap))] #[rustc_const_unstable(feature = "const_intrinsic_compare_bytes", issue = "none")] #[rustc_nounwind] pub fn compare_bytes(left: *const u8, right: *const u8, bytes: usize) -> i32; @@ -2844,18 +2843,3 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { write_bytes(dst, val, count) } } - -/// Backfill for bootstrap -#[cfg(bootstrap)] -pub unsafe fn compare_bytes(left: *const u8, right: *const u8, bytes: usize) -> i32 { - extern "C" { - fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> crate::ffi::c_int; - } - - if bytes != 0 { - // SAFETY: Since bytes is non-zero, the caller has met `memcmp`'s requirements. - unsafe { memcmp(left, right, bytes).into() } - } else { - 0 - } -} diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index ef0a2fd4ec4b..b99346b6ba60 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -14,7 +14,7 @@ //! //! ```rust //! #![feature(core_intrinsics, custom_mir)] -#![cfg_attr(not(bootstrap), doc = "#![allow(internal_features)]")] +//! #![allow(internal_features)] //! //! use core::intrinsics::mir::*; //! @@ -64,7 +64,7 @@ //! //! ```rust //! #![feature(core_intrinsics, custom_mir)] -#![cfg_attr(not(bootstrap), doc = "#![allow(internal_features)]")] +//! #![allow(internal_features)] //! //! use core::intrinsics::mir::*; //! @@ -318,7 +318,7 @@ define!( /// # Examples /// /// ```rust - #[cfg_attr(not(bootstrap), doc = "#![allow(internal_features)]")] + /// #![allow(internal_features)] /// #![feature(custom_mir, core_intrinsics)] /// /// use core::intrinsics::mir::*; diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index a2729b3743cc..f39c41764403 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -96,9 +96,9 @@ #![allow(explicit_outlives_requirements)] #![allow(incomplete_features)] #![warn(multiple_supertrait_upcastable)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] // Do not check link redundancy on bootstraping phase -#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))] +#![allow(rustdoc::redundant_explicit_links)] // // Library features: // tidy-alphabetical-start diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index 76b359196585..02534491da97 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -14,7 +14,7 @@ #![feature(staged_api)] #![feature(rustc_attrs)] #![feature(c_unwind)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #[cfg(target_os = "android")] mod android; diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index 009014de5c2c..e7d34daa0796 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -19,14 +19,13 @@ #![feature(panic_unwind)] #![feature(staged_api)] #![feature(std_internals)] -#![cfg_attr(bootstrap, feature(abi_thiscall))] #![feature(rustc_attrs)] #![panic_runtime] #![feature(panic_runtime)] #![feature(c_unwind)] // `real_imp` is unused with Miri, so silence warnings. #![cfg_attr(miri, allow(dead_code))] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] use alloc::boxed::Box; use core::any::Any; diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 83d637b685ac..d382fec93521 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -32,7 +32,7 @@ #![feature(min_specialization)] #![feature(strict_provenance)] #![recursion_limit = "256"] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #[unstable(feature = "proc_macro_internals", issue = "27812")] #[doc(hidden)] diff --git a/library/profiler_builtins/src/lib.rs b/library/profiler_builtins/src/lib.rs index a81d0a63547f..ac685b18c291 100644 --- a/library/profiler_builtins/src/lib.rs +++ b/library/profiler_builtins/src/lib.rs @@ -7,5 +7,5 @@ issue = "none" )] #![allow(unused_features)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #![feature(staged_api)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 58684ffe500a..1955ef815ff8 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -220,10 +220,10 @@ #![warn(missing_debug_implementations)] #![allow(explicit_outlives_requirements)] #![allow(unused_lifetimes)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #![deny(rustc::existing_doc_keyword)] #![deny(fuzzy_provenance_casts)] -#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))] +#![allow(rustdoc::redundant_explicit_links)] // Ensure that std can be linked against panic_abort despite compiled with `-C panic=unwind` #![deny(ffi_unwind_calls)] // std may use features in a platform-specific way diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 64d10dd5712a..413f0fba3422 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -21,7 +21,7 @@ #![feature(process_exitcode_internals)] #![feature(panic_can_unwind)] #![feature(test)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] // Public reexports pub use self::bench::{black_box, Bencher}; diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 0b4daeafe46d..62e97c65569f 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -5,7 +5,7 @@ #![feature(c_unwind)] #![feature(cfg_target_abi)] #![cfg_attr(not(target_env = "msvc"), feature(libc))] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] cfg_if::cfg_if! { if #[cfg(target_env = "msvc")] { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 4ef79af3124a..a2c828701e55 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2354,14 +2354,7 @@ impl<'test> TestCx<'test> { // Hide line numbers to reduce churn rustc.arg("-Zui-testing"); rustc.arg("-Zdeduplicate-diagnostics=no"); - // #[cfg(not(bootstrap)] unconditionally pass flag after beta bump - // since `ui-fulldeps --stage=1` builds using the stage 0 compiler, - // which doesn't have this flag. - if !(self.config.stage_id.starts_with("stage1-") - && self.config.suite == "ui-fulldeps") - { - rustc.arg("-Zwrite-long-types-to-disk=no"); - } + rustc.arg("-Zwrite-long-types-to-disk=no"); // FIXME: use this for other modes too, for perf? rustc.arg("-Cstrip=debuginfo"); } @@ -2483,13 +2476,8 @@ impl<'test> TestCx<'test> { rustc.args(&["-A", "unused"]); } - // #[cfg(not(bootstrap)] unconditionally pass flag after beta bump - // since `ui-fulldeps --stage=1` builds using the stage 0 compiler, - // which doesn't have this lint. - if !(self.config.stage_id.starts_with("stage1-") && self.config.suite == "ui-fulldeps") { - // Allow tests to use internal features. - rustc.args(&["-A", "internal_features"]); - } + // Allow tests to use internal features. + rustc.args(&["-A", "internal_features"]); if self.props.force_host { self.maybe_add_external_args(&mut rustc, &self.config.host_rustcflags); From 81a24922e796445054b4cb32e2dd644c696787a2 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Wed, 23 Aug 2023 23:53:37 +0100 Subject: [PATCH 157/197] lint: translate `RenamedOrRemovedLint` --- compiler/rustc_lint/messages.ftl | 11 +++++++--- compiler/rustc_lint/src/context.rs | 35 ++++++++++++++++-------------- compiler/rustc_lint/src/errors.rs | 16 +++++++++++--- compiler/rustc_lint/src/levels.rs | 26 ++++++++++++++-------- compiler/rustc_lint/src/lints.rs | 18 ++++++++++----- 5 files changed, 69 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index d7cb159149d8..7f7f36ca170d 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -158,13 +158,15 @@ lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}` lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not have an effect anymore. Use: {$new_name} +lint_check_name_removed = lint `{$lint_name}` has been removed: {$reason} + +lint_check_name_renamed = lint `{$lint_name}` has been renamed to `{$replace}` + lint_check_name_unknown = unknown lint: `{$lint_name}` .help = did you mean: `{$suggestion}` lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}` -lint_check_name_warning = {$msg} - lint_command_line_source = `forbid` lint level was set on command line lint_confusable_identifier_pair = found both `{$existing_sym}` and `{$sym}` as identifiers, which look alike @@ -484,8 +486,11 @@ lint_redundant_semicolons = *[false] this semicolon } -lint_renamed_or_removed_lint = {$msg} +lint_removed_lint = lint `{$name}` has been removed: {$reason} + +lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}` .suggestion = use the new name + .help = use the new name `{$replace}` lint_requested_level = requested on the command line with `{$level} {$lint_name}` diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index aabefb729f3d..9a0f3ca51181 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -17,8 +17,8 @@ use self::TargetLint::*; use crate::errors::{ - CheckNameDeprecated, CheckNameUnknown, CheckNameUnknownTool, CheckNameWarning, RequestedLevel, - UnsupportedGroup, + CheckNameDeprecated, CheckNameRemoved, CheckNameRenamed, CheckNameUnknown, + CheckNameUnknownTool, RequestedLevel, UnsupportedGroup, }; use crate::levels::LintLevelsBuilder; use crate::passes::{EarlyLintPassObject, LateLintPassObject}; @@ -124,9 +124,10 @@ pub enum CheckLintNameResult<'a> { NoLint(Option), /// The lint refers to a tool that has not been registered. NoTool, - /// The lint is either renamed or removed. This is the warning - /// message, and an optional new name (`None` if removed). - Warning(String, Option), + /// The lint has been renamed to a new name. + Renamed(String), + /// The lint has been removed due to the given reason. + Removed(String), /// The lint is from a tool. If the Option is None, then either /// the lint does not exist in the tool or the code was not /// compiled with the tool and therefore the lint was never @@ -344,9 +345,17 @@ impl LintStore { } let lint_name = lint_name.to_string(); match self.check_lint_name(lint_name_only, tool_name, registered_tools) { - CheckLintNameResult::Warning(msg, _) => { - sess.emit_warning(CheckNameWarning { - msg, + CheckLintNameResult::Renamed(replace) => { + sess.emit_warning(CheckNameRenamed { + lint_name: lint_name.clone(), + replace, + sub: RequestedLevel { level, lint_name }, + }); + } + CheckLintNameResult::Removed(reason) => { + sess.emit_warning(CheckNameRemoved { + lint_name: lint_name.clone(), + reason, sub: RequestedLevel { level, lint_name }, }); } @@ -445,14 +454,8 @@ impl LintStore { } } match self.by_name.get(&complete_name) { - Some(Renamed(new_name, _)) => CheckLintNameResult::Warning( - format!("lint `{complete_name}` has been renamed to `{new_name}`"), - Some(new_name.to_owned()), - ), - Some(Removed(reason)) => CheckLintNameResult::Warning( - format!("lint `{complete_name}` has been removed: {reason}"), - None, - ), + Some(Renamed(new_name, _)) => CheckLintNameResult::Renamed(new_name.to_string()), + Some(Removed(reason)) => CheckLintNameResult::Removed(reason.to_string()), None => match self.lint_groups.get(&*complete_name) { // If neither the lint, nor the lint group exists check if there is a `clippy::` // variant of this lint diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index 68167487a1bd..e63741820aff 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -134,9 +134,19 @@ pub struct CheckNameUnknownTool { } #[derive(Diagnostic)] -#[diag(lint_check_name_warning)] -pub struct CheckNameWarning { - pub msg: String, +#[diag(lint_check_name_renamed)] +pub struct CheckNameRenamed { + pub lint_name: String, + pub replace: String, + #[subdiagnostic] + pub sub: RequestedLevel, +} + +#[derive(Diagnostic)] +#[diag(lint_check_name_removed)] +pub struct CheckNameRemoved { + pub lint_name: String, + pub reason: String, #[subdiagnostic] pub sub: RequestedLevel, } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 0a40d17f98ed..f58782c0f224 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -4,8 +4,8 @@ use crate::{ fluent_generated as fluent, late::unerased_lint_store, lints::{ - DeprecatedLintName, IgnoredUnlessCrateSpecified, OverruledAttributeLint, - RenamedOrRemovedLint, RenamedOrRemovedLintSuggestion, UnknownLint, UnknownLintSuggestion, + DeprecatedLintName, IgnoredUnlessCrateSpecified, OverruledAttributeLint, RemovedLint, + RenamedLint, RenamedLintSuggestion, UnknownLint, UnknownLintSuggestion, }, }; use rustc_ast as ast; @@ -915,18 +915,26 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { _ if !self.warn_about_weird_lints => {} - CheckLintNameResult::Warning(msg, renamed) => { + CheckLintNameResult::Renamed(new_name) => { let suggestion = - renamed.as_ref().map(|replace| RenamedOrRemovedLintSuggestion { - suggestion: sp, - replace: replace.as_str(), - }); + RenamedLintSuggestion { suggestion: sp, replace: new_name.as_str() }; + let name = tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name); self.emit_spanned_lint( RENAMED_AND_REMOVED_LINTS, sp.into(), - RenamedOrRemovedLint { msg, suggestion }, + RenamedLint { name: name.as_str(), suggestion }, ); } + + CheckLintNameResult::Removed(reason) => { + let name = tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name); + self.emit_spanned_lint( + RENAMED_AND_REMOVED_LINTS, + sp.into(), + RemovedLint { name: name.as_str(), reason: reason.as_str() }, + ); + } + CheckLintNameResult::NoLint(suggestion) => { let name = if let Some(tool_ident) = tool_ident { format!("{}::{}", tool_ident.name, name) @@ -945,7 +953,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { // If this lint was renamed, apply the new lint instead of ignoring the attribute. // This happens outside of the match because the new lint should be applied even if // we don't warn about the name change. - if let CheckLintNameResult::Warning(_, Some(new_name)) = lint_result { + if let CheckLintNameResult::Renamed(new_name) = lint_result { // Ignore any errors or warnings that happen because the new name is inaccurate // NOTE: `new_name` already includes the tool name, so we don't have to add it again. if let CheckLintNameResult::Ok(ids) = diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 993c576d6970..0e942d774a7f 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1012,23 +1012,29 @@ pub struct DeprecatedLintName<'a> { pub replace: &'a str, } -// FIXME: Non-translatable msg #[derive(LintDiagnostic)] -#[diag(lint_renamed_or_removed_lint)] -pub struct RenamedOrRemovedLint<'a> { - pub msg: &'a str, +#[diag(lint_renamed_lint)] +pub struct RenamedLint<'a> { + pub name: &'a str, #[subdiagnostic] - pub suggestion: Option>, + pub suggestion: RenamedLintSuggestion<'a>, } #[derive(Subdiagnostic)] #[suggestion(lint_suggestion, code = "{replace}", applicability = "machine-applicable")] -pub struct RenamedOrRemovedLintSuggestion<'a> { +pub struct RenamedLintSuggestion<'a> { #[primary_span] pub suggestion: Span, pub replace: &'a str, } +#[derive(LintDiagnostic)] +#[diag(lint_removed_lint)] +pub struct RemovedLint<'a> { + pub name: &'a str, + pub reason: &'a str, +} + #[derive(LintDiagnostic)] #[diag(lint_unknown_lint)] pub struct UnknownLint { From 73152a3efb29807dffeb12456f5aedf79dfb308a Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Thu, 24 Aug 2023 00:23:01 +0100 Subject: [PATCH 158/197] refactor: use references to reduce unnecessary clones --- compiler/rustc_lint/src/context.rs | 15 ++++++----- compiler/rustc_lint/src/errors.rs | 40 +++++++++++++++--------------- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 9a0f3ca51181..9dfde84b5526 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -343,33 +343,32 @@ impl LintStore { sess.emit_err(UnsupportedGroup { lint_group: crate::WARNINGS.name_lower() }); return; } - let lint_name = lint_name.to_string(); match self.check_lint_name(lint_name_only, tool_name, registered_tools) { CheckLintNameResult::Renamed(replace) => { sess.emit_warning(CheckNameRenamed { - lint_name: lint_name.clone(), - replace, + lint_name, + replace: &replace, sub: RequestedLevel { level, lint_name }, }); } CheckLintNameResult::Removed(reason) => { sess.emit_warning(CheckNameRemoved { - lint_name: lint_name.clone(), - reason, + lint_name, + reason: &reason, sub: RequestedLevel { level, lint_name }, }); } CheckLintNameResult::NoLint(suggestion) => { sess.emit_err(CheckNameUnknown { - lint_name: lint_name.clone(), + lint_name, suggestion, sub: RequestedLevel { level, lint_name }, }); } CheckLintNameResult::Tool(Err((Some(_), new_name))) => { sess.emit_warning(CheckNameDeprecated { - lint_name: lint_name.clone(), - new_name, + lint_name, + new_name: &new_name, sub: RequestedLevel { level, lint_name }, }); } diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index e63741820aff..607875b3faa2 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -91,9 +91,9 @@ pub struct BuiltinEllipsisInclusiveRangePatterns { #[derive(Subdiagnostic)] #[note(lint_requested_level)] -pub struct RequestedLevel { +pub struct RequestedLevel<'a> { pub level: Level, - pub lint_name: String, + pub lint_name: &'a str, } #[derive(Diagnostic)] @@ -102,13 +102,13 @@ pub struct UnsupportedGroup { pub lint_group: String, } -pub struct CheckNameUnknown { - pub lint_name: String, +pub struct CheckNameUnknown<'a> { + pub lint_name: &'a str, pub suggestion: Option, - pub sub: RequestedLevel, + pub sub: RequestedLevel<'a>, } -impl IntoDiagnostic<'_> for CheckNameUnknown { +impl IntoDiagnostic<'_> for CheckNameUnknown<'_> { fn into_diagnostic( self, handler: &Handler, @@ -127,35 +127,35 @@ impl IntoDiagnostic<'_> for CheckNameUnknown { #[derive(Diagnostic)] #[diag(lint_check_name_unknown_tool, code = "E0602")] -pub struct CheckNameUnknownTool { +pub struct CheckNameUnknownTool<'a> { pub tool_name: Symbol, #[subdiagnostic] - pub sub: RequestedLevel, + pub sub: RequestedLevel<'a>, } #[derive(Diagnostic)] #[diag(lint_check_name_renamed)] -pub struct CheckNameRenamed { - pub lint_name: String, - pub replace: String, +pub struct CheckNameRenamed<'a> { + pub lint_name: &'a str, + pub replace: &'a str, #[subdiagnostic] - pub sub: RequestedLevel, + pub sub: RequestedLevel<'a>, } #[derive(Diagnostic)] #[diag(lint_check_name_removed)] -pub struct CheckNameRemoved { - pub lint_name: String, - pub reason: String, +pub struct CheckNameRemoved<'a> { + pub lint_name: &'a str, + pub reason: &'a str, #[subdiagnostic] - pub sub: RequestedLevel, + pub sub: RequestedLevel<'a>, } #[derive(Diagnostic)] #[diag(lint_check_name_deprecated)] -pub struct CheckNameDeprecated { - pub lint_name: String, - pub new_name: String, +pub struct CheckNameDeprecated<'a> { + pub lint_name: &'a str, + pub new_name: &'a str, #[subdiagnostic] - pub sub: RequestedLevel, + pub sub: RequestedLevel<'a>, } From 868706d9b50ddf27995a9ee4d863e163b78b7365 Mon Sep 17 00:00:00 2001 From: Frank King Date: Wed, 23 Aug 2023 20:53:47 +0800 Subject: [PATCH 159/197] Parse unnamed fields and anonymous structs or unions Anonymous structs or unions are only allowed in struct field definitions. Co-authored-by: carbotaniuman <41451839+carbotaniuman@users.noreply.github.com> --- compiler/rustc_ast/src/ast.rs | 4 + compiler/rustc_ast/src/mut_visit.rs | 3 + compiler/rustc_ast/src/token.rs | 2 + compiler/rustc_ast/src/visit.rs | 3 + compiler/rustc_ast_lowering/src/lib.rs | 12 +++ compiler/rustc_ast_passes/messages.ftl | 12 +++ .../rustc_ast_passes/src/ast_validation.rs | 85 ++++++++++++++++++- compiler/rustc_ast_passes/src/errors.rs | 27 ++++++ compiler/rustc_ast_passes/src/feature_gate.rs | 1 + compiler/rustc_ast_pretty/src/pprust/state.rs | 8 ++ .../rustc_ast_pretty/src/pprust/state/item.rs | 6 +- compiler/rustc_feature/src/active.rs | 2 + compiler/rustc_parse/src/parser/item.rs | 8 +- compiler/rustc_parse/src/parser/ty.rs | 46 ++++++++++ compiler/rustc_passes/src/hir_stats.rs | 2 + compiler/rustc_span/src/symbol.rs | 1 + src/tools/rustfmt/src/types.rs | 2 + .../rustfmt/tests/target/anonymous-types.rs | 19 +++++ .../feature-gate-unnamed_fields.rs | 26 ++++++ .../feature-gate-unnamed_fields.stderr | 84 ++++++++++++++++++ .../ui/parser/keyword-union-as-identifier.rs | 72 ++++++++++++++++ .../restrict_anonymous_structs.rs | 37 ++++++++ .../restrict_anonymous_structs.stderr | 78 +++++++++++++++++ .../restrict_anonymous_unions.rs | 37 ++++++++ .../restrict_anonymous_unions.stderr | 78 +++++++++++++++++ 25 files changed, 650 insertions(+), 5 deletions(-) create mode 100644 src/tools/rustfmt/tests/target/anonymous-types.rs create mode 100644 tests/ui/feature-gates/feature-gate-unnamed_fields.rs create mode 100644 tests/ui/feature-gates/feature-gate-unnamed_fields.stderr create mode 100644 tests/ui/parser/keyword-union-as-identifier.rs create mode 100644 tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs create mode 100644 tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr create mode 100644 tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs create mode 100644 tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 58725a08c7c5..395540764ea0 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2092,6 +2092,10 @@ pub enum TyKind { Never, /// A tuple (`(A, B, C, D,...)`). Tup(ThinVec>), + /// An anonymous struct type i.e. `struct { foo: Type }` + AnonStruct(ThinVec), + /// An anonymous union type i.e. `union { bar: Type }` + AnonUnion(ThinVec), /// A path (`module::module::...::Type`), optionally /// "qualified", e.g., ` as SomeTrait>::SomeType`. /// diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index bae3979fbf9f..55a1772adb1d 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -509,6 +509,9 @@ pub fn noop_visit_ty(ty: &mut P, vis: &mut T) { visit_vec(bounds, |bound| vis.visit_param_bound(bound)); } TyKind::MacCall(mac) => vis.visit_mac_call(mac), + TyKind::AnonStruct(fields) | TyKind::AnonUnion(fields) => { + fields.flat_map_in_place(|field| vis.flat_map_field_def(field)); + } } vis.visit_span(span); visit_lazy_tts(tokens, vis); diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index f4ad0efa4234..300b1486f9ba 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -486,6 +486,8 @@ impl Token { Lt | BinOp(Shl) | // associated path ModSep => true, // global path Interpolated(ref nt) => matches!(**nt, NtTy(..) | NtPath(..)), + // For anonymous structs or unions, which only appear in specific positions + // (type of struct fields or union fields), we don't consider them as regular types _ => false, } } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 6d474de2d15f..ddbbf5a10bcd 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -438,6 +438,9 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {} TyKind::MacCall(mac) => visitor.visit_mac_call(mac), TyKind::Never | TyKind::CVarArgs => {} + TyKind::AnonStruct(ref fields, ..) | TyKind::AnonUnion(ref fields, ..) => { + walk_list!(visitor, visit_field_def, fields) + } } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 0aeff22ca9f8..79ed6b9b2aac 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1293,6 +1293,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { TyKind::Err => { hir::TyKind::Err(self.tcx.sess.delay_span_bug(t.span, "TyKind::Err lowered")) } + // FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] + TyKind::AnonStruct(ref _fields) => hir::TyKind::Err( + self.tcx.sess.span_err(t.span, "anonymous structs are unimplemented"), + ), + // FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] + TyKind::AnonUnion(ref _fields) => hir::TyKind::Err( + self.tcx.sess.span_err(t.span, "anonymous unions are unimplemented"), + ), TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)), TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), TyKind::Ref(region, mt) => { diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 2f0ac0c2b198..429dc2c94a9c 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -1,3 +1,7 @@ +ast_passes_anon_struct_or_union_not_allowed = + anonymous {$struct_or_union}s are not allowed outside of unnamed struct or union fields + .label = anonymous {$struct_or_union} declared here + ast_passes_assoc_const_without_body = associated constant in `impl` without body .suggestion = provide a definition for the constant @@ -162,6 +166,14 @@ ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation} ast_passes_invalid_label = invalid label name `{$name}` +ast_passes_invalid_unnamed_field = + unnamed fields are not allowed outside of structs or unions + .label = unnamed field declared here + +ast_passes_invalid_unnamed_field_ty = + unnamed fields can only have struct or union types + .label = not a struct or union + ast_passes_item_underscore = `{$kind}` items in this context need a name .label = `_` is not a valid name for this `{$kind}` item diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index af594a00705f..371ae7947ca0 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -219,10 +219,27 @@ impl<'a> AstValidator<'a> { } } } + TyKind::AnonStruct(ref fields, ..) | TyKind::AnonUnion(ref fields, ..) => { + walk_list!(self, visit_field_def, fields) + } _ => visit::walk_ty(self, t), } } + fn visit_struct_field_def(&mut self, field: &'a FieldDef) { + if let Some(ident) = field.ident && + ident.name == kw::Underscore { + self.check_unnamed_field_ty(&field.ty, ident.span); + self.visit_vis(&field.vis); + self.visit_ident(ident); + self.visit_ty_common(&field.ty); + self.walk_ty(&field.ty); + walk_list!(self, visit_attribute, &field.attrs); + } else { + self.visit_field_def(field); + } + } + fn err_handler(&self) -> &rustc_errors::Handler { &self.session.diagnostic() } @@ -260,6 +277,42 @@ impl<'a> AstValidator<'a> { } } + fn check_unnamed_field_ty(&self, ty: &Ty, span: Span) { + if matches!( + &ty.kind, + // We already checked for `kw::Underscore` before calling this function, + // so skip the check + TyKind::AnonStruct(..) | TyKind::AnonUnion(..) + // If the anonymous field contains a Path as type, we can't determine + // if the path is a valid struct or union, so skip the check + | TyKind::Path(..) + ) { + return; + } + self.err_handler().emit_err(errors::InvalidUnnamedFieldTy { span, ty_span: ty.span }); + } + + fn deny_anon_struct_or_union(&self, ty: &Ty) { + let struct_or_union = match &ty.kind { + TyKind::AnonStruct(..) => "struct", + TyKind::AnonUnion(..) => "union", + _ => return, + }; + self.err_handler() + .emit_err(errors::AnonStructOrUnionNotAllowed { struct_or_union, span: ty.span }); + } + + fn deny_unnamed_field(&self, field: &FieldDef) { + if let Some(ident) = field.ident && + ident.name == kw::Underscore { + self.err_handler() + .emit_err(errors::InvalidUnnamedField { + span: field.span, + ident_span: ident.span + }); + } + } + fn check_trait_fn_not_const(&self, constness: Const) { if let Const::Yes(span) = constness { self.session.emit_err(errors::TraitFnConst { span }); @@ -785,6 +838,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_ty(&mut self, ty: &'a Ty) { self.visit_ty_common(ty); + self.deny_anon_struct_or_union(ty); self.walk_ty(ty) } @@ -799,6 +853,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_field_def(&mut self, field: &'a FieldDef) { + self.deny_unnamed_field(field); visit::walk_field_def(self, field) } @@ -991,10 +1046,38 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_mod_file_item_asciionly(item.ident); } } - ItemKind::Union(vdata, ..) => { + ItemKind::Struct(vdata, generics) => match vdata { + // Duplicating the `Visitor` logic allows catching all cases + // of `Anonymous(Struct, Union)` outside of a field struct or union. + // + // Inside `visit_ty` the validator catches every `Anonymous(Struct, Union)` it + // encounters, and only on `ItemKind::Struct` and `ItemKind::Union` + // it uses `visit_ty_common`, which doesn't contain that specific check. + VariantData::Struct(fields, ..) => { + self.visit_vis(&item.vis); + self.visit_ident(item.ident); + self.visit_generics(generics); + walk_list!(self, visit_struct_field_def, fields); + walk_list!(self, visit_attribute, &item.attrs); + return; + } + _ => {} + }, + ItemKind::Union(vdata, generics) => { if vdata.fields().is_empty() { self.err_handler().emit_err(errors::FieldlessUnion { span: item.span }); } + match vdata { + VariantData::Struct(fields, ..) => { + self.visit_vis(&item.vis); + self.visit_ident(item.ident); + self.visit_generics(generics); + walk_list!(self, visit_struct_field_def, fields); + walk_list!(self, visit_attribute, &item.attrs); + return; + } + _ => {} + } } ItemKind::Const(box ConstItem { defaultness, expr: None, .. }) => { self.check_defaultness(item.span, *defaultness); diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index ab8015c4a43b..d706cb170e83 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -701,3 +701,30 @@ pub struct ConstraintOnNegativeBound { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(ast_passes_invalid_unnamed_field_ty)] +pub struct InvalidUnnamedFieldTy { + #[primary_span] + pub span: Span, + #[label] + pub ty_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_invalid_unnamed_field)] +pub struct InvalidUnnamedField { + #[primary_span] + pub span: Span, + #[label] + pub ident_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_anon_struct_or_union_not_allowed)] +pub struct AnonStructOrUnionNotAllowed { + #[primary_span] + #[label] + pub span: Span, + pub struct_or_union: &'static str, +} diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index c4efad7caf26..036c53112416 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -570,6 +570,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { gate_all!(builtin_syntax, "`builtin #` syntax is unstable"); gate_all!(explicit_tail_calls, "`become` expression is experimental"); gate_all!(generic_const_items, "generic const items are experimental"); + gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented"); if !visitor.features.negative_bounds { for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() { diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 068b255e9f28..187c5bee8438 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1053,6 +1053,14 @@ impl<'a> State<'a> { } self.pclose(); } + ast::TyKind::AnonStruct(fields) => { + self.head("struct"); + self.print_record_struct_body(&fields, ty.span); + } + ast::TyKind::AnonUnion(fields) => { + self.head("union"); + self.print_record_struct_body(&fields, ty.span); + } ast::TyKind::Paren(typ) => { self.popen(); self.print_type(typ); diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index d27a44f1206d..3393f034bc3b 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -443,7 +443,11 @@ impl<'a> State<'a> { } } - fn print_record_struct_body(&mut self, fields: &[ast::FieldDef], span: rustc_span::Span) { + pub(crate) fn print_record_struct_body( + &mut self, + fields: &[ast::FieldDef], + span: rustc_span::Span, + ) { self.nbsp(); self.bopen(); diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 898f5fd3b709..cde9dbd8e923 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -581,6 +581,8 @@ declare_features! ( (active, type_privacy_lints, "1.72.0", Some(48054), None), /// Enables rustc to generate code that instructs libstd to NOT ignore SIGPIPE. (active, unix_sigpipe, "1.65.0", Some(97889), None), + /// Allows unnamed fields of struct and union type + (incomplete, unnamed_fields, "CURRENT_RUSTC_VERSION", Some(49804), None), /// Allows unsized fn parameters. (active, unsized_fn_params, "1.49.0", Some(48055), None), /// Allows unsized rvalues at arguments and parameters. diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 24c65d061f95..5db31c234783 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1594,7 +1594,7 @@ impl<'a> Parser<'a> { Ok((class_name, ItemKind::Union(vdata, generics))) } - fn parse_record_struct_body( + pub(crate) fn parse_record_struct_body( &mut self, adt_ty: &str, ident_span: Span, @@ -1869,7 +1869,7 @@ impl<'a> Parser<'a> { } } self.expect_field_ty_separator()?; - let ty = self.parse_ty()?; + let ty = self.parse_ty_for_field_def()?; if self.token.kind == token::Colon && self.look_ahead(1, |tok| tok.kind != token::Colon) { self.sess.emit_err(errors::SingleColonStructType { span: self.token.span }); } @@ -1894,7 +1894,9 @@ impl<'a> Parser<'a> { /// for better diagnostics and suggestions. fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> { let (ident, is_raw) = self.ident_or_err(true)?; - if !is_raw && ident.is_reserved() { + if ident.name == kw::Underscore { + self.sess.gated_spans.gate(sym::unnamed_fields, lo); + } else if !is_raw && ident.is_reserved() { let snapshot = self.create_snapshot_for_diagnostic(); let err = if self.check_fn_front_matter(false, Case::Sensitive) { let inherited_vis = Visibility { diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 3bb50b05aa34..fa81596cc96d 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -136,6 +136,17 @@ impl<'a> Parser<'a> { ) } + /// Parse a type suitable for a field defintion. + /// The difference from `parse_ty` is that this version + /// allows anonymous structs and unions. + pub fn parse_ty_for_field_def(&mut self) -> PResult<'a, P> { + if self.can_begin_anon_struct_or_union() { + self.parse_anon_struct_or_union() + } else { + self.parse_ty() + } + } + /// Parse a type suitable for a function or function pointer parameter. /// The difference from `parse_ty` is that this version allows `...` /// (`CVarArgs`) at the top level of the type. @@ -336,6 +347,36 @@ impl<'a> Parser<'a> { if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) } } + /// Parse an anonymous struct or union (only for field definitions): + /// ```ignore (feature-not-ready) + /// #[repr(C)] + /// struct Foo { + /// _: struct { // anonymous struct + /// x: u32, + /// y: f64, + /// } + /// _: union { // anonymous union + /// z: u32, + /// w: f64, + /// } + /// } + /// ``` + fn parse_anon_struct_or_union(&mut self) -> PResult<'a, P> { + assert!(self.token.is_keyword(kw::Union) || self.token.is_keyword(kw::Struct)); + let is_union = self.token.is_keyword(kw::Union); + + let lo = self.token.span; + self.bump(); + + let (fields, _recovered) = + self.parse_record_struct_body(if is_union { "union" } else { "struct" }, lo, false)?; + let span = lo.to(self.prev_token.span); + self.sess.gated_spans.gate(sym::unnamed_fields, span); + // These can be rejected during AST validation in `deny_anon_struct_or_union`. + let kind = if is_union { TyKind::AnonUnion(fields) } else { TyKind::AnonStruct(fields) }; + Ok(self.mk_ty(span, kind)) + } + /// Parses either: /// - `(TYPE)`, a parenthesized type. /// - `(TYPE,)`, a tuple with a single field of type TYPE. @@ -696,6 +737,11 @@ impl<'a> Parser<'a> { Ok(bounds) } + pub(super) fn can_begin_anon_struct_or_union(&mut self) -> bool { + (self.token.is_keyword(kw::Struct) || self.token.is_keyword(kw::Union)) + && self.look_ahead(1, |t| t == &token::OpenDelim(Delimiter::Brace)) + } + /// Can the current token begin a bound? fn can_begin_bound(&mut self) -> bool { // This needs to be synchronized with `TokenKind::can_begin_bound`. diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 5aa8aef6a859..24087a4eabbc 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -587,6 +587,8 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { BareFn, Never, Tup, + AnonStruct, + AnonUnion, Path, TraitObject, ImplTrait, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 745a3590720a..539fc9da1a87 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1603,6 +1603,7 @@ symbols! { unix_sigpipe, unlikely, unmarked_api, + unnamed_fields, unpin, unreachable, unreachable_2015, diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 18a08f17ba02..5e8edd8f8bf4 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -819,6 +819,8 @@ impl Rewrite for ast::Ty { ast::TyKind::Tup(ref items) => { rewrite_tuple(context, items.iter(), self.span, shape, items.len() == 1) } + ast::TyKind::AnonStruct(_) => Some(context.snippet(self.span).to_owned()), + ast::TyKind::AnonUnion(_) => Some(context.snippet(self.span).to_owned()), ast::TyKind::Path(ref q_self, ref path) => { rewrite_path(context, PathContext::Type, q_self, path, shape) } diff --git a/src/tools/rustfmt/tests/target/anonymous-types.rs b/src/tools/rustfmt/tests/target/anonymous-types.rs new file mode 100644 index 000000000000..8e08c314ed1f --- /dev/null +++ b/src/tools/rustfmt/tests/target/anonymous-types.rs @@ -0,0 +1,19 @@ +// Test for issue 85480 +// Pretty print anonymous struct and union types + +// pp-exact +// pretty-compare-only + +struct Foo { + _: union { + _: struct { + a: u8, + b: u16, + }, + c: u32, + }, + d: u64, + e: f32, +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-unnamed_fields.rs b/tests/ui/feature-gates/feature-gate-unnamed_fields.rs new file mode 100644 index 000000000000..4bbd0c83bfbc --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unnamed_fields.rs @@ -0,0 +1,26 @@ +struct Foo { + foo: u8, + _: union { //~ ERROR unnamed fields are not yet fully implemented [E0658] + //~^ ERROR unnamed fields are not yet fully implemented [E0658] + //~| ERROR anonymous unions are unimplemented + bar: u8, + baz: u16 + } +} + +union Bar { + foobar: u8, + _: struct { //~ ERROR unnamed fields are not yet fully implemented [E0658] + //~^ ERROR unnamed fields are not yet fully implemented [E0658] + //~| ERROR anonymous structs are unimplemented + foobaz: u8, + barbaz: u16 + } +} + +struct S; +struct Baz { + _: S //~ ERROR unnamed fields are not yet fully implemented [E0658] +} + +fn main(){} diff --git a/tests/ui/feature-gates/feature-gate-unnamed_fields.stderr b/tests/ui/feature-gates/feature-gate-unnamed_fields.stderr new file mode 100644 index 000000000000..f026f2c3600b --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unnamed_fields.stderr @@ -0,0 +1,84 @@ +error[E0658]: unnamed fields are not yet fully implemented + --> $DIR/feature-gate-unnamed_fields.rs:3:5 + | +LL | _: union { + | ^ + | + = note: see issue #49804 for more information + = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable + +error[E0658]: unnamed fields are not yet fully implemented + --> $DIR/feature-gate-unnamed_fields.rs:3:8 + | +LL | _: union { + | ________^ +LL | | +LL | | +LL | | bar: u8, +LL | | baz: u16 +LL | | } + | |_____^ + | + = note: see issue #49804 for more information + = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable + +error[E0658]: unnamed fields are not yet fully implemented + --> $DIR/feature-gate-unnamed_fields.rs:13:5 + | +LL | _: struct { + | ^ + | + = note: see issue #49804 for more information + = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable + +error[E0658]: unnamed fields are not yet fully implemented + --> $DIR/feature-gate-unnamed_fields.rs:13:8 + | +LL | _: struct { + | ________^ +LL | | +LL | | +LL | | foobaz: u8, +LL | | barbaz: u16 +LL | | } + | |_____^ + | + = note: see issue #49804 for more information + = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable + +error[E0658]: unnamed fields are not yet fully implemented + --> $DIR/feature-gate-unnamed_fields.rs:23:5 + | +LL | _: S + | ^ + | + = note: see issue #49804 for more information + = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable + +error: anonymous unions are unimplemented + --> $DIR/feature-gate-unnamed_fields.rs:3:8 + | +LL | _: union { + | ________^ +LL | | +LL | | +LL | | bar: u8, +LL | | baz: u16 +LL | | } + | |_____^ + +error: anonymous structs are unimplemented + --> $DIR/feature-gate-unnamed_fields.rs:13:8 + | +LL | _: struct { + | ________^ +LL | | +LL | | +LL | | foobaz: u8, +LL | | barbaz: u16 +LL | | } + | |_____^ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/parser/keyword-union-as-identifier.rs b/tests/ui/parser/keyword-union-as-identifier.rs new file mode 100644 index 000000000000..7062557d7312 --- /dev/null +++ b/tests/ui/parser/keyword-union-as-identifier.rs @@ -0,0 +1,72 @@ +// check-pass + +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] + +mod union { + type union = i32; + + pub struct Bar { + pub union: union, + } + + pub fn union() -> Bar { + Bar { + union: 5 + } + } +} + +mod struct_union { + pub struct union { + pub union: u32 + } + static union: union = union { union: 0 }; + + impl union { + pub fn union<'union>() -> &'union union { + &union + } + } + impl union {} + trait Foo {} + impl Foo for union {} + trait Bar { + fn bar() {} + } + impl Bar for union {} +} + +mod union_union { + pub union union { + pub union: u32 + } + const union: union = union { union: 0 }; + impl union { + pub fn union() -> union { + union + } + } +} + +mod trait_union { + pub trait union { + fn union() {} + } + impl union for () {} +} + +macro_rules! ty { + ($ty:ty { $($field:ident:$field_ty:ty)* }) => {}; +} + +fn main() { + let union = union::union(); + let _ = union.union; + let _ = struct_union::union::union().union; + let union = union_union::union::union(); + let _ = unsafe { union.union }; + <() as trait_union::union>::union(); + ty!(union {}); + ty!(union { union: union }); +} diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs new file mode 100644 index 000000000000..192bbba5a5b3 --- /dev/null +++ b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs @@ -0,0 +1,37 @@ +#![allow(incomplete_features)] +#![feature(unnamed_fields)] + +struct F { + field: struct { field: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields + //~^ ERROR anonymous structs are unimplemented + _: struct { field: u8 }, + //~^ ERROR anonymous structs are unimplemented +} + +struct G { + _: (u8, u8), //~ ERROR unnamed fields can only have struct or union types +} + +union H { + field: struct { field: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields + //~^ ERROR anonymous structs are unimplemented + _: struct { field: u8 }, + //~^ ERROR anonymous structs are unimplemented +} + +union I { + _: (u8, u8), //~ ERROR unnamed fields can only have struct or union types +} + +enum K { + M { + _ : struct { field: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields + //~^ ERROR unnamed fields are not allowed outside of structs or unions + //~| ERROR anonymous structs are unimplemented + }, + N { + _ : u8, //~ ERROR unnamed fields are not allowed outside of structs or unions + } +} + +fn main() {} diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr new file mode 100644 index 000000000000..fd731766c01f --- /dev/null +++ b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr @@ -0,0 +1,78 @@ +error: anonymous structs are not allowed outside of unnamed struct or union fields + --> $DIR/restrict_anonymous_structs.rs:5:12 + | +LL | field: struct { field: u8 }, + | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here + +error: unnamed fields can only have struct or union types + --> $DIR/restrict_anonymous_structs.rs:12:5 + | +LL | _: (u8, u8), + | ^ -------- not a struct or union + +error: anonymous structs are not allowed outside of unnamed struct or union fields + --> $DIR/restrict_anonymous_structs.rs:16:12 + | +LL | field: struct { field: u8 }, + | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here + +error: unnamed fields can only have struct or union types + --> $DIR/restrict_anonymous_structs.rs:23:5 + | +LL | _: (u8, u8), + | ^ -------- not a struct or union + +error: unnamed fields are not allowed outside of structs or unions + --> $DIR/restrict_anonymous_structs.rs:28:9 + | +LL | _ : struct { field: u8 }, + | -^^^^^^^^^^^^^^^^^^^^^^^ + | | + | unnamed field declared here + +error: anonymous structs are not allowed outside of unnamed struct or union fields + --> $DIR/restrict_anonymous_structs.rs:28:13 + | +LL | _ : struct { field: u8 }, + | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here + +error: unnamed fields are not allowed outside of structs or unions + --> $DIR/restrict_anonymous_structs.rs:33:9 + | +LL | _ : u8, + | -^^^^^ + | | + | unnamed field declared here + +error: anonymous structs are unimplemented + --> $DIR/restrict_anonymous_structs.rs:5:12 + | +LL | field: struct { field: u8 }, + | ^^^^^^^^^^^^^^^^^^^^ + +error: anonymous structs are unimplemented + --> $DIR/restrict_anonymous_structs.rs:7:8 + | +LL | _: struct { field: u8 }, + | ^^^^^^^^^^^^^^^^^^^^ + +error: anonymous structs are unimplemented + --> $DIR/restrict_anonymous_structs.rs:16:12 + | +LL | field: struct { field: u8 }, + | ^^^^^^^^^^^^^^^^^^^^ + +error: anonymous structs are unimplemented + --> $DIR/restrict_anonymous_structs.rs:18:8 + | +LL | _: struct { field: u8 }, + | ^^^^^^^^^^^^^^^^^^^^ + +error: anonymous structs are unimplemented + --> $DIR/restrict_anonymous_structs.rs:28:13 + | +LL | _ : struct { field: u8 }, + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs new file mode 100644 index 000000000000..c69266089bba --- /dev/null +++ b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs @@ -0,0 +1,37 @@ +#![allow(incomplete_features)] +#![feature(unnamed_fields)] + +struct F { + field: union { field: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields + //~^ ERROR anonymous unions are unimplemented + _: union { field: u8 }, + //~^ ERROR anonymous unions are unimplemented +} + +struct G { + _: (u8, u8), //~ ERROR unnamed fields can only have struct or union types +} + +union H { + field: union { field: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields + //~^ ERROR anonymous unions are unimplemented + _: union { field: u8 }, + //~^ ERROR anonymous unions are unimplemented +} + +union I { + _: (u8, u8), //~ ERROR unnamed fields can only have struct or union types +} + +enum K { + M { + _ : union { field: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields + //~^ ERROR unnamed fields are not allowed outside of structs or unions + //~| ERROR anonymous unions are unimplemented + }, + N { + _ : u8, //~ ERROR unnamed fields are not allowed outside of structs or unions + } +} + +fn main() {} diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr new file mode 100644 index 000000000000..c65cad775a90 --- /dev/null +++ b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr @@ -0,0 +1,78 @@ +error: anonymous unions are not allowed outside of unnamed struct or union fields + --> $DIR/restrict_anonymous_unions.rs:5:12 + | +LL | field: union { field: u8 }, + | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here + +error: unnamed fields can only have struct or union types + --> $DIR/restrict_anonymous_unions.rs:12:5 + | +LL | _: (u8, u8), + | ^ -------- not a struct or union + +error: anonymous unions are not allowed outside of unnamed struct or union fields + --> $DIR/restrict_anonymous_unions.rs:16:12 + | +LL | field: union { field: u8 }, + | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here + +error: unnamed fields can only have struct or union types + --> $DIR/restrict_anonymous_unions.rs:23:5 + | +LL | _: (u8, u8), + | ^ -------- not a struct or union + +error: unnamed fields are not allowed outside of structs or unions + --> $DIR/restrict_anonymous_unions.rs:28:9 + | +LL | _ : union { field: u8 }, + | -^^^^^^^^^^^^^^^^^^^^^^ + | | + | unnamed field declared here + +error: anonymous unions are not allowed outside of unnamed struct or union fields + --> $DIR/restrict_anonymous_unions.rs:28:13 + | +LL | _ : union { field: u8 }, + | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here + +error: unnamed fields are not allowed outside of structs or unions + --> $DIR/restrict_anonymous_unions.rs:33:9 + | +LL | _ : u8, + | -^^^^^ + | | + | unnamed field declared here + +error: anonymous unions are unimplemented + --> $DIR/restrict_anonymous_unions.rs:5:12 + | +LL | field: union { field: u8 }, + | ^^^^^^^^^^^^^^^^^^^ + +error: anonymous unions are unimplemented + --> $DIR/restrict_anonymous_unions.rs:7:8 + | +LL | _: union { field: u8 }, + | ^^^^^^^^^^^^^^^^^^^ + +error: anonymous unions are unimplemented + --> $DIR/restrict_anonymous_unions.rs:16:12 + | +LL | field: union { field: u8 }, + | ^^^^^^^^^^^^^^^^^^^ + +error: anonymous unions are unimplemented + --> $DIR/restrict_anonymous_unions.rs:18:8 + | +LL | _: union { field: u8 }, + | ^^^^^^^^^^^^^^^^^^^ + +error: anonymous unions are unimplemented + --> $DIR/restrict_anonymous_unions.rs:28:13 + | +LL | _ : union { field: u8 }, + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + From ec2c95e0932312c994ee8c5d52b7ee93b5ae65b9 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 23 Aug 2023 23:29:34 -0400 Subject: [PATCH 160/197] Accommodate tidy. In addition: Incorporated some review feedback (namely, removed a useless initial assignment to True that was never read), and unified code a bit more between bootstrap.py and download.rs (by using the same variable name for the same concept). --- src/bootstrap/bootstrap.py | 16 +++++++--------- src/bootstrap/download.rs | 4 ++-- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 588164e4a85c..9dbc87c337c7 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -650,26 +650,24 @@ class RustBuild(object): if self.get_toml("patch-binaries-for-nix", "build") == "false": return False - # Assume we should fix until we see evidence that it is not NixOS - should_fix_retval = True - # Use `/etc/os-release` instead of `/etc/NIXOS`. # The latter one does not exist on NixOS when using tmpfs as root. try: with open("/etc/os-release", "r") as f: - should_fix_retval = any(ln.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"') for ln in f) + is_nixos = any(ln.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"') + for ln in f) except FileNotFoundError: - should_fix_retval = False + is_nixos = False # If not on NixOS, then warn if user seems to be atop Nix shell - if not should_fix_retval: + if not is_nixos: in_nix_shell = os.getenv('IN_NIX_SHELL') if in_nix_shell: - print("The IN_NIX_SHELL environment variable is set to `{}`;".format(in_nix_shell), - "you may need to set `patch-binaries-for-nix=true` in your config.toml", + print("The IN_NIX_SHELL environment variable is `{}`;".format(in_nix_shell), + "you may need to set `patch-binaries-for-nix=true` in config.toml", file=sys.stderr) - return should_fix_retval + return is_nixos answer = self._should_fix_bins_and_dylibs = get_answer() if answer: diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs index bf8cb4bd7683..17c308e915b3 100644 --- a/src/bootstrap/download.rs +++ b/src/bootstrap/download.rs @@ -109,8 +109,8 @@ impl Config { let in_nix_shell = env::var("IN_NIX_SHELL"); if let Ok(in_nix_shell) = in_nix_shell { eprintln!( - "The IN_NIX_SHELL environment variable is set to `{in_nix_shell}`; \ - you may need to set `patch-binaries-for-nix=true` in your config.toml" + "The IN_NIX_SHELL environment variable is `{in_nix_shell}`; \ + you may need to set `patch-binaries-for-nix=true` in config.toml" ); } } From 9f1de6171c209ae20438827f42ffd625963adfc1 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Thu, 24 Aug 2023 06:31:10 +0200 Subject: [PATCH 161/197] Move extra_compiler_flags() to rustc_session To make it available to other parts of the compiler. --- compiler/rustc_driver_impl/src/lib.rs | 49 +-------------------------- compiler/rustc_session/src/utils.rs | 47 +++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 7bbed0877f07..841c626d0a33 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -140,12 +140,6 @@ pub const EXIT_FAILURE: i32 = 1; pub const DEFAULT_BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust/issues/new\ ?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md"; -const ICE_REPORT_COMPILER_FLAGS: &[&str] = &["-Z", "-C", "--crate-type"]; - -const ICE_REPORT_COMPILER_FLAGS_EXCLUDE: &[&str] = &["metadata", "extra-filename"]; - -const ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE: &[&str] = &["incremental"]; - pub fn abort_on_err(result: Result, sess: &Session) -> T { match result { Err(..) => { @@ -1250,47 +1244,6 @@ fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> { } } -/// Gets a list of extra command-line flags provided by the user, as strings. -/// -/// This function is used during ICEs to show more information useful for -/// debugging, since some ICEs only happens with non-default compiler flags -/// (and the users don't always report them). -fn extra_compiler_flags() -> Option<(Vec, bool)> { - let mut args = env::args_os().map(|arg| arg.to_string_lossy().to_string()).peekable(); - - let mut result = Vec::new(); - let mut excluded_cargo_defaults = false; - while let Some(arg) = args.next() { - if let Some(a) = ICE_REPORT_COMPILER_FLAGS.iter().find(|a| arg.starts_with(*a)) { - let content = if arg.len() == a.len() { - // A space-separated option, like `-C incremental=foo` or `--crate-type rlib` - match args.next() { - Some(arg) => arg.to_string(), - None => continue, - } - } else if arg.get(a.len()..a.len() + 1) == Some("=") { - // An equals option, like `--crate-type=rlib` - arg[a.len() + 1..].to_string() - } else { - // A non-space option, like `-Cincremental=foo` - arg[a.len()..].to_string() - }; - let option = content.split_once('=').map(|s| s.0).unwrap_or(&content); - if ICE_REPORT_COMPILER_FLAGS_EXCLUDE.iter().any(|exc| option == *exc) { - excluded_cargo_defaults = true; - } else { - result.push(a.to_string()); - match ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.iter().find(|s| option == **s) { - Some(s) => result.push(format!("{s}=[REDACTED]")), - None => result.push(content), - } - } - } - } - - if !result.is_empty() { Some((result, excluded_cargo_defaults)) } else { None } -} - /// Runs a closure and catches unwinds triggered by fatal errors. /// /// The compiler currently unwinds with a special sentinel value to abort @@ -1449,7 +1402,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info: None }; - if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() { + if let Some((flags, excluded_cargo_defaults)) = rustc_session::utils::extra_compiler_flags() { handler.emit_note(session_diagnostics::IceFlags { flags: flags.join(" ") }); if excluded_cargo_defaults { handler.emit_note(session_diagnostics::IceExcludeCargoDefaults); diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index 71f2591fe665..f76c69af526e 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -111,3 +111,50 @@ impl CanonicalizedPath { &self.original } } + +/// Gets a list of extra command-line flags provided by the user, as strings. +/// +/// This function is used during ICEs to show more information useful for +/// debugging, since some ICEs only happens with non-default compiler flags +/// (and the users don't always report them). +pub fn extra_compiler_flags() -> Option<(Vec, bool)> { + const ICE_REPORT_COMPILER_FLAGS: &[&str] = &["-Z", "-C", "--crate-type"]; + + const ICE_REPORT_COMPILER_FLAGS_EXCLUDE: &[&str] = &["metadata", "extra-filename"]; + + const ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE: &[&str] = &["incremental"]; + + let mut args = std::env::args_os().map(|arg| arg.to_string_lossy().to_string()).peekable(); + + let mut result = Vec::new(); + let mut excluded_cargo_defaults = false; + while let Some(arg) = args.next() { + if let Some(a) = ICE_REPORT_COMPILER_FLAGS.iter().find(|a| arg.starts_with(*a)) { + let content = if arg.len() == a.len() { + // A space-separated option, like `-C incremental=foo` or `--crate-type rlib` + match args.next() { + Some(arg) => arg.to_string(), + None => continue, + } + } else if arg.get(a.len()..a.len() + 1) == Some("=") { + // An equals option, like `--crate-type=rlib` + arg[a.len() + 1..].to_string() + } else { + // A non-space option, like `-Cincremental=foo` + arg[a.len()..].to_string() + }; + let option = content.split_once('=').map(|s| s.0).unwrap_or(&content); + if ICE_REPORT_COMPILER_FLAGS_EXCLUDE.iter().any(|exc| option == *exc) { + excluded_cargo_defaults = true; + } else { + result.push(a.to_string()); + match ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.iter().find(|s| option == **s) { + Some(s) => result.push(format!("{s}=[REDACTED]")), + None => result.push(content), + } + } + } + } + + if !result.is_empty() { Some((result, excluded_cargo_defaults)) } else { None } +} From 9ce35198bfd7a02248037d6afe31a652293a1fdf Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 6 Jul 2023 16:37:15 +0300 Subject: [PATCH 162/197] resolve: Pre-intern builtin name bindings --- compiler/rustc_resolve/src/ident.rs | 23 ++++++-------------- compiler/rustc_resolve/src/lib.rs | 33 +++++++++++++++++++++-------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 3bd9cea27ce6..669f79300644 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1,7 +1,5 @@ use rustc_ast::{self as ast, NodeId}; -use rustc_feature::is_builtin_attr_name; use rustc_hir::def::{DefKind, Namespace, NonMacroAttrKind, PartialRes, PerNS}; -use rustc_hir::PrimTy; use rustc_middle::bug; use rustc_middle::ty; use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK; @@ -9,7 +7,7 @@ use rustc_session::lint::BuiltinLintDiagnostics; use rustc_span::def_id::LocalDefId; use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext}; use rustc_span::symbol::{kw, Ident}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::Span; use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst}; use crate::late::{ @@ -562,17 +560,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { )), } } - Scope::BuiltinAttrs => { - if is_builtin_attr_name(ident.name) { - ok( - Res::NonMacroAttr(NonMacroAttrKind::Builtin(ident.name)), - DUMMY_SP, - this.arenas, - ) - } else { - Err(Determinacy::Determined) - } - } + Scope::BuiltinAttrs => match this.builtin_attrs_bindings.get(&ident.name) { + Some(binding) => Ok((*binding, Flags::empty())), + None => Err(Determinacy::Determined), + }, Scope::ExternPrelude => { match this.extern_prelude_get(ident, finalize.is_some()) { Some(binding) => Ok((binding, Flags::empty())), @@ -603,8 +594,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } result } - Scope::BuiltinTypes => match PrimTy::from_name(ident.name) { - Some(prim_ty) => ok(Res::PrimTy(prim_ty), DUMMY_SP, this.arenas), + Scope::BuiltinTypes => match this.builtin_types_bindings.get(&ident.name) { + Some(binding) => Ok((*binding, Flags::empty())), None => Err(Determinacy::Determined), }, }; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 76e54e60d142..c1bc27415711 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -39,13 +39,15 @@ use rustc_errors::{ Applicability, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, SubdiagnosticMessage, }; use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind}; +use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_fluent_macro::fluent_messages; use rustc_hir::def::Namespace::{self, *}; +use rustc_hir::def::NonMacroAttrKind; use rustc_hir::def::{self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, PartialRes, PerNS}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LocalDefIdSet}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::DefPathData; -use rustc_hir::TraitCandidate; +use rustc_hir::{PrimTy, TraitCandidate}; use rustc_index::IndexVec; use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_middle::metadata::ModChild; @@ -996,6 +998,8 @@ pub struct Resolver<'a, 'tcx> { arenas: &'a ResolverArenas<'a>, dummy_binding: NameBinding<'a>, + builtin_types_bindings: FxHashMap>, + builtin_attrs_bindings: FxHashMap>, used_extern_options: FxHashSet, macro_names: FxHashSet, @@ -1283,6 +1287,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let registered_tools = tcx.registered_tools(()); let features = tcx.features(); + let pub_vis = ty::Visibility::::Public; let mut resolver = Resolver { tcx, @@ -1330,14 +1335,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { macro_expanded_macro_export_errors: BTreeSet::new(), arenas, - dummy_binding: arenas.alloc_name_binding(NameBindingData { - kind: NameBindingKind::Res(Res::Err), - ambiguity: None, - warn_ambiguity: false, - expansion: LocalExpnId::ROOT, - span: DUMMY_SP, - vis: ty::Visibility::Public, - }), + dummy_binding: (Res::Err, pub_vis, DUMMY_SP, LocalExpnId::ROOT).to_name_binding(arenas), + builtin_types_bindings: PrimTy::ALL + .iter() + .map(|prim_ty| { + let binding = (Res::PrimTy(*prim_ty), pub_vis, DUMMY_SP, LocalExpnId::ROOT) + .to_name_binding(arenas); + (prim_ty.name(), binding) + }) + .collect(), + builtin_attrs_bindings: BUILTIN_ATTRIBUTES + .iter() + .map(|builtin_attr| { + let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(builtin_attr.name)); + let binding = + (res, pub_vis, DUMMY_SP, LocalExpnId::ROOT).to_name_binding(arenas); + (builtin_attr.name, binding) + }) + .collect(), used_extern_options: Default::default(), macro_names: FxHashSet::default(), From 2063067a8159d9527f98630af7d79397a358fcd3 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Thu, 24 Aug 2023 12:44:42 +0200 Subject: [PATCH 163/197] Fix ub-int-array test for big-endian platforms As of commit 7767cbb3b0b332fd0a46e347ea7f68f20109d768, the tests/ui/consts/const-eval/ub-int-array.rs test is failing on big-endian platforms (in particular s390x), as the stderr output contains a hex dump that depends on endianness. Since this point intentionally verifies the hex dump to check the uninitialized byte markers, I think we should not simply standardize away the hex dump as is done with some of the other tests in this directory. However, most of the test is already endian-independent. The only exception is one line of hex dump, which can also be made endian-independent by choosing appropriate constants in the source code. Since the 32bit and 64bit stderr outputs were already (and remain) identical, I've merged them and removed the stderr-per-bitwidth marker. Fixes (again) https://github.com/rust-lang/rust/issues/105383. --- .../const-eval/ub-int-array.64bit.stderr | 36 ------------------- tests/ui/consts/const-eval/ub-int-array.rs | 8 +++-- ...array.32bit.stderr => ub-int-array.stderr} | 8 ++--- 3 files changed, 10 insertions(+), 42 deletions(-) delete mode 100644 tests/ui/consts/const-eval/ub-int-array.64bit.stderr rename tests/ui/consts/const-eval/{ub-int-array.32bit.stderr => ub-int-array.stderr} (91%) diff --git a/tests/ui/consts/const-eval/ub-int-array.64bit.stderr b/tests/ui/consts/const-eval/ub-int-array.64bit.stderr deleted file mode 100644 index b3df41304ac3..000000000000 --- a/tests/ui/consts/const-eval/ub-int-array.64bit.stderr +++ /dev/null @@ -1,36 +0,0 @@ -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-int-array.rs:19:1 - | -LL | const UNINIT_INT_0: [u32; 3] = unsafe { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered uninitialized memory, but expected an integer - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 12, align: 4) { - __ __ __ __ 01 00 00 00 02 00 00 00 │ ░░░░........ - } - -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-int-array.rs:24:1 - | -LL | const UNINIT_INT_1: [u32; 3] = unsafe { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [1]: encountered uninitialized memory, but expected an integer - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 12, align: 4) { - 00 00 00 00 01 __ 01 01 02 02 __ 02 │ .....░....░. - } - -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-int-array.rs:42:1 - | -LL | const UNINIT_INT_2: [u32; 3] = unsafe { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [2]: encountered uninitialized memory, but expected an integer - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 12, align: 4) { - 00 00 00 00 01 01 01 01 02 02 02 __ │ ...........░ - } - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ub-int-array.rs b/tests/ui/consts/const-eval/ub-int-array.rs index adcf376b9c76..cde0749dc5fb 100644 --- a/tests/ui/consts/const-eval/ub-int-array.rs +++ b/tests/ui/consts/const-eval/ub-int-array.rs @@ -1,4 +1,3 @@ -// stderr-per-bitwidth //! Test the "array of int" fast path in validity checking, and in particular whether it //! points at the right array element. @@ -19,7 +18,12 @@ impl MaybeUninit { const UNINIT_INT_0: [u32; 3] = unsafe { //~^ ERROR it is undefined behavior to use this value //~| invalid value at [0] - mem::transmute([MaybeUninit { uninit: () }, MaybeUninit::new(1), MaybeUninit::new(2)]) + mem::transmute([ + MaybeUninit { uninit: () }, + // Constants chosen to achieve endianness-independent hex dump. + MaybeUninit::new(0x11111111), + MaybeUninit::new(0x22222222), + ]) }; const UNINIT_INT_1: [u32; 3] = unsafe { //~^ ERROR it is undefined behavior to use this value diff --git a/tests/ui/consts/const-eval/ub-int-array.32bit.stderr b/tests/ui/consts/const-eval/ub-int-array.stderr similarity index 91% rename from tests/ui/consts/const-eval/ub-int-array.32bit.stderr rename to tests/ui/consts/const-eval/ub-int-array.stderr index b3df41304ac3..c8efd7e1bd35 100644 --- a/tests/ui/consts/const-eval/ub-int-array.32bit.stderr +++ b/tests/ui/consts/const-eval/ub-int-array.stderr @@ -1,16 +1,16 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-int-array.rs:19:1 + --> $DIR/ub-int-array.rs:18:1 | LL | const UNINIT_INT_0: [u32; 3] = unsafe { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered uninitialized memory, but expected an integer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 12, align: 4) { - __ __ __ __ 01 00 00 00 02 00 00 00 │ ░░░░........ + __ __ __ __ 11 11 11 11 22 22 22 22 │ ░░░░...."""" } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-int-array.rs:24:1 + --> $DIR/ub-int-array.rs:28:1 | LL | const UNINIT_INT_1: [u32; 3] = unsafe { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [1]: encountered uninitialized memory, but expected an integer @@ -21,7 +21,7 @@ LL | const UNINIT_INT_1: [u32; 3] = unsafe { } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-int-array.rs:42:1 + --> $DIR/ub-int-array.rs:46:1 | LL | const UNINIT_INT_2: [u32; 3] = unsafe { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [2]: encountered uninitialized memory, but expected an integer From 05010b60740ca03e5bd566d656ce2ddfc1ac5e3e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 18 Aug 2023 14:21:12 +0800 Subject: [PATCH 164/197] resolve: Make bindings from extern prelude unique instead of creating a new every time a name from extern prelude is accessed --- .../rustc_resolve/src/build_reduced_graph.rs | 17 ++++---- compiler/rustc_resolve/src/lib.rs | 40 ++++++++++++++----- 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 127bec22c176..476b5f733a68 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -870,10 +870,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { let imported_binding = self.r.import(binding, import); if parent == self.r.graph_root { if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) { - if expansion != LocalExpnId::ROOT - && orig_name.is_some() - && entry.extern_crate_item.is_none() - { + if expansion != LocalExpnId::ROOT && orig_name.is_some() && !entry.is_import() { let msg = "macro-expanded `extern crate` items cannot \ shadow names passed with `--extern`"; self.r.tcx.sess.span_err(item.span, msg); @@ -884,10 +881,14 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { return; } } - let entry = self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert( - ExternPreludeEntry { extern_crate_item: None, introduced_by_item: true }, - ); - entry.extern_crate_item = Some(imported_binding); + let entry = self + .r + .extern_prelude + .entry(ident.normalize_to_macros_2_0()) + .or_insert(ExternPreludeEntry { binding: None, introduced_by_item: true }); + // Binding from `extern crate` item in source code can replace + // a binding from `--extern` on command line here. + entry.binding = Some(imported_binding); if orig_name.is_some() { entry.introduced_by_item = true; } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index c1bc27415711..2f104df02dce 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -885,10 +885,16 @@ impl<'a> NameBindingData<'a> { #[derive(Default, Clone)] struct ExternPreludeEntry<'a> { - extern_crate_item: Option>, + binding: Option>, introduced_by_item: bool, } +impl ExternPreludeEntry<'_> { + fn is_import(&self) -> bool { + self.binding.is_some_and(|binding| binding.is_import()) + } +} + /// Used for better errors for E0773 enum BuiltinMacroState { NotYetSeen(SyntaxExtensionKind), @@ -1742,7 +1748,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // but not introduce it, as used if they are accessed from lexical scope. if is_lexical_scope { if let Some(entry) = self.extern_prelude.get(&ident.normalize_to_macros_2_0()) { - if !entry.introduced_by_item && entry.extern_crate_item == Some(used_binding) { + if !entry.introduced_by_item && entry.binding == Some(used_binding) { return; } } @@ -1900,12 +1906,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Make sure `self`, `super` etc produce an error when passed to here. return None; } - self.extern_prelude.get(&ident.normalize_to_macros_2_0()).cloned().and_then(|entry| { - if let Some(binding) = entry.extern_crate_item { - if finalize && entry.introduced_by_item { - self.record_use(ident, binding, false); + + let norm_ident = ident.normalize_to_macros_2_0(); + let binding = self.extern_prelude.get(&norm_ident).cloned().and_then(|entry| { + Some(if let Some(binding) = entry.binding { + if finalize { + if !entry.is_import() { + self.crate_loader(|c| c.process_path_extern(ident.name, ident.span)); + } else if entry.introduced_by_item { + self.record_use(ident, binding, false); + } } - Some(binding) + binding } else { let crate_id = if finalize { let Some(crate_id) = @@ -1918,10 +1930,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.crate_loader(|c| c.maybe_process_path_extern(ident.name))? }; let crate_root = self.expect_module(crate_id.as_def_id()); - let vis = ty::Visibility::::Public; - Some((crate_root, vis, DUMMY_SP, LocalExpnId::ROOT).to_name_binding(self.arenas)) - } - }) + let vis = ty::Visibility::::Public; + (crate_root, vis, DUMMY_SP, LocalExpnId::ROOT).to_name_binding(self.arenas) + }) + }); + + if let Some(entry) = self.extern_prelude.get_mut(&norm_ident) { + entry.binding = binding; + } + + binding } /// Rustdoc uses this to resolve doc link paths in a recoverable way. `PathResult<'a>` From d1f8ea417c9276528f94766195337ef02fe39446 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 18 Aug 2023 17:18:26 +0800 Subject: [PATCH 165/197] resolve: Pre-intern tool module bindings --- compiler/rustc_resolve/src/ident.rs | 4 ++-- compiler/rustc_resolve/src/lib.rs | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 669f79300644..21bc54ede4db 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -572,8 +572,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { )), } } - Scope::ToolPrelude => match this.registered_tools.get(&ident).cloned() { - Some(ident) => ok(Res::ToolMod, ident.span, this.arenas), + Scope::ToolPrelude => match this.registered_tool_bindings.get(&ident) { + Some(binding) => Ok((*binding, Flags::empty())), None => Err(Determinacy::Determined), }, Scope::StdLibPrelude => { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 2f104df02dce..6c63abe47fbd 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1006,6 +1006,7 @@ pub struct Resolver<'a, 'tcx> { dummy_binding: NameBinding<'a>, builtin_types_bindings: FxHashMap>, builtin_attrs_bindings: FxHashMap>, + registered_tool_bindings: FxHashMap>, used_extern_options: FxHashSet, macro_names: FxHashSet, @@ -1359,6 +1360,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { (builtin_attr.name, binding) }) .collect(), + registered_tool_bindings: registered_tools + .iter() + .map(|ident| { + let binding = (Res::ToolMod, pub_vis, ident.span, LocalExpnId::ROOT) + .to_name_binding(arenas); + (*ident, binding) + }) + .collect(), used_extern_options: Default::default(), macro_names: FxHashSet::default(), From 02640f9d5985f87b4dccaf987e6c34d2b7a40fdd Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 18 Aug 2023 16:53:06 +0800 Subject: [PATCH 166/197] resolve: Make bindings for crate roots unique instead of creating a new every time `crate` or `$crate` is used --- compiler/rustc_resolve/src/ident.rs | 4 +--- compiler/rustc_resolve/src/lib.rs | 24 ++++++++++++++++++++++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 21bc54ede4db..7412b2d0581d 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -833,9 +833,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if ns == TypeNS { if ident.name == kw::Crate || ident.name == kw::DollarCrate { let module = self.resolve_crate_root(ident); - let binding = (module, Visibility::Public, module.span, LocalExpnId::ROOT) - .to_name_binding(self.arenas); - return Ok(binding); + return Ok(self.module_self_bindings[&module]); } else if ident.name == kw::Super || ident.name == kw::SelfLower { // FIXME: Implement these with renaming requirements so that e.g. // `use super;` doesn't work, but `use super as name;` does. diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 6c63abe47fbd..a2ee6c7b5293 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -519,7 +519,7 @@ struct ModuleData<'a> { /// All modules are unique and allocated on a same arena, /// so we can use referential equality to compare them. -#[derive(Clone, Copy, PartialEq)] +#[derive(Clone, Copy, PartialEq, Eq, Hash)] #[rustc_pass_by_value] struct Module<'a>(Interned<'a, ModuleData<'a>>); @@ -1007,6 +1007,9 @@ pub struct Resolver<'a, 'tcx> { builtin_types_bindings: FxHashMap>, builtin_attrs_bindings: FxHashMap>, registered_tool_bindings: FxHashMap>, + /// Binding for implicitly declared names that come with a module, + /// like `self` (not yet used), or `crate`/`$crate` (for root modules). + module_self_bindings: FxHashMap, NameBinding<'a>>, used_extern_options: FxHashSet, macro_names: FxHashSet, @@ -1122,6 +1125,7 @@ impl<'a> ResolverArenas<'a> { span: Span, no_implicit_prelude: bool, module_map: &mut FxHashMap>, + module_self_bindings: &mut FxHashMap, NameBinding<'a>>, ) -> Module<'a> { let module = Module(Interned::new_unchecked(self.modules.alloc(ModuleData::new( parent, @@ -1136,6 +1140,9 @@ impl<'a> ResolverArenas<'a> { } if let Some(def_id) = def_id { module_map.insert(def_id, module); + let vis = ty::Visibility::::Public; + let binding = (module, vis, module.span, LocalExpnId::ROOT).to_name_binding(self); + module_self_bindings.insert(module, binding); } module } @@ -1247,6 +1254,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ) -> Resolver<'a, 'tcx> { let root_def_id = CRATE_DEF_ID.to_def_id(); let mut module_map = FxHashMap::default(); + let mut module_self_bindings = FxHashMap::default(); let graph_root = arenas.new_module( None, ModuleKind::Def(DefKind::Mod, root_def_id, kw::Empty), @@ -1254,6 +1262,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { crate_span, attr::contains_name(attrs, sym::no_implicit_prelude), &mut module_map, + &mut module_self_bindings, ); let empty_module = arenas.new_module( None, @@ -1262,6 +1271,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { DUMMY_SP, true, &mut FxHashMap::default(), + &mut FxHashMap::default(), ); let mut visibilities = FxHashMap::default(); @@ -1368,6 +1378,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { (*ident, binding) }) .collect(), + module_self_bindings, used_extern_options: Default::default(), macro_names: FxHashSet::default(), @@ -1437,7 +1448,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { no_implicit_prelude: bool, ) -> Module<'a> { let module_map = &mut self.module_map; - self.arenas.new_module(parent, kind, expn_id, span, no_implicit_prelude, module_map) + let module_self_bindings = &mut self.module_self_bindings; + self.arenas.new_module( + parent, + kind, + expn_id, + span, + no_implicit_prelude, + module_map, + module_self_bindings, + ) } fn next_node_id(&mut self) -> NodeId { From 50bbe01de0abe85d1a4c07a2f163e540c1508f0d Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 22 Aug 2023 19:14:32 +0800 Subject: [PATCH 167/197] resolve: Make bindings for derive helper attributes unique instead of creating them every time such attribute is used --- compiler/rustc_resolve/src/diagnostics.rs | 2 +- compiler/rustc_resolve/src/ident.rs | 30 +++++++---------------- compiler/rustc_resolve/src/lib.rs | 2 +- compiler/rustc_resolve/src/macros.rs | 19 ++++++++++---- 4 files changed, 25 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index cd1a9b934cf5..d99fc07a7cd2 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1032,7 +1032,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .get(&expn_id) .into_iter() .flatten() - .map(|ident| TypoSuggestion::typo_from_ident(*ident, res)), + .map(|(ident, _)| TypoSuggestion::typo_from_ident(*ident, res)), ); } } diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 7412b2d0581d..2cf34ccb3ad1 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -421,26 +421,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { orig_ident.span.ctxt(), |this, scope, use_prelude, ctxt| { let ident = Ident::new(orig_ident.name, orig_ident.span.with_ctxt(ctxt)); - let ok = |res, span, arenas| { - Ok(( - (res, Visibility::Public, span, LocalExpnId::ROOT).to_name_binding(arenas), - Flags::empty(), - )) - }; let result = match scope { Scope::DeriveHelpers(expn_id) => { - if let Some(attr) = this - .helper_attrs - .get(&expn_id) - .and_then(|attrs| attrs.iter().rfind(|i| ident == **i)) - { - let binding = ( - Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper), - Visibility::Public, - attr.span, - expn_id, - ) - .to_name_binding(this.arenas); + if let Some(binding) = this.helper_attrs.get(&expn_id).and_then(|attrs| { + attrs.iter().rfind(|(i, _)| ident == *i).map(|(_, binding)| *binding) + }) { Ok((binding, Flags::empty())) } else { Err(Determinacy::Determined) @@ -459,11 +444,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ) { Ok((Some(ext), _)) => { if ext.helper_attrs.contains(&ident.name) { - result = ok( + let binding = ( Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat), + Visibility::Public, derive.span, - this.arenas, - ); + LocalExpnId::ROOT, + ) + .to_name_binding(this.arenas); + result = Ok((binding, Flags::empty())); break; } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index a2ee6c7b5293..57d9232005b2 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1047,7 +1047,7 @@ pub struct Resolver<'a, 'tcx> { /// `macro_rules` scopes produced by `macro_rules` item definitions. macro_rules_scopes: FxHashMap>, /// Helper attributes that are in scope for the given expansion. - helper_attrs: FxHashMap>, + helper_attrs: FxHashMap)>>, /// Ready or in-progress results of resolving paths inside the `#[derive(...)]` attribute /// with the given `ExpnId`. derive_data: FxHashMap, diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 6a5b675b4bb0..1199290a4d1c 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -7,7 +7,7 @@ use crate::errors::{ use crate::Namespace::*; use crate::{BuiltinMacroState, Determinacy}; use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet}; -use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment}; +use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding}; use rustc_ast::expand::StrippedCfgItem; use rustc_ast::{self as ast, attr, Crate, Inline, ItemKind, ModKind, NodeId}; use rustc_ast_pretty::pprust; @@ -20,10 +20,10 @@ use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::compile_declarative_macro; use rustc_expand::expand::{AstFragment, Invocation, InvocationKind, SupportsMacroExpansion}; use rustc_hir::def::{self, DefKind, NonMacroAttrKind}; -use rustc_hir::def_id::{CrateNum, LocalDefId}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_middle::middle::stability; use rustc_middle::ty::RegisteredTools; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{TyCtxt, Visibility}; use rustc_session::lint::builtin::{ LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE, UNKNOWN_DIAGNOSTIC_ATTRIBUTES, }; @@ -401,8 +401,17 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { } // Sort helpers in a stable way independent from the derive resolution order. entry.helper_attrs.sort_by_key(|(i, _)| *i); - self.helper_attrs - .insert(expn_id, entry.helper_attrs.iter().map(|(_, ident)| *ident).collect()); + let helper_attrs = entry + .helper_attrs + .iter() + .map(|(_, ident)| { + let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); + let binding = (res, Visibility::::Public, ident.span, expn_id) + .to_name_binding(self.arenas); + (*ident, binding) + }) + .collect(); + self.helper_attrs.insert(expn_id, helper_attrs); // Mark this derive as having `Copy` either if it has `Copy` itself or if its parent derive // has `Copy`, to support cases like `#[derive(Clone, Copy)] #[derive(Debug)]`. if entry.has_derive_copy || self.has_derive_copy(parent_scope.expansion) { From 453edebc703777dcfe39f8c1c7fa472d8ae7c70e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 23 Aug 2023 15:21:18 +0800 Subject: [PATCH 168/197] resolve: Leave a comment about name bindings for legacy derive helpers --- compiler/rustc_resolve/src/ident.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 2cf34ccb3ad1..61e05b65f90f 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -432,6 +432,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } Scope::DeriveHelpersCompat => { + // FIXME: Try running this logic eariler, to allocate name bindings for + // legacy derive helpers when creating an attribute invocation with + // following derives. Legacy derive helpers are not common, so it shouldn't + // affect performance. It should also allow to remove the `derives` + // component from `ParentScope`. let mut result = Err(Determinacy::Determined); for derive in parent_scope.derives { let parent_scope = &ParentScope { derives: &[], ..*parent_scope }; From 4c53783f3c27ce30119018c752bdc805222409da Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 21 Aug 2023 09:57:10 +0200 Subject: [PATCH 169/197] when terminating during unwinding, show the reason why --- compiler/rustc_borrowck/src/invalidation.rs | 2 +- compiler/rustc_borrowck/src/lib.rs | 4 +- compiler/rustc_borrowck/src/type_check/mod.rs | 6 +- compiler/rustc_codegen_cranelift/src/base.rs | 9 +- .../rustc_codegen_cranelift/src/constant.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/analyze.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/block.rs | 145 +++++++++--------- compiler/rustc_codegen_ssa/src/mir/mod.rs | 8 +- .../src/interpret/eval_context.rs | 5 +- .../rustc_const_eval/src/interpret/machine.rs | 11 +- .../src/interpret/terminator.rs | 4 +- .../src/transform/check_consts/check.rs | 2 +- .../check_consts/post_drop_elaboration.rs | 2 +- .../src/transform/validate.rs | 19 ++- compiler/rustc_hir/src/lang_items.rs | 1 + compiler/rustc_middle/src/mir/patch.rs | 29 ++-- compiler/rustc_middle/src/mir/syntax.rs | 17 +- compiler/rustc_middle/src/mir/terminator.rs | 88 ++++++++--- compiler/rustc_middle/src/mir/visit.rs | 2 +- compiler/rustc_mir_build/src/build/scope.rs | 4 +- compiler/rustc_mir_build/src/lints.rs | 2 +- .../rustc_mir_dataflow/src/elaborate_drops.rs | 2 +- .../src/framework/direction.rs | 8 +- .../src/impls/borrowed_locals.rs | 2 +- .../src/impls/storage_liveness.rs | 4 +- .../src/move_paths/builder.rs | 2 +- .../rustc_mir_dataflow/src/value_analysis.rs | 2 +- .../src/abort_unwinding_calls.rs | 2 +- .../src/add_call_guards.rs | 6 +- .../rustc_mir_transform/src/check_unsafety.rs | 2 +- .../src/const_prop_lint.rs | 2 +- .../rustc_mir_transform/src/coverage/graph.rs | 2 +- .../rustc_mir_transform/src/coverage/spans.rs | 2 +- compiler/rustc_mir_transform/src/dest_prop.rs | 2 +- .../src/elaborate_drops.rs | 12 +- compiler/rustc_mir_transform/src/generator.rs | 6 +- compiler/rustc_mir_transform/src/inline.rs | 8 +- .../src/remove_noop_landing_pads.rs | 2 +- .../src/separate_const_switch.rs | 4 +- compiler/rustc_mir_transform/src/shim.rs | 8 +- compiler/rustc_monomorphize/src/collector.rs | 32 ++-- compiler/rustc_smir/src/rustc_smir/mod.rs | 4 +- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/panicking.rs | 17 ++ .../clippy_utils/src/qualify_min_const_fn.rs | 2 +- src/tools/miri/src/machine.rs | 4 +- .../miri/tests/fail/panic/double_panic.stderr | 4 +- ...c_abort.main.AbortUnwindingCalls.after.mir | 2 +- .../basic_assignment.main.ElaborateDrops.diff | 6 +- ...ignment.main.SimplifyCfg-initial.after.mir | 6 +- ...main.ElaborateDrops.before.panic-abort.mir | 6 +- ...ain.ElaborateDrops.before.panic-unwind.mir | 6 +- .../building/enum_cast.droppy.built.after.mir | 2 +- ...e_out.move_out_by_subslice.built.after.mir | 6 +- ...move_out.move_out_from_end.built.after.mir | 6 +- ...pl#0}-clone.InstSimplify.panic-unwind.diff | 2 +- ..._inline_test.main.Derefer.panic-abort.diff | 2 +- ...inline_test.main.Derefer.panic-unwind.diff | 2 +- ...#0}.StateTransform.before.panic-unwind.mir | 4 +- .../asm_unwind.main.Inline.panic-abort.diff | 2 +- .../asm_unwind.main.Inline.panic-unwind.diff | 2 +- .../inline/cycle.f.Inline.panic-unwind.diff | 2 +- .../inline/cycle.g.Inline.panic-unwind.diff | 2 +- .../cycle.main.Inline.panic-unwind.diff | 2 +- ...ic_rust_call.call.Inline.panic-unwind.diff | 2 +- ...nline_box_fn.call.Inline.panic-unwind.diff | 2 +- ...nline_diverging.h.Inline.panic-unwind.diff | 4 +- .../issue_78442.bar.Inline.panic-unwind.diff | 2 +- ...ssue_78442.bar.RevealAll.panic-unwind.diff | 2 +- .../unsized_argument.caller.Inline.diff | 2 +- ...41110.main.ElaborateDrops.panic-abort.diff | 8 +- ...1110.main.ElaborateDrops.panic-unwind.diff | 8 +- ...41110.test.ElaborateDrops.panic-abort.diff | 10 +- ...1110.test.ElaborateDrops.panic-unwind.diff | 10 +- ...41888.main.ElaborateDrops.panic-abort.diff | 6 +- ...1888.main.ElaborateDrops.panic-unwind.diff | 6 +- ...test.ElaborateDrops.before.panic-abort.mir | 4 +- ...est.ElaborateDrops.before.panic-unwind.mir | 4 +- tests/mir-opt/issue_91633.bar.built.after.mir | 2 +- tests/mir-opt/issue_91633.foo.built.after.mir | 2 +- ...fg-initial.after-ElaborateDrops.after.diff | 2 +- ...fg-initial.after-ElaborateDrops.after.diff | 2 +- ...main.ElaborateDrops.before.panic-abort.mir | 2 +- ...ain.ElaborateDrops.before.panic-unwind.mir | 2 +- ...Cfg-elaborate-drops.after.panic-unwind.mir | 2 +- ...Cfg-elaborate-drops.after.panic-unwind.mir | 4 +- ...[String].AddMovesForPackedDrops.before.mir | 2 +- ...Vec_i32_.AddMovesForPackedDrops.before.mir | 2 +- 88 files changed, 380 insertions(+), 278 deletions(-) diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index d4c42a758748..84be50a64169 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -202,7 +202,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { } } TerminatorKind::Goto { target: _ } - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Unreachable | TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ } | TerminatorKind::FalseUnwind { real_target: _, unwind: _ } => { diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index ef2788efbcfc..ca96d14b89c1 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -770,7 +770,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro } TerminatorKind::Goto { target: _ } - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Unreachable | TerminatorKind::UnwindResume | TerminatorKind::Return @@ -817,7 +817,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro } } - TerminatorKind::UnwindTerminate + TerminatorKind::UnwindTerminate(_) | TerminatorKind::Assert { .. } | TerminatorKind::Call { .. } | TerminatorKind::Drop { .. } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index d91a3d94045e..3004291c3e75 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1334,7 +1334,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { match &term.kind { TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::GeneratorDrop | TerminatorKind::Unreachable @@ -1613,7 +1613,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { span_mirbug!(self, block_data, "resume on non-cleanup block!") } } - TerminatorKind::UnwindTerminate => { + TerminatorKind::UnwindTerminate(_) => { if !is_cleanup { span_mirbug!(self, block_data, "abort on non-cleanup block!") } @@ -1697,7 +1697,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { span_mirbug!(self, ctxt, "unwind on cleanup block") } } - UnwindAction::Unreachable | UnwindAction::Terminate => (), + UnwindAction::Unreachable | UnwindAction::Terminate(_) => (), } } diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index ed371a04c537..9159bc369875 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -474,8 +474,8 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { *destination, ); } - TerminatorKind::UnwindTerminate => { - codegen_panic_cannot_unwind(fx, source_info); + TerminatorKind::UnwindTerminate(reason) => { + codegen_unwind_terminate(fx, source_info, *reason); } TerminatorKind::UnwindResume => { // FIXME implement unwinding @@ -971,13 +971,14 @@ pub(crate) fn codegen_panic_nounwind<'tcx>( codegen_panic_inner(fx, rustc_hir::LangItem::PanicNounwind, &args, source_info.span); } -pub(crate) fn codegen_panic_cannot_unwind<'tcx>( +pub(crate) fn codegen_unwind_terminate<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, source_info: mir::SourceInfo, + reason: UnwindTerminateReason, ) { let args = []; - codegen_panic_inner(fx, rustc_hir::LangItem::PanicCannotUnwind, &args, source_info.span); + codegen_panic_inner(fx, reason.lang_item(), &args, source_info.span); } fn codegen_panic_inner<'tcx>( diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 7db5f79eead9..a934b0767f17 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -551,7 +551,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 3f5b46333d9b..7fda2d5fadf7 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -285,7 +285,7 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec TerminatorCodegenHelper<'tcx> { mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)), mir::UnwindAction::Continue => None, mir::UnwindAction::Unreachable => None, - mir::UnwindAction::Terminate => { + mir::UnwindAction::Terminate(reason) => { if fx.mir[self.bb].is_cleanup && base::wants_new_eh_instructions(fx.cx.tcx().sess) { // MSVC SEH will abort automatically if an exception tries to // propagate out from cleanup. @@ -191,7 +191,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { None } else { - Some(fx.terminate_block()) + Some(fx.terminate_block(reason)) } } }; @@ -264,7 +264,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { ) -> MergingSucc { let unwind_target = match unwind { mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)), - mir::UnwindAction::Terminate => Some(fx.terminate_block()), + mir::UnwindAction::Terminate(reason) => Some(fx.terminate_block(reason)), mir::UnwindAction::Continue => None, mir::UnwindAction::Unreachable => None, }; @@ -649,12 +649,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { helper: TerminatorCodegenHelper<'tcx>, bx: &mut Bx, terminator: &mir::Terminator<'tcx>, + reason: UnwindTerminateReason, ) { let span = terminator.source_info.span; self.set_debug_loc(bx, terminator.source_info); // Obtain the panic entry point. - let (fn_abi, llfn) = common::build_langcall(bx, Some(span), LangItem::PanicCannotUnwind); + let (fn_abi, llfn) = common::build_langcall(bx, Some(span), reason.lang_item()); // Codegen the actual panic invoke/call. let merging_succ = helper.do_call( @@ -1229,8 +1230,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { MergingSucc::False } - mir::TerminatorKind::UnwindTerminate => { - self.codegen_terminate_terminator(helper, bx, terminator); + mir::TerminatorKind::UnwindTerminate(reason) => { + self.codegen_terminate_terminator(helper, bx, terminator, reason); MergingSucc::False } @@ -1579,79 +1580,83 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }) } - fn terminate_block(&mut self) -> Bx::BasicBlock { - self.terminate_block.unwrap_or_else(|| { - let funclet; - let llbb; - let mut bx; - if base::wants_msvc_seh(self.cx.sess()) { - // This is a basic block that we're aborting the program for, - // notably in an `extern` function. These basic blocks are inserted - // so that we assert that `extern` functions do indeed not panic, - // and if they do we abort the process. - // - // On MSVC these are tricky though (where we're doing funclets). If - // we were to do a cleanuppad (like below) the normal functions like - // `longjmp` would trigger the abort logic, terminating the - // program. Instead we insert the equivalent of `catch(...)` for C++ - // which magically doesn't trigger when `longjmp` files over this - // frame. - // - // Lots more discussion can be found on #48251 but this codegen is - // modeled after clang's for: - // - // try { - // foo(); - // } catch (...) { - // bar(); - // } - // - // which creates an IR snippet like - // - // cs_terminate: - // %cs = catchswitch within none [%cp_terminate] unwind to caller - // cp_terminate: - // %cp = catchpad within %cs [null, i32 64, null] - // ... + fn terminate_block(&mut self, reason: UnwindTerminateReason) -> Bx::BasicBlock { + if let Some(bb) = self.terminate_in_cleanup_block && reason == UnwindTerminateReason::InCleanup { + return bb; + } - llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate"); - let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate"); + let funclet; + let llbb; + let mut bx; + if base::wants_msvc_seh(self.cx.sess()) { + // This is a basic block that we're aborting the program for, + // notably in an `extern` function. These basic blocks are inserted + // so that we assert that `extern` functions do indeed not panic, + // and if they do we abort the process. + // + // On MSVC these are tricky though (where we're doing funclets). If + // we were to do a cleanuppad (like below) the normal functions like + // `longjmp` would trigger the abort logic, terminating the + // program. Instead we insert the equivalent of `catch(...)` for C++ + // which magically doesn't trigger when `longjmp` files over this + // frame. + // + // Lots more discussion can be found on #48251 but this codegen is + // modeled after clang's for: + // + // try { + // foo(); + // } catch (...) { + // bar(); + // } + // + // which creates an IR snippet like + // + // cs_terminate: + // %cs = catchswitch within none [%cp_terminate] unwind to caller + // cp_terminate: + // %cp = catchpad within %cs [null, i32 64, null] + // ... - let mut cs_bx = Bx::build(self.cx, llbb); - let cs = cs_bx.catch_switch(None, None, &[cp_llbb]); + llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate"); + let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate"); - // The "null" here is actually a RTTI type descriptor for the - // C++ personality function, but `catch (...)` has no type so - // it's null. The 64 here is actually a bitfield which - // represents that this is a catch-all block. - bx = Bx::build(self.cx, cp_llbb); - let null = - bx.const_null(bx.type_ptr_ext(bx.cx().data_layout().instruction_address_space)); - let sixty_four = bx.const_i32(64); - funclet = Some(bx.catch_pad(cs, &[null, sixty_four, null])); - } else { - llbb = Bx::append_block(self.cx, self.llfn, "terminate"); - bx = Bx::build(self.cx, llbb); + let mut cs_bx = Bx::build(self.cx, llbb); + let cs = cs_bx.catch_switch(None, None, &[cp_llbb]); - let llpersonality = self.cx.eh_personality(); - bx.filter_landing_pad(llpersonality); + // The "null" here is actually a RTTI type descriptor for the + // C++ personality function, but `catch (...)` has no type so + // it's null. The 64 here is actually a bitfield which + // represents that this is a catch-all block. + bx = Bx::build(self.cx, cp_llbb); + let null = + bx.const_null(bx.type_ptr_ext(bx.cx().data_layout().instruction_address_space)); + let sixty_four = bx.const_i32(64); + funclet = Some(bx.catch_pad(cs, &[null, sixty_four, null])); + } else { + llbb = Bx::append_block(self.cx, self.llfn, "terminate"); + bx = Bx::build(self.cx, llbb); - funclet = None; - } + let llpersonality = self.cx.eh_personality(); + bx.filter_landing_pad(llpersonality); - self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span)); + funclet = None; + } - let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, LangItem::PanicCannotUnwind); - let fn_ty = bx.fn_decl_backend_type(&fn_abi); + self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span)); - let llret = bx.call(fn_ty, None, Some(&fn_abi), fn_ptr, &[], funclet.as_ref()); - bx.do_not_inline(llret); + let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, reason.lang_item()); + let fn_ty = bx.fn_decl_backend_type(&fn_abi); - bx.unreachable(); + let llret = bx.call(fn_ty, None, Some(&fn_abi), fn_ptr, &[], funclet.as_ref()); + bx.do_not_inline(llret); - self.terminate_block = Some(llbb); - llbb - }) + bx.unreachable(); + + if reason == UnwindTerminateReason::InCleanup { + self.terminate_in_cleanup_block = Some(llbb); + } + llbb } /// Get the backend `BasicBlock` for a MIR `BasicBlock`, either already diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index ccf93f208d50..7f38c54c36f0 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -83,8 +83,8 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { /// Cached unreachable block unreachable_block: Option, - /// Cached terminate upon unwinding block - terminate_block: Option, + /// Cached terminate upon unwinding (reason: InCleanup) block + terminate_in_cleanup_block: Option, /// The location where each MIR arg/var/tmp/ret is stored. This is /// usually an `PlaceRef` representing an alloca, but not always: @@ -174,7 +174,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let mut start_bx = Bx::build(cx, start_llbb); if mir.basic_blocks.iter().any(|bb| { - bb.is_cleanup || matches!(bb.terminator().unwind(), Some(mir::UnwindAction::Terminate)) + bb.is_cleanup || matches!(bb.terminator().unwind(), Some(mir::UnwindAction::Terminate(_))) }) { start_bx.set_personality_fn(cx.eh_personality()); } @@ -199,7 +199,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( personality_slot: None, cached_llbbs, unreachable_block: None, - terminate_block: None, + terminate_in_cleanup_block: None, cleanup_kinds, landing_pads: IndexVec::from_elem(None, &mir.basic_blocks), funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks.len()), diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 61d3de5c4050..90848dbfbc73 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -756,6 +756,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// /// If `target` is `UnwindAction::Unreachable`, that indicates the function does not allow /// unwinding, and doing so is UB. + #[cold] // usually we have normal returns, not unwinding pub fn unwind_to_block(&mut self, target: mir::UnwindAction) -> InterpResult<'tcx> { self.frame_mut().loc = match target { mir::UnwindAction::Cleanup(block) => Left(mir::Location { block, statement_index: 0 }), @@ -763,9 +764,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { mir::UnwindAction::Unreachable => { throw_ub_custom!(fluent::const_eval_unreachable_unwind); } - mir::UnwindAction::Terminate => { + mir::UnwindAction::Terminate(reason) => { self.frame_mut().loc = Right(self.frame_mut().body.span); - M::unwind_terminate(self)?; + M::unwind_terminate(self, reason)?; // This might have pushed a new stack frame, or it terminated execution. // Either way, `loc` will not be updated. return Ok(()); diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index d3c73b896c08..6be2e4069170 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -222,7 +222,10 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { fn panic_nounwind(_ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str) -> InterpResult<'tcx>; /// Called when unwinding reached a state where execution should be terminated. - fn unwind_terminate(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>; + fn unwind_terminate( + ecx: &mut InterpCx<'mir, 'tcx, Self>, + reason: mir::UnwindTerminateReason, + ) -> InterpResult<'tcx>; /// Called for all binary operations where the LHS has pointer type. /// @@ -462,6 +465,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { /// Called immediately after a stack frame got popped, but before jumping back to the caller. /// The `locals` have already been destroyed! + #[inline(always)] fn after_stack_pop( _ecx: &mut InterpCx<'mir, 'tcx, Self>, _frame: Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>, @@ -501,7 +505,10 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { } #[inline(always)] - fn unwind_terminate(_ecx: &mut InterpCx<$mir, $tcx, Self>) -> InterpResult<$tcx> { + fn unwind_terminate( + _ecx: &mut InterpCx<$mir, $tcx, Self>, + _reason: mir::UnwindTerminateReason, + ) -> InterpResult<$tcx> { unreachable!("unwinding cannot happen during compile-time evaluation") } diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index b2ebcceceb32..ca7c484ea314 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -196,8 +196,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - UnwindTerminate => { - M::unwind_terminate(self)?; + UnwindTerminate(reason) => { + M::unwind_terminate(self, reason)?; } // When we encounter Resume, we've finished unwinding diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index e67098a3ac38..f288ddc25d3a 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -1037,7 +1037,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { self.check_op(ops::Generator(hir::GeneratorKind::Gen)) } - TerminatorKind::UnwindTerminate => { + TerminatorKind::UnwindTerminate(_) => { // Cleanup blocks are skipped for const checking (see `visit_basic_block_data`). span_bug!(self.span, "`Terminate` terminator outside of cleanup block") } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs index a8c61d2c8fd8..fd6bc2ee9af5 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs @@ -106,7 +106,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> { } } - mir::TerminatorKind::UnwindTerminate + mir::TerminatorKind::UnwindTerminate(_) | mir::TerminatorKind::Call { .. } | mir::TerminatorKind::Assert { .. } | mir::TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 0dfbbf73dce4..b829f24ab7a3 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -10,8 +10,8 @@ use rustc_middle::mir::{ traversal, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, Local, Location, MirPass, MirPhase, NonDivergingIntrinsic, NullOp, Operand, Place, PlaceElem, PlaceRef, ProjectionElem, RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, - Terminator, TerminatorKind, UnOp, UnwindAction, VarDebugInfo, VarDebugInfoContents, - START_BLOCK, + Terminator, TerminatorKind, UnOp, UnwindAction, UnwindTerminateReason, VarDebugInfo, + VarDebugInfoContents, START_BLOCK, }; use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt}; use rustc_mir_dataflow::impls::MaybeStorageLive; @@ -274,7 +274,16 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> { self.fail(location, "`UnwindAction::Continue` in no-unwind function"); } } - UnwindAction::Unreachable | UnwindAction::Terminate => (), + UnwindAction::Terminate(UnwindTerminateReason::InCleanup) => { + if !is_cleanup { + self.fail( + location, + "`UnwindAction::Terminate(InCleanup)` in a non-cleanup block", + ); + } + } + // These are allowed everywhere. + UnwindAction::Unreachable | UnwindAction::Terminate(UnwindTerminateReason::Abi) => (), } } } @@ -501,7 +510,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { self.fail(location, "Cannot `UnwindResume` in a function that cannot unwind") } } - TerminatorKind::UnwindTerminate => { + TerminatorKind::UnwindTerminate(_) => { let bb = location.block; if !self.body.basic_blocks[bb].is_cleanup { self.fail(location, "Cannot `UnwindTerminate` from non-cleanup basic block") @@ -1233,7 +1242,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { | TerminatorKind::InlineAsm { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable => {} } diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 302a94984131..23b20543d535 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -238,6 +238,7 @@ language_item_table! { PanicLocation, sym::panic_location, panic_location, Target::Struct, GenericRequirement::None; PanicImpl, sym::panic_impl, panic_impl, Target::Fn, GenericRequirement::None; PanicCannotUnwind, sym::panic_cannot_unwind, panic_cannot_unwind, Target::Fn, GenericRequirement::Exact(0); + PanicInCleanup, sym::panic_in_cleanup, panic_in_cleanup, Target::Fn, GenericRequirement::Exact(0); /// libstd panic entry point. Necessary for const eval to be able to catch it BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None; diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs index cd74a403ff6b..419543b89889 100644 --- a/compiler/rustc_middle/src/mir/patch.rs +++ b/compiler/rustc_middle/src/mir/patch.rs @@ -14,7 +14,8 @@ pub struct MirPatch<'tcx> { resume_block: Option, // Only for unreachable in cleanup path. unreachable_cleanup_block: Option, - terminate_block: Option, + // Cached block for UnwindTerminate(InCleanup) + terminate_in_cleanup_block: Option, body_span: Span, next_local: usize, } @@ -29,19 +30,21 @@ impl<'tcx> MirPatch<'tcx> { next_local: body.local_decls.len(), resume_block: None, unreachable_cleanup_block: None, - terminate_block: None, + terminate_in_cleanup_block: None, body_span: body.span, }; for (bb, block) in body.basic_blocks.iter_enumerated() { // Check if we already have a resume block - if let TerminatorKind::UnwindResume = block.terminator().kind && block.statements.is_empty() { + if matches!(block.terminator().kind, TerminatorKind::UnwindResume) + && block.statements.is_empty() + { result.resume_block = Some(bb); continue; } // Check if we already have an unreachable block - if let TerminatorKind::Unreachable = block.terminator().kind + if matches!(block.terminator().kind, TerminatorKind::Unreachable) && block.statements.is_empty() && block.is_cleanup { @@ -50,8 +53,12 @@ impl<'tcx> MirPatch<'tcx> { } // Check if we already have a terminate block - if let TerminatorKind::UnwindTerminate = block.terminator().kind && block.statements.is_empty() { - result.terminate_block = Some(bb); + if matches!( + block.terminator().kind, + TerminatorKind::UnwindTerminate(UnwindTerminateReason::InCleanup) + ) && block.statements.is_empty() + { + result.terminate_in_cleanup_block = Some(bb); continue; } } @@ -93,8 +100,8 @@ impl<'tcx> MirPatch<'tcx> { bb } - pub fn terminate_block(&mut self) -> BasicBlock { - if let Some(bb) = self.terminate_block { + pub fn terminate_block(&mut self, reason: UnwindTerminateReason) -> BasicBlock { + if let Some(bb) = self.terminate_in_cleanup_block && reason == UnwindTerminateReason::InCleanup { return bb; } @@ -102,11 +109,13 @@ impl<'tcx> MirPatch<'tcx> { statements: vec![], terminator: Some(Terminator { source_info: SourceInfo::outermost(self.body_span), - kind: TerminatorKind::UnwindTerminate, + kind: TerminatorKind::UnwindTerminate(reason), }), is_cleanup: true, }); - self.terminate_block = Some(bb); + if reason == UnwindTerminateReason::InCleanup { + self.terminate_in_cleanup_block = Some(bb); + } bb } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index e91e822f915a..79b64a491f4e 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -621,7 +621,7 @@ pub enum TerminatorKind<'tcx> { /// /// Used to prevent unwinding for foreign items or with `-C unwind=abort`. Only permitted in /// cleanup blocks. - UnwindTerminate, + UnwindTerminate(UnwindTerminateReason), /// Returns from the function. /// @@ -813,7 +813,7 @@ impl TerminatorKind<'_> { TerminatorKind::Goto { .. } => "Goto", TerminatorKind::SwitchInt { .. } => "SwitchInt", TerminatorKind::UnwindResume => "UnwindResume", - TerminatorKind::UnwindTerminate => "UnwindTerminate", + TerminatorKind::UnwindTerminate(_) => "UnwindTerminate", TerminatorKind::Return => "Return", TerminatorKind::Unreachable => "Unreachable", TerminatorKind::Drop { .. } => "Drop", @@ -842,11 +842,22 @@ pub enum UnwindAction { /// Terminates the execution if unwind happens. /// /// Depending on the platform and situation this may cause a non-unwindable panic or abort. - Terminate, + Terminate(UnwindTerminateReason), /// Cleanups to be done. Cleanup(BasicBlock), } +/// The reason we are terminating the process during unwinding. +#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] +pub enum UnwindTerminateReason { + /// Unwinding is just not possible given the ABI of this function. + Abi, + /// We were already cleaning up for an ongoing unwind, and a *second*, *nested* unwind was + /// triggered by the drop glue. + InCleanup, +} + /// Information about an assertion failure. #[derive(Clone, Hash, HashStable, PartialEq, Debug)] #[derive(TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index bd87563e2bb4..c4d7f122ea99 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -1,3 +1,4 @@ +use rustc_hir::LangItem; use smallvec::SmallVec; use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind, UnwindAction}; @@ -100,6 +101,32 @@ impl<'a> Iterator for SwitchTargetsIter<'a> { impl<'a> ExactSizeIterator for SwitchTargetsIter<'a> {} +impl UnwindAction { + fn cleanup_block(self) -> Option { + match self { + UnwindAction::Cleanup(bb) => Some(bb), + UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate(_) => None, + } + } +} + +impl UnwindTerminateReason { + pub fn as_str(self) -> &'static str { + // Keep this in sync with the messages in `core/src/panicking.rs`. + match self { + UnwindTerminateReason::Abi => "panic in a function that cannot unwind", + UnwindTerminateReason::InCleanup => "panic in a destructor during cleanup", + } + } + + pub fn lang_item(self) -> LangItem { + match self { + UnwindTerminateReason::Abi => LangItem::PanicCannotUnwind, + UnwindTerminateReason::InCleanup => LangItem::PanicInCleanup, + } + } +} + #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct Terminator<'tcx> { pub source_info: SourceInfo, @@ -156,7 +183,7 @@ impl<'tcx> TerminatorKind<'tcx> { Some(t).into_iter().chain((&[]).into_iter().copied()) } UnwindResume - | UnwindTerminate + | UnwindTerminate(_) | GeneratorDrop | Return | Unreachable @@ -198,7 +225,7 @@ impl<'tcx> TerminatorKind<'tcx> { Some(t).into_iter().chain(&mut []) } UnwindResume - | UnwindTerminate + | UnwindTerminate(_) | GeneratorDrop | Return | Unreachable @@ -215,7 +242,7 @@ impl<'tcx> TerminatorKind<'tcx> { match *self { TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop @@ -234,7 +261,7 @@ impl<'tcx> TerminatorKind<'tcx> { match *self { TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop @@ -271,18 +298,27 @@ impl<'tcx> Debug for TerminatorKind<'tcx> { let labels = self.fmt_successor_labels(); assert_eq!(successor_count, labels.len()); - let unwind = match self.unwind() { - // Not needed or included in successors - None | Some(UnwindAction::Cleanup(_)) => None, - Some(UnwindAction::Continue) => Some("unwind continue"), - Some(UnwindAction::Unreachable) => Some("unwind unreachable"), - Some(UnwindAction::Terminate) => Some("unwind terminate"), + // `Cleanup` is already included in successors + let show_unwind = !matches!(self.unwind(), None | Some(UnwindAction::Cleanup(_))); + let fmt_unwind = |fmt: &mut Formatter<'_>| -> fmt::Result { + match self.unwind() { + // Not needed or included in successors + None | Some(UnwindAction::Cleanup(_)) => unreachable!(), + Some(UnwindAction::Continue) => write!(fmt, "unwind continue"), + Some(UnwindAction::Unreachable) => write!(fmt, "unwind unreachable"), + Some(UnwindAction::Terminate(reason)) => { + write!(fmt, "unwind terminate ({})", reason.as_str()) + } + } }; - match (successor_count, unwind) { - (0, None) => Ok(()), - (0, Some(unwind)) => write!(fmt, " -> {unwind}"), - (1, None) => write!(fmt, " -> {:?}", self.successors().next().unwrap()), + match (successor_count, show_unwind) { + (0, false) => Ok(()), + (0, true) => { + write!(fmt, " -> ")?; + fmt_unwind(fmt) + } + (1, false) => write!(fmt, " -> {:?}", self.successors().next().unwrap()), _ => { write!(fmt, " -> [")?; for (i, target) in self.successors().enumerate() { @@ -291,8 +327,9 @@ impl<'tcx> Debug for TerminatorKind<'tcx> { } write!(fmt, "{}: {:?}", labels[i], target)?; } - if let Some(unwind) = unwind { - write!(fmt, ", {unwind}")?; + if show_unwind { + write!(fmt, ", ")?; + fmt_unwind(fmt)?; } write!(fmt, "]") } @@ -312,7 +349,9 @@ impl<'tcx> TerminatorKind<'tcx> { Return => write!(fmt, "return"), GeneratorDrop => write!(fmt, "generator_drop"), UnwindResume => write!(fmt, "resume"), - UnwindTerminate => write!(fmt, "abort"), + UnwindTerminate(reason) => { + write!(fmt, "abort(\"{}\")", reason.as_str()) + } Yield { value, resume_arg, .. } => write!(fmt, "{resume_arg:?} = yield({value:?})"), Unreachable => write!(fmt, "unreachable"), Drop { place, .. } => write!(fmt, "drop({place:?})"), @@ -391,7 +430,7 @@ impl<'tcx> TerminatorKind<'tcx> { pub fn fmt_successor_labels(&self) -> Vec> { use self::TerminatorKind::*; match *self { - Return | UnwindResume | UnwindTerminate | Unreachable | GeneratorDrop => vec![], + Return | UnwindResume | UnwindTerminate(_) | Unreachable | GeneratorDrop => vec![], Goto { .. } => vec!["".into()], SwitchInt { ref targets, .. } => targets .values @@ -443,7 +482,8 @@ pub enum TerminatorEdges<'mir, 'tcx> { /// Special action for `Yield`, `Call` and `InlineAsm` terminators. AssignOnReturn { return_: Option, - unwind: UnwindAction, + /// The cleanup block, if it exists. + cleanup: Option, place: CallReturnPlaces<'mir, 'tcx>, }, /// Special edge for `SwitchInt`. @@ -486,7 +526,7 @@ impl<'tcx> TerminatorKind<'tcx> { pub fn edges(&self) -> TerminatorEdges<'_, 'tcx> { use TerminatorKind::*; match *self { - Return | UnwindResume | UnwindTerminate | GeneratorDrop | Unreachable => { + Return | UnwindResume | UnwindTerminate(_) | GeneratorDrop | Unreachable => { TerminatorEdges::None } @@ -496,7 +536,7 @@ impl<'tcx> TerminatorKind<'tcx> { | Drop { target, unwind, place: _, replace: _ } | FalseUnwind { real_target: target, unwind } => match unwind { UnwindAction::Cleanup(unwind) => TerminatorEdges::Double(target, unwind), - UnwindAction::Continue | UnwindAction::Terminate | UnwindAction::Unreachable => { + UnwindAction::Continue | UnwindAction::Terminate(_) | UnwindAction::Unreachable => { TerminatorEdges::Single(target) } }, @@ -508,7 +548,7 @@ impl<'tcx> TerminatorKind<'tcx> { Yield { resume: target, drop, resume_arg, value: _ } => { TerminatorEdges::AssignOnReturn { return_: Some(target), - unwind: drop.map_or(UnwindAction::Terminate, UnwindAction::Cleanup), + cleanup: drop, place: CallReturnPlaces::Yield(resume_arg), } } @@ -516,7 +556,7 @@ impl<'tcx> TerminatorKind<'tcx> { Call { unwind, destination, target, func: _, args: _, fn_span: _, call_source: _ } => { TerminatorEdges::AssignOnReturn { return_: target, - unwind, + cleanup: unwind.cleanup_block(), place: CallReturnPlaces::Call(destination), } } @@ -530,7 +570,7 @@ impl<'tcx> TerminatorKind<'tcx> { unwind, } => TerminatorEdges::AssignOnReturn { return_: destination, - unwind, + cleanup: unwind.cleanup_block(), place: CallReturnPlaces::InlineAsm(operands), }, diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index b3d3366ae104..87b04aabe6a3 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -470,7 +470,7 @@ macro_rules! make_mir_visitor { match kind { TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume | - TerminatorKind::UnwindTerminate | + TerminatorKind::UnwindTerminate(_) | TerminatorKind::GeneratorDrop | TerminatorKind::Unreachable | TerminatorKind::FalseEdge { .. } | diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 567e7bfb5bf8..4cf6a349af76 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -370,7 +370,7 @@ impl DropTree { let terminator = TerminatorKind::Drop { target: blocks[drop_data.1].unwrap(), // The caller will handle this if needed. - unwind: UnwindAction::Terminate, + unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup), place: drop_data.0.local.into(), replace: false, }; @@ -1507,7 +1507,7 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind { TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Yield { .. } diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index 84c80bf41a4d..94be38beee44 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -186,7 +186,7 @@ impl<'mir, 'tcx, C: TerminatorClassifier<'tcx>> TriColorVisitor UnwindAction { match self { Unwind::To(bb) => UnwindAction::Cleanup(bb), - Unwind::InCleanup => UnwindAction::Terminate, + Unwind::InCleanup => UnwindAction::Terminate(UnwindTerminateReason::InCleanup), } } diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 8a9e37c5a4fd..70451edd5004 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -1,5 +1,5 @@ use rustc_middle::mir::{ - self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdges, UnwindAction, + self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdges, }; use std::ops::RangeInclusive; @@ -486,10 +486,10 @@ impl Direction for Forward { propagate(target, exit_state); propagate(unwind, exit_state); } - TerminatorEdges::AssignOnReturn { return_, unwind, place } => { + TerminatorEdges::AssignOnReturn { return_, cleanup, place } => { // This must be done *first*, otherwise the unwind path will see the assignments. - if let UnwindAction::Cleanup(unwind) = unwind { - propagate(unwind, exit_state); + if let Some(cleanup) = cleanup { + propagate(cleanup, exit_state); } if let Some(return_) = return_ { analysis.apply_call_return_effect(exit_state, bb, place); diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 5ed8f20b73f1..3ad9d3d42640 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -131,7 +131,7 @@ where } } - TerminatorKind::UnwindTerminate + TerminatorKind::UnwindTerminate(_) | TerminatorKind::Assert { .. } | TerminatorKind::Call { .. } | TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 531390c2f077..94d6eb67d499 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -291,7 +291,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> { // Nothing to do for these. Match exhaustively so this fails to compile when new // variants are added. - TerminatorKind::UnwindTerminate + TerminatorKind::UnwindTerminate(_) | TerminatorKind::Assert { .. } | TerminatorKind::Drop { .. } | TerminatorKind::FalseEdge { .. } @@ -328,7 +328,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> { // Nothing to do for these. Match exhaustively so this fails to compile when new // variants are added. TerminatorKind::Yield { .. } - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Assert { .. } | TerminatorKind::Drop { .. } | TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 4adf3dec61be..2e3b9577b503 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -371,7 +371,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { // need recording. | TerminatorKind::Return | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::GeneratorDrop | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } => {} diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 1eea8eef0adf..6872ef5e9859 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -270,7 +270,7 @@ pub trait ValueAnalysis<'tcx> { } TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Assert { .. } diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 5aed89139e2f..4500bb7ff0f0 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -104,7 +104,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { for id in calls_to_terminate { let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap(); - *cleanup = UnwindAction::Terminate; + *cleanup = UnwindAction::Terminate(UnwindTerminateReason::Abi); } for id in cleanups_to_remove { diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs index fb4705e0754c..b814fbf32b14 100644 --- a/compiler/rustc_mir_transform/src/add_call_guards.rs +++ b/compiler/rustc_mir_transform/src/add_call_guards.rs @@ -53,8 +53,10 @@ impl AddCallGuards { kind: TerminatorKind::Call { target: Some(ref mut destination), unwind, .. }, source_info, }) if pred_count[*destination] > 1 - && (matches!(unwind, UnwindAction::Cleanup(_) | UnwindAction::Terminate) - || self == &AllCallEdges) => + && (matches!( + unwind, + UnwindAction::Cleanup(_) | UnwindAction::Terminate(_) + ) || self == &AllCallEdges) => { // It's a critical edge, break it let call_guard = BasicBlockData { diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index e72db1a59a05..0fce9cb19a84 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -58,7 +58,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { | TerminatorKind::Assert { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 4f8ca916d5b4..da8913d604b9 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -679,7 +679,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { // None of these have Operands to const-propagate. TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index d3d4fcd3a527..60461691e7f5 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -116,7 +116,7 @@ impl CoverageGraph { match term.kind { TerminatorKind::Return { .. } - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Yield { .. } | TerminatorKind::SwitchInt { .. } => { // The `bb` has more than one _outgoing_ edge, or exits the function. Save the diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 6fabaca524a0..717763a94a0e 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -868,7 +868,7 @@ pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option (), TerminatorKind::Drop { .. } => { diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index a80ae480089b..78d7ffb3698a 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -362,8 +362,13 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { UnwindAction::Unreachable => { Unwind::To(self.patch.unreachable_cleanup_block()) } - UnwindAction::Terminate => { - Unwind::To(self.patch.terminate_block()) + UnwindAction::Terminate(reason) => { + debug_assert_ne!( + reason, + UnwindTerminateReason::InCleanup, + "we are not in a cleanup block, InCleanup reason should be impossible" + ); + Unwind::To(self.patch.terminate_block(reason)) } } }; @@ -496,7 +501,8 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { if let TerminatorKind::Call { destination, target: Some(_), - unwind: UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate, + unwind: + UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate(_), .. } = data.terminator().kind { diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 96077322575e..1e7161189c3a 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1091,7 +1091,7 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { UnwindAction::Cleanup(tgt) => tgt, UnwindAction::Continue => elaborator.patch.resume_block(), UnwindAction::Unreachable => elaborator.patch.unreachable_cleanup_block(), - UnwindAction::Terminate => elaborator.patch.terminate_block(), + UnwindAction::Terminate(reason) => elaborator.patch.terminate_block(reason), }) }; elaborate_drop( @@ -1239,7 +1239,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { // These never unwind. TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop @@ -1759,7 +1759,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> { | TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 734e93783d10..9551c7a2a8d6 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -906,12 +906,12 @@ impl Integrator<'_, '_> { UnwindAction::Cleanup(_) | UnwindAction::Continue => { bug!("cleanup on cleanup block"); } - UnwindAction::Unreachable | UnwindAction::Terminate => return unwind, + UnwindAction::Unreachable | UnwindAction::Terminate(_) => return unwind, } } match unwind { - UnwindAction::Unreachable | UnwindAction::Terminate => unwind, + UnwindAction::Unreachable | UnwindAction::Terminate(_) => unwind, UnwindAction::Cleanup(target) => UnwindAction::Cleanup(self.map_block(target)), // Add an unwind edge to the original call's cleanup block UnwindAction::Continue => self.cleanup_block, @@ -1022,10 +1022,10 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> { UnwindAction::Cleanup(tgt) => TerminatorKind::Goto { target: tgt }, UnwindAction::Continue => TerminatorKind::UnwindResume, UnwindAction::Unreachable => TerminatorKind::Unreachable, - UnwindAction::Terminate => TerminatorKind::UnwindTerminate, + UnwindAction::Terminate(reason) => TerminatorKind::UnwindTerminate(reason), }; } - TerminatorKind::UnwindTerminate => {} + TerminatorKind::UnwindTerminate(_) => {} TerminatorKind::Unreachable => {} TerminatorKind::FalseEdge { ref mut real_target, ref mut imaginary_target } => { *real_target = self.map_block(*real_target); diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index 5782adbb3ffa..8c48a667786b 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -72,7 +72,7 @@ impl RemoveNoopLandingPads { TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } | TerminatorKind::Return - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Unreachable | TerminatorKind::Call { .. } | TerminatorKind::Assert { .. } diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs index de1b80585d15..e1e4acccccd3 100644 --- a/compiler/rustc_mir_transform/src/separate_const_switch.rs +++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs @@ -114,7 +114,7 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize { | TerminatorKind::Assert { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::Yield { .. } - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::InlineAsm { .. } @@ -166,7 +166,7 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize { } TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 079cf9eb4e96..e1000d969323 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -570,10 +570,10 @@ impl<'tcx> CloneShimBuilder<'tcx> { TerminatorKind::Drop { place: dest_field, target: unwind, - unwind: UnwindAction::Terminate, + unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup), replace: false, }, - true, + /* is_cleanup */ true, ); unwind = next_unwind; } @@ -851,10 +851,10 @@ fn build_call_shim<'tcx>( TerminatorKind::Drop { place: rcvr_place(), target: BasicBlock::new(4), - unwind: UnwindAction::Terminate, + unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup), replace: false, }, - true, + /* is_cleanup */ true, ); // BB #4 - resume diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index cd7908e75e20..f917e52109a8 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -737,6 +737,13 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { let source = self.body.source_info(location).span; let tcx = self.tcx; + let push_mono_lang_item = |this: &mut Self, lang_item: LangItem| { + let instance = Instance::mono(tcx, tcx.require_lang_item(lang_item, Some(source))); + if should_codegen_locally(tcx, &instance) { + this.output.push(create_fn_mono_item(tcx, instance, source)); + } + }; + match terminator.kind { mir::TerminatorKind::Call { ref func, .. } => { let callee_ty = func.ty(self.body, tcx); @@ -771,19 +778,10 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { mir::AssertKind::BoundsCheck { .. } => LangItem::PanicBoundsCheck, _ => LangItem::Panic, }; - let instance = Instance::mono(tcx, tcx.require_lang_item(lang_item, Some(source))); - if should_codegen_locally(tcx, &instance) { - self.output.push(create_fn_mono_item(tcx, instance, source)); - } + push_mono_lang_item(self, lang_item); } - mir::TerminatorKind::UnwindTerminate { .. } => { - let instance = Instance::mono( - tcx, - tcx.require_lang_item(LangItem::PanicCannotUnwind, Some(source)), - ); - if should_codegen_locally(tcx, &instance) { - self.output.push(create_fn_mono_item(tcx, instance, source)); - } + mir::TerminatorKind::UnwindTerminate(reason) => { + push_mono_lang_item(self, reason.lang_item()); } mir::TerminatorKind::Goto { .. } | mir::TerminatorKind::SwitchInt { .. } @@ -796,14 +794,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { | mir::TerminatorKind::FalseUnwind { .. } => bug!(), } - if let Some(mir::UnwindAction::Terminate) = terminator.unwind() { - let instance = Instance::mono( - tcx, - tcx.require_lang_item(LangItem::PanicCannotUnwind, Some(source)), - ); - if should_codegen_locally(tcx, &instance) { - self.output.push(create_fn_mono_item(tcx, instance, source)); - } + if let Some(mir::UnwindAction::Terminate(reason)) = terminator.unwind() { + push_mono_lang_item(self, reason.lang_item()); } self.super_terminator(terminator, location); diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index aea59c31379e..092d4932a6d6 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -590,7 +590,7 @@ impl<'tcx> Stable<'tcx> for mir::UnwindAction { match self { UnwindAction::Continue => stable_mir::mir::UnwindAction::Continue, UnwindAction::Unreachable => stable_mir::mir::UnwindAction::Unreachable, - UnwindAction::Terminate => stable_mir::mir::UnwindAction::Terminate, + UnwindAction::Terminate(_) => stable_mir::mir::UnwindAction::Terminate, UnwindAction::Cleanup(bb) => stable_mir::mir::UnwindAction::Cleanup(bb.as_usize()), } } @@ -788,7 +788,7 @@ impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> { otherwise: targets.otherwise().as_usize(), }, UnwindResume => Terminator::Resume, - UnwindTerminate => Terminator::Abort, + UnwindTerminate(_) => Terminator::Abort, Return => Terminator::Return, Unreachable => Terminator::Unreachable, Drop { place, target, unwind, replace: _ } => Terminator::Drop { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8aec12f128ec..90dc6766cf28 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1100,6 +1100,7 @@ symbols! { panic_handler, panic_impl, panic_implementation, + panic_in_cleanup, panic_info, panic_location, panic_misaligned_pointer_dereference, diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 7b6249207fe6..d5e4c113018c 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -179,6 +179,8 @@ fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! { /// Panic because we cannot unwind out of a function. /// +/// This is a separate function to avoid the codesize impact of each crate containing the string to +/// pass to `panic_nounwind`. /// This function is called directly by the codegen backend, and must not have /// any extra arguments (including those synthesized by track_caller). #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] @@ -189,6 +191,21 @@ fn panic_cannot_unwind() -> ! { panic_nounwind("panic in a function that cannot unwind") } +/// Panic because we are unwinding out of a destructor during cleanup. +/// +/// This is a separate function to avoid the codesize impact of each crate containing the string to +/// pass to `panic_nounwind`. +/// This function is called directly by the codegen backend, and must not have +/// any extra arguments (including those synthesized by track_caller). +#[cfg(not(bootstrap))] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[lang = "panic_in_cleanup"] // needed by codegen for panic in nounwind function +#[rustc_nounwind] +fn panic_in_cleanup() -> ! { + panic_nounwind("panic in a destructor during cleanup") +} + /// This function is used instead of panic_fmt in const eval. #[lang = "const_panic_fmt"] #[rustc_const_unstable(feature = "core_panic", issue = "none")] diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 43523faa2361..17233058c9c9 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -292,7 +292,7 @@ fn check_terminator<'tcx>( | TerminatorKind::Goto { .. } | TerminatorKind::Return | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Unreachable => Ok(()), TerminatorKind::Drop { place, .. } => { if !is_ty_const_destruct(tcx, place.ty(&body.local_decls, tcx).ty, body) { diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 550c9650fb39..17cfcbb20187 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -975,9 +975,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ecx.start_panic_nounwind(msg) } - fn unwind_terminate(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { + fn unwind_terminate(ecx: &mut InterpCx<'mir, 'tcx, Self>, reason: mir::UnwindTerminateReason) -> InterpResult<'tcx> { // Call the lang item. - let panic = ecx.tcx.lang_items().panic_cannot_unwind().unwrap(); + let panic = ecx.tcx.lang_items().get(reason.lang_item()).unwrap(); let panic = ty::Instance::mono(ecx.tcx.tcx, panic); ecx.call_function( panic, diff --git a/src/tools/miri/tests/fail/panic/double_panic.stderr b/src/tools/miri/tests/fail/panic/double_panic.stderr index 25c9a7c44bcb..9efba031250b 100644 --- a/src/tools/miri/tests/fail/panic/double_panic.stderr +++ b/src/tools/miri/tests/fail/panic/double_panic.stderr @@ -5,7 +5,7 @@ thread 'main' panicked at $DIR/double_panic.rs:LL:CC: second stack backtrace: thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC: -panic in a function that cannot unwind +panic in a destructor during cleanup stack backtrace: thread caused non-unwinding panic. aborting. error: abnormal termination: the program aborted execution @@ -20,7 +20,7 @@ LL | ABORT(); = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC - = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC + = note: inside `core::panicking::panic_in_cleanup` at RUSTLIB/core/src/panicking.rs:LL:CC note: inside `main` --> $DIR/double_panic.rs:LL:CC | diff --git a/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir b/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir index a59ffe97bf01..8b9c853eb853 100644 --- a/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir +++ b/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir @@ -9,7 +9,7 @@ fn main() -> () { bb0: { StorageLive(_1); _1 = const (); - asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind terminate]; + asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind terminate (panic in a function that cannot unwind)]; } bb1: { diff --git a/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff b/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff index 15269fb8f6c6..2b6e0fe489a6 100644 --- a/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff +++ b/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff @@ -47,7 +47,7 @@ bb2 (cleanup): { _5 = move _6; -- drop(_6) -> [return: bb6, unwind terminate]; +- drop(_6) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb6; } @@ -71,12 +71,12 @@ } bb6 (cleanup): { -- drop(_5) -> [return: bb7, unwind terminate]; +- drop(_5) -> [return: bb7, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb7; } bb7 (cleanup): { -- drop(_4) -> [return: bb8, unwind terminate]; +- drop(_4) -> [return: bb8, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb8; } diff --git a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir index a9bc2e890344..fac407ae1ea6 100644 --- a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir @@ -51,7 +51,7 @@ fn main() -> () { bb2 (cleanup): { _5 = move _6; - drop(_6) -> [return: bb6, unwind terminate]; + drop(_6) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)]; } bb3: { @@ -73,11 +73,11 @@ fn main() -> () { } bb6 (cleanup): { - drop(_5) -> [return: bb7, unwind terminate]; + drop(_5) -> [return: bb7, unwind terminate (panic in a destructor during cleanup)]; } bb7 (cleanup): { - drop(_4) -> [return: bb8, unwind terminate]; + drop(_4) -> [return: bb8, unwind terminate (panic in a destructor during cleanup)]; } bb8 (cleanup): { diff --git a/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-abort.mir b/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-abort.mir index d196b045a1b8..f7cfcf27fe5f 100644 --- a/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-abort.mir +++ b/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-abort.mir @@ -54,15 +54,15 @@ fn main() -> () { } bb6 (cleanup): { - drop(_7) -> [return: bb7, unwind terminate]; + drop(_7) -> [return: bb7, unwind terminate (panic in a destructor during cleanup)]; } bb7 (cleanup): { - drop(_1) -> [return: bb9, unwind terminate]; + drop(_1) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)]; } bb8 (cleanup): { - drop(_5) -> [return: bb9, unwind terminate]; + drop(_5) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)]; } bb9 (cleanup): { diff --git a/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-unwind.mir b/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-unwind.mir index a72d22a9c9ff..4cfdc8701c6b 100644 --- a/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-unwind.mir +++ b/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-unwind.mir @@ -54,15 +54,15 @@ fn main() -> () { } bb6 (cleanup): { - drop(_7) -> [return: bb7, unwind terminate]; + drop(_7) -> [return: bb7, unwind terminate (panic in a destructor during cleanup)]; } bb7 (cleanup): { - drop(_1) -> [return: bb9, unwind terminate]; + drop(_1) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)]; } bb8 (cleanup): { - drop(_5) -> [return: bb9, unwind terminate]; + drop(_5) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)]; } bb9 (cleanup): { diff --git a/tests/mir-opt/building/enum_cast.droppy.built.after.mir b/tests/mir-opt/building/enum_cast.droppy.built.after.mir index 1caf9e4a523c..d1f8b8daf74d 100644 --- a/tests/mir-opt/building/enum_cast.droppy.built.after.mir +++ b/tests/mir-opt/building/enum_cast.droppy.built.after.mir @@ -62,7 +62,7 @@ fn droppy() -> () { } bb4 (cleanup): { - drop(_2) -> [return: bb5, unwind terminate]; + drop(_2) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; } bb5 (cleanup): { diff --git a/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir b/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir index fea1138ba8d9..f7fc1eb7ce30 100644 --- a/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir +++ b/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir @@ -89,15 +89,15 @@ fn move_out_by_subslice() -> () { } bb9 (cleanup): { - drop(_1) -> [return: bb12, unwind terminate]; + drop(_1) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; } bb10 (cleanup): { - drop(_7) -> [return: bb11, unwind terminate]; + drop(_7) -> [return: bb11, unwind terminate (panic in a destructor during cleanup)]; } bb11 (cleanup): { - drop(_2) -> [return: bb12, unwind terminate]; + drop(_2) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; } bb12 (cleanup): { diff --git a/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir b/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir index 3def40a8578f..95c061dc9fa9 100644 --- a/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir +++ b/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir @@ -89,15 +89,15 @@ fn move_out_from_end() -> () { } bb9 (cleanup): { - drop(_1) -> [return: bb12, unwind terminate]; + drop(_1) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; } bb10 (cleanup): { - drop(_7) -> [return: bb11, unwind terminate]; + drop(_7) -> [return: bb11, unwind terminate (panic in a destructor during cleanup)]; } bb11 (cleanup): { - drop(_2) -> [return: bb12, unwind terminate]; + drop(_2) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; } bb12 (cleanup): { diff --git a/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-unwind.diff b/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-unwind.diff index 1a4372afe697..20f627a567db 100644 --- a/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-unwind.diff +++ b/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-unwind.diff @@ -63,7 +63,7 @@ } bb4 (cleanup): { - drop(_2) -> [return: bb5, unwind terminate]; + drop(_2) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; } bb5 (cleanup): { diff --git a/tests/mir-opt/derefer_inline_test.main.Derefer.panic-abort.diff b/tests/mir-opt/derefer_inline_test.main.Derefer.panic-abort.diff index 024d9bc7f514..b59a377d27ca 100644 --- a/tests/mir-opt/derefer_inline_test.main.Derefer.panic-abort.diff +++ b/tests/mir-opt/derefer_inline_test.main.Derefer.panic-abort.diff @@ -28,7 +28,7 @@ } bb4 (cleanup): { - drop(_2) -> [return: bb5, unwind terminate]; + drop(_2) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; } bb5 (cleanup): { diff --git a/tests/mir-opt/derefer_inline_test.main.Derefer.panic-unwind.diff b/tests/mir-opt/derefer_inline_test.main.Derefer.panic-unwind.diff index 2ada087b4bd6..effecc03738d 100644 --- a/tests/mir-opt/derefer_inline_test.main.Derefer.panic-unwind.diff +++ b/tests/mir-opt/derefer_inline_test.main.Derefer.panic-unwind.diff @@ -28,7 +28,7 @@ } bb4 (cleanup): { - drop(_2) -> [return: bb5, unwind terminate]; + drop(_2) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; } bb5 (cleanup): { diff --git a/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir b/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir index 6a4c5436fce4..8ec9c46f95f0 100644 --- a/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir +++ b/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir @@ -104,7 +104,7 @@ yields () bb13 (cleanup): { StorageDead(_3); - drop(_1) -> [return: bb14, unwind terminate]; + drop(_1) -> [return: bb14, unwind terminate (panic in a destructor during cleanup)]; } bb14 (cleanup): { @@ -113,6 +113,6 @@ yields () bb15 (cleanup): { StorageDead(_3); - drop(_1) -> [return: bb14, unwind terminate]; + drop(_1) -> [return: bb14, unwind terminate (panic in a destructor during cleanup)]; } } diff --git a/tests/mir-opt/inline/asm_unwind.main.Inline.panic-abort.diff b/tests/mir-opt/inline/asm_unwind.main.Inline.panic-abort.diff index 503dc5beb194..2371297aefb6 100644 --- a/tests/mir-opt/inline/asm_unwind.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/asm_unwind.main.Inline.panic-abort.diff @@ -17,7 +17,7 @@ StorageLive(_1); - _1 = foo() -> [return: bb1, unwind unreachable]; + StorageLive(_2); -+ asm!("", options(MAY_UNWIND)) -> [return: bb2, unwind terminate]; ++ asm!("", options(MAY_UNWIND)) -> [return: bb2, unwind terminate (panic in a function that cannot unwind)]; } bb1: { diff --git a/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff index 684211b53b33..4c0be81ea267 100644 --- a/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff @@ -32,7 +32,7 @@ + } + + bb3 (cleanup): { -+ drop(_2) -> [return: bb4, unwind terminate]; ++ drop(_2) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)]; + } + + bb4 (cleanup): { diff --git a/tests/mir-opt/inline/cycle.f.Inline.panic-unwind.diff b/tests/mir-opt/inline/cycle.f.Inline.panic-unwind.diff index f3a6ee22c208..6e95225a43d0 100644 --- a/tests/mir-opt/inline/cycle.f.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/cycle.f.Inline.panic-unwind.diff @@ -30,7 +30,7 @@ } bb3 (cleanup): { - drop(_1) -> [return: bb4, unwind terminate]; + drop(_1) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff b/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff index ad801fd280ac..cd3ea5ebd0e6 100644 --- a/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff @@ -36,7 +36,7 @@ + } + + bb3 (cleanup): { -+ drop(_2) -> [return: bb4, unwind terminate]; ++ drop(_2) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)]; + } + + bb4 (cleanup): { diff --git a/tests/mir-opt/inline/cycle.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/cycle.main.Inline.panic-unwind.diff index 99dc64115a98..66ce2f92186b 100644 --- a/tests/mir-opt/inline/cycle.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/cycle.main.Inline.panic-unwind.diff @@ -36,7 +36,7 @@ + } + + bb3 (cleanup): { -+ drop(_2) -> [return: bb4, unwind terminate]; ++ drop(_2) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)]; + } + + bb4 (cleanup): { diff --git a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff index ef85e075eeb3..daabb0ffc217 100644 --- a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff @@ -27,7 +27,7 @@ } bb3 (cleanup): { - drop(_1) -> [return: bb4, unwind terminate]; + drop(_1) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff index 5df730a99302..b3fee11e7dd3 100644 --- a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff @@ -30,7 +30,7 @@ } bb3 (cleanup): { - drop(_1) -> [return: bb4, unwind terminate]; + drop(_1) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff index 073ddeff7cab..e3f5e9810c6a 100644 --- a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff @@ -54,11 +54,11 @@ + } + + bb4 (cleanup): { -+ drop(_4) -> [return: bb5, unwind terminate]; ++ drop(_4) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; + } + + bb5 (cleanup): { -+ drop(_2) -> [return: bb6, unwind terminate]; ++ drop(_2) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)]; + } + + bb6 (cleanup): { diff --git a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff index b750330df927..9042121ea9f5 100644 --- a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff @@ -37,7 +37,7 @@ } bb4 (cleanup): { - drop(_1) -> [return: bb5, unwind terminate]; + drop(_1) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; } bb5 (cleanup): { diff --git a/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff b/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff index 7765e491d897..2a55b018f7c0 100644 --- a/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff +++ b/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff @@ -40,7 +40,7 @@ } bb4 (cleanup): { - drop(_1) -> [return: bb5, unwind terminate]; + drop(_1) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; } bb5 (cleanup): { diff --git a/tests/mir-opt/inline/unsized_argument.caller.Inline.diff b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff index 6ee6a0ffe4cd..0cddc5a36b1b 100644 --- a/tests/mir-opt/inline/unsized_argument.caller.Inline.diff +++ b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff @@ -40,7 +40,7 @@ bb4 (cleanup): { _8 = &mut _3; - _9 = as Drop>::drop(move _8) -> [return: bb1, unwind terminate]; + _9 = as Drop>::drop(move _8) -> [return: bb1, unwind terminate (panic in a destructor during cleanup)]; } } diff --git a/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-abort.diff b/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-abort.diff index 11501907b881..4f7ca616792d 100644 --- a/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-abort.diff +++ b/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-abort.diff @@ -40,17 +40,17 @@ } bb3 (cleanup): { -- drop(_3) -> [return: bb5, unwind terminate]; +- drop(_3) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb5; } bb4 (cleanup): { -- drop(_4) -> [return: bb5, unwind terminate]; +- drop(_4) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb5; } bb5 (cleanup): { -- drop(_2) -> [return: bb6, unwind terminate]; +- drop(_2) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb8; } @@ -59,7 +59,7 @@ + } + + bb7 (cleanup): { -+ drop(_2) -> [return: bb6, unwind terminate]; ++ drop(_2) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)]; + } + + bb8 (cleanup): { diff --git a/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-unwind.diff index 11501907b881..4f7ca616792d 100644 --- a/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-unwind.diff +++ b/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-unwind.diff @@ -40,17 +40,17 @@ } bb3 (cleanup): { -- drop(_3) -> [return: bb5, unwind terminate]; +- drop(_3) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb5; } bb4 (cleanup): { -- drop(_4) -> [return: bb5, unwind terminate]; +- drop(_4) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb5; } bb5 (cleanup): { -- drop(_2) -> [return: bb6, unwind terminate]; +- drop(_2) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb8; } @@ -59,7 +59,7 @@ + } + + bb7 (cleanup): { -+ drop(_2) -> [return: bb6, unwind terminate]; ++ drop(_2) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)]; + } + + bb8 (cleanup): { diff --git a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff index 65f4806aaf77..0f38e3961a6f 100644 --- a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff +++ b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff @@ -47,7 +47,7 @@ bb3 (cleanup): { _2 = move _5; -- drop(_5) -> [return: bb8, unwind terminate]; +- drop(_5) -> [return: bb8, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb8; } @@ -70,17 +70,17 @@ } bb7 (cleanup): { -- drop(_4) -> [return: bb8, unwind terminate]; +- drop(_4) -> [return: bb8, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb8; } bb8 (cleanup): { -- drop(_2) -> [return: bb9, unwind terminate]; +- drop(_2) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb9; } bb9 (cleanup): { -- drop(_1) -> [return: bb10, unwind terminate]; +- drop(_1) -> [return: bb10, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb12; } @@ -89,7 +89,7 @@ + } + + bb11 (cleanup): { -+ drop(_1) -> [return: bb10, unwind terminate]; ++ drop(_1) -> [return: bb10, unwind terminate (panic in a destructor during cleanup)]; + } + + bb12 (cleanup): { diff --git a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff index 4845fc732aab..8da15ec9e23e 100644 --- a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff +++ b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff @@ -47,7 +47,7 @@ bb3 (cleanup): { _2 = move _5; -- drop(_5) -> [return: bb8, unwind terminate]; +- drop(_5) -> [return: bb8, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb8; } @@ -70,17 +70,17 @@ } bb7 (cleanup): { -- drop(_4) -> [return: bb8, unwind terminate]; +- drop(_4) -> [return: bb8, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb8; } bb8 (cleanup): { -- drop(_2) -> [return: bb9, unwind terminate]; +- drop(_2) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb9; } bb9 (cleanup): { -- drop(_1) -> [return: bb10, unwind terminate]; +- drop(_1) -> [return: bb10, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb12; } @@ -89,7 +89,7 @@ + } + + bb11 (cleanup): { -+ drop(_1) -> [return: bb10, unwind terminate]; ++ drop(_1) -> [return: bb10, unwind terminate (panic in a destructor during cleanup)]; + } + + bb12 (cleanup): { diff --git a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff index aca7fe95c183..562e684f29fd 100644 --- a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff +++ b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff @@ -58,7 +58,7 @@ + _8 = const true; + _9 = const true; _1 = move _3; -- drop(_3) -> [return: bb11, unwind terminate]; +- drop(_3) -> [return: bb11, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb11; } @@ -102,7 +102,7 @@ } bb11 (cleanup): { -- drop(_1) -> [return: bb12, unwind terminate]; +- drop(_1) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb12; } @@ -124,7 +124,7 @@ + } + + bb16 (cleanup): { -+ drop(_1) -> [return: bb12, unwind terminate]; ++ drop(_1) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; + } + + bb17: { diff --git a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff index 60ce9cd8ad9d..c6cc80c09c08 100644 --- a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff +++ b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff @@ -58,7 +58,7 @@ + _8 = const true; + _9 = const true; _1 = move _3; -- drop(_3) -> [return: bb11, unwind terminate]; +- drop(_3) -> [return: bb11, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb11; } @@ -102,7 +102,7 @@ } bb11 (cleanup): { -- drop(_1) -> [return: bb12, unwind terminate]; +- drop(_1) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; + goto -> bb12; } @@ -124,7 +124,7 @@ + } + + bb16 (cleanup): { -+ drop(_1) -> [return: bb12, unwind terminate]; ++ drop(_1) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; + } + + bb17: { diff --git a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir index ae0beffae184..151571f57eb3 100644 --- a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir +++ b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir @@ -100,11 +100,11 @@ fn test() -> Option> { } bb11 (cleanup): { - drop(_1) -> [return: bb13, unwind terminate]; + drop(_1) -> [return: bb13, unwind terminate (panic in a destructor during cleanup)]; } bb12 (cleanup): { - drop(_5) -> [return: bb13, unwind terminate]; + drop(_5) -> [return: bb13, unwind terminate (panic in a destructor during cleanup)]; } bb13 (cleanup): { diff --git a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir index 7ecdc428e59e..bda3080edb9d 100644 --- a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir +++ b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir @@ -100,11 +100,11 @@ fn test() -> Option> { } bb11 (cleanup): { - drop(_1) -> [return: bb13, unwind terminate]; + drop(_1) -> [return: bb13, unwind terminate (panic in a destructor during cleanup)]; } bb12 (cleanup): { - drop(_5) -> [return: bb13, unwind terminate]; + drop(_5) -> [return: bb13, unwind terminate (panic in a destructor during cleanup)]; } bb13 (cleanup): { diff --git a/tests/mir-opt/issue_91633.bar.built.after.mir b/tests/mir-opt/issue_91633.bar.built.after.mir index 92f52e138a59..6aa49aab20e3 100644 --- a/tests/mir-opt/issue_91633.bar.built.after.mir +++ b/tests/mir-opt/issue_91633.bar.built.after.mir @@ -28,7 +28,7 @@ fn bar(_1: Box<[T]>) -> () { } bb3 (cleanup): { - drop(_1) -> [return: bb4, unwind terminate]; + drop(_1) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/issue_91633.foo.built.after.mir b/tests/mir-opt/issue_91633.foo.built.after.mir index 4529c58a1373..2cf683217432 100644 --- a/tests/mir-opt/issue_91633.foo.built.after.mir +++ b/tests/mir-opt/issue_91633.foo.built.after.mir @@ -45,7 +45,7 @@ fn foo(_1: Box<[T]>) -> T { } bb5 (cleanup): { - drop(_1) -> [return: bb6, unwind terminate]; + drop(_1) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)]; } bb6 (cleanup): { diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff index be09ed641b87..9452ba7e6bc9 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -243,7 +243,7 @@ } - bb25 (cleanup): { -- drop(_2) -> [return: bb26, unwind terminate]; +- drop(_2) -> [return: bb26, unwind terminate (panic in a destructor during cleanup)]; + bb22 (cleanup): { + goto -> bb27; } diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff index be09ed641b87..9452ba7e6bc9 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -243,7 +243,7 @@ } - bb25 (cleanup): { -- drop(_2) -> [return: bb26, unwind terminate]; +- drop(_2) -> [return: bb26, unwind terminate (panic in a destructor during cleanup)]; + bb22 (cleanup): { + goto -> bb27; } diff --git a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-abort.mir b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-abort.mir index e22fc7d54bc4..51a009056d74 100644 --- a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-abort.mir +++ b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-abort.mir @@ -31,7 +31,7 @@ fn main() -> () { } bb3 (cleanup): { - drop(_2) -> [return: bb4, unwind terminate]; + drop(_2) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-unwind.mir b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-unwind.mir index 6fb107929e6b..95820cfafbc1 100644 --- a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-unwind.mir +++ b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-unwind.mir @@ -31,7 +31,7 @@ fn main() -> () { } bb3 (cleanup): { - drop(_2) -> [return: bb4, unwind terminate]; + drop(_2) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir b/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir index bc04790028d3..9a43756cbc06 100644 --- a/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir +++ b/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir @@ -33,7 +33,7 @@ fn main() -> () { bb1 (cleanup): { (_1.0: Aligned) = move _4; - drop(_1) -> [return: bb3, unwind terminate]; + drop(_1) -> [return: bb3, unwind terminate (panic in a destructor during cleanup)]; } bb2: { diff --git a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir index 508f964099a1..09ff59ffa215 100644 --- a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir +++ b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir @@ -167,11 +167,11 @@ fn main() -> () { } bb7 (cleanup): { - drop(_21) -> [return: bb9, unwind terminate]; + drop(_21) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)]; } bb8 (cleanup): { - drop(_5) -> [return: bb9, unwind terminate]; + drop(_5) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)]; } bb9 (cleanup): { diff --git a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir index 9bf69acd3563..8d9f89855789 100644 --- a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir +++ b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir @@ -24,7 +24,7 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () { bb3 (cleanup): { _4 = &raw mut (*_1)[_3]; _3 = Add(move _3, const 1_usize); - drop((*_4)) -> [return: bb4, unwind terminate]; + drop((*_4)) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir b/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir index ee90a540720a..3768d34dd8ec 100644 --- a/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir +++ b/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir @@ -22,7 +22,7 @@ fn std::ptr::drop_in_place(_1: *mut Vec) -> () { } bb4 (cleanup): { - drop(((*_1).0: alloc::raw_vec::RawVec)) -> [return: bb2, unwind terminate]; + drop(((*_1).0: alloc::raw_vec::RawVec)) -> [return: bb2, unwind terminate (panic in a destructor during cleanup)]; } bb5: { From ddea3f981ea16ef4bc1dec043c071dd99a5e411d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 21 Aug 2023 12:25:15 +0200 Subject: [PATCH 170/197] document more things as needing to stay in sync --- compiler/rustc_middle/src/mir/mod.rs | 19 ++++++++++++++++--- library/core/src/panicking.rs | 2 ++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 9ef3a1b30e49..6484c30167cb 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1275,9 +1275,11 @@ impl AssertKind { matches!(self, OverflowNeg(..) | Overflow(Add | Sub | Mul | Shl | Shr, ..)) } - /// Getting a description does not require `O` to be printable, and does not - /// require allocation. - /// The caller is expected to handle `BoundsCheck` and `MisalignedPointerDereference` separately. + /// Get the message that is printed at runtime when this assertion fails. + /// + /// The caller is expected to handle `BoundsCheck` and `MisalignedPointerDereference` by + /// invoking the appropriate lang item (panic_bounds_check/panic_misaligned_pointer_dereference) + /// instead of printing a static message. pub fn description(&self) -> &'static str { use AssertKind::*; match self { @@ -1303,6 +1305,11 @@ impl AssertKind { } /// Format the message arguments for the `assert(cond, msg..)` terminator in MIR printing. + /// + /// Needs to be kept in sync with the run-time behavior (which is defined by + /// `AssertKind::description` and the lang items mentioned in its docs). + /// Note that we deliberately show more details here than we do at runtime, such as the actual + /// numbers that overflowed -- it is much easier to do so here than at runtime. pub fn fmt_assert_args(&self, f: &mut W) -> fmt::Result where O: Debug, @@ -1358,6 +1365,12 @@ impl AssertKind { } } + /// Format the diagnostic message for use in a lint (e.g. when the assertion fails during const-eval). + /// + /// Needs to be kept in sync with the run-time behavior (which is defined by + /// `AssertKind::description` and the lang items mentioned in its docs). + /// Note that we deliberately show more details here than we do at runtime, such as the actual + /// numbers that overflowed -- it is much easier to do so here than at runtime. pub fn diagnostic_message(&self) -> DiagnosticMessage { use crate::fluent_generated::*; use AssertKind::*; diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index d5e4c113018c..ab6aa0df4282 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -188,6 +188,7 @@ fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! { #[lang = "panic_cannot_unwind"] // needed by codegen for panic in nounwind function #[rustc_nounwind] fn panic_cannot_unwind() -> ! { + // Keep the text in sync with `UnwindTerminateReason::as_str` in `rustc_middle`. panic_nounwind("panic in a function that cannot unwind") } @@ -203,6 +204,7 @@ fn panic_cannot_unwind() -> ! { #[lang = "panic_in_cleanup"] // needed by codegen for panic in nounwind function #[rustc_nounwind] fn panic_in_cleanup() -> ! { + // Keep the text in sync with `UnwindTerminateReason::as_str` in `rustc_middle`. panic_nounwind("panic in a destructor during cleanup") } From 114fde6ac74ffbaaca4d7241c3ee4e11303ae50d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 22 Aug 2023 13:57:09 +0200 Subject: [PATCH 171/197] cache the terminate block with the last reason that we saw --- compiler/rustc_codegen_ssa/src/mir/block.rs | 8 +++----- compiler/rustc_codegen_ssa/src/mir/mod.rs | 7 ++++--- compiler/rustc_middle/src/mir/patch.rs | 22 +++++++++------------ 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 0af587e8de83..6aef16643949 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1581,8 +1581,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } fn terminate_block(&mut self, reason: UnwindTerminateReason) -> Bx::BasicBlock { - if let Some(bb) = self.terminate_in_cleanup_block && reason == UnwindTerminateReason::InCleanup { - return bb; + if let Some((cached_bb, cached_reason)) = self.terminate_block && reason == cached_reason { + return cached_bb; } let funclet; @@ -1653,9 +1653,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.unreachable(); - if reason == UnwindTerminateReason::InCleanup { - self.terminate_in_cleanup_block = Some(llbb); - } + self.terminate_block = Some((llbb, reason)); llbb } diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 7f38c54c36f0..37a209cec5ef 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -5,6 +5,7 @@ use rustc_index::IndexVec; use rustc_middle::mir; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::traversal; +use rustc_middle::mir::UnwindTerminateReason; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_target::abi::call::{FnAbi, PassMode}; @@ -83,8 +84,8 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { /// Cached unreachable block unreachable_block: Option, - /// Cached terminate upon unwinding (reason: InCleanup) block - terminate_in_cleanup_block: Option, + /// Cached terminate upon unwinding block and its reason + terminate_block: Option<(Bx::BasicBlock, UnwindTerminateReason)>, /// The location where each MIR arg/var/tmp/ret is stored. This is /// usually an `PlaceRef` representing an alloca, but not always: @@ -199,7 +200,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( personality_slot: None, cached_llbbs, unreachable_block: None, - terminate_in_cleanup_block: None, + terminate_block: None, cleanup_kinds, landing_pads: IndexVec::from_elem(None, &mir.basic_blocks), funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks.len()), diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs index 419543b89889..da486c3465a6 100644 --- a/compiler/rustc_middle/src/mir/patch.rs +++ b/compiler/rustc_middle/src/mir/patch.rs @@ -14,8 +14,8 @@ pub struct MirPatch<'tcx> { resume_block: Option, // Only for unreachable in cleanup path. unreachable_cleanup_block: Option, - // Cached block for UnwindTerminate(InCleanup) - terminate_in_cleanup_block: Option, + // Cached block for UnwindTerminate (with reason) + terminate_block: Option<(BasicBlock, UnwindTerminateReason)>, body_span: Span, next_local: usize, } @@ -30,7 +30,7 @@ impl<'tcx> MirPatch<'tcx> { next_local: body.local_decls.len(), resume_block: None, unreachable_cleanup_block: None, - terminate_in_cleanup_block: None, + terminate_block: None, body_span: body.span, }; @@ -53,12 +53,10 @@ impl<'tcx> MirPatch<'tcx> { } // Check if we already have a terminate block - if matches!( - block.terminator().kind, - TerminatorKind::UnwindTerminate(UnwindTerminateReason::InCleanup) - ) && block.statements.is_empty() + if let TerminatorKind::UnwindTerminate(reason) = block.terminator().kind + && block.statements.is_empty() { - result.terminate_in_cleanup_block = Some(bb); + result.terminate_block = Some((bb, reason)); continue; } } @@ -101,8 +99,8 @@ impl<'tcx> MirPatch<'tcx> { } pub fn terminate_block(&mut self, reason: UnwindTerminateReason) -> BasicBlock { - if let Some(bb) = self.terminate_in_cleanup_block && reason == UnwindTerminateReason::InCleanup { - return bb; + if let Some((cached_bb, cached_reason)) = self.terminate_block && reason == cached_reason { + return cached_bb; } let bb = self.new_block(BasicBlockData { @@ -113,9 +111,7 @@ impl<'tcx> MirPatch<'tcx> { }), is_cleanup: true, }); - if reason == UnwindTerminateReason::InCleanup { - self.terminate_in_cleanup_block = Some(bb); - } + self.terminate_block = Some((bb, reason)); bb } From af29a26378cdd90d663c5a93d671e70184772266 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 22 Aug 2023 14:41:55 +0200 Subject: [PATCH 172/197] add tests for both kinds of unwind-terminate messages --- tests/ui/backtrace.rs | 13 ++++++++----- tests/ui/panics/panic-in-cleanup.rs | 19 +++++++++++++++++++ tests/ui/panics/panic-in-cleanup.run.stderr | 10 ++++++++++ tests/ui/panics/panic-in-ffi.rs | 15 +++++++++++++++ tests/ui/panics/panic-in-ffi.run.stderr | 7 +++++++ 5 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 tests/ui/panics/panic-in-cleanup.rs create mode 100644 tests/ui/panics/panic-in-cleanup.run.stderr create mode 100644 tests/ui/panics/panic-in-ffi.rs create mode 100644 tests/ui/panics/panic-in-ffi.run.stderr diff --git a/tests/ui/backtrace.rs b/tests/ui/backtrace.rs index 66b378f62d63..95783945529a 100644 --- a/tests/ui/backtrace.rs +++ b/tests/ui/backtrace.rs @@ -100,14 +100,17 @@ fn runtest(me: &str) { let s = str::from_utf8(&out.stderr).unwrap(); // loosened the following from double::h to double:: due to // spurious failures on mac, 32bit, optimized - assert!(s.contains("stack backtrace") && contains_verbose_expected(s, "double"), - "bad output3: {}", s); + assert!( + s.contains("stack backtrace") && + s.contains("panic in a destructor during cleanup") && + contains_verbose_expected(s, "double"), + "bad output3: {}", s + ); // Make sure a stack trace isn't printed too many times // - // Currently it is printed 3 times ("once", "twice" and "panic in a - // function that cannot unwind") but in the future the last one may be - // removed. + // Currently it is printed 3 times ("once", "twice" and "panic in a destructor during + // cleanup") but in the future the last one may be removed. let p = template(me).arg("double-fail") .env("RUST_BACKTRACE", "1").spawn().unwrap(); let out = p.wait_with_output().unwrap(); diff --git a/tests/ui/panics/panic-in-cleanup.rs b/tests/ui/panics/panic-in-cleanup.rs new file mode 100644 index 000000000000..b4519da4e6a7 --- /dev/null +++ b/tests/ui/panics/panic-in-cleanup.rs @@ -0,0 +1,19 @@ +// run-fail +// check-run-results +// error-pattern: panic in a destructor during cleanup +// normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" +// normalize-stderr-test: "\n +at [^\n]+" -> "" +// ignore-emscripten no processes + +struct Bomb; + +impl Drop for Bomb { + fn drop(&mut self) { + panic!("BOOM"); + } +} + +fn main() { + let _b = Bomb; + panic!(); +} diff --git a/tests/ui/panics/panic-in-cleanup.run.stderr b/tests/ui/panics/panic-in-cleanup.run.stderr new file mode 100644 index 000000000000..fa201b9667f2 --- /dev/null +++ b/tests/ui/panics/panic-in-cleanup.run.stderr @@ -0,0 +1,10 @@ +thread 'main' panicked at $DIR/panic-in-cleanup.rs:18:5: +explicit panic +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +thread 'main' panicked at $DIR/panic-in-cleanup.rs:12:9: +BOOM +stack backtrace: +thread 'main' panicked at library/core/src/panicking.rs:126:5: +panic in a destructor during cleanup +stack backtrace: +thread caused non-unwinding panic. aborting. diff --git a/tests/ui/panics/panic-in-ffi.rs b/tests/ui/panics/panic-in-ffi.rs new file mode 100644 index 000000000000..bb30398531f0 --- /dev/null +++ b/tests/ui/panics/panic-in-ffi.rs @@ -0,0 +1,15 @@ +// run-fail +// check-run-results +// error-pattern: panic in a function that cannot unwind +// normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" +// normalize-stderr-test: "\n +at [^\n]+" -> "" +// ignore-emscripten no processes +#![feature(c_unwind)] + +extern "C" fn panic_in_ffi() { + panic!("Test"); +} + +fn main() { + panic_in_ffi(); +} diff --git a/tests/ui/panics/panic-in-ffi.run.stderr b/tests/ui/panics/panic-in-ffi.run.stderr new file mode 100644 index 000000000000..a6de98c4913e --- /dev/null +++ b/tests/ui/panics/panic-in-ffi.run.stderr @@ -0,0 +1,7 @@ +thread 'main' panicked at $DIR/panic-in-ffi.rs:10:5: +Test +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +thread 'main' panicked at library/core/src/panicking.rs:126:5: +panic in a function that cannot unwind +stack backtrace: +thread caused non-unwinding panic. aborting. From 290ce462526872f4fee675a23011f6fa27960ff0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 24 Aug 2023 13:31:43 +0200 Subject: [PATCH 173/197] bless more mir-opt tests by hand --- .../inline/inline_into_box_place.main.Inline.panic-unwind.diff | 2 +- .../pre-codegen/loops.filter_mapped.PreCodegen.after.mir | 2 +- tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir | 2 +- tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir | 2 +- .../range_iter.forward_loop.PreCodegen.after.panic-unwind.mir | 2 +- .../range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir | 2 +- ...slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir | 2 +- .../slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir | 2 +- .../slice_iter.range_loop.PreCodegen.after.panic-unwind.mir | 2 +- .../slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff index 54c33aac9e80..d017900fc4c5 100644 --- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff @@ -155,7 +155,7 @@ - StorageDead(_1); - return; + bb3 (cleanup): { -+ drop(_2) -> [return: bb2, unwind terminate]; ++ drop(_2) -> [return: bb2, unwind terminate (panic in a destructor during cleanup)]; } - bb4 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir index 940b9ae11561..d7059d21488a 100644 --- a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir @@ -83,7 +83,7 @@ fn filter_mapped(_1: impl Iterator, _2: impl Fn(T) -> Option) -> () } bb9 (cleanup): { - drop(_5) -> [return: bb10, unwind terminate]; + drop(_5) -> [return: bb10, unwind terminate (panic in a destructor during cleanup)]; } bb10 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir index 2614160363e8..9a10f5cb575a 100644 --- a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir @@ -75,7 +75,7 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { } bb9 (cleanup): { - drop(_5) -> [return: bb10, unwind terminate]; + drop(_5) -> [return: bb10, unwind terminate (panic in a destructor during cleanup)]; } bb10 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir index 8eff46fb9312..431661af705b 100644 --- a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir @@ -67,7 +67,7 @@ fn vec_move(_1: Vec) -> () { } bb9 (cleanup): { - drop(_3) -> [return: bb10, unwind terminate]; + drop(_3) -> [return: bb10, unwind terminate (panic in a destructor during cleanup)]; } bb10 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir index 4d7c017dad40..7cada9c148d4 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -127,7 +127,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb11 (cleanup): { - drop(_3) -> [return: bb12, unwind terminate]; + drop(_3) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; } bb12 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir index bbab4e47a3ab..ef1f934c52b2 100644 --- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir @@ -82,7 +82,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb8 (cleanup): { - drop(_3) -> [return: bb9, unwind terminate]; + drop(_3) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)]; } bb9 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index 836fa2677b18..b9636712f826 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -195,7 +195,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb11 (cleanup): { - drop(_2) -> [return: bb12, unwind terminate]; + drop(_2) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; } bb12 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index 65baaf64a9e7..0f323a56e61d 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -182,7 +182,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb11 (cleanup): { - drop(_2) -> [return: bb12, unwind terminate]; + drop(_2) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; } bb12 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir index f7b19e80e448..96160b272b98 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir @@ -143,7 +143,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb12 (cleanup): { - drop(_2) -> [return: bb13, unwind terminate]; + drop(_2) -> [return: bb13, unwind terminate (panic in a destructor during cleanup)]; } bb13 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index 43f8806e165a..67d8442ab206 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -196,7 +196,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb11 (cleanup): { - drop(_2) -> [return: bb12, unwind terminate]; + drop(_2) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; } bb12 (cleanup): { From e4c4f9b9d9dff15a8292c04057e538f3f3dbf797 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 24 Aug 2023 13:46:37 +0200 Subject: [PATCH 174/197] remove some unnecessary ignore-debug clauses --- tests/mir-opt/pre-codegen/chained_comparison.rs | 1 - tests/mir-opt/pre-codegen/checked_ops.rs | 1 - tests/mir-opt/pre-codegen/intrinsics.rs | 1 - tests/mir-opt/pre-codegen/loops.rs | 1 - tests/mir-opt/pre-codegen/mem_replace.rs | 2 +- tests/mir-opt/pre-codegen/range_iter.rs | 1 - .../pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir | 4 ++-- tests/mir-opt/pre-codegen/simple_option_map.rs | 1 - tests/mir-opt/pre-codegen/slice_index.rs | 2 +- tests/mir-opt/pre-codegen/slice_iter.rs | 2 +- tests/mir-opt/pre-codegen/try_identity.rs | 1 - tests/ui/consts/std/alloc.32bit.stderr | 4 ++-- tests/ui/consts/std/alloc.64bit.stderr | 4 ++-- tests/ui/consts/std/alloc.rs | 1 - 14 files changed, 9 insertions(+), 17 deletions(-) diff --git a/tests/mir-opt/pre-codegen/chained_comparison.rs b/tests/mir-opt/pre-codegen/chained_comparison.rs index f7879140f812..430300419837 100644 --- a/tests/mir-opt/pre-codegen/chained_comparison.rs +++ b/tests/mir-opt/pre-codegen/chained_comparison.rs @@ -1,5 +1,4 @@ // compile-flags: -O -Zmir-opt-level=2 -Cdebuginfo=2 -// ignore-debug #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/checked_ops.rs b/tests/mir-opt/pre-codegen/checked_ops.rs index dee43b0c6f88..23d78e987777 100644 --- a/tests/mir-opt/pre-codegen/checked_ops.rs +++ b/tests/mir-opt/pre-codegen/checked_ops.rs @@ -1,6 +1,5 @@ // compile-flags: -O -Zmir-opt-level=2 -Cdebuginfo=2 // needs-unwind -// ignore-debug // only-x86_64 #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/intrinsics.rs b/tests/mir-opt/pre-codegen/intrinsics.rs index ecdb656cb85a..e32e04384c4b 100644 --- a/tests/mir-opt/pre-codegen/intrinsics.rs +++ b/tests/mir-opt/pre-codegen/intrinsics.rs @@ -1,6 +1,5 @@ // compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 // only-64bit -// ignore-debug // Checks that we do not have any branches in the MIR for the two tested functions. diff --git a/tests/mir-opt/pre-codegen/loops.rs b/tests/mir-opt/pre-codegen/loops.rs index 67f549a511c8..f3ba409229d6 100644 --- a/tests/mir-opt/pre-codegen/loops.rs +++ b/tests/mir-opt/pre-codegen/loops.rs @@ -1,6 +1,5 @@ // compile-flags: -O -Zmir-opt-level=2 -g // needs-unwind -// ignore-debug #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/mem_replace.rs b/tests/mir-opt/pre-codegen/mem_replace.rs index e5066c38b967..a139848bab26 100644 --- a/tests/mir-opt/pre-codegen/mem_replace.rs +++ b/tests/mir-opt/pre-codegen/mem_replace.rs @@ -1,6 +1,6 @@ // compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 // only-64bit -// ignore-debug +// ignore-debug the standard library debug assertions leak into this test #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/range_iter.rs b/tests/mir-opt/pre-codegen/range_iter.rs index cabd9419e920..9552144787d1 100644 --- a/tests/mir-opt/pre-codegen/range_iter.rs +++ b/tests/mir-opt/pre-codegen/range_iter.rs @@ -1,6 +1,5 @@ // compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 // only-64bit -// ignore-debug // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir index 68d78f743281..312565e45c33 100644 --- a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir @@ -3,9 +3,9 @@ fn ezmap(_1: Option) -> Option { debug x => _1; let mut _0: std::option::Option; - scope 1 (inlined map::) { + scope 1 (inlined map::) { debug slf => _1; - debug f => const ZeroSized: [closure@$DIR/simple_option_map.rs:18:12: 18:15]; + debug f => const ZeroSized: [closure@$DIR/simple_option_map.rs:17:12: 17:15]; let mut _2: isize; let _3: i32; let mut _4: i32; diff --git a/tests/mir-opt/pre-codegen/simple_option_map.rs b/tests/mir-opt/pre-codegen/simple_option_map.rs index fb3da68e4af2..d4f28dda6c62 100644 --- a/tests/mir-opt/pre-codegen/simple_option_map.rs +++ b/tests/mir-opt/pre-codegen/simple_option_map.rs @@ -1,6 +1,5 @@ // compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 // only-64bit -// ignore-debug #[inline(always)] fn map(slf: Option, f: F) -> Option diff --git a/tests/mir-opt/pre-codegen/slice_index.rs b/tests/mir-opt/pre-codegen/slice_index.rs index d80bff50c31c..57ffb07e2947 100644 --- a/tests/mir-opt/pre-codegen/slice_index.rs +++ b/tests/mir-opt/pre-codegen/slice_index.rs @@ -1,6 +1,6 @@ // compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 // only-64bit -// ignore-debug +// ignore-debug the standard library debug assertions leak into this test // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/slice_iter.rs b/tests/mir-opt/pre-codegen/slice_iter.rs index 4e954aa34330..1790056369cd 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.rs +++ b/tests/mir-opt/pre-codegen/slice_iter.rs @@ -1,6 +1,6 @@ // compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 // only-64bit -// ignore-debug +// ignore-debug the standard library debug assertions leak into this test // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/try_identity.rs b/tests/mir-opt/pre-codegen/try_identity.rs index 079ecccab28c..a227c82d6a30 100644 --- a/tests/mir-opt/pre-codegen/try_identity.rs +++ b/tests/mir-opt/pre-codegen/try_identity.rs @@ -1,6 +1,5 @@ // compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 // only-64bit -// ignore-debug // Track the status of MIR optimizations simplifying `Ok(res?)` for both the old and new desugarings // of that syntax. diff --git a/tests/ui/consts/std/alloc.32bit.stderr b/tests/ui/consts/std/alloc.32bit.stderr index 8c83df53dade..da805de451c4 100644 --- a/tests/ui/consts/std/alloc.32bit.stderr +++ b/tests/ui/consts/std/alloc.32bit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/alloc.rs:12:1 + --> $DIR/alloc.rs:11:1 | LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x00000000, but expected a valid enum tag @@ -10,7 +10,7 @@ LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchec } error[E0080]: it is undefined behavior to use this value - --> $DIR/alloc.rs:16:1 + --> $DIR/alloc.rs:15:1 | LL | const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x00000003, but expected a valid enum tag diff --git a/tests/ui/consts/std/alloc.64bit.stderr b/tests/ui/consts/std/alloc.64bit.stderr index addedad17047..094503e10399 100644 --- a/tests/ui/consts/std/alloc.64bit.stderr +++ b/tests/ui/consts/std/alloc.64bit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/alloc.rs:12:1 + --> $DIR/alloc.rs:11:1 | LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x0000000000000000, but expected a valid enum tag @@ -10,7 +10,7 @@ LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchec } error[E0080]: it is undefined behavior to use this value - --> $DIR/alloc.rs:16:1 + --> $DIR/alloc.rs:15:1 | LL | const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x0000000000000003, but expected a valid enum tag diff --git a/tests/ui/consts/std/alloc.rs b/tests/ui/consts/std/alloc.rs index 9abf35d63d30..0a2c2f4dec80 100644 --- a/tests/ui/consts/std/alloc.rs +++ b/tests/ui/consts/std/alloc.rs @@ -1,5 +1,4 @@ // stderr-per-bitwidth -// ignore-debug (the debug assertions change the error) // Strip out raw byte dumps to make comparison platform-independent: // normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" // normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" From 6f8ae03f9b485c41a3c4fbc1f0d854b30b6e283a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 24 Aug 2023 14:26:26 +0200 Subject: [PATCH 175/197] make MIR less verbose --- compiler/rustc_middle/src/mir/terminator.rs | 17 +++++++++++++---- ...nic_abort.main.AbortUnwindingCalls.after.mir | 2 +- .../basic_assignment.main.ElaborateDrops.diff | 6 +++--- ...ssignment.main.SimplifyCfg-initial.after.mir | 6 +++--- ...r.main.ElaborateDrops.before.panic-abort.mir | 6 +++--- ....main.ElaborateDrops.before.panic-unwind.mir | 6 +++--- .../building/enum_cast.droppy.built.after.mir | 2 +- ...ove_out.move_out_by_subslice.built.after.mir | 6 +++--- ...y_move_out.move_out_from_end.built.after.mir | 6 +++--- ...impl#0}-clone.InstSimplify.panic-unwind.diff | 2 +- ...er_inline_test.main.Derefer.panic-abort.diff | 2 +- ...r_inline_test.main.Derefer.panic-unwind.diff | 2 +- ...re#0}.StateTransform.before.panic-unwind.mir | 4 ++-- .../asm_unwind.main.Inline.panic-abort.diff | 2 +- .../asm_unwind.main.Inline.panic-unwind.diff | 2 +- .../inline/cycle.f.Inline.panic-unwind.diff | 2 +- .../inline/cycle.g.Inline.panic-unwind.diff | 2 +- .../inline/cycle.main.Inline.panic-unwind.diff | 2 +- ...eric_rust_call.call.Inline.panic-unwind.diff | 2 +- .../inline_box_fn.call.Inline.panic-unwind.diff | 2 +- .../inline_diverging.h.Inline.panic-unwind.diff | 4 ++-- ...into_box_place.main.Inline.panic-unwind.diff | 2 +- .../issue_78442.bar.Inline.panic-unwind.diff | 2 +- .../issue_78442.bar.RevealAll.panic-unwind.diff | 2 +- .../inline/unsized_argument.caller.Inline.diff | 2 +- ...e_41110.main.ElaborateDrops.panic-abort.diff | 8 ++++---- ..._41110.main.ElaborateDrops.panic-unwind.diff | 8 ++++---- ...e_41110.test.ElaborateDrops.panic-abort.diff | 10 +++++----- ..._41110.test.ElaborateDrops.panic-unwind.diff | 10 +++++----- ...e_41888.main.ElaborateDrops.panic-abort.diff | 6 +++--- ..._41888.main.ElaborateDrops.panic-unwind.diff | 6 +++--- ...9.test.ElaborateDrops.before.panic-abort.mir | 4 ++-- ....test.ElaborateDrops.before.panic-unwind.mir | 4 ++-- tests/mir-opt/issue_91633.bar.built.after.mir | 2 +- tests/mir-opt/issue_91633.foo.built.after.mir | 2 +- ...yCfg-initial.after-ElaborateDrops.after.diff | 2 +- ...yCfg-initial.after-ElaborateDrops.after.diff | 2 +- ...l.main.ElaborateDrops.before.panic-abort.mir | 2 +- ....main.ElaborateDrops.before.panic-unwind.mir | 2 +- ...fyCfg-elaborate-drops.after.panic-unwind.mir | 2 +- .../loops.filter_mapped.PreCodegen.after.mir | 2 +- .../loops.mapped.PreCodegen.after.mir | 2 +- .../loops.vec_move.PreCodegen.after.mir | 2 +- ...rward_loop.PreCodegen.after.panic-unwind.mir | 2 +- ...usive_loop.PreCodegen.after.panic-unwind.mir | 2 +- ...rated_loop.PreCodegen.after.panic-unwind.mir | 2 +- ...rward_loop.PreCodegen.after.panic-unwind.mir | 2 +- ...range_loop.PreCodegen.after.panic-unwind.mir | 2 +- ...verse_loop.PreCodegen.after.panic-unwind.mir | 2 +- ...fyCfg-elaborate-drops.after.panic-unwind.mir | 4 ++-- ...e.[String].AddMovesForPackedDrops.before.mir | 2 +- ...e.Vec_i32_.AddMovesForPackedDrops.before.mir | 2 +- 52 files changed, 99 insertions(+), 90 deletions(-) diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index c4d7f122ea99..7eddf13b3fb5 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -119,6 +119,14 @@ impl UnwindTerminateReason { } } + /// A short representation of this used for MIR printing. + pub fn as_short_str(self) -> &'static str { + match self { + UnwindTerminateReason::Abi => "abi", + UnwindTerminateReason::InCleanup => "cleanup", + } + } + pub fn lang_item(self) -> LangItem { match self { UnwindTerminateReason::Abi => LangItem::PanicCannotUnwind, @@ -301,13 +309,14 @@ impl<'tcx> Debug for TerminatorKind<'tcx> { // `Cleanup` is already included in successors let show_unwind = !matches!(self.unwind(), None | Some(UnwindAction::Cleanup(_))); let fmt_unwind = |fmt: &mut Formatter<'_>| -> fmt::Result { + write!(fmt, "unwind ")?; match self.unwind() { // Not needed or included in successors None | Some(UnwindAction::Cleanup(_)) => unreachable!(), - Some(UnwindAction::Continue) => write!(fmt, "unwind continue"), - Some(UnwindAction::Unreachable) => write!(fmt, "unwind unreachable"), + Some(UnwindAction::Continue) => write!(fmt, "continue"), + Some(UnwindAction::Unreachable) => write!(fmt, "unreachable"), Some(UnwindAction::Terminate(reason)) => { - write!(fmt, "unwind terminate ({})", reason.as_str()) + write!(fmt, "terminate({})", reason.as_short_str()) } } }; @@ -350,7 +359,7 @@ impl<'tcx> TerminatorKind<'tcx> { GeneratorDrop => write!(fmt, "generator_drop"), UnwindResume => write!(fmt, "resume"), UnwindTerminate(reason) => { - write!(fmt, "abort(\"{}\")", reason.as_str()) + write!(fmt, "abort({})", reason.as_short_str()) } Yield { value, resume_arg, .. } => write!(fmt, "{resume_arg:?} = yield({value:?})"), Unreachable => write!(fmt, "unreachable"), diff --git a/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir b/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir index 8b9c853eb853..6c3128f8c36f 100644 --- a/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir +++ b/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir @@ -9,7 +9,7 @@ fn main() -> () { bb0: { StorageLive(_1); _1 = const (); - asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind terminate (panic in a function that cannot unwind)]; + asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind terminate(abi)]; } bb1: { diff --git a/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff b/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff index 2b6e0fe489a6..f187f9597279 100644 --- a/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff +++ b/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff @@ -47,7 +47,7 @@ bb2 (cleanup): { _5 = move _6; -- drop(_6) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)]; +- drop(_6) -> [return: bb6, unwind terminate(cleanup)]; + goto -> bb6; } @@ -71,12 +71,12 @@ } bb6 (cleanup): { -- drop(_5) -> [return: bb7, unwind terminate (panic in a destructor during cleanup)]; +- drop(_5) -> [return: bb7, unwind terminate(cleanup)]; + goto -> bb7; } bb7 (cleanup): { -- drop(_4) -> [return: bb8, unwind terminate (panic in a destructor during cleanup)]; +- drop(_4) -> [return: bb8, unwind terminate(cleanup)]; + goto -> bb8; } diff --git a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir index fac407ae1ea6..75070ffda11f 100644 --- a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir @@ -51,7 +51,7 @@ fn main() -> () { bb2 (cleanup): { _5 = move _6; - drop(_6) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)]; + drop(_6) -> [return: bb6, unwind terminate(cleanup)]; } bb3: { @@ -73,11 +73,11 @@ fn main() -> () { } bb6 (cleanup): { - drop(_5) -> [return: bb7, unwind terminate (panic in a destructor during cleanup)]; + drop(_5) -> [return: bb7, unwind terminate(cleanup)]; } bb7 (cleanup): { - drop(_4) -> [return: bb8, unwind terminate (panic in a destructor during cleanup)]; + drop(_4) -> [return: bb8, unwind terminate(cleanup)]; } bb8 (cleanup): { diff --git a/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-abort.mir b/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-abort.mir index f7cfcf27fe5f..1c7ef7f83456 100644 --- a/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-abort.mir +++ b/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-abort.mir @@ -54,15 +54,15 @@ fn main() -> () { } bb6 (cleanup): { - drop(_7) -> [return: bb7, unwind terminate (panic in a destructor during cleanup)]; + drop(_7) -> [return: bb7, unwind terminate(cleanup)]; } bb7 (cleanup): { - drop(_1) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)]; + drop(_1) -> [return: bb9, unwind terminate(cleanup)]; } bb8 (cleanup): { - drop(_5) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)]; + drop(_5) -> [return: bb9, unwind terminate(cleanup)]; } bb9 (cleanup): { diff --git a/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-unwind.mir b/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-unwind.mir index 4cfdc8701c6b..4ad1c2de1298 100644 --- a/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-unwind.mir +++ b/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-unwind.mir @@ -54,15 +54,15 @@ fn main() -> () { } bb6 (cleanup): { - drop(_7) -> [return: bb7, unwind terminate (panic in a destructor during cleanup)]; + drop(_7) -> [return: bb7, unwind terminate(cleanup)]; } bb7 (cleanup): { - drop(_1) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)]; + drop(_1) -> [return: bb9, unwind terminate(cleanup)]; } bb8 (cleanup): { - drop(_5) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)]; + drop(_5) -> [return: bb9, unwind terminate(cleanup)]; } bb9 (cleanup): { diff --git a/tests/mir-opt/building/enum_cast.droppy.built.after.mir b/tests/mir-opt/building/enum_cast.droppy.built.after.mir index d1f8b8daf74d..ea0edb610f5c 100644 --- a/tests/mir-opt/building/enum_cast.droppy.built.after.mir +++ b/tests/mir-opt/building/enum_cast.droppy.built.after.mir @@ -62,7 +62,7 @@ fn droppy() -> () { } bb4 (cleanup): { - drop(_2) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; + drop(_2) -> [return: bb5, unwind terminate(cleanup)]; } bb5 (cleanup): { diff --git a/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir b/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir index f7fc1eb7ce30..82424de03926 100644 --- a/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir +++ b/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir @@ -89,15 +89,15 @@ fn move_out_by_subslice() -> () { } bb9 (cleanup): { - drop(_1) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; + drop(_1) -> [return: bb12, unwind terminate(cleanup)]; } bb10 (cleanup): { - drop(_7) -> [return: bb11, unwind terminate (panic in a destructor during cleanup)]; + drop(_7) -> [return: bb11, unwind terminate(cleanup)]; } bb11 (cleanup): { - drop(_2) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; + drop(_2) -> [return: bb12, unwind terminate(cleanup)]; } bb12 (cleanup): { diff --git a/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir b/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir index 95c061dc9fa9..0872d1b6ac0c 100644 --- a/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir +++ b/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir @@ -89,15 +89,15 @@ fn move_out_from_end() -> () { } bb9 (cleanup): { - drop(_1) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; + drop(_1) -> [return: bb12, unwind terminate(cleanup)]; } bb10 (cleanup): { - drop(_7) -> [return: bb11, unwind terminate (panic in a destructor during cleanup)]; + drop(_7) -> [return: bb11, unwind terminate(cleanup)]; } bb11 (cleanup): { - drop(_2) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; + drop(_2) -> [return: bb12, unwind terminate(cleanup)]; } bb12 (cleanup): { diff --git a/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-unwind.diff b/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-unwind.diff index 20f627a567db..f2b87221f2b9 100644 --- a/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-unwind.diff +++ b/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-unwind.diff @@ -63,7 +63,7 @@ } bb4 (cleanup): { - drop(_2) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; + drop(_2) -> [return: bb5, unwind terminate(cleanup)]; } bb5 (cleanup): { diff --git a/tests/mir-opt/derefer_inline_test.main.Derefer.panic-abort.diff b/tests/mir-opt/derefer_inline_test.main.Derefer.panic-abort.diff index b59a377d27ca..8ac6acd0e4a8 100644 --- a/tests/mir-opt/derefer_inline_test.main.Derefer.panic-abort.diff +++ b/tests/mir-opt/derefer_inline_test.main.Derefer.panic-abort.diff @@ -28,7 +28,7 @@ } bb4 (cleanup): { - drop(_2) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; + drop(_2) -> [return: bb5, unwind terminate(cleanup)]; } bb5 (cleanup): { diff --git a/tests/mir-opt/derefer_inline_test.main.Derefer.panic-unwind.diff b/tests/mir-opt/derefer_inline_test.main.Derefer.panic-unwind.diff index effecc03738d..aa9fcb505e64 100644 --- a/tests/mir-opt/derefer_inline_test.main.Derefer.panic-unwind.diff +++ b/tests/mir-opt/derefer_inline_test.main.Derefer.panic-unwind.diff @@ -28,7 +28,7 @@ } bb4 (cleanup): { - drop(_2) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; + drop(_2) -> [return: bb5, unwind terminate(cleanup)]; } bb5 (cleanup): { diff --git a/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir b/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir index 8ec9c46f95f0..6fcceb6c66bf 100644 --- a/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir +++ b/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir @@ -104,7 +104,7 @@ yields () bb13 (cleanup): { StorageDead(_3); - drop(_1) -> [return: bb14, unwind terminate (panic in a destructor during cleanup)]; + drop(_1) -> [return: bb14, unwind terminate(cleanup)]; } bb14 (cleanup): { @@ -113,6 +113,6 @@ yields () bb15 (cleanup): { StorageDead(_3); - drop(_1) -> [return: bb14, unwind terminate (panic in a destructor during cleanup)]; + drop(_1) -> [return: bb14, unwind terminate(cleanup)]; } } diff --git a/tests/mir-opt/inline/asm_unwind.main.Inline.panic-abort.diff b/tests/mir-opt/inline/asm_unwind.main.Inline.panic-abort.diff index 2371297aefb6..aa9429c46d84 100644 --- a/tests/mir-opt/inline/asm_unwind.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/asm_unwind.main.Inline.panic-abort.diff @@ -17,7 +17,7 @@ StorageLive(_1); - _1 = foo() -> [return: bb1, unwind unreachable]; + StorageLive(_2); -+ asm!("", options(MAY_UNWIND)) -> [return: bb2, unwind terminate (panic in a function that cannot unwind)]; ++ asm!("", options(MAY_UNWIND)) -> [return: bb2, unwind terminate(abi)]; } bb1: { diff --git a/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff index 4c0be81ea267..ea9c360aa7b3 100644 --- a/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff @@ -32,7 +32,7 @@ + } + + bb3 (cleanup): { -+ drop(_2) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)]; ++ drop(_2) -> [return: bb4, unwind terminate(cleanup)]; + } + + bb4 (cleanup): { diff --git a/tests/mir-opt/inline/cycle.f.Inline.panic-unwind.diff b/tests/mir-opt/inline/cycle.f.Inline.panic-unwind.diff index 6e95225a43d0..b7fea4f2e147 100644 --- a/tests/mir-opt/inline/cycle.f.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/cycle.f.Inline.panic-unwind.diff @@ -30,7 +30,7 @@ } bb3 (cleanup): { - drop(_1) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)]; + drop(_1) -> [return: bb4, unwind terminate(cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff b/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff index cd3ea5ebd0e6..1fd1014ba1d5 100644 --- a/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff @@ -36,7 +36,7 @@ + } + + bb3 (cleanup): { -+ drop(_2) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)]; ++ drop(_2) -> [return: bb4, unwind terminate(cleanup)]; + } + + bb4 (cleanup): { diff --git a/tests/mir-opt/inline/cycle.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/cycle.main.Inline.panic-unwind.diff index 66ce2f92186b..e8299db47db7 100644 --- a/tests/mir-opt/inline/cycle.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/cycle.main.Inline.panic-unwind.diff @@ -36,7 +36,7 @@ + } + + bb3 (cleanup): { -+ drop(_2) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)]; ++ drop(_2) -> [return: bb4, unwind terminate(cleanup)]; + } + + bb4 (cleanup): { diff --git a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff index daabb0ffc217..b82961c2815d 100644 --- a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff @@ -27,7 +27,7 @@ } bb3 (cleanup): { - drop(_1) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)]; + drop(_1) -> [return: bb4, unwind terminate(cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff index b3fee11e7dd3..47fd0ed07999 100644 --- a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff @@ -30,7 +30,7 @@ } bb3 (cleanup): { - drop(_1) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)]; + drop(_1) -> [return: bb4, unwind terminate(cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff index e3f5e9810c6a..9f8c5806c90f 100644 --- a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff @@ -54,11 +54,11 @@ + } + + bb4 (cleanup): { -+ drop(_4) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; ++ drop(_4) -> [return: bb5, unwind terminate(cleanup)]; + } + + bb5 (cleanup): { -+ drop(_2) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)]; ++ drop(_2) -> [return: bb6, unwind terminate(cleanup)]; + } + + bb6 (cleanup): { diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff index d017900fc4c5..675292f06d66 100644 --- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff @@ -155,7 +155,7 @@ - StorageDead(_1); - return; + bb3 (cleanup): { -+ drop(_2) -> [return: bb2, unwind terminate (panic in a destructor during cleanup)]; ++ drop(_2) -> [return: bb2, unwind terminate(cleanup)]; } - bb4 (cleanup): { diff --git a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff index 9042121ea9f5..5a946712ea43 100644 --- a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff @@ -37,7 +37,7 @@ } bb4 (cleanup): { - drop(_1) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; + drop(_1) -> [return: bb5, unwind terminate(cleanup)]; } bb5 (cleanup): { diff --git a/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff b/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff index 2a55b018f7c0..cbfb39115b37 100644 --- a/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff +++ b/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff @@ -40,7 +40,7 @@ } bb4 (cleanup): { - drop(_1) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; + drop(_1) -> [return: bb5, unwind terminate(cleanup)]; } bb5 (cleanup): { diff --git a/tests/mir-opt/inline/unsized_argument.caller.Inline.diff b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff index 0cddc5a36b1b..ab81f7071486 100644 --- a/tests/mir-opt/inline/unsized_argument.caller.Inline.diff +++ b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff @@ -40,7 +40,7 @@ bb4 (cleanup): { _8 = &mut _3; - _9 = as Drop>::drop(move _8) -> [return: bb1, unwind terminate (panic in a destructor during cleanup)]; + _9 = as Drop>::drop(move _8) -> [return: bb1, unwind terminate(cleanup)]; } } diff --git a/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-abort.diff b/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-abort.diff index 4f7ca616792d..4469270a9b23 100644 --- a/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-abort.diff +++ b/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-abort.diff @@ -40,17 +40,17 @@ } bb3 (cleanup): { -- drop(_3) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; +- drop(_3) -> [return: bb5, unwind terminate(cleanup)]; + goto -> bb5; } bb4 (cleanup): { -- drop(_4) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; +- drop(_4) -> [return: bb5, unwind terminate(cleanup)]; + goto -> bb5; } bb5 (cleanup): { -- drop(_2) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)]; +- drop(_2) -> [return: bb6, unwind terminate(cleanup)]; + goto -> bb8; } @@ -59,7 +59,7 @@ + } + + bb7 (cleanup): { -+ drop(_2) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)]; ++ drop(_2) -> [return: bb6, unwind terminate(cleanup)]; + } + + bb8 (cleanup): { diff --git a/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-unwind.diff index 4f7ca616792d..4469270a9b23 100644 --- a/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-unwind.diff +++ b/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-unwind.diff @@ -40,17 +40,17 @@ } bb3 (cleanup): { -- drop(_3) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; +- drop(_3) -> [return: bb5, unwind terminate(cleanup)]; + goto -> bb5; } bb4 (cleanup): { -- drop(_4) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)]; +- drop(_4) -> [return: bb5, unwind terminate(cleanup)]; + goto -> bb5; } bb5 (cleanup): { -- drop(_2) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)]; +- drop(_2) -> [return: bb6, unwind terminate(cleanup)]; + goto -> bb8; } @@ -59,7 +59,7 @@ + } + + bb7 (cleanup): { -+ drop(_2) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)]; ++ drop(_2) -> [return: bb6, unwind terminate(cleanup)]; + } + + bb8 (cleanup): { diff --git a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff index 0f38e3961a6f..78184f6aeeb1 100644 --- a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff +++ b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff @@ -47,7 +47,7 @@ bb3 (cleanup): { _2 = move _5; -- drop(_5) -> [return: bb8, unwind terminate (panic in a destructor during cleanup)]; +- drop(_5) -> [return: bb8, unwind terminate(cleanup)]; + goto -> bb8; } @@ -70,17 +70,17 @@ } bb7 (cleanup): { -- drop(_4) -> [return: bb8, unwind terminate (panic in a destructor during cleanup)]; +- drop(_4) -> [return: bb8, unwind terminate(cleanup)]; + goto -> bb8; } bb8 (cleanup): { -- drop(_2) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)]; +- drop(_2) -> [return: bb9, unwind terminate(cleanup)]; + goto -> bb9; } bb9 (cleanup): { -- drop(_1) -> [return: bb10, unwind terminate (panic in a destructor during cleanup)]; +- drop(_1) -> [return: bb10, unwind terminate(cleanup)]; + goto -> bb12; } @@ -89,7 +89,7 @@ + } + + bb11 (cleanup): { -+ drop(_1) -> [return: bb10, unwind terminate (panic in a destructor during cleanup)]; ++ drop(_1) -> [return: bb10, unwind terminate(cleanup)]; + } + + bb12 (cleanup): { diff --git a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff index 8da15ec9e23e..688887c3c1f5 100644 --- a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff +++ b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff @@ -47,7 +47,7 @@ bb3 (cleanup): { _2 = move _5; -- drop(_5) -> [return: bb8, unwind terminate (panic in a destructor during cleanup)]; +- drop(_5) -> [return: bb8, unwind terminate(cleanup)]; + goto -> bb8; } @@ -70,17 +70,17 @@ } bb7 (cleanup): { -- drop(_4) -> [return: bb8, unwind terminate (panic in a destructor during cleanup)]; +- drop(_4) -> [return: bb8, unwind terminate(cleanup)]; + goto -> bb8; } bb8 (cleanup): { -- drop(_2) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)]; +- drop(_2) -> [return: bb9, unwind terminate(cleanup)]; + goto -> bb9; } bb9 (cleanup): { -- drop(_1) -> [return: bb10, unwind terminate (panic in a destructor during cleanup)]; +- drop(_1) -> [return: bb10, unwind terminate(cleanup)]; + goto -> bb12; } @@ -89,7 +89,7 @@ + } + + bb11 (cleanup): { -+ drop(_1) -> [return: bb10, unwind terminate (panic in a destructor during cleanup)]; ++ drop(_1) -> [return: bb10, unwind terminate(cleanup)]; + } + + bb12 (cleanup): { diff --git a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff index 562e684f29fd..b57fe348c2d9 100644 --- a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff +++ b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff @@ -58,7 +58,7 @@ + _8 = const true; + _9 = const true; _1 = move _3; -- drop(_3) -> [return: bb11, unwind terminate (panic in a destructor during cleanup)]; +- drop(_3) -> [return: bb11, unwind terminate(cleanup)]; + goto -> bb11; } @@ -102,7 +102,7 @@ } bb11 (cleanup): { -- drop(_1) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; +- drop(_1) -> [return: bb12, unwind terminate(cleanup)]; + goto -> bb12; } @@ -124,7 +124,7 @@ + } + + bb16 (cleanup): { -+ drop(_1) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; ++ drop(_1) -> [return: bb12, unwind terminate(cleanup)]; + } + + bb17: { diff --git a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff index c6cc80c09c08..2156850e38c0 100644 --- a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff +++ b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff @@ -58,7 +58,7 @@ + _8 = const true; + _9 = const true; _1 = move _3; -- drop(_3) -> [return: bb11, unwind terminate (panic in a destructor during cleanup)]; +- drop(_3) -> [return: bb11, unwind terminate(cleanup)]; + goto -> bb11; } @@ -102,7 +102,7 @@ } bb11 (cleanup): { -- drop(_1) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; +- drop(_1) -> [return: bb12, unwind terminate(cleanup)]; + goto -> bb12; } @@ -124,7 +124,7 @@ + } + + bb16 (cleanup): { -+ drop(_1) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; ++ drop(_1) -> [return: bb12, unwind terminate(cleanup)]; + } + + bb17: { diff --git a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir index 151571f57eb3..734629678503 100644 --- a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir +++ b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir @@ -100,11 +100,11 @@ fn test() -> Option> { } bb11 (cleanup): { - drop(_1) -> [return: bb13, unwind terminate (panic in a destructor during cleanup)]; + drop(_1) -> [return: bb13, unwind terminate(cleanup)]; } bb12 (cleanup): { - drop(_5) -> [return: bb13, unwind terminate (panic in a destructor during cleanup)]; + drop(_5) -> [return: bb13, unwind terminate(cleanup)]; } bb13 (cleanup): { diff --git a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir index bda3080edb9d..8264e2cabbc5 100644 --- a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir +++ b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir @@ -100,11 +100,11 @@ fn test() -> Option> { } bb11 (cleanup): { - drop(_1) -> [return: bb13, unwind terminate (panic in a destructor during cleanup)]; + drop(_1) -> [return: bb13, unwind terminate(cleanup)]; } bb12 (cleanup): { - drop(_5) -> [return: bb13, unwind terminate (panic in a destructor during cleanup)]; + drop(_5) -> [return: bb13, unwind terminate(cleanup)]; } bb13 (cleanup): { diff --git a/tests/mir-opt/issue_91633.bar.built.after.mir b/tests/mir-opt/issue_91633.bar.built.after.mir index 6aa49aab20e3..cce1a1fd2ef4 100644 --- a/tests/mir-opt/issue_91633.bar.built.after.mir +++ b/tests/mir-opt/issue_91633.bar.built.after.mir @@ -28,7 +28,7 @@ fn bar(_1: Box<[T]>) -> () { } bb3 (cleanup): { - drop(_1) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)]; + drop(_1) -> [return: bb4, unwind terminate(cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/issue_91633.foo.built.after.mir b/tests/mir-opt/issue_91633.foo.built.after.mir index 2cf683217432..a66769f0d112 100644 --- a/tests/mir-opt/issue_91633.foo.built.after.mir +++ b/tests/mir-opt/issue_91633.foo.built.after.mir @@ -45,7 +45,7 @@ fn foo(_1: Box<[T]>) -> T { } bb5 (cleanup): { - drop(_1) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)]; + drop(_1) -> [return: bb6, unwind terminate(cleanup)]; } bb6 (cleanup): { diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff index 9452ba7e6bc9..3e817ff433b8 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -243,7 +243,7 @@ } - bb25 (cleanup): { -- drop(_2) -> [return: bb26, unwind terminate (panic in a destructor during cleanup)]; +- drop(_2) -> [return: bb26, unwind terminate(cleanup)]; + bb22 (cleanup): { + goto -> bb27; } diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff index 9452ba7e6bc9..3e817ff433b8 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -243,7 +243,7 @@ } - bb25 (cleanup): { -- drop(_2) -> [return: bb26, unwind terminate (panic in a destructor during cleanup)]; +- drop(_2) -> [return: bb26, unwind terminate(cleanup)]; + bb22 (cleanup): { + goto -> bb27; } diff --git a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-abort.mir b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-abort.mir index 51a009056d74..99a7a6b6154d 100644 --- a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-abort.mir +++ b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-abort.mir @@ -31,7 +31,7 @@ fn main() -> () { } bb3 (cleanup): { - drop(_2) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)]; + drop(_2) -> [return: bb4, unwind terminate(cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-unwind.mir b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-unwind.mir index 95820cfafbc1..7364b329e123 100644 --- a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-unwind.mir +++ b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-unwind.mir @@ -31,7 +31,7 @@ fn main() -> () { } bb3 (cleanup): { - drop(_2) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)]; + drop(_2) -> [return: bb4, unwind terminate(cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir b/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir index 9a43756cbc06..0ef19180459d 100644 --- a/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir +++ b/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir @@ -33,7 +33,7 @@ fn main() -> () { bb1 (cleanup): { (_1.0: Aligned) = move _4; - drop(_1) -> [return: bb3, unwind terminate (panic in a destructor during cleanup)]; + drop(_1) -> [return: bb3, unwind terminate(cleanup)]; } bb2: { diff --git a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir index d7059d21488a..4db829a5ec34 100644 --- a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir @@ -83,7 +83,7 @@ fn filter_mapped(_1: impl Iterator, _2: impl Fn(T) -> Option) -> () } bb9 (cleanup): { - drop(_5) -> [return: bb10, unwind terminate (panic in a destructor during cleanup)]; + drop(_5) -> [return: bb10, unwind terminate(cleanup)]; } bb10 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir index 9a10f5cb575a..c30df7425d20 100644 --- a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir @@ -75,7 +75,7 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { } bb9 (cleanup): { - drop(_5) -> [return: bb10, unwind terminate (panic in a destructor during cleanup)]; + drop(_5) -> [return: bb10, unwind terminate(cleanup)]; } bb10 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir index 431661af705b..cb29473d7627 100644 --- a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir @@ -67,7 +67,7 @@ fn vec_move(_1: Vec) -> () { } bb9 (cleanup): { - drop(_3) -> [return: bb10, unwind terminate (panic in a destructor during cleanup)]; + drop(_3) -> [return: bb10, unwind terminate(cleanup)]; } bb10 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir index 7cada9c148d4..35f7356d47a6 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -127,7 +127,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb11 (cleanup): { - drop(_3) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; + drop(_3) -> [return: bb12, unwind terminate(cleanup)]; } bb12 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir index ef1f934c52b2..a677e8b439fa 100644 --- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir @@ -82,7 +82,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb8 (cleanup): { - drop(_3) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)]; + drop(_3) -> [return: bb9, unwind terminate(cleanup)]; } bb9 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index b9636712f826..3d76bab7ce70 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -195,7 +195,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb11 (cleanup): { - drop(_2) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; + drop(_2) -> [return: bb12, unwind terminate(cleanup)]; } bb12 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index 0f323a56e61d..e8586cec981c 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -182,7 +182,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb11 (cleanup): { - drop(_2) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; + drop(_2) -> [return: bb12, unwind terminate(cleanup)]; } bb12 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir index 96160b272b98..8bd072fd625e 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir @@ -143,7 +143,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb12 (cleanup): { - drop(_2) -> [return: bb13, unwind terminate (panic in a destructor during cleanup)]; + drop(_2) -> [return: bb13, unwind terminate(cleanup)]; } bb13 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index 67d8442ab206..3cdc49f6056b 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -196,7 +196,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb11 (cleanup): { - drop(_2) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)]; + drop(_2) -> [return: bb12, unwind terminate(cleanup)]; } bb12 (cleanup): { diff --git a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir index 09ff59ffa215..7d3346faba6c 100644 --- a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir +++ b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir @@ -167,11 +167,11 @@ fn main() -> () { } bb7 (cleanup): { - drop(_21) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)]; + drop(_21) -> [return: bb9, unwind terminate(cleanup)]; } bb8 (cleanup): { - drop(_5) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)]; + drop(_5) -> [return: bb9, unwind terminate(cleanup)]; } bb9 (cleanup): { diff --git a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir index 8d9f89855789..3a8b457a7a10 100644 --- a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir +++ b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir @@ -24,7 +24,7 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () { bb3 (cleanup): { _4 = &raw mut (*_1)[_3]; _3 = Add(move _3, const 1_usize); - drop((*_4)) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)]; + drop((*_4)) -> [return: bb4, unwind terminate(cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir b/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir index 3768d34dd8ec..b58794183551 100644 --- a/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir +++ b/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir @@ -22,7 +22,7 @@ fn std::ptr::drop_in_place(_1: *mut Vec) -> () { } bb4 (cleanup): { - drop(((*_1).0: alloc::raw_vec::RawVec)) -> [return: bb2, unwind terminate (panic in a destructor during cleanup)]; + drop(((*_1).0: alloc::raw_vec::RawVec)) -> [return: bb2, unwind terminate(cleanup)]; } bb5: { From d5e79f2b8d84fa64eed0da6413874560b2552900 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Thu, 24 Aug 2023 06:43:52 +0200 Subject: [PATCH 176/197] Include compiler flags when you `break rust;` --- compiler/rustc_hir_typeck/src/lib.rs | 6 ++++++ tests/ui/track-diagnostics/track.rs | 5 +++++ tests/ui/track-diagnostics/track.stderr | 2 ++ 3 files changed, 13 insertions(+) diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index c4d3cbc9faab..f17f1d14bf39 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -436,6 +436,12 @@ fn fatally_break_rust(tcx: TyCtxt<'_>) { tcx.sess.cfg_version, config::host_triple(), )); + if let Some((flags, excluded_cargo_defaults)) = rustc_session::utils::extra_compiler_flags() { + handler.note_without_error(format!("compiler flags: {}", flags.join(" "))); + if excluded_cargo_defaults { + handler.note_without_error("some of the compiler flags provided by cargo are hidden"); + } + } } fn has_expected_num_generic_args(tcx: TyCtxt<'_>, trait_did: DefId, expected: usize) -> bool { diff --git a/tests/ui/track-diagnostics/track.rs b/tests/ui/track-diagnostics/track.rs index 61b9137eadd9..97bd7789a633 100644 --- a/tests/ui/track-diagnostics/track.rs +++ b/tests/ui/track-diagnostics/track.rs @@ -6,6 +6,11 @@ // normalize-stderr-test ".rs:\d+:\d+" -> ".rs:LL:CC" // normalize-stderr-test "note: rustc .+ running on .+" -> "note: rustc $$VERSION running on $$TARGET" +// The test becomes too flaky if we care about exact args. If `-Z ui-testing` +// from compiletest and `-Z track-diagnostics` from `// compile-flags` at the +// top of this file are present, then assume all args are present. +// normalize-stderr-test "note: compiler flags: .*-Z ui-testing.*-Z track-diagnostics" -> "note: compiler flags: ... -Z ui-testing ... -Z track-diagnostics" + fn main() { break rust } diff --git a/tests/ui/track-diagnostics/track.stderr b/tests/ui/track-diagnostics/track.stderr index 8256c1f5f0ff..60254dc475be 100644 --- a/tests/ui/track-diagnostics/track.stderr +++ b/tests/ui/track-diagnostics/track.stderr @@ -20,6 +20,8 @@ note: we would appreciate a joke overview: https://github.com/rust-lang/rust/iss note: rustc $VERSION running on $TARGET +note: compiler flags: ... -Z ui-testing ... -Z track-diagnostics + error: aborting due to 3 previous errors Some errors have detailed explanations: E0268, E0425. From d3c3c17abb3a4cb38be0fec3ea2cb62bdd452e06 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 24 Aug 2023 09:41:30 +0100 Subject: [PATCH 177/197] Add more tests for if_let_guard --- .../rfcs/rfc-2294-if-let-guard/exhaustive.rs | 18 +++++++ .../rfc-2294-if-let-guard/exhaustive.stderr | 35 +++++++++++++ .../rfc-2294-if-let-guard/guard-lifetime-1.rs | 15 ++++++ .../guard-lifetime-1.stderr | 15 ++++++ .../rfc-2294-if-let-guard/guard-lifetime-2.rs | 16 ++++++ .../guard-mutability-1.rs | 14 +++++ .../guard-mutability-1.stderr | 11 ++++ .../guard-mutability-2.rs | 14 +++++ .../guard-mutability-2.stderr | 11 ++++ .../rfc-2294-if-let-guard/macro-expanded.rs | 16 ++++++ .../macro-expanded.stderr | 13 +++++ tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs | 27 ++++++++++ .../rfcs/rfc-2294-if-let-guard/parens.stderr | 52 +++++++++++++++++++ .../partially-macro-expanded.rs | 18 +++++++ .../rfcs/rfc-2294-if-let-guard/shadowing.rs | 23 ++++++++ 15 files changed, 298 insertions(+) create mode 100644 tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.rs create mode 100644 tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.stderr create mode 100644 tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.rs create mode 100644 tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.stderr create mode 100644 tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-2.rs create mode 100644 tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.rs create mode 100644 tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.stderr create mode 100644 tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.rs create mode 100644 tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.stderr create mode 100644 tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.rs create mode 100644 tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr create mode 100644 tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs create mode 100644 tests/ui/rfcs/rfc-2294-if-let-guard/parens.stderr create mode 100644 tests/ui/rfcs/rfc-2294-if-let-guard/partially-macro-expanded.rs create mode 100644 tests/ui/rfcs/rfc-2294-if-let-guard/shadowing.rs diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.rs new file mode 100644 index 000000000000..b4eb541398cf --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.rs @@ -0,0 +1,18 @@ +#![feature(if_let_guard)] +#![allow(irrefutable_let_patterns)] + +fn match_option(x: Option) { + match x { + //~^ ERROR non-exhaustive patterns: `None` not covered + Some(_) => {} + None if let y = x => {} + } +} + +fn main() { + let x = (); + match x { + //~^ ERROR non-exhaustive patterns: `()` not covered + y if let z = y => {} + } +} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.stderr new file mode 100644 index 000000000000..ddd08854ff77 --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.stderr @@ -0,0 +1,35 @@ +error[E0004]: non-exhaustive patterns: `None` not covered + --> $DIR/exhaustive.rs:5:11 + | +LL | match x { + | ^ pattern `None` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None if let y = x => {}, +LL + None => todo!() + | + +error[E0004]: non-exhaustive patterns: `()` not covered + --> $DIR/exhaustive.rs:14:11 + | +LL | match x { + | ^ pattern `()` not covered + | + = note: the matched value is of type `()` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ y if let z = y => {}, +LL + () => todo!() + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.rs new file mode 100644 index 000000000000..792225e656f4 --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.rs @@ -0,0 +1,15 @@ +// References to by-move bindings in an if-let guard *cannot* be used after the guard. + +#![feature(if_let_guard)] + +fn main() { + let x: Option> = Some(Some(String::new())); + match x { + Some(mut y) if let Some(ref z) = y => { + //~^ ERROR: cannot move out of `x.0` because it is borrowed + let _z: &String = z; + let _y: Option = y; + } + _ => {} + } +} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.stderr new file mode 100644 index 000000000000..b8e1bb324b1f --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.stderr @@ -0,0 +1,15 @@ +error[E0505]: cannot move out of `x.0` because it is borrowed + --> $DIR/guard-lifetime-1.rs:8:14 + | +LL | Some(mut y) if let Some(ref z) = y => { + | ^^^^^ + | | + | move out of `x.0` occurs here + | borrow of `x.0` occurs here +LL | +LL | let _z: &String = z; + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-2.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-2.rs new file mode 100644 index 000000000000..aa2154e3e9e2 --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-2.rs @@ -0,0 +1,16 @@ +// References to by-mutable-ref bindings in an if-let guard *can* be used after the guard. + +// check-pass + +#![feature(if_let_guard)] + +fn main() { + let mut x: Option> = Some(Some(String::new())); + match x { + Some(ref mut y) if let Some(ref z) = *y => { + let _z: &String = z; + let _y: &mut Option = y; + } + _ => {} + } +} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.rs new file mode 100644 index 000000000000..9353c9d92f89 --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.rs @@ -0,0 +1,14 @@ +// Check mutable bindings cannot be mutated by an if-let guard. + +#![feature(if_let_guard)] + +fn main() { + let x: Option> = Some(Some(6)); + match x { + Some(mut y) if let Some(ref mut z) = y => { + //~^ ERROR cannot borrow `y.0` as mutable, as it is immutable for the pattern guard + let _: &mut i32 = z; + } + _ => {} + } +} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.stderr new file mode 100644 index 000000000000..009d153387e3 --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.stderr @@ -0,0 +1,11 @@ +error[E0596]: cannot borrow `y.0` as mutable, as it is immutable for the pattern guard + --> $DIR/guard-mutability-1.rs:8:33 + | +LL | Some(mut y) if let Some(ref mut z) = y => { + | ^^^^^^^^^ cannot borrow as mutable + | + = note: variables bound in patterns are immutable until the end of the pattern guard + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.rs new file mode 100644 index 000000000000..4efa02f57a6c --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.rs @@ -0,0 +1,14 @@ +// Check mutable reference bindings cannot be mutated by an if-let guard. + +#![feature(if_let_guard)] + +fn main() { + let mut x: Option> = Some(Some(6)); + match x { + Some(ref mut y) if let Some(ref mut z) = *y => { + //~^ ERROR cannot borrow `y.0` as mutable, as it is immutable for the pattern guard + let _: &mut i32 = z; + } + _ => {} + } +} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.stderr new file mode 100644 index 000000000000..07e7c6a2c07e --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.stderr @@ -0,0 +1,11 @@ +error[E0596]: cannot borrow `y.0` as mutable, as it is immutable for the pattern guard + --> $DIR/guard-mutability-2.rs:8:37 + | +LL | Some(ref mut y) if let Some(ref mut z) = *y => { + | ^^^^^^^^^ cannot borrow as mutable + | + = note: variables bound in patterns are immutable until the end of the pattern guard + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.rs new file mode 100644 index 000000000000..423a2cd53fc5 --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.rs @@ -0,0 +1,16 @@ +// Expression macros can't expand to a let match guard. + +#![feature(if_let_guard)] +#![feature(let_chains)] + +macro_rules! m { + ($e:expr) => { let Some(x) = $e } + //~^ ERROR expected expression, found `let` statement +} + +fn main() { + match () { + () if m!(Some(5)) => {} + _ => {} + } +} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr new file mode 100644 index 000000000000..41a20bf8ae11 --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr @@ -0,0 +1,13 @@ +error: expected expression, found `let` statement + --> $DIR/macro-expanded.rs:7:20 + | +LL | ($e:expr) => { let Some(x) = $e } + | ^^^ +... +LL | () if m!(Some(5)) => {} + | ----------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs new file mode 100644 index 000000000000..9cb27c73b148 --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs @@ -0,0 +1,27 @@ +// Parenthesised let "expressions" are not allowed in guards + +#![feature(if_let_guard)] +#![feature(let_chains)] + +#[cfg(FALSE)] +fn un_cfged() { + match () { + () if let 0 = 1 => {} + () if (let 0 = 1) => {} + //~^ ERROR expected expression, found `let` statement + () if (((let 0 = 1))) => {} + //~^ ERROR expected expression, found `let` statement + } +} + +fn main() { + match () { + () if let 0 = 1 => {} + () if (let 0 = 1) => {} + //~^ ERROR expected expression, found `let` statement + //~| ERROR `let` expressions are not supported here + () if (((let 0 = 1))) => {} + //~^ ERROR expected expression, found `let` statement + //~| ERROR `let` expressions are not supported here + } +} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/parens.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/parens.stderr new file mode 100644 index 000000000000..85df360daabf --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/parens.stderr @@ -0,0 +1,52 @@ +error: expected expression, found `let` statement + --> $DIR/parens.rs:10:16 + | +LL | () if (let 0 = 1) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/parens.rs:12:18 + | +LL | () if (((let 0 = 1))) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/parens.rs:20:16 + | +LL | () if (let 0 = 1) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/parens.rs:23:18 + | +LL | () if (((let 0 = 1))) => {} + | ^^^ + +error: `let` expressions are not supported here + --> $DIR/parens.rs:20:16 + | +LL | () if (let 0 = 1) => {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/parens.rs:20:16 + | +LL | () if (let 0 = 1) => {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/parens.rs:23:18 + | +LL | () if (((let 0 = 1))) => {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/parens.rs:23:18 + | +LL | () if (((let 0 = 1))) => {} + | ^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/partially-macro-expanded.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/partially-macro-expanded.rs new file mode 100644 index 000000000000..d91b3a358da1 --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/partially-macro-expanded.rs @@ -0,0 +1,18 @@ +// Macros can be used for (parts of) the pattern and expression in an if let guard +// check-pass + +#![feature(if_let_guard)] +#![feature(let_chains)] + +macro_rules! m { + (pattern $i:ident) => { Some($i) }; + (expression $e:expr) => { $e }; +} + +fn main() { + match () { + () if let m!(pattern x) = m!(expression Some(4)) => {} + () if let [m!(pattern y)] = [Some(8 + m!(expression 4))] => {} + _ => {} + } +} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/shadowing.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/shadowing.rs new file mode 100644 index 000000000000..dba292ef9e21 --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/shadowing.rs @@ -0,0 +1,23 @@ +// Check shadowing in if let guards works as expected. +// check-pass + +#![feature(if_let_guard)] +#![feature(let_chains)] + +fn main() { + let x: Option> = Some(Some(6)); + match x { + Some(x) if let Some(x) = x => { + let _: i32 = x; + } + _ => {} + } + + let y: Option>> = Some(Some(Some(-24))); + match y { + Some(y) if let Some(y) = y && let Some(y) = y => { + let _: i32 = y; + } + _ => {} + } +} From 15a68610dd06351feac543afcd0802e6e2622ac8 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 24 Aug 2023 15:42:55 +0000 Subject: [PATCH 178/197] Only check packed ADT. --- compiler/rustc_const_eval/src/util/alignment.rs | 2 +- compiler/rustc_const_eval/src/util/mod.rs | 2 +- .../rustc_mir_transform/src/dead_store_elimination.rs | 10 ++++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 4f39dad205ae..c1f0ff260d2d 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -40,7 +40,7 @@ where } } -fn is_within_packed<'tcx, L>( +pub fn is_within_packed<'tcx, L>( tcx: TyCtxt<'tcx>, local_decls: &L, place: Place<'tcx>, diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs index 289e34225954..0aef7fa469e4 100644 --- a/compiler/rustc_const_eval/src/util/mod.rs +++ b/compiler/rustc_const_eval/src/util/mod.rs @@ -5,7 +5,7 @@ mod check_validity_requirement; mod compare_types; mod type_name; -pub use self::alignment::is_disaligned; +pub use self::alignment::{is_disaligned, is_within_packed}; pub use self::check_validity_requirement::check_validity_requirement; pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype}; pub use self::type_name::type_name; diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 47c1c465e563..ef14105041b4 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -12,7 +12,7 @@ //! will still not cause any further changes. //! -use crate::util::is_disaligned; +use crate::util::is_within_packed; use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; @@ -32,8 +32,6 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS .iterate_to_fixpoint() .into_results_cursor(body); - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); - // For blocks with a call terminator, if an argument copy can be turned into a move, // record it as (block, argument index). let mut call_operands_to_move = Vec::new(); @@ -52,7 +50,11 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS && !place.is_indirect() && !borrowed.contains(place.local) && !state.contains(place.local) - && !is_disaligned(tcx, body, param_env, place) + // If `place` is a projection of a disaligned field in a packed ADT, + // the move may be codegened as a pointer to that field. + // Using that disaligned pointer may trigger UB in the callee, + // so do nothing. + && is_within_packed(tcx, body, place).is_none() { call_operands_to_move.push((bb, index)); } From 339d636120cbec1a593557498389e616b47a032a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 24 Aug 2023 18:22:32 +0200 Subject: [PATCH 179/197] attempt to better normalize remote-test-client output for tests --- src/tools/compiletest/src/runtest.rs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 4ef79af3124a..f8e5a158bfdb 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -3634,26 +3634,30 @@ impl<'test> TestCx<'test> { let expected_stderr = self.load_expected_output(stderr_kind); let expected_stdout = self.load_expected_output(stdout_kind); - let normalized_stdout = match output_kind { + let mut normalized_stdout = + self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout); + match output_kind { TestOutput::Run if self.config.remote_test_client.is_some() => { // When tests are run using the remote-test-client, the string // 'uploaded "$TEST_BUILD_DIR/, waiting for result"' // is printed to stdout by the client and then captured in the ProcRes, - // so it needs to be removed when comparing the run-pass test execution output + // so it needs to be removed when comparing the run-pass test execution output. static REMOTE_TEST_RE: Lazy = Lazy::new(|| { Regex::new( "^uploaded \"\\$TEST_BUILD_DIR(/[[:alnum:]_\\-.]+)+\", waiting for result\n" ) .unwrap() }); - REMOTE_TEST_RE - .replace( - &self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout), - "", - ) - .to_string() + normalized_stdout = REMOTE_TEST_RE.replace(&normalized_stdout, "").to_string(); + // When there is a panic, the remote-test-client also prints "died due to signal"; + // that needs to be removed as well. + static SIGNAL_DIED_RE: Lazy = + Lazy::new(|| Regex::new("^died due to signal [0-9]+\n").unwrap()); + normalized_stdout = SIGNAL_DIED_RE.replace(&normalized_stdout, "").to_string(); + // FIXME: it would be much nicer if we could just tell the remote-test-client to not + // print these things. } - _ => self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout), + _ => {} }; let stderr = if explicit_format { From c6ba5d9806565f6ddeb731df9eb3d218a51be4e8 Mon Sep 17 00:00:00 2001 From: Caio Date: Thu, 24 Aug 2023 13:30:53 -0300 Subject: [PATCH 180/197] Add symbols for Clippy --- compiler/rustc_span/src/symbol.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index c0eff6dfd8fe..40eadaaa820d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -232,11 +232,13 @@ symbols! { NonZeroI32, NonZeroI64, NonZeroI8, + NonZeroIsize, NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, + NonZeroUsize, None, Ok, Option, @@ -278,6 +280,7 @@ symbols! { RwLock, RwLockReadGuard, RwLockWriteGuard, + Saturating, Send, SeqCst, SliceIndex, @@ -305,6 +308,7 @@ symbols! { Vec, VecDeque, Wrapper, + Wrapping, Yield, _DECLS, _Self, @@ -1373,6 +1377,7 @@ symbols! { sanitizer_cfi_normalize_integers, sanitizer_runtime, saturating_add, + saturating_div, saturating_sub, self_in_typedefs, self_struct_ctor, @@ -1691,7 +1696,10 @@ symbols! { windows_subsystem, with_negative_coherence, wrapping_add, + wrapping_div, wrapping_mul, + wrapping_rem, + wrapping_rem_euclid, wrapping_sub, wreg, write_bytes, From 8216f17d7d09d1ac6224b99c0ebf719ed276e4a7 Mon Sep 17 00:00:00 2001 From: Olanti Date: Thu, 24 Aug 2023 02:05:32 +0300 Subject: [PATCH 181/197] Move issue 29181, 2804, 17431, 66768 --- src/tools/tidy/src/ui_tests.rs | 4 ++-- tests/ui/{ => macros}/issue-2804.rs | 0 tests/ui/{issues => structs-enums/enum-rec}/issue-17431-6.rs | 0 .../{issues => structs-enums/enum-rec}/issue-17431-6.stderr | 0 tests/ui/{issues => structs-enums/enum-rec}/issue-17431-7.rs | 0 .../{issues => structs-enums/enum-rec}/issue-17431-7.stderr | 0 .../ui/{issues => structs-enums/struct-rec}/issue-17431-1.rs | 0 .../{issues => structs-enums/struct-rec}/issue-17431-1.stderr | 0 .../ui/{issues => structs-enums/struct-rec}/issue-17431-2.rs | 0 .../{issues => structs-enums/struct-rec}/issue-17431-2.stderr | 0 .../ui/{issues => structs-enums/struct-rec}/issue-17431-3.rs | 0 .../{issues => structs-enums/struct-rec}/issue-17431-3.stderr | 0 .../ui/{issues => structs-enums/struct-rec}/issue-17431-4.rs | 0 .../{issues => structs-enums/struct-rec}/issue-17431-4.stderr | 0 .../ui/{issues => structs-enums/struct-rec}/issue-17431-5.rs | 0 .../{issues => structs-enums/struct-rec}/issue-17431-5.stderr | 0 tests/ui/{issues => traits}/issue-66768.rs | 0 tests/ui/{issues => typeck}/auxiliary/issue-29181.rs | 0 tests/ui/{issues => typeck}/issue-29181.rs | 0 tests/ui/{issues => typeck}/issue-29181.stderr | 0 20 files changed, 2 insertions(+), 2 deletions(-) rename tests/ui/{ => macros}/issue-2804.rs (100%) rename tests/ui/{issues => structs-enums/enum-rec}/issue-17431-6.rs (100%) rename tests/ui/{issues => structs-enums/enum-rec}/issue-17431-6.stderr (100%) rename tests/ui/{issues => structs-enums/enum-rec}/issue-17431-7.rs (100%) rename tests/ui/{issues => structs-enums/enum-rec}/issue-17431-7.stderr (100%) rename tests/ui/{issues => structs-enums/struct-rec}/issue-17431-1.rs (100%) rename tests/ui/{issues => structs-enums/struct-rec}/issue-17431-1.stderr (100%) rename tests/ui/{issues => structs-enums/struct-rec}/issue-17431-2.rs (100%) rename tests/ui/{issues => structs-enums/struct-rec}/issue-17431-2.stderr (100%) rename tests/ui/{issues => structs-enums/struct-rec}/issue-17431-3.rs (100%) rename tests/ui/{issues => structs-enums/struct-rec}/issue-17431-3.stderr (100%) rename tests/ui/{issues => structs-enums/struct-rec}/issue-17431-4.rs (100%) rename tests/ui/{issues => structs-enums/struct-rec}/issue-17431-4.stderr (100%) rename tests/ui/{issues => structs-enums/struct-rec}/issue-17431-5.rs (100%) rename tests/ui/{issues => structs-enums/struct-rec}/issue-17431-5.stderr (100%) rename tests/ui/{issues => traits}/issue-66768.rs (100%) rename tests/ui/{issues => typeck}/auxiliary/issue-29181.rs (100%) rename tests/ui/{issues => typeck}/issue-29181.rs (100%) rename tests/ui/{issues => typeck}/issue-29181.stderr (100%) diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 3414924007b9..6a197527a64f 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -10,8 +10,8 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: usize = 900; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: usize = 1891; -const ROOT_ENTRY_LIMIT: usize = 866; +const ISSUES_ENTRY_LIMIT: usize = 1874; +const ROOT_ENTRY_LIMIT: usize = 865; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/ui/issue-2804.rs b/tests/ui/macros/issue-2804.rs similarity index 100% rename from tests/ui/issue-2804.rs rename to tests/ui/macros/issue-2804.rs diff --git a/tests/ui/issues/issue-17431-6.rs b/tests/ui/structs-enums/enum-rec/issue-17431-6.rs similarity index 100% rename from tests/ui/issues/issue-17431-6.rs rename to tests/ui/structs-enums/enum-rec/issue-17431-6.rs diff --git a/tests/ui/issues/issue-17431-6.stderr b/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr similarity index 100% rename from tests/ui/issues/issue-17431-6.stderr rename to tests/ui/structs-enums/enum-rec/issue-17431-6.stderr diff --git a/tests/ui/issues/issue-17431-7.rs b/tests/ui/structs-enums/enum-rec/issue-17431-7.rs similarity index 100% rename from tests/ui/issues/issue-17431-7.rs rename to tests/ui/structs-enums/enum-rec/issue-17431-7.rs diff --git a/tests/ui/issues/issue-17431-7.stderr b/tests/ui/structs-enums/enum-rec/issue-17431-7.stderr similarity index 100% rename from tests/ui/issues/issue-17431-7.stderr rename to tests/ui/structs-enums/enum-rec/issue-17431-7.stderr diff --git a/tests/ui/issues/issue-17431-1.rs b/tests/ui/structs-enums/struct-rec/issue-17431-1.rs similarity index 100% rename from tests/ui/issues/issue-17431-1.rs rename to tests/ui/structs-enums/struct-rec/issue-17431-1.rs diff --git a/tests/ui/issues/issue-17431-1.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-1.stderr similarity index 100% rename from tests/ui/issues/issue-17431-1.stderr rename to tests/ui/structs-enums/struct-rec/issue-17431-1.stderr diff --git a/tests/ui/issues/issue-17431-2.rs b/tests/ui/structs-enums/struct-rec/issue-17431-2.rs similarity index 100% rename from tests/ui/issues/issue-17431-2.rs rename to tests/ui/structs-enums/struct-rec/issue-17431-2.rs diff --git a/tests/ui/issues/issue-17431-2.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-2.stderr similarity index 100% rename from tests/ui/issues/issue-17431-2.stderr rename to tests/ui/structs-enums/struct-rec/issue-17431-2.stderr diff --git a/tests/ui/issues/issue-17431-3.rs b/tests/ui/structs-enums/struct-rec/issue-17431-3.rs similarity index 100% rename from tests/ui/issues/issue-17431-3.rs rename to tests/ui/structs-enums/struct-rec/issue-17431-3.rs diff --git a/tests/ui/issues/issue-17431-3.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-3.stderr similarity index 100% rename from tests/ui/issues/issue-17431-3.stderr rename to tests/ui/structs-enums/struct-rec/issue-17431-3.stderr diff --git a/tests/ui/issues/issue-17431-4.rs b/tests/ui/structs-enums/struct-rec/issue-17431-4.rs similarity index 100% rename from tests/ui/issues/issue-17431-4.rs rename to tests/ui/structs-enums/struct-rec/issue-17431-4.rs diff --git a/tests/ui/issues/issue-17431-4.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-4.stderr similarity index 100% rename from tests/ui/issues/issue-17431-4.stderr rename to tests/ui/structs-enums/struct-rec/issue-17431-4.stderr diff --git a/tests/ui/issues/issue-17431-5.rs b/tests/ui/structs-enums/struct-rec/issue-17431-5.rs similarity index 100% rename from tests/ui/issues/issue-17431-5.rs rename to tests/ui/structs-enums/struct-rec/issue-17431-5.rs diff --git a/tests/ui/issues/issue-17431-5.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-5.stderr similarity index 100% rename from tests/ui/issues/issue-17431-5.stderr rename to tests/ui/structs-enums/struct-rec/issue-17431-5.stderr diff --git a/tests/ui/issues/issue-66768.rs b/tests/ui/traits/issue-66768.rs similarity index 100% rename from tests/ui/issues/issue-66768.rs rename to tests/ui/traits/issue-66768.rs diff --git a/tests/ui/issues/auxiliary/issue-29181.rs b/tests/ui/typeck/auxiliary/issue-29181.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-29181.rs rename to tests/ui/typeck/auxiliary/issue-29181.rs diff --git a/tests/ui/issues/issue-29181.rs b/tests/ui/typeck/issue-29181.rs similarity index 100% rename from tests/ui/issues/issue-29181.rs rename to tests/ui/typeck/issue-29181.rs diff --git a/tests/ui/issues/issue-29181.stderr b/tests/ui/typeck/issue-29181.stderr similarity index 100% rename from tests/ui/issues/issue-29181.stderr rename to tests/ui/typeck/issue-29181.stderr From a8827eea27d6904976bb4f942edcf3c97da9a4b3 Mon Sep 17 00:00:00 2001 From: allaboutevemirolive Date: Thu, 24 Aug 2023 17:09:14 -0400 Subject: [PATCH 182/197] Add comment to the push_trailing function --- compiler/rustc_errors/src/lib.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index db5df554d23e..b7e1b0c8ad13 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -197,8 +197,14 @@ impl CodeSuggestion { use rustc_span::{CharPos, Pos}; - /// Append to a buffer the remainder of the line of existing source code, and return the - /// count of lines that have been added for accurate highlighting. + /// Extracts a substring from the provided `line_opt` based on the specified low and high indices, + /// appends it to the given buffer `buf`, and returns the count of newline characters in the substring + /// for accurate highlighting. + /// If `line_opt` is `None`, a newline character is appended to the buffer, and 0 is returned. + /// + /// ## Returns + /// + /// The count of newline characters in the extracted substring. fn push_trailing( buf: &mut String, line_opt: Option<&Cow<'_, str>>, @@ -206,22 +212,30 @@ impl CodeSuggestion { hi_opt: Option<&Loc>, ) -> usize { let mut line_count = 0; + // Convert CharPos to Usize, as CharPose is character offset + // Extract low index and high index let (lo, hi_opt) = (lo.col.to_usize(), hi_opt.map(|hi| hi.col.to_usize())); if let Some(line) = line_opt { if let Some(lo) = line.char_indices().map(|(i, _)| i).nth(lo) { + // Get high index while account for rare unicode and emoji with char_indices let hi_opt = hi_opt.and_then(|hi| line.char_indices().map(|(i, _)| i).nth(hi)); match hi_opt { + // If high index exist, take string from low to high index Some(hi) if hi > lo => { + // count how many '\n' exist line_count = line[lo..hi].matches('\n').count(); buf.push_str(&line[lo..hi]) } Some(_) => (), + // If high index absence, take string from low index till end string.len None => { + // count how many '\n' exist line_count = line[lo..].matches('\n').count(); buf.push_str(&line[lo..]) } } } + // If high index is None if hi_opt.is_none() { buf.push('\n'); } From 5d6e2d70509fb521d7329ffa43de538ecf9b3af5 Mon Sep 17 00:00:00 2001 From: Ramon de C Valle Date: Wed, 23 Aug 2023 16:02:25 -0700 Subject: [PATCH 183/197] Fix CFI: f32 and f64 are encoded incorrectly for c Fix #115150 by encoding f32 and f64 correctly for cross-language CFI. I missed changing the encoding for f32 and f64 when I introduced the integer normalization option in #105452 as integer normalization does not include floating point. `f32` and `f64` should be always encoded as `f` and `d` since they are both FFI safe when their representation are the same (i.e., IEEE 754) for both the Rust compiler and Clang. --- .../src/typeid/typeid_itanium_cxx_abi.rs | 17 +++++++++++++---- ...cfi-emit-type-metadata-id-itanium-cxx-abi.rs | 12 ++++++------ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index d345368d552b..77457c8daaa1 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -447,7 +447,7 @@ fn encode_ty<'tcx>( typeid.push('b'); } - ty::Int(..) | ty::Uint(..) | ty::Float(..) => { + ty::Int(..) | ty::Uint(..) => { // u as vendor extended type let mut s = String::from(match ty.kind() { ty::Int(IntTy::I8) => "u2i8", @@ -462,14 +462,23 @@ fn encode_ty<'tcx>( ty::Uint(UintTy::U64) => "u3u64", ty::Uint(UintTy::U128) => "u4u128", ty::Uint(UintTy::Usize) => "u5usize", - ty::Float(FloatTy::F32) => "u3f32", - ty::Float(FloatTy::F64) => "u3f64", - _ => "", + _ => bug!("encode_ty: unexpected `{:?}`", ty.kind()), }); compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); typeid.push_str(&s); } + // Rust's f32 and f64 single (32-bit) and double (64-bit) precision floating-point types + // have IEEE-754 binary32 and binary64 floating-point layouts, respectively. + // + // (See https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#fixed-width-floating-point-types.) + ty::Float(float_ty) => { + typeid.push(match float_ty { + FloatTy::F32 => 'f', + FloatTy::F64 => 'd', + }); + } + ty::Char => { // u4char as vendor extended type let mut s = String::from("u4char"); diff --git a/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs b/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs index da608e180c53..2d8b13e2080e 100644 --- a/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs +++ b/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs @@ -500,12 +500,12 @@ pub fn foo149(_: Type14, _: Type14, _: Type14) { } // CHECK: ![[TYPE45]] = !{i64 0, !"_ZTSFvu5usizeE"} // CHECK: ![[TYPE46]] = !{i64 0, !"_ZTSFvu5usizeS_E"} // CHECK: ![[TYPE47]] = !{i64 0, !"_ZTSFvu5usizeS_S_E"} -// CHECK: ![[TYPE48]] = !{i64 0, !"_ZTSFvu3f32E"} -// CHECK: ![[TYPE49]] = !{i64 0, !"_ZTSFvu3f32S_E"} -// CHECK: ![[TYPE50]] = !{i64 0, !"_ZTSFvu3f32S_S_E"} -// CHECK: ![[TYPE51]] = !{i64 0, !"_ZTSFvu3f64E"} -// CHECK: ![[TYPE52]] = !{i64 0, !"_ZTSFvu3f64S_E"} -// CHECK: ![[TYPE53]] = !{i64 0, !"_ZTSFvu3f64S_S_E"} +// CHECK: ![[TYPE48]] = !{i64 0, !"_ZTSFvfE"} +// CHECK: ![[TYPE49]] = !{i64 0, !"_ZTSFvffE"} +// CHECK: ![[TYPE50]] = !{i64 0, !"_ZTSFvfffE"} +// CHECK: ![[TYPE51]] = !{i64 0, !"_ZTSFvdE"} +// CHECK: ![[TYPE52]] = !{i64 0, !"_ZTSFvddE"} +// CHECK: ![[TYPE53]] = !{i64 0, !"_ZTSFvdddE"} // CHECK: ![[TYPE54]] = !{i64 0, !"_ZTSFvu4charE"} // CHECK: ![[TYPE55]] = !{i64 0, !"_ZTSFvu4charS_E"} // CHECK: ![[TYPE56]] = !{i64 0, !"_ZTSFvu4charS_S_E"} From df5a248cb1d557f8df9c9d0660e8d704bc1e0919 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 24 Aug 2023 20:08:22 +0200 Subject: [PATCH 184/197] keep trying which flags we need for this test until it passes bors --- tests/ui/panics/panic-in-cleanup.rs | 5 ++++- tests/ui/panics/panic-in-cleanup.run.stderr | 4 ++-- tests/ui/panics/panic-in-ffi.rs | 4 +++- tests/ui/panics/panic-in-ffi.run.stderr | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/ui/panics/panic-in-cleanup.rs b/tests/ui/panics/panic-in-cleanup.rs index b4519da4e6a7..a1c797268d10 100644 --- a/tests/ui/panics/panic-in-cleanup.rs +++ b/tests/ui/panics/panic-in-cleanup.rs @@ -1,9 +1,12 @@ // run-fail +// exec-env:RUST_BACKTRACE=0 // check-run-results // error-pattern: panic in a destructor during cleanup // normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" // normalize-stderr-test: "\n +at [^\n]+" -> "" -// ignore-emscripten no processes +// needs-unwind +// ignore-emscripten "RuntimeError" junk in output +// ignore-msvc SEH doesn't do panic-during-cleanup the same way as everyone else struct Bomb; diff --git a/tests/ui/panics/panic-in-cleanup.run.stderr b/tests/ui/panics/panic-in-cleanup.run.stderr index fa201b9667f2..923bac69c50e 100644 --- a/tests/ui/panics/panic-in-cleanup.run.stderr +++ b/tests/ui/panics/panic-in-cleanup.run.stderr @@ -1,7 +1,7 @@ -thread 'main' panicked at $DIR/panic-in-cleanup.rs:18:5: +thread 'main' panicked at $DIR/panic-in-cleanup.rs:21:5: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -thread 'main' panicked at $DIR/panic-in-cleanup.rs:12:9: +thread 'main' panicked at $DIR/panic-in-cleanup.rs:15:9: BOOM stack backtrace: thread 'main' panicked at library/core/src/panicking.rs:126:5: diff --git a/tests/ui/panics/panic-in-ffi.rs b/tests/ui/panics/panic-in-ffi.rs index bb30398531f0..da2b24945bed 100644 --- a/tests/ui/panics/panic-in-ffi.rs +++ b/tests/ui/panics/panic-in-ffi.rs @@ -1,9 +1,11 @@ // run-fail +// exec-env:RUST_BACKTRACE=0 // check-run-results // error-pattern: panic in a function that cannot unwind // normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" // normalize-stderr-test: "\n +at [^\n]+" -> "" -// ignore-emscripten no processes +// needs-unwind +// ignore-emscripten "RuntimeError" junk in output #![feature(c_unwind)] extern "C" fn panic_in_ffi() { diff --git a/tests/ui/panics/panic-in-ffi.run.stderr b/tests/ui/panics/panic-in-ffi.run.stderr index a6de98c4913e..3422f5ccc4d3 100644 --- a/tests/ui/panics/panic-in-ffi.run.stderr +++ b/tests/ui/panics/panic-in-ffi.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at $DIR/panic-in-ffi.rs:10:5: +thread 'main' panicked at $DIR/panic-in-ffi.rs:12:5: Test note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace thread 'main' panicked at library/core/src/panicking.rs:126:5: From cab9fc99c9394cf1ce74a19183362701e1608aa1 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Fri, 25 Aug 2023 09:25:57 +0300 Subject: [PATCH 185/197] Add stable for Constant in smir --- compiler/rustc_smir/src/rustc_smir/mod.rs | 14 +++++++++++++- compiler/rustc_smir/src/stable_mir/mir/body.rs | 13 ++++++++++--- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 392dbafcb3eb..e20f4845b4d4 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -481,7 +481,19 @@ impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> { match self { Copy(place) => stable_mir::mir::Operand::Copy(place.stable(tables)), Move(place) => stable_mir::mir::Operand::Move(place.stable(tables)), - Constant(c) => stable_mir::mir::Operand::Constant(c.to_string()), + Constant(c) => stable_mir::mir::Operand::Constant(c.stable(tables)), + } + } +} + +impl<'tcx> Stable<'tcx> for mir::Constant<'tcx> { + type T = stable_mir::mir::Constant; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + stable_mir::mir::Constant { + span: self.span.stable(tables), + user_ty: self.user_ty.map(|u| u.as_usize()).or(None), + literal: self.literal.stable(tables), } } } diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs index c16bd6cbd70e..03e19a3349ae 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/body.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs @@ -1,8 +1,8 @@ use crate::rustc_internal::Opaque; use crate::stable_mir::ty::{ - AdtDef, ClosureDef, Const, GeneratorDef, GenericArgs, Movability, Region, + AdtDef, ClosureDef, Const, ConstantKind, GeneratorDef, GenericArgs, Movability, Region, }; -use crate::stable_mir::{self, ty::Ty}; +use crate::stable_mir::{self, ty::Ty, Span}; #[derive(Clone, Debug)] pub struct Body { @@ -359,7 +359,7 @@ pub enum AggregateKind { pub enum Operand { Copy(Place), Move(Place), - Constant(String), + Constant(Constant), } #[derive(Clone, Debug)] @@ -383,6 +383,13 @@ pub type VariantIdx = usize; type UserTypeAnnotationIndex = usize; +#[derive(Clone, Debug)] +pub struct Constant { + pub span: Span, + pub user_ty: Option, + pub literal: ConstantKind, +} + #[derive(Clone, Debug)] pub struct SwitchTarget { pub value: u128, From 9c3f44f922adaf1a5797c5e5e66414369ad5ffc8 Mon Sep 17 00:00:00 2001 From: cui fliter Date: Wed, 23 Aug 2023 21:36:45 +0800 Subject: [PATCH 186/197] use the correct link Signed-off-by: cui fliter --- library/core/src/convert/num.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index 56ab63be27d3..b048b5135920 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -142,9 +142,9 @@ impl_from! { i16, isize, #[stable(feature = "lossless_iusize_conv", since = "1.2 // RISC-V defines the possibility of a 128-bit address space (RV128). -// CHERI proposes 256-bit “capabilities”. Unclear if this would be relevant to usize/isize. +// CHERI proposes 128-bit “capabilities”. Unclear if this would be relevant to usize/isize. // https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf -// https://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf +// https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-951.pdf // Note: integers can only be represented with full precision in a float if // they fit in the significand, which is 24 bits in f32 and 53 bits in f64. From 3dd1c6bc98c6c26f797527437b7f6195375bfcc6 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 25 Aug 2023 09:42:57 -0300 Subject: [PATCH 187/197] Add missing high-level stable_mir::generics_of fn --- compiler/rustc_smir/src/stable_mir/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs index 360f2195c1c3..44938eaa0353 100644 --- a/compiler/rustc_smir/src/stable_mir/mod.rs +++ b/compiler/rustc_smir/src/stable_mir/mod.rs @@ -109,6 +109,10 @@ pub fn trait_impl(trait_impl: &ImplDef) -> ImplTrait { with(|cx| cx.trait_impl(trait_impl)) } +pub fn generics_of(generic_def: &GenericDef) -> Generics { + with(|cx| cx.generics_of(generic_def)) +} + pub fn predicates_of(trait_def: &TraitDef) -> GenericPredicates { with(|cx| cx.predicates_of(trait_def)) } From ec21d584eee32b276b78c7115391218c799d5936 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 24 Aug 2023 15:36:40 -0400 Subject: [PATCH 188/197] Record allocation spans inside force_allocation --- .../rustc_const_eval/src/interpret/machine.rs | 11 +++++++- .../rustc_const_eval/src/interpret/place.rs | 9 ++++--- src/tools/miri/src/machine.rs | 18 +++++++++++++ .../dangling_pointers/dangling_primitive.rs | 13 ++++++++++ .../dangling_primitive.stderr | 26 +++++++++++++++++++ .../deref-partially-dangling.stderr | 7 ++++- .../fail/dangling_pointers/dyn_size.stderr | 7 ++++- .../dangling_pointers/stack_temporary.stderr | 12 ++++++++- .../intrinsics/out_of_bounds_ptr_1.stderr | 7 ++++- .../intrinsics/out_of_bounds_ptr_3.stderr | 7 ++++- 10 files changed, 107 insertions(+), 10 deletions(-) create mode 100644 src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.rs create mode 100644 src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.stderr diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index d3c73b896c08..ff106fa4b1bc 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -18,7 +18,7 @@ use crate::const_eval::CheckAlignment; use super::{ AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, FnArg, Frame, ImmTy, InterpCx, - InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, + InterpResult, MPlaceTy, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, }; /// Data returned by Machine::stack_pop, @@ -471,6 +471,15 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { assert!(!unwinding); Ok(StackPopJump::Normal) } + + fn after_local_allocated( + _ecx: &mut InterpCx<'mir, 'tcx, Self>, + _frame: usize, + _local: mir::Local, + _mplace: &MPlaceTy<'tcx, Self::Provenance>, + ) -> InterpResult<'tcx> { + Ok(()) + } } /// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index daadb7589647..40a7a0f4e56c 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -899,7 +899,7 @@ where if local_layout.is_unsized() { throw_unsup_format!("unsized locals are not supported"); } - let mplace = *self.allocate(local_layout, MemoryKind::Stack)?; + let mplace = self.allocate(local_layout, MemoryKind::Stack)?; // Preserve old value. (As an optimization, we can skip this if it was uninit.) if !matches!(local_val, Immediate::Uninit) { // We don't have to validate as we can assume the local was already @@ -909,15 +909,16 @@ where local_val, local_layout, local_layout.align.abi, - mplace, + *mplace, )?; } + M::after_local_allocated(self, frame, local, &mplace)?; // Now we can call `access_mut` again, asserting it goes well, and actually // overwrite things. This points to the entire allocation, not just the part // the place refers to, i.e. we do this before we apply `offset`. *M::access_local_mut(self, frame, local).unwrap() = - Operand::Indirect(mplace); - mplace + Operand::Indirect(*mplace); + *mplace } &mut Operand::Indirect(mplace) => mplace, // this already was an indirect local }; diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 550c9650fb39..7b8cfe78f572 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1405,4 +1405,22 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { } res } + + fn after_local_allocated( + ecx: &mut InterpCx<'mir, 'tcx, Self>, + frame: usize, + local: mir::Local, + mplace: &MPlaceTy<'tcx, Provenance> + ) -> InterpResult<'tcx> { + let Some(Provenance::Concrete { alloc_id, .. }) = mplace.ptr.provenance else { + panic!("after_local_allocated should only be called on fresh allocations"); + }; + let local_decl = &ecx.active_thread_stack()[frame].body.local_decls[local]; + let span = local_decl.source_info.span; + ecx.machine + .allocation_spans + .borrow_mut() + .insert(alloc_id, (span, None)); + Ok(()) + } } diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.rs b/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.rs new file mode 100644 index 000000000000..393127341ca9 --- /dev/null +++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.rs @@ -0,0 +1,13 @@ +// The interpreter tries to delay allocating locals until their address is taken. +// This test checks that we correctly use the span associated with the local itself, not the span +// where we take the address of the local and force it to be allocated. + +fn main() { + let ptr = { + let x = 0usize; // This line should appear in the helps + &x as *const usize // This line should NOT appear in the helps + }; + unsafe { + dbg!(*ptr); //~ ERROR: has been freed + } +} diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.stderr new file mode 100644 index 000000000000..bdc9c31db40c --- /dev/null +++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.stderr @@ -0,0 +1,26 @@ +error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling + --> $DIR/dangling_primitive.rs:LL:CC + | +LL | dbg!(*ptr); + | ^^^^^^^^^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information +help: ALLOC was allocated here: + --> $DIR/dangling_primitive.rs:LL:CC + | +LL | let x = 0usize; // This line should appear in the helps + | ^ +help: ALLOC was deallocated here: + --> $DIR/dangling_primitive.rs:LL:CC + | +LL | }; + | ^ + = note: BACKTRACE (of the first span): + = note: inside `main` at RUSTLIB/std/src/macros.rs:LL:CC + = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/fail/dangling_pointers/deref-partially-dangling.stderr b/src/tools/miri/tests/fail/dangling_pointers/deref-partially-dangling.stderr index fe039ef3adaf..92b1fcb11451 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/deref-partially-dangling.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/deref-partially-dangling.stderr @@ -6,7 +6,12 @@ LL | let val = unsafe { (*xptr).1 }; | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information - = note: BACKTRACE: +help: ALLOC was allocated here: + --> $DIR/deref-partially-dangling.rs:LL:CC + | +LL | let x = (1, 13); + | ^ + = note: BACKTRACE (of the first span): = note: inside `main` at $DIR/deref-partially-dangling.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/dangling_pointers/dyn_size.stderr b/src/tools/miri/tests/fail/dangling_pointers/dyn_size.stderr index 33aa6c844101..95a50bc8750d 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/dyn_size.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/dyn_size.stderr @@ -6,7 +6,12 @@ LL | let _ptr = unsafe { &*ptr }; | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information - = note: BACKTRACE: +help: ALLOC was allocated here: + --> $DIR/dyn_size.rs:LL:CC + | +LL | let buf = [0u32; 1]; + | ^^^ + = note: BACKTRACE (of the first span): = note: inside `main` at $DIR/dyn_size.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr b/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr index 500f28a3cbc7..4d2dfe28aed1 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr @@ -6,7 +6,17 @@ LL | let val = *x; | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information - = note: BACKTRACE: +help: ALLOC was allocated here: + --> $DIR/stack_temporary.rs:LL:CC + | +LL | let x = make_ref(&mut 0); // The temporary storing "0" is deallocated at the ";"! + | ^ +help: ALLOC was deallocated here: + --> $DIR/stack_temporary.rs:LL:CC + | +LL | let x = make_ref(&mut 0); // The temporary storing "0" is deallocated at the ";"! + | ^ + = note: BACKTRACE (of the first span): = note: inside `main` at $DIR/stack_temporary.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr index 4422310870a6..e1102a6d216a 100644 --- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr @@ -6,7 +6,12 @@ LL | let x = unsafe { x.offset(5) }; | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information - = note: BACKTRACE: +help: ALLOC was allocated here: + --> $DIR/out_of_bounds_ptr_1.rs:LL:CC + | +LL | let v = [0i8; 4]; + | ^ + = note: BACKTRACE (of the first span): = note: inside `main` at $DIR/out_of_bounds_ptr_1.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr index 1364e0f9009d..99f28b3e4f81 100644 --- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr +++ b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr @@ -6,7 +6,12 @@ LL | let x = unsafe { x.offset(-1) }; | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information - = note: BACKTRACE: +help: ALLOC was allocated here: + --> $DIR/out_of_bounds_ptr_3.rs:LL:CC + | +LL | let v = [0i8; 4]; + | ^ + = note: BACKTRACE (of the first span): = note: inside `main` at $DIR/out_of_bounds_ptr_3.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace From 8ecdefb3db7e854561fd382ba19675c894f40170 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Fri, 25 Aug 2023 11:58:31 -0400 Subject: [PATCH 189/197] Add a doc comment for the new hook Co-authored-by: Ralf Jung --- compiler/rustc_const_eval/src/interpret/machine.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index ff106fa4b1bc..2b8e8bfbdd91 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -472,6 +472,9 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { Ok(StackPopJump::Normal) } + /// Called immediately after actual memory was allocated for a local + /// but before the local's stack frame is updated to point to that memory. + #[inline(always)] fn after_local_allocated( _ecx: &mut InterpCx<'mir, 'tcx, Self>, _frame: usize, From 055452864e7fbb0cf15864160087d10030dc7260 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 25 Aug 2023 18:07:00 +0000 Subject: [PATCH 190/197] Walk through full path in point_at_path_if_possible --- .../src/fn_ctxt/adjust_fulfillment_errors.rs | 52 ++++++++++--------- .../ui/const-generics/exhaustive-value.stderr | 4 +- .../unsatisfied-bounds.stderr | 4 +- .../enum-unit-variant-trait-bound.rs | 6 +++ .../enum-unit-variant-trait-bound.stderr | 13 +++++ tests/ui/traits/suggest-where-clause.stderr | 12 ++--- 6 files changed, 57 insertions(+), 34 deletions(-) create mode 100644 tests/ui/trait-bounds/enum-unit-variant-trait-bound.rs create mode 100644 tests/ui/trait-bounds/enum-unit-variant-trait-bound.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index c44d12e61e33..1861f141eed4 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -1,6 +1,6 @@ use crate::FnCtxt; use rustc_hir as hir; -use rustc_hir::def::Res; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_infer::{infer::type_variable::TypeVariableOriginKind, traits::ObligationCauseCode}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor}; @@ -133,15 +133,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - // Notably, we only point to params that are local to the - // item we're checking, since those are the ones we are able - // to look in the final `hir::PathSegment` for. Everything else - // would require a deeper search into the `qpath` than I think - // is worthwhile. - if let Some(param_to_point_at) = param_to_point_at - && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath) + + for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] + .into_iter() + .flatten() { - return true; + if self.point_at_path_if_possible(error, def_id, param, qpath) { + return true; + } } } hir::ExprKind::MethodCall(segment, receiver, args, ..) => { @@ -168,10 +167,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } hir::ExprKind::Struct(qpath, fields, ..) => { - if let Res::Def( - hir::def::DefKind::Struct | hir::def::DefKind::Variant, - variant_def_id, - ) = self.typeck_results.borrow().qpath_res(qpath, hir_id) + if let Res::Def(DefKind::Struct | DefKind::Variant, variant_def_id) = + self.typeck_results.borrow().qpath_res(qpath, hir_id) { for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] @@ -193,10 +190,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - if let Some(param_to_point_at) = param_to_point_at - && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath) + + for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] + .into_iter() + .flatten() { - return true; + if self.point_at_path_if_possible(error, def_id, param, qpath) { + return true; + } } } _ => {} @@ -214,10 +215,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> bool { match qpath { hir::QPath::Resolved(_, path) => { - if let Some(segment) = path.segments.last() - && self.point_at_generic_if_possible(error, def_id, param, segment) - { - return true; + for segment in path.segments.iter().rev() { + if let Res::Def(kind, def_id) = segment.res + && !matches!(kind, DefKind::Mod | DefKind::ForeignMod) + && self.point_at_generic_if_possible(error, def_id, param, segment) + { + return true; + } } } hir::QPath::TypeRelative(_, segment) => { @@ -618,14 +622,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let variant_def_id = match expr_struct_def_kind { - hir::def::DefKind::Struct => { + DefKind::Struct => { if in_ty_adt.did() != expr_struct_def_id { // FIXME: Deal with type aliases? return Err(expr); } expr_struct_def_id } - hir::def::DefKind::Variant => { + DefKind::Variant => { // If this is a variant, its parent is the type definition. if in_ty_adt.did() != self.tcx.parent(expr_struct_def_id) { // FIXME: Deal with type aliases? @@ -727,14 +731,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let variant_def_id = match expr_struct_def_kind { - hir::def::DefKind::Ctor(hir::def::CtorOf::Struct, hir::def::CtorKind::Fn) => { + DefKind::Ctor(hir::def::CtorOf::Struct, hir::def::CtorKind::Fn) => { if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) { // FIXME: Deal with type aliases? return Err(expr); } self.tcx.parent(expr_ctor_def_id) } - hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => { + DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => { // For a typical enum like // `enum Blah { Variant(T) }` // we get the following resolutions: diff --git a/tests/ui/const-generics/exhaustive-value.stderr b/tests/ui/const-generics/exhaustive-value.stderr index 4a26e09772dc..0828f7896dc6 100644 --- a/tests/ui/const-generics/exhaustive-value.stderr +++ b/tests/ui/const-generics/exhaustive-value.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/exhaustive-value.rs:262:5 + --> $DIR/exhaustive-value.rs:262:16 | LL | <() as Foo>::test() - | ^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` + | ^ the trait `Foo` is not implemented for `()` | = help: the following other types implement trait `Foo`: <() as Foo<0>> diff --git a/tests/ui/generic-const-items/unsatisfied-bounds.stderr b/tests/ui/generic-const-items/unsatisfied-bounds.stderr index 1fda460372a5..2cee53431a42 100644 --- a/tests/ui/generic-const-items/unsatisfied-bounds.stderr +++ b/tests/ui/generic-const-items/unsatisfied-bounds.stderr @@ -27,10 +27,10 @@ LL | Infallible: From; | ^^^^^^^ required by this bound in `K` error[E0277]: the trait bound `Vec: Copy` is not satisfied - --> $DIR/unsatisfied-bounds.rs:32:13 + --> $DIR/unsatisfied-bounds.rs:32:26 | LL | let _ = <() as Trait>>::A; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Vec` + | ^^^^^^^ the trait `Copy` is not implemented for `Vec` | note: required by a bound in `Trait::A` --> $DIR/unsatisfied-bounds.rs:17:12 diff --git a/tests/ui/trait-bounds/enum-unit-variant-trait-bound.rs b/tests/ui/trait-bounds/enum-unit-variant-trait-bound.rs new file mode 100644 index 000000000000..91525bc90c4b --- /dev/null +++ b/tests/ui/trait-bounds/enum-unit-variant-trait-bound.rs @@ -0,0 +1,6 @@ +// Regression test for one part of issue #105306. + +fn main() { + let _ = Option::<[u8]>::None; + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time +} diff --git a/tests/ui/trait-bounds/enum-unit-variant-trait-bound.stderr b/tests/ui/trait-bounds/enum-unit-variant-trait-bound.stderr new file mode 100644 index 000000000000..32f6b00b20c4 --- /dev/null +++ b/tests/ui/trait-bounds/enum-unit-variant-trait-bound.stderr @@ -0,0 +1,13 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/enum-unit-variant-trait-bound.rs:4:22 + | +LL | let _ = Option::<[u8]>::None; + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `None` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-where-clause.stderr b/tests/ui/traits/suggest-where-clause.stderr index f3a4c6890337..5a5398848731 100644 --- a/tests/ui/traits/suggest-where-clause.stderr +++ b/tests/ui/traits/suggest-where-clause.stderr @@ -38,10 +38,10 @@ LL + fn check() { | error[E0277]: the trait bound `u64: From` is not satisfied - --> $DIR/suggest-where-clause.rs:15:5 + --> $DIR/suggest-where-clause.rs:15:18 | LL | >::from; - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `From` is not implemented for `u64` + | ^ the trait `From` is not implemented for `u64` | help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement | @@ -49,10 +49,10 @@ LL | fn check() where u64: From { | ++++++++++++++++++ error[E0277]: the trait bound `u64: From<::Item>` is not satisfied - --> $DIR/suggest-where-clause.rs:18:5 + --> $DIR/suggest-where-clause.rs:18:18 | LL | ::Item>>::from; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<::Item>` is not implemented for `u64` + | ^^^^^^^^^^^^^^^^^^^^^ the trait `From<::Item>` is not implemented for `u64` | help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement | @@ -60,10 +60,10 @@ LL | fn check() where u64: From<::Item> { | ++++++++++++++++++++++++++++++++++++++ error[E0277]: the trait bound `Misc<_>: From` is not satisfied - --> $DIR/suggest-where-clause.rs:23:5 + --> $DIR/suggest-where-clause.rs:23:22 | LL | as From>::from; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From` is not implemented for `Misc<_>` + | ^ the trait `From` is not implemented for `Misc<_>` error[E0277]: the size for values of type `[T]` cannot be known at compilation time --> $DIR/suggest-where-clause.rs:28:20 From 13e8b13e15ec38da731a72513851aced2ee8fb24 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 25 Aug 2023 18:28:34 +0000 Subject: [PATCH 191/197] Handle Self in paths too --- .../src/fn_ctxt/adjust_fulfillment_errors.rs | 36 +++++++++++++++++-- .../associated-const-array-len.stderr | 4 +-- tests/ui/associated-types/issue-44153.stderr | 4 +-- .../substs-ppaux.normal.stderr | 4 +-- .../substs-ppaux.verbose.stderr | 4 +-- .../dont-evaluate-array-len-on-err-1.stderr | 4 +-- .../consts/missing-larger-array-impl.stderr | 4 +-- tests/ui/issues/issue-39970.stderr | 4 +-- .../call-const-trait-method-fail.stderr | 4 +-- .../trait-where-clause-const.stderr | 2 +- .../trait-where-clause.stderr | 2 +- .../unevaluated_fixed_size_array_len.stderr | 4 +-- 12 files changed, 54 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index 1861f141eed4..f6a5b8f97a15 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -165,6 +165,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { return true; } + // Handle `Self` param specifically, since it's separated in + // the method call representation + if self_param_to_point_at.is_some() { + error.obligation.cause.span = receiver + .span + .find_ancestor_in_same_ctxt(error.obligation.cause.span) + .unwrap_or(receiver.span); + return true; + } } hir::ExprKind::Struct(qpath, fields, ..) => { if let Res::Def(DefKind::Struct | DefKind::Variant, variant_def_id) = @@ -214,7 +223,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { qpath: &hir::QPath<'tcx>, ) -> bool { match qpath { - hir::QPath::Resolved(_, path) => { + hir::QPath::Resolved(self_ty, path) => { for segment in path.segments.iter().rev() { if let Res::Def(kind, def_id) = segment.res && !matches!(kind, DefKind::Mod | DefKind::ForeignMod) @@ -223,11 +232,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return true; } } + // Handle `Self` param specifically, since it's separated in + // the path representation + if let Some(self_ty) = self_ty + && let ty::GenericArgKind::Type(ty) = param.unpack() + && ty == self.tcx.types.self_param + { + error.obligation.cause.span = self_ty + .span + .find_ancestor_in_same_ctxt(error.obligation.cause.span) + .unwrap_or(self_ty.span); + return true; + } } - hir::QPath::TypeRelative(_, segment) => { + hir::QPath::TypeRelative(self_ty, segment) => { if self.point_at_generic_if_possible(error, def_id, param, segment) { return true; } + // Handle `Self` param specifically, since it's separated in + // the path representation + if let ty::GenericArgKind::Type(ty) = param.unpack() + && ty == self.tcx.types.self_param + { + error.obligation.cause.span = self_ty + .span + .find_ancestor_in_same_ctxt(error.obligation.cause.span) + .unwrap_or(self_ty.span); + return true; + } } _ => {} } diff --git a/tests/ui/associated-consts/associated-const-array-len.stderr b/tests/ui/associated-consts/associated-const-array-len.stderr index 86c62e7b7f12..0e0dec35b53a 100644 --- a/tests/ui/associated-consts/associated-const-array-len.stderr +++ b/tests/ui/associated-consts/associated-const-array-len.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/associated-const-array-len.rs:5:16 + --> $DIR/associated-const-array-len.rs:5:17 | LL | const X: [i32; ::ID] = [0, 1, 2]; - | ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` + | ^^^ the trait `Foo` is not implemented for `i32` error: aborting due to previous error diff --git a/tests/ui/associated-types/issue-44153.stderr b/tests/ui/associated-types/issue-44153.stderr index 8bddcd955689..73365d64d560 100644 --- a/tests/ui/associated-types/issue-44153.stderr +++ b/tests/ui/associated-types/issue-44153.stderr @@ -1,8 +1,8 @@ error[E0271]: type mismatch resolving `<() as Array>::Element == &()` - --> $DIR/issue-44153.rs:18:5 + --> $DIR/issue-44153.rs:18:6 | LL | <() as Visit>::visit(); - | ^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Array>::Element == &()` + | ^^ type mismatch resolving `<() as Array>::Element == &()` | note: expected this to be `&()` --> $DIR/issue-44153.rs:10:20 diff --git a/tests/ui/associated-types/substs-ppaux.normal.stderr b/tests/ui/associated-types/substs-ppaux.normal.stderr index acdc3be8c676..015b22f790f8 100644 --- a/tests/ui/associated-types/substs-ppaux.normal.stderr +++ b/tests/ui/associated-types/substs-ppaux.normal.stderr @@ -71,10 +71,10 @@ LL | let x: () = foo::<'static>(); | ++ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/substs-ppaux.rs:49:5 + --> $DIR/substs-ppaux.rs:49:6 | LL | >::bar; - | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` note: required for `str` to implement `Foo<'_, '_, u8>` diff --git a/tests/ui/associated-types/substs-ppaux.verbose.stderr b/tests/ui/associated-types/substs-ppaux.verbose.stderr index ad67899e6da0..484581b10288 100644 --- a/tests/ui/associated-types/substs-ppaux.verbose.stderr +++ b/tests/ui/associated-types/substs-ppaux.verbose.stderr @@ -71,10 +71,10 @@ LL | let x: () = foo::<'static>(); | ++ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/substs-ppaux.rs:49:5 + --> $DIR/substs-ppaux.rs:49:6 | LL | >::bar; - | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` note: required for `str` to implement `Foo<'?0, '?1, u8>` diff --git a/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr b/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr index d8eebeb0d211..cb51d9b1ea59 100644 --- a/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr +++ b/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `[Adt; std::mem::size_of::()]: Foo` is not satisfied - --> $DIR/dont-evaluate-array-len-on-err-1.rs:15:9 + --> $DIR/dont-evaluate-array-len-on-err-1.rs:15:10 | LL | <[Adt; std::mem::size_of::()] as Foo>::bar() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[Adt; std::mem::size_of::()]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[Adt; std::mem::size_of::()]` error: aborting due to previous error diff --git a/tests/ui/consts/missing-larger-array-impl.stderr b/tests/ui/consts/missing-larger-array-impl.stderr index b8f6cb5ef977..fe9d0f6e6ed2 100644 --- a/tests/ui/consts/missing-larger-array-impl.stderr +++ b/tests/ui/consts/missing-larger-array-impl.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `[X; 35]: Default` is not satisfied - --> $DIR/missing-larger-array-impl.rs:7:5 + --> $DIR/missing-larger-array-impl.rs:7:6 | LL | <[X; 35] as Default>::default(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `[X; 35]` + | ^^^^^^^ the trait `Default` is not implemented for `[X; 35]` | = help: the following other types implement trait `Default`: [T; 0] diff --git a/tests/ui/issues/issue-39970.stderr b/tests/ui/issues/issue-39970.stderr index 8344b88c3bea..713bc404f670 100644 --- a/tests/ui/issues/issue-39970.stderr +++ b/tests/ui/issues/issue-39970.stderr @@ -1,8 +1,8 @@ error[E0271]: type mismatch resolving `<() as Array<'a>>::Element == ()` - --> $DIR/issue-39970.rs:19:5 + --> $DIR/issue-39970.rs:19:6 | LL | <() as Visit>::visit(); - | ^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Array<'a>>::Element == ()` + | ^^ type mismatch resolving `<() as Array<'a>>::Element == ()` | note: expected this to be `()` --> $DIR/issue-39970.rs:10:20 diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr index 2d9c49af85a9..452bf757df76 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `u32: ~const Plus` is not satisfied - --> $DIR/call-const-trait-method-fail.rs:25:7 + --> $DIR/call-const-trait-method-fail.rs:25:5 | LL | a.plus(b) - | ^^^^ the trait `Plus` is not implemented for `u32` + | ^ the trait `Plus` is not implemented for `u32` | = help: the trait `Plus` is implemented for `u32` diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr index e8d0eec020f4..c94563d3591b 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: ~const Bar` is not satisfied --> $DIR/trait-where-clause-const.rs:21:5 | LL | T::b(); - | ^^^^ the trait `Bar` is not implemented for `T` + | ^ the trait `Bar` is not implemented for `T` | note: required by a bound in `Foo::b` --> $DIR/trait-where-clause-const.rs:15:24 diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr index 11f0c40160d8..255878e17752 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: Bar` is not satisfied --> $DIR/trait-where-clause.rs:14:5 | LL | T::b(); - | ^^^^ the trait `Bar` is not implemented for `T` + | ^ the trait `Bar` is not implemented for `T` | note: required by a bound in `Foo::b` --> $DIR/trait-where-clause.rs:8:24 diff --git a/tests/ui/unevaluated_fixed_size_array_len.stderr b/tests/ui/unevaluated_fixed_size_array_len.stderr index 5e67b2c44f2b..b04a7b7f2f1d 100644 --- a/tests/ui/unevaluated_fixed_size_array_len.stderr +++ b/tests/ui/unevaluated_fixed_size_array_len.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `[(); 0]: Foo` is not satisfied - --> $DIR/unevaluated_fixed_size_array_len.rs:12:5 + --> $DIR/unevaluated_fixed_size_array_len.rs:12:6 | LL | <[(); 0] as Foo>::foo() - | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[(); 0]` + | ^^^^^^^ the trait `Foo` is not implemented for `[(); 0]` | = help: the trait `Foo` is implemented for `[(); 1]` From 1abaf40ec818dfc0a0ad50e6e772cce60acc8477 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Fri, 25 Aug 2023 17:54:50 -0400 Subject: [PATCH 192/197] Add a new helper to avoid calling io::Error::kind --- library/std/src/fs.rs | 3 +++ library/std/src/io/error.rs | 10 ++++++++++ library/std/src/io/mod.rs | 14 +++++++------- library/std/src/sys/itron/error.rs | 5 +++++ library/std/src/sys/sgx/mod.rs | 6 ++++++ library/std/src/sys/solid/error.rs | 5 +++++ library/std/src/sys/solid/mod.rs | 5 +++++ library/std/src/sys/solid/net.rs | 6 ++++++ library/std/src/sys/unix/mod.rs | 5 +++++ library/std/src/sys/unsupported/common.rs | 4 ++++ library/std/src/sys/wasi/mod.rs | 5 +++++ library/std/src/sys/windows/mod.rs | 5 +++++ 12 files changed, 66 insertions(+), 7 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 4094e378034e..3c67bea7a222 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -745,14 +745,17 @@ fn buffer_capacity_required(mut file: &File) -> Option { #[stable(feature = "rust1", since = "1.0.0")] impl Read for &File { + #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } + #[inline] fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { self.inner.read_vectored(bufs) } + #[inline] fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { self.inner.read_buf(cursor) } diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 34c0ce9dcf84..d6fce4ee78f5 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -916,6 +916,16 @@ impl Error { ErrorData::SimpleMessage(m) => m.kind, } } + + #[inline] + pub(crate) fn is_interrupted(&self) -> bool { + match self.repr.data() { + ErrorData::Os(code) => sys::is_interrupted(code), + ErrorData::Custom(c) => c.kind == ErrorKind::Interrupted, + ErrorData::Simple(kind) => kind == ErrorKind::Interrupted, + ErrorData::SimpleMessage(m) => m.kind == ErrorKind::Interrupted, + } + } } impl fmt::Debug for Repr { diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 71d91f21362e..e89843b57032 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -390,7 +390,7 @@ pub(crate) fn default_read_to_end( let mut cursor = read_buf.unfilled(); match r.read_buf(cursor.reborrow()) { Ok(()) => {} - Err(e) if e.kind() == ErrorKind::Interrupted => continue, + Err(e) if e.is_interrupted() => continue, Err(e) => return Err(e), } @@ -421,7 +421,7 @@ pub(crate) fn default_read_to_end( buf.extend_from_slice(&probe[..n]); break; } - Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, + Err(ref e) if e.is_interrupted() => continue, Err(e) => return Err(e), } } @@ -470,7 +470,7 @@ pub(crate) fn default_read_exact(this: &mut R, mut buf: &mut [ let tmp = buf; buf = &mut tmp[n..]; } - Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + Err(ref e) if e.is_interrupted() => {} Err(e) => return Err(e), } } @@ -860,7 +860,7 @@ pub trait Read { let prev_written = cursor.written(); match self.read_buf(cursor.reborrow()) { Ok(()) => {} - Err(e) if e.kind() == ErrorKind::Interrupted => continue, + Err(e) if e.is_interrupted() => continue, Err(e) => return Err(e), } @@ -1579,7 +1579,7 @@ pub trait Write { )); } Ok(n) => buf = &buf[n..], - Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + Err(ref e) if e.is_interrupted() => {} Err(e) => return Err(e), } } @@ -1943,7 +1943,7 @@ fn read_until(r: &mut R, delim: u8, buf: &mut Vec) -> R let (done, used) = { let available = match r.fill_buf() { Ok(n) => n, - Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, + Err(ref e) if e.is_interrupted() => continue, Err(e) => return Err(e), }; match memchr::memchr(delim, available) { @@ -2734,7 +2734,7 @@ impl Iterator for Bytes { return match self.inner.read(slice::from_mut(&mut byte)) { Ok(0) => None, Ok(..) => Some(Ok(byte)), - Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, + Err(ref e) if e.is_interrupted() => continue, Err(e) => Some(Err(e)), }; } diff --git a/library/std/src/sys/itron/error.rs b/library/std/src/sys/itron/error.rs index 830c60d329e4..fbc822d4eb6e 100644 --- a/library/std/src/sys/itron/error.rs +++ b/library/std/src/sys/itron/error.rs @@ -79,6 +79,11 @@ pub fn error_name(er: abi::ER) -> Option<&'static str> { } } +#[inline] +pub fn is_interrupted(er: abi::ER) -> bool { + er == abi::E_RLWAI +} + pub fn decode_error_kind(er: abi::ER) -> ErrorKind { match er { // Success diff --git a/library/std/src/sys/sgx/mod.rs b/library/std/src/sys/sgx/mod.rs index 9865a945bad1..09d3f7638ca2 100644 --- a/library/std/src/sys/sgx/mod.rs +++ b/library/std/src/sys/sgx/mod.rs @@ -86,6 +86,12 @@ pub fn sgx_ineffective(v: T) -> crate::io::Result { } } +#[inline] +pub fn is_interrupted(code: i32) -> bool { + use fortanix_sgx_abi::Error; + code == Error::Interrupted as _ +} + pub fn decode_error_kind(code: i32) -> ErrorKind { use fortanix_sgx_abi::Error; diff --git a/library/std/src/sys/solid/error.rs b/library/std/src/sys/solid/error.rs index 547b4f3a9840..d1877a8bcd2b 100644 --- a/library/std/src/sys/solid/error.rs +++ b/library/std/src/sys/solid/error.rs @@ -31,6 +31,11 @@ pub fn error_name(er: abi::ER) -> Option<&'static str> { } } +#[inline] +fn is_interrupted(er: abi::ER) -> bool { + false +} + pub fn decode_error_kind(er: abi::ER) -> ErrorKind { match er { // Success diff --git a/library/std/src/sys/solid/mod.rs b/library/std/src/sys/solid/mod.rs index 923d27fd9369..e7029174511c 100644 --- a/library/std/src/sys/solid/mod.rs +++ b/library/std/src/sys/solid/mod.rs @@ -72,6 +72,11 @@ pub fn unsupported_err() -> crate::io::Error { ) } +#[inline] +pub fn is_interrupted(code: i32) -> bool { + error::is_interrupted(code) +} + pub fn decode_error_kind(code: i32) -> crate::io::ErrorKind { error::decode_error_kind(code) } diff --git a/library/std/src/sys/solid/net.rs b/library/std/src/sys/solid/net.rs index 0bd2bc3b9619..bdd64ab02b77 100644 --- a/library/std/src/sys/solid/net.rs +++ b/library/std/src/sys/solid/net.rs @@ -181,6 +181,12 @@ pub(super) fn error_name(er: abi::ER) -> Option<&'static str> { unsafe { CStr::from_ptr(netc::strerror(er)) }.to_str().ok() } +#[inline] +pub fn is_interrupted(er: abi::ER) -> bool { + let errno = netc::SOLID_NET_ERR_BASE - er; + errno as libc::c_int == libc::EINTR +} + pub(super) fn decode_error_kind(er: abi::ER) -> ErrorKind { let errno = netc::SOLID_NET_ERR_BASE - er; match errno as libc::c_int { diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index 77ef086f29b5..6d7439033149 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -240,6 +240,11 @@ pub use crate::sys::android::signal; #[cfg(not(target_os = "android"))] pub use libc::signal; +#[inline] +pub(crate) fn is_interrupted(errno: i32) -> bool { + errno == libc::EINTR +} + pub fn decode_error_kind(errno: i32) -> ErrorKind { use ErrorKind::*; match errno as libc::c_int { diff --git a/library/std/src/sys/unsupported/common.rs b/library/std/src/sys/unsupported/common.rs index 5cd9e57de19e..5c379992b204 100644 --- a/library/std/src/sys/unsupported/common.rs +++ b/library/std/src/sys/unsupported/common.rs @@ -23,6 +23,10 @@ pub fn unsupported_err() -> std_io::Error { ) } +pub fn is_interrupted(_code: i32) -> bool { + false +} + pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind { crate::io::ErrorKind::Uncategorized } diff --git a/library/std/src/sys/wasi/mod.rs b/library/std/src/sys/wasi/mod.rs index 98517da1d0fe..5cbb5cb65ba8 100644 --- a/library/std/src/sys/wasi/mod.rs +++ b/library/std/src/sys/wasi/mod.rs @@ -76,6 +76,11 @@ cfg_if::cfg_if! { mod common; pub use common::*; +#[inline] +pub fn is_interrupted(errno: i32) -> bool { + errno == wasi::ERRNO_INTR.raw().into() +} + pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { use std_io::ErrorKind::*; if errno > u16::MAX as i32 || errno < 0 { diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index bcc172b0fae3..b609ad2472c6 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -60,6 +60,11 @@ pub unsafe fn cleanup() { net::cleanup(); } +#[inline] +pub fn is_interrupted(_errno: i32) -> bool { + false +} + pub fn decode_error_kind(errno: i32) -> ErrorKind { use ErrorKind::*; From 72b721f48e3695f25a0935ad535e75e6777d829b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 17 Aug 2023 11:24:56 +1000 Subject: [PATCH 193/197] Resolve all warnings in `run-coverage` tests When one of these tests fails, any compiler warnings will be printed to the console, which makes it harder to track down the actual reason for failure. (The outstanding warnings were found by temporarily adding `-Dwarnings` to the compiler arguments for `RunCoverage` in `src/tools/compiletest/src/runtest.rs`.) --- tests/run-coverage/async2.coverage | 6 ------ tests/run-coverage/async2.rs | 6 ------ tests/run-coverage/auxiliary/unused_mod_helper.rs | 1 + tests/run-coverage/auxiliary/used_crate.rs | 1 + tests/run-coverage/auxiliary/used_inline_crate.rs | 1 + tests/run-coverage/closure_macro_async.coverage | 2 +- tests/run-coverage/closure_macro_async.rs | 2 +- tests/run-coverage/dead_code.coverage | 2 +- tests/run-coverage/dead_code.rs | 2 +- tests/run-coverage/issue-93054.coverage | 2 ++ tests/run-coverage/issue-93054.rs | 2 ++ tests/run-coverage/match_or_pattern.coverage | 2 -- tests/run-coverage/match_or_pattern.rs | 2 -- tests/run-coverage/no_cov_crate.coverage | 2 ++ tests/run-coverage/no_cov_crate.rs | 2 ++ tests/run-coverage/unused.coverage | 2 ++ tests/run-coverage/unused.rs | 2 ++ tests/run-coverage/unused_mod.coverage | 1 + tests/run-coverage/uses_crate.coverage | 1 + tests/run-coverage/uses_inline_crate.coverage | 1 + 20 files changed, 22 insertions(+), 20 deletions(-) diff --git a/tests/run-coverage/async2.coverage b/tests/run-coverage/async2.coverage index 7e0139ae0362..db17b557167b 100644 --- a/tests/run-coverage/async2.coverage +++ b/tests/run-coverage/async2.coverage @@ -1,11 +1,5 @@ LL| |// compile-flags: --edition=2018 LL| | - LL| |use core::{ - LL| | future::Future, - LL| | marker::Send, - LL| | pin::Pin, - LL| |}; - LL| | LL| 1|fn non_async_func() { LL| 1| println!("non_async_func was covered"); LL| 1| let b = true; diff --git a/tests/run-coverage/async2.rs b/tests/run-coverage/async2.rs index 959d48ce9db1..21f4e65de302 100644 --- a/tests/run-coverage/async2.rs +++ b/tests/run-coverage/async2.rs @@ -1,11 +1,5 @@ // compile-flags: --edition=2018 -use core::{ - future::Future, - marker::Send, - pin::Pin, -}; - fn non_async_func() { println!("non_async_func was covered"); let b = true; diff --git a/tests/run-coverage/auxiliary/unused_mod_helper.rs b/tests/run-coverage/auxiliary/unused_mod_helper.rs index ae1cc1531ed7..88c5dac65cb5 100644 --- a/tests/run-coverage/auxiliary/unused_mod_helper.rs +++ b/tests/run-coverage/auxiliary/unused_mod_helper.rs @@ -1,3 +1,4 @@ +#[allow(dead_code)] pub fn never_called_function() { println!("I am never called"); } diff --git a/tests/run-coverage/auxiliary/used_crate.rs b/tests/run-coverage/auxiliary/used_crate.rs index 16592d48ddac..2107bb59c022 100644 --- a/tests/run-coverage/auxiliary/used_crate.rs +++ b/tests/run-coverage/auxiliary/used_crate.rs @@ -42,6 +42,7 @@ pub fn unused_function() { } } +#[allow(dead_code)] fn unused_private_function() { let is_true = std::env::args().len() == 1; let mut countdown = 2; diff --git a/tests/run-coverage/auxiliary/used_inline_crate.rs b/tests/run-coverage/auxiliary/used_inline_crate.rs index 8b8e9d5483f3..20882fd4df08 100644 --- a/tests/run-coverage/auxiliary/used_inline_crate.rs +++ b/tests/run-coverage/auxiliary/used_inline_crate.rs @@ -71,6 +71,7 @@ pub fn unused_function() { } #[inline(always)] +#[allow(dead_code)] fn unused_private_function() { let is_true = std::env::args().len() == 1; let mut countdown = 2; diff --git a/tests/run-coverage/closure_macro_async.coverage b/tests/run-coverage/closure_macro_async.coverage index 0e4365fc797d..4cd403847801 100644 --- a/tests/run-coverage/closure_macro_async.coverage +++ b/tests/run-coverage/closure_macro_async.coverage @@ -42,7 +42,7 @@ LL| | LL| |#[no_coverage] LL| |fn main() { - LL| | executor::block_on(test()); + LL| | executor::block_on(test()).unwrap(); LL| |} LL| | LL| |mod executor { diff --git a/tests/run-coverage/closure_macro_async.rs b/tests/run-coverage/closure_macro_async.rs index e3e89e9c8b3c..a90827572bb4 100644 --- a/tests/run-coverage/closure_macro_async.rs +++ b/tests/run-coverage/closure_macro_async.rs @@ -41,7 +41,7 @@ pub async fn test() -> Result<(), String> { #[no_coverage] fn main() { - executor::block_on(test()); + executor::block_on(test()).unwrap(); } mod executor { diff --git a/tests/run-coverage/dead_code.coverage b/tests/run-coverage/dead_code.coverage index 5074d8b3c377..c4ee9f23f082 100644 --- a/tests/run-coverage/dead_code.coverage +++ b/tests/run-coverage/dead_code.coverage @@ -1,4 +1,4 @@ - LL| |#![allow(unused_assignments, unused_variables)] + LL| |#![allow(dead_code, unused_assignments, unused_variables)] LL| | LL| 0|pub fn unused_pub_fn_not_in_library() { LL| 0| // Initialize test constants in a way that cannot be determined at compile time, to ensure diff --git a/tests/run-coverage/dead_code.rs b/tests/run-coverage/dead_code.rs index a1285df0ec62..3492712a6f98 100644 --- a/tests/run-coverage/dead_code.rs +++ b/tests/run-coverage/dead_code.rs @@ -1,4 +1,4 @@ -#![allow(unused_assignments, unused_variables)] +#![allow(dead_code, unused_assignments, unused_variables)] pub fn unused_pub_fn_not_in_library() { // Initialize test constants in a way that cannot be determined at compile time, to ensure diff --git a/tests/run-coverage/issue-93054.coverage b/tests/run-coverage/issue-93054.coverage index 074e6b9835a4..224c01d9a8ba 100644 --- a/tests/run-coverage/issue-93054.coverage +++ b/tests/run-coverage/issue-93054.coverage @@ -1,3 +1,5 @@ + LL| |#![allow(dead_code, unreachable_code)] + LL| | LL| |// Regression test for #93054: Functions using uninhabited types often only have a single, LL| |// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail. LL| |// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them. diff --git a/tests/run-coverage/issue-93054.rs b/tests/run-coverage/issue-93054.rs index c160b3db03f8..9f695b7fd11b 100644 --- a/tests/run-coverage/issue-93054.rs +++ b/tests/run-coverage/issue-93054.rs @@ -1,3 +1,5 @@ +#![allow(dead_code, unreachable_code)] + // Regression test for #93054: Functions using uninhabited types often only have a single, // unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail. // Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them. diff --git a/tests/run-coverage/match_or_pattern.coverage b/tests/run-coverage/match_or_pattern.coverage index 0b5a2c03dd36..94c7967215c1 100644 --- a/tests/run-coverage/match_or_pattern.coverage +++ b/tests/run-coverage/match_or_pattern.coverage @@ -1,5 +1,3 @@ - LL| |#![feature(or_patterns)] - LL| | LL| 1|fn main() { LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/run-coverage/match_or_pattern.rs b/tests/run-coverage/match_or_pattern.rs index 4c6a8a9b7037..ab7aee51d1bc 100644 --- a/tests/run-coverage/match_or_pattern.rs +++ b/tests/run-coverage/match_or_pattern.rs @@ -1,5 +1,3 @@ -#![feature(or_patterns)] - fn main() { // Initialize test constants in a way that cannot be determined at compile time, to ensure // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/run-coverage/no_cov_crate.coverage b/tests/run-coverage/no_cov_crate.coverage index c34dbde888ae..73f6fbd0c2ba 100644 --- a/tests/run-coverage/no_cov_crate.coverage +++ b/tests/run-coverage/no_cov_crate.coverage @@ -12,6 +12,7 @@ LL| |} LL| | LL| |#[no_coverage] + LL| |#[allow(dead_code)] LL| |fn do_not_add_coverage_not_called() { LL| | println!("not called and not covered"); LL| |} @@ -24,6 +25,7 @@ LL| 1| println!("called and covered"); LL| 1|} LL| | + LL| |#[allow(dead_code)] LL| 0|fn add_coverage_not_called() { LL| 0| println!("not called but covered"); LL| 0|} diff --git a/tests/run-coverage/no_cov_crate.rs b/tests/run-coverage/no_cov_crate.rs index 0bfbdda2cab0..5b748aeefb76 100644 --- a/tests/run-coverage/no_cov_crate.rs +++ b/tests/run-coverage/no_cov_crate.rs @@ -12,6 +12,7 @@ fn do_not_add_coverage_2() { } #[no_coverage] +#[allow(dead_code)] fn do_not_add_coverage_not_called() { println!("not called and not covered"); } @@ -24,6 +25,7 @@ fn add_coverage_2() { println!("called and covered"); } +#[allow(dead_code)] fn add_coverage_not_called() { println!("not called but covered"); } diff --git a/tests/run-coverage/unused.coverage b/tests/run-coverage/unused.coverage index ba25e34bf86d..056ffeb021a0 100644 --- a/tests/run-coverage/unused.coverage +++ b/tests/run-coverage/unused.coverage @@ -1,3 +1,5 @@ + LL| |#![allow(dead_code, unused_assignments, unused_must_use, unused_variables)] + LL| | LL| 2|fn foo(x: T) { LL| 2| let mut i = 0; LL| 22| while i < 10 { diff --git a/tests/run-coverage/unused.rs b/tests/run-coverage/unused.rs index fb6113eb01c2..d985af135470 100644 --- a/tests/run-coverage/unused.rs +++ b/tests/run-coverage/unused.rs @@ -1,3 +1,5 @@ +#![allow(dead_code, unused_assignments, unused_must_use, unused_variables)] + fn foo(x: T) { let mut i = 0; while i < 10 { diff --git a/tests/run-coverage/unused_mod.coverage b/tests/run-coverage/unused_mod.coverage index 558dfaa5cffc..a8fa24ac6a79 100644 --- a/tests/run-coverage/unused_mod.coverage +++ b/tests/run-coverage/unused_mod.coverage @@ -1,4 +1,5 @@ $DIR/auxiliary/unused_mod_helper.rs: + LL| |#[allow(dead_code)] LL| 0|pub fn never_called_function() { LL| 0| println!("I am never called"); LL| 0|} diff --git a/tests/run-coverage/uses_crate.coverage b/tests/run-coverage/uses_crate.coverage index 9da096dbd50a..2cee358665a4 100644 --- a/tests/run-coverage/uses_crate.coverage +++ b/tests/run-coverage/uses_crate.coverage @@ -90,6 +90,7 @@ $DIR/auxiliary/used_crate.rs: LL| 0| } LL| 0|} LL| | + LL| |#[allow(dead_code)] LL| 0|fn unused_private_function() { LL| 0| let is_true = std::env::args().len() == 1; LL| 0| let mut countdown = 2; diff --git a/tests/run-coverage/uses_inline_crate.coverage b/tests/run-coverage/uses_inline_crate.coverage index 48493e2079ca..7d909c78647a 100644 --- a/tests/run-coverage/uses_inline_crate.coverage +++ b/tests/run-coverage/uses_inline_crate.coverage @@ -120,6 +120,7 @@ $DIR/auxiliary/used_inline_crate.rs: LL| 0|} LL| | LL| |#[inline(always)] + LL| |#[allow(dead_code)] LL| 0|fn unused_private_function() { LL| 0| let is_true = std::env::args().len() == 1; LL| 0| let mut countdown = 2; From 4da38c31d21347fe7800c4263cb34a8c9e62d0fb Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 17 Aug 2023 11:32:33 +1000 Subject: [PATCH 194/197] Tidy up some awkwardly-placed comments in tests Prior to #114875, these tests were very sensitive to lines being added/removed, so the migration to `run-coverage` in #112300 tried hard to avoid disturbing the existing line numbers. That resulted in some awkward reshuffling when certain comments/directives needed to be added or moved. Now that we don't have to worry about preserving line numbers, we can rearrange those comments into a more conventional layout. --- tests/run-coverage-rustdoc/doctest.coverage | 4 +++- tests/run-coverage-rustdoc/doctest.rs | 4 +++- tests/run-coverage/auxiliary/used_crate.rs | 4 +++- tests/run-coverage/auxiliary/used_inline_crate.rs | 4 ++-- tests/run-coverage/closure.coverage | 7 ++++++- tests/run-coverage/closure.rs | 7 ++++++- tests/run-coverage/issue-85461.coverage | 1 + tests/run-coverage/issue-85461.rs | 1 + tests/run-coverage/uses_crate.coverage | 4 +++- tests/run-coverage/uses_inline_crate.coverage | 4 ++-- 10 files changed, 30 insertions(+), 10 deletions(-) diff --git a/tests/run-coverage-rustdoc/doctest.coverage b/tests/run-coverage-rustdoc/doctest.coverage index 07f1e6b3ee5d..5797784f411c 100644 --- a/tests/run-coverage-rustdoc/doctest.coverage +++ b/tests/run-coverage-rustdoc/doctest.coverage @@ -10,6 +10,8 @@ $DIR/auxiliary/doctest_crate.rs: LL| 3|} $DIR/doctest.rs: + LL| |// aux-build:doctest_crate.rs + LL| | LL| |//! This test ensures that code from doctests is properly re-mapped. LL| |//! See for more info. LL| |//! @@ -78,7 +80,7 @@ $DIR/doctest.rs: LL| |//! doctest_main() LL| |//! } LL| |//! ``` - LL| |// aux-build:doctest_crate.rs + LL| | LL| |/// doctest attached to fn testing external code: LL| |/// ``` LL| 1|/// extern crate doctest_crate; diff --git a/tests/run-coverage-rustdoc/doctest.rs b/tests/run-coverage-rustdoc/doctest.rs index 251b0c291e94..4006d723ce02 100644 --- a/tests/run-coverage-rustdoc/doctest.rs +++ b/tests/run-coverage-rustdoc/doctest.rs @@ -1,3 +1,5 @@ +// aux-build:doctest_crate.rs + //! This test ensures that code from doctests is properly re-mapped. //! See for more info. //! @@ -63,7 +65,7 @@ //! doctest_main() //! } //! ``` -// aux-build:doctest_crate.rs + /// doctest attached to fn testing external code: /// ``` /// extern crate doctest_crate; diff --git a/tests/run-coverage/auxiliary/used_crate.rs b/tests/run-coverage/auxiliary/used_crate.rs index 2107bb59c022..c086ef21e1a9 100644 --- a/tests/run-coverage/auxiliary/used_crate.rs +++ b/tests/run-coverage/auxiliary/used_crate.rs @@ -1,6 +1,8 @@ #![allow(unused_assignments, unused_variables)] +// Verify that coverage works with optimizations: // compile-flags: -C opt-level=3 -use std::fmt::Debug; // ^^ validates coverage now works with optimizations + +use std::fmt::Debug; pub fn used_function() { // Initialize test constants in a way that cannot be determined at compile time, to ensure diff --git a/tests/run-coverage/auxiliary/used_inline_crate.rs b/tests/run-coverage/auxiliary/used_inline_crate.rs index 20882fd4df08..a6651dd8a5ee 100644 --- a/tests/run-coverage/auxiliary/used_inline_crate.rs +++ b/tests/run-coverage/auxiliary/used_inline_crate.rs @@ -1,7 +1,7 @@ #![allow(unused_assignments, unused_variables)] - +// Verify that coverage works with optimizations: // compile-flags: -C opt-level=3 -// ^^ validates coverage now works with optimizations + use std::fmt::Debug; pub fn used_function() { diff --git a/tests/run-coverage/closure.coverage b/tests/run-coverage/closure.coverage index 809cf1f48211..211ba4cbe98c 100644 --- a/tests/run-coverage/closure.coverage +++ b/tests/run-coverage/closure.coverage @@ -1,6 +1,11 @@ LL| |#![allow(unused_assignments, unused_variables)] LL| |// compile-flags: -C opt-level=2 - LL| 1|fn main() { // ^^ fix described in rustc_middle/mir/mono.rs + LL| | + LL| |// This test used to be sensitive to certain coverage-specific hacks in + LL| |// `rustc_middle/mir/mono.rs`, but those hacks were later cleaned up by + LL| |// . + LL| | + LL| 1|fn main() { LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from LL| 1| // dependent conditions. diff --git a/tests/run-coverage/closure.rs b/tests/run-coverage/closure.rs index eb3a1ebff889..7c42458ae1b0 100644 --- a/tests/run-coverage/closure.rs +++ b/tests/run-coverage/closure.rs @@ -1,6 +1,11 @@ #![allow(unused_assignments, unused_variables)] // compile-flags: -C opt-level=2 -fn main() { // ^^ fix described in rustc_middle/mir/mono.rs + +// This test used to be sensitive to certain coverage-specific hacks in +// `rustc_middle/mir/mono.rs`, but those hacks were later cleaned up by +// . + +fn main() { // Initialize test constants in a way that cannot be determined at compile time, to ensure // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from // dependent conditions. diff --git a/tests/run-coverage/issue-85461.coverage b/tests/run-coverage/issue-85461.coverage index f97ab2303871..48e76318b0a4 100644 --- a/tests/run-coverage/issue-85461.coverage +++ b/tests/run-coverage/issue-85461.coverage @@ -24,6 +24,7 @@ $DIR/auxiliary/inline_always_with_dead_code.rs: $DIR/issue-85461.rs: LL| |// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)] + LL| | LL| |// aux-build:inline_always_with_dead_code.rs LL| |extern crate inline_always_with_dead_code; LL| | diff --git a/tests/run-coverage/issue-85461.rs b/tests/run-coverage/issue-85461.rs index 6f626b4a65b4..9d4c90a827ee 100644 --- a/tests/run-coverage/issue-85461.rs +++ b/tests/run-coverage/issue-85461.rs @@ -1,4 +1,5 @@ // Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)] + // aux-build:inline_always_with_dead_code.rs extern crate inline_always_with_dead_code; diff --git a/tests/run-coverage/uses_crate.coverage b/tests/run-coverage/uses_crate.coverage index 2cee358665a4..50d92102a109 100644 --- a/tests/run-coverage/uses_crate.coverage +++ b/tests/run-coverage/uses_crate.coverage @@ -1,7 +1,9 @@ $DIR/auxiliary/used_crate.rs: LL| |#![allow(unused_assignments, unused_variables)] + LL| |// Verify that coverage works with optimizations: LL| |// compile-flags: -C opt-level=3 - LL| |use std::fmt::Debug; // ^^ validates coverage now works with optimizations + LL| | + LL| |use std::fmt::Debug; LL| | LL| 1|pub fn used_function() { LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure diff --git a/tests/run-coverage/uses_inline_crate.coverage b/tests/run-coverage/uses_inline_crate.coverage index 7d909c78647a..c510b6a6c68e 100644 --- a/tests/run-coverage/uses_inline_crate.coverage +++ b/tests/run-coverage/uses_inline_crate.coverage @@ -1,8 +1,8 @@ $DIR/auxiliary/used_inline_crate.rs: LL| |#![allow(unused_assignments, unused_variables)] - LL| | + LL| |// Verify that coverage works with optimizations: LL| |// compile-flags: -C opt-level=3 - LL| |// ^^ validates coverage now works with optimizations + LL| | LL| |use std::fmt::Debug; LL| | LL| 1|pub fn used_function() { From 8d91e71e9a015c864b29725ec9430c5db4325cf4 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 17 Aug 2023 11:43:10 +1000 Subject: [PATCH 195/197] Various trivial formatting fixes in `run-coverage` tests These changes were made by manually running `rustfmt` on all of the test files, and then manually undoing all cases where the original formatting appeared to have been deliberate. `rustfmt +nightly --config-path=/dev/null --edition=2021 tests/run-coverage*/**/*.rs` --- tests/run-coverage/assert.coverage | 2 +- tests/run-coverage/assert.rs | 2 +- tests/run-coverage/async2.coverage | 6 ------ tests/run-coverage/async2.rs | 6 ------ .../auxiliary/inline_always_with_dead_code.rs | 4 ++-- tests/run-coverage/auxiliary/used_inline_crate.rs | 6 ------ tests/run-coverage/closure.coverage | 2 +- tests/run-coverage/closure.rs | 2 +- tests/run-coverage/closure_macro_async.coverage | 4 ---- tests/run-coverage/closure_macro_async.rs | 4 ---- tests/run-coverage/conditions.coverage | 1 - tests/run-coverage/conditions.rs | 1 - tests/run-coverage/drop_trait.coverage | 2 +- tests/run-coverage/drop_trait.rs | 2 +- tests/run-coverage/generics.coverage | 6 +----- tests/run-coverage/generics.rs | 6 +----- tests/run-coverage/issue-85461.coverage | 4 ++-- tests/run-coverage/issue-93054.coverage | 12 ++++++------ tests/run-coverage/issue-93054.rs | 12 ++++++------ tests/run-coverage/loops_branches.coverage | 3 +-- tests/run-coverage/loops_branches.rs | 3 +-- tests/run-coverage/overflow.coverage | 2 +- tests/run-coverage/overflow.rs | 2 +- tests/run-coverage/try_error_result.coverage | 14 +++++++------- tests/run-coverage/try_error_result.rs | 14 +++++++------- tests/run-coverage/uses_inline_crate.coverage | 6 ------ tests/run-coverage/while_early_ret.coverage | 2 +- tests/run-coverage/while_early_ret.rs | 2 +- tests/run-coverage/yield.coverage | 4 ++-- tests/run-coverage/yield.rs | 4 ++-- 30 files changed, 48 insertions(+), 92 deletions(-) diff --git a/tests/run-coverage/assert.coverage b/tests/run-coverage/assert.coverage index 3c6108e436a1..8b997724c4a7 100644 --- a/tests/run-coverage/assert.coverage +++ b/tests/run-coverage/assert.coverage @@ -7,7 +7,7 @@ ^1 LL| 3|} LL| | - LL| 1|fn main() -> Result<(),u8> { + LL| 1|fn main() -> Result<(), u8> { LL| 1| let mut countdown = 10; LL| 11| while countdown > 0 { LL| 11| if countdown == 1 { diff --git a/tests/run-coverage/assert.rs b/tests/run-coverage/assert.rs index d32a37e078e4..85e6662a6adc 100644 --- a/tests/run-coverage/assert.rs +++ b/tests/run-coverage/assert.rs @@ -6,7 +6,7 @@ fn might_fail_assert(one_plus_one: u32) { assert_eq!(1 + 1, one_plus_one, "the argument was wrong"); } -fn main() -> Result<(),u8> { +fn main() -> Result<(), u8> { let mut countdown = 10; while countdown > 0 { if countdown == 1 { diff --git a/tests/run-coverage/async2.coverage b/tests/run-coverage/async2.coverage index db17b557167b..fcb0a3aed64e 100644 --- a/tests/run-coverage/async2.coverage +++ b/tests/run-coverage/async2.coverage @@ -9,9 +9,6 @@ ^0 LL| 1|} LL| | - LL| | - LL| | - LL| | LL| 1|async fn async_func() { LL| 1| println!("async_func was covered"); LL| 1| let b = true; @@ -21,9 +18,6 @@ ^0 LL| 1|} LL| | - LL| | - LL| | - LL| | LL| 1|async fn async_func_just_println() { LL| 1| println!("async_func_just_println was covered"); LL| 1|} diff --git a/tests/run-coverage/async2.rs b/tests/run-coverage/async2.rs index 21f4e65de302..2884ff297aff 100644 --- a/tests/run-coverage/async2.rs +++ b/tests/run-coverage/async2.rs @@ -8,9 +8,6 @@ fn non_async_func() { } } - - - async fn async_func() { println!("async_func was covered"); let b = true; @@ -19,9 +16,6 @@ async fn async_func() { } } - - - async fn async_func_just_println() { println!("async_func_just_println was covered"); } diff --git a/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs b/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs index 2b21dee6ccff..9dc50dae25ae 100644 --- a/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs +++ b/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs @@ -4,9 +4,9 @@ mod foo { #[inline(always)] - pub fn called() { } + pub fn called() {} - fn uncalled() { } + fn uncalled() {} } pub mod bar { diff --git a/tests/run-coverage/auxiliary/used_inline_crate.rs b/tests/run-coverage/auxiliary/used_inline_crate.rs index a6651dd8a5ee..e8929de6b360 100644 --- a/tests/run-coverage/auxiliary/used_inline_crate.rs +++ b/tests/run-coverage/auxiliary/used_inline_crate.rs @@ -29,12 +29,6 @@ pub fn used_inline_function() { use_this_lib_crate(); } - - - - - - #[inline(always)] pub fn used_only_from_bin_crate_generic_function(arg: T) { println!("used_only_from_bin_crate_generic_function with {:?}", arg); diff --git a/tests/run-coverage/closure.coverage b/tests/run-coverage/closure.coverage index 211ba4cbe98c..930348dc4315 100644 --- a/tests/run-coverage/closure.coverage +++ b/tests/run-coverage/closure.coverage @@ -10,7 +10,7 @@ LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from LL| 1| // dependent conditions. LL| 1| let is_true = std::env::args().len() == 1; - LL| 1| let is_false = ! is_true; + LL| 1| let is_false = !is_true; LL| 1| LL| 1| let mut some_string = Some(String::from("the string content")); LL| 1| println!( diff --git a/tests/run-coverage/closure.rs b/tests/run-coverage/closure.rs index 7c42458ae1b0..16a2c4e33bd4 100644 --- a/tests/run-coverage/closure.rs +++ b/tests/run-coverage/closure.rs @@ -10,7 +10,7 @@ fn main() { // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from // dependent conditions. let is_true = std::env::args().len() == 1; - let is_false = ! is_true; + let is_false = !is_true; let mut some_string = Some(String::from("the string content")); println!( diff --git a/tests/run-coverage/closure_macro_async.coverage b/tests/run-coverage/closure_macro_async.coverage index 4cd403847801..018e3160e4f7 100644 --- a/tests/run-coverage/closure_macro_async.coverage +++ b/tests/run-coverage/closure_macro_async.coverage @@ -57,16 +57,12 @@ LL| | let mut future = unsafe { Pin::new_unchecked(&mut future) }; LL| | use std::hint::unreachable_unchecked; LL| | static VTABLE: RawWakerVTable = RawWakerVTable::new( - LL| | LL| | #[no_coverage] LL| | |_| unsafe { unreachable_unchecked() }, // clone - LL| | LL| | #[no_coverage] LL| | |_| unsafe { unreachable_unchecked() }, // wake - LL| | LL| | #[no_coverage] LL| | |_| unsafe { unreachable_unchecked() }, // wake_by_ref - LL| | LL| | #[no_coverage] LL| | |_| (), LL| | ); diff --git a/tests/run-coverage/closure_macro_async.rs b/tests/run-coverage/closure_macro_async.rs index a90827572bb4..3d6bdb38a2ab 100644 --- a/tests/run-coverage/closure_macro_async.rs +++ b/tests/run-coverage/closure_macro_async.rs @@ -56,16 +56,12 @@ mod executor { let mut future = unsafe { Pin::new_unchecked(&mut future) }; use std::hint::unreachable_unchecked; static VTABLE: RawWakerVTable = RawWakerVTable::new( - #[no_coverage] |_| unsafe { unreachable_unchecked() }, // clone - #[no_coverage] |_| unsafe { unreachable_unchecked() }, // wake - #[no_coverage] |_| unsafe { unreachable_unchecked() }, // wake_by_ref - #[no_coverage] |_| (), ); diff --git a/tests/run-coverage/conditions.coverage b/tests/run-coverage/conditions.coverage index 4749c353a64f..473335ff641a 100644 --- a/tests/run-coverage/conditions.coverage +++ b/tests/run-coverage/conditions.coverage @@ -59,7 +59,6 @@ LL| | } LL| 0| } LL| | - LL| | LL| 1| let mut countdown = 0; LL| 1| if true { LL| 1| countdown = 1; diff --git a/tests/run-coverage/conditions.rs b/tests/run-coverage/conditions.rs index 057599d1b471..fa7f2a116c21 100644 --- a/tests/run-coverage/conditions.rs +++ b/tests/run-coverage/conditions.rs @@ -55,7 +55,6 @@ fn main() { } } - let mut countdown = 0; if true { countdown = 1; diff --git a/tests/run-coverage/drop_trait.coverage b/tests/run-coverage/drop_trait.coverage index c99b980a339f..2c9439a93b12 100644 --- a/tests/run-coverage/drop_trait.coverage +++ b/tests/run-coverage/drop_trait.coverage @@ -11,7 +11,7 @@ LL| 2| } LL| |} LL| | - LL| 1|fn main() -> Result<(),u8> { + LL| 1|fn main() -> Result<(), u8> { LL| 1| let _firecracker = Firework { strength: 1 }; LL| 1| LL| 1| let _tnt = Firework { strength: 100 }; diff --git a/tests/run-coverage/drop_trait.rs b/tests/run-coverage/drop_trait.rs index a9b5d1d1e7fe..7b062719c6b0 100644 --- a/tests/run-coverage/drop_trait.rs +++ b/tests/run-coverage/drop_trait.rs @@ -11,7 +11,7 @@ impl Drop for Firework { } } -fn main() -> Result<(),u8> { +fn main() -> Result<(), u8> { let _firecracker = Firework { strength: 1 }; let _tnt = Firework { strength: 100 }; diff --git a/tests/run-coverage/generics.coverage b/tests/run-coverage/generics.coverage index 2ff8f917ed74..098391835663 100644 --- a/tests/run-coverage/generics.coverage +++ b/tests/run-coverage/generics.coverage @@ -41,7 +41,7 @@ ------------------ LL| |} LL| | - LL| 1|fn main() -> Result<(),u8> { + LL| 1|fn main() -> Result<(), u8> { LL| 1| let mut firecracker = Firework { strength: 1 }; LL| 1| firecracker.set_strength(2); LL| 1| @@ -54,10 +54,6 @@ LL| 1| return Err(1); LL| 0| } LL| 0| - LL| 0| - LL| 0| - LL| 0| - LL| 0| LL| 0| let _ = Firework { strength: 1000 }; LL| 0| LL| 0| Ok(()) diff --git a/tests/run-coverage/generics.rs b/tests/run-coverage/generics.rs index 150ffb9db395..bf4c2d8d6853 100644 --- a/tests/run-coverage/generics.rs +++ b/tests/run-coverage/generics.rs @@ -19,7 +19,7 @@ impl Drop for Firework where T: Copy + std::fmt::Display { } } -fn main() -> Result<(),u8> { +fn main() -> Result<(), u8> { let mut firecracker = Firework { strength: 1 }; firecracker.set_strength(2); @@ -32,10 +32,6 @@ fn main() -> Result<(),u8> { return Err(1); } - - - - let _ = Firework { strength: 1000 }; Ok(()) diff --git a/tests/run-coverage/issue-85461.coverage b/tests/run-coverage/issue-85461.coverage index 48e76318b0a4..cbc910664d06 100644 --- a/tests/run-coverage/issue-85461.coverage +++ b/tests/run-coverage/issue-85461.coverage @@ -5,9 +5,9 @@ $DIR/auxiliary/inline_always_with_dead_code.rs: LL| | LL| |mod foo { LL| | #[inline(always)] - LL| 2| pub fn called() { } + LL| 2| pub fn called() {} LL| | - LL| 0| fn uncalled() { } + LL| 0| fn uncalled() {} LL| |} LL| | LL| |pub mod bar { diff --git a/tests/run-coverage/issue-93054.coverage b/tests/run-coverage/issue-93054.coverage index 224c01d9a8ba..15f225326a42 100644 --- a/tests/run-coverage/issue-93054.coverage +++ b/tests/run-coverage/issue-93054.coverage @@ -6,26 +6,26 @@ LL| | LL| |// compile-flags: --edition=2021 LL| | - LL| |enum Never { } + LL| |enum Never {} LL| | LL| |impl Never { LL| | fn foo(self) { - LL| | match self { } - LL| | make().map(|never| match never { }); + LL| | match self {} + LL| | make().map(|never| match never {}); LL| | } LL| | LL| | fn bar(&self) { - LL| | match *self { } + LL| | match *self {} LL| | } LL| |} LL| | LL| 0|async fn foo2(never: Never) { - LL| | match never { } + LL| | match never {} LL| |} LL| | LL| 0|fn make() -> Option { LL| 0| None LL| 0|} LL| | - LL| 1|fn main() { } + LL| 1|fn main() {} diff --git a/tests/run-coverage/issue-93054.rs b/tests/run-coverage/issue-93054.rs index 9f695b7fd11b..da546cfeef85 100644 --- a/tests/run-coverage/issue-93054.rs +++ b/tests/run-coverage/issue-93054.rs @@ -6,25 +6,25 @@ // compile-flags: --edition=2021 -enum Never { } +enum Never {} impl Never { fn foo(self) { - match self { } - make().map(|never| match never { }); + match self {} + make().map(|never| match never {}); } fn bar(&self) { - match *self { } + match *self {} } } async fn foo2(never: Never) { - match never { } + match never {} } fn make() -> Option { None } -fn main() { } +fn main() {} diff --git a/tests/run-coverage/loops_branches.coverage b/tests/run-coverage/loops_branches.coverage index 148a22377f32..8cd6f1be3f7a 100644 --- a/tests/run-coverage/loops_branches.coverage +++ b/tests/run-coverage/loops_branches.coverage @@ -9,8 +9,7 @@ LL| 1| fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { LL| 1| if true { LL| 1| if false { - LL| 0| while true { - LL| 0| } + LL| 0| while true {} LL| 1| } LL| 1| write!(f, "cool")?; ^0 diff --git a/tests/run-coverage/loops_branches.rs b/tests/run-coverage/loops_branches.rs index 7116ce47f4b9..f3a343bcc1f4 100644 --- a/tests/run-coverage/loops_branches.rs +++ b/tests/run-coverage/loops_branches.rs @@ -9,8 +9,7 @@ impl std::fmt::Debug for DebugTest { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { if true { if false { - while true { - } + while true {} } write!(f, "cool")?; } else { diff --git a/tests/run-coverage/overflow.coverage b/tests/run-coverage/overflow.coverage index 2d60316e2158..cee076e88cd4 100644 --- a/tests/run-coverage/overflow.coverage +++ b/tests/run-coverage/overflow.coverage @@ -12,7 +12,7 @@ LL| 4| result LL| 4|} LL| | - LL| 1|fn main() -> Result<(),u8> { + LL| 1|fn main() -> Result<(), u8> { LL| 1| let mut countdown = 10; LL| 11| while countdown > 0 { LL| 11| if countdown == 1 { diff --git a/tests/run-coverage/overflow.rs b/tests/run-coverage/overflow.rs index 7df8de6f3cd1..bbb65c1b35df 100644 --- a/tests/run-coverage/overflow.rs +++ b/tests/run-coverage/overflow.rs @@ -12,7 +12,7 @@ fn might_overflow(to_add: u32) -> u32 { result } -fn main() -> Result<(),u8> { +fn main() -> Result<(), u8> { let mut countdown = 10; while countdown > 0 { if countdown == 1 { diff --git a/tests/run-coverage/try_error_result.coverage b/tests/run-coverage/try_error_result.coverage index fcdb7437d00d..5d48cbd62f20 100644 --- a/tests/run-coverage/try_error_result.coverage +++ b/tests/run-coverage/try_error_result.coverage @@ -1,7 +1,7 @@ LL| |#![allow(unused_assignments)] LL| |// failure-status: 1 LL| | - LL| 6|fn call(return_error: bool) -> Result<(),()> { + LL| 6|fn call(return_error: bool) -> Result<(), ()> { LL| 6| if return_error { LL| 1| Err(()) LL| | } else { @@ -9,7 +9,7 @@ LL| | } LL| 6|} LL| | - LL| 1|fn test1() -> Result<(),()> { + LL| 1|fn test1() -> Result<(), ()> { LL| 1| let mut LL| 1| countdown = 10 LL| | ; @@ -38,18 +38,18 @@ LL| | LL| |struct Thing1; LL| |impl Thing1 { - LL| 18| fn get_thing_2(&self, return_error: bool) -> Result { + LL| 18| fn get_thing_2(&self, return_error: bool) -> Result { LL| 18| if return_error { LL| 1| Err(()) LL| | } else { - LL| 17| Ok(Thing2{}) + LL| 17| Ok(Thing2 {}) LL| | } LL| 18| } LL| |} LL| | LL| |struct Thing2; LL| |impl Thing2 { - LL| 17| fn call(&self, return_error: bool) -> Result { + LL| 17| fn call(&self, return_error: bool) -> Result { LL| 17| if return_error { LL| 2| Err(()) LL| | } else { @@ -58,7 +58,7 @@ LL| 17| } LL| |} LL| | - LL| 1|fn test2() -> Result<(),()> { + LL| 1|fn test2() -> Result<(), ()> { LL| 1| let thing1 = Thing1{}; LL| 1| let mut LL| 1| countdown = 10 @@ -115,7 +115,7 @@ LL| 0| Ok(()) LL| 1|} LL| | - LL| 1|fn main() -> Result<(),()> { + LL| 1|fn main() -> Result<(), ()> { LL| 1| test1().expect_err("test1 should fail"); LL| 1| test2() LL| 1| ? diff --git a/tests/run-coverage/try_error_result.rs b/tests/run-coverage/try_error_result.rs index 9eb1d2db218b..557cbf22bfad 100644 --- a/tests/run-coverage/try_error_result.rs +++ b/tests/run-coverage/try_error_result.rs @@ -1,7 +1,7 @@ #![allow(unused_assignments)] // failure-status: 1 -fn call(return_error: bool) -> Result<(),()> { +fn call(return_error: bool) -> Result<(), ()> { if return_error { Err(()) } else { @@ -9,7 +9,7 @@ fn call(return_error: bool) -> Result<(),()> { } } -fn test1() -> Result<(),()> { +fn test1() -> Result<(), ()> { let mut countdown = 10 ; @@ -37,18 +37,18 @@ fn test1() -> Result<(),()> { struct Thing1; impl Thing1 { - fn get_thing_2(&self, return_error: bool) -> Result { + fn get_thing_2(&self, return_error: bool) -> Result { if return_error { Err(()) } else { - Ok(Thing2{}) + Ok(Thing2 {}) } } } struct Thing2; impl Thing2 { - fn call(&self, return_error: bool) -> Result { + fn call(&self, return_error: bool) -> Result { if return_error { Err(()) } else { @@ -57,7 +57,7 @@ impl Thing2 { } } -fn test2() -> Result<(),()> { +fn test2() -> Result<(), ()> { let thing1 = Thing1{}; let mut countdown = 10 @@ -109,7 +109,7 @@ fn test2() -> Result<(),()> { Ok(()) } -fn main() -> Result<(),()> { +fn main() -> Result<(), ()> { test1().expect_err("test1 should fail"); test2() ? diff --git a/tests/run-coverage/uses_inline_crate.coverage b/tests/run-coverage/uses_inline_crate.coverage index c510b6a6c68e..cc0e01ffde1c 100644 --- a/tests/run-coverage/uses_inline_crate.coverage +++ b/tests/run-coverage/uses_inline_crate.coverage @@ -32,12 +32,6 @@ $DIR/auxiliary/used_inline_crate.rs: LL| 1| use_this_lib_crate(); LL| 1|} LL| | - LL| | - LL| | - LL| | - LL| | - LL| | - LL| | LL| |#[inline(always)] LL| 2|pub fn used_only_from_bin_crate_generic_function(arg: T) { LL| 2| println!("used_only_from_bin_crate_generic_function with {:?}", arg); diff --git a/tests/run-coverage/while_early_ret.coverage b/tests/run-coverage/while_early_ret.coverage index 97808447ab74..49d39d366038 100644 --- a/tests/run-coverage/while_early_ret.coverage +++ b/tests/run-coverage/while_early_ret.coverage @@ -1,7 +1,7 @@ LL| |#![allow(unused_assignments)] LL| |// failure-status: 1 LL| | - LL| 1|fn main() -> Result<(),u8> { + LL| 1|fn main() -> Result<(), u8> { LL| 1| let mut countdown = 10; LL| | while LL| 7| countdown diff --git a/tests/run-coverage/while_early_ret.rs b/tests/run-coverage/while_early_ret.rs index 1c83c8fc7a8f..b2f0eee2cc0f 100644 --- a/tests/run-coverage/while_early_ret.rs +++ b/tests/run-coverage/while_early_ret.rs @@ -1,7 +1,7 @@ #![allow(unused_assignments)] // failure-status: 1 -fn main() -> Result<(),u8> { +fn main() -> Result<(), u8> { let mut countdown = 10; while countdown diff --git a/tests/run-coverage/yield.coverage b/tests/run-coverage/yield.coverage index 383dd9915004..90c2641a7d66 100644 --- a/tests/run-coverage/yield.coverage +++ b/tests/run-coverage/yield.coverage @@ -7,7 +7,7 @@ LL| 1|fn main() { LL| 1| let mut generator = || { LL| 1| yield 1; - LL| 1| return "foo" + LL| 1| return "foo"; LL| 1| }; LL| | LL| 1| match Pin::new(&mut generator).resume(()) { @@ -23,7 +23,7 @@ LL| 1| yield 1; LL| 1| yield 2; LL| 0| yield 3; - LL| 0| return "foo" + LL| 0| return "foo"; LL| 0| }; LL| | LL| 1| match Pin::new(&mut generator).resume(()) { diff --git a/tests/run-coverage/yield.rs b/tests/run-coverage/yield.rs index ff7616656ff5..361275c92158 100644 --- a/tests/run-coverage/yield.rs +++ b/tests/run-coverage/yield.rs @@ -7,7 +7,7 @@ use std::pin::Pin; fn main() { let mut generator = || { yield 1; - return "foo" + return "foo"; }; match Pin::new(&mut generator).resume(()) { @@ -23,7 +23,7 @@ fn main() { yield 1; yield 2; yield 3; - return "foo" + return "foo"; }; match Pin::new(&mut generator).resume(()) { From 20479074f4a68b855310ad79022499d7c7e08ade Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Sat, 26 Aug 2023 05:25:22 +0000 Subject: [PATCH 196/197] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index d96e7040aaf7..f0eb71c00171 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -c40cfcf0494ff7506e753e750adb00eeea839f9c +9334ec93541fd6963a3bfa2d2d09e3e33ac93131 From ec91a2361ba0de6aa90f92fe620d49ef84b177ef Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Sat, 26 Aug 2023 05:34:03 +0000 Subject: [PATCH 197/197] fmt --- src/tools/miri/src/machine.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 98f82ec9a0ff..9d01a04bf4ad 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -975,7 +975,10 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ecx.start_panic_nounwind(msg) } - fn unwind_terminate(ecx: &mut InterpCx<'mir, 'tcx, Self>, reason: mir::UnwindTerminateReason) -> InterpResult<'tcx> { + fn unwind_terminate( + ecx: &mut InterpCx<'mir, 'tcx, Self>, + reason: mir::UnwindTerminateReason, + ) -> InterpResult<'tcx> { // Call the lang item. let panic = ecx.tcx.lang_items().get(reason.lang_item()).unwrap(); let panic = ty::Instance::mono(ecx.tcx.tcx, panic); @@ -1410,17 +1413,14 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ecx: &mut InterpCx<'mir, 'tcx, Self>, frame: usize, local: mir::Local, - mplace: &MPlaceTy<'tcx, Provenance> + mplace: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let Some(Provenance::Concrete { alloc_id, .. }) = mplace.ptr.provenance else { panic!("after_local_allocated should only be called on fresh allocations"); }; let local_decl = &ecx.active_thread_stack()[frame].body.local_decls[local]; let span = local_decl.source_info.span; - ecx.machine - .allocation_spans - .borrow_mut() - .insert(alloc_id, (span, None)); + ecx.machine.allocation_spans.borrow_mut().insert(alloc_id, (span, None)); Ok(()) } }